forked from soutade/libgourou
		
	Remove QtCore and QtNetwork, replace them by libcurl + libc
This commit is contained in:
		| @@ -1,10 +1,10 @@ | ||||
|  | ||||
| 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= | ||||
| LDFLAGS=`pkg-config --libs Qt5Core Qt5Network` -L$(ROOT) -lcrypto -lzip -lz | ||||
| LDFLAGS=-L$(ROOT) -lcrypto -lzip -lz -lcurl | ||||
|  | ||||
| ifneq ($(STATIC_UTILS),) | ||||
| STATIC_DEP = $(ROOT)/libgourou.a | ||||
| @@ -18,7 +18,7 @@ else | ||||
| CXXFLAGS += -O2 | ||||
| endif | ||||
|  | ||||
| COMMON_DEPS = drmprocessorclientimpl.cpp $(STATIC_DEP) | ||||
| COMMON_DEPS = drmprocessorclientimpl.cpp utils_common.cpp $(STATIC_DEP) | ||||
|  | ||||
| all: $(TARGETS) | ||||
|  | ||||
|   | ||||
| @@ -26,21 +26,14 @@ | ||||
|   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| #include <unistd.h> | ||||
| #include <getopt.h> | ||||
|  #include <getopt.h> | ||||
|  | ||||
| #include <iostream> | ||||
|  | ||||
| #include <QFile> | ||||
| #include <QDir> | ||||
| #include <QCoreApplication> | ||||
| #include <QRunnable> | ||||
| #include <QThreadPool> | ||||
| #include <algorithm> | ||||
|  | ||||
| #include <libgourou.h> | ||||
| #include "drmprocessorclientimpl.h" | ||||
|  | ||||
| #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) | ||||
| #include "utils_common.h" | ||||
|  | ||||
| static const char* deviceFile     = "device.xml"; | ||||
| static const char* activationFile = "activation.xml"; | ||||
| @@ -49,23 +42,13 @@ static const char* acsmFile       = 0; | ||||
| static       bool  exportPrivateKey = false; | ||||
| static const char* outputFile     = 0; | ||||
| static const char* outputDir      = 0; | ||||
| static const char* defaultDirs[]  = { | ||||
|     ".adept/", | ||||
|     "./adobe-digital-editions/", | ||||
|     "./.adobe-digital-editions/" | ||||
| }; | ||||
|  | ||||
|  | ||||
| class ACSMDownloader: public QRunnable | ||||
| class ACSMDownloader | ||||
| { | ||||
| public: | ||||
|     ACSMDownloader(QCoreApplication* app): | ||||
| 	app(app) | ||||
|     { | ||||
| 	setAutoDelete(false); | ||||
|     } | ||||
|     | ||||
|     void run() | ||||
|      | ||||
|     int run() | ||||
|     { | ||||
| 	int ret = 0; | ||||
| 	try | ||||
| @@ -84,9 +67,8 @@ public: | ||||
| 	     | ||||
| 		if (outputDir) | ||||
| 		{ | ||||
| 		    QDir dir(outputDir); | ||||
| 		    if (!dir.exists(outputDir)) | ||||
| 			dir.mkpath(outputDir); | ||||
| 		    if (!fileExists(outputDir)) | ||||
| 			mkpath(outputDir); | ||||
| 		     | ||||
| 		    filename = std::string(outputDir) + "/" + filename; | ||||
| 		} | ||||
| @@ -116,9 +98,8 @@ public: | ||||
| 	     | ||||
| 		if (outputDir) | ||||
| 		{ | ||||
| 		    QDir dir(outputDir); | ||||
| 		    if (!dir.exists(outputDir)) | ||||
| 			dir.mkpath(outputDir); | ||||
| 		    if (!fileExists(outputDir)) | ||||
| 			mkpath(outputDir); | ||||
|  | ||||
| 		    filename = std::string(outputDir) + "/" + filename; | ||||
| 		} | ||||
| @@ -132,8 +113,7 @@ public: | ||||
| 			finalName += ".pdf"; | ||||
| 		    else | ||||
| 			finalName += ".epub"; | ||||
| 		    QDir dir; | ||||
| 		    dir.rename(filename.c_str(), finalName.c_str()); | ||||
| 		    rename(filename.c_str(), finalName.c_str()); | ||||
| 		    filename = finalName; | ||||
| 		} | ||||
| 		std::cout << "Created " << filename << std::endl; | ||||
| @@ -144,37 +124,10 @@ public: | ||||
| 	    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) | ||||
| { | ||||
| @@ -275,8 +228,7 @@ int main(int argc, char** argv) | ||||
| 	return -1; | ||||
|     } | ||||
|  | ||||
|     QCoreApplication app(argc, argv); | ||||
|     ACSMDownloader downloader(&app); | ||||
|     ACSMDownloader downloader; | ||||
|  | ||||
|     int i; | ||||
|     bool hasErrors = false; | ||||
| @@ -306,8 +258,7 @@ int main(int argc, char** argv) | ||||
|     } | ||||
|     else | ||||
|     { | ||||
| 	QFile file(acsmFile); | ||||
| 	if (!file.exists()) | ||||
| 	if (!fileExists(acsmFile)) | ||||
| 	{ | ||||
| 	    std::cout << "Error : " << acsmFile << " doesn't exists" << std::endl; | ||||
| 	    ret = -1; | ||||
| @@ -315,9 +266,7 @@ int main(int argc, char** argv) | ||||
| 	} | ||||
|     } | ||||
|      | ||||
|     QThreadPool::globalInstance()->start(&downloader); | ||||
|  | ||||
|     ret = app.exec(); | ||||
|     ret = downloader.run(); | ||||
|  | ||||
| end: | ||||
|     for (i=0; i<(int)ARRAY_SIZE(files); i++) | ||||
|   | ||||
| @@ -28,22 +28,16 @@ | ||||
|  | ||||
| #include <unistd.h> | ||||
| #include <getopt.h> | ||||
| #include <stdlib.h> | ||||
| #include <termios.h> | ||||
| #include <string.h> | ||||
| #include <limits.h> | ||||
|  | ||||
| #include <iostream> | ||||
| #include <ostream> | ||||
|  | ||||
| #include <QFile> | ||||
| #include <QDir> | ||||
| #include <QCoreApplication> | ||||
| #include <QRunnable> | ||||
| #include <QThreadPool> | ||||
|  | ||||
| #include <libgourou.h> | ||||
| #include "drmprocessorclientimpl.h" | ||||
|  | ||||
| #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) | ||||
| #include "utils_common.h" | ||||
|  | ||||
| static const char* username      = 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: | ||||
|     ADEPTActivate(QCoreApplication* app): | ||||
| 	app(app) | ||||
|     { | ||||
| 	setAutoDelete(false); | ||||
|     } | ||||
|     | ||||
|     void run() | ||||
| public:   | ||||
|  | ||||
|     int run() | ||||
|     { | ||||
| 	int ret = 0; | ||||
| 	try | ||||
| @@ -128,17 +117,10 @@ public: | ||||
| 	    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) | ||||
| { | ||||
| @@ -162,8 +144,8 @@ static void usage(const char* cmd) | ||||
| static const char* abspath(const char* filename) | ||||
| { | ||||
|     const char* root = getcwd(0, PATH_MAX); | ||||
|     QString fullPath = QString(root) + QString("/") + QString(filename); | ||||
|     const char* res = strdup(fullPath.toStdString().c_str()); | ||||
|     std::string fullPath = std::string(root) + std::string("/") + filename; | ||||
|     const char* res = strdup(fullPath.c_str()); | ||||
|  | ||||
|     free((void*)root); | ||||
|  | ||||
| @@ -255,9 +237,8 @@ int main(int argc, char** argv) | ||||
| 	// Relative path | ||||
| 	if (_outputDir[0] == '.' || _outputDir[0] != '/') | ||||
| 	{ | ||||
| 	    QFile file(_outputDir); | ||||
| 	    // realpath doesn't works if file/dir doesn't exists | ||||
| 	    if (file.exists()) | ||||
| 	    if (fileExists(_outputDir)) | ||||
| 		outputDir = strdup(realpath(_outputDir, 0)); | ||||
| 	    else | ||||
| 		outputDir = strdup(abspath(_outputDir)); | ||||
| @@ -266,10 +247,8 @@ int main(int argc, char** argv) | ||||
| 	    outputDir = strdup(_outputDir); | ||||
|     } | ||||
|  | ||||
|     QCoreApplication app(argc, argv); | ||||
|  | ||||
|     QFile file(outputDir); | ||||
|     if (file.exists()) | ||||
|     std::string pass; | ||||
|     if (fileExists(outputDir)) | ||||
|     { | ||||
| 	int key; | ||||
| 	 | ||||
| @@ -289,7 +268,6 @@ int main(int argc, char** argv) | ||||
| 	    ; | ||||
|     } | ||||
|  | ||||
|     std::string pass; | ||||
|     if (!password) | ||||
|     { | ||||
| 	char prompt[128]; | ||||
| @@ -298,13 +276,11 @@ int main(int argc, char** argv) | ||||
| 	password = pass.c_str(); | ||||
|     } | ||||
|          | ||||
|     ADEPTActivate activate(&app); | ||||
|     QThreadPool::globalInstance()->start(&activate); | ||||
|     ADEPTActivate activate; | ||||
|  | ||||
|     ret = app.exec(); | ||||
|     ret = activate.run(); | ||||
|  | ||||
| end: | ||||
|      | ||||
| end:     | ||||
|     free((void*)outputDir); | ||||
|     return ret; | ||||
| } | ||||
|   | ||||
| @@ -26,23 +26,15 @@ | ||||
|   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| #include <unistd.h> | ||||
| #include <getopt.h> | ||||
|  | ||||
| #include <iostream> | ||||
|  | ||||
| #include <QFile> | ||||
| #include <QDir> | ||||
| #include <QCoreApplication> | ||||
| #include <QRunnable> | ||||
| #include <QThreadPool> | ||||
| #include <QTemporaryFile> | ||||
|  | ||||
| #include <libgourou.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* activationFile = "activation.xml"; | ||||
| @@ -50,13 +42,9 @@ static const char* devicekeyFile  = "devicesalt"; | ||||
| static const char* inputFile      = 0; | ||||
| static const char* outputFile     = 0; | ||||
| static const char* outputDir      = 0; | ||||
| static const char* defaultDirs[]  = { | ||||
|     ".adept/", | ||||
|     "./adobe-digital-editions/", | ||||
|     "./.adobe-digital-editions/" | ||||
| }; | ||||
| static char* encryptionKeyUser  = 0; | ||||
| static unsigned char* encryptionKey  = 0; | ||||
|  | ||||
| static char*          encryptionKeyUser  = 0; | ||||
| static unsigned char* encryptionKey      = 0; | ||||
| static unsigned       encryptionKeySize  = 0; | ||||
|  | ||||
| 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())); | ||||
| } | ||||
|  | ||||
| class ADEPTRemove: public QRunnable | ||||
| class ADEPTRemove | ||||
| { | ||||
| public: | ||||
|     ADEPTRemove(QCoreApplication* app): | ||||
| 	app(app) | ||||
|     { | ||||
| 	setAutoDelete(false); | ||||
|     } | ||||
|     | ||||
|     void run() | ||||
|     int run() | ||||
|     { | ||||
| 	int ret = 0; | ||||
| 	try | ||||
| @@ -104,9 +87,8 @@ public: | ||||
| 	     | ||||
| 	    if (outputDir) | ||||
| 	    { | ||||
| 		QDir dir(outputDir); | ||||
| 		if (!dir.exists(outputDir)) | ||||
| 		    dir.mkpath(outputDir); | ||||
| 		if (!fileExists(outputDir)) | ||||
| 		    mkpath(outputDir); | ||||
|  | ||||
| 		filename = std::string(outputDir) + "/" + filename; | ||||
| 	    } | ||||
| @@ -122,11 +104,8 @@ public: | ||||
| 	     | ||||
| 	    if (inputFile != filename) | ||||
| 	    { | ||||
| 		QFile::remove(filename.c_str()); | ||||
| 		if (!QFile::copy(inputFile, filename.c_str())) | ||||
| 		{ | ||||
| 		    EXCEPTION(gourou::DRM_FILE_ERROR, "Unable to copy " << inputFile << " into " << filename); | ||||
| 		} | ||||
| 		unlink(filename.c_str()); | ||||
| 		fileCopy(inputFile, filename.c_str()); | ||||
| 		processor.removeDRM(inputFile, filename, type, encryptionKey, encryptionKeySize); | ||||
| 		std::cout << "DRM removed into new file " << filename << std::endl; | ||||
| 	    } | ||||
| @@ -135,18 +114,16 @@ public: | ||||
| 		// Use temp file for PDF | ||||
| 		if (type == gourou::DRMProcessor::ITEM_TYPE::PDF) | ||||
| 		{ | ||||
| 		    QTemporaryFile tempFile; | ||||
| 		    tempFile.open(); | ||||
| 		    tempFile.setAutoRemove(false); // In case of failure | ||||
| 		    processor.removeDRM(inputFile, tempFile.fileName().toStdString(), type, encryptionKey, encryptionKeySize); | ||||
| 		    char* tempFile = tempnam("/tmp", NULL); | ||||
| 		    processor.removeDRM(inputFile, tempFile, type, encryptionKey, encryptionKeySize); | ||||
| 		    /* Original file must be removed before doing a copy... */ | ||||
| 		    QFile origFile(inputFile); | ||||
| 		    origFile.remove(); | ||||
| 		    if (!QFile::copy(tempFile.fileName(), filename.c_str())) | ||||
| 		    unlink(inputFile); | ||||
| 		    if (!rename(tempFile, 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 | ||||
| 		    processor.removeDRM(inputFile, filename, type, encryptionKey, encryptionKeySize); | ||||
| @@ -158,38 +135,10 @@ public: | ||||
| 	    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) | ||||
| { | ||||
|     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; | ||||
|     } | ||||
|  | ||||
|     QCoreApplication app(argc, argv); | ||||
|     ADEPTRemove remover(&app); | ||||
|     ADEPTRemove remover; | ||||
|  | ||||
|     int i; | ||||
|     bool hasErrors = false; | ||||
| @@ -335,10 +283,8 @@ int main(int argc, char** argv) | ||||
|     if (hasErrors) | ||||
| 	goto end; | ||||
|         | ||||
|     QThreadPool::globalInstance()->start(&remover); | ||||
|  | ||||
|     ret = app.exec(); | ||||
|  | ||||
|     ret = remover.run(); | ||||
|      | ||||
| end: | ||||
|     for (i=0; i<(int)ARRAY_SIZE(files); i++) | ||||
|     { | ||||
|   | ||||
| @@ -25,17 +25,18 @@ | ||||
|   (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 <bytearray.h> | ||||
|  | ||||
| #include <algorithm>  | ||||
| #include <cctype> | ||||
| #include <locale> | ||||
|  | ||||
| #include <openssl/rand.h> | ||||
| #include <openssl/pkcs12.h> | ||||
| #include <openssl/evp.h> | ||||
| #include <openssl/err.h> | ||||
|  | ||||
| #include <QCoreApplication> | ||||
| #include <QNetworkReply> | ||||
| #include <QNetworkRequest> | ||||
| #include <QNetworkAccessManager> | ||||
| #include <QFile> | ||||
| #include <curl/curl.h> | ||||
|  | ||||
| #include <zlib.h> | ||||
| #include <zip.h> | ||||
| @@ -44,6 +45,27 @@ | ||||
| #include <libgourou_log.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 */ | ||||
| void* DRMProcessorClientImpl::createDigest(const std::string& digestName) | ||||
| { | ||||
| @@ -90,78 +112,120 @@ void DRMProcessorClientImpl::randBytes(unsigned char* bytesOut, unsigned int len | ||||
| /* HTTP interface */ | ||||
| #define DISPLAY_THRESHOLD 10*1024 // Threshold to display download progression | ||||
|  | ||||
| static void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { | ||||
|     // For "big" files only | ||||
|     if (bytesTotal >= DISPLAY_THRESHOLD && gourou::logLevel >= gourou::WARN) | ||||
| static int downloadProgress(void *clientp, curl_off_t dltotal, curl_off_t dlnow, | ||||
| 			    curl_off_t ultotal, curl_off_t ulnow) | ||||
| { | ||||
| // For "big" files only | ||||
|     if (dltotal >= DISPLAY_THRESHOLD && gourou::logLevel >= gourou::WARN) | ||||
|     { | ||||
| 	int percent = 0; | ||||
| 	if (bytesTotal) | ||||
| 	    percent = (bytesReceived * 100) / bytesTotal; | ||||
| 	if (dltotal) | ||||
| 	    percent = (dlnow * 100) / dltotal; | ||||
|  | ||||
| 	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) | ||||
| { | ||||
|     QNetworkRequest request(QUrl(URL.c_str())); | ||||
|     QNetworkAccessManager networkManager; | ||||
|     QByteArray replyData; | ||||
|     gourou::ByteArray replyData; | ||||
|     std::map<std::string, std::string> localHeaders; | ||||
|  | ||||
|     if (!responseHeaders) | ||||
| 	responseHeaders = &localHeaders; | ||||
|      | ||||
|     GOUROU_LOG(gourou::INFO, "Send request to " << URL); | ||||
|     if (POSTData.size()) | ||||
|     { | ||||
| 	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()) | ||||
| 	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"); | ||||
| 	return sendHTTPRequest(location.constData(), POSTData, contentType, responseHeaders); | ||||
| 	curl_easy_setopt(curl, CURLOPT_POST, 1L); | ||||
| 	curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, POSTData.size()); | ||||
| 	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, POSTData.data()); | ||||
|     } | ||||
|  | ||||
|     if (reply->error() != QNetworkReply::NoError) | ||||
| 	EXCEPTION(gourou::CLIENT_NETWORK_ERROR, "Error " << reply->errorString().toStdString()); | ||||
|     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlRead); | ||||
|     curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&replyData); | ||||
|  | ||||
|     QList<QByteArray> headers = reply->rawHeaderList(); | ||||
|     for (int i = 0; i < headers.size(); ++i) { | ||||
| 	if (gourou::logLevel >= gourou::DEBUG) | ||||
| 	    std::cout << headers[i].constData() << " : "  << reply->rawHeader(headers[i]).constData() << std::endl; | ||||
| 	if (responseHeaders) | ||||
| 	    (*responseHeaders)[headers[i].constData()] = reply->rawHeader(headers[i]).constData(); | ||||
|     } | ||||
|     curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curlHeaders); | ||||
|     curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void*)responseHeaders); | ||||
|      | ||||
|     curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, downloadProgress); | ||||
|     curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); | ||||
|      | ||||
|     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) | ||||
| 	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()); | ||||
|     } | ||||
| 	 | ||||
|     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, | ||||
|   | ||||
							
								
								
									
										127
									
								
								utils/utils_common.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								utils/utils_common.cpp
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										64
									
								
								utils/utils_common.h
									
									
									
									
									
										Normal 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 | ||||
		Reference in New Issue
	
	Block a user