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"