Coverage Report

Created: 2026-08-31 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl/lib/protocol.c
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
}