mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 18:32:51 +00:00
1077 lines
31 KiB
C++
1077 lines
31 KiB
C++
/*
|
|
KNode, the KDE newsreader
|
|
Copyright (c) 1999-2006 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 "knarticlefactory.h"
|
|
|
|
#include "knglobals.h"
|
|
#include "kngroupmanager.h"
|
|
#include "knaccountmanager.h"
|
|
#include "knfoldermanager.h"
|
|
#include "knarticlemanager.h"
|
|
#include "knfolder.h"
|
|
#include "kncomposer.h"
|
|
#include "knnntpaccount.h"
|
|
#include "mailsendjob.h"
|
|
#include "nntpjobs.h"
|
|
#include "utilities.h"
|
|
#include "resource.h"
|
|
#include "settings.h"
|
|
#include "utils/locale.h"
|
|
|
|
#include <QByteArray>
|
|
#include <QList>
|
|
#include <QListWidget>
|
|
#include <KPIMIdentities/Identity>
|
|
#include <KPIMIdentities/IdentityManager>
|
|
#include <KPIMUtils/Email>
|
|
#include <QLabel>
|
|
#include <kiconloader.h>
|
|
#include <klocale.h>
|
|
#include <kmessagebox.h>
|
|
#include <kwindowsystem.h>
|
|
#include <ktoolinvocation.h>
|
|
#include <kvbox.h>
|
|
#include <mailtransport/transportmanager.h>
|
|
|
|
|
|
using namespace KNode;
|
|
using namespace KNode::Utilities;
|
|
using namespace MailTransport;
|
|
|
|
KNArticleFactory::KNArticleFactory( QObject *parent )
|
|
: QObject( parent ), s_endErrDlg(0)
|
|
{
|
|
}
|
|
|
|
|
|
KNArticleFactory::~KNArticleFactory()
|
|
{
|
|
for ( QList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
|
|
delete (*it);
|
|
delete s_endErrDlg;
|
|
}
|
|
|
|
|
|
void KNArticleFactory::createPosting( KNNntpAccount::Ptr a )
|
|
{
|
|
if(!a)
|
|
return;
|
|
|
|
KNLocalArticle::Ptr art = newArticle( a, Locale::defaultCharset() );
|
|
|
|
if(!art)
|
|
return;
|
|
|
|
art->setServerId(a->id());
|
|
art->setDoPost(true);
|
|
art->setDoMail(false);
|
|
|
|
KNComposer *c = new KNComposer( art, QString(), QString(), true, false, false, false );
|
|
mCompList.append( c );
|
|
connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
|
|
c->show();
|
|
}
|
|
|
|
|
|
void KNArticleFactory::createPosting( KNGroup::Ptr g )
|
|
{
|
|
if(!g)
|
|
return;
|
|
|
|
QByteArray chset = Locale::defaultCharset( g );
|
|
KNLocalArticle::Ptr art = newArticle( g, 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(), QString(), true, false, false, false );
|
|
mCompList.append( c );
|
|
connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
|
|
c->show();
|
|
}
|
|
|
|
|
|
void KNArticleFactory::createReply( KNRemoteArticle::Ptr a, const QString &selectedText, bool post, bool mail )
|
|
{
|
|
if(!a)
|
|
return;
|
|
|
|
KNGroup::Ptr g = boost::static_pointer_cast<KNGroup>( a->collection() );
|
|
|
|
QByteArray chset;
|
|
if ( knGlobals.settings()->useOwnCharset() ) {
|
|
chset = Locale::defaultCharset( g );
|
|
} else {
|
|
chset = a->contentType()->charset();
|
|
}
|
|
|
|
//create new article
|
|
KNLocalArticle::Ptr art = newArticle( g, 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).toUpper() != "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).toUpper()=="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(), KGuiItem(i18n("Reply Public")), KGuiItem(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::Types::Mailbox address;
|
|
if(replyTo && !replyTo->isEmpty()) {
|
|
foreach( const KMime::Types::Mailbox &mbox, replyTo->mailboxes() ) {
|
|
art->to()->addAddress( mbox );
|
|
}
|
|
}
|
|
else {
|
|
KMime::Headers::From *from=a->from();
|
|
foreach( const KMime::Types::Mailbox &mbox, from->mailboxes() ) {
|
|
art->to()->addAddress( mbox );
|
|
}
|
|
}
|
|
|
|
//References
|
|
KMime::Headers::References *references=a->references(false);
|
|
QByteArray refs;
|
|
if (references)
|
|
refs=references->as7BitString(false);
|
|
else
|
|
refs = "";
|
|
|
|
art->references()->from7BitString(refs);
|
|
art->references()->appendIdentifier(a->messageID()->as7BitString(false));
|
|
|
|
//Mail-Copies-To
|
|
bool authorDislikesMailCopies=false;
|
|
bool authorWantsMailCopies=false;
|
|
KMime::Headers::MailCopiesTo *mailCopiesTo=a->mailCopiesTo(false);
|
|
|
|
if( mailCopiesTo && !mailCopiesTo->isEmpty() ) {
|
|
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(), "mailCopiesToWarning" );
|
|
if ( authorWantsMailCopies && !mailCopiesTo->mailboxes().isEmpty() ) {
|
|
art->to()->clear();
|
|
foreach ( const KMime::Types::Mailbox &mbox, mailCopiesTo->mailboxes() ) {
|
|
art->to()->addAddress( mbox );
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------- </Headers> ---------------------------
|
|
|
|
//--------------------------- <Body> -----------------------------
|
|
|
|
// attribution line
|
|
QString attribution = knGlobals.settings()->intro();
|
|
QString name( a->from()->displayNames().join( ", ") );
|
|
if ( name.isEmpty() && !a->from()->isEmpty() )
|
|
name = QString::fromLatin1( a->from()->addresses().first() );
|
|
attribution.replace(QRegExp("%NAME"),name);
|
|
if ( !a->from()->isEmpty() )
|
|
attribution.replace(QRegExp("%EMAIL"), QString::fromLatin1(a->from()->addresses().first()));
|
|
attribution.replace( QRegExp("%DATE"), KGlobal::locale()->formatDateTime(a->date()->dateTime().toLocalZone().dateTime(), KLocale::LongDate) );
|
|
QString msid = a->messageID()->identifier();
|
|
attribution.replace( QRegExp("%MSIDX"), msid );
|
|
attribution.replace( QRegExp("%MSID"), QLatin1Char('<') + msid + QLatin1Char('>') );
|
|
attribution.replace(QRegExp("%GROUP"),g->groupname());
|
|
attribution.replace(QRegExp("%L"),"\n");
|
|
attribution+="\n\n";
|
|
|
|
QString quoted=attribution;
|
|
QString notRewraped;
|
|
QStringList text;
|
|
QStringList::Iterator line;
|
|
bool incSig = knGlobals.settings()->includeSignature();
|
|
|
|
if (selectedText.isEmpty()) {
|
|
KMime::Content *tc = a->textContent();
|
|
if(tc)
|
|
text = tc->decodedText( true, knGlobals.settings()->removeTrailingNewlines() ).split( '\n' );
|
|
}
|
|
else
|
|
text = selectedText.split('\n');
|
|
|
|
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.settings()->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.settings()->maxLineLength(), '>', !incSig, false );
|
|
}
|
|
|
|
//-------------------------- </Body> -----------------------------
|
|
|
|
if ( art->doMail() && knGlobals.settings()->useExternalMailer() ) {
|
|
sendMailExternal(address.prettyAddress(), subject, quoted);
|
|
art->setDoMail(false);
|
|
if (!art->doPost()) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
//open composer
|
|
KNComposer *c=new KNComposer(art, quoted, notRewraped, true, authorDislikesMailCopies, authorWantsMailCopies);
|
|
mCompList.append( c );
|
|
connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
|
|
c->show();
|
|
}
|
|
|
|
|
|
void KNArticleFactory::createForward( KNArticle::Ptr a )
|
|
{
|
|
if(!a)
|
|
return;
|
|
|
|
KMime::Headers::ContentType *ct=a->contentType();
|
|
QByteArray chset;
|
|
bool incAtt = ( !knGlobals.settings()->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(), KGuiItem(i18n("Forward")), KGuiItem(i18n("Do Not Forward")))
|
|
);
|
|
|
|
if ( knGlobals.settings()->useOwnCharset() )
|
|
chset = Locale::defaultCharset();
|
|
else
|
|
chset = a->contentType()->charset();
|
|
|
|
//create new article
|
|
KNLocalArticle::Ptr art = newArticle( knGlobals.groupManager()->currentGroup(), 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)
|
|
fwd += text->decodedText( false, false );
|
|
|
|
fwd += QString("\n--------------- %1\n").arg(i18n("Forwarded message (end)"));
|
|
|
|
//--------------------------- </Body> ----------------------------
|
|
|
|
|
|
//------------------------ <Attachments> -------------------------
|
|
|
|
if(incAtt) {
|
|
KMime::Content::List al = a->attachments( false );
|
|
foreach ( KMime::Content *c, al )
|
|
art->addContent( new KMime::Content(c->head(), c->body()) );
|
|
}
|
|
|
|
//------------------------ </Attachments> ------------------------
|
|
|
|
|
|
if ( knGlobals.settings()->useExternalMailer() ) {
|
|
sendMailExternal( QString(), subject, fwd );
|
|
return;
|
|
}
|
|
|
|
//open composer
|
|
KNComposer *c = new KNComposer( art, fwd, QString(), true );
|
|
mCompList.append( c );
|
|
connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
|
|
c->show();
|
|
}
|
|
|
|
|
|
void KNArticleFactory::createCancel( KNArticle::Ptr a )
|
|
{
|
|
if(!cancelAllowed(a))
|
|
return;
|
|
|
|
if( KMessageBox::No == KMessageBox::questionYesNo( knGlobals.topWidget,
|
|
i18n("Do you really want to cancel this article?"), QString(), KGuiItem(i18n("Cancel Article")), KStandardGuiItem::cancel() ) )
|
|
return;
|
|
|
|
bool sendNow;
|
|
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")))) {
|
|
case KMessageBox::Yes : sendNow = true; break;
|
|
case KMessageBox::No : sendNow = false; break;
|
|
default : return;
|
|
}
|
|
|
|
KNGroup::Ptr grp;
|
|
KNNntpAccount::Ptr nntp;
|
|
|
|
if ( a->type() == KNArticle::ATremote )
|
|
nntp = boost::static_pointer_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::Ptr la = boost::static_pointer_cast<KNLocalArticle>( a );
|
|
la->setCanceled(true);
|
|
la->updateListItem();
|
|
nntp=knGlobals.accountManager()->account(la->serverId());
|
|
}
|
|
|
|
if ( !a->newsgroups()->isEmpty() )
|
|
grp = knGlobals.groupManager()->group(a->newsgroups()->groups().first(), nntp);
|
|
|
|
KNLocalArticle::Ptr art = newArticle( grp, "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();
|
|
QByteArray 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::Ptr 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(), KGuiItem(i18n("Supersede")), KStandardGuiItem::cancel() ) )
|
|
return;
|
|
|
|
KNGroup::Ptr grp;
|
|
KNNntpAccount::Ptr nntp;
|
|
|
|
if ( a->type() == KNArticle::ATremote )
|
|
nntp = boost::static_pointer_cast<KNGroup>( a->collection() )->account();
|
|
else {
|
|
KNLocalArticle::Ptr la = boost::static_pointer_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;
|
|
}
|
|
}
|
|
|
|
if ( !a->newsgroups()->isEmpty() )
|
|
grp = knGlobals.groupManager()->group(a->newsgroups()->groups().first(), nntp);
|
|
|
|
//new article
|
|
KNLocalArticle::Ptr art = newArticle( grp, 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)
|
|
text = textContent->decodedText();
|
|
|
|
//open composer
|
|
KNComposer *c=new KNComposer(art, text);
|
|
mCompList.append( c );
|
|
connect(c, SIGNAL(composerDone(KNComposer*)), this, SLOT(slotComposerDone(KNComposer*)));
|
|
c->show();
|
|
}
|
|
|
|
|
|
void KNArticleFactory::createMail(KMime::Types::Mailbox *address)
|
|
{
|
|
if ( knGlobals.settings()->useExternalMailer() ) {
|
|
sendMailExternal(address->prettyAddress());
|
|
return;
|
|
}
|
|
|
|
//create new article
|
|
KNLocalArticle::Ptr art = newArticle( knGlobals.groupManager()->currentGroup(), Locale::defaultCharset() );
|
|
if(!art)
|
|
return;
|
|
|
|
art->setDoMail(true);
|
|
art->setDoPost(false);
|
|
art->to()->addAddress((*address));
|
|
|
|
//open composer
|
|
KNComposer *c = new KNComposer( art, QString(), QString(), 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;
|
|
mailtoURL.setProtocol("mailto");
|
|
|
|
if (!address.isEmpty())
|
|
mailtoURL.setPath(address);
|
|
if (!subject.isEmpty())
|
|
queries.append(QLatin1String("subject=")+KUrl::toPercentEncoding(subject));
|
|
if (!body.isEmpty())
|
|
queries.append(QLatin1String("body=")+KUrl::toPercentEncoding(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);
|
|
|
|
KToolInvocation::invokeMailer(mailtoURL);
|
|
}
|
|
|
|
|
|
void KNArticleFactory::edit( KNLocalArticle::Ptr a )
|
|
{
|
|
if(!a)
|
|
return;
|
|
|
|
KNComposer *com=findComposer(a);
|
|
if(com) {
|
|
#ifdef Q_OS_UNIX
|
|
KWindowSystem::activateWindow(com->winId());
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
if(a->editDisabled()) {
|
|
KMessageBox::sorry(knGlobals.topWidget, i18n("This article cannot be edited."));
|
|
return;
|
|
}
|
|
|
|
//load article body
|
|
if(!a->hasContent())
|
|
knGlobals.articleManager()->loadArticle(a);
|
|
|
|
//open composer
|
|
com = new KNComposer( a, QString() );
|
|
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::Ptr ser;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
// filter out internal headers
|
|
QByteArray head = (*it)->head();
|
|
KMime::Headers::Base *header = 0;
|
|
while ( true ) {
|
|
header = KMime::HeaderParsing::extractFirstHeader( head );
|
|
if ( !header ) {
|
|
break;
|
|
}
|
|
if ( qstrncmp( header->type(), "X-KNode", 7 ) == 0 ) {
|
|
(*it)->removeHeader( header->type() );
|
|
}
|
|
}
|
|
(*it)->assemble(); // Validate change made above
|
|
|
|
|
|
if ( (*it)->doPost() && !(*it)->posted() ) {
|
|
ser = knGlobals.accountManager()->account( (*it)->serverId() );
|
|
job = new ArticlePostJob( this, ser, (*it) );
|
|
emitJob(job);
|
|
}
|
|
if ( (*it)->doMail() && !(*it)->mailed() ) {
|
|
int transportId = TransportManager::self()->defaultTransportId();
|
|
job = new MailSendJob( this, transportId, (*it) );
|
|
emitJob(job);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void KNArticleFactory::sendOutbox()
|
|
{
|
|
KNLocalArticle::List lst;
|
|
KNFolder::Ptr ob;
|
|
|
|
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() ) {
|
|
QList<KNComposer*>::Iterator it = mCompList.begin();
|
|
if ( !(*it)->close() )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void KNArticleFactory::deleteComposerForArticle( KNLocalArticle::Ptr a )
|
|
{
|
|
KNComposer *com = findComposer( a );
|
|
if ( com ) {
|
|
mCompList.removeAll( com );
|
|
com->deleteLater();
|
|
}
|
|
}
|
|
|
|
|
|
KNComposer* KNArticleFactory::findComposer( KNLocalArticle::Ptr a )
|
|
{
|
|
for ( QList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
|
|
if ( (*it)->article() == a )
|
|
return (*it);
|
|
return 0;
|
|
}
|
|
|
|
|
|
void KNArticleFactory::configChanged()
|
|
{
|
|
for ( QList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
|
|
(*it)->setConfig( false );
|
|
}
|
|
|
|
|
|
void KNArticleFactory::processJob(KNJobData *j)
|
|
{
|
|
KNLocalArticle::Ptr art = boost::static_pointer_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 canceled the article posting. 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::Ptr KNArticleFactory::newArticle( KNCollection::Ptr col, const QByteArray &defChset, bool withXHeaders, KNArticle::Ptr origPost )
|
|
{
|
|
if ( knGlobals.settings()->generateMessageID() && knGlobals.settings()->hostname().isEmpty() ) {
|
|
KMessageBox::sorry(knGlobals.topWidget, i18n("Please set a hostname for the generation\nof the message-id or disable it."));
|
|
return KNLocalArticle::Ptr();
|
|
}
|
|
|
|
KNLocalArticle::Ptr art( new KNLocalArticle( KNArticleCollection::Ptr() ) );
|
|
KPIMIdentities::Identity id;
|
|
|
|
if (col) {
|
|
if (col->type() == KNCollection::CTgroup) {
|
|
id = boost::static_pointer_cast<KNGroup>( col )->identity();
|
|
if ( id.isNull() ) {
|
|
id = boost::static_pointer_cast<KNGroup>( col )->account()->identity();
|
|
}
|
|
} else if (col->type() == KNCollection::CTnntpAccount) {
|
|
id = boost::static_pointer_cast<KNNntpAccount>( col )->identity();
|
|
}
|
|
}
|
|
if ( id.isNull() ) {
|
|
id = KNGlobals::self()->settings()->identity();
|
|
}
|
|
// Identity UOID
|
|
KMime::Headers::Generic *xKnodeIdentity = new KMime::Headers::Generic( "X-KNode-Identity",
|
|
art.get(),
|
|
QByteArray::number( id.uoid() ) );
|
|
art->setHeader( xKnodeIdentity );
|
|
|
|
//Message-id
|
|
if ( knGlobals.settings()->generateMessageID() )
|
|
art->messageID()->generate( knGlobals.settings()->hostname().toLatin1() );
|
|
|
|
//From
|
|
KMime::Headers::From *from=art->from();
|
|
if ( KPIMUtils::isValidSimpleAddress( id.primaryEmailAddress() ) ) {
|
|
from->fromUnicodeString( id.fullEmailAddr(), Locale::defaultCharset() );
|
|
} else {
|
|
KMessageBox::sorry( knGlobals.topWidget,
|
|
i18n( "<qt>Please enter a valid email address for the "
|
|
"identity named <emphasis>%1</emphasis> "
|
|
"at the identity section of the configuration dialog.</qt>",
|
|
id.identityName() ) );
|
|
return KNLocalArticle::Ptr();
|
|
}
|
|
|
|
//Reply-To
|
|
if ( KPIMUtils::isValidAddress( id.replyToAddr() ) == KPIMUtils::AddressOk ) {
|
|
art->replyTo()->fromUnicodeString( id.replyToAddr(), Locale::defaultCharset() );
|
|
} else {
|
|
art->removeHeader( "Reply-To" );
|
|
}
|
|
|
|
//Mail-Copies-To
|
|
if ( KPIMUtils::isValidAddress( id.property( "Mail-Copies-To" ).toString() ) == KPIMUtils::AddressOk ) {
|
|
art->mailCopiesTo()->fromUnicodeString( id.property( "Mail-Copies-To" ).toString(), Locale::defaultCharset() );
|
|
} else {
|
|
art->removeHeader( "Mail-Copies-To" );
|
|
}
|
|
|
|
//Organization
|
|
if ( !id.organization().trimmed().isEmpty() ) {
|
|
art->organization()->fromUnicodeString( id.organization(), Locale::defaultCharset() );
|
|
} else {
|
|
art->removeHeader( "Organization" );
|
|
}
|
|
|
|
//Date
|
|
art->date()->setDateTime( KDateTime::currentLocalDateTime() );
|
|
|
|
//User-Agent
|
|
if( !knGlobals.settings()->noUserAgent() ) {
|
|
art->userAgent()->from7BitString("KNode/" KNODE_VERSION);
|
|
}
|
|
|
|
//Mime
|
|
KMime::Headers::ContentType *type=art->contentType();
|
|
type->setMimeType("text/plain");
|
|
|
|
type->setCharset(defChset);
|
|
|
|
if ( defChset.toLower() == "us-ascii" )
|
|
art->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit);
|
|
else
|
|
art->contentTransferEncoding()->setEncoding( knGlobals.settings()->allow8BitBody() ? KMime::Headers::CE8Bit : KMime::Headers::CEquPr );
|
|
|
|
//X-Headers
|
|
if(withXHeaders) {
|
|
XHeader::List xhdr = knGlobals.settings()->xHeaders();
|
|
for ( XHeader::List::Iterator it = xhdr.begin(); it != xhdr.end(); ++it ) {
|
|
QString value = (*it).value();
|
|
if(origPost) {
|
|
QString name( origPost->from()->displayNames().join(", ") );
|
|
if ( name.isEmpty() && !origPost->from()->isEmpty() )
|
|
name = QString::fromLatin1( origPost->from()->addresses().first() );
|
|
value.replace(QRegExp("%NAME"), name);
|
|
if ( !origPost->from()->isEmpty() )
|
|
value.replace( QRegExp("%EMAIL"), QString::fromLatin1(origPost->from()->addresses().first() ) );
|
|
}
|
|
else
|
|
if ( value.indexOf( "%NAME" ) != -1 || value.indexOf( "%EMAIL" ) != -1 )
|
|
continue;
|
|
|
|
art->setHeader( new KMime::Headers::Generic( (*it).name().toLatin1(), art.get(), value,
|
|
Locale::defaultCharset() ) );
|
|
}
|
|
}
|
|
|
|
return art;
|
|
}
|
|
|
|
|
|
bool KNArticleFactory::cancelAllowed( KNArticle::Ptr a )
|
|
{
|
|
if(!a)
|
|
return false;
|
|
|
|
if(a->type()==KNArticle::ATlocal) {
|
|
KNLocalArticle::Ptr localArt = boost::static_pointer_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() == KNArticle::ATremote ) {
|
|
KNRemoteArticle::Ptr remArt = boost::static_pointer_cast<KNRemoteArticle>( a );
|
|
KPIMIdentities::IdentityManager *im = KNGlobals::self()->identityManager();
|
|
bool ownArticle = false;
|
|
const QList<QByteArray> fromAddr = remArt->from()->addresses();
|
|
foreach ( const QByteArray &addr, fromAddr ) {
|
|
if ( im->thatIsMe( QString::fromLatin1( addr ) ) ) {
|
|
ownArticle = true;
|
|
break;
|
|
}
|
|
}
|
|
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 :
|
|
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.removeAll( com );
|
|
com->deleteLater();
|
|
}
|
|
#ifdef Q_OS_UNIX
|
|
else
|
|
KWindowSystem::activateWindow(com->winId());
|
|
#endif
|
|
}
|
|
|
|
|
|
void KNArticleFactory::slotSendErrorDialogDone()
|
|
{
|
|
s_endErrDlg->deleteLater();
|
|
s_endErrDlg=0;
|
|
}
|
|
|
|
|
|
//======================================================================================================
|
|
|
|
|
|
KNSendErrorDialog::KNSendErrorDialog()
|
|
: KDialog( knGlobals.topWidget )
|
|
{
|
|
setCaption( i18n("Errors While Sending") );
|
|
setButtons( Close );
|
|
KVBox *page = new KVBox( this );
|
|
setMainWidget( page );
|
|
setDefaultButton( Close );
|
|
|
|
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);
|
|
mErrorList = new QListWidget( page );
|
|
mError = new QLabel( QString(), page );
|
|
mError->setWordWrap( true );
|
|
|
|
connect( mErrorList, SIGNAL(currentRowChanged(int)), 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)
|
|
{
|
|
ErrorListItem *item = new ErrorListItem( subject, error );
|
|
item->setIcon( UserIcon("snderr") );
|
|
mErrorList->addItem( item );
|
|
mErrorList->setCurrentItem( item );
|
|
}
|
|
|
|
|
|
void KNSendErrorDialog::slotHighlighted(int idx)
|
|
{
|
|
ErrorListItem *item = static_cast<ErrorListItem*>( mErrorList->item( idx ) );
|
|
if ( item ) {
|
|
QString tmp = i18n("<b>Error message:</b><br />") + item->error();
|
|
mError->setText( tmp );
|
|
}
|
|
}
|
|
|
|
//-------------------------------
|