Esempio n. 1
0
void
make_connection(struct socket *socket, struct uri *uri,
		socket_connect_T connect_done, int no_cache)
{
	unsigned char *host = get_uri_string(uri, URI_DNS_HOST);
	struct connect_info *connect_info;
	enum dns_result result;
	enum blacklist_flags verify;

	socket->ops->set_timeout(socket, connection_state(0));

	if (!host) {
		socket->ops->retry(socket, connection_state(S_OUT_OF_MEM));
		return;
	}

	connect_info = init_connection_info(uri, socket, connect_done);
	if (!connect_info) {
		mem_free(host);
		socket->ops->retry(socket, connection_state(S_OUT_OF_MEM));
		return;
	}

	socket->connect_info = connect_info;
	/* XXX: Keep here and not in init_connection_info() to make
	 * complete_connect_socket() work from the HTTP implementation. */
	socket->need_ssl = get_protocol_need_ssl(uri->protocol);
	if (!socket->set_no_tls) {
		enum blacklist_flags flags = get_blacklist_flags(uri);
		socket->no_tls = ((flags & SERVER_BLACKLIST_NO_TLS) != 0);
		socket->set_no_tls = 1;
	}

	verify = get_blacklist_flags(uri);
	socket->verify = ((verify & SERVER_BLACKLIST_NO_CERT_VERIFY) == 0);

	debug_transfer_log("\nCONNECTION: ", -1);
	debug_transfer_log(host, -1);
	debug_transfer_log("\n", -1);

	result = find_host(host, &connect_info->dnsquery, (dns_callback_T) dns_found,
			   socket, no_cache);

	mem_free(host);

	if (result == DNS_ASYNC)
		socket->ops->set_state(socket, connection_state(S_DNS));
}
Esempio n. 2
0
void http_send_header(struct connection *c)
{
    static unsigned char *accept_charset = NULL;
    struct http_connection_info *info;
    int http10 = http_bugs.http10;
    struct cache_entry *e = NULL;
    unsigned char *hdr;
    unsigned char *h, *u;
    int l = 0;
    int la;
    unsigned char *post;
    unsigned char *host;

    find_in_cache(c->url, &c->cache);

    host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url);
    set_timeout(c);
    info = mem_calloc(sizeof(struct http_connection_info));
    c->info = info;
    if ((h = get_host_name(host))) {
        info->bl_flags = get_blacklist_flags(h);
        mem_free(h);
    }
    if (info->bl_flags & BL_HTTP10) http10 = 1;
    info->http10 = http10;
    post = strchr(host, POST_CHAR);
    if (post) post++;
    hdr = init_str();
    if (!post) add_to_str(&hdr, &l, "GET ");
    else {
        add_to_str(&hdr, &l, "POST ");
        c->unrestartable = 2;
    }
    if (upcase(c->url[0]) != 'P') add_to_str(&hdr, &l, "/");
    if (!(u = get_url_data(c->url))) {
        mem_free(hdr);
        setcstate(c, S_BAD_URL);
        http_end_request(c, 0);
        return;
    }
    if (post && post < u) {
        mem_free(hdr);
        setcstate(c, S_BAD_URL);
        http_end_request(c, 0);
        return;
    }
    add_url_to_str(&hdr, &l, u);
    if (!http10) add_to_str(&hdr, &l, " HTTP/1.1\r\n");
    else add_to_str(&hdr, &l, " HTTP/1.0\r\n");
    if ((h = get_host_name(host))) {
        add_to_str(&hdr, &l, "Host: ");
        add_to_str(&hdr, &l, h);
        mem_free(h);
        if ((h = get_port_str(host))) {
            add_to_str(&hdr, &l, ":");
            add_to_str(&hdr, &l, h);
            mem_free(h);
        }
        add_to_str(&hdr, &l, "\r\n");
    }
    add_to_str(&hdr, &l, "User-Agent: ");
    if (!(*http_bugs.fake_useragent)) {
        add_to_str(&hdr, &l, "Links (" VERSION_STRING "; ");
        add_to_str(&hdr, &l, system_name);
        if (!F && !list_empty(terminals)) {
            struct terminal *t = terminals.prev;
            if (!t->spec->braille) {
                add_to_str(&hdr, &l, "; ");
                add_num_to_str(&hdr, &l, t->x);
                add_to_str(&hdr, &l, "x");
                add_num_to_str(&hdr, &l, t->y);
            } else {
                add_to_str(&hdr, &l, "; braille");
            }
        }
#ifdef G
        if (F && drv) {
            add_to_str(&hdr, &l, "; ");
            add_to_str(&hdr, &l, drv->name);
        }
#endif
        add_to_str(&hdr, &l, ")\r\n");
    }
    else {
        add_to_str(&hdr, &l, http_bugs.fake_useragent);
        add_to_str(&hdr, &l, "\r\n");
    }
    switch (http_bugs.referer)
    {
    case REFERER_FAKE:
        add_to_str(&hdr, &l, "Referer: ");
        add_to_str(&hdr, &l, http_bugs.fake_referer);
        add_to_str(&hdr, &l, "\r\n");
        break;

    case REFERER_SAME_URL:
        add_to_str(&hdr, &l, "Referer: ");
        add_url_to_str(&hdr, &l, host);
        add_to_str(&hdr, &l, "\r\n");
        break;

    case REFERER_REAL_SAME_SERVER:
    {
        unsigned char *h, *j;
        int brk = 1;
        if ((h = get_host_name(host))) {
            if ((j = get_host_name(c->prev_url))) {
                if (!strcasecmp(h, j)) brk = 0;
                mem_free(j);
            }
            mem_free(h);
        }
        if (brk) break;
        /* fall through */
    }
    case REFERER_REAL:
    {
        unsigned char *ref;
        unsigned char *user, *ins;
        int ulen;
        if (!(c->prev_url)) break;   /* no referrer */

        ref = stracpy(c->prev_url);
        if (!parse_url(ref, NULL, &user, &ulen, NULL, NULL, &ins, NULL, NULL, NULL, NULL, NULL, NULL) && ulen && ins) {
            memmove(user, ins, strlen(ins) + 1);
        }
        add_to_str(&hdr, &l, "Referer: ");
        add_url_to_str(&hdr, &l, ref);
        add_to_str(&hdr, &l, "\r\n");
        mem_free(ref);
    }
    break;
    }

    add_to_str(&hdr, &l, "Accept: */*\r\n");
#if defined(HAVE_ZLIB) || defined(HAVE_BZIP2)
    if (!http_bugs.no_compression && !(info->bl_flags & BL_NO_COMPRESSION)) {
        int q = strlen(c->url);
        if (q >= 2 && !strcasecmp(c->url + q - 2, ".Z")) goto skip_compress;
        if (q >= 3 && !strcasecmp(c->url + q - 3, ".gz")) goto skip_compress;
        if (q >= 4 && !strcasecmp(c->url + q - 4, ".bz2")) goto skip_compress;
        add_to_str(&hdr, &l, "Accept-Encoding: ");
#if defined(HAVE_ZLIB)
        add_to_str(&hdr, &l, "gzip, deflate, ");
#endif
#if defined(HAVE_BZIP2)
        add_to_str(&hdr, &l, "bzip2, ");
#endif
        hdr[l-2] = '\r';
        hdr[l-1] = '\n';
skip_compress:
        ;
    }
#endif
    if (!(accept_charset)) {
        int i;
        unsigned char *cs, *ac;
        int aclen = 0;
        ac = init_str();
        for (i = 0; (cs = get_cp_mime_name(i)); i++) {
            if (aclen) add_to_str(&ac, &aclen, ", ");
            else add_to_str(&ac, &aclen, "Accept-Charset: ");
            add_to_str(&ac, &aclen, cs);
        }
        if (aclen) add_to_str(&ac, &aclen, "\r\n");
        if ((accept_charset = malloc(strlen(ac) + 1))) strcpy(accept_charset, ac);
        else accept_charset = "";
        mem_free(ac);
    }
    if (!(info->bl_flags & BL_NO_CHARSET) && !http_bugs.no_accept_charset) add_to_str(&hdr, &l, accept_charset);
    if (!(info->bl_flags & BL_NO_ACCEPT_LANGUAGE)) {
        add_to_str(&hdr, &l, "Accept-Language: ");
        la = l;
        add_to_str(&hdr, &l, _(TEXT(T__ACCEPT_LANGUAGE), NULL));
        add_to_str(&hdr, &l, ", ");
        if (!strstr(hdr + la, "en,") && !strstr(hdr + la, "en;")) add_to_str(&hdr, &l, "en;q=0.2, ");
        add_to_str(&hdr, &l, "*;q=0.1\r\n");
    }
    if (!http10) {
        if (upcase(c->url[0]) != 'P') add_to_str(&hdr, &l, "Connection: ");
        else add_to_str(&hdr, &l, "Proxy-Connection: ");
        if (!post || !http_bugs.bug_post_no_keepalive) add_to_str(&hdr, &l, "Keep-Alive\r\n");
        else add_to_str(&hdr, &l, "close\r\n");
    }
    if ((e = c->cache)) {
        int code, vers;
        if (get_http_code(e->head, &code, &vers) || code >= 400) goto skip_ifmod_and_range;
        if (!e->incomplete && e->head && c->no_cache <= NC_IF_MOD) {
            unsigned char *m;
            if (e->last_modified) m = stracpy(e->last_modified);
            else if ((m = parse_http_header(e->head, "Date", NULL))) ;
            else if ((m = parse_http_header(e->head, "Expires", NULL))) ;
            else goto skip_ifmod;
            add_to_str(&hdr, &l, "If-Modified-Since: ");
            add_to_str(&hdr, &l, m);
            add_to_str(&hdr, &l, "\r\n");
            mem_free(m);
        }
skip_ifmod:
        ;
    }
    if (c->from && (c->est_length == -1 || c->from < c->est_length) && c->no_cache < NC_IF_MOD && !(info->bl_flags & BL_NO_RANGE)) {
        /* If the cached entity is compressed and we turned off compression,
           request the whole file */
        if ((info->bl_flags & BL_NO_COMPRESSION || http_bugs.no_compression) && e) {
            unsigned char *d;
            if ((d = parse_http_header(e->head, "Transfer-Encoding", NULL))) {
                mem_free(d);
                goto skip_range;
            }
        }
        add_to_str(&hdr, &l, "Range: bytes=");
        add_num_to_str(&hdr, &l, c->from);
        add_to_str(&hdr, &l, "-\r\n");
skip_range:
        ;
    }
skip_ifmod_and_range:
    if (c->no_cache >= NC_PR_NO_CACHE) add_to_str(&hdr, &l, "Pragma: no-cache\r\nCache-Control: no-cache\r\n");
    if ((h = get_auth_string(c->url))) {
        add_to_str(&hdr, &l, h);
        mem_free(h);
    }
    if (post) {
        unsigned char *pd = strchr(post, '\n');
        if (pd) {
            add_to_str(&hdr, &l, "Content-Type: ");
            add_bytes_to_str(&hdr, &l, post, pd - post);
            add_to_str(&hdr, &l, "\r\n");
            post = pd + 1;
        }
        add_to_str(&hdr, &l, "Content-Length: ");
        add_num_to_str(&hdr, &l, strlen(post) / 2);
        add_to_str(&hdr, &l, "\r\n");
    }
    send_cookies(&hdr, &l, host);
    add_to_str(&hdr, &l, "\r\n");
    if (post) {
        while (post[0] && post[1]) {
            int h1, h2;
            h1 = post[0] <= '9' ? (unsigned)post[0] - '0' : post[0] >= 'A' ? upcase(post[0]) - 'A' + 10 : 0;
            if (h1 < 0 || h1 >= 16) h1 = 0;
            h2 = post[1] <= '9' ? (unsigned)post[1] - '0' : post[1] >= 'A' ? upcase(post[1]) - 'A' + 10 : 0;
            if (h2 < 0 || h2 >= 16) h2 = 0;
            add_chr_to_str(&hdr, &l, h1 * 16 + h2);
            post += 2;
        }
    }
    write_to_socket(c, c->sock1, hdr, l, http_get_header);
    mem_free(hdr);
    setcstate(c, S_SENT);
}