menu: added new Keywords tag to .desktop files
[barry.git] / src / r_cstore.cc
blobe6eb94d19ea1799437744e282fe1d86ba3343bf7
1 ///
2 /// \file r_cstore.cc
3 /// Blackberry database record parser class for
4 /// Content Store records.
5 ///
7 /*
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.
23 #include "i18n.h"
24 #include "r_cstore.h"
25 #include "record-internal.h"
26 #include "data.h"
28 #include <iostream>
29 #include <sstream>
30 #include <iomanip>
31 #include "ios_state.h"
33 #define __DEBUG_MODE__
34 #include "debug.h"
36 using namespace std;
37 using namespace Barry::Protocol;
39 namespace Barry {
42 ///////////////////////////////////////////////////////////////////////////////
43 // ContentStore class
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()
57 Clear();
60 ContentStore::~ContentStore()
64 const unsigned char* ContentStore::ParseField(const unsigned char *begin,
65 const unsigned char *end,
66 const IConverter *ic)
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
73 return begin;
75 if( !btohs(field->size) ) // if field has no size, something's up
76 return begin;
78 switch( field->type )
80 case CSFC_FILENAME:
81 Filename = ParseFieldString(field);
82 return begin;
84 case CSFC_FOLDER_FLAG:
85 FolderFlag = false;
87 // the CSFC_FOLDER_FLAG field seems to always
88 // contain the string "folder".. so check for it
89 string s = ParseFieldString(field);
90 if( s == "folder" ) {
91 FolderFlag = true;
94 return begin;
96 case CSFC_FILE_CONTENT:
97 if( FileSize ) {
98 // size already received, append data to FileContent
99 FileContent.append((const char*)field->u.raw,
100 btohs(field->size));
102 else {
103 FileSize = btohll(field->u.uint64);
105 return begin;
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,
111 btohs(field->size));
112 return begin;
115 // if still not handled, add to the Unknowns list
116 UnknownField uf;
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
122 return begin;
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
147 data.Zap();
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."));
155 // Filename
156 BuildField(data, offset, CSFC_FILENAME, Filename);
158 // Folder?
159 if( FolderFlag ) {
160 BuildField(data, offset, CSFC_FOLDER_FLAG, string("folder"));
162 else {
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:
168 // 64 bit size
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);
184 // advance
185 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();
202 RecordId = 0;
204 Filename.clear();
205 FolderFlag = false;
206 FileContent.clear();
207 FileDescriptor.clear();
209 Unknowns.clear();
211 // internal variables
212 FileSize = 0;
215 const FieldHandle<ContentStore>::ListT& ContentStore::GetFieldHandles()
217 static FieldHandle<ContentStore>::ListT fhv;
219 if( fhv.size() )
220 return 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"));
238 return fhv;
241 std::string ContentStore::GetDescription() const
243 return Filename;
246 void ContentStore::Dump(std::ostream &os) const
248 ios_format_state state(os);
250 os.setf(ios::left);
251 os.fill(' ');
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
266 os << Unknowns;
269 bool ContentStore::operator<(const ContentStore &other) const
271 return RecordId < other.RecordId;
274 } // namespace Barry