Example #1
0
utility::string_t uri::decode(const utility::string_t &encoded)
{
    std::string utf8raw;
    for(auto iter = encoded.begin(); iter != encoded.end(); ++iter)
    {
        if(*iter == _XPLATSTR('%'))
        {
            if(++iter == encoded.end())
            {
                throw uri_exception("Invalid URI string, two hexadecimal digits must follow '%'");
            }
            int decimal_value = hex_char_digit_to_decimal_char(static_cast<int>(*iter)) << 4;
            if(++iter == encoded.end())
            {
                throw uri_exception("Invalid URI string, two hexadecimal digits must follow '%'");
            }
            decimal_value += hex_char_digit_to_decimal_char(static_cast<int>(*iter));

            utf8raw.push_back(static_cast<char>(decimal_value));
        }
        else
        {
            // encoded string has to be ASCII.
            utf8raw.push_back(reinterpret_cast<const char &>(*iter));
        }
    }
    return to_string_t(utf8raw);
}
Example #2
0
std::vector<unsigned char> _from_base64(const utility::string_t& input)
{
    std::vector<unsigned char> result;

    if ( input.empty() ) 
        return result;

    size_t padding = 0;

    // Validation
    {
        auto size = input.size();

        if ( (size % 4) != 0 )
        {
            throw std::runtime_error("length of base64 string is not an even multiple of 4");
        }

        for (auto iter = input.begin(); iter != input.end(); ++iter,--size)
        {
            auto ch = *iter;
            if ( ch < 0 || _base64_dectbl[ch] == 255 )
            {
                throw std::runtime_error("invalid character found in base64 string");
            }
            if ( _base64_dectbl[ch] == 254 )
            {
                padding++;
                // padding only at the end
                if ( size > 2 || (size == 2 && _base64_dectbl[*(iter+1)] != 254) )
                {
                    throw std::runtime_error("invalid padding character found in base64 string");
                }
            }
        }
    }


    auto size = input.size();
    const char_t* ptr = &input[0];

    auto outsz = (size / 4)*3;
    outsz -= padding;

    result.resize(outsz);

    size_t idx = 0;
    for (; size > 4; ++idx )
    {
        unsigned char target[3];
        memset(target, 0, sizeof(target));
        _triple_byte* record = reinterpret_cast<_triple_byte*>(target);

        unsigned char val0 = _base64_dectbl[ptr[0]];
        unsigned char val1 = _base64_dectbl[ptr[1]];
        unsigned char val2 = _base64_dectbl[ptr[2]];
        unsigned char val3 = _base64_dectbl[ptr[3]];

        record->_0   = val0;
        record->_1_1 = val1 >> 4;
        result[idx] = target[0];

        record->_1_2 = val1 & 0xF;
        record->_2_1 = val2 >> 2;
        result[++idx] = target[1];

        record->_2_2 = val2 & 0x3;
        record->_3   = val3 & 0x3F;
        result[++idx] = target[2];

        ptr += 4;
        size -= 4;
    }

    // Handle the last four bytes separately, to avoid having the conditional statements
    // in all the iterations (a performance issue).

    { 
        unsigned char target[3];
        memset(target, 0, sizeof(target));
        _triple_byte* record = reinterpret_cast<_triple_byte*>(target);

        unsigned char val0 = _base64_dectbl[ptr[0]];
        unsigned char val1 = _base64_dectbl[ptr[1]];
        unsigned char val2 = _base64_dectbl[ptr[2]];
        unsigned char val3 = _base64_dectbl[ptr[3]];

        record->_0   = val0;
        record->_1_1 = val1 >> 4;
        result[idx] = target[0];

        record->_1_2 = val1 & 0xF;
        if ( val2 != 254 )
        {
            record->_2_1 = val2 >> 2;
            result[++idx] = target[1];
        }
        else
        {
            // There shouldn't be any information (ones) in the unused bits,
            if ( record->_1_2 != 0 )