vjournal.cc

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-2011, 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()
00036         : m_gJournalData(0)
00037 {
00038 }
00039 
00040 vJournal::~vJournal()
00041 {
00042         if( m_gJournalData ) {
00043                 g_free(m_gJournalData);
00044         }
00045 }
00046 
00047 bool vJournal::HasMultipleVJournals() const
00048 {
00049         int count = 0;
00050         b_VFormat *format = const_cast<b_VFormat*>(Format());
00051         GList *attrs = format ? b_vformat_get_attributes(format) : 0;
00052         for( ; attrs; attrs = attrs->next ) {
00053                 b_VFormatAttribute *attr = (b_VFormatAttribute*) attrs->data;
00054                 if( strcasecmp(b_vformat_attribute_get_name(attr), "BEGIN") == 0 &&
00055                     strcasecmp(b_vformat_attribute_get_nth_value(attr, 0), "VJOURNAL") == 0 )
00056                 {
00057                         count++;
00058                 }
00059         }
00060         return count > 1;
00061 }
00062 
00063 
00064 // Main conversion routine for converting from Barry::Memo to
00065 // a vJournal string of data.
00066 const std::string& vJournal::ToMemo(const Barry::Memo &memo)
00067 {
00068 //      Trace trace("vJournal::ToMemo");
00069         std::ostringstream oss;
00070         memo.Dump(oss);
00071 //      trace.logf("ToMemo, initial Barry record: %s", oss.str().c_str());
00072 
00073         // start fresh
00074         Clear();
00075         SetFormat( b_vformat_new() );
00076         if( !Format() )
00077                 throw ConvertError("resource error allocating vformat");
00078 
00079         // store the Barry object we're working with
00080         m_BarryMemo = memo;
00081 
00082         // begin building vJournal data
00083         AddAttr(NewAttr("PRODID", "-//OpenSync//NONSGML Barry Memo Record//EN"));
00084         AddAttr(NewAttr("BEGIN", "VJOURNAL"));
00085         AddAttr(NewAttr("SEQUENCE", "0"));
00086         AddAttr(NewAttr("SUMMARY", memo.Title.c_str()));
00087         AddAttr(NewAttr("DESCRIPTION", memo.Body.c_str()));
00088         AddAttr(NewAttr("CATEGORIES", ToStringList(memo.Categories).c_str()));
00089 
00090 
00091         // FIXME - add a truly globally unique "UID" string?
00092 
00093         AddAttr(NewAttr("END", "VJOURNAL"));
00094 
00095         // generate the raw VJOURNAL data
00096         m_gJournalData = b_vformat_to_string(Format(), VFORMAT_NOTE);
00097         m_vJournalData = m_gJournalData;
00098 
00099 //      trace.logf("ToMemo, resulting vjournal data: %s", m_vJournalData.c_str());
00100         return m_vJournalData;
00101 }
00102 
00103 // Main conversion routine for converting from vJournal data string
00104 // to a Barry::Memo object.
00105 const Barry::Memo& vJournal::ToBarry(const char *vjournal, uint32_t RecordId)
00106 {
00107         using namespace std;
00108 
00109 //      Trace trace("vJournal::ToBarry");
00110 //      trace.logf("ToBarry, working on vmemo data: %s", vjournal);
00111 
00112         // we only handle vJournal data with one vmemo block
00113         if( HasMultipleVJournals() )
00114                 throw ConvertError("vCalendar data contains more than one VJOURNAL block, unsupported");
00115 
00116         // start fresh
00117         Clear();
00118 
00119         // store the vJournal raw data
00120         m_vJournalData = vjournal;
00121 
00122         // create format parser structures
00123         SetFormat( b_vformat_new_from_string(vjournal) );
00124         if( !Format() )
00125                 throw ConvertError("resource error allocating vjournal");
00126 
00127         string title = GetAttr("SUMMARY", "/vjournal");
00128 //      trace.logf("SUMMARY attr retrieved: %s", title.c_str());
00129         if( title.size() == 0 ) {
00130                 title = "<blank subject>";
00131 //              trace.logf("ERROR: bad data, blank SUMMARY: %s", vjournal);
00132         }
00133 
00134         string body = GetAttr("DESCRIPTION", "/vjournal");
00135 //      trace.logf("DESCRIPTION attr retrieved: %s", body.c_str());
00136 
00137 
00138         //
00139         // Now, run checks and convert into Barry object
00140         //
00141 
00142 
00143         Barry::Memo &rec = m_BarryMemo;
00144         rec.SetIds(Barry::Memo::GetDefaultRecType(), RecordId);
00145 
00146         rec.Title = title;
00147         rec.Body = body;
00148         rec.Categories = GetValueVector("CATEGORIES","/vjournal");
00149 
00150         std::ostringstream oss;
00151         m_BarryMemo.Dump(oss);
00152 //      trace.logf("ToBarry, resulting Barry record: %s", oss.str().c_str());
00153         return m_BarryMemo;
00154 }
00155 
00156 // Transfers ownership of m_gMemoData to the caller.
00157 char* vJournal::ExtractVJournal()
00158 {
00159         char *ret = m_gJournalData;
00160         m_gJournalData = 0;
00161         return ret;
00162 }
00163 
00164 void vJournal::Clear()
00165 {
00166         vBase::Clear();
00167         m_vJournalData.clear();
00168         m_BarryMemo.Clear();
00169 
00170         if( m_gJournalData ) {
00171                 g_free(m_gJournalData);
00172                 m_gJournalData = 0;
00173         }
00174 }
00175 
00176 }} // namespace Barry::Sync
00177