* file.c (close_textarea): delete (HTMLtagproc1): rewrite delete HTML_EOL move HTML_LISTING, HTML_N_LISTING add HTML_PRE_PLAIN, HTML_N_PRE_PLAIN add HTML_PLAINTEXT end_tag (HTMLlineproc0): s/str/line/ rewrite (completeHTMLstream): </textarea> if necessary * fm.h (struct readbuffer): delete ignore_tag add end_tag (RB_XMPMODE): deleted (RB_LSTMODE): deleted (RB_SCRIPT): added (RB_STYLE): added (RB_*): renumber (R_ST_EOL): added (R_ST_*): renumber (ST_IS_TAG): check R_ST_EOL * form.c (form_fputs_decode): remove <eol> handling * frame.c (newFrame): remove_space() (CASE_TABLE_TAG): added (createFrameFile): rewrite * html.c (TagMAP): delete eol add pre_plain, /pre_plain * html.h (HTML_EOL): deleted (HTML_PRE_PLAIN): added (HTML_N_PRE_PLAIN): added * table.c (visible_length): rewrite (visible_length_plain): added (maximum_visible_length_plain): added (do_refill): R_ST_EOL (table_close_select): end_tag (table_close_textarea): end_tag (TAG_ACTION_PLAIN): added (feed_table_tag): rewrite (feed_table): rewrite * table.h (TBLM_*) reassign (struct table_mode): delete ignore_tag add end_tag * tagtable.tab (eol): deleted (pre_plain): added (/pre_plain): added From: Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp>
		
			
				
	
	
		
			884 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			884 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Id: form.c,v 1.25 2002/12/03 15:35:10 ukai Exp $ */
 | 
						|
/* 
 | 
						|
 * HTML forms
 | 
						|
 */
 | 
						|
#include "fm.h"
 | 
						|
#include "parsetag.h"
 | 
						|
#include "parsetagx.h"
 | 
						|
#include "myctype.h"
 | 
						|
#include "local.h"
 | 
						|
 | 
						|
#ifndef HAVE_LSTAT
 | 
						|
/* lstat is identical to stat, only the link itself is statted, not the file
 | 
						|
 * that is obtained by tracing the links. But on OS/2 systems, there is no
 | 
						|
 * differences. */
 | 
						|
#define lstat stat
 | 
						|
#endif				/* not HAVE_LSTAT */
 | 
						|
 | 
						|
extern Str *textarea_str;
 | 
						|
#ifdef MENU_SELECT
 | 
						|
extern FormSelectOption *select_option;
 | 
						|
#include "menu.h"
 | 
						|
#endif				/* MENU_SELECT */
 | 
						|
 | 
						|
/* *INDENT-OFF* */
 | 
						|
struct {
 | 
						|
    char *action;
 | 
						|
    void (*rout)(struct parsed_tagarg *);
 | 
						|
} internal_action[] = {
 | 
						|
    {"map", follow_map}, 
 | 
						|
    {"option", panel_set_option},
 | 
						|
#ifdef USE_COOKIE
 | 
						|
    {"cookie", set_cookie_flag},
 | 
						|
#endif				/* USE_COOKIE */
 | 
						|
    {"download", download_action},
 | 
						|
    {"none", NULL},
 | 
						|
    {NULL, NULL},
 | 
						|
};
 | 
						|
/* *INDENT-ON* */
 | 
						|
 | 
						|
struct form_list *
 | 
						|
newFormList(char *action, char *method, char *charset, char *enctype,
 | 
						|
	    char *target, char *name, struct form_list *_next)
 | 
						|
{
 | 
						|
    struct form_list *l;
 | 
						|
    Str a = Strnew_charp(action);
 | 
						|
    int m = FORM_METHOD_GET;
 | 
						|
    int e = FORM_ENCTYPE_URLENCODED;
 | 
						|
    int c = 0;
 | 
						|
 | 
						|
    if (method == NULL || !strcasecmp(method, "get"))
 | 
						|
	m = FORM_METHOD_GET;
 | 
						|
    else if (!strcasecmp(method, "post"))
 | 
						|
	m = FORM_METHOD_POST;
 | 
						|
    else if (!strcasecmp(method, "internal"))
 | 
						|
	m = FORM_METHOD_INTERNAL;
 | 
						|
    /* unknown method is regarded as 'get' */
 | 
						|
 | 
						|
    if (enctype != NULL && !strcasecmp(enctype, "multipart/form-data")) {
 | 
						|
	e = FORM_ENCTYPE_MULTIPART;
 | 
						|
	if (m == FORM_METHOD_GET)
 | 
						|
	    m = FORM_METHOD_POST;
 | 
						|
    }
 | 
						|
 | 
						|
    if (charset != NULL)
 | 
						|
	c = *charset;
 | 
						|
 | 
						|
    l = New(struct form_list);
 | 
						|
    l->item = l->lastitem = NULL;
 | 
						|
    l->action = a;
 | 
						|
    l->method = m;
 | 
						|
    l->charset = c;
 | 
						|
    l->enctype = e;
 | 
						|
    l->target = target;
 | 
						|
    l->name = name;
 | 
						|
    l->next = _next;
 | 
						|
    l->nitems = 0;
 | 
						|
    l->body = NULL;
 | 
						|
    l->length = 0;
 | 
						|
    return l;
 | 
						|
}
 | 
						|
 | 
						|
/* 
 | 
						|
 * add <input> element to form_list
 | 
						|
 */
 | 
						|
struct form_item_list *
 | 
						|
formList_addInput(struct form_list *fl, struct parsed_tag *tag)
 | 
						|
{
 | 
						|
    struct form_item_list *item;
 | 
						|
    char *p;
 | 
						|
    int i;
 | 
						|
 | 
						|
    /* if not in <form>..</form> environment, just ignore <input> tag */
 | 
						|
    if (fl == NULL)
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    item = New(struct form_item_list);
 | 
						|
    item->type = FORM_UNKNOWN;
 | 
						|
    item->size = -1;
 | 
						|
    item->rows = 0;
 | 
						|
    item->checked = item->init_checked = 0;
 | 
						|
    item->accept = 0;
 | 
						|
    item->name = NULL;
 | 
						|
    item->value = item->init_value = NULL;
 | 
						|
    item->readonly = 0;
 | 
						|
    if (parsedtag_get_value(tag, ATTR_TYPE, &p)) {
 | 
						|
	item->type = formtype(p);
 | 
						|
	if (item->size < 0 &&
 | 
						|
	    (item->type == FORM_INPUT_TEXT ||
 | 
						|
	     item->type == FORM_INPUT_FILE ||
 | 
						|
	     item->type == FORM_INPUT_PASSWORD))
 | 
						|
	    item->size = FORM_I_TEXT_DEFAULT_SIZE;
 | 
						|
    }
 | 
						|
    if (parsedtag_get_value(tag, ATTR_NAME, &p))
 | 
						|
	item->name = Strnew_charp(p);
 | 
						|
    if (parsedtag_get_value(tag, ATTR_VALUE, &p))
 | 
						|
	item->value = item->init_value = Strnew_charp(p);
 | 
						|
    item->checked = item->init_checked = parsedtag_exists(tag, ATTR_CHECKED);
 | 
						|
    item->accept = parsedtag_exists(tag, ATTR_ACCEPT);
 | 
						|
    parsedtag_get_value(tag, ATTR_SIZE, &item->size);
 | 
						|
    parsedtag_get_value(tag, ATTR_MAXLENGTH, &item->maxlength);
 | 
						|
    item->readonly = parsedtag_exists(tag, ATTR_READONLY);
 | 
						|
    if (parsedtag_get_value(tag, ATTR_TEXTAREANUMBER, &i))
 | 
						|
	item->value = item->init_value = textarea_str[i];
 | 
						|
#ifdef MENU_SELECT
 | 
						|
    if (parsedtag_get_value(tag, ATTR_SELECTNUMBER, &i))
 | 
						|
	item->select_option = select_option[i].first;
 | 
						|
#endif				/* MENU_SELECT */
 | 
						|
    if (parsedtag_get_value(tag, ATTR_ROWS, &p))
 | 
						|
	item->rows = atoi(p);
 | 
						|
    if (item->type == FORM_UNKNOWN) {
 | 
						|
	/* type attribute is missing. Ignore the tag. */
 | 
						|
	return NULL;
 | 
						|
    }
 | 
						|
#ifdef MENU_SELECT
 | 
						|
    if (item->type == FORM_SELECT) {
 | 
						|
	chooseSelectOption(item, item->select_option);
 | 
						|
	item->init_selected = item->selected;
 | 
						|
	item->init_value = item->value;
 | 
						|
	item->init_label = item->label;
 | 
						|
    }
 | 
						|
#endif				/* MENU_SELECT */
 | 
						|
    if (item->type == FORM_INPUT_FILE && item->value && item->value->length) {
 | 
						|
	/* security hole ! */
 | 
						|
	return NULL;
 | 
						|
    }
 | 
						|
    item->parent = fl;
 | 
						|
    item->next = NULL;
 | 
						|
    if (fl->item == NULL) {
 | 
						|
	fl->item = fl->lastitem = item;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	fl->lastitem->next = item;
 | 
						|
	fl->lastitem = item;
 | 
						|
    }
 | 
						|
    if (item->type == FORM_INPUT_HIDDEN)
 | 
						|
	return NULL;
 | 
						|
    fl->nitems++;
 | 
						|
    return item;
 | 
						|
}
 | 
						|
 | 
						|
static char *_formtypetbl[] = {
 | 
						|
    "text", "password", "checkbox", "radio", "submit",
 | 
						|
    "reset", "hidden", "image", "select", "textarea", "button", "file", 0,
 | 
						|
};
 | 
						|
 | 
						|
static char *_formmethodtbl[] = {
 | 
						|
    "GET", "POST", "INTERNAL", "HEAD"
 | 
						|
};
 | 
						|
 | 
						|
char *
 | 
						|
form2str(FormItemList *fi)
 | 
						|
{
 | 
						|
    Str tmp;
 | 
						|
    if (fi->type == FORM_INPUT_SUBMIT ||
 | 
						|
	fi->type == FORM_INPUT_IMAGE || fi->type == FORM_INPUT_BUTTON) {
 | 
						|
	tmp = Strnew_charp(_formmethodtbl[fi->parent->method]);
 | 
						|
	Strcat_char(tmp, ' ');
 | 
						|
	Strcat(tmp, fi->parent->action);
 | 
						|
	return tmp->ptr;
 | 
						|
    }
 | 
						|
    else
 | 
						|
	return _formtypetbl[fi->type];
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
formtype(char *typestr)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    for (i = 0; _formtypetbl[i]; i++) {
 | 
						|
	if (!strcasecmp(typestr, _formtypetbl[i]))
 | 
						|
	    return i;
 | 
						|
    }
 | 
						|
    return FORM_UNKNOWN;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
formRecheckRadio(Anchor *a, Buffer *buf, FormItemList *fi)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    Anchor *a2;
 | 
						|
    FormItemList *f2;
 | 
						|
 | 
						|
    for (i = 0; i < buf->formitem->nanchor; i++) {
 | 
						|
	a2 = &buf->formitem->anchors[i];
 | 
						|
	f2 = (FormItemList *)a2->url;
 | 
						|
	if (f2->parent == fi->parent && f2 != fi &&
 | 
						|
	    f2->type == FORM_INPUT_RADIO && Strcmp(f2->name, fi->name) == 0) {
 | 
						|
	    f2->checked = 0;
 | 
						|
	    formUpdateBuffer(a2, buf, f2);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    fi->checked = 1;
 | 
						|
    formUpdateBuffer(a, buf, fi);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
formResetBuffer(Buffer *buf, AnchorList *formitem)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    Anchor *a;
 | 
						|
    FormItemList *f1, *f2;
 | 
						|
 | 
						|
    if (buf == NULL || buf->formitem == NULL || formitem == NULL)
 | 
						|
	return;
 | 
						|
    for (i = 0; i < buf->formitem->nanchor && i < formitem->nanchor; i++) {
 | 
						|
	a = &buf->formitem->anchors[i];
 | 
						|
	f1 = (FormItemList *)a->url;
 | 
						|
	f2 = (FormItemList *)formitem->anchors[i].url;
 | 
						|
	if (f1->type != f2->type ||
 | 
						|
	    strcmp(((f1->name == NULL) ? "" : f1->name->ptr),
 | 
						|
		   ((f2->name == NULL) ? "" : f2->name->ptr)))
 | 
						|
	    break;		/* What's happening */
 | 
						|
	switch (f1->type) {
 | 
						|
	case FORM_INPUT_TEXT:
 | 
						|
	case FORM_INPUT_PASSWORD:
 | 
						|
	case FORM_INPUT_FILE:
 | 
						|
	case FORM_TEXTAREA:
 | 
						|
	    f1->value = f2->value;
 | 
						|
	    f1->init_value = f2->init_value;
 | 
						|
	    break;
 | 
						|
	case FORM_INPUT_CHECKBOX:
 | 
						|
	case FORM_INPUT_RADIO:
 | 
						|
	    f1->checked = f2->checked;
 | 
						|
	    f1->init_checked = f2->init_checked;
 | 
						|
	    break;
 | 
						|
	case FORM_SELECT:
 | 
						|
#ifdef MENU_SELECT
 | 
						|
	    f1->select_option = f2->select_option;
 | 
						|
	    f1->value = f2->value;
 | 
						|
	    f1->label = f2->label;
 | 
						|
	    f1->selected = f2->selected;
 | 
						|
	    f1->init_value = f2->init_value;
 | 
						|
	    f1->init_label = f2->init_label;
 | 
						|
	    f1->init_selected = f2->init_selected;
 | 
						|
#endif				/* MENU_SELECT */
 | 
						|
	    break;
 | 
						|
	default:
 | 
						|
	    continue;
 | 
						|
	}
 | 
						|
	formUpdateBuffer(a, buf, f1);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
formUpdateBuffer(Anchor *a, Buffer *buf, FormItemList *form)
 | 
						|
{
 | 
						|
    int i, j, k;
 | 
						|
    Buffer save;
 | 
						|
    char *p;
 | 
						|
    int spos, epos, c_len, rows, c_rows, pos, col = 0;
 | 
						|
    Lineprop c_type;
 | 
						|
    Line *l;
 | 
						|
 | 
						|
    copyBuffer(&save, buf);
 | 
						|
    gotoLine(buf, a->start.line);
 | 
						|
    switch (form->type) {
 | 
						|
    case FORM_TEXTAREA:
 | 
						|
    case FORM_INPUT_TEXT:
 | 
						|
    case FORM_INPUT_FILE:
 | 
						|
    case FORM_INPUT_PASSWORD:
 | 
						|
    case FORM_INPUT_CHECKBOX:
 | 
						|
    case FORM_INPUT_RADIO:
 | 
						|
#ifdef MENU_SELECT
 | 
						|
    case FORM_SELECT:
 | 
						|
#endif				/* MENU_SELECT */
 | 
						|
	spos = a->start.pos - 1;
 | 
						|
	epos = a->end.pos;
 | 
						|
	break;
 | 
						|
    default:
 | 
						|
	spos = a->start.pos;
 | 
						|
	epos = a->end.pos - 1;
 | 
						|
    }
 | 
						|
    switch (form->type) {
 | 
						|
    case FORM_INPUT_CHECKBOX:
 | 
						|
    case FORM_INPUT_RADIO:
 | 
						|
	if (form->checked)
 | 
						|
	    buf->currentLine->lineBuf[spos + 1] = '*';
 | 
						|
	else
 | 
						|
	    buf->currentLine->lineBuf[spos + 1] = ' ';
 | 
						|
	break;
 | 
						|
    case FORM_INPUT_TEXT:
 | 
						|
    case FORM_INPUT_FILE:
 | 
						|
    case FORM_INPUT_PASSWORD:
 | 
						|
    case FORM_TEXTAREA:
 | 
						|
#ifdef MENU_SELECT
 | 
						|
    case FORM_SELECT:
 | 
						|
	if (form->type == FORM_SELECT) {
 | 
						|
	    p = form->label->ptr;
 | 
						|
	    updateSelectOption(form, form->select_option);
 | 
						|
	}
 | 
						|
	else
 | 
						|
#endif				/* MENU_SELECT */
 | 
						|
	    p = form->value->ptr;
 | 
						|
	j = 0;
 | 
						|
	l = buf->currentLine;
 | 
						|
	if (form->type == FORM_TEXTAREA) {
 | 
						|
	    int n = a->y - buf->currentLine->linenumber;
 | 
						|
	    if (n > 0)
 | 
						|
		for (; l && n; l = l->prev, n--) ;
 | 
						|
	    else if (n < 0)
 | 
						|
		for (; l && n; l = l->prev, n++) ;
 | 
						|
	    if (!l)
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	rows = form->rows ? form->rows : 1;
 | 
						|
	if (rows > 1)
 | 
						|
	    col = COLPOS(l, a->start.pos);
 | 
						|
	for (c_rows = 0; c_rows < rows; c_rows++, l = l->next) {
 | 
						|
	    if (rows > 1) {
 | 
						|
		pos = columnPos(l, col);
 | 
						|
		a = retrieveAnchor(buf->formitem, l->linenumber, pos);
 | 
						|
		if (a == NULL)
 | 
						|
		    break;
 | 
						|
		spos = a->start.pos - 1;
 | 
						|
		epos = a->end.pos;
 | 
						|
	    }
 | 
						|
	    i = spos + 1;
 | 
						|
	    while (p[j]) {
 | 
						|
		if (rows > 1 && (p[j] == '\r' || p[j] == '\n'))
 | 
						|
		    break;
 | 
						|
		if (p[j] == '\r') {
 | 
						|
		    j++;
 | 
						|
		    continue;
 | 
						|
		}
 | 
						|
		c_type = get_mctype(&p[j]);
 | 
						|
		c_len = get_mclen(c_type);
 | 
						|
		k = i + c_len;
 | 
						|
		if (k > epos)
 | 
						|
		    break;
 | 
						|
#ifdef JP_CHARSET
 | 
						|
		if (c_type == PC_KANJI && form->type != FORM_INPUT_PASSWORD) {
 | 
						|
		    SetCharType(l->propBuf[i], PC_KANJI1);
 | 
						|
		    SetCharType(l->propBuf[i + 1], PC_KANJI2);
 | 
						|
		}
 | 
						|
		else
 | 
						|
#endif				/* JP_CHARSET */
 | 
						|
		    SetCharType(l->propBuf[i], PC_ASCII);
 | 
						|
 | 
						|
		for (; i < k; i++, j++) {
 | 
						|
		    if (form->type == FORM_INPUT_PASSWORD)
 | 
						|
			l->lineBuf[i] = '*';
 | 
						|
		    else if (c_type == PC_CTRL ||
 | 
						|
			     IS_UNPRINTABLE_ASCII(p[j], c_type))
 | 
						|
			l->lineBuf[i] = ' ';
 | 
						|
		    else
 | 
						|
			l->lineBuf[i] = p[j];
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    if (rows > 1) {
 | 
						|
		if (!FoldTextarea) {
 | 
						|
		    while (p[j] && p[j] != '\r' && p[j] != '\n')
 | 
						|
			j++;
 | 
						|
		}
 | 
						|
		if (p[j] == '\r')
 | 
						|
		    j++;
 | 
						|
		if (p[j] == '\n')
 | 
						|
		    j++;
 | 
						|
	    }
 | 
						|
	    for (; i < epos; i++) {
 | 
						|
		l->lineBuf[i] = ' ';
 | 
						|
		SetCharType(l->propBuf[i], PC_ASCII);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	break;
 | 
						|
    }
 | 
						|
    copyBuffer(buf, &save);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Str
 | 
						|
textfieldrep(Str s, int width)
 | 
						|
{
 | 
						|
    Lineprop c_type;
 | 
						|
    Str n = Strnew_size(width + 2);
 | 
						|
    int i, j, k, c_len;
 | 
						|
 | 
						|
    j = 0;
 | 
						|
    for (i = 0; i < s->length; i += c_len) {
 | 
						|
	c_type = get_mctype(&s->ptr[i]);
 | 
						|
	c_len = get_mclen(c_type);
 | 
						|
	if (s->ptr[i] == '\r') {
 | 
						|
	    continue;
 | 
						|
	}
 | 
						|
	k = j + c_len;
 | 
						|
	if (k > width)
 | 
						|
	    break;
 | 
						|
	if (IS_CNTRL(s->ptr[i])) {
 | 
						|
	    Strcat_char(n, ' ');
 | 
						|
	}
 | 
						|
	else if (s->ptr[i] == '&')
 | 
						|
	    Strcat_charp(n, "&");
 | 
						|
	else if (s->ptr[i] == '<')
 | 
						|
	    Strcat_charp(n, "<");
 | 
						|
	else if (s->ptr[i] == '>')
 | 
						|
	    Strcat_charp(n, ">");
 | 
						|
	else
 | 
						|
	    Strcat_charp_n(n, &s->ptr[i], c_len);
 | 
						|
	j = k;
 | 
						|
    }
 | 
						|
    for (; j < width; j++)
 | 
						|
	Strcat_char(n, ' ');
 | 
						|
    return n;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
form_fputs_decode(Str s, FILE * f)
 | 
						|
{
 | 
						|
    char *p;
 | 
						|
    Str z = Strnew();
 | 
						|
 | 
						|
    for (p = s->ptr; *p;) {
 | 
						|
	switch (*p) {
 | 
						|
#if !defined( __CYGWIN__ ) && !defined( __EMX__ )
 | 
						|
	case '\r':
 | 
						|
	    if (*(p + 1) == '\n')
 | 
						|
		p++;
 | 
						|
	    /* continue to the next label */
 | 
						|
#endif				/* !defined( __CYGWIN__ ) && !defined( __EMX__ 
 | 
						|
				 * ) */
 | 
						|
	default:
 | 
						|
	    Strcat_char(z, *p);
 | 
						|
	    p++;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
#ifdef JP_CHARSET
 | 
						|
    fputs(conv_str(z, InnerCode, DisplayCode)->ptr, f);
 | 
						|
#else				/* not JP_CHARSET */
 | 
						|
    fputs(z->ptr, f);
 | 
						|
#endif				/* not JP_CHARSET */
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
input_textarea(FormItemList *fi)
 | 
						|
{
 | 
						|
    char *tmpf = tmpfname(TMPF_DFL, NULL)->ptr;
 | 
						|
    Str tmp;
 | 
						|
    FILE *f;
 | 
						|
#ifdef JP_CHARSET
 | 
						|
    char code = DisplayCode, ic;
 | 
						|
#endif
 | 
						|
 | 
						|
    f = fopen(tmpf, "w");
 | 
						|
    if (f == NULL) {
 | 
						|
	disp_err_message("Can't open temporary file", FALSE);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
    if (fi->value)
 | 
						|
	form_fputs_decode(fi->value, f);
 | 
						|
    fclose(f);
 | 
						|
 | 
						|
    fmTerm();
 | 
						|
    system(myEditor(Editor, tmpf, 1)->ptr);
 | 
						|
    fmInit();
 | 
						|
 | 
						|
    if (fi->readonly)
 | 
						|
	goto input_end;
 | 
						|
    f = fopen(tmpf, "r");
 | 
						|
    if (f == NULL) {
 | 
						|
	disp_err_message("Can't open temporary file", FALSE);
 | 
						|
	goto input_end;
 | 
						|
    }
 | 
						|
    fi->value = Strnew();
 | 
						|
    while (tmp = Strfgets(f), tmp->length > 0) {
 | 
						|
	if (tmp->length == 1 && tmp->ptr[tmp->length - 1] == '\n') {
 | 
						|
	    /* null line with bare LF */
 | 
						|
	    tmp = Strnew_charp("\r\n");
 | 
						|
	}
 | 
						|
	else if (tmp->length > 1 && tmp->ptr[tmp->length - 1] == '\n' &&
 | 
						|
		 tmp->ptr[tmp->length - 2] != '\r') {
 | 
						|
	    Strshrink(tmp, 1);
 | 
						|
	    Strcat_charp(tmp, "\r\n");
 | 
						|
	}
 | 
						|
#ifdef JP_CHARSET
 | 
						|
	if ((ic = checkShiftCode(tmp, code)) != '\0')
 | 
						|
	    tmp = conv_str(tmp, (code = ic), InnerCode);
 | 
						|
#endif				/* not JP_CHARSET */
 | 
						|
	Strcat(fi->value, tmp);
 | 
						|
    }
 | 
						|
    fclose(f);
 | 
						|
  input_end:
 | 
						|
    unlink(tmpf);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
do_internal(char *action, char *data)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; internal_action[i].action; i++) {
 | 
						|
	if (strcasecmp(internal_action[i].action, action) == 0) {
 | 
						|
	    if (internal_action[i].rout)
 | 
						|
		internal_action[i].rout(cgistr2tagarg(data));
 | 
						|
	    return;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#ifdef MENU_SELECT
 | 
						|
void
 | 
						|
addSelectOption(FormSelectOption *fso, Str value, Str label, int chk)
 | 
						|
{
 | 
						|
    FormSelectOptionItem *o;
 | 
						|
    o = New(FormSelectOptionItem);
 | 
						|
    if (value == NULL)
 | 
						|
	value = label;
 | 
						|
    o->value = value;
 | 
						|
    Strremovefirstspaces(label);
 | 
						|
    Strremovetrailingspaces(label);
 | 
						|
    o->label = label;
 | 
						|
    o->checked = chk;
 | 
						|
    o->next = NULL;
 | 
						|
    if (fso->first == NULL)
 | 
						|
	fso->first = fso->last = o;
 | 
						|
    else {
 | 
						|
	fso->last->next = o;
 | 
						|
	fso->last = o;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
chooseSelectOption(FormItemList *fi, FormSelectOptionItem *item)
 | 
						|
{
 | 
						|
    FormSelectOptionItem *opt;
 | 
						|
    int i;
 | 
						|
 | 
						|
    fi->selected = 0;
 | 
						|
    if (item == NULL) {
 | 
						|
	fi->value = Strnew_size(0);
 | 
						|
	fi->label = Strnew_size(0);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
    fi->value = item->value;
 | 
						|
    fi->label = item->label;
 | 
						|
    for (i = 0, opt = item; opt != NULL; i++, opt = opt->next) {
 | 
						|
	if (opt->checked) {
 | 
						|
	    fi->value = opt->value;
 | 
						|
	    fi->label = opt->label;
 | 
						|
	    fi->selected = i;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    updateSelectOption(fi, item);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
updateSelectOption(FormItemList *fi, FormSelectOptionItem *item)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    if (fi == NULL || item == NULL)
 | 
						|
	return;
 | 
						|
    for (i = 0; item != NULL; i++, item = item->next) {
 | 
						|
	if (i == fi->selected)
 | 
						|
	    item->checked = TRUE;
 | 
						|
	else
 | 
						|
	    item->checked = FALSE;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
formChooseOptionByMenu(struct form_item_list *fi, int x, int y)
 | 
						|
{
 | 
						|
    int i, n, selected = -1, init_select = fi->selected;
 | 
						|
    FormSelectOptionItem *opt;
 | 
						|
    char **label;
 | 
						|
 | 
						|
    for (n = 0, opt = fi->select_option; opt != NULL; n++, opt = opt->next) ;
 | 
						|
    label = New_N(char *, n + 1);
 | 
						|
    for (i = 0, opt = fi->select_option; opt != NULL; i++, opt = opt->next)
 | 
						|
	label[i] = opt->label->ptr;
 | 
						|
    label[n] = NULL;
 | 
						|
 | 
						|
    optionMenu(x, y, label, &selected, init_select, NULL);
 | 
						|
 | 
						|
    if (selected < 0)
 | 
						|
	return 0;
 | 
						|
    for (i = 0, opt = fi->select_option; opt != NULL; i++, opt = opt->next) {
 | 
						|
	if (i == selected) {
 | 
						|
	    fi->selected = selected;
 | 
						|
	    fi->value = opt->value;
 | 
						|
	    fi->label = opt->label;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    updateSelectOption(fi, fi->select_option);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
#endif				/* MENU_SELECT */
 | 
						|
 | 
						|
void
 | 
						|
form_write_data(FILE * f, char *boundary, char *name, char *value)
 | 
						|
{
 | 
						|
    fprintf(f, "--%s\r\n", boundary);
 | 
						|
    fprintf(f, "Content-Disposition: form-data; name=\"%s\"\r\n\r\n", name);
 | 
						|
    fprintf(f, "%s\r\n", value);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
form_write_from_file(FILE * f, char *boundary, char *name, char *filename,
 | 
						|
		     char *file)
 | 
						|
{
 | 
						|
    FILE *fd;
 | 
						|
    struct stat st;
 | 
						|
    int c;
 | 
						|
    char *type;
 | 
						|
 | 
						|
    fprintf(f, "--%s\r\n", boundary);
 | 
						|
    fprintf(f,
 | 
						|
	    "Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",
 | 
						|
	    name, mybasename(filename));
 | 
						|
    type = guessContentType(file);
 | 
						|
    fprintf(f, "Content-Type: %s\r\n\r\n",
 | 
						|
	    type ? type : "application/octet-stream");
 | 
						|
 | 
						|
    if (lstat(file, &st) < 0)
 | 
						|
	goto write_end;
 | 
						|
    if (S_ISDIR(st.st_mode))
 | 
						|
	goto write_end;
 | 
						|
    fd = fopen(file, "r");
 | 
						|
    if (fd != NULL) {
 | 
						|
	while ((c = fgetc(fd)) != EOF)
 | 
						|
	    fputc(c, f);
 | 
						|
	fclose(fd);
 | 
						|
    }
 | 
						|
  write_end:
 | 
						|
    fprintf(f, "\r\n");
 | 
						|
}
 | 
						|
 | 
						|
struct pre_form_item {
 | 
						|
    int type;
 | 
						|
    char *name;
 | 
						|
    char *value;
 | 
						|
    int checked;
 | 
						|
    struct pre_form_item *next;
 | 
						|
};
 | 
						|
 | 
						|
struct pre_form {
 | 
						|
    ParsedURL url;
 | 
						|
    char *action;
 | 
						|
    struct pre_form_item *item;
 | 
						|
    struct pre_form *next;
 | 
						|
};
 | 
						|
 | 
						|
static struct pre_form *PreForm = NULL;
 | 
						|
 | 
						|
static struct pre_form *
 | 
						|
add_pre_form(struct pre_form *prev, char *url, char *action)
 | 
						|
{
 | 
						|
    struct pre_form *new;
 | 
						|
 | 
						|
    if (prev)
 | 
						|
	new = prev->next = New(struct pre_form);
 | 
						|
    else
 | 
						|
	new = PreForm = New(struct pre_form);
 | 
						|
    parseURL2(url, &new->url, NULL);
 | 
						|
    if (action && *action)
 | 
						|
	new->action = action;
 | 
						|
    else
 | 
						|
	new->action = NULL;
 | 
						|
    new->item = NULL;
 | 
						|
    new->next = NULL;
 | 
						|
    return new;
 | 
						|
}
 | 
						|
 | 
						|
static struct pre_form_item *
 | 
						|
add_pre_form_item(struct pre_form *pf, struct pre_form_item *prev, int type,
 | 
						|
		  char *name, char *value, char *checked)
 | 
						|
{
 | 
						|
    struct pre_form_item *new;
 | 
						|
 | 
						|
    if (!pf)
 | 
						|
	return NULL;
 | 
						|
    if (prev)
 | 
						|
	new = prev->next = New(struct pre_form_item);
 | 
						|
    else
 | 
						|
	new = pf->item = New(struct pre_form_item);
 | 
						|
    new->type = type;
 | 
						|
    new->name = name;
 | 
						|
    new->value = value;
 | 
						|
    if (checked && *checked && (!strcmp(checked, "0") ||
 | 
						|
				strcasecmp(checked, "off")
 | 
						|
				|| !strcasecmp(checked, "no")))
 | 
						|
	new->checked = 0;
 | 
						|
    else
 | 
						|
	new->checked = 1;
 | 
						|
    new->next = NULL;
 | 
						|
    return new;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * url <url> [<action>]
 | 
						|
 * text <name> <value>
 | 
						|
 * file <name> <value>
 | 
						|
 * passwd <name> <value>
 | 
						|
 * checkbox <name> <value> [<checked>]
 | 
						|
 * radio <name> <value>
 | 
						|
 * select <name> <value>
 | 
						|
 * submit [<name> [<value>]]
 | 
						|
 * textarea <name>
 | 
						|
 * <value>
 | 
						|
 * /textarea
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
loadPreForm(void)
 | 
						|
{
 | 
						|
    FILE *fp;
 | 
						|
    Str line = NULL, textarea = NULL;
 | 
						|
    struct pre_form *pf = NULL;
 | 
						|
    struct pre_form_item *pi = NULL;
 | 
						|
    int type = -1;
 | 
						|
    char *name = NULL;
 | 
						|
 | 
						|
    PreForm = NULL;
 | 
						|
    fp = openSecretFile(pre_form_file);
 | 
						|
    if (fp == NULL)
 | 
						|
	return;
 | 
						|
    while (1) {
 | 
						|
	char *p, *s, *arg;
 | 
						|
 | 
						|
	line = Strfgets(fp);
 | 
						|
	if (line->length == 0)
 | 
						|
	    break;
 | 
						|
	if (textarea && !(!strncmp(line->ptr, "/textarea", 9) &&
 | 
						|
			  IS_SPACE(line->ptr[9]))) {
 | 
						|
	    Strcat(textarea, line);
 | 
						|
	    continue;
 | 
						|
	}
 | 
						|
	Strchop(line);
 | 
						|
	Strremovefirstspaces(line);
 | 
						|
	p = line->ptr;
 | 
						|
	if (*p == '#' || *p == '\0')
 | 
						|
	    continue;		/* comment or empty line */
 | 
						|
	s = getWord(&p);
 | 
						|
	arg = getWord(&p);
 | 
						|
 | 
						|
	if (!strcmp(s, "url")) {
 | 
						|
	    if (!arg || !*arg)
 | 
						|
		continue;
 | 
						|
	    p = getQWord(&p);
 | 
						|
	    pf = add_pre_form(pf, arg, p);
 | 
						|
	    pi = pf->item;
 | 
						|
	    continue;
 | 
						|
	}
 | 
						|
	if (!pf)
 | 
						|
	    continue;
 | 
						|
	if (!strcmp(s, "text"))
 | 
						|
	    type = FORM_INPUT_TEXT;
 | 
						|
	else if (!strcmp(s, "file"))
 | 
						|
	    type = FORM_INPUT_FILE;
 | 
						|
	else if (!strcmp(s, "passwd") || !strcmp(s, "password"))
 | 
						|
	    type = FORM_INPUT_PASSWORD;
 | 
						|
	else if (!strcmp(s, "checkbox"))
 | 
						|
	    type = FORM_INPUT_CHECKBOX;
 | 
						|
	else if (!strcmp(s, "radio"))
 | 
						|
	    type = FORM_INPUT_RADIO;
 | 
						|
	else if (!strcmp(s, "submit"))
 | 
						|
	    type = FORM_INPUT_SUBMIT;
 | 
						|
	else if (!strcmp(s, "select"))
 | 
						|
	    type = FORM_SELECT;
 | 
						|
	else if (!strcmp(s, "textarea")) {
 | 
						|
	    type = FORM_TEXTAREA;
 | 
						|
	    name = Strnew_charp(arg)->ptr;
 | 
						|
	    textarea = Strnew();
 | 
						|
	    continue;
 | 
						|
	}
 | 
						|
	else if (textarea && name && !strcmp(s, "/textarea")) {
 | 
						|
	    pi = add_pre_form_item(pf, pi, type, name, textarea->ptr, NULL);
 | 
						|
	    textarea = NULL;
 | 
						|
	    name = NULL;
 | 
						|
	    continue;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    continue;
 | 
						|
	s = getQWord(&p);
 | 
						|
	pi = add_pre_form_item(pf, pi, type, arg, s, getQWord(&p));
 | 
						|
    }
 | 
						|
    fclose(fp);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
preFormUpdateBuffer(Buffer *buf)
 | 
						|
{
 | 
						|
    struct pre_form *pf;
 | 
						|
    struct pre_form_item *pi;
 | 
						|
    int i;
 | 
						|
    Anchor *a;
 | 
						|
    FormList *fl;
 | 
						|
    FormItemList *fi;
 | 
						|
#ifdef MENU_SELECT
 | 
						|
    FormSelectOptionItem *opt;
 | 
						|
    int j;
 | 
						|
#endif
 | 
						|
 | 
						|
    if (!buf || !buf->formitem || !PreForm)
 | 
						|
	return;
 | 
						|
 | 
						|
    for (pf = PreForm; pf; pf = pf->next) {
 | 
						|
	if (Strcmp(parsedURL2Str(&buf->currentURL), parsedURL2Str(&pf->url)))
 | 
						|
	    continue;
 | 
						|
	for (i = 0; i < buf->formitem->nanchor; i++) {
 | 
						|
	    a = &buf->formitem->anchors[i];
 | 
						|
	    fi = (FormItemList *)a->url;
 | 
						|
	    fl = fi->parent;
 | 
						|
	    if (pf->action
 | 
						|
		&& (!fl->action || Strcmp_charp(fl->action, pf->action)))
 | 
						|
		continue;
 | 
						|
	    for (pi = pf->item; pi; pi = pi->next) {
 | 
						|
		if (pi->type != fi->type)
 | 
						|
		    continue;
 | 
						|
		if (pi->type == FORM_INPUT_SUBMIT) {
 | 
						|
		    if ((!pi->name || !*pi->name ||
 | 
						|
			 (fi->name && !Strcmp_charp(fi->name, pi->name))) &&
 | 
						|
			(!pi->value || !*pi->value ||
 | 
						|
			 (fi->value && !Strcmp_charp(fi->value, pi->value))))
 | 
						|
			buf->submit = a;
 | 
						|
		    continue;
 | 
						|
		}
 | 
						|
		if (!pi->name || !fi->name || Strcmp_charp(fi->name, pi->name))
 | 
						|
		    continue;
 | 
						|
		switch (pi->type) {
 | 
						|
		case FORM_INPUT_TEXT:
 | 
						|
		case FORM_INPUT_FILE:
 | 
						|
		case FORM_INPUT_PASSWORD:
 | 
						|
		case FORM_TEXTAREA:
 | 
						|
		    fi->value = Strnew_charp(pi->value);
 | 
						|
		    formUpdateBuffer(a, buf, fi);
 | 
						|
		    break;
 | 
						|
		case FORM_INPUT_CHECKBOX:
 | 
						|
		    if (pi->value && fi->value &&
 | 
						|
			!Strcmp_charp(fi->value, pi->value)) {
 | 
						|
			fi->checked = pi->checked;
 | 
						|
			formUpdateBuffer(a, buf, fi);
 | 
						|
		    }
 | 
						|
		    break;
 | 
						|
		case FORM_INPUT_RADIO:
 | 
						|
		    if (pi->value && fi->value &&
 | 
						|
			!Strcmp_charp(fi->value, pi->value))
 | 
						|
			formRecheckRadio(a, buf, fi);
 | 
						|
		    break;
 | 
						|
#ifdef MENU_SELECT
 | 
						|
		case FORM_SELECT:
 | 
						|
		    for (j = 0, opt = fi->select_option; opt != NULL;
 | 
						|
			 j++, opt = opt->next) {
 | 
						|
			if (pi->value && opt->value &&
 | 
						|
			    !Strcmp_charp(opt->value, pi->value)) {
 | 
						|
			    fi->selected = j;
 | 
						|
			    fi->value = opt->value;
 | 
						|
			    fi->label = opt->label;
 | 
						|
			    updateSelectOption(fi, fi->select_option);
 | 
						|
			    formUpdateBuffer(a, buf, fi);
 | 
						|
			    break;
 | 
						|
			}
 | 
						|
		    }
 | 
						|
		    break;
 | 
						|
#endif
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 |