예제 #1
0
unsigned char *translate_hashbang(unsigned char *up)
{
	unsigned char *u, *p, *dp, *data, *post_seq;
	int q;
	unsigned char *r;
	int rl;
	if (!strstr(cast_const_char up, "#!") && !strstr(cast_const_char up, "#%21")) return up;
	u = stracpy(up);
	p = extract_position(u);
	if (!p) {
		free_u_ret_up:
		mem_free(u);
		return up;
	}
	if (p[0] == '!') dp = p + 1;
	else if (!casecmp(p, cast_uchar "%21", 3)) dp = p + 3;
	else {
		mem_free(p);
		goto free_u_ret_up;
	}
	if (!(post_seq = cast_uchar strchr(cast_const_char u, POST_CHAR))) post_seq = cast_uchar strchr(cast_const_char u, 0);
	data = get_url_data(u);
	if (!data) data = u;
	r = init_str();
	rl = 0;
	add_bytes_to_str(&r, &rl, u, post_seq - u);
	q = (int)strlen(cast_const_char data);
	if (q && (data[q - 1] == '&' || data[q - 1] == '?'))
		;
	else if (strchr(cast_const_char data, '?')) add_chr_to_str(&r, &rl, '&');
	else add_chr_to_str(&r, &rl, '?');
	add_to_str(&r, &rl, cast_uchar "_escaped_fragment_=");
	for (; *dp; dp++) {
		unsigned char c = *dp;
		if (c <= 0x20 || c == 0x23 || c == 0x25 || c == 0x26 || c == 0x2b || c >= 0x7f) {
			unsigned char h[4];
			sprintf(cast_char h, "%%%02X", c);
			add_to_str(&r, &rl, h);
		} else {
			add_chr_to_str(&r, &rl, c);
		}
	}
	add_to_str(&r, &rl, post_seq);
	mem_free(u);
	mem_free(p);
	mem_free(up);
	return r;
}
예제 #2
0
void ftp_send_retr_req(struct connection *c, int state)
{
	struct ftp_connection_info *fi;
	unsigned char *login;
	int logl = 0;
	set_timeout(c);
	login = init_str();
	if (!c->info && !(fi = add_file_cmd_to_str(c))) {
		mem_free(login);
		return;
	} else fi = c->info;
	if (ftp_options.fast_ftp) a:add_to_str(&login, &logl, fi->cmdbuf);
	else {
		unsigned char *nl = strchr(fi->cmdbuf, '\n');
		if (!nl) goto a;
		nl++;
		add_bytes_to_str(&login, &logl, fi->cmdbuf, nl - fi->cmdbuf);
		memmove(fi->cmdbuf, nl, strlen(nl) + 1);
	}
	write_to_socket(c, c->sock1, login, strlen(login), ftp_retr_1);
	mem_free(login);
	setcstate(c, state);
}
예제 #3
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);
}
예제 #4
0
static struct ftp_connection_info *add_file_cmd_to_str(struct connection *c)
{
    unsigned char *d = get_url_data(c->url);
    unsigned char *de;
    int del;
    unsigned char port_string[50];
    struct ftp_connection_info *inf, *inf2;
    unsigned char *s;
    int l;
    if (!d) {
        internal("get_url_data failed");
        setcstate(c, S_INTERNAL);
        abort_connection(c);
        return NULL;
    }

    de = init_str(), del = 0;
    add_conv_str(&de, &del, d, strlen(cast_const_char d), -2);
    d = de;
    inf = mem_alloc(sizeof(struct ftp_connection_info));
    memset(inf, 0, sizeof(struct ftp_connection_info));
    l = 0;
    s = init_str();
    inf->pasv = ftp_options.passive_ftp;
#ifdef LINKS_2
    if (*c->socks_proxy) inf->pasv = 1;
    if (ftp_options.eprt_epsv || is_ipv6(c->sock1)) inf->eprt_epsv = 1;
#endif
    c->info = inf;

    if (!inf->pasv) {
        int ps;
#ifdef SUPPORT_IPV6
        if (is_ipv6(c->sock1)) {
            ps = get_pasv_socket_ipv6(c, c->sock1, &c->sock2, port_string);
            if (ps) {
                mem_free(d);
                mem_free(s);
                return NULL;
            }
        } else
#endif
        {
            unsigned char pc[6];
            ps = get_pasv_socket(c, c->sock1, &c->sock2, pc);
            if (ps) {
                mem_free(d);
                mem_free(s);
                return NULL;
            }
            if (inf->eprt_epsv)
                sprintf(cast_char port_string, "|1|%d.%d.%d.%d|%d|", pc[0], pc[1], pc[2], pc[3], (pc[4] << 8) | pc[5]);
            else
                sprintf(cast_char port_string, "%d,%d,%d,%d,%d,%d", pc[0], pc[1], pc[2], pc[3], pc[4], pc[5]);
        }
        if (strlen(cast_const_char port_string) >= sizeof(port_string))
            internal("buffer overflow in get_pasv_socket_ipv6: %d > %d", (int)strlen(cast_const_char port_string), (int)sizeof(port_string));
    }
#ifdef HAVE_IPTOS
    if (ftp_options.set_tos) {
        int rx;
        int on = IPTOS_THROUGHPUT;
        EINTRLOOP(rx, setsockopt(c->sock2, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)));
    }
#endif
    if (!(de = cast_uchar strchr(cast_const_char d, POST_CHAR))) de = d + strlen(cast_const_char d);
    if (d == de || de[-1] == '/') {
        inf->dir = 1;
        inf->pending_commands = 4;
        add_to_str(&s, &l, cast_uchar "TYPE A\r\n");
        add_port_pasv(&s, &l, inf, port_string);
        add_to_str(&s, &l, cast_uchar "CWD /");
        add_bytes_to_str(&s, &l, d, de - d);
        add_to_str(&s, &l, cast_uchar "\r\nLIST\r\n");
        c->from = 0;
    } else {
        inf->dir = 0;
        inf->pending_commands = 3;
        add_to_str(&s, &l, cast_uchar "TYPE I\r\n");
        add_port_pasv(&s, &l, inf, port_string);
        if (c->from && c->no_cache < NC_IF_MOD) {
            add_to_str(&s, &l, cast_uchar "REST ");
            add_num_to_str(&s, &l, c->from);
            add_to_str(&s, &l, cast_uchar "\r\n");
            inf->rest_sent = 1;
            inf->pending_commands++;
        } else c->from = 0;
        add_to_str(&s, &l, cast_uchar "RETR /");
        add_bytes_to_str(&s, &l, d, de - d);
        add_to_str(&s, &l, cast_uchar "\r\n");
    }
    inf->opc = inf->pending_commands;
    if ((unsigned)l > MAXINT - sizeof(struct ftp_connection_info) - 1) overalloc();
    inf2 = mem_realloc(inf, sizeof(struct ftp_connection_info) + l + 1);
    strcpy(cast_char (inf = inf2)->cmdbuf, cast_const_char s);
    mem_free(s);
    c->info = inf;
    mem_free(d);
    return inf;
}
예제 #5
0
struct ftp_connection_info *add_file_cmd_to_str(struct connection *c)
{
	unsigned char *d = get_url_data(c->url);
	unsigned char *de;
	int del;
	unsigned char pc[6];
	int ps;
	struct ftp_connection_info *inf, *inf2;
	unsigned char *s;
	int l;
	if (!d) {
		internal("get_url_data failed");
		setcstate(c, S_INTERNAL);
		abort_connection(c);
		return NULL;
	}
	de = init_str(), del = 0;
	add_conv_str(&de, &del, d, strlen(d), -2);
	d = de;
	inf = mem_alloc(sizeof(struct ftp_connection_info));
	memset(inf, 0, sizeof(struct ftp_connection_info));
	l = 0;
	s = init_str();
	inf->pasv = ftp_options.passive_ftp;
	if (*c->socks_proxy) inf->pasv = 1;
	c->info = inf;
	if (!inf->pasv) if ((ps = get_pasv_socket(c, c->sock1, &c->sock2, pc))) {
		mem_free(d);
		return NULL;
	}
#ifdef HAVE_IPTOS
	if (ftp_options.set_tos) {
		int on = IPTOS_THROUGHPUT;
		setsockopt(c->sock2, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int));
	}
#endif
	if (!(de = strchr(d, POST_CHAR))) de = d + strlen(d);
	if (d == de || de[-1] == '/') {
		inf->dir = 1;
		inf->pending_commands = 4;
		add_to_str(&s, &l, "TYPE A\r\n");
		if (!inf->pasv) {
			add_to_str(&s, &l, "PORT ");
			add_num_to_str(&s, &l, pc[0]);
			add_chr_to_str(&s, &l, ',');
			add_num_to_str(&s, &l, pc[1]);
			add_chr_to_str(&s, &l, ',');
			add_num_to_str(&s, &l, pc[2]);
			add_chr_to_str(&s, &l, ',');
			add_num_to_str(&s, &l, pc[3]);
			add_chr_to_str(&s, &l, ',');
			add_num_to_str(&s, &l, pc[4]);
			add_chr_to_str(&s, &l, ',');
			add_num_to_str(&s, &l, pc[5]);
			add_to_str(&s, &l, "\r\n");
		} else {
			add_to_str(&s, &l, "PASV\r\n");
		}
		add_to_str(&s, &l, "CWD /");
		add_bytes_to_str(&s, &l, d, de - d);
		add_to_str(&s, &l, "\r\nLIST\r\n");
		c->from = 0;
	} else {
		inf->dir = 0;
		inf->pending_commands = 3;
		add_to_str(&s, &l, "TYPE I\r\n");
		if (!inf->pasv) {
			add_to_str(&s, &l, "PORT ");
			add_num_to_str(&s, &l, pc[0]);
			add_chr_to_str(&s, &l, ',');
			add_num_to_str(&s, &l, pc[1]);
			add_chr_to_str(&s, &l, ',');
			add_num_to_str(&s, &l, pc[2]);
			add_chr_to_str(&s, &l, ',');
			add_num_to_str(&s, &l, pc[3]);
			add_chr_to_str(&s, &l, ',');
			add_num_to_str(&s, &l, pc[4]);
			add_chr_to_str(&s, &l, ',');
			add_num_to_str(&s, &l, pc[5]);
			add_to_str(&s, &l, "\r\n");
		} else {
			add_to_str(&s, &l, "PASV\r\n");
		}
		if (c->from && c->no_cache < NC_IF_MOD) {
			add_to_str(&s, &l, "REST ");
			add_num_to_str(&s, &l, c->from);
			add_to_str(&s, &l, "\r\n");
			inf->rest_sent = 1;
			inf->pending_commands++;
		} else c->from = 0;
		add_to_str(&s, &l, "RETR /");
		add_bytes_to_str(&s, &l, d, de - d);
		add_to_str(&s, &l, "\r\n");
	}
	inf->opc = inf->pending_commands;
	if ((unsigned)l > MAXINT - sizeof(struct ftp_connection_info) - 1) overalloc();
	inf2 = mem_realloc(inf, sizeof(struct ftp_connection_info) + l + 1);
	strcpy((inf = inf2)->cmdbuf, s);
	mem_free(s);
	c->info = inf;
	mem_free(d);
	return inf;
}