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", "#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)" },
74 {"wss", "#if defined(USE_WEBSOCKETS) && \\\n"
75 " defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" },
76 { NULL, NULL }
77 };
78
calc(const char * s,int add,int shift)79 unsigned int calc(const char *s, int add, int shift)
80 {
81 const char *so = s;
82 unsigned int c = add;
83 while(*s) {
84 c <<= shift;
85 c += *s;
86 s++;
87 }
88 return c;
89 }
90
91 unsigned int num[100];
92 unsigned int ix[100];
93
showtable(int try,int init,int shift)94 static void showtable(int try, int init, int shift)
95 {
96 int nulls = 0;
97 int i;
98 for(i = 0; scheme[i].n; ++i)
99 num[i] = calc(scheme[i].n, init, shift);
100 for(i = 0; scheme[i].n; ++i)
101 ix[i] = num[i] % try;
102 printf("/*\n"
103 " unsigned int c = %d\n"
104 " while(l) {\n"
105 " c <<= %d;\n"
106 " c += Curl_raw_tolower(*s);\n"
107 " s++;\n"
108 " l--;\n"
109 " }\n"
110 "*/\n", init, shift);
111
112 printf(" static const struct Curl_handler * const protocols[%d] = {", try);
113
114 /* generate table */
115 for(i = 0; i < try; i++) {
116 int match = 0;
117 int j;
118 for(j = 0; scheme[j].n; j++) {
119 if(ix[j] == i) {
120 printf("\n");
121 printf("%s\n", scheme[j].ifdef);
122 printf(" &Curl_handler_%s,\n", scheme[j].n);
123 printf("#else\n NULL,\n");
124 printf("#endif");
125 match = 1;
126 nulls = 0;
127 break;
128 }
129 }
130 if(!match) {
131 if(!nulls || (nulls > 10)) {
132 printf("\n ");
133 nulls = 0;
134 }
135 printf(" NULL,", nulls);
136 nulls++;
137 }
138 }
139 printf("\n };\n");
140 }
141
main(void)142 int main(void)
143 {
144 int i;
145 int try;
146 int besttry = 9999;
147 int bestadd = 0;
148 int bestshift = 0;
149 int add;
150 int shift;
151 for(shift = 0; shift < 8; shift++) {
152 for(add = 0; add < 999; add++) {
153 for(i = 0; scheme[i].n; ++i) {
154 unsigned int v = calc(scheme[i].n, add, shift);
155 int j;
156 int badcombo = 0;
157 for(j = 0; j < i; j++) {
158
159 if(num[j] == v) {
160 /*
161 printf("NOPE: %u is a dupe (%s and %s)\n",
162 v, scheme[i], scheme[j]);
163 */
164 badcombo = 1;
165 break;
166 }
167 }
168 if(badcombo)
169 break;
170 num[i] = v;
171 }
172 #if 0
173 for(i = 0; scheme[i].n; ++i) {
174 printf("%u - %s\n", num[i], scheme[i].n);
175 }
176 #endif
177 /* try different remainders to find smallest possible table */
178 for(try = 28; try < 199; try++) {
179 int good = 1;
180 for(i = 0; scheme[i].n; ++i) {
181 ix[i] = num[i] % try;
182 }
183 /* check for dupes */
184 for(i = 0; scheme[i].n && good; ++i) {
185 int j;
186 for(j = 0; j < i; j++) {
187 if(ix[j] == ix[i]) {
188 good = 0;
189 break;
190 }
191 }
192 }
193 if(good) {
194 if(try < besttry) {
195 besttry = try;
196 bestadd = add;
197 bestshift = shift;
198 }
199 break;
200 }
201 }
202 }
203 }
204
205 showtable(besttry, bestadd, bestshift);
206 }
207