desktop: fixed SyncStatusDlg resize bug
[barry/progweb.git] / src / r_bookmark.cc
blob1dc9043fc087f323d46df09152b33770c6b7b260
1 ///
2 /// \file r_bookmark.cc
3 /// Record parsing class for the phone browser bookmarks database.
4 ///
6 /*
7 Copyright (C) 2008-2010, Nicolas VIVIEN
8 Copyright (C) 2005-2012, Net Direct Inc. (http://www.netdirect.ca/)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License in the COPYING file at the
20 root directory of this project for more details.
23 #include "r_bookmark.h"
24 #include "record-internal.h"
25 #include "protostructs.h"
26 #include "data.h"
27 #include "time.h"
28 #include "iconv.h"
29 #include "debug.h"
30 #include <ostream>
31 #include <iomanip>
32 #include <iostream>
33 #include "ios_state.h"
35 using namespace std;
36 using namespace Barry::Protocol;
38 namespace Barry {
40 ///////////////////////////////////////////////////////////////////////////////
41 // Bookmark Class
43 // Bookmark Field Codes
44 #define BMKFC_BOOKMARK_TYPE 0x01
45 #define BMKFC_STRUCT1 0x11
46 #define BMKFC_STRUCT2 0x12
48 #define BMKFC_END 0xffff
50 // Bookmark Struct1 section codes
51 #define BMK1SC_HOMEPAGE_KEY 0x85 // default section on 9550...
52 // has browser dropdown grayed
53 // out
54 #define BMK1SC_BOOKMARK_ID 0x87 // when user adds a bookmark
55 #define BMK1SC_BOOKMARK_ID2 0x84 // only Nicolas sees this?
56 #define BMK1SC_NAME 0x04
57 #define BMK1SC_ICON 0x05
58 #define BMK1SC_FOLDERS 0x81
60 //static FieldLink<Bookmark> BookmarkFieldLinks[] = {
61 // { BMKFC_END, "End of List", 0, 0, 0, 0, 0, 0, 0, false }
62 //};
64 Bookmark::Bookmark()
66 Clear();
69 Bookmark::~Bookmark()
73 const unsigned char* Bookmark::ParseStruct1Field(const unsigned char *begin,
74 const unsigned char *end,
75 const IConverter *ic)
77 // grab section type
78 const uint8_t type = *begin;
79 begin += 1;
80 if( begin > end )
81 return begin;
83 switch( type )
85 case BMK1SC_HOMEPAGE_KEY:
86 case BMK1SC_BOOKMARK_ID:
87 case BMK1SC_BOOKMARK_ID2:
89 const BookmarkId *id = (const BookmarkId*) begin;
90 begin += BOOKMARK_ID_SIZE;
91 if( begin > end )
92 return begin;
94 // not sure where id->bookmark_id links to, so ignore
95 // for now...
96 Index = id->index;
98 return begin;
100 case BMK1SC_NAME:
101 case BMK1SC_ICON:
103 const VarStringField *f = (const VarStringField*) begin;
104 begin += VARSTRING_FIELD_HEADER_SIZE;
105 if( begin > end )
106 return begin;
108 const uint16_t size = be_btohs(f->be_size);
110 if( f->present == 1) { // if field is defined
111 begin += size;
112 if( begin > end )
113 return begin;
115 switch( type )
117 case BMK1SC_NAME:
118 Name = ParseFieldString(f->data, size);
119 break;
120 case BMK1SC_ICON:
121 Icon = ParseFieldString(f->data, size);
122 break;
123 default:
124 throw std::logic_error("Check cases");
125 break;
128 else if( f->present == 0 && size > 0xA0 ) {
129 // FIXME - a size of 0xA5 seems to occasionally
130 // appear, with 5 bytes of id-looking data
131 // we just skip it here.... note this
132 // may be a different field, but it meshes
133 // itself into the ICON section somehow,
134 // that is unclear
136 // example with the A5, before modification to add '?'
137 // Type: 0x11 Data:
138 // 00000000: 85 9b ed ca 13 00 04 01 00 09 48 6f 6d 65 20 50 ..........Home P
139 // 00000010: 61 67 65 81 b9 fc f8 f6 c2 e3 a4 d5 08 01 05 00 age.............
140 // 00000020: 00 a5 b8 f0 97 e4 3a 00 00 01 ......:...
142 // example without the A5, after record modified:
143 // Type: 0x11 Data:
144 // 00000000: 85 9b ed ca 13 00 04 01 00 0a 48 6f 6d 65 20 50 ..........Home P
145 // 00000010: 61 67 65 3f 81 b9 fc f8 f6 c2 e3 a4 d5 08 01 05 age?............
146 // 00000020: 00 00 00 00 00 01 ......
149 begin += size & 0x0F;
152 return begin;
154 case BMK1SC_FOLDERS:
156 //const BookmarkFolders *f = (const BookmarkFolders*) begin;
157 begin += BOOKMARK_FOLDERS_HEADER_SIZE;
158 if( begin > end )
159 return begin;
161 // currently don't know how to link these to
162 // anything else in the device.... skipping
164 return begin;
167 case 0x08:
168 isdefined = *b;
169 b += sizeof(uint8_t);
170 if (isdefined == 1) { // if field is defined
171 const uint16_t size = be_btohs(*((const uint16_t *) b));
172 b += sizeof(uint16_t);
173 b += size;
175 break;
178 default:
179 // if we are 3 bytes away from the end, these are the
180 // display, javascript, and browser identity flags
181 // (make sure to account for the type we ate above)
182 if( (end - begin) == 2 ) {
183 if ((Barry::Bookmark::DisplayModeType) *(begin - 3) > Barry::Bookmark::DisplayUnknown)
184 DisplayMode = Barry::Bookmark::DisplayUnknown;
185 else
186 DisplayMode = (Barry::Bookmark::DisplayModeType) *(begin - 3);
188 if ((Barry::Bookmark::JavaScriptModeType) *(begin - 2) > Barry::Bookmark::JavaScriptUnknown)
189 JavaScriptMode = Barry::Bookmark::JavaScriptUnknown;
190 else
191 JavaScriptMode = (Barry::Bookmark::JavaScriptModeType) *(begin - 2);
193 if ((Barry::Bookmark::BrowserIdentityType) *(begin - 1) > Barry::Bookmark::IdentityUnknown)
194 BrowserIdentity = Barry::Bookmark::IdentityUnknown;
195 else
196 BrowserIdentity = (Barry::Bookmark::BrowserIdentityType) *(begin - 1);
198 // if we are at the beginning, this could be the 7750
199 // with its odd no-code ID... the 7750 seems to have
200 // a BOOKMARK_ID record without any code byte,
201 // so check that the data looks like this:
202 // XX XX XX XX 00
203 // with the 4 byte ID and the index of 0, being the
204 // first default bookmark
205 else if( (begin + 3) < end && begin[3] == 0 ) {
206 // recurse into ourselves
207 return ParseStruct1Field(begin + 4, end, ic);
209 else {
210 ddout("Bookmark parser: unknown section type: "
211 << std::hex << (unsigned int) type);
213 break;
216 return begin;
219 const unsigned char* Bookmark::ParseStruct2(const unsigned char *begin,
220 const unsigned char *end,
221 const IConverter *ic)
223 // first field in struct2 seems to always be the URL
225 // grab size and advance over string, checking sizes
226 const StringField *field = (const StringField*) begin;
227 begin += STRING_FIELD_HEADER_SIZE;
228 if( begin > end )
229 return begin;
231 const uint16_t size = be_btohs(field->be_size);
232 begin += sizeof(uint16_t) + size;
233 if( begin > end ) // if begin==end, we are ok
234 return begin;
236 Url = ParseFieldString(field->data, size);
238 // FIXME - more fields after this, but unknown meaning
240 return begin;
243 const unsigned char* Bookmark::ParseField(const unsigned char *begin,
244 const unsigned char *end,
245 const IConverter *ic)
247 const CommonField *field = (const CommonField *) begin;
249 // advance and check size
250 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
251 if( begin > end ) // if begin==end, we are ok
252 return begin;
254 if( !btohs(field->size) ) // if field has no size, something's up
255 return begin;
258 const unsigned char *b = field->u.raw;
259 const unsigned char *e = begin;
261 // handle special cases
262 switch( field->type )
264 case BMKFC_STRUCT1:
265 while (b <= e) {
266 b = ParseStruct1Field(b, e, ic);
268 return b;
270 case BMKFC_BOOKMARK_TYPE:
271 // above size check guarantees at least one byte,
272 // so this is safe
273 if( field->u.raw[0] != 'D' ) {
274 throw Error( "Bookmark::ParseField: BookmarkType is not 'D'" );
276 return begin;
278 case BMKFC_STRUCT2:
279 begin = ParseStruct2(b, e, ic);
280 return begin;
283 // if still not handled, add to the Unknowns list
284 UnknownField uf;
285 uf.type = field->type;
286 uf.data.assign((const char*)field->u.raw, btohs(field->size));
287 Unknowns.push_back(uf);
289 // return new pointer for next field
290 return begin;
293 void Bookmark::ParseHeader(const Data &data, size_t &offset)
295 // no header in Bookmark records
298 void Bookmark::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
300 const unsigned char *finish = ParseCommonFields(*this,
301 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
302 offset += finish - (data.GetData() + offset);
305 void Bookmark::Validate() const
309 void Bookmark::BuildHeader(Data &data, size_t &offset) const
311 // not yet implemented
314 void Bookmark::BuildFields(Data &data, size_t &offset, const IConverter *ic) const
316 // not yet implemented
319 void Bookmark::Dump(std::ostream &os) const
321 ios_format_state state(os);
323 static const char *DisplayModeName[] = { "Automatic", "Enabled", "Disabled", "Unknown" };
324 static const char *JavaScriptModeName[] = { "Automatic", "Enabled", "Disabled", "Unknown" };
325 static const char *BrowserIdentityName[] = { "Automatic", "BlackBerry", "FireFox", "Internet Explorer", "Unknown" };
327 os << "Bookmark entry: 0x" << setbase(16) << RecordId
328 << " (" << (unsigned int)RecType << ")"
329 << " (index " << (unsigned int)Index << ")\n";
331 if( Name.size() )
332 os << " Name: " << Name << "\n";
333 if( Icon.size() )
334 os << " Icon: " << Icon << "\n";
335 if( Url.size() )
336 os << " Url: " << Url << "\n";
337 os << " Display mode: " << DisplayModeName[DisplayMode] << "\n";
338 os << " JavaScript mode: " << JavaScriptModeName[JavaScriptMode] << "\n";
339 os << " Browser Identity mode: " << BrowserIdentityName[BrowserIdentity] << "\n";
341 os << Unknowns;
342 os << "\n\n";
345 bool Bookmark::operator<(const Bookmark &other) const
347 int cmp = Name.compare(other.Name);
348 return cmp < 0;
351 void Bookmark::Clear()
353 RecType = GetDefaultRecType();
354 RecordId = 0;
355 Index = 0;
357 Name.clear();
358 Icon.clear();
359 Url.clear();
361 BrowserIdentity = IdentityUnknown;
362 DisplayMode = DisplayUnknown;
363 JavaScriptMode = JavaScriptUnknown;
365 Unknowns.clear();
368 const FieldHandle<Bookmark>::ListT& Bookmark::GetFieldHandles()
370 static FieldHandle<Bookmark>::ListT fhv;
372 if( fhv.size() )
373 return fhv;
375 #undef CONTAINER_OBJECT_NAME
376 #define CONTAINER_OBJECT_NAME fhv
378 #undef RECORD_CLASS_NAME
379 #define RECORD_CLASS_NAME Bookmark
381 FHP(RecType, "Record Type");
382 FHP(RecordId, "Unique Record ID");
384 FHP(Index, "Bookmark Field Index");
386 FHP(Name, "Site Name");
387 FHP(Icon, "Site Icon");
388 FHP(Url, "Site URL");
390 FHE(bit, BrowserIdentityType, BrowserIdentity, "Browser Identity");
391 FHE_CONST(bit, IdentityAuto, "Auto detect browser");
392 FHE_CONST(bit, IdentityBlackBerry, "BlackBerry browser");
393 FHE_CONST(bit, IdentityFireFox, "FireFox browser");
394 FHE_CONST(bit, IdentityInternetExplorer, "Internet Explorer browser");
395 FHE_CONST(bit, IdentityUnknown, "Unknown browser");
397 FHE(dmc, DisplayModeType, DisplayMode, "Display Mode");
398 FHE_CONST(dmc, DisplayAuto, "Automatic");
399 FHE_CONST(dmc, DisplayColomn, "Column");
400 FHE_CONST(dmc, DisplayPage, "Page");
401 FHE_CONST(dmc, DisplayUnknown, "Unknown");
403 FHE(jsm, JavaScriptModeType, JavaScriptMode, "JavaScript Mode");
404 FHE_CONST(jsm, JavaScriptAuto, "Automatic");
405 FHE_CONST(jsm, JavaScriptEnabled, "Enabled");
406 FHE_CONST(jsm, JavaScriptDisabled, "Disabled");
407 FHE_CONST(jsm, JavaScriptUnknown, "Unknown");
409 FHP(Unknowns, "Unknown Fields");
411 return fhv;
414 std::string Bookmark::GetDescription() const
416 return Name;
419 } // namespace Barry