You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1112 lines
32 KiB
1112 lines
32 KiB
/*
|
|
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 <tqlayout.h>
|
|
#include <tqlabel.h>
|
|
#include <tqvbox.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(TQObject *p, const char *n)
|
|
: TQObject(p, n), s_endErrDlg(0)
|
|
{
|
|
}
|
|
|
|
|
|
KNArticleFactory::~KNArticleFactory()
|
|
{
|
|
for ( TQValueList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
|
|
delete (*it);
|
|
delete s_endErrDlg;
|
|
}
|
|
|
|
|
|
void KNArticleFactory::createPosting(KNNntpAccount *a)
|
|
{
|
|
if(!a)
|
|
return;
|
|
|
|
TQString 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, TQString::null, sig, TQString::null, true );
|
|
mCompList.append( c );
|
|
connect(c, TQT_SIGNAL(composerDone(KNComposer*)), this, TQT_SLOT(slotComposerDone(KNComposer*)));
|
|
c->show();
|
|
}
|
|
|
|
|
|
void KNArticleFactory::createPosting(KNGroup *g)
|
|
{
|
|
if(!g)
|
|
return;
|
|
|
|
TQCString chset;
|
|
if (g->useCharset())
|
|
chset = g->defaultCharset();
|
|
else
|
|
chset = knGlobals.configManager()->postNewsTechnical()->charset();
|
|
|
|
TQString 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, TQString::null, sig, TQString::null, true);
|
|
mCompList.append( c );
|
|
connect(c, TQT_SIGNAL(composerDone(KNComposer*)), this, TQT_SLOT(slotComposerDone(KNComposer*)));
|
|
c->show();
|
|
}
|
|
|
|
|
|
void KNArticleFactory::createReply(KNRemoteArticle *a, TQString selectedText, bool post, bool mail)
|
|
{
|
|
if(!a)
|
|
return;
|
|
|
|
KNGroup *g=static_cast<KNGroup*>(a->collection());
|
|
|
|
TQCString 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
|
|
TQString 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
|
|
TQString 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?"), TQString::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);
|
|
TQCString 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)"),
|
|
TQString::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
|
|
TQString attribution=knGlobals.configManager()->postNewsComposer()->intro();
|
|
TQString name(a->from()->name());
|
|
if (name.isEmpty())
|
|
name = TQString::fromLatin1(a->from()->email());
|
|
attribution.replace(TQRegExp("%NAME"),name);
|
|
attribution.replace(TQRegExp("%EMAIL"),TQString::fromLatin1(a->from()->email()));
|
|
attribution.replace(TQRegExp("%DATE"),KGlobal::locale()->formatDateTime(a->date()->qdt(),false));
|
|
attribution.replace(TQRegExp("%MSID"),a->messageID()->asUnicodeString());
|
|
attribution.replace(TQRegExp("%GROUP"),g->groupname());
|
|
attribution.replace(TQRegExp("%L"),"\n");
|
|
attribution+="\n\n";
|
|
|
|
TQString quoted=attribution;
|
|
TQString notRewraped=TQString::null;
|
|
TQStringList text;
|
|
TQStringList::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 = TQStringList::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, TQT_SIGNAL(composerDone(KNComposer*)), this, TQT_SLOT(slotComposerDone(KNComposer*)));
|
|
c->show();
|
|
}
|
|
|
|
|
|
void KNArticleFactory::createForward(KNArticle *a)
|
|
{
|
|
if(!a)
|
|
return;
|
|
|
|
KMime::Headers::ContentType *ct=a->contentType();
|
|
TQCString 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?"), TQString::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
|
|
TQString sig;
|
|
KNLocalArticle *art=newArticle(knGlobals.groupManager()->currentGroup(), sig, chset);
|
|
if(!art)
|
|
return;
|
|
|
|
art->setDoPost(false);
|
|
art->setDoMail(true);
|
|
|
|
//------------------------- <Headers> ----------------------------
|
|
|
|
//subject
|
|
TQString subject=("Fwd: "+a->subject()->asUnicodeString());
|
|
art->subject()->fromUnicodeString(subject, a->subject()->rfc2047Charset());
|
|
|
|
//------------------------- </Headers> ---------------------------
|
|
|
|
//--------------------------- <Body> -----------------------------
|
|
|
|
TQString fwd = TQString("\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) {
|
|
TQStringList decodedLines;
|
|
text->decodedText( decodedLines, false, false );
|
|
for(TQStringList::Iterator it=decodedLines.begin(); it!=decodedLines.end(); ++it)
|
|
fwd += (*it) + "\n";
|
|
}
|
|
|
|
fwd += TQString("\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(TQString::null, subject, fwd);
|
|
delete art;
|
|
return;
|
|
}
|
|
|
|
//open composer
|
|
KNComposer *c=new KNComposer(art, fwd, sig, TQString::null, true);
|
|
mCompList.append( c );
|
|
connect(c, TQT_SIGNAL(composerDone(KNComposer*)), this, TQT_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?"), TQString::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);
|
|
|
|
TQString 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();
|
|
TQCString 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(TQString::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?"), TQString::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
|
|
TQString 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
|
|
TQString 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, TQT_SIGNAL(composerDone(KNComposer*)), this, TQT_SLOT(slotComposerDone(KNComposer*)));
|
|
c->show();
|
|
}
|
|
|
|
|
|
void KNArticleFactory::createMail(KMime::Headers::AddressField *address)
|
|
{
|
|
if (knGlobals.configManager()->postNewsTechnical()->useExternalMailer()) {
|
|
sendMailExternal(address->asUnicodeString());
|
|
return;
|
|
}
|
|
|
|
//create new article
|
|
TQString 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, TQString::null, sig, TQString::null, true);
|
|
mCompList.append( c );
|
|
connect(c, TQT_SIGNAL(composerDone(KNComposer*)), this, TQT_SLOT(slotComposerDone(KNComposer*)));
|
|
c->show();
|
|
}
|
|
|
|
|
|
void KNArticleFactory::sendMailExternal(const TQString &address, const TQString &subject, const TQString &body)
|
|
{
|
|
KURL mailtoURL;
|
|
TQStringList queries;
|
|
TQString query=TQString::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 ( TQStringList::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, TQString::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, TQT_SIGNAL(composerDone(KNComposer*)), this, TQT_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() ) {
|
|
TQValueList<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 ( TQValueList<KNComposer*>::Iterator it = mCompList.begin(); it != mCompList.end(); ++it )
|
|
if ( (*it)->article() == a )
|
|
return (*it);
|
|
return 0;
|
|
}
|
|
|
|
|
|
void KNArticleFactory::configChanged()
|
|
{
|
|
for ( TQValueList<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, TQString &sig, TQCString 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) {
|
|
TQString value = (*it).value();
|
|
if(origPost) {
|
|
TQString name(origPost->from()->name());
|
|
if (name.isEmpty())
|
|
name = TQString::fromLatin1(origPost->from()->email());
|
|
value.replace(TQRegExp("%NAME"), name);
|
|
value.replace(TQRegExp("%EMAIL"), TQString::fromLatin1(origPost->from()->email()));
|
|
}
|
|
else
|
|
if(value.find("%NAME") != -1 || value.find("%EMAIL") != -1)
|
|
continue;
|
|
|
|
art->setHeader( new KMime::Headers::Generic( (TQCString("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=TQString::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, TQT_SIGNAL(closeClicked()), this, TQT_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);
|
|
|
|
TQVBox *page = makeVBoxMainWidget();
|
|
|
|
new TQLabel(TQString("<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 TQLabel(TQString::null, page);
|
|
|
|
connect(j_obs, TQT_SIGNAL(highlighted(int)), this, TQT_SLOT(slotHighlighted(int)));
|
|
|
|
KNHelper::restoreWindowSize("sendDlg", this, TQSize(320,250));
|
|
}
|
|
|
|
|
|
KNSendErrorDialog::~KNSendErrorDialog()
|
|
{
|
|
KNHelper::saveWindowSize("sendDlg", size());
|
|
}
|
|
|
|
|
|
void KNSendErrorDialog::append(const TQString &subject, const TQString &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) {
|
|
TQString tmp=i18n("<b>Error message:</b><br>")+it->error;
|
|
e_rror->setText(tmp);
|
|
}
|
|
}
|
|
|
|
//-------------------------------
|
|
#include "knarticlefactory.moc"
|
|
|
|
// kate: space-indent on; indent-width 2;
|