LCOV - code coverage report
Current view: top level - src - base64.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 45 49 91.8 %
Date: 2024-04-29 14:43:01 Functions: 2 2 100.0 %

          Line data    Source code
       1             : // base64 encodig and decoding.
       2             : //
       3             : // Based on the implementations by
       4             : // Jouni Malinen <j@w1.fi> and contributors from wpa_supplicant and hostapd in
       5             : // http://web.mit.edu/freebsd/head/contrib/wpa/ and
       6             : // http://web.mit.edu/freebsd/head/contrib/wpa/src/utils/base64.c and
       7             : // http://web.mit.edu/freebsd/head/contrib/wpa/src/utils/base64.h
       8             : //
       9             : // Published under a 3-clause BSD license
      10             : //
      11             : 
      12             : #include <string>
      13             : #include <cstring>
      14             : #include <stdexcept>
      15             : 
      16             : #include "crpropa/base64.h"
      17             : 
      18             : namespace crpropa
      19             : {
      20             : 
      21             : //Alphabet used
      22             : static const unsigned char encode_alphabet[65] =
      23             : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      24             : static int decode_alphabet[256] = {-1};
      25             : 
      26             : /// Encodes data
      27          99 : std::string Base64::encode(const unsigned char *src, size_t len)
      28             : {
      29          99 :                 size_t olen = 4*((len + 2) / 3); /* 3-byte blocks to 4-byte */
      30             : 
      31          99 :                 if (olen < len)
      32           0 :                         throw std::runtime_error("Integer overflow in Base64::encoding, data to large!");
      33             : 
      34             :                 std::string outStr;
      35             :                 outStr.resize(olen);
      36             : 
      37             :                 unsigned char *out = (unsigned char*) outStr.c_str();
      38             :                 unsigned char *pos = out;
      39             :                 const unsigned char *end, *in;
      40             : 
      41          99 :                 end = src + len;
      42             :                 in = src;
      43        6666 :                 while (end - in >= 3) {
      44        6567 :                                 *pos++ = encode_alphabet[in[0] >> 2];
      45        6567 :                                 *pos++ = encode_alphabet[((in[0] & 0x03) << 4) | (in[1] >> 4)];
      46        6567 :                                 *pos++ = encode_alphabet[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
      47        6567 :                                 *pos++ = encode_alphabet[in[2] & 0x3f];
      48        6567 :                                 in += 3;
      49             :                 }
      50             : 
      51          99 :                 if (end - in) {
      52          66 :                                 *pos++ = encode_alphabet[in[0] >> 2];
      53          66 :                                 if (end - in == 1) {
      54          33 :                                                 *pos++ = encode_alphabet[(in[0] & 0x03) << 4];
      55          33 :                                                 *pos++ = '=';
      56             :                                 }
      57             :                                 else {
      58          33 :                                                 *pos++ = encode_alphabet[((in[0] & 0x03) << 4) |
      59          33 :                                                                 (in[1] >> 4)];
      60          33 :                                                 *pos++ = encode_alphabet[(in[1] & 0x0f) << 2];
      61             :                                 }
      62          66 :                                 *pos++ = '=';
      63             :                 }
      64             : 
      65          99 :                 return outStr;
      66             : }
      67             : 
      68             : 
      69         100 : std::string Base64::decode(const std::string &data)
      70             : {
      71             : const unsigned char *src = (unsigned char*) data.c_str();
      72             : size_t len = data.size();
      73             : 
      74         100 : if (decode_alphabet[0] == -1)
      75             : { // build decode alphabet
      76             :         std::memset(decode_alphabet, 0x80, 256);
      77          65 :         for (size_t i = 0; i < sizeof(encode_alphabet) - 1; i++)
      78          64 :                 decode_alphabet[encode_alphabet[i]] = (unsigned char) i;
      79           1 :         decode_alphabet['='] = 0;
      80             : }
      81             : 
      82             : size_t olen = 0;
      83       26656 : for (size_t i = 0; i < len; i++) {
      84       26556 :         if (decode_alphabet[src[i]] != 0x80)
      85       26556 :                 olen++;
      86             : }
      87             : 
      88         100 : if (olen == 0 || olen % 4)
      89           0 :                         throw std::runtime_error("Base64 decode, invalid input size");
      90             : 
      91         100 : olen = olen / 4 * 3;
      92             : std::string str;
      93             : str.resize(olen);
      94             : 
      95             : unsigned char *out = (unsigned char*) str.c_str();
      96             : unsigned char *pos = out;
      97             : 
      98             : size_t count = 0;
      99             : int pad = 0;
     100             : unsigned char block[4];
     101       26589 : for (size_t i = 0; i < len; i++) {
     102       26556 :         unsigned char tmp = decode_alphabet[src[i]];
     103       26556 :         if (tmp == 0x80)
     104           0 :                 continue;
     105             : 
     106       26556 :         if (src[i] == '=')
     107         101 :                 pad++;
     108       26556 :         block[count] = tmp;
     109       26556 :         count++;
     110       26556 :         if (count == 4) {
     111        6639 :                 *pos++ = (block[0] << 2) | (block[1] >> 4);
     112        6639 :                 *pos++ = (block[1] << 4) | (block[2] >> 2);
     113        6639 :                 *pos++ = (block[2] << 6) | block[3];
     114             :                 count = 0;
     115        6639 :                 if (pad) {
     116          67 :                         if (pad == 1)
     117             :                                 pos--;
     118          34 :                         else if (pad == 2)
     119             :                                 pos -= 2;
     120             :                         else {
     121           0 :                                 throw std::runtime_error("Base64 decode, invalid padding");
     122             :                         }
     123             :                         break;
     124             :                 }
     125             :         }
     126             : }
     127         100 : return str;
     128             : }
     129             : };

Generated by: LCOV version 1.14