Line | Count | Source |
1 | | /*************************************************************************** |
2 | | * _ _ ____ _ |
3 | | * Project ___| | | | _ \| | |
4 | | * / __| | | | |_) | | |
5 | | * | (__| |_| | _ <| |___ |
6 | | * \___|\___/|_| \_\_____| |
7 | | * |
8 | | * Copyright (C) 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.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 | | * SPDX-License-Identifier: curl |
22 | | * |
23 | | ***************************************************************************/ |
24 | | #include "curl_setup.h" |
25 | | |
26 | | #include "protocol.h" |
27 | | #include "strcase.h" |
28 | | |
29 | | #include "dict.h" |
30 | | #include "file.h" |
31 | | #include "ftp.h" |
32 | | #include "gopher.h" |
33 | | #include "http.h" |
34 | | #include "imap.h" |
35 | | #include "curl_ldap.h" |
36 | | #include "mqtt.h" |
37 | | #include "pop3.h" |
38 | | #include "rtsp.h" |
39 | | #include "smtp.h" |
40 | | #include "telnet.h" |
41 | | #include "tftp.h" |
42 | | #include "ws.h" |
43 | | #include "vssh/ssh.h" |
44 | | |
45 | | |
46 | | /* All URI schemes known to libcurl, but not necessarily implemented |
47 | | * by protocol handlers. */ |
48 | | const struct Curl_scheme Curl_scheme_dict = { |
49 | | "dict", /* scheme */ |
50 | | #ifdef CURL_DISABLE_DICT |
51 | | ZERO_NULL, |
52 | | #else |
53 | | &Curl_protocol_dict, |
54 | | #endif |
55 | | CURLPROTO_DICT, /* protocol */ |
56 | | CURLPROTO_DICT, /* family */ |
57 | | PROTOPT_NONE | PROTOPT_NOURLQUERY, /* flags */ |
58 | | PORT_DICT, /* defport */ |
59 | | }; |
60 | | |
61 | | const struct Curl_scheme Curl_scheme_file = { |
62 | | "file", /* scheme */ |
63 | | #ifdef CURL_DISABLE_FILE |
64 | | ZERO_NULL, |
65 | | #else |
66 | | &Curl_protocol_file, |
67 | | #endif |
68 | | CURLPROTO_FILE, /* protocol */ |
69 | | CURLPROTO_FILE, /* family */ |
70 | | PROTOPT_NONETWORK | PROTOPT_NOURLQUERY, /* flags */ |
71 | | 0 /* defport */ |
72 | | }; |
73 | | |
74 | | const struct Curl_scheme Curl_scheme_ftp = { |
75 | | "ftp", /* scheme */ |
76 | | #ifdef CURL_DISABLE_FTP |
77 | | ZERO_NULL, |
78 | | #else |
79 | | &Curl_protocol_ftp, |
80 | | #endif |
81 | | CURLPROTO_FTP, /* protocol */ |
82 | | CURLPROTO_FTP, /* family */ |
83 | | PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD | |
84 | | PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP | |
85 | | PROTOPT_WILDCARD | PROTOPT_SSL_REUSE | |
86 | | PROTOPT_CONN_REUSE, /* flags */ |
87 | | PORT_FTP, /* defport */ |
88 | | }; |
89 | | |
90 | | const struct Curl_scheme Curl_scheme_ftps = { |
91 | | "ftps", /* scheme */ |
92 | | #if defined(CURL_DISABLE_FTP) || !defined(USE_SSL) |
93 | | ZERO_NULL, |
94 | | #else |
95 | | &Curl_protocol_ftp, |
96 | | #endif |
97 | | CURLPROTO_FTPS, /* protocol */ |
98 | | CURLPROTO_FTP, /* family */ |
99 | | PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION | |
100 | | PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD | |
101 | | PROTOPT_CONN_REUSE, /* flags */ |
102 | | PORT_FTPS, /* defport */ |
103 | | }; |
104 | | |
105 | | const struct Curl_scheme Curl_scheme_gopher = { |
106 | | "gopher", /* scheme */ |
107 | | #ifdef CURL_DISABLE_GOPHER |
108 | | ZERO_NULL, |
109 | | #else |
110 | | &Curl_protocol_gopher, |
111 | | #endif |
112 | | CURLPROTO_GOPHER, /* protocol */ |
113 | | CURLPROTO_GOPHER, /* family */ |
114 | | PROTOPT_NONE, /* flags */ |
115 | | PORT_GOPHER, /* defport */ |
116 | | }; |
117 | | |
118 | | const struct Curl_scheme Curl_scheme_gophers = { |
119 | | "gophers", /* scheme */ |
120 | | #if defined(CURL_DISABLE_GOPHER) || !defined(USE_SSL) |
121 | | ZERO_NULL, |
122 | | #else |
123 | | &Curl_protocol_gophers, |
124 | | #endif |
125 | | CURLPROTO_GOPHERS, /* protocol */ |
126 | | CURLPROTO_GOPHER, /* family */ |
127 | | PROTOPT_SSL, /* flags */ |
128 | | PORT_GOPHER, /* defport */ |
129 | | }; |
130 | | |
131 | | const struct Curl_scheme Curl_scheme_http = { |
132 | | "http", /* scheme */ |
133 | | #ifdef CURL_DISABLE_HTTP |
134 | | ZERO_NULL, |
135 | | #else |
136 | | &Curl_protocol_http, |
137 | | #endif |
138 | | CURLPROTO_HTTP, /* protocol */ |
139 | | CURLPROTO_HTTP, /* family */ |
140 | | PROTOPT_CREDSPERREQUEST | /* flags */ |
141 | | PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE, |
142 | | PORT_HTTP, /* defport */ |
143 | | }; |
144 | | |
145 | | const struct Curl_scheme Curl_scheme_https = { |
146 | | "https", /* scheme */ |
147 | | #if defined(CURL_DISABLE_HTTP) || !defined(USE_SSL) |
148 | | ZERO_NULL, |
149 | | #else |
150 | | &Curl_protocol_http, |
151 | | #endif |
152 | | CURLPROTO_HTTPS, /* protocol */ |
153 | | CURLPROTO_HTTP, /* family */ |
154 | | PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN | /* flags */ |
155 | | PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE | |
156 | | PROTOPT_HTTP_PROXY_TUNNEL, |
157 | | PORT_HTTPS, /* defport */ |
158 | | }; |
159 | | |
160 | | const struct Curl_scheme Curl_scheme_imap = { |
161 | | "imap", /* scheme */ |
162 | | #ifdef CURL_DISABLE_IMAP |
163 | | ZERO_NULL, |
164 | | #else |
165 | | &Curl_protocol_imap, |
166 | | #endif |
167 | | CURLPROTO_IMAP, /* protocol */ |
168 | | CURLPROTO_IMAP, /* family */ |
169 | | PROTOPT_CLOSEACTION | /* flags */ |
170 | | PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | |
171 | | PROTOPT_CONN_REUSE, |
172 | | PORT_IMAP, /* defport */ |
173 | | }; |
174 | | |
175 | | const struct Curl_scheme Curl_scheme_imaps = { |
176 | | "imaps", /* scheme */ |
177 | | #if defined(CURL_DISABLE_IMAP) || !defined(USE_SSL) |
178 | | ZERO_NULL, |
179 | | #else |
180 | | &Curl_protocol_imap, |
181 | | #endif |
182 | | CURLPROTO_IMAPS, /* protocol */ |
183 | | CURLPROTO_IMAP, /* family */ |
184 | | PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */ |
185 | | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE, |
186 | | PORT_IMAPS, /* defport */ |
187 | | }; |
188 | | |
189 | | const struct Curl_scheme Curl_scheme_ldap = { |
190 | | "ldap", /* scheme */ |
191 | | #ifdef CURL_DISABLE_LDAP |
192 | | ZERO_NULL, |
193 | | #else |
194 | | &Curl_protocol_ldap, |
195 | | #endif |
196 | | CURLPROTO_LDAP, /* protocol */ |
197 | | CURLPROTO_LDAP, /* family */ |
198 | | PROTOPT_SSL_REUSE, /* flags */ |
199 | | PORT_LDAP, /* defport */ |
200 | | }; |
201 | | |
202 | | const struct Curl_scheme Curl_scheme_ldaps = { |
203 | | "ldaps", /* scheme */ |
204 | | #if defined(CURL_DISABLE_LDAP) || !defined(HAVE_LDAP_SSL) |
205 | | ZERO_NULL, |
206 | | #else |
207 | | &Curl_protocol_ldap, |
208 | | #endif |
209 | | CURLPROTO_LDAPS, /* protocol */ |
210 | | CURLPROTO_LDAP, /* family */ |
211 | | PROTOPT_SSL, /* flags */ |
212 | | PORT_LDAPS, /* defport */ |
213 | | }; |
214 | | |
215 | | const struct Curl_scheme Curl_scheme_mqtt = { |
216 | | "mqtt", /* scheme */ |
217 | | #ifdef CURL_DISABLE_MQTT |
218 | | ZERO_NULL, |
219 | | #else |
220 | | &Curl_protocol_mqtt, |
221 | | #endif |
222 | | CURLPROTO_MQTT, /* protocol */ |
223 | | CURLPROTO_MQTT, /* family */ |
224 | | PROTOPT_NONE, /* flags */ |
225 | | PORT_MQTT, /* defport */ |
226 | | }; |
227 | | |
228 | | const struct Curl_scheme Curl_scheme_mqtts = { |
229 | | "mqtts", /* scheme */ |
230 | | #if defined(CURL_DISABLE_MQTT) || !defined(USE_SSL) |
231 | | ZERO_NULL, |
232 | | #else |
233 | | &Curl_protocol_mqtts, |
234 | | #endif |
235 | | CURLPROTO_MQTTS, /* protocol */ |
236 | | CURLPROTO_MQTT, /* family */ |
237 | | PROTOPT_SSL, /* flags */ |
238 | | PORT_MQTTS, /* defport */ |
239 | | }; |
240 | | |
241 | | const struct Curl_scheme Curl_scheme_pop3 = { |
242 | | "pop3", /* scheme */ |
243 | | #ifdef CURL_DISABLE_POP3 |
244 | | ZERO_NULL, |
245 | | #else |
246 | | &Curl_protocol_pop3, |
247 | | #endif |
248 | | CURLPROTO_POP3, /* protocol */ |
249 | | CURLPROTO_POP3, /* family */ |
250 | | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */ |
251 | | PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | PROTOPT_CONN_REUSE, |
252 | | PORT_POP3, /* defport */ |
253 | | }; |
254 | | |
255 | | const struct Curl_scheme Curl_scheme_pop3s = { |
256 | | "pop3s", /* scheme */ |
257 | | #if defined(CURL_DISABLE_POP3) || !defined(USE_SSL) |
258 | | ZERO_NULL, |
259 | | #else |
260 | | &Curl_protocol_pop3, |
261 | | #endif |
262 | | CURLPROTO_POP3S, /* protocol */ |
263 | | CURLPROTO_POP3, /* family */ |
264 | | PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */ |
265 | | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE, |
266 | | PORT_POP3S, /* defport */ |
267 | | }; |
268 | | |
269 | | const struct Curl_scheme Curl_scheme_rtsp = { |
270 | | "rtsp", /* scheme */ |
271 | | #ifdef CURL_DISABLE_RTSP |
272 | | ZERO_NULL, |
273 | | #else |
274 | | &Curl_protocol_rtsp, |
275 | | #endif |
276 | | CURLPROTO_RTSP, /* protocol */ |
277 | | CURLPROTO_RTSP, /* family */ |
278 | | PROTOPT_CONN_REUSE, /* flags */ |
279 | | PORT_RTSP, /* defport */ |
280 | | }; |
281 | | |
282 | | const struct Curl_scheme Curl_scheme_sftp = { |
283 | | "sftp", /* scheme */ |
284 | | #ifndef USE_SSH |
285 | | NULL, |
286 | | #else |
287 | | &Curl_protocol_sftp, |
288 | | #endif |
289 | | CURLPROTO_SFTP, /* protocol */ |
290 | | CURLPROTO_SFTP, /* family */ |
291 | | PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */ |
292 | | PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE, |
293 | | PORT_SSH /* defport */ |
294 | | }; |
295 | | |
296 | | const struct Curl_scheme Curl_scheme_scp = { |
297 | | "scp", /* scheme */ |
298 | | #ifndef USE_SSH |
299 | | NULL, |
300 | | #else |
301 | | &Curl_protocol_scp, |
302 | | #endif |
303 | | CURLPROTO_SCP, /* protocol */ |
304 | | CURLPROTO_SCP, /* family */ |
305 | | PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */ |
306 | | PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE, |
307 | | PORT_SSH, /* defport */ |
308 | | }; |
309 | | |
310 | | const struct Curl_scheme Curl_scheme_smtp = { |
311 | | "smtp", /* scheme */ |
312 | | #ifdef CURL_DISABLE_SMTP |
313 | | ZERO_NULL, |
314 | | #else |
315 | | &Curl_protocol_smtp, |
316 | | #endif |
317 | | CURLPROTO_SMTP, /* protocol */ |
318 | | CURLPROTO_SMTP, /* family */ |
319 | | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */ |
320 | | PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | PROTOPT_CONN_REUSE, |
321 | | PORT_SMTP, /* defport */ |
322 | | }; |
323 | | |
324 | | const struct Curl_scheme Curl_scheme_smtps = { |
325 | | "smtps", /* scheme */ |
326 | | #if defined(CURL_DISABLE_SMTP) || !defined(USE_SSL) |
327 | | ZERO_NULL, |
328 | | #else |
329 | | &Curl_protocol_smtp, |
330 | | #endif |
331 | | CURLPROTO_SMTPS, /* protocol */ |
332 | | CURLPROTO_SMTP, /* family */ |
333 | | PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */ |
334 | | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE, |
335 | | PORT_SMTPS, /* defport */ |
336 | | }; |
337 | | |
338 | | const struct Curl_scheme Curl_scheme_socks = { |
339 | | "socks", /* scheme */ |
340 | | ZERO_NULL, |
341 | | CURLPROTO_SOCKS, /* protocol */ |
342 | | CURLPROTO_SOCKS, /* family */ |
343 | | PROTOPT_NO_TRANSFER, /* flags */ |
344 | | PORT_SOCKS, /* defport */ |
345 | | }; |
346 | | |
347 | | const struct Curl_scheme Curl_scheme_socks4 = { |
348 | | "socks4", /* scheme */ |
349 | | ZERO_NULL, |
350 | | CURLPROTO_SOCKS, /* protocol */ |
351 | | CURLPROTO_SOCKS, /* family */ |
352 | | PROTOPT_NO_TRANSFER, /* flags */ |
353 | | PORT_SOCKS, /* defport */ |
354 | | }; |
355 | | |
356 | | const struct Curl_scheme Curl_scheme_socks4a = { |
357 | | "socks4a", /* scheme */ |
358 | | ZERO_NULL, |
359 | | CURLPROTO_SOCKS, /* protocol */ |
360 | | CURLPROTO_SOCKS, /* family */ |
361 | | PROTOPT_NO_TRANSFER, /* flags */ |
362 | | PORT_SOCKS, /* defport */ |
363 | | }; |
364 | | |
365 | | const struct Curl_scheme Curl_scheme_socks5 = { |
366 | | "socks5", /* scheme */ |
367 | | ZERO_NULL, |
368 | | CURLPROTO_SOCKS, /* protocol */ |
369 | | CURLPROTO_SOCKS, /* family */ |
370 | | PROTOPT_NO_TRANSFER, /* flags */ |
371 | | PORT_SOCKS, /* defport */ |
372 | | }; |
373 | | |
374 | | const struct Curl_scheme Curl_scheme_socks5h = { |
375 | | "socks5h", /* scheme */ |
376 | | ZERO_NULL, |
377 | | CURLPROTO_SOCKS, /* protocol */ |
378 | | CURLPROTO_SOCKS, /* family */ |
379 | | PROTOPT_NO_TRANSFER, /* flags */ |
380 | | PORT_SOCKS, /* defport */ |
381 | | }; |
382 | | |
383 | | const struct Curl_scheme Curl_scheme_telnet = { |
384 | | "telnet", /* scheme */ |
385 | | #ifdef CURL_DISABLE_TELNET |
386 | | ZERO_NULL, |
387 | | #else |
388 | | &Curl_protocol_telnet, |
389 | | #endif |
390 | | CURLPROTO_TELNET, /* protocol */ |
391 | | CURLPROTO_TELNET, /* family */ |
392 | | PROTOPT_NONE | PROTOPT_NOURLQUERY, /* flags */ |
393 | | PORT_TELNET, /* defport */ |
394 | | }; |
395 | | |
396 | | const struct Curl_scheme Curl_scheme_tftp = { |
397 | | "tftp", /* scheme */ |
398 | | #ifdef CURL_DISABLE_TFTP |
399 | | ZERO_NULL, |
400 | | #else |
401 | | &Curl_protocol_tftp, |
402 | | #endif |
403 | | CURLPROTO_TFTP, /* protocol */ |
404 | | CURLPROTO_TFTP, /* family */ |
405 | | PROTOPT_NOTCPPROXY | PROTOPT_NOURLQUERY, /* flags */ |
406 | | PORT_TFTP, /* defport */ |
407 | | }; |
408 | | |
409 | | const struct Curl_scheme Curl_scheme_ws = { |
410 | | "ws", /* scheme */ |
411 | | #if defined(CURL_DISABLE_WEBSOCKETS) || defined(CURL_DISABLE_HTTP) |
412 | | ZERO_NULL, |
413 | | #else |
414 | | &Curl_protocol_ws, |
415 | | #endif |
416 | | CURLPROTO_WS, /* protocol */ |
417 | | CURLPROTO_HTTP, /* family */ |
418 | | PROTOPT_CREDSPERREQUEST | /* flags */ |
419 | | PROTOPT_USERPWDCTRL | PROTOPT_HTTP_PROXY_TUNNEL, |
420 | | PORT_HTTP /* defport */ |
421 | | }; |
422 | | |
423 | | const struct Curl_scheme Curl_scheme_wss = { |
424 | | "wss", /* scheme */ |
425 | | #if defined(CURL_DISABLE_WEBSOCKETS) || defined(CURL_DISABLE_HTTP) || \ |
426 | | !defined(USE_SSL) |
427 | | ZERO_NULL, |
428 | | #else |
429 | | &Curl_protocol_ws, |
430 | | #endif |
431 | | CURLPROTO_WSS, /* protocol */ |
432 | | CURLPROTO_HTTP, /* family */ |
433 | | PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */ |
434 | | PROTOPT_USERPWDCTRL | PROTOPT_HTTP_PROXY_TUNNEL, |
435 | | PORT_HTTPS /* defport */ |
436 | | }; |
437 | | |
438 | | static const struct Curl_scheme *two_letter_scheme(const char *scheme) |
439 | 10.0k | { |
440 | 10.0k | if((Curl_raw_tolower(scheme[0]) == 'w') && |
441 | 10.0k | (Curl_raw_tolower(scheme[1]) == 's')) |
442 | 10.0k | return &Curl_scheme_ws; |
443 | 0 | return NULL; |
444 | 10.0k | } |
445 | | |
446 | | static const struct Curl_scheme *three_letter_scheme(const char *scheme) |
447 | 10.0k | { |
448 | 10.0k | char s0 = Curl_raw_tolower(scheme[0]); |
449 | 10.0k | char s1 = Curl_raw_tolower(scheme[1]); |
450 | 10.0k | char s2 = Curl_raw_tolower(scheme[2]); |
451 | 10.0k | if(s0 == 'f') { |
452 | 0 | if(s1 == 't' && s2 == 'p') |
453 | 0 | return &Curl_scheme_ftp; |
454 | 0 | } |
455 | 10.0k | else if(s0 == 'w') { |
456 | 10.0k | if(s1 == 's' && s2 == 's') |
457 | 10.0k | return &Curl_scheme_wss; |
458 | 10.0k | } |
459 | 0 | else if(s0 == 's') { |
460 | 0 | if(s1 == 'c' && s2 == 'p') |
461 | 0 | return &Curl_scheme_scp; |
462 | 0 | } |
463 | 0 | return NULL; |
464 | 10.0k | } |
465 | | |
466 | | static const struct Curl_scheme *four_letter_scheme(const char *scheme) |
467 | 10.0k | { |
468 | 10.0k | char s0 = Curl_raw_tolower(scheme[0]); |
469 | 10.0k | char s1 = Curl_raw_tolower(scheme[1]); |
470 | 10.0k | char s2 = Curl_raw_tolower(scheme[2]); |
471 | 10.0k | char s3 = Curl_raw_tolower(scheme[3]); |
472 | 10.0k | if(s3 == 'p') { |
473 | 10.0k | if(s0 == 'h') { |
474 | 10.0k | if(s1 == 't' && s2 == 't') |
475 | 10.0k | return &Curl_scheme_http; |
476 | 10.0k | } |
477 | 0 | else if(s0 == 'i') { |
478 | 0 | if(s1 == 'm' && s2 == 'a') |
479 | 0 | return &Curl_scheme_imap; |
480 | 0 | } |
481 | 0 | else if(s0 == 'l') { |
482 | 0 | if(s1 == 'd' && s2 == 'a') |
483 | 0 | return &Curl_scheme_ldap; |
484 | 0 | } |
485 | 0 | else if(s0 == 'r') { |
486 | 0 | if(s1 == 't' && s2 == 's') |
487 | 0 | return &Curl_scheme_rtsp; |
488 | 0 | } |
489 | 0 | else if(s0 == 't') { |
490 | 0 | if(s1 == 'f' && s2 == 't') |
491 | 0 | return &Curl_scheme_tftp; |
492 | 0 | } |
493 | 0 | else if(s0 == 's') { |
494 | 0 | if(s1 == 'f' && s2 == 't') |
495 | 0 | return &Curl_scheme_sftp; |
496 | 0 | if(s1 == 'm' && s2 == 't') |
497 | 0 | return &Curl_scheme_smtp; |
498 | 0 | } |
499 | 10.0k | } |
500 | 0 | else if(s0 == 'f') { |
501 | 0 | if(s1 == 't' && s2 == 'p' && s3 == 's') |
502 | 0 | return &Curl_scheme_ftps; |
503 | 0 | if(s1 == 'i' && s2 == 'l' && s3 == 'e') |
504 | 0 | return &Curl_scheme_file; |
505 | 0 | } |
506 | 0 | else if(s0 == 'm') { |
507 | 0 | if(s1 == 'q' && s2 == 't' && s3 == 't') |
508 | 0 | return &Curl_scheme_mqtt; |
509 | 0 | } |
510 | 0 | else if(s0 == 'p') { |
511 | 0 | if(s1 == 'o' && s2 == 'p' && s3 == '3') |
512 | 0 | return &Curl_scheme_pop3; |
513 | 0 | } |
514 | 0 | else if(s0 == 'd') { |
515 | 0 | if(s1 == 'i' && s2 == 'c' && s3 == 't') |
516 | 0 | return &Curl_scheme_dict; |
517 | 0 | } |
518 | 0 | return NULL; |
519 | 10.0k | } |
520 | | |
521 | | static const struct Curl_scheme *five_letter_scheme(const char *scheme) |
522 | 10.0k | { |
523 | 10.0k | char s4 = Curl_raw_tolower(scheme[4]); |
524 | 10.0k | if(s4 == 's') { |
525 | 10.0k | char s0 = Curl_raw_tolower(scheme[0]); |
526 | 10.0k | char s1 = Curl_raw_tolower(scheme[1]); |
527 | 10.0k | char s2 = Curl_raw_tolower(scheme[2]); |
528 | 10.0k | char s3 = Curl_raw_tolower(scheme[3]); |
529 | 10.0k | if(s3 == 'p') { |
530 | 10.0k | switch(s0) { |
531 | 10.0k | case 'h': |
532 | 10.0k | if(s1 == 't' && s2 == 't') |
533 | 10.0k | return &Curl_scheme_https; |
534 | 0 | break; |
535 | 0 | case 'l': |
536 | 0 | if(s1 == 'd' && s2 == 'a') |
537 | 0 | return &Curl_scheme_ldaps; |
538 | 0 | break; |
539 | 0 | case 'i': |
540 | 0 | if(s1 == 'm' && s2 == 'a') |
541 | 0 | return &Curl_scheme_imaps; |
542 | 0 | break; |
543 | 0 | case 's': |
544 | 0 | if(s1 == 'm' && s2 == 't') |
545 | 0 | return &Curl_scheme_smtps; |
546 | 0 | break; |
547 | 0 | default: |
548 | 0 | break; |
549 | 10.0k | } |
550 | 10.0k | } |
551 | 0 | else if(s0 == 'p') { |
552 | 0 | if(s1 == 'o' && s2 == 'p' && s3 == '3') |
553 | 0 | return &Curl_scheme_pop3s; |
554 | 0 | } |
555 | 0 | else if(s0 == 'm') { |
556 | 0 | if(s1 == 'q' && s2 == 't' && s3 == 't') |
557 | 0 | return &Curl_scheme_mqtts; |
558 | 0 | } |
559 | 0 | else if(s0 == 's') { |
560 | 0 | if(s1 == 'o' && s2 == 'c' && s3 == 'k') |
561 | 0 | return &Curl_scheme_socks; |
562 | 0 | } |
563 | 10.0k | } |
564 | 0 | return NULL; |
565 | 10.0k | } |
566 | | |
567 | | static const struct Curl_scheme *six_letter_scheme(const char *scheme) |
568 | 38.7k | { |
569 | 38.7k | char s0 = Curl_raw_tolower(scheme[0]); |
570 | 38.7k | switch(s0) { |
571 | 0 | case 's': |
572 | 0 | if(curl_strnequal("ocks4", &scheme[1], 5)) |
573 | 0 | return &Curl_scheme_socks4; |
574 | 0 | if(curl_strnequal("ocks5", &scheme[1], 5)) |
575 | 0 | return &Curl_scheme_socks5; |
576 | 0 | break; |
577 | 38.7k | case 'g': |
578 | 38.7k | if(curl_strnequal("opher", &scheme[1], 5)) |
579 | 38.7k | return &Curl_scheme_gopher; |
580 | 0 | break; |
581 | 0 | case 't': |
582 | 0 | if(curl_strnequal("elnet", &scheme[1], 5)) |
583 | 0 | return &Curl_scheme_telnet; |
584 | 0 | break; |
585 | 38.7k | } |
586 | 0 | return NULL; |
587 | 38.7k | } |
588 | | |
589 | | static const struct Curl_scheme *seven_letter_scheme(const char *scheme) |
590 | 30.3k | { |
591 | 30.3k | char s0 = Curl_raw_tolower(scheme[0]); |
592 | 30.3k | if(s0 == 's') { |
593 | 0 | if(curl_strnequal("ocks4a", &scheme[1], 6)) |
594 | 0 | return &Curl_scheme_socks4a; |
595 | 0 | if(curl_strnequal("ocks5h", &scheme[1], 6)) |
596 | 0 | return &Curl_scheme_socks5h; |
597 | 0 | } |
598 | 30.3k | else if(s0 == 'g') { |
599 | 30.3k | if(curl_strnequal("ophers", &scheme[1], 6)) |
600 | 30.3k | return &Curl_scheme_gophers; |
601 | 30.3k | } |
602 | 0 | return NULL; |
603 | 30.3k | } |
604 | | |
605 | | /* Returns a struct scheme pointer if the name is a known scheme. Check the |
606 | | ->run struct field for non-NULL to figure out if an implementation is |
607 | | present. */ |
608 | | const struct Curl_scheme *Curl_getn_scheme(const char *scheme, size_t len) |
609 | 109k | { |
610 | 109k | typedef const struct Curl_scheme *(*letterfunc)(const char *ptr); |
611 | 109k | static const letterfunc parse[] = { |
612 | 109k | two_letter_scheme, |
613 | 109k | three_letter_scheme, |
614 | 109k | four_letter_scheme, |
615 | 109k | five_letter_scheme, |
616 | 109k | six_letter_scheme, |
617 | 109k | seven_letter_scheme |
618 | 109k | }; |
619 | | |
620 | 109k | if(len < 2 || len > 7) |
621 | 0 | return NULL; |
622 | | |
623 | 109k | return parse[len - 2](scheme); |
624 | 109k | } |
625 | | |
626 | | const struct Curl_scheme *Curl_get_scheme(const char *scheme) |
627 | 39.1k | { |
628 | 39.1k | return Curl_getn_scheme(scheme, strlen(scheme)); |
629 | 39.1k | } |