Remove QtCore and QtNetwork, replace them by libcurl + libc

This commit is contained in:
Grégory Soutadé 2022-03-16 22:45:33 +01:00
parent 0f475423c0
commit 2ce6142596
10 changed files with 363 additions and 237 deletions

View File

@ -39,8 +39,7 @@ For libgourou :
For utils : For utils :
* QT5Core * libcurl
* QT5Network
* OpenSSL * OpenSSL
* libzip * libzip

View File

@ -40,7 +40,7 @@
#define ACS_SERVER "http://adeactivate.adobe.com/adept" #define ACS_SERVER "http://adeactivate.adobe.com/adept"
#endif #endif
#define LIBGOUROU_VERSION "0.5.3" #define LIBGOUROU_VERSION "0.6"
namespace gourou namespace gourou
{ {

View File

@ -111,7 +111,8 @@ namespace gourou
CLIENT_ZIP_ERROR, CLIENT_ZIP_ERROR,
CLIENT_GENERIC_EXCEPTION, CLIENT_GENERIC_EXCEPTION,
CLIENT_NETWORK_ERROR, CLIENT_NETWORK_ERROR,
CLIENT_INVALID_PKCS8 CLIENT_INVALID_PKCS8,
CLIENT_FILE_ERROR
}; };
enum DRM_REMOVAL_ERROR { enum DRM_REMOVAL_ERROR {

View File

@ -1,10 +1,10 @@
TARGETS=acsmdownloader adept_activate adept_remove TARGETS=acsmdownloader adept_activate adept_remove
CXXFLAGS=-Wall `pkg-config --cflags Qt5Core Qt5Network` -fPIC -I$(ROOT)/include -I$(ROOT)/lib/pugixml/src/ CXXFLAGS=-Wall -fPIC -I$(ROOT)/include -I$(ROOT)/lib/pugixml/src/
STATIC_DEP= STATIC_DEP=
LDFLAGS=`pkg-config --libs Qt5Core Qt5Network` -L$(ROOT) -lcrypto -lzip -lz LDFLAGS=-L$(ROOT) -lcrypto -lzip -lz -lcurl
ifneq ($(STATIC_UTILS),) ifneq ($(STATIC_UTILS),)
STATIC_DEP = $(ROOT)/libgourou.a STATIC_DEP = $(ROOT)/libgourou.a
@ -18,7 +18,7 @@ else
CXXFLAGS += -O2 CXXFLAGS += -O2
endif endif
COMMON_DEPS = drmprocessorclientimpl.cpp $(STATIC_DEP) COMMON_DEPS = drmprocessorclientimpl.cpp utils_common.cpp $(STATIC_DEP)
all: $(TARGETS) all: $(TARGETS)

View File

@ -26,21 +26,14 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <unistd.h> #include <getopt.h>
#include <getopt.h>
#include <iostream> #include <iostream>
#include <algorithm>
#include <QFile>
#include <QDir>
#include <QCoreApplication>
#include <QRunnable>
#include <QThreadPool>
#include <libgourou.h> #include <libgourou.h>
#include "drmprocessorclientimpl.h" #include "drmprocessorclientimpl.h"
#include "utils_common.h"
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
static const char* deviceFile = "device.xml"; static const char* deviceFile = "device.xml";
static const char* activationFile = "activation.xml"; static const char* activationFile = "activation.xml";
@ -49,23 +42,13 @@ static const char* acsmFile = 0;
static bool exportPrivateKey = false; static bool exportPrivateKey = false;
static const char* outputFile = 0; static const char* outputFile = 0;
static const char* outputDir = 0; static const char* outputDir = 0;
static const char* defaultDirs[] = {
".adept/",
"./adobe-digital-editions/",
"./.adobe-digital-editions/"
};
class ACSMDownloader: public QRunnable class ACSMDownloader
{ {
public: public:
ACSMDownloader(QCoreApplication* app):
app(app) int run()
{
setAutoDelete(false);
}
void run()
{ {
int ret = 0; int ret = 0;
try try
@ -84,9 +67,8 @@ public:
if (outputDir) if (outputDir)
{ {
QDir dir(outputDir); if (!fileExists(outputDir))
if (!dir.exists(outputDir)) mkpath(outputDir);
dir.mkpath(outputDir);
filename = std::string(outputDir) + "/" + filename; filename = std::string(outputDir) + "/" + filename;
} }
@ -116,9 +98,8 @@ public:
if (outputDir) if (outputDir)
{ {
QDir dir(outputDir); if (!fileExists(outputDir))
if (!dir.exists(outputDir)) mkpath(outputDir);
dir.mkpath(outputDir);
filename = std::string(outputDir) + "/" + filename; filename = std::string(outputDir) + "/" + filename;
} }
@ -132,8 +113,7 @@ public:
finalName += ".pdf"; finalName += ".pdf";
else else
finalName += ".epub"; finalName += ".epub";
QDir dir; rename(filename.c_str(), finalName.c_str());
dir.rename(filename.c_str(), finalName.c_str());
filename = finalName; filename = finalName;
} }
std::cout << "Created " << filename << std::endl; std::cout << "Created " << filename << std::endl;
@ -144,37 +124,10 @@ public:
ret = 1; ret = 1;
} }
this->app->exit(ret); return ret;
} }
private:
QCoreApplication* app;
}; };
static const char* findFile(const char* filename, bool inDefaultDirs=true)
{
QFile file(filename);
if (file.exists())
return strdup(filename);
if (!inDefaultDirs) return 0;
for (int i=0; i<(int)ARRAY_SIZE(defaultDirs); i++)
{
QString path = QString(defaultDirs[i]) + QString(filename);
file.setFileName(path);
if (file.exists())
return strdup(path.toStdString().c_str());
}
return 0;
}
static void version(void)
{
std::cout << "Current libgourou version : " << gourou::DRMProcessor::VERSION << std::endl ;
}
static void usage(const char* cmd) static void usage(const char* cmd)
{ {
@ -275,8 +228,7 @@ int main(int argc, char** argv)
return -1; return -1;
} }
QCoreApplication app(argc, argv); ACSMDownloader downloader;
ACSMDownloader downloader(&app);
int i; int i;
bool hasErrors = false; bool hasErrors = false;
@ -306,8 +258,7 @@ int main(int argc, char** argv)
} }
else else
{ {
QFile file(acsmFile); if (!fileExists(acsmFile))
if (!file.exists())
{ {
std::cout << "Error : " << acsmFile << " doesn't exists" << std::endl; std::cout << "Error : " << acsmFile << " doesn't exists" << std::endl;
ret = -1; ret = -1;
@ -315,9 +266,7 @@ int main(int argc, char** argv)
} }
} }
QThreadPool::globalInstance()->start(&downloader); ret = downloader.run();
ret = app.exec();
end: end:
for (i=0; i<(int)ARRAY_SIZE(files); i++) for (i=0; i<(int)ARRAY_SIZE(files); i++)

View File

@ -28,22 +28,16 @@
#include <unistd.h> #include <unistd.h>
#include <getopt.h> #include <getopt.h>
#include <stdlib.h>
#include <termios.h> #include <termios.h>
#include <string.h>
#include <limits.h>
#include <iostream> #include <iostream>
#include <ostream> #include <ostream>
#include <QFile>
#include <QDir>
#include <QCoreApplication>
#include <QRunnable>
#include <QThreadPool>
#include <libgourou.h> #include <libgourou.h>
#include "drmprocessorclientimpl.h" #include "drmprocessorclientimpl.h"
#include "utils_common.h"
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
static const char* username = 0; static const char* username = 0;
static const char* password = 0; static const char* password = 0;
@ -100,16 +94,11 @@ static std::string getpass(const char *prompt, bool show_asterisk=false)
} }
class ADEPTActivate: public QRunnable class ADEPTActivate
{ {
public: public:
ADEPTActivate(QCoreApplication* app):
app(app) int run()
{
setAutoDelete(false);
}
void run()
{ {
int ret = 0; int ret = 0;
try try
@ -128,17 +117,10 @@ public:
ret = 1; ret = 1;
} }
this->app->exit(ret); return ret;
} }
private:
QCoreApplication* app;
}; };
static void version(void)
{
std::cout << "Current libgourou version : " << gourou::DRMProcessor::VERSION << std::endl ;
}
static void usage(const char* cmd) static void usage(const char* cmd)
{ {
@ -162,8 +144,8 @@ static void usage(const char* cmd)
static const char* abspath(const char* filename) static const char* abspath(const char* filename)
{ {
const char* root = getcwd(0, PATH_MAX); const char* root = getcwd(0, PATH_MAX);
QString fullPath = QString(root) + QString("/") + QString(filename); std::string fullPath = std::string(root) + std::string("/") + filename;
const char* res = strdup(fullPath.toStdString().c_str()); const char* res = strdup(fullPath.c_str());
free((void*)root); free((void*)root);
@ -255,9 +237,8 @@ int main(int argc, char** argv)
// Relative path // Relative path
if (_outputDir[0] == '.' || _outputDir[0] != '/') if (_outputDir[0] == '.' || _outputDir[0] != '/')
{ {
QFile file(_outputDir);
// realpath doesn't works if file/dir doesn't exists // realpath doesn't works if file/dir doesn't exists
if (file.exists()) if (fileExists(_outputDir))
outputDir = strdup(realpath(_outputDir, 0)); outputDir = strdup(realpath(_outputDir, 0));
else else
outputDir = strdup(abspath(_outputDir)); outputDir = strdup(abspath(_outputDir));
@ -266,10 +247,8 @@ int main(int argc, char** argv)
outputDir = strdup(_outputDir); outputDir = strdup(_outputDir);
} }
QCoreApplication app(argc, argv); std::string pass;
if (fileExists(outputDir))
QFile file(outputDir);
if (file.exists())
{ {
int key; int key;
@ -289,7 +268,6 @@ int main(int argc, char** argv)
; ;
} }
std::string pass;
if (!password) if (!password)
{ {
char prompt[128]; char prompt[128];
@ -298,13 +276,11 @@ int main(int argc, char** argv)
password = pass.c_str(); password = pass.c_str();
} }
ADEPTActivate activate(&app); ADEPTActivate activate;
QThreadPool::globalInstance()->start(&activate);
ret = app.exec(); ret = activate.run();
end: end:
free((void*)outputDir); free((void*)outputDir);
return ret; return ret;
} }

View File

@ -26,23 +26,15 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <unistd.h>
#include <getopt.h> #include <getopt.h>
#include <iostream> #include <iostream>
#include <QFile>
#include <QDir>
#include <QCoreApplication>
#include <QRunnable>
#include <QThreadPool>
#include <QTemporaryFile>
#include <libgourou.h> #include <libgourou.h>
#include <libgourou_common.h> #include <libgourou_common.h>
#include "drmprocessorclientimpl.h"
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) #include "drmprocessorclientimpl.h"
#include "utils_common.h"
static const char* deviceFile = "device.xml"; static const char* deviceFile = "device.xml";
static const char* activationFile = "activation.xml"; static const char* activationFile = "activation.xml";
@ -50,13 +42,9 @@ static const char* devicekeyFile = "devicesalt";
static const char* inputFile = 0; static const char* inputFile = 0;
static const char* outputFile = 0; static const char* outputFile = 0;
static const char* outputDir = 0; static const char* outputDir = 0;
static const char* defaultDirs[] = {
".adept/", static char* encryptionKeyUser = 0;
"./adobe-digital-editions/", static unsigned char* encryptionKey = 0;
"./.adobe-digital-editions/"
};
static char* encryptionKeyUser = 0;
static unsigned char* encryptionKey = 0;
static unsigned encryptionKeySize = 0; static unsigned encryptionKeySize = 0;
static inline unsigned char htoi(unsigned char c) static inline unsigned char htoi(unsigned char c)
@ -78,16 +66,11 @@ static inline bool endsWith(const std::string& s, const std::string& suffix)
return s.rfind(suffix) == std::abs((int)(s.size()-suffix.size())); return s.rfind(suffix) == std::abs((int)(s.size()-suffix.size()));
} }
class ADEPTRemove: public QRunnable class ADEPTRemove
{ {
public: public:
ADEPTRemove(QCoreApplication* app):
app(app)
{
setAutoDelete(false);
}
void run() int run()
{ {
int ret = 0; int ret = 0;
try try
@ -104,9 +87,8 @@ public:
if (outputDir) if (outputDir)
{ {
QDir dir(outputDir); if (!fileExists(outputDir))
if (!dir.exists(outputDir)) mkpath(outputDir);
dir.mkpath(outputDir);
filename = std::string(outputDir) + "/" + filename; filename = std::string(outputDir) + "/" + filename;
} }
@ -122,11 +104,8 @@ public:
if (inputFile != filename) if (inputFile != filename)
{ {
QFile::remove(filename.c_str()); unlink(filename.c_str());
if (!QFile::copy(inputFile, filename.c_str())) fileCopy(inputFile, filename.c_str());
{
EXCEPTION(gourou::DRM_FILE_ERROR, "Unable to copy " << inputFile << " into " << filename);
}
processor.removeDRM(inputFile, filename, type, encryptionKey, encryptionKeySize); processor.removeDRM(inputFile, filename, type, encryptionKey, encryptionKeySize);
std::cout << "DRM removed into new file " << filename << std::endl; std::cout << "DRM removed into new file " << filename << std::endl;
} }
@ -135,18 +114,16 @@ public:
// Use temp file for PDF // Use temp file for PDF
if (type == gourou::DRMProcessor::ITEM_TYPE::PDF) if (type == gourou::DRMProcessor::ITEM_TYPE::PDF)
{ {
QTemporaryFile tempFile; char* tempFile = tempnam("/tmp", NULL);
tempFile.open(); processor.removeDRM(inputFile, tempFile, type, encryptionKey, encryptionKeySize);
tempFile.setAutoRemove(false); // In case of failure
processor.removeDRM(inputFile, tempFile.fileName().toStdString(), type, encryptionKey, encryptionKeySize);
/* Original file must be removed before doing a copy... */ /* Original file must be removed before doing a copy... */
QFile origFile(inputFile); unlink(inputFile);
origFile.remove(); if (!rename(tempFile, filename.c_str()))
if (!QFile::copy(tempFile.fileName(), filename.c_str()))
{ {
EXCEPTION(gourou::DRM_FILE_ERROR, "Unable to copy " << tempFile.fileName().toStdString() << " into " << filename); free(tempFile);
EXCEPTION(gourou::DRM_FILE_ERROR, "Unable to copy " << tempFile << " into " << filename);
} }
tempFile.setAutoRemove(true); free(tempFile);
} }
else else
processor.removeDRM(inputFile, filename, type, encryptionKey, encryptionKeySize); processor.removeDRM(inputFile, filename, type, encryptionKey, encryptionKeySize);
@ -158,38 +135,10 @@ public:
ret = 1; ret = 1;
} }
this->app->exit(ret); return ret;
} }
private:
QCoreApplication* app;
}; };
static const char* findFile(const char* filename, bool inDefaultDirs=true)
{
QFile file(filename);
if (file.exists())
return strdup(filename);
if (!inDefaultDirs) return 0;
for (int i=0; i<(int)ARRAY_SIZE(defaultDirs); i++)
{
QString path = QString(defaultDirs[i]) + QString(filename);
file.setFileName(path);
if (file.exists())
return strdup(path.toStdString().c_str());
}
return 0;
}
static void version(void)
{
std::cout << "Current libgourou version : " << gourou::DRMProcessor::VERSION << std::endl ;
}
static void usage(const char* cmd) static void usage(const char* cmd)
{ {
std::cout << "Remove ADEPT DRM (from Adobe) of EPUB/PDF file" << std::endl; std::cout << "Remove ADEPT DRM (from Adobe) of EPUB/PDF file" << std::endl;
@ -288,8 +237,7 @@ int main(int argc, char** argv)
return -1; return -1;
} }
QCoreApplication app(argc, argv); ADEPTRemove remover;
ADEPTRemove remover(&app);
int i; int i;
bool hasErrors = false; bool hasErrors = false;
@ -335,10 +283,8 @@ int main(int argc, char** argv)
if (hasErrors) if (hasErrors)
goto end; goto end;
QThreadPool::globalInstance()->start(&remover); ret = remover.run();
ret = app.exec();
end: end:
for (i=0; i<(int)ARRAY_SIZE(files); i++) for (i=0; i<(int)ARRAY_SIZE(files); i++)
{ {

View File

@ -25,17 +25,18 @@
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <bytearray.h>
#include <algorithm>
#include <cctype>
#include <locale>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/pkcs12.h> #include <openssl/pkcs12.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <QCoreApplication> #include <curl/curl.h>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QFile>
#include <zlib.h> #include <zlib.h>
#include <zip.h> #include <zip.h>
@ -44,6 +45,27 @@
#include <libgourou_log.h> #include <libgourou_log.h>
#include "drmprocessorclientimpl.h" #include "drmprocessorclientimpl.h"
// https://stackoverflow.com/questions/216823/how-to-trim-a-stdstring
// trim from start (in place)
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}
/* Digest interface */ /* Digest interface */
void* DRMProcessorClientImpl::createDigest(const std::string& digestName) void* DRMProcessorClientImpl::createDigest(const std::string& digestName)
{ {
@ -90,78 +112,120 @@ void DRMProcessorClientImpl::randBytes(unsigned char* bytesOut, unsigned int len
/* HTTP interface */ /* HTTP interface */
#define DISPLAY_THRESHOLD 10*1024 // Threshold to display download progression #define DISPLAY_THRESHOLD 10*1024 // Threshold to display download progression
static void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { static int downloadProgress(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
// For "big" files only curl_off_t ultotal, curl_off_t ulnow)
if (bytesTotal >= DISPLAY_THRESHOLD && gourou::logLevel >= gourou::WARN) {
// For "big" files only
if (dltotal >= DISPLAY_THRESHOLD && gourou::logLevel >= gourou::WARN)
{ {
int percent = 0; int percent = 0;
if (bytesTotal) if (dltotal)
percent = (bytesReceived * 100) / bytesTotal; percent = (dlnow * 100) / dltotal;
std::cout << "\rDownload " << percent << "%" << std::flush; std::cout << "\rDownload " << percent << "%" << std::flush;
} }
return 0;
}
static size_t curlRead(void *data, size_t size, size_t nmemb, void *userp)
{
gourou::ByteArray* replyData = (gourou::ByteArray*) userp;
replyData->append((unsigned char*)data, size*nmemb);
return size*nmemb;
}
static size_t curlHeaders(char *buffer, size_t size, size_t nitems, void *userdata)
{
std::map<std::string, std::string>* responseHeaders = (std::map<std::string, std::string>*)userdata;
std::string::size_type pos = 0;
std::string buf(buffer, size*nitems);
pos = buf.find(":", pos);
if (pos != std::string::npos)
{
std::string key = std::string(buffer, pos);
std::string value = std::string(&buffer[pos+1], (size*nitems)-(pos+1));
trim(key);
trim(value);
(*responseHeaders)[key] = value;
if (gourou::logLevel >= gourou::DEBUG)
std::cout << key << " : " << value << std::endl;
}
return size*nitems;
} }
std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, const std::string& POSTData, const std::string& contentType, std::map<std::string, std::string>* responseHeaders) std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, const std::string& POSTData, const std::string& contentType, std::map<std::string, std::string>* responseHeaders)
{ {
QNetworkRequest request(QUrl(URL.c_str())); gourou::ByteArray replyData;
QNetworkAccessManager networkManager; std::map<std::string, std::string> localHeaders;
QByteArray replyData;
if (!responseHeaders)
responseHeaders = &localHeaders;
GOUROU_LOG(gourou::INFO, "Send request to " << URL); GOUROU_LOG(gourou::INFO, "Send request to " << URL);
if (POSTData.size()) if (POSTData.size())
{ {
GOUROU_LOG(gourou::DEBUG, "<<< " << std::endl << POSTData); GOUROU_LOG(gourou::DEBUG, "<<< " << std::endl << POSTData);
} }
request.setRawHeader("Accept", "*/*");
request.setRawHeader("User-Agent", "book2png");
if (contentType.size())
request.setRawHeader("Content-Type", contentType.c_str());
QNetworkReply* reply; CURL *curl = curl_easy_init();
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
curl_easy_setopt(curl, CURLOPT_USERAGENT, "book2png");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
struct curl_slist *list = NULL;
list = curl_slist_append(list, "Accept: */*");
std::string _contentType;
if (contentType.size())
{
_contentType = "Content-Type: " + contentType;
list = curl_slist_append(list, _contentType.c_str());
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
if (POSTData.size()) if (POSTData.size())
reply = networkManager.post(request, POSTData.c_str());
else
reply = networkManager.get(request);
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
// Handled just below
QObject::connect(reply, &QNetworkReply::errorOccurred, &loop, &QEventLoop::quit);
QObject::connect(reply, &QNetworkReply::downloadProgress, &loop, downloadProgress);
loop.exec();
QByteArray location = reply->rawHeader("Location");
if (location.size() != 0)
{ {
GOUROU_LOG(gourou::DEBUG, "New location"); curl_easy_setopt(curl, CURLOPT_POST, 1L);
return sendHTTPRequest(location.constData(), POSTData, contentType, responseHeaders); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, POSTData.size());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, POSTData.data());
} }
if (reply->error() != QNetworkReply::NoError) curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlRead);
EXCEPTION(gourou::CLIENT_NETWORK_ERROR, "Error " << reply->errorString().toStdString()); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&replyData);
QList<QByteArray> headers = reply->rawHeaderList(); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curlHeaders);
for (int i = 0; i < headers.size(); ++i) { curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void*)responseHeaders);
if (gourou::logLevel >= gourou::DEBUG)
std::cout << headers[i].constData() << " : " << reply->rawHeader(headers[i]).constData() << std::endl; curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, downloadProgress);
if (responseHeaders) curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
(*responseHeaders)[headers[i].constData()] = reply->rawHeader(headers[i]).constData();
} res = curl_easy_perform(curl);
curl_slist_free_all(list);
curl_easy_cleanup(curl);
if (res != CURLE_OK)
EXCEPTION(gourou::CLIENT_NETWORK_ERROR, "Error " << curl_easy_strerror(res));
replyData = reply->readAll();
if (replyData.size() >= DISPLAY_THRESHOLD && gourou::logLevel >= gourou::WARN) if (replyData.size() >= DISPLAY_THRESHOLD && gourou::logLevel >= gourou::WARN)
std::cout << std::endl; std::cout << std::endl;
if (reply->rawHeader("Content-Type") == "application/vnd.adobe.adept+xml")
if ((*responseHeaders)["Content-Type"] == "application/vnd.adobe.adept+xml")
{ {
GOUROU_LOG(gourou::DEBUG, ">>> " << std::endl << replyData.data()); GOUROU_LOG(gourou::DEBUG, ">>> " << std::endl << replyData.data());
} }
return std::string(replyData.data(), replyData.length()); return std::string((char*)replyData.data(), replyData.length());
} }
void DRMProcessorClientImpl::RSAPrivateEncrypt(const unsigned char* RSAKey, unsigned int RSAKeyLength, void DRMProcessorClientImpl::RSAPrivateEncrypt(const unsigned char* RSAKey, unsigned int RSAKeyLength,

127
utils/utils_common.cpp Normal file
View File

@ -0,0 +1,127 @@
/*
Copyright (c) 2022, Grégory Soutadé
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <limits.h>
#include <iostream>
#include <libgourou.h>
#include <libgourou_common.h>
#include "utils_common.h"
static const char* defaultDirs[] = {
".adept/",
"./adobe-digital-editions/",
"./.adobe-digital-editions/"
};
void version(void)
{
std::cout << "Current libgourou version : " << gourou::DRMProcessor::VERSION << std::endl ;
}
bool fileExists(const char* filename)
{
struct stat _stat;
int ret = stat(filename, &_stat);
return (ret == 0);
}
const char* findFile(const char* filename, bool inDefaultDirs)
{
if (fileExists(filename))
return strdup(filename);
if (!inDefaultDirs) return 0;
for (int i=0; i<(int)ARRAY_SIZE(defaultDirs); i++)
{
std::string path = std::string(defaultDirs[i]) + filename;
if (fileExists(path.c_str()))
return strdup(path.c_str());
}
return 0;
}
// https://stackoverflow.com/questions/2336242/recursive-mkdir-system-call-on-unix
void mkpath(const char *dir)
{
char tmp[PATH_MAX];
char *p = NULL;
size_t len;
snprintf(tmp, sizeof(tmp),"%s",dir);
len = strlen(tmp);
if (tmp[len - 1] == '/')
tmp[len - 1] = 0;
for (p = tmp + 1; *p; p++)
if (*p == '/') {
*p = 0;
mkdir(tmp, S_IRWXU);
*p = '/';
}
mkdir(tmp, S_IRWXU);
}
void fileCopy(const char* in, const char* out)
{
char buffer[4096];
int ret, fdIn, fdOut;
fdIn = open(in, O_RDONLY);
if (!fdIn)
EXCEPTION(gourou::CLIENT_FILE_ERROR, "Unable to open " << in);
fdOut = open(out, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
if (!fdOut)
{
close (fdIn);
EXCEPTION(gourou::CLIENT_FILE_ERROR, "Unable to open " << out);
}
while (true)
{
ret = ::read(fdIn, buffer, sizeof(buffer));
if (ret <= 0)
break;
::write(fdOut, buffer, ret);
}
close (fdIn);
close (fdOut);
}

64
utils/utils_common.h Normal file
View File

@ -0,0 +1,64 @@
/*
Copyright (c) 2022, Grégory Soutadé
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _UTILS_COMMON_H_
#define _UTILS_COMMON_H_
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
/**
* @brief Display libgourou version
*/
void version(void);
/**
* @brief Find a given filename in current directory and/or in default directories
*
* @param filename Filename to search
* @param inDefaultDirs Search is default directories or not
*
* @return A copy of full path
*/
const char* findFile(const char* filename, bool inDefaultDirs=true);
/**
* @brief Does the file (or directory exists)
*/
bool fileExists(const char* filename);
/**
* @brief Recursively created dir
*/
void mkpath(const char *dir);
/**
* @brief Copy file in into file out
*/
void fileCopy(const char* in, const char* out);
#endif