40 #include <kpimutils/email.h>
41 #include <kabc/phonenumber.h>
42 #include <kabc/vcardconverter.h>
44 #ifndef KDEPIM_NO_KCAL
49 #include <kcalcore/calendar.h>
50 #include <kcalcore/icalformat.h>
51 #include <kcalutils/incidenceformatter.h>
53 #include <klocalizedstring.h>
54 #include <kdatetime.h>
56 #include <QtCore/QBuffer>
60 using namespace KCalCore;
61 using namespace KTnef;
72 return tnefMsg->
findProp( key < 0x10000 ? key & 0xFFFF : key >> 16, fallback );
87 static struct save_tz set_tz( const char *_tc )
89 const char *tc = _tc?_tc:
"UTC";
99 if ( !qgetenv(
"TZ" ).isEmpty() ) {
100 tz_env = qstrdup( qgetenv(
"TZ" ) );
103 char *tmp_env = (
char*)malloc( strlen( tc ) + 4 );
104 strcpy( tmp_env,
"TZ=" );
105 strcpy( tmp_env+3, tc );
108 rv.tz_env_str = tmp_env;
119 static void unset_tz(
struct save_tz old_tz )
121 if ( old_tz.old_tz ) {
122 char *tmp_env = (
char*)malloc( strlen( old_tz.old_tz ) + 4 );
123 strcpy( tmp_env,
"TZ=" );
124 strcpy( tmp_env+3, old_tz.old_tz );
127 free( old_tz.old_tz );
130 putenv( strdup(
"TZ" ) );
135 if ( old_tz.tz_env_str ) {
136 free( old_tz.tz_env_str );
140 static KDateTime utc2Local(
const KDateTime &utcdt )
144 save_tz tmp_tz = set_tz(
"UTC" );
145 time_t utc = utcdt.toTime_t();
148 localtime_r( &utc, &tmL );
149 return KDateTime(
QDate( tmL.tm_year + 1900, tmL.tm_mon + 1, tmL.tm_mday ),
150 QTime( tmL.tm_hour, tmL.tm_min, tmL.tm_sec ) );
153 static KDateTime pureISOToLocalQDateTime(
const QString &dtStr,
154 bool bDateOnly =
false )
158 int year, month, day, hour, minute, second;
172 minute = dtStr.
mid( 11, 2 ).
toInt();
173 second = dtStr.
mid( 13, 2 ).
toInt();
175 tmpDate.
setYMD( year, month, day );
176 tmpTime.
setHMS( hour, minute, second );
179 KDateTime dT = KDateTime( tmpDate, tmpTime );
183 if ( dtStr.
at( dtStr.
length() - 1 ) ==
'Z' ) {
186 dT = utc2Local( dT );
203 MemoryCalendar::Ptr cal(
new MemoryCalendar( KDateTime::UTC ) );
204 KABC::Addressee addressee;
205 ICalFormat calFormat;
206 Event::Ptr event(
new Event() );
218 bool bCompatClassAppointment =
false;
219 bool bCompatMethodRequest =
false;
220 bool bCompatMethodCancled =
false;
221 bool bCompatMethodAccepted =
false;
222 bool bCompatMethodAcceptedCond =
false;
223 bool bCompatMethodDeclined =
false;
225 bCompatClassAppointment =
true;
227 bCompatMethodRequest =
true;
230 bCompatMethodCancled =
true;
233 bCompatMethodAccepted =
true;
236 bCompatMethodAcceptedCond =
true;
239 bCompatMethodDeclined =
true;
242 bool bCompatClassNote = ( msgClass ==
"IPM.MICROSOFT MAIL.NOTE" );
244 if ( bCompatClassAppointment ||
"IPM.APPOINTMENT" == msgClass ) {
246 bool bIsReply =
false;
247 QString prodID =
"-//Microsoft Corporation//Outlook ";
249 prodID +=
"MIMEDIR/EN\n";
250 prodID +=
"VERSION:2.0\n";
251 calFormat.setApplication(
"Outlook", prodID );
254 if ( bCompatMethodRequest ) {
255 method = iTIPRequest;
256 }
else if ( bCompatMethodCancled ) {
258 }
else if ( bCompatMethodAccepted || bCompatMethodAcceptedCond ||
259 bCompatMethodDeclined ) {
271 if ( tnefMsg->
findProp(0x0c17) ==
"1" ) {
274 method = iTIPRequest;
278 ScheduleMessage schedMsg( event, method, ScheduleMessage::Unknown );
282 if ( !sSenderSearchKeyEmail.isEmpty() ) {
283 int colon = sSenderSearchKeyEmail.
indexOf(
':' );
285 if ( sSenderSearchKeyEmail.indexOf(
':' ) == -1 ) {
286 sSenderSearchKeyEmail.remove( 0, colon+1 );
292 if ( attendees.count() ) {
294 it != attendees.end(); ++it ) {
297 if ( (*it).indexOf(
'@' ) == -1 ) {
300 Attendee::Ptr attendee(
new Attendee( s, s,
true ) );
302 if ( bCompatMethodAccepted ) {
303 attendee->setStatus( Attendee::Accepted );
305 if ( bCompatMethodDeclined ) {
306 attendee->setStatus( Attendee::Declined );
308 if ( bCompatMethodAcceptedCond ) {
309 attendee->setStatus( Attendee::Tentative );
312 attendee->setStatus( Attendee::NeedsAction );
313 attendee->setRole( Attendee::ReqParticipant );
315 event->addAttendee( attendee );
321 s = sSenderSearchKeyEmail;
322 if ( !s.isEmpty() ) {
323 Attendee::Ptr attendee(
new Attendee(
QString(),
QString(),
true ) );
325 if ( bCompatMethodAccepted ) {
326 attendee->setStatus( Attendee::Accepted );
328 if ( bCompatMethodAcceptedCond ) {
329 attendee->setStatus( Attendee::Declined );
331 if ( bCompatMethodDeclined ) {
332 attendee->setStatus( Attendee::Tentative );
335 attendee->setStatus( Attendee::NeedsAction );
336 attendee->setRole( Attendee::ReqParticipant );
338 event->addAttendee( attendee );
342 if ( s.isEmpty() && !bIsReply ) {
343 s = sSenderSearchKeyEmail;
346 if ( !s.isEmpty() ) {
347 event->setOrganizer( s );
351 event->setDtStart( KDateTime::fromString( s ) );
354 event->setDtEnd( KDateTime::fromString( s ) );
357 event->setLocation( s );
374 event->setCategories( s );
377 event->setDescription( s );
380 event->setSummary( s );
383 event->setPriority( s.toInt() );
386 Alarm::Ptr alarm(
new Alarm( event.data() ) );
387 KDateTime highNoonTime =
388 pureISOToLocalQDateTime( tnefMsg->
findProp( 0x8502 ).
389 remove(
QChar(
'-' ) ).
remove(
QChar(
':' ) ) );
390 KDateTime wakeMeUpTime =
391 pureISOToLocalQDateTime( tnefMsg->
findProp( 0x8560,
"" ).
392 remove(
QChar(
'-' ) ).
remove(
QChar(
':' ) ) );
393 alarm->setTime( wakeMeUpTime );
395 if ( highNoonTime.isValid() && wakeMeUpTime.isValid() ) {
396 alarm->setStartOffset( Duration( highNoonTime, wakeMeUpTime ) );
399 alarm->setStartOffset( Duration( 15 * 60 ) );
401 alarm->setDisplayAlarm( i18n(
"Reminder" ) );
405 event->addAlarm( alarm );
408 if ( event->uid().isEmpty() ) {
409 event->setUid( CalFormat::createUniqueId() );
411 cal->addEvent( event );
414 }
else if ( bCompatClassNote ||
"IPM.CONTACT" == msgClass ) {
415 addressee.setUid( stringProp( tnefMsg, attMSGID ) );
416 addressee.setFormattedName( stringProp( tnefMsg, MAPI_TAG_PR_DISPLAY_NAME ) );
417 addressee.insertEmail( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_EMAIL1EMAILADDRESS ),
true );
418 addressee.insertEmail( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_EMAIL2EMAILADDRESS ),
false );
419 addressee.insertEmail( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_EMAIL3EMAILADDRESS ),
false );
420 addressee.insertCustom(
"KADDRESSBOOK",
"X-IMAddress",
421 sNamedProp( tnefMsg, MAPI_TAG_CONTACT_IMADDRESS ) );
422 addressee.insertCustom(
"KADDRESSBOOK",
"X-SpousesName",
423 stringProp( tnefMsg, MAPI_TAG_PR_SPOUSE_NAME ) );
424 addressee.insertCustom(
"KADDRESSBOOK",
"X-ManagersName",
425 stringProp( tnefMsg, MAPI_TAG_PR_MANAGER_NAME ) );
426 addressee.insertCustom(
"KADDRESSBOOK",
"X-AssistantsName",
427 stringProp( tnefMsg, MAPI_TAG_PR_ASSISTANT ) );
428 addressee.insertCustom(
"KADDRESSBOOK",
"X-Department",
429 stringProp( tnefMsg, MAPI_TAG_PR_DEPARTMENT_NAME ) );
430 addressee.insertCustom(
"KADDRESSBOOK",
"X-Office",
431 stringProp( tnefMsg, MAPI_TAG_PR_OFFICE_LOCATION ) );
432 addressee.insertCustom(
"KADDRESSBOOK",
"X-Profession",
433 stringProp( tnefMsg, MAPI_TAG_PR_PROFESSION ) );
436 remove(
QChar(
'-' ) ).
remove(
QChar(
':' ) );
438 addressee.insertCustom(
"KADDRESSBOOK",
"X-Anniversary", s );
441 addressee.setUrl( KUrl( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_WEBPAGE ) ) );
444 addressee.setFamilyName( stringProp( tnefMsg, MAPI_TAG_PR_SURNAME ) );
445 addressee.setGivenName( stringProp( tnefMsg, MAPI_TAG_PR_GIVEN_NAME ) );
446 addressee.setAdditionalName( stringProp( tnefMsg, MAPI_TAG_PR_MIDDLE_NAME ) );
447 addressee.setPrefix( stringProp( tnefMsg, MAPI_TAG_PR_DISPLAY_NAME_PREFIX ) );
448 addressee.setSuffix( stringProp( tnefMsg, MAPI_TAG_PR_GENERATION ) );
450 addressee.setNickName( stringProp( tnefMsg, MAPI_TAG_PR_NICKNAME ) );
451 addressee.setRole( stringProp( tnefMsg, MAPI_TAG_PR_TITLE ) );
452 addressee.setOrganization( stringProp( tnefMsg, MAPI_TAG_PR_COMPANY_NAME ) );
459 adr.setPostOfficeBox( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_PO_BOX ) );
460 adr.setStreet( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_STREET ) );
461 adr.setLocality( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_CITY ) );
462 adr.setRegion( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_STATE_OR_PROVINCE ) );
463 adr.setPostalCode( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_POSTAL_CODE ) );
464 adr.setCountry( stringProp( tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_COUNTRY ) );
465 adr.setType( KABC::Address::Home );
466 addressee.insertAddress( adr );
468 adr.setPostOfficeBox( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSPOBOX ) );
469 adr.setStreet( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSSTREET ) );
470 adr.setLocality( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSCITY ) );
471 adr.setRegion( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSSTATE ) );
472 adr.setPostalCode( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSPOSTALCODE ) );
473 adr.setCountry( sNamedProp( tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSCOUNTRY ) );
474 adr.setType( KABC::Address::Work );
475 addressee.insertAddress( adr );
477 adr.setPostOfficeBox( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_PO_BOX ) );
478 adr.setStreet( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_STREET ) );
479 adr.setLocality( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_CITY ) );
480 adr.setRegion( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_STATE_OR_PROVINCE ) );
481 adr.setPostalCode( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_POSTAL_CODE ) );
482 adr.setCountry( stringProp( tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_COUNTRY ) );
483 adr.setType( KABC::Address::Dom );
484 addressee.insertAddress( adr );
493 nr = stringProp( tnefMsg, MAPI_TAG_PR_HOME_TELEPHONE_NUMBER );
494 addressee.insertPhoneNumber(
495 KABC::PhoneNumber( nr, KABC::PhoneNumber::Home ) );
496 nr = stringProp( tnefMsg, MAPI_TAG_PR_BUSINESS_TELEPHONE_NUMBER );
497 addressee.insertPhoneNumber(
498 KABC::PhoneNumber( nr, KABC::PhoneNumber::Work ) );
499 nr = stringProp( tnefMsg, MAPI_TAG_PR_MOBILE_TELEPHONE_NUMBER );
500 addressee.insertPhoneNumber(
501 KABC::PhoneNumber( nr, KABC::PhoneNumber::Cell ) );
502 nr = stringProp( tnefMsg, MAPI_TAG_PR_HOME_FAX_NUMBER );
503 addressee.insertPhoneNumber(
504 KABC::PhoneNumber( nr, KABC::PhoneNumber::Fax | KABC::PhoneNumber::Home ) );
505 nr = stringProp( tnefMsg, MAPI_TAG_PR_BUSINESS_FAX_NUMBER );
506 addressee.insertPhoneNumber(
507 KABC::PhoneNumber( nr, KABC::PhoneNumber::Fax | KABC::PhoneNumber::Work ) );
509 s = tnefMsg->
findProp( MAPI_TAG_PR_BIRTHDAY ).
510 remove(
QChar(
'-' ) ).
remove(
QChar(
':' ) );
515 bOk = ( !addressee.isEmpty() );
516 }
else if (
"IPM.NOTE" == msgClass ) {
532 KABC::VCardConverter converter;
536 #ifndef KDEPIM_NO_KCAL
539 KCal::InvitationFormatterHelper *h )
552 const MemoryCalendar::Ptr &cal,
553 KCalUtils::InvitationFormatterHelper *h )
556 QString iCal = KCalUtils::IncidenceFormatter::formatICalInvitation( vPart, cal, h,
true );
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QString findProp(int key, const QString &fallback=QString(), bool convertToUpper=false) const
Finds a property by key, returning a formatted value.
bool setHMS(int h, int m, int s, int ms)
This file is part of the API for handling TNEF data and defines the KTNEFMessage class.
QString & remove(int position, int n)
Represents a TNEF message.
This file is part of the API for handling TNEF data and provides some basic definitions for general u...
QString fromUtf8(const char *str, int size)
bool setYMD(int y, int m, int d)
This file is part of the API for handling TNEF data and defines the KTNEFParser class.
int toInt(bool *ok, int base) const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QString findNamedProp(const QString &name, const QString &fallback=QString(), bool convertToUpper=false) const
Finds a property by name, returning a formatted value.
bool openDevice(QIODevice *device)
Opens the QIODevice device for parsing.
QDateTime fromString(const QString &string, Qt::DateFormat format)
QString mid(int position, int n) const
const QChar at(int position) const
QStringList split(const QString &sep, const QString &str, bool allowEmptyEntries)
QString left(int n) const
KTNEFMessage * message() const
Returns the KTNEFMessage used in the parsing process.