18 #include "mimeheader.h"
19 #include "mimehdrline.h"
20 #include "mailheader.h"
21 #include "rfcdecoder.h"
26 #include <tdeglobal.h>
27 #include <kinstance.h>
28 #include <kiconloader.h>
29 #include <kmimetype.h>
30 #include <kmimemagic.h>
34 mimeHeader::mimeHeader ():
35 typeList (17, false), dispositionList (17, false)
38 originalHdrLines.setAutoDelete (
true);
39 additionalHdrLines.setAutoDelete (
false);
40 nestedParts.setAutoDelete (
true);
41 typeList.setAutoDelete (
true);
42 dispositionList.setAutoDelete (
true);
45 contentType =
"application/octet-stream";
48 mimeHeader::~mimeHeader ()
79 originalHdrLines.append (addLine);
80 if (tqstrnicmp (addLine->
getLabel (),
"Content-", 8))
82 additionalHdrLines.append (addLine);
87 const char *aCStr = addLine->
getValue ().data ();
88 TQDict < TQString > *aList = 0;
96 if (aCStr[skip - 1] ==
'\r')
98 if (aCStr[skip - 1] ==
'\n')
100 if (aCStr[skip - 2] ==
'\r')
102 if (aCStr[skip - 1] ==
';')
105 TQCString mimeValue = TQCString (aCStr, skip - cut + 1);
108 if (!tqstricmp (addLine->
getLabel (),
"Content-Disposition"))
110 aList = &dispositionList;
111 _contentDisposition = mimeValue;
113 else if (!tqstricmp (addLine->
getLabel (),
"Content-Type"))
116 contentType = mimeValue;
119 if (!tqstricmp (addLine->
getLabel (),
"Content-Transfer-Encoding"))
121 contentEncoding = mimeValue;
123 else if (!tqstricmp (addLine->
getLabel (),
"Content-ID"))
125 contentID = mimeValue;
127 else if (!tqstricmp (addLine->
getLabel (),
"Content-Description"))
129 _contentDescription = mimeValue;
131 else if (!tqstricmp (addLine->
getLabel (),
"Content-MD5"))
133 contentMD5 = mimeValue;
135 else if (!tqstricmp (addLine->
getLabel (),
"Content-Length"))
137 contentLength = mimeValue.toULong ();
141 additionalHdrLines.append (addLine);
150 addParameter (TQCString (aCStr, skip).simplifyWhiteSpace(), aList);
152 mimeValue = TQCString (addLine->
getValue ().data (), skip);
164 mimeHeader::addParameter (
const TQCString& aParameter, TQDict < TQString > *aList)
171 int pos = aParameter.find (
'=');
173 aValue =
new TQString ();
174 aValue->setLatin1 (aParameter.right (aParameter.length () - pos - 1));
175 aLabel = aParameter.left (pos);
176 if ((*aValue)[0] ==
'"')
177 *aValue = aValue->mid (1, aValue->length () - 2);
179 aList->insert (aLabel, aValue);
184 mimeHeader::getDispositionParm (
const TQCString& aStr)
186 return getParameter (aStr, &dispositionList);
190 mimeHeader::getTypeParm (
const TQCString& aStr)
192 return getParameter (aStr, &typeList);
196 mimeHeader::setDispositionParm (
const TQCString& aLabel,
const TQString& aValue)
198 setParameter (aLabel, aValue, &dispositionList);
203 mimeHeader::setTypeParm (
const TQCString& aLabel,
const TQString& aValue)
205 setParameter (aLabel, aValue, &typeList);
208 TQDictIterator < TQString > mimeHeader::getDispositionIterator ()
210 return TQDictIterator < TQString > (dispositionList);
213 TQDictIterator < TQString > mimeHeader::getTypeIterator ()
215 return TQDictIterator < TQString > (typeList);
218 TQPtrListIterator < mimeHdrLine > mimeHeader::getOriginalIterator ()
220 return TQPtrListIterator < mimeHdrLine > (originalHdrLines);
223 TQPtrListIterator < mimeHdrLine > mimeHeader::getAdditionalIterator ()
225 return TQPtrListIterator < mimeHdrLine > (additionalHdrLines);
229 mimeHeader::outputHeader (
mimeIO & useIO)
231 if (!getDisposition ().isEmpty ())
233 useIO.outputMimeLine (TQCString (
"Content-Disposition: ")
235 + outputParameter (&dispositionList));
238 if (!getType ().isEmpty ())
240 useIO.outputMimeLine (TQCString (
"Content-Type: ")
241 + getType () + outputParameter (&typeList));
243 if (!getDescription ().isEmpty ())
244 useIO.outputMimeLine (TQCString (
"Content-Description: ") +
246 if (!getID ().isEmpty ())
247 useIO.outputMimeLine (TQCString (
"Content-ID: ") + getID ());
248 if (!getMD5 ().isEmpty ())
249 useIO.outputMimeLine (TQCString (
"Content-MD5: ") + getMD5 ());
250 if (!getEncoding ().isEmpty ())
251 useIO.outputMimeLine (TQCString (
"Content-Transfer-Encoding: ") +
254 TQPtrListIterator < mimeHdrLine > ait = getAdditionalIterator ();
255 while (ait.current ())
257 useIO.outputMimeLine (ait.current ()->getLabel () +
": " +
258 ait.current ()->getValue ());
261 useIO.outputMimeLine (TQCString (
""));
265 mimeHeader::getParameter (
const TQCString& aStr, TQDict < TQString > *aDict)
267 TQString retVal, *found;
271 found = aDict->find (aStr);
275 found = aDict->find (aStr +
"*");
279 TQString decoded, encoded;
285 search.setNum (part);
286 search = aStr +
"*" + search;
287 found = aDict->find (search);
290 found = aDict->find (search +
"*");
301 if (encoded.find (
'\'') >= 0)
309 encoded.local8Bit ());
327 mimeHeader::setParameter (
const TQCString& aLabel,
const TQString& aValue,
328 TQDict < TQString > *aDict)
332 TQString val = aValue;
338 if (encoded && aLabel.find (
'*') == -1)
345 llen = aLabel.length();
346 if (vlen + llen + 4 > 80 && llen < 80 - 8 - 2 )
348 const int limit = 80 - 8 - 2 - (int)llen;
354 TQCString shortLabel;
356 while (!val.isEmpty ())
359 if ( limit >=
int(vlen) ) {
366 if ( val[partLen-1] ==
'%' ) {
369 else if ( partLen > 1 && val[partLen-2] ==
'%' ) {
374 if ( partLen >
int(vlen) ) {
378 shortValue = val.left( partLen );
379 shortLabel.setNum (i);
380 shortLabel = aLabel +
"*" + shortLabel;
381 val = val.right( vlen - partLen );
382 vlen = vlen - partLen;
387 shortValue =
"''" + shortValue;
394 aDict->insert (shortLabel,
new TQString (shortValue));
400 aDict->insert (aLabel,
new TQString (val));
406 mimeHeader::outputParameter (TQDict < TQString > *aDict)
411 TQDictIterator < TQString > it (*aDict);
412 while (it.current ())
414 retVal += (
";\n\t" + it.currentKey () +
"=").latin1 ();
415 if (it.current ()->find (
' ') > 0 || it.current ()->find (
';') > 0)
417 retVal +=
'"' + it.current ()->utf8 () +
'"';
421 retVal += it.current ()->utf8 ();
432 mimeHeader::outputPart (
mimeIO & useIO)
434 TQPtrListIterator < mimeHeader > nestedParts = getNestedIterator ();
436 if (!getTypeParm (
"boundary").isEmpty ())
437 boundary = getTypeParm (
"boundary").latin1 ();
439 outputHeader (useIO);
440 if (!getPreBody ().isEmpty ())
441 useIO.outputMimeLine (getPreBody ());
442 if (getNestedMessage ())
443 getNestedMessage ()->outputPart (useIO);
444 while (nestedParts.current ())
446 if (!boundary.isEmpty ())
447 useIO.outputMimeLine (
"--" + boundary);
448 nestedParts.current ()->outputPart (useIO);
451 if (!boundary.isEmpty ())
452 useIO.outputMimeLine (
"--" + boundary +
"--");
453 if (!getPostBody ().isEmpty ())
454 useIO.outputMimeLine (getPostBody ());
458 mimeHeader::parsePart (
mimeIO & useIO,
const TQString& boundary)
462 TQCString preNested, postNested;
463 mbox = parseHeader (useIO);
465 kdDebug(7116) <<
"mimeHeader::parsePart - parsing part '" << getType () <<
"'" << endl;
466 if (!tqstrnicmp (getType (),
"Multipart", 9))
468 retVal = parseBody (useIO, preNested, getTypeParm (
"boundary"));
469 setPreBody (preNested);
476 if (!tqstrnicmp (getType (),
"Multipart/Digest", 16))
477 aHeader->setType (
"Message/RFC822");
479 localRetVal = aHeader->parsePart (useIO, getTypeParm (
"boundary"));
480 addNestedPart (aHeader);
484 if (!tqstrnicmp (getType (),
"Message/RFC822", 14))
487 retVal = msgHeader->parsePart (useIO, boundary);
488 setNestedMessage (msgHeader);
492 retVal = parseBody (useIO, postNested, boundary, mbox);
493 setPostBody (postNested);
499 mimeHeader::parseBody (
mimeIO & useIO, TQCString & messageBody,
500 const TQString& boundary,
bool mbox)
504 TQString partBoundary;
508 if (!boundary.isEmpty ())
510 partBoundary = TQString (
"--") + boundary;
511 partEnd = TQString (
"--") + boundary +
"--";
514 while (useIO.inputLine (inputStr))
517 if (!partEnd.isEmpty ()
518 && !tqstrnicmp (inputStr, partEnd.latin1 (), partEnd.length () - 1))
523 else if (!partBoundary.isEmpty ()
524 && !tqstrnicmp (inputStr, partBoundary.latin1 (),
525 partBoundary.length () - 1))
530 else if (mbox && inputStr.find (
"From ") == 0)
536 if (buffer.length () > 16384)
538 messageBody += buffer;
543 messageBody += buffer;
548 mimeHeader::parseHeader (
mimeIO & useIO)
555 kdDebug(7116) <<
"mimeHeader::parseHeader - starting parsing" << endl;
556 while (useIO.inputLine (inputStr))
559 if (inputStr.find (
"From ") != 0 || !first)
562 appended = my_line.appendStr (inputStr);
565 addHdrLine (&my_line);
566 appended = my_line.
setStr (inputStr);
576 inputStr = (
const char *) NULL;
579 kdDebug(7116) <<
"mimeHeader::parseHeader - finished parsing" << endl;
584 mimeHeader::bodyPart (
const TQString & _str)
587 int pt = _str.find(
'.');
590 TQString tempStr = _str;
593 tempStr = _str.right (_str.length () - pt - 1);
596 kdDebug(7116) <<
"mimeHeader::bodyPart - recursing message" << endl;
597 tempPart = nestedMessage->nestedParts.at (_str.left(pt).toULong() - 1);
601 kdDebug(7116) <<
"mimeHeader::bodyPart - recursing mixed" << endl;
602 tempPart = nestedParts.at (_str.left(pt).toULong() - 1);
605 tempPart = tempPart->bodyPart (tempStr);
609 kdDebug(7116) <<
"mimeHeader::bodyPart - returning part " << _str << endl;
613 kdDebug(7116) <<
"mimeHeader::bodyPart - message" << endl;
614 return nestedMessage->nestedParts.at (_str.toULong () - 1);
616 kdDebug(7116) <<
"mimeHeader::bodyPart - mixed" << endl;
617 return nestedParts.at (_str.toULong () - 1);
620 void mimeHeader::serialize(TQDataStream& stream)
622 int nestedcount = nestedParts.count();
623 if (nestedParts.isEmpty() && nestedMessage)
625 stream << nestedcount << contentType << TQString (getTypeParm (
"name")) << _contentDescription
626 << _contentDisposition << contentEncoding << contentLength << partSpecifier;
629 nestedMessage->serialize(stream);
632 if (!nestedParts.isEmpty())
634 TQPtrListIterator < mimeHeader > it(nestedParts);
636 while ( (part = it.current()) != 0 )
639 part->serialize(stream);
644 #ifdef KMAIL_COMPATIBLE
647 mimeHeader::bodyDecoded ()
649 kdDebug(7116) <<
"mimeHeader::bodyDecoded" << endl;
652 temp = bodyDecodedBinary ();
653 return TQString::fromLatin1 (temp.data (), temp.count ());
657 mimeHeader::bodyDecodedBinary ()
661 if (contentEncoding.find (
"quoted-printable", 0,
false) == 0)
662 retVal = KCodecs::quotedPrintableDecode(postMultipartBody);
663 else if (contentEncoding.find (
"base64", 0,
false) == 0)
664 KCodecs::base64Decode(postMultipartBody, retVal);
665 else retVal = postMultipartBody;
667 kdDebug(7116) <<
"mimeHeader::bodyDecodedBinary - size is " << retVal.size () << endl;
672 mimeHeader::setBodyEncodedBinary (
const TQByteArray & _arr)
674 setBodyEncoded (_arr);
678 mimeHeader::setBodyEncoded (
const TQByteArray & _arr)
682 kdDebug(7116) <<
"mimeHeader::setBodyEncoded - in size " << _arr.size () << endl;
683 if (contentEncoding.find (
"quoted-printable", 0,
false) == 0)
684 setVal = KCodecs::quotedPrintableEncode(_arr);
685 else if (contentEncoding.find (
"base64", 0,
false) == 0)
686 KCodecs::base64Encode(_arr, setVal);
688 setVal.duplicate (_arr);
689 kdDebug(7116) <<
"mimeHeader::setBodyEncoded - out size " << setVal.size () << endl;
691 postMultipartBody.duplicate (setVal);
692 kdDebug(7116) <<
"mimeHeader::setBodyEncoded - out size " << postMultipartBody.size () << endl;
696 mimeHeader::iconName ()
702 KMimeType::mimeType (contentType.lower ())->icon (TQString(),
false);
704 TDEGlobal::instance ()->iconLoader ()->iconPath (fileName, TDEIcon::Desktop);
711 mimeHeader::setNestedMessage (
mailHeader * inPart,
bool destroy)
714 nestedMessage = inPart;
718 mimeHeader::headerAsString ()
723 return myIO.getString ();
727 mimeHeader::magicSetType (
bool aAutoDecode)
731 KMimeMagicResult *result;
733 KMimeMagic::self ()->setFollowLinks (TRUE);
736 body = bodyDecodedBinary ();
738 body = postMultipartBody;
740 result = KMimeMagic::self ()->findBufferType (body);
741 mimetype = result->mimeType ();
742 contentType = mimetype;
static int parseSeparator(char, const char *)
parses continuated lines
const TQCString & getLabel()
return the label
int setStr(const char *)
parse a Line into the class and report characters slurped
const TQCString & getValue()
return the value
static const TQString encodeRFC2231String(const TQString &_str)
encode a RFC2231 String
static const TQString decodeRFC2231String(const TQString &_str)
decode a RFC2231 String