⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 4 页
字号:
		abort_connection(conn);	}}static void http_send_header(struct connection *);voidhttp_protocol_handler(struct connection *conn){	/* setcstate(conn, S_CONN); */	set_connection_timeout(conn);	if (!has_keepalive_connection(conn)) {		make_connection(conn, &conn->socket, http_send_header);	} else {		http_send_header(conn);	}}voidproxy_protocol_handler(struct connection *conn){	http_protocol_handler(conn);}static void http_get_header(struct connection *);#define IS_PROXY_URI(x) ((x)->protocol == PROTOCOL_PROXY)#define connection_is_https_proxy(conn) \	(IS_PROXY_URI((conn)->uri) && (conn)->proxied_uri->protocol == PROTOCOL_HTTPS)static voidhttp_send_header(struct connection *conn){	struct http_connection_info *info;	int trace = get_opt_bool("protocol.http.trace");	struct string header;	unsigned char *post_data = NULL;	struct auth_entry *entry;	struct uri *uri = conn->proxied_uri; /* Set to the real uri */	unsigned char *optstr;	int use_connect, talking_to_proxy;	set_connection_timeout(conn);	/* Sanity check for a host */	if (!uri || !uri->host || !*uri->host || !uri->hostlen) {		http_end_request(conn, S_BAD_URL, 0);		return;	}	info = mem_calloc(1, sizeof(*info));	if (!info) {		abort_conn_with_state(conn, S_OUT_OF_MEM);		return;	}	/* If called from HTTPS proxy connection the connection info might have	 * already been allocated. */	mem_free_set(&conn->info, info);	info->sent_version.major = 1;	info->sent_version.minor = 1;	info->bl_flags = get_blacklist_flags(uri);	if (info->bl_flags & SERVER_BLACKLIST_HTTP10	    || get_opt_bool("protocol.http.bugs.http10")) {		info->sent_version.major = 1;		info->sent_version.minor = 0;	}	if (!init_string(&header)) {		http_end_request(conn, S_OUT_OF_MEM, 0);		return;	}	talking_to_proxy = IS_PROXY_URI(conn->uri) && !conn->socket.ssl;	use_connect = connection_is_https_proxy(conn) && !conn->socket.ssl;	if (trace) {		add_to_string(&header, "TRACE ");	} else if (use_connect) {		add_to_string(&header, "CONNECT ");	} else if (uri->post) {		add_to_string(&header, "POST ");		conn->unrestartable = 1;	} else {		add_to_string(&header, "GET ");	}	if (!talking_to_proxy) {		add_char_to_string(&header, '/');	}	if (use_connect) {		/* Add port if it was specified or the default port */		add_uri_to_string(&header, uri, URI_HTTP_CONNECT);	} else {		if (connection_is_https_proxy(conn) && conn->socket.ssl) {			add_url_to_http_string(&header, uri, URI_DATA);		} else if (talking_to_proxy) {			add_url_to_http_string(&header, uri, URI_PROXY);		} else {			add_url_to_http_string(&header, conn->uri, URI_DATA);		}	}	add_to_string(&header, " HTTP/");	add_long_to_string(&header, info->sent_version.major);	add_char_to_string(&header, '.');	add_long_to_string(&header, info->sent_version.minor);	add_crlf_to_string(&header);	add_to_string(&header, "Host: ");	add_uri_to_string(&header, uri, URI_HTTP_HOST);	add_crlf_to_string(&header);	if (talking_to_proxy) {		unsigned char *user = get_opt_str("protocol.http.proxy.user");		unsigned char *passwd = get_opt_str("protocol.http.proxy.passwd");		if (proxy_auth.digest) {			unsigned char *response;			int userlen = int_min(strlen(user), HTTP_AUTH_USER_MAXLEN - 1);			int passwordlen = int_min(strlen(passwd), HTTP_AUTH_PASSWORD_MAXLEN - 1);			if (userlen)				memcpy(proxy_auth.user, user, userlen);			proxy_auth.user[userlen] = '\0';			if (passwordlen)				memcpy(proxy_auth.password, passwd, passwordlen);			proxy_auth.password[passwordlen] = '\0';			/* FIXME: @uri is the proxied URI. Maybe the passed URI			 * should be the proxy URI aka conn->uri. --jonas */			response = get_http_auth_digest_response(&proxy_auth, uri);			if (response) {				add_to_string(&header, "Proxy-Authorization: Digest ");				add_to_string(&header, response);				add_crlf_to_string(&header);				mem_free(response);			}		} else {			if (user[0]) {				unsigned char *proxy_data;				proxy_data = straconcat(user, ":", passwd, NULL);				if (proxy_data) {					unsigned char *proxy_64 = base64_encode(proxy_data);					if (proxy_64) {						add_to_string(&header, "Proxy-Authorization: Basic ");						add_to_string(&header, proxy_64);						add_crlf_to_string(&header);						mem_free(proxy_64);					}					mem_free(proxy_data);				}			}		}	}	optstr = get_opt_str("protocol.http.user_agent");	if (*optstr && strcmp(optstr, " ")) {		unsigned char *ustr, ts[64] = "";		add_to_string(&header, "User-Agent: ");		if (!list_empty(terminals)) {			unsigned int tslen = 0;			struct terminal *term = terminals.prev;			ulongcat(ts, &tslen, term->width, 3, 0);			ts[tslen++] = 'x';			ulongcat(ts, &tslen, term->height, 3, 0);		}		ustr = subst_user_agent(optstr, VERSION_STRING, system_name,					ts);		if (ustr) {			add_to_string(&header, ustr);			mem_free(ustr);		}		add_crlf_to_string(&header);	}	switch (get_opt_int("protocol.http.referer.policy")) {		case REFERER_NONE:			/* oh well */			break;		case REFERER_FAKE:			optstr = get_opt_str("protocol.http.referer.fake");			if (!optstr[0]) break;			add_to_string(&header, "Referer: ");			add_to_string(&header, optstr);			add_crlf_to_string(&header);			break;		case REFERER_TRUE:			if (!conn->referrer) break;			add_to_string(&header, "Referer: ");			add_url_to_http_string(&header, conn->referrer, URI_HTTP_REFERRER);			add_crlf_to_string(&header);			break;		case REFERER_SAME_URL:			add_to_string(&header, "Referer: ");			add_url_to_http_string(&header, uri, URI_HTTP_REFERRER);			add_crlf_to_string(&header);			break;	}	add_to_string(&header, "Accept: */*");	add_crlf_to_string(&header);	/* TODO: Make this encoding.c function. */#if defined(CONFIG_GZIP) || defined(CONFIG_BZIP2)	add_to_string(&header, "Accept-Encoding: ");#ifdef BUG_517#ifdef CONFIG_BZIP2	add_to_string(&header, "bzip2");#endif#endif#ifdef CONFIG_GZIP#ifdef BUG_517#ifdef CONFIG_BZIP2	add_to_string(&header, ", ");#endif#endif	add_to_string(&header, "gzip");#endif	add_crlf_to_string(&header);#endif	if (!accept_charset) {		init_accept_charset();	}	if (!(info->bl_flags & SERVER_BLACKLIST_NO_CHARSET)	    && !get_opt_bool("protocol.http.bugs.accept_charset")	    && accept_charset) {		add_to_string(&header, accept_charset);	}	optstr = get_opt_str("protocol.http.accept_language");	if (optstr[0]) {		add_to_string(&header, "Accept-Language: ");		add_to_string(&header, optstr);		add_crlf_to_string(&header);	}#ifdef ENABLE_NLS	else if (get_opt_bool("protocol.http.accept_ui_language")) {		unsigned char *code = language_to_iso639(current_language);		if (code) {			add_to_string(&header, "Accept-Language: ");			add_to_string(&header, code);			add_crlf_to_string(&header);		}	}#endif	/* FIXME: What about post-HTTP/1.1?? --Zas */	if (HTTP_1_1(info->sent_version)) {		if (!IS_PROXY_URI(conn->uri)) {			add_to_string(&header, "Connection: ");		} else {			add_to_string(&header, "Proxy-Connection: ");		}		if (!uri->post || !get_opt_bool("protocol.http.bugs.post_no_keepalive")) {			add_to_string(&header, "Keep-Alive");		} else {			add_to_string(&header, "close");		}		add_crlf_to_string(&header);	}	if (conn->cached) {		if (!conn->cached->incomplete && conn->cached->head && conn->cached->last_modified		    && conn->cache_mode <= CACHE_MODE_CHECK_IF_MODIFIED) {			add_to_string(&header, "If-Modified-Since: ");			add_to_string(&header, conn->cached->last_modified);			add_crlf_to_string(&header);		}	}	if (conn->cache_mode >= CACHE_MODE_FORCE_RELOAD) {		add_to_string(&header, "Pragma: no-cache");		add_crlf_to_string(&header);		add_to_string(&header, "Cache-Control: no-cache");		add_crlf_to_string(&header);	}	if (conn->from || (conn->progress.start > 0)) {		/* conn->from takes precedence. conn->progress.start is set only the first		 * time, then conn->from gets updated and in case of any retries		 * etc we have everything interesting in conn->from already. */		add_to_string(&header, "Range: bytes=");		add_long_to_string(&header, conn->from ? conn->from : conn->progress.start);		add_char_to_string(&header, '-');		add_crlf_to_string(&header);	}	entry = find_auth(uri);	if (entry) {		if (entry->digest) {			unsigned char *response;			response = get_http_auth_digest_response(entry, uri);			if (response) {				add_to_string(&header, "Authorization: Digest ");				add_to_string(&header, response);				add_crlf_to_string(&header);				mem_free(response);			}		} else {			/* RFC2617 section 2 [Basic Authentication Scheme]			 *			 * To receive authorization, the client sends the userid			 * and password, separated by a single colon (":")			 * character, within a base64 [7] encoded string in the			 * credentials. */			unsigned char *id;			/* Create base64 encoded string. */			id = straconcat(entry->user, ":", entry->password, NULL);			if (id) {				unsigned char *base64 = base64_encode(id);				mem_free_set(&id, base64);			}			if (id) {				add_to_string(&header, "Authorization: Basic ");				add_to_string(&header, id);				add_crlf_to_string(&header);				mem_free(id);			}		}	}	if (uri->post) {		/* We search for first '\n' in uri->post to get content type		 * as set by get_form_uri(). This '\n' is dropped if any		 * and replaced by correct '\r\n' termination here. */		unsigned char *postend = strchr(uri->post, '\n');		if (postend) {			add_to_string(&header, "Content-Type: ");			add_bytes_to_string(&header, uri->post, postend - uri->post);			add_crlf_to_string(&header);		}		post_data = postend ? postend + 1 : uri->post;		add_to_string(&header, "Content-Length: ");		add_long_to_string(&header, strlen(post_data) / 2);		add_crlf_to_string(&header);	}#ifdef CONFIG_COOKIES	{		struct string *cookies = send_cookies(uri);		if (cookies) {			add_to_string(&header, "Cookie: ");			add_string_to_string(&header, cookies);			add_crlf_to_string(&header);			done_string(cookies);		}	}#endif	add_crlf_to_string(&header);	if (post_data) {#define POST_BUFFER_SIZE 4096		unsigned char *post = post_data;		unsigned char buffer[POST_BUFFER_SIZE];		int n = 0;		while (post[0] && post[1]) {			int h1, h2;			h1 = unhx(post[0]);			assert(h1 >= 0 && h1 < 16);			if_assert_failed h1 = 0;			h2 = unhx(post[1]);			assert(h2 >= 0 && h2 < 16);			if_assert_failed h2 = 0;			buffer[n++] = (h1<<4) + h2;			post += 2;			if (n == POST_BUFFER_SIZE) {				add_bytes_to_string(&header, buffer, n);				n = 0;			}		}		if (n)			add_bytes_to_string(&header, buffer, n);#undef POST_BUFFER_SIZE	}	write_to_socket(conn, &conn->socket, header.source, header.length,			http_get_header);	done_string(&header);	set_connection_state(conn, S_SENT);}/* This function decompresses the data block given in @data (if it was * compressed), which is long @len bytes. The decompressed data block is given * back to the world as the return value and its length is stored into * @new_len. * * In this function, value of either info->chunk_remaining or info->length is * being changed (it depends on if chunked mode is used or not). * * Note that the function is still a little esotheric for me. Don't take it * lightly and don't mess with it without grave reason! If you dare to touch * this without testing the changes on slashdot, freshmeat and cvsweb * (including revision history), don't dare to send me any patches! ;) --pasky * * This function gotta die. */static unsigned char *decompress_data(struct connection *conn, unsigned char *data, int len,		int *new_len){	struct http_connection_info *info = conn->info;	/* to_read is number of bytes to be read from the decoder. It is 65536	 * (then we are just emptying the decoder buffer as we finished the walk	 * through the incoming stream already) or PIPE_BUF / 2 (when we are	 * still walking through the stream - then we write PIPE_BUF / 2 to the	 * pipe and read it back to the decoder ASAP; the point is that we can't	 * write more than PIPE_BUF to the pipe at once, but we also have to	 * never let read_encoded() (gzread(), in fact) to empty the pipe - that	 * causes further malfunction of zlib :[ ... so we will make sure that

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -