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
00085 void KTNEFWriter::addProperty( int tag, int type, const QVariant &value )
00086 {
00087 d->properties.addProperty( tag, type, value );
00088 }
00089
00090
00091 void addToChecksum( quint32 i, quint16 &checksum )
00092 {
00093 checksum += i & 0xff;
00094 checksum += (i >> 8) & 0xff;
00095 checksum += (i >> 16) & 0xff;
00096 checksum += (i >> 24) & 0xff;
00097 }
00098
00099 void addToChecksum( QByteArray &cs, quint16 &checksum )
00100 {
00101 int len = cs.length();
00102 for ( int i=0; i<len; i++ ) {
00103 checksum += (quint8)cs[i];
00104 }
00105 }
00106
00107 void writeCString( QDataStream &stream, QByteArray &str )
00108 {
00109 stream.writeRawData( str.data(), str.length() );
00110 stream << (quint8)0;
00111 }
00112
00113 quint32 mergeTagAndType( quint32 tag, quint32 type )
00114 {
00115 return ( ( type & 0xffff ) << 16 ) | ( tag & 0xffff );
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 bool KTNEFWriter::writeProperty( QDataStream &stream, int &bytes, int tag ) const
00127 {
00128 QMap<int,KTNEFProperty*>& properties = d->properties.properties();
00129 QMap<int,KTNEFProperty*>::Iterator it = properties.find( tag );
00130
00131 if ( it == properties.end() ) {
00132 return false;
00133 }
00134
00135 KTNEFProperty *property = *it;
00136
00137 quint32 i;
00138 quint16 checksum = 0;
00139 QList<QVariant> list;
00140 QString s;
00141 QByteArray cs, cs2;
00142 QDateTime dt;
00143 QDate date;
00144 QTime time;
00145 switch( tag ) {
00146 case attMSGSTATUS:
00147
00148 i = property->value().toUInt() & 0xff;
00149 checksum = i;
00150
00151 stream << (quint8)LVL_MESSAGE;
00152 stream << mergeTagAndType( tag, property->type() );
00153 stream << (quint32)1;
00154 stream << (quint8)i;
00155
00156 bytes += 10;
00157 break;
00158
00159 case attMSGPRIORITY:
00160 case attREQUESTRES:
00161
00162 i = property->value().toUInt() & 0xffff;
00163 addToChecksum( i, checksum );
00164
00165 stream << (quint8)LVL_MESSAGE;
00166 stream << mergeTagAndType( tag, property->type() );
00167 stream << (quint32)2;
00168 stream << (quint16)i;
00169
00170 bytes += 11;
00171 break;
00172
00173 case attTNEFVERSION:
00174
00175 i = property->value().toUInt();
00176 addToChecksum( i, checksum );
00177
00178 stream << (quint8)LVL_MESSAGE;
00179 stream << mergeTagAndType( tag, property->type() );
00180 stream << (quint32)4;
00181 stream << (quint32)i;
00182
00183 bytes += 13;
00184 break;
00185
00186 case attOEMCODEPAGE:
00187
00188 list = property->value().toList();
00189 assert( list.count() == 2 );
00190
00191 stream << (quint8)LVL_MESSAGE;
00192 stream << mergeTagAndType( tag, property->type() );
00193 stream << (quint32)8;
00194
00195 i = list[0].toInt();
00196 addToChecksum( i, checksum );
00197 stream << (quint32)i;
00198 i = list[1].toInt();
00199 addToChecksum( i, checksum );
00200 stream << (quint32)i;
00201
00202 bytes += 17;
00203 break;
00204
00205 case attMSGCLASS:
00206 case attSUBJECT:
00207 case attBODY:
00208 case attMSGID:
00209
00210 cs = property->value().toString().toLocal8Bit();
00211 addToChecksum( cs, checksum );
00212
00213 stream << (quint8)LVL_MESSAGE;
00214 stream << mergeTagAndType( tag, property->type() );
00215 stream << (quint32)cs.length()+1;
00216 writeCString( stream, cs );
00217
00218 bytes += 9 + cs.length()+1;
00219 break;
00220
00221 case attFROM:
00222
00223 list = property->value().toList();
00224 assert( list.count() == 2 );
00225
00226 cs = list[0].toString().toLocal8Bit();
00227 cs2 = (QString("smtp:") + list[1].toString()).toLocal8Bit();
00228 i = 18 + cs.length() + cs2.length();
00229
00230 stream << (quint8)LVL_MESSAGE;
00231 stream << mergeTagAndType( tag, property->type() );
00232 stream << (quint32)i;
00233
00234
00235
00236
00237
00238 stream << (quint16)4;
00239 stream << (quint16)i;
00240 stream << (quint16)(cs.length()+1);
00241 stream << (quint16)(cs2.length()+1);
00242
00243
00244
00245
00246
00247 writeCString( stream, cs );
00248 writeCString( stream, cs2 );
00249
00250
00251 stream << (quint32)0 << (quint32)0;
00252
00253 addToChecksum( 4, checksum );
00254 addToChecksum( i, checksum );
00255 addToChecksum( cs.length()+1, checksum );
00256 addToChecksum( cs2.length()+1, checksum );
00257 addToChecksum( cs, checksum );
00258 addToChecksum( cs2, checksum );
00259
00260 bytes += 10;
00261 break;
00262
00263 case attDATESENT:
00264 case attDATERECD:
00265 case attDATEMODIFIED:
00266
00267 dt = property->value().toDateTime();
00268 time = dt.time();
00269 date = dt.date();
00270
00271 stream << (quint8)LVL_MESSAGE;
00272 stream << mergeTagAndType( tag, property->type() );
00273 stream << (quint32)14;
00274
00275 i = (quint16)date.year();
00276 addToChecksum( i, checksum );
00277 stream << (quint16)i;
00278 i = (quint16)date.month();
00279 addToChecksum( i, checksum );
00280 stream << (quint16)i;
00281 i = (quint16)date.day();
00282 addToChecksum( i, checksum );
00283 stream << (quint16)i;
00284 i = (quint16)time.hour();
00285 addToChecksum( i, checksum );
00286 stream << (quint16)i;
00287 i = (quint16)time.minute();
00288 addToChecksum( i, checksum );
00289 stream << (quint16)i;
00290 i = (quint16)time.second();
00291 addToChecksum( i, checksum );
00292 stream << (quint16)i;
00293 i = (quint16)date.dayOfWeek();
00294 addToChecksum( i, checksum );
00295 stream << (quint16)i;
00296 break;
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 default:
00322 kDebug(5975) << "Unknown TNEF tag:" << tag;
00323 return false;
00324 }
00325
00326 stream << (quint16)checksum;
00327 return true;
00328 }
00329
00330 bool KTNEFWriter::writeFile( QIODevice &file ) const
00331 {
00332 if ( !file.open( QIODevice::WriteOnly ) ) {
00333 return false;
00334 }
00335
00336 QDataStream stream( &file );
00337 return writeFile( stream );
00338 }
00339
00340 bool KTNEFWriter::writeFile( QDataStream &stream ) const
00341 {
00342 stream.setByteOrder( QDataStream::LittleEndian );
00343
00344
00345 stream << TNEF_SIGNATURE;
00346
00347
00348
00349 stream << d->mFirstAttachNum;
00350
00351
00352 bool ok = true;
00353 int bytesWritten = 0;
00354 ok &= writeProperty( stream, bytesWritten, attTNEFVERSION );
00355 ok &= writeProperty( stream, bytesWritten, attOEMCODEPAGE );
00356 ok &= writeProperty( stream, bytesWritten, attMSGCLASS );
00357 ok &= writeProperty( stream, bytesWritten, attMSGPRIORITY );
00358 ok &= writeProperty( stream, bytesWritten, attSUBJECT );
00359 ok &= writeProperty( stream, bytesWritten, attDATESENT );
00360 ok &= writeProperty( stream, bytesWritten, attDATESTART );
00361 ok &= writeProperty( stream, bytesWritten, attDATEEND );
00362
00363 ok &= writeProperty( stream, bytesWritten, attREQUESTRES );
00364 ok &= writeProperty( stream, bytesWritten, attFROM );
00365 ok &= writeProperty( stream, bytesWritten, attDATERECD );
00366 ok &= writeProperty( stream, bytesWritten, attMSGSTATUS );
00367 ok &= writeProperty( stream, bytesWritten, attBODY );
00368 return ok;
00369 }
00370
00371
00372 void KTNEFWriter::setSender( const QString &name, const QString &email )
00373 {
00374 assert( !name.isEmpty() );
00375 assert( !email.isEmpty() );
00376
00377 QVariant v1( name );
00378 QVariant v2( email );
00379
00380 QList<QVariant> list;
00381 list << v1;
00382 list << v2;
00383
00384 QVariant v( list );
00385 addProperty( attFROM, 0, list );
00386 }
00387
00388 void KTNEFWriter::setMessageType( MessageType m )
00389 {
00390
00391
00392
00393 QVariant v;
00394 switch( m ) {
00395 case Appointment:
00396 v = QVariant( QString( "IPM.Appointment" ) );
00397 break;
00398
00399 case MeetingCancelled:
00400 v = QVariant( QString( "IPM.Schedule.Meeting.Cancelled" ) );
00401 break;
00402
00403 case MeetingRequest:
00404 v = QVariant( QString( "IPM.Schedule.Meeting.Request" ) );
00405 break;
00406
00407 case MeetingNo:
00408 v = QVariant( QString( "IPM.Schedule.Meeting.Resp.Neg" ) );
00409 break;
00410
00411 case MeetingYes:
00412 v = QVariant( QString( "IPM.Schedule.Meeting.Resp.Pos" ) );
00413 break;
00414
00415 case MeetingTent:
00416
00417 v = QVariant( QString( "IPM.Schedule.Meeting.Resp.Tent" ) );
00418 break;
00419
00420 default:
00421 return;
00422 }
00423
00424 addProperty( attMSGCLASS, atpWORD, v );
00425 }
00426
00427
00428 void KTNEFWriter::setMethod( Method )
00429 {
00430
00431 }
00432
00433
00434 void KTNEFWriter::clearAttendees()
00435 {
00436
00437 }
00438
00439
00440 void KTNEFWriter::addAttendee( const QString &, Role ,
00441 PartStat , bool ,
00442 const QString & )
00443 {
00444
00445 }
00446
00447
00448
00449
00450 void KTNEFWriter::setOrganizer( const QString &organizer )
00451 {
00452 int i = organizer.indexOf( '<' );
00453
00454 if ( i == -1 ) {
00455 return;
00456 }
00457
00458 QString name = organizer.left( i );
00459 name.trimmed();
00460
00461 QString email = organizer.right( i+1 );
00462 email = email.left( email.length()-1 );
00463 email.trimmed();
00464
00465 setSender( name, email );
00466 }
00467
00468 void KTNEFWriter::setDtStart( const QDateTime &dtStart )
00469 {
00470 QVariant v( dtStart );
00471 addProperty( attDATESTART, atpDATE, v );
00472 }
00473
00474 void KTNEFWriter::setDtEnd( const QDateTime &dtEnd )
00475 {
00476 QVariant v( dtEnd );
00477 addProperty( attDATEEND, atpDATE, v );
00478 }
00479
00480 void KTNEFWriter::setLocation( const QString & )
00481 {
00482
00483 }
00484
00485 void KTNEFWriter::setUID( const QString &uid )
00486 {
00487 QVariant v( uid );
00488 addProperty( attMSGID, atpSTRING, v );
00489 }
00490
00491
00492 void KTNEFWriter::setDtStamp( const QDateTime &dtStamp )
00493 {
00494 QVariant v( dtStamp );
00495 addProperty( attDATESENT, atpDATE, v );
00496 }
00497
00498 void KTNEFWriter::setCategories( const QStringList &)
00499 {
00500
00501 }
00502
00503
00504 void KTNEFWriter::setDescription( const QString &body )
00505 {
00506 QVariant v( body );
00507 addProperty( attBODY, atpTEXT, v );
00508 }
00509
00510 void KTNEFWriter::setSummary( const QString &s )
00511 {
00512 QVariant v( s );
00513 addProperty( attSUBJECT, atpSTRING, v );
00514 }
00515
00516
00517
00518 void KTNEFWriter::setPriority( Priority p )
00519 {
00520 QVariant v( (quint32)p );
00521 addProperty( attMSGPRIORITY, atpSHORT, v );
00522 }
00523
00524 void KTNEFWriter::setAlarm( const QString &,
00525 AlarmAction ,
00526 const QDateTime & )
00527 {
00528 }