1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23 #include "curl_setup.h" 24 25 #include <curl/curl.h> 26 27 #include "strcase.h" 28 29 /* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because 30 its behavior is altered by the current locale. */ 31 char Curl_raw_toupper(char in) 32 { 33 #if !defined(CURL_DOES_CONVERSIONS) 34 if(in >= 'a' && in <= 'z') 35 return (char)('A' + in - 'a'); 36 #else 37 switch (in) { 38 case 'a': 39 return 'A'; 40 case 'b': 41 return 'B'; 42 case 'c': 43 return 'C'; 44 case 'd': 45 return 'D'; 46 case 'e': 47 return 'E'; 48 case 'f': 49 return 'F'; 50 case 'g': 51 return 'G'; 52 case 'h': 53 return 'H'; 54 case 'i': 55 return 'I'; 56 case 'j': 57 return 'J'; 58 case 'k': 59 return 'K'; 60 case 'l': 61 return 'L'; 62 case 'm': 63 return 'M'; 64 case 'n': 65 return 'N'; 66 case 'o': 67 return 'O'; 68 case 'p': 69 return 'P'; 70 case 'q': 71 return 'Q'; 72 case 'r': 73 return 'R'; 74 case 's': 75 return 'S'; 76 case 't': 77 return 'T'; 78 case 'u': 79 return 'U'; 80 case 'v': 81 return 'V'; 82 case 'w': 83 return 'W'; 84 case 'x': 85 return 'X'; 86 case 'y': 87 return 'Y'; 88 case 'z': 89 return 'Z'; 90 } 91 #endif 92 93 return in; 94 } 95 96 /* 97 * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant 98 * to be locale independent and only compare strings we know are safe for 99 * this. See https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for 100 * some further explanation to why this function is necessary. 101 * 102 * The function is capable of comparing a-z case insensitively even for 103 * non-ascii. 104 * 105 * @unittest: 1301 106 */ 107 108 int Curl_strcasecompare(const char *first, const char *second) 109 { 110 while(*first && *second) { 111 if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) 112 /* get out of the loop as soon as they don't match */ 113 break; 114 first++; 115 second++; 116 } 117 /* we do the comparison here (possibly again), just to make sure that if the 118 loop above is skipped because one of the strings reached zero, we must not 119 return this as a successful match */ 120 return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second)); 121 } 122 123 int Curl_safe_strcasecompare(const char *first, const char *second) 124 { 125 if(first && second) 126 /* both pointers point to something then compare them */ 127 return Curl_strcasecompare(first, second); 128 else 129 /* if both pointers are NULL then treat them as equal */ 130 return (NULL == first && NULL == second); 131 } 132 133 /* 134 * @unittest: 1301 135 */ 136 int Curl_strncasecompare(const char *first, const char *second, size_t max) 137 { 138 while(*first && *second && max) { 139 if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) { 140 break; 141 } 142 max--; 143 first++; 144 second++; 145 } 146 if(0 == max) 147 return 1; /* they are equal this far */ 148 149 return Curl_raw_toupper(*first) == Curl_raw_toupper(*second); 150 } 151 152 /* Copy an upper case version of the string from src to dest. The 153 * strings may overlap. No more than n characters of the string are copied 154 * (including any NUL) and the destination string will NOT be 155 * NUL-terminated if that limit is reached. 156 */ 157 void Curl_strntoupper(char *dest, const char *src, size_t n) 158 { 159 if(n < 1) 160 return; 161 162 do { 163 *dest++ = Curl_raw_toupper(*src); 164 } while(*src++ && --n); 165 } 166 167 /* --- public functions --- */ 168 169 int curl_strequal(const char *first, const char *second) 170 { 171 return Curl_strcasecompare(first, second); 172 } 173 int curl_strnequal(const char *first, const char *second, size_t max) 174 { 175 return Curl_strncasecompare(first, second, max); 176 } 177