backend.c (8584B)
1 /* $Id$ */ 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 (is_html_type(buf->type) && 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 = DEFAULT_COLS; 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 }