forked from soutade/libgourou
Add adept_loan_mgt util
This commit is contained in:
parent
570ad83747
commit
8fe8ba2808
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
TARGETS=acsmdownloader adept_activate adept_remove
|
TARGETS=acsmdownloader adept_activate adept_remove adept_loan_mgt
|
||||||
|
|
||||||
CXXFLAGS=-Wall -fPIC -I$(ROOT)/include -I$(ROOT)/lib/pugixml/src/
|
CXXFLAGS=-Wall -fPIC -I$(ROOT)/include -I$(ROOT)/lib/pugixml/src/
|
||||||
|
|
||||||
|
@ -18,17 +18,26 @@ else
|
||||||
CXXFLAGS += -O2
|
CXXFLAGS += -O2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
COMMON_DEPS = drmprocessorclientimpl.cpp utils_common.cpp $(STATIC_DEP)
|
COMMON_DEPS = drmprocessorclientimpl.cpp utils_common.cpp
|
||||||
|
COMMON_OBJECTS = $(COMMON_DEPS:.cpp=.o)
|
||||||
|
COMMON_LIB = utils.a
|
||||||
|
|
||||||
all: $(TARGETS)
|
all: $(TARGETS)
|
||||||
|
|
||||||
acsmdownloader: acsmdownloader.cpp $(COMMON_DEPS)
|
${COMMON_LIB}: ${COMMON_DEPS} ${STATIC_DEP}
|
||||||
|
$(CXX) $(CXXFLAGS) ${COMMON_DEPS} $(LDFLAGS) -c
|
||||||
|
$(AR) crs $@ ${COMMON_OBJECTS} $(STATIC_DEP)
|
||||||
|
|
||||||
|
acsmdownloader: acsmdownloader.cpp ${COMMON_LIB}
|
||||||
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
|
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
|
||||||
|
|
||||||
adept_activate: adept_activate.cpp $(COMMON_DEPS)
|
adept_activate: adept_activate.cpp ${COMMON_LIB}
|
||||||
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
|
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
|
||||||
|
|
||||||
adept_remove: adept_remove.cpp $(COMMON_DEPS)
|
adept_remove: adept_remove.cpp ${COMMON_LIB}
|
||||||
|
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
|
||||||
|
|
||||||
|
adept_loan_mgt: adept_loan_mgt.cpp ${COMMON_LIB}
|
||||||
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
|
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
|
@ -27,11 +27,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <libgourou.h>
|
#include <libgourou.h>
|
||||||
|
#include <libgourou_common.h>
|
||||||
|
|
||||||
#include "drmprocessorclientimpl.h"
|
#include "drmprocessorclientimpl.h"
|
||||||
#include "utils_common.h"
|
#include "utils_common.h"
|
||||||
|
|
||||||
|
@ -54,7 +57,6 @@ public:
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
DRMProcessorClientImpl client;
|
|
||||||
gourou::DRMProcessor processor(&client, deviceFile, activationFile, devicekeyFile);
|
gourou::DRMProcessor processor(&client, deviceFile, activationFile, devicekeyFile);
|
||||||
gourou::User* user = processor.getUser();
|
gourou::User* user = processor.getUser();
|
||||||
|
|
||||||
|
@ -118,6 +120,8 @@ public:
|
||||||
filename = finalName;
|
filename = finalName;
|
||||||
}
|
}
|
||||||
std::cout << "Created " << filename << std::endl;
|
std::cout << "Created " << filename << std::endl;
|
||||||
|
|
||||||
|
serializeLoanToken(item);
|
||||||
}
|
}
|
||||||
} catch(std::exception& e)
|
} catch(std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -127,6 +131,52 @@ public:
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serializeLoanToken(gourou::FulfillmentItem* item)
|
||||||
|
{
|
||||||
|
gourou::LoanToken* token = item->getLoanToken();
|
||||||
|
|
||||||
|
// No loan token available
|
||||||
|
if (!token)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pugi::xml_document doc;
|
||||||
|
|
||||||
|
pugi::xml_node decl = doc.append_child(pugi::node_declaration);
|
||||||
|
decl.append_attribute("version") = "1.0";
|
||||||
|
|
||||||
|
pugi::xml_node root = doc.append_child("loanToken");
|
||||||
|
gourou::appendTextElem(root, "id", (*token)["id"]);
|
||||||
|
gourou::appendTextElem(root, "operatorURL", (*token)["operatorURL"]);
|
||||||
|
gourou::appendTextElem(root, "validity", (*token)["validity"]);
|
||||||
|
gourou::appendTextElem(root, "name", item->getMetadata("title"));
|
||||||
|
|
||||||
|
char * activationDir = strdup(deviceFile);
|
||||||
|
activationDir = dirname(activationDir);
|
||||||
|
|
||||||
|
gourou::StringXMLWriter xmlWriter;
|
||||||
|
doc.save(xmlWriter, " ");
|
||||||
|
std::string xmlStr = xmlWriter.getResult();
|
||||||
|
|
||||||
|
// Use first bytes of SHA1(id) as filename
|
||||||
|
unsigned char sha1[gourou::SHA1_LEN];
|
||||||
|
client.digest("SHA1", (unsigned char*)(*token)["id"].c_str(), (*token)["id"].size(), sha1);
|
||||||
|
gourou::ByteArray tmp(sha1, sizeof(sha1));
|
||||||
|
std::string filenameHex = tmp.toHex();
|
||||||
|
std::string filename(filenameHex.c_str(), ID_HASH_SIZE);
|
||||||
|
std::string fullPath = std::string(activationDir);
|
||||||
|
fullPath += std::string ("/") + std::string(LOANS_DIR);
|
||||||
|
mkpath(fullPath.c_str());
|
||||||
|
fullPath += filename + std::string(".xml");
|
||||||
|
gourou::writeFile(fullPath, xmlStr);
|
||||||
|
|
||||||
|
std::cout << "Loan token serialized into " << fullPath << std::endl;
|
||||||
|
|
||||||
|
free(activationDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DRMProcessorClientImpl client;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
479
utils/adept_loan_mgt.cpp
Normal file
479
utils/adept_loan_mgt.cpp
Normal file
|
@ -0,0 +1,479 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2022, Grégory Soutadé
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the copyright holder nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#define _XOPEN_SOURCE 700
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <libgourou.h>
|
||||||
|
#include <libgourou_common.h>
|
||||||
|
#include "drmprocessorclientimpl.h"
|
||||||
|
#include "utils_common.h"
|
||||||
|
|
||||||
|
#define MAX_SIZE_BOOK_NAME 30
|
||||||
|
|
||||||
|
static char* activationDir = 0;
|
||||||
|
static const char* deviceFile = "device.xml";
|
||||||
|
static const char* activationFile = "activation.xml";
|
||||||
|
static const char* devicekeyFile = "devicesalt";
|
||||||
|
static bool list = false;
|
||||||
|
static const char* returnID = 0;
|
||||||
|
static const char* deleteID = 0;
|
||||||
|
|
||||||
|
struct Loan
|
||||||
|
{
|
||||||
|
std::string id;
|
||||||
|
std::string operatorURL;
|
||||||
|
std::string validity;
|
||||||
|
std::string bookName;
|
||||||
|
|
||||||
|
std::string path;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LoanMGT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~LoanMGT()
|
||||||
|
{
|
||||||
|
for (const auto& kv : loanedBooks)
|
||||||
|
delete kv.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
int run()
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DRMProcessorClientImpl client;
|
||||||
|
gourou::DRMProcessor processor(&client, deviceFile, activationFile, devicekeyFile);
|
||||||
|
|
||||||
|
loadLoanedBooks();
|
||||||
|
|
||||||
|
if (list)
|
||||||
|
displayLoanList();
|
||||||
|
else if (returnID)
|
||||||
|
returnBook(processor);
|
||||||
|
else if (deleteID)
|
||||||
|
deleteLoan();
|
||||||
|
} catch(std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << e.what() << std::endl;
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void loadLoanedBooks()
|
||||||
|
{
|
||||||
|
DIR *dp;
|
||||||
|
struct dirent *ep;
|
||||||
|
int entryLen;
|
||||||
|
struct Loan* loan;
|
||||||
|
char * res;
|
||||||
|
|
||||||
|
std::string loanDir = std::string(activationDir) + std::string("/") + LOANS_DIR;
|
||||||
|
|
||||||
|
if (!fileExists(loanDir.c_str()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
dp = opendir (loanDir.c_str());
|
||||||
|
|
||||||
|
if(!dp)
|
||||||
|
EXCEPTION(gourou::USER_INVALID_INPUT, "Cannot read directory " << loanDir);
|
||||||
|
|
||||||
|
while ((ep = readdir (dp)))
|
||||||
|
{
|
||||||
|
if (ep->d_type != DT_LNK &&
|
||||||
|
ep->d_type != DT_REG)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
entryLen = strlen(ep->d_name);
|
||||||
|
|
||||||
|
if (entryLen <= 4 ||
|
||||||
|
ep->d_name[entryLen-4] != '.' ||
|
||||||
|
ep->d_name[entryLen-3] != 'x' ||
|
||||||
|
ep->d_name[entryLen-2] != 'm' ||
|
||||||
|
ep->d_name[entryLen-1] != 'l')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string id = std::string(ep->d_name, entryLen-4);
|
||||||
|
|
||||||
|
loan = new Loan;
|
||||||
|
loan->path = loanDir + std::string("/") + ep->d_name;
|
||||||
|
|
||||||
|
pugi::xml_document xmlDoc;
|
||||||
|
pugi::xml_node node;
|
||||||
|
|
||||||
|
if (!xmlDoc.load_file(loan->path.c_str(), pugi::parse_ws_pcdata_single|pugi::parse_escapes, pugi::encoding_utf8))
|
||||||
|
{
|
||||||
|
std::cout << "Invalid loan entry " << loan->path << std::endl;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// id
|
||||||
|
node = xmlDoc.select_node("//id").node();
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
std::cout << "Invalid loan entry " << ep->d_name << ", no id element" << std::endl;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
loan->id = node.first_child().value();
|
||||||
|
|
||||||
|
// operatorURL
|
||||||
|
node = xmlDoc.select_node("//operatorURL").node();
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
std::cout << "Invalid loan entry " << ep->d_name << ", no operatorURL element" << std::endl;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
loan->operatorURL = node.first_child().value();
|
||||||
|
|
||||||
|
// validity
|
||||||
|
node = xmlDoc.select_node("//validity").node();
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
std::cout << "Invalid loan entry " << ep->d_name << ", no validity element" << std::endl;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
loan->validity = node.first_child().value();
|
||||||
|
|
||||||
|
// bookName
|
||||||
|
node = xmlDoc.select_node("//name").node();
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
std::cout << "Invalid loan entry " << ep->d_name << ", no name element" << std::endl;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
loan->bookName = node.first_child().value();
|
||||||
|
|
||||||
|
struct tm tm;
|
||||||
|
res = strptime(loan->validity.c_str(), "%Y-%m-%dT%H:%M:%S%Z", &tm);
|
||||||
|
if (*res == 0)
|
||||||
|
{
|
||||||
|
if (mktime(&tm) <= time(NULL))
|
||||||
|
loan->validity = " (Expired)";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Unable to parse validity timestamp :" << loan->validity << std::endl;
|
||||||
|
loan->validity = " (Unknown)";
|
||||||
|
}
|
||||||
|
|
||||||
|
loanedBooks[id] = loan;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (loan)
|
||||||
|
delete loan;
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir (dp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayLoanList()
|
||||||
|
{
|
||||||
|
if (!loanedBooks.size())
|
||||||
|
{
|
||||||
|
std::cout << "Any book loaned" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Loan* loan;
|
||||||
|
unsigned int maxSizeBookName=0;
|
||||||
|
// Compute max size
|
||||||
|
for (const auto& kv : loanedBooks)
|
||||||
|
{
|
||||||
|
loan = kv.second;
|
||||||
|
if (loan->bookName.size() > maxSizeBookName)
|
||||||
|
maxSizeBookName = loan->bookName.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxSizeBookName > MAX_SIZE_BOOK_NAME)
|
||||||
|
maxSizeBookName = MAX_SIZE_BOOK_NAME;
|
||||||
|
else if ((maxSizeBookName % 2))
|
||||||
|
maxSizeBookName++;
|
||||||
|
|
||||||
|
// std::cout << " ID Book Expiration" << std::endl;
|
||||||
|
// std::cout << "------------------------------" << std::endl;
|
||||||
|
|
||||||
|
int fillID, fillBookName, fillExpiration=(20 - 10)/2;
|
||||||
|
|
||||||
|
fillID = (ID_HASH_SIZE - 2) / 2;
|
||||||
|
fillBookName = (maxSizeBookName - 4) / 2;
|
||||||
|
|
||||||
|
std::cout.width (fillID);
|
||||||
|
std::cout << "";
|
||||||
|
std::cout << "ID" ;
|
||||||
|
std::cout.width (fillID);
|
||||||
|
std::cout << "";
|
||||||
|
std::cout << " " ;
|
||||||
|
|
||||||
|
std::cout.width (fillBookName);
|
||||||
|
std::cout << "";
|
||||||
|
std::cout << "Book" ;
|
||||||
|
std::cout.width (fillBookName);
|
||||||
|
std::cout << "";
|
||||||
|
std::cout << " " ;
|
||||||
|
|
||||||
|
std::cout.width (fillExpiration);
|
||||||
|
std::cout << "";
|
||||||
|
std::cout << "Exipration";
|
||||||
|
std::cout.width (fillExpiration);
|
||||||
|
std::cout << "" << std::endl;
|
||||||
|
|
||||||
|
std::cout.fill ('-');
|
||||||
|
std::cout.width (ID_HASH_SIZE + 4 + maxSizeBookName + 4 + 20);
|
||||||
|
std::cout << "" << std::endl;
|
||||||
|
std::cout.fill (' ');
|
||||||
|
|
||||||
|
std::string bookName;
|
||||||
|
|
||||||
|
for (const auto& kv : loanedBooks)
|
||||||
|
{
|
||||||
|
loan = kv.second;
|
||||||
|
|
||||||
|
std::cout << kv.first;
|
||||||
|
std::cout << " ";
|
||||||
|
|
||||||
|
if (loan->bookName.size() > MAX_SIZE_BOOK_NAME)
|
||||||
|
bookName = std::string(loan->bookName.c_str(), MAX_SIZE_BOOK_NAME);
|
||||||
|
else
|
||||||
|
bookName = loan->bookName;
|
||||||
|
|
||||||
|
std::cout << bookName;
|
||||||
|
std::cout.width (maxSizeBookName - bookName.size());
|
||||||
|
std::cout << "";
|
||||||
|
std::cout << " ";
|
||||||
|
|
||||||
|
std::cout << loan->validity << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void returnBook(gourou::DRMProcessor& processor)
|
||||||
|
{
|
||||||
|
struct Loan* loan = loanedBooks[std::string(returnID)];
|
||||||
|
|
||||||
|
if (!loan)
|
||||||
|
{
|
||||||
|
std::cout << "Error : Loan " << returnID << " doesn't exists" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
processor.returnLoan(loan->id, loan->operatorURL);
|
||||||
|
|
||||||
|
deleteID = returnID;
|
||||||
|
if (deleteLoan(false))
|
||||||
|
{
|
||||||
|
std::cout << "Loan " << returnID << " successfully returned" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool deleteLoan(bool displayResult=true)
|
||||||
|
{
|
||||||
|
struct Loan* loan = loanedBooks[std::string(deleteID)];
|
||||||
|
|
||||||
|
if (!loan)
|
||||||
|
{
|
||||||
|
std::cout << "Error : Loan " << deleteID << " doesn't exists" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlink(loan->path.c_str()))
|
||||||
|
{
|
||||||
|
std::cout << "Error : Cannot delete " << loan->path << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (displayResult)
|
||||||
|
{
|
||||||
|
std::cout << "Loan " << deleteID << " deleted" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, struct Loan*> loanedBooks;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void usage(const char* cmd)
|
||||||
|
{
|
||||||
|
std::cout << "Manage loaned books" << std::endl;
|
||||||
|
|
||||||
|
std::cout << "Usage: " << cmd << " [(-d|--activation-dir) dir] (-l|--list)|(-D|--delete loanID)|(-R|--delete loanID) [(-v|--verbose)] [(-h|--help)]" << std::endl << std::endl;
|
||||||
|
|
||||||
|
std::cout << " " << "-d|--activation-dir" << "\t" << "Directory of device.xml/activation.xml and device key" << std::endl;
|
||||||
|
std::cout << " " << "-l|--list" << "\t\t" << "List all loaned books" << std::endl;
|
||||||
|
std::cout << " " << "-r|--return" << "\t\t" << "Return a loaned book" << std::endl;
|
||||||
|
std::cout << " " << "-D|--delete" << "\t\t" << "Delete a loan entry without returning it" << 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;
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "Activation directory is optional. If not set, it's 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};
|
||||||
|
int verbose = gourou::DRMProcessor::getLogLevel();
|
||||||
|
int actions = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int option_index = 0;
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"activation-dir", required_argument, 0, 'd' },
|
||||||
|
{"list", no_argument, 0, 'l' },
|
||||||
|
{"return", no_argument, 0, 'r' },
|
||||||
|
{"delete", no_argument, 0, 'D' },
|
||||||
|
{"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:lr:D:vVh",
|
||||||
|
long_options, &option_index);
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'd':
|
||||||
|
activationDir = optarg;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
list = true;
|
||||||
|
actions++;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
returnID = optarg;
|
||||||
|
actions++;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
deleteID = optarg;
|
||||||
|
actions++;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose++;
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
version();
|
||||||
|
return 0;
|
||||||
|
case 'h':
|
||||||
|
usage(argv[0]);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gourou::DRMProcessor::setLogLevel(verbose);
|
||||||
|
|
||||||
|
// By default, simply list books loaned
|
||||||
|
if (actions == 0)
|
||||||
|
list = true;
|
||||||
|
else if (actions != 1)
|
||||||
|
{
|
||||||
|
usage(argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoanMGT loanMGT;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
bool hasErrors = false;
|
||||||
|
const char* orig;
|
||||||
|
char *filename;
|
||||||
|
for (i=0; i<(int)ARRAY_SIZE(files); i++)
|
||||||
|
{
|
||||||
|
orig = *files[i];
|
||||||
|
|
||||||
|
if (activationDir)
|
||||||
|
{
|
||||||
|
std::string path = std::string(activationDir) + std::string("/") + orig;
|
||||||
|
filename = strdup(path.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
filename = strdup(orig);
|
||||||
|
*files[i] = findFile(filename);
|
||||||
|
free(filename);
|
||||||
|
if (!*files[i])
|
||||||
|
{
|
||||||
|
std::cout << "Error : " << orig << " doesn't exists, did you activate your device ?" << std::endl;
|
||||||
|
hasErrors = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasErrors)
|
||||||
|
{
|
||||||
|
// In case of activation dir was provided by user
|
||||||
|
activationDir = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activationDir)
|
||||||
|
activationDir = strdup(activationDir); // For below free
|
||||||
|
else
|
||||||
|
{
|
||||||
|
activationDir = strdup(deviceFile);
|
||||||
|
activationDir = dirname(activationDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = loanMGT.run();
|
||||||
|
|
||||||
|
end:
|
||||||
|
for (i=0; i<(int)ARRAY_SIZE(files); i++)
|
||||||
|
{
|
||||||
|
if (*files[i])
|
||||||
|
free((void*)*files[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activationDir)
|
||||||
|
free(activationDir);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -29,6 +29,9 @@
|
||||||
#ifndef _UTILS_COMMON_H_
|
#ifndef _UTILS_COMMON_H_
|
||||||
#define _UTILS_COMMON_H_
|
#define _UTILS_COMMON_H_
|
||||||
|
|
||||||
|
#define LOANS_DIR "loans/"
|
||||||
|
#define ID_HASH_SIZE 16
|
||||||
|
|
||||||
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
|
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue
Block a user