void location_goto(struct document_view *doc_view, unsigned char *url) { unsigned char *new_abs_url; struct uri *new_uri; struct delayed_goto *deg; /* Workaround for bug 611. Does not crash, but may lead to infinite loop.*/ if (!doc_view) return; new_abs_url = join_urls(doc_view->document->uri, trim_chars(url, ' ', 0)); if (!new_abs_url) return; new_uri = get_uri(new_abs_url, 0); mem_free(new_abs_url); if (!new_uri) return; deg = mem_calloc(1, sizeof(*deg)); if (!deg) { done_uri(new_uri); return; } assert(doc_view->vs); deg->vs = doc_view->vs; deg->uri = new_uri; /* It does not seem to be very safe inside of frames to * call goto_uri() right away. */ register_bottom_half(delayed_goto, deg); }
void html_a(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) { unsigned char *href; href = get_url_val(a, (unsigned char *)"href", html_context->doc_cp); if (href) { unsigned char *target; mem_free_set(&format.link, join_urls(html_context->base_href, trim_chars(href, ' ', 0))); mem_free(href); target = get_target(html_context->options, a); if (target) { mem_free_set(&format.target, target); } else { mem_free_set(&format.target, stracpy(html_context->base_target)); } if (0) { ; /* Shut up compiler */ #ifdef CONFIG_GLOBHIST } else if (get_global_history_item(format.link)) { format.style.color.foreground = format.color.vlink; html_top->pseudo_class &= ~ELEMENT_LINK; html_top->pseudo_class |= ELEMENT_VISITED; #endif #ifdef CONFIG_BOOKMARKS } else if (get_bookmark(format.link)) { format.style.color.foreground = format.color.bookmark_link; html_top->pseudo_class &= ~ELEMENT_VISITED; /* XXX: Really set ELEMENT_LINK? --pasky */ html_top->pseudo_class |= ELEMENT_LINK; #endif } else { format.style.color.foreground = format.color.clink; html_top->pseudo_class &= ~ELEMENT_VISITED; html_top->pseudo_class |= ELEMENT_LINK; } mem_free_set(&format.title, get_attr_val(a, (unsigned char *)"title", html_context->doc_cp)); html_focusable(html_context, a); } else { pop_html_element(html_context); } set_fragment_identifier(html_context, a, (unsigned char *)"name"); }
void html_frame(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) { unsigned char *name, *src, *url; src = get_url_val(a, (unsigned char *)"src", html_context->doc_cp); if (!src) { url = stracpy((const unsigned char *)"about:blank"); } else { url = join_urls(html_context->base_href, src); mem_free(src); } if (!url) return; name = get_attr_val(a, (unsigned char *)"name", html_context->doc_cp); if (!name) { name = stracpy(url); } else if (!name[0]) { /* When name doesn't have a value */ mem_free(name); name = stracpy(url); } if (!name) return; if (!html_context->options->frames || !html_top->frameset) { html_focusable(html_context, a); put_link_line((unsigned char *)"Frame: ", name, url, (unsigned char *)"", html_context); } else { if (html_context->special_f(html_context, SP_USED, NULL)) { html_context->special_f(html_context, SP_FRAME, html_top->frameset, name, url); } } mem_free(name); mem_free(url); }
void html_base(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) { unsigned char *al; al = get_url_val(a, (unsigned char *)"href", html_context->doc_cp); if (al) { unsigned char *base = join_urls(html_context->base_href, al); struct uri *uri = base ? get_uri(base, 0) : NULL; mem_free(al); mem_free_if(base); if (uri) { done_uri(html_context->base_href); html_context->base_href = uri; } } al = get_target(html_context->options, a); if (al) mem_free_set(&html_context->base_target, al); }
void end_dump(struct status *stat, void *p) { struct cache_entry *ce = stat->ce; int oh = get_output_handle(); if (oh == -1) return; if (ce && ce->redirect && dump_red_count++ < MAX_REDIRECTS) { unsigned char *u, *p; if (stat->state >= 0) change_connection(stat, NULL, PRI_CANCEL); u = join_urls(ce->url, ce->redirect); if (!http_bugs.bug_302_redirect) if (!ce->redirect_get && (p = strchr(ce->url, POST_CHAR))) add_to_strn(&u, p); load_url(u, stat, PRI_MAIN, 0); mem_free(u); return; } if (stat->state >= 0 && stat->state < S_TRANS) return; if (stat->state >= S_TRANS && dmp != D_SOURCE) return; if (dmp == D_SOURCE) { if (ce) { struct fragment *frag; nextfrag: foreach(frag, ce->frag) if (frag->offset <= dump_pos && frag->offset + frag->length > dump_pos) { int l = frag->length - (dump_pos - frag->offset); int w = hard_write(oh, frag->data + dump_pos - frag->offset, l); if (w != l) { detach_connection(stat, dump_pos); if (w < 0) fprintf(stderr, "Error writing to stdout: %s.\n", strerror(errno)); else fprintf(stderr, "Can't write to stdout.\n"); retval = RET_ERROR; goto terminate; } dump_pos += w; detach_connection(stat, dump_pos); goto nextfrag; } } if (stat->state >= 0) return; } else if (ce) {
/* prefix can have entities in it, but linkname cannot. */ void put_link_line(unsigned char *prefix, unsigned char *linkname, unsigned char *link, unsigned char *target, struct html_context *html_context) { html_context->has_link_lines = 1; html_stack_dup(html_context, ELEMENT_KILLABLE); ln_break(html_context, 1); mem_free_set(&format.link, NULL); mem_free_set(&format.target, NULL); mem_free_set(&format.title, NULL); format.form = NULL; put_chrs(html_context, prefix, strlen((const char *)prefix)); format.link = join_urls(html_context->base_href, link); format.target = stracpy(target); format.style.color.foreground = format.color.clink; /* linkname typically comes from get_attr_val, which * has already expanded character entity references. * Tell put_chrs not to expand them again. */ format.style.attr |= AT_NO_ENTITIES; put_chrs(html_context, linkname, strlen((const char *)linkname)); ln_break(html_context, 1); pop_html_element(html_context); }
static void html_img_do(unsigned char *a, unsigned char *object_src, struct html_context *html_context) { int ismap, usemap = 0; int add_brackets = 0; unsigned char *src = NULL; unsigned char *label = NULL; unsigned char *usemap_attr; struct document_options *options = html_context->options; int display_style = options->image_link.display_style; /* Note about display_style: * 0 means always display IMG * 1 means always display filename * 2 means display alt/title attribute if possible, IMG if not * 3 means display alt/title attribute if possible, filename if not */ usemap_attr = get_attr_val(a, (unsigned char *)"usemap", html_context->doc_cp); if (usemap_attr) { unsigned char *joined_urls = join_urls(html_context->base_href, usemap_attr); unsigned char *map_url; mem_free(usemap_attr); if (!joined_urls) return; map_url = straconcat((unsigned char *)"MAP@", joined_urls, (unsigned char *) NULL); mem_free(joined_urls); if (!map_url) return; html_stack_dup(html_context, ELEMENT_KILLABLE); mem_free_set(&format.link, map_url); format.form = NULL; format.style.attr |= AT_BOLD; usemap = 1; } ismap = format.link && has_attr(a, (unsigned char *)"ismap", html_context->doc_cp) && !usemap; if (display_style == 2 || display_style == 3) { label = get_attr_val(a, (unsigned char *)"alt", html_context->doc_cp); if (!label) label = get_attr_val(a, (unsigned char *)"title", html_context->doc_cp); /* Little hack to preserve rendering of [ ], in directory listings, * but we still want to drop extra spaces in alt or title attribute * to limit display width on certain websites. --Zas */ if (label && strlen((const char *)label) > 5) clr_spaces(label); } src = null_or_stracpy(object_src); if (!src) src = get_url_val(a, (unsigned char *)"src", html_context->doc_cp); if (!src) src = get_url_val(a, (unsigned char *)"dynsrc", html_context->doc_cp); /* If we have no label yet (no title or alt), so * just use default ones, or image filename. */ if (!label || !*label) { mem_free_set(&label, NULL); /* Do we want to display images with no alt/title and with no * link on them ? * If not, just exit now. */ if (!options->images && !format.link) { mem_free_if(src); if (usemap) pop_html_element(html_context); return; } add_brackets = 1; if (usemap) { label = stracpy((const unsigned char *)"USEMAP"); } else if (ismap) { label = stracpy((const unsigned char *)"ISMAP"); } else { if (display_style == 3) label = get_image_filename_from_src(options->image_link.filename_maxlen, src); } } else { label = get_image_label(options->image_link.label_maxlen, label); } if (!label || !*label) { mem_free_set(&label, NULL); add_brackets = 1; if (display_style == 1) label = get_image_filename_from_src(options->image_link.filename_maxlen, src); if (!label || !*label) mem_free_set(&label, stracpy((const unsigned char *)"IMG")); } mem_free_set(&format.image, NULL); mem_free_set(&format.title, NULL); if (label) { int img_link_tag = options->image_link.tagging; if (img_link_tag && (img_link_tag == 2 || add_brackets)) { unsigned char *img_link_prefix = options->image_link.prefix; unsigned char *img_link_suffix = options->image_link.suffix; unsigned char *new_label = straconcat(img_link_prefix, label, img_link_suffix, (unsigned char *) NULL); if (new_label) mem_free_set(&label, new_label); } if (!options->image_link.show_any_as_links) { put_image_label(a, label, html_context); } else { if (src) { format.image = join_urls(html_context->base_href, src); } format.title = get_attr_val(a, (unsigned char *)"title", html_context->doc_cp); if (ismap) { unsigned char *new_link; html_stack_dup(html_context, ELEMENT_KILLABLE); new_link = straconcat(format.link, (unsigned char *)"?0,0", (unsigned char *) NULL); if (new_link) mem_free_set(&format.link, new_link); } put_image_label(a, label, html_context); if (ismap) pop_html_element(html_context); mem_free_set(&format.image, NULL); mem_free_set(&format.title, NULL); } mem_free(label); } mem_free_if(src); if (usemap) pop_html_element(html_context); }
void html_form(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) { unsigned char *al; struct form *form; html_context->was_br = 1; form = init_form(); if (!form) return; form->method = FORM_METHOD_GET; form->form_num = a - html_context->startf; al = get_attr_val(a, (unsigned char *)"method", html_context->doc_cp); if (al) { if (!c_strcasecmp((const char *)al, "post")) { unsigned char *enctype; enctype = get_attr_val(a, (unsigned char *)"enctype", html_context->doc_cp); form->method = FORM_METHOD_POST; if (enctype) { if (!c_strcasecmp((const char *)enctype, "multipart/form-data")) form->method = FORM_METHOD_POST_MP; else if (!c_strcasecmp((const char *)enctype, "text/plain")) form->method = FORM_METHOD_POST_TEXT_PLAIN; mem_free(enctype); } } mem_free(al); } form->onsubmit = get_attr_val(a, (unsigned char *)"onsubmit", html_context->doc_cp); al = get_attr_val(a, (unsigned char *)"name", html_context->doc_cp); if (al) form->name = al; al = get_attr_val(a, (unsigned char *)"action", html_context->doc_cp); /* The HTML specification at * http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.3 states * that the behavior of an empty action attribute should be undefined. * Mozilla handles action="" as action="<current-URI>" which seems * reasonable. (bug 615) */ if (al && *al) { form->action = join_urls(html_context->base_href, trim_chars(al, ' ', NULL)); mem_free(al); } else { enum uri_component components = URI_ORIGINAL; mem_free_if(al); /* We have to do following for GET method, because we would end * up with two '?' otherwise. */ if (form->method == FORM_METHOD_GET) components = URI_FORM_GET; form->action = get_uri_string(html_context->base_href, components); /* No action URI should contain post data */ assert(!form->action || !strchr((char *)form->action, POST_CHAR)); /* GET method URIs should not have '?'. */ assert(!form->action || form->method != FORM_METHOD_GET || !strchr((char *)form->action, '?')); } al = get_target(html_context->options, a); form->target = al ? al : stracpy(html_context->base_target); html_context->special_f(html_context, SP_FORM, form); }
static void html_input_format(struct html_context *html_context, unsigned char *a, struct form_control *fc) { put_chrs(html_context, (unsigned char *)" ", 1); html_stack_dup(html_context, ELEMENT_KILLABLE); html_focusable(html_context, a); format.form = fc; if (format.title) mem_free(format.title); format.title = get_attr_val(a, (unsigned char *)"title", html_context->doc_cp); switch (fc->type) { case FC_TEXT: case FC_PASSWORD: case FC_FILE: { int i; format.style.attr |= AT_BOLD; for (i = 0; i < fc->size; i++) put_chrs(html_context, (unsigned char *)"_", 1); break; } case FC_CHECKBOX: format.style.attr |= AT_BOLD; put_chrs(html_context, (unsigned char *)"[ ]", 8); break; case FC_RADIO: format.style.attr |= AT_BOLD; put_chrs(html_context, (unsigned char *)"( )", 8); break; case FC_IMAGE: { unsigned char *al; mem_free_set(&format.image, NULL); al = get_url_val(a, (unsigned char *)"src", html_context->doc_cp); if (!al) al = get_url_val(a, (unsigned char *)"dynsrc", html_context->doc_cp); if (al) { format.image = join_urls(html_context->base_href, al); mem_free(al); } format.style.attr |= AT_BOLD; put_chrs(html_context, (unsigned char *)"[ ", 7); format.style.attr |= AT_NO_ENTITIES; if (fc->alt) put_chrs(html_context, fc->alt, strlen((const char *)fc->alt)); else if (fc->name) put_chrs(html_context, fc->name, strlen((const char *)fc->name)); else put_chrs(html_context, (unsigned char *)"Submit", 6); format.style.attr &= ~AT_NO_ENTITIES; put_chrs(html_context, (unsigned char *)" ]", 7); break; } case FC_SUBMIT: case FC_RESET: case FC_BUTTON: format.style.attr |= AT_BOLD; put_chrs(html_context, (unsigned char *)"[ ", 7); if (fc->default_value) { format.style.attr |= AT_NO_ENTITIES; put_chrs(html_context, fc->default_value, strlen((const char *)fc->default_value)); format.style.attr &= ~AT_NO_ENTITIES; } put_chrs(html_context, (unsigned char *)" ]", 7); break; case FC_TEXTAREA: case FC_SELECT: case FC_HIDDEN: INTERNAL("bad control type"); } pop_html_element(html_context); put_chrs(html_context, (unsigned char *)" ", 1); }
void html_a( struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5 ) { int eax; int ecx; int edx; unsigned char *href; if ( get_attr_value( a, "href", html_context->doc_cp, HTML_ATTR_EAT_NL ) ) { unsigned char *target; if ( html_context->stack.list_head_elinks ) { mem_free( &html_context->stack.list_head_elinks ); } strlen( &href[0] ); if ( href[0] == ' ' ) { do { href[0] = href[1]; *(int*)(strlen( &href[0] ))--; } while ( href[0] == ' ' ); } if ( eax ) { if ( href[ eax - 1 ] == ' ' ) { do { *(char*)(edx - 1) = 0; if ( eax == 1 ) href[0] = href[0]; else } while ( *(char*)(edx - 2) != ' ' ); href[0] = href[0]; } eax += 0; memmove( &href[0], &href[0], 1 ); &html_context->stack.list_head_elinks = ((void)( struct css_stylesheet *, struct uri *, unsigned char *, int )*)join_urls( html_context->base_href, &href[0] ); mem_free( &href[0] ); if ( get_target( html_context->options, a ) ) { if ( html_context->stack.list_head_elinks ) { mem_free( &html_context->stack.list_head_elinks ); html_context->stack.next = html_context->stack.next; } &html_context->stack.list_head_elinks = &target[0]; } else { if ( html_context->stack.list_head_elinks ) { mem_free( &html_context->stack.list_head_elinks ); } &html_context->stack.list_head_elinks = ((void)( struct css_stylesheet *, struct uri *, unsigned char *, int )*)stracpy( html_context->base_target ); } if ( get_global_history_item( &html_context->stack.list_head_elinks ) ) { &html_context->stack.list_head_elinks = &html_context->stack.list_head_elinks; &html_context->stack.list_head_elinks &= -2; &html_context->stack.list_head_elinks |= 2; } else { &html_context->stack.list_head_elinks = html_context->stack.next ? &html_context->stack.list_head_elinks : &html_context->stack.list_head_elinks; &html_context->stack.list_head_elinks &= -3; &html_context->stack.list_head_elinks |= 1; } if ( html_context->stack.list_head_elinks ) { mem_free( &html_context->stack.list_head_elinks ); } &html_context->stack.list_head_elinks = ((void)( struct css_stylesheet *, struct uri *, unsigned char *, int )*)get_attr_value( a, "title", html_context->doc_cp, HTML_ATTR_NONE ); html_focusable( &html_context[0], a ); xxx3 = "name"; html_context = &html_context[0]; a = a; } memmove( &href[0], &href[0], 1 ); &html_context->stack.list_head_elinks = ((void)( struct css_stylesheet *, struct uri *, unsigned char *, int )*)join_urls( html_context->base_href, &href[0] ); mem_free( &href[0] ); } else
void html_script(struct html_context *html_context, unsigned char *a, unsigned char *html, unsigned char *eof, unsigned char **end) { #ifdef CONFIG_ECMASCRIPT /* TODO: <noscript> processing. Well, same considerations apply as to * CSS property display: none processing. */ /* TODO: Charsets for external scripts. */ unsigned char *type, *language, *src; int in_comment = 0; #endif html_skip(html_context, a); #ifdef CONFIG_ECMASCRIPT /* We try to process nested <script> if we didn't process the parent * one. That's why's all the fuzz. */ /* Ref: * http://www.ietf.org/internet-drafts/draft-hoehrmann-script-types-03.txt */ type = get_attr_val(a, (unsigned char *)"type", html_context->doc_cp); if (type) { unsigned char *pos = type; if (!c_strncasecmp((const char *)type, "text/", 5)) { pos += 5; } else if (!c_strncasecmp((const char *)type, "application/", 12)) { pos += 12; } else { mem_free(type); not_processed: /* Permit nested scripts and retreat. */ html_top->invisible++; return; } if (!c_strncasecmp((const char *)pos, "javascript", 10)) { int len = strlen((const char *)pos); if (len > 10 && !isdigit(pos[10])) { mem_free(type); goto not_processed; } } else if (c_strcasecmp((const char *)pos, "ecmascript") && c_strcasecmp((const char *)pos, "jscript") && c_strcasecmp((const char *)pos, "livescript") && c_strcasecmp((const char *)pos, "x-javascript") && c_strcasecmp((const char *)pos, "x-ecmascript")) { mem_free(type); goto not_processed; } mem_free(type); } /* Check that the script content is ecmascript. The value of the * language attribute can be JavaScript with optional version digits * postfixed (like: ``JavaScript1.1''). * That attribute is deprecated in favor of type by HTML 4.01 */ language = get_attr_val(a, (unsigned char *)"language", html_context->doc_cp); if (language) { int languagelen = strlen((const char *)language); if (languagelen < 10 || (languagelen > 10 && !isdigit(language[10])) || c_strncasecmp((const char *)language, "javascript", 10)) { mem_free(language); html_top->invisible++; return; //goto not_processed; } mem_free(language); } if (html_context->part->document && (src = get_attr_val(a, (unsigned char *)"src", html_context->doc_cp))) { /* External reference. */ unsigned char *import_url; struct uri *uri; if (!get_opt_bool((const unsigned char *)"ecmascript.enable", NULL)) { mem_free(src); html_top->invisible++; return; //goto not_processed; } /* HTML <head> urls should already be fine but we can.t detect them. */ import_url = join_urls(html_context->base_href, src); mem_free(src); if (!import_url) goto imported; uri = get_uri(import_url, URI_BASE); if (!uri) goto imported; /* Request the imported script as part of the document ... */ html_context->special_f(html_context, SP_SCRIPT, uri); done_uri(uri); /* Create URL reference onload snippet. */ insert_in_string(&import_url, 0, (const unsigned char *)"^", 1); add_to_string_list(&html_context->part->document->onload_snippets, import_url, -1); imported: /* Retreat. Do not permit nested scripts, tho'. */ if (import_url) mem_free(import_url); return; } /* Positive, grab the rest and interpret it. */ /* First position to the real script start. */ while (html < eof && *html <= ' ') html++; if (eof - html > 4 && !strncmp((const char *)html, "<!--", 4)) { in_comment = 1; /* We either skip to the end of line or to -->. */ for (; *html != '\n' && *html != '\r' && eof - html >= 3; html++) { if (!strncmp((const char *)html, "-->", 3)) { /* This means the document is probably broken. * We will now try to process the rest of * <script> contents, which is however likely * to be empty. Should we try to process the * comment too? Currently it seems safer but * less tolerant to broken pages, if there are * any like this. */ html += 3; in_comment = 0; break; } } } *end = html; /* Now look ahead for the script end. The <script> contents is raw * CDATA, so we just look for the ending tag and need not care for * any quote marks counting etc - YET, we are more tolerant and permit * </script> stuff inside of the script if the whole <script> element * contents is wrapped in a comment. See i.e. Mozilla bug 26857 for fun * reading regarding this. */ for (; *end < eof; (*end)++) { unsigned char *name; int namelen; if (in_comment) { /* TODO: If we ever get some standards-quirk mode * distinction, this should be disabled in the * standards mode (and we should just look for CDATA * end, which is "</"). --pasky */ if (eof - *end >= 3 && !strncmp((const char *)*end, "-->", 3)) { /* Next iteration will jump passed the ending '>' */ (*end) += 2; in_comment = 0; } continue; /* XXX: Scan for another comment? That's admittelly * already stretching things a little bit to an * extreme ;-). */ } if (**end != '<') continue; /* We want to land before the closing element, that's why we * don't pass @end also as the appropriate parse_element() * argument. */ if (parse_element(*end, eof, &name, &namelen, NULL, NULL)) continue; if (c_strlcasecmp(name, namelen, (const unsigned char *)"/script", 7)) continue; /* We have won! */ break; } if (*end >= eof) { /* Either the document is not completely loaded yet or it's * broken. At any rate, run away screaming. */ *end = eof; /* Just for sanity. */ return; } if (html_context->part->document && *html != '^') { add_to_string_list(&html_context->part->document->onload_snippets, html, *end - html); } #endif }