00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
#ifdef HAVE_CONFIG_H
00027
#include <config.h>
00028
#endif
00029
00030
#include "kmgroupware.h"
00031
00032
#include "kfileio.h"
00033
#include "kmmainwin.h"
00034
#include "kmmainwidget.h"
00035
#include "kmfoldermgr.h"
00036
#include "kmfoldertree.h"
00037
#include "kmcomposewin.h"
00038
#include "kmidentity.h"
00039
#include "identitymanager.h"
00040
#include "kmacctmgr.h"
00041
#include "kmgroupwarefuncs.h"
00042
#include "kmcommands.h"
00043
#include "kmfolderindex.h"
00044
#include "kmkernel.h"
00045
#include "objecttreeparser.h"
00046
#include "kmailicalifaceimpl.h"
00047
00048
using KMail::ObjectTreeParser;
00049
00050
#include <libkcal/icalformat.h>
00051
#include <libkcal/calendarlocal.h>
00052
#include <libkcal/event.h>
00053
00054
using namespace KCal;
00055
00056
#include <kabc/addressee.h>
00057
#include <kabc/address.h>
00058
#include <kabc/phonenumber.h>
00059
#include <kabc/vcardconverter.h>
00060
00061
using namespace KABC;
00062
00063
#include <ktnef/ktnefparser.h>
00064
#include <ktnef/ktnefmessage.h>
00065
#include <ktnef/ktnefdefs.h>
00066
00067
#include <kurl.h>
00068
#include <kmessagebox.h>
00069
#include <klibloader.h>
00070
#include <dcopclient.h>
00071
#include <kparts/part.h>
00072
#include <kconfig.h>
00073
#include <kapplication.h>
00074
#include <kinputdialog.h>
00075
00076
#include <kdebug.h>
00077
00078
#include <qregexp.h>
00079
#include <qbuffer.h>
00080
#include <qfile.h>
00081
00082
#include <mimelib/enum.h>
00083
#include <mimelib/headers.h>
00084
#include <mimelib/bodypart.h>
00085
#include <mimelib/string.h>
00086
#include <mimelib/text.h>
00087
00088
#include <assert.h>
00089
00090
00091 KMGroupware::KMGroupware( QObject* parent,
const char* name )
00092 : QObject( parent, name ), mUseGroupware( false ), mMainWidget( 0 )
00093 {
00094 }
00095
00096
00097 KMGroupware::~KMGroupware()
00098 {
00099 }
00100
00101
void KMGroupware::readConfig()
00102 {
00103 KConfigGroup options( KMKernel::config(),
"Groupware" );
00104
00105
00106
if( options.readEntry(
"Enabled",
"notset" ) ==
"notset" )
00107
return;
00108
00109 mUseGroupware = options.readBoolEntry(
"Enabled",
true );
00110 }
00111
00112
bool KMGroupware::vPartFoundAndDecoded( KMMessage* msg, QString& s )
00113 {
00114 assert( msg );
00115
00116
if( ( DwMime::kTypeText == msg->type() && ( DwMime::kSubtypeVCal == msg->subtype() ||
00117 DwMime::kSubtypeXVCard == msg->subtype() ) ) ||
00118 ( DwMime::kTypeApplication == msg->type() &&
00119 DwMime::kSubtypeOctetStream == msg->subtype() ) )
00120 {
00121 s = QString::fromUtf8( msg->bodyDecoded() );
00122
return true;
00123 }
else if( DwMime::kTypeMultipart == msg->type() &&
00124 (DwMime::kSubtypeMixed == msg->subtype() ) ||
00125 (DwMime::kSubtypeAlternative == msg->subtype() ))
00126 {
00127
00128 DwBodyPart* dwPart = msg->findDwBodyPart( DwMime::kTypeApplication,
00129 DwMime::kSubtypeMsTNEF );
00130
if( !dwPart )
00131 dwPart = msg->findDwBodyPart( DwMime::kTypeApplication,
00132 DwMime::kSubtypeOctetStream );
00133
if( dwPart ){
00134
00135 KMMessagePart msgPart;
00136 KMMessage::bodyPart(dwPart, &msgPart);
00137
return KMGroupware::msTNEFToVPart( msgPart.bodyDecodedBinary(), s );
00138 }
00139
else {
00140 dwPart = msg->findDwBodyPart( DwMime::kTypeText,
00141 DwMime::kSubtypeVCal );
00142
if (dwPart) {
00143 KMMessagePart msgPart;
00144 KMMessage::bodyPart(dwPart, &msgPart);
00145 s = msgPart.body();
00146
return true;
00147 }
00148 }
00149 }
else if( DwMime::kTypeMultipart == msg->type() &&
00150 DwMime::kSubtypeMixed == msg->subtype() ){
00151 }
00152
00153
return false;
00154 }
00155
00156
00157
00158
00159
00160
void KMGroupware::requestAddresses( QString fname )
00161 {
00162 QFile file( fname );
00163
if( file.open( IO_WriteOnly ) ) {
00164 QTextStream ts( &file );
00165 ts.setEncoding( QTextStream::UnicodeUTF8 );
00166
00167
KMFolder* contacts = kmkernel->iCalIface().folderFromType(
"Contact" );
00168
if( contacts ) {
00169 QString s;
00170
for(
int i=0; i<contacts->
count(); ++i ) {
00171
bool unget = !contacts->
isMessage(i);
00172
if( KMGroupware::vPartFoundAndDecoded( contacts->
getMsg( i ), s ) ) {
00173 ts << s;
00174 s.replace(
'\n',
"\\n");
00175 s.truncate(65);
00176 }
00177
if( unget ) contacts->
unGetMsg(i);
00178 }
00179 }
else {
00180 kdDebug(5006) <<
"+++KMGroupware::requestAddresses(): Contacts folder does not exist" << endl;
00181 }
00182 file.close();
00183 }
else {
00184 kdDebug(5006) <<
"+++KMGroupware::requestAddresses(): could not open file" << endl;
00185 }
00186 }
00187
00188
00189
bool KMGroupware::storeAddresses( QString fname, QStringList delUIDs )
00190 {
00191
KMFolder* contacts = kmkernel->iCalIface().folderFromType(
"Contact" );
00192
if( !contacts ) {
00193 kdDebug(5006) <<
"KMGroupware::storeAddresses(): Contacts folder does not exist" << endl;
00194
return false;
00195 }
00196
00197 QFile file( fname );
00198 QStringList vCards;
00199
if( file.open( IO_ReadOnly ) ) {
00200 QTextStream ts( &file );
00201 ts.setEncoding( QTextStream::UnicodeUTF8 );
00202 QString currentVCard;
00203
while( !ts.eof() ) {
00204 QString line;
00205 line = ts.readLine();
00206
if( line.isEmpty() ) {
00207
00208 vCards << currentVCard;
00209 currentVCard =
"";
00210 }
else {
00211
00212 currentVCard += line +
"\r\n";
00213 }
00214 }
00215 file.close();
00216 }
else{
00217 kdDebug(5006) <<
"KMGroupware::storeAddresses(): could not open file" << endl;
00218
return false;
00219 }
00220
00221
for( QStringList::iterator it = delUIDs.begin(); it != delUIDs.end(); ++it ) {
00222 KMMessage* msg = kmkernel->iCalIface().findMessageByUID( *it, contacts );
00223
if( msg )
00224 kmkernel->iCalIface().deleteMsg( msg );
00225
else
00226 kdDebug(5006) <<
"vCard not found, cannot remove: " << *it << endl;
00227 }
00228
00229
for( QStringList::iterator it2 = vCards.begin(); it2 != vCards.end(); ++it2 ) {
00230 QCString vCard( (*it2).utf8() );
00231 QString uid(
"UID" );
00232 QString name(
"NAME" );
00233 vPartMicroParser( vCard, uid, name );
00234 KMMessage* msg = kmkernel->iCalIface().findMessageByUID( uid, contacts );
00235
if( !msg ) {
00236
00237 msg =
new KMMessage();
00238 msg->initHeader();
00239 msg->setType( DwMime::kTypeText );
00240 msg->setSubtype( DwMime::kSubtypeXVCard );
00241 msg->setHeaderField(
"Content-Type",
"Text/X-VCard; charset=\"utf-8\"" );
00242 msg->setSubject(
"Contact" );
00243 msg->setTo( name );
00244
00245
00246 msg->setBodyEncoded( vCard );
00247
00248
00249 msg->touch();
00250 contacts->
addMsg( msg );
00251 }
else {
00252
00253 QString s;
00254
if( vPartFoundAndDecoded( msg, s ) && s.utf8() != vCard ) {
00255 msg->setBodyEncoded( vCard );
00256 msg->setTo( name );
00257 }
00258 }
00259 }
00260
return true;
00261 }
00262
00263
00264 KMGroupware::VCalType KMGroupware::getVCalType(
const QString &vCal )
00265 {
00266
00267
00268
00269
00270
if( vCal.find( QRegExp(
"BEGIN:\\s*VEVENT" ) ) != -1 )
00271
return vCalEvent;
00272
else if( vCal.find( QRegExp(
"BEGIN:\\s*VTODO" ) ) != -1 )
00273
return vCalTodo;
00274
return vCalUnknown;
00275 }
00276
00277
00278
void KMGroupware::processVCalRequest(
const QCString& receiver,
00279
const QString& vCalIn,
00280 QString& choice )
00281 {
00282
#if 0
00283
00284
00285
00286 KMMessage* msgOld = mMainWidget->headers()->currentMsg();
00287 KConfigGroup options( KMKernel::config(),
"Groupware" );
00288 QString fromAddress;
00289
if( options.readBoolEntry(
"LegacyMangleFromToHeaders",
false ) ) {
00290 QStringList toAddresses = KMMessage::splitEmailAddrList( msgOld->to() );
00291
if( toAddresses.count() <= 1 )
00292
00293
00294 fromAddress = msgOld->to();
00295
else {
00296
00297
00298
00299
for( QStringList::Iterator sit = toAddresses.begin();
00300 sit != toAddresses.end(); ++sit ) {
00301
if( KMMessage::getEmailAddr( *sit ) ==
00302 kmkernel->identityManager()->defaultIdentity().emailAddr().local8Bit() ) {
00303
00304
00305 fromAddress = *sit;
00306
break;
00307 }
00308 }
00309
00310
00311
00312
if( fromAddress.isEmpty() ) {
00313
bool bOk;
00314 fromAddress = KInputDialog::getItem( i18n(
"Select Address" ),
00315 i18n(
"In order to let Outlook(tm) recognize you as the receiver, you need to indicate which one of the following addresses is your email address:" ),
00316 toAddresses, 0,
false, &bOk,
00317 kmkernel->mainWin() );
00318
if( !bOk )
00319
00320
00321 fromAddress = toAddresses.first();
00322 }
00323 }
00324 }
00325
#endif
00326
00327 QByteArray data, replyData;
00328 QCString replyType;
00329 QDataStream arg( data, IO_WriteOnly );
00330 arg << choice << receiver << vCalIn;
00331
if( kapp->dcopClient()->call(
"korganizer",
"KOrganizerIface",
00332
"eventRequest(QString,QCString,QString)",
00333 data, replyType, replyData )
00334 && replyType ==
"bool" )
00335 {
00336
bool rc;
00337 QDataStream replyStream( replyData, IO_ReadOnly );
00338 replyStream >> rc;
00339 kdDebug(5006) <<
"KOrganizer call succeeded, rc = " << rc << endl;
00340
00341
if( rc && mMainWidget ) mMainWidget->slotTrashMsg();
00342 }
else
00343 kdDebug(5006) <<
"KOrganizer call failed";
00344 }
00345
00346
00347
00348
void KMGroupware::processVCalReply(
const QCString& sender,
00349
const QString& vCal,
00350
const QString& choice )
00351 {
00352 VCalType type = getVCalType( vCal );
00353
if( type == vCalUnknown ) {
00354 kdDebug(5006) <<
"processVCalReply called with something that is not a vCal\n";
00355
return;
00356 }
00357
00358
if( choice ==
"enter" ) {
00359
00360 QByteArray data, replyData;
00361 QCString replyType;
00362 QDataStream arg( data, IO_WriteOnly );
00363 arg << sender << vCal;
00364
if( kapp->dcopClient()->call(
"korganizer",
"KOrganizerIface",
00365
"eventReply(QCString,QString)",
00366 data, replyType, replyData )
00367 && replyType ==
"bool" )
00368 {
00369
bool rc;
00370 QDataStream replyStream( replyData, IO_ReadOnly );
00371 replyStream >> rc;
00372 kdDebug(5006) <<
"KOrganizer call succeeded, rc = " << rc << endl;
00373
00374
if( rc )
00375 kdDebug(5006) <<
"KOrganizer call succeeded\n";
00376 }
else
00377 kdDebug(5006) <<
"KOrganizer call failed\n";
00378
00379
00380 KMessageBox::information( kmkernel->mainWin(), (type == vCalEvent ?
00381 i18n(
"The answer was registered in your calendar.") :
00382 i18n("The answer was registered in your task list.")),
00383 QString::null, "groupwareBox");
00384 }
else if( choice ==
"cancel" ) {
00385
#if 0
00386
00387 QString uid(
"UID" );
00388 QString descr(
"DESCRIPTION");
00389 QString summary(
"SUMMARY");
00390
00391 vPartMicroParser( vCal.utf8(), uid, descr, summary );
00392
if( type == vCalEvent ) {
00393 emit signalEventDeleted( uid );
00394 KMessageBox::information( kmkernel->mainWin(), i18n(
"<qt>The event <b>%1</b> was deleted from your calendar.</qt>")
00395 .arg( descr) );
00396 }
else if( type == vCalTodo ) {
00397 emit signalTaskDeleted( uid );
00398 KMessageBox::information( kmkernel->mainWin(), i18n(
"The task was deleted from your tasks")
00399 .arg( summary ) );
00400 }
00401
#endif
00402
}
else {
00403
00404
return;
00405 }
00406
00407
00408
if( mMainWidget ) mMainWidget->slotTrashMsg();
00409 }
00410
00411
00412
00413
bool KMGroupware::vPartToHTML(
int ,
const QString& vCal,
00414 QString fname, QString& prefix,
00415 QString& postfix )
const
00416
{
00417 VCalType type = getVCalType( vCal );
00418
if( type == vCalUnknown ) {
00419 kdDebug(5006) <<
"Unknown incidence!\n";
00420
return false;
00421 }
00422
00423 CalendarLocal cl;
00424 ICalFormat format;
00425 format.fromString(&cl, vCal);
00426
00427 Event::List eventList = cl.events();
00428
00429 eventList.setAutoDelete(
false);
00430
00431
if( eventList.count() == 0 )
00432
00433
00434
return false;
00435
00436
00437
00438 Event* event = eventList.first();
00439 QString sLocation = event->location();
00440 QString sDtEnd = event->dtEndTimeStr();
00441 QString sDtStart = event->dtStartTimeStr();
00442 QString sDescr = event->description().simplifyWhiteSpace();
00443 QString sMethod;
00444
00445 QString sAttendee;
00446 Attendee::List attendees = event->attendees();
00447
if( attendees.count() == 0 ) {
00448 kdDebug(5006) <<
"No attendees in the iCal!\n";
00449
return false;
00450 }
00451
if( attendees.count() != 1 )
00452 kdDebug(5006) <<
"Warning: attendeecount in the reply should be 1 but is "
00453 << attendees.count() << endl;
00454 Attendee* attendee = *attendees.begin();
00455
00456
00457 sMethod =
"METHOD";
00458 vPartMicroParser( vCal.utf8(), sMethod );
00459
00460 QString sSummary = event->summary();
00461
00462 kdDebug(5006) <<
"Event stuff: " << sLocation <<
", " << sDtEnd <<
", "
00463 << sDtStart <<
", " << sDescr <<
", " << sMethod <<
", "
00464 << sAttendee << endl;
00465
00466 string2HTML( sLocation );
00467 string2HTML( sDescr );
00468
00469 sMethod = sMethod.lower();
00470
00471 QString typeString;
00472
if( type == vCalEvent )
00473 typeString = i18n(
"calendar");
00474
else
00475 typeString = i18n(
"tasks");
00476
00477
if( sMethod ==
"request" ) {
00478
if( type == vCalEvent ) {
00479 prefix = i18n(
"You have been invited to a meeting");
00480 prefix +=
"<br>";
00481
if( !sLocation.isEmpty() )
00482 prefix.append( i18n(
"The meeting will take place in %1 from %2 to %3" )
00483 .arg( sLocation ).arg( sDtStart ).arg( sDtEnd ) );
00484
else
00485 prefix.append( i18n(
"The meeting will take place from %1 to %2" )
00486 .arg( sDtStart )
00487 .arg( sDtEnd ) );
00488 }
else {
00489 prefix = i18n(
"You have been assigned a task:<br>%1" ).arg( sSummary );
00490 }
00491 }
else if( sMethod ==
"reply" ) {
00492
switch( attendee->status() ) {
00493
case Attendee::Accepted:
00494
if( type == vCalEvent )
00495 prefix = i18n(
"Sender <b>accepts</b> the invitation to meet in %1<br>from %2 to %3.")
00496 .arg( sLocation ).arg( sDtStart ).arg( sDtEnd );
00497
else if( type == vCalTodo )
00498 prefix = i18n(
"Sender <b>accepts</b> the task <b>%1</b>." ).arg(sSummary );
00499
break;
00500
00501
case Attendee::Tentative:
00502
if( type == vCalEvent )
00503 prefix = i18n(
"Sender <b>tentatively accepts</b> the invitation to meet in %1<br>from %2 to %3.")
00504 .arg( sLocation ).arg( sDtStart ).arg( sDtEnd );
00505
else if( type == vCalTodo )
00506 prefix = i18n(
"Sender <b>tentatively accepts</b> the task <b>%1</b>." ).
00507 arg(sSummary );
00508
break;
00509
00510
case Attendee::Declined:
00511
if( type == vCalEvent )
00512 prefix = i18n(
"Sender <b>declines</b> the invitation to meet in %1<br>from %2 to %3.")
00513 .arg( sLocation ).arg( sDtStart ).arg( sDtEnd );
00514
else if( vCalTodo )
00515 prefix = i18n(
"Sender <b>declines</b> the task %1." ).arg( sSummary );
00516
break;
00517
00518
default:
00519
if( type == vCalEvent ) {
00520 prefix = i18n(
"This is an unknown reply to the event in %1 from %2 to %3")
00521 .arg( sLocation ).arg( sDtStart ).arg( sDtEnd );
00522 }
else if( type == vCalTodo ) {
00523 prefix = i18n(
"This is an unknown reply to the task %1").arg(sSummary);
00524 }
00525 }
00526 }
else if( sMethod ==
"cancel" ) {
00527
if( type == vCalEvent ) {
00528 prefix = i18n(
"The event %1 was canceled").arg(sSummary);
00529 }
else if( type == vCalTodo ) {
00530 prefix = i18n(
"The task %1 was canceled").arg(sSummary);
00531 }
00532 }
00533
00534
00535
00536
if(
false && mUseGroupware ) {
00537 prefix.append(
"<br> <br> <br><table border=\"0\" cellspacing=\"0\"><tr><td> </td><td>" );
00538
if( sMethod ==
"request" || sMethod ==
"update" ) {
00539
00540 prefix.append( QString(
"<a href=\"kmail:groupware_vCal_request_accept#%1\"><b>")
00541 .arg(fname) );
00542 prefix.append( i18n(
"[Accept]") );
00543 prefix.append( QString(
"</b></a></td><td> </td><td>") );
00544
00545 prefix.append( QString(
"<a href=\"kmail:groupware_vCal_request_accept conditionally#%1\"><b>")
00546 .arg( fname ) );
00547 prefix.append( i18n(
"[Accept cond.]") );
00548 prefix.append( QString(
"</b></a></td><td> </td><td>") );
00549
00550 prefix.append( QString(
"<a href=\"kmail:groupware_vCal_request_decline#%1\"><b>")
00551 .arg( fname ) );
00552 prefix.append( i18n(
"[Decline]") );
00553 prefix.append( QString(
"</b></a></td><td> </td><td>" ) );
00554
if( type == vCalEvent ) {
00555
00556 prefix.append(QString(
"<a href=\"kmail:groupware_vCal_request_check#%1\"><b>")
00557 .arg(fname));
00558 prefix.append(i18n(
"[Check my calendar...]"));
00559 prefix.append(QString(
"</b></a>"));
00560 }
00561 }
else if( sMethod ==
"reply" ) {
00562
00563 prefix.append(QString(
"<a href=\"kmail:groupware_vCal_reply_enter#%1\"><b>")
00564 .arg(fname));
00565
if( type == vCalEvent )
00566 prefix.append(i18n(
"[Enter this into my calendar]"));
00567
else
00568 prefix.append(i18n(
"[Enter this into my tasks]"));
00569 prefix.append(QString(
"</b></a>"));
00570 }
else if( sMethod ==
"cancel" ) {
00571
00572 prefix.append( QString(
"<a href=\"kmail:groupware_vCal_cancel_enter#%1\"><b>")
00573 .arg( fname ) );
00574 prefix.append( i18n(
"[Remove this from my calendar]"));
00575 prefix.append(QString(
"</b></a>"));
00576 }
00577 prefix.append(
"</td></tr></table>" );
00578 }
00579
00580
if( sMethod ==
"request" || sMethod ==
"cancel" ) {
00581 sDescr.prepend(
"<br> <br> <br><u>" + i18n(
"Description:")
00582 +
"</u><br><table border=\"0\"><tr><td> </td><td>" );
00583 sDescr.append(
"</td></tr></table>" );
00584 prefix.append( sDescr );
00585 }
00586 prefix.append(
" <br> <br><u>");
00587 prefix.append(i18n(
"Original message:"));
00588 prefix.append(
"</u><br><table border=\"0\"><tr><td> </td><td>");
00589
00590 postfix =
"</td></tr></table>";
00591
00592
return true;
00593 }
00594
00595
00596
00597
00598 QString stringProp( KTNEFMessage* tnefMsg,
const Q_UINT32& key,
00599
const QString& fallback = QString::null)
00600 {
00601
return tnefMsg->findProp( key < 0x10000 ? key & 0xFFFF : key >> 16, fallback );
00602 }
00603
00604 QString sNamedProp( KTNEFMessage* tnefMsg,
const QString& name,
00605
const QString& fallback = QString::null)
00606 {
00607
return tnefMsg->findNamedProp( name, fallback );
00608 }
00609
00610
00611
00612
bool KMGroupware::msTNEFToVPart(
const QByteArray& tnef, QString& vPart )
00613 {
00614
00615
00616
bool bOk =
false;
00617
00618 KTNEFParser parser;
00619 QBuffer buf( tnef );
00620 CalendarLocal cal;
00621 Addressee addressee;
00622 VCardConverter cardConv;
00623 ICalFormat calFormat;
00624 Event* event =
new Event();
00625
00626
if( parser.openDevice( &buf ) )
00627 {
00628 KTNEFMessage* tnefMsg = parser.message();
00629
00630
00631
00632
00633 QString msgClass = tnefMsg->findProp(0x001A, QString::null,
true).upper();
00634
if( !msgClass.isEmpty() ){
00635
00636
00637
bool bCompatClassAppointment =
false;
00638
bool bCompatMethodRequest =
false;
00639
bool bCompatMethodCancled =
false;
00640
bool bCompatMethodAccepted =
false;
00641
bool bCompatMethodAcceptedCond =
false;
00642
bool bCompatMethodDeclined =
false;
00643
if( msgClass.startsWith(
"IPM.MICROSOFT SCHEDULE." ) ){
00644 bCompatClassAppointment =
true;
00645
if( msgClass.endsWith(
".MTGREQ" ) )
00646 bCompatMethodRequest =
true;
00647
if( msgClass.endsWith(
".MTGCNCL" ) )
00648 bCompatMethodCancled =
true;
00649
if( msgClass.endsWith(
".MTGRESPP" ) )
00650 bCompatMethodAccepted =
true;
00651
if( msgClass.endsWith(
".MTGRESPA" ) )
00652 bCompatMethodAcceptedCond =
true;
00653
if( msgClass.endsWith(
".MTGRESPN" ) )
00654 bCompatMethodDeclined =
true;
00655 }
00656
bool bCompatClassNote = (msgClass ==
"IPM.MICROSOFT MAIL.NOTE");
00657
00658
00659
if( bCompatClassAppointment ||
"IPM.APPOINTMENT" == msgClass ){
00660
00661
00662
bool bIsReply =
false;
00663 QString prodID;
00664 prodID +=
"-//Microsoft Corporation//Outlook ";
00665 prodID += tnefMsg->findNamedProp(
"0x8554",
"9.0");
00666 prodID +=
"MIMEDIR/EN\n";
00667 prodID +=
"VERSION:2.0\n";
00668 calFormat.setApplication(
"Outlook", prodID);
00669
00670 Scheduler::Method method;
00671
00672
if( bCompatMethodRequest )
00673 method = Scheduler::Request;
00674
else if ( bCompatMethodCancled )
00675 method = Scheduler::Cancel;
00676
else if ( bCompatMethodAccepted ||
00677 bCompatMethodAcceptedCond ||
00678 bCompatMethodDeclined ){
00679 method = Scheduler::Reply;
00680 bIsReply =
true;
00681 }
00682
else{
00683
00684
00685
00686
00687
00688
00689
00690
00691
if( tnefMsg->findProp(0x0c17) ==
"1" )
00692 bIsReply =
true;
00693 method = Scheduler::Request;
00694 }
00695
00697 ScheduleMessage schedMsg(event, method, ScheduleMessage::Unknown );
00698
00699 QString sSenderSearchKeyEmail( tnefMsg->findProp(0x0C1D) );
00700
00701
if( !sSenderSearchKeyEmail.isEmpty() ){
00702
int colon = sSenderSearchKeyEmail.find(
':');
00703
if( sSenderSearchKeyEmail.find(
':') == -1 )
00704 sSenderSearchKeyEmail.remove(0, colon+1);
00705 }
00706
00707 QString s( tnefMsg->findProp(0x0e04) );
00708 QStringList attendees = QStringList::split(
';', s);
00709
if( attendees.count() ){
00710
for ( QStringList::Iterator it = attendees.begin(); it != attendees.end(); ++it ) {
00711
00712
if( (*it).find(
'@') == -1 ){
00713 s = (*it).stripWhiteSpace();
00714
00715 Attendee *attendee =
new Attendee(s,s,
true);
00716
if (bIsReply) {
00717
if (bCompatMethodAccepted)
00718 attendee->setStatus(Attendee::Accepted);
00719
if (bCompatMethodAcceptedCond)
00720 attendee->setStatus(Attendee::Declined);
00721
if (bCompatMethodDeclined)
00722 attendee->setStatus(Attendee::Tentative);
00723 }
00724
else {
00725 attendee->setStatus(Attendee::NeedsAction);
00726 attendee->setRole(Attendee::ReqParticipant);
00727 }
00728 event->addAttendee(attendee);
00729 }
00730 }
00731 }
00732
else
00733 {
00734
00735
00736 s = sSenderSearchKeyEmail;
00737
if( !s.isEmpty() ){
00738 Attendee *attendee =
new Attendee(QString::null,QString::null,
true);
00739
if (bIsReply) {
00740
if (bCompatMethodAccepted)
00741 attendee->setStatus(Attendee::Accepted);
00742
if (bCompatMethodAcceptedCond)
00743 attendee->setStatus(Attendee::Declined);
00744
if (bCompatMethodDeclined)
00745 attendee->setStatus(Attendee::Tentative);
00746 }
00747
else {
00748 attendee->setStatus(Attendee::NeedsAction);
00749 attendee->setRole(Attendee::ReqParticipant);
00750 }
00751 event->addAttendee(attendee);
00752 }
00753 }
00754 s = tnefMsg->findProp(0x0c1f);
00755
if( s.isEmpty() && !bIsReply )
00756 s = sSenderSearchKeyEmail;
00757
if( !s.isEmpty() )
00758 event->setOrganizer(s);
00759
00760 s = tnefMsg->findProp(0x8516)
00761 .replace(QChar(
'-'), QString::null)
00762 .replace(QChar(
':'), QString::null);
00763 event->setDtStart(QDateTime::fromString(s));
00764
00765 s = tnefMsg->findProp(0x8517)
00766 .replace(QChar(
'-'), QString::null)
00767 .replace(QChar(
':'), QString::null);
00768
00769 event->setDtEnd(QDateTime::fromString(s));
00770
00771 s = tnefMsg->findProp(0x8208);
00772 event->setLocation(s);
00773
00774
00775
00776
00777
00778
00779 s = tnefMsg->findProp(0x0023);
00780 event->setUid(s);
00781
00782
00783
00784 s = tnefMsg->findProp(0x8202)
00785 .replace(QChar(
'-'), QString::null)
00786 .replace(QChar(
':'), QString::null);
00787
00788
00789
00790
00791 s = tnefMsg->findNamedProp(
"Keywords");
00792 event->setCategories(s);
00793
00794 s = tnefMsg->findProp(0x1000);
00795 event->setDescription(s);
00796
00797 s = tnefMsg->findProp(0x0070);
00798 event->setSummary(s);
00799
00800
00801 s = tnefMsg->findProp(0x0026);
00802 event->setPriority(s.toInt());
00803
00804
00805
if(!tnefMsg->findProp(0x8503).isEmpty()) {
00806
00807 Alarm *alarm =
new Alarm(event);
00808
00809 QDateTime highNoonTime(
00810 pureISOToLocalQDateTime( tnefMsg->findProp(0x8502)
00811 .replace(QChar(
'-'),
"")
00812 .replace(QChar(
':'),
"") ) );
00813 QDateTime wakeMeUpTime(
00814 pureISOToLocalQDateTime( tnefMsg->findProp(0x8560,
"")
00815 .replace(QChar(
'-'),
"")
00816 .replace(QChar(
':'),
"") ) );
00817
00818 alarm->setTime(wakeMeUpTime);
00819
00820
if( highNoonTime.isValid() && wakeMeUpTime.isValid() )
00821 alarm->setStartOffset(Duration(highNoonTime, wakeMeUpTime));
00822
else
00823
00824 alarm->setStartOffset(Duration(15*60));
00825 alarm->setDisplayAlarm(i18n(
"Reminder"));
00826
00827
00828
00829 event->addAlarm(alarm);
00830 }
00831 cal.addEvent(event);
00832 bOk =
true;
00833
00834
00835 }
else if( bCompatClassNote ||
"IPM.CONTACT" == msgClass ){
00836
00837 addressee.setUid(stringProp(tnefMsg, attMSGID));
00838 addressee.setFormattedName(stringProp(tnefMsg, MAPI_TAG_PR_DISPLAY_NAME));
00839 addressee.insertEmail(sNamedProp(tnefMsg, MAPI_TAG_CONTACT_EMAIL1EMAILADDRESS),
true);
00840 addressee.insertEmail(sNamedProp(tnefMsg, MAPI_TAG_CONTACT_EMAIL2EMAILADDRESS),
false);
00841 addressee.insertEmail(sNamedProp(tnefMsg, MAPI_TAG_CONTACT_EMAIL3EMAILADDRESS),
false);
00842 addressee.insertCustom(
"KADDRESSBOOK",
"X-IMAddress",
00843 sNamedProp(tnefMsg, MAPI_TAG_CONTACT_IMADDRESS));
00844 addressee.insertCustom(
"KADDRESSBOOK",
"X-SpousesName",
00845 stringProp(tnefMsg, MAPI_TAG_PR_SPOUSE_NAME));
00846 addressee.insertCustom(
"KADDRESSBOOK",
"X-ManagersName",
00847 stringProp(tnefMsg, MAPI_TAG_PR_MANAGER_NAME));
00848 addressee.insertCustom(
"KADDRESSBOOK",
"X-AssistantsName",
00849 stringProp(tnefMsg, MAPI_TAG_PR_ASSISTANT));
00850 addressee.insertCustom(
"KADDRESSBOOK",
"X-Department",
00851 stringProp(tnefMsg, MAPI_TAG_PR_DEPARTMENT_NAME));
00852 addressee.insertCustom(
"KADDRESSBOOK",
"X-Office",
00853 stringProp(tnefMsg, MAPI_TAG_PR_OFFICE_LOCATION));
00854 addressee.insertCustom(
"KADDRESSBOOK",
"X-Profession",
00855 stringProp(tnefMsg, MAPI_TAG_PR_PROFESSION));
00856
00857 QString s = tnefMsg->findProp( MAPI_TAG_PR_WEDDING_ANNIVERSARY)
00858 .replace(QChar(
'-'), QString::null)
00859 .replace(QChar(
':'), QString::null);
00860
00861
if( !s.isEmpty() )
00862 addressee.insertCustom(
"KADDRESSBOOK",
"X-Anniversary", s);
00863
00864 addressee.setUrl(KURL( sNamedProp(tnefMsg, MAPI_TAG_CONTACT_WEBPAGE )));
00865
00866
00867 addressee.setFamilyName(stringProp(tnefMsg, MAPI_TAG_PR_SURNAME));
00868 addressee.setGivenName(stringProp(tnefMsg, MAPI_TAG_PR_GIVEN_NAME));
00869 addressee.setAdditionalName(stringProp(tnefMsg, MAPI_TAG_PR_MIDDLE_NAME));
00870 addressee.setPrefix(stringProp(tnefMsg, MAPI_TAG_PR_DISPLAY_NAME_PREFIX));
00871 addressee.setSuffix(stringProp(tnefMsg, MAPI_TAG_PR_GENERATION));
00872
00873 addressee.setNickName(stringProp(tnefMsg, MAPI_TAG_PR_NICKNAME));
00874 addressee.setRole(stringProp(tnefMsg, MAPI_TAG_PR_TITLE));
00875 addressee.setOrganization(stringProp(tnefMsg, MAPI_TAG_PR_COMPANY_NAME));
00876
00877
00878
00879
00880
00881 Address adr;
00882
00883 adr.setPostOfficeBox(stringProp(tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_PO_BOX));
00884 adr.setStreet(stringProp(tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_STREET));
00885 adr.setLocality(stringProp(tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_CITY));
00886 adr.setRegion(stringProp(tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_STATE_OR_PROVINCE));
00887 adr.setPostalCode(stringProp(tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_POSTAL_CODE));
00888 adr.setCountry(stringProp(tnefMsg, MAPI_TAG_PR_HOME_ADDRESS_COUNTRY));
00889 adr.setType(Address::Home);
00890
00891 addressee.insertAddress(adr);
00892
00893 adr.setPostOfficeBox(sNamedProp(tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSPOBOX));
00894 adr.setStreet(sNamedProp(tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSSTREET));
00895 adr.setLocality(sNamedProp(tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSCITY));
00896 adr.setRegion(sNamedProp(tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSSTATE));
00897 adr.setPostalCode(sNamedProp(tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSPOSTALCODE));
00898 adr.setCountry(sNamedProp(tnefMsg, MAPI_TAG_CONTACT_BUSINESSADDRESSCOUNTRY));
00899 adr.setType(Address::Work);
00900
00901 addressee.insertAddress(adr);
00902
00903 adr.setPostOfficeBox(stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_PO_BOX));
00904 adr.setStreet(stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_STREET));
00905 adr.setLocality(stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_CITY));
00906 adr.setRegion(stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_STATE_OR_PROVINCE));
00907 adr.setPostalCode(stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_POSTAL_CODE));
00908 adr.setCountry(stringProp(tnefMsg, MAPI_TAG_PR_OTHER_ADDRESS_COUNTRY));
00909 adr.setType(Address::Dom);
00910
00911 addressee.insertAddress(adr);
00912
00913
00914
00915
00916
00917 QString nr;
00918 nr = stringProp(tnefMsg, MAPI_TAG_PR_HOME_TELEPHONE_NUMBER);
00919 addressee.insertPhoneNumber(KABC::PhoneNumber(nr,PhoneNumber::Home));
00920 nr = stringProp(tnefMsg, MAPI_TAG_PR_BUSINESS_TELEPHONE_NUMBER);
00921 addressee.insertPhoneNumber(KABC::PhoneNumber(nr,PhoneNumber::Work));
00922 nr = stringProp(tnefMsg, MAPI_TAG_PR_MOBILE_TELEPHONE_NUMBER);
00923 addressee.insertPhoneNumber(KABC::PhoneNumber(nr,PhoneNumber::Cell));
00924 nr = stringProp(tnefMsg, MAPI_TAG_PR_HOME_FAX_NUMBER);
00925 addressee.insertPhoneNumber(KABC::PhoneNumber(nr,PhoneNumber::Fax|PhoneNumber::Home));
00926 nr = stringProp(tnefMsg, MAPI_TAG_PR_BUSINESS_FAX_NUMBER);
00927 addressee.insertPhoneNumber(KABC::PhoneNumber(nr,PhoneNumber::Fax|PhoneNumber::Work));
00928
00929 s = tnefMsg->findProp( MAPI_TAG_PR_BIRTHDAY)
00930 .replace(QChar(
'-'), QString::null)
00931 .replace(QChar(
':'), QString::null);
00932
if( !s.isEmpty() )
00933 addressee.setBirthday(QDateTime::fromString(s));
00934
00935 bOk = (!addressee.isEmpty());
00936
00937 }
else if(
"IPM.NOTE" == msgClass ){
00938
00939 }
00940 }
00941 }
00942
00943
00944
00945 QString s;
00946 vPart = calFormat.toString(&cal);
00947
if (cardConv.addresseeToVCard(addressee, s, VCardConverter::v3_0))
00948 vPart += s;
00949
00950
return bOk;
00951 }
00952
00953
00954
00955
bool KMGroupware::msTNEFToHTML( KMReaderWin* reader, QString& vPart, QString fname,
00956 QString& prefix, QString& postfix )
const
00957
{
00958 QByteArray tnef( kFileToBytes( fname,
false ) );
00959
if( tnef.count() ) {
00960
int updateCounter = 0;
00961
if( msTNEFToVPart( tnef, vPart ) ){
00962 QByteArray theBody( vPart.utf8() );
00963 QString fname2( ObjectTreeParser::byteArrayToTempFile( reader,
00964
"groupware",
00965
"vPart_decoded.raw",
00966 theBody ) );
00967
if( !fname2.isEmpty() )
00968
return vPartToHTML( updateCounter, vPart, fname2, prefix, postfix );
00969 }
00970 }
else{
00971 KMessageBox::error(0, i18n(
"<qt>Unable to open file <b>%1</b>.</qt>").arg(fname));
00972 }
00973
return false;
00974 }
00975
00976
00977
00978
bool KMGroupware::foundGroupwareLink(
const QString aUrl, QString& gwType, QString& gwAction,
00979 QString& gwAction2, QString& gwData )
00980 {
00981
static QString gwPrefix(
"groupware_");
00982 gwType =
"";
00983 gwAction =
"";
00984 gwAction2 =
"";
00985 gwData =
"";
00986
00987
int i1 = aUrl.find( gwPrefix );
00988
if( -1 < i1 ) {
00989 i1 += gwPrefix.length();
00990
00991
int i2 = aUrl.find(
"_", i1);
00992
if( i1 <= i2 )
00993 {
00994
00995 gwType = aUrl.mid( i1, i2-i1 );
00996 i1 = i2+1;
00997 i2 = aUrl.find(
"_", i1);
00998
if( i1 <= i2 )
00999 {
01000
01001 gwAction = aUrl.mid( i1, i2-i1 );
01002 i1 = i2+1;
01003 i2 = aUrl.find(
"#", i1);
01004
if( i1 <= i2 )
01005 {
01006
01007 gwAction2 = aUrl.mid( i1, i2-i1 );
01008 i2 += 1;
01009
01010 gwData = aUrl.mid( i2 );
01011 }
01012 }
01013 }
01014 }
01015
return !gwType.isEmpty();
01016 }
01017
01018
01019
bool KMGroupware::handleLink(
const KURL &aUrl, KMMessage* msg )
01020 {
01021 QString gwType, gwAction, gwAction2, gwData;
01022
01023
if( !aUrl.hasRef() || !foundGroupwareLink( aUrl.path()+
"#"+aUrl.ref(), gwType,
01024 gwAction, gwAction2, gwData ) )
01025
01026
return false;
01027
01028
if( gwType !=
"vCal" || gwData.isEmpty()
01029 || (
"request" != gwAction &&
"reply" != gwAction
01030 &&
"cancel" != gwAction ) ) {
01031
01032 kdDebug(5006) <<
"Unhandled groupware link\n";
01033
return true;
01034 }
01035
01036
01037 QFile file( gwData );
01038
if( !file.open( IO_ReadOnly ) ) {
01039 kdDebug(5006) <<
"Could not open file " << gwData << endl;
01040
return true;
01041 }
01042 QTextStream ts( &file );
01043 ts.setEncoding( QTextStream::UnicodeUTF8 );
01044 QString vCal = ts.read();
01045 file.close();
01046
01047
01048 QString receiver;
01049
if( msg ) {
01050
KMIdentity ident = kmkernel->identityManager()->identityForAddress( msg->to() );
01051
if( ident != KMIdentity::null ) {
01052 receiver = ident.
emailAddr();
01053 }
else {
01054 QStringList addrs = KMMessage::splitEmailAddrList( msg->to() );
01055
bool ok;
01056 receiver = KInputDialog::getItem( i18n(
"Select Address"),
01057 i18n(
"None of your identities match the receiver "
01058
"of this message,<br> please choose which of "
01059
"the following addresses is yours:"),
01060 addrs, 0, FALSE, &ok, kmkernel->mainWin() );
01061
if( !ok )
return false;
01062 }
01063 }
01064
01065
01066 QCString sender = KMMessage::getEmailAddr( msg->from() );
01067
01068
if(
"request" == gwAction )
01069 processVCalRequest( receiver.utf8(), vCal, gwAction2 );
01070
else if(
"reply" == gwAction )
01071 processVCalReply( sender, vCal, gwAction2 );
01072
else if(
"cancel" == gwAction )
01073
01074 processVCalReply( sender, vCal, gwAction );
01075
01076
return true;
01077 }
01078
01079
01085
bool KMGroupware::incomingResourceMessage( KMAccount* , KMMessage* )
01086 {
01087
#if 0
01088
01089
01090
if( !mUseGroupware)
01091
return false;
01092
01093 QString vCalIn;
01094
if( vPartFoundAndDecoded( msg, vCalIn ) )
01095
return false;
01096
01097
bool vCalInOK, vCalOutOK, isFree;
01098 QString vCalOut;
01099 QDateTime start, end;
01100 emit( signalResourceRequest( acct->intervals(), KMMessage::getEmailAddr( msg->to() ),
01101 vCalIn, vCalInOK, vCalOut, vCalOutOK, isFree, start, end ) );
01102
if( !vCalInOK || !vCalOutOK )
01103
return false;
01104
01105
01106 KConfigGroup options( KMKernel::config(),
"Groupware" );
01107
if( isFree && options.readBoolEntry(
"AutoAccept",
false ) )
01108
return false;
01109
if( !isFree && options.readBoolEntry(
"AutoDeclConflict",
false ) )
01110
return false;
01111
01112
01113 KMMessage* msgNew = 0;
01114
if( msg ){
01115 msgNew = msg->createReply( KMail::ReplyAuthor, vCalOut,
false,
true, TRUE );
01116 msgNew->setType( DwMime::kTypeText );
01117 msgNew->setSubtype( DwMime::kSubtypeVCal );
01118 msgNew->setHeaderField(
"Content-Type",
"text/calendar; method=REPLY; charset=\"utf-8\"");
01119 internal_directlySendMessage( msgNew );
01120 }
01121
01122
01123 acct->addInterval( qMakePair( start, end ) );
01124
#endif
01125
01126
return true;
01127 }
01128
01129
01130
void KMGroupware::reloadFolderTree()
const
01131
{
01132
01133
if( mMainWidget && mMainWidget->folderTree() )
01134 mMainWidget->folderTree()->reload();
01135 }
01136
01137
#include "kmgroupware.moc"