Tizen 2.1 base
[framework/web/wrt-commons.git] / modules / vcore / src / vcore / Base64.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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 #include <algorithm>
17 #include <string>
18 #include <string.h>
19 #include <openssl/bio.h>
20 #include <openssl/evp.h>
21 #include <openssl/buffer.h>
22
23 #include <dpl/log/log.h>
24 #include <dpl/scoped_free.h>
25
26 #include "Base64.h"
27
28 namespace ValidationCore {
29 Base64Encoder::Base64Encoder() :
30     m_b64(0),
31     m_bmem(0),
32     m_finalized(false)
33 {
34 }
35
36 void Base64Encoder::append(const std::string &data)
37 {
38     if (m_finalized) {
39         LogWarning("Already finalized.");
40         ThrowMsg(Exception::AlreadyFinalized, "Already finalized");
41     }
42
43     if (!m_b64) {
44         reset();
45     }
46     BIO_write(m_b64, data.c_str(), data.size());
47 }
48
49 void Base64Encoder::finalize()
50 {
51     if (m_finalized) {
52         LogWarning("Already finalized.");
53         ThrowMsg(Exception::AlreadyFinalized, "Already finalized.");
54     }
55     m_finalized = true;
56     BIO_flush(m_b64);
57 }
58
59 std::string Base64Encoder::get()
60 {
61     if (!m_finalized) {
62         LogWarning("Not finalized");
63         ThrowMsg(Exception::NotFinalized, "Not finalized");
64     }
65     BUF_MEM *bptr = 0;
66     BIO_get_mem_ptr(m_b64, &bptr);
67     if (bptr == 0) {
68         LogError("Bio internal error");
69         ThrowMsg(Exception::InternalError, "Bio internal error");
70     }
71
72     if (bptr->length > 0) {
73         return std::string(bptr->data, bptr->length - 1);
74     }
75     return std::string();
76 }
77
78 void Base64Encoder::reset()
79 {
80     m_finalized = false;
81     BIO_free_all(m_b64);
82     m_b64 = BIO_new(BIO_f_base64());
83     m_bmem = BIO_new(BIO_s_mem());
84     if (!m_b64 || !m_bmem) {
85         LogError("Error during allocation memory in BIO");
86         ThrowMsg(Exception::InternalError,
87                  "Error during allocation memory in BIO");
88     }
89     m_b64 = BIO_push(m_b64, m_bmem);
90 }
91
92 Base64Encoder::~Base64Encoder()
93 {
94     BIO_free_all(m_b64);
95 }
96
97 Base64Decoder::Base64Decoder() :
98     m_finalized(false)
99 {
100 }
101
102 void Base64Decoder::append(const std::string &data)
103 {
104     if (m_finalized) {
105         LogWarning("Already finalized.");
106         ThrowMsg(Exception::AlreadyFinalized, "Already finalized.");
107     }
108     m_input.append(data);
109 }
110
111 static bool whiteCharacter(char a)
112 {
113     if (a == '\n') { return true; }
114     return false;
115 }
116
117 bool Base64Decoder::finalize()
118 {
119     if (m_finalized) {
120         LogWarning("Already finalized.");
121         ThrowMsg(Exception::AlreadyFinalized, "Already finalized.");
122     }
123
124     m_finalized = true;
125
126     m_input.erase(std::remove_if(m_input.begin(),
127                                  m_input.end(),
128                                  whiteCharacter),
129                   m_input.end());
130
131     for (size_t i = 0; i<m_input.size(); ++i) {
132         if (isalnum(m_input[i])
133             || m_input[i] == '+'
134             || m_input[i] == '/'
135             || m_input[i] == '=')
136         {
137             continue;
138         }
139         LogError("Base64 input contains illegal chars: " << m_input[i]);
140         return false;
141     }
142
143     BIO *b64, *bmem;
144     size_t len = m_input.size();
145
146     DPL::ScopedFree<char> buffer(static_cast<char*>(malloc(len)));
147
148     if (!buffer) {
149         LogError("Error in malloc.");
150         ThrowMsg(Exception::InternalError, "Error in malloc.");
151     }
152
153     memset(buffer.Get(), 0, len);
154     b64 = BIO_new(BIO_f_base64());
155     if (!b64) {
156         LogError("Couldn't create BIO object.");
157         ThrowMsg(Exception::InternalError, "Couldn't create BIO object.");
158     }
159     BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
160     DPL::ScopedFree<char> tmp(strdup(m_input.c_str()));
161     m_input.clear();
162
163     bmem = BIO_new_mem_buf(tmp.Get(), len);
164
165     if (!bmem) {
166         BIO_free(b64);
167         LogError("Internal error in BIO");
168         ThrowMsg(Exception::InternalError, "Internal error in BIO");
169     }
170
171     bmem = BIO_push(b64, bmem);
172
173     if (!bmem) {
174         BIO_free(b64);
175         LogError("Internal error in BIO");
176         ThrowMsg(Exception::InternalError, "Internal error in BIO");
177     }
178
179     int readlen = BIO_read(bmem, buffer.Get(), len);
180     m_output.clear();
181
182     bool status = true;
183
184     if (readlen > 0) {
185         m_output.append(buffer.Get(), readlen);
186     } else {
187         status = false;
188     }
189
190     BIO_free_all(bmem);
191     return status;
192 }
193
194 std::string Base64Decoder::get() const
195 {
196     if (!m_finalized) {
197         LogWarning("Not finalized.");
198         ThrowMsg(Exception::NotFinalized, "Not finalized");
199     }
200     return m_output;
201 }
202
203 void Base64Decoder::reset()
204 {
205     m_finalized = false;
206     m_input.clear();
207     m_output.clear();
208 }
209 } // namespace ValidationCore