4 #include <kmimemagic.h>
11 #include "kmmessage.h"
12 #include "globalsettings.h"
15 #include <kmime_charfreq.h>
16 #include <kmime_codecs.h>
17 #include <mimelib/enum.h>
18 #include <mimelib/utility.h>
19 #include <mimelib/string.h>
21 #include <kiconloader.h>
22 #include <tqtextcodec.h>
27 using namespace KMime;
30 KMMessagePart::KMMessagePart()
31 : mType(
"text"), mSubtype(
"plain"), mCte(
"7bit"), mBodyDecodedSize(0),
32 mParent(0), mLoadHeaders(false), mLoadPart(false)
37 KMMessagePart::KMMessagePart( TQDataStream & stream )
38 : mParent(0), mLoadHeaders(false), mLoadPart(false)
41 stream >> mOriginalContentTypeStr >> mName >> mContentDescription
42 >> mContentDisposition >> mCte >> size >> mPartSpecifier;
44 kasciitolower( mContentDisposition.data() );
45 kasciitoupper( mOriginalContentTypeStr.data() );
48 int sep = mOriginalContentTypeStr.find(
'/');
49 mType = mOriginalContentTypeStr.left(sep);
50 mSubtype = mOriginalContentTypeStr.mid(sep+1);
52 mBodyDecodedSize = size;
57 KMMessagePart::~KMMessagePart()
63 void KMMessagePart::clear()
65 mOriginalContentTypeStr = TQCString();
69 mContentDescription = TQCString();
70 mContentDisposition = TQCString();
72 mAdditionalCTypeParamStr = TQCString();
74 mParameterAttribute = TQCString();
75 mParameterValue = TQString();
76 mCharset = TQCString();
77 mPartSpecifier = TQString();
86 void KMMessagePart::duplicate(
const KMMessagePart & msgPart )
95 int KMMessagePart::decodedSize(
void)
const
97 if (mBodyDecodedSize < 0)
98 mBodyDecodedSize = bodyDecodedBinary().size();
99 return mBodyDecodedSize;
104 void KMMessagePart::setBody(
const TQCString &aStr)
109 if (enc == DwMime::kCte7bit || enc == DwMime::kCte8bit || enc == DwMime::kCteBinary)
110 mBodyDecodedSize = mBody.size();
112 mBodyDecodedSize = -1;
115 void KMMessagePart::setBody(
const DwString &aStr)
117 mBody.duplicate( aStr.c_str(), aStr.length() );
120 if (enc == DwMime::kCte7bit || enc == DwMime::kCte8bit || enc == DwMime::kCteBinary)
121 mBodyDecodedSize = mBody.size();
123 mBodyDecodedSize = -1;
126 void KMMessagePart::setBody(
const TQByteArray &aStr)
131 if (enc == DwMime::kCte7bit || enc == DwMime::kCte8bit || enc == DwMime::kCteBinary)
132 mBodyDecodedSize = mBody.size();
134 mBodyDecodedSize = -1;
137 void KMMessagePart::setBodyFromUnicode(
const TQString & str ) {
139 if ( encoding.isEmpty() )
141 const TQTextCodec * codec = KMMsgBase::codecForName( encoding );
143 TQValueList<int> dummy;
144 setCharset( encoding );
145 setBodyAndGuessCte( codec->fromUnicode( str ), dummy,
false );
148 const TQTextCodec * KMMessagePart::codec()
const {
149 const TQTextCodec * c = KMMsgBase::codecForName( charset() );
154 c = KMMsgBase::codecForName( GlobalSettings::self()->fallbackCharacterEncoding().latin1() );
159 c = kmkernel->networkCodec();
164 TQString KMMessagePart::bodyToUnicode(
const TQTextCodec* codec)
const {
167 codec = this->codec();
170 return codec->toUnicode( bodyDecoded() );
173 void KMMessagePart::setCharset(
const TQCString & c ) {
174 if ( type() != DwMime::kTypeText )
176 <<
"KMMessagePart::setCharset(): trying to set a charset for a non-textual mimetype." << endl
177 <<
"Fix this caller:" << endl
178 <<
"====================================================================" << endl
179 << kdBacktrace( 5 ) << endl
180 <<
"====================================================================" << endl;
185 void KMMessagePart::setBodyEncoded(
const TQCString& aStr)
187 mBodyDecodedSize = aStr.size() - 1;
190 case DwMime::kCteQuotedPrintable:
191 case DwMime::kCteBase64:
193 Codec * codec = Codec::codecForName( cteStr() );
197 mBody.resize( codec->maxEncodedSizeFor( mBodyDecodedSize ) );
198 TQCString::ConstIterator iit = aStr.data();
199 TQCString::ConstIterator iend = aStr.data() + mBodyDecodedSize;
200 TQByteArray::Iterator oit = mBody.begin();
201 TQByteArray::ConstIterator oend = mBody.end();
202 if ( !codec->encode( iit, iend, oit, oend ) )
203 kdWarning(5006) << codec->name()
204 <<
" codec lies about it's maxEncodedSizeFor( "
205 << mBodyDecodedSize <<
" ). Result truncated!" << endl;
206 mBody.truncate( oit - mBody.begin() );
210 kdWarning(5006) <<
"setBodyEncoded: unknown encoding '" << cteStr()
211 <<
"'. Assuming binary." << endl;
213 case DwMime::kCte7bit:
214 case DwMime::kCte8bit:
215 case DwMime::kCteBinary:
217 mBody.duplicate( aStr.data(), mBodyDecodedSize );
222 void KMMessagePart::setBodyAndGuessCte(
const TQByteArray& aBuf,
223 TQValueList<int> & allowedCte,
227 mBodyDecodedSize = aBuf.size();
235 DwCteEnumToStr(allowedCte[0], dwCte);
236 kdDebug(5006) <<
"CharFreq returned " << cf.type() <<
"/"
237 << cf.printableRatio() <<
" and I chose "
238 << dwCte.c_str() << endl;
241 setCte( allowedCte[0] );
242 setBodyEncodedBinary( aBuf );
245 void KMMessagePart::setBodyAndGuessCte(
const TQCString& aBuf,
246 TQValueList<int> & allowedCte,
250 mBodyDecodedSize = aBuf.size() - 1;
252 CharFreq cf( aBuf.data(), mBodyDecodedSize );
258 DwCteEnumToStr(allowedCte[0], dwCte);
259 kdDebug(5006) <<
"CharFreq returned " << cf.type() <<
"/"
260 << cf.printableRatio() <<
" and I chose "
261 << dwCte.c_str() << endl;
264 setCte( allowedCte[0] );
265 setBodyEncoded( aBuf );
269 void KMMessagePart::setBodyEncodedBinary(
const TQByteArray& aStr)
271 mBodyDecodedSize = aStr.size();
280 case DwMime::kCteQuotedPrintable:
281 case DwMime::kCteBase64:
283 Codec * codec = Codec::codecForName( cteStr() );
286 mBody = codec->encode( aStr );
289 mBodyDecodedSize = -1;
293 kdWarning(5006) <<
"setBodyEncodedBinary: unknown encoding '" << cteStr()
294 <<
"'. Assuming binary." << endl;
296 case DwMime::kCte7bit:
297 case DwMime::kCte8bit:
298 case DwMime::kCteBinary:
306 void KMMessagePart::setMessageBody(
const TQByteArray& aBuf )
309 mBodyDecodedSize = aBuf.size();
312 switch ( cf.type() ) {
313 case CharFreq::SevenBitText:
314 case CharFreq::SevenBitData:
315 cte = DwMime::kCte7bit;
317 case CharFreq::EightBitText:
318 case CharFreq::EightBitData:
319 cte = DwMime::kCte8bit;
322 kdWarning(5006) <<
"Calling " << k_funcinfo
323 <<
" with something containing neither 7 nor 8 bit text!"
324 <<
" Fix this caller: " << kdBacktrace() << endl;
327 setBodyEncodedBinary( aBuf );
331 TQByteArray KMMessagePart::bodyDecodedBinary()
const
333 if (mBody.isEmpty())
return TQByteArray();
338 case DwMime::kCte7bit:
339 case DwMime::kCte8bit:
340 case DwMime::kCteBinary:
341 result.duplicate(mBody);
344 if (
const Codec * codec = Codec::codecForName( cteStr() ) )
346 result = codec->decode( mBody );
348 kdWarning(5006) <<
"bodyDecodedBinary: unknown encoding '" << cteStr()
349 <<
"'. Assuming binary." << endl;
350 result.duplicate(mBody);
354 assert( mBodyDecodedSize < 0
355 || (
unsigned int)mBodyDecodedSize == result.size() );
356 if ( mBodyDecodedSize < 0 )
357 mBodyDecodedSize = result.size();
362 TQCString KMMessagePart::bodyDecoded(
void)
const
364 if (mBody.isEmpty())
return TQCString(
"");
365 bool decodeBinary =
false;
371 case DwMime::kCte7bit:
372 case DwMime::kCte8bit:
373 case DwMime::kCteBinary:
379 if (
const Codec * codec = Codec::codecForName( cteStr() ) ) {
382 int bufSize = codec->maxDecodedSizeFor( mBody.size() ) + 1;
383 result.resize( bufSize );
384 TQByteArray::ConstIterator iit = mBody.begin();
385 TQCString::Iterator oit = result.begin();
386 TQCString::ConstIterator oend = result.begin() + bufSize;
387 if ( !codec->decode( iit, mBody.end(), oit, oend ) )
388 kdWarning(5006) << codec->name()
389 <<
" lies about it's maxDecodedSizeFor( "
390 << mBody.size() <<
" ). Result truncated!" << endl;
391 len = oit - result.begin();
392 result.truncate( len );
394 kdWarning(5006) <<
"bodyDecoded: unknown encoding '" << cteStr()
395 <<
"'. Assuming binary." << endl;
400 if ( decodeBinary ) {
409 result = result.replace(
"\r\n",
"\n" );
411 assert( mBodyDecodedSize < 0 || mBodyDecodedSize == len );
412 if ( mBodyDecodedSize < 0 )
413 mBodyDecodedSize = len;
420 void KMMessagePart::magicSetType(
bool aAutoDecode)
422 KMimeMagic::self()->setFollowLinks(
true );
424 const TQByteArray body = ( aAutoDecode ) ? bodyDecodedBinary() : mBody ;
425 KMimeMagicResult * result = KMimeMagic::self()->findBufferType( body );
427 TQString mimetype = result->mimeType();
428 const int sep = mimetype.find(
'/');
429 mType = mimetype.left(sep).latin1();
430 mSubtype = mimetype.mid(sep+1).latin1();
435 TQString KMMessagePart::iconName(
int size )
const
437 TQCString mimeType( mType +
"/" + mSubtype );
438 kasciitolower( mimeType.data() );
441 KMimeType::mimeType( mimeType )->icon( TQString(),
false );
442 if ( fileName.isEmpty() )
444 fileName = this->fileName();
445 if ( fileName.isEmpty() ) fileName = this->name();
446 if ( !fileName.isEmpty() )
448 fileName = KMimeType::findByPath(
"/tmp/"+fileName, 0,
true )->icon( TQString(),
true );
453 TDEGlobal::instance()->iconLoader()->iconPath( fileName, size );
459 int KMMessagePart::type()
const {
460 return DwTypeStrToEnum(DwString(mType));
465 void KMMessagePart::setType(
int aType)
468 DwTypeEnumToStr(aType, dwType);
469 mType = dwType.c_str();
473 int KMMessagePart::subtype()
const {
474 return DwSubtypeStrToEnum(DwString(mSubtype));
479 void KMMessagePart::setSubtype(
int aSubtype)
482 DwSubtypeEnumToStr(aSubtype, dwSubtype);
483 mSubtype = dwSubtype.c_str();
487 TQCString KMMessagePart::parameterAttribute(
void)
const
489 return mParameterAttribute;
493 TQString KMMessagePart::parameterValue(
void)
const
495 return mParameterValue;
499 void KMMessagePart::setParameter(
const TQCString &attribute,
500 const TQString &value)
502 mParameterAttribute = attribute;
503 mParameterValue = value;
507 TQCString KMMessagePart::contentTransferEncodingStr(
void)
const
514 int KMMessagePart::contentTransferEncoding(
void)
const
516 return DwCteStrToEnum(DwString(mCte));
521 void KMMessagePart::setContentTransferEncodingStr(
const TQCString &aStr)
528 void KMMessagePart::setContentTransferEncoding(
int aCte)
531 DwCteEnumToStr(aCte, dwCte);
532 mCte = dwCte.c_str();
538 TQString KMMessagePart::contentDescription(
void)
const
540 return KMMsgBase::decodeRFC2047String(mContentDescription, charset());
545 void KMMessagePart::setContentDescription(
const TQString &aStr)
547 TQCString encoding = KMMsgBase::autoDetectCharset(charset(),
549 if (encoding.isEmpty()) encoding =
"utf-8";
550 mContentDescription = KMMsgBase::encodeRFC2047String(aStr, encoding);
555 TQString KMMessagePart::fileName(
void)
const
561 if ( mContentDisposition.contains(
"filename*",
false ) ) {
564 str = KMMsgBase::extractRFC2231HeaderField( mContentDisposition,
"filename" );
565 return KMMsgBase::decodeRFC2231String(str);
571 int startOfFilename = mContentDisposition.find(
"filename=", 0,
false);
572 if (startOfFilename < 0)
574 startOfFilename += 9;
578 if (
'"' == mContentDisposition[startOfFilename] ) {
580 endOfFilename = mContentDisposition.find(
'"', startOfFilename) - 1;
583 endOfFilename = mContentDisposition.find(
';', startOfFilename) - 1;
585 if (endOfFilename < 0)
586 endOfFilename = 32767;
588 const TQCString str = mContentDisposition.mid(startOfFilename,
589 endOfFilename-startOfFilename+1)
591 return KMMsgBase::decodeRFC2047String(str);
597 TQCString KMMessagePart::body()
const
599 return TQCString( mBody.data(), mBody.size() + 1 );
602 DwString KMMessagePart::dwBody()
const
static TQValueList< int > determineAllowedCtes(const KMime::CharFreq &cf, bool allow8Bit, bool willBeSigned)
Returns a list of content-transfer-encodings that can be used with the given result of the character ...
static const TQStringList & preferredCharsets()
Get a list of preferred message charsets.
void setFromTQCString(TQByteArray &arr, const TQCString &cstr)
Fills a TQByteArray from a TQCString - removing the trailing null.
void setFromByteArray(TQCString &cstr, const TQByteArray &arr)
Fills a TQCString from a TQByteArray - adding the trailing null.
DwString dwString(const TQCString &str)
Construct a DwString from a TQCString.