819 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			819 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* $Id: frame.c,v 1.8 2002/01/15 03:45:02 ukai Exp $ */
 | |
| #include "fm.h"
 | |
| #include "parsetagx.h"
 | |
| #include "myctype.h"
 | |
| #include <signal.h>
 | |
| #include <setjmp.h>
 | |
| 
 | |
| #ifdef KANJI_SYMBOLS
 | |
| #define RULE_WIDTH 2
 | |
| #else				/* not KANJI_SYMBOLS */
 | |
| #define RULE_WIDTH 1
 | |
| #endif				/* not KANJI_SYMBOLS */
 | |
| 
 | |
| static JMP_BUF AbortLoading;
 | |
| struct frameset *renderFrameSet = NULL;
 | |
| 
 | |
| static MySignalHandler
 | |
| KeyAbort(SIGNAL_ARG)
 | |
| {
 | |
|     LONGJMP(AbortLoading, 1);
 | |
| }
 | |
| 
 | |
| struct frameset *
 | |
| newFrameSet(struct parsed_tag *tag)
 | |
| {
 | |
|     struct frameset *f;
 | |
|     int i;
 | |
|     char *cols = NULL, *rows = NULL, *p, *q;
 | |
|     char *length[100];
 | |
| 
 | |
|     f = New(struct frameset);
 | |
|     f->attr = F_FRAMESET;
 | |
|     f->name = NULL;
 | |
|     f->currentURL = NULL;
 | |
|     parsedtag_get_value(tag, ATTR_COLS, &cols);
 | |
|     parsedtag_get_value(tag, ATTR_ROWS, &rows);
 | |
|     i = 0;
 | |
|     if (cols) {
 | |
| 	length[i] = p = cols;
 | |
| 	while (*p != '\0')
 | |
| 	    if (*p++ == ',') {
 | |
| 		length[++i] = p;
 | |
| 		if (i >= sizeof(length) / sizeof(length[0]) - 2)
 | |
| 		    break;
 | |
| 	    }
 | |
| 	length[++i] = p + 1;
 | |
|     }
 | |
|     if (i > 1) {
 | |
| 	f->col = i;
 | |
| 	f->width = New_N(char *, i);
 | |
| 	p = length[i];
 | |
| 	do {
 | |
| 	    i--;
 | |
| 	    q = p - 2;
 | |
| 	    p = length[i];
 | |
| 	    switch (*q) {
 | |
| 		Str tmp;
 | |
| 	    case '%':
 | |
| 		f->width[i] = allocStr(p, q - p + 1);
 | |
| 		break;
 | |
| 	    case '*':
 | |
| 		f->width[i] = "*";
 | |
| 		break;
 | |
| 	    default:
 | |
| 		tmp = Sprintf("%d", atoi(p));
 | |
| 		f->width[i] = tmp->ptr;
 | |
| 		break;
 | |
| 	    }
 | |
| 	} while (i);
 | |
|     }
 | |
|     else {
 | |
| 	f->col = 1;
 | |
| 	f->width = New_N(char *, 1);
 | |
| 	f->width[0] = "*";
 | |
|     }
 | |
|     i = 0;
 | |
|     if (rows) {
 | |
| 	length[i] = p = rows;
 | |
| 	while (*p != '\0')
 | |
| 	    if (*p++ == ',') {
 | |
| 		length[++i] = p;
 | |
| 		if (i >= sizeof(length) / sizeof(length[0]) - 2)
 | |
| 		    break;
 | |
| 	    }
 | |
| 	length[++i] = p + 1;
 | |
|     }
 | |
|     if (i > 1) {
 | |
| 	f->row = i;
 | |
| 	f->height = New_N(char *, i);
 | |
| 	p = length[i];
 | |
| 	do {
 | |
| 	    i--;
 | |
| 	    q = p - 2;
 | |
| 	    p = length[i];
 | |
| 	    f->height[i] = allocStr(p, q - p + 1);
 | |
| 	} while (i);
 | |
|     }
 | |
|     else {
 | |
| 	f->row = 1;
 | |
| 	f->height = New_N(char *, 1);
 | |
| 	f->height[0] = "*";
 | |
|     }
 | |
|     i = f->row * f->col;
 | |
|     f->i = 0;
 | |
|     f->frame = New_N(union frameset_element, i);
 | |
|     do {
 | |
| 	i--;
 | |
| 	f->frame[i].element = NULL;
 | |
|     } while (i);
 | |
|     return f;
 | |
| }
 | |
| 
 | |
| struct frame_body *
 | |
| newFrame(struct parsed_tag *tag, Buffer *buf)
 | |
| {
 | |
|     struct frame_body *body;
 | |
|     char *p;
 | |
| 
 | |
|     body = New(struct frame_body);
 | |
|     bzero((void *)body, sizeof(*body));
 | |
|     body->attr = F_UNLOADED;
 | |
|     body->flags = 0;
 | |
|     body->baseURL = baseURL(buf);
 | |
|     if (tag) {
 | |
| 	if (parsedtag_get_value(tag, ATTR_SRC, &p))
 | |
| 	    body->url = url_quote_conv(p, buf->document_code);
 | |
| 	if (parsedtag_get_value(tag, ATTR_NAME, &p) && *p != '_')
 | |
| 	    body->name = url_quote_conv(p, buf->document_code);
 | |
|     }
 | |
|     return body;
 | |
| }
 | |
| 
 | |
| static void
 | |
| unloadFrame(struct frame_body *b)
 | |
| {
 | |
|     if (b->source && b->flags & FB_TODELETE)
 | |
| 	pushText(fileToDelete, b->source);
 | |
|     b->attr = F_UNLOADED;
 | |
| }
 | |
| 
 | |
| void
 | |
| deleteFrame(struct frame_body *b)
 | |
| {
 | |
|     if (b == NULL)
 | |
| 	return;
 | |
|     unloadFrame(b);
 | |
|     bzero((void *)b, sizeof(*b));
 | |
| }
 | |
| 
 | |
| void
 | |
| addFrameSetElement(struct frameset *f, union frameset_element element)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     if (f == NULL)
 | |
| 	return;
 | |
|     i = f->i;
 | |
|     if (i >= f->col * f->row)
 | |
| 	return;
 | |
|     f->frame[i] = element;
 | |
|     f->i++;
 | |
| }
 | |
| 
 | |
| void
 | |
| deleteFrameSet(struct frameset *f)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     if (f == NULL)
 | |
| 	return;
 | |
|     for (i = 0; i < f->col * f->row; i++) {
 | |
| 	deleteFrameSetElement(f->frame[i]);
 | |
|     }
 | |
|     f->name = NULL;
 | |
|     f->currentURL = NULL;
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void
 | |
| deleteFrameSetElement(union frameset_element e)
 | |
| {
 | |
|     if (e.element == NULL)
 | |
| 	return;
 | |
|     switch (e.element->attr) {
 | |
|     case F_UNLOADED:
 | |
| 	break;
 | |
|     case F_BODY:
 | |
| 	deleteFrame(e.body);
 | |
| 	break;
 | |
|     case F_FRAMESET:
 | |
| 	deleteFrameSet(e.set);
 | |
| 	break;
 | |
|     default:
 | |
| 	break;
 | |
|     }
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static struct frame_body *
 | |
| copyFrame(struct frame_body *ob)
 | |
| {
 | |
|     struct frame_body *rb;
 | |
| 
 | |
|     rb = New(struct frame_body);
 | |
|     bcopy((const void *)ob, (void *)rb, sizeof(struct frame_body));
 | |
|     rb->flags &= ~FB_TODELETE;
 | |
|     return rb;
 | |
| }
 | |
| 
 | |
| struct frameset *
 | |
| copyFrameSet(struct frameset *of)
 | |
| {
 | |
|     struct frameset *rf;
 | |
|     int n;
 | |
| 
 | |
|     rf = New(struct frameset);
 | |
|     n = of->col * of->row;
 | |
|     bcopy((const void *)of, (void *)rf, sizeof(struct frameset));
 | |
|     rf->width = New_N(char *, rf->col);
 | |
|     bcopy((const void *)of->width,
 | |
| 	  (void *)rf->width, sizeof(char *) * rf->col);
 | |
|     rf->height = New_N(char *, rf->row);
 | |
|     bcopy((const void *)of->height,
 | |
| 	  (void *)rf->height, sizeof(char *) * rf->row);
 | |
|     rf->frame = New_N(union frameset_element, n);
 | |
|     while (n) {
 | |
| 	n--;
 | |
| 	if (!of->frame[n].element)
 | |
| 	    goto attr_default;
 | |
| 	switch (of->frame[n].element->attr) {
 | |
| 	case F_UNLOADED:
 | |
| 	case F_BODY:
 | |
| 	    rf->frame[n].body = copyFrame(of->frame[n].body);
 | |
| 	    break;
 | |
| 	case F_FRAMESET:
 | |
| 	    rf->frame[n].set = copyFrameSet(of->frame[n].set);
 | |
| 	    break;
 | |
| 	default:
 | |
| 	  attr_default:
 | |
| 	    rf->frame[n].element = NULL;
 | |
| 	    break;
 | |
| 	}
 | |
|     }
 | |
|     return rf;
 | |
| }
 | |
| 
 | |
| void
 | |
| flushFrameSet(struct frameset *fs)
 | |
| {
 | |
|     int n = fs->i;
 | |
| 
 | |
|     while (n) {
 | |
| 	n--;
 | |
| 	if (!fs->frame[n].element)
 | |
| 	    goto attr_default;
 | |
| 	switch (fs->frame[n].element->attr) {
 | |
| 	case F_UNLOADED:
 | |
| 	case F_BODY:
 | |
| 	    fs->frame[n].body->nameList = NULL;
 | |
| 	    break;
 | |
| 	case F_FRAMESET:
 | |
| 	    flushFrameSet(fs->frame[n].set);
 | |
| 	    break;
 | |
| 	default:
 | |
| 	  attr_default:
 | |
| 	    /* nothing to do */
 | |
| 	    break;
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| pushFrameTree(struct frameset_queue **fqpp, struct frameset *fs, Buffer *buf)
 | |
| {
 | |
|     struct frameset_queue *rfq, *cfq = *fqpp;
 | |
| 
 | |
|     if (!fs)
 | |
| 	return;
 | |
| 
 | |
|     rfq = New(struct frameset_queue);
 | |
|     rfq->linenumber = (buf
 | |
| 		       && buf->currentLine) ? buf->currentLine->linenumber : 1;
 | |
|     rfq->top_linenumber = (buf && buf->topLine) ? buf->topLine->linenumber : 1;
 | |
|     rfq->pos = buf ? buf->pos : 0;
 | |
|     rfq->currentColumn = buf ? buf->currentColumn : 0;
 | |
|     rfq->formitem = buf ? buf->formitem : NULL;
 | |
| 
 | |
|     rfq->back = cfq;
 | |
|     if (cfq) {
 | |
| 	rfq->next = cfq->next;
 | |
| 	if (cfq->next)
 | |
| 	    cfq->next->back = rfq;
 | |
| 	cfq->next = rfq;
 | |
|     }
 | |
|     else
 | |
| 	rfq->next = cfq;
 | |
|     rfq->frameset = fs;
 | |
|     *fqpp = rfq;
 | |
|     return;
 | |
| }
 | |
| 
 | |
| struct frameset *
 | |
| popFrameTree(struct frameset_queue **fqpp)
 | |
| {
 | |
|     struct frameset_queue *rfq = NULL, *cfq = *fqpp;
 | |
|     struct frameset *rfs = NULL;
 | |
| 
 | |
|     if (!cfq)
 | |
| 	return rfs;
 | |
| 
 | |
|     rfs = cfq->frameset;
 | |
|     if (cfq->next) {
 | |
| 	(rfq = cfq->next)->back = cfq->back;
 | |
|     }
 | |
|     if (cfq->back) {
 | |
| 	(rfq = cfq->back)->next = cfq->next;
 | |
|     }
 | |
|     *fqpp = rfq;
 | |
|     bzero((void *)cfq, sizeof(struct frameset_queue));
 | |
|     return rfs;
 | |
| }
 | |
| 
 | |
| void
 | |
| resetFrameElement(union frameset_element *f_element,
 | |
| 		  Buffer *buf, char *referer, FormList *request)
 | |
| {
 | |
|     char *f_name;
 | |
|     struct frame_body *f_body;
 | |
| 
 | |
|     f_name = f_element->element->name;
 | |
|     if (buf->frameset) {
 | |
| 	/* frame cascade */
 | |
| 	deleteFrameSetElement(*f_element);
 | |
| 	f_element->set = buf->frameset;
 | |
| 	f_element->set->currentURL = New(ParsedURL);
 | |
| 	copyParsedURL(f_element->set->currentURL, &buf->currentURL);
 | |
| 	buf->frameset = popFrameTree(&(buf->frameQ));
 | |
| 	f_element->set->name = f_name;
 | |
|     }
 | |
|     else {
 | |
| 	f_body = newFrame(NULL, buf);
 | |
| 	f_body->attr = F_BODY;
 | |
| 	f_body->name = f_name;
 | |
| 	f_body->url = parsedURL2Str(&buf->currentURL)->ptr;
 | |
| 	if (buf->real_scheme == SCM_LOCAL) {
 | |
| 	    f_body->source = buf->sourcefile;
 | |
| 	}
 | |
| 	else {
 | |
| 	    Str tmp = tmpfname(TMPF_FRAME, NULL);
 | |
| 	    rename(buf->sourcefile, tmp->ptr);
 | |
| 	    f_body->source = tmp->ptr;
 | |
| 	    f_body->flags |= FB_TODELETE;
 | |
| 	    buf->sourcefile = NULL;
 | |
| 	}
 | |
| 	f_body->type = buf->type;
 | |
| 	f_body->referer = referer;
 | |
| 	f_body->request = request;
 | |
| 	deleteFrameSetElement(*f_element);
 | |
| 	f_element->body = f_body;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static struct frameset *
 | |
| frame_download_source(struct frame_body *b, ParsedURL *currentURL,
 | |
| 		      ParsedURL *baseURL, int flag)
 | |
| {
 | |
|     Buffer *buf;
 | |
|     struct frameset *ret_frameset = NULL;
 | |
|     Str tmp;
 | |
|     ParsedURL url;
 | |
| 
 | |
|     if (b == NULL || b->url == NULL || b->url[0] == '\0')
 | |
| 	return NULL;
 | |
|     if (b->baseURL)
 | |
| 	baseURL = b->baseURL;
 | |
|     parseURL2(b->url, &url, currentURL);
 | |
|     switch (url.scheme) {
 | |
|     case SCM_LOCAL:
 | |
| #if 0
 | |
| 	b->source = url.real_file;
 | |
| #endif
 | |
| 	b->flags = 0;
 | |
|     default:
 | |
| 	is_redisplay = TRUE;
 | |
| 	w3m_dump |= DUMP_FRAME;
 | |
| 	buf = loadGeneralFile(b->url,
 | |
| 			      baseURL ? baseURL : currentURL,
 | |
| 			      b->referer, flag, b->request);
 | |
| 	w3m_dump &= ~DUMP_FRAME;
 | |
| 	is_redisplay = FALSE;
 | |
| 	break;
 | |
|     }
 | |
| 
 | |
|     if (buf == NULL || buf == NO_BUFFER) {
 | |
| 	b->source = NULL;
 | |
| 	b->flags = (buf == NO_BUFFER) ? FB_NO_BUFFER : 0;
 | |
| 	return NULL;
 | |
|     }
 | |
|     b->url = parsedURL2Str(&buf->currentURL)->ptr;
 | |
|     b->source = buf->sourcefile;
 | |
|     b->type = buf->type;
 | |
|     if (buf->real_scheme != SCM_LOCAL) {
 | |
| 	tmp = tmpfname(TMPF_FRAME, NULL);
 | |
| 	rename(buf->sourcefile, tmp->ptr);
 | |
| 	b->source = tmp->ptr;
 | |
| 	b->flags |= FB_TODELETE;
 | |
| 	buf->sourcefile = NULL;
 | |
|     }
 | |
|     b->attr = F_BODY;
 | |
|     if (buf->frameset) {
 | |
| 	ret_frameset = buf->frameset;
 | |
| 	ret_frameset->name = b->name;
 | |
| 	ret_frameset->currentURL = New(ParsedURL);
 | |
| 	copyParsedURL(ret_frameset->currentURL, &buf->currentURL);
 | |
| 	buf->frameset = popFrameTree(&(buf->frameQ));
 | |
|     }
 | |
|     discardBuffer(buf);
 | |
|     return ret_frameset;
 | |
| }
 | |
| 
 | |
| static int
 | |
| createFrameFile(struct frameset *f, FILE * f1, Buffer *current, int level,
 | |
| 		int force_reload)
 | |
| {
 | |
|     int r, c, t_stack;
 | |
|     URLFile f2;
 | |
| #ifdef JP_CHARSET
 | |
|     char code, ic, charset[2];
 | |
| #endif				/* JP_CHARSET */
 | |
|     char *d_target, *p_target, *s_target, *t_target;
 | |
|     ParsedURL *currentURL, base;
 | |
|     MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
 | |
|     int flag;
 | |
| 
 | |
|     if (f == NULL)
 | |
| 	return -1;
 | |
| 
 | |
|     if (level == 0) {
 | |
| 	if (SETJMP(AbortLoading) != 0) {
 | |
| 	    if (fmInitialized)
 | |
| 		term_raw();
 | |
| 	    signal(SIGINT, prevtrap);
 | |
| 	    return -1;
 | |
| 	}
 | |
| 	prevtrap = signal(SIGINT, KeyAbort);
 | |
| 	if (fmInitialized)
 | |
| 	    term_cbreak();
 | |
| 
 | |
| 	f->name = "_top";
 | |
|     }
 | |
| 
 | |
|     if (level > 7) {
 | |
| 	fputs("Too many frameset tasked.\n", f1);
 | |
| 	return -1;
 | |
|     }
 | |
| 
 | |
|     if (level == 0) {
 | |
| 	fprintf(f1, "<html><head><title>%s</title></head><body>\n",
 | |
| 		html_quote(current->buffername));
 | |
| 	fputs("<table hborder width=\"100%\">\n", f1);
 | |
|     }
 | |
|     else
 | |
| 	fputs("<table hborder>\n", f1);
 | |
| 
 | |
|     currentURL = f->currentURL ? f->currentURL : ¤t->currentURL;
 | |
| #ifdef JP_CHARSET
 | |
|     charset[1] = '\0';
 | |
| #endif
 | |
|     for (r = 0; r < f->row; r++) {
 | |
| 	fputs("<tr valign=top>\n", f1);
 | |
| 	for (c = 0; c < f->col; c++) {
 | |
| 	    union frameset_element frame;
 | |
| 	    struct frameset *f_frameset;
 | |
| 	    int i = c + r * f->col;
 | |
| 	    char *p = "";
 | |
| 	    Str tok = Strnew();
 | |
| 	    int status;
 | |
| 
 | |
| 	    frame = f->frame[i];
 | |
| 
 | |
| 	    if (frame.element == NULL) {
 | |
| 		fputs("<td>\n</td>\n", f1);
 | |
| 		continue;
 | |
| 	    }
 | |
| 
 | |
| 	    fputs("<td", f1);
 | |
| 	    if (frame.element->name)
 | |
| 		fprintf(f1, " id=\"_%s\"", html_quote(frame.element->name));
 | |
| 	    if (!r)
 | |
| 		fprintf(f1, " width=\"%s\"", f->width[c]);
 | |
| 	    fputs(">\n", f1);
 | |
| 
 | |
| 	    flag = 0;
 | |
| 	    if (force_reload) {
 | |
| 		flag |= RG_NOCACHE;
 | |
| 		if (frame.element->attr == F_BODY)
 | |
| 		    unloadFrame(frame.body);
 | |
| 	    }
 | |
| 	    switch (frame.element->attr) {
 | |
| 	    default:
 | |
| 		fprintf(f1, "Frameset \"%s\" frame %d: type unrecognized",
 | |
| 			html_quote(f->name), i + 1);
 | |
| 		break;
 | |
| 	    case F_UNLOADED:
 | |
| 		if (!frame.body->name && f->name) {
 | |
| 		    frame.body->name = Sprintf("%s_%d", f->name, i)->ptr;
 | |
| 		}
 | |
| 		fflush(f1);
 | |
| 		f_frameset = frame_download_source(frame.body,
 | |
| 						   currentURL,
 | |
| 						   current->baseURL, flag);
 | |
| 		if (f_frameset) {
 | |
| 		    deleteFrame(frame.body);
 | |
| 		    f->frame[i].set = frame.set = f_frameset;
 | |
| 		    goto render_frameset;
 | |
| 		}
 | |
| 		/* fall through */
 | |
| 	    case F_BODY:
 | |
| 		init_stream(&f2, SCM_LOCAL, NULL);
 | |
| 		if (frame.body->source) {
 | |
| 		    fflush(f1);
 | |
| 		    examineFile(frame.body->source, &f2);
 | |
| 		}
 | |
| 		if (f2.stream == NULL) {
 | |
| 		    frame.body->attr = F_UNLOADED;
 | |
| 		    if (frame.body->flags & FB_NO_BUFFER)
 | |
| 			fprintf(f1, "Open %s with other method",
 | |
| 				frame.body->url);
 | |
| 		    else if (frame.body->url)
 | |
| 			fprintf(f1, "Can't open %s", frame.body->url);
 | |
| 		    else
 | |
| 			fprintf(f1,
 | |
| 				"This frame (%s) contains no src attribute",
 | |
| 				frame.body->name ? frame.body->
 | |
| 				name : "(no name)");
 | |
| 		    break;
 | |
| 		}
 | |
| 		parseURL2(frame.body->url, &base, currentURL);
 | |
| 		p_target = f->name;
 | |
| 		s_target = frame.body->name;
 | |
| 		t_target = "_blank";
 | |
| 		d_target = TargetSelf ? s_target : t_target;
 | |
| #ifdef JP_CHARSET
 | |
| 		code = '\0';
 | |
| #endif				/* JP_CHARSET */
 | |
| 		t_stack = 0;
 | |
| 		if (frame.body->type &&
 | |
| 		    !strcasecmp(frame.body->type, "text/plain")) {
 | |
| 		    Str tmp;
 | |
| 		    fprintf(f1, "<pre>\n");
 | |
| 		    while ((tmp = StrmyUFgets(&f2))->length) {
 | |
| #ifdef JP_CHARSET
 | |
| 			if ((ic = checkShiftCode(tmp, code)) != '\0')
 | |
| 			    tmp = conv_str(tmp, (code = ic), InnerCode);
 | |
| 
 | |
| #endif				/* JP_CHARSET */
 | |
| 			cleanup_line(tmp, HTML_MODE);
 | |
| 			fprintf(f1, "%s", html_quote(tmp->ptr));
 | |
| 		    }
 | |
| 		    fprintf(f1, "</pre>\n");
 | |
| 		    UFclose(&f2);
 | |
| 		    break;
 | |
| 		}
 | |
| 		do {
 | |
| 		    status = R_ST_NORMAL;
 | |
| 		    do {
 | |
| 			if (*p == '\0') {
 | |
| 			    Str tmp = StrmyUFgets(&f2);
 | |
| 			    if (tmp->length == 0 && status != R_ST_NORMAL)
 | |
| 				tmp = correct_irrtag(status);
 | |
| 			    if (tmp->length == 0)
 | |
| 				break;
 | |
| #ifdef JP_CHARSET
 | |
| 			    if ((ic = checkShiftCode(tmp, code)) != '\0')
 | |
| 				tmp = conv_str(tmp, (code = ic), InnerCode);
 | |
| 
 | |
| #endif				/* JP_CHARSET */
 | |
| 			    cleanup_line(tmp, HTML_MODE);
 | |
| 			    p = tmp->ptr;
 | |
| 			}
 | |
| 			if (status == R_ST_NORMAL || ST_IS_COMMENT(status))
 | |
| 			    read_token(tok, &p, &status, 1, 0);
 | |
| 			else
 | |
| 			    read_token(tok, &p, &status, 1, 1);
 | |
| 		    } while (status != R_ST_NORMAL);
 | |
| 
 | |
| 		    if (tok->length == 0)
 | |
| 			continue;
 | |
| 
 | |
| 		    if (tok->ptr[0] == '<') {
 | |
| 			char *q = tok->ptr;
 | |
| 			int j, a_target = 0;
 | |
| 			struct parsed_tag *tag;
 | |
| 			ParsedURL url;
 | |
| 
 | |
| 			if (!(tag = parse_tag(&q, FALSE)))
 | |
| 			    goto token_end;
 | |
| 
 | |
| 			switch (tag->tagid) {
 | |
| 			case HTML_TITLE:
 | |
| 			    fputs("<!-- title:", f1);
 | |
| 			    goto token_end;
 | |
| 			case HTML_N_TITLE:
 | |
| 			    fputs("-->", f1);
 | |
| 			    goto token_end;
 | |
| 			case HTML_BASE:
 | |
| 			    if (parsedtag_get_value(tag, ATTR_HREF, &q)) {
 | |
| 				q = url_quote_conv(q, code);
 | |
| 				parseURL(q, &base, NULL);
 | |
| 			    }
 | |
| 			    if (parsedtag_get_value(tag, ATTR_TARGET, &q)) {
 | |
| 				if (!strcasecmp(q, "_self"))
 | |
| 				    d_target = s_target;
 | |
| 				else if (!strcasecmp(q, "_parent"))
 | |
| 				    d_target = p_target;
 | |
| 				else
 | |
| 				    d_target = url_quote_conv(q, code);
 | |
| 			    }
 | |
| 			    /* fall thru, "BASE" is prohibit tag */
 | |
| 			case HTML_HEAD:
 | |
| 			case HTML_N_HEAD:
 | |
| 			case HTML_BODY:
 | |
| 			case HTML_N_BODY:
 | |
| 			case HTML_META:
 | |
| 			case HTML_DOCTYPE:
 | |
| 			    /* prohibit_tags */
 | |
| 			    Strshrinkfirst(tok, 1);
 | |
| 			    Strshrink(tok, 1);
 | |
| 			    fprintf(f1, "<!-- %s -->", tok->ptr);
 | |
| 			    goto token_end;
 | |
| 			case HTML_TABLE:
 | |
| 			    t_stack++;
 | |
| 			    break;
 | |
| 			case HTML_N_TABLE:
 | |
| 			    t_stack--;
 | |
| 			    if (t_stack < 0) {
 | |
| 				t_stack = 0;
 | |
| 				Strshrinkfirst(tok, 1);
 | |
| 				Strshrink(tok, 1);
 | |
| 				fprintf(f1,
 | |
| 					"<!-- table stack underflow: %s -->",
 | |
| 					tok->ptr);
 | |
| 				goto token_end;
 | |
| 			    }
 | |
| 			    break;
 | |
| 			case HTML_THEAD:
 | |
| 			case HTML_N_THEAD:
 | |
| 			case HTML_TBODY:
 | |
| 			case HTML_N_TBODY:
 | |
| 			case HTML_TFOOT:
 | |
| 			case HTML_N_TFOOT:
 | |
| 			case HTML_TD:
 | |
| 			case HTML_N_TD:
 | |
| 			case HTML_TR:
 | |
| 			case HTML_N_TR:
 | |
| 			case HTML_TH:
 | |
| 			case HTML_N_TH:
 | |
| 			    /* table_tags MUST be in table stack */
 | |
| 			    if (!t_stack) {
 | |
| 				Strshrinkfirst(tok, 1);
 | |
| 				Strshrink(tok, 1);
 | |
| 				fprintf(f1, "<!-- %s -->", tok->ptr);
 | |
| 				goto token_end;
 | |
| 
 | |
| 			    }
 | |
| 			    break;
 | |
| 			default:
 | |
| 			    break;
 | |
| 			}
 | |
| 			for (j = 0; j < TagMAP[tag->tagid].max_attribute; j++) {
 | |
| 			    switch (tag->attrid[j]) {
 | |
| 			    case ATTR_SRC:
 | |
| 			    case ATTR_HREF:
 | |
| 			    case ATTR_ACTION:
 | |
| 				if (!tag->value[j])
 | |
| 				    break;
 | |
| 				tag->value[j] =
 | |
| 				    url_quote_conv(tag->value[j], code);
 | |
| 				parseURL2(tag->value[j], &url, &base);
 | |
| 				if (url.scheme == SCM_UNKNOWN ||
 | |
| #ifndef USE_W3MMAILER
 | |
| 				    url.scheme == SCM_MAILTO ||
 | |
| #endif
 | |
| 				    url.scheme == SCM_MISSING)
 | |
| 				    break;
 | |
| 				a_target |= 1;
 | |
| 				tag->value[j] = parsedURL2Str(&url)->ptr;
 | |
| 				tag->need_reconstruct = TRUE;
 | |
| 				parsedtag_set_value(tag,
 | |
| 						    ATTR_REFERER,
 | |
| 						    parsedURL2Str(&base)->ptr);
 | |
| #ifdef JP_CHARSET
 | |
| 				if (code != '\0') {
 | |
| 				    charset[0] = code;
 | |
| 				    parsedtag_set_value(tag,
 | |
| 							ATTR_CHARSET, charset);
 | |
| 				}
 | |
| #endif
 | |
| 				break;
 | |
| 			    case ATTR_TARGET:
 | |
| 				if (!tag->value[j])
 | |
| 				    break;
 | |
| 				a_target |= 2;
 | |
| 				if (!strcasecmp(tag->value[j], "_self")) {
 | |
| 				    parsedtag_set_value(tag,
 | |
| 							ATTR_TARGET, s_target);
 | |
| 				}
 | |
| 				else if (!strcasecmp(tag->value[j], "_parent")) {
 | |
| 				    parsedtag_set_value(tag,
 | |
| 							ATTR_TARGET, p_target);
 | |
| 				}
 | |
| 				break;
 | |
| 			    case ATTR_NAME:
 | |
| 			    case ATTR_ID:
 | |
| 				if (!tag->value[j])
 | |
| 				    break;
 | |
| 				parsedtag_set_value(tag,
 | |
| 						    ATTR_FRAMENAME, s_target);
 | |
| 				break;
 | |
| 			    }
 | |
| 			}
 | |
| 			if (a_target == 1) {
 | |
| 			    /* there is HREF attribute and no TARGET
 | |
| 			     * attribute */
 | |
| 			    parsedtag_set_value(tag, ATTR_TARGET, d_target);
 | |
| 			}
 | |
| 			if (parsedtag_need_reconstruct(tag))
 | |
| 			    Strfputs(parsedtag2str(tag), f1);
 | |
| 			else
 | |
| 			    Strfputs(tok, f1);
 | |
| 		    }
 | |
| 		    else {
 | |
| 			Strfputs(tok, f1);
 | |
| 		    }
 | |
| 		  token_end:
 | |
| 		    Strclear(tok);
 | |
| 		} while (*p != '\0' || !iseos(f2.stream));
 | |
| 		while (t_stack--)
 | |
| 		    fputs("</TABLE>\n", f1);
 | |
| 		UFclose(&f2);
 | |
| 		break;
 | |
| 	    case F_FRAMESET:
 | |
| 	      render_frameset:
 | |
| 		if (!frame.set->name && f->name) {
 | |
| 		    frame.set->name = Sprintf("%s_%d", f->name, i)->ptr;
 | |
| 		}
 | |
| 		createFrameFile(frame.set, f1, current, level + 1,
 | |
| 				force_reload);
 | |
| 		break;
 | |
| 	    }
 | |
| 	    fputs("</td>\n", f1);
 | |
| 	}
 | |
| 	fputs("</tr>\n", f1);
 | |
|     }
 | |
| 
 | |
|     fputs("</table>\n", f1);
 | |
|     if (level == 0) {
 | |
| 	fputs("</body></html>\n", f1);
 | |
| 	signal(SIGINT, prevtrap);
 | |
| 	if (fmInitialized)
 | |
| 	    term_raw();
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| Buffer *
 | |
| renderFrame(Buffer *Cbuf, int force_reload)
 | |
| {
 | |
|     Str tmp;
 | |
|     FILE *f;
 | |
|     Buffer *buf;
 | |
|     int flag;
 | |
|     struct frameset *fset;
 | |
| 
 | |
|     tmp = tmpfname(TMPF_FRAME, ".html");
 | |
|     f = fopen(tmp->ptr, "w");
 | |
|     if (f == NULL)
 | |
| 	return NULL;
 | |
|     /* 
 | |
|      * if (Cbuf->frameQ != NULL) fset = Cbuf->frameQ->frameset; else */
 | |
|     fset = Cbuf->frameset;
 | |
|     if (fset == NULL || createFrameFile(fset, f, Cbuf, 0, force_reload) < 0)
 | |
| 	return NULL;
 | |
|     fclose(f);
 | |
|     flag = RG_FRAME;
 | |
|     if ((Cbuf->currentURL).is_nocache)
 | |
| 	flag |= RG_NOCACHE;
 | |
|     renderFrameSet = Cbuf->frameset;
 | |
|     flushFrameSet(renderFrameSet);
 | |
|     buf = loadGeneralFile(tmp->ptr, NULL, NULL, flag, NULL);
 | |
|     renderFrameSet = NULL;
 | |
|     if (buf == NULL || buf == NO_BUFFER)
 | |
| 	return NULL;
 | |
|     buf->sourcefile = tmp->ptr;
 | |
|     copyParsedURL(&buf->currentURL, &Cbuf->currentURL);
 | |
|     return buf;
 | |
| }
 | |
| 
 | |
| union frameset_element *
 | |
| search_frame(struct frameset *fset, char *name)
 | |
| {
 | |
|     int i;
 | |
|     union frameset_element *e = NULL;
 | |
| 
 | |
|     for (i = 0; i < fset->col * fset->row; i++) {
 | |
| 	e = &(fset->frame[i]);
 | |
| 	if (e->element != NULL) {
 | |
| 	    if (e->element->name && !strcmp(e->element->name, name)) {
 | |
| 		return e;
 | |
| 	    }
 | |
| 	    else if (e->element->attr == F_FRAMESET &&
 | |
| 		     (e = search_frame(e->set, name))) {
 | |
| 		return e;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     return NULL;
 | |
| }
 |