1f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org/* 2f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * Copyright 2008 The WebRTC Project Authors. All rights reserved. 3f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * 4f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * Use of this source code is governed by a BSD-style license 5f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 6f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 7f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * in the file PATENTS. All contributing project authors may 8f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org */ 10f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 11f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/urlencode.h" 12f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 13f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/common.h" 14f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/stringutils.h" 15f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 16f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstatic int HexPairValue(const char * code) { 17f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org int value = 0; 181711104b8a1771d2879b73cee1debfe017a66c15henrike@webrtc.org for (const char * pch = code; pch < code + 2; ++pch) { 191711104b8a1771d2879b73cee1debfe017a66c15henrike@webrtc.org value <<= 4; 201711104b8a1771d2879b73cee1debfe017a66c15henrike@webrtc.org int digit = *pch; 21f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org if (digit >= '0' && digit <= '9') { 22f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org value += digit - '0'; 23f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 24f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org else if (digit >= 'A' && digit <= 'F') { 25f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org value += digit - 'A' + 10; 26f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 27f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org else if (digit >= 'a' && digit <= 'f') { 28f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org value += digit - 'a' + 10; 29f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 30f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org else { 31f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return -1; 32f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 33f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 341711104b8a1771d2879b73cee1debfe017a66c15henrike@webrtc.org return value; 35f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 36f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 37c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.orgstatic int InternalUrlDecode(const char *source, char *dest, 38c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org bool encode_space_as_plus) { 39f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org char * start = dest; 40f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 41f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org while (*source) { 42f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org switch (*source) { 43f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org case '+': 44f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org if (encode_space_as_plus) { 45f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *(dest++) = ' '; 46f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } else { 47f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *dest++ = *source; 48f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 49f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org break; 50f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org case '%': 51f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org if (source[1] && source[2]) { 52f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org int value = HexPairValue(source + 1); 53f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org if (value >= 0) { 541711104b8a1771d2879b73cee1debfe017a66c15henrike@webrtc.org *(dest++) = static_cast<char>(value); 55f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org source += 2; 56f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 57f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org else { 58f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *dest++ = '?'; 59f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 60f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 61f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org else { 62f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *dest++ = '?'; 63f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 64f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org break; 65f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org default: 66f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *dest++ = *source; 67f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 68f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org source++; 69f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 70f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 71f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *dest = 0; 72f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return static_cast<int>(dest - start); 73f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 74f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 75c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.orgstatic bool IsValidUrlChar(char ch, bool unsafe_only) { 76c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org if (unsafe_only) { 77c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org return !(ch <= ' ' || strchr("\\\"^&`<>[]{}", ch)); 78c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org } else { 79c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org return isalnum(ch) || strchr("-_.!~*'()", ch); 80c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org } 81c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org} 82c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org 83c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.orgnamespace rtc { 84c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org 85f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint UrlDecode(const char *source, char *dest) { 86f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return InternalUrlDecode(source, dest, true); 87f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 88f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 89f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint UrlDecodeWithoutEncodingSpaceAsPlus(const char *source, char *dest) { 90f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return InternalUrlDecode(source, dest, false); 91f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 92f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 93f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint InternalUrlEncode(const char *source, char *dest, unsigned int max, 94f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org bool encode_space_as_plus, bool unsafe_only) { 95f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org static const char *digits = "0123456789ABCDEF"; 96f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org if (max == 0) { 97f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return 0; 98f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 99f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 100f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org char *start = dest; 101f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org while (static_cast<unsigned>(dest - start) < max && *source) { 102f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org unsigned char ch = static_cast<unsigned char>(*source); 103f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org if (*source == ' ' && encode_space_as_plus && !unsafe_only) { 104f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *dest++ = '+'; 105f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } else if (IsValidUrlChar(ch, unsafe_only)) { 106f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *dest++ = *source; 107f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } else { 108f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org if (static_cast<unsigned>(dest - start) + 4 > max) { 109f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org break; 110f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 111f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *dest++ = '%'; 112f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *dest++ = digits[(ch >> 4) & 0x0F]; 113f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *dest++ = digits[ ch & 0x0F]; 114f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 115f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org source++; 116f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org } 117f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org ASSERT(static_cast<unsigned int>(dest - start) < max); 118f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *dest = 0; 119f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 120f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return static_cast<int>(dest - start); 121f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 122f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 123f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint UrlEncode(const char *source, char *dest, unsigned max) { 124f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return InternalUrlEncode(source, dest, max, true, false); 125f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 126f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 127f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint UrlEncodeWithoutEncodingSpaceAsPlus(const char *source, char *dest, 128f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org unsigned max) { 129f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return InternalUrlEncode(source, dest, max, false, false); 130f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 131f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 132f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint UrlEncodeOnlyUnsafeChars(const char *source, char *dest, unsigned max) { 133f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return InternalUrlEncode(source, dest, max, false, true); 134f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 135f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 136f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstd::string 137f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgInternalUrlDecodeString(const std::string & encoded, 138f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org bool encode_space_as_plus) { 139f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org size_t needed_length = encoded.length() + 1; 140f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org char* buf = STACK_ARRAY(char, needed_length); 141f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org InternalUrlDecode(encoded.c_str(), buf, encode_space_as_plus); 142f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return buf; 143f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 144f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 145f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstd::string 146f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgUrlDecodeString(const std::string & encoded) { 147f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return InternalUrlDecodeString(encoded, true); 148f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 149f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 150f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstd::string 151f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgUrlDecodeStringWithoutEncodingSpaceAsPlus(const std::string & encoded) { 152f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return InternalUrlDecodeString(encoded, false); 153f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 154f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 155f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstd::string 156f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgInternalUrlEncodeString(const std::string & decoded, 157f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org bool encode_space_as_plus, 158f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org bool unsafe_only) { 159f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org int needed_length = static_cast<int>(decoded.length()) * 3 + 1; 160f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org char* buf = STACK_ARRAY(char, needed_length); 161f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org InternalUrlEncode(decoded.c_str(), buf, needed_length, 162f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org encode_space_as_plus, unsafe_only); 163f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return buf; 164f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 165f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 166f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstd::string 167f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgUrlEncodeString(const std::string & decoded) { 168f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return InternalUrlEncodeString(decoded, true, false); 169f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 170f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 171f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstd::string 172f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgUrlEncodeStringWithoutEncodingSpaceAsPlus(const std::string & decoded) { 173f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return InternalUrlEncodeString(decoded, false, false); 174f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 175f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 176f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstd::string 177f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgUrlEncodeStringForOnlyUnsafeChars(const std::string & decoded) { 178f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org return InternalUrlEncodeString(decoded, false, true); 179f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 180c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org 181c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org} // namespace rtc 182