libkmime

kmime_mdn.cpp

00001 /*  -*- c++ -*-
00002     kmime_mdn.cpp
00003 
00004     This file is part of KMime, the KDE internet mail/usenet news message library.
00005     Copyright (c) 2002 Marc Mutz <mutz@kde.org>
00006 
00007     KMime is free software; you can redistribute it and/or modify it
00008     under the terms of the GNU General Public License, version 2, as
00009     published by the Free Software Foundation.
00010 
00011     KMime is distributed in the hope that it will be useful, but
00012     WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this library; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019 
00020     In addition, as a special exception, the copyright holders give
00021     permission to link the code of this library with any edition of
00022     the Qt library by Trolltech AS, Norway (or with modified versions
00023     of Qt that use the same license as Qt), and distribute linked
00024     combinations including the two.  You must obey the GNU General
00025     Public License in all respects for all of the code used other than
00026     Qt.  If you modify this file, you may extend this exception to
00027     your version of the file, but you are not obligated to do so.  If
00028     you do not wish to do so, delete this exception statement from
00029     your version.
00030 */
00031 
00032 #include "kmime_mdn.h"
00033 
00034 #include "kmime_version.h"
00035 #include "kmime_util.h"
00036 
00037 #include <klocale.h>
00038 #include <kdebug.h>
00039 
00040 #include <qcstring.h>
00041 
00042 #include <unistd.h> // gethostname
00043 
00044 namespace KMime {
00045 
00046 namespace MDN {
00047 
00048   static const struct {
00049     DispositionType dispositionType;
00050     const char * string;
00051     const char * description;
00052   } dispositionTypes[] = {
00053     { Displayed, "displayed",
00054       I18N_NOOP("The message sent on ${date} to ${to} with subject "
00055         "\"${subject}\" has been displayed. This is no guarantee that "
00056         "the message has been read or understood.") },
00057     { Deleted, "deleted",
00058       I18N_NOOP("The message sent on ${date} to ${to} with subject "
00059         "\"${subject}\" has been deleted unseen. This is no guarantee "
00060         "that the message will not be \"undeleted\" and nonetheless "
00061         "read later on.") },
00062     { Dispatched, "dispatched",
00063       I18N_NOOP("The message sent on ${date} to ${to} with subject "
00064         "\"${subject}\" has been dispatched. This is no guarantee "
00065         "that the message will not be read later on.") },
00066     { Processed, "processed",
00067       I18N_NOOP("The message sent on ${date} to ${to} with subject "
00068         "\"${subject}\" has been processed by some automatic means.") },
00069     { Denied, "denied",
00070       I18N_NOOP("The message sent on ${date} to ${to} with subject "
00071         "\"${subject}\" has been acted upon. The sender does not wish "
00072         "to disclose more details to you than that.") },
00073     { Failed, "failed",
00074       I18N_NOOP("Generation of a Message Disposition Notification for the "
00075         "message sent on ${date} to ${to} with subject \"${subject}\" "
00076         "failed. Reason is given in the Failure: header field below.") }
00077   };
00078 
00079   static const int numDispositionTypes
00080            = sizeof dispositionTypes / sizeof *dispositionTypes;
00081 
00082 
00083   static const char * stringFor( DispositionType d ) {
00084     for ( int i = 0 ; i < numDispositionTypes ; ++i )
00085       if ( dispositionTypes[i].dispositionType == d )
00086     return dispositionTypes[i].string;
00087     return 0;
00088   }
00089 
00090 
00091   //
00092   // disposition-modifier
00093   //
00094   static const struct {
00095     DispositionModifier dispositionModifier;
00096     const char * string;
00097   } dispositionModifiers[] = {
00098     { Error, "error" },
00099     { Warning, "warning" },
00100     { Superseded, "superseded" },
00101     { Expired, "expired" },
00102     { MailboxTerminated, "mailbox-terminated" }
00103   };
00104 
00105   static const int numDispositionModifiers
00106        = sizeof dispositionModifiers / sizeof * dispositionModifiers;
00107 
00108 
00109   static const char * stringFor( DispositionModifier m ) {
00110     for ( int i = 0 ; i < numDispositionModifiers ; ++i )
00111       if ( dispositionModifiers[i].dispositionModifier == m )
00112     return dispositionModifiers[i].string;
00113     return 0;
00114   }
00115 
00116   //
00117   // action-mode (part of disposition-mode)
00118   //
00119 
00120   static const struct {
00121     ActionMode actionMode;
00122     const char * string;
00123   } actionModes[] = {
00124     { ManualAction, "manual-action" },
00125     { AutomaticAction, "automatic-action" }
00126   };
00127 
00128   static const int numActionModes = sizeof actionModes / sizeof *actionModes;
00129 
00130   static const char * stringFor( ActionMode a ) {
00131     for ( int i = 0 ; i < numActionModes ; ++i )
00132       if ( actionModes[i].actionMode == a )
00133     return actionModes[i].string;
00134     return 0;
00135   }
00136 
00137 
00138   //
00139   // sending-mode (part of disposition-mode)
00140   //
00141 
00142   static const struct {
00143     SendingMode sendingMode;
00144     const char * string;
00145   } sendingModes[] = {
00146     { SentManually, "MDN-sent-manually" },
00147     { SentAutomatically, "MDN-sent-automatically" }
00148   };
00149 
00150   static const int numSendingModes = sizeof sendingModes / sizeof *sendingModes;
00151 
00152   static const char * stringFor( SendingMode s ) {
00153     for ( int i = 0 ; i < numSendingModes ; ++i )
00154       if ( sendingModes[i].sendingMode == s )
00155     return sendingModes[i].string;
00156     return 0;
00157   }
00158 
00159   static QCString dispositionField( DispositionType d, ActionMode a, SendingMode s,
00160                     const QValueList<DispositionModifier> & m ) {
00161 
00162     // mandatory parts: Disposition: foo/baz; bar
00163     QCString result = "Disposition: ";
00164     result += stringFor( a );
00165     result += "/";
00166     result += stringFor( s );
00167     result += "; ";
00168     result += stringFor( d );
00169 
00170     // optional parts: Disposition: foo/baz; bar/mod1,mod2,mod3
00171     bool first = true;
00172     for ( QValueList<DispositionModifier>::const_iterator mt = m.begin() ;
00173       mt != m.end() ; ++mt ) {
00174       if ( first ) {
00175     result += "/";
00176     first = false;
00177       } else {
00178     result += ",";
00179       }
00180       result += stringFor( *mt );
00181     }
00182     return result + "\n";
00183   }
00184 
00185   static QCString finalRecipient( const QString & recipient ) {
00186     if ( recipient.isEmpty() )
00187       return QCString();
00188     else
00189       return "Final-Recipient: rfc822; "
00190     + encodeRFC2047String( recipient, "utf-8" ) + "\n";
00191   }
00192 
00193   static QCString orginalRecipient( const QCString & recipient ) {
00194     if ( recipient.isEmpty() )
00195       return QCString();
00196     else
00197       return "Original-Recipient: " + recipient + "\n";
00198   }
00199 
00200   static QCString originalMessageID( const QCString & msgid ) {
00201     if ( msgid.isEmpty() )
00202       return QCString();
00203     else
00204       return "Original-Message-ID: " + msgid + "\n";
00205   }
00206 
00207   static QCString reportingUAField() {
00208     char hostName[256];
00209     if ( gethostname( hostName, 255 ) )
00210       hostName[0] = '\0'; // gethostname failed: pretend empty string
00211     else
00212       hostName[255] = '\0'; // gethostname may have returned 255 chars (man page)
00213     return QCString("Reporting-UA: ") + hostName
00214       + "; KMime " KMIME_VERSION_STRING "\n";
00215   }
00216 
00217   QCString dispositionNotificationBodyContent( const QString & r,
00218                            const QCString & o,
00219                            const QCString & omid,
00220                            DispositionType d,
00221                            ActionMode a,
00222                            SendingMode s,
00223                            const QValueList<DispositionModifier> & m,
00224                            const QString & special )
00225   {
00226     // in Perl: chomp(special) 
00227     QString spec;
00228     if ( special.endsWith("\n") )
00229       spec = special.left( special.length() - 1 );
00230     else
00231       spec = special;
00232 
00233     // std headers:
00234     QCString result = reportingUAField();
00235     result += orginalRecipient( o );
00236     result += finalRecipient( r );
00237     result += originalMessageID( omid );
00238     result += dispositionField( d, a, s, m );
00239 
00240     // headers that are only present for certain disposition {types,modifiers}:
00241     if ( d == Failed )
00242       result += "Failure: " + encodeRFC2047String( spec, "utf-8" ) + "\n";
00243     else if ( m.contains( Error ) )
00244       result += "Error: " + encodeRFC2047String( spec, "utf-8" ) + "\n";
00245     else if ( m.contains( Warning ) )
00246       result += "Warning: " + encodeRFC2047String( spec, "utf-8" ) + "\n";
00247 
00248     return result;
00249   }
00250 
00251   QString descriptionFor( DispositionType d,
00252               const QValueList<DispositionModifier> & ) {
00253     for ( int i = 0 ; i < numDispositionTypes ; ++i )
00254       if ( dispositionTypes[i].dispositionType == d )
00255     return i18n( dispositionTypes[i].description );
00256     kdWarning() << "KMime::MDN::descriptionFor(): No such disposition type: "
00257         << (int)d << endl;
00258     return QString::null;
00259   }
00260 
00261 } // namespace MDN
00262 } // namespace KMime
KDE Home | KDE Accessibility Home | Description of Access Keys