r_folder.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       r_folder.cc
00003 ///             Record parsing class for the folders database.
00004 ///
00005 
00006 /*
00007     Copyright (C) 2005-2012, Net Direct Inc. (http://www.netdirect.ca/)
00008     Copyright (C) 2007, Brian Edginton
00009 
00010     This program is free software; you can redistribute it and/or modify
00011     it under the terms of the GNU General Public License as published by
00012     the Free Software Foundation; either version 2 of the License, or
00013     (at your option) any later version.
00014 
00015     This program is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00018 
00019     See the GNU General Public License in the COPYING file at the
00020     root directory of this project for more details.
00021 */
00022 
00023 #include "r_folder.h"
00024 #include "record-internal.h"
00025 #include "protostructs.h"
00026 #include "data.h"
00027 #include "time.h"
00028 #include "debug.h"
00029 #include "iconv.h"
00030 #include <iostream>
00031 #include <sstream>
00032 #include <iomanip>
00033 #include "ios_state.h"
00034 
00035 using namespace std;
00036 using namespace Barry::Protocol;
00037 
00038 namespace Barry {
00039 
00040 
00041 ///////////////////////////////////////////////////////////////////////////////
00042 // Folder Class, static members
00043 
00044 //
00045 // Note! These functions currently only pass the same values through.
00046 //       In actuality, these are technically two different values:
00047 //       one on the raw protocol side, and the other part of the
00048 //       guaranteed Barry API.  If the Blackberry ever changes the
00049 //       meanings for these codes, do the translation here.
00050 //
00051 
00052 Folder::FolderType Folder::TypeProto2Rec(uint8_t t)
00053 {
00054         return (FolderType)t;
00055 }
00056 
00057 uint8_t Folder::TypeRec2Proto(FolderType t)
00058 {
00059         return t;
00060 }
00061 
00062 
00063 
00064 ///////////////////////////////////////////////////////////////////////////////
00065 // Folder Class
00066 
00067 // Folder Field Codes
00068 
00069 #define FFC_NUMBER      0x0a
00070 #define FFC_LEVEL       0x0b
00071 #define FFC_NAME        0x0c
00072 #define FFC_ADDRESS1    0x0d
00073 #define FFC_ADDRESS2    0x0e
00074 #define FFC_TYPE        0x0f
00075 #define FFC_END         0xffff
00076 
00077 #define INVALID         -1
00078 
00079 #define SEPARATOR       0x2f
00080 #define ROOT_SEPARATOR  0x3a
00081 
00082 static FieldLink<Folder> FolderFieldLinks[] = {
00083     { FFC_NAME, "FolderName",  0, 0, &Folder::Name, 0, 0, 0, 0, true },
00084     { FFC_END,  "End of List", 0, 0, 0, 0, 0, 0, 0, false },
00085 };
00086 
00087 Folder::Folder()
00088 {
00089         Clear();
00090 }
00091 
00092 
00093 Folder::~Folder()
00094 {
00095 }
00096 
00097 const unsigned char* Folder::ParseField(const unsigned char *begin,
00098                                         const unsigned char *end,
00099                                         const IConverter *ic)
00100 {
00101         const CommonField *field = (const CommonField *) begin;
00102 
00103         // advance and check size
00104         begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
00105         if( begin > end )       // if begin==end, we are ok
00106                 return begin;
00107 
00108         if( !btohs(field->size) )   // if field has no size, something's up
00109                 return begin;
00110 
00111         // cycle through the type table
00112         for(    FieldLink<Folder> *b = FolderFieldLinks;
00113                 b->type != FFC_END;
00114                 b++ )
00115         {
00116                 if( b->type == field->type ) {
00117                         if( b->strMember ) {
00118                                 std::string &s = this->*(b->strMember);
00119                                 s = ParseFieldString(field);
00120                                 if( b->iconvNeeded && ic )
00121                                         s = ic->FromBB(s);
00122                                 return begin;   // done!
00123                         }
00124                         else if( b->timeMember && btohs(field->size) == 4 ) {
00125                                 TimeT &t = this->*(b->timeMember);
00126                                 t.Time= min2time(field->u.min1900);
00127                                 return begin;
00128                         }
00129                 }
00130         }
00131         // handle special cases
00132         switch( field->type )
00133         {
00134         case FFC_TYPE:
00135                 Type = TypeProto2Rec(field->u.raw[0]);
00136                 return begin;
00137         case FFC_NUMBER:
00138                 Number = field->u.raw[0];       // two's complement
00139                 return begin;
00140         case FFC_LEVEL:
00141                 Level = field->u.raw[0];
00142                 return begin;
00143         }
00144 
00145         // if still not handled, add to the Unknowns list
00146         UnknownField uf;
00147         uf.type = field->type;
00148         uf.data.assign((const char*)field->u.raw, btohs(field->size));
00149         Unknowns.push_back(uf);
00150 
00151         // return new pointer for next field
00152         return begin;
00153 }
00154 
00155 void Folder::ParseHeader(const Data &data, size_t &offset)
00156 {
00157         // no header in Folder records
00158 }
00159 
00160 void Folder::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
00161 {
00162         const unsigned char *finish = ParseCommonFields(*this,
00163                 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
00164         offset += finish - (data.GetData() + offset);
00165 }
00166 
00167 void Folder::Validate() const
00168 {
00169 }
00170 
00171 void Folder::BuildHeader(Data &data, size_t &offset) const
00172 {
00173         // not yet implemented
00174 }
00175 
00176 void Folder::BuildFields(Data &data, size_t &offset, const IConverter *ic) const
00177 {
00178         // not yet implemented
00179 }
00180 
00181 void Folder::Clear()
00182 {
00183         RecType = GetDefaultRecType();
00184         RecordId = 0;
00185 
00186         Name.clear();
00187         Number = 0;
00188         Level = 0;
00189 
00190         Type = FolderSubtree;
00191 
00192         Unknowns.clear();
00193 }
00194 
00195 const FieldHandle<Folder>::ListT& Folder::GetFieldHandles()
00196 {
00197         static FieldHandle<Folder>::ListT fhv;
00198 
00199         if( fhv.size() )
00200                 return fhv;
00201 
00202 #undef CONTAINER_OBJECT_NAME
00203 #define CONTAINER_OBJECT_NAME fhv
00204 
00205 #undef RECORD_CLASS_NAME
00206 #define RECORD_CLASS_NAME Folder
00207 
00208         FHP(RecType, "Record Type Code");
00209         FHP(RecordId, "Unique Record ID");
00210 
00211         FHD(Name, "Folder Name", FFC_NAME, true);
00212         FHD(Number, "Order Number", FFC_NUMBER, false);
00213         FHD(Level, "Folder Level", FFC_LEVEL, false);
00214 
00215         FHE(ft, FolderType, Type, "Folder Type");
00216         FHE_CONST(ft, FolderSubtree, "Subtree");
00217         FHE_CONST(ft, FolderDeleted, "Deleted");
00218         FHE_CONST(ft, FolderInbox, "Inbox");
00219         FHE_CONST(ft, FolderOutbox, "Outbox");
00220         FHE_CONST(ft, FolderSent, "Sent");
00221         FHE_CONST(ft, FolderOther, "Other");
00222         FHE_CONST(ft, FolderDraft, "Draft");
00223 
00224 // Not yet implemented
00225 //      FHE(fst, FolderStatusType, ..., "Folder Status");
00226 //      FHE_CONST(fst, FolderOrphan, "Orphan");
00227 //      FHE_CONST(fst, FolderUnfiled, "Unfiled");
00228 //      FHE_CONST(fst, FolderFiled, "Filed");
00229 
00230         FHP(Unknowns, "Unknown Fields");
00231 
00232         return fhv;
00233 }
00234 
00235 std::string Folder::GetDescription() const
00236 {
00237         ostringstream oss;
00238         oss << Name << " (" << Level << ")";
00239         return oss.str();
00240 }
00241 
00242 void Folder::Dump(std::ostream &os) const
00243 {
00244         ios_format_state state(os);
00245 
00246         static const char *FolderTypeString[] = { "Subtree", "Deleted", "Inbox", "Outbox", "Sent", "Other"};
00247 //      static const char *FolderStatusString[] = { "Orphan", "Unfiled", "Filed" };
00248 
00249         os << "Folder Records\n\n";
00250         os << "Folder Name: " << Name << "\n";
00251         os << "Folder Type: ";
00252         if( Type < FolderDraft )
00253                 os << FolderTypeString[Type] << "\n";
00254         else if( Type == FolderDraft )
00255                 os << "Draft\n";
00256         else
00257                 os << "Unknown (" << std::hex << Type << ")\n";
00258         os << "Folder Number: " << std::dec << Number << "\n";
00259         os << "Folder Level: " << std::dec << Level << "\n";
00260         os << "\n";
00261         os << Unknowns;
00262         os << "\n\n";
00263 }
00264 
00265 } // namespace Barry
00266