ACSMDownloader

ACSMDownloader Git Source Tree

Root/src/acsmdownloader.cpp

1/*
2 Copyright 2021 Grégory Soutadé
3
4 This is a free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 It is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with it. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include <unistd.h>
19#include <getopt.h>
20
21#include <iostream>
22#include <log.h>
23
24#include <QFile>
25#include <QCoreApplication>
26
27#include <dp.h>
28#include <rmsdk_wrapper.h>
29
30#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
31
32int verbose = INFO;
33
34static const char* deviceFile = "device.xml";
35static const char* activationFile = "activation.xml";
36static const char* devicekeyFile = "devicesalt";
37static const char* acsmFile = 0;
38static const char* outputFile = 0;
39static const char* outputDir = 0;
40static const char* defaultDirs[] = {
41 ".adept/",
42 "./adobe-digital-editions/",
43 "./.adobe-digital-editions/"
44};
45
46class ACSMDownloader
47{
48public:
49 ACSMDownloader(QCoreApplication* app):
50app(app)
51 {
52
53 }
54
55 static void* run(void* param)
56 {
57ACSMDownloader* _this;
58
59LOG_FUNC();
60
61int ret = dp::platformInit(0xFFFFFFFF);
62
63if (ret) {
64 LOG(ERROR, "Error platform init " << ret);
65 _this->app->exit(ret);
66 return 0;
67}
68
69dp::cryptRegisterOpenSSL();
70dp::documentRegisterEPUB();
71dp::documentRegisterPDF();
72
73LOG(DEBUG, "Create Adobe objects");
74
75try
76{
77 MockDRMProcessorClient processorClient(outputDir, outputFile);
78 MockDevice device(&processorClient, deviceFile, activationFile, devicekeyFile);
79 MockProvider provider(&device);
80 device.setProvider(&provider);
81 dpdev::DeviceProvider::addProvider(&provider);
82
83 MockNetProvider netProvider;
84 dpnet::NetProvider::setProvider(&netProvider);
85
86 adept::DRMProviderImpl* _prov = rmsdk::getProvider();
87
88 LOG(DEBUG, "Create DRM Processor");
89 adept::DRMProcessorImpl* drmprocessor = _prov->createDRMProcessor(&processorClient, &device);
90
91 processorClient.setProcessor(drmprocessor);
92
93 unsigned char* buffer;
94 int buffer_size;
95 MockDevice::readFile(acsmFile, &buffer, &buffer_size, true);
96
97 LOG(DEBUG, "Init workflow ");
98
99 drmprocessor->initWorkflows(WORKFLOW_AUTH_SIGN_IN|WORKFLOW_FULFILLMENT|WORKFLOW_DOWNLOAD|WORKFLOW_NOTIFICATION, dp::Data(buffer, buffer_size));
100
101 LOG(DEBUG, "Start work");
102 drmprocessor->startWorkflows(WORKFLOW_AUTH_SIGN_IN|WORKFLOW_FULFILLMENT|WORKFLOW_DOWNLOAD|WORKFLOW_NOTIFICATION);
103 delete[] buffer;
104
105 LOG(DEBUG, "Bye bye");
106
107 ret = (int)processorClient.getErrors();
108}
109catch(std::exception& e)
110{
111 LOG(ERROR, e.what());
112 ret = 1;
113}
114
115_this->app->exit(ret);
116
117return 0;
118 }
119
120private:
121 QCoreApplication* app;
122};
123
124static const char* findFile(const char* filename, bool inDefaultDirs=true)
125{
126 QFile file(filename);
127
128 if (file.exists())
129return strdup(filename);
130
131 if (!inDefaultDirs) return 0;
132
133 for (int i=0; i<(int)ARRAY_SIZE(defaultDirs); i++)
134 {
135uft::String path = uft::String(defaultDirs[i]) + filename;
136file.setFileName(path.c_str());
137if (file.exists())
138 return strdup(path.c_str());
139 }
140
141 return 0;
142}
143
144static void usage(void)
145{
146 std::cout << "Download EPUB file from ACSM request file" << std::endl;
147
148 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;
149
150 std::cout << " " << "-d|--device-file" << "\t" << "device.xml file from eReader" << std::endl;
151 std::cout << " " << "-a|--activation-file" << "\t" << "activation.xml file from eReader" << std::endl;
152 std::cout << " " << "-k|--device-key-file" << "\t" << "private device key file (eg devicesalt/devkey.bin) from eReader" << std::endl;
153 std::cout << " " << "-O|--output-dir" << "\t" << "Optional output directory were to put result (default ./)" << std::endl;
154 std::cout << " " << "-o|--output-file" << "\t" << "Optional output epub filename (default <title.epub>)" << std::endl;
155 std::cout << " " << "-f|--acsm-file" << "\t" << "ACSM request file for epub download" << std::endl;
156 std::cout << " " << "-v|--verbose" << "\t\t" << "Increase verbosity, can be set multiple times" << std::endl;
157 std::cout << " " << "-h|--help" << "\t\t" << "This help" << std::endl;
158
159 std::cout << std::endl;
160 std::cout << "Device file, activation file and device key file are optionals. If not set, they are looked into :" << std::endl;
161 std::cout << " * Current directory" << std::endl;
162 std::cout << " * .adept" << std::endl;
163 std::cout << " * adobe-digital-editions directory" << std::endl;
164 std::cout << " * .adobe-digital-editions directory" << std::endl;
165}
166
167int main(int argc, char** argv)
168{
169 int c, ret = -1;
170
171 const char** files[] = {&devicekeyFile, &deviceFile, &activationFile};
172
173 while (1) {
174int option_index = 0;
175static struct option long_options[] = {
176 {"device-file", required_argument, 0, 'd' },
177 {"activation-file", required_argument, 0, 'a' },
178 {"device-key-file", required_argument, 0, 'k' },
179 {"output-dir", required_argument, 0, 'O' },
180 {"output-file", required_argument, 0, 'o' },
181 {"acsm-file", required_argument, 0, 'f' },
182 {"verbose", no_argument, 0, 'v' },
183 {"help", no_argument, 0, 'h' },
184 {0, 0, 0, 0 }
185};
186
187c = getopt_long(argc, argv, "d:a:k:O:o:f:vh",
188 long_options, &option_index);
189if (c == -1)
190 break;
191
192switch (c) {
193case 'd':
194 deviceFile = optarg;
195 break;
196case 'a':
197 activationFile = optarg;
198 break;
199case 'k':
200 devicekeyFile = optarg;
201 break;
202case 'f':
203 acsmFile = optarg;
204 break;
205case 'O':
206 outputDir = optarg;
207 break;
208case 'o':
209 outputFile = optarg;
210 break;
211case 'v':
212 verbose++;
213 break;
214case 'h':
215 usage();
216 return 0;
217 break;
218default:
219 usage();
220 return -1;
221}
222 }
223
224 if (!acsmFile || (outputDir && !outputDir[0]) ||
225(outputFile && !outputFile[0]))
226 {
227usage();
228return -1;
229 }
230
231 int i;
232 for (i=0; i<(int)ARRAY_SIZE(files); i++)
233 {
234*files[i] = findFile(*files[i]);
235if (!*files[i])
236{
237 LOG(ERROR, "Error : " << *files[i] << " doesn't exists");
238 return -1;
239}
240 }
241
242 QFile file(acsmFile);
243 if (!file.exists())
244 {
245LOG(ERROR, "Error : " << acsmFile << " doesn't exists");
246return -1;
247 }
248
249 LOG(INFO, "RMSDK Version " << dp::getVersionInfo("hobbes").utf8());
250
251 QCoreApplication app(argc, argv);
252
253 ACSMDownloader downloader(&app);
254 pthread_t thread;
255 pthread_create(&thread, NULL, ACSMDownloader::run, (void*)&downloader);
256
257 ret = app.exec();
258
259 for (i=0; i<(int)ARRAY_SIZE(files); i++)
260free((void*)*files[i]);
261
262 return ret;
263}

Archive Download this file

Branches