mimeio.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       mimeio.cc
00003 ///             Storage, parser, builder classes for MIME objects
00004 ///             (vcard, vevent, vtodo, vjournal)
00005 ///
00006 
00007 /*
00008     Copyright (C) 2010-2012, Net Direct Inc. (http://www.netdirect.ca/)
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 "mimeio.h"
00024 #include "vcard.h"
00025 #include "vevent.h"
00026 #include "vtodo.h"
00027 #include "vjournal.h"
00028 #include <iostream>
00029 #include <fstream>
00030 #include <strings.h>
00031 
00032 using namespace std;
00033 
00034 namespace Barry {
00035 
00036 MimeBuilder::MimeBuilder(const std::string &filename)
00037         : m_ifs( new std::ifstream(filename.c_str()) )
00038         , m_is(*m_ifs)
00039 {
00040 }
00041 
00042 MimeBuilder::MimeBuilder(std::istream &is)
00043         : m_is(is)
00044 {
00045 }
00046 
00047 bool MimeBuilder::BuildRecord(DBData &data, size_t &offset,
00048                                 const IConverter *ic)
00049 {
00050         string vrec;
00051         vector<string> types;
00052         while( ReadMimeRecord(m_is, vrec, types) ) {
00053                 if( !vrec.size() ) {
00054                         // end of file
00055                         return false;
00056                 }
00057                 else if( IsMember(Sync::vCard::GetVName(), types) ) {
00058                         Sync::vCard vcard;
00059                         SetDBData(vcard.ToBarry(vrec.c_str(), 0),
00060                                 data, offset, ic);
00061                         return true;
00062                 }
00063                 else if( IsMember(Sync::vCalendar::GetVName(), types) ) {
00064                         Sync::vTimeConverter vtc;
00065                         Sync::vCalendar vcal(vtc);
00066                         SetDBData(vcal.ToBarry(vrec.c_str(), 0),
00067                                 data, offset, ic);
00068                         return true;
00069                 }
00070                 else if( IsMember(Sync::vTodo::GetVName(), types) ) {
00071                         Sync::vTimeConverter vtc;
00072                         Sync::vTodo vtodo(vtc);
00073                         SetDBData(vtodo.ToBarry(vrec.c_str(), 0),
00074                                 data, offset, ic);
00075                         return true;
00076                 }
00077                 else if( IsMember(Sync::vJournal::GetVName(), types) ) {
00078                         Sync::vTimeConverter vtc;
00079                         Sync::vJournal vjournal(vtc);
00080                         SetDBData(vjournal.ToBarry(vrec.c_str(), 0),
00081                                 data, offset, ic);
00082                         return true;
00083                 }
00084                 else {
00085                         // read the next one
00086                 }
00087         }
00088 
00089         // end of file
00090         return false;
00091 }
00092 
00093 bool MimeBuilder::FetchRecord(DBData &data, const IConverter *ic)
00094 {
00095         size_t offset = 0;
00096         return BuildRecord(data, offset, ic);
00097 }
00098 
00099 bool MimeBuilder::EndOfFile() const
00100 {
00101         return !m_is;
00102 }
00103 
00104 // return false at end of file, true if a record was read
00105 bool MimeBuilder::ReadMimeRecord(std::istream &is, std::string &vrec,
00106                                 std::vector<std::string> &types)
00107 {
00108         vrec.clear();
00109         types.clear();
00110 
00111         string line;
00112 
00113         // ignore whitespace
00114         while( getline(is, line) ) {
00115                 if( strcasecmp(line.substr(0, 6).c_str(), "BEGIN:") == 0 ) {
00116                         vrec += line;
00117                         vrec += "\n";
00118                         types.push_back(line.substr(6));
00119                         break;
00120                 }
00121         }
00122 
00123         if( !vrec.size() )
00124                 return false;
00125 
00126         // load until end
00127         int count = 0;
00128         while( getline(is, line) ) {
00129                 // end on blank lines
00130                 if( !line.size() )
00131                         return true;
00132 
00133                 vrec += line;
00134                 vrec += "\n";
00135 
00136                 // pick up innermost BEGIN line
00137                 if( strcasecmp(line.substr(0, 6).c_str(), "BEGIN:") == 0 ) {
00138                         string type = line.substr(6);
00139                         while( type.size() && type[type.size()-1] == '\r' ) {
00140                                 type = type.substr(0, type.size()-1);
00141                         }
00142                         types.push_back(type);
00143                 }
00144 
00145                 // place an upper limit on the number of lines...
00146                 // since a MIME data block shouldn't be more than
00147                 // a few pages of lines!
00148                 count++;
00149                 if( count > 200 )
00150                         return false;
00151         }
00152         // assume that end of file is the same as "blank line"
00153         return true;
00154 }
00155 
00156 bool MimeBuilder::IsMember(const std::string &item,
00157                         const std::vector<std::string> &types)
00158 {
00159         std::vector<std::string>::const_iterator i = types.begin();
00160         for( ; i != types.end(); ++i ) {
00161                 if( strcasecmp(i->c_str(), item.c_str()) == 0 )
00162                         return true;
00163         }
00164         return false;
00165 }
00166 
00167 } // namespace Barry
00168