// This file is part of BOINC. // http://boinc.berkeley.edu // Copyright (C) 2009 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License // as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // BOINC is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see . #if defined(_WIN32) #include "boinc_win.h" #else #include "config.h" #include #include #include #include #include #endif #include "str_util.h" #include "str_replace.h" #include "url.h" using std::string; // Break a URL down into its protocol, server, port and file components // URL format: // [{http|https|socks}://][user[:passwd]@]host.dom.dom[:port][/dir/file] // void parse_url(const char* url, PARSED_URL& purl) { char* p, *q, *buf; char _buf[256]; // strip off the protocol if present // if (strncmp(url, "http://", 7) == 0) { safe_strcpy(_buf, url+7); purl.protocol = URL_PROTOCOL_HTTP; } else if (strncmp(url, "https://", 8) == 0) { safe_strcpy(_buf, url+8); purl.protocol = URL_PROTOCOL_HTTPS; } else if (strncmp(url, "socks://", 8) == 0) { safe_strcpy(_buf, url+8); purl.protocol = URL_PROTOCOL_SOCKS; } else { safe_strcpy(_buf, url); purl.protocol = URL_PROTOCOL_UNKNOWN; } buf = _buf; // parse user name and password // safe_strcpy(purl.user, ""); safe_strcpy(purl.passwd, ""); p = strchr(buf, '@'); if (p) { *p = 0; q = strchr(buf, ':'); if (q) { *q = 0; safe_strcpy(purl.user, buf); safe_strcpy(purl.passwd, q+1); } else { safe_strcpy(purl.user, buf); } buf = p+1; } // parse and strip off file part if present // p = strchr(buf, '/'); if (p) { safe_strcpy(purl.file, p+1); *p = 0; } else { safe_strcpy(purl.file, ""); } // parse and strip off port if present // p = strchr(buf,':'); if (p) { purl.port = atol(p+1); *p = 0; } else { // CMC note: if they didn't pass in a port #, // but the url starts with https://, assume they // want a secure port (HTTPS, port 443) purl.port = (purl.protocol == URL_PROTOCOL_HTTPS) ? 443 : 80; } // what remains is the host // safe_strcpy(purl.host, buf); } // The following functions do "URL-escaping", i.e. escaping GET arguments // to be passed in a URL static char x2c(char *what) { char digit; digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0')); digit *= 16; digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0')); return digit; } // size not really needed since unescaping can only shrink // void unescape_url(char *url, int url_size) { int x,y; for (x=0,y=0; url[y] && (x(buf[i])); } snprintf(url, len, "http%s://%s", (bSSL ? "s" : ""), buf); url[len-1] = 0; } void canonicalize_master_url(string& url) { char buf[1024]; safe_strcpy(buf, url.c_str()); canonicalize_master_url(buf, sizeof(buf)); url = buf; } // return true if url1 and url2 are the same // except ur1 is http: and url2 is https: // bool is_https_transition(const char* url1, const char* url2) { if (strstr(url1, "http://") != url1) return false; if (strstr(url2, "https://") != url2) return false; if (strcmp(url1+strlen("http://"), url2+strlen("https://"))) return false; return true; } // return true if url1 and url2 are the same except protocol // bool urls_match(const char* url1, const char* url2) { const char* p = strstr(url1, "//"); const char* q = strstr(url2, "//"); if (!p || !q) return false; return strcmp(p, q) == 0; } // is the string a valid master URL, in canonical form? // bool valid_master_url(char* buf) { char* p, *q; size_t n; bool bSSL = false; p = strstr(buf, "http://"); if (p != buf) { // allow https p = strstr(buf, "https://"); if (p == buf) { bSSL = true; } else { return false; // no http or https, it's bad! } } q = p+strlen(bSSL ? "https://" : "http://"); p = strchr(q, '.'); if (!p) return false; if (p == q) return false; q = p+1; p = strchr(q, '/'); if (!p) return false; if (p == q) return false; n = strlen(buf); if (buf[n-1] != '/') return false; return true; } void escape_project_url(char *in, char* out) { escape_url_readable(in, out); char& last = out[strlen(out)-1]; // remove trailing _ if (last == '_') { last = '\0'; } } bool is_https(const char* url) { return (strncmp(url, "https://", 8) == 0); }