/
contentprovider.py
123 lines (108 loc) · 5.19 KB
/
contentprovider.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python2
# pPub by Thanasis Georgiou <sakisds@gmx.com>
# pPub is free software; you can redistribute it and/or modify it under the terms
# of the GNU General Public Licence as published by the Free Software Foundation.
# pPub 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 Licence for more details.
# You should have received a copy of the GNU General Public Licence along with
# pPub; if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
# Fifth Floor, Boston, MA 02110-1301, USA.
import hashlib
import zipfile
import os
import shutil
from xml2obj import *
class ContentProvider(): #Manages book files and provides metadata
def __init__(self, config, window):
self.window = window
#Check if cache folder exists
self.config = config
self.cache_path = self.config.get("Main", "cacheDir")
if not os.path.exists(self.cache_path):
os.mkdir(self.cache_path) #If not create it
self.ready = False
def prepare_book(self, filepath):
#Clear any old files from the cache
if os.path.exists(self.cache_path):
shutil.rmtree(self.cache_path)
#Extract new book
zipfile.ZipFile(filepath).extractall(path=self.cache_path)
#Set permissions
os.system("chmod 700 "+self.cache_path)
#Find opf file
if os.path.exists(self.cache_path+"META-INF/container.xml"):
container_data = xml2obj(open(self.cache_path+"META-INF/container.xml", "r"))
opf_file_path = container_data.rootfiles.rootfile.full_path
#Load opf
metadata = xml2obj(open(self.cache_path+opf_file_path, "r"))
self.oebps = os.path.split(opf_file_path)[0]
#Find ncx file
for x in metadata.manifest.item:
if x.media_type == "application/x-dtbncx+xml":
ncx_file_path = self.cache_path+"/"+self.oebps+"/"+x.href
#Load titles and filepaths
self.titles = []
self.files = []
if os.access(ncx_file_path, os.R_OK): #Check if ncx is accessible
#Parse ncx file
pat=re.compile('-(.*)-')
for line in open(ncx_file_path):
line=line.strip()
if "<text>" in line:
out = line.replace("<text>", "")
out = out.replace("</text>", "")
out = out.replace("<content", "")
self.titles.append(out)
if "<content" in line:
out = line.replace("<content src=\"", "")
out = out.replace("\"", "")
out = out.replace("/>", "")
self.files.append(out)
while not len(self.titles) == len(self.files):
self.titles.remove(self.titles[0])
#Validate files
if not os.path.exists(self.cache_path+"/"+self.oebps+"/"+self.files[0]):
#Reload files
self.files = []
for x in metadata.manifest.item:
if x.media_type == "application/xhtml+xml":
self.files.append(x.href)
self.titles = []
i = 1
while not len(self.titles) == len(self.files):
self.titles.append("Chapter "+str(i))
i += 1
#Calculate MD5 of book (for bookmarks)
md5 = hashlib.md5()
with open(filepath,'rb') as f:
for chunk in iter(lambda: f.read(128*md5.block_size), ''):
md5.update(chunk)
#Metadata
self.book_name = unicode(metadata.metadata.dc_title).encode("utf-8")
self.book_author = unicode(metadata.metadata.dc_creator).encode("utf-8")
self.book_md5 = md5.hexdigest()
#Add book to config (used for bookmarks)
if not self.config.has_section(self.book_md5):
self.config.add_section(self.book_md5)
self.config.set(self.book_md5, "count", 0)
self.config.set(self.book_md5, "chapter", 0)
self.config.set(self.book_md5, "pos", 0.0)
self.config.set(self.book_md5, "stylesheet","")
#End of preparations
self.ready = True
return True
else: #Else show an error dialog
error_dialog = Gtk.MessageDialog(self.window, 0, Gtk.MessageType.ERROR,
Gtk.ButtonsType.OK, "Could not open book.")
error_dialog.format_secondary_text("Make sure the book you are trying to open is in supported format and try again.")
error_dialog.run()
error_dialog.destroy()
self.ready = False
return False
def get_chapter_file(self, number): #Returns a chapter file (for viewer)
return self.cache_path+"/"+self.oebps+"/"+self.files[number]
def get_chapter_count(self): #Returns number of chapters
return len(self.files)-1
def get_status(self):
return self.ready