3 /// Blackberry database record parser class for
4 /// Content Store records.
8 Copyright (C) 2010-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.
25 #include "record-internal.h"
31 #include "ios_state.h"
33 #define __DEBUG_MODE__
37 using namespace Barry::Protocol
;
42 ///////////////////////////////////////////////////////////////////////////////
45 // ContentStore field codes
46 #define CSFC_FILENAME 0x01 // may not always be a complete file,but
47 // a folder name as well
48 #define CSFC_FOLDER_FLAG 0x05
49 #define CSFC_FILE_DESCRIPTOR 0x06
50 #define CSFC_FILE_CONTENT 0x07
53 #define MAX_CONTENT_BLOCK_SIZE 0xfffe
55 ContentStore::ContentStore()
60 ContentStore::~ContentStore()
64 const unsigned char* ContentStore::ParseField(const unsigned char *begin
,
65 const unsigned char *end
,
68 const CommonField
*field
= (const CommonField
*) begin
;
70 // advance and check size
71 begin
+= COMMON_FIELD_HEADER_SIZE
+ btohs(field
->size
);
72 if( begin
> end
) // if begin==end, we are ok
75 if( !btohs(field
->size
) ) // if field has no size, something's up
81 Filename
= ParseFieldString(field
);
84 case CSFC_FOLDER_FLAG
:
87 // the CSFC_FOLDER_FLAG field seems to always
88 // contain the string "folder".. so check for it
89 string s
= ParseFieldString(field
);
96 case CSFC_FILE_CONTENT
:
98 // size already received, append data to FileContent
99 FileContent
.append((const char*)field
->u
.raw
,
103 FileSize
= btohll(field
->u
.uint64
);
107 case CSFC_FILE_DESCRIPTOR
:
108 // need to parse this further, but until then, just
109 // store it as a chunk of data
110 FileDescriptor
.assign((const char*)field
->u
.raw
,
115 // if still not handled, add to the Unknowns list
117 uf
.type
= field
->type
;
118 uf
.data
.assign((const char*)field
->u
.raw
, btohs(field
->size
));
119 Unknowns
.push_back(uf
);
121 // return new pointer for next field
125 void ContentStore::ParseHeader(const Data
&data
, size_t &offset
)
127 // no header to parse
130 void ContentStore::ParseFields(const Data
&data
, size_t &offset
, const IConverter
*ic
)
132 const unsigned char *finish
= ParseCommonFields(*this,
133 data
.GetData() + offset
, data
.GetData() + data
.GetSize(), ic
);
134 offset
+= finish
- (data
.GetData() + offset
);
137 void ContentStore::Validate() const
141 void ContentStore::BuildHeader(Data
&data
, size_t &offset
) const
145 void ContentStore::BuildFields(Data
&data
, size_t &offset
, const IConverter
*ic
) const
149 if( !Filename
.size() )
150 throw BadData(_("Content Store must have a name."));
152 if( !FolderFlag
&& !FileContent
.size() )
153 throw BadData(_("Content Store item without any data."));
156 BuildField(data
, offset
, CSFC_FILENAME
, Filename
);
160 BuildField(data
, offset
, CSFC_FOLDER_FLAG
, string("folder"));
163 // write file descriptor first
164 BuildField(data
, offset
, CSFC_FILE_DESCRIPTOR
,
165 FileDescriptor
.data(), FileDescriptor
.size());
167 // a normal file... the file content is given:
169 // content in blocks of 0xfffe bytes until done
170 // all with the same ID
172 // force the size to actual, and write it first
173 uint64_t RealSize
= FileContent
.size();
174 BuildField(data
, offset
, CSFC_FILE_CONTENT
, RealSize
);
176 // write data in blocks of 0xfffe bytes
177 for( size_t foff
= 0; foff
< FileContent
.size(); ) {
178 size_t blocksize
= FileContent
.size() - foff
;
179 if( blocksize
> MAX_CONTENT_BLOCK_SIZE
)
180 blocksize
= MAX_CONTENT_BLOCK_SIZE
;
181 BuildField(data
, offset
, CSFC_FILE_CONTENT
,
182 FileContent
.data() + foff
, blocksize
);
189 // and finally save unknowns
190 UnknownsType::const_iterator
191 ub
= Unknowns
.begin(), ue
= Unknowns
.end();
192 for( ; ub
!= ue
; ub
++ ) {
193 BuildField(data
, offset
, *ub
);
196 data
.ReleaseBuffer(offset
);
199 void ContentStore::Clear()
201 RecType
= GetDefaultRecType();
207 FileDescriptor
.clear();
211 // internal variables
215 const FieldHandle
<ContentStore
>::ListT
& ContentStore::GetFieldHandles()
217 static FieldHandle
<ContentStore
>::ListT fhv
;
222 #undef CONTAINER_OBJECT_NAME
223 #define CONTAINER_OBJECT_NAME fhv
225 #undef RECORD_CLASS_NAME
226 #define RECORD_CLASS_NAME ContentStore
228 FHP(RecType
, _("Record Type Code"));
229 FHP(RecordId
, _("Unique Record ID"));
231 FHD(Filename
, _("File or Folder Name"), CSFC_FILENAME
, true);
232 FHD(FolderFlag
, _("Folder Flag"), CSFC_FOLDER_FLAG
, false);
233 FHD(FileContent
, _("File Content"), CSFC_FILE_CONTENT
, false);
234 FHD(FileDescriptor
, _("File Descriptor"), CSFC_FILE_DESCRIPTOR
, false);
236 FHP(Unknowns
, _("Unknown Fields"));
241 std::string
ContentStore::GetDescription() const
246 void ContentStore::Dump(std::ostream
&os
) const
248 ios_format_state
state(os
);
253 os
<< _("ContentStore: ") << "0x" << hex
<< RecordId
254 << " (" << (unsigned int)RecType
<< ")\n";
256 os
<< _(" Filename: ") << Filename
<< endl
;
257 os
<< _(" Folder: ") << (FolderFlag
? "yes" : "no") << endl
;
258 os
<< _(" BB Size: ") << dec
<< FileSize
<< endl
;
259 os
<< _(" Actual Size: ") << FileContent
.size() << endl
;
260 os
<< _(" Descriptor:\n")
261 << Data(FileDescriptor
.data(), FileDescriptor
.size()) << endl
;
262 os
<< _(" Content:\n")
263 << Data(FileContent
.data(), FileContent
.size()) << endl
;
265 // and finally print unknowns
269 bool ContentStore::operator<(const ContentStore
&other
) const
271 return RecordId
< other
.RecordId
;