mirror of
https://github.com/Leseratte10/acsm-calibre-plugin.git
synced 2024-12-23 01:34:36 +06:00
Experimental eReader authorization support
This commit is contained in:
parent
7373a33709
commit
01d34288c4
@ -35,6 +35,14 @@ This makes the book available for someone else again, but it does not automatica
|
|||||||
|
|
||||||
Note: You can only return books that you downloaded with version 0.0.9 (or newer) of this plugin. You cannot return books downloaded with ADE or with earlier versions of this plugin.
|
Note: You can only return books that you downloaded with version 0.0.9 (or newer) of this plugin. You cannot return books downloaded with ADE or with earlier versions of this plugin.
|
||||||
|
|
||||||
|
## Authorizing eReaders
|
||||||
|
|
||||||
|
As of v0.0.16, the plugin can also authorize an eReader connected to the Computer through USB. For now, this only works with devices that export their `.adobe-digital-editions` folder through USB. In order to authorize such an eReader, just open the plugin settings and click "Authorize eReader over USB" (only available if the plugin is authorized with an AdobeID). Then select the eReader in the folder selection dialog. This process does not work with eReaders relying on a specific USB driver for the ADE connection such as the Sony PRS-T2 (and probably some other older Sony devices).
|
||||||
|
|
||||||
|
Right now, this process is fairly experimental as I do not own a physical eReader that supports this functionality, so I've only been able to test this with a fake, emulated eReader and not with a real device.
|
||||||
|
|
||||||
|
Note that this process will use up one of your six mobile/tethered eReader authorizations on your AdobeID. While it is possible to clone a computer activation by exporting it on one computer and importing it on another, this is not possible with eReader authorizations.
|
||||||
|
|
||||||
## Standalone version
|
## Standalone version
|
||||||
|
|
||||||
In the folder "calibre-plugin" in this repo (or inside the Calibre plugin ZIP file) there's some scripts that can also be used standalone without Calibre. If you want to use these, you need to extract the whole ZIP file.
|
In the folder "calibre-plugin" in this repo (or inside the Calibre plugin ZIP file) there's some scripts that can also be used standalone without Calibre. If you want to use these, you need to extract the whole ZIP file.
|
||||||
@ -49,5 +57,4 @@ Though, generally it's recommended to use the Calibre plugin instead of these st
|
|||||||
|
|
||||||
- Support to copy an authorization from the plugin to an ADE install
|
- Support to copy an authorization from the plugin to an ADE install
|
||||||
- Support for Adobe's "auth" download method instead of the "simple" method.
|
- Support for Adobe's "auth" download method instead of the "simple" method.
|
||||||
- Support to authorize an eReader that's connected over USB
|
|
||||||
- ...
|
- ...
|
@ -34,7 +34,8 @@
|
|||||||
# allow converting an anonymous auth to an AdobeID auth,
|
# allow converting an anonymous auth to an AdobeID auth,
|
||||||
# update python-cryptography from 3.4.8 to 36.0.1, update python-rsa from 4.7.2 to 4.8.
|
# update python-cryptography from 3.4.8 to 36.0.1, update python-rsa from 4.7.2 to 4.8.
|
||||||
# Currently in development:
|
# Currently in development:
|
||||||
# Ignore fatal HTTP errors during optional fulfillment notifications.
|
# Ignore fatal HTTP errors during optional fulfillment notifications,
|
||||||
|
# allow authorizing an eReader through USB.
|
||||||
|
|
||||||
PLUGIN_NAME = "DeACSM"
|
PLUGIN_NAME = "DeACSM"
|
||||||
PLUGIN_VERSION_TUPLE = (0, 0, 15)
|
PLUGIN_VERSION_TUPLE = (0, 0, 15)
|
||||||
|
@ -111,13 +111,13 @@ class ConfigWidget(QWidget):
|
|||||||
self.button_convert_anon_to_account.clicked.connect(self.convert_anon_to_account)
|
self.button_convert_anon_to_account.clicked.connect(self.convert_anon_to_account)
|
||||||
ua_group_box_layout.addWidget(self.button_convert_anon_to_account)
|
ua_group_box_layout.addWidget(self.button_convert_anon_to_account)
|
||||||
|
|
||||||
#if mail is not None:
|
if mail is not None:
|
||||||
# We do have an email. Offer to manage devices / eReaders
|
# We do have an email. Offer to manage devices / eReaders
|
||||||
# Button commented out as this isn't fully implemented yet.
|
# This isn't really tested a lot ...
|
||||||
#self.button_manage_ext_device = QtGui.QPushButton(self)
|
self.button_manage_ext_device = QtGui.QPushButton(self)
|
||||||
#self.button_manage_ext_device.setText(_("Manage connected eReaders"))
|
self.button_manage_ext_device.setText(_("Authorize eReader over USB"))
|
||||||
#self.button_manage_ext_device.clicked.connect(self.manage_ext_device)
|
self.button_manage_ext_device.clicked.connect(self.manage_ext_device)
|
||||||
#ua_group_box_layout.addWidget(self.button_manage_ext_device)
|
ua_group_box_layout.addWidget(self.button_manage_ext_device)
|
||||||
|
|
||||||
self.button_switch_ade_version = QtGui.QPushButton(self)
|
self.button_switch_ade_version = QtGui.QPushButton(self)
|
||||||
self.button_switch_ade_version.setText(_("Change ADE version"))
|
self.button_switch_ade_version.setText(_("Change ADE version"))
|
||||||
@ -241,6 +241,20 @@ class ConfigWidget(QWidget):
|
|||||||
# Unfortunately, I didn't find a nice cross-platform API to query for USB mass storage devices.
|
# Unfortunately, I didn't find a nice cross-platform API to query for USB mass storage devices.
|
||||||
# So just open up a folder picker dialog and have the user select the eReader's root folder.
|
# So just open up a folder picker dialog and have the user select the eReader's root folder.
|
||||||
|
|
||||||
|
try:
|
||||||
|
from calibre_plugins.deacsm.libadobe import update_account_path, VAR_VER_HOBBES_VERSIONS
|
||||||
|
from calibre_plugins.deacsm.libadobeAccount import activateDevice, exportProxyAuth
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
from libadobe import update_account_path, VAR_VER_HOBBES_VERSIONS
|
||||||
|
from libadobeAccount import activateDevice, exportProxyAuth
|
||||||
|
except:
|
||||||
|
print("{0} v{1}: Error while importing Account stuff".format(PLUGIN_NAME, PLUGIN_VERSION))
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
|
||||||
|
update_account_path(self.deacsmprefs["path_to_account_data"])
|
||||||
|
|
||||||
info_string, activated, mail = self.get_account_info()
|
info_string, activated, mail = self.get_account_info()
|
||||||
|
|
||||||
if not activated:
|
if not activated:
|
||||||
@ -249,7 +263,12 @@ class ConfigWidget(QWidget):
|
|||||||
if mail is None:
|
if mail is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
info_dialog(None, "Manage eReader", "Please select the eBook reader you want to manage", show=True, show_copy_button=False)
|
msg = "Please select the eBook reader you want to link to your account.\n"
|
||||||
|
msg += "Either select the root drive / mountpoint, or any folder on the eReader.\n"
|
||||||
|
msg += "Note that this feature is experimental and only works with eReaders that "
|
||||||
|
msg += "export their .adobe-digital-editions folder."
|
||||||
|
|
||||||
|
info_dialog(None, "Authorize eReader", msg, show=True, show_copy_button=False)
|
||||||
|
|
||||||
dialog = QFileDialog()
|
dialog = QFileDialog()
|
||||||
dialog.setFileMode(QFileDialog.Directory)
|
dialog.setFileMode(QFileDialog.Directory)
|
||||||
@ -261,7 +280,7 @@ class ConfigWidget(QWidget):
|
|||||||
x = dialog.selectedFiles()[0]
|
x = dialog.selectedFiles()[0]
|
||||||
if not os.path.isdir(x):
|
if not os.path.isdir(x):
|
||||||
# This is not supposed to happen.
|
# This is not supposed to happen.
|
||||||
error_dialog(None, "Manage eReader", "Device not found", show=True, show_copy_button=False)
|
error_dialog(None, "Authorize eReader", "Device not found", show=True, show_copy_button=False)
|
||||||
return
|
return
|
||||||
|
|
||||||
idx = 0
|
idx = 0
|
||||||
@ -269,7 +288,9 @@ class ConfigWidget(QWidget):
|
|||||||
idx = idx + 1
|
idx = idx + 1
|
||||||
if idx > 15:
|
if idx > 15:
|
||||||
# Failsafe, max. 15 folder levels.
|
# Failsafe, max. 15 folder levels.
|
||||||
break
|
error_dialog(None, "Authorize eReader", "Didn't find an ADE-compatible eReader in that location. (Too many levels)", show=True, show_copy_button=False)
|
||||||
|
return
|
||||||
|
|
||||||
adobe_path = os.path.join(x, ".adobe-digital-editions")
|
adobe_path = os.path.join(x, ".adobe-digital-editions")
|
||||||
print("Checking " + adobe_path)
|
print("Checking " + adobe_path)
|
||||||
if os.path.isdir(adobe_path):
|
if os.path.isdir(adobe_path):
|
||||||
@ -281,11 +302,11 @@ class ConfigWidget(QWidget):
|
|||||||
|
|
||||||
if x_old == x:
|
if x_old == x:
|
||||||
# We're at the drive root and still didn't find an activation
|
# We're at the drive root and still didn't find an activation
|
||||||
error_dialog(None, "Manage eReader", "Didn't find an ADE-compatible eReader in that location. (No Folder)", show=True, show_copy_button=False)
|
error_dialog(None, "Authorize eReader", "Didn't find an ADE-compatible eReader in that location. (No Folder)", show=True, show_copy_button=False)
|
||||||
return
|
return
|
||||||
|
|
||||||
if not os.path.isfile(os.path.join(adobe_path, "device.xml")):
|
if not os.path.isfile(os.path.join(adobe_path, "device.xml")):
|
||||||
error_dialog(None, "Manage eReader", "Didn't find an ADE-compatible eReader in that location. (No File)", show=True, show_copy_button=False)
|
error_dialog(None, "Authorize eReader", "Didn't find an ADE-compatible eReader in that location. (No File)", show=True, show_copy_button=False)
|
||||||
return
|
return
|
||||||
|
|
||||||
dev_xml_path = os.path.join(adobe_path, "device.xml")
|
dev_xml_path = os.path.join(adobe_path, "device.xml")
|
||||||
@ -297,7 +318,7 @@ class ConfigWidget(QWidget):
|
|||||||
devClass = dev_xml_tree.find("./%s" % (adNS("deviceClass"))).text
|
devClass = dev_xml_tree.find("./%s" % (adNS("deviceClass"))).text
|
||||||
devName = dev_xml_tree.find("./%s" % (adNS("deviceName"))).text
|
devName = dev_xml_tree.find("./%s" % (adNS("deviceName"))).text
|
||||||
except:
|
except:
|
||||||
error_dialog(None, "Manage eReader", "Reader data is invalid.", show=True, show_copy_button=False)
|
error_dialog(None, "Authorize eReader", "Reader data is invalid.", show=True, show_copy_button=False)
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -310,12 +331,55 @@ class ConfigWidget(QWidget):
|
|||||||
print("Found Reader with Class " + devClass + " and Name " + devName)
|
print("Found Reader with Class " + devClass + " and Name " + devName)
|
||||||
|
|
||||||
if os.path.isfile(act_xml_path):
|
if os.path.isfile(act_xml_path):
|
||||||
print("Already activated.")
|
|
||||||
msg = "The given device (Type \""+devClass+"\", Name \""+devName+"\") is already connected to an AdobeID.\n"
|
|
||||||
msg += "Currently, this plugin does not support un-authorizing an eReader."
|
|
||||||
|
|
||||||
error_dialog(None, "Manage eReader", msg, show=True, show_copy_button=False)
|
active_device_act = etree.parse(act_xml_path)
|
||||||
return
|
adNS = lambda tag: '{%s}%s' % ('http://ns.adobe.com/adept', tag)
|
||||||
|
act_uuid = active_device_act.find("./%s/%s" % (adNS("credentials"), adNS("user"))).text
|
||||||
|
act_username_name = None
|
||||||
|
try:
|
||||||
|
act_username = active_device_act.find("./%s/%s" % (adNS("credentials"), adNS("username")))
|
||||||
|
act_username_name = act_username.text
|
||||||
|
act_username_method = act_username.get("method", "AdobeID")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
act_dev_uuid = None
|
||||||
|
act_dev_uuid = active_device_act.find("./%s/%s" % (adNS("activationToken"), adNS("device"))).text
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
msg = "The following device:\n\n"
|
||||||
|
msg += "Path: " + os.path.dirname(adobe_path) + "\n"
|
||||||
|
msg += "Type: " + devClass + "\n"
|
||||||
|
msg += "Name: " + devName + "\n"
|
||||||
|
if devSerial is not None:
|
||||||
|
msg += "Serial: " + devSerial + "\n"
|
||||||
|
if act_dev_uuid is not None:
|
||||||
|
msg += "UUID: " + act_dev_uuid + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
msg += "\nis already connected to the following AdobeID:\n\n"
|
||||||
|
msg += "UUID: " + act_uuid + "\n"
|
||||||
|
if (act_username_name is not None):
|
||||||
|
msg += "Username: " + act_username_name + "\n"
|
||||||
|
msg += "Type: " + act_username_method + "\n"
|
||||||
|
else:
|
||||||
|
msg += "Type: anonymous authorization\n"
|
||||||
|
|
||||||
|
msg += "\nDo you want to remove this authorization and link this device to your AdobeID?\n\n"
|
||||||
|
msg += "Click \"No\" to cancel, or \"Yes\" to remove the existing authorization from the device and authorize it with your AdobeID."
|
||||||
|
|
||||||
|
ok = question_dialog(None, "Authorize eReader", msg)
|
||||||
|
|
||||||
|
if (not ok):
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.remove(act_xml_path)
|
||||||
|
except:
|
||||||
|
error_dialog(None, "Authorize eReader", "Failed to remove existing authorization.", show=True, show_copy_button=False)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
msg = "Found an unactivated eReader:\n\n"
|
msg = "Found an unactivated eReader:\n\n"
|
||||||
@ -326,17 +390,54 @@ class ConfigWidget(QWidget):
|
|||||||
msg += "Serial: " + devSerial + "\n"
|
msg += "Serial: " + devSerial + "\n"
|
||||||
msg += "\nDo you want to authorize this device with your AdobeID?"
|
msg += "\nDo you want to authorize this device with your AdobeID?"
|
||||||
|
|
||||||
ok = question_dialog(None, "Manage eReader", msg)
|
ok = question_dialog(None, "Authorize eReader", msg)
|
||||||
if not ok:
|
if not ok:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
# Okay, if we end up here, the user wants to authorize his eReader to his current AdobeID.
|
# Okay, if we end up here, the user wants to authorize his eReader to his current AdobeID.
|
||||||
# Rest still needs to be implemented.
|
# Figure out what ADE version we're currently emulating:
|
||||||
#
|
|
||||||
|
|
||||||
error_dialog(None, "Manage eReader", "Not yet implemented.", show=True, show_copy_button=False)
|
device_xml_path = os.path.join(self.deacsmprefs["path_to_account_data"], "device.xml")
|
||||||
|
|
||||||
|
try:
|
||||||
|
containerdev = etree.parse(device_xml_path)
|
||||||
|
except (FileNotFoundError, OSError) as e:
|
||||||
|
return error_dialog(None, "Failed", "Error while reading device.xml", show=True, show_copy_button=False)
|
||||||
|
|
||||||
|
try:
|
||||||
|
adeptNS = lambda tag: '{%s}%s' % ('http://ns.adobe.com/adept', tag)
|
||||||
|
|
||||||
|
# Determine the ADE version we're emulating:
|
||||||
|
ver = containerdev.findall("./%s" % (adeptNS("version")))
|
||||||
|
|
||||||
|
# "Default" entry would be for the old 10.0.4 entry.
|
||||||
|
# As 10.X is in the 3.0 range, assume we're on ADE 3.0.1 with hobbes version 10.0.85385
|
||||||
|
v_idx = VAR_VER_HOBBES_VERSIONS.index("10.0.85385")
|
||||||
|
|
||||||
|
for f in ver:
|
||||||
|
if f.get("name") == "hobbes":
|
||||||
|
hobbes_version = f.get("value")
|
||||||
|
|
||||||
|
if hobbes_version is not None:
|
||||||
|
v_idx = VAR_VER_HOBBES_VERSIONS.index(hobbes_version)
|
||||||
|
except:
|
||||||
|
return error_dialog(None, "Authorize eReader", "Error while determining ADE version", show=True, show_copy_button=False)
|
||||||
|
|
||||||
|
|
||||||
|
# Activate the target device with that version.
|
||||||
|
ret, data = activateDevice(v_idx, dev_xml_tree)
|
||||||
|
|
||||||
|
if not ret:
|
||||||
|
return error_dialog(None, "Authorize eReader", "Couldn't activate device, server returned error.", show=True, det_msg=data, show_copy_button=False)
|
||||||
|
|
||||||
|
ret, data = exportProxyAuth(act_xml_path, data)
|
||||||
|
|
||||||
|
if not ret:
|
||||||
|
return error_dialog(None, "Authorize eReader", "Error while writing activation to device.", show=True, det_msg=data, show_copy_button=False)
|
||||||
|
|
||||||
|
|
||||||
|
return info_dialog(None, "Authorize eReader", "Reader authorized successfully.", show=True, show_copy_button=False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -921,7 +1022,7 @@ class ConfigWidget(QWidget):
|
|||||||
if (success is False):
|
if (success is False):
|
||||||
return error_dialog(None, "ADE activation failed", "Login unsuccessful", det_msg=str(resp), show=True, show_copy_button=True)
|
return error_dialog(None, "ADE activation failed", "Login unsuccessful", det_msg=str(resp), show=True, show_copy_button=True)
|
||||||
|
|
||||||
success, resp = activateDevice(idx)
|
success, resp = activateDevice(idx, None)
|
||||||
if (success is False):
|
if (success is False):
|
||||||
return error_dialog(None, "ADE activation failed", "Couldn't activate device", det_msg=str(resp), show=True, show_copy_button=True)
|
return error_dialog(None, "ADE activation failed", "Couldn't activate device", det_msg=str(resp), show=True, show_copy_button=True)
|
||||||
|
|
||||||
@ -1106,7 +1207,7 @@ class ConfigWidget(QWidget):
|
|||||||
if (success is False):
|
if (success is False):
|
||||||
return error_dialog(None, "ADE activation failed", "Login unsuccessful", det_msg=str(resp), show=True, show_copy_button=True)
|
return error_dialog(None, "ADE activation failed", "Login unsuccessful", det_msg=str(resp), show=True, show_copy_button=True)
|
||||||
|
|
||||||
success, resp = activateDevice(vers_idx)
|
success, resp = activateDevice(vers_idx, None)
|
||||||
if (success is False):
|
if (success is False):
|
||||||
return error_dialog(None, "ADE activation failed", "Couldn't activate device", det_msg=str(resp), show=True, show_copy_button=True)
|
return error_dialog(None, "ADE activation failed", "Couldn't activate device", det_msg=str(resp), show=True, show_copy_button=True)
|
||||||
|
|
||||||
|
@ -472,6 +472,175 @@ def signIn(account_type: str, username: str, passwd: str):
|
|||||||
|
|
||||||
return True, "Done"
|
return True, "Done"
|
||||||
|
|
||||||
|
def exportProxyAuth(act_xml_path, activationToken):
|
||||||
|
# This authorizes a tethered device.
|
||||||
|
# ret, data = exportProxyAuth(act_xml_path, data)
|
||||||
|
|
||||||
|
activationxml = etree.parse(get_activation_xml_path())
|
||||||
|
adNS = lambda tag: '{%s}%s' % ('http://ns.adobe.com/adept', tag)
|
||||||
|
|
||||||
|
# At some point I should probably rewrite this, but I want to be sure the format is
|
||||||
|
# correct so I'm recreating the whole XML myself.
|
||||||
|
|
||||||
|
rt_si_authURL = activationxml.find("./%s/%s" % (adNS("activationServiceInfo"), adNS("authURL"))).text
|
||||||
|
rt_si_userInfoURL = activationxml.find("./%s/%s" % (adNS("activationServiceInfo"), adNS("userInfoURL"))).text
|
||||||
|
rt_si_activationURL = activationxml.find("./%s/%s" % (adNS("activationServiceInfo"), adNS("activationURL"))).text
|
||||||
|
rt_si_certificate = activationxml.find("./%s/%s" % (adNS("activationServiceInfo"), adNS("certificate"))).text
|
||||||
|
|
||||||
|
rt_c_user = activationxml.find("./%s/%s" % (adNS("credentials"), adNS("user"))).text
|
||||||
|
rt_c_licenseCertificate = activationxml.find("./%s/%s" % (adNS("credentials"), adNS("licenseCertificate"))).text
|
||||||
|
rt_c_privateLicenseKey = activationxml.find("./%s/%s" % (adNS("credentials"), adNS("privateLicenseKey"))).text
|
||||||
|
rt_c_authenticationCertificate = activationxml.find("./%s/%s" % (adNS("credentials"), adNS("authenticationCertificate"))).text
|
||||||
|
|
||||||
|
rt_c_username = None
|
||||||
|
rt_c_usernameMethod = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
rt_c_username = activationxml.find("./%s/%s" % (adNS("credentials"), adNS("username"))).text
|
||||||
|
rt_c_usernameMethod = activationxml.find("./%s/%s" % (adNS("credentials"), adNS("username"))).get("method", "AdobeID")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
ret = "<?xml version=\"1.0\"?>"
|
||||||
|
ret += "<activationInfo xmlns=\"http://ns.adobe.com/adept\">"
|
||||||
|
ret += "<adept:activationServiceInfo xmlns:adept=\"http://ns.adobe.com/adept\">"
|
||||||
|
ret += "<adept:authURL>%s</adept:authURL>" % (rt_si_authURL)
|
||||||
|
ret += "<adept:userInfoURL>%s</adept:userInfoURL>" % (rt_si_userInfoURL)
|
||||||
|
ret += "<adept:activationURL>%s</adept:activationURL>" % (rt_si_activationURL)
|
||||||
|
ret += "<adept:certificate>%s</adept:certificate>" % (rt_si_certificate)
|
||||||
|
ret += "</adept:activationServiceInfo>"
|
||||||
|
|
||||||
|
ret += "<adept:credentials xmlns:adept=\"http://ns.adobe.com/adept\">"
|
||||||
|
ret += "<adept:user>%s</adept:user>" % (rt_c_user)
|
||||||
|
ret += "<adept:licenseCertificate>%s</adept:licenseCertificate>" % (rt_c_licenseCertificate)
|
||||||
|
ret += "<adept:privateLicenseKey>%s</adept:privateLicenseKey>" % (rt_c_privateLicenseKey)
|
||||||
|
ret += "<adept:authenticationCertificate>%s</adept:authenticationCertificate>" % (rt_c_authenticationCertificate)
|
||||||
|
|
||||||
|
if rt_c_username is not None:
|
||||||
|
ret += "<adept:username method=\"%s\">%s</adept:username>" % (rt_c_usernameMethod, rt_c_username)
|
||||||
|
|
||||||
|
ret += "</adept:credentials>"
|
||||||
|
|
||||||
|
activationToken = activationToken.decode("latin-1")
|
||||||
|
# Yeah, terrible hack, but Adobe sends the token with namespace but exports it without.
|
||||||
|
activationToken = activationToken.replace(' xmlns="http://ns.adobe.com/adept"', '')
|
||||||
|
|
||||||
|
ret += activationToken
|
||||||
|
|
||||||
|
ret += "</activationInfo>"
|
||||||
|
|
||||||
|
# Okay, now we can finally write this to the device.
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = open(act_xml_path, "w")
|
||||||
|
f.write(ret)
|
||||||
|
f.close()
|
||||||
|
except:
|
||||||
|
return False, "Can't write file"
|
||||||
|
|
||||||
|
return True, "Done"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def buildActivateReqProxy(useVersionIndex: int = 0, proxyData = None):
|
||||||
|
|
||||||
|
if proxyData is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if useVersionIndex >= len(VAR_VER_SUPP_CONFIG_NAMES):
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
build_id = VAR_VER_BUILD_IDS[useVersionIndex]
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if build_id not in VAR_VER_ALLOWED_BUILD_IDS_AUTHORIZE:
|
||||||
|
# ADE 1.7.2 or another version that authorization is disabled for
|
||||||
|
return False
|
||||||
|
|
||||||
|
local_device_xml = etree.parse(get_device_path())
|
||||||
|
local_activation_xml = etree.parse(get_activation_xml_path())
|
||||||
|
adNS = lambda tag: '{%s}%s' % ('http://ns.adobe.com/adept', tag)
|
||||||
|
|
||||||
|
version = None
|
||||||
|
clientOS = None
|
||||||
|
clientLocale = None
|
||||||
|
|
||||||
|
ver = local_device_xml.findall("./%s" % (adNS("version")))
|
||||||
|
|
||||||
|
|
||||||
|
for f in ver:
|
||||||
|
if f.get("name") == "hobbes":
|
||||||
|
version = f.get("value")
|
||||||
|
elif f.get("name") == "clientOS":
|
||||||
|
clientOS = f.get("value")
|
||||||
|
elif f.get("name") == "clientLocale":
|
||||||
|
clientLocale = f.get("value")
|
||||||
|
|
||||||
|
if (version is None or clientOS is None or clientLocale is None):
|
||||||
|
return False, "Required version information missing"
|
||||||
|
|
||||||
|
|
||||||
|
ret = ""
|
||||||
|
|
||||||
|
ret += "<?xml version=\"1.0\"?>"
|
||||||
|
ret += "<adept:activate xmlns:adept=\"http://ns.adobe.com/adept\" requestType=\"initial\">"
|
||||||
|
ret += "<adept:fingerprint>%s</adept:fingerprint>" % (proxyData.find("./%s" % (adNS("fingerprint"))).text)
|
||||||
|
ret += "<adept:deviceType>%s</adept:deviceType>" % (proxyData.find("./%s" % (adNS("deviceType"))).text)
|
||||||
|
ret += "<adept:clientOS>%s</adept:clientOS>" % (clientOS)
|
||||||
|
ret += "<adept:clientLocale>%s</adept:clientLocale>" % (clientLocale)
|
||||||
|
ret += "<adept:clientVersion>%s</adept:clientVersion>" % (VAR_VER_SUPP_VERSIONS[useVersionIndex])
|
||||||
|
|
||||||
|
ret += "<adept:proxyDevice>"
|
||||||
|
ret += "<adept:softwareVersion>%s</adept:softwareVersion>" % (version)
|
||||||
|
ret += "<adept:clientOS>%s</adept:clientOS>" % (clientOS)
|
||||||
|
ret += "<adept:clientLocale>%s</adept:clientLocale>" % (clientLocale)
|
||||||
|
ret += "<adept:clientVersion>%s</adept:clientVersion>" % (VAR_VER_SUPP_VERSIONS[useVersionIndex])
|
||||||
|
ret += "<adept:deviceType>%s</adept:deviceType>" % (local_device_xml.find("./%s" % (adNS("deviceType"))).text)
|
||||||
|
ret += "<adept:productName>%s</adept:productName>" % ("ADOBE Digitial Editions")
|
||||||
|
# YES, this typo ("Digitial" instead of "Digital") IS present in ADE!!
|
||||||
|
|
||||||
|
ret += "<adept:fingerprint>%s</adept:fingerprint>" % (local_device_xml.find("./%s" % (adNS("fingerprint"))).text)
|
||||||
|
|
||||||
|
ret += "<adept:activationToken>"
|
||||||
|
ret += "<adept:user>%s</adept:user>" % (local_activation_xml.find("./%s/%s" % (adNS("activationToken"), adNS("user"))).text)
|
||||||
|
ret += "<adept:device>%s</adept:device>" % (local_activation_xml.find("./%s/%s" % (adNS("activationToken"), adNS("device"))).text)
|
||||||
|
ret += "</adept:activationToken>"
|
||||||
|
ret += "</adept:proxyDevice>"
|
||||||
|
|
||||||
|
ret += "<adept:targetDevice>"
|
||||||
|
|
||||||
|
target_hobbes_vers = proxyData.findall("./%s" % (adNS("version")))
|
||||||
|
hobbes_version = None
|
||||||
|
for f in target_hobbes_vers:
|
||||||
|
if f.get("name") == "hobbes":
|
||||||
|
hobbes_version = f.get("value")
|
||||||
|
break
|
||||||
|
|
||||||
|
if hobbes_version is not None:
|
||||||
|
ret += "<adept:softwareVersion>%s</adept:softwareVersion>" % (hobbes_version)
|
||||||
|
|
||||||
|
ret += "<adept:clientVersion>%s</adept:clientVersion>" % (proxyData.find("./%s" % (adNS("deviceClass"))).text)
|
||||||
|
ret += "<adept:deviceType>%s</adept:deviceType>" % (proxyData.find("./%s" % (adNS("deviceType"))).text)
|
||||||
|
ret += "<adept:productName>%s</adept:productName>" % ("ADOBE Digitial Editions")
|
||||||
|
ret += "<adept:fingerprint>%s</adept:fingerprint>" % (proxyData.find("./%s" % (adNS("fingerprint"))).text)
|
||||||
|
|
||||||
|
|
||||||
|
ret += "</adept:targetDevice>"
|
||||||
|
|
||||||
|
ret += addNonce()
|
||||||
|
|
||||||
|
ret += "<adept:user>%s</adept:user>" % (local_activation_xml.find("./%s/%s" % (adNS("activationToken"), adNS("user"))).text)
|
||||||
|
|
||||||
|
ret += "</adept:activate>"
|
||||||
|
|
||||||
|
return True, ret
|
||||||
|
|
||||||
|
|
||||||
def buildActivateReq(useVersionIndex: int = 0):
|
def buildActivateReq(useVersionIndex: int = 0):
|
||||||
@ -589,7 +758,7 @@ def changeDeviceVersion(useVersionIndex: int = 0):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def activateDevice(useVersionIndex: int = 0):
|
def activateDevice(useVersionIndex: int = 0, proxyData = None):
|
||||||
|
|
||||||
if useVersionIndex >= len(VAR_VER_SUPP_CONFIG_NAMES):
|
if useVersionIndex >= len(VAR_VER_SUPP_CONFIG_NAMES):
|
||||||
return False, "Invalid Version index"
|
return False, "Invalid Version index"
|
||||||
@ -611,8 +780,10 @@ def activateDevice(useVersionIndex: int = 0):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if proxyData is not None:
|
||||||
result, activate_req = buildActivateReq(useVersionIndex)
|
result, activate_req = buildActivateReqProxy(useVersionIndex, proxyData)
|
||||||
|
else:
|
||||||
|
result, activate_req = buildActivateReq(useVersionIndex)
|
||||||
if (result is False):
|
if (result is False):
|
||||||
return False, "Building activation request failed: " + activate_req
|
return False, "Building activation request failed: " + activate_req
|
||||||
|
|
||||||
@ -663,6 +834,11 @@ def activateDevice(useVersionIndex: int = 0):
|
|||||||
print("Response from server: ")
|
print("Response from server: ")
|
||||||
print(ret)
|
print(ret)
|
||||||
|
|
||||||
|
if proxyData is not None:
|
||||||
|
# If we have a proxy device, this function doesn't know where to store the activation.
|
||||||
|
# Just return the data and have the caller figure that out.
|
||||||
|
return True, ret
|
||||||
|
|
||||||
# Soooo, lets go and append that to the XML:
|
# Soooo, lets go and append that to the XML:
|
||||||
|
|
||||||
f = open(get_activation_xml_path(), "r")
|
f = open(get_activation_xml_path(), "r")
|
||||||
|
Loading…
Reference in New Issue
Block a user