summaryrefslogtreecommitdiffstats
path: root/knode/knarticlefactory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'knode/knarticlefactory.cpp')
-rw-r--r--knode/knarticlefactory.cpp1111
1 files changed, 1111 insertions, 0 deletions
diff --git a/knode/knarticlefactory.cpp b/knode/knarticlefactory.cpp
new file mode 100644
index 000000000..3c072887b
--- /dev/null
+++ b/knode/knarticlefactory.cpp
@@ -0,0 +1,1111 @@
+/*
+ KNode, the KDE newsreader
+ Copyright (c) 1999-2005 the KNode authors.
+ See file AUTHORS for details
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US
+*/
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qvbox.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kwin.h>
+#include <kapplication.h>
+
+#include "knarticlefactory.h"
+#include "knglobals.h"
+#include "knconfigmanager.h"
+#include "kngroupmanager.h"
+#include "knaccountmanager.h"
+#include "knfoldermanager.h"
+#include "knarticlemanager.h"
+#include "knfolder.h"
+#include "kncomposer.h"
+#include "knnntpaccount.h"
+#include "utilities.h"
+#include "resource.h"
+
+
+KNArticleFactory::KNArticleFactory(QObject *p, const char *n)
+ : QObject(p, n), s_endErrDlg(0)
+{
+}
+
+
+KNArticleFactory::~KNArticleFactory()
+{
+ for ( QValueList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
+ delete (*it);
+ delete s_endErrDlg;
+}
+
+
+void KNArticleFactory::createPosting(KNNntpAccount *a)
+{
+ if(!a)
+ return;
+
+ QString sig;
+ KNLocalArticle *art=newArticle(a, sig, knGlobals.configManager()->postNewsTechnical()->charset());
+ if(!art)
+ return;
+
+ art->setServerId(a->id());
+ art->setDoPost(true);
+ art->setDoMail(false);
+
+ KNComposer *c = new KNComposer( art, QString::null, sig, QString::null, true );
+ mCompList.append( c );
+ connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
+ c->show();
+}
+
+
+void KNArticleFactory::createPosting(KNGroup *g)
+{
+ if(!g)
+ return;
+
+ QCString chset;
+ if (g->useCharset())
+ chset = g->defaultCharset();
+ else
+ chset = knGlobals.configManager()->postNewsTechnical()->charset();
+
+ QString sig;
+ KNLocalArticle *art=newArticle(g, sig, chset);
+
+ if(!art)
+ return;
+
+ art->setServerId(g->account()->id());
+ art->setDoPost(true);
+ art->setDoMail(false);
+ art->newsgroups()->fromUnicodeString(g->groupname(), art->defaultCharset());
+
+ KNComposer *c=new KNComposer(art, QString::null, sig, QString::null, true);
+ mCompList.append( c );
+ connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
+ c->show();
+}
+
+
+void KNArticleFactory::createReply(KNRemoteArticle *a, QString selectedText, bool post, bool mail)
+{
+ if(!a)
+ return;
+
+ KNGroup *g=static_cast<KNGroup*>(a->collection());
+
+ QCString chset;
+ if (knGlobals.configManager()->postNewsTechnical()->useOwnCharset()) {
+ if (g->useCharset())
+ chset = g->defaultCharset();
+ else
+ chset = knGlobals.configManager()->postNewsTechnical()->charset();
+ } else
+ chset = knGlobals.configManager()->postNewsTechnical()->findComposerCharset(a->contentType()->charset());
+
+ //create new article
+ QString sig;
+ KNLocalArticle *art=newArticle(g, sig, chset, true, a);
+ if(!art)
+ return;
+
+ art->setServerId(g->account()->id());
+ art->setDoPost(post);
+ art->setDoMail(mail);
+
+ //------------------------- <Headers> ----------------------------
+
+ //subject
+ QString subject=a->subject()->asUnicodeString();
+ if(subject.left(3).upper()!="RE:")
+ subject.prepend("Re: ");
+ art->subject()->fromUnicodeString(subject, a->subject()->rfc2047Charset());
+
+ //newsgroups
+ KMime::Headers::FollowUpTo *fup2=a->followUpTo(false);
+ if(fup2 && !fup2->isEmpty()) {
+ if( ( fup2->as7BitString(false).upper()=="POSTER" ) ) { //Followup-To: poster
+ if( post && // user wanted to reply by public posting?
+ // ask the user if she wants to ignore this F'up-To: poster
+ ( KMessageBox::Yes != KMessageBox::questionYesNo(knGlobals.topWidget,
+ 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::null, i18n("Reply Public"), i18n("Reply by Email")) ))
+ {
+ art->setDoPost(false);
+ art->setDoMail(true);
+ }
+ art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false));
+ }
+ else
+ art->newsgroups()->from7BitString(fup2->as7BitString(false));
+ }
+ else
+ art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false));
+
+ //To
+ KMime::Headers::ReplyTo *replyTo=a->replyTo(false);
+ KMime::Headers::AddressField address;
+ if(replyTo && !replyTo->isEmpty()) {
+ if(replyTo->hasName())
+ address.setName(replyTo->name());
+ if(replyTo->hasEmail())
+ address.setEmail(replyTo->email().copy());
+ }
+ else {
+ KMime::Headers::From *from=a->from();
+ if(from->hasName())
+ address.setName(from->name());
+ if(from->hasEmail())
+ address.setEmail(from->email().copy());
+ }
+ art->to()->addAddress(address);
+
+ //References
+ KMime::Headers::References *references=a->references(false);
+ QCString refs;
+ if (references)
+ refs=references->as7BitString(false);
+ else
+ refs = "";
+
+ art->references()->from7BitString(refs);
+ art->references()->append(a->messageID()->as7BitString(false));
+
+ //Mail-Copies-To
+ bool authorDislikesMailCopies=false;
+ bool authorWantsMailCopies=false;
+ KMime::Headers::MailCopiesTo *mailCopiesTo=a->mailCopiesTo(false);
+
+ if(mailCopiesTo && !mailCopiesTo->isEmpty() && mailCopiesTo->isValid()) {
+ authorDislikesMailCopies = mailCopiesTo->neverCopy();
+ authorWantsMailCopies = mailCopiesTo->alwaysCopy();
+ if (authorWantsMailCopies) // warn the user
+ KMessageBox::information(knGlobals.topWidget,i18n("The author requested a mail copy of your reply. (Mail-Copies-To header)"),
+ QString::null,"mailCopiesToWarning");
+ if (authorWantsMailCopies && mailCopiesTo->hasEmail()) {
+ address.setName(mailCopiesTo->name());
+ address.setEmail(mailCopiesTo->email());
+ art->to()->clear();
+ art->to()->addAddress(address);
+ }
+ }
+
+ //------------------------- </Headers> ---------------------------
+
+ //--------------------------- <Body> -----------------------------
+
+ // attribution line
+ QString attribution=knGlobals.configManager()->postNewsComposer()->intro();
+ QString name(a->from()->name());
+ if (name.isEmpty())
+ name = QString::fromLatin1(a->from()->email());
+ attribution.replace(QRegExp("%NAME"),name);
+ attribution.replace(QRegExp("%EMAIL"),QString::fromLatin1(a->from()->email()));
+ attribution.replace(QRegExp("%DATE"),KGlobal::locale()->formatDateTime(a->date()->qdt(),false));
+ attribution.replace(QRegExp("%MSID"),a->messageID()->asUnicodeString());
+ attribution.replace(QRegExp("%GROUP"),g->groupname());
+ attribution.replace(QRegExp("%L"),"\n");
+ attribution+="\n\n";
+
+ QString quoted=attribution;
+ QString notRewraped=QString::null;
+ QStringList text;
+ QStringList::Iterator line;
+ bool incSig=knGlobals.configManager()->postNewsComposer()->includeSignature();
+
+ if (selectedText.isEmpty()) {
+ KMime::Content *tc = a->textContent();
+ if(tc)
+ tc->decodedText(text, true, knGlobals.configManager()->readNewsViewer()->removeTrailingNewlines());
+ }
+ else
+ text = QStringList::split('\n',selectedText,true);
+
+ for(line=text.begin(); line!=text.end(); ++line) {
+ if(!incSig && (*line)=="-- ")
+ break;
+
+ if ((*line)[0]=='>')
+ quoted+=">"+(*line)+"\n"; // second quote level without space
+ else
+ quoted+="> "+(*line)+"\n";
+ }
+
+ if(knGlobals.configManager()->postNewsComposer()->rewrap()) { //rewrap original article
+
+ notRewraped=quoted; // store the original text in here, the user can request it in the composer
+ quoted=attribution;
+
+ quoted += KNHelper::rewrapStringList(text, knGlobals.configManager()->postNewsComposer()->maxLineLength(), '>', !incSig, false);
+ }
+
+ //-------------------------- </Body> -----------------------------
+
+ if (art->doMail() && knGlobals.configManager()->postNewsTechnical()->useExternalMailer()) {
+ sendMailExternal(address.asUnicodeString(), subject, quoted);
+ art->setDoMail(false);
+ if (!art->doPost()) {
+ delete art;
+ return;
+ }
+ }
+
+ //open composer
+ KNComposer *c=new KNComposer(art, quoted, sig, notRewraped, true, authorDislikesMailCopies, authorWantsMailCopies);
+ mCompList.append( c );
+ connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
+ c->show();
+}
+
+
+void KNArticleFactory::createForward(KNArticle *a)
+{
+ if(!a)
+ return;
+
+ KMime::Headers::ContentType *ct=a->contentType();
+ QCString chset;
+ bool incAtt = ( !knGlobals.configManager()->postNewsTechnical()->useExternalMailer() &&
+ ct->isMultipart() && ct->isSubtype("mixed") &&
+ KMessageBox::Yes == KMessageBox::questionYesNo(knGlobals.topWidget,
+ i18n("This article contains attachments. Do you want them to be forwarded as well?"), QString::null, i18n("Forward"), i18n("Do Not Forward"))
+ );
+
+ if (knGlobals.configManager()->postNewsTechnical()->useOwnCharset())
+ chset = knGlobals.configManager()->postNewsTechnical()->charset();
+ else
+ chset = knGlobals.configManager()->postNewsTechnical()->findComposerCharset(a->contentType()->charset());
+
+ //create new article
+ QString sig;
+ KNLocalArticle *art=newArticle(knGlobals.groupManager()->currentGroup(), sig, chset);
+ if(!art)
+ return;
+
+ art->setDoPost(false);
+ art->setDoMail(true);
+
+ //------------------------- <Headers> ----------------------------
+
+ //subject
+ QString subject=("Fwd: "+a->subject()->asUnicodeString());
+ art->subject()->fromUnicodeString(subject, a->subject()->rfc2047Charset());
+
+ //------------------------- </Headers> ---------------------------
+
+ //--------------------------- <Body> -----------------------------
+
+ QString fwd = QString("\n--------------- %1\n\n").arg(i18n("Forwarded message (begin)"));
+
+ fwd+=( i18n("Subject") + ": " + a->subject()->asUnicodeString() + "\n" );
+ fwd+=( i18n("From") + ": " + a->from()->asUnicodeString() + "\n" );
+ fwd+=( i18n("Date") + ": " + a->date()->asUnicodeString() + "\n" );
+ fwd+=( i18n("Newsgroup") + ": " + a->newsgroups()->asUnicodeString() + "\n\n" );
+
+ KMime::Content *text=a->textContent();
+ if(text) {
+ QStringList decodedLines;
+ text->decodedText( decodedLines, false, false );
+ for(QStringList::Iterator it=decodedLines.begin(); it!=decodedLines.end(); ++it)
+ fwd += (*it) + "\n";
+ }
+
+ fwd += QString("\n--------------- %1\n").arg(i18n("Forwarded message (end)"));
+
+ //--------------------------- </Body> ----------------------------
+
+
+ //------------------------ <Attachments> -------------------------
+
+ if(incAtt) {
+ KMime::Content::List al;
+
+ a->attachments(&al, false);
+ for(KMime::Content *c=al.first(); c; c=al.next()) {
+ art->addContent( new KMime::Content(c->head(), c->body()) );
+ }
+ }
+
+ //------------------------ </Attachments> ------------------------
+
+
+ if (knGlobals.configManager()->postNewsTechnical()->useExternalMailer()) {
+ sendMailExternal(QString::null, subject, fwd);
+ delete art;
+ return;
+ }
+
+ //open composer
+ KNComposer *c=new KNComposer(art, fwd, sig, QString::null, true);
+ mCompList.append( c );
+ connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
+ c->show();
+}
+
+
+void KNArticleFactory::createCancel(KNArticle *a)
+{
+ if(!cancelAllowed(a))
+ return;
+
+ if(KMessageBox::No==KMessageBox::questionYesNo(knGlobals.topWidget,
+ i18n("Do you really want to cancel this article?"), QString::null, i18n("Cancel Article"), KStdGuiItem::cancel()))
+ return;
+
+ bool sendNow;
+ switch (KMessageBox::warningYesNoCancel(knGlobals.topWidget, i18n("Do you want to send the cancel\nmessage now or later?"), i18n("Question"),i18n("&Now"),i18n("&Later"))) {
+ case KMessageBox::Yes : sendNow = true; break;
+ case KMessageBox::No : sendNow = false; break;
+ default : return;
+ }
+
+ KNGroup *grp;
+ KNNntpAccount *nntp=0;
+
+ if(a->type()==KMime::Base::ATremote)
+ nntp=(static_cast<KNGroup*>(a->collection()))->account();
+ else {
+ if(!nntp)
+ nntp=knGlobals.accountManager()->first();
+ if(!nntp) {
+ KMessageBox::error(knGlobals.topWidget, i18n("You have no valid news accounts configured."));
+ return;
+ }
+ KNLocalArticle *la=static_cast<KNLocalArticle*>(a);
+ la->setCanceled(true);
+ la->updateListItem();
+ nntp=knGlobals.accountManager()->account(la->serverId());
+ }
+
+ grp=knGlobals.groupManager()->group(a->newsgroups()->firstGroup(), nntp);
+
+ QString sig;
+ KNLocalArticle *art=newArticle(grp, sig, "us-ascii", false);
+ if(!art)
+ return;
+
+ //init
+ art->setDoPost(true);
+ art->setDoMail(false);
+
+ //server
+ art->setServerId(nntp->id());
+
+ //subject
+ KMime::Headers::MessageID *msgId=a->messageID();
+ QCString tmp;
+ tmp="cancel of "+msgId->as7BitString(false);
+ art->subject()->from7BitString(tmp);
+
+ //newsgroups
+ art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false));
+
+ //control
+ tmp="cancel "+msgId->as7BitString(false);
+ art->control()->from7BitString(tmp);
+
+ //Lines
+ art->lines()->setNumberOfLines(1);
+
+ //body
+ art->fromUnicodeString(QString::fromLatin1("cancel by original author\n"));
+
+ //assemble
+ art->assemble();
+
+ //send
+ KNLocalArticle::List lst;
+ lst.append(art);
+ sendArticles( lst, sendNow );
+}
+
+
+void KNArticleFactory::createSupersede(KNArticle *a)
+{
+ if (!a)
+ return;
+
+ if(!cancelAllowed(a))
+ return;
+
+ if(KMessageBox::No==KMessageBox::questionYesNo(knGlobals.topWidget,
+ i18n("Do you really want to supersede this article?"), QString::null, i18n("Supersede"), KStdGuiItem::cancel()))
+ return;
+
+ KNGroup *grp;
+ KNNntpAccount *nntp;
+
+ if(a->type()==KMime::Base::ATremote)
+ nntp=(static_cast<KNGroup*>(a->collection()))->account();
+ else {
+ KNLocalArticle *la=static_cast<KNLocalArticle*>(a);
+ la->setCanceled(true);
+ la->updateListItem();
+ nntp=knGlobals.accountManager()->account(la->serverId());
+ if(!nntp)
+ nntp=knGlobals.accountManager()->first();
+ if(!nntp) {
+ KMessageBox::error(knGlobals.topWidget, i18n("You have no valid news accounts configured."));
+ return;
+ }
+ }
+
+ grp=knGlobals.groupManager()->group(a->newsgroups()->firstGroup(), nntp);
+
+ //new article
+ QString sig;
+ KNLocalArticle *art=newArticle(grp, sig, knGlobals.configManager()->postNewsTechnical()->findComposerCharset(a->contentType()->charset()));
+ if(!art)
+ return;
+
+ art->setDoPost(true);
+ art->setDoMail(false);
+
+ //server
+ art->setServerId(nntp->id());
+
+ //subject
+ art->subject()->fromUnicodeString(a->subject()->asUnicodeString(), a->subject()->rfc2047Charset());
+
+ //newsgroups
+ art->newsgroups()->from7BitString(a->newsgroups()->as7BitString(false));
+
+ //followup-to
+ art->followUpTo()->from7BitString(a->followUpTo()->as7BitString(false));
+
+ //References
+ if ( !a->references()->isEmpty() )
+ art->references()->from7BitString( a->references()->as7BitString(false) );
+
+ //Supersedes
+ art->supersedes()->from7BitString(a->messageID()->as7BitString(false));
+
+ //Body
+ QString text;
+ KMime::Content *textContent=a->textContent();
+ if(textContent)
+ textContent->decodedText(text);
+
+ //open composer
+ KNComposer *c=new KNComposer(art, text, sig);
+ mCompList.append( c );
+ connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
+ c->show();
+}
+
+
+void KNArticleFactory::createMail(KMime::Headers::AddressField *address)
+{
+ if (knGlobals.configManager()->postNewsTechnical()->useExternalMailer()) {
+ sendMailExternal(address->asUnicodeString());
+ return;
+ }
+
+ //create new article
+ QString sig;
+ KNLocalArticle *art=newArticle(knGlobals.groupManager()->currentGroup(), sig, knGlobals.configManager()->postNewsTechnical()->charset());
+ if(!art)
+ return;
+
+ art->setDoMail(true);
+ art->setDoPost(false);
+ art->to()->addAddress((*address));
+
+ //open composer
+ KNComposer *c=new KNComposer(art, QString::null, sig, QString::null, true);
+ mCompList.append( c );
+ connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
+ c->show();
+}
+
+
+void KNArticleFactory::sendMailExternal(const QString &address, const QString &subject, const QString &body)
+{
+ KURL mailtoURL;
+ QStringList queries;
+ QString query=QString::null;
+ mailtoURL.setProtocol("mailto");
+
+ if (!address.isEmpty())
+ mailtoURL.setPath(address);
+ if (!subject.isEmpty())
+ queries.append("subject="+KURL::encode_string(subject));
+ if (!body.isEmpty())
+ queries.append("body="+KURL::encode_string(body));
+
+ if (queries.count() > 0) {
+ query = "?";
+ for ( QStringList::Iterator it = queries.begin(); it != queries.end(); ++it ) {
+ if (it != queries.begin())
+ query.append("&");
+ query.append((*it));
+ }
+ }
+
+ if (!query.isEmpty())
+ mailtoURL.setQuery(query);
+
+ kapp->invokeMailer(mailtoURL);
+}
+
+
+void KNArticleFactory::edit(KNLocalArticle *a)
+{
+ if(!a)
+ return;
+
+ KNComposer *com=findComposer(a);
+ if(com) {
+ KWin::activateWindow(com->winId());
+ return;
+ }
+
+ if(a->editDisabled()) {
+ KMessageBox::sorry(knGlobals.topWidget, i18n("This article cannot be edited."));
+ return;
+ }
+
+ //find signature
+ KNConfig::Identity *id=knGlobals.configManager()->identity();
+
+ if(a->doPost()) {
+ KNNntpAccount *acc=knGlobals.accountManager()->account(a->serverId());
+ if(acc) {
+ KMime::Headers::Newsgroups *grps=a->newsgroups();
+ KNGroup *grp=knGlobals.groupManager()->group(grps->firstGroup(), acc);
+ if (grp && grp->identity())
+ id=grp->identity();
+ else if (acc->identity())
+ id=acc->identity();
+ }
+ }
+
+ //load article body
+ if(!a->hasContent())
+ knGlobals.articleManager()->loadArticle(a);
+
+ //open composer
+ com=new KNComposer(a, QString::null, id->getSignature());
+ if(id->useSigGenerator() && !id->getSigGeneratorStdErr().isEmpty())
+ KMessageBox::information(knGlobals.topWidget,
+ i18n("<qt>The signature generator program produced the "
+ "following output:<br><br>%1</qt>")
+ .arg(id->getSigGeneratorStdErr()));
+
+ mCompList.append( com );
+ connect(com, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
+ com->show();
+}
+
+
+void KNArticleFactory::sendArticles( KNLocalArticle::List &l, bool now )
+{
+ KNJobData *job=0;
+ KNServerInfo *ser=0;
+
+ KNLocalArticle::List unsent, sent;
+ for ( KNLocalArticle::List::Iterator it = l.begin(); it != l.end(); ++it ) {
+ if ( (*it)->pending() )
+ unsent.append( (*it) );
+ else
+ sent.append( (*it) );
+ }
+
+ if(!sent.isEmpty()) {
+ showSendErrorDialog();
+ for ( KNLocalArticle::List::Iterator it = sent.begin(); it != sent.end(); ++it )
+ s_endErrDlg->append( (*it)->subject()->asUnicodeString(), i18n("Article has already been sent.") );
+ }
+
+ if(!now) {
+ knGlobals.articleManager()->moveIntoFolder(unsent, knGlobals.folderManager()->outbox());
+ return;
+ }
+
+
+ for ( KNLocalArticle::List::Iterator it = unsent.begin(); it != unsent.end(); ++it ) {
+
+ if ( (*it)->isLocked() )
+ continue;
+
+ if ( !(*it)->hasContent() ) {
+ if ( !knGlobals.articleManager()->loadArticle( (*it) ) ) {
+ showSendErrorDialog();
+ s_endErrDlg->append( (*it)->subject()->asUnicodeString(), i18n("Unable to load article.") );
+ continue;
+ }
+ }
+
+ if ( (*it)->doPost() && !(*it)->posted() ) {
+ ser = knGlobals.accountManager()->account( (*it)->serverId() );
+ job = new KNJobData( KNJobData::JTpostArticle, this, ser, (*it) );
+ emitJob(job);
+ }
+ else if( (*it)->doMail() && !(*it)->mailed() ) {
+ ser = knGlobals.accountManager()->smtp();
+ job = new KNJobData( KNJobData::JTmail, this, ser, (*it) );
+ emitJob(job);
+ }
+ }
+}
+
+
+void KNArticleFactory::sendOutbox()
+{
+ KNLocalArticle::List lst;
+ KNFolder *ob=0;
+
+ if(!knGlobals.folderManager()->loadOutbox()) {
+ KMessageBox::error(knGlobals.topWidget, i18n("Unable to load the outbox-folder."));
+ return;
+ }
+
+ ob=knGlobals.folderManager()->outbox();
+ for(int i=0; i< ob->length(); i++)
+ lst.append(ob->at(i));
+
+ sendArticles( lst, true );
+}
+
+
+bool KNArticleFactory::closeComposeWindows()
+{
+ while ( !mCompList.isEmpty() ) {
+ QValueList<KNComposer*>::Iterator it = mCompList.begin();
+ if ( !(*it)->close() )
+ return false;
+ }
+
+ return true;
+}
+
+
+void KNArticleFactory::deleteComposerForArticle(KNLocalArticle *a)
+{
+ KNComposer *com = findComposer( a );
+ if ( com ) {
+ mCompList.remove( com );
+ delete com;
+ }
+}
+
+
+KNComposer* KNArticleFactory::findComposer(KNLocalArticle *a)
+{
+ for ( QValueList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
+ if ( (*it)->article() == a )
+ return (*it);
+ return 0;
+}
+
+
+void KNArticleFactory::configChanged()
+{
+ for ( QValueList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
+ (*it)->setConfig( false );
+}
+
+
+void KNArticleFactory::processJob(KNJobData *j)
+{
+ KNLocalArticle *art=static_cast<KNLocalArticle*>(j->data());
+ KNLocalArticle::List lst;
+ lst.append(art);
+
+ if(j->canceled()) {
+ delete j;
+
+ //sending of this article was canceled => move it to the "Outbox-Folder"
+ if(art->collection()!=knGlobals.folderManager()->outbox())
+ knGlobals.articleManager()->moveIntoFolder(lst, knGlobals.folderManager()->outbox());
+
+ KMessageBox::information(knGlobals.topWidget, i18n("You have aborted the posting of articles. The unsent articles are stored in the \"Outbox\" folder."));
+
+ return;
+ }
+
+ if(!j->success()) {
+ showSendErrorDialog();
+ s_endErrDlg->append(art->subject()->asUnicodeString(), j->errorString());
+ delete j; //unlock article
+
+ //sending of this article failed => move it to the "Outbox-Folder"
+ if(art->collection()!=knGlobals.folderManager()->outbox())
+ knGlobals.articleManager()->moveIntoFolder(lst, knGlobals.folderManager()->outbox());
+ }
+ else {
+
+ //disable edit
+ art->setEditDisabled(true);
+
+ switch(j->type()) {
+
+ case KNJobData::JTpostArticle:
+ delete j; //unlock article
+ art->setPosted(true);
+ if(art->doMail() && !art->mailed()) { //article has been posted, now mail it
+ sendArticles( lst, true );
+ return;
+ }
+ break;
+
+ case KNJobData::JTmail:
+ delete j; //unlock article
+ art->setMailed(true);
+ break;
+
+ default: break;
+ };
+
+ //article has been sent successfully => move it to the "Sent-folder"
+ knGlobals.articleManager()->moveIntoFolder(lst, knGlobals.folderManager()->sent());
+ }
+}
+
+
+KNLocalArticle* KNArticleFactory::newArticle(KNCollection *col, QString &sig, QCString defChset, bool withXHeaders, KNArticle *origPost)
+{
+ KNConfig::PostNewsTechnical *pnt=knGlobals.configManager()->postNewsTechnical();
+
+ if(pnt->generateMessageID() && pnt->hostname().isEmpty()) {
+ KMessageBox::sorry(knGlobals.topWidget, i18n("Please set a hostname for the generation\nof the message-id or disable it."));
+ return 0;
+ }
+
+ KNLocalArticle *art=new KNLocalArticle(0);
+ KNConfig::Identity *tmpId=0, *id=0;
+
+ if (col) {
+ if (col->type() == KNCollection::CTgroup) {
+ id = (static_cast<KNGroup *>(col))->identity();
+ tmpId = (static_cast<KNGroup *>(col))->account()->identity();
+ } else
+ if (col->type() == KNCollection::CTnntpAccount) {
+ id = (static_cast<KNNntpAccount *>(col))->identity();
+ }
+ }
+
+ // determine active innermost non-empty identity
+ if (!id) {
+ if (tmpId)
+ id = tmpId;
+ else
+ id = knGlobals.configManager()->identity();
+ }
+
+ //Message-id
+ if(pnt->generateMessageID())
+ art->messageID()->generate(pnt->hostname());
+
+ //From
+ KMime::Headers::From *from=art->from();
+ from->setRFC2047Charset(pnt->charset());
+
+ //name
+ if(id->hasName())
+ from->setName(id->name());
+
+ //email
+ if(id->hasEmail()&&id->emailIsValid())
+ from->setEmail(id->email().latin1());
+ else {
+ if ( id->hasEmail() )
+ KMessageBox::sorry(knGlobals.topWidget,
+ i18n("Please enter a valid email address at the identity tab of the account configuration dialog."));
+ else
+ KMessageBox::sorry(knGlobals.topWidget,
+ i18n("Please enter a valid email address at the identity section of the configuration dialog."));
+ delete art;
+ return 0;
+ }
+
+ //Reply-To
+ if(id->hasReplyTo()) {
+ art->replyTo()->fromUnicodeString(id->replyTo(), pnt->charset());
+ if (!art->replyTo()->hasEmail()) // the header is invalid => drop it
+ art->removeHeader("Reply-To");
+ }
+
+ //Mail-Copies-To
+ if(id->hasMailCopiesTo()) {
+ art->mailCopiesTo()->fromUnicodeString(id->mailCopiesTo(), pnt->charset());
+ if (!art->mailCopiesTo()->isValid()) // the header is invalid => drop it
+ art->removeHeader("Mail-Copies-To");
+ }
+
+ //Organization
+ if(id->hasOrga())
+ art->organization()->fromUnicodeString(id->orga(), pnt->charset());
+
+ //Date
+ art->date()->setUnixTime(); //set current date+time
+
+ //User-Agent
+ if( !pnt->noUserAgent() ) {
+ art->userAgent()->from7BitString("KNode/" KNODE_VERSION);
+ }
+
+ //Mime
+ KMime::Headers::ContentType *type=art->contentType();
+ type->setMimeType("text/plain");
+
+ type->setCharset(defChset);
+
+ if (defChset.lower()=="us-ascii")
+ art->contentTransferEncoding()->setCte(KMime::Headers::CE7Bit);
+ else
+ art->contentTransferEncoding()->setCte(pnt->allow8BitBody()? KMime::Headers::CE8Bit : KMime::Headers::CEquPr);
+
+ //X-Headers
+ if(withXHeaders) {
+ KNConfig::XHeaders::Iterator it;
+ for(it=pnt->xHeaders().begin(); it!=pnt->xHeaders().end(); ++it) {
+ QString value = (*it).value();
+ if(origPost) {
+ QString name(origPost->from()->name());
+ if (name.isEmpty())
+ name = QString::fromLatin1(origPost->from()->email());
+ value.replace(QRegExp("%NAME"), name);
+ value.replace(QRegExp("%EMAIL"), QString::fromLatin1(origPost->from()->email()));
+ }
+ else
+ if(value.find("%NAME") != -1 || value.find("%EMAIL") != -1)
+ continue;
+
+ art->setHeader( new KMime::Headers::Generic( (QCString("X-")+(*it).name()), art, value, pnt->charset() ) );
+ }
+ }
+
+ //Signature
+ if(id->hasSignature())
+ {
+ sig=id->getSignature();
+ if(id->useSigGenerator() && !id->getSigGeneratorStdErr().isEmpty())
+ KMessageBox::information(knGlobals.topWidget,
+ i18n("<qt>The signature generator program produced the "
+ "following output:<br><br>%1</qt>")
+ .arg(id->getSigGeneratorStdErr()));
+ }
+ else
+ sig=QString::null;
+
+ return art;
+}
+
+
+bool KNArticleFactory::cancelAllowed(KNArticle *a)
+{
+ if(!a)
+ return false;
+
+ if(a->type()==KMime::Base::ATlocal) {
+ KNLocalArticle *localArt=static_cast<KNLocalArticle*>(a);
+
+ if(localArt->doMail() && !localArt->doPost()) {
+ KMessageBox::sorry(knGlobals.topWidget, i18n("Emails cannot be canceled or superseded."));
+ return false;
+ }
+
+ KMime::Headers::Control *ctrl=localArt->control(false);
+ if(ctrl && ctrl->isCancel()) {
+ KMessageBox::sorry(knGlobals.topWidget, i18n("Cancel messages cannot be canceled or superseded."));
+ return false;
+ }
+
+ if(!localArt->posted()) {
+ KMessageBox::sorry(knGlobals.topWidget, i18n("Only sent articles can be canceled or superseded."));
+ return false;
+ }
+
+ if(localArt->canceled()) {
+ KMessageBox::sorry(knGlobals.topWidget, i18n("This article has already been canceled or superseded."));
+ return false;
+ }
+
+ KMime::Headers::MessageID *mid=localArt->messageID(false);
+ if(!mid || mid->isEmpty()) {
+ KMessageBox::sorry(knGlobals.topWidget, i18n(
+"This article cannot be canceled or superseded,\n\
+because its message-id has not been created by KNode.\n\
+But you can look for your article in the newsgroup\n\
+and cancel (or supersede) it there."));
+ return false;
+ }
+
+ return true;
+ }
+ else if(a->type()==KMime::Base::ATremote) {
+
+ KNRemoteArticle *remArt=static_cast<KNRemoteArticle*>(a);
+ KNGroup *g=static_cast<KNGroup*>(a->collection());
+ KNConfig::Identity *defId=knGlobals.configManager()->identity(),
+ *gid=g->identity(),
+ *accId=g->account()->identity();
+ bool ownArticle = false;
+
+ if (gid && gid->hasName())
+ ownArticle |= ( gid->name() == remArt->from()->name() );
+ if (accId && accId->hasName())
+ ownArticle |= ( accId->name() == remArt->from()->name() );
+ ownArticle |= ( defId->name() == remArt->from()->name() );
+
+ if(ownArticle) {
+ ownArticle = false;
+ if(gid && gid->hasEmail())
+ ownArticle |= ( gid->email().latin1() == remArt->from()->email() );
+ if (accId && accId->hasEmail())
+ ownArticle |= ( accId->email().latin1() == remArt->from()->email() );
+ ownArticle |= ( defId->email().latin1() == remArt->from()->email() );
+ }
+
+ if(!ownArticle) {
+ KMessageBox::sorry(knGlobals.topWidget, i18n("This article does not appear to be from you.\nYou can only cancel or supersede your own articles."));
+ return false;
+ }
+
+ if(!remArt->hasContent()) {
+ KMessageBox::sorry(knGlobals.topWidget, i18n("You have to download the article body\nbefore you can cancel or supersede the article."));
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+
+void KNArticleFactory::showSendErrorDialog()
+{
+ if(!s_endErrDlg) {
+ s_endErrDlg=new KNSendErrorDialog();
+ connect(s_endErrDlg, SIGNAL(closeClicked()), this, SLOT(slotSendErrorDialogDone()));
+ }
+ s_endErrDlg->show();
+}
+
+
+void KNArticleFactory::slotComposerDone(KNComposer *com)
+{
+ bool delCom=true;
+ KNLocalArticle::List lst;
+ lst.append(com->article());
+
+ switch(com->result()) {
+
+ case KNComposer::CRsendNow:
+ delCom=com->hasValidData();
+ if(delCom) {
+ if ( com->applyChanges() )
+ sendArticles( lst, true );
+ else
+ delCom = false;
+ }
+ break;
+
+ case KNComposer::CRsendLater:
+ delCom=com->hasValidData();
+ if(delCom) {
+ if ( com->applyChanges() )
+ sendArticles( lst, false );
+ else
+ delCom = false;
+ }
+ break;
+
+ case KNComposer::CRsave :
+ if ( com->applyChanges() )
+ knGlobals.articleManager()->moveIntoFolder(lst, knGlobals.folderManager()->drafts());
+ break;
+
+ case KNComposer::CRdelAsk:
+ delCom=knGlobals.articleManager()->deleteArticles(lst, true);
+ break;
+
+ case KNComposer::CRdel:
+ delCom=knGlobals.articleManager()->deleteArticles(lst, false);
+ break;
+
+ case KNComposer::CRcancel:
+ // just close...
+ break;
+
+ default: break;
+
+ };
+
+ if ( delCom ) {
+ mCompList.remove( com );
+ delete com;
+ } else
+ KWin::activateWindow(com->winId());
+}
+
+
+void KNArticleFactory::slotSendErrorDialogDone()
+{
+ s_endErrDlg->delayedDestruct();
+ s_endErrDlg=0;
+}
+
+
+//======================================================================================================
+
+
+KNSendErrorDialog::KNSendErrorDialog()
+ : KDialogBase(knGlobals.topWidget, 0, true, i18n("Errors While Sending"), Close, Close, true)
+{
+ p_ixmap=knGlobals.configManager()->appearance()->icon(KNConfig::Appearance::sendErr);
+
+ QVBox *page = makeVBoxMainWidget();
+
+ new QLabel(QString("<b>%1</b><br>%2").arg(i18n("Errors occurred while sending these articles:"))
+ .arg(i18n("The unsent articles are stored in the \"Outbox\" folder.")), page);
+ j_obs=new KNDialogListBox(true, page);
+ e_rror=new QLabel(QString::null, page);
+
+ connect(j_obs, SIGNAL(highlighted(int)), this, SLOT(slotHighlighted(int)));
+
+ KNHelper::restoreWindowSize("sendDlg", this, QSize(320,250));
+}
+
+
+KNSendErrorDialog::~KNSendErrorDialog()
+{
+ KNHelper::saveWindowSize("sendDlg", size());
+}
+
+
+void KNSendErrorDialog::append(const QString &subject, const QString &error)
+{
+
+ LBoxItem *it=new LBoxItem(error, subject, &p_ixmap);
+ j_obs->insertItem(it);
+ j_obs->setCurrentItem(it);
+}
+
+
+void KNSendErrorDialog::slotHighlighted(int idx)
+{
+ LBoxItem *it=static_cast<LBoxItem*>(j_obs->item(idx));
+ if(it) {
+ QString tmp=i18n("<b>Error message:</b><br>")+it->error;
+ e_rror->setText(tmp);
+ }
+}
+
+//-------------------------------
+#include "knarticlefactory.moc"
+
+// kate: space-indent on; indent-width 2;