vjournal.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       vjournal.cc
00003 ///             Conversion routines for vjournals (VCALENDAR, etc)
00004 ///
00005 
00006 /*
00007     Copyright (C) 2008-2009, Nicolas VIVIEN
00008     Copyright (C) 2006-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 "vjournal.h"
00024 //#include "trace.h"
00025 #include <stdint.h>
00026 #include <glib.h>
00027 #include <strings.h>
00028 #include <sstream>
00029 
00030 namespace Barry { namespace Sync {
00031 
00032 //////////////////////////////////////////////////////////////////////////////
00033 // vJournal
00034 
00035 vJournal::vJournal(vTimeConverter &vtc)
00036         : m_vtc(vtc)
00037         , m_gJournalData(0)
00038 {
00039 }
00040 
00041 vJournal::~vJournal()
00042 {
00043         if( m_gJournalData ) {
00044                 g_free(m_gJournalData);
00045         }
00046 }
00047 
00048 bool vJournal::HasMultipleVJournals() const
00049 {
00050         int count = 0;
00051         b_VFormat *format = const_cast<b_VFormat*>(Format());
00052         GList *attrs = format ? b_vformat_get_attributes(format) : 0;
00053         for( ; attrs; attrs = attrs->next ) {
00054                 b_VFormatAttribute *attr = (b_VFormatAttribute*) attrs->data;
00055                 if( strcasecmp(b_vformat_attribute_get_name(attr), "BEGIN") == 0 &&
00056                     strcasecmp(b_vformat_attribute_get_nth_value(attr, 0), "VJOURNAL") == 0 )
00057                 {
00058                         count++;
00059                 }
00060         }
00061         return count > 1;
00062 }
00063 
00064 
00065 // Main conversion routine for converting from Barry::Memo to
00066 // a vJournal string of data.
00067 const std::string& vJournal::ToMemo(const Barry::Memo &memo)
00068 {
00069 //      Trace trace("vJournal::ToMemo");
00070         std::ostringstream oss;
00071         memo.Dump(oss);
00072 //      trace.logf("ToMemo, initial Barry record: %s", oss.str().c_str());
00073 
00074         // start fresh
00075         Clear();
00076         SetFormat( b_vformat_new() );
00077         if( !Format() )
00078                 throw ConvertError("resource error allocating vformat");
00079 
00080         // store the Barry object we're working with
00081         m_BarryMemo = memo;
00082 
00083         // RFC section 4.8.7.2 requires DTSTAMP in all VEVENT, VTODO,
00084         // VJOURNAL, and VFREEBUSY calendar components, and it must be
00085         // in UTC.  DTSTAMP holds the timestamp of when the iCal object itself
00086         // was created, not when the object was created in the device or app.
00087         // So, find out what time it is "now".
00088         time_t now = time(NULL);
00089 
00090         // begin building vJournal data
00091         AddAttr(NewAttr("PRODID", "-//OpenSync//NONSGML Barry Memo Record//EN"));
00092         AddAttr(NewAttr("BEGIN", "VJOURNAL"));
00093         AddAttr(NewAttr("DTSTAMP", m_vtc.unix2vtime(&now).c_str())); // see note above
00094         AddAttr(NewAttr("SEQUENCE", "0"));
00095         AddAttr(NewAttr("SUMMARY", memo.Title.c_str()));
00096         AddAttr(NewAttr("DESCRIPTION", memo.Body.c_str()));
00097         AddAttr(NewAttr("CATEGORIES", ToStringList(memo.Categories).c_str()));
00098 
00099 
00100         // FIXME - add a truly globally unique "UID" string?
00101 
00102         AddAttr(NewAttr("END", "VJOURNAL"));
00103 
00104         // generate the raw VJOURNAL data
00105         m_gJournalData = b_vformat_to_string(Format(), VFORMAT_NOTE);
00106         m_vJournalData = m_gJournalData;
00107 
00108 //      trace.logf("ToMemo, resulting vjournal data: %s", m_vJournalData.c_str());
00109         return m_vJournalData;
00110 }
00111 
00112 // Main conversion routine for converting from vJournal data string
00113 // to a Barry::Memo object.
00114 const Barry::Memo& vJournal::ToBarry(const char *vjournal, uint32_t RecordId)
00115 {
00116         using namespace std;
00117 
00118 //      Trace trace("vJournal::ToBarry");
00119 //      trace.logf("ToBarry, working on vmemo data: %s", vjournal);
00120 
00121         // we only handle vJournal data with one vmemo block
00122         if( HasMultipleVJournals() )
00123                 throw ConvertError("vCalendar data contains more than one VJOURNAL block, unsupported");
00124 
00125         // start fresh
00126         Clear();
00127 
00128         // store the vJournal raw data
00129         m_vJournalData = vjournal;
00130 
00131         // create format parser structures
00132         SetFormat( b_vformat_new_from_string(vjournal) );
00133         if( !Format() )
00134                 throw ConvertError("resource error allocating vjournal");
00135 
00136         string title = GetAttr("SUMMARY", "/vjournal");
00137 //      trace.logf("SUMMARY attr retrieved: %s", title.c_str());
00138         if( title.size() == 0 ) {
00139                 title = "<blank subject>";
00140 //              trace.logf("ERROR: bad data, blank SUMMARY: %s", vjournal);
00141         }
00142 
00143         string body = GetAttr("DESCRIPTION", "/vjournal");
00144 //      trace.logf("DESCRIPTION attr retrieved: %s", body.c_str());
00145 
00146 
00147         //
00148         // Now, run checks and convert into Barry object
00149         //
00150 
00151 
00152         Barry::Memo &rec = m_BarryMemo;
00153         rec.SetIds(Barry::Memo::GetDefaultRecType(), RecordId);
00154 
00155         rec.Title = title;
00156         rec.Body = body;
00157         rec.Categories = GetValueVector("CATEGORIES","/vjournal");
00158 
00159         std::ostringstream oss;
00160         m_BarryMemo.Dump(oss);
00161 //      trace.logf("ToBarry, resulting Barry record: %s", oss.str().c_str());
00162         return m_BarryMemo;
00163 }
00164 
00165 // Transfers ownership of m_gMemoData to the caller.
00166 char* vJournal::ExtractVJournal()
00167 {
00168         char *ret = m_gJournalData;
00169         m_gJournalData = 0;
00170         return ret;
00171 }
00172 
00173 void vJournal::Clear()
00174 {
00175         vBase::Clear();
00176         m_vJournalData.clear();
00177         m_BarryMemo.Clear();
00178 
00179         if( m_gJournalData ) {
00180                 g_free(m_gJournalData);
00181                 m_gJournalData = 0;
00182         }
00183 }
00184 
00185 }} // namespace Barry::Sync
00186