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-2013, 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.
24 #include "r_bookmark.h"
25 #include "record-internal.h"
26 #include "protostructs.h"
34 #include "ios_state.h"
37 using namespace Barry::Protocol
;
41 ///////////////////////////////////////////////////////////////////////////////
44 // Bookmark Field Codes
45 #define BMKFC_BOOKMARK_TYPE 0x01
46 #define BMKFC_STRUCT1 0x11
47 #define BMKFC_STRUCT2 0x12
49 #define BMKFC_END 0xffff
51 // Bookmark Struct1 section codes
52 #define BMK1SC_HOMEPAGE_KEY 0x85 // default section on 9550...
53 // has browser dropdown grayed
55 #define BMK1SC_BOOKMARK_ID 0x87 // when user adds a bookmark
56 #define BMK1SC_BOOKMARK_ID2 0x84 // only Nicolas sees this?
57 #define BMK1SC_NAME 0x04
58 #define BMK1SC_ICON 0x05
59 #define BMK1SC_FOLDERS 0x81
61 //static FieldLink<Bookmark> BookmarkFieldLinks[] = {
62 // { BMKFC_END, "End of List", 0, 0, 0, 0, 0, 0, 0, false }
74 const unsigned char* Bookmark::ParseStruct1Field(const unsigned char *begin
,
75 const unsigned char *end
,
79 const uint8_t type
= *begin
;
86 case BMK1SC_HOMEPAGE_KEY
:
87 case BMK1SC_BOOKMARK_ID
:
88 case BMK1SC_BOOKMARK_ID2
:
90 const BookmarkId
*id
= (const BookmarkId
*) begin
;
91 begin
+= BOOKMARK_ID_SIZE
;
95 // not sure where id->bookmark_id links to, so ignore
104 const VarStringField
*f
= (const VarStringField
*) begin
;
105 begin
+= VARSTRING_FIELD_HEADER_SIZE
;
109 const uint16_t size
= be_btohs(f
->be_size
);
111 if( f
->present
== 1) { // if field is defined
119 Name
= ParseFieldString(f
->data
, size
);
122 Icon
= ParseFieldString(f
->data
, size
);
125 throw std::logic_error("Bookmark: Check case statement. Should never happen.");
129 else if( f
->present
== 0 && size
> 0xA0 ) {
130 // FIXME - a size of 0xA5 seems to occasionally
131 // appear, with 5 bytes of id-looking data
132 // we just skip it here.... note this
133 // may be a different field, but it meshes
134 // itself into the ICON section somehow,
137 // example with the A5, before modification to add '?'
139 // 00000000: 85 9b ed ca 13 00 04 01 00 09 48 6f 6d 65 20 50 ..........Home P
140 // 00000010: 61 67 65 81 b9 fc f8 f6 c2 e3 a4 d5 08 01 05 00 age.............
141 // 00000020: 00 a5 b8 f0 97 e4 3a 00 00 01 ......:...
143 // example without the A5, after record modified:
145 // 00000000: 85 9b ed ca 13 00 04 01 00 0a 48 6f 6d 65 20 50 ..........Home P
146 // 00000010: 61 67 65 3f 81 b9 fc f8 f6 c2 e3 a4 d5 08 01 05 age?............
147 // 00000020: 00 00 00 00 00 01 ......
150 begin
+= size
& 0x0F;
157 //const BookmarkFolders *f = (const BookmarkFolders*) begin;
158 begin
+= BOOKMARK_FOLDERS_HEADER_SIZE
;
162 // currently don't know how to link these to
163 // anything else in the device.... skipping
170 b += sizeof(uint8_t);
171 if (isdefined == 1) { // if field is defined
172 const uint16_t size = be_btohs(*((const uint16_t *) b));
173 b += sizeof(uint16_t);
180 // if we are 3 bytes away from the end, these are the
181 // display, javascript, and browser identity flags
182 // (make sure to account for the type we ate above)
183 if( (end
- begin
) == 2 ) {
184 if ((Barry::Bookmark::DisplayModeType
) *(begin
- 3) > Barry::Bookmark::DisplayUnknown
)
185 DisplayMode
= Barry::Bookmark::DisplayUnknown
;
187 DisplayMode
= (Barry::Bookmark::DisplayModeType
) *(begin
- 3);
189 if ((Barry::Bookmark::JavaScriptModeType
) *(begin
- 2) > Barry::Bookmark::JavaScriptUnknown
)
190 JavaScriptMode
= Barry::Bookmark::JavaScriptUnknown
;
192 JavaScriptMode
= (Barry::Bookmark::JavaScriptModeType
) *(begin
- 2);
194 if ((Barry::Bookmark::BrowserIdentityType
) *(begin
- 1) > Barry::Bookmark::IdentityUnknown
)
195 BrowserIdentity
= Barry::Bookmark::IdentityUnknown
;
197 BrowserIdentity
= (Barry::Bookmark::BrowserIdentityType
) *(begin
- 1);
199 // if we are at the beginning, this could be the 7750
200 // with its odd no-code ID... the 7750 seems to have
201 // a BOOKMARK_ID record without any code byte,
202 // so check that the data looks like this:
204 // with the 4 byte ID and the index of 0, being the
205 // first default bookmark
206 else if( (begin
+ 3) < end
&& begin
[3] == 0 ) {
207 // recurse into ourselves
208 return ParseStruct1Field(begin
+ 4, end
, ic
);
211 ddout("Bookmark parser: unknown section type: "
212 << std::hex
<< (unsigned int) type
);
220 const unsigned char* Bookmark::ParseStruct2(const unsigned char *begin
,
221 const unsigned char *end
,
222 const IConverter
*ic
)
224 // first field in struct2 seems to always be the URL
226 // grab size and advance over string, checking sizes
227 const StringField
*field
= (const StringField
*) begin
;
228 begin
+= STRING_FIELD_HEADER_SIZE
;
232 const uint16_t size
= be_btohs(field
->be_size
);
233 begin
+= sizeof(uint16_t) + size
;
234 if( begin
> end
) // if begin==end, we are ok
237 Url
= ParseFieldString(field
->data
, size
);
239 // FIXME - more fields after this, but unknown meaning
244 const unsigned char* Bookmark::ParseField(const unsigned char *begin
,
245 const unsigned char *end
,
246 const IConverter
*ic
)
248 const CommonField
*field
= (const CommonField
*) begin
;
250 // advance and check size
251 begin
+= COMMON_FIELD_HEADER_SIZE
+ btohs(field
->size
);
252 if( begin
> end
) // if begin==end, we are ok
255 if( !btohs(field
->size
) ) // if field has no size, something's up
259 const unsigned char *b
= field
->u
.raw
;
260 const unsigned char *e
= begin
;
262 // handle special cases
263 switch( field
->type
)
267 b
= ParseStruct1Field(b
, e
, ic
);
271 case BMKFC_BOOKMARK_TYPE
:
272 // above size check guarantees at least one byte,
274 if( field
->u
.raw
[0] != 'D' ) {
275 throw Error( _("Bookmark::ParseField: BookmarkType is not 'D'") );
280 begin
= ParseStruct2(b
, e
, ic
);
284 // if still not handled, add to the Unknowns list
286 uf
.type
= field
->type
;
287 uf
.data
.assign((const char*)field
->u
.raw
, btohs(field
->size
));
288 Unknowns
.push_back(uf
);
290 // return new pointer for next field
294 void Bookmark::ParseHeader(const Data
&data
, size_t &offset
)
296 // no header in Bookmark records
299 void Bookmark::ParseFields(const Data
&data
, size_t &offset
, const IConverter
*ic
)
301 const unsigned char *finish
= ParseCommonFields(*this,
302 data
.GetData() + offset
, data
.GetData() + data
.GetSize(), ic
);
303 offset
+= finish
- (data
.GetData() + offset
);
306 void Bookmark::Validate() const
310 void Bookmark::BuildHeader(Data
&data
, size_t &offset
) const
312 // not yet implemented
315 void Bookmark::BuildFields(Data
&data
, size_t &offset
, const IConverter
*ic
) const
317 // not yet implemented
320 void Bookmark::Dump(std::ostream
&os
) const
322 ios_format_state
state(os
);
324 static const char *DisplayModeName
[] = {
330 static const char *JavaScriptModeName
[] = {
336 static const char *BrowserIdentityName
[] = {
340 N_("Internet Explorer"),
344 os
<< _("Bookmark entry: ") << "0x" << setbase(16) << RecordId
345 << " (" << (unsigned int)RecType
<< ")"
346 << " (" << _("index ") << (unsigned int)Index
<< ")\n";
349 os
<< _(" Name: ") << Name
<< "\n";
351 os
<< _(" Icon: ") << Icon
<< "\n";
353 os
<< _(" Url: ") << Url
<< "\n";
354 os
<< _(" Display mode: ")
355 << gettext( DisplayModeName
[DisplayMode
] ) << "\n";
356 os
<< _(" JavaScript mode: ")
357 << gettext( JavaScriptModeName
[JavaScriptMode
] ) << "\n";
358 os
<< _(" Browser Identity: ")
359 << gettext( BrowserIdentityName
[BrowserIdentity
] ) << "\n";
365 bool Bookmark::operator<(const Bookmark
&other
) const
367 int cmp
= Name
.compare(other
.Name
);
371 void Bookmark::Clear()
373 RecType
= GetDefaultRecType();
381 BrowserIdentity
= IdentityUnknown
;
382 DisplayMode
= DisplayUnknown
;
383 JavaScriptMode
= JavaScriptUnknown
;
388 const FieldHandle
<Bookmark
>::ListT
& Bookmark::GetFieldHandles()
390 static FieldHandle
<Bookmark
>::ListT fhv
;
395 #undef CONTAINER_OBJECT_NAME
396 #define CONTAINER_OBJECT_NAME fhv
398 #undef RECORD_CLASS_NAME
399 #define RECORD_CLASS_NAME Bookmark
401 FHP(RecType
, _("Record Type"));
402 FHP(RecordId
, _("Unique Record ID"));
404 FHP(Index
, _("Bookmark Field Index"));
406 FHP(Name
, _("Site Name"));
407 FHP(Icon
, _("Site Icon"));
408 FHP(Url
, _("Site URL"));
410 FHE(bit
, BrowserIdentityType
, BrowserIdentity
, _("Browser Identity"));
411 FHE_CONST(bit
, IdentityAuto
, _("Auto detect browser"));
412 FHE_CONST(bit
, IdentityBlackBerry
, _("BlackBerry browser"));
413 FHE_CONST(bit
, IdentityFireFox
, _("FireFox browser"));
414 FHE_CONST(bit
, IdentityInternetExplorer
, _("Internet Explorer browser"));
415 FHE_CONST(bit
, IdentityUnknown
, _("Unknown browser"));
417 FHE(dmc
, DisplayModeType
, DisplayMode
, _("Display Mode"));
418 FHE_CONST(dmc
, DisplayAuto
, _("Automatic"));
419 FHE_CONST(dmc
, DisplayColomn
, _("Column"));
420 FHE_CONST(dmc
, DisplayPage
, _("Page"));
421 FHE_CONST(dmc
, DisplayUnknown
, _("Unknown"));
423 FHE(jsm
, JavaScriptModeType
, JavaScriptMode
, _("JavaScript Mode"));
424 FHE_CONST(jsm
, JavaScriptAuto
, _("Automatic"));
425 FHE_CONST(jsm
, JavaScriptEnabled
, _("Enabled"));
426 FHE_CONST(jsm
, JavaScriptDisabled
, _("Disabled"));
427 FHE_CONST(jsm
, JavaScriptUnknown
, _("Unknown"));
429 FHP(Unknowns
, _("Unknown Fields"));
434 std::string
Bookmark::GetDescription() const