Coverage Report

Created: 2026-09-01 06:58

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
static const struct Curl_scheme *two_letter_scheme(const char *scheme)
466
390
{
467
390
  if((Curl_raw_tolower(scheme[0]) == 'w') &&
468
375
     (Curl_raw_tolower(scheme[1]) == 's'))
469
368
    return &Curl_scheme_ws;
470
22
  return NULL;
471
390
}
472
473
static const struct Curl_scheme *three_letter_scheme(const char *scheme)
474
5.31k
{
475
5.31k
  char s0 = Curl_raw_tolower(scheme[0]);
476
5.31k
  char s1 = Curl_raw_tolower(scheme[1]);
477
5.31k
  char s2 = Curl_raw_tolower(scheme[2]);
478
5.31k
  if(s0 == 'f') {
479
92
    if(s1 == 't' && s2 == 'p')
480
82
      return &Curl_scheme_ftp;
481
92
  }
482
5.22k
  else if(s0 == 'w') {
483
108
    if(s1 == 's' && s2 == 's')
484
86
      return &Curl_scheme_wss;
485
108
  }
486
5.11k
  else if(s0 == 's') {
487
5.09k
    if(s1 == 'c' && s2 == 'p')
488
1
      return &Curl_scheme_scp;
489
5.09k
    if(s1 == 'm' && s2 == 'b')
490
5.06k
      return &Curl_scheme_smb;
491
5.09k
  }
492
77
  return NULL;
493
5.31k
}
494
495
static const struct Curl_scheme *four_letter_scheme(const char *scheme)
496
750
{
497
750
  char s0 = Curl_raw_tolower(scheme[0]);
498
750
  char s1 = Curl_raw_tolower(scheme[1]);
499
750
  char s2 = Curl_raw_tolower(scheme[2]);
500
750
  char s3 = Curl_raw_tolower(scheme[3]);
501
750
  if(s3 == 'p') {
502
343
    if(s0 == 'h') {
503
100
      if(s1 == 't' && s2 == 't')
504
87
        return &Curl_scheme_http;
505
100
    }
506
243
    else if(s0 == 'i') {
507
35
      if(s1 == 'm' && s2 == 'a')
508
19
        return &Curl_scheme_imap;
509
35
    }
510
208
    else if(s0 == 'l') {
511
34
      if(s1 == 'd' && s2 == 'a')
512
24
        return &Curl_scheme_ldap;
513
34
    }
514
174
    else if(s0 == 'r') {
515
44
      if(s1 == 't' && s2 == 's')
516
37
        return &Curl_scheme_rtsp;
517
44
    }
518
130
    else if(s0 == 't') {
519
54
      if(s1 == 'f' && s2 == 't')
520
35
        return &Curl_scheme_tftp;
521
54
    }
522
76
    else if(s0 == 's') {
523
58
      if(s1 == 'f' && s2 == 't')
524
1
        return &Curl_scheme_sftp;
525
57
      if(s1 == 'm' && s2 == 't')
526
39
        return &Curl_scheme_smtp;
527
57
    }
528
343
  }
529
407
  else if(s0 == 'f') {
530
117
    if(s1 == 't' && s2 == 'p' && s3 == 's')
531
34
      return &Curl_scheme_ftps;
532
83
    if(s1 == 'i' && s2 == 'l' && s3 == 'e')
533
51
      return &Curl_scheme_file;
534
83
  }
535
290
  else if(s0 == 'm') {
536
133
    if(s1 == 'q' && s2 == 't' && s3 == 't')
537
115
      return &Curl_scheme_mqtt;
538
133
  }
539
157
  else if(s0 == 'p') {
540
98
    if(s1 == 'o' && s2 == 'p' && s3 == '3')
541
83
      return &Curl_scheme_pop3;
542
98
  }
543
59
  else if(s0 == 'd') {
544
17
    if(s1 == 'i' && s2 == 'c' && s3 == 't')
545
1
      return &Curl_scheme_dict;
546
17
  }
547
42
  else if(s0 == 's') {
548
24
    if(s1 == 'm' && s2 == 'b' && s3 == 's')
549
1
      return &Curl_scheme_smbs;
550
24
  }
551
223
  return NULL;
552
750
}
553
554
static const struct Curl_scheme *five_letter_scheme(const char *scheme)
555
373
{
556
373
  char s4 = Curl_raw_tolower(scheme[4]);
557
373
  if(s4 == 's') {
558
366
    char s0 = Curl_raw_tolower(scheme[0]);
559
366
    char s1 = Curl_raw_tolower(scheme[1]);
560
366
    char s2 = Curl_raw_tolower(scheme[2]);
561
366
    char s3 = Curl_raw_tolower(scheme[3]);
562
366
    if(s3 == 'p') {
563
103
      switch(s0) {
564
20
      case 'h':
565
20
        if(s1 == 't' && s2 == 't')
566
13
          return &Curl_scheme_https;
567
7
        break;
568
40
      case 'l':
569
40
        if(s1 == 'd' && s2 == 'a')
570
27
          return &Curl_scheme_ldaps;
571
13
        break;
572
22
      case 'i':
573
22
        if(s1 == 'm' && s2 == 'a')
574
10
          return &Curl_scheme_imaps;
575
12
        break;
576
20
      case 's':
577
20
        if(s1 == 'm' && s2 == 't')
578
10
          return &Curl_scheme_smtps;
579
10
        break;
580
10
      default:
581
1
        break;
582
103
      }
583
103
    }
584
263
    else if(s0 == 'p') {
585
121
      if(s1 == 'o' && s2 == 'p' && s3 == '3')
586
99
        return &Curl_scheme_pop3s;
587
121
    }
588
142
    else if(s0 == 'm') {
589
109
      if(s1 == 'q' && s2 == 't' && s3 == 't')
590
92
        return &Curl_scheme_mqtts;
591
109
    }
592
33
    else if(s0 == 's') {
593
19
      if(s1 == 'o' && s2 == 'c' && s3 == 'k')
594
1
        return &Curl_scheme_socks;
595
19
    }
596
366
  }
597
121
  return NULL;
598
373
}
599
600
static const struct Curl_scheme *six_letter_scheme(const char *scheme)
601
8
{
602
8
  char s0 = Curl_raw_tolower(scheme[0]);
603
8
  switch(s0) {
604
3
  case 's':
605
3
    if(curl_strnequal("ocks4", &scheme[1], 5))
606
1
      return &Curl_scheme_socks4;
607
2
    if(curl_strnequal("ocks5", &scheme[1], 5))
608
1
      return &Curl_scheme_socks5;
609
1
    break;
610
1
  case 'g':
611
1
    if(curl_strnequal("opher", &scheme[1], 5))
612
0
      return &Curl_scheme_gopher;
613
1
    break;
614
1
  case 't':
615
1
    if(curl_strnequal("elnet", &scheme[1], 5))
616
0
      return &Curl_scheme_telnet;
617
1
    break;
618
8
  }
619
6
  return NULL;
620
8
}
621
622
static const struct Curl_scheme *seven_letter_scheme(const char *scheme)
623
11
{
624
11
  char s0 = Curl_raw_tolower(scheme[0]);
625
11
  if(s0 == 's') {
626
1
    if(curl_strnequal("ocks4a", &scheme[1], 6))
627
0
      return &Curl_scheme_socks4a;
628
1
    if(curl_strnequal("ocks5h", &scheme[1], 6))
629
0
      return &Curl_scheme_socks5h;
630
1
  }
631
10
  else if(s0 == 'g') {
632
3
    if(curl_strnequal("ophers", &scheme[1], 6))
633
0
      return &Curl_scheme_gophers;
634
3
  }
635
11
  return NULL;
636
11
}
637
638
/* Returns a struct scheme pointer if the name is a known scheme. Check the
639
   ->run struct field for non-NULL to figure out if an implementation is
640
   present. */
641
const struct Curl_scheme *Curl_getn_scheme(const char *scheme, size_t len)
642
6.90k
{
643
6.90k
  typedef const struct Curl_scheme *(*letterfunc)(const char *ptr);
644
6.90k
  static const letterfunc parse[] = {
645
6.90k
    two_letter_scheme,
646
6.90k
    three_letter_scheme,
647
6.90k
    four_letter_scheme,
648
6.90k
    five_letter_scheme,
649
6.90k
    six_letter_scheme,
650
6.90k
    seven_letter_scheme
651
6.90k
  };
652
653
6.90k
  if(len < 2 || len > 7)
654
57
    return NULL;
655
656
6.84k
  return parse[len - 2](scheme);
657
6.90k
}
658
659
const struct Curl_scheme *Curl_get_scheme(const char *scheme)
660
0
{
661
0
  return Curl_getn_scheme(scheme, strlen(scheme));
662
0
}