1 | /*␊ |
2 | Copyright (c) 2021, Grégory Soutadé␊ |
3 | ␊ |
4 | All rights reserved.␊ |
5 | Redistribution and use in source and binary forms, with or without␊ |
6 | modification, are permitted provided that the following conditions are met:␊ |
7 | ␊ |
8 | * Redistributions of source code must retain the above copyright␊ |
9 | notice, this list of conditions and the following disclaimer.␊ |
10 | * Redistributions in binary form must reproduce the above copyright␊ |
11 | notice, this list of conditions and the following disclaimer in the␊ |
12 | documentation and/or other materials provided with the distribution.␊ |
13 | * Neither the name of the copyright holder nor the␊ |
14 | names of its contributors may be used to endorse or promote products␊ |
15 | derived from this software without specific prior written permission.␊ |
16 | ␊ |
17 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY␊ |
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED␊ |
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE␊ |
20 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY␊ |
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES␊ |
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;␊ |
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND␊ |
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT␊ |
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS␊ |
26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.␊ |
27 | */␊ |
28 | ␊ |
29 | #include <openssl/rand.h>␊ |
30 | #include <openssl/pkcs12.h>␊ |
31 | #include <openssl/evp.h>␊ |
32 | #include <openssl/err.h>␊ |
33 | ␊ |
34 | #include <QCoreApplication>␊ |
35 | #include <QNetworkReply>␊ |
36 | #include <QNetworkRequest>␊ |
37 | #include <QNetworkAccessManager>␊ |
38 | #include <QFile>␊ |
39 | ␊ |
40 | #include <zip.h>␊ |
41 | #include <zlib.h>␊ |
42 | ␊ |
43 | #include <libgourou_common.h>␊ |
44 | #include <libgourou_log.h>␊ |
45 | #include "drmprocessorclientimpl.h"␊ |
46 | ␊ |
47 | /* Digest interface */␊ |
48 | void* DRMProcessorClientImpl::createDigest(const std::string& digestName)␊ |
49 | {␊ |
50 | EVP_MD_CTX *sha_ctx = EVP_MD_CTX_new();␊ |
51 | const EVP_MD* md = EVP_get_digestbyname(digestName.c_str());␊ |
52 | EVP_DigestInit(sha_ctx, md);␊ |
53 | ␊ |
54 | return sha_ctx;␊ |
55 | }␊ |
56 | ␊ |
57 | int DRMProcessorClientImpl::digestUpdate(void* handler, unsigned char* data, unsigned int length)␊ |
58 | {␊ |
59 | return EVP_DigestUpdate((EVP_MD_CTX *)handler, data, length);␊ |
60 | }␊ |
61 | ␊ |
62 | int DRMProcessorClientImpl::digestFinalize(void* handler, unsigned char* digestOut)␊ |
63 | {␊ |
64 | int res = EVP_DigestFinal((EVP_MD_CTX *)handler, digestOut, NULL);␊ |
65 | EVP_MD_CTX_free((EVP_MD_CTX *)handler);␊ |
66 | return res;␊ |
67 | }␊ |
68 | ␊ |
69 | int DRMProcessorClientImpl::digest(const std::string& digestName, unsigned char* data, unsigned int length, unsigned char* digestOut)␊ |
70 | {␊ |
71 | void* handler = createDigest(digestName);␊ |
72 | if (!handler)␊ |
73 | ␉return -1;␊ |
74 | if (digestUpdate(handler, data, length))␊ |
75 | ␉return -1;␊ |
76 | return digestFinalize(handler, digestOut);␊ |
77 | }␊ |
78 | ␊ |
79 | /* Random interface */␊ |
80 | void DRMProcessorClientImpl::randBytes(unsigned char* bytesOut, unsigned int length)␊ |
81 | {␊ |
82 | RAND_bytes(bytesOut, length);␊ |
83 | }␊ |
84 | ␊ |
85 | /* HTTP interface */␊ |
86 | std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, const std::string& POSTData, const std::string& contentType, std::map<std::string, std::string>* responseHeaders)␊ |
87 | {␊ |
88 | QNetworkRequest request(QUrl(URL.c_str()));␊ |
89 | QNetworkAccessManager networkManager;␊ |
90 | QByteArray replyData;␊ |
91 | ␊ |
92 | GOUROU_LOG(gourou::INFO, "Send request to " << URL);␊ |
93 | if (POSTData.size())␊ |
94 | {␊ |
95 | ␉GOUROU_LOG(gourou::DEBUG, "<<< " << std::endl << POSTData);␊ |
96 | }␊ |
97 | ␉␊ |
98 | request.setRawHeader("Accept", "*/*");␊ |
99 | request.setRawHeader("User-Agent", "book2png");␊ |
100 | if (contentType.size())␊ |
101 | ␉request.setRawHeader("Content-Type", contentType.c_str());␊ |
102 | ␊ |
103 | QNetworkReply* reply;␊ |
104 | ␊ |
105 | if (POSTData.size())␊ |
106 | ␉reply = networkManager.post(request, POSTData.c_str());␊ |
107 | else␊ |
108 | ␉reply = networkManager.get(request);␊ |
109 | ␊ |
110 | QCoreApplication* app = QCoreApplication::instance();␊ |
111 | networkManager.moveToThread(app->thread());␊ |
112 | while (!reply->isFinished())␊ |
113 | ␉app->processEvents();␊ |
114 | ␊ |
115 | QByteArray location = reply->rawHeader("Location");␊ |
116 | if (location.size() != 0)␊ |
117 | {␊ |
118 | ␉GOUROU_LOG(gourou::DEBUG, "New location");␊ |
119 | ␉return sendHTTPRequest(location.constData(), POSTData, contentType);␊ |
120 | }␊ |
121 | ␊ |
122 | if (reply->error() != QNetworkReply::NoError)␊ |
123 | ␉EXCEPTION(gourou::CLIENT_NETWORK_ERROR, "Error " << reply->errorString().toStdString());␊ |
124 | ␊ |
125 | QList<QByteArray> headers = reply->rawHeaderList();␊ |
126 | for (int i = 0; i < headers.size(); ++i) {␊ |
127 | ␉if (gourou::logLevel >= gourou::DEBUG)␊ |
128 | ␉ std::cout << headers[i].constData() << " : " << reply->rawHeader(headers[i]).constData() << std::endl;␊ |
129 | ␉if (responseHeaders)␊ |
130 | ␉ (*responseHeaders)[headers[i].constData()] = reply->rawHeader(headers[i]).constData();␊ |
131 | }␊ |
132 | ␊ |
133 | replyData = reply->readAll();␊ |
134 | if (reply->rawHeader("Content-Type") == "application/vnd.adobe.adept+xml")␊ |
135 | {␊ |
136 | ␉GOUROU_LOG(gourou::DEBUG, ">>> " << std::endl << replyData.data());␊ |
137 | }␊ |
138 | ␉␊ |
139 | return std::string(replyData.data(), replyData.length());␊ |
140 | }␊ |
141 | ␊ |
142 | void DRMProcessorClientImpl::RSAPrivateEncrypt(const unsigned char* RSAKey, unsigned int RSAKeyLength,␊ |
143 | ␉␉␉␉␉ const RSA_KEY_TYPE keyType, const std::string& password,␊ |
144 | ␉␉␉␉␉ const unsigned char* data, unsigned dataLength,␊ |
145 | ␉␉␉␉␉ unsigned char* res)␊ |
146 | {␊ |
147 | PKCS12 * pkcs12;␊ |
148 | EVP_PKEY* pkey;␊ |
149 | X509* cert;␊ |
150 | STACK_OF(X509)* ca;␊ |
151 | RSA * rsa;␊ |
152 | ␊ |
153 | pkcs12 = d2i_PKCS12(NULL, &RSAKey, RSAKeyLength);␊ |
154 | if (!pkcs12)␊ |
155 | ␉EXCEPTION(gourou::CLIENT_INVALID_PKCS12, ERR_error_string(ERR_get_error(), NULL));␊ |
156 | PKCS12_parse(pkcs12, password.c_str(), &pkey, &cert, &ca);␊ |
157 | rsa = EVP_PKEY_get1_RSA(pkey);␊ |
158 | ␊ |
159 | int ret = RSA_private_encrypt(dataLength, data, res, rsa, RSA_PKCS1_PADDING);␊ |
160 | ␊ |
161 | if (ret < 0)␊ |
162 | ␉EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL));␊ |
163 | ␊ |
164 | if (gourou::logLevel >= gourou::DEBUG)␊ |
165 | {␊ |
166 | ␉printf("Sig : ");␊ |
167 | ␉for(int i=0; i<(int)sizeof(res); i++)␊ |
168 | ␉ printf("%02x ", res[i]);␊ |
169 | ␉printf("\n");␊ |
170 | }␊ |
171 | }␊ |
172 | ␉␉␉ ␊ |
173 | void DRMProcessorClientImpl::RSAPublicEncrypt(const unsigned char* RSAKey, unsigned int RSAKeyLength,␊ |
174 | ␉␉␉␉␉ const RSA_KEY_TYPE keyType,␊ |
175 | ␉␉␉␉␉ const unsigned char* data, unsigned dataLength,␊ |
176 | ␉␉␉␉␉ unsigned char* res)␊ |
177 | {␊ |
178 | X509 * x509 = d2i_X509(0, &RSAKey, RSAKeyLength);␊ |
179 | if (!x509)␊ |
180 | ␉EXCEPTION(gourou::CLIENT_INVALID_CERTIFICATE, "Invalid certificate");␊ |
181 | ␉␊ |
182 | EVP_PKEY * evpKey = X509_get_pubkey(x509);␊ |
183 | RSA* rsa = EVP_PKEY_get1_RSA(evpKey);␊ |
184 | EVP_PKEY_free(evpKey);␊ |
185 | ␊ |
186 | if (!rsa)␊ |
187 | ␉EXCEPTION(gourou::CLIENT_NO_PRIV_KEY, "No private key in certificate");␊ |
188 | ␊ |
189 | int ret = RSA_public_encrypt(dataLength, data, res, rsa, RSA_PKCS1_PADDING);␊ |
190 | if (ret < 0)␊ |
191 | ␉EXCEPTION(gourou::CLIENT_RSA_ERROR, ERR_error_string(ERR_get_error(), NULL));␊ |
192 | }␊ |
193 | ␊ |
194 | void* DRMProcessorClientImpl::generateRSAKey(int keyLengthBits)␊ |
195 | {␊ |
196 | BIGNUM * bn = BN_new();␊ |
197 | RSA * rsa = RSA_new();␊ |
198 | BN_set_word(bn, 0x10001);␊ |
199 | RSA_generate_key_ex(rsa, keyLengthBits, bn, 0);␊ |
200 | BN_free(bn);␊ |
201 | ␊ |
202 | return rsa;␊ |
203 | }␊ |
204 | ␊ |
205 | void DRMProcessorClientImpl::destroyRSAHandler(void* handler)␊ |
206 | {␊ |
207 | RSA_free((RSA*)handler);␊ |
208 | }␊ |
209 | ␊ |
210 | void DRMProcessorClientImpl::extractRSAPublicKey(void* handler, unsigned char** keyOut, unsigned int* keyOutLength)␊ |
211 | {␊ |
212 | EVP_PKEY * evpKey = EVP_PKEY_new();␊ |
213 | EVP_PKEY_set1_RSA(evpKey, (RSA*)handler);␊ |
214 | X509_PUBKEY *x509_pubkey = 0;␊ |
215 | X509_PUBKEY_set(&x509_pubkey, evpKey);␊ |
216 | ␊ |
217 | *keyOutLength = i2d_X509_PUBKEY(x509_pubkey, keyOut);␊ |
218 | ␊ |
219 | X509_PUBKEY_free(x509_pubkey);␊ |
220 | EVP_PKEY_free(evpKey);␊ |
221 | }␊ |
222 | ␊ |
223 | void DRMProcessorClientImpl::extractRSAPrivateKey(void* handler, unsigned char** keyOut, unsigned int* keyOutLength)␊ |
224 | {␊ |
225 | EVP_PKEY * evpKey = EVP_PKEY_new();␊ |
226 | EVP_PKEY_set1_RSA(evpKey, (RSA*)handler);␊ |
227 | PKCS8_PRIV_KEY_INFO * privKey = EVP_PKEY2PKCS8(evpKey);␊ |
228 | ␊ |
229 | *keyOutLength = i2d_PKCS8_PRIV_KEY_INFO(privKey, keyOut);␊ |
230 | ␊ |
231 | PKCS8_PRIV_KEY_INFO_free(privKey);␊ |
232 | EVP_PKEY_free(evpKey);␊ |
233 | }␊ |
234 | ␉␉␉␉ ␊ |
235 | void DRMProcessorClientImpl::extractCertificate(const unsigned char* RSAKey, unsigned int RSAKeyLength,␊ |
236 | ␉␉␉␉␉␉const RSA_KEY_TYPE keyType, const std::string& password,␊ |
237 | ␉␉␉␉␉␉unsigned char** certOut, unsigned int* certOutLength)␊ |
238 | {␊ |
239 | PKCS12 * pkcs12;␊ |
240 | EVP_PKEY* pkey = 0;␊ |
241 | X509* cert = 0;␊ |
242 | STACK_OF(X509)* ca;␊ |
243 | ␊ |
244 | pkcs12 = d2i_PKCS12(NULL, &RSAKey, RSAKeyLength);␊ |
245 | if (!pkcs12)␊ |
246 | ␉EXCEPTION(gourou::CLIENT_INVALID_PKCS12, ERR_error_string(ERR_get_error(), NULL));␊ |
247 | PKCS12_parse(pkcs12, password.c_str(), &pkey, &cert, &ca);␊ |
248 | ␊ |
249 | *certOutLength = i2d_X509(cert, certOut);␊ |
250 | ␊ |
251 | EVP_PKEY_free(pkey);␊ |
252 | }␊ |
253 | ␊ |
254 | /* Crypto interface */␊ |
255 | void DRMProcessorClientImpl::AESEncrypt(CHAINING_MODE chaining,␊ |
256 | ␉␉␉␉␉const unsigned char* key, unsigned int keyLength,␊ |
257 | ␉␉␉␉␉const unsigned char* iv, unsigned int ivLength,␊ |
258 | ␉␉␉␉␉const unsigned char* dataIn, unsigned int dataInLength,␊ |
259 | ␉␉␉␉␉unsigned char* dataOut, unsigned int* dataOutLength)␊ |
260 | {␊ |
261 | void* handler = AESEncryptInit(chaining, key, keyLength, iv, ivLength);␊ |
262 | AESEncryptUpdate(handler, dataIn, dataInLength, dataOut, dataOutLength);␊ |
263 | AESEncryptFinalize(handler, dataOut+*dataOutLength, dataOutLength);␊ |
264 | }␊ |
265 | ␊ |
266 | void* DRMProcessorClientImpl::AESEncryptInit(CHAINING_MODE chaining,␊ |
267 | ␉␉␉␉␉ const unsigned char* key, unsigned int keyLength,␊ |
268 | ␉␉␉␉␉ const unsigned char* iv, unsigned int ivLength)␊ |
269 | {␊ |
270 | EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();␊ |
271 | ␊ |
272 | switch(keyLength)␊ |
273 | {␊ |
274 | case 16:␊ |
275 | ␉switch(chaining)␊ |
276 | ␉{␊ |
277 | ␉case CHAIN_ECB:␊ |
278 | ␉ EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv);␊ |
279 | ␉ break;␊ |
280 | ␉case CHAIN_CBC:␊ |
281 | ␉ EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);␊ |
282 | ␉ break;␊ |
283 | ␉default:␊ |
284 | ␉ EXCEPTION(gourou::CLIENT_BAD_CHAINING, "Unknown chaining mode " << chaining);␊ |
285 | ␉}␊ |
286 | ␉break;␊ |
287 | default:␊ |
288 | ␉EVP_CIPHER_CTX_free(ctx);␊ |
289 | ␉EXCEPTION(gourou::CLIENT_BAD_KEY_SIZE, "Invalid key size " << keyLength);␊ |
290 | }␊ |
291 | ␊ |
292 | return ctx;␊ |
293 | }␊ |
294 | ␊ |
295 | void* DRMProcessorClientImpl::AESDecryptInit(CHAINING_MODE chaining,␊ |
296 | ␉␉␉␉␉ const unsigned char* key, unsigned int keyLength,␊ |
297 | ␉␉␉␉␉ const unsigned char* iv, unsigned int ivLength)␊ |
298 | {␊ |
299 | EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();␊ |
300 | ␊ |
301 | switch(keyLength)␊ |
302 | {␊ |
303 | case 16:␊ |
304 | ␉switch(chaining)␊ |
305 | ␉{␊ |
306 | ␉case CHAIN_ECB:␊ |
307 | ␉ EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv);␊ |
308 | ␉ break;␊ |
309 | ␉case CHAIN_CBC:␊ |
310 | ␉ EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);␊ |
311 | ␉ break;␊ |
312 | ␉default:␊ |
313 | ␉ EXCEPTION(gourou::CLIENT_BAD_CHAINING, "Unknown chaining mode " << chaining);␊ |
314 | ␉}␊ |
315 | ␉break;␊ |
316 | default:␊ |
317 | ␉EVP_CIPHER_CTX_free(ctx);␊ |
318 | ␉EXCEPTION(gourou::CLIENT_BAD_KEY_SIZE, "Invalid key size " << keyLength);␊ |
319 | }␊ |
320 | ␊ |
321 | return ctx;␊ |
322 | }␊ |
323 | ␊ |
324 | void DRMProcessorClientImpl::AESEncryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength,␊ |
325 | ␉␉ unsigned char* dataOut, unsigned int* dataOutLength)␊ |
326 | {␊ |
327 | EVP_EncryptUpdate((EVP_CIPHER_CTX*)handler, dataOut, (int*)dataOutLength, dataIn, dataInLength);␊ |
328 | }␊ |
329 | ␊ |
330 | void DRMProcessorClientImpl::AESEncryptFinalize(void* handler,␊ |
331 | ␉␉␉␉␉␉unsigned char* dataOut, unsigned int* dataOutLength)␊ |
332 | {␊ |
333 | int len;␊ |
334 | EVP_EncryptFinal_ex((EVP_CIPHER_CTX*)handler, dataOut, &len);␊ |
335 | *dataOutLength += len;␊ |
336 | EVP_CIPHER_CTX_free((EVP_CIPHER_CTX*)handler);␊ |
337 | }␊ |
338 | ␊ |
339 | void DRMProcessorClientImpl::AESDecrypt(CHAINING_MODE chaining,␊ |
340 | ␉␉␉␉␉const unsigned char* key, unsigned int keyLength,␊ |
341 | ␉␉␉␉␉const unsigned char* iv, unsigned int ivLength,␊ |
342 | ␉␉␉␉␉const unsigned char* dataIn, unsigned int dataInLength,␊ |
343 | ␉␉␉␉␉unsigned char* dataOut, unsigned int* dataOutLength)␊ |
344 | {␊ |
345 | void* handler = AESDecryptInit(chaining, key, keyLength, iv, ivLength);␊ |
346 | AESDecryptUpdate(handler, dataIn, dataInLength, dataOut, dataOutLength);␊ |
347 | AESDecryptFinalize(handler, dataOut+*dataOutLength, dataOutLength);␊ |
348 | }␊ |
349 | ␊ |
350 | void DRMProcessorClientImpl::AESDecryptUpdate(void* handler, const unsigned char* dataIn, unsigned int dataInLength,␊ |
351 | ␉␉␉␉␉ unsigned char* dataOut, unsigned int* dataOutLength)␊ |
352 | {␊ |
353 | EVP_DecryptUpdate((EVP_CIPHER_CTX*)handler, dataOut, (int*)dataOutLength, dataIn, dataInLength);␊ |
354 | }␊ |
355 | ␊ |
356 | void DRMProcessorClientImpl::AESDecryptFinalize(void* handler, unsigned char* dataOut, unsigned int* dataOutLength)␊ |
357 | {␊ |
358 | int len;␊ |
359 | EVP_DecryptFinal_ex((EVP_CIPHER_CTX*)handler, dataOut, &len);␊ |
360 | *dataOutLength += len;␊ |
361 | EVP_CIPHER_CTX_free((EVP_CIPHER_CTX*)handler);␊ |
362 | }␊ |
363 | ␊ |
364 | void* DRMProcessorClientImpl::zipOpen(const std::string& path)␊ |
365 | {␊ |
366 | zip_t* handler = zip_open(path.c_str(), 0, 0);␊ |
367 | ␊ |
368 | if (!handler)␊ |
369 | ␉EXCEPTION(gourou::CLIENT_BAD_ZIP_FILE, "Invalid zip file " << path);␊ |
370 | ␊ |
371 | return handler;␊ |
372 | }␊ |
373 | ␊ |
374 | std::string DRMProcessorClientImpl::zipReadFile(void* handler, const std::string& path)␊ |
375 | {␊ |
376 | std::string res;␊ |
377 | unsigned char* buffer;␊ |
378 | zip_stat_t sb;␊ |
379 | ␊ |
380 | if (zip_stat((zip_t *)handler, path.c_str(), 0, &sb) < 0)␊ |
381 | ␉EXCEPTION(gourou::CLIENT_ZIP_ERROR, "Zip error " << zip_strerror((zip_t *)handler));␊ |
382 | ␊ |
383 | if (!(sb.valid & (ZIP_STAT_INDEX|ZIP_STAT_SIZE)))␊ |
384 | ␉EXCEPTION(gourou::CLIENT_ZIP_ERROR, "Required fields missing");␊ |
385 | ␊ |
386 | buffer = new unsigned char[sb.size];␊ |
387 | ␊ |
388 | zip_file_t *f = zip_fopen_index((zip_t *)handler, sb.index, ZIP_FL_COMPRESSED);␊ |
389 | ␊ |
390 | zip_fread(f, buffer, sb.size);␊ |
391 | zip_fclose(f);␊ |
392 | ␊ |
393 | res = std::string((char*)buffer, sb.size);␊ |
394 | delete[] buffer;␊ |
395 | ␊ |
396 | return res;␊ |
397 | }␊ |
398 | ␊ |
399 | void DRMProcessorClientImpl::zipWriteFile(void* handler, const std::string& path, const std::string& content)␊ |
400 | {␊ |
401 | zip_source_t* s = zip_source_buffer((zip_t*)handler, content.c_str(), content.length(), 0);␊ |
402 | if (zip_file_add((zip_t*)handler, path.c_str(), s, ZIP_FL_OVERWRITE|ZIP_FL_ENC_UTF_8) < 0)␊ |
403 | {␊ |
404 | ␉zip_source_free(s);␊ |
405 | ␉EXCEPTION(gourou::CLIENT_ZIP_ERROR, "Zip error " << zip_strerror((zip_t *)handler));␊ |
406 | }␊ |
407 | }␊ |
408 | ␊ |
409 | void DRMProcessorClientImpl::zipDeleteFile(void* handler, const std::string& path)␊ |
410 | {␊ |
411 | zip_int64_t idx = zip_name_locate((zip_t*)handler, path.c_str(), 0);␊ |
412 | ␊ |
413 | if (idx < 0)␊ |
414 | ␉EXCEPTION(gourou::CLIENT_ZIP_ERROR, "No such file " << path.c_str());␊ |
415 | ␊ |
416 | if (zip_delete((zip_t*)handler, idx))␊ |
417 | ␉EXCEPTION(gourou::CLIENT_ZIP_ERROR, "Zip error " << zip_strerror((zip_t *)handler));␊ |
418 | }␊ |
419 | ␊ |
420 | void DRMProcessorClientImpl::zipClose(void* handler)␊ |
421 | {␊ |
422 | zip_close((zip_t*)handler);␊ |
423 | }␊ |
424 | ␊ |
425 | void DRMProcessorClientImpl::inflate(std::string data, gourou::ByteArray& result,␊ |
426 | ␉␉␉␉ int wbits)␊ |
427 | {␊ |
428 | unsigned int dataSize = data.size()*2;␊ |
429 | unsigned char* buffer = new unsigned char[dataSize];␊ |
430 | ␊ |
431 | z_stream infstream;␊ |
432 | ␊ |
433 | infstream.zalloc = Z_NULL;␊ |
434 | infstream.zfree = Z_NULL;␊ |
435 | infstream.opaque = Z_NULL;␊ |
436 | ␊ |
437 | infstream.avail_in = (uInt)data.size();␊ |
438 | infstream.next_in = (Bytef *)data.c_str(); // input char array␊ |
439 | infstream.avail_out = (uInt)dataSize; // size of output␊ |
440 | infstream.next_out = (Bytef *)buffer; // output char array␊ |
441 | ␊ |
442 | int ret = inflateInit2(&infstream, wbits);␊ |
443 | ␊ |
444 | ret = ::inflate(&infstream, Z_SYNC_FLUSH);␊ |
445 | while (ret == Z_OK || ret == Z_STREAM_END)␊ |
446 | {␊ |
447 | ␉result.append(buffer, dataSize-infstream.avail_out);␊ |
448 | ␉if (ret == Z_STREAM_END) break;␊ |
449 | ␉infstream.avail_out = (uInt)dataSize; // size of output␊ |
450 | ␉infstream.next_out = (Bytef *)buffer; // output char array␊ |
451 | ␉ret = ::inflate(&infstream, Z_SYNC_FLUSH);␊ |
452 | }␊ |
453 | ␊ |
454 | inflateEnd(&infstream);␊ |
455 | ␊ |
456 | delete[] buffer;␊ |
457 | ␊ |
458 | if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR)␊ |
459 | ␉EXCEPTION(gourou::CLIENT_ZIP_ERROR, zError(ret));␊ |
460 | }␊ |
461 | ␉␊ |
462 | void DRMProcessorClientImpl::deflate(std::string data, gourou::ByteArray& result,␊ |
463 | ␉␉␉ int wbits, int compressionLevel)␊ |
464 | {␊ |
465 | unsigned int dataSize = data.size();␊ |
466 | unsigned char* buffer = new unsigned char[dataSize];␊ |
467 | ␊ |
468 | z_stream defstream;␊ |
469 | ␊ |
470 | defstream.zalloc = Z_NULL;␊ |
471 | defstream.zfree = Z_NULL;␊ |
472 | defstream.opaque = Z_NULL;␊ |
473 | ␊ |
474 | defstream.avail_in = (uInt)data.size();␊ |
475 | defstream.next_in = (Bytef *)data.c_str(); // input char array␊ |
476 | defstream.avail_out = (uInt)dataSize; // size of output␊ |
477 | defstream.next_out = (Bytef *)buffer; // output char array␊ |
478 | ␊ |
479 | int ret = deflateInit2(&defstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, wbits,␊ |
480 | ␉␉␉ compressionLevel, Z_DEFAULT_STRATEGY);␊ |
481 | ␊ |
482 | ret = ::deflate(&defstream, Z_SYNC_FLUSH);␊ |
483 | while (ret == Z_OK || ret == Z_STREAM_END)␊ |
484 | {␊ |
485 | ␉result.append(buffer, dataSize-defstream.avail_out);␊ |
486 | ␉if (ret == Z_STREAM_END) break;␊ |
487 | ␉defstream.avail_out = (uInt)dataSize; // size of output␊ |
488 | ␉defstream.next_out = (Bytef *)buffer; // output char array␊ |
489 | ␉ret = ::deflate(&defstream, Z_SYNC_FLUSH);␊ |
490 | }␊ |
491 | ␊ |
492 | deflateEnd(&defstream);␊ |
493 | ␊ |
494 | delete[] buffer;␊ |
495 | ␊ |
496 | if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR)␊ |
497 | ␉EXCEPTION(gourou::CLIENT_ZIP_ERROR, zError(ret));␊ |
498 | }␊ |