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