00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00053 class KTnef::KTNEFWriter::PrivateData
00054 {
00055 public:
00056 PrivateData() { mFirstAttachNum = QDateTime::currentDateTime().toTime_t(); }
00057 KTNEFPropertySet properties;
00058 quint16 mFirstAttachNum;
00059 };
00060
00061
00062 KTNEFWriter::KTNEFWriter() : d( new KTnef::KTNEFWriter::PrivateData )
00063 {
00064
00065
00066 QVariant v(0x00010000);
00067 addProperty( attTNEFVERSION, atpDWORD, v );
00068
00069
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
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
00117
00118
00119
00120
00121
00122
00123
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
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
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
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
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
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
00222 list = property->value().toList();
00223 assert( list.count() == 2 );
00224
00225 cs = list[0].toString().toLocal8Bit();
00226 cs2 = ( QString( "smtp:" ) + list[1].toString() ).toLocal8Bit();
00227 i = 18 + cs.length() + cs2.length();
00228
00229 stream << (quint8)LVL_MESSAGE;
00230 stream << mergeTagAndType( tag, property->type() );
00231 stream << (quint32)i;
00232
00233
00234
00235
00236
00237 stream << (quint16)4;
00238 stream << (quint16)i;
00239 stream << (quint16)( cs.length() + 1 );
00240 stream << (quint16)( cs2.length() + 1 );
00241
00242
00243
00244
00245
00246 writeCString( stream, cs );
00247 writeCString( stream, cs2 );
00248
00249
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
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
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
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
00344 stream << TNEF_SIGNATURE;
00345
00346
00347
00348 stream << d->mFirstAttachNum;
00349
00350
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
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 );
00384 }
00385
00386 void KTNEFWriter::setMessageType( MessageType m )
00387 {
00388
00389
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
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
00447
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 & )
00479 {
00480
00481 }
00482
00483 void KTNEFWriter::setUID( const QString &uid )
00484 {
00485 QVariant v( uid );
00486 addProperty( attMSGID, atpSTRING, v );
00487 }
00488
00489
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
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
00515
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 }