void tn_func(struct session *ses, unsigned char *url, struct list_head *prog, unsigned char *t1, unsigned char *t2) { unsigned char *m; unsigned char *h, *p; int hl, pl; unsigned char *hh, *pp; int f = 1; if (parse_url(url, NULL, NULL, NULL, NULL, NULL, &h, &hl, &p, &pl, NULL, NULL, NULL) || !hl) goto fail; if (!(hh = memacpy(h, hl))) goto fail; if (pl && !(pp = memacpy(p, pl))) goto fail1; check_shell_security(&hh); if (pl) check_shell_security(&pp); m = mem_alloc(strlen(hh) + (pl ? strlen(pp) : 0) + 2); f = 0; strcpy(m, hh); if (pl) { strcat(m, " "); strcat(m, pp); m[hl + 1 + pl] = 0; } prog_func(ses->term, prog, m, t1); mem_free(m); if (pl) mem_free(pp); fail1: mem_free(hh); fail: if (f) msg_box(ses->term, NULL, TEXT(T_BAD_URL_SYNTAX), AL_CENTER, t2, NULL, 1, TEXT(T_CANCEL), NULL, B_ENTER | B_ESC); }
unsigned char *get_host_name(unsigned char *url) { unsigned char *h; int hl; if (parse_url(url, NULL, NULL, NULL, NULL, NULL, &h, &hl, NULL, NULL, NULL, NULL, NULL)) return stracpy(cast_uchar ""); return memacpy(h, hl); }
unsigned char *get_pass(unsigned char *url) { unsigned char *h; int hl; if (parse_url(url, NULL,NULL, NULL, &h, &hl, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) return NULL; return memacpy(h, hl); }
/* Inspired by Vim this is used to hook into the stdout write method so written * data is displayed in a nice message box. */ static VALUE erb_module_message(VALUE self, VALUE str) { unsigned char *message, *line_end; struct terminal *term; str = rb_obj_as_string(str); message = memacpy(RSTRING(str)->ptr, RSTRING(str)->len); if (!message) return Qnil; line_end = strchr(message, '\n'); if (line_end) *line_end = '\0'; term = get_default_terminal(); if (!term) { usrerror("[Ruby] %s", message); mem_free(message); return Qnil; } info_box(term, MSGBOX_NO_TEXT_INTL | MSGBOX_FREE_TEXT, N_("Ruby Message"), ALIGN_LEFT, message); return Qnil; }
/* Get image filename from its src attribute. */ static unsigned char * get_image_filename_from_src(int max_len, unsigned char *src) { unsigned char *text = NULL; unsigned char *start, *filename; int len; if (!src) return NULL; /* We can display image as [foo.gif]. */ len = strcspn((const char *)src, "?"); for (start = src + len; start > src; start--) if (dir_sep(start[-1])) { break; } len -= start - src; filename = memacpy(start, len); if (filename) { /* XXX: Due to a compatibility alias (added: 2004-12-15 in * 0.10pre3.CVS for document.browse.images.file_tags) this can * return a negative @max_len. */ text = truncate_label(filename, max_len); mem_free(filename); } return text; }
unsigned char *get_port_str(unsigned char *url) { unsigned char *h; int hl; if (parse_url(url, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &h, &hl, NULL, NULL, NULL)) return NULL; return hl ? memacpy(h, hl) : NULL; }
static unsigned char * get_fragment_content_type(struct cache_entry *cached) { struct fragment *fragment; size_t length; unsigned char *sample; unsigned char *ctype = NULL; if (list_empty(cached->frag)) return NULL; fragment = cached->frag.next; if (fragment->offset) return NULL; length = fragment->length > 1024 ? 1024 : fragment->length; sample = memacpy(fragment->data, length); if (!sample) return NULL; if (c_strcasestr((const char *)sample, "<html>")) ctype = stracpy("text/html"); mem_free(sample); return ctype; }
unsigned char *get_next_path_filename( unsigned char **path_ptr, unsigned char separator ) { int eax; int ecx; unsigned char *path; unsigned char *filename; int filenamelen; path[0] = path_ptr[0]; { unsigned char *tmp; filenamelen = 0; if ( path[0] & 255 ) { if ( path[0] != separator ) { do { path[0] = path[1]; if ( path[0] == 0 ) filenamelen = path[0] - path[0]; else { path_ptr[0] = path_ptr[0]; } } while ( path[0] != separator ); filenamelen = path[0] - path[0]; } path_ptr[0] = &path[1]; if ( filenamelen >= 1 ) { if ( memacpy( &path[0], filenamelen ) ) { mem_free( (void*)memacpy( &path[0], filenamelen ) ); return expand_tilde( memacpy( &path[0], filenamelen ) ); } filename[0] = 0; } } path_ptr[0] = &path[0]; if ( filenamelen >= 1 ) { } path_ptr[0] = &path[1]; } }
unsigned char * stracpy(const unsigned char *src) { assertm(src, "[stracpy]"); if_assert_failed return NULL; return memacpy(src, strlen((const char *)src)); }
unsigned char *get_host_and_pass(unsigned char *url) { unsigned char *u, *h, *p, *z, *k; int hl, pl; if (parse_url(url, NULL, &u, NULL, NULL, NULL, &h, &hl, &p, &pl, NULL, NULL, NULL)) return NULL; z = u ? u : h; k = p ? p + pl : h + hl; return memacpy(z, k - z); }
void parse_mimetypes_file( unsigned char *filename ) { int edx; FILE *file = fopen64( &filename[0], "rb" ); unsigned char line[1024]; if ( file ) { do { if ( fgets( line, 1023, file ) ) { unsigned char *ctype; unsigned char *token; if ( strchr( line, 35 ) ) *(char*)(strchr( line, 35 )) = 0; ctype[0] = line[0]; if ( ( ctype[0] & 255 ) && token[0] ) { token[0] = 0; if ( strchr( &ctype[0], 47 ) ) { token[0] = token[1]; while ( token[0] == 0 || token[0] == 0 ) { token[0] = 0; if ( !get_hash_item( mimetypes_map, &token[0], strlen( &token[0] ) ) && get_hash_item( mimetypes_map, &token[0], strlen( &token[0] ) ) ) { *ebp_1084 = memacpy( &ctype[0], strlen( &ctype[0] ) ); if ( ebp_1084 ) { memcpy( &token[0], &edi, edx + 4 ); if ( eax == 0 ) goto B34; else { token[0] = token[0] + 1; } } B34: done_mimetypes_entry( &edx ); } } } } } else fclose( file ); } while ( token[0] ); } if ( 0 ^ 0 ) { __stack_chk_fail( ); } return; }
void data_protocol_handler(struct connection *conn) { struct uri *uri = conn->uri; struct cache_entry *cached = get_cache_entry(uri); unsigned char *data_start, *data; int base64 = 0; if (!cached) { abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } conn->cached = cached; data_start = parse_data_protocol_header(conn, &base64); if (!data_start) { abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } /* Allocate the data string because URI decoding will possibly modify * it. */ data = memacpy(data_start, uri->datalen - (data_start - uri->data)); if (!data) { abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } if (base64) { unsigned char *decoded = base64_encode(data); if (!decoded) { abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } mem_free_set(&data, decoded); } else { decode_uri(data); } { /* Use strlen() to get the correct decoded length */ int datalen = strlen((const char *)data); add_fragment(cached, conn->from, data, datalen); conn->from += datalen; } mem_free(data); abort_connection(conn, connection_state(S_OK)); }
unsigned char *get_keepalive_id(unsigned char *url) { unsigned char *h, *p, *k, *d; int hl, pl; if (parse_url(url, NULL, NULL, NULL, NULL, NULL, &h, &hl, &p, &pl, &d, NULL, NULL)) return NULL; if (!casecmp(url, cast_uchar "proxy://", 8) && !casecmp(d, cast_uchar "https://", 8)) { if (parse_url(d, NULL, NULL, NULL, NULL, NULL, &h, &hl, &p, &pl, NULL, NULL, NULL)) return NULL; } k = p ? p + pl : h + hl; if (!k) return stracpy(cast_uchar ""); return memacpy(url, k - url); }
static enum evhook_status script_hook_goto_url(va_list ap, void *data) { unsigned char **url = va_arg(ap, unsigned char **); struct session *ses = va_arg(ap, struct session *); int error; VALUE args[2]; VALUE result; if (*url == NULL) return EVENT_HOOK_STATUS_NEXT; args[0] = rb_str_new(*url, strlen((const char *)*url)); if (!ses || !have_location(ses)) { args[1] = Qnil; } else { args[1] = rb_str_new(struri(cur_loc(ses)->vs.uri), strlen((const char *)struri(cur_loc(ses)->vs.uri))); } result = erb_protected_method_call("goto_url_hook", 2, args, &error); if (error) { erb_report_error(ses, error); return EVENT_HOOK_STATUS_NEXT; } switch (rb_type(result)) { case T_STRING: { unsigned char *new_url; new_url = memacpy(RSTRING(result)->ptr, RSTRING(result)->len); if (new_url) { mem_free_set(url, new_url); } break; } case T_NIL: break; default: alert_ruby_error(ses, "goto_url_hook must return a string or nil"); } return EVENT_HOOK_STATUS_NEXT; }
static enum evhook_status script_hook_follow_url(va_list ap, void *data) { unsigned char **url = va_arg(ap, unsigned char **); struct session *ses = va_arg(ap, struct session *); int error; VALUE args[1]; VALUE result; evhook_use_params(url && ses); if (*url == NULL) return EVENT_HOOK_STATUS_NEXT; args[0] = rb_str_new(*url, strlen((const char *)*url)); result = erb_protected_method_call("follow_url_hook", 1, args, &error); if (error) { erb_report_error(ses, error); return EVENT_HOOK_STATUS_NEXT; } switch (rb_type(result)) { case T_STRING: { unsigned char *new_url; new_url = memacpy(RSTRING(result)->ptr, RSTRING(result)->len); if (new_url) { mem_free_set(url, new_url); } break; } case T_NIL: break; default: alert_ruby_error(ses, "follow_url_hook must return a string or nil"); } return EVENT_HOOK_STATUS_NEXT; }
/** Check if the URI is obfuscated (bug 382). The problem is said to occur when * a URI designed to pass access a specific location with a supplied username, * contains misleading chars prior to the @ symbol. * * An attacker can exploit this issue by supplying a malicious URI pointing to * a page designed to mimic that of a trusted site, and tricking a victim who * follows a link into believing they are actually at the trusted location. * * Only the user ID (and not also the password) is checked because only the * user ID is displayed in the status bar. */ static int check_malicious_uri(struct uri *uri) { unsigned char *user, *pos; int warn = 0; assert(uri->user && uri->userlen); user = pos = memacpy(uri->user, uri->userlen); if (!user) return 0; decode_uri_for_display(user); while (*pos) { int length, trailing_dots; for (length = 0; pos[length] != '\0'; length++) if (!(isalnum(pos[length]) || pos[length] == '.')) break; /* Wind back so that the TLD part is checked correctly. */ for (trailing_dots = 0; trailing_dots < length; trailing_dots++) if (!length || pos[length - trailing_dots - 1] != '.') break; /* Not perfect, but I am clueless as how to do better. Besides * I don't really think it is an issue for ELinks. --jonas */ if (end_with_known_tld(pos, length - trailing_dots) != -1) { warn = 1; break; } pos += length; while (*pos && (!isalnum(*pos) || *pos == '.')) pos++; } mem_free(user); return warn; }
static unsigned char * init_data_protocol_header(struct cache_entry *cached, unsigned char *type, int typelen) { unsigned char *head; assert(typelen); type = memacpy(type, typelen); if (!type) return NULL; /* Set fake content type */ head = straconcat((const unsigned char *)"\r\nContent-Type: ", type, "\r\n", (unsigned char *) NULL); mem_free(type); if (!head) return NULL; mem_free_set(&cached->head, head); return head; }
/* The Ruby function can return: * - "PROXY:PORT" to use the specified proxy * - "" to not use any proxy * - nil to use the default proxies */ static enum evhook_status script_hook_get_proxy(va_list ap, void *data) { unsigned char **new_proxy_url = va_arg(ap, unsigned char **); unsigned char *url = va_arg(ap, unsigned char *); int error; VALUE args[1]; VALUE result; if (!new_proxy_url || !url) return EVENT_HOOK_STATUS_NEXT; args[0] = rb_str_new(url, strlen((const char *)url)); result = erb_protected_method_call("proxy_hook", 1, args, &error); if (error) { erb_report_error(NULL, error); return EVENT_HOOK_STATUS_NEXT; } switch (rb_type(result)) { case T_STRING: { unsigned char *proxy; proxy = memacpy(RSTRING(result)->ptr, RSTRING(result)->len); if (proxy) { mem_free_set(new_proxy_url, proxy); } break; } case T_NIL: break; default: alert_ruby_error(NULL, "proxy_hook must return a string or nil"); } return EVENT_HOOK_STATUS_NEXT; }
unsigned char *parse_header_param(unsigned char *x, unsigned char *e) { unsigned char u; size_t le = strlen(e); int lp; unsigned char *y = x; a: if (!(y = strchr(y, ';'))) return NULL; while (*y && (*y == ';' || *y <= ' ')) y++; if (strlen(y) < le) return NULL; if (casecmp(y, e, le)) goto a; y += le; while (*y && (*y <= ' ' || *y == '=')) y++; u = ';'; if (*y == '\'' || *y == '"') u = *y++; lp = 0; while (y[lp] >= ' ' && y[lp] != u) { lp++; if (lp == MAXINT) overalloc(); } return memacpy(y, lp); }
/* Searches a word to find an email adress or an URI to add as a link. */ static inline struct link * check_link_word(struct document *document, unsigned char *uri, int length, int x, int y) { struct uri test; unsigned char *where = NULL; unsigned char *mailto = memchr(uri, '@', length); int keep = uri[length]; struct link *new_link; assert(document); if_assert_failed return NULL; uri[length] = 0; if (mailto && mailto > uri && mailto - uri < length - 1) { where = straconcat("mailto:", uri, (unsigned char *) NULL); } else if (parse_uri(&test, uri) == URI_ERRNO_OK && test.protocol != PROTOCOL_UNKNOWN && (test.datalen || test.hostlen)) { where = memacpy(uri, length); } uri[length] = keep; if (!where) return NULL; /* We need to reparse the URI and normalize it so that the protocol and * host part are converted to lowercase. */ normalize_uri(NULL, where); new_link = add_document_link(document, where, length, x, y); if (!new_link) mem_free(where); return new_link; }
/* sezere 1 cookie z retezce str, na zacatku nesmi byt zadne whitechars * na konci muze byt strednik nebo 0 * cookie musi byt ve tvaru nazev=hodnota, kolem rovnase nesmi byt zadne mezery * (respektive mezery se budou pocitat do nazvu a do hodnoty) */ int set_cookie(struct terminal *term, unsigned char *url, unsigned char *str) { int noval = 0; struct cookie *cookie; struct c_server *cs; unsigned char *p, *q, *s, *server, *date; d_opt = &dd_opt; int accept_cookies = dds.allow_cookies; if (accept_cookies == ACCEPT_NONE) { return 0; } for (p = str; *p != ';' && *p; p++) { /*if (WHITECHAR(*p)) return 0;*/ } for (q = str; *q != '='; q++) if (!*q || q >= p) { noval = 1; break; } if (str == q || q + 1 == p) return 0; cookie = mem_alloc(sizeof(struct cookie)); server = get_host_name(url); cookie->name = memacpy(str, q - str); cookie->value = !noval ? memacpy(q + 1, p - q - 1) : NULL; cookie->server = stracpy(server); date = parse_header_param(str, cast_uchar "expires", 0); if (date) { cookie->expires = parse_http_date(date); /* kdo tohle napsal a proc ?? */ /*if (! cookie->expires) cookie->expires++;*/ /* no harm and we can use zero then */ mem_free(date); } else cookie->expires = 0; if (!(cookie->path = parse_header_param(str, cast_uchar "path", 0))) { /*unsigned char *w;*/ cookie->path = stracpy(cast_uchar "/"); /* add_to_strn(&cookie->path, document); for (w = cookie->path; *w; w++) if (end_of_dir(cookie->path, *w)) { *w = 0; break; } for (w = cookie->path + strlen(cast_const_char cookie->path) - 1; w >= cookie->path; w--) if (*w == '/') { w[1] = 0; break; } */ } else { if (cookie->path[0] != '/') { add_to_strn(&cookie->path, cast_uchar "x"); memmove(cookie->path + 1, cookie->path, strlen(cast_const_char cookie->path) - 1); cookie->path[0] = '/'; } } if (!(cookie->domain = parse_header_param(str, cast_uchar "domain", 0))) cookie->domain = stracpy(server); if (cookie->domain[0] == '.') memmove(cookie->domain, cookie->domain + 1, strlen(cast_const_char cookie->domain)); if ((s = parse_header_param(str, cast_uchar "secure", 0))) { cookie->secure = 1; mem_free(s); } else cookie->secure = 0; if (check_domain_security(server, cookie->domain)) { mem_free(cookie->domain); cookie->domain = stracpy(server); } foreach (cs, c_servers) if (!strcasecmp(cast_const_char cs->server, cast_const_char server)) { if (cs->accpt) goto ok; else { free_cookie(cookie); mem_free(cookie); mem_free(server); return 0; } } if (accept_cookies != ACCEPT_ALL) { free_cookie(cookie); mem_free(cookie); mem_free(server); return 1; } ok: accept_cookie(cookie); mem_free(server); return 0; }
unsigned char *translate_url(unsigned char *url, unsigned char *cwd) { unsigned char *ch; unsigned char *nu, *da; unsigned char *prefix; int sl; while (*url == ' ') url++; if (*url && url[strlen(cast_const_char url) - 1] == ' ') { nu = stracpy(url); while (*nu && nu[strlen(cast_const_char nu) - 1] == ' ') nu[strlen(cast_const_char nu) - 1] = 0; ch = translate_url(nu, cwd); mem_free(nu); return ch; } if (!casecmp(cast_uchar "proxy://", url, 8)) return NULL; if (!parse_url(url, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &da, NULL, NULL)) { nu = stracpy(url); goto return_nu; } if (strchr(cast_const_char url, POST_CHAR)) return NULL; if (strstr(cast_const_char url, "://")) { nu = stracpy(url); extend_str(&nu, 1); ch = cast_uchar strrchr(cast_const_char nu, '#'); if (!ch || strchr(cast_const_char ch, '/')) ch = nu + strlen(cast_const_char nu); memmove(ch + 1, ch, strlen(cast_const_char ch) + 1); *ch = '/'; if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_nu; mem_free(nu); } prefix = cast_uchar "file://"; if (url[0] == '[' && strchr(cast_const_char url, ']')) { ch = url; goto http; } ch = url + strcspn(cast_const_char url, ".:/@"); sl = 0; #ifdef SPAD if (strchr(cast_const_char url, ':') && _is_local(cast_const_char url)) goto set_prefix; #endif if (*ch != ':' || *(url + strcspn(cast_const_char url, "/@")) == '@') { if (*url != '.' && *ch == '.') { unsigned char *e, *f, *g; int tl; for (e = ch + 1; *(f = e + strcspn(cast_const_char e, ".:/")) == '.'; e = f + 1) ; g = memacpy(e, f - e); tl = is_tld(g); mem_free(g); if (tl) http: prefix = cast_uchar "http://", sl = 1; } if (*ch == '@' || *ch == ':' || !cmpbeg(url, cast_uchar "ftp.")) prefix = cast_uchar "ftp://", sl = 1; goto set_prefix; set_prefix: nu = stracpy(prefix); add_to_strn(&nu, url); if (sl && !strchr(cast_const_char url, '/')) add_to_strn(&nu, cast_uchar "/"); if (parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { mem_free(nu); return NULL; } goto return_nu; } #ifdef DOS_FS if (ch == url + 1) goto set_prefix; #endif if (!(nu = memacpy(url, ch - url + 1))) return NULL; add_to_strn(&nu, cast_uchar "//"); add_to_strn(&nu, ch + 1); if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_nu; add_to_strn(&nu, cast_uchar "/"); if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_nu; mem_free(nu); return NULL; return_nu: insert_wd(&nu, cwd); extend_str(&nu, 1); translate_directories(nu); nu = translate_hashbang(nu); return nu; }
/* * U funkce join_urls musi byt prvni url absolutni (takove, co projde funkci * parse_url bez chyby --- pokud neni absolutni, tak to spatne na internal) a * druhe url je relativni cesta vuci nemu nebo taky absolutni url. Pokud je * druhe url absolutni, vrati se to; pokud je relativni, tak se spoji prvni a * druhe url. */ unsigned char *join_urls(unsigned char *base, unsigned char *rel) { unsigned char *p, *n, *pp, *ch; int l; int lo = !casecmp(base, cast_uchar "file://", 7); int data = !casecmp(base, cast_uchar "data:", 5); if (rel[0] == '#' || !rel[0]) { n = stracpy(base); for (p = n; *p && *p != POST_CHAR && *p != '#'; p++) ; *p = 0; add_to_strn(&n, rel); goto return_n; } if (rel[0] == '?' || rel[0] == '&') { unsigned char rj[3]; unsigned char *d = get_url_data(base); if (!d) goto bad_base; rj[0] = rel[0]; rj[1] = POST_CHAR; rj[2] = 0; d += strcspn(cast_const_char d, cast_const_char rj); n = memacpy(base, d - base); add_to_strn(&n, rel); goto return_n; } if (rel[0] == '/' && rel[1] == '/' && !data) { unsigned char *s; if (!(s = cast_uchar strstr(cast_const_char base, "//"))) { if (!(s = cast_uchar strchr(cast_const_char base, ':'))) { bad_base: internal("bad base url: %s", base); return NULL; } s++; } n = memacpy(base, s - base); add_to_strn(&n, rel); if (!parse_url(n, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_n; add_to_strn(&n, cast_uchar "/"); if (!parse_url(n, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_n; mem_free(n); } if (!casecmp(cast_uchar "proxy://", rel, 8)) goto prx; if (!parse_url(rel, &l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { n = stracpy(rel); goto return_n; } n = stracpy(rel); while (n[0] && n[strlen(cast_const_char n) - 1] <= ' ') n[strlen(cast_const_char n) - 1] = 0; extend_str(&n, 1); ch = cast_uchar strrchr(cast_const_char n, '#'); if (!ch || strchr(cast_const_char ch, '/')) ch = n + strlen(cast_const_char n); memmove(ch + 1, ch, strlen(cast_const_char ch) + 1); *ch = '/'; if (!parse_url(n, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_n; mem_free(n); prx: if (parse_url(base, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &p, NULL, NULL) || !p) { goto bad_base; } if (!dsep(*p)) p--; if (!data) { if (end_of_dir(base, rel[0])) for (; *p; p++) { if (end_of_dir(base, *p)) break; } else if (!dsep(rel[0])) for (pp = p; *pp; pp++) { if (end_of_dir(base, *pp)) break; if (dsep(*pp)) p = pp + 1; } } n = memacpy(base, p - base); add_to_strn(&n, rel); goto return_n; return_n: extend_str(&n, 1); translate_directories(n); return n; }
void ses_goto(struct session *ses, struct uri *uri, unsigned char *target_frame, struct location *target_location, enum cache_mode cache_mode, enum task_type task_type, int redir) { /* [gettext_accelerator_context(ses_goto)] */ struct task *task; int referrer_incomplete = 0; int malicious_uri = 0; int confirm_submit = uri->form && get_opt_bool("document.browse.forms" ".confirm_submit", ses); unsigned char *m1 = NULL, *message = NULL; struct memory_list *mlist = NULL; if (ses->doc_view && ses->doc_view->document && ses->doc_view->document->refresh) { kill_document_refresh(ses->doc_view->document->refresh); } assertm(!ses->loading_uri, "Buggy URI reference counting"); /* Reset the redirect counter if this is not a redirect. */ if (!redir) { ses->redirect_cnt = 0; } /* Figure out whether to confirm submit or not */ /* Only confirm submit if we are posting form data or a misleading URI * was detected. */ /* Note uri->post might be empty here but we are still supposely * posting form data so this should be more correct. */ if (uri->user && uri->userlen && get_opt_bool("document.browse.links.warn_malicious", ses) && check_malicious_uri(uri)) { malicious_uri = 1; confirm_submit = 1; } else if (uri->form) { /* First check if the referring URI was incomplete. It * indicates that the posted form data might be incomplete too. * See bug 460. */ if (ses->referrer) { struct cache_entry *cached; cached = find_in_cache(ses->referrer); referrer_incomplete = (cached && cached->incomplete); } if (referrer_incomplete) { confirm_submit = 1; } else if (get_validated_cache_entry(uri, cache_mode)) { confirm_submit = 0; } } if (!confirm_submit) { ses_load(ses, get_uri_reference(uri), target_frame, target_location, cache_mode, task_type); return; } task = mem_alloc(sizeof(*task)); if (!task) return; task->ses = ses; task->uri = get_uri_reference(uri); task->cache_mode = cache_mode; task->session_task.type = task_type; task->session_task.target.frame = null_or_stracpy(target_frame); task->session_task.target.location = target_location; if (malicious_uri) { unsigned char *host = memacpy(uri->host, uri->hostlen); unsigned char *user = memacpy(uri->user, uri->userlen); unsigned char *uristring = get_uri_string(uri, URI_PUBLIC); message = msg_text(ses->tab->term, N_("The URL you are about to follow might be maliciously " "crafted in order to confuse you. By following the URL " "you will be connecting to host \"%s\" as user \"%s\".\n\n" "Do you want to go to URL %s?"), host, user, uristring); mem_free_if(host); mem_free_if(user); mem_free_if(uristring); } else if (redir) { m1 = N_("Do you want to follow the redirect and post form data " "to URL %s?"); } else if (referrer_incomplete) { m1 = N_("The form data you are about to post might be incomplete.\n" "Do you want to post to URL %s?"); } else if (task_type == TASK_FORWARD) { m1 = N_("Do you want to post form data to URL %s?"); } else { m1 = N_("Do you want to repost form data to URL %s?"); } if (!message && m1) { unsigned char *uristring = get_uri_string(uri, URI_PUBLIC); message = msg_text(ses->tab->term, m1, uristring); mem_free_if(uristring); } add_to_ml(&mlist, task, (void *) NULL); if (task->session_task.target.frame) add_to_ml(&mlist, task->session_task.target.frame, (void *) NULL); msg_box(ses->tab->term, mlist, MSGBOX_FREE_TEXT, N_("Warning"), ALIGN_CENTER, message, task, 2, MSG_BOX_BUTTON(N_("~Yes"), post_yes, B_ENTER), MSG_BOX_BUTTON(N_("~No"), post_no, B_ESC)); }
static enum parse_error parse_set_common(struct option *opt_tree, struct conf_parsing_state *state, struct string *mirror, int is_system_conf, int want_domain) { const unsigned char *domain_orig = NULL; size_t domain_len = 0; unsigned char *domain_copy = NULL; const unsigned char *optname_orig; size_t optname_len; unsigned char *optname_copy; skip_white(&state->pos); if (!*state->pos.look) return show_parse_error(state, ERROR_PARSE); if (want_domain) { domain_orig = state->pos.look; while (isident(*state->pos.look) || *state->pos.look == '*' || *state->pos.look == '.' || *state->pos.look == '+') state->pos.look++; domain_len = state->pos.look - domain_orig; skip_white(&state->pos); } /* Option name */ optname_orig = state->pos.look; while (is_option_name_char(*state->pos.look) || *state->pos.look == '.') state->pos.look++; optname_len = state->pos.look - optname_orig; skip_white(&state->pos); /* Equal sign */ if (*state->pos.look != '=') return show_parse_error(state, ERROR_PARSE); state->pos.look++; /* '=' */ skip_white(&state->pos); if (!*state->pos.look) return show_parse_error(state, ERROR_VALUE); optname_copy = memacpy(optname_orig, optname_len); if (!optname_copy) return show_parse_error(state, ERROR_NOMEM); if (want_domain) { domain_copy = memacpy(domain_orig, domain_len); if (!domain_copy) { mem_free(optname_copy); return show_parse_error(state, ERROR_NOMEM); } } /* Option value */ { struct option *opt; unsigned char *val; const struct conf_parsing_pos pos_before_value = state->pos; if (want_domain && *domain_copy) { struct option *domain_tree; domain_tree = get_domain_tree(domain_copy); if (!domain_tree) { mem_free(domain_copy); mem_free(optname_copy); skip_option_value(&state->pos); return show_parse_error(state, ERROR_NOMEM); } if (mirror) { opt = get_opt_rec_real(domain_tree, optname_copy); } else { opt = get_opt_rec(opt_tree, optname_copy); if (opt) { opt = get_option_shadow(opt, opt_tree, domain_tree); if (!opt) { mem_free(domain_copy); mem_free(optname_copy); skip_option_value(&state->pos); return show_parse_error(state, ERROR_NOMEM); } } } } else { opt = mirror ? get_opt_rec_real(opt_tree, optname_copy) : get_opt_rec(opt_tree, optname_copy); } if (want_domain) mem_free(domain_copy); domain_copy = NULL; mem_free(optname_copy); optname_copy = NULL; if (!opt || (opt->flags & OPT_HIDDEN)) { show_parse_error(state, ERROR_OPTION); skip_option_value(&state->pos); return ERROR_OPTION; /* TODO: Distinguish between two scenarios: * - A newer version of ELinks has saved an * option that this version does not recognize. * The option must be preserved. (This works.) * - The user has added an option, saved * elinks.conf, restarted ELinks, deleted the * option, and is now saving elinks.conf again. * The option should be rewritten to "unset". * (This does not work yet.) * In both cases, ELinks has no struct option * for that name. Possible fixes: * - If the tree has OPT_AUTOCREATE, then * assume the user had created that option, * and rewrite it to "unset". Otherwise, * keep it. * - When the user deletes an option, just mark * it with OPT_DELETED, and keep it in memory * as long as OPT_TOUCHED is set. */ } if (!option_types[opt->type].read) { show_parse_error(state, ERROR_VALUE); skip_option_value(&state->pos); return ERROR_VALUE; } val = option_types[opt->type].read(opt, &state->pos.look, &state->pos.line); if (!val) { /* The reader function failed. Jump back to * the beginning of the value and skip it with * the generic code. For the error message, * use the line number at the beginning of the * value, because the ending position is not * interesting if there is an unclosed quote. */ state->pos = pos_before_value; show_parse_error(state, ERROR_VALUE); skip_option_value(&state->pos); return ERROR_VALUE; } if (!mirror) { /* loading a configuration file */ if (!option_types[opt->type].set || !option_types[opt->type].set(opt, val)) { mem_free(val); return show_parse_error(state, ERROR_VALUE); } } else if (is_system_conf) { /* scanning a file that will not be rewritten */ struct option *flagsite = indirect_option(opt); if (!(flagsite->flags & OPT_DELETED) && option_types[opt->type].equals && option_types[opt->type].equals(opt, val)) flagsite->flags &= ~OPT_MUST_SAVE; else flagsite->flags |= OPT_MUST_SAVE; } else { /* rewriting a configuration file */ struct option *flagsite = indirect_option(opt); if (flagsite->flags & OPT_DELETED) { /* Replace the "set" command with an * "unset" command. */ add_to_string(mirror, "unset "); add_bytes_to_string(mirror, optname_orig, optname_len); state->mirrored = state->pos.look; } else if (option_types[opt->type].write) { add_bytes_to_string(mirror, state->mirrored, pos_before_value.look - state->mirrored); option_types[opt->type].write(opt, mirror); state->mirrored = state->pos.look; } /* Remember that the option need not be * written to the end of the file. */ flagsite->flags &= ~OPT_MUST_SAVE; } mem_free(val); } return ERROR_NONE; }
unsigned char *get_protocol_name(unsigned char *url) { int l; if (parse_url(url, &l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) return NULL; return memacpy(url, l); }
unsigned char *translate_url(unsigned char *url, unsigned char *cwd) { unsigned char *ch; unsigned char *nu, *da; unsigned char *prefix; int sl; while (*url == ' ') url++; if (*url && url[strlen(cast_const_char url) - 1] == ' ') { nu = stracpy(url); while (*nu && nu[strlen(cast_const_char nu) - 1] == ' ') nu[strlen(cast_const_char nu) - 1] = 0; ch = translate_url(nu, cwd); mem_free(nu); return ch; } if (!casecmp(cast_uchar "proxy://", url, 8)) return NULL; if (!parse_url(url, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &da, NULL, NULL)) { nu = stracpy(url); goto return_nu; } if (strchr(cast_const_char url, POST_CHAR)) return NULL; if (strstr(cast_const_char url, "://")) { nu = stracpy(url); extend_str(&nu, 1); ch = cast_uchar strrchr(cast_const_char nu, '#'); if (!ch || strchr(cast_const_char ch, '/')) ch = nu + strlen(cast_const_char nu); memmove(ch + 1, ch, strlen(cast_const_char ch) + 1); *ch = '/'; if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_nu; mem_free(nu); } prefix = cast_uchar "file://"; if (url[0] == '[' && strchr(cast_const_char url, ']')) { ch = url; goto http; } ch = url + strcspn(cast_const_char url, ".:/@"); sl = 0; #ifdef SPAD if (strchr(cast_const_char url, ':') && _is_local(cast_const_char url)) goto set_prefix; #endif if (*ch != ':' || *(url + strcspn(cast_const_char url, "/@")) == '@') { if (*url != '.' && *ch == '.') { unsigned char *f, *e; int i; for (e = ch + 1; *(f = e + strcspn(cast_const_char e, ".:/")) == '.'; e = f + 1) ; for (i = 0; i < f - e; i++) if (e[i] < '0' || e[i] > '9') goto noip; goto http; noip: if (f - e == 2 && casecmp(e, cast_uchar "gz", 2)) { http: prefix = cast_uchar "http://", sl = 1; } else { char *tld[] = { "com", "edu", "net", "org", "gov", "mil", "int", "arpa", "aero", "biz", "coop", "info", "museum", "name", "pro", "cat", "jobs", "mobi", "travel", "tel", "onion", "exit", NULL }; for (i = 0; tld[i]; i++) if ((size_t)(f - e) == strlen(cast_const_char tld[i]) && !casecmp(cast_uchar tld[i], e, f - e)) goto http; } } if (*ch == '@' || *ch == ':' || !cmpbeg(url, cast_uchar "ftp.")) prefix = cast_uchar "ftp://", sl = 1; goto set_prefix; set_prefix: nu = stracpy(prefix); add_to_strn(&nu, url); if (sl && !strchr(cast_const_char url, '/')) add_to_strn(&nu, cast_uchar "/"); if (parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { mem_free(nu); return NULL; } goto return_nu; } #ifdef DOS_FS if (ch == url + 1) goto set_prefix; #endif if (!(nu = memacpy(url, ch - url + 1))) return NULL; add_to_strn(&nu, cast_uchar "//"); add_to_strn(&nu, ch + 1); if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_nu; add_to_strn(&nu, cast_uchar "/"); if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) goto return_nu; mem_free(nu); return NULL; return_nu: insert_wd(&nu, cwd); extend_str(&nu, 1); translate_directories(nu); nu = translate_hashbang(nu); return nu; }
static void smb_got_header(struct socket *socket, struct read_buffer *rb) { struct connection *conn = socket->conn; struct read_buffer *buf; int error = 0; conn->cached = get_cache_entry(conn->uri); if (!conn->cached) { /* Even though these are pipes rather than real * sockets, call close_socket instead of close, to * ensure that abort_connection won't try to close the * file descriptors again. (Could we skip the calls * and assume abort_connection will do them?) */ close_socket(socket); close_socket(conn->data_socket); abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } socket->state = SOCKET_END_ONCLOSE; if (rb->length > 0) { unsigned char *ctype = memacpy(rb->data, rb->length); if (ctype && *ctype) { if (!strcmp(ctype, "text/x-error")) { error = 1; mem_free(ctype); } else { if (ctype[0] >= '0' && ctype[0] <= '9') { #ifdef HAVE_ATOLL conn->est_length = (off_t)atoll(ctype); #else conn->est_length = (off_t)atol(ctype); #endif mem_free(ctype); /* avoid error */ if (!conn->est_length) { abort_connection(conn, connection_state(S_OK)); return; } } else mem_free_set(&conn->cached->content_type, ctype); } } else { mem_free_if(ctype); } } buf = alloc_read_buffer(conn->data_socket); if (!buf) { close_socket(socket); close_socket(conn->data_socket); abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } if (error) { mem_free_set(&conn->cached->content_type, stracpy("text/html")); read_from_socket(conn->data_socket, buf, connection_state(S_CONN), smb_got_error); } else { read_from_socket(conn->data_socket, buf, connection_state(S_CONN), smb_got_data); } }
static enum parse_error parse_unset(struct option *opt_tree, struct conf_parsing_state *state, struct string *mirror, int is_system_conf) { const unsigned char *optname_orig; size_t optname_len; unsigned char *optname_copy; skip_white(&state->pos); if (!*state->pos.look) return show_parse_error(state, ERROR_PARSE); /* Option name */ optname_orig = state->pos.look; while (is_option_name_char(*state->pos.look) || *state->pos.look == '.') state->pos.look++; optname_len = state->pos.look - optname_orig; optname_copy = memacpy(optname_orig, optname_len); if (!optname_copy) return show_parse_error(state, ERROR_NOMEM); { struct option *opt; opt = get_opt_rec_real(opt_tree, optname_copy); mem_free(optname_copy); optname_copy = NULL; if (!opt || (opt->flags & OPT_HIDDEN)) { /* The user wanted to delete the option, and * it has already been deleted; this is not an * error. This might happen if a version of * ELinks has a built-in URL rewriting rule, * the user disables it, and a later version * no longer has it. */ return ERROR_NONE; } if (!mirror) { /* loading a configuration file */ if (opt->flags & OPT_ALLOC) delete_option(opt); else mark_option_as_deleted(opt); } else if (is_system_conf) { /* scanning a file that will not be rewritten */ struct option *flagsite = indirect_option(opt); if (flagsite->flags & OPT_DELETED) flagsite->flags &= ~OPT_MUST_SAVE; else flagsite->flags |= OPT_MUST_SAVE; } else { /* rewriting a configuration file */ struct option *flagsite = indirect_option(opt); if (flagsite->flags & OPT_DELETED) { /* The "unset" command is already in the file, * and unlike with "set", there is no value * to be updated. */ } else if (option_types[opt->type].write) { /* Replace the "unset" command with a * "set" command. */ add_to_string(mirror, "set "); add_bytes_to_string(mirror, optname_orig, optname_len); add_to_string(mirror, " = "); option_types[opt->type].write(opt, mirror); state->mirrored = state->pos.look; } /* Remember that the option need not be * written to the end of the file. */ flagsite->flags &= ~OPT_MUST_SAVE; } } return ERROR_NONE; }
int html_parse_meta_refresh(const unsigned char *content, unsigned long *delay_out, unsigned char **url_out) { const unsigned char *scan = content; char *delay_end; int saw_delay = 0; const unsigned char *url_begin; const unsigned char *url_end; *url_out = NULL; *delay_out = 0; while (LWS(*scan)) ++scan; /* TODO: Do we need to switch to the "C" locale and back? */ *delay_out = strtoul(scan, &delay_end, 10); saw_delay = (scan != (const unsigned char *) delay_end); scan = (const unsigned char *) delay_end; if (saw_delay) { /* Omit any fractional part. */ if (*scan == '.') { ++scan; while (!(*scan == '\0' || LWS(*scan) || *scan == ';' || *scan == ',')) ++scan; } if (!(*scan == '\0' || LWS(*scan) || *scan == ';' || *scan == ',')) { /* The delay is followed by garbage. Give up. */ return -1; } /* Between the delay and the URL, there must be at * least one LWS, semicolon, or comma; optionally with * more LWS around it. */ while (LWS(*scan)) ++scan; if (*scan == ';' || *scan == ',') ++scan; } else { /* The delay was not specified. The delimiter must be * a semicolon or a comma, optionally with LWS. LWS * alone does not suffice. */ while (*scan != '\0' && *scan != ';' && *scan != ',') ++scan; if (*scan == ';' || *scan == ',') ++scan; } while (LWS(*scan)) ++scan; /* Presume the URL begins here... */ url_begin = scan; /* ..unless there is "URL=" with at least one equals sign, * and optional spaces. */ if ((scan[0] == 'U' || scan[0] == 'u') && (scan[1] == 'R' || scan[1] == 'r') && (scan[2] == 'L' || scan[2] == 'l')) { scan += 3; while (LWS(*scan)) ++scan; if (*scan == '=') { ++scan; while (LWS(*scan)) ++scan; url_begin = scan; } } if (*url_begin == '"' || *url_begin == '\'') { unsigned char quote = *url_begin++; url_end = strchr(url_begin, quote); if (url_end == NULL) url_end = strchr(url_begin, '\0'); } else { url_end = strchr(url_begin, '\0'); } /* In any case, trim all spaces from the end of the URL. */ while (url_begin < url_end && LWS(url_end[-1])) --url_end; if (url_begin != url_end) { *url_out = memacpy(url_begin, url_end - url_begin); if (!*url_out) return -1; } else if (!saw_delay) { /* There is no delay and no URL. */ return -1; } return 0; }