| /* | 
 |  *  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_ |