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

KTNEF Library

  • ktnef
ktnefwriter.cpp
Go to the documentation of this file.
1/*
2 ktnefwriter.cpp
3
4 Copyright (C) 2002 Bo Thorsen <bo@sonofthor.dk>
5
6 This file is part of KTNEF, the KDE TNEF support library/program.
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22 */
31#include "ktnefwriter.h"
32#include "ktnefproperty.h"
33#include "ktnefpropertyset.h"
34#include "ktnefdefs.h"
35
36#include <kdebug.h>
37
38#include <QtCore/QFile>
39#include <QtCore/QDateTime>
40#include <QtCore/QDataStream>
41#include <QtCore/QList>
42#include <QtCore/QByteArray>
43
44#include <assert.h>
45
46using namespace KTnef;
47
52//@cond PRIVATE
53class KTnef::KTNEFWriter::PrivateData
54{
55 public:
56 PrivateData() { mFirstAttachNum = QDateTime::currentDateTime().toTime_t(); }
57 KTNEFPropertySet properties;
58 quint16 mFirstAttachNum;
59};
60//@endcond
61
62KTNEFWriter::KTNEFWriter() : d( new KTnef::KTNEFWriter::PrivateData )
63{
64 // This is not something the user should fiddle with
65 // First set the TNEF version
66 QVariant v(0x00010000);
67 addProperty( attTNEFVERSION, atpDWORD, v );
68
69 // Now set the code page to something reasonable. TODO: Use the right one
70 QVariant v1( (quint32)0x4e4 );
71 QVariant v2( (quint32)0x0 );
72 QList<QVariant> list;
73 list << v1;
74 list << v2;
75 v = QVariant( list );
76 addProperty( attOEMCODEPAGE, atpBYTE, list );
77}
78
79KTNEFWriter::~KTNEFWriter()
80{
81 delete d;
82}
83
84void KTNEFWriter::addProperty( int tag, int type, const QVariant &value )
85{
86 d->properties.addProperty( tag, type, value );
87}
88
89//@cond IGNORE
90void addToChecksum( quint32 i, quint16 &checksum )
91{
92 checksum += i & 0xff;
93 checksum += ( i >> 8 ) & 0xff;
94 checksum += ( i >> 16 ) & 0xff;
95 checksum += ( i >> 24 ) & 0xff;
96}
97
98void addToChecksum( QByteArray &cs, quint16 &checksum )
99{
100 int len = cs.length();
101 for ( int i=0; i<len; i++ ) {
102 checksum += (quint8)cs[i];
103 }
104}
105
106void writeCString( QDataStream &stream, QByteArray &str )
107{
108 stream.writeRawData( str.data(), str.length() );
109 stream << (quint8)0;
110}
111
112quint32 mergeTagAndType( quint32 tag, quint32 type )
113{
114 return ( ( type & 0xffff ) << 16 ) | ( tag & 0xffff );
115}
116//@endcond
117
118/* This writes a TNEF property to the file.
119 *
120 * A TNEF property has a 1 byte type (LVL_MESSAGE or LVL_ATTACHMENT),
121 * a 4 byte type/tag, a 4 byte length, the data and finally the checksum.
122 *
123 * The checksum is a 16 byte int with all bytes in the data added.
124 */
125bool KTNEFWriter::writeProperty( QDataStream &stream, int &bytes, int tag ) const
126{
127 QMap<int,KTNEFProperty*>& properties = d->properties.properties();
128 QMap<int,KTNEFProperty*>::Iterator it = properties.find( tag );
129
130 if ( it == properties.end() ) {
131 return false;
132 }
133
134 KTNEFProperty *property = *it;
135
136 quint32 i;
137 quint16 checksum = 0;
138 QList<QVariant> list;
139 QString s;
140 QByteArray cs, cs2;
141 QDateTime dt;
142 QDate date;
143 QTime time;
144 switch( tag ) {
145 case attMSGSTATUS:
146 // quint8
147 i = property->value().toUInt() & 0xff;
148 checksum = i;
149
150 stream << (quint8)LVL_MESSAGE;
151 stream << mergeTagAndType( tag, property->type() );
152 stream << (quint32)1;
153 stream << (quint8)i;
154
155 bytes += 10;
156 break;
157
158 case attMSGPRIORITY:
159 case attREQUESTRES:
160 // quint16
161 i = property->value().toUInt() & 0xffff;
162 addToChecksum( i, checksum );
163
164 stream << (quint8)LVL_MESSAGE;
165 stream << mergeTagAndType( tag, property->type() );
166 stream << (quint32)2;
167 stream << (quint16)i;
168
169 bytes += 11;
170 break;
171
172 case attTNEFVERSION:
173 // quint32
174 i = property->value().toUInt();
175 addToChecksum( i, checksum );
176
177 stream << (quint8)LVL_MESSAGE;
178 stream << mergeTagAndType( tag, property->type() );
179 stream << (quint32)4;
180 stream << (quint32)i;
181
182 bytes += 13;
183 break;
184
185 case attOEMCODEPAGE:
186 // 2 quint32
187 list = property->value().toList();
188 assert( list.count() == 2 );
189
190 stream << (quint8)LVL_MESSAGE;
191 stream << mergeTagAndType( tag, property->type() );
192 stream << (quint32)8;
193
194 i = list[0].toInt();
195 addToChecksum( i, checksum );
196 stream << (quint32)i;
197 i = list[1].toInt();
198 addToChecksum( i, checksum );
199 stream << (quint32)i;
200
201 bytes += 17;
202 break;
203
204 case attMSGCLASS:
205 case attSUBJECT:
206 case attBODY:
207 case attMSGID:
208 // QCString
209 cs = property->value().toString().toLocal8Bit();
210 addToChecksum( cs, checksum );
211
212 stream << (quint8)LVL_MESSAGE;
213 stream << mergeTagAndType( tag, property->type() );
214 stream << (quint32)cs.length()+1;
215 writeCString( stream, cs );
216
217 bytes += 9 + cs.length()+1;
218 break;
219
220 case attFROM:
221 // 2 QString encoded to a TRP structure
222 list = property->value().toList();
223 assert( list.count() == 2 );
224
225 cs = list[0].toString().toLocal8Bit(); // Name
226 cs2 = QString( QLatin1String( "smtp:" ) + list[1].toString() ).toLocal8Bit(); // Email address
227 i = 18 + cs.length() + cs2.length(); // 2 * sizof(TRP) + strings + 2x'\0'
228
229 stream << (quint8)LVL_MESSAGE;
230 stream << mergeTagAndType( tag, property->type() );
231 stream << (quint32)i;
232
233 // The stream has to be aligned to 4 bytes for the strings
234 // TODO: Or does it? Looks like Outlook doesn't do this
235 // bytes += 17;
236 // Write the first TRP structure
237 stream << (quint16)4; // trpidOneOff
238 stream << (quint16)i; // totalsize
239 stream << (quint16)( cs.length() + 1 ); // sizeof name
240 stream << (quint16)( cs2.length() + 1 );// sizeof address
241
242 // if ( bytes % 4 != 0 )
243 // Align the buffer
244
245 // Write the strings
246 writeCString( stream, cs );
247 writeCString( stream, cs2 );
248
249 // Write the empty padding TRP structure (just zeroes)
250 stream << (quint32)0 << (quint32)0;
251
252 addToChecksum( 4, checksum );
253 addToChecksum( i, checksum );
254 addToChecksum( cs.length()+1, checksum );
255 addToChecksum( cs2.length()+1, checksum );
256 addToChecksum( cs, checksum );
257 addToChecksum( cs2, checksum );
258
259 bytes += 10;
260 break;
261
262 case attDATESENT:
263 case attDATERECD:
264 case attDATEMODIFIED:
265 // QDateTime
266 dt = property->value().toDateTime();
267 time = dt.time();
268 date = dt.date();
269
270 stream << (quint8)LVL_MESSAGE;
271 stream << mergeTagAndType( tag, property->type() );
272 stream << (quint32)14;
273
274 i = (quint16)date.year();
275 addToChecksum( i, checksum );
276 stream << (quint16)i;
277 i = (quint16)date.month();
278 addToChecksum( i, checksum );
279 stream << (quint16)i;
280 i = (quint16)date.day();
281 addToChecksum( i, checksum );
282 stream << (quint16)i;
283 i = (quint16)time.hour();
284 addToChecksum( i, checksum );
285 stream << (quint16)i;
286 i = (quint16)time.minute();
287 addToChecksum( i, checksum );
288 stream << (quint16)i;
289 i = (quint16)time.second();
290 addToChecksum( i, checksum );
291 stream << (quint16)i;
292 i = (quint16)date.dayOfWeek();
293 addToChecksum( i, checksum );
294 stream << (quint16)i;
295 break;
296/*
297 case attMSGSTATUS:
298 {
299 quint8 c;
300 quint32 flag = 0;
301 if ( c & fmsRead ) flag |= MSGFLAG_READ;
302 if ( !( c & fmsModified ) ) flag |= MSGFLAG_UNMODIFIED;
303 if ( c & fmsSubmitted ) flag |= MSGFLAG_SUBMIT;
304 if ( c & fmsHasAttach ) flag |= MSGFLAG_HASATTACH;
305 if ( c & fmsLocal ) flag |= MSGFLAG_UNSENT;
306 d->stream_ >> c;
307
308 i = property->value().toUInt();
309 stream << (quint8)LVL_MESSAGE;
310 stream << (quint32)type;
311 stream << (quint32)2;
312 stream << (quint8)i;
313 addToChecksum( i, checksum );
314 // from reader: d->message_->addProperty( 0x0E07, MAPI_TYPE_ULONG, flag );
315 }
316 kDebug() << "Message Status" << "(length=" << i2 << ")";
317 break;
318*/
319
320 default:
321 kDebug() << "Unknown TNEF tag:" << tag;
322 return false;
323 }
324
325 stream << (quint16)checksum;
326 return true;
327}
328
329bool KTNEFWriter::writeFile( QIODevice &file ) const
330{
331 if ( !file.open( QIODevice::WriteOnly ) ) {
332 return false;
333 }
334
335 QDataStream stream( &file );
336 return writeFile( stream );
337}
338
339bool KTNEFWriter::writeFile( QDataStream &stream ) const
340{
341 stream.setByteOrder( QDataStream::LittleEndian );
342
343 // Start by writing the opening TNEF stuff
344 stream << TNEF_SIGNATURE;
345
346 // Store the PR_ATTACH_NUM value for the first attachment
347 // ( must be stored even if *no* attachments are stored )
348 stream << d->mFirstAttachNum;
349
350 // Now do some writing
351 bool ok = true;
352 int bytesWritten = 0;
353 ok &= writeProperty( stream, bytesWritten, attTNEFVERSION );
354 ok &= writeProperty( stream, bytesWritten, attOEMCODEPAGE );
355 ok &= writeProperty( stream, bytesWritten, attMSGCLASS );
356 ok &= writeProperty( stream, bytesWritten, attMSGPRIORITY );
357 ok &= writeProperty( stream, bytesWritten, attSUBJECT );
358 ok &= writeProperty( stream, bytesWritten, attDATESENT );
359 ok &= writeProperty( stream, bytesWritten, attDATESTART );
360 ok &= writeProperty( stream, bytesWritten, attDATEEND );
361 // ok &= writeProperty( stream, bytesWritten, attAIDOWNER );
362 ok &= writeProperty( stream, bytesWritten, attREQUESTRES );
363 ok &= writeProperty( stream, bytesWritten, attFROM );
364 ok &= writeProperty( stream, bytesWritten, attDATERECD );
365 ok &= writeProperty( stream, bytesWritten, attMSGSTATUS );
366 ok &= writeProperty( stream, bytesWritten, attBODY );
367 return ok;
368}
369
370void KTNEFWriter::setSender( const QString &name, const QString &email )
371{
372 assert( !name.isEmpty() );
373 assert( !email.isEmpty() );
374
375 QVariant v1( name );
376 QVariant v2( email );
377
378 QList<QVariant> list;
379 list << v1;
380 list << v2;
381
382 QVariant v( list );
383 addProperty( attFROM, 0, list ); // What's up with the 0 here ??
384}
385
386void KTNEFWriter::setMessageType( MessageType m )
387{
388 // Note that the MessageType list here is probably not long enough,
389 // more entries are most likely needed later
390
391 QVariant v;
392 switch( m ) {
393 case Appointment:
394 v = QVariant( QString( "IPM.Appointment" ) );
395 break;
396
397 case MeetingCancelled:
398 v = QVariant( QString( "IPM.Schedule.Meeting.Cancelled" ) );
399 break;
400
401 case MeetingRequest:
402 v = QVariant( QString( "IPM.Schedule.Meeting.Request" ) );
403 break;
404
405 case MeetingNo:
406 v = QVariant( QString( "IPM.Schedule.Meeting.Resp.Neg" ) );
407 break;
408
409 case MeetingYes:
410 v = QVariant( QString( "IPM.Schedule.Meeting.Resp.Pos" ) );
411 break;
412
413 case MeetingTent:
414 // Tent?
415 v = QVariant( QString( "IPM.Schedule.Meeting.Resp.Tent" ) );
416 break;
417
418 default:
419 return;
420 }
421
422 addProperty( attMSGCLASS, atpWORD, v );
423}
424
425void KTNEFWriter::setMethod( Method )
426{
427
428}
429
430void KTNEFWriter::clearAttendees()
431{
432
433}
434
435void KTNEFWriter::addAttendee( const QString &cn, Role r,
436 PartStat p, bool rsvp,
437 const QString &mailto )
438{
439 Q_UNUSED( cn );
440 Q_UNUSED( r );
441 Q_UNUSED( p );
442 Q_UNUSED( rsvp );
443 Q_UNUSED( mailto );
444}
445
446// I assume this is the same as the sender?
447// U also assume that this is like "Name <address>"
448void KTNEFWriter::setOrganizer( const QString &organizer )
449{
450 int i = organizer.indexOf( '<' );
451
452 if ( i == -1 ) {
453 return;
454 }
455
456 QString name = organizer.left( i ).trimmed();
457
458 QString email = organizer.right( i+1 );
459 email = email.left( email.length()-1 ).trimmed();
460
461 setSender( name, email );
462}
463
464void KTNEFWriter::setDtStart( const QDateTime &dtStart )
465{
466 QVariant v( dtStart );
467 addProperty( attDATESTART, atpDATE, v );
468}
469
470void KTNEFWriter::setDtEnd( const QDateTime &dtEnd )
471{
472 QVariant v( dtEnd );
473 addProperty( attDATEEND, atpDATE, v );
474}
475
476void KTNEFWriter::setLocation( const QString &/*location*/ )
477{
478
479}
480
481void KTNEFWriter::setUID( const QString &uid )
482{
483 QVariant v( uid );
484 addProperty( attMSGID, atpSTRING, v );
485}
486
487// Date sent
488void KTNEFWriter::setDtStamp( const QDateTime &dtStamp )
489{
490 QVariant v( dtStamp );
491 addProperty( attDATESENT, atpDATE, v );
492}
493
494void KTNEFWriter::setCategories( const QStringList &)
495{
496
497}
498
499// I hope this is the body
500void KTNEFWriter::setDescription( const QString &body )
501{
502 QVariant v( body );
503 addProperty( attBODY, atpTEXT, v );
504}
505
506void KTNEFWriter::setSummary( const QString &s )
507{
508 QVariant v( s );
509 addProperty( attSUBJECT, atpSTRING, v );
510}
511
512// TNEF encoding: Normal = 3, high = 2, low = 1
513// MAPI encoding: Normal = -1, high = 0, low = 1
514void KTNEFWriter::setPriority( Priority p )
515{
516 QVariant v( (quint32)p );
517 addProperty( attMSGPRIORITY, atpSHORT, v );
518}
519
520void KTNEFWriter::setAlarm( const QString &description,
521 AlarmAction action,
522 const QDateTime &wakeBefore )
523{
524 Q_UNUSED( description );
525 Q_UNUSED( action );
526 Q_UNUSED( wakeBefore );
527}
KTnef::KTNEFPropertySet
Interface for setting MAPI properties and TNEF attributes.
Definition: ktnefpropertyset.h:49
KTnef::KTNEFProperty
Interface for setting MAPI properties.
Definition: ktnefproperty.h:45
KTnef::KTNEFProperty::value
QVariant value() const
Returns the value of the property.
Definition: ktnefproperty.cpp:143
KTnef::KTNEFWriter
Manages the writing of TNEF attachments.
Definition: ktnefwriter.h:51
KTnef::KTNEFWriter::setPriority
void setPriority(Priority priority)
Sets the priority to priority.
Definition: ktnefwriter.cpp:514
KTnef::KTNEFWriter::AlarmAction
AlarmAction
The different alarm actions.
Definition: ktnefwriter.h:111
KTnef::KTNEFWriter::setAlarm
void setAlarm(const QString &description, AlarmAction action, const QDateTime &wakeBefore)
Sets the alarm.
Definition: ktnefwriter.cpp:520
KTnef::KTNEFWriter::setOrganizer
void setOrganizer(const QString &organizer)
Sets the name of the organizer to organizer.
Definition: ktnefwriter.cpp:448
KTnef::KTNEFWriter::clearAttendees
void clearAttendees()
Clears the attendees list.
Definition: ktnefwriter.cpp:430
KTnef::KTNEFWriter::KTNEFWriter
KTNEFWriter()
Constructs a TNEF writer object.
Definition: ktnefwriter.cpp:62
KTnef::KTNEFWriter::Role
Role
The different types of meeting roles.
Definition: ktnefwriter.h:79
KTnef::KTNEFWriter::setDtStamp
void setDtStamp(const QDateTime &dtStamp)
Sets the timestamp to dtStamp.
Definition: ktnefwriter.cpp:488
KTnef::KTNEFWriter::setCategories
void setCategories(const QStringList &categories)
Sets the category list to categories.
Definition: ktnefwriter.cpp:494
KTnef::KTNEFWriter::MessageType
MessageType
The different types of messages.
Definition: ktnefwriter.h:56
KTnef::KTNEFWriter::MeetingTent
@ MeetingTent
Tentative affirmative to a meeting request.
Definition: ktnefwriter.h:62
KTnef::KTNEFWriter::MeetingNo
@ MeetingNo
Negative response to a meeting request.
Definition: ktnefwriter.h:60
KTnef::KTNEFWriter::MeetingRequest
@ MeetingRequest
Meeting request.
Definition: ktnefwriter.h:59
KTnef::KTNEFWriter::Appointment
@ Appointment
Appointment.
Definition: ktnefwriter.h:57
KTnef::KTNEFWriter::MeetingYes
@ MeetingYes
Affirmative response to a meeting request.
Definition: ktnefwriter.h:61
KTnef::KTNEFWriter::MeetingCancelled
@ MeetingCancelled
The meeting is cancelled.
Definition: ktnefwriter.h:58
KTnef::KTNEFWriter::Priority
Priority
The different priorities.
Definition: ktnefwriter.h:102
KTnef::KTNEFWriter::~KTNEFWriter
~KTNEFWriter()
Destroys the TNEF writer object.
Definition: ktnefwriter.cpp:79
KTnef::KTNEFWriter::writeFile
bool writeFile(QIODevice &file) const
Writes the attachment to the #QIODevice specified by file.
Definition: ktnefwriter.cpp:329
KTnef::KTNEFWriter::setMethod
void setMethod(Method method)
Sets the Method to method.
Definition: ktnefwriter.cpp:425
KTnef::KTNEFWriter::setLocation
void setLocation(const QString &location)
Sets the Location to location.
Definition: ktnefwriter.cpp:476
KTnef::KTNEFWriter::addProperty
void addProperty(int tag, int type, const QVariant &value)
Adds a TNEF property.
Definition: ktnefwriter.cpp:84
KTnef::KTNEFWriter::writeProperty
bool writeProperty(QDataStream &stream, int &bytes, int tag) const
Writes a TNEF property to the #QDataStream specified by stream.
Definition: ktnefwriter.cpp:125
KTnef::KTNEFWriter::setSummary
void setSummary(const QString &summary)
Sets the summary to summary.
Definition: ktnefwriter.cpp:506
KTnef::KTNEFWriter::Method
Method
The different types of message statuses.
Definition: ktnefwriter.h:68
KTnef::KTNEFWriter::PartStat
PartStat
The different types of participant statuses.
Definition: ktnefwriter.h:89
KTnef::KTNEFWriter::setDtEnd
void setDtEnd(const QDateTime &dtEnd)
Sets the Ending Date and Time to dtEnd.
Definition: ktnefwriter.cpp:470
KTnef::KTNEFWriter::setDtStart
void setDtStart(const QDateTime &dtStart)
Sets the Starting Date and Time to dtStart.
Definition: ktnefwriter.cpp:464
KTnef::KTNEFWriter::setDescription
void setDescription(const QString &description)
Sets the description to description.
Definition: ktnefwriter.cpp:500
KTnef::KTNEFWriter::setSender
void setSender(const QString &name, const QString &email)
Sets the sender's name and email address.
Definition: ktnefwriter.cpp:370
KTnef::KTNEFWriter::setMessageType
void setMessageType(MessageType methodType)
Sets the MessageType to methodType.
Definition: ktnefwriter.cpp:386
KTnef::KTNEFWriter::addAttendee
void addAttendee(const QString &name, Role role, PartStat partstat, bool rsvp, const QString &email)
Adds a meeting participant (attendee).
Definition: ktnefwriter.cpp:435
KTnef::KTNEFWriter::setUID
void setUID(const QString &uid)
Sets the UID to uid.
Definition: ktnefwriter.cpp:481
ktnefdefs.h
This file is part of the API for handling TNEF data and provides some basic definitions for general u...
ktnefproperty.h
This file is part of the API for handling TNEF data and defines the KTNEFProperty class.
ktnefpropertyset.h
This file is part of the API for handling TNEF data and defines the KTNEFPropertySet class.
ktnefwriter.h
This file is part of the API for handling TNEF data and defines the KTNEFWriter class.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu Jul 21 2022 00:00:00 by doxygen 1.9.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KTNEF Library

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

kdepimlibs-4.14.10 API Reference

Skip menu "kdepimlibs-4.14.10 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • 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