456 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			456 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* $Id: backend.c,v 1.7 2001/12/27 18:22:59 ukai Exp $ */
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <sys/types.h>
 | |
| #include <ctype.h>
 | |
| #include "fm.h"
 | |
| #include "gc.h"
 | |
| #include "terms.h"
 | |
| 
 | |
| 
 | |
| /* Prototype declaration of internal functions */
 | |
| #ifdef HAVE_READLINE
 | |
| #include <readline/readline.h>
 | |
| #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("<pre>\n");
 | |
| 	    last = Strnew_m_charp("</pre><title>", html_quote(buf->buffername),
 | |
| 				  "</title>\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;
 | |
| }
 |