there still are no eBooks and my zipper is stuck

In this previous post I had wondered about packaging "eBooks" (or is it "ebooks" or "e-books"?) in a password protected ZIP file.

The idea was that I'd have two main components:

  1. an online server that managed user login/credentials, etc.
  2. a custom web-browser that would be able to receive the ZIP password from the server upon user authentication and then read the ZIP contents into memory and push them out. This browser would disallow things like copy/pasting the content, printing, and accessing the content beyond a certain date, etc. depending upon permissions embedded in a permissions JSON file within the ZIP file.

The premise is that this could allow what are essentially web pages, i.e. applications, to be read with some sort of easy protection and without the necessary constraints (and benefits) that a standardized format like EPUB provides.

Anyway, I did some early tests using the PyQT/WebKit library for Python.

I wrapped a single-page HTML file in a password protected ZIP file and had the local instance of the browser open the file after reading the contents inside the ZIP file (but without actually unzipping the files).

I'm going to skip over HTML5 audio/video tags for now because I *think* they aren't working due to a bug with the WebKit for PyQt4. I haven't tried PyQT5 yet, by the way. At any rate, downloading videos is clearly out of the question. It may simply be better to restrict audio/video content to online content only. That's to say that the files are online, but still only accessible via the custom browser upon authentication. Hell, it may be better for ALL the content to be online only as that would make the whole ZIP file thing unnecessary.

But let me get back to the ZIP file.

I was wrong in thinking I only needed the two components mentioned above.

This became apparent when I tried a small HTML site in which files were linked to each other and/or including external CSS and JavaScript files. Basically, what would happen it that when an HTML file (rendered from behind the ZIP file) tried to include a CSS file, for instance, it couldn't find the CSS file because the in-memory HTML had no idea that it or the CSS file it included was behind a ZIP file firewall.

Then I realized I needed a third component, and intermediary between the ZIP file and the browser. And that's a local server that would proxy all the hyperlinks and include requests. It would then retrieve the file from the ZIP file and serve it back up with the appropriate HTTP header for the MIME type.

To do that I needed a Python web-framework, preferably lightweight and with easy-to-follow documentation.

After finding the documentation for CherryPy a little too involved, I stumbled upon Bottle. And I'm sure glad I did. This whole ZIP thing was a proof-of-concept so I doubt it'll go anywhere (I still like the idea of a custom browser accessing protected online content). But I definitely see myself using Bottle to make desktop applications that look/feel like web applications.

Anyway …

… the proxy thing is working but loading large images is a little slow, so there it is.

Example code is here and as you can see it only handles HTML (default), CSS, JavaScript, and PNG files/MIME types. I don't have the code for the custom browser yet, but that's actually a different issue. For now, I was just trying to deal with the proxy issue. Any old browser would work, but obviously the content then becomes copy-able.

from bottle import *
import zipfile
    
#### return protected zipped file as read string. Currently hard-coded to open "zipped_p/test.zip".
def p_retzip(z='index.html'):
    zipped = zipfile.ZipFile('zipped_p/test.zip', 'r')
    password = '123' #this is the password that would be handed-off via an online server.
    content = zipped.open(z, 'r', password) #open the file content.
    content = content.read()
    return content

#### proxying password protected zipped files.
# note: using 7-ZIP this doesn't seem to work with AES-256 but does work with ZipCrypto.
@route('/closed/<filepath:path>')
def server_static(filepath):

    # quick/dirty handling of three basic MIME types.
    if '.css' in filepath:
        response.set_header('Content-Type', 'text/css')
    if '.js' in filepath:
        response.set_header('Content-Type', 'application/javascript')
    if '.png' in filepath:
        response.set_header('Content-Type', 'image/png')
    
    # have the p_retzip() function read the contents and then return the contents to the browser.
    return p_retzip(filepath)
           
# launch server; after which you can go to http://localhost:8080/closed/index.html with regular browser or custom browser.
run(host='localhost', port=8080)
--------------

Related Content:

Leave a Comment

Your email address will not be published. Required fields are marked *

*