kde-playground/kdepim/knode/knarticlefactory.cpp
2015-04-14 21:49:29 +00:00

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 );
}
}
//-------------------------------