00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <klocale.h>
00017 #include <kcodecs.h>
00018 #include <kmimetype.h>
00019
00020 #include "knhdrviewitem.h"
00021 #include "kngroup.h"
00022 #include "knglobals.h"
00023 #include "knconfigmanager.h"
00024 #include "utilities.h"
00025 #include "settings.h"
00026
00027
00028 #include <QByteArray>
00029
00030 using namespace KMime;
00031
00032
00033 KNArticle::KNArticle(KNArticleCollection *c) : i_d(-1), c_ol(c), i_tem(0)
00034 {
00035 }
00036
00037
00038 KNArticle::~KNArticle()
00039 {
00040 delete i_tem;
00041 }
00042
00043
00044 void KNArticle::clear()
00045 {
00046 f_lags.clear();
00047 }
00048
00049
00050 void KNArticle::setListItem(KNHdrViewItem *it)
00051 {
00052 i_tem=it;
00053 if(i_tem) i_tem->art=this;
00054 }
00055
00056
00057 void KNArticle::setLocked(bool b)
00058 {
00059 f_lags.set(0, b);
00060 if(c_ol) {
00061 if(b)
00062 c_ol->articleLocked();
00063 else
00064 c_ol->articleUnlocked();
00065 }
00066 }
00067
00068
00069 QByteArray KNArticle::assembleHeaders()
00070 {
00071
00072 for ( Headers::Base::List::Iterator it = h_eaders.begin(); it != h_eaders.end(); ) {
00073 if ( (*it)->isXHeader() && ( strncasecmp( (*it)->type(), "X-KNode", 7 ) == 0 ) )
00074 it = h_eaders.erase( it );
00075 else
00076 ++it;
00077 }
00078
00079 return KMime::NewsArticle::assembleHeaders();
00080 }
00081
00082
00083
00084
00085
00086 KNRemoteArticle::KNRemoteArticle(KNGroup *g)
00087 : KNArticle(g), a_rticleNumber(-1), i_dRef(-1), d_ref(0), t_hrLevel(0), s_core(0),
00088 c_olor(knGlobals.settings()->unreadThreadColor()),
00089 u_nreadFups(0), n_ewFups(0), s_ubThreadChangeDate(0)
00090 {
00091 m_essageID.setParent(this);
00092 f_rom.setParent(this);
00093 r_eferences.setParent(this);
00094
00095 if (g && g->useCharset())
00096 setDefaultCharset( g->defaultCharset() );
00097 else
00098 setDefaultCharset( knGlobals.settings()->charset().toLatin1() );
00099 }
00100
00101
00102 KNRemoteArticle::~KNRemoteArticle()
00103 {}
00104
00105
00106 void KNRemoteArticle::parse()
00107 {
00108 KNArticle::parse();
00109 QByteArray raw;
00110 if( !(raw=rawHeader(m_essageID.type())).isEmpty() )
00111 m_essageID.from7BitString(raw);
00112
00113 if( !(raw=rawHeader(f_rom.type())).isEmpty() )
00114 f_rom.from7BitString(raw);
00115
00116 if( !(raw=rawHeader(r_eferences.type())).isEmpty() )
00117 r_eferences.from7BitString(raw);
00118 }
00119
00120
00121 void KNRemoteArticle::clear()
00122 {
00123 m_essageID.clear();
00124 f_rom.clear();
00125 r_eferences.clear();
00126 KNArticle::clear();
00127 }
00128
00129
00130 Headers::Base* KNRemoteArticle::getHeaderByType(const char *type)
00131 {
00132 if(strcasecmp("Message-ID", type)==0) {
00133 if(m_essageID.isEmpty()) return 0;
00134 else return &m_essageID;
00135 }
00136 else if(strcasecmp("From", type)==0) {
00137 if(f_rom.isEmpty()) return 0;
00138 else return &f_rom;
00139 }
00140 else if(strcasecmp("References", type)==0) {
00141 if(r_eferences.isEmpty()) return 0;
00142 else return &r_eferences;
00143 }
00144 else
00145 return KNArticle::getHeaderByType(type);
00146 }
00147
00148
00149 void KNRemoteArticle::setHeader(Headers::Base *h)
00150 {
00151 bool del=true;
00152 if(h->is("Message-ID"))
00153 m_essageID.from7BitString(h->as7BitString(false));
00154 else if(h->is("From")) {
00155 foreach ( KMime::Types::Mailbox mbox, static_cast<Headers::From*>( h )->mailboxes() )
00156 f_rom.addAddress( mbox );
00157 }
00158 else if(h->is("References")) {
00159 r_eferences.from7BitString(h->as7BitString(false));
00160 }
00161 else {
00162 del=false;
00163 KNArticle::setHeader(h);
00164 }
00165
00166 if(del) delete h;
00167 }
00168
00169
00170 bool KNRemoteArticle::removeHeader(const char *type)
00171 {
00172 if(strcasecmp("Message-ID", type)==0)
00173 m_essageID.clear();
00174 else if(strcasecmp("From", type)==0)
00175 f_rom.clear();
00176 else if(strcasecmp("References", type)==0)
00177 r_eferences.clear();
00178 else
00179 return KNArticle::removeHeader(type);
00180
00181 return true;
00182 }
00183
00184
00185 void KNRemoteArticle::initListItem()
00186 {
00187 if(!i_tem) return;
00188
00189 KMime::Types::Mailbox mbox;
00190 if ( !f_rom.isEmpty() )
00191 mbox = f_rom.mailboxes().first();
00192 if ( mbox.hasName() )
00193 i_tem->setText( 1, mbox.name() );
00194 else
00195 i_tem->setText( 1, QString::fromLatin1( mbox.address() ) );
00196
00197 updateListItem();
00198 }
00199
00200
00201 void KNRemoteArticle::updateListItem()
00202 {
00203 if(!i_tem) return;
00204
00205 KNode::Appearance *app=knGlobals.configManager()->appearance();
00206
00207 if(isRead()) {
00208 if(hasContent())
00209 i_tem->setPixmap(0, app->icon(KNode::Appearance::greyBallChkd));
00210 else
00211 i_tem->setPixmap(0, app->icon(KNode::Appearance::greyBall));
00212 }
00213 else {
00214 if(hasContent())
00215 i_tem->setPixmap(0,app->icon(KNode::Appearance::redBallChkd));
00216 else
00217 i_tem->setPixmap(0, app->icon(KNode::Appearance::redBall));
00218 }
00219
00220 if(hasNewFollowUps())
00221 i_tem->setPixmap(1, app->icon(KNode::Appearance::newFups));
00222 else
00223 i_tem->setPixmap(1, app->icon(KNode::Appearance::null));
00224
00225 if(isWatched())
00226 i_tem->setPixmap(2, app->icon(KNode::Appearance::eyes));
00227 else {
00228 if(isIgnored())
00229 i_tem->setPixmap(2, app->icon(KNode::Appearance::ignore));
00230 else
00231 i_tem->setPixmap(2, app->icon(KNode::Appearance::null));
00232 }
00233
00234 i_tem->setExpandable( (threadMode() && hasVisibleFollowUps()) );
00235
00236 i_tem->repaint();
00237 }
00238
00239
00240 void KNRemoteArticle::thread(KNRemoteArticle::List &l)
00241 {
00242 KNRemoteArticle *tmp=0, *ref=this;
00243 KNGroup *g=static_cast<KNGroup*>(c_ol);
00244 int idRef=i_dRef, topID=-1;
00245
00246 while(idRef!=0) {
00247 ref=g->byId(idRef);
00248 if(!ref)
00249 return;
00250 idRef=ref->idRef();
00251 }
00252
00253 topID=ref->id();
00254 l.append(ref);
00255
00256 for(int i=0; i<g->length(); i++) {
00257 tmp=g->at(i);
00258 if(tmp->idRef()!=0) {
00259 idRef=tmp->idRef();
00260 while(idRef!=0) {
00261 ref=g->byId(idRef);
00262 idRef=ref->idRef();
00263 }
00264 if(ref->id()==topID)
00265 l.append(tmp);
00266 }
00267 }
00268 }
00269
00270
00271 void KNRemoteArticle::setForceDefaultCharset(bool b)
00272 {
00273 if (!b) {
00274 KNGroup *g=static_cast<KNGroup*>(c_ol);
00275 if (g && g->useCharset())
00276 setDefaultCharset( g->defaultCharset() );
00277 else
00278 setDefaultCharset( knGlobals.settings()->charset().toLatin1() );
00279 }
00280 KNArticle::setForceDefaultCharset( b );
00281 initListItem();
00282 }
00283
00284
00285 void KNRemoteArticle::propagateThreadChangedDate()
00286 {
00287 KNRemoteArticle *ref=this;
00288 KNGroup *g=static_cast<KNGroup*>(c_ol);
00289 int idRef=i_dRef;
00290
00291 while (idRef!=0) {
00292 ref=g->byId(idRef);
00293 if(!ref)
00294 return;
00295 idRef=ref->idRef();
00296 }
00297
00298 if (date()->dateTime() > ref->date()->dateTime()) {
00299 ref->setSubThreadChangeDate(date()->dateTime().toTime_t());
00300 }
00301 }
00302
00303
00304
00305
00306
00307 KNLocalArticle::KNLocalArticle(KNArticleCollection *c)
00308 : KNArticle(c), s_Offset(0), e_Offset(0), s_erverId(-1)
00309 {
00310 n_ewsgroups.setParent(this);
00311 t_o.setParent(this);
00312 setDefaultCharset( knGlobals.settings()->charset().toLatin1() );
00313 }
00314
00315
00316 KNLocalArticle::~KNLocalArticle()
00317 {}
00318
00319
00320 void KNLocalArticle::parse()
00321 {
00322 KNArticle::parse();
00323 QByteArray raw;
00324
00325 if( !(raw=rawHeader(n_ewsgroups.type())).isEmpty() )
00326 n_ewsgroups.from7BitString(raw);
00327
00328 if( !(raw=rawHeader(t_o.type())).isEmpty() )
00329 t_o.from7BitString(raw);
00330 }
00331
00332
00333 void KNLocalArticle::clear()
00334 {
00335 KNArticle::clear();
00336 n_ewsgroups.clear();
00337 t_o.clear();
00338 }
00339
00340
00341 Headers::Base* KNLocalArticle::getHeaderByType(const char *type)
00342 {
00343 if(strcasecmp("Newsgroups", type)==0)
00344 return newsgroups(false);
00345 else if(strcasecmp("To", type)==0)
00346 return to(false);
00347 else
00348 return KNArticle::getHeaderByType(type);
00349 }
00350
00351
00352 void KNLocalArticle::setHeader(Headers::Base *h)
00353 {
00354 bool del=true;
00355 if(h->is("To"))
00356 t_o.from7BitString(h->as7BitString(false));
00357 else if(h->is("Newsgroups"))
00358 n_ewsgroups.from7BitString(h->as7BitString(false));
00359 else {
00360 del=false;
00361 KNArticle::setHeader(h);
00362 }
00363
00364 if(del) delete h;
00365 }
00366
00367
00368 bool KNLocalArticle::removeHeader(const char *type)
00369 {
00370 if(strcasecmp("To", type)==0)
00371 t_o.clear();
00372 else if(strcasecmp("Newsgroups", type)==0)
00373 n_ewsgroups.clear();
00374 else
00375 return KNArticle::removeHeader(type);
00376
00377 return true;
00378 }
00379
00380
00381 void KNLocalArticle::updateListItem()
00382 {
00383 if(!i_tem)
00384 return;
00385
00386 QString tmp;
00387 int idx=0;
00388 KNode::Appearance *app=knGlobals.configManager()->appearance();
00389
00390 if(isSavedRemoteArticle()) {
00391 i_tem->setPixmap(0, app->icon(KNode::Appearance::savedRemote));
00392 if (!n_ewsgroups.isEmpty())
00393 tmp=n_ewsgroups.asUnicodeString();
00394 else
00395 tmp=t_o.asUnicodeString();
00396 }
00397 else {
00398
00399 if(doPost()) {
00400 tmp+=n_ewsgroups.asUnicodeString();
00401 if(canceled())
00402 i_tem->setPixmap(idx++, app->icon(KNode::Appearance::canceledPosting));
00403 else
00404 i_tem->setPixmap(idx++, app->icon(KNode::Appearance::posting));
00405 }
00406
00407 if(doMail()) {
00408 i_tem->setPixmap(idx++, app->icon(KNode::Appearance::mail));
00409 if(doPost())
00410 tmp+=" / ";
00411 tmp+=t_o.asUnicodeString();
00412 }
00413
00414 }
00415
00416 i_tem->setText(1, tmp);
00417 }
00418
00419
00420 void KNLocalArticle::setForceDefaultCharset( bool b )
00421 {
00422 if (!b)
00423 setDefaultCharset( knGlobals.settings()->charset().toLatin1() );
00424 KNArticle::setForceDefaultCharset( b );
00425 updateListItem();
00426 }
00427
00428
00429
00430
00431
00432 KNAttachment::KNAttachment(Content *c)
00433 : c_ontent(c), l_oadHelper(0), f_ile(0), i_sAttached(true)
00434 {
00435 Headers::ContentType *t=c->contentType();
00436 Headers::ContentTransferEncoding *e=c->contentTransferEncoding();
00437 Headers::ContentDescription *d=c->contentDescription(false);
00438
00439 n_ame=t->name();
00440
00441 if(d)
00442 d_escription=d->asUnicodeString();
00443
00444
00445 setMimeType(t->mimeType());
00446
00447 if(e->encoding()==Headers::CEuuenc) {
00448 setCte( Headers::CEbase64 );
00449 updateContentInfo();
00450 }
00451 else
00452 e_ncoding.setEncoding( e->encoding() );
00453
00454
00455 h_asChanged=false;
00456 }
00457
00458
00459 KNAttachment::KNAttachment(KNLoadHelper *helper)
00460 : c_ontent(0), l_oadHelper(helper), f_ile(helper->getFile()), i_sAttached(false), h_asChanged(true)
00461 {
00462 setMimeType(KMimeType::findByPath(f_ile->fileName())->name());
00463 n_ame=helper->getURL().fileName();
00464 }
00465
00466
00467 KNAttachment::~KNAttachment()
00468 {
00469 if(!i_sAttached && c_ontent)
00470 delete c_ontent;
00471 delete l_oadHelper;
00472 }
00473
00474
00475 void KNAttachment::setMimeType(const QString &s)
00476 {
00477 mMimeType = s;
00478 h_asChanged=true;
00479
00480 if ( !mMimeType.contains( "text/", Qt::CaseInsensitive ) ) {
00481 f_b64=true;
00482 e_ncoding.setEncoding(Headers::CEbase64);
00483 }
00484 else {
00485 f_b64=false;
00486 if ( knGlobals.settings()->allow8BitBody() )
00487 setCte(Headers::CE8Bit);
00488 else
00489 setCte(Headers::CEquPr);
00490 }
00491 }
00492
00493
00494 QString KNAttachment::contentSize() const
00495 {
00496 QString ret;
00497 int s=0;
00498
00499 if(c_ontent && c_ontent->hasContent())
00500 s=c_ontent->size();
00501 else {
00502 if (f_ile)
00503 s=f_ile->size();
00504 }
00505
00506 if(s > 1023) {
00507 s=s/1024;
00508 ret.setNum(s);
00509 ret+=" kB";
00510 }
00511 else {
00512 ret.setNum(s);
00513 ret+=" Bytes";
00514 }
00515
00516 return ret;
00517 }
00518
00519
00520 void KNAttachment::updateContentInfo()
00521 {
00522 if(!h_asChanged || !c_ontent)
00523 return;
00524
00525
00526 Headers::ContentType *t=c_ontent->contentType();
00527 t->setMimeType( mMimeType.toLatin1() );
00528 t->setName(n_ame, "UTF-8");
00529 t->setCategory(Headers::CCmixedPart);
00530
00531
00532 if(d_escription.isEmpty())
00533 c_ontent->removeHeader("Content-Description");
00534 else
00535 c_ontent->contentDescription()->fromUnicodeString(d_escription, "UTF-8");
00536
00537
00538 Headers::ContentDisposition *d=c_ontent->contentDisposition();
00539 d->setDisposition(Headers::CDattachment);
00540 d->setFilename(n_ame);
00541
00542
00543 if(i_sAttached)
00544 c_ontent->changeEncoding(e_ncoding.encoding());
00545 else
00546 c_ontent->contentTransferEncoding()->setEncoding(e_ncoding.encoding());
00547
00548 c_ontent->assemble();
00549
00550 h_asChanged=false;
00551 }
00552
00553
00554
00555 void KNAttachment::attach(Content *c)
00556 {
00557 if(i_sAttached || !f_ile)
00558 return;
00559
00560 c_ontent=new Content();
00561 updateContentInfo();
00562 Headers::ContentType *type=c_ontent->contentType();
00563 Headers::ContentTransferEncoding *e=c_ontent->contentTransferEncoding();
00564 QByteArray data;
00565
00566 data = f_ile->readAll();
00567
00568 if ( data.size() < f_ile->size() && f_ile->error() != QFile::NoError ) {
00569 KNHelper::displayExternalFileError();
00570 delete c_ontent;
00571 c_ontent=0;
00572 } else {
00573 if (e_ncoding.encoding()==Headers::CEbase64 || !type->isText()) {
00574 c_ontent->setBody( KCodecs::base64Encode(data, true) + '\n' );
00575
00576 e->setEncoding(Headers::CEbase64);
00577 e->setDecoded(false);
00578 } else {
00579 c_ontent->setBody( data + '\n' );
00580
00581 e->setDecoded(true);
00582 }
00583 }
00584
00585 if(c_ontent) {
00586 c->addContent(c_ontent);
00587 i_sAttached=true;
00588 }
00589 }
00590
00591
00592 void KNAttachment::detach(Content *c)
00593 {
00594 if(i_sAttached) {
00595 c->removeContent(c_ontent, false);
00596 i_sAttached=false;
00597 }
00598 }