2 /// \file r_bookmark.cc
3 /// Record parsing class for the phone browser bookmarks database.
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"
33 #include "ios_state.h"
36 using namespace Barry::Protocol
;
40 ///////////////////////////////////////////////////////////////////////////////
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
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 }
73 const unsigned char* Bookmark::ParseStruct1Field(const unsigned char *begin
,
74 const unsigned char *end
,
78 const uint8_t type
= *begin
;
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
;
94 // not sure where id->bookmark_id links to, so ignore
103 const VarStringField
*f
= (const VarStringField
*) begin
;
104 begin
+= VARSTRING_FIELD_HEADER_SIZE
;
108 const uint16_t size
= be_btohs(f
->be_size
);
110 if( f
->present
== 1) { // if field is defined
118 Name
= ParseFieldString(f
->data
, size
);
121 Icon
= ParseFieldString(f
->data
, size
);
124 throw std::logic_error("Check cases");
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,
136 // example with the A5, before modification to add '?'
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:
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;
156 //const BookmarkFolders *f = (const BookmarkFolders*) begin;
157 begin
+= BOOKMARK_FOLDERS_HEADER_SIZE
;
161 // currently don't know how to link these to
162 // anything else in the device.... skipping
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);
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
;
186 DisplayMode
= (Barry::Bookmark::DisplayModeType
) *(begin
- 3);
188 if ((Barry::Bookmark::JavaScriptModeType
) *(begin
- 2) > Barry::Bookmark::JavaScriptUnknown
)
189 JavaScriptMode
= Barry::Bookmark::JavaScriptUnknown
;
191 JavaScriptMode
= (Barry::Bookmark::JavaScriptModeType
) *(begin
- 2);
193 if ((Barry::Bookmark::BrowserIdentityType
) *(begin
- 1) > Barry::Bookmark::IdentityUnknown
)
194 BrowserIdentity
= Barry::Bookmark::IdentityUnknown
;
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:
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
);
210 ddout("Bookmark parser: unknown section type: "
211 << std::hex
<< (unsigned int) type
);
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
;
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
236 Url
= ParseFieldString(field
->data
, size
);
238 // FIXME - more fields after this, but unknown meaning
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
254 if( !btohs(field
->size
) ) // if field has no size, something's up
258 const unsigned char *b
= field
->u
.raw
;
259 const unsigned char *e
= begin
;
261 // handle special cases
262 switch( field
->type
)
266 b
= ParseStruct1Field(b
, e
, ic
);
270 case BMKFC_BOOKMARK_TYPE
:
271 // above size check guarantees at least one byte,
273 if( field
->u
.raw
[0] != 'D' ) {
274 throw Error( "Bookmark::ParseField: BookmarkType is not 'D'" );
279 begin
= ParseStruct2(b
, e
, ic
);
283 // if still not handled, add to the Unknowns list
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
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";
332 os
<< " Name: " << Name
<< "\n";
334 os
<< " Icon: " << Icon
<< "\n";
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";
345 bool Bookmark::operator<(const Bookmark
&other
) const
347 int cmp
= Name
.compare(other
.Name
);
351 void Bookmark::Clear()
353 RecType
= GetDefaultRecType();
361 BrowserIdentity
= IdentityUnknown
;
362 DisplayMode
= DisplayUnknown
;
363 JavaScriptMode
= JavaScriptUnknown
;
368 const FieldHandle
<Bookmark
>::ListT
& Bookmark::GetFieldHandles()
370 static FieldHandle
<Bookmark
>::ListT 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");
414 std::string
Bookmark::GetDescription() const