00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "knarticlefactory.h"
00017
00018 #include "knglobals.h"
00019 #include "kngroupmanager.h"
00020 #include "knaccountmanager.h"
00021 #include "knfoldermanager.h"
00022 #include "knarticlemanager.h"
00023 #include "knfolder.h"
00024 #include "kncomposer.h"
00025 #include "knnntpaccount.h"
00026 #include "mailsendjob.h"
00027 #include "nntpjobs.h"
00028 #include "utilities.h"
00029 #include "resource.h"
00030 #include "settings.h"
00031 #include "utils/locale.h"
00032
00033 #include <QByteArray>
00034 #include <QList>
00035 #include <QListWidget>
00036 #include <KPIMIdentities/Identity>
00037 #include <KPIMIdentities/IdentityManager>
00038 #include <KPIMUtils/Email>
00039 #include <QLabel>
00040 #include <kiconloader.h>
00041 #include <klocale.h>
00042 #include <kmessagebox.h>
00043 #include <kwindowsystem.h>
00044 #include <ktoolinvocation.h>
00045 #include <kvbox.h>
00046 #include <mailtransport/transportmanager.h>
00047
00048
00049 using namespace KNode;
00050 using namespace KNode::Utilities;
00051 using namespace MailTransport;
00052
00053 KNArticleFactory::KNArticleFactory( QObject *parent )
00054 : QObject( parent ), s_endErrDlg(0)
00055 {
00056 }
00057
00058
00059 KNArticleFactory::~KNArticleFactory()
00060 {
00061 for ( QList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
00062 delete (*it);
00063 delete s_endErrDlg;
00064 }
00065
00066
00067 void KNArticleFactory::createPosting(KNNntpAccount *a)
00068 {
00069 if(!a)
00070 return;
00071
00072 KPIMIdentities::Identity identity;
00073 KNLocalArticle *art = newArticle( a, Locale::defaultCharset() );
00074 if(!art)
00075 return;
00076
00077 art->setServerId(a->id());
00078 art->setDoPost(true);
00079 art->setDoMail(false);
00080
00081 KNComposer *c = new KNComposer( art, QString(), QString(), true, false, false, false );
00082 mCompList.append( c );
00083 connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
00084 c->show();
00085 }
00086
00087
00088 void KNArticleFactory::createPosting(KNGroup *g)
00089 {
00090 if(!g)
00091 return;
00092
00093 QByteArray chset = Locale::defaultCharset( g );
00094
00095 KPIMIdentities::Identity identity;
00096 KNLocalArticle *art = newArticle( g, chset );
00097
00098 if(!art)
00099 return;
00100
00101 art->setServerId(g->account()->id());
00102 art->setDoPost(true);
00103 art->setDoMail(false);
00104 art->newsgroups()->fromUnicodeString(g->groupname(), art->defaultCharset());
00105 KNComposer *c = new KNComposer( art, QString(), QString(), true, false, false, false );
00106 mCompList.append( c );
00107 connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
00108 c->show();
00109 }
00110
00111
00112 void KNArticleFactory::createReply(KNRemoteArticle *a, const QString &selectedText, bool post, bool mail)
00113 {
00114 if(!a)
00115 return;
00116
00117 KNGroup *g=static_cast<KNGroup*>(a->collection());
00118
00119 QByteArray chset;
00120 if ( knGlobals.settings()->useOwnCharset() ) {
00121 chset = Locale::defaultCharset( g );
00122 } else {
00123 chset = a->contentType()->charset();
00124 }
00125
00126
00127 KPIMIdentities::Identity identity;
00128 KNLocalArticle *art = newArticle( g, chset, true, a );
00129 if(!art)
00130 return;
00131
00132 art->setServerId(g->account()->id());
00133 art->setDoPost(post);
00134 art->setDoMail(mail);
00135
00136
00137
00138
00139 QString subject=a->subject()->asUnicodeString();
00140 if ( subject.left(3).toUpper() != "RE:" )
00141 subject.prepend("Re: ");
00142 art->subject()->fromUnicodeString(subject, a->subject()->rfc2047Charset());
00143
00144
00145 KMime::Headers::FollowUpTo *fup2=a->followUpTo(false);
00146 if(fup2 && !fup2->isEmpty()) {
00147 if( ( fup2->as7BitString(false).toUpper()=="POSTER" ) ) {
00148 if( post &&
00149
00150 ( KMessageBox::Yes != KMessageBox::questionYesNo(knGlobals.topWidget,
00151 i18n("The author has requested a reply by email instead\nof a followup to the newsgroup. (Followup-To: poster)\nDo you want to reply in public anyway?"), QString(), KGuiItem(i18n("Reply Public")), KGuiItem(i18n("Reply by Email"))) ))
00152 {
00153 art->setDoPost(false);
00154 art->setDoMail(true);
00155 }
00156 art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false));
00157 }
00158 else
00159 art->newsgroups()->from7BitString(fup2->as7BitString(false));
00160 }
00161 else
00162 art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false));
00163
00164
00165 KMime::Headers::ReplyTo *replyTo=a->replyTo(false);
00166 KMime::Types::Mailbox address;
00167 if(replyTo && !replyTo->isEmpty()) {
00168 foreach( const KMime::Types::Mailbox &mbox, replyTo->mailboxes() ) {
00169 art->to()->addAddress( mbox );
00170 }
00171 }
00172 else {
00173 KMime::Headers::From *from=a->from();
00174 foreach( const KMime::Types::Mailbox &mbox, from->mailboxes() ) {
00175 art->to()->addAddress( mbox );
00176 }
00177 }
00178
00179
00180 KMime::Headers::References *references=a->references(false);
00181 QByteArray refs;
00182 if (references)
00183 refs=references->as7BitString(false);
00184 else
00185 refs = "";
00186
00187 art->references()->from7BitString(refs);
00188 art->references()->appendIdentifier(a->messageID()->as7BitString(false));
00189
00190
00191 bool authorDislikesMailCopies=false;
00192 bool authorWantsMailCopies=false;
00193 KMime::Headers::MailCopiesTo *mailCopiesTo=a->mailCopiesTo(false);
00194
00195 if( mailCopiesTo && !mailCopiesTo->isEmpty() ) {
00196 authorDislikesMailCopies = mailCopiesTo->neverCopy();
00197 authorWantsMailCopies = mailCopiesTo->alwaysCopy();
00198 if (authorWantsMailCopies)
00199 KMessageBox::information( knGlobals.topWidget, i18n("The author requested a mail copy of your reply. (Mail-Copies-To header)"),
00200 QString(), "mailCopiesToWarning" );
00201 if ( authorWantsMailCopies && !mailCopiesTo->mailboxes().isEmpty() ) {
00202 art->to()->clear();
00203 foreach ( const KMime::Types::Mailbox &mbox, mailCopiesTo->mailboxes() ) {
00204 art->to()->addAddress( mbox );
00205 }
00206 }
00207 }
00208
00209
00210
00211
00212
00213
00214 QString attribution = knGlobals.settings()->intro();
00215 QString name( a->from()->displayNames().join( ", ") );
00216 if ( name.isEmpty() && !a->from()->isEmpty() )
00217 name = QString::fromLatin1( a->from()->addresses().first() );
00218 attribution.replace(QRegExp("%NAME"),name);
00219 if ( !a->from()->isEmpty() )
00220 attribution.replace(QRegExp("%EMAIL"), QString::fromLatin1(a->from()->addresses().first()));
00221 attribution.replace( QRegExp("%DATE"), KGlobal::locale()->formatDateTime(a->date()->dateTime().toLocalZone().dateTime(), KLocale::LongDate) );
00222 QString msid = a->messageID()->identifier();
00223 attribution.replace( QRegExp("%MSIDX"), msid );
00224 attribution.replace( QRegExp("%MSID"), QLatin1Char('<') + msid + QLatin1Char('>') );
00225 attribution.replace(QRegExp("%GROUP"),g->groupname());
00226 attribution.replace(QRegExp("%L"),"\n");
00227 attribution+="\n\n";
00228
00229 QString quoted=attribution;
00230 QString notRewraped;
00231 QStringList text;
00232 QStringList::Iterator line;
00233 bool incSig = knGlobals.settings()->includeSignature();
00234
00235 if (selectedText.isEmpty()) {
00236 KMime::Content *tc = a->textContent();
00237 if(tc)
00238 text = tc->decodedText( true, knGlobals.settings()->removeTrailingNewlines() ).split( '\n' );
00239 }
00240 else
00241 text = selectedText.split('\n');
00242
00243 for(line=text.begin(); line!=text.end(); ++line) {
00244 if(!incSig && (*line)=="-- ")
00245 break;
00246
00247 if ((*line)[0]=='>')
00248 quoted += '>' + (*line) + '\n';
00249 else
00250 quoted += "> " +(*line) + '\n';
00251 }
00252
00253 if ( knGlobals.settings()->rewrap() ) {
00254
00255 notRewraped=quoted;
00256 quoted=attribution;
00257
00258 quoted += KNHelper::rewrapStringList( text, knGlobals.settings()->maxLineLength(), '>', !incSig, false );
00259 }
00260
00261
00262
00263 if ( art->doMail() && knGlobals.settings()->useExternalMailer() ) {
00264 sendMailExternal(address.prettyAddress(), subject, quoted);
00265 art->setDoMail(false);
00266 if (!art->doPost()) {
00267 delete art;
00268 return;
00269 }
00270 }
00271
00272
00273 KNComposer *c=new KNComposer(art, quoted, notRewraped, true, authorDislikesMailCopies, authorWantsMailCopies);
00274 mCompList.append( c );
00275 connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
00276 c->show();
00277 }
00278
00279
00280 void KNArticleFactory::createForward(KNArticle *a)
00281 {
00282 if(!a)
00283 return;
00284
00285 KMime::Headers::ContentType *ct=a->contentType();
00286 QByteArray chset;
00287 bool incAtt = ( !knGlobals.settings()->useExternalMailer() &&
00288 ct->isMultipart() && ct->isSubtype("mixed") &&
00289 KMessageBox::Yes == KMessageBox::questionYesNo(knGlobals.topWidget,
00290 i18n("This article contains attachments. Do you want them to be forwarded as well?"), QString(), KGuiItem(i18n("Forward")), KGuiItem(i18n("Do Not Forward")))
00291 );
00292
00293 if ( knGlobals.settings()->useOwnCharset() )
00294 chset = Locale::defaultCharset();
00295 else
00296 chset = a->contentType()->charset();
00297
00298
00299 KPIMIdentities::Identity identity;
00300 KNLocalArticle *art = newArticle( knGlobals.groupManager()->currentGroup(), chset );
00301 if(!art)
00302 return;
00303
00304 art->setDoPost(false);
00305 art->setDoMail(true);
00306
00307
00308
00309
00310 QString subject=("Fwd: "+a->subject()->asUnicodeString());
00311 art->subject()->fromUnicodeString(subject, a->subject()->rfc2047Charset());
00312
00313
00314
00315
00316
00317 QString fwd = QString("\n--------------- %1\n\n").arg(i18n("Forwarded message (begin)"));
00318
00319 fwd+=( i18n("Subject") + ": " + a->subject()->asUnicodeString() + '\n' );
00320 fwd+=( i18n("From") + ": " + a->from()->asUnicodeString() + '\n' );
00321 fwd+=( i18n("Date") + ": " + a->date()->asUnicodeString() + '\n' );
00322 fwd+=( i18n("Newsgroup") + ": " + a->newsgroups()->asUnicodeString() + "\n\n" );
00323
00324 KMime::Content *text=a->textContent();
00325 if(text)
00326 fwd += text->decodedText( false, false );
00327
00328 fwd += QString("\n--------------- %1\n").arg(i18n("Forwarded message (end)"));
00329
00330
00331
00332
00333
00334
00335 if(incAtt) {
00336 KMime::Content::List al = a->attachments( false );
00337 foreach ( KMime::Content *c, al )
00338 art->addContent( new KMime::Content(c->head(), c->body()) );
00339 }
00340
00341
00342
00343
00344 if ( knGlobals.settings()->useExternalMailer() ) {
00345 sendMailExternal( QString(), subject, fwd );
00346 delete art;
00347 return;
00348 }
00349
00350
00351 KNComposer *c = new KNComposer( art, fwd, QString(), true );
00352 mCompList.append( c );
00353 connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
00354 c->show();
00355 }
00356
00357
00358 void KNArticleFactory::createCancel(KNArticle *a)
00359 {
00360 if(!cancelAllowed(a))
00361 return;
00362
00363 if( KMessageBox::No == KMessageBox::questionYesNo( knGlobals.topWidget,
00364 i18n("Do you really want to cancel this article?"), QString(), KGuiItem(i18n("Cancel Article")), KStandardGuiItem::cancel() ) )
00365 return;
00366
00367 bool sendNow;
00368 switch (KMessageBox::warningYesNoCancel(knGlobals.topWidget, i18n("Do you want to send the cancel\nmessage now or later?"), i18n("Question"),KGuiItem(i18n("&Now")),KGuiItem(i18n("&Later")))) {
00369 case KMessageBox::Yes : sendNow = true; break;
00370 case KMessageBox::No : sendNow = false; break;
00371 default : return;
00372 }
00373
00374 KNGroup *grp = 0;
00375 KNNntpAccount *nntp=0;
00376
00377 if ( a->type() == KNArticle::ATremote )
00378 nntp=(static_cast<KNGroup*>(a->collection()))->account();
00379 else {
00380 if(!nntp)
00381 nntp=knGlobals.accountManager()->first();
00382 if(!nntp) {
00383 KMessageBox::error(knGlobals.topWidget, i18n("You have no valid news accounts configured."));
00384 return;
00385 }
00386 KNLocalArticle *la=static_cast<KNLocalArticle*>(a);
00387 la->setCanceled(true);
00388 la->updateListItem();
00389 nntp=knGlobals.accountManager()->account(la->serverId());
00390 }
00391
00392 if ( !a->newsgroups()->isEmpty() )
00393 grp = knGlobals.groupManager()->group(a->newsgroups()->groups().first(), nntp);
00394
00395 KPIMIdentities::Identity identity;
00396 KNLocalArticle *art = newArticle( grp, "us-ascii", false );
00397 if(!art)
00398 return;
00399
00400
00401 art->setDoPost(true);
00402 art->setDoMail(false);
00403
00404
00405 art->setServerId(nntp->id());
00406
00407
00408 KMime::Headers::MessageID *msgId=a->messageID();
00409 QByteArray tmp;
00410 tmp="cancel of "+msgId->as7BitString(false);
00411 art->subject()->from7BitString(tmp);
00412
00413
00414 art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false));
00415
00416
00417 tmp="cancel "+msgId->as7BitString(false);
00418 art->control()->from7BitString(tmp);
00419
00420
00421 art->lines()->setNumberOfLines(1);
00422
00423
00424 art->fromUnicodeString(QString::fromLatin1("cancel by original author\n"));
00425
00426
00427 art->assemble();
00428
00429
00430 KNLocalArticle::List lst;
00431 lst.append(art);
00432 sendArticles( lst, sendNow );
00433 }
00434
00435
00436 void KNArticleFactory::createSupersede(KNArticle *a)
00437 {
00438 if (!a)
00439 return;
00440
00441 if(!cancelAllowed(a))
00442 return;
00443
00444 if ( KMessageBox::No==KMessageBox::questionYesNo( knGlobals.topWidget,
00445 i18n("Do you really want to supersede this article?"), QString(), KGuiItem(i18n("Supersede")), KStandardGuiItem::cancel() ) )
00446 return;
00447
00448 KNGroup *grp = 0;
00449 KNNntpAccount *nntp;
00450
00451 if ( a->type() == KNArticle::ATremote )
00452 nntp=(static_cast<KNGroup*>(a->collection()))->account();
00453 else {
00454 KNLocalArticle *la=static_cast<KNLocalArticle*>(a);
00455 la->setCanceled(true);
00456 la->updateListItem();
00457 nntp=knGlobals.accountManager()->account(la->serverId());
00458 if(!nntp)
00459 nntp=knGlobals.accountManager()->first();
00460 if(!nntp) {
00461 KMessageBox::error(knGlobals.topWidget, i18n("You have no valid news accounts configured."));
00462 return;
00463 }
00464 }
00465
00466 if ( !a->newsgroups()->isEmpty() )
00467 grp = knGlobals.groupManager()->group(a->newsgroups()->groups().first(), nntp);
00468
00469
00470 KPIMIdentities::Identity identity;
00471 KNLocalArticle *art = newArticle( grp, a->contentType()->charset() );
00472 if(!art)
00473 return;
00474
00475 art->setDoPost(true);
00476 art->setDoMail(false);
00477
00478
00479 art->setServerId(nntp->id());
00480
00481
00482 art->subject()->fromUnicodeString(a->subject()->asUnicodeString(), a->subject()->rfc2047Charset());
00483
00484
00485 art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false));
00486
00487
00488 art->followUpTo()->from7BitString(a->followUpTo()->as7BitString(false));
00489
00490
00491 if ( !a->references()->isEmpty() )
00492 art->references()->from7BitString( a->references()->as7BitString(false) );
00493
00494
00495 art->supersedes()->from7BitString(a->messageID()->as7BitString(false));
00496
00497
00498 QString text;
00499 KMime::Content *textContent=a->textContent();
00500 if(textContent)
00501 text = textContent->decodedText();
00502
00503
00504 KNComposer *c=new KNComposer(art, text);
00505 mCompList.append( c );
00506 connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
00507 c->show();
00508 }
00509
00510
00511 void KNArticleFactory::createMail(KMime::Types::Mailbox *address)
00512 {
00513 if ( knGlobals.settings()->useExternalMailer() ) {
00514 sendMailExternal(address->prettyAddress());
00515 return;
00516 }
00517
00518
00519 KPIMIdentities::Identity identity;
00520 KNLocalArticle *art = newArticle( knGlobals.groupManager()->currentGroup(), Locale::defaultCharset() );
00521 if(!art)
00522 return;
00523
00524 art->setDoMail(true);
00525 art->setDoPost(false);
00526 art->to()->addAddress((*address));
00527
00528
00529 KNComposer *c = new KNComposer( art, QString(), QString(), true );
00530 mCompList.append( c );
00531 connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
00532 c->show();
00533 }
00534
00535
00536 void KNArticleFactory::sendMailExternal(const QString &address, const QString &subject, const QString &body)
00537 {
00538 KUrl mailtoURL;
00539 QStringList queries;
00540 QString query;
00541 mailtoURL.setProtocol("mailto");
00542
00543 if (!address.isEmpty())
00544 mailtoURL.setPath(address);
00545 if (!subject.isEmpty())
00546 queries.append("subject="+KUrl::toPercentEncoding(subject));
00547 if (!body.isEmpty())
00548 queries.append("body="+KUrl::toPercentEncoding(body));
00549
00550 if (queries.count() > 0) {
00551 query = '?';
00552 for ( QStringList::Iterator it = queries.begin(); it != queries.end(); ++it ) {
00553 if (it != queries.begin())
00554 query.append( '&' );
00555 query.append((*it));
00556 }
00557 }
00558
00559 if (!query.isEmpty())
00560 mailtoURL.setQuery(query);
00561
00562 KToolInvocation::invokeMailer(mailtoURL);
00563 }
00564
00565
00566 void KNArticleFactory::edit(KNLocalArticle *a)
00567 {
00568 if(!a)
00569 return;
00570
00571 KNComposer *com=findComposer(a);
00572 if(com) {
00573 #ifdef Q_OS_UNIX
00574 KWindowSystem::activateWindow(com->winId());
00575 #endif
00576 return;
00577 }
00578
00579 if(a->editDisabled()) {
00580 KMessageBox::sorry(knGlobals.topWidget, i18n("This article cannot be edited."));
00581 return;
00582 }
00583
00584
00585 KPIMIdentities::Identity id = KNGlobals::self()->settings()->identity();
00586
00587 if(a->doPost()) {
00588 KNNntpAccount *acc=knGlobals.accountManager()->account(a->serverId());
00589 if(acc) {
00590 KMime::Headers::Newsgroups *grps=a->newsgroups();
00591 if ( !grps->isEmpty() ) {
00592 KNGroup *grp = knGlobals.groupManager()->group(grps->groups().first(), acc);
00593 if ( grp && !grp->identity().isNull() ) {
00594 id = grp->identity();
00595 } else if ( !acc->identity().isNull() ) {
00596 id = acc->identity();
00597 }
00598 }
00599 }
00600 }
00601
00602
00603 if(!a->hasContent())
00604 knGlobals.articleManager()->loadArticle(a);
00605
00606
00607 com = new KNComposer( a, QString() );
00608 mCompList.append( com );
00609 connect(com, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
00610 com->show();
00611 }
00612
00613
00614 void KNArticleFactory::sendArticles( KNLocalArticle::List &l, bool now )
00615 {
00616 KNJobData *job=0;
00617 KNServerInfo *ser=0;
00618
00619 KNLocalArticle::List unsent, sent;
00620 for ( KNLocalArticle::List::Iterator it = l.begin(); it != l.end(); ++it ) {
00621 if ( (*it)->pending() )
00622 unsent.append( (*it) );
00623 else
00624 sent.append( (*it) );
00625 }
00626
00627 if(!sent.isEmpty()) {
00628 showSendErrorDialog();
00629 for ( KNLocalArticle::List::Iterator it = sent.begin(); it != sent.end(); ++it )
00630 s_endErrDlg->append( (*it)->subject()->asUnicodeString(), i18n("Article has already been sent.") );
00631 }
00632
00633 if(!now) {
00634 knGlobals.articleManager()->moveIntoFolder(unsent, knGlobals.folderManager()->outbox());
00635 return;
00636 }
00637
00638
00639 for ( KNLocalArticle::List::Iterator it = unsent.begin(); it != unsent.end(); ++it ) {
00640
00641 if ( (*it)->isLocked() )
00642 continue;
00643
00644 if ( !(*it)->hasContent() ) {
00645 if ( !knGlobals.articleManager()->loadArticle( (*it) ) ) {
00646 showSendErrorDialog();
00647 s_endErrDlg->append( (*it)->subject()->asUnicodeString(), i18n("Unable to load article.") );
00648 continue;
00649 }
00650 }
00651
00652
00653
00654 QByteArray head = (*it)->head();
00655 KMime::Headers::Base *header = 0;
00656 while ( true ) {
00657 header = KMime::HeaderParsing::extractFirstHeader( head );
00658 if ( !header ) {
00659 break;
00660 }
00661 if ( qstrncmp( header->type(), "X-KNode", 7 ) == 0 ) {
00662 (*it)->removeHeader( header->type() );
00663 }
00664 }
00665 (*it)->assemble();
00666
00667
00668 if ( (*it)->doPost() && !(*it)->posted() ) {
00669 ser = knGlobals.accountManager()->account( (*it)->serverId() );
00670 job = new ArticlePostJob( this, ser, (*it) );
00671 emitJob(job);
00672 }
00673 if ( (*it)->doMail() && !(*it)->mailed() ) {
00674 int transportId = TransportManager::self()->defaultTransportId();
00675 job = new MailSendJob( this, transportId, (*it) );
00676 emitJob(job);
00677 }
00678 }
00679 }
00680
00681
00682 void KNArticleFactory::sendOutbox()
00683 {
00684 KNLocalArticle::List lst;
00685 KNFolder *ob=0;
00686
00687 if(!knGlobals.folderManager()->loadOutbox()) {
00688 KMessageBox::error(knGlobals.topWidget, i18n("Unable to load the outbox-folder."));
00689 return;
00690 }
00691
00692 ob=knGlobals.folderManager()->outbox();
00693 for(int i=0; i< ob->length(); i++)
00694 lst.append(ob->at(i));
00695
00696 sendArticles( lst, true );
00697 }
00698
00699
00700 bool KNArticleFactory::closeComposeWindows()
00701 {
00702 while ( !mCompList.isEmpty() ) {
00703 QList<KNComposer*>::Iterator it = mCompList.begin();
00704 if ( !(*it)->close() )
00705 return false;
00706 }
00707
00708 return true;
00709 }
00710
00711
00712 void KNArticleFactory::deleteComposerForArticle(KNLocalArticle *a)
00713 {
00714 KNComposer *com = findComposer( a );
00715 if ( com ) {
00716 mCompList.removeAll( com );
00717 com->deleteLater();
00718 }
00719 }
00720
00721
00722 KNComposer* KNArticleFactory::findComposer(KNLocalArticle *a)
00723 {
00724 for ( QList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
00725 if ( (*it)->article() == a )
00726 return (*it);
00727 return 0;
00728 }
00729
00730
00731 void KNArticleFactory::configChanged()
00732 {
00733 for ( QList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
00734 (*it)->setConfig( false );
00735 }
00736
00737
00738 void KNArticleFactory::processJob(KNJobData *j)
00739 {
00740 KNLocalArticle *art=static_cast<KNLocalArticle*>(j->data());
00741 KNLocalArticle::List lst;
00742 lst.append(art);
00743
00744 if(j->canceled()) {
00745 delete j;
00746
00747
00748 if(art->collection()!=knGlobals.folderManager()->outbox())
00749 knGlobals.articleManager()->moveIntoFolder(lst, knGlobals.folderManager()->outbox());
00750
00751 KMessageBox::information(knGlobals.topWidget, i18n("You canceled the article posting. The unsent articles are stored in the \"Outbox\" folder."));
00752
00753 return;
00754 }
00755
00756 if(!j->success()) {
00757 showSendErrorDialog();
00758 s_endErrDlg->append(art->subject()->asUnicodeString(), j->errorString());
00759 delete j;
00760
00761
00762 if(art->collection()!=knGlobals.folderManager()->outbox())
00763 knGlobals.articleManager()->moveIntoFolder(lst, knGlobals.folderManager()->outbox());
00764 }
00765 else {
00766
00767
00768 art->setEditDisabled(true);
00769
00770 switch(j->type()) {
00771
00772 case KNJobData::JTpostArticle:
00773 delete j;
00774 art->setPosted(true);
00775 if(art->doMail() && !art->mailed()) {
00776 sendArticles( lst, true );
00777 return;
00778 }
00779 break;
00780
00781 case KNJobData::JTmail:
00782 delete j;
00783 art->setMailed(true);
00784 break;
00785
00786 default: break;
00787 };
00788
00789
00790 knGlobals.articleManager()->moveIntoFolder(lst, knGlobals.folderManager()->sent());
00791 }
00792 }
00793
00794
00795 KNLocalArticle* KNArticleFactory::newArticle( KNCollection *col, const QByteArray &defChset, bool withXHeaders, KNArticle *origPost )
00796 {
00797 if ( knGlobals.settings()->generateMessageID() && knGlobals.settings()->hostname().isEmpty() ) {
00798 KMessageBox::sorry(knGlobals.topWidget, i18n("Please set a hostname for the generation\nof the message-id or disable it."));
00799 return 0;
00800 }
00801
00802 KNLocalArticle *art=new KNLocalArticle(0);
00803 KPIMIdentities::Identity id;
00804 if (col) {
00805 if (col->type() == KNCollection::CTgroup) {
00806 id = (static_cast<KNGroup *>(col))->identity();
00807 if ( id.isNull() ) {
00808 id = (static_cast<KNGroup *>(col))->account()->identity();
00809 }
00810 } else if (col->type() == KNCollection::CTnntpAccount) {
00811 id = (static_cast<KNNntpAccount *>(col))->identity();
00812 }
00813 }
00814 if ( id.isNull() ) {
00815 id = KNGlobals::self()->settings()->identity();
00816 }
00817
00818 KMime::Headers::Generic *xKnodeIdentity = new KMime::Headers::Generic( "X-KNode-Identity",
00819 art,
00820 QByteArray::number( id.uoid() ) );
00821 art->setHeader( xKnodeIdentity );
00822
00823
00824 if ( knGlobals.settings()->generateMessageID() )
00825 art->messageID()->generate( knGlobals.settings()->hostname().toLatin1() );
00826
00827
00828 KMime::Headers::From *from=art->from();
00829 if ( KPIMUtils::isValidSimpleAddress( id.emailAddr() ) ) {
00830 from->fromUnicodeString( id.fullEmailAddr(), Locale::defaultCharset() );
00831 } else {
00832 KMessageBox::sorry( knGlobals.topWidget,
00833 i18n( "<qt>Please enter a valid email address for the "
00834 "identity named <emphasis>%1</emphasis> "
00835 "at the identity section of the configuration dialog.</qt>",
00836 id.identityName() ) );
00837 delete art;
00838 return 0;
00839 }
00840
00841
00842 if ( KPIMUtils::isValidAddress( id.replyToAddr() ) == KPIMUtils::AddressOk ) {
00843 art->replyTo()->fromUnicodeString( id.replyToAddr(), Locale::defaultCharset() );
00844 } else {
00845 art->removeHeader( "Reply-To" );
00846 }
00847
00848
00849 if ( KPIMUtils::isValidAddress( id.property( "Mail-Copies-To" ).toString() ) == KPIMUtils::AddressOk ) {
00850 art->mailCopiesTo()->fromUnicodeString( id.property( "Mail-Copies-To" ).toString(), Locale::defaultCharset() );
00851 } else {
00852 art->removeHeader( "Mail-Copies-To" );
00853 }
00854
00855
00856 if ( !id.organization().trimmed().isEmpty() ) {
00857 art->organization()->fromUnicodeString( id.organization(), Locale::defaultCharset() );
00858 } else {
00859 art->removeHeader( "Organization" );
00860 }
00861
00862
00863 art->date()->setDateTime( KDateTime::currentLocalDateTime() );
00864
00865
00866 if( !knGlobals.settings()->noUserAgent() ) {
00867 art->userAgent()->from7BitString("KNode/" KNODE_VERSION);
00868 }
00869
00870
00871 KMime::Headers::ContentType *type=art->contentType();
00872 type->setMimeType("text/plain");
00873
00874 type->setCharset(defChset);
00875
00876 if ( defChset.toLower() == "us-ascii" )
00877 art->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit);
00878 else
00879 art->contentTransferEncoding()->setEncoding( knGlobals.settings()->allow8BitBody() ? KMime::Headers::CE8Bit : KMime::Headers::CEquPr );
00880
00881
00882 if(withXHeaders) {
00883 XHeader::List xhdr = knGlobals.settings()->xHeaders();
00884 for ( XHeader::List::Iterator it = xhdr.begin(); it != xhdr.end(); ++it ) {
00885 QString value = (*it).value();
00886 if(origPost) {
00887 QString name( origPost->from()->displayNames().join(", ") );
00888 if ( name.isEmpty() && !origPost->from()->isEmpty() )
00889 name = QString::fromLatin1( origPost->from()->addresses().first() );
00890 value.replace(QRegExp("%NAME"), name);
00891 if ( !origPost->from()->isEmpty() )
00892 value.replace( QRegExp("%EMAIL"), QString::fromLatin1(origPost->from()->addresses().first() ) );
00893 }
00894 else
00895 if ( value.indexOf( "%NAME" ) != -1 || value.indexOf( "%EMAIL" ) != -1 )
00896 continue;
00897
00898 art->setHeader( new KMime::Headers::Generic( (*it).name().toLatin1(), art, value,
00899 Locale::defaultCharset() ) );
00900 }
00901 }
00902
00903 return art;
00904 }
00905
00906
00907 bool KNArticleFactory::cancelAllowed(KNArticle *a)
00908 {
00909 if(!a)
00910 return false;
00911
00912 if(a->type()==KNArticle::ATlocal) {
00913 KNLocalArticle *localArt=static_cast<KNLocalArticle*>(a);
00914
00915 if(localArt->doMail() && !localArt->doPost()) {
00916 KMessageBox::sorry(knGlobals.topWidget, i18n("Emails cannot be canceled or superseded."));
00917 return false;
00918 }
00919
00920 KMime::Headers::Control *ctrl=localArt->control(false);
00921 if(ctrl && ctrl->isCancel()) {
00922 KMessageBox::sorry(knGlobals.topWidget, i18n("Cancel messages cannot be canceled or superseded."));
00923 return false;
00924 }
00925
00926 if(!localArt->posted()) {
00927 KMessageBox::sorry(knGlobals.topWidget, i18n("Only sent articles can be canceled or superseded."));
00928 return false;
00929 }
00930
00931 if(localArt->canceled()) {
00932 KMessageBox::sorry(knGlobals.topWidget, i18n("This article has already been canceled or superseded."));
00933 return false;
00934 }
00935
00936 KMime::Headers::MessageID *mid=localArt->messageID(false);
00937 if(!mid || mid->isEmpty()) {
00938 KMessageBox::sorry(knGlobals.topWidget, i18n(
00939 "This article cannot be canceled or superseded,\n\
00940 because its message-id has not been created by KNode.\n\
00941 But you can look for your article in the newsgroup\n\
00942 and cancel (or supersede) it there."));
00943 return false;
00944 }
00945
00946 return true;
00947 }
00948 else if ( a->type() == KNArticle::ATremote ) {
00949
00950 KNRemoteArticle *remArt=static_cast<KNRemoteArticle*>(a);
00951
00952 KPIMIdentities::IdentityManager *im = KNGlobals::self()->identityManager();
00953 bool ownArticle = false;
00954 const QList<QByteArray> fromAddr = remArt->from()->addresses();
00955 foreach ( const QByteArray &addr, fromAddr ) {
00956 if ( im->thatIsMe( QString::fromLatin1( addr ) ) ) {
00957 ownArticle = true;
00958 break;
00959 }
00960 }
00961 if(!ownArticle) {
00962 KMessageBox::sorry(knGlobals.topWidget, i18n("This article does not appear to be from you.\nYou can only cancel or supersede your own articles."));
00963 return false;
00964 }
00965
00966 if(!remArt->hasContent()) {
00967 KMessageBox::sorry(knGlobals.topWidget, i18n("You have to download the article body\nbefore you can cancel or supersede the article."));
00968 return false;
00969 }
00970
00971 return true;
00972 }
00973
00974 return false;
00975 }
00976
00977
00978 void KNArticleFactory::showSendErrorDialog()
00979 {
00980 if(!s_endErrDlg) {
00981 s_endErrDlg=new KNSendErrorDialog();
00982 connect(s_endErrDlg, SIGNAL(closeClicked()), this, SLOT(slotSendErrorDialogDone()));
00983 }
00984 s_endErrDlg->show();
00985 }
00986
00987
00988 void KNArticleFactory::slotComposerDone(KNComposer *com)
00989 {
00990 bool delCom=true;
00991 KNLocalArticle::List lst;
00992 lst.append(com->article());
00993
00994 switch(com->result()) {
00995
00996 case KNComposer::CRsendNow:
00997 delCom=com->hasValidData();
00998 if(delCom) {
00999 if ( com->applyChanges() )
01000 sendArticles( lst, true );
01001 else
01002 delCom = false;
01003 }
01004 break;
01005
01006 case KNComposer::CRsendLater:
01007 delCom=com->hasValidData();
01008 if(delCom) {
01009 if ( com->applyChanges() )
01010 sendArticles( lst, false );
01011 else
01012 delCom = false;
01013 }
01014 break;
01015
01016 case KNComposer::CRsave :
01017 com->applyChanges();
01018 knGlobals.articleManager()->moveIntoFolder(lst, knGlobals.folderManager()->drafts());
01019 break;
01020
01021 case KNComposer::CRdelAsk:
01022 delCom=knGlobals.articleManager()->deleteArticles(lst, true);
01023 break;
01024
01025 case KNComposer::CRdel:
01026 delCom=knGlobals.articleManager()->deleteArticles(lst, false);
01027 break;
01028
01029 case KNComposer::CRcancel:
01030
01031 break;
01032
01033 default: break;
01034
01035 };
01036
01037 if ( delCom ) {
01038 mCompList.removeAll( com );
01039 com->deleteLater();
01040 }
01041 #ifdef Q_OS_UNIX
01042 else
01043 KWindowSystem::activateWindow(com->winId());
01044 #endif
01045 }
01046
01047
01048 void KNArticleFactory::slotSendErrorDialogDone()
01049 {
01050 s_endErrDlg->deleteLater();
01051 s_endErrDlg=0;
01052 }
01053
01054
01055
01056
01057
01058 KNSendErrorDialog::KNSendErrorDialog()
01059 : KDialog( knGlobals.topWidget )
01060 {
01061 setCaption( i18n("Errors While Sending") );
01062 setButtons( Close );
01063 KVBox *page = new KVBox( this );
01064 setMainWidget( page );
01065 setDefaultButton( Close );
01066
01067 new QLabel(QString("<b>%1</b><br>%2").arg(i18n("Errors occurred while sending these articles:"))
01068 .arg(i18n("The unsent articles are stored in the \"Outbox\" folder.")), page);
01069 mErrorList = new QListWidget( page );
01070 mError = new QLabel( QString(), page );
01071 mError->setWordWrap( true );
01072
01073 connect( mErrorList, SIGNAL( currentRowChanged( int ) ), SLOT( slotHighlighted( int ) ) );
01074
01075 KNHelper::restoreWindowSize("sendDlg", this, QSize(320,250));
01076 }
01077
01078
01079 KNSendErrorDialog::~KNSendErrorDialog()
01080 {
01081 KNHelper::saveWindowSize("sendDlg", size());
01082 }
01083
01084
01085 void KNSendErrorDialog::append(const QString &subject, const QString &error)
01086 {
01087 ErrorListItem *item = new ErrorListItem( subject, error );
01088 item->setIcon( UserIcon("snderr") );
01089 mErrorList->addItem( item );
01090 mErrorList->setCurrentItem( item );
01091 }
01092
01093
01094 void KNSendErrorDialog::slotHighlighted(int idx)
01095 {
01096 ErrorListItem *item = static_cast<ErrorListItem*>( mErrorList->item( idx ) );
01097 if ( item ) {
01098 QString tmp = i18n("<b>Error message:</b><br />") + item->error();
01099 mError->setText( tmp );
01100 }
01101 }
01102
01103
01104 #include "knarticlefactory.moc"