1 /*
2 *
3 * cgi.c -
4 *
5 * Copyright (C) 1997-1999 Satoru Takabayashi All rights reserved.
6 * This is free software with ABSOLUTELY NO WARRANTY.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * 02111-1307, USA
22 *
23 * This file must be encoded in EUC-JP encoding.
24 *
25 */
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <ctype.h>
31 #include "namazu.h"
32 #include "util.h"
33
34 uchar *ScriptName = "", *QueryString = "", *ContentLength = "";
35
36 /* validate dbname (if it contain '/', it's invalid) */
validate_dbname(uchar * dbname)37 int validate_dbname(uchar * dbname)
38 {
39 int win32 = 0;
40 #if defined(WIN32) || defined(OS2)
41 win32 = 1;
42 #endif
43
44 if (*dbname == '\0' || *dbname == '/' || (win32 && *dbname == '\\')) {
45 fputs(MSG_MIME_HEADER, stdout);
46 fputx(MSG_INVALID_DB_NAME, stdout);
47 exit(1);
48 }
49 while (*dbname) {
50 if (strncmp("../", dbname, 3) == 0 ||
51 strcmp("..", dbname) == 0 ||
52 (win32 && strncmp("..\\", dbname, 3) == 0))
53 {
54 fputs(MSG_MIME_HEADER, stdout);
55 fputx(MSG_INVALID_DB_NAME, stdout);
56 exit(1);
57 }
58 /* Skip until next '/' */
59 while (*dbname && *dbname != '/' && !(win32 && *dbname == '\\'))
60 dbname++;
61 /* Skip '/' */
62 if (*dbname)
63 dbname++;
64 }
65 dbname--; /* remove ending slashed */
66 while (*dbname == '/' || (win32 && *dbname == '\\')) {
67 *dbname = '\0';
68 dbname--;
69 }
70 return 1;
71 }
72
73
74 /* get CGI variables, very complicated routine */
get_cgi_variables(uchar * query,uchar * subquery)75 int get_cgi_variables(uchar * query, uchar *subquery)
76 {
77 int i;
78 uchar *qs, tmp[BUFSIZE];
79 int content_length;
80
81 if ((QueryString = getenv("QUERY_STRING"))) {
82 content_length = strlen(QueryString);
83 if (content_length > QUERY_STRING_MAX_LENGTH) {
84 fputs(MSG_MIME_HEADER, stdout);
85 fputx(MSG_QUERY_STRING_TOO_LONG, stdout);
86 exit(1);
87 }
88 if (!(ScriptName = getenv("SCRIPT_NAME"))) {
89 return 1;
90 }
91 } else {
92 if ((ContentLength = getenv("CONTENT_LENGTH"))) {
93 content_length = atoi(ContentLength);
94 if (content_length > QUERY_STRING_MAX_LENGTH) {
95 fputs(MSG_MIME_HEADER, stdout);
96 fputx(MSG_QUERY_STRING_TOO_LONG, stdout);
97 exit(1);
98 }
99 QueryString = (uchar *)malloc(content_length * sizeof(uchar) + 1);
100 if (QueryString == NULL)
101 error("QueryString( get_cgi_variables )");
102
103 fread(QueryString, sizeof(char), content_length, stdin);
104 HtmlOutput = 1;
105 HidePageIndex = 1;
106 } else {
107 return 1;
108 }
109 }
110 qs = QueryString;
111 DbNumber = 0;
112
113 /* note that CERN HTTPD would add empty PATH_INFO */
114 if (getenv("PATH_INFO")) {
115 char *path_info = getenv("PATH_INFO");
116 if (strlen(path_info) > 0 && strlen(path_info) < 128) {
117 validate_dbname(path_info);
118 sprintf(tmp, "%s%s", DEFAULT_DIR, path_info);
119 DbNames[DbNumber] = (uchar *) malloc(strlen(tmp) + 1);
120 if (DbNames[DbNumber] == NULL) {
121 error("cgi: malloc(dbname)");
122 }
123 strcpy(DbNames[DbNumber], tmp);
124 DbNumber++;
125 }
126 }
127
128 while (*qs) {
129 if (*qs == '&') {
130 qs++;
131 continue;
132 } else if (!strncmp(qs, "key=", 4)) {
133 qs += 4;
134
135 for (i = 0; *qs && *qs != '&'; qs++, i++) {
136 *(query + i) = *qs;
137 }
138 *(query + i) = '\0';
139 decode_url_string(query);
140 if (strlen(query) > QUERY_MAX_LENGTH) {
141 fputs(MSG_MIME_HEADER, stdout);
142 fputx(MSG_TOO_LONG_KEY, stdout);
143 exit(1);
144 }
145
146 #ifdef MSIE4MACFIX
147 #define MSIE4MAC "Mozilla/4.0 (compatible; MSIE 4.01; Mac"
148
149 if (!strncmp(query, "%1B", 3)) {
150 char *agent = getenv("HTTP_USER_AGENT");
151 if (agent && !strncmp(agent, MSIE4MAC, strlen(MSIE4MAC))) {
152 decode_url_string(query);
153 }
154 }
155 #endif MSIE4MACFIX
156
157 } else if (!strncmp(qs, "subquery=", 4)) {
158 qs += 9;
159
160 for (i = 0; *qs && *qs != '&'; qs++, i++) {
161 *(subquery + i) = *qs;
162 }
163 *(subquery + i) = '\0';
164 decode_url_string(subquery);
165 if (strlen(subquery) > QUERY_MAX_LENGTH) {
166 fputs(MSG_MIME_HEADER, stdout);
167 fputx(MSG_TOO_LONG_KEY, stdout);
168 exit(1);
169 }
170
171 #ifdef MSIE4MACFIX
172 #define MSIE4MAC "Mozilla/4.0 (compatible; MSIE 4.01; Mac"
173
174 if (!strncmp(subquery, "%1B", 3)) {
175 char *agent = getenv("HTTP_USER_AGENT");
176 if (agent && !strncmp(agent, MSIE4MAC, strlen(MSIE4MAC))) {
177 decode_url_string(subquery);
178 }
179 }
180 #endif MSIE4MACFIX
181
182 } else if (!strncmp(qs, "format=short", 12)) {
183 ShortFormat = 1;
184 qs += 12;
185 } else if (!strncmp(qs, "sort=", 5)) {
186 qs += 5;
187 if (!strncmp(qs, "score", 5)) {
188 ScoreSort = 1;
189 qs += 5;
190 } else if (!strncmp(qs, "later", 5)) {
191 LaterOrder = 1;
192 ScoreSort = 0;
193 qs += 5;
194 } else if (!strncmp(qs, "earlier", 7)) {
195 LaterOrder = 0;
196 ScoreSort = 0;
197 qs += 7;
198 }
199 while (*qs && *qs != '&')
200 qs++;
201 } else if (!strncmp(qs, "max=", 4)) {
202 qs += 4;
203 sscanf(qs, "%d", &HListMax);
204 if (HListMax < 0)
205 HListMax = 0;
206 if (HListMax > HLIST_MAX_MAX)
207 HListMax = HLIST_MAX_MAX;
208 while (*qs && *qs != '&')
209 qs++;
210 } else if (!strncmp(qs, "whence=", 7)) {
211 qs += 7;
212 sscanf(qs, "%d", &HListWhence);
213 if (HListWhence < 0)
214 HListWhence = 0;
215 while (*qs && *qs != '&')
216 qs++;
217 } else if (!strncmp(qs, "lang=", 5)) {
218 qs += 5;
219 strncpy(Lang, qs, 2);
220 qs += 2;
221 initialize_message();
222 while (*qs && *qs != '&')
223 qs++;
224 } else if (!strncmp(qs, "reference=off", 13)) {
225 NoReference = 1;
226 qs += 13;
227 } else if (!strncmp(qs, "mode=tknamazu", 13)) {
228 ModeTknamazu = 1;
229 qs += 13;
230 } else if (!strncmp(qs, "dbname=", 7)) {
231 uchar *pp;
232
233 qs += 7;
234 for (i = 0; *qs && *qs != '&' && i <= DBNAMELENG_MAX; i++, qs++)
235 tmp[i] = *qs;
236 tmp[i] = '\0';
237 decode_url_string(tmp);
238 for (pp = tmp; *pp ;) {
239 uchar name[BUFSIZE], *x;
240
241 if ((x = strchr(pp, (int)','))) {
242 *x = '\0';
243 strcpy(name, pp);
244 pp = x + 1;
245 } else {
246 strcpy(name, pp);
247 pp += strlen(pp);
248 }
249 if (DbNumber >= DB_MAX) { /* ignore too many indices */
250 continue;
251 }
252 DbNames[DbNumber] = (uchar *)
253 malloc(strlen(DEFAULT_DIR) + 1 + strlen(name) + 1);
254 if (DbNames[DbNumber] == NULL) {
255 error("cgi: malloc(dbname)");
256 }
257 validate_dbname(name);
258 strcpy(DbNames[DbNumber], DEFAULT_DIR);
259 strcat(DbNames[DbNumber], "/");
260 strcat(DbNames[DbNumber], name);
261 DbNumber++;
262 }
263 while (*qs && *qs != '&')
264 qs++;
265 } else {
266 qs++;
267 }
268 }
269 return 0;
270 }
271
272
273 /* initialize CGI mode. actually, to be invoked from commandline
274 * with no arguments also trhough this function */
cgi_initialize(uchar * query,uchar * subquery)275 void cgi_initialize(uchar * query, uchar *subquery)
276 {
277 if (get_cgi_variables(query, subquery))
278 show_usage(); /* if it is NOT CGI, show usage usage */
279 if (DbNumber == 0) {
280 DbNames[DbNumber] = (uchar *) malloc(strlen(DEFAULT_DIR) + 1);
281 if (DbNames[DbNumber] == NULL) {
282 error("cgi_initialize: malloc(dbname)");
283 }
284 strcpy(DbNames[DbNumber], DEFAULT_DIR);
285 DbNumber++;
286 }
287 }
288
289 /* decde URLencode */
290 /* c & 0xdf means to uppercase c */
URLdecode(uchar c,uchar c2)291 uchar URLdecode(uchar c, uchar c2)
292 {
293
294 c = ((c >= 'A' ? ((c & 0xdf) - 'A') + 10 : (c - '0'))) * 16;
295 c += (c2 >= 'A' ? ((c2 & 0xdf) - 'A') + 10 : (c2 - '0'));
296 return c;
297 }
298
299
300
301
302