]> git.phdru.name Git - bookmarks_db.git/blob - Storage/bkmk_stjson.py
Implemented JSON loading.
[bookmarks_db.git] / Storage / bkmk_stjson.py
1 """
2     Bookmarks storage manager - json.
3
4     Written by Broytman, Jul 2010. Copyright (C) 2010 PhiloSoft Design
5 """
6
7
8 try:
9    import json
10 except ImportError:
11    import simplejson as json
12
13 from bkmk_objects import Folder, Bookmark, Ruler, Walker
14
15
16 class storage_json(Walker):
17     filename = "bookmarks_db.json"
18
19     def root_folder(self, f):
20         self.dict = {}
21
22     def start_folder(self, f, level):
23         pass
24
25     def bookmark(self, b, level):
26         pass
27
28     def ruler(self, r, level):
29         pass
30
31     def store(self, root_folder):
32         root_folder.walk_depth(self)
33
34         outfile = open(self.filename, 'wb')
35         json.dump(self.dict, outfile)
36         outfile.close()
37         del self.dict
38
39
40     def load(self):
41         infile = open(self.filename, 'rb')
42         bkmk_s = infile.read()
43         infile.close()
44
45         # Work around a bug in Mozilla - remove the trailing comma
46         bkmk_s = bkmk_s.strip().replace(',]', ']')
47         bookmarks_dict = json.loads(bkmk_s)
48
49         root_folder = Folder()
50         root_folder.header = ''
51         self.folder_stack = [root_folder]
52         self.current_folder = root_folder
53
54         self.load_folder(root_folder, bookmarks_dict)
55         if self.folder_stack:
56             raise RuntimeError('Excessive folder stack: %s' % self.folder_stack)
57
58         return root_folder
59
60     def load_folder(self, folder, _dict):
61         if _dict["type"] != "text/x-moz-place-container":
62             raise ValueError("Root object is not a Mozilla container")
63
64         folder.id = _dict["id"]
65         folder.index = _dict.get("index")
66         folder.parent_idx = _dict.get("parent")
67
68         folder.name = encode(_dict["title"])
69         folder.href = _dict.get("uri")
70         folder.comment = ''
71         folder.add_date = _dict["dateAdded"]
72         folder.last_modified = _dict["lastModified"]
73
74         for record in _dict["children"]:
75             if record["type"] == "text/x-moz-place":
76                 bookmark = Bookmark(
77                     href=record["uri"],
78                     add_date=record.get("dateAdded"),
79                     last_modified=record.get("lastModified"),
80                     charset=record.get("charset"))
81                 bookmark.id = record["id"]
82                 bookmark.parent_idx = record["parent"]
83                 bookmark.name = encode(record["title"])
84                 self.current_folder.append(bookmark)
85
86             elif record["type"] == "text/x-moz-place-container":
87                 folder = Folder(
88                     add_date=record["dateAdded"], comment=None,
89                     last_modified=record["lastModified"])
90                 folder.id = record["id"]
91                 folder.parent_idx = record["parent"]
92                 folder.name = encode(record["title"])
93                 self.current_folder.append(folder)
94                 self.folder_stack.append(folder)
95                 self.current_folder = folder
96                 self.load_folder(folder, record)
97
98             elif record["type"] == "text/x-moz-place-separator":
99                 ruler = Ruler()
100                 ruler.add_date = record["dateAdded"]
101                 ruler.id = record["id"]
102                 ruler.index = record["index"]
103                 ruler.last_modified = record["lastModified"]
104                 ruler.parent_idx = record["parent"]
105                 ruler.name = encode(record["title"])
106                 self.current_folder.append(ruler)
107
108             else:
109                 raise ValueError('Unknown record type "%s"' % record["type"])
110
111         del self.folder_stack[-1]
112         if self.folder_stack:
113             self.current_folder = self.folder_stack[-1]
114         else:
115             self.current_folder = None
116
117 def encode(title):
118     return title.encode("UTF-8", "xmlcharrefreplace")