1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef TALK_BASE_HTTPCOMMON_INL_H__ 29 #define TALK_BASE_HTTPCOMMON_INL_H__ 30 31 #include "talk/base/common.h" 32 #include "talk/base/httpcommon.h" 33 34 namespace talk_base { 35 36 /////////////////////////////////////////////////////////////////////////////// 37 // Url 38 /////////////////////////////////////////////////////////////////////////////// 39 40 template<class CTYPE> 41 void Url<CTYPE>::do_set_url(const CTYPE* val, size_t len) { 42 if (ascnicmp(val, "http://", 7) == 0) { 43 val += 7; len -= 7; 44 secure_ = false; 45 } else if (ascnicmp(val, "https://", 8) == 0) { 46 val += 8; len -= 8; 47 secure_ = true; 48 } else { 49 clear(); 50 return; 51 } 52 const CTYPE* path = strchrn(val, len, static_cast<CTYPE>('/')); 53 if (!path) { 54 path = val + len; 55 } 56 size_t address_length = (path - val); 57 do_set_address(val, address_length); 58 do_set_full_path(path, len - address_length); 59 } 60 61 template<class CTYPE> 62 void Url<CTYPE>::do_set_address(const CTYPE* val, size_t len) { 63 if (const CTYPE* colon = strchrn(val, len, static_cast<CTYPE>(':'))) { 64 host_.assign(val, colon - val); 65 // Note: In every case, we're guaranteed that colon is followed by a null, 66 // or non-numeric character. 67 port_ = static_cast<uint16>(::strtoul(colon + 1, NULL, 10)); 68 // TODO: Consider checking for invalid data following port number. 69 } else { 70 host_.assign(val, len); 71 port_ = HttpDefaultPort(secure_); 72 } 73 } 74 75 template<class CTYPE> 76 void Url<CTYPE>::do_set_full_path(const CTYPE* val, size_t len) { 77 const CTYPE* query = strchrn(val, len, static_cast<CTYPE>('?')); 78 if (!query) { 79 query = val + len; 80 } 81 size_t path_length = (query - val); 82 if (0 == path_length) { 83 // TODO: consider failing in this case. 84 path_.assign(1, static_cast<CTYPE>('/')); 85 } else { 86 ASSERT(val[0] == static_cast<CTYPE>('/')); 87 path_.assign(val, path_length); 88 } 89 query_.assign(query, len - path_length); 90 } 91 92 template<class CTYPE> 93 void Url<CTYPE>::do_get_url(string* val) const { 94 CTYPE protocol[9]; 95 asccpyn(protocol, ARRAY_SIZE(protocol), secure_ ? "https://" : "http://"); 96 val->append(protocol); 97 do_get_address(val); 98 do_get_full_path(val); 99 } 100 101 template<class CTYPE> 102 void Url<CTYPE>::do_get_address(string* val) const { 103 val->append(host_); 104 if (port_ != HttpDefaultPort(secure_)) { 105 CTYPE format[5], port[32]; 106 asccpyn(format, ARRAY_SIZE(format), ":%hu"); 107 sprintfn(port, ARRAY_SIZE(port), format, port_); 108 val->append(port); 109 } 110 } 111 112 template<class CTYPE> 113 void Url<CTYPE>::do_get_full_path(string* val) const { 114 val->append(path_); 115 val->append(query_); 116 } 117 118 template<class CTYPE> 119 bool Url<CTYPE>::get_attribute(const string& name, string* value) const { 120 if (query_.empty()) 121 return false; 122 123 std::string::size_type pos = query_.find(name, 1); 124 if (std::string::npos == pos) 125 return false; 126 127 pos += name.length() + 1; 128 if ((pos > query_.length()) || (static_cast<CTYPE>('=') != query_[pos-1])) 129 return false; 130 131 std::string::size_type end = query_.find(static_cast<CTYPE>('&'), pos); 132 if (std::string::npos == end) { 133 end = query_.length(); 134 } 135 value->assign(query_.substr(pos, end - pos)); 136 return true; 137 } 138 139 /////////////////////////////////////////////////////////////////////////////// 140 141 } // namespace talk_base 142 143 #endif // TALK_BASE_HTTPCOMMON_INL_H__ 144