lib: fixed missing endian adjustment in bookmark parser
[barry.git] / src / r_bookmark.cc
blob586aa783611df38fabab6f0e0264a32fc54437fa
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-2010, 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 <ostream>
30 #include <iomanip>
31 #include <iostream>
33 using namespace std;
34 using namespace Barry::Protocol;
36 namespace Barry {
38 ///////////////////////////////////////////////////////////////////////////////
39 // Bookmark Class
41 // Bookmark Field Codes
42 #define BMKFC_BOOKMARK_TYPE 0x01
44 #define BMKFC_NAME 0x04
45 #define BMKFC_URL 0xff
46 #define BMKFC_ICON 0x05
48 #define BMKFC_STRUCT1 0x11
49 #define BMKFC_STRUCT2 0x12
51 #define BMKFC_END 0xffff
53 static FieldLink<Bookmark> BookmarkFieldLinks[] = {
54 { BMKFC_NAME, "Name", 0, 0, &Bookmark::Name, 0, 0, 0, 0, true },
55 { BMKFC_URL, "URL", 0, 0, &Bookmark::URL, 0, 0, 0, 0, true },
56 { BMKFC_ICON, "Icon", 0, 0, &Bookmark::Icon, 0, 0, 0, 0, true },
57 { BMKFC_END, "End of List", 0, 0, 0, 0, 0, 0, 0, false }
60 Bookmark::Bookmark()
62 Clear();
65 Bookmark::~Bookmark()
69 const unsigned char* Bookmark::ParseField(const unsigned char *begin,
70 const unsigned char *end,
71 const IConverter *ic)
73 const CommonField *field = (const CommonField *) begin;
75 // advance and check size
76 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
77 if( begin > end ) // if begin==end, we are ok
78 return begin;
80 if( !btohs(field->size) ) // if field has no size, something's up
81 return begin;
83 if( field->type == BMKFC_BOOKMARK_TYPE ) {
84 if( field->u.raw[0] != 'D' ) {
85 throw Error( "Bookmark::ParseField: BookmarkType is not 'D'" );
87 return begin;
91 uint8_t isdefined;
93 const unsigned char *b = field->u.raw;
94 const unsigned char *e = begin;
96 // handle special cases
97 switch( field->type )
99 case BMKFC_STRUCT1:
100 while (b < e) {
101 const uint8_t type = *b;
103 // advance and check size
104 b += 1;
105 if( b > e ) // if begin==end, we are ok
106 continue;
108 switch (type)
110 case 0x81:
111 b += 8; // 8 fields unknown
112 break;
113 case 0x84:
114 case 0x85:
115 b += 5; // 4 fields unknown
116 break;
117 case BMKFC_NAME:
118 isdefined = *b;
119 b += sizeof(uint8_t);
120 if (isdefined == 1) { // if field is defined
121 const uint16_t size = be_btohs(*((const uint16_t *) b));
122 b += sizeof(uint16_t);
123 Name = ParseFieldString(b, size);
124 b += size;
126 break;
127 case BMKFC_ICON:
128 isdefined = *b;
129 b += sizeof(uint8_t);
130 if (isdefined == 1) { // if field is defined
131 const uint16_t size = be_btohs(*((const uint16_t *) b));
132 b += sizeof(uint16_t);
133 Icon = ParseFieldString(b, size);
134 b += size;
136 break;
137 case 0x08:
138 isdefined = *b;
139 b += sizeof(uint8_t);
140 if (isdefined == 1) { // if field is defined
141 const uint16_t size = be_btohs(*((const uint16_t *) b));
142 b += sizeof(uint16_t);
143 b += size;
145 break;
149 if( btohs(field->size) >= 3 ) {
150 if ((Barry::Bookmark::DisplayModeType) *(begin - 3) > Barry::Bookmark::DisplayUnknown)
151 DisplayMode = Barry::Bookmark::DisplayUnknown;
152 else
153 DisplayMode = (Barry::Bookmark::DisplayModeType) *(begin - 3);
155 if ((Barry::Bookmark::JavaScriptModeType) *(begin - 2) > Barry::Bookmark::JavaScriptUnknown)
156 JavaScriptMode = Barry::Bookmark::JavaScriptUnknown;
157 else
158 JavaScriptMode = (Barry::Bookmark::JavaScriptModeType) *(begin - 2);
160 if ((Barry::Bookmark::BrowserIdentityType) *(begin - 1) > Barry::Bookmark::IdentityUnknown)
161 BrowserIdentity = Barry::Bookmark::IdentityUnknown;
162 else
163 BrowserIdentity = (Barry::Bookmark::BrowserIdentityType) *(begin - 1);
166 // return begin;
167 break;
169 case BMKFC_STRUCT2:
171 const uint16_t size = be_btohs(*((const uint16_t *) b));
172 b += sizeof(uint16_t);
173 URL = ParseFieldString(b, size);
174 b += size;
177 // return begin;
178 break;
181 // if still not handled, add to the Unknowns list
182 UnknownField uf;
183 uf.type = field->type;
184 uf.data.assign((const char*)field->u.raw, btohs(field->size));
185 Unknowns.push_back(uf);
187 // return new pointer for next field
188 return begin;
191 void Bookmark::ParseHeader(const Data &data, size_t &offset)
193 // no header in Bookmark records
196 void Bookmark::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
198 const unsigned char *finish = ParseCommonFields(*this,
199 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
200 offset += finish - (data.GetData() + offset);
203 void Bookmark::Dump(std::ostream &os) const
205 static const char *DisplayModeName[] = { "Automatique", "Enabled", "Disabled", "Unknown" };
206 static const char *JavaScriptModeName[] = { "Automatique", "Enabled", "Disabled", "Unknown" };
207 static const char *BrowserIdentityName[] = { "Automatique", "BlackBerry", "FireFox", "Internet Explorer", "Unknown" };
209 os << "Bookmark entry: 0x" << setbase(16) << RecordId
210 << " (" << (unsigned int)RecType << ")\n";
212 // cycle through the type table
213 for( const FieldLink<Bookmark> *b = BookmarkFieldLinks;
214 b->type != BMKFC_END;
215 b++ )
217 if( b->strMember ) {
218 const std::string &s = this->*(b->strMember);
219 if( s.size() )
220 os << " " << b->name << ": " << s << "\n";
222 else if( b->timeMember ) {
223 time_t t = this->*(b->timeMember);
224 if( t > 0 )
225 os << " " << b->name << ": " << ctime(&t);
226 else
227 os << " " << b->name << ": unknown\n";
231 os << " Display mode: " << DisplayModeName[DisplayMode] << "\n";
232 os << " JavaScript mode: " << JavaScriptModeName[JavaScriptMode] << "\n";
233 os << " Browser Identity mode: " << BrowserIdentityName[BrowserIdentity] << "\n";
235 os << Unknowns;
236 os << "\n\n";
239 bool Bookmark::operator<(const Bookmark &other) const
241 int cmp = Name.compare(other.Name);
242 return cmp < 0;
245 void Bookmark::Clear()
247 RecType = GetDefaultRecType();
248 RecordId = 0;
250 Name.clear();
251 Icon.clear();
252 URL.clear();
254 BrowserIdentity = IdentityUnknown;
255 DisplayMode = DisplayUnknown;
256 JavaScriptMode = JavaScriptUnknown;
258 Unknowns.clear();
261 } // namespace Barry