forked from soutade/libgourou
Add DRM removal for ePub only
This commit is contained in:
@@ -24,33 +24,48 @@
|
||||
|
||||
namespace gourou
|
||||
{
|
||||
std::map<const unsigned char*, int> ByteArray::refCounter;
|
||||
std::map<unsigned char*, int> ByteArray::refCounter;
|
||||
|
||||
ByteArray::ByteArray():_data(0), _length(0)
|
||||
ByteArray::ByteArray(bool useMalloc):_useMalloc(useMalloc), _data(0), _length(0)
|
||||
{}
|
||||
|
||||
ByteArray::ByteArray(const unsigned char* data, unsigned int length)
|
||||
ByteArray::ByteArray(unsigned int length, bool useMalloc):
|
||||
_useMalloc(useMalloc)
|
||||
{
|
||||
initData(0, length);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const unsigned char* data, unsigned int length):
|
||||
_useMalloc(false)
|
||||
{
|
||||
initData(data, length);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const char* data, int length)
|
||||
ByteArray::ByteArray(const char* data, int length):
|
||||
_useMalloc(false)
|
||||
{
|
||||
if (length == -1)
|
||||
length = strlen(data);
|
||||
|
||||
initData((const unsigned char*)data, (unsigned int) length);
|
||||
initData((unsigned char*)data, (unsigned int) length);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const std::string& str)
|
||||
ByteArray::ByteArray(const std::string& str):
|
||||
_useMalloc(false)
|
||||
{
|
||||
initData((unsigned char*)str.c_str(), (unsigned int)str.length());
|
||||
}
|
||||
|
||||
void ByteArray::initData(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
_data = new unsigned char[length];
|
||||
memcpy((void*)_data, data, length);
|
||||
if (_useMalloc)
|
||||
_data = (unsigned char*)malloc(length);
|
||||
else
|
||||
_data = new unsigned char[length];
|
||||
|
||||
if (data)
|
||||
memcpy((void*)_data, data, length);
|
||||
|
||||
_length = length;
|
||||
|
||||
addRef();
|
||||
@@ -58,6 +73,7 @@ namespace gourou
|
||||
|
||||
ByteArray::ByteArray(const ByteArray& other)
|
||||
{
|
||||
this->_useMalloc = other._useMalloc;
|
||||
this->_data = other._data;
|
||||
this->_length = other._length;
|
||||
|
||||
@@ -68,6 +84,7 @@ namespace gourou
|
||||
{
|
||||
delRef();
|
||||
|
||||
this->_useMalloc = other._useMalloc;
|
||||
this->_data = other._data;
|
||||
this->_length = other._length;
|
||||
|
||||
@@ -97,7 +114,10 @@ namespace gourou
|
||||
|
||||
if (refCounter[_data] == 1)
|
||||
{
|
||||
delete[] _data;
|
||||
if (_useMalloc)
|
||||
free(_data);
|
||||
else
|
||||
delete[] _data;
|
||||
refCounter.erase(_data);
|
||||
}
|
||||
else
|
||||
@@ -152,8 +172,13 @@ namespace gourou
|
||||
|
||||
void ByteArray::append(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
const unsigned char* oldData = _data;
|
||||
unsigned char* newData = new unsigned char[_length+length];
|
||||
unsigned char* oldData = _data;
|
||||
unsigned char* newData;
|
||||
|
||||
if (_useMalloc)
|
||||
newData = (unsigned char*)malloc(_length+length);
|
||||
else
|
||||
newData = new unsigned char[_length+length];
|
||||
|
||||
memcpy(newData, oldData, _length);
|
||||
|
||||
@@ -170,4 +195,10 @@ namespace gourou
|
||||
void ByteArray::append(unsigned char c) { append(&c, 1);}
|
||||
void ByteArray::append(const char* str) { append((const unsigned char*)str, strlen(str));}
|
||||
void ByteArray::append(const std::string& str) { append((const unsigned char*)str.c_str(), str.length()); }
|
||||
|
||||
void ByteArray::resize(unsigned length)
|
||||
{
|
||||
delRef();
|
||||
initData(0, length);
|
||||
}
|
||||
}
|
||||
|
@@ -597,7 +597,7 @@ namespace gourou
|
||||
|
||||
GOUROU_LOG(INFO, "Download into " << path);
|
||||
|
||||
std::string rightsStr = item->getRights();
|
||||
ByteArray rightsStr(item->getRights());
|
||||
|
||||
if (item->getMetadata("format").find("application/pdf") != std::string::npos)
|
||||
res = PDF;
|
||||
@@ -925,4 +925,80 @@ namespace gourou
|
||||
|
||||
int DRMProcessor::getLogLevel() {return (int)gourou::logLevel;}
|
||||
void DRMProcessor::setLogLevel(int logLevel) {gourou::logLevel = (GOUROU_LOG_LEVEL)logLevel;}
|
||||
|
||||
void DRMProcessor::removeEPubDRM(const std::string& ePubFile)
|
||||
{
|
||||
ByteArray zipData;
|
||||
void* zipHandler = client->zipOpen(ePubFile);
|
||||
|
||||
client->zipReadFile(zipHandler, "META-INF/rights.xml", zipData);
|
||||
pugi::xml_document rightsDoc;
|
||||
rightsDoc.load_string((const char*)zipData.data());
|
||||
|
||||
std::string encryptedKey = extractTextElem(rightsDoc, "/adept:rights/licenseToken/encryptedKey");
|
||||
ByteArray arrayEncryptedKey = ByteArray::fromBase64(encryptedKey);
|
||||
unsigned char decryptedKey[RSA_KEY_SIZE];
|
||||
|
||||
std::string privateKeyData = user->getPrivateLicenseKey();
|
||||
ByteArray privateRSAKey = ByteArray::fromBase64(privateKeyData);
|
||||
|
||||
ByteArray deviceKey(device->getDeviceKey(), Device::DEVICE_KEY_SIZE);
|
||||
std::string pkcs12 = user->getPKCS12();
|
||||
|
||||
client->RSAPrivateDecrypt(privateRSAKey.data(), privateRSAKey.length(),
|
||||
RSAInterface::RSA_KEY_PKCS12, deviceKey.toBase64().data(),
|
||||
arrayEncryptedKey.data(), arrayEncryptedKey.length(), decryptedKey);
|
||||
|
||||
if (decryptedKey[0] != 0x00 || decryptedKey[1] != 0x02 ||
|
||||
decryptedKey[RSA_KEY_SIZE-16-1] != 0x00)
|
||||
EXCEPTION(CLIENT_DRM_ERR_ENCRYPTION_KEY, "Unable to retrieve encryption key");
|
||||
|
||||
client->zipReadFile(zipHandler, "META-INF/encryption.xml", zipData);
|
||||
pugi::xml_document encryptionDoc;
|
||||
encryptionDoc.load_string((const char*)zipData.data());
|
||||
|
||||
pugi::xpath_node_set nodeSet = encryptionDoc.select_nodes("//CipherReference");
|
||||
|
||||
for (pugi::xpath_node_set::const_iterator it = nodeSet.begin();
|
||||
it != nodeSet.end(); ++it)
|
||||
{
|
||||
std::string encryptedFile = it->node().attribute("URI").value();
|
||||
|
||||
GOUROU_LOG(DEBUG, "Encrypted file " << encryptedFile);
|
||||
|
||||
client->zipReadFile(zipHandler, encryptedFile, zipData, false);
|
||||
|
||||
unsigned char* _data = zipData.data();
|
||||
ByteArray clearData(zipData.length()-16+1); /* Reserve 1 byte for 'Z' */
|
||||
unsigned char* _clearData = clearData.data();
|
||||
gourou::ByteArray inflateData(true);
|
||||
unsigned int dataOutLength;
|
||||
|
||||
client->AESDecrypt(CryptoInterface::CHAIN_CBC,
|
||||
decryptedKey+RSA_KEY_SIZE-16, 16, /* Key */
|
||||
_data, 16, /* IV */
|
||||
&_data[16], zipData.length()-16,
|
||||
_clearData, &dataOutLength);
|
||||
|
||||
// Add 'Z' at the end, done in ineptepub.py
|
||||
_clearData[dataOutLength] = 'Z';
|
||||
|
||||
client->inflate(clearData, inflateData);
|
||||
|
||||
client->zipWriteFile(zipHandler, encryptedFile, inflateData);
|
||||
}
|
||||
|
||||
client->zipDeleteFile(zipHandler, "META-INF/rights.xml");
|
||||
client->zipDeleteFile(zipHandler, "META-INF/encryption.xml");
|
||||
|
||||
client->zipClose(zipHandler);
|
||||
}
|
||||
|
||||
void DRMProcessor::removeDRM(const std::string& ePubFile, ITEM_TYPE type)
|
||||
{
|
||||
if (type == EPUB)
|
||||
removeEPubDRM(ePubFile);
|
||||
else
|
||||
EXCEPTION(CLIENT_DRM_FORMAT_NOT_SUPPORTED, "Can't remove DRM in PDF");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user