403 lines
9.4 KiB
C
403 lines
9.4 KiB
C
/* $Id: backend.c,v 1.4 2001/11/21 19:24:35 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* );
|
|
|
|
|
|
/* 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, 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;
|
|
}
|