Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 72cb22ad2a | |||
| b44b988966 | |||
| 76cab18667 | |||
| 2387dff2cb | |||
| a7cfd3ef89 | |||
| 772abdd2f9 | |||
| 1605656c73 |
@@ -12,6 +12,8 @@ LDFLAGS = -lpugixml
|
||||
|
||||
VERSION := $(shell cat include/libgourou.h |grep LIBGOUROU_VERSION|cut -d '"' -f2)
|
||||
|
||||
UNAME := $(shell uname -s)
|
||||
|
||||
BUILD_STATIC ?= 0
|
||||
BUILD_SHARED ?= 1
|
||||
BUILD_UTILS ?= 1
|
||||
@@ -27,8 +29,13 @@ ifneq ($(BUILD_STATIC), 0)
|
||||
STATIC_UTILS=1
|
||||
endif
|
||||
ifneq ($(BUILD_SHARED), 0)
|
||||
TARGETS += libgourou.so
|
||||
TARGET_LIBRARIES += libgourou.so libgourou.so.$(VERSION)
|
||||
ifeq ($(UNAME), Darwin)
|
||||
TARGETS += libgourou.dylib
|
||||
TARGET_LIBRARIES += libgourou.dylib libgourou.dylib.$(VERSION)
|
||||
else
|
||||
TARGETS += libgourou.so
|
||||
TARGET_LIBRARIES += libgourou.so libgourou.so.$(VERSION)
|
||||
endif
|
||||
endif
|
||||
ifneq ($(BUILD_UTILS), 0)
|
||||
TARGETS += build_utils
|
||||
@@ -82,6 +89,12 @@ libgourou.so.$(VERSION): $(OBJECTS) $(UPDFPARSERLIB)
|
||||
libgourou.so: libgourou.so.$(VERSION)
|
||||
ln -f -s $^ $@
|
||||
|
||||
libgourou.dylib.$(VERSION): $(OBJECTS) $(UPDFPARSERLIB)
|
||||
$(CXX) $^ $(LDFLAGS) -o $@ -shared
|
||||
|
||||
libgourou.dylib: libgourou.dylib.$(VERSION)
|
||||
ln -f -s $^ $@
|
||||
|
||||
build_utils: $(TARGET_LIBRARIES)
|
||||
$(MAKE) -C utils ROOT=$(PWD) CXX=$(CXX) AR=$(AR) DEBUG=$(DEBUG) STATIC_UTILS=$(STATIC_UTILS) DESTDIR=$(DESTDIR) PREFIX=$(PREFIX)
|
||||
|
||||
|
||||
@@ -165,8 +165,8 @@ namespace gourou
|
||||
Exception(const Exception& other)
|
||||
{
|
||||
this->code = other.code;
|
||||
this->line = line;
|
||||
this->file = file;
|
||||
this->line = other.line;
|
||||
this->file = other.file;
|
||||
this->fullmessage = strdup(other.fullmessage);
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ namespace gourou
|
||||
|
||||
private:
|
||||
int code, line;
|
||||
const char* message, *file;
|
||||
const char* file;
|
||||
char* fullmessage;
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -202,7 +202,7 @@ namespace gourou
|
||||
char* tmp = new char[_length*2+1];
|
||||
|
||||
for(int i=0; i<(int)_length; i++)
|
||||
sprintf(&tmp[i*2], "%02x", _data[i]);
|
||||
snprintf(&tmp[i*2], (_length-i)*2+1, "%02x", _data[i]);
|
||||
|
||||
tmp[_length*2] = 0;
|
||||
|
||||
|
||||
+27
-3
@@ -525,7 +525,7 @@ namespace gourou
|
||||
time_t expirationTime = parseDateTime(expiration.c_str(), "%Y-%m-%dT%H:%M:%S");
|
||||
|
||||
if (time(NULL) > expirationTime)
|
||||
GOUROU_LOG(WARN, "WARNING: ACSM file expired (" << expiration << "). It may not work");
|
||||
GOUROU_LOG(WARN, "WARNING: ACSM file expired (" << expiration << "), It may not work.");
|
||||
}
|
||||
|
||||
// Build req file
|
||||
@@ -1342,7 +1342,7 @@ namespace gourou
|
||||
|
||||
uPDFParser::Integer* ebxVersion;
|
||||
std::vector<uPDFParser::Object*> objects = parser.objects();
|
||||
std::vector<uPDFParser::Object*>::iterator it;
|
||||
std::vector<uPDFParser::Object*>::iterator it, ebxIt;
|
||||
std::vector<uPDFParser::Object*>::reverse_iterator rIt;
|
||||
std::vector<uPDFParser::Object*> ebxObjects;
|
||||
unsigned char decryptedKey[16];
|
||||
@@ -1513,10 +1513,34 @@ namespace gourou
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete objects that reference EBX objects, except in trailer */
|
||||
for(it = objects.begin(); it != objects.end(); it++)
|
||||
{
|
||||
uPDFParser::Object* object = *it;
|
||||
|
||||
if (object->hasKey("Encrypt") && (*object)["Encrypt"]->type() == uPDFParser::DataType::REFERENCE)
|
||||
{
|
||||
uPDFParser::Reference* encrypt = (uPDFParser::Reference*)(*object)["Encrypt"];
|
||||
|
||||
/* Delete EBX objects */
|
||||
for(ebxIt = ebxObjects.begin(); ebxIt != ebxObjects.end(); ebxIt++)
|
||||
{
|
||||
if (encrypt->value() == (*ebxIt)->objectId())
|
||||
{
|
||||
GOUROU_LOG(ERROR, "Delete stream id " << object->objectId());
|
||||
|
||||
parser.removeObject(object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete EBX objects */
|
||||
for(it = ebxObjects.begin(); it != ebxObjects.end(); it++)
|
||||
parser.removeObject(*it);
|
||||
|
||||
uPDFParser::Object& trailer = parser.getTrailer();
|
||||
uPDFParser::Object& trailer = parser.getTrailer();
|
||||
trailer.deleteKey("Encrypt");
|
||||
|
||||
parser.write(filenameOut);
|
||||
|
||||
+24
-22
@@ -64,19 +64,18 @@ public:
|
||||
if (exportPrivateKey)
|
||||
{
|
||||
std::string filename;
|
||||
if (!outputFile)
|
||||
filename = std::string("Adobe_PrivateLicenseKey--") + user->getUsername() + ".der";
|
||||
else
|
||||
if (outputFile)
|
||||
filename = outputFile;
|
||||
|
||||
if (outputDir)
|
||||
else
|
||||
{
|
||||
if (!fileExists(outputDir))
|
||||
mkpath(outputDir);
|
||||
|
||||
filename = std::string(outputDir) + "/" + filename;
|
||||
filename = std::string("Adobe_PrivateLicenseKey--") + user->getUsername() + ".der";
|
||||
|
||||
if (outputDir)
|
||||
filename = std::string(outputDir) + "/" + filename;
|
||||
}
|
||||
|
||||
createPath(filename.c_str());
|
||||
|
||||
processor.exportPrivateLicenseKey(filename);
|
||||
|
||||
std::cout << "Private license key exported to " << filename << std::endl;
|
||||
@@ -86,7 +85,9 @@ public:
|
||||
gourou::FulfillmentItem* item = processor.fulfill(acsmFile, notify);
|
||||
|
||||
std::string filename;
|
||||
if (!outputFile)
|
||||
if (outputFile)
|
||||
filename = outputFile;
|
||||
else
|
||||
{
|
||||
filename = item->getMetadata("title");
|
||||
if (filename == "")
|
||||
@@ -96,18 +97,13 @@ public:
|
||||
// Remove invalid characters
|
||||
std::replace(filename.begin(), filename.end(), '/', '_');
|
||||
}
|
||||
}
|
||||
else
|
||||
filename = outputFile;
|
||||
|
||||
if (outputDir)
|
||||
{
|
||||
if (!fileExists(outputDir))
|
||||
mkpath(outputDir);
|
||||
|
||||
filename = std::string(outputDir) + "/" + filename;
|
||||
if (outputDir)
|
||||
filename = std::string(outputDir) + "/" + filename;
|
||||
}
|
||||
|
||||
createPath(filename.c_str());
|
||||
|
||||
gourou::DRMProcessor::ITEM_TYPE type = processor.download(item, filename, resume);
|
||||
|
||||
if (!outputFile)
|
||||
@@ -186,8 +182,8 @@ static void usage(const char* cmd)
|
||||
std::cout << basename((char*)cmd) << " download EPUB file from ACSM request file" << std::endl << std::endl;
|
||||
std::cout << "Usage: " << basename((char*)cmd) << " [OPTIONS] file.acsm" << std::endl << std::endl;
|
||||
std::cout << "Global Options:" << std::endl;
|
||||
std::cout << " " << "-O|--output-dir" << "\t" << "Optional output directory were to put result (default ./)" << std::endl;
|
||||
std::cout << " " << "-o|--output-file" << "\t" << "Optional output filename (default <title.(epub|pdf|der)>)" << std::endl;
|
||||
std::cout << " " << "-O|--output-dir" << "\t" << "Optional output directory were to put result (default ./) (not compatible with -o)" << std::endl;
|
||||
std::cout << " " << "-o|--output-file" << "\t" << "Optional output filename (default <title.(epub|pdf|der)>) (not compatible with -O)" << std::endl;
|
||||
std::cout << " " << "-f|--acsm-file" << "\t" << "Backward compatibility: ACSM request file for epub download" << std::endl;
|
||||
std::cout << " " << "-e|--export-private-key"<< "\t" << "Export private key in DER format" << std::endl;
|
||||
std::cout << " " << "-r|--resume" << "\t\t" << "Try to resume download (in case of previous failure)" << std::endl;
|
||||
@@ -309,6 +305,12 @@ int main(int argc, char** argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (outputDir && outputFile)
|
||||
{
|
||||
std::cout << "Error : you cannot use both -o and -O" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ACSMDownloader downloader;
|
||||
|
||||
int i;
|
||||
@@ -339,7 +341,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!fileExists(acsmFile))
|
||||
if (!pathExists(acsmFile))
|
||||
{
|
||||
std::cout << "Error : " << acsmFile << " doesn't exists" << std::endl;
|
||||
ret = -1;
|
||||
|
||||
@@ -240,7 +240,7 @@ int main(int argc, char** argv)
|
||||
if (_outputDir[0] == '.' || _outputDir[0] != '/')
|
||||
{
|
||||
// realpath doesn't works if file/dir doesn't exists
|
||||
if (fileExists(_outputDir))
|
||||
if (pathExists(_outputDir))
|
||||
outputDir = strdup(realpath(_outputDir, 0));
|
||||
else
|
||||
outputDir = strdup(abspath(_outputDir));
|
||||
@@ -250,7 +250,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
std::string pass;
|
||||
if (fileExists(outputDir))
|
||||
if (pathExists(outputDir))
|
||||
{
|
||||
int key;
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ private:
|
||||
|
||||
std::string loanDir = std::string(adeptDir) + std::string("/") + LOANS_DIR;
|
||||
|
||||
if (!fileExists(loanDir.c_str()))
|
||||
if (!pathExists(loanDir.c_str()))
|
||||
return;
|
||||
|
||||
dp = opendir (loanDir.c_str());
|
||||
|
||||
+17
-12
@@ -81,19 +81,16 @@ public:
|
||||
gourou::DRMProcessor processor(&client, deviceFile, activationFile, devicekeyFile);
|
||||
|
||||
std::string filename;
|
||||
if (!outputFile)
|
||||
filename = std::string(inputFile);
|
||||
else
|
||||
if (outputFile)
|
||||
filename = outputFile;
|
||||
|
||||
if (outputDir)
|
||||
else
|
||||
{
|
||||
if (!fileExists(outputDir))
|
||||
mkpath(outputDir);
|
||||
filename = std::string(inputFile);
|
||||
|
||||
filename = std::string(outputDir) + "/" + filename;
|
||||
if (outputDir)
|
||||
filename = std::string(outputDir) + "/" + filename;
|
||||
}
|
||||
|
||||
|
||||
if (endsWith(filename, ".epub"))
|
||||
type = gourou::DRMProcessor::ITEM_TYPE::EPUB;
|
||||
else if (endsWith(filename, ".pdf"))
|
||||
@@ -102,7 +99,9 @@ public:
|
||||
{
|
||||
EXCEPTION(gourou::DRM_FORMAT_NOT_SUPPORTED, "Unsupported file format of " << filename);
|
||||
}
|
||||
|
||||
|
||||
createPath(filename.c_str());
|
||||
|
||||
if (inputFile != filename)
|
||||
{
|
||||
unlink(filename.c_str());
|
||||
@@ -147,8 +146,8 @@ static void usage(const char* cmd)
|
||||
std::cout << "Usage: " << basename((char*)cmd) << " [OPTIONS] file(.epub|pdf)" << std::endl << std::endl;
|
||||
|
||||
std::cout << "Global Options:" << std::endl;
|
||||
std::cout << " " << "-O|--output-dir" << "\t" << "Optional output directory were to put result (default ./)" << std::endl;
|
||||
std::cout << " " << "-o|--output-file" << "\t" << "Optional output filename (default inplace DRM removal>)" << std::endl;
|
||||
std::cout << " " << "-O|--output-dir" << "\t" << "Optional output directory were to put result (default ./) (not compatible with -o)" << std::endl;
|
||||
std::cout << " " << "-o|--output-file" << "\t" << "Optional output filename (default inplace DRM removal>) (not compatible with -O)" << std::endl;
|
||||
std::cout << " " << "-f|--input-file" << "\t" << "Backward compatibility: EPUB/PDF file to process" << std::endl;
|
||||
std::cout << " " << "-v|--verbose" << "\t\t" << "Increase verbosity, can be set multiple times" << std::endl;
|
||||
std::cout << " " << "-V|--version" << "\t\t" << "Display libgourou version" << std::endl;
|
||||
@@ -259,6 +258,12 @@ int main(int argc, char** argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (outputDir && outputFile)
|
||||
{
|
||||
std::cout << "Error : you cannot use both -o and -O" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ADEPTRemove remover;
|
||||
|
||||
int i;
|
||||
|
||||
@@ -147,6 +147,7 @@ void DRMProcessorClientImpl::randBytes(unsigned char* bytesOut, unsigned int len
|
||||
#define HTTP_REQ_MAX_RETRY 5
|
||||
#define DISPLAY_THRESHOLD 10*1024 // Threshold to display download progression
|
||||
static unsigned downloadedBytes;
|
||||
static int lastPercent = -1;
|
||||
|
||||
static int downloadProgress(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
|
||||
curl_off_t ultotal, curl_off_t ulnow)
|
||||
@@ -158,7 +159,11 @@ static int downloadProgress(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
|
||||
if (dltotal)
|
||||
percent = (dlnow * 100) / dltotal;
|
||||
|
||||
std::cout << "\rDownload " << percent << "%" << std::flush;
|
||||
if (lastPercent != percent)
|
||||
{
|
||||
std::cout << "\rDownload " << percent << "%" << std::flush;
|
||||
lastPercent = percent;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -279,6 +284,7 @@ std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, cons
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, downloadProgress);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
|
||||
lastPercent = -1;
|
||||
|
||||
for (int i=0; i<HTTP_REQ_MAX_RETRY; i++)
|
||||
{
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ int main(int argc, char** argv)
|
||||
|
||||
fullPath = std::string(mountPoint) + util;
|
||||
|
||||
if (std::string(util) == "launcher" || !fileExists(fullPath.c_str()))
|
||||
if (std::string(util) == "launcher" || !pathExists(fullPath.c_str()))
|
||||
fullPath = std::string(mountPoint) + DEFAULT_UTIL;
|
||||
|
||||
free(argv0);
|
||||
|
||||
+16
-6
@@ -33,6 +33,7 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -51,10 +52,10 @@ void version(void)
|
||||
std::cout << "Current libgourou version : " << gourou::DRMProcessor::VERSION << std::endl ;
|
||||
}
|
||||
|
||||
bool fileExists(const char* filename)
|
||||
bool pathExists(const char* path)
|
||||
{
|
||||
struct stat _stat;
|
||||
int ret = stat(filename, &_stat);
|
||||
int ret = stat(path, &_stat);
|
||||
|
||||
return (ret == 0);
|
||||
}
|
||||
@@ -67,15 +68,15 @@ const char* findFile(const char* filename, bool inDefaultDirs)
|
||||
if (adeptDir && adeptDir[0])
|
||||
{
|
||||
path = adeptDir + std::string("/") + filename;
|
||||
if (fileExists(path.c_str()))
|
||||
if (pathExists(path.c_str()))
|
||||
return strdup(path.c_str());
|
||||
}
|
||||
|
||||
path = gourou::DRMProcessor::getDefaultAdeptDir() + filename;
|
||||
if (fileExists(path.c_str()))
|
||||
if (pathExists(path.c_str()))
|
||||
return strdup(path.c_str());
|
||||
|
||||
if (fileExists(filename))
|
||||
if (pathExists(filename))
|
||||
return strdup(filename);
|
||||
|
||||
if (!inDefaultDirs) return 0;
|
||||
@@ -83,7 +84,7 @@ const char* findFile(const char* filename, bool inDefaultDirs)
|
||||
for (int i=0; i<(int)ARRAY_SIZE(defaultDirs); i++)
|
||||
{
|
||||
path = std::string(defaultDirs[i]) + filename;
|
||||
if (fileExists(path.c_str()))
|
||||
if (pathExists(path.c_str()))
|
||||
return strdup(path.c_str());
|
||||
}
|
||||
|
||||
@@ -152,3 +153,12 @@ void fileCopy(const char* in, const char* out)
|
||||
close (fdIn);
|
||||
close (fdOut);
|
||||
}
|
||||
|
||||
void createPath(const char* filename)
|
||||
{
|
||||
char* basepath = strdup(filename);
|
||||
char* outputDir = dirname(basepath);
|
||||
if (outputDir && !pathExists(outputDir))
|
||||
mkpath(outputDir);
|
||||
free(basepath);
|
||||
}
|
||||
|
||||
@@ -50,9 +50,9 @@ void version(void);
|
||||
const char* findFile(const char* filename, bool inDefaultDirs=true);
|
||||
|
||||
/**
|
||||
* @brief Does the file (or directory exists)
|
||||
* @brief Does the file (or directory) exists
|
||||
*/
|
||||
bool fileExists(const char* filename);
|
||||
bool pathExists(const char* path);
|
||||
|
||||
/**
|
||||
* @brief Recursively created dir
|
||||
@@ -64,4 +64,9 @@ void mkpath(const char *dir);
|
||||
*/
|
||||
void fileCopy(const char* in, const char* out);
|
||||
|
||||
/**
|
||||
* @brief Create intermediate directories if it does not exists
|
||||
*/
|
||||
void createPath(const char* filename);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user