]> git.phdru.name Git - bookmarks_db.git/blob - Storage/bkmk_stjson.py
Store json.
[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 = dict = {}
21         dict["children"] = children = []
22         self.folder_stack = [children]
23         dict["dateAdded"] = f.add_date
24         dict["id"] = f.id
25         dict["lastModified"] = f.last_modified
26         dict["root"] = "placesRoot"
27         dict["title"] = ""
28         dict["type"] = "text/x-moz-place-container"
29
30     def start_folder(self, f, level):
31         dict = {}
32         dict["children"] = children = []
33         dict["dateAdded"] = f.add_date
34         dict["id"] = f.id
35         index = getattr(f, 'index')
36         if index: dict["index"] = index
37         dict["lastModified"] = f.last_modified
38         parent_idx = getattr(f, 'parent_idx')
39         if parent_idx: dict["parent"] = parent_idx
40         dict["title"] = f.name.decode('utf-8')
41         dict["type"] = "text/x-moz-place-container"
42         self.folder_stack[-1].append(dict)
43         self.folder_stack.append(children)
44
45     def end_folder(self, f, level):
46         del self.folder_stack[-1]
47
48     def bookmark(self, b, level):
49         dict = {}
50         charset = getattr(b, 'charset')
51         if charset: dict["charset"] = charset
52         dict["dateAdded"] = b.add_date
53         dict["id"] = b.id
54         index = getattr(b, 'index')
55         if index: dict["index"] = index
56         dict["lastModified"] = b.last_modified
57         dict["parent"] = b.parent_idx
58         dict["title"] = b.name.decode('utf-8')
59         dict["type"] = "text/x-moz-place"
60         dict["uri"] = b.href
61         self.folder_stack[-1].append(dict)
62
63     def ruler(self, r, level):
64         dict = {}
65         dict["dateAdded"] = r.add_date
66         dict["id"] = r.id
67         dict["index"] = r.index
68         dict["lastModified"] = r.last_modified
69         dict["parent"] = r.parent_idx
70         dict["title"] = r.name.decode('utf-8')
71         dict["type"] = "text/x-moz-place-separator"
72         self.folder_stack[-1].append(dict)
73
74     def store(self, root_folder):
75         root_folder.walk_depth(self)
76
77         outfile = open(self.filename, 'wb')
78         json.dump(self.dict, outfile)
79         outfile.close()
80         del self.dict
81
82
83     def load(self):
84         infile = open(self.filename, 'rb')
85         bkmk_s = infile.read()
86         infile.close()
87
88         # Work around a bug in Mozilla - remove the trailing comma
89         bkmk_s = bkmk_s.strip().replace(',]', ']')
90         bookmarks_dict = json.loads(bkmk_s)
91
92         root_folder = Folder()
93         root_folder.header = ''
94         self.folder_stack = [root_folder]
95         self.current_folder = root_folder
96
97         self.load_folder(root_folder, bookmarks_dict)
98         if self.folder_stack:
99             raise RuntimeError('Excessive folder stack: %s' % self.folder_stack)
100
101         return root_folder
102
103     def load_folder(self, folder, _dict):
104         if _dict["type"] != "text/x-moz-place-container":
105             raise ValueError("Root object is not a Mozilla container")
106
107         folder.id = _dict["id"]
108         folder.index = _dict.get("index")
109         folder.parent_idx = _dict.get("parent")
110
111         folder.name = encode(_dict["title"])
112         folder.comment = ''
113         folder.add_date = _dict["dateAdded"]
114         folder.last_modified = _dict["lastModified"]
115
116         for record in _dict["children"]:
117             if record["type"] == "text/x-moz-place":
118                 bookmark = Bookmark(
119                     href=record["uri"],
120                     add_date=record.get("dateAdded"),
121                     last_modified=record.get("lastModified"),
122                     charset=record.get("charset"))
123                 bookmark.id = record["id"]
124                 bookmark.index = record.get("index")
125                 bookmark.parent_idx = record["parent"]
126                 bookmark.name = encode(record["title"])
127                 self.current_folder.append(bookmark)
128
129             elif record["type"] == "text/x-moz-place-container":
130                 folder = Folder(
131                     add_date=record["dateAdded"], comment=None,
132                     last_modified=record["lastModified"])
133                 folder.id = record["id"]
134                 folder.parent_idx = record["parent"]
135                 folder.name = encode(record["title"])
136                 self.current_folder.append(folder)
137                 self.folder_stack.append(folder)
138                 self.current_folder = folder
139                 self.load_folder(folder, record)
140
141             elif record["type"] == "text/x-moz-place-separator":
142                 ruler = Ruler()
143                 ruler.add_date = record["dateAdded"]
144                 ruler.id = record["id"]
145                 ruler.index = record["index"]
146                 ruler.last_modified = record["lastModified"]
147                 ruler.parent_idx = record["parent"]
148                 ruler.name = encode(record["title"])
149                 self.current_folder.append(ruler)
150
151             else:
152                 raise ValueError('Unknown record type "%s"' % record["type"])
153
154         del self.folder_stack[-1]
155         if self.folder_stack:
156             self.current_folder = self.folder_stack[-1]
157         else:
158             self.current_folder = None
159
160 def encode(title):
161     return title.encode("UTF-8", "xmlcharrefreplace")