]> git.phdru.name Git - bookmarks_db.git/blob - bkmk_parser.py
2008.
[bookmarks_db.git] / bkmk_parser.py
1 """
2    Parser for Netscape Navigator's and Mozilla's bookmarks.html
3
4    Written by BroytMann. Copyright (C) 1997-2008 PhiloSoft Design
5 """
6
7
8 import sys, os
9 from m_lib.net.www.html import HTMLParser
10 from bkmk_objects import Folder, Bookmark, Ruler
11
12
13 DEBUG = os.environ.has_key("BKMK_DEBUG")
14
15 if DEBUG:
16    def debug(note):
17       print note
18
19    def dump_names(folder_stack):
20       l = []
21       for object in folder_stack:
22          if object.isFolder:
23             l.append(object.name)
24       return "'%s'" % "' '".join(l)
25
26 else:
27    def debug(note):
28       pass
29    dump_names = debug
30
31
32 DEFAULT_CHARSET = None
33
34 class BkmkParser(HTMLParser):
35    def __init__(self):
36       HTMLParser.__init__(self)
37
38       self.urls = 0
39       self.objects = 0
40
41       self.charset = ""
42       self.recode = None
43
44
45    def handle_data(self, data):
46       if data:
47          if DEFAULT_CHARSET:
48             data = unicode(data, self.charset, "replace").encode(DEFAULT_CHARSET, "xmlcharrefreplace")
49          self.accumulator += data
50
51
52    # Mozilla - get charset
53    def do_meta(self, attrs):
54       http_equiv = ""
55       content = ""
56
57       for attrname, value in attrs:
58          value = value.strip()
59          if attrname == 'http-equiv':
60             http_equiv = value.lower()
61          elif attrname == 'content':
62             content = value
63
64       if http_equiv == "content-type":
65          try:
66             # extract charset from "text/html; charset=UTF-8"
67             self.charset = content.split('=')[1]
68          except IndexError:
69             pass
70          else:
71             global DEFAULT_CHARSET
72             DEFAULT_CHARSET = sys.getdefaultencoding()
73             if DEFAULT_CHARSET == "ascii":
74                try:
75                   import locale
76                except ImportError:
77                   pass
78                else:
79                   DEFAULT_CHARSET = locale.getpreferredencoding()
80
81
82    def start_title(self, attrs):
83       if DEFAULT_CHARSET:
84          self.accumulator += '<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=%s">\n' % DEFAULT_CHARSET
85       self.accumulator += "<TITLE>"
86
87    def end_title(self):
88       self.accumulator += "</TITLE>"
89
90
91    # Start root folder
92    def start_h1(self, attrs):
93       root_folder = Folder()
94       self.current_object = root_folder
95       self.root_folder = root_folder
96       self.current_folder = root_folder
97       self.folder_stack = [root_folder]
98
99       self.root_folder.header = self.accumulator.strip()
100       self.accumulator = ''
101
102    def end_h1(self):
103       accumulator = self.accumulator
104       self.accumulator = ''
105
106       debug("Root folder name: `%s'" % accumulator)
107       self.root_folder.name = accumulator
108
109
110    # Start a folder
111    def start_h3(self, attrs):
112       last_modified = None
113       for attrname, value in attrs:
114          value = value.strip()
115          if attrname == 'add_date':
116             add_date = value
117          elif attrname == 'last_modified':
118             last_modified = value
119
120       debug("New folder...")
121       folder = Folder(add_date, last_modified=last_modified)
122       self.current_object = folder
123       self.current_folder.append(folder)
124       self.folder_stack.append(folder) # push new folder
125       self.current_folder = folder
126       self.objects += 1
127
128    def end_h3(self):
129       accumulator = self.accumulator
130       self.accumulator = ''
131
132       debug("Folder name: `%s'" % accumulator)
133       self.current_folder.name = accumulator
134
135
136    # Start a bookmark
137    def start_a(self, attrs):
138       add_date = None
139       last_visit = None
140       last_modified = None
141       keyword = None
142       icon = None
143       charset = None
144
145       for attrname, value in attrs:
146          value = value.strip()
147          if attrname == "href":
148             href = value
149          elif attrname == "add_date":
150             add_date = value
151          elif attrname == "last_visit":
152             last_visit = value
153          elif attrname == "last_modified":
154             last_modified = value
155          elif attrname == "shortcuturl":
156             keyword = value
157          elif attrname == "icon":
158             icon = value
159          elif attrname == "last_charset":
160             charset = value
161
162       debug("Bookmark points to: `%s'" % href)
163       bookmark = Bookmark(href, add_date, last_visit, last_modified,
164          keyword or '', '', icon, charset)
165       self.current_object = bookmark
166       self.current_folder.append(bookmark)
167       self.urls += 1
168       self.objects += 1
169
170    def end_a(self):
171       accumulator = self.accumulator
172       self.accumulator = ''
173
174       debug("Bookmark name: `%s'" % accumulator)
175       bookmark = self.current_folder[-1]
176       bookmark.name = accumulator
177
178
179    def flush(self):
180       accumulator = self.accumulator
181
182       if accumulator:
183          self.accumulator = ''
184
185          current_object = self.current_object
186          if current_object:
187             current_object.comment += accumulator.strip()
188             debug("Comment: `%s'" % current_object.comment)
189
190
191    def start_dl(self, attrs):
192       self.flush()
193
194    do_dt = start_dl
195
196
197    # End of folder
198    def end_dl(self):
199       self.flush()
200       debug("End folder")
201       debug("Folder stack: %s" % dump_names(self.folder_stack))
202       if self.folder_stack:
203          del self.folder_stack[-1] # pop last folder
204          if self.folder_stack:
205             self.current_folder = self.folder_stack[-1]
206          else:
207             debug("FOLDER STACK is EMPTY!!! (1)")
208       else:
209          debug("FOLDER STACK is EMPTY!!! (2)")
210       self.current_object = None
211
212
213    def close(self):
214       HTMLParser.close(self)
215       if self.folder_stack:
216          raise ValueError, "wrong folder stack: %s" % self.folder_stack
217
218
219    def do_dd(self, attrs):
220       pass
221
222    do_p = do_dd
223
224
225    # Start ruler
226    def do_hr(self, attrs):
227       self.flush()
228       debug("Ruler")
229       self.current_folder.append(Ruler())
230       self.current_object = None
231       self.objects += 1
232
233
234    # BR in comment
235    def do_br(self, attrs):
236       self.accumulator += "<BR>"
237
238
239    # Allow < in the text
240    def unknown_starttag(self, tag, attrs):
241       self.accumulator += "<%s>" % tag
242
243
244    # Do not allow unknow end tags
245    def unknown_endtag(self, tag):
246       raise NotImplementedError("Unknow end tag `%s'" % tag)