Intial commit
[profile/ivi/w3m.git] / backend.c
1 /* $Id: backend.c,v 1.13 2003/09/22 21:02:16 ukai Exp $ */
2 #include <stdio.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include "fm.h"
6 #include <gc.h>
7 #include "terms.h"
8
9
10 /* Prototype declaration of internal functions */
11 #ifdef HAVE_READLINE
12 #include <readline/readline.h>
13 #else                           /* ! HAVE_READLINE */
14 static char *readline(char *);
15 #endif                          /* ! HAVE_READLINE */
16 static TextList *split(char *);
17
18
19 /* Prototype declaration of command functions */
20 static void get(TextList *);
21 static void post(TextList *);
22 static void set(TextList *);
23 static void show(TextList *);
24 static void quit(TextList *);
25 static void help(TextList *);
26
27
28 /* *INDENT-OFF* */
29 /* Table of command functions */
30 struct {
31     const char *name;
32     const char *option_string;
33     const char *help;
34     void (*func)(TextList*);
35 } command_table[] = {
36     {"get", "[-download_only] URL", "Retrieve URL.", get},
37     {"post", "[-download_only] [-target TARGET] [-charset CHARSET]"
38      " [-enctype ENCTYPE] [-body BODY] [-boundary BOUNDARY] [-length LEN] URL",
39      "Retrieve URL.", post},
40     {"set", "VARIABLE VALUE", "Set VALUE to VARIABLE.", set},
41     {"show", "VARIABLE", "Show value of VARIABLE.", show},
42     {"quit", "", "Quit program.", quit},
43     {"help", "", "Display help messages.", help},
44     {NULL, NULL, NULL, NULL},
45 };
46 /* *INDENT-ON* */
47
48 /* Prototype declaration of functions to manipulate configuration variables */
49 static void set_column(TextList *);
50 static void show_column(TextList *);
51
52
53 /* *INDENT-OFF* */
54 /* Table of configuration variables */
55 struct {
56     const char *name;
57     void (*set_func)(TextList*);
58     void (*show_func)(TextList*);
59 } variable_table[] = {
60     {"column", set_column, show_column},
61     {NULL, NULL, NULL},
62 };
63 /* *INDENT-ON* */
64
65 static void
66 print_headers(Buffer *buf, int len)
67 {
68     TextListItem *tp;
69
70     if (buf->document_header) {
71         for (tp = buf->document_header->first; tp; tp = tp->next)
72             printf("%s\n", tp->ptr);
73     }
74     printf("w3m-current-url: %s\n", parsedURL2Str(&buf->currentURL)->ptr);
75     if (buf->baseURL)
76         printf("w3m-base-url: %s\n", parsedURL2Str(buf->baseURL)->ptr);
77     printf("w3m-content-type: %s\n", buf->type);
78 #ifdef USE_M17N
79     if (buf->document_charset)
80         printf("w3m-content-charset: %s\n",
81                wc_ces_to_charset(buf->document_charset));
82 #endif
83     if (len > 0)
84         printf("w3m-content-length: %d\n", len);
85 }
86
87
88 static void
89 internal_get(char *url, int flag, FormList *request)
90 {
91     Buffer *buf;
92
93     backend_halfdump_buf = NULL;
94     do_download = flag;
95     buf = loadGeneralFile(url, NULL, NO_REFERER, 0, request);
96     do_download = FALSE;
97     if (buf != NULL && buf != NO_BUFFER) {
98         if (!strcasecmp(buf->type, "text/html") && backend_halfdump_buf) {
99             TextLineListItem *p;
100             Str first, last;
101             int len = 0;
102             for (p = backend_halfdump_buf->first; p; p = p->next) {
103                 p->ptr->line = Str_conv_to_halfdump(p->ptr->line);
104                 len += p->ptr->line->length + 1;
105             }
106             first = Strnew_charp("<pre>\n");
107             last = Strnew_m_charp("</pre><title>", html_quote(buf->buffername),
108                                   "</title>\n", NULL);
109             print_headers(buf, len + first->length + last->length);
110             printf("\n");
111             printf("%s", first->ptr);
112             for (p = backend_halfdump_buf->first; p; p = p->next)
113                 printf("%s\n", p->ptr->line->ptr);
114             printf("%s", last->ptr);
115         }
116         else {
117             if (!strcasecmp(buf->type, "text/plain")) {
118                 Line *lp;
119                 int len = 0;
120                 for (lp = buf->firstLine; lp; lp = lp->next) {
121                     len += lp->len;
122                     if (lp->lineBuf[lp->len - 1] != '\n')
123                         len++;
124                 }
125                 print_headers(buf, len);
126                 printf("\n");
127                 saveBuffer(buf, stdout, TRUE);
128             }
129             else {
130                 print_headers(buf, 0);
131             }
132         }
133     }
134 }
135
136
137 /* Command: get */
138 static void
139 get(TextList *argv)
140 {
141     char *p, *url = NULL;
142     int flag = FALSE;
143
144     while ((p = popText(argv))) {
145         if (!strcasecmp(p, "-download_only"))
146             flag = TRUE;
147         else
148             url = p;
149     }
150     if (url) {
151         internal_get(url, flag, NULL);
152     }
153 }
154
155
156 /* Command: post */
157 static void
158 post(TextList *argv)
159 {
160     FormList *request;
161     char *p, *target = NULL, *charset = NULL,
162         *enctype = NULL, *body = NULL, *boundary = NULL, *url = NULL;
163     int flag = FALSE, length = 0;
164
165     while ((p = popText(argv))) {
166         if (!strcasecmp(p, "-download_only"))
167             flag = TRUE;
168         else if (!strcasecmp(p, "-target"))
169             target = popText(argv);
170         else if (!strcasecmp(p, "-charset"))
171             charset = popText(argv);
172         else if (!strcasecmp(p, "-enctype"))
173             enctype = popText(argv);
174         else if (!strcasecmp(p, "-body"))
175             body = popText(argv);
176         else if (!strcasecmp(p, "-boundary"))
177             boundary = popText(argv);
178         else if (!strcasecmp(p, "-length"))
179             length = atol(popText(argv));
180         else
181             url = p;
182     }
183     if (url) {
184         request =
185             newFormList(NULL, "post", charset, enctype, target, NULL, NULL);
186         request->body = body;
187         request->boundary = boundary;
188         request->length = (length > 0) ? length : (body ? strlen(body) : 0);
189         internal_get(url, flag, request);
190     }
191 }
192
193
194 /* Command: set */
195 static void
196 set(TextList *argv)
197 {
198     if (argv->nitem > 1) {
199         int i;
200         for (i = 0; variable_table[i].name; i++) {
201             if (!strcasecmp(variable_table[i].name, argv->first->ptr)) {
202                 popText(argv);
203                 if (variable_table[i].set_func)
204                     variable_table[i].set_func(argv);
205                 break;
206             }
207         }
208     }
209 }
210
211
212 /* Command: show */
213 static void
214 show(TextList *argv)
215 {
216     if (argv->nitem >= 1) {
217         int i;
218         for (i = 0; variable_table[i].name; i++) {
219             if (!strcasecmp(variable_table[i].name, argv->first->ptr)) {
220                 popText(argv);
221                 if (variable_table[i].show_func)
222                     variable_table[i].show_func(argv);
223                 break;
224             }
225         }
226     }
227 }
228
229
230 /* Command: quit */
231 static void
232 quit(TextList *argv)
233 {
234 #ifdef USE_COOKIE
235     save_cookies();
236 #endif                          /* USE_COOKIE */
237     w3m_exit(0);
238 }
239
240
241 /* Command: help */
242 static void
243 help(TextList *argv)
244 {
245     int i;
246     for (i = 0; command_table[i].name; i++)
247         printf("%s %s\n    %s\n",
248                command_table[i].name,
249                command_table[i].option_string, command_table[i].help);
250 }
251
252
253 /* Sub command: set COLS */
254 static void
255 set_column(TextList *argv)
256 {
257     if (argv->nitem == 1) {
258         COLS = atol(argv->first->ptr);
259     }
260 }
261
262 /* Sub command: show COLS */
263 static void
264 show_column(TextList *argv)
265 {
266     fprintf(stdout, "column=%d\n", COLS);
267 }
268
269
270 /* Call appropriate command function based on given string */
271 static void
272 call_command_function(char *str)
273 {
274     int i;
275     TextList *argv = split(str);
276     if (argv->nitem > 0) {
277         for (i = 0; command_table[i].name; i++) {
278             if (!strcasecmp(command_table[i].name, argv->first->ptr)) {
279                 popText(argv);
280                 if (command_table[i].func)
281                     command_table[i].func(argv);
282                 break;
283             }
284         }
285     }
286 }
287
288
289 /* Main function */
290 int
291 backend(void)
292 {
293     char *str;
294
295     w3m_dump = 0;
296     if (COLS == 0)
297         COLS = 80;
298 #ifdef USE_MOUSE
299     use_mouse = FALSE;
300 #endif                          /* USE_MOUSE */
301
302     if (backend_batch_commands) {
303         while ((str = popText(backend_batch_commands)))
304             call_command_function(str);
305     }
306     else {
307         while ((str = readline("w3m> ")))
308             call_command_function(str);
309     }
310     quit(NULL);
311     return 0;
312 }
313
314
315 /* Dummy function of readline(). */
316 #ifndef HAVE_READLINE
317 static char *
318 readline(char *prompt)
319 {
320     Str s;
321     fputs(prompt, stdout);
322     fflush(stdout);
323     s = Strfgets(stdin);
324     if (feof(stdin) && (strlen(s->ptr) == 0))
325         return NULL;
326     else
327         return s->ptr;
328 }
329 #endif                          /* ! HAVE_READLINE */
330
331
332 /* Splits a string into a list of tokens and returns that list. */
333 static TextList *
334 split(char *p)
335 {
336     int in_double_quote = FALSE, in_single_quote = FALSE;
337     Str s = Strnew();
338     TextList *tp = newTextList();
339
340     for (; *p; p++) {
341         switch (*p) {
342         case '"':
343             if (in_single_quote)
344                 Strcat_char(s, '"');
345             else
346                 in_double_quote = !in_double_quote;
347             break;
348         case '\'':
349             if (in_double_quote)
350                 Strcat_char(s, '\'');
351             else
352                 in_single_quote = !in_single_quote;
353             break;
354         case '\\':
355             if (!in_single_quote) {
356                 /* Process escape characters. */
357                 p++;
358                 switch (*p) {
359                 case 't':
360                     Strcat_char(s, '\t');
361                     break;
362                 case 'r':
363                     Strcat_char(s, '\r');
364                     break;
365                 case 'f':
366                     Strcat_char(s, '\f');
367                     break;
368                 case 'n':
369                     Strcat_char(s, '\n');
370                     break;
371                 case '\0':
372                     goto LAST;
373                 default:
374                     Strcat_char(s, *p);
375                 }
376             }
377             else {
378                 Strcat_char(s, *p);
379             }
380             break;
381         case ' ':
382         case '\t':
383         case '\r':
384         case '\f':
385         case '\n':
386             /* Separators are detected. */
387             if (in_double_quote || in_single_quote) {
388                 Strcat_char(s, *p);
389             }
390             else if (s->length > 0) {
391                 pushText(tp, s->ptr);
392                 s = Strnew();
393             }
394             break;
395         default:
396             Strcat_char(s, *p);
397         }
398     }
399   LAST:
400     if (s->length > 0)
401         pushText(tp, s->ptr);
402     return tp;
403 }