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 <stdio.h>
25 #include <curl/curl.h>
26
27 /*
28 * Use this tool to generate an updated table for the Curl_getn_scheme_handler
29 * function in url.c.
30 */
31
32 struct detail {
33 const char *n;
34 const char *ifdef;
35 };
36
37 static const struct detail scheme[] = {
38 {"dict", "#ifndef CURL_DISABLE_DICT" },
39 {"file", "#ifndef CURL_DISABLE_FILE" },
40 {"ftp", "#ifndef CURL_DISABLE_FTP" },
41 {"ftps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)" },
42 {"gopher", "#ifndef CURL_DISABLE_GOPHER" },
43 {"gophers", "#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)" },
44 {"http", "#ifndef CURL_DISABLE_HTTP" },
45 {"https", "#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" },
46 {"imap", "#ifndef CURL_DISABLE_IMAP" },
47 {"imaps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)" },
48 {"ldap", "#ifndef CURL_DISABLE_LDAP" },
49 {"ldaps", "#if !defined(CURL_DISABLE_LDAP) && \\\n"
50 " !defined(CURL_DISABLE_LDAPS) && \\\n"
51 " ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \\\n"
52 " (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))" },
53 {"mqtt", "#ifndef CURL_DISABLE_MQTT" },
54 {"pop3", "#ifndef CURL_DISABLE_POP3" },
55 {"pop3s", "#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)" },
56 {"rtmp", "#ifdef USE_LIBRTMP" },
57 {"rtmpt", "#ifdef USE_LIBRTMP" },
58 {"rtmpe", "#ifdef USE_LIBRTMP" },
59 {"rtmpte", "#ifdef USE_LIBRTMP" },
60 {"rtmps", "#ifdef USE_LIBRTMP" },
61 {"rtmpts", "#ifdef USE_LIBRTMP" },
62 {"rtsp", "#ifndef CURL_DISABLE_RTSP" },
63 {"scp", "#if defined(USE_SSH) && !defined(USE_WOLFSSH)" },
64 {"sftp", "#if defined(USE_SSH)" },
65 {"smb", "#if !defined(CURL_DISABLE_SMB) && \\\n"
66 " defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)" },
67 {"smbs", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \\\n"
68 " defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)" },
69 {"smtp", "#ifndef CURL_DISABLE_SMTP" },
70 {"smtps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)" },
71 {"telnet", "#ifndef CURL_DISABLE_TELNET" },
72 {"tftp", "#ifndef CURL_DISABLE_TFTP" },
73 {"ws",
74 "#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)" },
75 {"wss", "#if !defined(CURL_DISABLE_WEBSOCKETS) && \\\n"
76 " defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" },
77 { NULL, NULL }
78 };
79
calc(const char * s,int add,int shift)80 unsigned int calc(const char *s, int add, int shift)
81 {
82 const char *so = s;
83 unsigned int c = add;
84 while(*s) {
85 c <<= shift;
86 c += *s;
87 s++;
88 }
89 return c;
90 }
91
92 unsigned int num[100];
93 unsigned int ix[100];
94
showtable(int try,int init,int shift)95 static void showtable(int try, int init, int shift)
96 {
97 int nulls = 0;
98 int i;
99 for(i = 0; scheme[i].n; ++i)
100 num[i] = calc(scheme[i].n, init, shift);
101 for(i = 0; scheme[i].n; ++i)
102 ix[i] = num[i] % try;
103 printf("/*\n"
104 " unsigned int c = %d\n"
105 " while(l) {\n"
106 " c <<= %d;\n"
107 " c += Curl_raw_tolower(*s);\n"
108 " s++;\n"
109 " l--;\n"
110 " }\n"
111 "*/\n", init, shift);
112
113 printf(" static const struct Curl_handler * const protocols[%d] = {", try);
114
115 /* generate table */
116 for(i = 0; i < try; i++) {
117 int match = 0;
118 int j;
119 for(j = 0; scheme[j].n; j++) {
120 if(ix[j] == i) {
121 printf("\n");
122 printf("%s\n", scheme[j].ifdef);
123 printf(" &Curl_handler_%s,\n", scheme[j].n);
124 printf("#else\n NULL,\n");
125 printf("#endif");
126 match = 1;
127 nulls = 0;
128 break;
129 }
130 }
131 if(!match) {
132 if(!nulls || (nulls > 10)) {
133 printf("\n ");
134 nulls = 0;
135 }
136 printf(" NULL,", nulls);
137 nulls++;
138 }
139 }
140 printf("\n };\n");
141 }
142
main(void)143 int main(void)
144 {
145 int i;
146 int try;
147 int besttry = 9999;
148 int bestadd = 0;
149 int bestshift = 0;
150 int add;
151 int shift;
152 for(shift = 0; shift < 8; shift++) {
153 for(add = 0; add < 999; add++) {
154 for(i = 0; scheme[i].n; ++i) {
155 unsigned int v = calc(scheme[i].n, add, shift);
156 int j;
157 int badcombo = 0;
158 for(j = 0; j < i; j++) {
159
160 if(num[j] == v) {
161 /*
162 printf("NOPE: %u is a dupe (%s and %s)\n",
163 v, scheme[i], scheme[j]);
164 */
165 badcombo = 1;
166 break;
167 }
168 }
169 if(badcombo)
170 break;
171 num[i] = v;
172 }
173 #if 0
174 for(i = 0; scheme[i].n; ++i) {
175 printf("%u - %s\n", num[i], scheme[i].n);
176 }
177 #endif
178 /* try different remainders to find smallest possible table */
179 for(try = 28; try < 199; try++) {
180 int good = 1;
181 for(i = 0; scheme[i].n; ++i) {
182 ix[i] = num[i] % try;
183 }
184 /* check for dupes */
185 for(i = 0; scheme[i].n && good; ++i) {
186 int j;
187 for(j = 0; j < i; j++) {
188 if(ix[j] == ix[i]) {
189 good = 0;
190 break;
191 }
192 }
193 }
194 if(good) {
195 if(try < besttry) {
196 besttry = try;
197 bestadd = add;
198 bestshift = shift;
199 }
200 break;
201 }
202 }
203 }
204 }
205
206 showtable(besttry, bestadd, bestshift);
207 }
208