/* $Id: backend.c,v 1.3 2001/11/20 17:49:23 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* ); /* 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 }, }; /* Prototype declaration of functions to manipulate configuration variables */ static void set_column( TextList* ); static void show_column( TextList* ); /* 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 }, }; 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_str = Strnew_charp( "
\n" );
    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" ) ){
	    Strcat( backend_halfdump_str,
		    Sprintf( "
%s\n", buf->buffername ) ); print_headers( buf, backend_halfdump_str->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" ); Strfputs( backend_halfdump_str, stdout ); } 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 MOUSE use_mouse = FALSE; #endif /* 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; }