Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a79bdd1e21 | ||
|
|
55ab41613e | ||
|
|
8129ec4423 | ||
|
|
9ab66ddba9 | ||
|
|
e5697378e9 | ||
|
|
fd8ce841eb | ||
|
|
8413b844db | ||
|
|
dd6001805f | ||
|
|
1f6e0ecdc8 | ||
|
|
89a5408c2d | ||
|
|
56e4fda760 | ||
|
|
59c801da08 | ||
|
|
f01bf9e837 | ||
|
|
c57aba8061 | ||
|
|
33ea9e7d65 | ||
|
|
dc15fc7197 |
2
Makefile
2
Makefile
@@ -54,7 +54,7 @@ $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
|
||||
libgourou: libgourou.a libgourou.so
|
||||
|
||||
libgourou.a: $(OBJECTS)
|
||||
$(AR) crs $@ obj/*.o $(LDFLAGS)
|
||||
$(AR) crs $@ obj/*.o ./lib/updfparser/obj/*.o
|
||||
|
||||
libgourou.so: $(OBJECTS) $(UPDFPARSERLIB)
|
||||
$(CXX) obj/*.o $(LDFLAGS) -o $@ -shared
|
||||
|
||||
@@ -27,19 +27,19 @@ Utils
|
||||
You can import configuration from your eReader or create a new one with utils/activate :
|
||||
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD
|
||||
./utils/activate -u <AdobeID USERNAME>
|
||||
./activate -u <AdobeID USERNAME>
|
||||
|
||||
Then a _./.adept_ directory is created with all configuration file
|
||||
|
||||
To download an ePub/PDF :
|
||||
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD
|
||||
./utils/acsmdownloader -f <ACSM_FILE>
|
||||
./acsmdownloader -f <ACSM_FILE>
|
||||
|
||||
To export your private key :
|
||||
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD
|
||||
./utils/acsmdownloader --export-private-key [-o adobekey_1.der]
|
||||
./acsmdownloader --export-private-key [-o adobekey_1.der]
|
||||
|
||||
|
||||
Sources
|
||||
|
||||
@@ -34,6 +34,12 @@ namespace gourou
|
||||
class FulfillmentItem
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Main constructor. Not to be called by user
|
||||
*
|
||||
* @param doc Fulfill reply
|
||||
* @param user User pointer
|
||||
*/
|
||||
FulfillmentItem(pugi::xml_document& doc, User* user);
|
||||
|
||||
/**
|
||||
@@ -59,6 +65,7 @@ namespace gourou
|
||||
std::string getResource();
|
||||
|
||||
private:
|
||||
pugi::xml_document fulfillDoc;
|
||||
pugi::xml_node metadatas;
|
||||
pugi::xml_document rights;
|
||||
std::string downloadURL;
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#define ACS_SERVER "http://adeactivate.adobe.com/adept"
|
||||
#endif
|
||||
|
||||
#define LIBGOUROU_VERSION "0.4"
|
||||
#define LIBGOUROU_VERSION "0.4.5"
|
||||
|
||||
namespace gourou
|
||||
{
|
||||
|
||||
@@ -68,6 +68,7 @@ namespace gourou
|
||||
|
||||
enum DOWNLOAD_ERROR {
|
||||
DW_NO_ITEM = 0x1200,
|
||||
DW_NO_EBX_HANDLER,
|
||||
};
|
||||
|
||||
enum SIGNIN_ERROR {
|
||||
@@ -293,7 +294,7 @@ namespace gourou
|
||||
*/
|
||||
static inline void writeFile(std::string path, ByteArray& data)
|
||||
{
|
||||
writeFile(path, data.data(), data.length()-1);
|
||||
writeFile(path, data.data(), data.length());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,14 +37,14 @@ namespace gourou
|
||||
ByteArray::ByteArray(const char* data, int length)
|
||||
{
|
||||
if (length == -1)
|
||||
length = strlen(data) + 1;
|
||||
length = strlen(data);
|
||||
|
||||
initData((const unsigned char*)data, (unsigned int) length);
|
||||
}
|
||||
|
||||
ByteArray::ByteArray(const std::string& str)
|
||||
{
|
||||
initData((unsigned char*)str.c_str(), (unsigned int)str.length() + 1);
|
||||
initData((unsigned char*)str.c_str(), (unsigned int)str.length());
|
||||
}
|
||||
|
||||
void ByteArray::initData(const unsigned char* data, unsigned int length)
|
||||
|
||||
@@ -24,8 +24,10 @@
|
||||
namespace gourou
|
||||
{
|
||||
FulfillmentItem::FulfillmentItem(pugi::xml_document& doc, User* user)
|
||||
: fulfillDoc()
|
||||
{
|
||||
metadatas = doc.select_node("//metadata").node();
|
||||
fulfillDoc.reset(doc); /* We must keep a copy */
|
||||
metadatas = fulfillDoc.select_node("//metadata").node();
|
||||
|
||||
if (!metadatas)
|
||||
EXCEPTION(FFI_INVALID_FULFILLMENT_DATA, "No metadata tag in document");
|
||||
|
||||
@@ -599,7 +599,11 @@ namespace gourou
|
||||
|
||||
std::string rightsStr = item->getRights();
|
||||
|
||||
if (headers.count("Content-Type") && headers["Content-Type"] == "application/pdf")
|
||||
if (item->getMetadata("format").find("application/pdf") != std::string::npos)
|
||||
res = PDF;
|
||||
|
||||
if (headers.count("Content-Type") &&
|
||||
headers["Content-Type"].find("application/pdf") != std::string::npos)
|
||||
res = PDF;
|
||||
|
||||
if (res == EPUB)
|
||||
@@ -611,6 +615,7 @@ namespace gourou
|
||||
else if (res == PDF)
|
||||
{
|
||||
uPDFParser::Parser parser;
|
||||
bool EBXHandlerFound = false;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -631,6 +636,7 @@ namespace gourou
|
||||
// Update EBX_HANDLER with rights
|
||||
if ((*it)->hasKey("Filter") && (**it)["Filter"]->str() == "/EBX_HANDLER")
|
||||
{
|
||||
EBXHandlerFound = true;
|
||||
uPDFParser::Object* ebx = (*it)->clone();
|
||||
(*ebx)["ADEPT_ID"] = new uPDFParser::String(item->getResource());
|
||||
(*ebx)["EBX_BOOKID"] = new uPDFParser::String(item->getResource());
|
||||
@@ -642,7 +648,12 @@ namespace gourou
|
||||
}
|
||||
}
|
||||
|
||||
if (EBXHandlerFound)
|
||||
parser.write(path, true);
|
||||
else
|
||||
{
|
||||
EXCEPTION(DW_NO_EBX_HANDLER, "EBX_HANDLER not found");
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -907,7 +918,7 @@ namespace gourou
|
||||
|
||||
ByteArray privateLicenseKey = ByteArray::fromBase64(user->getPrivateLicenseKey());
|
||||
/* In adobekey.py, we get base64 decoded data [26:] */
|
||||
write(fd, privateLicenseKey.data()+26, privateLicenseKey.length()-1-26);
|
||||
write(fd, privateLicenseKey.data()+26, privateLicenseKey.length()-26);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
TARGETS=acsmdownloader adept_activate
|
||||
|
||||
CXXFLAGS=-Wall `pkg-config --cflags Qt5Core Qt5Network` -fPIC -I$(ROOT)/include -I$(ROOT)/lib/pugixml/src/
|
||||
|
||||
STATIC_DEP=
|
||||
LDFLAGS=`pkg-config --libs Qt5Core Qt5Network` -L$(ROOT) -lcrypto -lzip -lz
|
||||
|
||||
ifneq ($(STATIC_UTILS),)
|
||||
LDFLAGS=`pkg-config --libs Qt5Core Qt5Network` -L$(ROOT) $(ROOT)/libgourou.a -lcrypto -lzip
|
||||
STATIC_DEP = $(ROOT)/libgourou.a
|
||||
else
|
||||
LDFLAGS=`pkg-config --libs Qt5Core Qt5Network` -L$(ROOT) -lgourou -lcrypto -lzip -lz
|
||||
LDFLAGS += -lgourou
|
||||
endif
|
||||
|
||||
ifneq ($(DEBUG),)
|
||||
@@ -16,10 +20,10 @@ endif
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
acsmdownloader: drmprocessorclientimpl.cpp acsmdownloader.cpp
|
||||
acsmdownloader: drmprocessorclientimpl.cpp acsmdownloader.cpp $(STATIC_DEP)
|
||||
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
|
||||
|
||||
adept_activate: drmprocessorclientimpl.cpp adept_activate.cpp
|
||||
adept_activate: drmprocessorclientimpl.cpp adept_activate.cpp $(STATIC_DEP)
|
||||
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
|
||||
|
||||
clean:
|
||||
|
||||
@@ -79,6 +79,8 @@ public:
|
||||
std::string filename;
|
||||
if (!outputFile)
|
||||
filename = std::string("Adobe_PrivateLicenseKey--") + user->getUsername() + ".der";
|
||||
else
|
||||
filename = outputFile;
|
||||
|
||||
if (outputDir)
|
||||
{
|
||||
@@ -103,6 +105,11 @@ public:
|
||||
filename = item->getMetadata("title");
|
||||
if (filename == "")
|
||||
filename = "output";
|
||||
else
|
||||
{
|
||||
// Remove invalid characters
|
||||
std::replace(filename.begin(), filename.end(), '/', '_');
|
||||
}
|
||||
}
|
||||
else
|
||||
filename = outputFile;
|
||||
@@ -173,7 +180,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] [(-s|--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)] [(-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;
|
||||
|
||||
@@ -116,7 +116,7 @@ std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, cons
|
||||
if (location.size() != 0)
|
||||
{
|
||||
GOUROU_LOG(gourou::DEBUG, "New location");
|
||||
return sendHTTPRequest(location.constData(), POSTData, contentType);
|
||||
return sendHTTPRequest(location.constData(), POSTData, contentType, responseHeaders);
|
||||
}
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
@@ -441,21 +441,26 @@ void DRMProcessorClientImpl::inflate(std::string data, gourou::ByteArray& result
|
||||
|
||||
int ret = inflateInit2(&infstream, wbits);
|
||||
|
||||
ret = ::inflate(&infstream, Z_SYNC_FLUSH);
|
||||
if (ret != Z_OK)
|
||||
EXCEPTION(gourou::CLIENT_ZIP_ERROR, infstream.msg);
|
||||
|
||||
ret = ::inflate(&infstream, Z_FINISH);
|
||||
while (ret == Z_OK || ret == Z_STREAM_END)
|
||||
{
|
||||
result.append(buffer, dataSize-infstream.avail_out);
|
||||
if (ret == Z_STREAM_END) break;
|
||||
if ((ret == Z_OK && infstream.avail_out != 0) || ret == Z_STREAM_END)
|
||||
break;
|
||||
infstream.avail_out = (uInt)dataSize; // size of output
|
||||
infstream.next_out = (Bytef *)buffer; // output char array
|
||||
ret = ::inflate(&infstream, Z_SYNC_FLUSH);
|
||||
ret = ::inflate(&infstream, Z_FINISH);
|
||||
}
|
||||
|
||||
inflateEnd(&infstream);
|
||||
if (ret == Z_STREAM_END)
|
||||
ret = inflateEnd(&infstream);
|
||||
|
||||
delete[] buffer;
|
||||
|
||||
if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR)
|
||||
if (ret != Z_OK && ret != Z_STREAM_END)
|
||||
EXCEPTION(gourou::CLIENT_ZIP_ERROR, zError(ret));
|
||||
}
|
||||
|
||||
@@ -479,20 +484,25 @@ void DRMProcessorClientImpl::deflate(std::string data, gourou::ByteArray& result
|
||||
int ret = deflateInit2(&defstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, wbits,
|
||||
compressionLevel, Z_DEFAULT_STRATEGY);
|
||||
|
||||
ret = ::deflate(&defstream, Z_SYNC_FLUSH);
|
||||
if (ret != Z_OK)
|
||||
EXCEPTION(gourou::CLIENT_ZIP_ERROR, defstream.msg);
|
||||
|
||||
ret = ::deflate(&defstream, Z_FINISH);
|
||||
while (ret == Z_OK || ret == Z_STREAM_END)
|
||||
{
|
||||
result.append(buffer, dataSize-defstream.avail_out);
|
||||
if (ret == Z_STREAM_END) break;
|
||||
if ((ret == Z_OK && defstream.avail_out != 0) || ret == Z_STREAM_END)
|
||||
break;
|
||||
defstream.avail_out = (uInt)dataSize; // size of output
|
||||
defstream.next_out = (Bytef *)buffer; // output char array
|
||||
ret = ::deflate(&defstream, Z_SYNC_FLUSH);
|
||||
ret = ::deflate(&defstream, Z_FINISH);
|
||||
}
|
||||
|
||||
deflateEnd(&defstream);
|
||||
if (ret == Z_STREAM_END)
|
||||
ret = deflateEnd(&defstream);
|
||||
|
||||
delete[] buffer;
|
||||
|
||||
if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR)
|
||||
if (ret != Z_OK && ret != Z_STREAM_END)
|
||||
EXCEPTION(gourou::CLIENT_ZIP_ERROR, zError(ret));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user