1 /*
2  *
3  * form.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 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <unistd.h>
32 #ifdef __EMX__
33 #include <sys/types.h>
34 #endif
35 #include <sys/stat.h>
36 #include "namazu.h"
37 #include "util.h"
38 
39 /* load the whole of file */
load_headfoot(uchar * fname)40 uchar *load_headfoot(uchar *fname)
41 {
42     uchar *buf;
43     FILE *fp;
44     struct stat fstatus;
45 
46     stat(fname, &fstatus);
47     fp = fopen(fname, "rb");
48     if (fp == NULL) {
49         fprintf(stderr, "warning: Can't open %s\n", fname);
50         return 0;
51     }
52     buf = (uchar *) malloc(fstatus.st_size + 1);
53     if (buf == NULL) {
54 	 error("cat_head_or_foot(malloc)");
55     }
56     if (fread(buf, sizeof(uchar), fstatus.st_size, fp) == 0
57 	&& fstatus.st_size != 0)
58         error("cat_head_or_foot(fread)");
59     *(buf + fstatus.st_size) = '\0';
60     fclose(fp);
61     return buf;
62 }
63 
64 /* compare the element
65  * some measure of containing LF or redundant spaces are acceptable.
66  * igonore cases
67  */
cmp_element(uchar * s1,uchar * s2)68 int cmp_element(uchar *s1, uchar *s2)
69 {
70     for (; *s1 && *s2; s1++, s2++) {
71         if (*s2 == ' ') {
72             while (*s1 == ' ' || *s1 == '\t' || *s1 == '\n' || *s1 == '\r') {
73                 s1++;
74             }
75             s2++;
76         }
77         if (toupper(*s1) != toupper(*s2)) {
78             break;
79         }
80     }
81     if (*s2 == '\0') {
82         return 0;
83     } else {
84         return 1;
85     }
86 }
87 
88 #define iseuc(c)  ((c) >= 0xa1 && (c) <= 0xfe)
89 
90 /* replace <INPUT TYPE="TEXT" NAME="key"  VALUE="hogehoge"> */
replace_key_value(uchar * p,uchar * orig_query)91 int replace_key_value(uchar *p, uchar *orig_query)
92 {
93     uchar query[BUFSIZE];
94 
95     strcpy(query, orig_query);
96 
97     if (!cmp_element(p, "INPUT TYPE=\"TEXT\" NAME=\"key\"")) {
98         for (; *p; p++)
99             fputc(*p, stdout);
100         printf(" VALUE=\"");
101         fputx(query, stdout);
102         fputs("\"", stdout);
103         return 0;
104     }
105     return 1;
106 }
107 
108 /* replace <FORM METHOD="GET" ACTION="/somewhere/namazu.cgi"> */
replace_action(uchar * p)109 int replace_action(uchar *p)
110 {
111     if (!cmp_element(p, "FORM METHOD=\"GET\"")) {
112         char *script_name = getenv("SCRIPT_NAME");
113         if (script_name) {
114             printf("FORM METHOD=\"GET\" ACTION=\"%s\"", script_name);
115             return 0;
116         } else {
117             return 1;
118         }
119     }
120     return 1;
121 }
122 
123 /* delete string */
delete_str(uchar * s,uchar * d)124 void delete_str(uchar *s, uchar *d)
125 {
126     int l;
127     uchar *tmp;
128 
129     l = strlen(d);
130     for (tmp = s; *tmp; tmp++) {
131         if (!strncmp(tmp, d, l)) {
132             strcpy(tmp, tmp + l);
133             tmp--;
134         }
135     }
136     chop(s);
137 }
138 
get_value(uchar * s,uchar * v)139 void get_value(uchar *s, uchar *v)
140 {
141     *v = '\0';
142     for (; *s; s++) {
143         if (!strncmp(s, "VALUE=\"", 7)) {
144             for (s += 7; *s && *s != '"'; s++, v++) {
145                 *v = *s;
146             }
147             *v = '\0';
148             return;
149         }
150     }
151 }
152 
get_select_name(uchar * s,uchar * v)153 void get_select_name(uchar *s, uchar *v)
154 {
155     *v = '\0';
156     for (; *s; s++) {
157         if (!cmp_element(s, "SELECT NAME=\"")) {
158             s = strchr(s, '"') + 1;
159             for (; *s && *s != '"'; s++, v++) {
160                 *v = *s;
161             }
162             *v = '\0';
163             return;
164         }
165     }
166 }
167 
str_backward_cmp(uchar * str1,uchar * str2)168 int str_backward_cmp(uchar *str1, uchar *str2)
169 {
170     uchar *p, *q;
171 
172     p = str1 + strlen(str1) -1;
173     q = str2 + strlen(str2) -1;
174 
175     for (; p >= str1 && q >= str2; p--, q--) {
176         if (*p != *q) {
177             return 1;
178         }
179     }
180 #if  defined(WIN32) || defined(OS2)
181     if (*q != '\\' && *q != '/') {
182 #else
183     if (*q != '/') {
184 #endif
185 	return 1;
186     }
187     return 0;
188 }
189 
190 
191 int select_option(uchar *s, uchar *name, uchar *subquery)
192 {
193     uchar value[BUFSIZE];
194 
195     if (!cmp_element(s, "OPTION")) {
196         delete_str(s,"SELECTED ");
197         fputs(s, stdout);
198         get_value(s, value);
199         if (!strcmp(name, "format")) {
200             if (!strcmp(value, "short") && ShortFormat) {
201                 fputs(" SELECTED", stdout);
202             } else if (!strcmp(value, "long") && (!ShortFormat)) {
203                 fputs(" SELECTED", stdout);
204             }
205         } else if (!strcmp(name, "sort")) {
206             if (!strcmp(value, "later") && LaterOrder && !ScoreSort) {
207                 fputs(" SELECTED", stdout);
208             } else if (!strcmp(value, "earlier")  && !LaterOrder && !ScoreSort)
209             {
210                 fputs(" SELECTED", stdout);
211             } else if (!strcmp(value, "score") && ScoreSort) {
212                 fputs(" SELECTED", stdout);
213             }
214         } else if (!strcmp(name, "lang")) {
215             if (!strcmp(value, Lang)) {
216                 fputs(" SELECTED", stdout);
217             }
218         } else if (!strcmp(name, "dbname")) {
219             if (*DbNames[0] && !str_backward_cmp(value, DbNames[0])) {
220                 fputs(" SELECTED", stdout);
221             }
222         } else if (!strcmp(name, "subquery")) {
223             if (!strcmp(value, subquery)) {
224                 fputs(" SELECTED", stdout);
225             }
226         } else if (!strcmp(name, "max")) {
227             if (atoi(value) == HListMax) {
228                 fputs(" SELECTED", stdout);
229             }
230         }
231         return 0;
232     }
233     return 1;
234 }
235 
236 /* mark CHECKBOX of dbname with CHECKED */
237 int check_checkbox(uchar *s)
238 {
239     uchar value[BUFSIZE];
240     int i;
241 
242     if (!cmp_element(s, "INPUT TYPE=\"CHECKBOX\" NAME=\"dbname\"")) {
243         uchar *pp;
244         int db_count, searched;
245 
246         delete_str(s,"CHECKED");
247         fputs(s, stdout);
248         get_value(s, value);
249         for (pp = value, db_count = searched = 0 ; *pp ;db_count++) {
250             uchar name[BUFSIZE], *x;
251             if ((x = strchr(pp, (int)','))) {
252                 *x = '\0';
253                 strcpy(name, pp);
254                 pp = x + 1;
255             } else {
256                 strcpy(name, pp);
257                 pp += strlen(pp);
258             }
259             for (i = 0; i < DbNumber; i++) {
260                 if (!str_backward_cmp(name, DbNames[i])) {
261                     searched++;
262                     break;
263                 }
264             }
265         }
266         if (db_count == searched) {
267             printf(" CHECKED");
268         }
269         return 0;
270     }
271     return 1;
272 }
273 
274 /* treat an HTML tag */
275 void treat_tag(uchar *p, uchar *q, uchar *query,
276                uchar *select_name, uchar *subquery)
277 {
278     uchar tmp[BUFSIZE];
279     int l;
280 
281     l = q - p + 1;
282     if (l < BUFSIZE - 1) {
283         strncpy(tmp, p, l);
284         tmp[l] = '\0';
285         if (!replace_key_value(tmp, query))
286             return;
287         if (!replace_action(tmp))
288             return;
289         if (!select_option(tmp, select_name, subquery))
290             return;
291         if (!check_checkbox(tmp))
292             return;
293         get_select_name(tmp, select_name);
294     }
295     fputs(tmp, stdout);
296 }
297 
298 /* display header or footer file.
299  * very foolish
300  */
301 void cat_head_or_foot(uchar * fname, uchar * query, uchar *subquery)
302 {
303     uchar *buf, *p, *q, name[BUFSIZE] = "";
304     int f, f2;
305     buf = load_headfoot(fname);
306     if (buf == NULL) {
307         return;
308     }
309 
310     for (p = buf, f = f2 = 0; *p; p++) {
311         if (BASE_URL[0] && !strncmp(p, "\n</HEAD>", 8)) {
312             printf("\n<BASE HREF=\"%s\">", BASE_URL);
313         }
314 
315         if (!f && *p == '<') {
316             if (!strncmp(p, "</TITLE>", 8)) {
317 		if (*query != '\0') {
318 		    printf(": &lt;");
319 		    fputx(query, stdout);
320 		    printf("&gt;");
321 		}
322 		printf("</TITLE>\n");
323                 p = strchr(p, '>');
324                 continue;
325             }
326 
327             if (!IsCGI && !ForcePrintForm && !strncmp(p, "<FORM ",  6)) f2 = 1;
328             if (!IsCGI && !ForcePrintForm && !strncmp(p, "</FORM>", 7))
329             {f2 = 0; p += 6; continue;}
330             if (f2) continue;
331             /* In case of file's encoding is ISO-2022-JP,
332                the problem occurs if JIS X 208 characters in element */
333             q = (uchar *)strchr(p, (int)'>');
334             fputs("<", stdout);
335             treat_tag(p + 1, q - 1, query, name, subquery);
336             fputs(">", stdout);
337             p = q;
338         } else {
339             if (!strncmp(p, "\x1b$", 2)
340                 && (*(p + 2) == 'B' || *(p + 2) == '@'))
341             {
342                 f = 1;
343             } else if (!strncmp(p, "\x1b(", 2) &&
344                        (*(p + 2) == 'J' || *(p + 2) == 'B' || *(p + 2) == 'H'))
345             {
346                 f = 0;
347             }
348             if (f2) continue;
349             fputc(*p, stdout);
350         }
351     }
352     free(buf);
353 }
354 
355