All these functions, StrmyUFgets, StrISgets, etc. can potentially return NULL. Add a check for it.
947 lines
22 KiB
C
947 lines
22 KiB
C
/* $Id: frame.c,v 1.34 2003/09/26 17:59:51 ukai Exp $ */
|
|
#include "fm.h"
|
|
#include "parsetagx.h"
|
|
#include "myctype.h"
|
|
#include <signal.h>
|
|
#include <setjmp.h>
|
|
|
|
static JMP_BUF AbortLoading;
|
|
struct frameset *renderFrameSet = NULL;
|
|
|
|
static MySignalHandler
|
|
KeyAbort(SIGNAL_ARG)
|
|
{
|
|
LONGJMP(AbortLoading, 1);
|
|
}
|
|
|
|
static int
|
|
parseFrameSetLength(char *s, char ***ret)
|
|
{
|
|
int i, len;
|
|
char *p, *q, **lv;
|
|
|
|
i = 1;
|
|
|
|
if (s)
|
|
for (p = s; (p = strchr(p, ',')); ++p)
|
|
++i;
|
|
else
|
|
s = "*";
|
|
|
|
lv = New_N(char *, i);
|
|
|
|
for (i = 0, p = s;; ++p) {
|
|
SKIP_BLANKS(p);
|
|
len = strtol(p, &q, 10);
|
|
|
|
switch (*q) {
|
|
case '%':
|
|
lv[i++] = Sprintf("%d%%", len)->ptr;
|
|
break;
|
|
case '*':
|
|
lv[i++] = "*";
|
|
break;
|
|
default:
|
|
lv[i++] = Sprintf("%d", len)->ptr;
|
|
break;
|
|
}
|
|
|
|
if (!(p = strchr(q, ',')))
|
|
break;
|
|
}
|
|
|
|
*ret = lv;
|
|
return i;
|
|
}
|
|
|
|
struct frameset *
|
|
newFrameSet(struct parsed_tag *tag)
|
|
{
|
|
struct frameset *f;
|
|
int i;
|
|
char *cols = NULL, *rows = NULL;
|
|
|
|
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);
|
|
f->col = parseFrameSetLength(cols, &f->width);
|
|
f->row = parseFrameSetLength(rows, &f->height);
|
|
f->i = 0;
|
|
i = f->row * f->col;
|
|
f->frame = New_N(union frameset_element, i);
|
|
do {
|
|
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_encode(remove_space(p), body->baseURL,
|
|
buf->document_charset);
|
|
if (parsedtag_get_value(tag, ATTR_NAME, &p) && *p != '_')
|
|
body->name = url_quote_conv(p, buf->document_charset);
|
|
}
|
|
return body;
|
|
}
|
|
|
|
static void
|
|
unloadFrame(struct frame_body *b)
|
|
{
|
|
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));
|
|
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;
|
|
f_body->source = buf->sourcefile;
|
|
buf->sourcefile = NULL;
|
|
if (buf->mailcap_source) {
|
|
f_body->source = buf->mailcap_source;
|
|
buf->mailcap_source = 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;
|
|
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 | RG_FRAME_SRC, b->request);
|
|
#ifdef USE_SSL
|
|
/* XXX certificate? */
|
|
if (buf && buf != NO_BUFFER)
|
|
b->ssl_certificate = buf->ssl_certificate;
|
|
#endif
|
|
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->type = buf->type;
|
|
b->source = buf->sourcefile;
|
|
buf->sourcefile = NULL;
|
|
if (buf->mailcap_source) {
|
|
b->source = buf->mailcap_source;
|
|
buf->mailcap_source = 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;
|
|
}
|
|
|
|
#define CASE_TABLE_TAG \
|
|
case HTML_TR:\
|
|
case HTML_N_TR:\
|
|
case HTML_TD:\
|
|
case HTML_N_TD:\
|
|
case HTML_TH:\
|
|
case HTML_N_TH:\
|
|
case HTML_THEAD:\
|
|
case HTML_N_THEAD:\
|
|
case HTML_TBODY:\
|
|
case HTML_N_TBODY:\
|
|
case HTML_TFOOT:\
|
|
case HTML_N_TFOOT:\
|
|
case HTML_COLGROUP:\
|
|
case HTML_N_COLGROUP:\
|
|
case HTML_COL
|
|
|
|
static int
|
|
createFrameFile(struct frameset *f, FILE * f1, Buffer *current, int level,
|
|
int force_reload)
|
|
{
|
|
int r, c, t_stack;
|
|
URLFile f2;
|
|
#ifdef USE_M17N
|
|
wc_ces charset, doc_charset;
|
|
#endif
|
|
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) {
|
|
TRAP_OFF;
|
|
return -1;
|
|
}
|
|
TRAP_ON;
|
|
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;
|
|
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 = "";
|
|
int status = R_ST_NORMAL;
|
|
Str tok = Strnew();
|
|
int pre_mode = 0;
|
|
int end_tag = 0;
|
|
|
|
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:
|
|
/* FIXME: gettextize? */
|
|
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)
|
|
/* FIXME: gettextize? */
|
|
fprintf(f1, "Open %s with other method",
|
|
html_quote(frame.body->url));
|
|
else if (frame.body->url)
|
|
/* FIXME: gettextize? */
|
|
fprintf(f1, "Can't open %s",
|
|
html_quote(frame.body->url));
|
|
else
|
|
/* FIXME: gettextize? */
|
|
fprintf(f1,
|
|
"This frame (%s) contains no src attribute",
|
|
frame.body->name ? html_quote(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 USE_M17N
|
|
charset = WC_CES_US_ASCII;
|
|
if (current->document_charset != WC_CES_US_ASCII)
|
|
doc_charset = current->document_charset;
|
|
else
|
|
doc_charset = DocumentCharset;
|
|
#endif
|
|
t_stack = 0;
|
|
if (frame.body->type &&
|
|
!strcasecmp(frame.body->type, "text/plain")) {
|
|
Str tmp;
|
|
fprintf(f1, "<pre>\n");
|
|
while ((tmp = StrmyUFgets(&f2)) && tmp->length) {
|
|
tmp = convertLine(NULL, tmp, HTML_MODE, &charset,
|
|
doc_charset);
|
|
fprintf(f1, "%s", html_quote(tmp->ptr));
|
|
}
|
|
fprintf(f1, "</pre>\n");
|
|
UFclose(&f2);
|
|
break;
|
|
}
|
|
do {
|
|
int is_tag = FALSE;
|
|
char *q;
|
|
struct parsed_tag *tag;
|
|
|
|
do {
|
|
if (*p == '\0') {
|
|
Str tmp = StrmyUFgets(&f2);
|
|
if (!tmp || tmp->length == 0)
|
|
break;
|
|
tmp = convertLine(NULL, tmp, HTML_MODE, &charset,
|
|
doc_charset);
|
|
p = tmp->ptr;
|
|
}
|
|
read_token(tok, &p, &status, 1, status != R_ST_NORMAL);
|
|
} while (status != R_ST_NORMAL);
|
|
|
|
if (tok->length == 0)
|
|
continue;
|
|
|
|
if (tok->ptr[0] == '<') {
|
|
if (tok->ptr[1] &&
|
|
REALLY_THE_BEGINNING_OF_A_TAG(tok->ptr))
|
|
is_tag = TRUE;
|
|
else if (!(pre_mode & (RB_PLAIN | RB_INTXTA |
|
|
RB_SCRIPT | RB_STYLE))) {
|
|
p = Strnew_m_charp(tok->ptr + 1, p, NULL)->ptr;
|
|
tok = Strnew_charp("<");
|
|
}
|
|
}
|
|
if (is_tag) {
|
|
if (pre_mode & (RB_PLAIN | RB_INTXTA | RB_SCRIPT |
|
|
RB_STYLE)) {
|
|
q = tok->ptr;
|
|
if ((tag = parse_tag(&q, FALSE)) &&
|
|
tag->tagid == end_tag) {
|
|
if (pre_mode & RB_PLAIN) {
|
|
fputs("</PRE_PLAIN>", f1);
|
|
pre_mode = 0;
|
|
end_tag = 0;
|
|
goto token_end;
|
|
}
|
|
pre_mode = 0;
|
|
end_tag = 0;
|
|
goto proc_normal;
|
|
}
|
|
if (strncmp(tok->ptr, "<!--", 4) &&
|
|
(q = strchr(tok->ptr + 1, '<'))) {
|
|
tok = Strnew_charp_n(tok->ptr, q - tok->ptr);
|
|
p = Strnew_m_charp(q, p, NULL)->ptr;
|
|
status = R_ST_NORMAL;
|
|
}
|
|
is_tag = FALSE;
|
|
}
|
|
else if (pre_mode & RB_INSELECT) {
|
|
q = tok->ptr;
|
|
if ((tag = parse_tag(&q, FALSE))) {
|
|
if ((tag->tagid == end_tag) ||
|
|
(tag->tagid == HTML_N_FORM)) {
|
|
if (tag->tagid == HTML_N_FORM)
|
|
fputs("</SELECT>", f1);
|
|
pre_mode = 0;
|
|
end_tag = 0;
|
|
goto proc_normal;
|
|
}
|
|
if (t_stack) {
|
|
switch (tag->tagid) {
|
|
case HTML_TABLE:
|
|
case HTML_N_TABLE:
|
|
CASE_TABLE_TAG:
|
|
fputs("</SELECT>", f1);
|
|
pre_mode = 0;
|
|
end_tag = 0;
|
|
goto proc_normal;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
proc_normal:
|
|
if (is_tag) {
|
|
char *q = tok->ptr;
|
|
int j, a_target = 0;
|
|
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:
|
|
/* "BASE" is prohibit tag */
|
|
if (parsedtag_get_value(tag, ATTR_HREF, &q)) {
|
|
q = url_encode(remove_space(q), NULL, charset);
|
|
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, charset);
|
|
}
|
|
Strshrinkfirst(tok, 1);
|
|
Strshrink(tok, 1);
|
|
fprintf(f1, "<!-- %s -->", html_quote(tok->ptr));
|
|
goto token_end;
|
|
case HTML_META:
|
|
if (parsedtag_get_value(tag, ATTR_HTTP_EQUIV, &q)
|
|
&& !strcasecmp(q, "refresh")) {
|
|
if (parsedtag_get_value(tag, ATTR_CONTENT, &q)
|
|
) {
|
|
Str s_tmp = NULL;
|
|
int refresh_interval =
|
|
getMetaRefreshParam(q, &s_tmp);
|
|
if (s_tmp) {
|
|
q = html_quote(s_tmp->ptr);
|
|
fprintf(f1,
|
|
"Refresh (%d sec) <a href=\"%s\">%s</a>\n",
|
|
refresh_interval, q, q);
|
|
}
|
|
}
|
|
}
|
|
#ifdef USE_M17N
|
|
if (UseContentCharset &&
|
|
parsedtag_get_value(tag, ATTR_HTTP_EQUIV, &q)
|
|
&& !strcasecmp(q, "Content-Type")
|
|
&& parsedtag_get_value(tag, ATTR_CONTENT, &q)
|
|
&& (q = strcasestr(q, "charset")) != NULL) {
|
|
q += 7;
|
|
SKIP_BLANKS(q);
|
|
if (*q == '=') {
|
|
wc_ces c;
|
|
q++;
|
|
SKIP_BLANKS(q);
|
|
if ((c = wc_guess_charset(q, 0)) != 0) {
|
|
doc_charset = c;
|
|
charset = WC_CES_US_ASCII;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
/* fall thru, "META" is prohibit tag */
|
|
case HTML_HEAD:
|
|
case HTML_N_HEAD:
|
|
case HTML_BODY:
|
|
case HTML_N_BODY:
|
|
case HTML_DOCTYPE:
|
|
/* prohibit_tags */
|
|
Strshrinkfirst(tok, 1);
|
|
Strshrink(tok, 1);
|
|
fprintf(f1, "<!-- %s -->", html_quote(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 -->",
|
|
html_quote(tok->ptr));
|
|
goto token_end;
|
|
}
|
|
break;
|
|
CASE_TABLE_TAG:
|
|
/* table_tags MUST be in table stack */
|
|
if (!t_stack) {
|
|
Strshrinkfirst(tok, 1);
|
|
Strshrink(tok, 1);
|
|
fprintf(f1, "<!-- %s -->",
|
|
html_quote(tok->ptr));
|
|
goto token_end;
|
|
|
|
}
|
|
break;
|
|
case HTML_SELECT:
|
|
pre_mode = RB_INSELECT;
|
|
end_tag = HTML_N_SELECT;
|
|
break;
|
|
case HTML_TEXTAREA:
|
|
pre_mode = RB_INTXTA;
|
|
end_tag = HTML_N_TEXTAREA;
|
|
break;
|
|
case HTML_SCRIPT:
|
|
pre_mode = RB_SCRIPT;
|
|
end_tag = HTML_N_SCRIPT;
|
|
break;
|
|
case HTML_STYLE:
|
|
pre_mode = RB_STYLE;
|
|
end_tag = HTML_N_STYLE;
|
|
break;
|
|
case HTML_LISTING:
|
|
pre_mode = RB_PLAIN;
|
|
end_tag = HTML_N_LISTING;
|
|
fputs("<PRE_PLAIN>", f1);
|
|
goto token_end;
|
|
case HTML_XMP:
|
|
pre_mode = RB_PLAIN;
|
|
end_tag = HTML_N_XMP;
|
|
fputs("<PRE_PLAIN>", f1);
|
|
goto token_end;
|
|
case HTML_PLAINTEXT:
|
|
pre_mode = RB_PLAIN;
|
|
end_tag = MAX_HTMLTAG;
|
|
fputs("<PRE_PLAIN>", f1);
|
|
goto token_end;
|
|
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_encode(remove_space(tag->value[j]),
|
|
&base, charset);
|
|
tag->need_reconstruct = TRUE;
|
|
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;
|
|
parsedtag_set_value(tag,
|
|
ATTR_REFERER,
|
|
parsedURL2Str(&base)->ptr);
|
|
#ifdef USE_M17N
|
|
if (tag->attrid[j] == ATTR_ACTION &&
|
|
charset != WC_CES_US_ASCII)
|
|
parsedtag_set_value(tag,
|
|
ATTR_CHARSET,
|
|
wc_ces_to_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))
|
|
tok = parsedtag2str(tag);
|
|
Strfputs(tok, f1);
|
|
}
|
|
else {
|
|
if (pre_mode & RB_PLAIN)
|
|
fprintf(f1, "%s", html_quote(tok->ptr));
|
|
else if (pre_mode & RB_INTXTA)
|
|
fprintf(f1, "%s",
|
|
html_quote(html_unquote(tok->ptr)));
|
|
else
|
|
Strfputs(tok, f1);
|
|
}
|
|
token_end:
|
|
Strclear(tok);
|
|
} while (*p != '\0' || !iseos(f2.stream));
|
|
if (pre_mode & RB_PLAIN)
|
|
fputs("</PRE_PLAIN>\n", f1);
|
|
else if (pre_mode & RB_INTXTA)
|
|
fputs("</TEXTAREA></FORM>\n", f1);
|
|
else if (pre_mode & RB_INSELECT)
|
|
fputs("</SELECT></FORM>\n", f1);
|
|
else if (pre_mode & (RB_SCRIPT | RB_STYLE)) {
|
|
if (status != R_ST_NORMAL)
|
|
fputs(correct_irrtag(status)->ptr, f1);
|
|
if (pre_mode & RB_SCRIPT)
|
|
fputs("</SCRIPT>\n", f1);
|
|
else if (pre_mode & RB_STYLE)
|
|
fputs("</STYLE>\n", f1);
|
|
}
|
|
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);
|
|
TRAP_OFF;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Buffer *
|
|
renderFrame(Buffer *Cbuf, int force_reload)
|
|
{
|
|
Str tmp;
|
|
FILE *f;
|
|
Buffer *buf;
|
|
int flag;
|
|
struct frameset *fset;
|
|
#ifdef USE_M17N
|
|
wc_ces doc_charset = DocumentCharset;
|
|
#endif
|
|
|
|
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) {
|
|
fclose(f);
|
|
return NULL;
|
|
}
|
|
fclose(f);
|
|
flag = RG_FRAME;
|
|
if ((Cbuf->currentURL).is_nocache)
|
|
flag |= RG_NOCACHE;
|
|
renderFrameSet = Cbuf->frameset;
|
|
flushFrameSet(renderFrameSet);
|
|
#ifdef USE_M17N
|
|
DocumentCharset = InnerCharset;
|
|
#endif
|
|
buf = loadGeneralFile(tmp->ptr, NULL, NULL, flag, NULL);
|
|
#ifdef USE_M17N
|
|
DocumentCharset = doc_charset;
|
|
#endif
|
|
renderFrameSet = NULL;
|
|
if (buf == NULL || buf == NO_BUFFER)
|
|
return NULL;
|
|
buf->sourcefile = tmp->ptr;
|
|
#ifdef USE_M17N
|
|
buf->document_charset = Cbuf->document_charset;
|
|
#endif
|
|
copyParsedURL(&buf->currentURL, &Cbuf->currentURL);
|
|
preFormUpdateBuffer(buf);
|
|
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;
|
|
}
|