3 /// Blackberry database record parser class for
4 /// Content Store records.
8 Copyright (C) 2010-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.
24 #include "record-internal.h"
30 #include "ios_state.h"
32 #define __DEBUG_MODE__
36 using namespace Barry::Protocol
;
41 ///////////////////////////////////////////////////////////////////////////////
44 // ContentStore field codes
45 #define CSFC_FILENAME 0x01 // may not always be a complete file,but
46 // a folder name as well
47 #define CSFC_FOLDER_FLAG 0x05
48 #define CSFC_FILE_DESCRIPTOR 0x06
49 #define CSFC_FILE_CONTENT 0x07
52 #define MAX_CONTENT_BLOCK_SIZE 0xfffe
54 ContentStore::ContentStore()
59 ContentStore::~ContentStore()
63 const unsigned char* ContentStore::ParseField(const unsigned char *begin
,
64 const unsigned char *end
,
67 const CommonField
*field
= (const CommonField
*) begin
;
69 // advance and check size
70 begin
+= COMMON_FIELD_HEADER_SIZE
+ btohs(field
->size
);
71 if( begin
> end
) // if begin==end, we are ok
74 if( !btohs(field
->size
) ) // if field has no size, something's up
80 Filename
= ParseFieldString(field
);
83 case CSFC_FOLDER_FLAG
:
86 // the CSFC_FOLDER_FLAG field seems to always
87 // contain the string "folder".. so check for it
88 string s
= ParseFieldString(field
);
95 case CSFC_FILE_CONTENT
:
97 // size already received, append data to FileContent
98 FileContent
.append((const char*)field
->u
.raw
,
102 FileSize
= btohll(field
->u
.uint64
);
106 case CSFC_FILE_DESCRIPTOR
:
107 // need to parse this further, but until then, just
108 // store it as a chunk of data
109 FileDescriptor
.assign((const char*)field
->u
.raw
,
114 // if still not handled, add to the Unknowns list
116 uf
.type
= field
->type
;
117 uf
.data
.assign((const char*)field
->u
.raw
, btohs(field
->size
));
118 Unknowns
.push_back(uf
);
120 // return new pointer for next field
124 void ContentStore::ParseHeader(const Data
&data
, size_t &offset
)
126 // no header to parse
129 void ContentStore::ParseFields(const Data
&data
, size_t &offset
, const IConverter
*ic
)
131 const unsigned char *finish
= ParseCommonFields(*this,
132 data
.GetData() + offset
, data
.GetData() + data
.GetSize(), ic
);
133 offset
+= finish
- (data
.GetData() + offset
);
136 void ContentStore::Validate() const
140 void ContentStore::BuildHeader(Data
&data
, size_t &offset
) const
144 void ContentStore::BuildFields(Data
&data
, size_t &offset
, const IConverter
*ic
) const
148 if( !Filename
.size() )
149 throw BadData("Content Store must have a name.");
151 if( !FolderFlag
&& !FileContent
.size() )
152 throw BadData("Content Store item without any data.");
155 BuildField(data
, offset
, CSFC_FILENAME
, Filename
);
159 BuildField(data
, offset
, CSFC_FOLDER_FLAG
, string("folder"));
162 // write file descriptor first
163 BuildField(data
, offset
, CSFC_FILE_DESCRIPTOR
,
164 FileDescriptor
.data(), FileDescriptor
.size());
166 // a normal file... the file content is given:
168 // content in blocks of 0xfffe bytes until done
169 // all with the same ID
171 // force the size to actual, and write it first
172 uint64_t RealSize
= FileContent
.size();
173 BuildField(data
, offset
, CSFC_FILE_CONTENT
, RealSize
);
175 // write data in blocks of 0xfffe bytes
176 for( size_t foff
= 0; foff
< FileContent
.size(); ) {
177 size_t blocksize
= FileContent
.size() - foff
;
178 if( blocksize
> MAX_CONTENT_BLOCK_SIZE
)
179 blocksize
= MAX_CONTENT_BLOCK_SIZE
;
180 BuildField(data
, offset
, CSFC_FILE_CONTENT
,
181 FileContent
.data() + foff
, blocksize
);
188 // and finally save unknowns
189 UnknownsType::const_iterator
190 ub
= Unknowns
.begin(), ue
= Unknowns
.end();
191 for( ; ub
!= ue
; ub
++ ) {
192 BuildField(data
, offset
, *ub
);
195 data
.ReleaseBuffer(offset
);
198 void ContentStore::Clear()
200 RecType
= GetDefaultRecType();
206 FileDescriptor
.clear();
210 // internal variables
214 const FieldHandle
<ContentStore
>::ListT
& ContentStore::GetFieldHandles()
216 static FieldHandle
<ContentStore
>::ListT fhv
;
221 #undef CONTAINER_OBJECT_NAME
222 #define CONTAINER_OBJECT_NAME fhv
224 #undef RECORD_CLASS_NAME
225 #define RECORD_CLASS_NAME ContentStore
227 FHP(RecType
, "Record Type Code");
228 FHP(RecordId
, "Unique Record ID");
230 FHD(Filename
, "File or Folder Name", CSFC_FILENAME
, true);
231 FHD(FolderFlag
, "Folder Flag", CSFC_FOLDER_FLAG
, false);
232 FHD(FileContent
, "File Content", CSFC_FILE_CONTENT
, false);
233 FHD(FileDescriptor
, "File Descriptor", CSFC_FILE_DESCRIPTOR
, false);
235 FHP(Unknowns
, "Unknown Fields");
240 std::string
ContentStore::GetDescription() const
245 void ContentStore::Dump(std::ostream
&os
) const
247 ios_format_state
state(os
);
252 os
<< "ContentStore: 0x" << hex
<< RecordId
253 << " (" << (unsigned int)RecType
<< ")\n";
255 os
<< " Filename: " << Filename
<< endl
;
256 os
<< " Folder: " << (FolderFlag
? "yes" : "no") << endl
;
257 os
<< " BB Size: " << dec
<< FileSize
<< endl
;
258 os
<< " Actual Size: " << FileContent
.size() << endl
;
259 os
<< " Descriptor:\n"
260 << Data(FileDescriptor
.data(), FileDescriptor
.size()) << endl
;
262 << Data(FileContent
.data(), FileContent
.size()) << endl
;
264 // and finally print unknowns
268 bool ContentStore::operator<(const ContentStore
&other
) const
270 return RecordId
< other
.RecordId
;