/* $Id: backend.c,v 1.7 2001/12/27 18:22:59 ukai Exp $ */ #include #include #include #include #include "fm.h" #include "gc.h" #include "terms.h" /* Prototype declaration of internal functions */ #ifdef HAVE_READLINE #include #else /* ! HAVE_READLINE */ static char *readline(char *); #endif /* ! HAVE_READLINE */ static TextList *split(char *); /* Prototype declaration of command functions */ static void get(TextList *); static void post(TextList *); static void set(TextList *); static void show(TextList *); static void quit(TextList *); static void help(TextList *); /* *INDENT-OFF* */ /* Table of command functions */ struct { const char *name; const char *option_string; const char *help; void (*func)(TextList*); } command_table[] = { {"get", "[-download_only] URL", "Retrieve URL.", get}, {"post", "[-download_only] [-target TARGET] [-charset CHARSET]" " [-enctype ENCTYPE] [-body BODY] [-boundary BOUNDARY] [-length LEN] URL", "Retrieve URL.", post}, {"set", "VARIABLE VALUE", "Set VALUE to VARIABLE.", set}, {"show", "VARIABLE", "Show value of VARIABLE.", show}, {"quit", "", "Quit program.", quit}, {"help", "", "Display help messages.", help}, {NULL, NULL, NULL, NULL}, }; /* *INDENT-ON* */ /* Prototype declaration of functions to manipulate configuration variables */ static void set_column(TextList *); static void show_column(TextList *); /* *INDENT-OFF* */ /* Table of configuration variables */ struct { const char *name; void (*set_func)(TextList*); void (*show_func)(TextList*); } variable_table[] = { {"column", set_column, show_column}, {NULL, NULL, NULL}, }; /* *INDENT-ON* */ static char * get_mime_charset_name(int coding) { Str r; switch (coding) { case CODE_EUC: r = Strnew_charp("euc-japan"); break; case CODE_SJIS: r = Strnew_charp("shift_jis"); break; case CODE_JIS_m: case CODE_JIS_n: case CODE_JIS_N: case CODE_JIS_j: case CODE_JIS_J: r = Strnew_charp("iso-2022-jp"); break; default: return NULL; } return r->ptr; } static void print_headers(Buffer *buf, int len) { TextListItem *tp; if (buf->document_header) { for (tp = buf->document_header->first; tp; tp = tp->next) printf("%s\n", tp->ptr); } printf("w3m-content-type: %s\n", buf->type); #ifdef JP_CHARSET if (buf->document_code) printf("w3m-content-charset: %s\n", get_mime_charset_name(buf->document_code)); #endif if (len > 0) printf("w3m-content-length: %d\n", len); } static void print_formlist(int fid, FormList *fp) { Str s = Sprintf("w3m-form: (formlist (fid %d) (action \"%s\") (method \"%s\")", fid, fp->action->ptr, (fp->method == FORM_METHOD_POST) ? "post" : ((fp->method == FORM_METHOD_INTERNAL) ? "internal" : "get")); if (fp->target) Strcat(s, Sprintf(" (target \"%s\")", fp->target)); if (fp->charset) Strcat(s, Sprintf(" (charset '%s)", get_mime_charset_name(fp->charset))); if (fp->enctype == FORM_ENCTYPE_MULTIPART) Strcat_charp(s, " (enctype \"multipart/form-data\")"); if (fp->boundary) Strcat(s, Sprintf(" (boundary \"%s\")", fp->boundary)); Strcat_charp(s, ")\n"); Strfputs(s, stdout); } static void internal_get(char *url, int flag, FormList *request) { Buffer *buf; backend_halfdump_buf = NULL; do_download = flag; buf = loadGeneralFile(url, NULL, NO_REFERER, 0, request); do_download = FALSE; if (buf != NULL && buf != NO_BUFFER) { if (!strcasecmp(buf->type, "text/html") && backend_halfdump_buf) { TextLineListItem *p; Str first, last; int len = 0; for (p = backend_halfdump_buf->first; p; p = p->next) len += p->ptr->line->length + 1; first = Strnew_charp("
\n");
	    last = Strnew_m_charp("
", html_quote(buf->buffername), "\n", NULL); print_headers(buf, len + first->length + last->length); if (buf->formlist) { FormList *fp; int fid = 0; for (fp = buf->formlist; fp; fp = fp->next) fid++; for (fp = buf->formlist; fp; fp = fp->next) print_formlist(--fid, fp); } printf("\n"); printf("%s", first->ptr); for (p = backend_halfdump_buf->first; p; p = p->next) printf("%s\n", p->ptr->line->ptr); printf("%s", last->ptr); } else { if (!strcasecmp(buf->type, "text/plain")) { Line *lp; int len = 0; for (lp = buf->firstLine; lp; lp = lp->next) { len += lp->len; if (lp->lineBuf[lp->len - 1] != '\n') len++; } print_headers(buf, len); printf("\n"); saveBuffer(buf, stdout); } else { print_headers(buf, 0); } } } } /* Command: get */ static void get(TextList *argv) { char *p, *url = NULL; int flag = FALSE; while ((p = popText(argv))) { if (!strcasecmp(p, "-download_only")) flag = TRUE; else url = p; } if (url) { internal_get(url, flag, NULL); } } /* Command: post */ static void post(TextList *argv) { FormList *request; char *p, *target = NULL, *charset = NULL, *enctype = NULL, *body = NULL, *boundary = NULL, *url = NULL; int flag = FALSE, length = 0; while ((p = popText(argv))) { if (!strcasecmp(p, "-download_only")) flag = TRUE; else if (!strcasecmp(p, "-target")) target = popText(argv); else if (!strcasecmp(p, "-charset")) charset = popText(argv); else if (!strcasecmp(p, "-enctype")) enctype = popText(argv); else if (!strcasecmp(p, "-body")) body = popText(argv); else if (!strcasecmp(p, "-boundary")) boundary = popText(argv); else if (!strcasecmp(p, "-length")) length = atol(popText(argv)); else url = p; } if (url) { request = newFormList(NULL, "post", charset, enctype, target, NULL, NULL); request->body = body; request->boundary = boundary; request->length = (length > 0) ? length : (body ? strlen(body) : 0); internal_get(url, flag, request); } } /* Command: set */ static void set(TextList *argv) { if (argv->nitem > 1) { int i; for (i = 0; variable_table[i].name; i++) { if (!strcasecmp(variable_table[i].name, argv->first->ptr)) { popText(argv); if (variable_table[i].set_func) variable_table[i].set_func(argv); break; } } } } /* Command: show */ static void show(TextList *argv) { if (argv->nitem >= 1) { int i; for (i = 0; variable_table[i].name; i++) { if (!strcasecmp(variable_table[i].name, argv->first->ptr)) { popText(argv); if (variable_table[i].show_func) variable_table[i].show_func(argv); break; } } } } /* Command: quit */ static void quit(TextList *argv) { #ifdef USE_COOKIE save_cookies(); #endif /* USE_COOKIE */ w3m_exit(0); } /* Command: help */ static void help(TextList *argv) { int i; for (i = 0; command_table[i].name; i++) printf("%s %s\n %s\n", command_table[i].name, command_table[i].option_string, command_table[i].help); } /* Sub command: set COLS */ static void set_column(TextList *argv) { if (argv->nitem == 1) { COLS = atol(argv->first->ptr); } } /* Sub command: show COLS */ static void show_column(TextList *argv) { fprintf(stdout, "column=%d\n", COLS); } /* Call appropriate command function based on given string */ static void call_command_function(char *str) { int i; TextList *argv = split(str); if (argv->nitem > 0) { for (i = 0; command_table[i].name; i++) { if (!strcasecmp(command_table[i].name, argv->first->ptr)) { popText(argv); if (command_table[i].func) command_table[i].func(argv); break; } } } } /* Main function */ int backend(void) { char *str; w3m_dump = 0; if (COLS == 0) COLS = 80; #ifdef USE_MOUSE use_mouse = FALSE; #endif /* USE_MOUSE */ if (backend_batch_commands) { while ((str = popText(backend_batch_commands))) call_command_function(str); } else { while ((str = readline("w3m> "))) call_command_function(str); } quit(NULL); return 0; } /* Dummy function of readline(). */ #ifndef HAVE_READLINE static char * readline(char *prompt) { Str s; fputs(prompt, stdout); fflush(stdout); s = Strfgets(stdin); if (feof(stdin) && (strlen(s->ptr) == 0)) return NULL; else return s->ptr; } #endif /* ! HAVE_READLINE */ /* Splits a string into a list of tokens and returns that list. */ static TextList * split(char *p) { int in_double_quote = FALSE, in_single_quote = FALSE; Str s = Strnew(); TextList *tp = newTextList(); for (; *p; p++) { switch (*p) { case '"': if (in_single_quote) Strcat_char(s, '"'); else in_double_quote = !in_double_quote; break; case '\'': if (in_double_quote) Strcat_char(s, '\''); else in_single_quote = !in_single_quote; break; case '\\': if (!in_single_quote) { /* Process escape characters. */ p++; switch (*p) { case 't': Strcat_char(s, '\t'); break; case 'r': Strcat_char(s, '\r'); break; case 'f': Strcat_char(s, '\f'); break; case 'n': Strcat_char(s, '\n'); break; case '\0': goto LAST; default: Strcat_char(s, *p); } } else { Strcat_char(s, *p); } break; case ' ': case '\t': case '\r': case '\f': case '\n': /* Separators are detected. */ if (in_double_quote || in_single_quote) { Strcat_char(s, *p); } else if (s->length > 0) { pushText(tp, s->ptr); s = Strnew(); } break; default: Strcat_char(s, *p); } } LAST: if (s->length > 0) pushText(tp, s->ptr); return tp; }