コード例 #1
0
ファイル: url.c プロジェクト: OS2World/APP-INTERNET-Links
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;
}
コード例 #2
0
ファイル: url.c プロジェクト: engine12/links
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;
}
コード例 #3
0
ファイル: url.c プロジェクト: OS2World/APP-INTERNET-Links
/*
 * 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;
}
コード例 #4
0
void http_got_header(struct connection *c, struct read_buffer *rb)
{
    int cf;
    int state = c->state != S_PROC ? S_GETH : S_PROC;
    unsigned char *head;
    unsigned char *cookie, *ch;
    int a, h, version;
    unsigned char *d;
    struct cache_entry *e;
    struct http_connection_info *info;
    unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url);
    set_timeout(c);
    info = c->info;
    if (rb->close == 2) {
        unsigned char *h;
        if (!c->tries && (h = get_host_name(host))) {
            if (info->bl_flags & BL_NO_CHARSET) {
                del_blacklist_entry(h, BL_NO_CHARSET);
            } else {
                add_blacklist_entry(h, BL_NO_CHARSET);
                c->tries = -1;
            }
            mem_free(h);
        }
        setcstate(c, S_CANT_READ);
        retry_connection(c);
        return;
    }
    rb->close = 0;
again:
    if ((a = get_header(rb)) == -1) {
        setcstate(c, S_HTTP_ERROR);
        abort_connection(c);
        return;
    }
    if (!a) {
        read_from_socket(c, c->sock1, rb, http_got_header);
        setcstate(c, state);
        return;
    }
    if (a != -2) {
        head = mem_alloc(a + 1);
        memcpy(head, rb->data, a);
        head[a] = 0;
        kill_buffer_data(rb, a);
    } else {
        head = stracpy("HTTP/0.9 200 OK\r\nContent-Type: text/html\r\n\r\n");
    }
    if (get_http_code(head, &h, &version) || h == 101) {
        mem_free(head);
        setcstate(c, S_HTTP_ERROR);
        abort_connection(c);
        return;
    }
    if (check_http_server_bugs(host, c->info, head) && is_connection_restartable(c)) {
        mem_free(head);
        setcstate(c, S_RESTART);
        retry_connection(c);
        return;
    }
    ch = head;
    while ((cookie = parse_http_header(ch, "Set-Cookie", &ch))) {
        unsigned char *host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url);
        set_cookie(NULL, host, cookie);
        mem_free(cookie);
    }
    if (h == 100) {
        mem_free(head);
        state = S_PROC;
        goto again;
    }
    if (h < 200) {
        mem_free(head);
        setcstate(c, S_HTTP_ERROR);
        abort_connection(c);
        return;
    }
    if (h == 204) {
        mem_free(head);
        setcstate(c, S_HTTP_204);
        http_end_request(c, 0);
        return;
    }
    if (h == 304) {
        mem_free(head);
        setcstate(c, S_OK);
        http_end_request(c, 1);
        return;
    }
    if ((h == 500 || h == 502 || h == 503 || h == 504) && http_bugs.retry_internal_errors && is_connection_restartable(c)) {
        /* !!! FIXME: wait some time ... */
        mem_free(head);
        setcstate(c, S_RESTART);
        retry_connection(c);
        return;
    }
    if (!c->cache && get_cache_entry(c->url, &c->cache)) {
        mem_free(head);
        setcstate(c, S_OUT_OF_MEM);
        abort_connection(c);
        return;
    }
    e = c->cache;
    e->http_code = h;
    if (e->head) mem_free(e->head);
    e->head = head;
    if ((d = parse_http_header(head, "Expires", NULL))) {
        time_t t = parse_http_date(d);
        if (t && e->expire_time != 1) e->expire_time = t;
        mem_free(d);
    }
    if ((d = parse_http_header(head, "Pragma", NULL))) {
        if (!casecmp(d, "no-cache", 8)) e->expire_time = 1;
        mem_free(d);
    }
    if ((d = parse_http_header(head, "Cache-Control", NULL))) {
        char *f = d;
        while (1) {
            while (*f && (*f == ' ' || *f == ',')) f++;
            if (!*f) break;
            if (!casecmp(f, "no-cache", 8) || !casecmp(f, "must-revalidate", 15)) {
                e->expire_time = 1;
            }
            if (!casecmp(f, "max-age=", 8)) {
                if (e->expire_time != 1) e->expire_time = time(NULL) + atoi(f + 8);
            }
            while (*f && *f != ',') f++;
        }
        mem_free(d);
    }
#ifdef HAVE_SSL
    if (c->ssl) {
        int l = 0;
        if (e->ssl_info) mem_free(e->ssl_info);
        e->ssl_info = init_str();
        add_num_to_str(&e->ssl_info, &l, SSL_get_cipher_bits(c->ssl, NULL));
        add_to_str(&e->ssl_info, &l, "-bit ");
        add_to_str(&e->ssl_info, &l, SSL_get_cipher_version(c->ssl));
        add_to_str(&e->ssl_info, &l, " ");
        add_to_str(&e->ssl_info, &l, (unsigned  char *)SSL_get_cipher_name(c->ssl));
    }
#endif
    if (e->redirect) mem_free(e->redirect), e->redirect = NULL;
    if (h == 301 || h == 302 || h == 303 || h == 307) {
        if ((h == 302 || h == 307) && !e->expire_time) e->expire_time = 1;
        if ((d = parse_http_header(e->head, "Location", NULL))) {
            unsigned char *user, *ins;
            unsigned char *newuser, *newpassword;
            if (!parse_url(d, NULL, &user, NULL, NULL, NULL, &ins, NULL, NULL, NULL, NULL, NULL, NULL) && !user && ins && (newuser = get_user_name(host))) {
                if (*newuser) {
                    int ins_off = ins - d;
                    newpassword = get_pass(host);
                    if (!newpassword) newpassword = stracpy("");
                    add_to_strn(&newuser, ":");
                    add_to_strn(&newuser, newpassword);
                    add_to_strn(&newuser, "@");
                    extend_str(&d, strlen(newuser));
                    ins = d + ins_off;
                    memmove(ins + strlen(newuser), ins, strlen(ins) + 1);
                    memcpy(ins, newuser, strlen(newuser));
                    mem_free(newpassword);
                }
                mem_free(newuser);
            }
            if (e->redirect) mem_free(e->redirect);
            e->redirect = d;
            e->redirect_get = h == 303;
        }
    }
    if (!e->expire_time && strchr(c->url, POST_CHAR)) e->expire_time = 1;
    info->close = 0;
    info->length = -1;
    info->version = version;
    if ((d = parse_http_header(e->head, "Connection", NULL)) || (d = parse_http_header(e->head, "Proxy-Connection", NULL))) {
        if (!strcasecmp(d, "close")) info->close = 1;
        mem_free(d);
    } else if (version < 11) info->close = 1;
    cf = c->from;
    c->from = 0;
    if ((d = parse_http_header(e->head, "Content-Range", NULL))) {
        if (strlen(d) > 6) {
            d[5] = 0;
            if (!(strcasecmp(d, "bytes")) && d[6] >= '0' && d[6] <= '9') {
#if defined(HAVE_STRTOLL)
                long long f = strtoll(d + 6, NULL, 10);
#elif defined(HAVE_STRTOQ)
                longlong f = strtoq(d + 6, NULL, 10);
#else
                long f = strtol(d + 6, NULL, 10);
                if (f == MAXLONG) f = -1;
#endif
                if (f >= 0 && (off_t)f >= 0 && (off_t)f == f) c->from = f;
            }
        }
        mem_free(d);
    }
    if (cf && !c->from && !c->unrestartable) c->unrestartable = 1;
    if (c->from > cf || c->from < 0) {
        setcstate(c, S_HTTP_ERROR);
        abort_connection(c);
        return;
    }
    if ((d = parse_http_header(e->head, "Content-Length", NULL))) {
        unsigned char *ep;
#if defined(HAVE_STRTOLL)
        long long l = strtoll(d, (char **)(void *)&ep, 10);
#elif defined(HAVE_STRTOQ)
        longlong l = strtoq(d, (char **)(void *)&ep, 10);
#else
        long l = strtol(d, (char **)(void *)&ep, 10);
        if (l == MAXLONG) l = -1;
#endif
        if (!*ep && l >= 0 && (off_t)l >= 0 && (off_t)l == l) {
            if (!info->close || version >= 11) info->length = l;
            if (c->from + l >= 0) c->est_length = c->from + l;
        }
        mem_free(d);
    }
    if ((d = parse_http_header(e->head, "Accept-Ranges", NULL))) {
        if (!strcasecmp(d, "none") && !c->unrestartable) c->unrestartable = 1;
        mem_free(d);
    } else {
        if (!c->unrestartable && !c->from) c->unrestartable = 1;
    }
    if (info->bl_flags & BL_NO_RANGE && !c->unrestartable) c->unrestartable = 1;
    if ((d = parse_http_header(e->head, "Transfer-Encoding", NULL))) {
        if (!strcasecmp(d, "chunked")) {
            info->length = -2;
            info->chunk_remaining = -1;
        }
        mem_free(d);
    }
    if (!info->close && info->length == -1) info->close = 1;
    if ((d = parse_http_header(e->head, "Last-Modified", NULL))) {
        if (e->last_modified && strcasecmp(e->last_modified, d)) {
            delete_entry_content(e);
            if (c->from) {
                c->from = 0;
                mem_free(d);
                setcstate(c, S_MODIFIED);
                retry_connection(c);
                return;
            }
        }
        if (!e->last_modified) e->last_modified = d;
        else mem_free(d);
    }
    if (!e->last_modified && (d = parse_http_header(e->head, "Date", NULL)))
        e->last_modified = d;
    if (info->length == -1 || (version < 11 && info->close)) rb->close = 1;
    read_http_data(c, rb);
}