Initial commit
This commit is contained in:
263
src/acsmdownloader.cpp
Normal file
263
src/acsmdownloader.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
Copyright 2021 Grégory Soutadé
|
||||
|
||||
This is a free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with it. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <log.h>
|
||||
|
||||
#include <QFile>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include <dp.h>
|
||||
#include <rmsdk_wrapper.h>
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
|
||||
|
||||
int verbose = INFO;
|
||||
|
||||
static const char* deviceFile = "device.xml";
|
||||
static const char* activationFile = "activation.xml";
|
||||
static const char* devicekeyFile = "devicesalt";
|
||||
static const char* acsmFile = 0;
|
||||
static const char* outputFile = 0;
|
||||
static const char* outputDir = 0;
|
||||
static const char* defaultDirs[] = {
|
||||
".adept/",
|
||||
"./adobe-digital-editions/",
|
||||
"./.adobe-digital-editions/"
|
||||
};
|
||||
|
||||
class ACSMDownloader
|
||||
{
|
||||
public:
|
||||
ACSMDownloader(QCoreApplication* app):
|
||||
app(app)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void* run(void* param)
|
||||
{
|
||||
ACSMDownloader* _this;
|
||||
|
||||
LOG_FUNC();
|
||||
|
||||
int ret = dp::platformInit(0xFFFFFFFF);
|
||||
|
||||
if (ret) {
|
||||
LOG(ERROR, "Error platform init " << ret);
|
||||
_this->app->exit(ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dp::cryptRegisterOpenSSL();
|
||||
dp::documentRegisterEPUB();
|
||||
dp::documentRegisterPDF();
|
||||
|
||||
LOG(DEBUG, "Create Adobe objects");
|
||||
|
||||
try
|
||||
{
|
||||
MockDRMProcessorClient processorClient(outputDir, outputFile);
|
||||
MockDevice device(&processorClient, deviceFile, activationFile, devicekeyFile);
|
||||
MockProvider provider(&device);
|
||||
device.setProvider(&provider);
|
||||
dpdev::DeviceProvider::addProvider(&provider);
|
||||
|
||||
MockNetProvider netProvider;
|
||||
dpnet::NetProvider::setProvider(&netProvider);
|
||||
|
||||
adept::DRMProviderImpl* _prov = rmsdk::getProvider();
|
||||
|
||||
LOG(DEBUG, "Create DRM Processor");
|
||||
adept::DRMProcessorImpl* drmprocessor = _prov->createDRMProcessor(&processorClient, &device);
|
||||
|
||||
processorClient.setProcessor(drmprocessor);
|
||||
|
||||
unsigned char* buffer;
|
||||
int buffer_size;
|
||||
MockDevice::readFile(acsmFile, &buffer, &buffer_size, true);
|
||||
|
||||
LOG(DEBUG, "Init workflow ");
|
||||
|
||||
drmprocessor->initWorkflows(WORKFLOW_AUTH_SIGN_IN|WORKFLOW_FULFILLMENT|WORKFLOW_DOWNLOAD|WORKFLOW_NOTIFICATION, dp::Data(buffer, buffer_size));
|
||||
|
||||
LOG(DEBUG, "Start work");
|
||||
drmprocessor->startWorkflows(WORKFLOW_AUTH_SIGN_IN|WORKFLOW_FULFILLMENT|WORKFLOW_DOWNLOAD|WORKFLOW_NOTIFICATION);
|
||||
delete[] buffer;
|
||||
|
||||
LOG(DEBUG, "Bye bye");
|
||||
|
||||
ret = (int)processorClient.getErrors();
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
LOG(ERROR, e.what());
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
_this->app->exit(ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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++)
|
||||
{
|
||||
uft::String path = uft::String(defaultDirs[i]) + filename;
|
||||
file.setFileName(path.c_str());
|
||||
if (file.exists())
|
||||
return strdup(path.c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
std::cout << "Download EPUB file from ACSM request file" << std::endl;
|
||||
|
||||
std::cout << "Usage: ./acsmdownloader [(-d|--device-file) device.xml] [(-a|--activation-file) activation.xml] [(-s|--device-key-file) devicesalt] [(-O|--output-dir) dir] [(-o|--output-file) output.epub] [(-v|--verbose)] [(-h|--help)] (-f|--acsm-file) file.acsm" << std::endl << std::endl;
|
||||
|
||||
std::cout << " " << "-d|--device-file" << "\t" << "device.xml file from eReader" << std::endl;
|
||||
std::cout << " " << "-a|--activation-file" << "\t" << "activation.xml file from eReader" << std::endl;
|
||||
std::cout << " " << "-k|--device-key-file" << "\t" << "private device key file (eg devicesalt/devkey.bin) from eReader" << 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 epub filename (default <title.epub>)" << std::endl;
|
||||
std::cout << " " << "-f|--acsm-file" << "\t" << "ACSM request file for epub download" << std::endl;
|
||||
std::cout << " " << "-v|--verbose" << "\t\t" << "Increase verbosity, can be set multiple times" << std::endl;
|
||||
std::cout << " " << "-h|--help" << "\t\t" << "This help" << std::endl;
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << "Device file, activation file and device key file are optionals. If not set, they are looked into :" << std::endl;
|
||||
std::cout << " * Current directory" << std::endl;
|
||||
std::cout << " * .adept" << std::endl;
|
||||
std::cout << " * adobe-digital-editions directory" << std::endl;
|
||||
std::cout << " * .adobe-digital-editions directory" << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int c, ret = -1;
|
||||
|
||||
const char** files[] = {&devicekeyFile, &deviceFile, &activationFile};
|
||||
|
||||
while (1) {
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{"device-file", required_argument, 0, 'd' },
|
||||
{"activation-file", required_argument, 0, 'a' },
|
||||
{"device-key-file", required_argument, 0, 'k' },
|
||||
{"output-dir", required_argument, 0, 'O' },
|
||||
{"output-file", required_argument, 0, 'o' },
|
||||
{"acsm-file", required_argument, 0, 'f' },
|
||||
{"verbose", no_argument, 0, 'v' },
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "d:a:k:O:o:f:vh",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'd':
|
||||
deviceFile = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
activationFile = optarg;
|
||||
break;
|
||||
case 'k':
|
||||
devicekeyFile = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
acsmFile = optarg;
|
||||
break;
|
||||
case 'O':
|
||||
outputDir = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
outputFile = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!acsmFile || (outputDir && !outputDir[0]) ||
|
||||
(outputFile && !outputFile[0]))
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i=0; i<(int)ARRAY_SIZE(files); i++)
|
||||
{
|
||||
*files[i] = findFile(*files[i]);
|
||||
if (!*files[i])
|
||||
{
|
||||
LOG(ERROR, "Error : " << *files[i] << " doesn't exists");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
QFile file(acsmFile);
|
||||
if (!file.exists())
|
||||
{
|
||||
LOG(ERROR, "Error : " << acsmFile << " doesn't exists");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG(INFO, "RMSDK Version " << dp::getVersionInfo("hobbes").utf8());
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
ACSMDownloader downloader(&app);
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, NULL, ACSMDownloader::run, (void*)&downloader);
|
||||
|
||||
ret = app.exec();
|
||||
|
||||
for (i=0; i<(int)ARRAY_SIZE(files); i++)
|
||||
free((void*)*files[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user