1 /*
2  * Copyright (C) 2016 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 /*
18    base64.cpp and base64.h
19 
20    Copyright (C) 2004-2008 René Nyffenegger
21 
22    This source code is provided 'as-is', without any express or implied
23    warranty. In no event will the author be held liable for any damages
24    arising from the use of this software.
25 
26    Permission is granted to anyone to use this software for any purpose,
27    including commercial applications, and to alter it and redistribute it
28    freely, subject to the following restrictions:
29 
30    1. The origin of this source code must not be misrepresented; you must not
31    claim that you wrote the original source code. If you use this source code
32    in a product, an acknowledgment in the product documentation would be
33    appreciated but is not required.
34 
35    2. Altered source versions must be plainly marked as such, and must not be
36    misrepresented as being the original source code.
37 
38    3. This notice may not be removed or altered from any source distribution.
39 
40    René Nyffenegger rene.nyffenegger@adp-gmbh.ch
41 */
42 #include "ignition/common/Base64.hh"
43 #include <algorithm>
44 #include <cstring>
45 #include <iostream>
46 
47 using namespace ignition;
48 using namespace common;
49 
50 static const char base64Chars[] =
51 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
52 "abcdefghijklmnopqrstuvwxyz"
53 "0123456789+/";
54 
55 /////////////////////////////////////////////////
IsBase64(unsigned char _c)56 static inline bool IsBase64(unsigned char _c)
57 {
58   return (isalnum(_c) || (_c == '+') || (_c == '/'));
59 }
60 
61 /////////////////////////////////////////////////
Encode(const char * _bytesToEncode,unsigned int _inLen,std::string & _result)62 void Base64::Encode(const char *_bytesToEncode, unsigned int _inLen,
63                     std::string &_result)
64 {
65   int i = 0;
66   unsigned char charArray3[3];
67   unsigned char charArray4[4];
68 
69   while (_inLen--)
70   {
71     charArray3[i++] = *(_bytesToEncode++);
72     if (i == 3)
73     {
74       charArray4[0] = (charArray3[0] & 0xfc) >> 2;
75       charArray4[1] = ((charArray3[0] & 0x03) << 4) +
76         ((charArray3[1] & 0xf0) >> 4);
77       charArray4[2] = ((charArray3[1] & 0x0f) << 2) +
78         ((charArray3[2] & 0xc0) >> 6);
79       charArray4[3] = charArray3[2] & 0x3f;
80 
81       for (i = 0; i < 4; ++i)
82         _result += base64Chars[charArray4[i]];
83       i = 0;
84     }
85   }
86 
87   if (i)
88   {
89     for (int j = i; j < 3; ++j)
90       charArray3[j] = '\0';
91 
92     charArray4[0] = (charArray3[0] & 0xfc) >> 2;
93     charArray4[1] = ((charArray3[0] & 0x03) << 4) +
94       ((charArray3[1] & 0xf0) >> 4);
95     charArray4[2] = ((charArray3[1] & 0x0f) << 2) +
96       ((charArray3[2] & 0xc0) >> 6);
97     charArray4[3] = charArray3[2] & 0x3f;
98 
99     for (int j = 0; (j < i + 1); ++j)
100       _result += base64Chars[charArray4[j]];
101 
102     while ((i++ < 3))
103       _result += '=';
104   }
105 }
106 
107 /////////////////////////////////////////////////
Decode(const std::string & _encodedString)108 std::string Base64::Decode(const std::string &_encodedString)
109 {
110   int inLen = _encodedString.size();
111   int i = 0;
112   int in = 0;
113   unsigned char charArray4[4], charArray3[3];
114   std::string ret;
115 
116   while (inLen-- && (_encodedString[in] != '=') &&
117       IsBase64(_encodedString[in]))
118   {
119     charArray4[i++] = _encodedString[in];
120     in++;
121 
122     if (i == 4)
123     {
124       for (i = 0; i < 4; ++i)
125       {
126         const char *match = std::find(base64Chars,
127             base64Chars + std::strlen(base64Chars),
128             static_cast<char>(charArray4[i]));
129 
130         charArray4[i] = match - base64Chars;
131       }
132 
133       charArray3[0] = (charArray4[0] << 2) +
134         ((charArray4[1] & 0x30) >> 4);
135       charArray3[1] = ((charArray4[1] & 0xf) << 4) +
136         ((charArray4[2] & 0x3c) >> 2);
137       charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3];
138 
139       for (i = 0; (i < 3); ++i)
140         ret += charArray3[i];
141       i = 0;
142     }
143   }
144 
145   if (i)
146   {
147     for (int j = i; j < 4; ++j)
148       charArray4[j] = 0;
149 
150     for (int j = 0; j < 4; ++j)
151     {
152       const char *match = std::find(base64Chars,
153           base64Chars + std::strlen(base64Chars),
154           static_cast<char>(charArray4[j]));
155 
156       charArray4[j] = match - base64Chars;
157     }
158 
159     charArray3[0] = (charArray4[0] << 2) + ((charArray4[1] & 0x30) >> 4);
160     charArray3[1] = ((charArray4[1] & 0xf) << 4) +
161       ((charArray4[2] & 0x3c) >> 2);
162     charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3];
163 
164     for (int j = 0; (j < i - 1); ++j)
165       ret += charArray3[j];
166   }
167 
168   return ret;
169 }
170