Add resume option to acsmdownloader
This commit is contained in:
@@ -42,6 +42,7 @@ static const char* acsmFile = 0;
|
||||
static bool exportPrivateKey = false;
|
||||
static const char* outputFile = 0;
|
||||
static const char* outputDir = 0;
|
||||
static bool resume = false;
|
||||
|
||||
|
||||
class ACSMDownloader
|
||||
@@ -104,7 +105,7 @@ public:
|
||||
filename = std::string(outputDir) + "/" + filename;
|
||||
}
|
||||
|
||||
gourou::DRMProcessor::ITEM_TYPE type = processor.download(item, filename);
|
||||
gourou::DRMProcessor::ITEM_TYPE type = processor.download(item, filename, resume);
|
||||
|
||||
if (!outputFile)
|
||||
{
|
||||
@@ -133,7 +134,7 @@ static void usage(const char* cmd)
|
||||
{
|
||||
std::cout << "Download EPUB file from ACSM request file" << std::endl;
|
||||
|
||||
std::cout << "Usage: " << cmd << " [(-d|--device-file) device.xml] [(-a|--activation-file) activation.xml] [(-k|--device-key-file) devicesalt] [(-O|--output-dir) dir] [(-o|--output-file) output(.epub|.pdf|.der)] [(-v|--verbose)] [(-h|--help)] (-f|--acsm-file) file.acsm|(-e|--export-private-key)" << std::endl << std::endl;
|
||||
std::cout << "Usage: " << cmd << " [(-d|--device-file) device.xml] [(-a|--activation-file) activation.xml] [(-k|--device-key-file) devicesalt] [(-O|--output-dir) dir] [(-o|--output-file) output(.epub|.pdf|.der)] [(-r|--resume)] [(-v|--verbose)] [(-h|--help)] (-f|--acsm-file) file.acsm|(-e|--export-private-key)" << 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;
|
||||
@@ -142,6 +143,7 @@ static void usage(const char* cmd)
|
||||
std::cout << " " << "-o|--output-file" << "\t" << "Optional output filename (default <title.(epub|pdf|der)>)" << std::endl;
|
||||
std::cout << " " << "-f|--acsm-file" << "\t" << "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;
|
||||
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;
|
||||
std::cout << " " << "-h|--help" << "\t\t" << "This help" << std::endl;
|
||||
@@ -171,13 +173,14 @@ int main(int argc, char** argv)
|
||||
{"output-file", required_argument, 0, 'o' },
|
||||
{"acsm-file", required_argument, 0, 'f' },
|
||||
{"export-private-key",no_argument, 0, 'e' },
|
||||
{"resume", no_argument, 0, 'r' },
|
||||
{"verbose", no_argument, 0, 'v' },
|
||||
{"version", no_argument, 0, 'V' },
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "d:a:k:O:o:f:evVh",
|
||||
c = getopt_long(argc, argv, "d:a:k:O:o:f:ervVh",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
@@ -204,6 +207,9 @@ int main(int argc, char** argv)
|
||||
case 'e':
|
||||
exportPrivateKey = true;
|
||||
break;
|
||||
case 'r':
|
||||
resume = true;
|
||||
break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
@@ -175,7 +175,7 @@ static size_t curlHeaders(char *buffer, size_t size, size_t nitems, void *userda
|
||||
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, int fd)
|
||||
std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, const std::string& POSTData, const std::string& contentType, std::map<std::string, std::string>* responseHeaders, int fd, bool resume)
|
||||
{
|
||||
gourou::ByteArray replyData;
|
||||
std::map<std::string, std::string> localHeaders;
|
||||
@@ -191,6 +191,18 @@ std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, cons
|
||||
|
||||
unsigned prevDownloadedBytes;
|
||||
downloadedBytes = 0;
|
||||
if (fd && resume)
|
||||
{
|
||||
struct stat _stat;
|
||||
if (!fstat(fd, &_stat))
|
||||
{
|
||||
GOUROU_LOG(gourou::WARN, "Resume download @ " << _stat.st_size << " bytes");
|
||||
downloadedBytes = _stat.st_size;
|
||||
}
|
||||
else
|
||||
GOUROU_LOG(gourou::WARN, "Want to resume, but fstat failed");
|
||||
}
|
||||
|
||||
CURL *curl = curl_easy_init();
|
||||
CURLcode res;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
|
||||
@@ -244,7 +256,7 @@ std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, cons
|
||||
// Connexion failed, wait & retry
|
||||
if (res == CURLE_COULDNT_CONNECT)
|
||||
{
|
||||
GOUROU_LOG(gourou::WARN, "Connection failed, attempt " << (i+1) << "/" << HTTP_REQ_MAX_RETRY);
|
||||
GOUROU_LOG(gourou::WARN, "\nConnection failed, attempt " << (i+1) << "/" << HTTP_REQ_MAX_RETRY);
|
||||
}
|
||||
// Transfer failed but some data has been received
|
||||
// --> try again without incrementing tries
|
||||
@@ -252,11 +264,11 @@ std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, cons
|
||||
{
|
||||
if (prevDownloadedBytes != downloadedBytes)
|
||||
{
|
||||
GOUROU_LOG(gourou::WARN, "Connection broken, but data received, try again");
|
||||
GOUROU_LOG(gourou::WARN, "\nConnection broken, but data received, try again");
|
||||
i--;
|
||||
}
|
||||
else
|
||||
GOUROU_LOG(gourou::WARN, "Connection broken and no data received, attempt " << (i+1) << "/" << HTTP_REQ_MAX_RETRY);
|
||||
GOUROU_LOG(gourou::WARN, "\nConnection broken and no data received, attempt " << (i+1) << "/" << HTTP_REQ_MAX_RETRY);
|
||||
}
|
||||
// Other error --> fail
|
||||
else
|
||||
|
@@ -46,7 +46,7 @@ public:
|
||||
virtual void randBytes(unsigned char* bytesOut, unsigned int length);
|
||||
|
||||
/* HTTP interface */
|
||||
virtual std::string sendHTTPRequest(const std::string& URL, const std::string& POSTData=std::string(""), const std::string& contentType=std::string(""), std::map<std::string, std::string>* responseHeaders=0, int fd=0);
|
||||
virtual std::string sendHTTPRequest(const std::string& URL, const std::string& POSTData=std::string(""), const std::string& contentType=std::string(""), std::map<std::string, std::string>* responseHeaders=0, int fd=0, bool resume=false);
|
||||
|
||||
virtual void RSAPrivateEncrypt(const unsigned char* RSAKey, unsigned int RSAKeyLength,
|
||||
const RSA_KEY_TYPE keyType, const std::string& password,
|
||||
|
Reference in New Issue
Block a user