mirror of
https://github.com/curl/curl.git
synced 2026-04-12 00:11:42 +08:00
Add protocol.h and protocol.c containing all about libcurl's known URI schemes and their protocol handlers (so they exist). Moves the scheme definitions from the various sources files into protocol.c. Schemes are known and used, even of the protocol handler is not build or just not implemented at all. Closes #20906
572 lines
17 KiB
C
572 lines
17 KiB
C
/***************************************************************************
|
|
* _ _ ____ _
|
|
* Project ___| | | | _ \| |
|
|
* / __| | | | |_) | |
|
|
* | (__| |_| | _ <| |___
|
|
* \___|\___/|_| \_\_____|
|
|
*
|
|
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
*
|
|
* This software is licensed as described in the file COPYING, which
|
|
* you should have received as part of this distribution. The terms
|
|
* are also available at https://curl.se/docs/copyright.html.
|
|
*
|
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
* copies of the Software, and permit persons to whom the Software is
|
|
* furnished to do so, under the terms of the COPYING file.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
* SPDX-License-Identifier: curl
|
|
*
|
|
***************************************************************************/
|
|
#include "curl_setup.h"
|
|
|
|
#include "protocol.h"
|
|
#include "strcase.h"
|
|
|
|
#include "dict.h"
|
|
#include "file.h"
|
|
#include "ftp.h"
|
|
#include "gopher.h"
|
|
#include "http.h"
|
|
#include "imap.h"
|
|
#include "curl_ldap.h"
|
|
#include "mqtt.h"
|
|
#include "pop3.h"
|
|
#include "curl_rtmp.h"
|
|
#include "rtsp.h"
|
|
#include "smb.h"
|
|
#include "smtp.h"
|
|
#include "telnet.h"
|
|
#include "tftp.h"
|
|
#include "ws.h"
|
|
#include "vssh/ssh.h"
|
|
|
|
|
|
/* All URI schemes known to libcurl, but not necessarily implemented
|
|
* by protocol handlers. */
|
|
const struct Curl_scheme Curl_scheme_dict = {
|
|
"dict", /* scheme */
|
|
#ifdef CURL_DISABLE_DICT
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_dict,
|
|
#endif
|
|
CURLPROTO_DICT, /* protocol */
|
|
CURLPROTO_DICT, /* family */
|
|
PROTOPT_NONE | PROTOPT_NOURLQUERY, /* flags */
|
|
PORT_DICT, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_file = {
|
|
"file", /* scheme */
|
|
#ifdef CURL_DISABLE_FILE
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_file,
|
|
#endif
|
|
CURLPROTO_FILE, /* protocol */
|
|
CURLPROTO_FILE, /* family */
|
|
PROTOPT_NONETWORK | PROTOPT_NOURLQUERY, /* flags */
|
|
0 /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_ftp = {
|
|
"ftp", /* scheme */
|
|
#ifdef CURL_DISABLE_FTP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_ftp,
|
|
#endif
|
|
CURLPROTO_FTP, /* protocol */
|
|
CURLPROTO_FTP, /* family */
|
|
PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD |
|
|
PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP |
|
|
PROTOPT_WILDCARD | PROTOPT_SSL_REUSE |
|
|
PROTOPT_CONN_REUSE, /* flags */
|
|
PORT_FTP, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_ftps = {
|
|
"ftps", /* scheme */
|
|
#if defined(CURL_DISABLE_FTP) || !defined(USE_SSL)
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_ftp,
|
|
#endif
|
|
CURLPROTO_FTPS, /* protocol */
|
|
CURLPROTO_FTP, /* family */
|
|
PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
|
|
PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD |
|
|
PROTOPT_CONN_REUSE, /* flags */
|
|
PORT_FTPS, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_gopher = {
|
|
"gopher", /* scheme */
|
|
#ifdef CURL_DISABLE_GOPHER
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_gopher,
|
|
#endif
|
|
CURLPROTO_GOPHER, /* protocol */
|
|
CURLPROTO_GOPHER, /* family */
|
|
PROTOPT_NONE, /* flags */
|
|
PORT_GOPHER, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_gophers = {
|
|
"gophers", /* scheme */
|
|
#if defined(CURL_DISABLE_GOPHER) || !defined(USE_SSL)
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_gophers,
|
|
#endif
|
|
CURLPROTO_GOPHERS, /* protocol */
|
|
CURLPROTO_GOPHER, /* family */
|
|
PROTOPT_SSL, /* flags */
|
|
PORT_GOPHER, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_http = {
|
|
"http", /* scheme */
|
|
#ifdef CURL_DISABLE_HTTP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_http,
|
|
#endif
|
|
CURLPROTO_HTTP, /* protocol */
|
|
CURLPROTO_HTTP, /* family */
|
|
PROTOPT_CREDSPERREQUEST | /* flags */
|
|
PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE,
|
|
PORT_HTTP, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_https = {
|
|
"https", /* scheme */
|
|
#if defined(CURL_DISABLE_HTTP) || !defined(USE_SSL)
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_http,
|
|
#endif
|
|
CURLPROTO_HTTPS, /* protocol */
|
|
CURLPROTO_HTTP, /* family */
|
|
PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN | /* flags */
|
|
PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE,
|
|
PORT_HTTPS, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_imap = {
|
|
"imap", /* scheme */
|
|
#ifdef CURL_DISABLE_IMAP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_imap,
|
|
#endif
|
|
CURLPROTO_IMAP, /* protocol */
|
|
CURLPROTO_IMAP, /* family */
|
|
PROTOPT_CLOSEACTION | /* flags */
|
|
PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE |
|
|
PROTOPT_CONN_REUSE,
|
|
PORT_IMAP, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_imaps = {
|
|
"imaps", /* scheme */
|
|
#if defined(CURL_DISABLE_IMAP) || !defined(USE_SSL)
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_imap,
|
|
#endif
|
|
CURLPROTO_IMAPS, /* protocol */
|
|
CURLPROTO_IMAP, /* family */
|
|
PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
|
|
PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE,
|
|
PORT_IMAPS, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_ldap = {
|
|
"ldap", /* scheme */
|
|
#ifdef CURL_DISABLE_LDAP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_ldap,
|
|
#endif
|
|
CURLPROTO_LDAP, /* protocol */
|
|
CURLPROTO_LDAP, /* family */
|
|
PROTOPT_SSL_REUSE, /* flags */
|
|
PORT_LDAP, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_ldaps = {
|
|
"ldaps", /* scheme */
|
|
#if defined(CURL_DISABLE_LDAP) || !defined(HAVE_LDAP_SSL)
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_ldap,
|
|
#endif
|
|
CURLPROTO_LDAPS, /* protocol */
|
|
CURLPROTO_LDAP, /* family */
|
|
PROTOPT_SSL, /* flags */
|
|
PORT_LDAPS, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_mqtt = {
|
|
"mqtt", /* scheme */
|
|
#ifdef CURL_DISABLE_MQTT
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_mqtt,
|
|
#endif
|
|
CURLPROTO_MQTT, /* protocol */
|
|
CURLPROTO_MQTT, /* family */
|
|
PROTOPT_NONE, /* flags */
|
|
PORT_MQTT, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_mqtts = {
|
|
"mqtts", /* scheme */
|
|
#if defined(CURL_DISABLE_MQTT) || !defined(USE_SSL)
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_mqtts,
|
|
#endif
|
|
CURLPROTO_MQTTS, /* protocol */
|
|
CURLPROTO_MQTT, /* family */
|
|
PROTOPT_SSL, /* flags */
|
|
PORT_MQTTS, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_pop3 = {
|
|
"pop3", /* scheme */
|
|
#ifdef CURL_DISABLE_POP3
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_pop3,
|
|
#endif
|
|
CURLPROTO_POP3, /* protocol */
|
|
CURLPROTO_POP3, /* family */
|
|
PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
|
|
PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | PROTOPT_CONN_REUSE,
|
|
PORT_POP3, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_pop3s = {
|
|
"pop3s", /* scheme */
|
|
#if defined(CURL_DISABLE_POP3) || !defined(USE_SSL)
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_pop3,
|
|
#endif
|
|
CURLPROTO_POP3S, /* protocol */
|
|
CURLPROTO_POP3, /* family */
|
|
PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
|
|
PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE,
|
|
PORT_POP3S, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_rtmp = {
|
|
"rtmp", /* scheme */
|
|
#ifndef USE_LIBRTMP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_rtmp,
|
|
#endif
|
|
CURLPROTO_RTMP, /* protocol */
|
|
CURLPROTO_RTMP, /* family */
|
|
PROTOPT_NONE, /* flags */
|
|
PORT_RTMP, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_rtmpt = {
|
|
"rtmpt", /* scheme */
|
|
#ifndef USE_LIBRTMP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_rtmp,
|
|
#endif
|
|
CURLPROTO_RTMPT, /* protocol */
|
|
CURLPROTO_RTMPT, /* family */
|
|
PROTOPT_NONE, /* flags */
|
|
PORT_RTMPT, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_rtmpe = {
|
|
"rtmpe", /* scheme */
|
|
#ifndef USE_LIBRTMP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_rtmp,
|
|
#endif
|
|
CURLPROTO_RTMPE, /* protocol */
|
|
CURLPROTO_RTMPE, /* family */
|
|
PROTOPT_NONE, /* flags */
|
|
PORT_RTMP, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_rtmpte = {
|
|
"rtmpte", /* scheme */
|
|
#ifndef USE_LIBRTMP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_rtmp,
|
|
#endif
|
|
CURLPROTO_RTMPTE, /* protocol */
|
|
CURLPROTO_RTMPTE, /* family */
|
|
PROTOPT_NONE, /* flags */
|
|
PORT_RTMPT, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_rtmps = {
|
|
"rtmps", /* scheme */
|
|
#ifndef USE_LIBRTMP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_rtmp,
|
|
#endif
|
|
CURLPROTO_RTMPS, /* protocol */
|
|
CURLPROTO_RTMP, /* family */
|
|
PROTOPT_NONE, /* flags */
|
|
PORT_RTMPS, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_rtmpts = {
|
|
"rtmpts", /* scheme */
|
|
#ifndef USE_LIBRTMP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_rtmp,
|
|
#endif
|
|
CURLPROTO_RTMPTS, /* protocol */
|
|
CURLPROTO_RTMPT, /* family */
|
|
PROTOPT_NONE, /* flags */
|
|
PORT_RTMPS, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_rtsp = {
|
|
"rtsp", /* scheme */
|
|
#ifdef CURL_DISABLE_RTSP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_rtsp,
|
|
#endif
|
|
CURLPROTO_RTSP, /* protocol */
|
|
CURLPROTO_RTSP, /* family */
|
|
PROTOPT_CONN_REUSE, /* flags */
|
|
PORT_RTSP, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_sftp = {
|
|
"SFTP", /* scheme */
|
|
#ifndef USE_SSH
|
|
NULL,
|
|
#else
|
|
&Curl_protocol_sftp,
|
|
#endif
|
|
CURLPROTO_SFTP, /* protocol */
|
|
CURLPROTO_SFTP, /* family */
|
|
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */
|
|
PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE,
|
|
PORT_SSH /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_scp = {
|
|
"SCP", /* scheme */
|
|
#ifndef USE_SSH
|
|
NULL,
|
|
#else
|
|
&Curl_protocol_scp,
|
|
#endif
|
|
CURLPROTO_SCP, /* protocol */
|
|
CURLPROTO_SCP, /* family */
|
|
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */
|
|
PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE,
|
|
PORT_SSH, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_smb = {
|
|
"smb", /* scheme */
|
|
#if defined(CURL_DISABLE_SMB) || !defined(USE_CURL_NTLM_CORE)
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_smb,
|
|
#endif
|
|
CURLPROTO_SMB, /* protocol */
|
|
CURLPROTO_SMB, /* family */
|
|
PROTOPT_CONN_REUSE, /* flags */
|
|
PORT_SMB, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_smbs = {
|
|
"smbs", /* scheme */
|
|
#if defined(CURL_DISABLE_SMB) || !defined(USE_CURL_NTLM_CORE) || \
|
|
!defined(USE_SSL)
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_smb,
|
|
#endif
|
|
CURLPROTO_SMBS, /* protocol */
|
|
CURLPROTO_SMB, /* family */
|
|
PROTOPT_SSL | PROTOPT_CONN_REUSE, /* flags */
|
|
PORT_SMBS, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_smtp = {
|
|
"smtp", /* scheme */
|
|
#ifdef CURL_DISABLE_SMTP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_smtp,
|
|
#endif
|
|
CURLPROTO_SMTP, /* protocol */
|
|
CURLPROTO_SMTP, /* family */
|
|
PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
|
|
PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | PROTOPT_CONN_REUSE,
|
|
PORT_SMTP, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_smtps = {
|
|
"smtps", /* scheme */
|
|
#if defined(CURL_DISABLE_SMTP) || !defined(USE_SSL)
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_smtp,
|
|
#endif
|
|
CURLPROTO_SMTPS, /* protocol */
|
|
CURLPROTO_SMTP, /* family */
|
|
PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
|
|
PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE,
|
|
PORT_SMTPS, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_telnet = {
|
|
"telnet", /* scheme */
|
|
#ifdef CURL_DISABLE_TELNET
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_telnet,
|
|
#endif
|
|
CURLPROTO_TELNET, /* protocol */
|
|
CURLPROTO_TELNET, /* family */
|
|
PROTOPT_NONE | PROTOPT_NOURLQUERY, /* flags */
|
|
PORT_TELNET, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_tftp = {
|
|
"tftp", /* scheme */
|
|
#ifdef CURL_DISABLE_TFTP
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_tftp,
|
|
#endif
|
|
CURLPROTO_TFTP, /* protocol */
|
|
CURLPROTO_TFTP, /* family */
|
|
PROTOPT_NOTCPPROXY | PROTOPT_NOURLQUERY, /* flags */
|
|
PORT_TFTP, /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_ws = {
|
|
"WS", /* scheme */
|
|
#if defined(CURL_DISABLE_WEBSOCKETS) || defined(CURL_DISABLE_HTTP)
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_ws,
|
|
#endif
|
|
CURLPROTO_WS, /* protocol */
|
|
CURLPROTO_HTTP, /* family */
|
|
PROTOPT_CREDSPERREQUEST | /* flags */
|
|
PROTOPT_USERPWDCTRL,
|
|
PORT_HTTP /* defport */
|
|
};
|
|
|
|
const struct Curl_scheme Curl_scheme_wss = {
|
|
"WSS", /* scheme */
|
|
#if defined(CURL_DISABLE_WEBSOCKETS) || defined(CURL_DISABLE_HTTP) || \
|
|
!defined(USE_SSL)
|
|
ZERO_NULL,
|
|
#else
|
|
&Curl_protocol_ws,
|
|
#endif
|
|
CURLPROTO_WSS, /* protocol */
|
|
CURLPROTO_HTTP, /* family */
|
|
PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */
|
|
PROTOPT_USERPWDCTRL,
|
|
PORT_HTTPS /* defport */
|
|
};
|
|
|
|
/* Returns a struct scheme pointer if the name is a known scheme. Check the
|
|
->run struct field for non-NULL to figure out if an implementation is
|
|
present. */
|
|
const struct Curl_scheme *Curl_getn_scheme(const char *scheme, size_t len)
|
|
{
|
|
/* table generated by schemetable.c:
|
|
1. gcc schemetable.c && ./a.out
|
|
2. check how small the table gets
|
|
3. tweak the hash algorithm, then rerun from 1
|
|
4. when the table is good enough
|
|
5. copy the table into this source code
|
|
6. make sure this function uses the same hash function that worked for
|
|
schemetable.c
|
|
*/
|
|
static const struct Curl_scheme * const all_schemes[67] = {
|
|
&Curl_scheme_file,
|
|
&Curl_scheme_mqtts, NULL,
|
|
&Curl_scheme_gophers, NULL,
|
|
&Curl_scheme_rtmpe,
|
|
&Curl_scheme_smtp,
|
|
&Curl_scheme_sftp,
|
|
&Curl_scheme_smb,
|
|
&Curl_scheme_smtps,
|
|
&Curl_scheme_telnet,
|
|
&Curl_scheme_gopher,
|
|
&Curl_scheme_tftp, NULL, NULL, NULL,
|
|
&Curl_scheme_ftps,
|
|
&Curl_scheme_http,
|
|
&Curl_scheme_imap,
|
|
&Curl_scheme_rtmps,
|
|
&Curl_scheme_rtmpt, NULL, NULL, NULL,
|
|
&Curl_scheme_ldaps,
|
|
&Curl_scheme_wss,
|
|
&Curl_scheme_https, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
&Curl_scheme_rtsp,
|
|
&Curl_scheme_smbs,
|
|
&Curl_scheme_scp, NULL, NULL, NULL,
|
|
&Curl_scheme_pop3, NULL, NULL,
|
|
&Curl_scheme_rtmp, NULL, NULL, NULL,
|
|
&Curl_scheme_rtmpte, NULL, NULL, NULL,
|
|
&Curl_scheme_dict, NULL, NULL, NULL,
|
|
&Curl_scheme_mqtt,
|
|
&Curl_scheme_pop3s,
|
|
&Curl_scheme_imaps, NULL,
|
|
&Curl_scheme_ws, NULL,
|
|
&Curl_scheme_rtmpts,
|
|
&Curl_scheme_ldap, NULL, NULL,
|
|
&Curl_scheme_ftp,
|
|
};
|
|
|
|
if(len && (len <= 7)) {
|
|
const char *s = scheme;
|
|
size_t l = len;
|
|
const struct Curl_scheme *h;
|
|
unsigned int c = 978;
|
|
while(l) {
|
|
c <<= 5;
|
|
c += (unsigned int)Curl_raw_tolower(*s);
|
|
s++;
|
|
l--;
|
|
}
|
|
|
|
h = all_schemes[c % 67];
|
|
if(h && curl_strnequal(scheme, h->name, len) && !h->name[len])
|
|
return h;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
const struct Curl_scheme *Curl_get_scheme(const char *scheme)
|
|
{
|
|
return Curl_getn_scheme(scheme, strlen(scheme));
|
|
}
|