📄 http.c
字号:
/* If the server specified a new location then lets store it. */ if (!hs->newloc) hs->newloc = hgetlocation(hdr); if (!hs->remote_time) hs->remote_time = hgetmodified(hdr); if (hs->accept_ranges == -1) hs->accept_ranges = hgetaccept_ranges(hdr); if (!hs->newloc) hs->newloc = hgetlocation(hdr); kfree(hdr); } if (H_20X(statcode)) return HOK; if (H_REDIRECTED(statcode) || statcode == HTTP_MULTIPLE_CHOICES) { /* RFC2068 says that in case of the 300 (multiple choices) response, the server can output a preferred URL through `Location' header; otherwise, the request should be treated like GET. So, if the location is set, it will be a redirection; otherwise, just proceed normally. */ if (statcode == HTTP_MULTIPLE_CHOICES && !hs->newloc) return HOK; else { if (all_headers) kfree(all_headers); if (type) kfree(type); return NEWLOCATION; } } if (statcode == HTTP_UNAUTHORIZED) return HAUTHREQ; if (statcode == HTTP_NOT_FOUND) return HTTPNSFOD; if (statcode == HTTP_INTERNAL) return INTERNALSERVERR; if (statcode == HTTP_NOT_IMPLEMENTED) return UNKNOWNREQ; if (statcode == HTTP_BAD_GATEWAY) return BADGATEWAY; if (statcode == HTTP_UNAVAILABLE) return SERVICEUNAVAIL; if (statcode == HTTP_GATEWAY_TIMEOUT) return GATEWAYTIMEOUT; return HERR;}/****************************************************************************** ...******************************************************************************/char *get_basic_auth_str(char *user, char *passwd, char *auth_header){ char *p1, *p2, *ret; int len = strlen(user) + strlen(passwd) + 1; int b64len = 4 * ((len + 2) / 3); p1 = kmalloc(len + 1); sprintf(p1, "%s:%s", user, passwd); p2 = kmalloc(b64len + 1); /* Encode username:passwd to base64. */ base64_encode(p1, p2, len); ret = kmalloc(strlen(auth_header) + b64len + 11); sprintf(ret, "%s: Basic %s\r\n", auth_header, p2); kfree(p1); kfree(p2); return ret;}/****************************************************************************** ...******************************************************************************/boolean http_use_proxy(connection_t * connection){ return (connection->http_proxy && connection->http_proxy->use_proxy && connection->http_proxy->proxy_url.url) ? TRUE : FALSE;}/****************************************************************************** ...******************************************************************************/uerr_t proz_http_get_url_info(connection_t * connection){ uerr_t err; int remote_port_len; char *user, *passwd, *www_auth = NULL, *proxy_auth = NULL, *referer = NULL, *location = NULL, *pragma_no_cache = NULL; char *request, *remote_port; netrc_entry *netrc_ent; memset(&connection->hs, 0, sizeof(connection->hs)); if (http_use_proxy(connection)) { connection_show_message(connection, _("Connecting to %s"), connection->http_proxy->proxy_url.host); err = connect_to_server(&connection->data_sock, connection->http_proxy->proxy_url.host, connection->http_proxy->proxy_url.port, &connection->xfer_timeout); if (err != NOCONERROR) { connection_show_message(connection, _("Error connecting to %s"), connection->http_proxy->proxy_url.host); return err; } } else { connection_show_message(connection, _("Connecting to %s"), connection->u.host); err = connect_to_server(&connection->data_sock, connection->u.host, connection->u.port, &connection->xfer_timeout); if (err != NOCONERROR) { connection_show_message(connection, _("Error connecting to %s"), connection->u.host); return err; } } user = connection->u.user; passwd = connection->u.passwd; /* Use .netrc if asked to do so. */ if (connection->use_netrc == TRUE) { netrc_ent = search_netrc(libprozrtinfo.netrc_list, connection->u.host); if (netrc_ent != NULL) { user = netrc_ent->account; passwd = netrc_ent->password; } } user = user ? user : ""; passwd = passwd ? passwd : ""; if (strlen(user) || strlen(passwd)) { /* Construct the necessary header. */ www_auth = get_basic_auth_str(user, passwd, "Authorization"); proz_debug(_("Authenticating as user %s password %s"), user, passwd); proz_debug(_("Authentification string=%s"), www_auth); } else www_auth = 0; if (http_use_proxy(connection)) { if (strlen(connection->http_proxy->username) || strlen(connection->http_proxy->passwd)) proxy_auth = get_basic_auth_str(connection->http_proxy->username, connection->http_proxy->passwd, "Proxy-Authorization"); } if (connection->u.port == 80) { remote_port = NULL; remote_port_len = 0; } else { remote_port = (char *) alloca(64); remote_port_len = sprintf(remote_port, ":%d", connection->u.port); } if (connection->u.referer) { referer = (char *) alloca(13 + strlen(connection->u.referer)); sprintf(referer, "Referer: %s\r\n", connection->u.referer); } /* If we go through a proxy the request for the URL is different */ if (http_use_proxy(connection)) { location = (char *) alloca(strlen(connection->u.url) + 1); strcpy(location, connection->u.url); } else { location = (char *) alloca(strlen(connection->u.path) + 1); strcpy(location, connection->u.path); } /*Use no-cache directive for proxy servers? */ if (http_use_proxy(connection) && (connection->http_no_cache || connection->attempts > 0)) { pragma_no_cache = (char *) alloca(21); sprintf(pragma_no_cache, "Pragma: no-cache\r\n"); } request = (char *) alloca(strlen(location) + strlen(connection->user_agent) + strlen(connection->u.host) + remote_port_len + (referer ? strlen(referer) : 0) + (www_auth ? strlen(www_auth) : 0) + (proxy_auth ? strlen(proxy_auth) : 0) + 64 + (pragma_no_cache ? strlen(pragma_no_cache) : 0)); sprintf(request, "GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s%s\r\nAccept: */*\r\n%s%s%s%s\r\n", location, connection->user_agent, connection->u.host, remote_port ? remote_port : "", referer ? referer : "", www_auth ? www_auth : "", proxy_auth ? proxy_auth : "", pragma_no_cache ? pragma_no_cache : ""); proz_debug("HTTP request = %s", request); connection_show_message(connection, _("Sending HTTP request")); err = http_fetch_headers(connection, &connection->hs, request); close_sock(&connection->data_sock); if (err == HOK) { connection->main_file_size = connection->hs.contlen; if (connection->hs.accept_ranges == 1) connection->resume_support = TRUE; else if (connection->hs.accept_ranges == -1) connection->resume_support = FALSE; } connection->file_type = REGULAR_FILE; return err;}/*Loops for connection->attempts */uerr_t http_get_url_info_loop(connection_t * connection){ pthread_mutex_lock(&connection->access_mutex); connection->running = TRUE; pthread_mutex_unlock(&connection->access_mutex); assert(connection->attempts >= 0); do { if (connection->attempts > 0 && connection->err != NEWLOCATION) { connection_show_message(connection, _("Retrying...Attempt %d in %d seconds"), connection->attempts, connection->retry_delay.tv_sec); delay_ms(connection->retry_delay.tv_sec * 1000); } /*Push the handler which will cleanup any sockets that are left open */ pthread_cleanup_push(cleanup_socks, (void *) connection); connection->err = proz_http_get_url_info(connection); /*pop the handler */ pthread_cleanup_pop(0); connection->attempts++; switch (connection->err) { case HOK: connection_show_message(connection, _("Successfully got info")); pthread_mutex_lock(&connection->access_mutex); connection->running = FALSE; pthread_mutex_unlock(&connection->access_mutex); return connection->err; break; case NEWLOCATION: return connection->err; break; case HTTPNSFOD: connection_show_message(connection, _("File not found!")); pthread_mutex_lock(&connection->access_mutex); connection->running = FALSE; pthread_mutex_unlock(&connection->access_mutex); return connection->err; break; default: connection_show_message(connection, proz_strerror(connection->err)); break; } } while ((connection->attempts < connection->max_attempts) || connection->max_attempts == 0); connection_show_message(connection, _ ("I have tried %d attempt(s) and have failed, aborting"), connection->attempts); pthread_mutex_lock(&connection->access_mutex); connection->running = FALSE; pthread_mutex_unlock(&connection->access_mutex); return connection->err;}/* I am writing a seperate function to handle FTP proxying through HTTP, I MHO whoever thought of using HTTP to proxy FTP is a shithead, its such a PITA ;) */uerr_t ftp_get_url_info_from_http_proxy(connection_t * connection){ uerr_t err; int remote_port_len; char *user, *passwd, *www_auth = NULL, *proxy_auth = NULL, *pragma_no_cache = NULL; char *request, *remote_port; netrc_entry *netrc_ent; memset(&connection->hs, 0, sizeof(connection->hs)); err = connect_to_server(&connection->data_sock, connection->ftp_proxy->proxy_url.host, connection->ftp_proxy->proxy_url.port, &connection->xfer_timeout); if (err != NOCONERROR) { connection_show_message(connection, _("Error connecting to %s"), connection->ftp_proxy->proxy_url.host); return err; } user = connection->u.user; passwd = connection->u.passwd; /* Use .netrc if asked to do so. */ if (connection->use_netrc == TRUE) { netrc_ent = search_netrc(libprozrtinfo.netrc_list, connection->u.host); if (netrc_ent != NULL) { user = netrc_ent->account; passwd = netrc_ent->password; } } user = user ? user : ""; passwd = passwd ? passwd : ""; if (strlen(user) || strlen(passwd)) { /* Construct the necessary header. */ www_auth = get_basic_auth_str(user, passwd, "Authorization"); proz_debug(_("Authenticating as user %s password %s"), user, passwd); proz_debug(_("Authentification string=%s"), www_auth); } else www_auth = 0; if (strlen(connection->ftp_proxy->username) || strlen(connection->ftp_proxy->passwd)) proxy_auth = get_basic_auth_str(connection->ftp_proxy->username, connection->ftp_proxy->passwd, "Proxy-Authorization"); remote_port = (char *) alloca(64); remote_port_len = sprintf(remote_port, ":%d", connection->u.port); if (http_use_proxy(connection) && (connection->http_no_cache || connection->attempts > 0)) { pragma_no_cache = (char *) alloca(21); sprintf(pragma_no_cache, "Pragma: no-cache\r\n"); } /*Referrer TAG should not be needed in FTP through HTTP proxy..right */ request = (char *) alloca(strlen(connection->u.url) + strlen(connection->user_agent) + strlen(connection->u.host) + remote_port_len + (www_auth ? strlen(www_auth) : 0) + (proxy_auth ? strlen(proxy_auth) : 0) + 64 + (pragma_no_cache ? strlen(pragma_no_cache) : 0)); sprintf(request, "GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s%s\r\nAccept: */*\r\n%s%s%s\r\n", connection->u.url, connection->user_agent, connection->u.host, remote_port, www_auth ? www_auth : "", proxy_auth ? proxy_auth : "", pragma_no_cache ? pragma_no_cache : ""); proz_debug("HTTP request = %s", request); err = http_fetch_headers(connection, &connection->hs, request); close_sock(&connection->data_sock); /*Convert the error code to the equivalent FTP one if possible */ if (err == HOK) { connection->main_file_size = connection->hs.contlen; if (connection->hs.accept_ranges == 1) connection->resume_support = TRUE; else if (connection->hs.accept_ranges == -1) connection->resume_support = FALSE; return FTPOK; } if (err == HAUTHREQ) return FTPLOGREFUSED; else if (err == HTTPNSFOD) return FTPNSFOD; /* connection->file_type = REGULAR_FILE; */ return FTPERR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -