• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@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. */
Curl_raw_toupper(char in)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 /* Portable, consistent tolower (remember EBCDIC). Do not use tolower() because
98    its behavior is altered by the current locale. */
Curl_raw_tolower(char in)99 char Curl_raw_tolower(char in)
100 {
101 #if !defined(CURL_DOES_CONVERSIONS)
102   if(in >= 'A' && in <= 'Z')
103     return (char)('a' + in - 'A');
104 #else
105   switch(in) {
106   case 'A':
107     return 'a';
108   case 'B':
109     return 'b';
110   case 'C':
111     return 'c';
112   case 'D':
113     return 'd';
114   case 'E':
115     return 'e';
116   case 'F':
117     return 'f';
118   case 'G':
119     return 'g';
120   case 'H':
121     return 'h';
122   case 'I':
123     return 'i';
124   case 'J':
125     return 'j';
126   case 'K':
127     return 'k';
128   case 'L':
129     return 'l';
130   case 'M':
131     return 'm';
132   case 'N':
133     return 'n';
134   case 'O':
135     return 'o';
136   case 'P':
137     return 'p';
138   case 'Q':
139     return 'q';
140   case 'R':
141     return 'r';
142   case 'S':
143     return 's';
144   case 'T':
145     return 't';
146   case 'U':
147     return 'u';
148   case 'V':
149     return 'v';
150   case 'W':
151     return 'w';
152   case 'X':
153     return 'x';
154   case 'Y':
155     return 'y';
156   case 'Z':
157     return 'z';
158   }
159 #endif
160 
161   return in;
162 }
163 
164 
165 /*
166  * Curl_strcasecompare() is for doing "raw" case insensitive strings. This is
167  * meant to be locale independent and only compare strings we know are safe
168  * for this.  See
169  * https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for some
170  * further explanation to why this function is necessary.
171  *
172  * The function is capable of comparing a-z case insensitively even for
173  * non-ascii.
174  *
175  * @unittest: 1301
176  */
177 
Curl_strcasecompare(const char * first,const char * second)178 int Curl_strcasecompare(const char *first, const char *second)
179 {
180   while(*first && *second) {
181     if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
182       /* get out of the loop as soon as they don't match */
183       break;
184     first++;
185     second++;
186   }
187   /* we do the comparison here (possibly again), just to make sure that if the
188      loop above is skipped because one of the strings reached zero, we must not
189      return this as a successful match */
190   return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
191 }
192 
Curl_safe_strcasecompare(const char * first,const char * second)193 int Curl_safe_strcasecompare(const char *first, const char *second)
194 {
195   if(first && second)
196     /* both pointers point to something then compare them */
197     return Curl_strcasecompare(first, second);
198 
199   /* if both pointers are NULL then treat them as equal */
200   return (NULL == first && NULL == second);
201 }
202 
203 /*
204  * @unittest: 1301
205  */
Curl_strncasecompare(const char * first,const char * second,size_t max)206 int Curl_strncasecompare(const char *first, const char *second, size_t max)
207 {
208   while(*first && *second && max) {
209     if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
210       break;
211     }
212     max--;
213     first++;
214     second++;
215   }
216   if(0 == max)
217     return 1; /* they are equal this far */
218 
219   return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
220 }
221 
222 /* Copy an upper case version of the string from src to dest.  The
223  * strings may overlap.  No more than n characters of the string are copied
224  * (including any NUL) and the destination string will NOT be
225  * NUL-terminated if that limit is reached.
226  */
Curl_strntoupper(char * dest,const char * src,size_t n)227 void Curl_strntoupper(char *dest, const char *src, size_t n)
228 {
229   if(n < 1)
230     return;
231 
232   do {
233     *dest++ = Curl_raw_toupper(*src);
234   } while(*src++ && --n);
235 }
236 
237 /* Copy a lower case version of the string from src to dest.  The
238  * strings may overlap.  No more than n characters of the string are copied
239  * (including any NUL) and the destination string will NOT be
240  * NUL-terminated if that limit is reached.
241  */
Curl_strntolower(char * dest,const char * src,size_t n)242 void Curl_strntolower(char *dest, const char *src, size_t n)
243 {
244   if(n < 1)
245     return;
246 
247   do {
248     *dest++ = Curl_raw_tolower(*src);
249   } while(*src++ && --n);
250 }
251 
252 /* --- public functions --- */
253 
curl_strequal(const char * first,const char * second)254 int curl_strequal(const char *first, const char *second)
255 {
256   return Curl_strcasecompare(first, second);
257 }
curl_strnequal(const char * first,const char * second,size_t max)258 int curl_strnequal(const char *first, const char *second, size_t max)
259 {
260   return Curl_strncasecompare(first, second, max);
261 }
262