3 /// Blackberry database record parser class for
4 /// Content Store records.
8 Copyright (C) 2010-2011, 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::BuildHeader(Data
&data
, size_t &offset
) const
140 void ContentStore::BuildFields(Data
&data
, size_t &offset
, const IConverter
*ic
) const
144 if( !Filename
.size() )
145 throw BadData("Content Store must have a name.");
147 if( !FolderFlag
&& !FileContent
.size() )
148 throw BadData("Content Store item without any data.");
151 BuildField(data
, offset
, CSFC_FILENAME
, Filename
);
155 BuildField(data
, offset
, CSFC_FOLDER_FLAG
, string("folder"));
158 // write file descriptor first
159 BuildField(data
, offset
, CSFC_FILE_DESCRIPTOR
,
160 FileDescriptor
.data(), FileDescriptor
.size());
162 // a normal file... the file content is given:
164 // content in blocks of 0xfffe bytes until done
165 // all with the same ID
167 // force the size to actual, and write it first
168 uint64_t RealSize
= FileContent
.size();
169 BuildField(data
, offset
, CSFC_FILE_CONTENT
, RealSize
);
171 // write data in blocks of 0xfffe bytes
172 for( size_t foff
= 0; foff
< FileContent
.size(); ) {
173 size_t blocksize
= FileContent
.size() - foff
;
174 if( blocksize
> MAX_CONTENT_BLOCK_SIZE
)
175 blocksize
= MAX_CONTENT_BLOCK_SIZE
;
176 BuildField(data
, offset
, CSFC_FILE_CONTENT
,
177 FileContent
.data() + foff
, blocksize
);
184 // and finally save unknowns
185 UnknownsType::const_iterator
186 ub
= Unknowns
.begin(), ue
= Unknowns
.end();
187 for( ; ub
!= ue
; ub
++ ) {
188 BuildField(data
, offset
, *ub
);
191 data
.ReleaseBuffer(offset
);
194 void ContentStore::Clear()
196 RecType
= GetDefaultRecType();
202 FileDescriptor
.clear();
206 // internal variables
210 std::string
ContentStore::GetDescription() const
215 void ContentStore::Dump(std::ostream
&os
) const
217 ios_format_state
state(os
);
222 os
<< "ContentStore: 0x" << hex
<< RecordId
223 << " (" << (unsigned int)RecType
<< ")\n";
225 os
<< " Filename: " << Filename
<< endl
;
226 os
<< " Folder: " << (FolderFlag
? "yes" : "no") << endl
;
227 os
<< " BB Size: " << dec
<< FileSize
<< endl
;
228 os
<< " Actual Size: " << FileContent
.size() << endl
;
229 os
<< " Descriptor:\n"
230 << Data(FileDescriptor
.data(), FileDescriptor
.size()) << endl
;
232 << Data(FileContent
.data(), FileContent
.size()) << endl
;
234 // and finally print unknowns
238 bool ContentStore::operator<(const ContentStore
&other
) const
240 return RecordId
< other
.RecordId
;