• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.8.3 API Reference
  • KDE Home
  • Contact Us
 

KTNEF Library

ktnefwriter.cpp
Go to the documentation of this file.
00001 /*
00002     ktnefwriter.cpp
00003 
00004     Copyright (C) 2002 Bo Thorsen  <bo@sonofthor.dk>
00005 
00006     This file is part of KTNEF, the KDE TNEF support library/program.
00007 
00008     This library is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU Library General Public
00010     License as published by the Free Software Foundation; either
00011     version 2 of the License, or (at your option) any later version.
00012 
00013     This library is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016     Library General Public License for more details.
00017 
00018     You should have received a copy of the GNU Library General Public License
00019     along with this library; see the file COPYING.LIB.  If not, write to
00020     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021     Boston, MA 02110-1301, USA.
00022  */
00031 #include "ktnefwriter.h"
00032 #include "ktnefproperty.h"
00033 #include "ktnefpropertyset.h"
00034 #include "ktnefdefs.h"
00035 
00036 #include <kdebug.h>
00037 
00038 #include <QtCore/QFile>
00039 #include <QtCore/QDateTime>
00040 #include <QtCore/QDataStream>
00041 #include <QtCore/QList>
00042 #include <QtCore/QByteArray>
00043 
00044 #include <assert.h>
00045 
00046 using namespace KTnef;
00047 
00052 //@cond PRIVATE
00053 class KTnef::KTNEFWriter::PrivateData
00054 {
00055   public:
00056     PrivateData() { mFirstAttachNum = QDateTime::currentDateTime().toTime_t(); }
00057     KTNEFPropertySet properties;
00058     quint16 mFirstAttachNum;
00059 };
00060 //@endcond
00061 
00062 KTNEFWriter::KTNEFWriter() : d( new KTnef::KTNEFWriter::PrivateData )
00063 {
00064   // This is not something the user should fiddle with
00065   // First set the TNEF version
00066   QVariant v(0x00010000);
00067   addProperty( attTNEFVERSION, atpDWORD, v );
00068 
00069   // Now set the code page to something reasonable. TODO: Use the right one
00070   QVariant v1( (quint32)0x4e4 );
00071   QVariant v2( (quint32)0x0 );
00072   QList<QVariant> list;
00073   list << v1;
00074   list << v2;
00075   v = QVariant( list );
00076   addProperty( attOEMCODEPAGE, atpBYTE, list );
00077 }
00078 
00079 KTNEFWriter::~KTNEFWriter()
00080 {
00081   delete d;
00082 }
00083 
00084 void KTNEFWriter::addProperty( int tag, int type, const QVariant &value )
00085 {
00086   d->properties.addProperty( tag, type, value );
00087 }
00088 
00089 //@cond IGNORE
00090 void addToChecksum( quint32 i, quint16 &checksum )
00091 {
00092   checksum += i & 0xff;
00093   checksum += ( i >> 8 ) & 0xff;
00094   checksum += ( i >> 16 ) & 0xff;
00095   checksum += ( i >> 24 ) & 0xff;
00096 }
00097 
00098 void addToChecksum( QByteArray &cs, quint16 &checksum )
00099 {
00100   int len = cs.length();
00101   for ( int i=0; i<len; i++ ) {
00102     checksum += (quint8)cs[i];
00103   }
00104 }
00105 
00106 void writeCString( QDataStream &stream, QByteArray &str )
00107 {
00108   stream.writeRawData( str.data(), str.length() );
00109   stream << (quint8)0;
00110 }
00111 
00112 quint32 mergeTagAndType( quint32 tag, quint32 type )
00113 {
00114   return ( ( type & 0xffff ) << 16 ) | ( tag & 0xffff );
00115 }
00116 //@endcond
00117 
00118 /* This writes a TNEF property to the file.
00119  *
00120  * A TNEF property has a 1 byte type (LVL_MESSAGE or LVL_ATTACHMENT),
00121  * a 4 byte type/tag, a 4 byte length, the data and finally the checksum.
00122  *
00123  * The checksum is a 16 byte int with all bytes in the data added.
00124  */
00125 bool KTNEFWriter::writeProperty( QDataStream &stream, int &bytes, int tag ) const
00126 {
00127   QMap<int,KTNEFProperty*>& properties = d->properties.properties();
00128   QMap<int,KTNEFProperty*>::Iterator it = properties.find( tag );
00129 
00130   if ( it == properties.end() ) {
00131     return false;
00132   }
00133 
00134   KTNEFProperty *property = *it;
00135 
00136   quint32 i;
00137   quint16 checksum = 0;
00138   QList<QVariant> list;
00139   QString s;
00140   QByteArray cs, cs2;
00141   QDateTime dt;
00142   QDate date;
00143   QTime time;
00144   switch( tag ) {
00145   case attMSGSTATUS:
00146     // quint8
00147     i = property->value().toUInt() & 0xff;
00148     checksum = i;
00149 
00150     stream << (quint8)LVL_MESSAGE;
00151     stream << mergeTagAndType( tag, property->type() );
00152     stream << (quint32)1;
00153     stream << (quint8)i;
00154 
00155     bytes += 10;
00156     break;
00157 
00158   case attMSGPRIORITY:
00159   case attREQUESTRES:
00160     // quint16
00161     i = property->value().toUInt() & 0xffff;
00162     addToChecksum( i, checksum );
00163 
00164     stream << (quint8)LVL_MESSAGE;
00165     stream << mergeTagAndType( tag, property->type() );
00166     stream << (quint32)2;
00167     stream << (quint16)i;
00168 
00169     bytes += 11;
00170     break;
00171 
00172   case attTNEFVERSION:
00173     // quint32
00174     i = property->value().toUInt();
00175     addToChecksum( i, checksum );
00176 
00177     stream << (quint8)LVL_MESSAGE;
00178     stream << mergeTagAndType( tag, property->type() );
00179     stream << (quint32)4;
00180     stream << (quint32)i;
00181 
00182     bytes += 13;
00183     break;
00184 
00185   case attOEMCODEPAGE:
00186     // 2 quint32
00187     list = property->value().toList();
00188     assert( list.count() == 2 );
00189 
00190     stream << (quint8)LVL_MESSAGE;
00191     stream << mergeTagAndType( tag, property->type() );
00192     stream << (quint32)8;
00193 
00194     i = list[0].toInt();
00195     addToChecksum( i, checksum );
00196     stream << (quint32)i;
00197     i = list[1].toInt();
00198     addToChecksum( i, checksum );
00199     stream << (quint32)i;
00200 
00201     bytes += 17;
00202     break;
00203 
00204   case attMSGCLASS:
00205   case attSUBJECT:
00206   case attBODY:
00207   case attMSGID:
00208     // QCString
00209     cs = property->value().toString().toLocal8Bit();
00210     addToChecksum( cs, checksum );
00211 
00212     stream << (quint8)LVL_MESSAGE;
00213     stream << mergeTagAndType( tag, property->type() );
00214     stream << (quint32)cs.length()+1;
00215     writeCString( stream, cs );
00216 
00217     bytes += 9 + cs.length()+1;
00218     break;
00219 
00220   case attFROM:
00221     // 2 QString encoded to a TRP structure
00222     list = property->value().toList();
00223     assert( list.count() == 2 );
00224 
00225     cs = list[0].toString().toLocal8Bit();                           // Name
00226     cs2 = QString( QLatin1String( "smtp:" ) + list[1].toString() ).toLocal8Bit(); // Email address
00227     i = 18 + cs.length() + cs2.length(); // 2 * sizof(TRP) + strings + 2x'\0'
00228 
00229     stream << (quint8)LVL_MESSAGE;
00230     stream << mergeTagAndType( tag, property->type() );
00231     stream << (quint32)i;
00232 
00233     // The stream has to be aligned to 4 bytes for the strings
00234     // TODO: Or does it? Looks like Outlook doesn't do this
00235     // bytes += 17;
00236     // Write the first TRP structure
00237     stream << (quint16)4;                   // trpidOneOff
00238     stream << (quint16)i;                   // totalsize
00239     stream << (quint16)( cs.length() + 1 ); // sizeof name
00240     stream << (quint16)( cs2.length() + 1 );// sizeof address
00241 
00242     // if ( bytes % 4 != 0 )
00243       // Align the buffer
00244 
00245     // Write the strings
00246     writeCString( stream, cs );
00247     writeCString( stream, cs2 );
00248 
00249     // Write the empty padding TRP structure (just zeroes)
00250     stream << (quint32)0 << (quint32)0;
00251 
00252     addToChecksum( 4, checksum );
00253     addToChecksum( i, checksum );
00254     addToChecksum( cs.length()+1, checksum );
00255     addToChecksum( cs2.length()+1, checksum );
00256     addToChecksum( cs, checksum );
00257     addToChecksum( cs2, checksum );
00258 
00259     bytes += 10;
00260     break;
00261 
00262   case attDATESENT:
00263   case attDATERECD:
00264   case attDATEMODIFIED:
00265     // QDateTime
00266     dt = property->value().toDateTime();
00267     time = dt.time();
00268     date = dt.date();
00269 
00270     stream << (quint8)LVL_MESSAGE;
00271     stream << mergeTagAndType( tag, property->type() );
00272     stream << (quint32)14;
00273 
00274     i = (quint16)date.year();
00275     addToChecksum( i, checksum );
00276     stream << (quint16)i;
00277     i = (quint16)date.month();
00278     addToChecksum( i, checksum );
00279     stream << (quint16)i;
00280     i = (quint16)date.day();
00281     addToChecksum( i, checksum );
00282     stream << (quint16)i;
00283     i = (quint16)time.hour();
00284     addToChecksum( i, checksum );
00285     stream << (quint16)i;
00286     i = (quint16)time.minute();
00287     addToChecksum( i, checksum );
00288     stream << (quint16)i;
00289     i = (quint16)time.second();
00290     addToChecksum( i, checksum );
00291     stream << (quint16)i;
00292     i = (quint16)date.dayOfWeek();
00293     addToChecksum( i, checksum );
00294     stream << (quint16)i;
00295     break;
00296 /*
00297   case attMSGSTATUS:
00298     {
00299       quint8 c;
00300       quint32 flag = 0;
00301       if ( c & fmsRead ) flag |= MSGFLAG_READ;
00302       if ( !( c & fmsModified ) ) flag |= MSGFLAG_UNMODIFIED;
00303       if ( c & fmsSubmitted ) flag |= MSGFLAG_SUBMIT;
00304       if ( c & fmsHasAttach ) flag |= MSGFLAG_HASATTACH;
00305       if ( c & fmsLocal ) flag |= MSGFLAG_UNSENT;
00306       d->stream_ >> c;
00307 
00308       i = property->value().toUInt();
00309       stream << (quint8)LVL_MESSAGE;
00310       stream << (quint32)type;
00311       stream << (quint32)2;
00312       stream << (quint8)i;
00313       addToChecksum( i, checksum );
00314       // from reader: d->message_->addProperty( 0x0E07, MAPI_TYPE_ULONG, flag );
00315     }
00316     kDebug() << "Message Status" << "(length=" << i2 << ")";
00317     break;
00318 */
00319 
00320   default:
00321     kDebug() << "Unknown TNEF tag:" << tag;
00322     return false;
00323   }
00324 
00325   stream << (quint16)checksum;
00326   return true;
00327 }
00328 
00329 bool KTNEFWriter::writeFile( QIODevice &file ) const
00330 {
00331   if ( !file.open( QIODevice::WriteOnly ) ) {
00332     return false;
00333   }
00334 
00335   QDataStream stream( &file );
00336   return writeFile( stream );
00337 }
00338 
00339 bool KTNEFWriter::writeFile( QDataStream &stream ) const
00340 {
00341   stream.setByteOrder( QDataStream::LittleEndian );
00342 
00343   // Start by writing the opening TNEF stuff
00344   stream << TNEF_SIGNATURE;
00345 
00346   // Store the PR_ATTACH_NUM value for the first attachment
00347   // ( must be stored even if *no* attachments are stored )
00348   stream << d->mFirstAttachNum;
00349 
00350   // Now do some writing
00351   bool ok = true;
00352   int bytesWritten = 0;
00353   ok &= writeProperty( stream, bytesWritten, attTNEFVERSION );
00354   ok &= writeProperty( stream, bytesWritten, attOEMCODEPAGE );
00355   ok &= writeProperty( stream, bytesWritten, attMSGCLASS );
00356   ok &= writeProperty( stream, bytesWritten, attMSGPRIORITY );
00357   ok &= writeProperty( stream, bytesWritten, attSUBJECT );
00358   ok &= writeProperty( stream, bytesWritten, attDATESENT );
00359   ok &= writeProperty( stream, bytesWritten, attDATESTART );
00360   ok &= writeProperty( stream, bytesWritten, attDATEEND );
00361   // ok &= writeProperty( stream, bytesWritten, attAIDOWNER );
00362   ok &= writeProperty( stream, bytesWritten, attREQUESTRES );
00363   ok &= writeProperty( stream, bytesWritten, attFROM );
00364   ok &= writeProperty( stream, bytesWritten, attDATERECD );
00365   ok &= writeProperty( stream, bytesWritten, attMSGSTATUS );
00366   ok &= writeProperty( stream, bytesWritten, attBODY );
00367   return ok;
00368 }
00369 
00370 void KTNEFWriter::setSender( const QString &name, const QString &email )
00371 {
00372   assert( !name.isEmpty() );
00373   assert( !email.isEmpty() );
00374 
00375   QVariant v1( name );
00376   QVariant v2( email );
00377 
00378   QList<QVariant> list;
00379   list << v1;
00380   list << v2;
00381 
00382   QVariant v( list );
00383   addProperty( attFROM, 0, list ); // What's up with the 0 here ??
00384 }
00385 
00386 void KTNEFWriter::setMessageType( MessageType m )
00387 {
00388   // Note that the MessageType list here is probably not long enough,
00389   // more entries are most likely needed later
00390 
00391   QVariant v;
00392   switch( m ) {
00393   case Appointment:
00394     v = QVariant( QString( "IPM.Appointment" ) );
00395     break;
00396 
00397   case MeetingCancelled:
00398     v = QVariant( QString( "IPM.Schedule.Meeting.Cancelled" ) );
00399     break;
00400 
00401   case MeetingRequest:
00402     v = QVariant( QString( "IPM.Schedule.Meeting.Request" ) );
00403     break;
00404 
00405   case MeetingNo:
00406     v = QVariant( QString( "IPM.Schedule.Meeting.Resp.Neg" ) );
00407     break;
00408 
00409   case MeetingYes:
00410     v = QVariant( QString( "IPM.Schedule.Meeting.Resp.Pos" ) );
00411     break;
00412 
00413   case MeetingTent:
00414     // Tent?
00415     v = QVariant( QString( "IPM.Schedule.Meeting.Resp.Tent" ) );
00416     break;
00417 
00418   default:
00419     return;
00420   }
00421 
00422   addProperty( attMSGCLASS, atpWORD, v );
00423 }
00424 
00425 void KTNEFWriter::setMethod( Method )
00426 {
00427 
00428 }
00429 
00430 void KTNEFWriter::clearAttendees()
00431 {
00432 
00433 }
00434 
00435 void KTNEFWriter::addAttendee( const QString &cn, Role r,
00436                                PartStat p, bool rsvp,
00437                                const QString &mailto )
00438 {
00439   Q_UNUSED( cn );
00440   Q_UNUSED( r );
00441   Q_UNUSED( p );
00442   Q_UNUSED( rsvp );
00443   Q_UNUSED( mailto );
00444 }
00445 
00446 // I assume this is the same as the sender?
00447 // U also assume that this is like "Name <address>"
00448 void KTNEFWriter::setOrganizer( const QString &organizer )
00449 {
00450   int i = organizer.indexOf( '<' );
00451 
00452   if ( i == -1 ) {
00453     return;
00454   }
00455 
00456   QString name = organizer.left( i );
00457   name.trimmed();
00458 
00459   QString email = organizer.right( i+1 );
00460   email = email.left( email.length()-1 );
00461   email.trimmed();
00462 
00463   setSender( name, email );
00464 }
00465 
00466 void KTNEFWriter::setDtStart( const QDateTime &dtStart )
00467 {
00468   QVariant v( dtStart );
00469   addProperty( attDATESTART, atpDATE, v );
00470 }
00471 
00472 void KTNEFWriter::setDtEnd( const QDateTime &dtEnd )
00473 {
00474   QVariant v( dtEnd );
00475   addProperty( attDATEEND, atpDATE, v );
00476 }
00477 
00478 void KTNEFWriter::setLocation( const QString &/*location*/ )
00479 {
00480 
00481 }
00482 
00483 void KTNEFWriter::setUID( const QString &uid )
00484 {
00485   QVariant v( uid );
00486   addProperty( attMSGID, atpSTRING, v );
00487 }
00488 
00489 // Date sent
00490 void KTNEFWriter::setDtStamp( const QDateTime &dtStamp )
00491 {
00492   QVariant v( dtStamp );
00493   addProperty( attDATESENT, atpDATE, v );
00494 }
00495 
00496 void KTNEFWriter::setCategories( const QStringList &)
00497 {
00498 
00499 }
00500 
00501 // I hope this is the body
00502 void KTNEFWriter::setDescription( const QString &body )
00503 {
00504   QVariant v( body );
00505   addProperty( attBODY, atpTEXT, v );
00506 }
00507 
00508 void KTNEFWriter::setSummary( const QString &s )
00509 {
00510   QVariant v( s );
00511   addProperty( attSUBJECT, atpSTRING, v );
00512 }
00513 
00514 // TNEF encoding: Normal =  3, high = 2, low = 1
00515 // MAPI encoding: Normal = -1, high = 0, low = 1
00516 void KTNEFWriter::setPriority( Priority p )
00517 {
00518   QVariant v( (quint32)p );
00519   addProperty( attMSGPRIORITY, atpSHORT, v );
00520 }
00521 
00522 void KTNEFWriter::setAlarm( const QString &description,
00523                             AlarmAction action,
00524                             const QDateTime &wakeBefore )
00525 {
00526   Q_UNUSED( description );
00527   Q_UNUSED( action );
00528   Q_UNUSED( wakeBefore );
00529 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 22:20:37 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KTNEF Library

Skip menu "KTNEF Library"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdepimlibs-4.8.3 API Reference

Skip menu "kdepimlibs-4.8.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal