Giter VIP home page Giter VIP logo

acsm-calibre-plugin's Introduction

Calibre ACSM Input plugin

This is a Calibre plugin that allows you to turn ACSM files into EPUB or PDF files without the need for Adobe Digital Editions. It is a full Python reimplementation of libgourou by Grégory Soutadé (http://indefero.soutade.fr/p/libgourou/), and has since been extended by more and more features.

ACSM Input Plugin for Calibre - Copyright (c) 2021-2023 Leseratte10
ACSM Input Plugin for Calibre / acsm-calibre-plugin
Formerly known as "DeACSM"
Copyright (c) 2021-2023 Leseratte10

This software is based on a Python reimplementation of the C++ library 
"libgourou" by Grégory Soutadé which is under the LGPLv3 or later 
license (http://indefero.soutade.fr/p/libgourou/).

I have no idea whether a reimplementation in another language counts 
as "derivative use", so just in case it does, I'm putting this project 
under the GPLv3 (which is allowed in the LGPLv3 license) to prevent any 
licensing issues. 

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

See the "LICENSE" file for a full copy of the GNU GPL v3.

Known bugs

  • Versions 0.0.16 and below did sometimes return the wrong eBook (or none at all) when trying to return a book to the library through the "Loaned books" list, if you had multiple active loans from the same distributor / library. This will be fixed with the next release.

Setup

Download the plugin and import it into Calibre, then open the plugin settings. The plugin should display "Not authorized for any ADE ID". You now have multiple options to authorize the plugin:

  • You can click on "Link to ADE account" and enter your AdobeID credentials to link your Calibre installation to your AdobeID account. This uses up one of your available activations.
  • You can click on "Create anonymous authorization" to create an anonymous authorization. Make sure to create backups of that authorization.
  • If you have ADE installed and activated on your machine, you can click "Import activation from ADE" to clone the existing activation from your ADE installation.
  • If you have used this plugin before, you can click on "Import existing activation backup" to import a previously created activation backup (ZIP) file to restore an activation. This functionality can also be used to clone one activation to multiple computers.

During authorization, the plugin may ask you for the ADE version to emulate. Usually you can leave this setting as it is (ADE 2.0.1).

After you've activated the plugin, make a backup of the activation using the "Export account activation data". Then click "Export account encryption key" and import the resulting file into the DeDRM plugin for DRM removal. If you're using noDRM's fork of the DeDRM plugin, this step will happen automatically. If you don't have the DeDRM plugin set up (or you're not using noDRM's fork and didn't import the key file) you will not be able to read the downloaded books in Calibre due to the DRM.

Once that's done, download an ACSM file from Adobe's test library and see if you can import it into Calibre: https://www.adobe.com/de/solutions/ebook/digital-editions/sample-ebook-library.html

IMPORTANT:

  • I would suggest creating a new dummy AdobeID to use for Calibre so just in case Adobe detects this and bans you, you don't lose your main AdobeID.
  • Combined with that I suggest using the DeDRM plugin to make sure that losing your AdobeID doesn't also mean you'll lose access to all your eBooks.
  • If you use an anonymous authorization, make sure you make backups of the activation data.
  • If you use an anonymous authorization, you have the ability to copy that authorization into an AdobeID account at a later time (by clicking "Connect anonymous auth to ADE account"). This is useful if you have books linked to your authorization that you want to read elsewhere. Same restrictions as with ADE apply - you can only do this ONCE per AdobeID, and only if the AdobeID hasn't been in use elsewhere yet.
  • This software is not approved by Adobe. I am not responsible if Adobe detects that you're using nonstandard software and bans your account. Do not complain to me if Adobe bans your main ADE account - you have been warned.

Returning books

If a book is marked as returnable (like a library book), you can "return" it to the library using this plugin. Just open the plugin settings, click "Show loaned books" (the option is only visible if you have at least one loaned book that's been downloaded with this plugin), select the book, then click the arrow button to return. Or click the "X" button to just remove the loan record from the list without returning the book.

This makes the book available for someone else again, but it does not automatically get deleted from your Calibre library - you are responsible for doing that after returning a book.

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, and I've only tested this with a Pocketbook reader so far.

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

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.

  • register_ADE_account.py can be used to authorize a computer with an ADE account. This creates the three files activation.xml, device.xml and devicesalt. These files are in the same format as the ones for the Calibre computer authorization (inside the plugins/DeACSM/account/ folder). A ZIP activation export from Calibre will also contain these three files.
  • fulfill.py can be used - with valid ADE account files in the same folder - to turn an URLLink.acsm file into an eBook.
  • get_key_from_Adobe.py can be used to contact the Adobe server and download the DER key file for a given AdobeID to import into a DeDRM plugin. Just input your credentials and this script will output the DER file that can be used with DeDRM to decrypt books for this AdobeID. This works independantly from the account activation files or from this plugin, so it's a good way to get your AdobeID decryption key, especially if you're on Linux and it's too difficult to export the keys from ADE running inside Wine. This process does not use up one of your six device activations.

Though, generally it's recommended to use the Calibre plugin instead of these standalone scripts. Except for maybe the get_key_from_Adobe.py script if you want to remove DRM from existing eBooks without having to extract the key from ADE.

To-Do list for the future?

  • Support to copy an authorization from the plugin to an ADE install
  • Support for multiple independant authorizations (with an easy way to switch between them)
  • Import a JoinedAccount authorization from ADE (ADE2.0+)
  • Import multiple account authorizations from ADE (ADE2.0+)
  • Support to add an AdobeID to an eReader without replacing the existing one
  • Support for Adobe's "auth" download method instead of the "simple" method (ADE2.0+)
  • Support the JoinAccounts, ActivateLinkedAccounts and GetCredentialList functions to allow for merged AdobeIDs (ADE2.0+)
  • Support the SyncToDevice function to auto-download new books from ADE into Calibre (ADE4.0+)
  • Add small link in settings window that will open a popup with all the expert stuff like de-auth and account joining.
  • ...

acsm-calibre-plugin's People

Contributors

fperrin avatar hub2git avatar leseratte10 avatar melvyn2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

acsm-calibre-plugin's Issues

Encryption key export broken?

Bug description

I'm trying to import an ADE book with Calibre. I successfully logged in to my Adobe account with your plugin and I can download the epub from the ACSM.

But then Calibre fails the decryption:

DeDRM v10.0.3: Found new key 'DeACSM_uuid_44c825f8-2faf-4521-b803-d997eab0e949' in DeACSM plugin
DeDRM v10.0.3: Trying a new default key
s_3mohg7.epub is a secure Adobe Adept ePub.
Could not decrypt s_3mohg7.epub because of an exception:
Traceback (most recent call last):
  File "/home/tobias/.config/calibre/plugins/DeDRM.zip/ineptepub.py", line 305, in decryptBook
    rsakey = RSA.import_key(userkey) # parses the ASN1 structure
  File "/usr/lib/python3/dist-packages/Cryptodome/PublicKey/RSA.py", line 786, in import_key
    return _import_keyDER(extern_key, passphrase)
  File "/usr/lib/python3/dist-packages/Cryptodome/PublicKey/RSA.py", line 685, in _import_keyDER
    raise ValueError("RSA key format is not supported")
ValueError: RSA key format is not supported

DeDRM v10.0.3: Failed to decrypt with new default key after 2.4 seconds
DeDRM v10.0.3: Ultimately failed to decrypt after 2.4 seconds. Read the FAQs at noDRM's repository: https://github.com/noDRM/DeDRM_tools/blob/master/FAQs.md
DeACSM v0.0.16: Running file type plugin failed with traceback:
Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 486, in run
    plugin_ret = plugin.run(rpl)
  File "calibre_plugins.dedrm.__init__", line 1067, in run
    decrypted_ebook = self.ePubDecrypt(path_to_ebook)
  File "calibre_plugins.dedrm.__init__", line 665, in ePubDecrypt
    raise DeDRMError("{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at noDRM's repository: https://github.com/noDRM/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
calibre_plugins.dedrm.DeDRMError: DeDRM v10.0.3: Ultimately failed to decrypt after 2.4 seconds. Read the FAQs at noDRM's repository: https://github.com/noDRM/DeDRM_tools/blob/master/FAQs.md
DeACSM v0.0.16: Plugin returned nothing - skipping

I then tried to export the key from DeACSM into DeDRM manually, that didn't work either.

I tried to inspect the exported .der key manually, and it seems it's broken? At least openssl thinks so (replaced long hex sequences with [...]):

$ openssl asn1parse -inform DER -in adobe_uuid_44c825f8-2faf-4521-b803-d997eab0e949.der
    0:d=0  hl=4 l= 606 cons: SEQUENCE          
    4:d=1  hl=2 l=   1 prim: INTEGER           :00
    7:d=1  hl=3 l= 129 prim: INTEGER           :[...]
  139:d=1  hl=2 l=   3 prim: INTEGER           :010001
  144:d=1  hl=3 l= 129 prim: INTEGER           :[...]
  276:d=1  hl=2 l=  65 prim: INTEGER           :[...]
  343:d=1  hl=2 l=  65 prim: INTEGER           :[...]
  410:d=1  hl=2 l=  65 prim: INTEGER           :[...]
  477:d=1  hl=2 l=  65 prim: INTEGER           :[...]
  544:d=1  hl=2 l=  64 prim: INTEGER           :[...]
Error in encoding
80D2EB137B7F0000:error:0680009B:asn1 encoding routines:ASN1_get_object:too long:../crypto/asn1/asn1_lib.c:95:

Operating system

Linux

Which version of Calibre are you running?

6.8.0

Which version of the ACSM Input plugin are you running?

v0.0.16

Further information

No response

Suggestion: Make an Icon in the Main Menu

Hi, is it possible to have an icon in the Main Menu like Kindle Unpack does? This is for other feature like returning books, authorizing ADE, etc. Thanks for considering this!

OSError [Errno 5] I/O error when importing plugin

Bug description

ERROR: Unhandled exception: <b>OSError</b>:[Errno 5] Errore di input/output

calibre 6.9  embedded-python: True
Linux-5.19.17-x86_64-AMD_Ryzen_Threadripper_2990WX_32-Core_Processor-with-glibc2.36 Linux ('64bit', 'ELF')
('Linux', '5.19.17', '#1 SMP PREEMPT_DYNAMIC Mon Oct 24 13:00:29 CDT 2022')
Python 3.10.1
Interface language: None
Successfully initialized third party plugins: Gather KFX-ZIP (from KFX Input) (1, 50, 0) && DeDRM (10, 0, 3) && Package KFX (from KFX Input) (1, 50, 0) && Audit Log (1, 0, 18) && Extract ISBN (1, 6, 0) && KFX metadata reader (from KFX Input) (1, 50, 0) && KFX Input (1, 50, 0)
Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 155, in initialize
    print("Module update from \"{0}\" to \"{1}\", extracting ...".format(id, id_plugin))
OSError: [Errno 5] Errore di input/output

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "calibre/customize/ui.py", line 676, in initialize_plugin
  File "calibre_plugins.deacsm.__init__", line 236, in initialize
    traceback.print_exc()
  File "traceback.py", line 179, in print_exc
  File "traceback.py", line 121, in print_exception
OSError: [Errno 5] Errore di input/output

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "calibre/gui2/preferences/plugins.py", line 325, in add_plugin
  File "calibre/customize/ui.py", line 486, in add_plugin
  File "calibre/customize/ui.py", line 679, in initialize_plugin
OSError: [Errno 5] Errore di input/output

Operating system

Linux

Which version of Calibre are you running?

6.9.0

Which version of the ACSM Input plugin are you running?

v0.0.16

Further information

No response

"No module named libadobe" when attempting to import plugin

Bug description

"Invalid Plugin" error when attempting to import plugin, first time installing. Looks like there are two modules it can't find, libadobe and oscrypto.
Error message:

calibre, version 5.41.0
ERROR: Unhandled exception: <b>InvalidPlugin</b>:Initialization of plugin Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 184, in initialize
  File "calibre\customize\zipplugin.py", line 191, in exec_module
  File "calibre_plugins.deacsm.libadobe", line 29, in &lt;module&gt;
ModuleNotFoundError: No module named 'oscrypto'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "calibre\customize\ui.py", line 673, in initialize_plugin
  File "calibre_plugins.deacsm.__init__", line 187, in initialize
ModuleNotFoundError: No module named 'libadobe'
 failed with traceback:
Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 184, in initialize
  File "calibre\customize\zipplugin.py", line 191, in exec_module
  File "calibre_plugins.deacsm.libadobe", line 29, in &lt;module&gt;
ModuleNotFoundError: No module named 'oscrypto'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "calibre\customize\ui.py", line 673, in initialize_plugin
  File "calibre_plugins.deacsm.__init__", line 187, in initialize
ModuleNotFoundError: No module named 'libadobe'


calibre 5.41  embedded-python: True is64bit: False
Windows-10-10.0.19041 Windows ('32bit', 'WindowsPE')
32bit process running on 64bit windows
('Windows', '10', '10.0.19041')
Python 3.8.5
Windows: ('10', '10.0.19041', '', 'Multiprocessor Free')
Interface language: None
Successfully initialized third party plugins: DeDRM (7, 2, 1)
Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 184, in initialize
  File "calibre\customize\zipplugin.py", line 191, in exec_module
  File "calibre_plugins.deacsm.libadobe", line 29, in <module>
ModuleNotFoundError: No module named 'oscrypto'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "calibre\customize\ui.py", line 673, in initialize_plugin
  File "calibre_plugins.deacsm.__init__", line 187, in initialize
ModuleNotFoundError: No module named 'libadobe'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "calibre\gui2\preferences\plugins.py", line 326, in add_plugin
  File "calibre\customize\ui.py", line 483, in add_plugin
  File "calibre\customize\ui.py", line 678, in initialize_plugin
calibre.customize.InvalidPlugin: Initialization of plugin Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 184, in initialize
  File "calibre\customize\zipplugin.py", line 191, in exec_module
  File "calibre_plugins.deacsm.libadobe", line 29, in <module>
ModuleNotFoundError: No module named 'oscrypto'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "calibre\customize\ui.py", line 673, in initialize_plugin
  File "calibre_plugins.deacsm.__init__", line 187, in initialize
ModuleNotFoundError: No module named 'libadobe'
 failed with traceback:
Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 184, in initialize
  File "calibre\customize\zipplugin.py", line 191, in exec_module
  File "calibre_plugins.deacsm.libadobe", line 29, in <module>
ModuleNotFoundError: No module named 'oscrypto'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "calibre\customize\ui.py", line 673, in initialize_plugin
  File "calibre_plugins.deacsm.__init__", line 187, in initialize
ModuleNotFoundError: No module named 'libadobe'

Thanks for your time.

Operating system

Windows

Which version of Calibre are you running?

v5.41.0

Which version of the DeACSM plugin are you running?

v0.0.15

Further information

No response

ACSM Not Converted

Bug description

Hi,

I think this may be related to some existing SSL issues but I'm not sure so I'm dropping it here. Feel free to merge accordingly.

I had DeACSM and DeDRM working correctly in Calibre but after updating to 6.23 DeACSM stopped importing as an EPUB. The files show up in Calibre as tiny ACSM files. I enabled debugging and got this:


calibre 6.23  embedded-python: True
Windows-10-10.0.19045-SP0 Windows ('64bit', 'WindowsPE')
('Windows', '10', '10.0.19045')
Python 3.10.1
Windows: ('10', '10.0.19045', 'SP0', 'Multiprocessor Free')
Interface language: None
Successfully initialized third party plugins: DeACSM (0, 0, 16) && DeDRM (10, 0, 3) && KoboTouchExtended (3, 6, 3)
calibre 6.23  embedded-python: True
Windows-10-10.0.19045-SP0 Windows ('64bit', 'WindowsPE')
('Windows', '10', '10.0.19045')
Python 3.10.1
Windows: ('10', '10.0.19045', 'SP0', 'Multiprocessor Free')
Interface language: None
Successfully initialized third party plugins: DeACSM (0, 0, 16) && DeDRM (10, 0, 3) && KoboTouchExtended (3, 6, 3)
QPA platform: windows
devicePixelRatio: 1.5
logicalDpi: 96.0 x 96.0
physicalDpi: 110.96245733788396 x 110.83636363636363
[0.00] Starting up...
[0.00] Showing splash screen...
[0.22] splash screen shown
[0.22] Initializing db...
[0.31] db initialized
[0.31] Constructing main UI...
[1.42] main UI initialized...
[1.42] Hiding splash screen
Starting QuickView
[23.48] splash screen hidden
[23.48] Started up in 23.48 seconds with 13 books
stdout+stderr from file dialog helper: [b'', b'']
piped data from file dialog helper: [b'L\xd7\x07\xd0_\xc3\xcf\x17\xa3}\\\xc8"\x7f\xdbJ\xcds\x14\x8d\xc7\xf5q\xd4\xda\xa0m\x1c!\xfe\xb8\xc8', b'C:\\Users\\REMOVED.acsm']
Running file type plugin DeACSM failed with traceback:
Traceback (most recent call last):
  File "urllib\request.py", line 1348, in do_open
  File "http\client.py", line 1282, in request
  File "http\client.py", line 1328, in _send_request
  File "http\client.py", line 1277, in endheaders
  File "http\client.py", line 1037, in _send_output
  File "http\client.py", line 975, in send
  File "http\client.py", line 1454, in connect
  File "ssl.py", line 512, in wrap_socket
  File "ssl.py", line 1070, in _create
  File "ssl.py", line 1341, in do_handshake
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:997)

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "calibre\customize\ui.py", line 187, in _run_filetype_plugins
  File "calibre_plugins.deacsm.__init__", line 422, in run
  File "calibre_plugins.deacsm.__init__", line 324, in download
  File "C:\Users\REMOVED\AppData\Roaming\calibre\plugins\DeACSM.zip\libadobe.py", line 267, in sendHTTPRequest_DL2FILE
  File "urllib\request.py", line 216, in urlopen
  File "urllib\request.py", line 519, in open
  File "urllib\request.py", line 536, in _open
  File "urllib\request.py", line 496, in _call_chain
  File "urllib\request.py", line 1391, in https_open
  File "urllib\request.py", line 1351, in do_open
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:997)>
DeACSM v0.0.16: Trying to parse file REMOVED.acsm
DeACSM v0.0.16: Try to fulfill ...
Notifying server ...
Notifying server https://acsepub.contentreserve.com/fulfillment/FulfillmentNotification
Fulfillment notification successful.
Notifying optional server https://ofs.contentreserve.com/ACSNotificationService.svc/Notify
Weird Fulfillment Notification response: 
DeACSM v0.0.16: Downloading book ...
DeACSM v0.0.16: Loading book from https://acs.cdn.overdrive.com/ACSStore1/0111-1/5CC/7F7/F4/{REMOVED}Fmt410.epub

The file ends there. But copy/pasting that link in a browser downloaded an EPUB file which I was able to successfully import/remove DRM from, so something is going wrong with DeACSM.

Operating system

Windows

Which version of Calibre are you running?

6.23

Which version of the ACSM Input plugin are you running?

v0.0.16

Import type

Clicking the 'Add books' button in the menu bar

Further information

No response

Calculate Nonce

I'm implementing this in Lua (for real this time :) so that I can make a KOReader plugin.
I've gotten through signing in, and now I need to do activation.
The one thing that's tripping me up is calculating this nonce:

dt = datetime.utcnow()
usec = dt.microsecond
sec = (dt - datetime(1970,1,1)).total_seconds()


Ntime = int(int(sec * 1000) + usec/1000)

I think I get the part about converting it to Gregorian after that, and it looks like you're just calculating the current unix timestamp, right?
I don't get the whole usec thing though... why are you converting the unix timestamp to μs, and then adding the current μs divided by 1000 to it?

fulfill.py doesn't accept any filename besides "URLLink.acsm"

Bug description

I use fulfill.py directly to get books from .acsm files, without using Calibre. I noticed that fulfill.py only accepts .acsm files named "URLLink.acsm", and rejects any other filename. Is there a reason for this behavior? I think fulfill.py would be easier to use if it just accepted any .acsm filename.

Operating system

Linux

Which version of Calibre are you running?

none

Which version of the DeACSM plugin are you running?

0.0.15

Further information

No response

Error when trying to add plugin to Calibre

So, when I go to add the plugin through normal means, I get the following error

`calibre, version 5.25.0
ERROR: Unhandled exception: InvalidPlugin:Initialization of plugin Traceback (most recent call last):
File "/usr/lib/calibre/calibre/customize/ui.py", line 674, in initialize_plugin
p.initialize()
File "calibre_plugins.deacsm.init", line 138, in initialize
update_account_path(deacsmprefs["path_to_account_data"])
UnboundLocalError: local variable 'update_account_path' referenced before assignment
failed with traceback:
Traceback (most recent call last):
File "/usr/lib/calibre/calibre/customize/ui.py", line 674, in initialize_plugin
p.initialize()
File "calibre_plugins.deacsm.init", line 138, in initialize
update_account_path(deacsmprefs["path_to_account_data"])
UnboundLocalError: local variable 'update_account_path' referenced before assignment

calibre 5.25 embedded-python: False is64bit: True
Linux-5.13.0-16-generic-x86_64-with-glibc2.34 Linux ('64bit', 'ELF')
('Linux', '5.13.0-16-generic', '#16-Ubuntu SMP Fri Sep 3 14:53:27 UTC 2021')
Python 3.9.7
Interface language: None
Successfully initialized third party plugins: DeDRM (7, 2, 1) && Obok DeDRM (7, 2, 1)
Traceback (most recent call last):
File "/usr/lib/calibre/calibre/customize/ui.py", line 674, in initialize_plugin
p.initialize()
File "calibre_plugins.deacsm.init", line 138, in initialize
update_account_path(deacsmprefs["path_to_account_data"])
UnboundLocalError: local variable 'update_account_path' referenced before assignment

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/lib/calibre/calibre/gui2/preferences/plugins.py", line 327, in add_plugin
plugin = add_plugin(path)
File "/usr/lib/calibre/calibre/customize/ui.py", line 484, in add_plugin
plugin = initialize_plugin(plugin, path_to_zip_file, PluginInstallationType.EXTERNAL)
File "/usr/lib/calibre/calibre/customize/ui.py", line 679, in initialize_plugin
raise InvalidPlugin((_('Initialization of plugin %s failed with traceback:')
calibre.customize.InvalidPlugin: Initialization of plugin Traceback (most recent call last):
File "/usr/lib/calibre/calibre/customize/ui.py", line 674, in initialize_plugin
p.initialize()
File "calibre_plugins.deacsm.init", line 138, in initialize
update_account_path(deacsmprefs["path_to_account_data"])
UnboundLocalError: local variable 'update_account_path' referenced before assignment
failed with traceback:
Traceback (most recent call last):
File "/usr/lib/calibre/calibre/customize/ui.py", line 674, in initialize_plugin
p.initialize()
File "calibre_plugins.deacsm.init", line 138, in initialize
update_account_path(deacsmprefs["path_to_account_data"])
UnboundLocalError: local variable 'update_account_path' referenced before assignment
`

Running Kubuntu 21.10, with Calibre 5.25.0

Sorting XML keys for activation

Sorry to bother you again, but I'm a little confused.
In order to verify that the activation request came from the user you claim to be, you sign the SHA1 of the request with your auth key, correct?
The only thing I don't get is the key sorting: do you need to sort the XML you send to adobe, or only sort before you sign it (and still send the unordered version to adobe, who re-sorts it on the other end)
The reason I ask is that when I'm signing the keys, I could sort them pretty easily, as they're parsed and I can move them around, etc.
The problem is that the XML builder I'm using doesn't support sorting, so in order to sort them in XML form I would have to modify it significantly.

Activation token

So, I just would like to clarify a few things:
First, when activating, do we actually need to save anything it returns, other than the Device UUID? I'm a little confused, as the "activation token" you send to the server is not what is returned by the activation request, and is instead just constructed from the user and device UUIDs... so what is the signature for?

Second, where in your plugin is the book decrypted? I see that it downloads the epub, and inserts rights.xml, but what happens next so you can read it?

0.0.16 or 0.1.0 and how to install 0.1.0

Bug description

Thanks for your work. Should I go with official last release 0.0.16 or install current master with 0.1.0? Any advice? And how can I install 0.1.0 if there is no release?

Operating system

MacOS

Which version of Calibre are you running?

6.17.0

Which version of the ACSM Input plugin are you running?

v0.0.16

Import type

No response

Further information

No response

De-ACSM got overwhelmed with multiple ACSMs then deadlocked

Bug description

Several books went through fine but the rest suddenly didn't. The bar for processing stuck. I aborted and tried again to no avail. When the ACSM is processed in other device, it's said it's already fulfilled. Processed fine in ADE.

Calibre error.txt

Operating system

Windows

Which version of Calibre are you running?

6.11

Which version of the ACSM Input plugin are you running?

v0.0.17

Import type

Dragging-and-Dropping the ACSM file into the Calibre window

Further information

Version I use: https://github.com/Leseratte10/acsm-calibre-plugin/actions/runs/3689432064

Cannot decode ACSM file with calibre

Hi,

I'm not able to convert ACSM to epub file in calibre. I tried the Adobe test files and they work as expected. File is converted to epub.
i'm getting this error in the logfile.

Running file type plugin DeACSM failed with traceback:
Traceback (most recent call last):
File "urllib\request.py", line 1350, in do_open
File "http\client.py", line 1255, in request
File "http\client.py", line 1301, in _send_request
File "http\client.py", line 1250, in endheaders
File "http\client.py", line 1010, in _send_output
File "http\client.py", line 950, in send
File "http\client.py", line 921, in connect
File "socket.py", line 787, in create_connection
File "socket.py", line 918, in getaddrinfo
socket.gaierror: [Errno 11001] getaddrinfo failed

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "calibre\customize\ui.py", line 175, in _run_filetype_plugins
File "calibre_plugins.deacsm.init", line 378, in run
File "calibre_plugins.deacsm.libadobeFulfill", line 420, in fulfill
File "calibre_plugins.deacsm.libadobeFulfill", line 674, in performFulfillmentNotification
File "calibre_plugins.deacsm.libadobe", line 307, in sendRequestDocuRC
File "calibre_plugins.deacsm.libadobe", line 274, in sendPOSTHTTPRequest
File "urllib\request.py", line 222, in urlopen
File "urllib\request.py", line 525, in open
File "urllib\request.py", line 542, in _open
File "urllib\request.py", line 502, in _call_chain
File "urllib\request.py", line 1379, in http_open
File "urllib\request.py", line 1353, in do_open
urllib.error.URLError: <urlopen error [Errno 11001] getaddrinfo failed>
DeACSM v0.0.15: Trying to parse file URLLink.acsm
DeACSM v0.0.15: Try to fulfill ...

Operating system
Windows

Which version of Calibre are you running?
5.41

Which version of the DeACSM plugin are you running?
0.0.15

Further information
No response

TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'

Bug description

I get a bug when trying to show loaned books from the plugin:

calibre, version 5.43.0
ERROR: Unhandled exception: <b>TypeError</b>:unsupported operand type(s) for +: 'NoneType' and 'str'

calibre 5.43  embedded-python: False is64bit: True
Linux-6.3.8-200.fc38.x86_64-x86_64-with-glibc2.37 Linux ('64bit', 'ELF')
('Linux', '6.3.8-200.fc38.x86_64', '#1 SMP PREEMPT_DYNAMIC Thu Jun 15 02:15:40 UTC 2023')
Python 3.11.3
Interface language: None
Successfully initialized third party plugins: DeACSM (0, 0, 16) && DeDRM (7, 2, 1)
Traceback (most recent call last):
  File "calibre_plugins.deacsm.config", line 1298, in show_rented_books
    d = RentedBooksDialog(self, self.deacsmprefs["list_of_rented_books"])
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "calibre_plugins.deacsm.config", line 1321, in __init__
    self.populate_list()
  File "calibre_plugins.deacsm.config", line 1398, in populate_list
    item = QListWidgetItem(book["book_name"] + " " + info)
                           ~~~~~~~~~~~~~~~~~~^~~~~
TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'

Is this maybe due to me having deleted a book and it still being somehow in the database?

Operating system

Linux

Which version of Calibre are you running?

5.43.0

Which version of the ACSM Input plugin are you running?

v0.0.16

Import type

No response

Further information

No response

"No module named libadobe"

Bug description

I tried to install DeACSM, but it failed with:

calibre, version 5.35.0
ERROR: Install plugin failed: A problem occurred while installing this plugin. This plugin will now be uninstalled. Please post the error message in details below into the forum thread for this plugin and restart calibre.

Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 184, in initialize
    from calibre_plugins.deacsm.libadobe import createDeviceKeyFile, update_account_path
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "/usr/lib/calibre/calibre/customize/zipplugin.py", line 191, in exec_module
    exec(compiled, module.__dict__)
  File "calibre_plugins.deacsm.libadobe", line 18, in <module>
    from Crypto.Cipher import AES
  File "/usr/lib/python3.10/site-packages/Crypto/Cipher/__init__.py", line 27, in <module>
    from Crypto.Cipher._mode_ecb import _create_ecb_cipher
  File "/usr/lib/python3.10/site-packages/Crypto/Cipher/_mode_ecb.py", line 29, in <module>
    from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
  File "/usr/lib/python3.10/site-packages/Crypto/Util/_raw_api.py", line 81, in <module>
    ffi = FFI()
  File "/home/system/.local/lib/python3.10/site-packages/cffi/api.py", line 54, in __init__
    raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r.  When we import the top-level '_cffi_backend' extension module, we get version %s, located in %r.  The two versions should be equal; check your installation." % (
Exception: Version mismatch: this is the 'cffi' package version 1.14.6, located in '/home/system/.local/lib/python3.10/site-packages/cffi/api.py'.  When we import the top-level '_cffi_backend' extension module, we get version 1.15.0, located in '/usr/lib/python3.10/site-packages/_cffi_backend.cpython-310-aarch64-linux-gnu.so'.  The two versions should be equal; check your installation.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/calibre/calibre/customize/ui.py", line 673, in initialize_plugin
    p.initialize()
  File "calibre_plugins.deacsm.__init__", line 187, in initialize
    from libadobe import createDeviceKeyFile, update_account_path
ModuleNotFoundError: No module named 'libadobe'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/calibre/calibre/gui2/dialogs/plugin_updater.py", line 712, in _install_clicked
    plugin = add_plugin(zip_path)
  File "/usr/lib/calibre/calibre/customize/ui.py", line 483, in add_plugin
    plugin = initialize_plugin(plugin, path_to_zip_file, PluginInstallationType.EXTERNAL)
  File "/usr/lib/calibre/calibre/customize/ui.py", line 678, in initialize_plugin
    raise InvalidPlugin((_('Initialization of plugin %s failed with traceback:')
calibre.customize.InvalidPlugin: Initialization of plugin Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 184, in initialize
    from calibre_plugins.deacsm.libadobe import createDeviceKeyFile, update_account_path
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "/usr/lib/calibre/calibre/customize/zipplugin.py", line 191, in exec_module
    exec(compiled, module.__dict__)
  File "calibre_plugins.deacsm.libadobe", line 18, in <module>
    from Crypto.Cipher import AES
  File "/usr/lib/python3.10/site-packages/Crypto/Cipher/__init__.py", line 27, in <module>
    from Crypto.Cipher._mode_ecb import _create_ecb_cipher
  File "/usr/lib/python3.10/site-packages/Crypto/Cipher/_mode_ecb.py", line 29, in <module>
    from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
  File "/usr/lib/python3.10/site-packages/Crypto/Util/_raw_api.py", line 81, in <module>
    ffi = FFI()
  File "/home/system/.local/lib/python3.10/site-packages/cffi/api.py", line 54, in __init__
    raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r.  When we import the top-level '_cffi_backend' extension module, we get version %s, located in %r.  The two versions should be equal; check your installation." % (
Exception: Version mismatch: this is the 'cffi' package version 1.14.6, located in '/home/system/.local/lib/python3.10/site-packages/cffi/api.py'.  When we import the top-level '_cffi_backend' extension module, we get version 1.15.0, located in '/usr/lib/python3.10/site-packages/_cffi_backend.cpython-310-aarch64-linux-gnu.so'.  The two versions should be equal; check your installation.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/calibre/calibre/customize/ui.py", line 673, in initialize_plugin
    p.initialize()
  File "calibre_plugins.deacsm.__init__", line 187, in initialize
    from libadobe import createDeviceKeyFile, update_account_path
ModuleNotFoundError: No module named 'libadobe'
 failed with traceback:
Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 184, in initialize
    from calibre_plugins.deacsm.libadobe import createDeviceKeyFile, update_account_path
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "/usr/lib/calibre/calibre/customize/zipplugin.py", line 191, in exec_module
    exec(compiled, module.__dict__)
  File "calibre_plugins.deacsm.libadobe", line 18, in <module>
    from Crypto.Cipher import AES
  File "/usr/lib/python3.10/site-packages/Crypto/Cipher/__init__.py", line 27, in <module>
    from Crypto.Cipher._mode_ecb import _create_ecb_cipher
  File "/usr/lib/python3.10/site-packages/Crypto/Cipher/_mode_ecb.py", line 29, in <module>
    from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
  File "/usr/lib/python3.10/site-packages/Crypto/Util/_raw_api.py", line 81, in <module>
    ffi = FFI()
  File "/home/system/.local/lib/python3.10/site-packages/cffi/api.py", line 54, in __init__
    raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r.  When we import the top-level '_cffi_backend' extension module, we get version %s, located in %r.  The two versions should be equal; check your installation." % (
Exception: Version mismatch: this is the 'cffi' package version 1.14.6, located in '/home/system/.local/lib/python3.10/site-packages/cffi/api.py'.  When we import the top-level '_cffi_backend' extension module, we get version 1.15.0, located in '/usr/lib/python3.10/site-packages/_cffi_backend.cpython-310-aarch64-linux-gnu.so'.  The two versions should be equal; check your installation.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/calibre/calibre/customize/ui.py", line 673, in initialize_plugin
    p.initialize()
  File "calibre_plugins.deacsm.__init__", line 187, in initialize
    from libadobe import createDeviceKeyFile, update_account_path
ModuleNotFoundError: No module named 'libadobe'

Operating system

Linux

Which version of Calibre are you running?

5.35

Which version of the DeACSM plugin are you running?

v0.0.15

Further information

No response

Install plugin failed

calibre, version 3.39.1
ERROR: Install plugin failed: A problem occurred while installing this plugin. This plugin will now be uninstalled. Please post the error message in details below into the forum thread for this plugin and restart calibre.

Traceback (most recent call last):
File "/usr/lib/calibre/calibre/gui2/dialogs/plugin_updater.py", line 726, in _install_clicked
plugin = add_plugin(zip_path)
File "/usr/lib/calibre/calibre/customize/ui.py", line 472, in add_plugin
plugin = load_plugin(path_to_zip_file)
File "/usr/lib/calibre/calibre/customize/ui.py", line 61, in load_plugin
return loader.load(path_to_zip_file)
File "/usr/lib/calibre/calibre/customize/zipplugin.py", line 200, in load
reload(m)
File "/usr/lib/calibre/calibre/customize/zipplugin.py", line 180, in load_module
import_name), 'exec', dont_inherit=True)
File "calibre_plugins.deacsm.init", line 243
def download(self, replyData: str):
^
SyntaxError: invalid syntax

Plugin cannot install/initialize due to `OSError: dlopen(libcrypto.dylib)`

Bug description

DeACSM is failing to install due to failing to dlopen libcrypto. The relevant error appears to be:
OSError: dlopen(/usr/local/lib/libcrypto.dylib, 0x0006): tried: '/usr/local/lib/libcrypto.dylib' (code signature in &lt;1FCD44A2-E972-3D3D-95D1-4B7BF8459E95&gt; '/usr/local/Cellar/openssl@3/3.1.2/lib/libcrypto.3.dylib' not valid for use in process: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed.) Full trace is below.

I had Calibre successfully importing acsm previously, though I had both this and DeDRM installed and I don't recall which I actually had doing the import decryption. Something changed since my last successful import a couple months ago - possibly because I upgraded from macOS 12 (Monterey) to 13 (Ventura), not sure.

/usr/local/lib/libcrypto.dylib is a symlink to /usr/local/Cellar/openssl@3/3.1.2/lib/libcrypto.3.dylib, installed by Homebrew (and freshly upgraded from 3.1.1 to see if that would fix this problem). Homebrew seems to not sign this; I tried signing it ad-hoc with codesign --sign - /usr/local/lib/libcrypto.dylib but it just changed the error message to not valid for use in process: mapped file has no Team ID and is not a platform binary (signed with custom identity or adhoc?)

I'm not sure if the right place for this issue is here, or with the Python oscrypto lib, or with Homebrew.
I also see somebody on MobileRead encountering the same issue: https://www.mobileread.com/forums/showthread.php?p=4341213

Full trace:
calibre 6.22  embedded-python: True
macOS-13.5.1-x86_64-i386-64bit Darwin ('64bit', '')
('Darwin', '22.6.0', 'Darwin Kernel Version 22.6.0: Wed Jul  5 22:21:56 PDT 2023; root:xnu-8796.141.3~6/RELEASE_X86_64')
Python 3.10.1
OSX: ('13.5.1', ('', '', ''), 'x86_64')
Interface language: None
Successfully initialized third party plugins: DeDRM (10, 0, 3)
QPA platform: cocoa
Starting QuickView
2023-08-21 13:44:58.206 calibre-debug[26453:2678849] +[CATransaction synchronize] called within transaction
2023-08-21 13:44:58.395 calibre-debug[26453:2678849] +[CATransaction synchronize] called within transaction
Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 226, in initialize
    from libadobe import createDeviceKeyFile, update_account_path, sendHTTPRequest
  File "/Users/ethan/in/firefox/DeACSM_0.0.16.zip/libadobe.py", line 59, in <module>
    from oscrypto import keys
  File "/Users/ethan/Library/Preferences/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/keys.py", line 5, in <module>
    from ._asymmetric import parse_certificate, parse_private, parse_public
  File "/Users/ethan/Library/Preferences/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_asymmetric.py", line 27, in <module>
    from .kdf import pbkdf1, pbkdf2, pkcs12_kdf
  File "/Users/ethan/Library/Preferences/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/kdf.py", line 9, in <module>
    from .util import rand_bytes
  File "/Users/ethan/Library/Preferences/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/util.py", line 10, in <module>
    from ._mac.util import rand_bytes
  File "/Users/ethan/Library/Preferences/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_mac/util.py", line 208, in <module>
    from .._openssl._libcrypto import libcrypto
  File "/Users/ethan/Library/Preferences/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto.py", line 24, in <module>
    from ._libcrypto_ctypes import (
  File "/Users/ethan/Library/Preferences/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_ctypes.py", line 30, in <module>
    libcrypto = CDLL(libcrypto_path, use_errno=True)
  File "ctypes/__init__.py", line 374, in __init__
OSError: dlopen(/usr/local/lib/libcrypto.dylib, 0x0006): tried: '/usr/local/lib/libcrypto.dylib' (code signature in <1FCD44A2-E972-3D3D-95D1-4B7BF8459E95> '/usr/local/Cellar/openssl@3/3.1.2/lib/libcrypto.3.dylib' not valid for use in process: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed.), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/lib/libcrypto.dylib' (no such file), '/usr/local/lib/libcrypto.dylib' (code signature in <1FCD44A2-E972-3D3D-95D1-4B7BF8459E95> '/usr/local/Cellar/openssl@3/3.1.2/lib/libcrypto.3.dylib' not valid for use in process: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed.), '/usr/local/Cellar/openssl@3/3.1.2/lib/libcrypto.3.dylib' (code signature in <1FCD44A2-E972-3D3D-95D1-4B7BF8459E95> '/usr/local/Cellar/openssl@3/3.1.2/lib/libcrypto.3.dylib' not valid for use in process: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed.), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/Cellar/openssl@3/3.1.2/lib/libcrypto.3.dylib' (no such file), '/usr/local/Cellar/openssl@3/3.1.2/lib/libcrypto.3.dylib' (code signature in <1FCD44A2-E972-3D3D-95D1-4B7BF8459E95> '/usr/local/Cellar/openssl@3/3.1.2/lib/libcrypto.3.dylib' not valid for use in process: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed.)

Operating system

MacOS

Which version of Calibre are you running?

6.22.0

Which version of the ACSM Input plugin are you running?

v0.0.16

Import type

No response

Further information

No response

Apostrophe in title got converted to weird unicode

Hello, sometimes, a book title that has apostrophe in the title got converted into weird unicode (’) so for example: The Bookseller's Apprentice becomes The Bookseller’s Apprentice. The folder name becomes The BookselleraEUTMs Apprentice - Amelia Mellor.
Is this due to Calibre, ADE, the plugin, Windows?
Haven't figured out the situation that caused this. Should I send a log when re-processing these titles?

Attached is some screenshot:
image image image

Option to elect ADE version on authorisation missing>

When I authorise to a new Adobe ID there is no option presented to select the version of ADE as described in the documentation. Is this no longer an option? What version of ADE is selected by default? And thanks for the great work!

"This book is locked by DRM" after adding

Bug description

  • Installed plugin
  • Created anonymous ID thing
  • Restarted calibre
  • Imported the acsm file I got from my library, the book got added with the correct title and author, and I can find the .epub file in my file system
  • Double-click it in calibre, it opens the book reader but shows me the below alert

image

Operating system

Linux

Which version of Calibre are you running?

5.34

Which version of the DeACSM plugin are you running?

?

Further information

No response

Document E_AUTH_USER_AUTH

I just thought it might be useful to document (in the error codes wiki) the E_AUTH_USER_AUTH error code: something along the lines of:

This error occurs if the XML signature is invalid and can't be parsed properly. This either means something went wrong when generating the signature, or it's an Adobe server issue.

If this happens with the Calibre plugin, please open a bug report.

Calibre loads the file but plugin does not find the book

Bug description

Hello and thanks for all of your hard work with this plugin!

I'm using the plugin on a Linux machine running PopOS and have deDRM installed as well. I have some books in ASCM format and have added those to Calibre and they open just fine using deDRM. Other ASCM files when added to Calibre remain as ASCM files instead of being converted to epub format. Should I change the ADE version? Thanks again!

Operating system

Linux

Which version of Calibre are you running?

6.8

Which version of the ACSM Input plugin are you running?

0.0.16

Further information

No response

Bug while importing books from my local library

Bug description

Importing books from Adobe's test library works well. But I have an error when trying to import books from a local library, any help would be appreciated.

[1.72] Started up in 1.72 seconds with 17 books
Starting QuickView
Running file type plugin DeACSM failed with traceback:
Traceback (most recent call last):
  File "calibre/customize/ui.py", line 175, in _run_filetype_plugins
  File "calibre_plugins.deacsm.__init__", line 378, in run
    success, replyData = fulfill(path_to_ebook, deacsmprefs["notify_fulfillment"])
  File "calibre_plugins.deacsm.libadobeFulfill", line 439, in fulfill
    updateLoanReturnData(adobe_fulfill_response)
  File "calibre_plugins.deacsm.libadobeFulfill", line 479, in updateLoanReturnData
    deviceUUID = fulfillmentResultToken.find("./%s/%s/%s/%s" % (adNS("fulfillmentResult"), adNS("resourceItemInfo"), adNS("licenseToken"), adNS("device"))).text
AttributeError: 'NoneType' object has no attribute 'text'

Thanks a lot for this awesome plugging!

Operating system

MacOS

Which version of Calibre are you running?

5.42.0

Which version of the DeACSM plugin are you running?

v0.0.15

Further information

No response

plug-in installation fails

Bug description

I attempted to install the plugin by first downloading the plugin zip file from the github release. I got the error message below. I also attempted to install from an interactive calibre session, which also resulted in this error.

Operating system

Linux

Which version of Calibre are you running?

5.35.0

Which version of the DeACSM plugin are you running?

v0.0.15

Further information

calibre, version 5.35.0
ERROR: Install plugin failed: A problem occurred while installing this plugin. This plugin will now be uninstalled. Please post the error message in details below into the forum thread for this plugin and restart calibre.

Traceback (most recent call last):
File "calibre_plugins.deacsm.init", line 125, in initialize
print("Module update from "{0}" to "{1}", extracting ...".format(id, id_plugin))
OSError: [Errno 5] Input/output error

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "calibre/customize/ui.py", line 673, in initialize_plugin
File "calibre_plugins.deacsm.init", line 204, in initialize
traceback.print_exc()
File "traceback.py", line 163, in print_exc
File "traceback.py", line 105, in print_exception
OSError: [Errno 5] Input/output error

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "calibre/gui2/dialogs/plugin_updater.py", line 712, in _install_clicked
File "calibre/customize/ui.py", line 483, in add_plugin
File "calibre/customize/ui.py", line 676, in initialize_plugin
OSError: [Errno 5] Input/output error

Create implementation-agnostic ADEPT documentation

It would be great if you could create some kind of spec for ADEPT so that different implementations can be made without reading all of the source code. I'm doing a lot of work for my rust implementation just trying to figure out all of what needs to be done.

"OverflowError: int too big to convert" when linking ADE account

I have DeACMS 0.0.9 installed in Calibre 5.30, but when I try link my ADE account, I got the following error.

calibre, version 5.30.0
VIRHE Unhandled exception: <b>OverflowError</b>:int too big to convert

calibre 5.30  embedded-python: False is64bit: True
Linux-5.15.0-1-cachyos-rc-x86_64-with-glibc2.33 Linux ('64bit', 'ELF')
('Linux', '5.15.0-1-cachyos-rc', '#1 SMP PREEMPT Thu, 21 Oct 2021 00:52:38 +0000')
Python 3.9.7
Interface language: fi
Successfully initialized third party plugins: DeACSM (0, 0, 9) && DeDRM (7, 2, 1)
Traceback (most recent call last):
  File "calibre_plugins.deacsm.config", line 257, in link_account
    success, resp = activateDevice()
  File "calibre_plugins.deacsm.libadobeAccount", line 316, in activateDevice
    result, activate_req = buildActivateReq()
  File "calibre_plugins.deacsm.libadobeAccount", line 305, in buildActivateReq
    ret += addNonce()
  File "calibre_plugins.deacsm.libadobe", line 284, in addNonce
    final = bytearray(nonce320.to_bytes(4, 'little'))
OverflowError: int too big to convert

Error: Did not find ENC

Bug description

Hi!

DeACSM fails with some (I have two files *.acsm files). I checked one of these.

Here's end of Calibre log:

</envelope>Traceback (most recent call last):
  File "calibre/customize/ui.py", line 432, in get_file_type_metadata
  File "calibre/customize/builtins.py", line 315, in get_metadata
  File "calibre/ebooks/metadata/pdf.py", line 124, in get_metadata
ValueError: Could not read info dict from PDF

Not notifying any server since that was disabled.
DeACSM v0.0.16: Downloading book ...
DeACSM v0.0.16: Loading book from <removed>
Download took 30188 ms (HTTP 200)
That's a PDF file
DeACSM v0.0.16: Downloaded PDF, adding encryption config ...
Searching for startxref ...
Got startxref: 21779570
Error: Did not find ENC - took 285 ms
Error, enc not found
DeACSM v0.0.16: There was an error patching the PDF file.
Syntax Error: Document stream is empty
pdfinfo errored out with return code: 1
Added 0 books in 35.4 seconds

I have the full log and *.acsm file. Unfortunately, I cannot download the book by ADE, because I have different credentials on my Windows installation with ADE and different on my Linux system.

I'm happy to help you investigate this issue.

Operating system

Linux

Which version of Calibre are you running?

5.37

Which version of the ACSM Input plugin are you running?

v0.0.16

Further information

No response

DeACSM does not turn ACSM into epub

Bug description

I have bought an ebook with format epub and DRM.

Windows 10: I have downloaded the ACSM file and imported it in Adobe Digital Edition v2.0.1 and got the epub with DRM. The I used epubee to make it DRM free. It worked fine.

Linux: I have downloaded the ASCM file. I have installed Calibre v6.9.0 and two configured Plug-ins: DeACSM v0.0.16, DeDRM v10.0.3. Then I imported the ACSM file into Calibre but DeACSM does not turn ACSM into epub. The I imported the epub with DRM (the one I got from Windows) and wanted DeDRM to remove the DRM. But it did not work. Calibre viewer told me, that the eBook has DRM.
Then I have loaned an ebook from a Library. I have downloaded the ACSM file and imported the ACSM file into Calibre. This time the two Plug-ins worked correctly. DeACSM turned ACSM into epub and DeDRM removed the DRM successfully.

Any ideas? Thank you in advance!

Operating system

Linux

Which version of Calibre are you running?

6.9.0

Which version of the ACSM Input plugin are you running?

v.0.0.16

Further information

No response

Processing an ACSM file added via a plugin

Bug description

I've been using your plugin together with DeDRM to download from the library. The library is a non-US library and cannot send directly to the Kindle so calibre + DeACSM + DeDRM has been a real life saver.

I'm working on a plugin that downloads the .acsm. The plugin doesn't do much else except call calibre to download the .acsm file and depends on DeACSM and DeDRM to do the heavy lifting.

The problem is that the epub from the plugin downloaded .acsm does not contain any meta data at all. The epub is otherwise fine and viewable from calibre. My calibre setup seems fine because dragging a downloaded .acsm into calibre works perfectly (full meta, cover, title, author, etc).

Screenshot 2023-06-29 at 6 03 55 PM

Log from processing plugin-provided .acsm

DeACSM v0.0.16: Trying to parse file TheLastMusketeer_9780062048400_564352.acsm
DeACSM v0.0.16: Try to fulfill ...
Not notifying any server since that was disabled.
DeACSM v0.0.16: Downloading book ...
DeACSM v0.0.16: Loading book from https://acs.cdn.overdrive.com/ACSStore1/0293-1/941/FDF/FF/{941FDFFF-6CFD-4E11-A53D-178C18A32631}Fmt410.epub
Download took 524 ms (HTTP 200)
That's a ZIP file -> EPUB
DeACSM v0.0.16: File successfully fulfilled ...
DeACSM v0.0.16: Executing plugin DeDRM ...
DeDRM v10.0.3: Trying to decrypt 73bhkix9.epub
DeDRM v10.0.3: Verifying zip archive integrity
DeDRM v10.0.3: 73bhkix9.epub is a secure Adobe Adept ePub for UUID 53c5d855-9583-4ff0-8d85-76fa3c47d485
DeDRM v10.0.3: Trying UUID-matched encryption key DeACSM_uuid_53c5d855-9583-4ff0-8d85-76fa3c47d485
eda6cq9i.epub is a secure Adobe Adept ePub.
DeDRM v10.0.3: Decrypted with key DeACSM_uuid_53c5d855-9583-4ff0-8d85-76fa3c47d485 after 0.2 seconds
Watermark: Successfully stripped 39 ADEPT watermark(s) from ebook.
DeDRM v10.0.3: Post-processing took 0.1 seconds
DeDRM v10.0.3: Finished after 0.3 seconds
DeACSM v0.0.16: Plugin returned path '/var/folders/kr/bxxq54x51l714b1mrzyj0t1h0000gn/C/calibre_6.21.0_tmp_jxa1dsxh/trmhsgp9.epub', updating.
DeACSM v0.0.16: Deleting existing ACSM file /var/folders/kr/bxxq54x51l714b1mrzyj0t1h0000gn/C/calibre_6.21.0_tmp_jxa1dsxh/hkl6l6sr/TheLastMusketeer_9780062048400_564352.acsm ...
Job: 0 Downloading <redacted> finished
Starting job: Downloading <redacted>

Log from processing downloaded .acsm

DeACSM v0.0.16: Trying to parse file The Last Musketeer - Stuart Gibbs.acsm
DeACSM v0.0.16: Try to fulfill ...
Not notifying any server since that was disabled.
DeACSM v0.0.16: Downloading book ...
DeACSM v0.0.16: Loading book from https://acs.cdn.overdrive.com/ACSStore1/0293-1/941/FDF/FF/{941FDFFF-6CFD-4E11-A53D-178C18A32631}Fmt410.epub
Download took 74 ms (HTTP 200)
That's a ZIP file -> EPUB
DeACSM v0.0.16: File successfully fulfilled ...
DeACSM v0.0.16: Executing plugin DeDRM ...
DeDRM v10.0.3: Trying to decrypt 3wgeii6t.epub
DeDRM v10.0.3: Verifying zip archive integrity
DeDRM v10.0.3: 3wgeii6t.epub is a secure Adobe Adept ePub for UUID 53c5d855-9583-4ff0-8d85-76fa3c47d485
DeDRM v10.0.3: Trying UUID-matched encryption key DeACSM_uuid_53c5d855-9583-4ff0-8d85-76fa3c47d485
qfk0il7s.epub is a secure Adobe Adept ePub.
DeDRM v10.0.3: Decrypted with key DeACSM_uuid_53c5d855-9583-4ff0-8d85-76fa3c47d485 after 0.1 seconds
Watermark: Successfully stripped 39 ADEPT watermark(s) from ebook.
DeDRM v10.0.3: Post-processing took 0.1 seconds
DeDRM v10.0.3: Finished after 0.3 seconds
DeACSM v0.0.16: Plugin returned path '/var/folders/kr/bxxq54x51l714b1mrzyj0t1h0000gn/C/calibre_6.21.0_tmp_jxa1dsxh/lifprm8h.epub', updating.
DeACSM v0.0.16: Deleting existing ACSM file /<redacted>/The Last Musketeer - Stuart Gibbs.acsm ...
Added The Last Musketeer to db in: 0.1
Added 1 books in 3.0 seconds

The plugin is very much in a draft state so I'm not quite ready to publish it publicly. But briefly, the plugin calls calibre's download_ebook() with a custom browser instance that sends the required auth HTTP headers.

endpoint_url, headers = self.client.get_loan_fulfilment_details(
    loan["id"], loan["cardId"], format_id
)

def create_custom_browser():
    br = browser()
    for k, v in headers.items():
        br.set_header(k, v)
    return br

self.gui.download_ebook(url=endpoint_url, create_browser=create_custom_browser)

Operating system

MacOS

Which version of Calibre are you running?

6.21.0

Which version of the ACSM Input plugin are you running?

v0.0.16

Import type

No response

Further information

No response

Help with installation

Bug description

Hi, my friend tried to install ACSM INput in Mac but keep failing. I gave her the beta version (the one after you fix PDF)

This is the log. What's left is ACSM Input Plugin GUI Extension which can't be uninstalled, only disabled. Thanks for your help.

calibre, version 6.11.0
ERROR: Unhandled exception: InvalidPlugin:Initialisation of plug-in Traceback (most recent call last):
File "calibre/customize/ui.py", line 676, in initialize_plugin
File "calibre_plugins.deacsm.init", line 289, in initialize
deacsmprefs = prefs.ACSMInput_Prefs()
File "calibre_plugins.deacsm.prefs", line 58, in init
raise Exception("Why does the account folder not exist?")
Exception: Why does the account folder not exist?
failed with traceback:
Traceback (most recent call last):
File "calibre/customize/ui.py", line 676, in initialize_plugin
File "calibre_plugins.deacsm.init", line 289, in initialize
deacsmprefs = prefs.ACSMInput_Prefs()
File "calibre_plugins.deacsm.prefs", line 58, in init
raise Exception("Why does the account folder not exist?")
Exception: Why does the account folder not exist?

calibre 6.11 embedded-python: True
macOS-10.15.7-x86_64-i386-64bit Darwin ('64bit', '')
('Darwin', '19.6.0', 'Darwin Kernel Version 19.6.0: Tue Jun 21 21:18:39 PDT 2022; root:xnu-6153.141.66~1/RELEASE_X86_64')
Python 3.10.1
OSX: ('10.15.7', ('', '', ''), 'x86_64')
Interface language: en_GB
Successfully initialized third party plugins: Gather KFX-ZIP (from KFX Input) (1, 50, 0) && Package KFX (from KFX Input) (1, 50, 0) && EpubMerge (2, 7, 0) && EpubSplit (2, 8, 0) && KFX metadata reader (from KFX Input) (1, 50, 0) && KFX Input (1, 50, 0) && Set KFX metadata (from KFX Output) (1, 65, 0) && KFX Output (1, 65, 0) && KindleUnpack - The Plugin (0, 81, 5) && ACSM Input Plugin GUI Extension (0, 1, 0)
Traceback (most recent call last):
File "calibre/customize/ui.py", line 676, in initialize_plugin
File "calibre_plugins.deacsm.init", line 289, in initialize
deacsmprefs = prefs.ACSMInput_Prefs()
File "calibre_plugins.deacsm.prefs", line 58, in init
raise Exception("Why does the account folder not exist?")
Exception: Why does the account folder not exist?

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "calibre/gui2/preferences/plugins.py", line 325, in add_plugin
File "calibre/customize/ui.py", line 486, in add_plugin
File "calibre/customize/ui.py", line 681, in initialize_plugin
calibre.customize.InvalidPlugin: Initialisation of plug-in Traceback (most recent call last):
File "calibre/customize/ui.py", line 676, in initialize_plugin
File "calibre_plugins.deacsm.init", line 289, in initialize
deacsmprefs = prefs.ACSMInput_Prefs()
File "calibre_plugins.deacsm.prefs", line 58, in init
raise Exception("Why does the account folder not exist?")
Exception: Why does the account folder not exist?
failed with traceback:
Traceback (most recent call last):
File "calibre/customize/ui.py", line 676, in initialize_plugin
File "calibre_plugins.deacsm.init", line 289, in initialize
deacsmprefs = prefs.ACSMInput_Prefs()
File "calibre_plugins.deacsm.prefs", line 58, in init
raise Exception("Why does the account folder not exist?")
Exception: Why does the account folder not exist?

Operating system

MacOS

Which version of Calibre are you running?

6.11

Which version of the ACSM Input plugin are you running?

v0.0.17

Import type

No response

Further information

No response

DeACSM and Windows

Linux: DeACSM Version 0.0.10 works without errors. Adobe Digital Edition is not necessary any more. acsm-files can be opened directly in Calibre and epubs get decrypted automatically using DeDRM 7.2.1. Very fine!

Windows: I have installed Calibre and the plugins DeACSM and DeDRM. Same configuration like Linux. But if I want to open acsm-file directly in Calibre it claims missing Adobe Digital Edition.

So, does DeACSM only work in Linux or is there a bug?

Thank you!

How can I import to Calibre?

The instructions say to import to Calibre, but there is no zip file in the folder from which I can load the plugin.

How is it done?

Sorry if it looks like a stupid question, but I just don't see how to integrate the plugin to Calibre. Any help would be greatly appreciated.

Combination of deACSM and deDRM creates blank pdf (DRM not removed)

Bug description

hi,

I just tried, as several suggested, to use deACSM plugin in combination with DeDRM from this repo.

Unfortunately this just loaded a blank pdf, as normally happend when loading a pdf from ADE without removing the DRM.

Also the log show that a IndexError in de DeDRM: index out of range is thrown.
But, When the ACSM is opend in ADE (with my Adobe ID) -> the PDF gets imported into calibre -> DeDRM removes the DRM.
What not works is:

  • ACSM directly opened in calibre (anonymous auth)-> PDF gets downloaded by DeACSM > DeDRM cannot remove DRM
  • ACSM directly opened in calibre (Adobe ID)-> PDF gets downloaded by DeACSM > DeDRM cannot remove DRM

Also when I then try to redownload the fulfilled PDF from deACSM, with my Adobe ID, it cannot be opened in ADE, as E_LIC_ALREADY_FULFILLED_BY_ANOTHER_USER

I asked already the DeDRM community for help, but I think something doesn't work with deACSM noDRM/DeDRM_tools#195

How can I help to find the bug?

Operating system

MacOS

Which version of Calibre are you running?

6.5.0

Which version of the ACSM Input plugin are you running?

v0.0.16

Further information

Using calibre Qt style: True
calibre Debug log
calibre 6.5  embedded-python: True
macOS-12.6-x86_64-i386-64bit Darwin ('64bit', '')
('Darwin', '21.6.0', 'Darwin Kernel Version 21.6.0: Mon Aug 22 20:17:10 PDT 2022; root:xnu-8020.140.49~2/RELEASE_X86_64')
Python 3.10.1
OSX: ('12.6', ('', '', ''), 'x86_64')
Interface language: None
Successfully initialized third party plugins: DeACSM (0, 0, 16) && DeDRM (10, 0, 3) && Find Duplicates (1, 9, 7)
calibre 6.5  embedded-python: True
macOS-12.6-x86_64-i386-64bit Darwin ('64bit', '')
('Darwin', '21.6.0', 'Darwin Kernel Version 21.6.0: Mon Aug 22 20:17:10 PDT 2022; root:xnu-8020.140.49~2/RELEASE_X86_64')
Python 3.10.1
OSX: ('12.6', ('', '', ''), 'x86_64')
Interface language: None
Successfully initialized third party plugins: DeACSM (0, 0, 16) && DeDRM (10, 0, 3) && Find Duplicates (1, 9, 7)
QPA platform: cocoa
devicePixelRatio: 1.0
logicalDpi: 72.0 x 72.0
physicalDpi: 72.00000108133152 x 72.00000108133152
[0.00] Starting up...
[0.03] Showing splash screen...
[0.27] splash screen shown
[0.27] Initializing db...
[0.35] db initialized
[0.35] Constructing main UI...
[1.35] main UI initialized...
[1.35] Hiding splash screen
Starting QuickView
[5.48] splash screen hidden
[5.48] Started up in 5.48 seconds with 2790 books
DeDRM v10.0.3: Trying to decrypt v4sj3lko.pdf
DeDRM v10.0.3: v4sj3lko.pdf is a PDF ebook with encryption EBX_HANDLER
DeDRM v10.0.3: v4sj3lko.pdf is a PDF ebook (EBX) for UUID 616bc716-fca7-4970-b104-491cd0ea2f98
DeDRM v10.0.3: Trying encryption key default_key
ebx_V is 4  and ebx_type is 6
length is 16 and len(bookkey) is 0
DeDRM v10.0.3: Exception when decrypting after 0.1 seconds
Traceback (most recent call last):
  File "calibre_plugins.dedrm.__init__", line 724, in PDFIneptDecrypt
    result = ineptpdf.decryptBook(userkey, path_to_ebook, of.name)
  File "/Users/lorenz/Library/Preferences/calibre/plugins/DeDRM.zip/ineptpdf.py", line 2286, in decryptBook
    serializer = PDFSerializer(inf, userkey, inept)
  File "/Users/lorenz/Library/Preferences/calibre/plugins/DeDRM.zip/ineptpdf.py", line 2094, in __init__
    doc.initialize(userkey, inept)
  File "/Users/lorenz/Library/Preferences/calibre/plugins/DeDRM.zip/ineptpdf.py", line 1253, in initialize
    return self.initialize_ebx_inept(password, docid, param)
  File "/Users/lorenz/Library/Preferences/calibre/plugins/DeDRM.zip/ineptpdf.py", line 1707, in initialize_ebx_inept
    print("bookkey[0] is %d" % bookkey[0])
IndexError: index out of range
DeDRM v10.0.3: Failed to decrypt with key default_key after 0.1 seconds
DeDRM v10.0.3: Looking for new default Adobe Digital Editions Keys after 0.1 seconds
DeDRM v10.0.3: Found new key 'DeACSM_uuid_616bc716-fca7-4970-b104-491cd0ea2f98' in DeACSM plugin
DeDRM v10.0.3: Trying a new default key
ebx_V is 4  and ebx_type is 6
length is 16 and len(bookkey) is 0
DeDRM v10.0.3: Exception when decrypting after 0.3 seconds
Traceback (most recent call last):
  File "calibre_plugins.dedrm.__init__", line 795, in PDFIneptDecrypt
    result = ineptpdf.decryptBook(userkey, path_to_ebook, of.name)
  File "/Users/lorenz/Library/Preferences/calibre/plugins/DeDRM.zip/ineptpdf.py", line 2286, in decryptBook
    serializer = PDFSerializer(inf, userkey, inept)
  File "/Users/lorenz/Library/Preferences/calibre/plugins/DeDRM.zip/ineptpdf.py", line 2094, in __init__
    doc.initialize(userkey, inept)
  File "/Users/lorenz/Library/Preferences/calibre/plugins/DeDRM.zip/ineptpdf.py", line 1253, in initialize
    return self.initialize_ebx_inept(password, docid, param)
  File "/Users/lorenz/Library/Preferences/calibre/plugins/DeDRM.zip/ineptpdf.py", line 1707, in initialize_ebx_inept
    print("bookkey[0] is %d" % bookkey[0])
IndexError: index out of range
DeDRM v10.0.3: Failed to decrypt with new default key after 0.3 seconds
DeDRM v10.0.3: Trying a new default key
ebx_V is 4  and ebx_type is 6
length is 16 and len(bookkey) is 0
DeDRM v10.0.3: Exception when decrypting after 0.4 seconds
Traceback (most recent call last):
  File "calibre_plugins.dedrm.__init__", line 795, in PDFIneptDecrypt
    result = ineptpdf.decryptBook(userkey, path_to_ebook, of.name)
  File "/Users/lorenz/Library/Preferences/calibre/plugins/DeDRM.zip/ineptpdf.py", line 2286, in decryptBook
    serializer = PDFSerializer(inf, userkey, inept)
  File "/Users/lorenz/Library/Preferences/calibre/plugins/DeDRM.zip/ineptpdf.py", line 2094, in __init__
    doc.initialize(userkey, inept)
  File "/Users/lorenz/Library/Preferences/calibre/plugins/DeDRM.zip/ineptpdf.py", line 1253, in initialize
    return self.initialize_ebx_inept(password, docid, param)
  File "/Users/lorenz/Library/Preferences/calibre/plugins/DeDRM.zip/ineptpdf.py", line 1707, in initialize_ebx_inept
    print("bookkey[0] is %d" % bookkey[0])
IndexError: index out of range
DeDRM v10.0.3: Failed to decrypt with new default key after 0.4 seconds
DeDRM v10.0.3: Finished after 0.4 seconds
Traceback (most recent call last):
  File "calibre/customize/ui.py", line 435, in get_file_type_metadata
  File "calibre/customize/builtins.py", line 324, in get_metadata
  File "calibre/ebooks/metadata/pdf.py", line 124, in get_metadata
ValueError: Could not read info dict from PDF
DeACSM v0.0.16: Trying to parse file GehirnGeist032022.acsm
DeACSM v0.0.16: Try to fulfill ...
Notifying server ...
Notifying server https://acs6.onleihe.de/fulfillment/FulfillmentNotification
Fulfillment notification successful.
Notifying optional server https://ws.onleihe.de/acs6-return
Fulfillment notification successful (204).
DeACSM v0.0.16: Downloading book ...
DeACSM v0.0.16: Loading book from https://dp1.onleihe.de/downloadprovider/epub/20220204/9d375dc8-1ed5-33b9-973d-276290acda70.pdf
Download took 3410 ms (HTTP 200)
That's a PDF file
DeACSM v0.0.16: Downloaded PDF, adding encryption config ...
Searching for startxref ...
Got startxref: 8883863
Found ENC after 5 attempts - took 1 ms
Found EBX after 2062 attempts - took 4 ms


Encryption handler:
<</Root 1 0 R/Info 5 0 R/Encrypt 2051 0 R/ID[<05339E570442487CB736AB79F76DDE58><A56123FCE4CBD0477D31148C634E625F>]/Size 2052>>
EBX handler:
<</EBX_PUBLISHER(Spektrum der Wissenschaft Verlagsgesellschaft mbH)/Filter/EBX_HANDLER/Length 128/ADEPT_ID(urn:uuid:a08ebdff-6bae-4a13-92c2-0ab28d1021ff)/V 4/EBX_TITLE(Gehirn & Geist \\\(03/2022\\\))/EBX_AUTHOR()>>
Trimmed encryption handler:
<</Root 1 0 R/Info 5 0 R/Encrypt 2051 0 R/ID[<05339E570442487CB736AB79F76DDE58><A56123FCE4CBD0477D31148C634E625F>]/Size 2052>>
Updated EBX handler not logged due to sensitive data
Whole DRM patching took 25 milliseconds.
DeACSM v0.0.16: File successfully fulfilled ...
DeACSM v0.0.16: Executing plugin DeDRM ...
DeACSM v0.0.16: Plugin returned nothing - skipping
Syntax Error: Couldn't find the 'EBX_HANDLER' security handler
pdfinfo errored out with return code: 1

[Feature Request] Anonymous activation

I think that anonymous activation simply require you to set the type to "anonymous" and provide a zero length username and password. I'm working on the feature in my rust version and it seems to work, but I can't properly test because my crypto code seems to be broken, causing Adobe to complain about "invalid auth key format" - I think I accidentally exported and encrypted the public key, not the private key 😅

Not working with books from CloudLibrary

Bug description

Importing acsm books from Libby/Overdrive works fine but anything from CloudLibrary just imports the ACSM itself with the book having no metadata (just called the name of the book + the number id in the file name). Adobe imports the file fine and the plugin still can't fulfill it even after Adobe does (so it's not a case of only not working on initial auth then working on subsequent auths)

Log:

stdout+stderr from file dialog helper: [b'', b'']
piped data from file dialog helper: [b'\\WEc\x05O\x02O\x18\xe7\x99!a\xf0\x9c\xa3!\xa2\xbc\xf0\x8eHh\xb3r\xe3\xae\xe9\x19\x0b\x11\x9c', b'D:\\Downloads\\What Would Google Do__9780061893933.acsm']
Running file type plugin DeACSM failed with traceback:
Traceback (most recent call last):
  File "calibre\customize\ui.py", line 175, in _run_filetype_plugins
  File "calibre_plugins.deacsm.__init__", line 378, in run
  File "calibre_plugins.deacsm.libadobeFulfill", line 420, in fulfill
  File "calibre_plugins.deacsm.libadobeFulfill", line 674, in performFulfillmentNotification
  File "calibre_plugins.deacsm.libadobe", line 307, in sendRequestDocuRC
  File "calibre_plugins.deacsm.libadobe", line 273, in sendPOSTHTTPRequest
  File "urllib\request.py", line 328, in __init__
  File "urllib\request.py", line 354, in full_url
  File "urllib\request.py", line 383, in _parse
ValueError: unknown url type: 'fulfillment.yourcloudlibrary.com/notify'
Integration status: True
DeACSM v0.0.15: Trying to parse file What Would Google Do__9780061893933.acsm
DeACSM v0.0.15: Try to fulfill ...
Notifying server ...
Notifying server http://fulfillment.yourcloudlibrary.com/fulfillment/FulfillmentNotification
Fulfillment notification successful.
Notifying optional server fulfillment.yourcloudlibrary.com/notify

Operating system

Windows

Which version of Calibre are you running?

5.42

Which version of the DeACSM plugin are you running?

v0.0.15

Further information

No response

Doesn't work with ACSM files from Google Play Books

Bug description

This is probably more of a feature request than a bug, but it appears that the acsm files from Google Play Books are a different format, which causes the following error when trying to open them:

Traceback (most recent call last):
  File "/usr/lib64/calibre/calibre/customize/ui.py", line 175, in _run_filetype_plugins
    nfp = plugin.run(nfp) or nfp
  File "calibre_plugins.deacsm.__init__", line 324, in run
    success, replyData = fulfill(path_to_ebook, deacsmprefs["notify_fulfillment"])
  File "calibre_plugins.deacsm.libadobeFulfill", line 322, in fulfill
    mimetype = acsmxml.find("./%s/%s/%s" % (adNS("resourceItemInfo"), adNS("metadata"), dcNS("format"))).text
AttributeError: 'NoneType' object has no attribute 'text'

The issue is that these ascm files do not have the <metadata> tag at all. <resourceItemInfo> instead looks like this:

<resourceItemInfo>
        <resource>urn:uuid:bc30db2e-38bf-5956-2221-bdf7e1e7e0f5</resource>
        <resourceItem>1</resourceItem>
        <src>https://books.google.com/books/download/Mockingjay_Hunger_Games_Book_Three.epub?acsid=urn:uuid:bc30db2e-38bf-5956-2221-bdf7e1e7e0f5&amp;output=acs4_book_bytes&amp;ar=4ad7a2b478964a50ec5e0f567678ecfe</src>
        <downloadType>simple</downloadType>
    </resourceItemInfo>

Operating system

Linux

Which version of Calibre are you running?

5.33

Which version of the DeACSM plugin are you running?

v0.0.14

Further information

No response

Adding lots of ACSM files at once doesn't populate loan list correctly

Bug description

When adding multiple ACSM files from a library at once, the loaned book list isn't always populated correctly.

I suspect this is due to a race condition. When importing multiple books, Calibre seems to run multiple instances of the plugin at once.

This means when there's code like this (pseudocode):

  • Get book list
  • Add entry to temporary book list
  • Write book list back to file

then some records can get overwritten when they're created at the exact same time.

So, I need to add some kind of lock that only one instance of the plugin can mess with the loan list at once, and others will have to wait.

Bug first reported by @p1nkyy in #31 (comment)

Operating system

Linux, Windows, MacOS

Which version of the DeACSM plugin are you running?

v0.0.16

Install plugin failed, libcrypto missing symbol

I cannot install the plugin on a stock Ubuntu 22.04 installation. Am I missing some requirements?

calibre, version 5.37.0
FEHLER: Erweiterungsinstallation fehlgeschlagen: Während der Installation der Erweiterung ist ein Problem aufgetreten. Diese Erweiterung wird nun entfernt. Bitte veröffentlichen Sie die folgende detaillierte Fehlermeldung im Diskussionsforum dieser Erweiterung und starten Sie Calibre neu.

Traceback (most recent call last):
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_ctypes.py", line 304, in <module>
    libcrypto.EVP_PKEY_size.argtypes = [
  File "/usr/lib/python3.10/ctypes/__init__.py", line 387, in __getattr__
    func = self.__getitem__(name)
  File "/usr/lib/python3.10/ctypes/__init__.py", line 392, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /lib/x86_64-linux-gnu/libcrypto.so.3: undefined symbol: EVP_PKEY_size

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 184, in initialize
    from calibre_plugins.deacsm.libadobe import createDeviceKeyFile, update_account_path
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "/usr/lib/calibre/calibre/customize/zipplugin.py", line 191, in exec_module
    exec(compiled, module.__dict__)
  File "calibre_plugins.deacsm.libadobe", line 29, in <module>
    from oscrypto import keys
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/keys.py", line 5, in <module>
    from ._asymmetric import parse_certificate, parse_private, parse_public
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_asymmetric.py", line 27, in <module>
    from .kdf import pbkdf1, pbkdf2, pkcs12_kdf
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/kdf.py", line 9, in <module>
    from .util import rand_bytes
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/util.py", line 14, in <module>
    from ._openssl.util import rand_bytes
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/util.py", line 6, in <module>
    from ._libcrypto import libcrypto, libcrypto_version_info, handle_openssl_error
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto.py", line 15, in <module>
    from ._libcrypto_ctypes import (
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_ctypes.py", line 688, in <module>
    raise FFIEngineError('Error initializing ctypes')
oscrypto._ffi.FFIEngineError: Error initializing ctypes

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/calibre/calibre/customize/ui.py", line 673, in initialize_plugin
    p.initialize()
  File "calibre_plugins.deacsm.__init__", line 187, in initialize
    from libadobe import createDeviceKeyFile, update_account_path
ModuleNotFoundError: No module named 'libadobe'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/calibre/calibre/gui2/dialogs/plugin_updater.py", line 712, in _install_clicked
    plugin = add_plugin(zip_path)
  File "/usr/lib/calibre/calibre/customize/ui.py", line 483, in add_plugin
    plugin = initialize_plugin(plugin, path_to_zip_file, PluginInstallationType.EXTERNAL)
  File "/usr/lib/calibre/calibre/customize/ui.py", line 678, in initialize_plugin
    raise InvalidPlugin((_('Initialization of plugin %s failed with traceback:')
calibre.customize.InvalidPlugin: Initialisierung der Erweiterung Traceback (most recent call last):
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_ctypes.py", line 304, in <module>
    libcrypto.EVP_PKEY_size.argtypes = [
  File "/usr/lib/python3.10/ctypes/__init__.py", line 387, in __getattr__
    func = self.__getitem__(name)
  File "/usr/lib/python3.10/ctypes/__init__.py", line 392, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /lib/x86_64-linux-gnu/libcrypto.so.3: undefined symbol: EVP_PKEY_size

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 184, in initialize
    from calibre_plugins.deacsm.libadobe import createDeviceKeyFile, update_account_path
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "/usr/lib/calibre/calibre/customize/zipplugin.py", line 191, in exec_module
    exec(compiled, module.__dict__)
  File "calibre_plugins.deacsm.libadobe", line 29, in <module>
    from oscrypto import keys
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/keys.py", line 5, in <module>
    from ._asymmetric import parse_certificate, parse_private, parse_public
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_asymmetric.py", line 27, in <module>
    from .kdf import pbkdf1, pbkdf2, pkcs12_kdf
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/kdf.py", line 9, in <module>
    from .util import rand_bytes
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/util.py", line 14, in <module>
    from ._openssl.util import rand_bytes
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/util.py", line 6, in <module>
    from ._libcrypto import libcrypto, libcrypto_version_info, handle_openssl_error
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto.py", line 15, in <module>
    from ._libcrypto_ctypes import (
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_ctypes.py", line 688, in <module>
    raise FFIEngineError('Error initializing ctypes')
oscrypto._ffi.FFIEngineError: Error initializing ctypes

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/calibre/calibre/customize/ui.py", line 673, in initialize_plugin
    p.initialize()
  File "calibre_plugins.deacsm.__init__", line 187, in initialize
    from libadobe import createDeviceKeyFile, update_account_path
ModuleNotFoundError: No module named 'libadobe'
 fehlgeschlagen. Rückverfolgung:
Traceback (most recent call last):
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_ctypes.py", line 304, in <module>
    libcrypto.EVP_PKEY_size.argtypes = [
  File "/usr/lib/python3.10/ctypes/__init__.py", line 387, in __getattr__
    func = self.__getitem__(name)
  File "/usr/lib/python3.10/ctypes/__init__.py", line 392, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /lib/x86_64-linux-gnu/libcrypto.so.3: undefined symbol: EVP_PKEY_size

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "calibre_plugins.deacsm.__init__", line 184, in initialize
    from calibre_plugins.deacsm.libadobe import createDeviceKeyFile, update_account_path
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "/usr/lib/calibre/calibre/customize/zipplugin.py", line 191, in exec_module
    exec(compiled, module.__dict__)
  File "calibre_plugins.deacsm.libadobe", line 29, in <module>
    from oscrypto import keys
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/keys.py", line 5, in <module>
    from ._asymmetric import parse_certificate, parse_private, parse_public
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_asymmetric.py", line 27, in <module>
    from .kdf import pbkdf1, pbkdf2, pkcs12_kdf
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/kdf.py", line 9, in <module>
    from .util import rand_bytes
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/util.py", line 14, in <module>
    from ._openssl.util import rand_bytes
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/util.py", line 6, in <module>
    from ._libcrypto import libcrypto, libcrypto_version_info, handle_openssl_error
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto.py", line 15, in <module>
    from ._libcrypto_ctypes import (
  File "/home/user/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto_ctypes.py", line 688, in <module>
    raise FFIEngineError('Error initializing ctypes')
oscrypto._ffi.FFIEngineError: Error initializing ctypes

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/calibre/calibre/customize/ui.py", line 673, in initialize_plugin
    p.initialize()
  File "calibre_plugins.deacsm.__init__", line 187, in initialize
    from libadobe import createDeviceKeyFile, update_account_path
ModuleNotFoundError: No module named 'libadobe'

Calibre crash upon linking ADE account

Bug description

When trying to link ADE account (with any method), Calibre crashes and I get "wait/force quit" message. Tried almost all previous versions of ACSM plugin, and got the same issue.
I'm running Calibre v. 6.23 on Ubuntu 22.04.2 LTS.

Operating system

Linux

Which version of Calibre are you running?

6.23

Which version of the ACSM Input plugin are you running?

v0.0.16

Import type

No response

Further information

No response

DRM still present despite importing correctly

Bug description

Steps taken:

  • Installed / setup DeDRM plugin per README
  • Downloaded *.acsm formatted book from Overdrive/Libby
  • Imported into Calibre successfully
  • When going to open book in built-in Calibre ereader, get error This book is locked by DRM

Logs here.

Operating system

Windows

Which version of Calibre are you running?

6.5

Which version of the DeACSM plugin are you running?

v0.0.16

Further information

No response

Returning book doesn't work

Bug description

Hello, I mainly borrowed books from Overdrive or BorrowBox. Returning books don't really work. I click the arrow, it said 'Book is returned' and it disappeared from the Show Loaned Books list, but when I get back to the library's 'Loan' page, the book is still there and not yet returned. Only when I click Return manually will the book disappear. I currently am waiting for 1 book that I returned from the plugin to see whether after several hours it will be returned in Overdrive.
I don't know what debug process to include but let me know what to do so I can help. Thanks!

Operating system

Windows

Which version of Calibre are you running?

6.0

Which version of the DeACSM plugin are you running?

v0.0.16

Further information

No response

acsm file loading into calibre instead of being "converted" to epub

Bug description

The plugin works great on my Windows 10 desktop computer, and I authorised it with ADE there. I exported all calibre data and imported it into calibre on my Linux laptop (running Pop! OS 22.04 LTS). Here is the output of running calibre-debug --gui and then adding an .acsm file:

DeACSM v0.0.15: Try to fulfill ...
Running file type plugin DeACSM failed with traceback:
Traceback (most recent call last):
  File "/usr/lib/calibre/calibre/customize/ui.py", line 175, in _run_filetype_plugins
    nfp = plugin.run(nfp) or nfp
  File "calibre_plugins.deacsm.__init__", line 385, in run
    success, replyData = fulfill(path_to_ebook, deacsmprefs["notify_fulfillment"])
  File "/home/citizenfour/.config/calibre/plugins/DeACSM.zip/libadobeFulfill.py", line 380, in fulfill
    signature = sign_node(fulfill_request_xml)
  File "/home/citizenfour/.config/calibre/plugins/DeACSM.zip/libadobe.py", line 518, in sign_node
    my_priv_key, _, _ = keys.parse_pkcs12(my_pkcs12, base64.b64encode(devkey_bytes))
  File "/home/citizenfour/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/asymmetric.py", line 774, in
parse_pkcs12
    return _parse_pkcs12(data, password, load_private_key)
  File "/home/citizenfour/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_asymmetric.py", line 866, in _parse_pkcs12
    decrypted_content = _decrypt_encrypted_data(encryption_algorithm_info, encrypted_content, password)
  File "/home/citizenfour/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_asymmetric.py", line 1036, in
_decrypt_encrypted_data
    plaintext = decrypt_func(enc_key, encrypted_content, enc_iv)
  File "/home/citizenfour/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/symmetric.py", line 364, in
rc2_cbc_pkcs5_decrypt
    return _decrypt('rc2', key, data, iv, True)
  File "/home/citizenfour/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/symmetric.py", line 750, in _decrypt
    handle_openssl_error(res)
  File "/home/citizenfour/.config/calibre/plugins/DeACSM/modules/oscrypto/oscrypto/_openssl/_libcrypto.py", line 86, in
handle_openssl_error
    raise exception_class(_try_decode(error_string))
OSError: error:0308010C:digital envelope routines::unsupported
Added TheModernWitchcraftG 9781507211496 4630375 to db in: 0.0
Added 1 books in 0.7 seconds

Operating system

Linux

Which version of Calibre are you running?

5.37

Which version of the DeACSM plugin are you running?

0.0.15

Further information

This seems similar to issue #19 but I'm not sure so am filing a new issue rather than reopening that one.

[Suggestion] Add job queue in the bottom of Calibre

Hello, it'd be nice for ACSM Input to show the Jobs queue in the bottom of Calibre. I was using https://github.com/ping/libby-calibre-plugin and it shows the number of jobs i queued and I feel that it's so nice. So far with ACSM Input I was always just guessing whether it was working in the background or not. An indicator would be nice. Thank you!

EDIT: I set Calibre to automatically process ACSM files added to certain folder, so no progress bar whatsoever. ACSM Input just ran in the background and suddenly a new title popped up in my Calibre usually.

pdftohtml conversion fails during import

Bug description

This is the first time I'm using the ACSM-Calibre-Plugin, but I was able to add the test library books successfully.

System OS: Ubuntu 22.10

I was attempting to import a book that was loaned via archive.org, which is an encrypted adobe pdf, .acsm.

Attempt no. 1:

  • I added the ACSM-Calibre-Plugin to my calibre install, which had a pre-existing noDRM de-drm plugin installed.

    • i also happened to turn the verbose logging on
  • I restarted Calibre, then authorized the ACSM plugin with my adobe id. (the same adobe id that i can open the pdf in adobe editions with)

  • I exported the key to file.

  • In the noDRM de-drm plugin, I clicked on Adobe Digital Editions Ebooks, then clicked the green + icon. It added a UUID to the list.
    Screenshot from 2023-06-15 10-02-20
    Screenshot from 2023-06-15 10-02-39

  • I then attempted to drag and drop the .acsm file into calibre.

  • it showed the processing bar, but eventually failed.
    import_fails.log

  • in my main calibre library, it shows the acsm file
    image

  • if i open the ACSM plugin's configuration menu, I do see my book listed as currently on loan -- however there are always two entries, even if I have only imported the book once.
    image

Other Attempts:
I tried the same general process several times but with the following changes:

  • different ADE versions in the ACSM plugin config
  • importing via add new book button vs drag and drop vs automatic import from local folder
  • exporting the key explicitly to file and importing into the noDRM de-drm plugin rather than the Plus icon.

no difference, and the logs still showed the ValueError exception:

ValueError: decoding with 'hex' codec failed (ValueError: string argument should contain only ASCII characters)

Operating system

Linux

Which version of Calibre are you running?

6.3.0

Which version of the ACSM Input plugin are you running?

v0.0.16

Import type

Clicking the 'Add books' button in the menu bar, Dragging-and-Dropping the ACSM file into the Calibre window, Using an auto-add folder (Preferences -> Adding books -> Automatic adding)

Further information

Can also provide ACSM file used if desired.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.