|  | /* | 
|  | *  Copyright 2004 The WebRTC Project Authors. All rights reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #ifndef RTC_BASE_HTTPCOMMON_INL_H_ | 
|  | #define RTC_BASE_HTTPCOMMON_INL_H_ | 
|  |  | 
|  | #include "rtc_base/arraysize.h" | 
|  | #include "rtc_base/checks.h" | 
|  | #include "rtc_base/httpcommon.h" | 
|  |  | 
|  | namespace rtc { | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  | // Url | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | template<class CTYPE> | 
|  | void Url<CTYPE>::do_set_url(const CTYPE* val, size_t len) { | 
|  | if (ascnicmp(val, "http://", 7) == 0) { | 
|  | val += 7; len -= 7; | 
|  | secure_ = false; | 
|  | } else if (ascnicmp(val, "https://", 8) == 0) { | 
|  | val += 8; len -= 8; | 
|  | secure_ = true; | 
|  | } else { | 
|  | clear(); | 
|  | return; | 
|  | } | 
|  | const CTYPE* path = strchrn(val, len, static_cast<CTYPE>('/')); | 
|  | if (!path) { | 
|  | path = val + len; | 
|  | } | 
|  | size_t address_length = (path - val); | 
|  | do_set_address(val, address_length); | 
|  | do_set_full_path(path, len - address_length); | 
|  | } | 
|  |  | 
|  | template<class CTYPE> | 
|  | void Url<CTYPE>::do_set_address(const CTYPE* val, size_t len) { | 
|  | if (const CTYPE* at = strchrn(val, len, static_cast<CTYPE>('@'))) { | 
|  | // Everything before the @ is a user:password combo, so skip it. | 
|  | len -= at - val + 1; | 
|  | val = at + 1; | 
|  | } | 
|  | if (const CTYPE* colon = strchrn(val, len, static_cast<CTYPE>(':'))) { | 
|  | host_.assign(val, colon - val); | 
|  | // Note: In every case, we're guaranteed that colon is followed by a null, | 
|  | // or non-numeric character. | 
|  | port_ = static_cast<uint16_t>(::strtoul(colon + 1, nullptr, 10)); | 
|  | // TODO: Consider checking for invalid data following port number. | 
|  | } else { | 
|  | host_.assign(val, len); | 
|  | port_ = HttpDefaultPort(secure_); | 
|  | } | 
|  | } | 
|  |  | 
|  | template<class CTYPE> | 
|  | void Url<CTYPE>::do_set_full_path(const CTYPE* val, size_t len) { | 
|  | const CTYPE* query = strchrn(val, len, static_cast<CTYPE>('?')); | 
|  | if (!query) { | 
|  | query = val + len; | 
|  | } | 
|  | size_t path_length = (query - val); | 
|  | if (0 == path_length) { | 
|  | // TODO: consider failing in this case. | 
|  | path_.assign(1, static_cast<CTYPE>('/')); | 
|  | } else { | 
|  | RTC_DCHECK(val[0] == static_cast<CTYPE>('/')); | 
|  | path_.assign(val, path_length); | 
|  | } | 
|  | query_.assign(query, len - path_length); | 
|  | } | 
|  |  | 
|  | template<class CTYPE> | 
|  | void Url<CTYPE>::do_get_url(string* val) const { | 
|  | CTYPE protocol[9]; | 
|  | asccpyn(protocol, arraysize(protocol), secure_ ? "https://" : "http://"); | 
|  | val->append(protocol); | 
|  | do_get_address(val); | 
|  | do_get_full_path(val); | 
|  | } | 
|  |  | 
|  | template<class CTYPE> | 
|  | void Url<CTYPE>::do_get_address(string* val) const { | 
|  | val->append(host_); | 
|  | if (port_ != HttpDefaultPort(secure_)) { | 
|  | CTYPE format[5], port[32]; | 
|  | asccpyn(format, arraysize(format), ":%hu"); | 
|  | sprintfn(port, arraysize(port), format, port_); | 
|  | val->append(port); | 
|  | } | 
|  | } | 
|  |  | 
|  | template<class CTYPE> | 
|  | void Url<CTYPE>::do_get_full_path(string* val) const { | 
|  | val->append(path_); | 
|  | val->append(query_); | 
|  | } | 
|  |  | 
|  | template<class CTYPE> | 
|  | bool Url<CTYPE>::get_attribute(const string& name, string* value) const { | 
|  | if (query_.empty()) | 
|  | return false; | 
|  |  | 
|  | std::string::size_type pos = query_.find(name, 1); | 
|  | if (std::string::npos == pos) | 
|  | return false; | 
|  |  | 
|  | pos += name.length() + 1; | 
|  | if ((pos > query_.length()) || (static_cast<CTYPE>('=') != query_[pos-1])) | 
|  | return false; | 
|  |  | 
|  | std::string::size_type end = query_.find(static_cast<CTYPE>('&'), pos); | 
|  | if (std::string::npos == end) { | 
|  | end = query_.length(); | 
|  | } | 
|  | value->assign(query_.substr(pos, end - pos)); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | }  // namespace rtc | 
|  |  | 
|  | #endif  // RTC_BASE_HTTPCOMMON_INL_H_ |