Compare commits

...

4 commits

Author SHA1 Message Date
Radon Rosborough
d7bd98e719 Use -fmacro-prefix-map for utils
The __FILE__ macro is used in the EXCEPTION macro to report the file
name alongside error messages. This macro reports the file name
exactly as it is passed to the compiler. For most source files in
libgourou this is a nice relative path such as "src/libgourou.cpp".
However, for EXCEPTION instances in libgourou_common.h, the compiler
flag is "-I$(ROOT)/include", where $(ROOT) is an absolute path passed
from the higher Makefile. This results in an absolute path to the
build directory being hardcoded into the utils shared library and
binaries, and reported in error messages. Besides being less readable
than the more common relative paths, this triggers warnings from
packaging tools that detect inadvertent references to temporary build
directories that end up in compiled binaries and might indicate a bug.

There is a GCC feature -fmacro-prefix-map which allows to perform
substition on the values that are used for __FILE__. Use that option
to strip out the absolute path component, without changing any
functionality.

The feature was added to GCC on 2018-01-18 and released in GCC 8.1.0.

7365279fca
2026-03-14 13:51:40 +01:00
Grégory Soutadé
72cb22ad2a Refresh curl download percent only when updated 2026-02-17 20:07:57 +01:00
Grégory Soutadé
b44b988966 Fix bug in utils with -o and -O options 2026-02-01 08:56:27 +01:00
Grégory Soutadé
76cab18667 Delete all referenced objects deleted by libgourou during PDF DRM removal 2026-01-31 20:31:44 +01:00
10 changed files with 103 additions and 51 deletions

View file

@ -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);

View file

@ -6,7 +6,7 @@ TARGETS=$(TARGET_BINARIES) launcher
MAN_PAGES=acsmdownloader adept_activate adept_remove adept_loan_mgt
CXXFLAGS=-Wall -fPIC -I$(ROOT)/include -fdata-sections -ffunction-sections
CXXFLAGS=-Wall -fPIC -I$(ROOT)/include -fmacro-prefix-map=$(ROOT)/= -fdata-sections -ffunction-sections
STATIC_DEP=
# LDFLAGS += -Wl,--gc-sections

View file

@ -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;

View file

@ -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;

View file

@ -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());

View file

@ -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;

View file

@ -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++)
{

View file

@ -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);

View file

@ -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);
}

View file

@ -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