desktop: CalEditDlg: fixed dialog title bar
[barry.git] / src / r_cstore.cc
blob2c7e430806dfed53db2945cc60c5bf10d55eb7a8
1 ///
2 /// \file r_cstore.cc
3 /// Blackberry database record parser class for
4 /// Content Store records.
5 ///
7 /*
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.
23 #include "r_cstore.h"
24 #include "record-internal.h"
25 #include "data.h"
27 #include <iostream>
28 #include <sstream>
29 #include <iomanip>
30 #include "ios_state.h"
32 #define __DEBUG_MODE__
33 #include "debug.h"
35 using namespace std;
36 using namespace Barry::Protocol;
38 namespace Barry {
41 ///////////////////////////////////////////////////////////////////////////////
42 // ContentStore class
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()
56 Clear();
59 ContentStore::~ContentStore()
63 const unsigned char* ContentStore::ParseField(const unsigned char *begin,
64 const unsigned char *end,
65 const IConverter *ic)
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
72 return begin;
74 if( !btohs(field->size) ) // if field has no size, something's up
75 return begin;
77 switch( field->type )
79 case CSFC_FILENAME:
80 Filename = ParseFieldString(field);
81 return begin;
83 case CSFC_FOLDER_FLAG:
84 FolderFlag = false;
86 // the CSFC_FOLDER_FLAG field seems to always
87 // contain the string "folder".. so check for it
88 string s = ParseFieldString(field);
89 if( s == "folder" ) {
90 FolderFlag = true;
93 return begin;
95 case CSFC_FILE_CONTENT:
96 if( FileSize ) {
97 // size already received, append data to FileContent
98 FileContent.append((const char*)field->u.raw,
99 btohs(field->size));
101 else {
102 FileSize = btohll(field->u.uint64);
104 return begin;
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,
110 btohs(field->size));
111 return begin;
114 // if still not handled, add to the Unknowns list
115 UnknownField uf;
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
121 return begin;
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
146 data.Zap();
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.");
154 // Filename
155 BuildField(data, offset, CSFC_FILENAME, Filename);
157 // Folder?
158 if( FolderFlag ) {
159 BuildField(data, offset, CSFC_FOLDER_FLAG, string("folder"));
161 else {
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:
167 // 64 bit size
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);
183 // advance
184 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();
201 RecordId = 0;
203 Filename.clear();
204 FolderFlag = false;
205 FileContent.clear();
206 FileDescriptor.clear();
208 Unknowns.clear();
210 // internal variables
211 FileSize = 0;
214 const FieldHandle<ContentStore>::ListT& ContentStore::GetFieldHandles()
216 static FieldHandle<ContentStore>::ListT fhv;
218 if( fhv.size() )
219 return 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");
237 return fhv;
240 std::string ContentStore::GetDescription() const
242 return Filename;
245 void ContentStore::Dump(std::ostream &os) const
247 ios_format_state state(os);
249 os.setf(ios::left);
250 os.fill(' ');
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;
261 os << " Content:\n"
262 << Data(FileContent.data(), FileContent.size()) << endl;
264 // and finally print unknowns
265 os << Unknowns;
268 bool ContentStore::operator<(const ContentStore &other) const
270 return RecordId < other.RecordId;
273 } // namespace Barry