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

KTNEF Library

  • sources
  • kde-4.12
  • kdepimlibs
  • 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 
46 using namespace KTnef;
47 
52 //@cond PRIVATE
53 class KTnef::KTNEFWriter::PrivateData
54 {
55  public:
56  PrivateData() { mFirstAttachNum = QDateTime::currentDateTime().toTime_t(); }
57  KTNEFPropertySet properties;
58  quint16 mFirstAttachNum;
59 };
60 //@endcond
61 
62 KTNEFWriter::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 
79 KTNEFWriter::~KTNEFWriter()
80 {
81  delete d;
82 }
83 
84 void KTNEFWriter::addProperty( int tag, int type, const QVariant &value )
85 {
86  d->properties.addProperty( tag, type, value );
87 }
88 
89 //@cond IGNORE
90 void 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 
98 void 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 
106 void writeCString( QDataStream &stream, QByteArray &str )
107 {
108  stream.writeRawData( str.data(), str.length() );
109  stream << (quint8)0;
110 }
111 
112 quint32 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  */
125 bool 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 
329 bool 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 
339 bool 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 
370 void 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 
386 void 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 
425 void KTNEFWriter::setMethod( Method )
426 {
427 
428 }
429 
430 void KTNEFWriter::clearAttendees()
431 {
432 
433 }
434 
435 void 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>"
448 void 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 
464 void KTNEFWriter::setDtStart( const QDateTime &dtStart )
465 {
466  QVariant v( dtStart );
467  addProperty( attDATESTART, atpDATE, v );
468 }
469 
470 void KTNEFWriter::setDtEnd( const QDateTime &dtEnd )
471 {
472  QVariant v( dtEnd );
473  addProperty( attDATEEND, atpDATE, v );
474 }
475 
476 void KTNEFWriter::setLocation( const QString &/*location*/ )
477 {
478 
479 }
480 
481 void KTNEFWriter::setUID( const QString &uid )
482 {
483  QVariant v( uid );
484  addProperty( attMSGID, atpSTRING, v );
485 }
486 
487 // Date sent
488 void KTNEFWriter::setDtStamp( const QDateTime &dtStamp )
489 {
490  QVariant v( dtStamp );
491  addProperty( attDATESENT, atpDATE, v );
492 }
493 
494 void KTNEFWriter::setCategories( const QStringList &)
495 {
496 
497 }
498 
499 // I hope this is the body
500 void KTNEFWriter::setDescription( const QString &body )
501 {
502  QVariant v( body );
503  addProperty( attBODY, atpTEXT, v );
504 }
505 
506 void 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
514 void KTNEFWriter::setPriority( Priority p )
515 {
516  QVariant v( (quint32)p );
517  addProperty( attMSGPRIORITY, atpSHORT, v );
518 }
519 
520 void 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::KTNEFWriter::setSender
void setSender(const QString &name, const QString &email)
Sets the sender's name and email address.
Definition: ktnefwriter.cpp:370
KTnef::KTNEFWriter::setOrganizer
void setOrganizer(const QString &organizer)
Sets the name of the organizer to organizer.
Definition: ktnefwriter.cpp:448
KTnef::KTNEFWriter::Priority
Priority
The different priorities.
Definition: ktnefwriter.h:102
KTnef::KTNEFWriter::MeetingTent
Tentative affirmative to a meeting request.
Definition: ktnefwriter.h:62
KTnef::KTNEFWriter::setDtEnd
void setDtEnd(const QDateTime &dtEnd)
Sets the Ending Date and Time to dtEnd.
Definition: ktnefwriter.cpp:470
KTnef::KTNEFWriter::PartStat
PartStat
The different types of participant statuses.
Definition: ktnefwriter.h:89
KTnef::KTNEFWriter::MeetingRequest
Meeting request.
Definition: ktnefwriter.h:59
KTnef::KTNEFWriter::addProperty
void addProperty(int tag, int type, const QVariant &value)
Adds a TNEF property.
Definition: ktnefwriter.cpp:84
KTnef::KTNEFWriter::MeetingNo
Negative response to a meeting request.
Definition: ktnefwriter.h:60
KTnef::KTNEFWriter::setCategories
void setCategories(const QStringList &categories)
Sets the category list to categories.
Definition: ktnefwriter.cpp:494
KTnef::KTNEFWriter::MeetingYes
Affirmative response to a meeting request.
Definition: ktnefwriter.h:61
KTnef::KTNEFWriter
Manages the writing of TNEF attachments.
Definition: ktnefwriter.h:50
KTnef::KTNEFWriter::MeetingCancelled
The meeting is cancelled.
Definition: ktnefwriter.h:58
KTnef::KTNEFWriter::setLocation
void setLocation(const QString &location)
Sets the Location to location.
Definition: ktnefwriter.cpp:476
KTnef::KTNEFWriter::MessageType
MessageType
The different types of messages.
Definition: ktnefwriter.h:56
KTnef::KTNEFWriter::setDescription
void setDescription(const QString &description)
Sets the description to description.
Definition: ktnefwriter.cpp:500
ktnefdefs.h
This file is part of the API for handling TNEF data and provides some basic definitions for general u...
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::KTNEFPropertySet
Interface for setting MAPI properties and TNEF attributes.
Definition: ktnefpropertyset.h:48
KTnef::KTNEFWriter::setSummary
void setSummary(const QString &summary)
Sets the summary to summary.
Definition: ktnefwriter.cpp:506
KTnef::KTNEFProperty::value
QVariant value() const
Returns the value of the property.
Definition: ktnefproperty.cpp:143
KTnef::KTNEFWriter::KTNEFWriter
KTNEFWriter()
Constructs a TNEF writer object.
Definition: ktnefwriter.cpp:62
KTnef::KTNEFWriter::setMethod
void setMethod(Method method)
Sets the Method to method.
Definition: ktnefwriter.cpp:425
KTnef::KTNEFWriter::setPriority
void setPriority(Priority priority)
Sets the priority to priority.
Definition: ktnefwriter.cpp:514
KTnef::KTNEFWriter::Role
Role
The different types of meeting roles.
Definition: ktnefwriter.h:79
KTnef::KTNEFWriter::setDtStart
void setDtStart(const QDateTime &dtStart)
Sets the Starting Date and Time to dtStart.
Definition: ktnefwriter.cpp:464
KTnef::KTNEFWriter::setUID
void setUID(const QString &uid)
Sets the UID to uid.
Definition: ktnefwriter.cpp:481
ktnefwriter.h
This file is part of the API for handling TNEF data and defines the KTNEFWriter class.
KTnef::KTNEFWriter::clearAttendees
void clearAttendees()
Clears the attendees list.
Definition: ktnefwriter.cpp:430
ktnefpropertyset.h
This file is part of the API for handling TNEF data and defines the KTNEFPropertySet class...
ktnefproperty.h
This file is part of the API for handling TNEF data and defines the KTNEFProperty class...
KTnef::KTNEFWriter::Method
Method
The different types of message statuses.
Definition: ktnefwriter.h:68
KTnef::KTNEFWriter::setDtStamp
void setDtStamp(const QDateTime &dtStamp)
Sets the timestamp to dtStamp.
Definition: ktnefwriter.cpp:488
KTnef::KTNEFWriter::Appointment
Appointment.
Definition: ktnefwriter.h:57
KTnef::KTNEFProperty
Interface for setting MAPI properties.
Definition: ktnefproperty.h:44
KTnef::KTNEFWriter::setMessageType
void setMessageType(MessageType methodType)
Sets the MessageType to methodType.
Definition: ktnefwriter.cpp:386
KTnef::KTNEFWriter::writeFile
bool writeFile(QIODevice &file) const
Writes the attachment to the #QIODevice specified by file.
Definition: ktnefwriter.cpp:329
KTnef::KTNEFWriter::~KTNEFWriter
~KTNEFWriter()
Destroys the TNEF writer object.
Definition: ktnefwriter.cpp:79
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::setAlarm
void setAlarm(const QString &description, AlarmAction action, const QDateTime &wakeBefore)
Sets the alarm.
Definition: ktnefwriter.cpp:520
KTnef::KTNEFWriter::AlarmAction
AlarmAction
The different alarm actions.
Definition: ktnefwriter.h:111
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:01:10 by doxygen 1.8.7 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 API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kldap
  • kmbox
  • kmime
  • kpimidentities
  • kpimtextedit
  • kresources
  • ktnef
  • kxmlrpcclient
  • microblog

Search



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