diff options
author | npmccallum <npmccallum@c587cffe-e639-0410-9787-d7902ae8ed56> | 2010-01-17 00:49:40 +0000 |
---|---|---|
committer | npmccallum <npmccallum@c587cffe-e639-0410-9787-d7902ae8ed56> | 2010-01-17 00:49:40 +0000 |
commit | eb677dcd774a460da9349cc3622c5e14317645bd (patch) | |
tree | 75881e126bd950a8d1654490a0bf959fd85492c2 /libproxy/pac.cpp | |
parent | fc72a9f5414d7498c78dc7b6a1382cd0631cbf49 (diff) | |
download | libproxy-eb677dcd774a460da9349cc3622c5e14317645bd.tar.gz |
make code more c++ish (major rework)
git-svn-id: http://libproxy.googlecode.com/svn/trunk@457 c587cffe-e639-0410-9787-d7902ae8ed56
Diffstat (limited to 'libproxy/pac.cpp')
-rw-r--r-- | libproxy/pac.cpp | 210 |
1 files changed, 79 insertions, 131 deletions
diff --git a/libproxy/pac.cpp b/libproxy/pac.cpp index bd533a7..c842537 100644 --- a/libproxy/pac.cpp +++ b/libproxy/pac.cpp @@ -17,177 +17,125 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ******************************************************************************/ -#include <unistd.h> -#include <string.h> -#include <time.h> -#include <sys/types.h> -#include <sys/stat.h> +#include <cstdlib> // For atoi(...) +#include <sys/stat.h> // For stat(...) +#include <cstdio> // For sscanf(...) #ifdef _WIN32 #include <winsock2.h> +#define pfsize(st) (st.st_size) #else #include <sys/socket.h> +#define pfsize(st) (st.st_blksize * st.st_blocks) #endif -#include "url.hpp" -#include "misc.hpp" #include "pac.hpp" +// This mime type should be reported by the web server #define PAC_MIME_TYPE "application/x-ns-proxy-autoconfig" +// Fall back to checking for this mime type, which servers often report wrong +#define PAC_MIME_TYPE_FB "text/plain" -/** - * ProxyAutoConfig object. All fields are private. - */ -struct _pxPAC { - pxURL *url; - char *cache; - time_t expires; -}; - -/** - * Frees memory used by the ProxyAutoConfig. - */ -void -px_pac_free(pxPAC *self) -{ - if (!self) return; - px_url_free(self->url); - px_free(self->cache); - px_free(self); -} +// This is the maximum pac size (to avoid memory attacks) +#define PAC_MAX_SIZE 102400 -/** - * Get the URL which the pxPAC uses. - * @return The URL that the pxPAC came from - */ -const pxURL * -px_pac_get_url(pxPAC *self) -{ - return self->url; -} +namespace com { +namespace googlecode { +namespace libproxy { +using namespace std; -/** - * Create a new ProxyAutoConfig. - * @url The URL where the PAC file is found - * @return A new ProxyAutoConfig or NULL on error - */ -pxPAC * -px_pac_new(pxURL *url) +static inline string _readline(int fd) { - if (!url) return NULL; - - /* Allocate the object */ - pxPAC *self = (pxPAC *) px_malloc0(sizeof(pxPAC)); - - /* Copy the given URL */ - self->url = px_url_new(px_url_to_string(url)); /* Always returns valid value */ - - /* Make sure we have a real pxPAC */ - if (!px_pac_reload(self)) { px_pac_free(self); return NULL; } - - return self; + // Read a character. + // If we don't get a character, return empty string. + // If we are at the end of the line, return empty string. + char c = '\0'; + if (read(fd, &c, 1) != 1 || c == '\n') return ""; + return string(1, c) + _readline(fd); } -/** - * Create a new ProxyAutoConfig (from a string for convenience). - * @url The url (string) where the PAC file is found - * @return A new ProxyAutoConfig or NULL on error - */ -pxPAC * -px_pac_new_from_string(char *url) -{ - /* Create temporary URL */ - pxURL *tmpurl = px_url_new(url); - if (!tmpurl) return NULL; - - /* Create pac */ - pxPAC *self = px_pac_new(tmpurl); - px_url_free(tmpurl); /* Free no longer used URL */ - if (!self) return NULL; - return self; +pac::~pac() { + delete this->pacurl; } -/** - * Returns the Javascript code which the pxPAC uses. - * @return The Javascript code used by the pxPAC - */ -const char * -px_pac_to_string(pxPAC *self) -{ - return self->cache; +pac::pac(const pac& pac) { + this->pacurl = new libproxy::url(*pac.pacurl); + this->cache = pac.cache; } -/** - * Download the latest version of the pxPAC file - * @return Whether the download was successful or not - */ -bool -px_pac_reload(pxPAC *self) -{ +pac::pac(const url& url) throw (io_error) { int sock; - char *line = NULL; - const char *headers[3] = { "Accept: " PAC_MIME_TYPE, "Connection: close", NULL }; bool correct_mime_type; - unsigned long int content_length = 0; + unsigned long int content_length = 0, status = 0; + + this->pacurl = new libproxy::url(url.to_string().find("pac+") == 0 ? url.to_string().substr(4) : url); /* Get the pxPAC */ - sock = px_url_get(self->url, headers); - if (sock < 0) return false; + map<string, string> headers; + headers["Accept"] = PAC_MIME_TYPE; + headers["Connection"] = "close"; + sock = this->pacurl->open(headers); + if (sock < 0) throw io_error("Unable to connect: " + url.to_string()); - if (strcmp(px_url_get_scheme(self->url),"file")) + if (url.get_scheme() != "file") { /* Verify status line */ - line = px_readline(sock, NULL, 0); - if (!line) goto error; - if (strncmp(line, "HTTP", strlen("HTTP"))) goto error; /* Check valid HTTP response */ - if (!strchr(line, ' ') || atoi(strchr(line, ' ') + 1) != 200) goto error; /* Check status code */ + string line = _readline(sock); + if (sscanf(line.c_str(), "HTTP/1.%*d %d", &status) != 1 || status != 200) goto error; /* Check for correct mime type and content length */ - while (strcmp(line, "\r")) { - /* Check for content type */ - if (strstr(line, "Content-Type: ") == line && strstr(line, PAC_MIME_TYPE)) + for (line = _readline(sock) ; line != "\r" && line != "" ; line = _readline(sock)) { + // Check for content type + if (line.find("Content-Type: ") == 0 && + line.find(PAC_MIME_TYPE) != string::npos || + line.find(PAC_MIME_TYPE_FB) != string::npos) correct_mime_type = true; - /* Check for content length */ - else if (strstr(line, "Content-Length: ") == line) - content_length = atoi(line + strlen("Content-Length: ")); - - /* Get new line */ - px_free(line); - line = px_readline(sock, NULL, 0); - if (!line) goto error; + // Check for content length + else if (content_length == 0) + sscanf(line.c_str(), "Content-Length: %lu", &content_length); } - /* Get content */ - if (!content_length || !correct_mime_type) goto error; - px_free(line); line = NULL; - px_free(self->cache); - self->cache = (char *) px_malloc0(content_length+1); - for (int recvd=0 ; recvd != content_length ; ) - recvd += recv(sock, self->cache + recvd, content_length - recvd, 0); + // Get content + if (!content_length || content_length > PAC_MAX_SIZE || !correct_mime_type) goto error; + char *buffer = new char[content_length]; + for (int recvd=0 ; recvd < content_length ; ) + recvd += recv(sock, buffer + recvd, content_length - recvd, 0); + this->cache = buffer; + delete buffer; } else { /* file:// url */ - struct stat buffer; + struct stat st; int status; - if (fstat(sock, &buffer)) goto error; -#ifdef _WIN32 - self->cache = (char *) px_malloc0(buffer.st_size + 1); - status = read(sock, self->cache, buffer.st_size); -#else - self->cache = (char *) px_malloc0(buffer.st_blksize * buffer.st_blocks + 1); - status = read(sock, self->cache, buffer.st_blksize * buffer.st_blocks); -#endif + if (fstat(sock, &st) || pfsize(st) > PAC_MAX_SIZE) goto error; + char *buffer = new char[pfsize(st)+1]; + if (read(sock, buffer, pfsize(st)) == 0) { + delete buffer; + goto error; + } + this->cache = buffer; + delete buffer; } - /* Clean up */ + // Clean up close(sock); - return true; + return; + +error: + if (sock >= 0) close(sock); + throw io_error("Unable to read PAC from " + url.to_string()); +} - error: - px_free(self->cache); self->cache = NULL; - if (sock >= 0) close(sock); - px_free(line); - return false; +url pac::get_url() const { + return *(this->pacurl); +} + +string pac::to_string() const { + return this->cache; +} + +} +} } |