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, "method", html_context->doc_cp); if (al) { if (!c_strcasecmp(al, "post")) { unsigned char *enctype; enctype = get_attr_val(a, "enctype", html_context->doc_cp); form->method = FORM_METHOD_POST; if (enctype) { if (!c_strcasecmp(enctype, "multipart/form-data")) form->method = FORM_METHOD_POST_MP; else if (!c_strcasecmp(enctype, "text/plain")) form->method = FORM_METHOD_POST_TEXT_PLAIN; mem_free(enctype); } } mem_free(al); } form->onsubmit = get_attr_val(a, "onsubmit", html_context->doc_cp); al = get_attr_val(a, "name", html_context->doc_cp); if (al) form->name = al; al = get_attr_val(a, "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(form->action, POST_CHAR)); /* GET method URIs should not have '?'. */ assert(!form->action || form->method != FORM_METHOD_GET || !strchr(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); }
unsigned char * get_content_type(struct cache_entry *cached) { unsigned char *extension, *ctype; debug_get_content_type_params(cached); if (cached->content_type) return cached->content_type; /* If there's one in header, it's simple.. */ if (cached->head) { ctype = get_cache_header_content_type(cached); if (ctype && *ctype) { cached->content_type = ctype; return ctype; } mem_free_if(ctype); } /* We can't use the extension string we are getting below, because we * want to support also things like "ps.gz" - that'd never work, as we * would always compare only to "gz". */ /* Guess type accordingly to the extension */ extension = get_extension_from_uri(cached->uri); debug_extension(extension); if (extension) { /* XXX: A little hack for making extension handling case * insensitive. We could probably do it better by making * guess_encoding() case independent the real problem however * is with default (via option system) and mimetypes resolving * doing that option and hash lookup will not be easy to * convert. --jonas */ convert_to_lowercase_locale_indep(extension, strlen(extension)); ctype = get_extension_content_type(extension); mem_free(extension); if (ctype && *ctype) { cached->content_type = ctype; return ctype; } mem_free_if(ctype); } ctype = get_fragment_content_type(cached); if (ctype && *ctype) { cached->content_type = ctype; return ctype; } debug_ctype(get_default_mime_type()); /* text/plain for pager mode */ if (cached->uri && cached->uri->string && !strcmp(cached->uri->string, "file:///dev/stdin")) { cached->content_type = stracpy("text/plain"); } else /* Fallback.. use some hardwired default */ cached->content_type = stracpy(get_default_mime_type()); return cached->content_type; }
void html_input(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) { unsigned char *al; struct form_control *fc; int cp = html_context->doc_cp; fc = init_form_control(FC_TEXT, a, html_context); if (!fc) return; al = get_attr_val(a, "type", cp); if (al) { if (!c_strcasecmp(al, "text")) fc->type = FC_TEXT; else if (!c_strcasecmp(al, "hidden")) fc->type = FC_HIDDEN; else if (!c_strcasecmp(al, "button")) fc->type = FC_BUTTON; else if (!c_strcasecmp(al, "checkbox")) fc->type = FC_CHECKBOX; else if (!c_strcasecmp(al, "radio")) fc->type = FC_RADIO; else if (!c_strcasecmp(al, "password")) fc->type = FC_PASSWORD; else if (!c_strcasecmp(al, "submit")) fc->type = FC_SUBMIT; else if (!c_strcasecmp(al, "reset")) fc->type = FC_RESET; else if (!c_strcasecmp(al, "file")) fc->type = FC_FILE; else if (!c_strcasecmp(al, "image")) fc->type = FC_IMAGE; /* else unknown type, let it default to FC_TEXT. */ mem_free(al); } if (fc->type == FC_HIDDEN) fc->default_value = get_lit_attr_val(a, "value", cp); else if (fc->type != FC_FILE) fc->default_value = get_attr_val(a, "value", cp); if (!fc->default_value) { if (fc->type == FC_CHECKBOX) fc->default_value = stracpy("on"); else if (fc->type == FC_SUBMIT) fc->default_value = stracpy("Submit"); else if (fc->type == FC_RESET) fc->default_value = stracpy("Reset"); else if (fc->type == FC_BUTTON) fc->default_value = stracpy("Button"); } if (!fc->default_value) fc->default_value = stracpy(""); fc->id = get_attr_val(a, "id", cp); fc->name = get_attr_val(a, "name", cp); fc->size = get_num(a, "size", cp); if (fc->size == -1) fc->size = html_context->options->default_form_input_size; fc->size++; if (fc->size > html_context->options->box.width) fc->size = html_context->options->box.width; fc->maxlength = get_num(a, "maxlength", cp); if (fc->maxlength == -1) fc->maxlength = INT_MAX; if (fc->type == FC_CHECKBOX || fc->type == FC_RADIO) fc->default_state = has_attr(a, "checked", cp); if (fc->type == FC_IMAGE) fc->alt = get_attr_val(a, "alt", cp); if (fc->type != FC_HIDDEN) { html_input_format(html_context, a, fc); } html_context->special_f(html_context, SP_CONTROL, fc); }
static void do_html_select(unsigned char *attr, unsigned char *html, unsigned char *eof, unsigned char **end, struct html_context *html_context) { struct conv_table *ct = html_context->special_f(html_context, SP_TABLE, NULL); struct form_control *fc; struct string lbl = NULL_STRING, orig_lbl = NULL_STRING; unsigned char **values = NULL; unsigned char **labels; unsigned char *name, *t_attr, *en; int namelen; int nnmi = 0; int order = 0; int preselect = -1; int group = 0; int i, max_width; int closing_tag; html_focusable(html_context, attr); init_menu(&lnk_menu); se: en = html; see: html = en; while (html < eof && *html != '<') html++; if (html >= eof) { abort: *end = html; if (lbl.source) done_string(&lbl); if (orig_lbl.source) done_string(&orig_lbl); if (values) { int j; for (j = 0; j < order; j++) mem_free_if(values[j]); mem_free(values); } destroy_menu(&lnk_menu); *end = en; return; } if (lbl.source) { unsigned char *q, *s = en; int l = html - en; while (l && isspace(s[0])) s++, l--; while (l && isspace(s[l-1])) l--; q = convert_string(ct, s, l, html_context->options->cp, CSM_DEFAULT, NULL, NULL, NULL); if (q) add_to_string(&lbl, q), mem_free(q); add_bytes_to_string(&orig_lbl, s, l); } if (html + 2 <= eof && (html[1] == '!' || html[1] == '?')) { html = skip_comment(html, eof); goto se; } if (parse_element(html, eof, &name, &namelen, &t_attr, &en)) { html++; goto se; } if (!namelen) goto see; if (name[0] == '/') { namelen--; if (!namelen) goto see; name++; closing_tag = 1; } else { closing_tag = 0; } if (closing_tag && !c_strlcasecmp(name, namelen, "SELECT", 6)) { add_select_item(&lnk_menu, &lbl, &orig_lbl, values, order, nnmi); goto end_parse; } if (!c_strlcasecmp(name, namelen, "OPTION", 6)) { add_select_item(&lnk_menu, &lbl, &orig_lbl, values, order, nnmi); if (!closing_tag) { unsigned char *value, *label; if (has_attr(t_attr, "disabled", html_context->doc_cp)) goto see; if (preselect == -1 && has_attr(t_attr, "selected", html_context->doc_cp)) preselect = order; value = get_attr_val(t_attr, "value", html_context->doc_cp); if (!mem_align_alloc(&values, order, order + 1, 0xFF)) goto abort; values[order++] = value; label = get_attr_val(t_attr, "label", html_context->doc_cp); if (label) new_menu_item(&lnk_menu, label, order - 1, 0); if (!value || !label) { init_string(&lbl); init_string(&orig_lbl); nnmi = !!label; } } goto see; } if (!c_strlcasecmp(name, namelen, "OPTGROUP", 8)) { add_select_item(&lnk_menu, &lbl, &orig_lbl, values, order, nnmi); if (group) new_menu_item(&lnk_menu, NULL, -1, 0), group = 0; if (!closing_tag) { unsigned char *label; label = get_attr_val(t_attr, "label", html_context->doc_cp); if (!label) { label = stracpy(""); if (!label) goto see; } new_menu_item(&lnk_menu, label, -1, 0); group = 1; } } goto see; end_parse: *end = en; if (!order) goto abort; labels = mem_calloc(order, sizeof(unsigned char *)); if (!labels) goto abort; fc = init_form_control(FC_SELECT, attr, html_context); if (!fc) { mem_free(labels); goto abort; } fc->id = get_attr_val(attr, "id", html_context->doc_cp); fc->name = get_attr_val(attr, "name", html_context->doc_cp); fc->default_state = preselect < 0 ? 0 : preselect; fc->default_value = order ? stracpy(values[fc->default_state]) : stracpy(""); fc->nvalues = order; fc->values = values; fc->menu = detach_menu(&lnk_menu); fc->labels = labels; menu_labels(fc->menu, "", labels); put_chrs(html_context, "[", 1); html_stack_dup(html_context, ELEMENT_KILLABLE); format.form = fc; format.style.attr |= AT_BOLD; max_width = 0; for (i = 0; i < order; i++) { if (!labels[i]) continue; #ifdef CONFIG_UTF8 if (html_context->options->utf8) int_lower_bound(&max_width, utf8_ptr2cells(labels[i], NULL)); else #endif /* CONFIG_UTF8 */ int_lower_bound(&max_width, strlen(labels[i])); } for (i = 0; i < max_width; i++) put_chrs(html_context, "_", 1); pop_html_element(html_context); put_chrs(html_context, "]", 1); html_context->special_f(html_context, SP_CONTROL, fc); }
void g_put_chars(struct g_part *p, unsigned char *s, int l) { struct g_object_text *t = NULL; struct link *link; if (putchars_link_ptr) { link = NULL; goto check_link; } while (par_format.align != AL_NO && p->cx == -1 && l && *s == ' ') s++, l--; if (!l) return; g_nobreak = 0; if (p->cx < par_format.leftmargin * G_HTML_MARGIN) p->cx = par_format.leftmargin * G_HTML_MARGIN; if (html_format_changed) { if (memcmp(&ta_cache, &format, sizeof(struct text_attrib_beginning)) || xstrcmp(cached_font_face, format.fontface) || cached_font_face == to_je_ale_prasarna || xstrcmp(format.link, last_link) || xstrcmp(format.target, last_target) || xstrcmp(format.image, last_image) || format.form != last_form || ((format.js_event || last_js_event) && compare_js_event_spec(format.js_event, last_js_event)) ) { /*if (!html_format_changed) internal("html_format_changed not set");*/ flush_pending_text_to_line(p); if (xstrcmp(cached_font_face, format.fontface) || cached_font_face == to_je_ale_prasarna) { if (cached_font_face && cached_font_face != to_je_ale_prasarna) mem_free(cached_font_face); cached_font_face = stracpy(format.fontface); } memcpy(&ta_cache, &format, sizeof(struct text_attrib_beginning)); if (p->current_style) g_free_style(p->current_style); p->current_style = get_style_by_ta(&format); } html_format_changed = 0; } /*if (p->cx <= par_format.leftmargin * G_HTML_MARGIN && *s == ' ' && par_format.align != AL_NO) s++, l--;*/ if (!p->text) { link = NULL; t = mem_calloc(sizeof(struct g_object_text) + ALLOC_GR); t->mouse_event = g_text_mouse; t->draw = g_text_draw; t->destruct = g_text_destruct; t->get_list = NULL; /*t->style = get_style_by_ta(format);*/ t->style = g_clone_style(p->current_style); t->bg = NULL; /* FIXME!!! */ t->yw = t->style->height; /*t->xw = 0; t->y = 0;*/ if (format.baseline) { if (format.baseline < 0) t->y = -(t->style->height / 3); if (format.baseline > 0) t->y = get_real_font_size(format.baseline) - (t->style->height / 2); } check_link: if (last_link || last_image || last_form || format.link || format.image || format.form || format.js_event || last_js_event ) goto process_link; back_link: if (putchars_link_ptr) { *putchars_link_ptr = link; return; } if (!link) t->link_num = -1; else { t->link_num = link - p->data->links; t->link_order = link->obj_order++; } t->text[0] = 0; p->pending_text_len = 0; p->text = t; } if (p->pending_text_len == -1) { p->pending_text_len = strlen(p->text->text); goto a1; } if ((p->pending_text_len & ~(ALLOC_GR - 1)) != ((p->pending_text_len + l) & ~(ALLOC_GR - 1))) a1:{ struct g_object_text *t; if ((unsigned)l > MAXINT) overalloc(); if ((unsigned)p->pending_text_len + (unsigned)l > MAXINT - ALLOC_GR) overalloc(); t = mem_realloc(p->text, sizeof(struct g_object_text) + ((p->pending_text_len + l + ALLOC_GR) & ~(ALLOC_GR - 1))); if (p->w.last_wrap >= p->text->text && p->w.last_wrap < p->text->text + p->pending_text_len) p->w.last_wrap += (unsigned char *)t - (unsigned char *)p->text; if (p->w.last_wrap_obj == p->text) p->w.last_wrap_obj = t; p->text = t; } memcpy(p->text->text + p->pending_text_len, s, l), p->text->text[p->pending_text_len += l] = 0; p->text->xw += g_text_width(p->text->style, p->text->text + p->pending_text_len - l); /* !!! FIXME: move to g_wrap_text */ if (par_format.align != AL_NO) { p->w.text = p->text->text + p->pending_text_len - l; p->w.style = p->text->style; p->w.obj = p->text; p->w.width = rm(par_format) - par_format.leftmargin * G_HTML_MARGIN; if (p->w.width < 0) p->w.width = 0; if (!g_wrap_text(&p->w)) { split_line_object(p, p->w.last_wrap_obj, p->w.last_wrap); } } return; /* !!! WARNING: THE FOLLOWING CODE IS SHADOWED IN HTML_R.C */ process_link: if ((last_link /*|| last_target*/ || last_image || last_form) && !putchars_link_ptr && !xstrcmp(format.link, last_link) && !xstrcmp(format.target, last_target) && !xstrcmp(format.image, last_image) && format.form == last_form && ((!format.js_event && !last_js_event) || !compare_js_event_spec(format.js_event, last_js_event))) { if (!p->data) goto back_link; if (!p->data->nlinks) { internal("no link"); goto back_link; } link = &p->data->links[p->data->nlinks - 1]; goto back_link; } else { if (last_link) mem_free(last_link); if (last_target) mem_free(last_target); if (last_image) mem_free(last_image); free_js_event_spec(last_js_event); last_link = last_target = last_image = NULL; last_form = NULL; last_js_event = NULL; if (!(format.link || format.image || format.form || format.js_event)) goto back_link; /*if (d_opt->num_links) { unsigned char s[64]; unsigned char *fl = format.link, *ft = format.target, *fi = format.image; struct form_control *ff = format.form; struct js_event_spec *js = format.js_event; format.link = format.target = format.image = NULL; format.form = NULL; format.js_event = NULL; s[0] = '['; snzprint(s + 1, 62, p->link_num); strcat(s, "]"); g_put_chars(p, s, strlen(s)); if (ff && ff->type == FC_TEXTAREA) g_line_break(p); if (p->cx < par_format.leftmargin * G_HTML_MARGIN) p->cx = par_format.leftmargin * G_HTML_MARGIN; format.link = fl, format.target = ft, format.image = fi; format.form = ff; format.js_event = js; }*/ p->link_num++; last_link = stracpy(format.link); last_target = stracpy(format.target); last_image = stracpy(format.image); last_form = format.form; copy_js_event_spec(&last_js_event, format.js_event); if (!p->data) goto back_link; if (!(link = new_link(p->data))) goto back_link; link->num = p->link_num - 1; link->pos = DUMMY; copy_js_event_spec(&link->js_event, format.js_event); if (!last_form) { link->type = L_LINK; link->where = stracpy(last_link); link->target = stracpy(last_target); } else { link->type = last_form->type == FC_TEXT || last_form->type == FC_PASSWORD || last_form->type == FC_FILE ? L_FIELD : last_form->type == FC_TEXTAREA ? L_AREA : last_form->type == FC_CHECKBOX || last_form->type == FC_RADIO ? L_CHECKBOX : last_form->type == FC_SELECT ? L_SELECT : L_BUTTON; link->form = last_form; link->target = stracpy(last_form->target); } link->where_img = stracpy(last_image); link->sel_color = 0; link->n = 0; } goto back_link; }
void do_image(struct g_part *p, struct image_description *im) { struct g_object_image *io; struct link *link; link = NULL; putchars_link_ptr = &link; g_put_chars(p, NULL, 0); putchars_link_ptr = NULL; if (!link) im->link_num = -1; else { im->link_num = link - p->data->links; im->link_order = link->obj_order++; if (link->img_alt) mem_free(link->img_alt); link->img_alt = stracpy(im->alt); } io = insert_image(p, im); if (!io) goto ab; io->ismap = im->ismap; add_object(p, (struct g_object *)io); if (im->usemap && p->data) { unsigned char *tag = extract_position(im->usemap); struct additional_file *af = request_additional_file(current_f_data, im->usemap); af->need_reparse = 1; if (af->rq && (af->rq->state == O_LOADING || af->rq->state == O_INCOMPLETE || af->rq->state == O_OK) && af->rq->ce) { struct memory_list *ml; struct menu_item *menu; struct cache_entry *ce = af->rq->ce; unsigned char *start, *end; int i; struct image_map *map; get_file(af->rq, &start, &end); if (start == end) goto ft; if (get_image_map(ce->head, start, end, tag, &menu, &ml, format.href_base, format.target_base, 0, 0, 0, 1)) goto ft; map = mem_alloc(sizeof(struct image_map)); map->n_areas = 0; for (i = 0; menu[i].text; i++) { struct link_def *ld = menu[i].data; struct map_area *a; struct link *link; int shape = !ld->shape || !*ld->shape ? SHAPE_RECT : !strcasecmp(ld->shape, "default") ? SHAPE_DEFAULT : !strcasecmp(ld->shape, "rect") ? SHAPE_RECT : !strcasecmp(ld->shape, "circle") ? SHAPE_CIRCLE : !strcasecmp(ld->shape, "poly") || !strcasecmp(ld->shape, "polygon") ? SHAPE_POLY : -1; if (shape == -1) continue; if ((unsigned)map->n_areas > (MAXINT - sizeof(struct image_map)) / sizeof(struct map_area) - 1) overalloc(); map = mem_realloc(map, sizeof(struct image_map) + (map->n_areas + 1) * sizeof(struct map_area)); a = &map->area[map->n_areas++]; a->shape = shape; a->coords = DUMMY; a->ncoords = 0; if (ld->coords) { unsigned char *p = ld->coords; int num; next_coord: num = 0; while (*p && (*p < '0' || *p > '9')) p++; if (!*p) goto noc; while (*p >= '0' && *p <= '9' && num < 10000000) num = num * 10 + *p - '0', p++; if (*p == '.') { p++; while (*p >= '0' && *p <= '9') p++; } if (*p == '%' && num < 1000) { int m = io->xw < io->yw ? io->xw : io->yw; num = num * m / 100; p++; } else num = num * d_opt->image_scale / 100; if ((unsigned)a->ncoords > MAXINT / sizeof(int) - 1) overalloc(); a->coords = mem_realloc(a->coords, (a->ncoords + 1) * sizeof(int)); a->coords[a->ncoords++] = num; goto next_coord; } noc: if (!(link = new_link(p->data))) a->link_num = -1; else { link->pos = DUMMY; link->type = L_LINK; link->where = stracpy(ld->link); link->target = stracpy(ld->target); link->img_alt = stracpy(ld->label); link->where_img = stracpy(im->url); #ifdef JS if (ld->onclick || ld->ondblclick || ld->onmousedown || ld->onmouseup || ld->onmouseover || ld->onmouseout || ld->onmousemove) { create_js_event_spec(&link->js_event); link->js_event->click_code = stracpy(ld->onclick); link->js_event->dbl_code = stracpy(ld->ondblclick); link->js_event->down_code = stracpy(ld->onmousedown); link->js_event->up_code = stracpy(ld->onmouseup); link->js_event->over_code = stracpy(ld->onmouseover); link->js_event->out_code = stracpy(ld->onmouseout); link->js_event->move_code = stracpy(ld->onmousemove); } #endif a->link_num = link - p->data->links; } if (last_link) mem_free(last_link), last_link = NULL; } io->map = map; freeml(ml); ft:; } if (tag) mem_free(tag); } ab: if (im->usemap) mem_free(im->usemap); }
void html_frameset(struct html_context *html_context, unsigned char *a, unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5) { struct frameset_param fp; unsigned char *cols, *rows; int width, height; /* XXX: This is still not 100% correct. We should also ignore the * frameset when we encountered anything 3v1l (read as: non-whitespace * text/element/anything) in the document outside of <head>. Well, this * is still better than nothing and it should heal up the security * concerns at least because sane sites should enclose the documents in * <body> elements ;-). See also bug 171. --pasky */ if (search_html_stack(html_context, (unsigned char *)"BODY") || !html_context->options->frames || !html_context->special_f(html_context, SP_USED, NULL)) return; cols = get_attr_val(a, (unsigned char *)"cols", html_context->doc_cp); if (!cols) { cols = stracpy((const unsigned char *)"100%"); if (!cols) return; } rows = get_attr_val(a, (unsigned char *)"rows", html_context->doc_cp); if (!rows) { rows = stracpy((const unsigned char *)"100%"); if (!rows) { mem_free(cols); return; } } if (!html_top->frameset) { width = html_context->options->box.width; height = html_context->options->box.height; html_context->options->needs_height = 1; } else { struct frameset_desc *frameset_desc = html_top->frameset; int offset; if (frameset_desc->box.y >= frameset_desc->box.height) goto free_and_return; offset = frameset_desc->box.x + frameset_desc->box.y * frameset_desc->box.width; width = frameset_desc->frame_desc[offset].width; height = frameset_desc->frame_desc[offset].height; } fp.width = fp.height = NULL; parse_frame_widths(cols, width, HTML_FRAME_CHAR_WIDTH, &fp.width, &fp.x); parse_frame_widths(rows, height, HTML_FRAME_CHAR_HEIGHT, &fp.height, &fp.y); fp.parent = html_top->frameset; if (fp.x && fp.y) { html_top->frameset = (struct frameset_desc *)html_context->special_f(html_context, SP_FRAMESET, &fp); } mem_free_if(fp.width); mem_free_if(fp.height); free_and_return: mem_free(cols); mem_free(rows); }
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, "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("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, "ismap", html_context->doc_cp) && !usemap; if (display_style == 2 || display_style == 3) { label = get_attr_val(a, "alt", html_context->doc_cp); if (!label) label = get_attr_val(a, "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(label) > 5) clr_spaces(label); } src = null_or_stracpy(object_src); if (!src) src = get_url_val(a, "src", html_context->doc_cp); if (!src) src = get_url_val(a, "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("USEMAP"); } else if (ismap) { label = stracpy("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("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, "title", html_context->doc_cp); if (ismap) { unsigned char *new_link; html_stack_dup(html_context, ELEMENT_KILLABLE); new_link = straconcat(format.link, "?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); }
/* Extract the value of name part of the value of attribute content. * Ie. @name = "charset" and @str = "text/html; charset=iso-8859-1" * will store in *@ret an allocated string containing "iso-8859-1". * It supposes that separator is ';' and ignore first element in the * list. (ie. '1' is ignored in "1; URL=xxx") * The return value is one of: * * - HEADER_PARAM_FOUND: the parameter was found, copied, and stored in *@ret. * - HEADER_PARAM_NOT_FOUND: the parameter is not there. *@ret is now NULL. * - HEADER_PARAM_OUT_OF_MEMORY: error. *@ret is now NULL. * * If @ret is NULL, then this function doesn't actually access *@ret, * and cannot fail with HEADER_PARAM_OUT_OF_MEMORY. Some callers may * rely on this. */ enum parse_header_param parse_header_param(unsigned char *str, unsigned char *name, unsigned char **ret) { unsigned char *p = str; int namelen, plen = 0; if (ret) *ret = NULL; /* default in case of early return */ assert(str && name && *name); if_assert_failed return HEADER_PARAM_NOT_FOUND; /* Returns now if string @str is empty. */ if (!*p) return HEADER_PARAM_NOT_FOUND; namelen = strlen((const char *)name); do { p = (unsigned char *)strchr((char *)p, ';'); if (!p) return HEADER_PARAM_NOT_FOUND; while (*p && (*p == ';' || *p <= ' ')) p++; if (strlen((const char *)p) < namelen) return HEADER_PARAM_NOT_FOUND; } while (c_strncasecmp((const char *)p, (const char *)name, namelen)); p += namelen; while (*p && (*p <= ' ' || *p == '=')) p++; if (!*p) { if (ret) { *ret = stracpy((const unsigned char *)""); if (!*ret) return HEADER_PARAM_OUT_OF_MEMORY; } return HEADER_PARAM_FOUND; } while ((p[plen] > ' ' || LWS(p[plen])) && p[plen] != ';') plen++; /* Trim ending spaces */ while (plen > 0 && LWS(p[plen - 1])) plen--; /* XXX: Drop enclosing single quotes if there's some. * * Some websites like newsnow.co.uk are using single quotes around url * in URL field in meta tag content attribute like this: * <meta http-equiv="Refresh" content="0; URL='http://www.site.com/path/xxx.htm'"> * * This is an attempt to handle that, but it may break something else. * We drop all pair of enclosing quotes found (eg. '''url''' => url). * Please report any issue related to this. --Zas */ while (plen > 1 && *p == '\'' && p[plen - 1] == '\'') { p++; plen -= 2; } if (ret) { *ret = memacpy(p, plen); if (!*ret) return HEADER_PARAM_OUT_OF_MEMORY; } return HEADER_PARAM_FOUND; }