Main Page   Class Hierarchy   Alphabetical List   Compound List   Examples  

header.h

00001 /***************************************************************************
00002     copyright            : (C) 2002-2008 by Stefano Barbato
00003     email                : stefano@codesink.org
00004 
00005     $Id: header.h,v 1.16 2008-10-07 11:06:27 tat Exp $
00006  ***************************************************************************/
00007 #ifndef _MIMETIC_RFC822_HEADER_H_
00008 #define _MIMETIC_RFC822_HEADER_H_
00009 #include <string>
00010 #include <deque>
00011 #include <cassert>
00012 #include <functional>
00013 #include <iostream>
00014 #include <mimetic/strutils.h>
00015 #include <mimetic/utils.h>
00016 #include <mimetic/rfc822/field.h>
00017 #include <mimetic/rfc822/mailbox.h>
00018 #include <mimetic/rfc822/messageid.h>
00019 #include <mimetic/rfc822/mailboxlist.h>
00020 #include <mimetic/rfc822/addresslist.h>
00021 
00022 namespace mimetic
00023 {
00024 
00025 
00026 /// RFC822 header class object
00027 /*!
00028     Use this class to build or parse message header fields.
00029     This is a STL container so you can browse fields using iterators(see ex. below).
00030 
00031     \sa <a href="../RFC/rfc822.txt">RFC822</a>
00032  */
00033 class Rfc822Header: public std::deque<Field>
00034 {
00035 public:
00036     struct find_by_name: 
00037         public std::unary_function<const Field, bool>
00038     {
00039         find_by_name(const std::string&);
00040         bool operator()(const Field&) const;
00041     private:
00042         const istring m_name;
00043     };
00044 
00045     bool hasField(const std::string&) const;
00046     
00047     const Field& field(const std::string&) const;
00048     Field& field(const std::string&);
00049 
00050     const Mailbox& sender() const;
00051     Mailbox& sender();
00052     void sender(const Mailbox&);
00053 
00054     const MailboxList& from() const;
00055     MailboxList& from();
00056     void from(const MailboxList&);
00057 
00058     const AddressList& to() const;
00059     AddressList& to();
00060     void to(const AddressList&);
00061 
00062     const std::string& subject() const;
00063     std::string& subject();
00064     void subject(const std::string&);
00065 
00066     const AddressList& replyto() const;
00067     AddressList& replyto();
00068     void replyto(const AddressList&);
00069 
00070     const AddressList& cc() const;
00071     AddressList& cc();
00072     void cc(const AddressList&);
00073 
00074     const AddressList& bcc() const;
00075     AddressList& bcc();
00076     void bcc(const AddressList&);
00077 
00078     const MessageId& messageid() const;
00079     MessageId& messageid();
00080     void messageid(const MessageId&);
00081 protected:
00082     template<typename T>
00083     const T& getField(const std::string&) const;
00084     template<typename T>
00085     T& getField(const std::string&);
00086     template<typename T>
00087     void setField(const std::string&, const T&);
00088 };
00089 
00090 
00091 // template member functions
00092 template<typename T>
00093 const T& Rfc822Header::getField(const std::string& name) const
00094 {
00095     const_iterator it;
00096     it = find_if(begin(), end(), find_by_name(name));
00097     if(it != end())
00098     {
00099         // cast away constness
00100         Field& f = const_cast<Field&>(*it);
00101         // to be sure that it's the correct type
00102         FieldValue* pFv = f.m_pValue;
00103         if(!pFv->typeChecked())
00104         {
00105             std::string val = pFv->str();
00106             delete pFv;
00107             pFv = new T(val);
00108             f.m_pValue = pFv;
00109         }
00110         return static_cast<const T&>(*pFv);
00111     } else {
00112         static const T null;
00113         return null;
00114     }
00115 }
00116 template<typename T>
00117 T& Rfc822Header::getField(const std::string& name)
00118 {    
00119     iterator it;
00120     it = find_if(begin(), end(), find_by_name(name));
00121     if(it != end())
00122     {
00123         FieldValue* pFv = it->m_pValue;
00124         if(pFv == 0)
00125         {
00126             pFv = new T;
00127             assert(pFv);
00128             it->m_pValue = pFv;
00129         }
00130         // be sure that it's the correct type
00131         else if(!pFv->typeChecked())
00132         {
00133             std::string val = pFv->str();
00134             delete pFv;
00135             pFv = new T(val);
00136             it->m_pValue = pFv;
00137         }
00138         return static_cast<T&>(*pFv);
00139     } else {
00140         // insert and get the reference of the actual 
00141         // obj in the container, then modify its fields
00142         Field f;
00143         it = insert(end(), f);
00144         it->name(name);
00145         T* pT = new T;
00146         assert(pT);
00147         it->m_pValue = pT;
00148         assert(it->m_pValue->typeChecked());
00149         return *pT;
00150     }
00151 }
00152 
00153 template<typename T>
00154 void Rfc822Header::setField(const std::string& name, const T& obj) 
00155 {
00156     // remove if already exists
00157     iterator bit = begin(), eit = end();
00158     iterator found = find_if(bit, eit, find_by_name(name));
00159     if(found != eit)
00160         erase(found);
00161     // add field
00162     Field f;
00163     iterator it;
00164     it = insert(end(), f);
00165     it->name(name);
00166     it->m_pValue = new T(obj);
00167 }
00168 
00169 }
00170 
00171 #endif