Coverage Report

Created: 2026-10-15 06:20

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 "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
502
{
440
502
  if((Curl_raw_tolower(scheme[0]) == 'w') &&
441
468
     (Curl_raw_tolower(scheme[1]) == 's'))
442
456
    return &Curl_scheme_ws;
443
46
  return NULL;
444
502
}
445
446
static const struct Curl_scheme *three_letter_scheme(const char *scheme)
447
337
{
448
337
  char s0 = Curl_raw_tolower(scheme[0]);
449
337
  char s1 = Curl_raw_tolower(scheme[1]);
450
337
  char s2 = Curl_raw_tolower(scheme[2]);
451
337
  if(s0 == 'f') {
452
229
    if(s1 == 't' && s2 == 'p')
453
197
      return &Curl_scheme_ftp;
454
229
  }
455
108
  else if(s0 == 'w') {
456
36
    if(s1 == 's' && s2 == 's')
457
10
      return &Curl_scheme_wss;
458
36
  }
459
72
  else if(s0 == 's') {
460
40
    if(s1 == 'c' && s2 == 'p')
461
10
      return &Curl_scheme_scp;
462
40
  }
463
120
  return NULL;
464
337
}
465
466
static const struct Curl_scheme *four_letter_scheme(const char *scheme)
467
9.95k
{
468
9.95k
  char s0 = Curl_raw_tolower(scheme[0]);
469
9.95k
  char s1 = Curl_raw_tolower(scheme[1]);
470
9.95k
  char s2 = Curl_raw_tolower(scheme[2]);
471
9.95k
  char s3 = Curl_raw_tolower(scheme[3]);
472
9.95k
  if(s3 == 'p') {
473
9.39k
    if(s0 == 'h') {
474
8.84k
      if(s1 == 't' && s2 == 't')
475
8.81k
        return &Curl_scheme_http;
476
8.84k
    }
477
550
    else if(s0 == 'i') {
478
86
      if(s1 == 'm' && s2 == 'a')
479
58
        return &Curl_scheme_imap;
480
86
    }
481
464
    else if(s0 == 'l') {
482
97
      if(s1 == 'd' && s2 == 'a')
483
71
        return &Curl_scheme_ldap;
484
97
    }
485
367
    else if(s0 == 'r') {
486
91
      if(s1 == 't' && s2 == 's')
487
66
        return &Curl_scheme_rtsp;
488
91
    }
489
276
    else if(s0 == 't') {
490
134
      if(s1 == 'f' && s2 == 't')
491
109
        return &Curl_scheme_tftp;
492
134
    }
493
142
    else if(s0 == 's') {
494
119
      if(s1 == 'f' && s2 == 't')
495
14
        return &Curl_scheme_sftp;
496
105
      if(s1 == 'm' && s2 == 't')
497
69
        return &Curl_scheme_smtp;
498
105
    }
499
9.39k
  }
500
561
  else if(s0 == 'f') {
501
333
    if(s1 == 't' && s2 == 'p' && s3 == 's')
502
10
      return &Curl_scheme_ftps;
503
323
    if(s1 == 'i' && s2 == 'l' && s3 == 'e')
504
247
      return &Curl_scheme_file;
505
323
  }
506
228
  else if(s0 == 'm') {
507
110
    if(s1 == 'q' && s2 == 't' && s3 == 't')
508
70
      return &Curl_scheme_mqtt;
509
110
  }
510
118
  else if(s0 == 'p') {
511
43
    if(s1 == 'o' && s2 == 'p' && s3 == '3')
512
10
      return &Curl_scheme_pop3;
513
43
  }
514
75
  else if(s0 == 'd') {
515
48
    if(s1 == 'i' && s2 == 'c' && s3 == 't')
516
11
      return &Curl_scheme_dict;
517
48
  }
518
406
  return NULL;
519
9.95k
}
520
521
static const struct Curl_scheme *five_letter_scheme(const char *scheme)
522
532
{
523
532
  char s4 = Curl_raw_tolower(scheme[4]);
524
532
  if(s4 == 's') {
525
515
    char s0 = Curl_raw_tolower(scheme[0]);
526
515
    char s1 = Curl_raw_tolower(scheme[1]);
527
515
    char s2 = Curl_raw_tolower(scheme[2]);
528
515
    char s3 = Curl_raw_tolower(scheme[3]);
529
515
    if(s3 == 'p') {
530
363
      switch(s0) {
531
35
      case 'h':
532
35
        if(s1 == 't' && s2 == 't')
533
14
          return &Curl_scheme_https;
534
21
        break;
535
237
      case 'l':
536
237
        if(s1 == 'd' && s2 == 'a')
537
214
          return &Curl_scheme_ldaps;
538
23
        break;
539
38
      case 'i':
540
38
        if(s1 == 'm' && s2 == 'a')
541
10
          return &Curl_scheme_imaps;
542
28
        break;
543
40
      case 's':
544
40
        if(s1 == 'm' && s2 == 't')
545
10
          return &Curl_scheme_smtps;
546
30
        break;
547
30
      default:
548
13
        break;
549
363
      }
550
363
    }
551
152
    else if(s0 == 'p') {
552
43
      if(s1 == 'o' && s2 == 'p' && s3 == '3')
553
10
        return &Curl_scheme_pop3s;
554
43
    }
555
109
    else if(s0 == 'm') {
556
43
      if(s1 == 'q' && s2 == 't' && s3 == 't')
557
10
        return &Curl_scheme_mqtts;
558
43
    }
559
66
    else if(s0 == 's') {
560
50
      if(s1 == 'o' && s2 == 'c' && s3 == 'k')
561
10
        return &Curl_scheme_socks;
562
50
    }
563
515
  }
564
254
  return NULL;
565
532
}
566
567
static const struct Curl_scheme *six_letter_scheme(const char *scheme)
568
28.3k
{
569
28.3k
  char s0 = Curl_raw_tolower(scheme[0]);
570
28.3k
  switch(s0) {
571
324
  case 's':
572
324
    if(curl_strnequal("ocks4", &scheme[1], 5))
573
10
      return &Curl_scheme_socks4;
574
314
    if(curl_strnequal("ocks5", &scheme[1], 5))
575
304
      return &Curl_scheme_socks5;
576
10
    break;
577
27.9k
  case 'g':
578
27.9k
    if(curl_strnequal("opher", &scheme[1], 5))
579
27.9k
      return &Curl_scheme_gopher;
580
18
    break;
581
18
  case 't':
582
10
    if(curl_strnequal("elnet", &scheme[1], 5))
583
0
      return &Curl_scheme_telnet;
584
10
    break;
585
28.3k
  }
586
60
  return NULL;
587
28.3k
}
588
589
static const struct Curl_scheme *seven_letter_scheme(const char *scheme)
590
30.0k
{
591
30.0k
  char s0 = Curl_raw_tolower(scheme[0]);
592
30.0k
  if(s0 == 's') {
593
31
    if(curl_strnequal("ocks4a", &scheme[1], 6))
594
13
      return &Curl_scheme_socks4a;
595
18
    if(curl_strnequal("ocks5h", &scheme[1], 6))
596
8
      return &Curl_scheme_socks5h;
597
18
  }
598
30.0k
  else if(s0 == 'g') {
599
29.9k
    if(curl_strnequal("ophers", &scheme[1], 6))
600
29.9k
      return &Curl_scheme_gophers;
601
29.9k
  }
602
43
  return NULL;
603
30.0k
}
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
69.8k
{
610
69.8k
  typedef const struct Curl_scheme *(*letterfunc)(const char *ptr);
611
69.8k
  static const letterfunc parse[] = {
612
69.8k
    two_letter_scheme,
613
69.8k
    three_letter_scheme,
614
69.8k
    four_letter_scheme,
615
69.8k
    five_letter_scheme,
616
69.8k
    six_letter_scheme,
617
69.8k
    seven_letter_scheme
618
69.8k
  };
619
620
69.8k
  if(len < 2 || len > 7)
621
122
    return NULL;
622
623
69.6k
  return parse[len - 2](scheme);
624
69.8k
}
625
626
const struct Curl_scheme *Curl_get_scheme(const char *scheme)
627
29.9k
{
628
29.9k
  return Curl_getn_scheme(scheme, strlen(scheme));
629
29.9k
}