diff --git a/src/node.cc b/src/node.cc index bc95e93a583148..50a70d41108d04 100644 --- a/src/node.cc +++ b/src/node.cc @@ -69,7 +69,6 @@ #if defined(_MSC_VER) #include #include -#define strcasecmp _stricmp #define getpid GetCurrentProcessId #define umask _umask typedef int mode_t; @@ -1381,27 +1380,27 @@ enum encoding ParseEncoding(const char* encoding, break; } - if (strcasecmp(encoding, "utf8") == 0) { + if (StringEqualNoCase(encoding, "utf8")) { return UTF8; - } else if (strcasecmp(encoding, "utf-8") == 0) { + } else if (StringEqualNoCase(encoding, "utf-8")) { return UTF8; - } else if (strcasecmp(encoding, "ascii") == 0) { + } else if (StringEqualNoCase(encoding, "ascii")) { return ASCII; - } else if (strcasecmp(encoding, "base64") == 0) { + } else if (StringEqualNoCase(encoding, "base64")) { return BASE64; - } else if (strcasecmp(encoding, "ucs2") == 0) { + } else if (StringEqualNoCase(encoding, "ucs2")) { return UCS2; - } else if (strcasecmp(encoding, "ucs-2") == 0) { + } else if (StringEqualNoCase(encoding, "ucs-2")) { return UCS2; - } else if (strcasecmp(encoding, "utf16le") == 0) { + } else if (StringEqualNoCase(encoding, "utf16le")) { return UCS2; - } else if (strcasecmp(encoding, "utf-16le") == 0) { + } else if (StringEqualNoCase(encoding, "utf-16le")) { return UCS2; - } else if (strcasecmp(encoding, "binary") == 0) { + } else if (StringEqualNoCase(encoding, "binary")) { return BINARY; - } else if (strcasecmp(encoding, "buffer") == 0) { + } else if (StringEqualNoCase(encoding, "buffer")) { return BUFFER; - } else if (strcasecmp(encoding, "hex") == 0) { + } else if (StringEqualNoCase(encoding, "hex")) { return HEX; } else { return default_encoding; diff --git a/src/node_crypto.cc b/src/node_crypto.cc index d50671aa760e2b..71799d0bfa3ef3 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -24,10 +24,6 @@ #include #include -#if defined(_MSC_VER) -#define strcasecmp _stricmp -#endif - #define THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(val, prefix) \ do { \ if (!Buffer::HasInstance(val) && !val->IsString()) { \ @@ -4446,7 +4442,7 @@ void DiffieHellman::DiffieHellmanGroup( for (size_t i = 0; i < arraysize(modp_groups); ++i) { const modp_group* it = modp_groups + i; - if (strcasecmp(*group_name, it->name) != 0) + if (!StringEqualNoCase(*group_name, it->name)) continue; initialized = diffieHellman->Init(it->prime, diff --git a/src/util-inl.h b/src/util-inl.h index 7ff6e51937bde7..355dfcdbee3257 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -203,7 +203,19 @@ void SwapBytes(uint16_t* dst, const uint16_t* src, size_t buflen) { dst[i] = (src[i] << 8) | (src[i] >> 8); } +char ToLower(char c) { + return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c; +} +bool StringEqualNoCase(const char* a, const char* b) { + do { + if (*a == '\0') + return *b == '\0'; + if (*b == '\0') + return *a == '\0'; + } while (ToLower(*a++) == ToLower(*b++)); + return false; +} } // namespace node diff --git a/src/util.h b/src/util.h index 1f9f81cfd38e16..dce6c343b1b443 100644 --- a/src/util.h +++ b/src/util.h @@ -178,6 +178,12 @@ inline TypeName* Unwrap(v8::Local object); inline void SwapBytes(uint16_t* dst, const uint16_t* src, size_t buflen); +// tolower() is locale-sensitive. Use ToLower() instead. +inline char ToLower(char c); + +// strcasecmp() is locale-sensitive. Use StringEqualNoCase() instead. +inline bool StringEqualNoCase(const char* a, const char* b); + // Allocates an array of member type T. For up to kStackStorageSize items, // the stack is used, otherwise malloc(). template diff --git a/test/cctest/util.cc b/test/cctest/util.cc index fe966d9b34073c..37133aca562b72 100644 --- a/test/cctest/util.cc +++ b/test/cctest/util.cc @@ -56,3 +56,21 @@ TEST(UtilTest, ListHead) { EXPECT_TRUE(list.IsEmpty()); EXPECT_FALSE(list.begin() != list.end()); } + +TEST(UtilTest, StringEqualNoCase) { + using node::StringEqualNoCase; + EXPECT_FALSE(StringEqualNoCase("a", "b")); + EXPECT_TRUE(StringEqualNoCase("", "")); + EXPECT_TRUE(StringEqualNoCase("equal", "equal")); + EXPECT_TRUE(StringEqualNoCase("equal", "EQUAL")); + EXPECT_TRUE(StringEqualNoCase("EQUAL", "EQUAL")); + EXPECT_FALSE(StringEqualNoCase("equal", "equals")); + EXPECT_FALSE(StringEqualNoCase("equals", "equal")); +} + +TEST(UtilTest, ToLower) { + using node::ToLower; + EXPECT_EQ('0', ToLower('0')); + EXPECT_EQ('a', ToLower('a')); + EXPECT_EQ('a', ToLower('A')); +}