summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/Base64.cpp
blob: 6b4151935788bdb530976698e1fd5e13afe9cd4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 *  Copyright (C) 2011-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#include "Base64.h"

#define PADDING '='

const std::string Base64::m_characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                         "abcdefghijklmnopqrstuvwxyz"
                                         "0123456789+/";

void Base64::Encode(const char* input, unsigned int length, std::string &output)
{
  if (input == NULL || length == 0)
    return;

  long l;
  output.clear();
  output.reserve(((length + 2) / 3) * 4);

  for (unsigned int i = 0; i < length; i += 3)
  {
    l  = ((((unsigned long) input[i]) << 16) & 0xFFFFFF) |
         ((((i + 1) < length) ? (((unsigned long) input[i + 1]) << 8) : 0) & 0xFFFF) |
         ((((i + 2) < length) ? (((unsigned long) input[i + 2]) << 0) : 0) & 0x00FF);

    output.push_back(m_characters[(l >> 18) & 0x3F]);
    output.push_back(m_characters[(l >> 12) & 0x3F]);

    if (i + 1 < length)
      output.push_back(m_characters[(l >> 6) & 0x3F]);
    if (i + 2 < length)
      output.push_back(m_characters[(l >> 0) & 0x3F]);
  }

  int left = 3 - (length % 3);

  if (length % 3)
  {
    for (int i = 0; i < left; i++)
      output.push_back(PADDING);
  }
}

std::string Base64::Encode(const char* input, unsigned int length)
{
  std::string output;
  Encode(input, length, output);

  return output;
}

void Base64::Encode(const std::string &input, std::string &output)
{
  Encode(input.c_str(), input.size(), output);
}

std::string Base64::Encode(const std::string &input)
{
  std::string output;
  Encode(input, output);

  return output;
}

void Base64::Decode(const char* input, unsigned int length, std::string &output)
{
  if (input == NULL || length == 0)
    return;

  long l;
  output.clear();

  for (unsigned int index = 0; index < length; index++)
  {
    if (input[index] == '=')
    {
      length = index;
      break;
    }
  }

  output.reserve(length - ((length + 2) / 4));

  for (unsigned int i = 0; i < length; i += 4)
  {
    l = ((((unsigned long) m_characters.find(input[i])) & 0x3F) << 18);
    l |= (((i + 1) < length) ? ((((unsigned long) m_characters.find(input[i + 1])) & 0x3F) << 12) : 0);
    l |= (((i + 2) < length) ? ((((unsigned long) m_characters.find(input[i + 2])) & 0x3F) <<  6) : 0);
    l |= (((i + 3) < length) ? ((((unsigned long) m_characters.find(input[i + 3])) & 0x3F) <<  0) : 0);

    output.push_back((char)((l >> 16) & 0xFF));
    if (i + 2 < length)
      output.push_back((char)((l >> 8) & 0xFF));
    if (i + 3 < length)
      output.push_back((char)((l >> 0) & 0xFF));
  }
}

std::string Base64::Decode(const char* input, unsigned int length)
{
  std::string output;
  Decode(input, length, output);

  return output;
}

void Base64::Decode(const std::string &input, std::string &output)
{
  size_t length = input.find_first_of(PADDING);
  if (length == std::string::npos)
    length = input.size();

  Decode(input.c_str(), length, output);
}

std::string Base64::Decode(const std::string &input)
{
  std::string output;
  Decode(input, output);

  return output;
}