aboutsummaryrefslogtreecommitdiffstats
path: root/backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend.c')
-rw-r--r--backend.c405
1 files changed, 405 insertions, 0 deletions
diff --git a/backend.c b/backend.c
new file mode 100644
index 0000000..3befd72
--- /dev/null
+++ b/backend.c
@@ -0,0 +1,405 @@
+#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* );
+
+
+/* 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( "<pre>\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( "</pre><title>%s</title>\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 );
+ 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 ){
+ deleteFiles();
+#ifdef USE_COOKIE
+ save_cookies();
+#endif /* USE_COOKIE */
+ 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;
+ extern int w3m_dump; /* Declared in main.c. */
+
+ w3m_dump = FALSE;
+ w3m_halfdump = FALSE;
+ if (COLS == 0) COLS = 80;
+#ifdef MOUSE
+ mouse_end();
+ 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;
+}