3 /// Blackberry database record parser class for
4 /// Content Store records.
8 Copyright (C) 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.
24 #include "record-internal.h"
31 #define __DEBUG_MODE__
35 using namespace Barry::Protocol
;
40 ///////////////////////////////////////////////////////////////////////////////
43 // ContentStore field codes
44 #define CSFC_FILENAME 0x01 // may not always be a complete file,but
45 // a folder name as well
46 #define CSFC_FOLDER_FLAG 0x05
47 #define CSFC_FILE_DESCRIPTOR 0x06
48 #define CSFC_FILE_CONTENT 0x07
51 #define MAX_CONTENT_BLOCK_SIZE 0xfffe
53 ContentStore::ContentStore()
58 ContentStore::~ContentStore()
62 const unsigned char* ContentStore::ParseField(const unsigned char *begin
,
63 const unsigned char *end
,
66 const CommonField
*field
= (const CommonField
*) begin
;
68 // advance and check size
69 begin
+= COMMON_FIELD_HEADER_SIZE
+ btohs(field
->size
);
70 if( begin
> end
) // if begin==end, we are ok
73 if( !btohs(field
->size
) ) // if field has no size, something's up
79 Filename
= ParseFieldString(field
);
82 case CSFC_FOLDER_FLAG
:
85 // the CSFC_FOLDER_FLAG field seems to always
86 // contain the string "folder".. so check for it
87 string s
= ParseFieldString(field
);
94 case CSFC_FILE_CONTENT
:
96 // size already received, append data to FileContent
97 FileContent
.append((const char*)field
->u
.raw
,
101 FileSize
= btohll(field
->u
.uint64
);
105 case CSFC_FILE_DESCRIPTOR
:
106 // need to parse this further, but until then, just
107 // store it as a chunk of data
108 FileDescriptor
.assign((const char*)field
->u
.raw
,
113 // if still not handled, add to the Unknowns list
115 uf
.type
= field
->type
;
116 uf
.data
.assign((const char*)field
->u
.raw
, btohs(field
->size
));
117 Unknowns
.push_back(uf
);
119 // return new pointer for next field
123 void ContentStore::ParseHeader(const Data
&data
, size_t &offset
)
125 // no header to parse
128 void ContentStore::ParseFields(const Data
&data
, size_t &offset
, const IConverter
*ic
)
130 const unsigned char *finish
= ParseCommonFields(*this,
131 data
.GetData() + offset
, data
.GetData() + data
.GetSize(), ic
);
132 offset
+= finish
- (data
.GetData() + offset
);
135 void ContentStore::BuildHeader(Data
&data
, size_t &offset
) const
139 void ContentStore::BuildFields(Data
&data
, size_t &offset
, const IConverter
*ic
) const
143 if( !Filename
.size() )
144 throw BadData("Content Store must have a name.");
146 if( !FolderFlag
&& !FileContent
.size() )
147 throw BadData("Content Store item without any data.");
150 BuildField(data
, offset
, CSFC_FILENAME
, Filename
);
154 BuildField(data
, offset
, CSFC_FOLDER_FLAG
, string("folder"));
157 // write file descriptor first
158 BuildField(data
, offset
, CSFC_FILE_DESCRIPTOR
,
159 FileDescriptor
.data(), FileDescriptor
.size());
161 // a normal file... the file content is given:
163 // content in blocks of 0xfffe bytes until done
164 // all with the same ID
166 // force the size to actual, and write it first
167 uint64_t RealSize
= FileContent
.size();
168 BuildField(data
, offset
, CSFC_FILE_CONTENT
, RealSize
);
170 // write data in blocks of 0xfffe bytes
171 for( size_t foff
= 0; foff
< FileContent
.size(); ) {
172 size_t blocksize
= FileContent
.size() - foff
;
173 if( blocksize
> MAX_CONTENT_BLOCK_SIZE
)
174 blocksize
= MAX_CONTENT_BLOCK_SIZE
;
175 BuildField(data
, offset
, CSFC_FILE_CONTENT
,
176 FileContent
.data() + foff
, blocksize
);
183 // and finally save unknowns
184 UnknownsType::const_iterator
185 ub
= Unknowns
.begin(), ue
= Unknowns
.end();
186 for( ; ub
!= ue
; ub
++ ) {
187 BuildField(data
, offset
, *ub
);
190 data
.ReleaseBuffer(offset
);
193 void ContentStore::Clear()
195 RecType
= GetDefaultRecType();
201 FileDescriptor
.clear();
205 // internal variables
209 void ContentStore::Dump(std::ostream
&os
) const
211 ios::fmtflags oldflags
= os
.setf(ios::left
);
212 char fill
= os
.fill(' ');
214 os
<< "ContentStore: 0x" << hex
<< RecordId
215 << " (" << (unsigned int)RecType
<< ")\n";
217 os
<< " Filename: " << Filename
<< endl
;
218 os
<< " Folder: " << (FolderFlag
? "yes" : "no") << endl
;
219 os
<< " BB Size: " << dec
<< FileSize
<< endl
;
220 os
<< " Actual Size: " << FileContent
.size() << endl
;
221 os
<< " Descriptor:\n"
222 << Data(FileDescriptor
.data(), FileDescriptor
.size()) << endl
;
224 << Data(FileContent
.data(), FileContent
.size()) << endl
;
226 // and finally print unknowns
229 // cleanup the stream
234 bool ContentStore::operator<(const ContentStore
&other
) const
236 return RecordId
< other
.RecordId
;