/components/turbopower_ipro/ipmsg.pas

http://github.com/graemeg/lazarus · Pascal · 3913 lines · 3167 code · 357 blank · 389 comment · 307 complexity · 49ed960178c43d853e819ba5dc768291 MD5 · raw file

Large files are truncated click here to view the full file

  1. {******************************************************************}
  2. {* IPMSG.PAS - MIME message classes *}
  3. {******************************************************************}
  4. { $Id$ }
  5. (* ***** BEGIN LICENSE BLOCK *****
  6. * Version: MPL 1.1
  7. *
  8. * The contents of this file are subject to the Mozilla Public License Version
  9. * 1.1 (the "License"); you may not use this file except in compliance with
  10. * the License. You may obtain a copy of the License at
  11. * http://www.mozilla.org/MPL/
  12. *
  13. * Software distributed under the License is distributed on an "AS IS" basis,
  14. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  15. * for the specific language governing rights and limitations under the
  16. * License.
  17. *
  18. * The Original Code is TurboPower Internet Professional
  19. *
  20. * The Initial Developer of the Original Code is
  21. * TurboPower Software
  22. *
  23. * Portions created by the Initial Developer are Copyright (C) 2000-2002
  24. * the Initial Developer. All Rights Reserved.
  25. *
  26. * Contributor(s):
  27. *
  28. * Markus Kaemmerer <mk@happyarts.de> SourceForge: mkaemmerer
  29. *
  30. * ***** END LICENSE BLOCK ***** *)
  31. { Global defines potentially affecting this unit }
  32. {$I IPDEFINE.INC}
  33. unit IpMsg;
  34. interface
  35. uses
  36. {$IFDEF IP_LAZARUS}
  37. LCLType,
  38. LCLIntf,
  39. LazFileUtils, LazUTF8Classes,
  40. {$ELSE}
  41. Windows,
  42. {$ENDIF}
  43. Classes,
  44. SysUtils,
  45. IpStrms,
  46. {$IFNDEF IP_LAZARUS}
  47. //IpSock, //JMN
  48. {$ENDIF}
  49. IpUtils,
  50. IpConst;
  51. type
  52. TIpMimeEncodingMethod = (em7Bit, em8Bit, emBase64, emBinary, emBinHex,
  53. emQuoted, emUUEncode, emUnknown);
  54. { TIpMimeEntity }
  55. type
  56. TIpCodingProgressEvent = procedure(Sender : TObject; Progress : Byte;
  57. var Abort : Boolean) of object;
  58. {Begin !!.12}
  59. type
  60. TIpHeaderTypes = (htBCC, htCC, htControl, htDate, htDispositionNotify,
  61. htFollowUp, htFrom, htInReplyTo, htKeywords,
  62. htMessageID, htNewsgroups, htNNTPPostingHost,
  63. htOrganization, htPath, htPostingHost, htReceived,
  64. htReferences, htReplyTo, htReturnPath, htSender,
  65. htSubject, htTo, htUserFields, htXIpro);
  66. TIpHeaderInfo = record
  67. FieldType : TIpHeaderTypes;
  68. FieldString : string;
  69. end;
  70. const
  71. IpMaxHeaders = 24;
  72. IpHeaderXRef : array [0..IpMaxHeaders - 1] of TIpHeaderInfo =
  73. ((FieldType : htBCC; FieldString : 'BCC'),
  74. (FieldType : htCC; FieldString : 'CC'),
  75. (FieldType : htControl; FieldString : 'Control: '),
  76. (FieldType : htDate; FieldString : 'Date'),
  77. (FieldType : htDispositionNotify; FieldString : 'Disposition-Notification-To'),
  78. (FieldType : htFollowUp; FieldString : 'Followup-To: '),
  79. (FieldType : htFrom; FieldString : 'From'),
  80. (FieldType : htInReplyTo; FieldString : 'In-Reply-To'),
  81. (FieldType : htKeywords; FieldString : 'Keywords'),
  82. (FieldType : htMessageID; FieldString : 'Message-ID'),
  83. (FieldType : htNewsgroups; FieldString : 'Newsgroups'),
  84. (FieldType : htNNTPPostingHost; FieldString : 'NNTP-Posting-Host'),
  85. (FieldType : htOrganization; FieldString : 'Organization'),
  86. (FieldType : htPath; FieldString : 'Path'),
  87. (FieldType : htPostingHost; FieldString : 'Posting-Host'),
  88. (FieldType : htReceived; FieldString : 'Received'),
  89. (FieldType : htReferences; FieldString : 'References'),
  90. (FieldType : htReplyTo; FieldString : 'Reply-To'),
  91. (FieldType : htReturnPath; FieldString : 'Return-Path'),
  92. (FieldType : htSender; FieldString : 'Sender'),
  93. (FieldType : htSubject; FieldString : 'Subject'),
  94. (FieldType : htTo; FieldString : 'To'),
  95. (FieldType : htUserFields; FieldString : 'X-'),
  96. (FieldType : htXIpro; FieldString : 'X-Ipro'));
  97. type
  98. TIpHeaderCollection = class;
  99. TIpHeaderItem = class (TCollectionItem)
  100. private
  101. FCollection : TIpHeaderCollection;
  102. FName : string;
  103. FNameL : string;
  104. { Lower case version of FName. Used to speed up header searches. }
  105. FProperty : Boolean; {!!.13}
  106. FValue : TStringList;
  107. protected
  108. procedure SetName(const Name : string);
  109. procedure SetValue (v : TStringList);
  110. public
  111. constructor Create (Collection : TCollection); override;
  112. destructor Destroy; override;
  113. published
  114. property Collection : TIpHeaderCollection
  115. read FCollection write FCollection;
  116. property Name : string read FName write SetName;
  117. property NameL : string read FNameL;
  118. { Lower case version of Name property. }
  119. property IsProperty : Boolean read FProperty write FProperty; {!!.13}
  120. { Set to True if this header is exposed via an iPRO property. }{!!.13}
  121. property Value : TStringList read FValue write SetValue;
  122. end;
  123. TIpHeaderCollection = class (TCollection)
  124. private
  125. FOwner : TPersistent;
  126. protected
  127. function GetItem (Index : Integer) : TIpHeaderItem;
  128. function GetOwner : TPersistent; override;
  129. procedure SetItem (Index : Integer; Value : TIpHeaderItem);
  130. public
  131. constructor Create (AOwner : TPersistent);
  132. {$IFNDEF VERSION5}
  133. procedure Delete (Item : integer);
  134. {$ENDIF}
  135. function HasHeader (AName : string) : Integer;
  136. procedure HeaderByName (AName : string;
  137. Headers : TStringList);
  138. procedure LoadHeaders (AHeaderList : TStringList;
  139. Append : Boolean);
  140. property Items[Index : Integer] : TIpHeaderItem
  141. read GetItem write SetItem;
  142. end;
  143. {End !!.12}
  144. TIpMimeParts = class; { Forwards }
  145. TIpMimeEntity = class(TPersistent)
  146. protected {private}
  147. FProgress : Byte;
  148. PrevProgress : Byte;
  149. FMimeParts : TIpMimeParts;
  150. FParentBoundary : string;
  151. FBody : TIpAnsiTextStream;
  152. FEntityName : string;
  153. FBoundary : string;
  154. FCharacterSet : string;
  155. FContentDescription : string;
  156. FContentDispositionType : string;
  157. FContentID : string;
  158. FContentSubtype : string;
  159. FContentType : string;
  160. FCreationDate : string;
  161. FContentTransferEncoding : TIpMimeEncodingMethod;
  162. FFileName : string;
  163. FIsMime : Boolean;
  164. FIsMultipart : Boolean;
  165. FModificationDate : string;
  166. FMimeVersion : string;
  167. FOnCodingProgress : TIpCodingProgressEvent;
  168. FOriginalSize : Longint;
  169. FParent : TIpMimeEntity;
  170. FReadDate : string;
  171. FRelatedType : string; {!!.02}
  172. FRelatedSubtype : string; {!!.02}
  173. FRelatedStart : string; {!!.02}
  174. FRelatedStartInfo : string; {!!.02}
  175. FAttachmentCount : Integer; {!!.12}
  176. protected {methods}
  177. procedure Clear; virtual;
  178. procedure ClearBodyLargeAttach(const AttachmentSize : Longint); virtual; {!!.12}
  179. function ContainsSpecialChars(const Value : string) : Boolean; {!!.14}
  180. procedure DecodeContentDisposition(const aDisp : string);
  181. procedure DecodeContentType(const aType : string);
  182. function DecodeContentTransferEncoding(const aEncoding : string) :
  183. TIpMimeEncodingMethod;
  184. procedure DecodeMimeHeaders(RawHeaders : TStringlist);
  185. procedure DoOnCodingProgress(Count, TotalSize : Longint; var Abort : Boolean);
  186. procedure EncodeContentDisposition(RawHeaders : TStringList);
  187. procedure EncodeContentType(RawHeaders : TStringList);
  188. procedure EncodeContentTransferEncoding(RawHeaders : TStringList);
  189. procedure EncodeMimeHeaders(RawHeaders : TStringlist);
  190. procedure OctetStreamToHextetStream(InStream : TStream; OutStream : TIpAnsiTextStream;
  191. const Table; PadChar, Delim : AnsiChar);
  192. procedure Decode8Bit(OutStream : TStream);
  193. procedure DecodeBase64(OutStream : TStream);
  194. procedure DecodeBinHex(OutStream : TStream);
  195. procedure DecodeQuoted(OutStream : TStream);
  196. procedure DecodeUUEncode(OutStream : TStream);
  197. procedure Encode8Bit(InStream : TStream);
  198. procedure EncodeBase64(InStream : TStream);
  199. procedure EncodeBinHex(InStream : TStream; const aFileName : string);
  200. procedure EncodeQuoted(InStream : TStream);
  201. procedure EncodeUUEncode(InStream : TStream; const aFileName : string);
  202. function DecodeEntity(InStream : TIpAnsiTextStream) : string;
  203. function DecodeEntityAsAttachment(InStream : TIpAnsiTextStream) : string; {!!.01}
  204. function EncodeEntity(OutStream : TIpAnsiTextStream) : string;
  205. procedure ReadBody(InStream : TIpAnsiTextStream; const StartLine : string); {!!.12}
  206. protected {properties}
  207. property OnCodingProgress : TIpCodingProgressEvent
  208. read FOnCodingProgress write FOnCodingProgress;
  209. public {methods}
  210. constructor Create(ParentEntity : TIpMimeEntity); virtual;
  211. destructor Destroy; override;
  212. procedure ClearBody;
  213. procedure EncodeBodyFile(const InFile : string);
  214. procedure EncodeBodyStream(InStream : TStream; const aFileName : string);
  215. procedure EncodeBodyStrings(InStrings : TStrings; const aFileName : string);
  216. procedure ExtractBodyFile(const OutFile : string);
  217. procedure ExtractBodyStream(OutStream : TStream);
  218. procedure ExtractBodyStrings(OutStrings : TStrings);
  219. function FindNestedMimePart(const aType, aSubType, aContentID : string) : TIpMimeEntity; {!!.02}
  220. function GetMimePart(const aType, aSubType, aContentID : string;
  221. CanCreate : Boolean) : TIpMimeEntity;
  222. function NewMimePart : TIpMimeEntity;
  223. property AttachmentCount : Integer read FAttachmentCount; {!!.12}
  224. public {properties}
  225. property Body : TIpAnsiTextStream
  226. read FBody;
  227. property Boundary : string
  228. read FBoundary write FBoundary;
  229. property CharacterSet : string
  230. read FCharacterSet write FCharacterSet;
  231. property ContentDescription : string
  232. read FContentDescription write FContentDescription;
  233. property ContentDispositionType : string
  234. read FContentDispositionType write FContentDispositionType;
  235. property ContentID : string
  236. read FContentID write FContentID;
  237. property ContentSubtype : string
  238. read FContentSubtype write FContentSubtype;
  239. property ContentTransferEncoding : TIpMimeEncodingMethod
  240. read FContentTransferEncoding write FContentTransferEncoding;
  241. property ContentType : string
  242. read FContentType write FContentType;
  243. property CreationDate : string
  244. read FCreationDate write FCreationDate;
  245. property EntityName : string
  246. read FEntityName write FEntityName;
  247. property FileName : string
  248. read FFileName write FFileName;
  249. property IsMime : Boolean
  250. read FIsMime;
  251. property IsMultipart : Boolean
  252. read FIsMultipart;
  253. property MimeParts : TIpMimeParts
  254. read FMimeParts;
  255. property MimeVersion : string
  256. read FMimeVersion write FMimeVersion;
  257. property ModificationDate : string
  258. read FModificationDate write FModificationDate;
  259. property OriginalSize : Longint
  260. read FOriginalSize write FOriginalSize;
  261. property Parent : TIpMimeEntity
  262. read FParent;
  263. property ReadDate : string
  264. read FReadDate write FReadDate;
  265. property RelatedStart : string {!!.02}
  266. read FRelatedStart write FRelatedStart;
  267. property RelatedStartInfo : string {!!.02}
  268. read FRelatedStartInfo write FRelatedStartInfo;
  269. property RelatedSubtype : string {!!.02}
  270. read FRelatedSubtype write FRelatedSubtype;
  271. property RelatedType : string {!!.02}
  272. read FRelatedType write FRelatedType;
  273. end;
  274. { TIpMimeParts }
  275. TIpMimeParts = class
  276. protected {private}
  277. Entitys : TList;
  278. function GetCount : Integer;
  279. function GetPart(aIndex : Integer) : TIpMimeEntity;
  280. public {methods}
  281. constructor Create;
  282. destructor Destroy; override;
  283. function Add(aEntity : TIpMimeEntity) : Integer;
  284. function Remove(aEntity : TIpMimeEntity) : Integer;
  285. procedure Clear;
  286. procedure Delete(aIndex : Integer);
  287. function IndexOf(aEntity : TIpMimeEntity) : Integer;
  288. public {properties}
  289. property Count : Integer
  290. read GetCount;
  291. property Parts[aIndex : Integer] : TIpMimeEntity
  292. read GetPart; default;
  293. end;
  294. { TIpMessage }
  295. type
  296. TIpMessage = class(TIpMimeEntity)
  297. protected {private}
  298. MsgStream : TIpAnsiTextStream;
  299. protected {property variables}
  300. FBCC : TStringList;
  301. FCC : TStringList;
  302. FDate : string;
  303. FFrom : string;
  304. FInReplyTo : string;
  305. FKeywords : string;
  306. FFollowupTo : string; {!!.12}
  307. FControl : string; {!!.12}
  308. FMessageID : string;
  309. FMessageTag : Integer;
  310. FNewsgroups : TStringList;
  311. FNNTPPostingHost : string;
  312. FOrganization : string;
  313. FPath : TStringList;
  314. FPostingHost : string;
  315. FReceived : TStringList;
  316. FRecipients : TStringList;
  317. FReferences : TStringList;
  318. FReplyTo : string;
  319. FReturnPath : string;
  320. FSender : string;
  321. FSubject : string;
  322. FUserFields : TStringList;
  323. FHeaders : TIpHeaderCollection; {!!.12}
  324. FDispositionNotify: string;
  325. protected {methods}
  326. procedure CheckAllHeaders; {!!.12}
  327. procedure CheckHeaderType (HeaderInfo : TIpHeaderItem; {!!.12}
  328. HeaderType : TIpHeaderTypes); {!!.12}
  329. procedure Clear; override;
  330. procedure NewMessageStream;
  331. function GetPosition : Longint;
  332. function GetSize : Longint;
  333. procedure SetPosition(Value : Longint);
  334. procedure SetBCC(const Value: TStringList);
  335. procedure SetCC(const Value: TStringList);
  336. procedure SetNewsgroups(const Value: TStringList);
  337. procedure SetPath(const Value: TStringList);
  338. procedure SetReceived(const Value: TStringList);
  339. procedure SetRecipients(const Value: TStringList);
  340. procedure SetReferences(const Value: TStringlist);
  341. procedure SetUserFields(const Value: TStringList);
  342. public {methods}
  343. constructor CreateMessage; virtual;
  344. destructor Destroy; override;
  345. procedure AddDefaultAttachment(const aFileName : string); {!!.02}
  346. procedure AddDefaultAttachmentAs (const aFileName : string; {!!.12}
  347. const AttachmentName : string); {!!.12}
  348. procedure Assign(Source : TPersistent); override;
  349. function AtEndOfStream : Boolean;
  350. procedure DecodeMessage; virtual;
  351. procedure EncodeMessage; virtual;
  352. function GetBodyHtml(CanCreate : Boolean) : TIpMimeEntity;
  353. function GetBodyPlain(CanCreate : Boolean) : TIpMimeEntity;
  354. procedure LoadFromFile(const aFileName : string);
  355. procedure LoadFromStream(aStream : TStream); {!!.12}
  356. procedure NewMessage;
  357. function ReadLine : string;
  358. function ReadLineCRLF : string;
  359. procedure SaveToFile(const aFileName : string);
  360. procedure SaveToStream(Stream: TStream); {!!.12}
  361. procedure SetHeaders(Headers : TIpHeaderCollection); {!!.12}
  362. procedure WriteLine(const aSt : string);
  363. public {properties}
  364. property BCC : TStringList
  365. read FBCC write SetBCC; {!!.01}
  366. property CC : TStringList
  367. read FCC write SetCC; {!!.01}
  368. property Control : string {!!.12}
  369. read FControl write FControl; {!!.12}
  370. property Date : string
  371. read FDate write FDate;
  372. property DispositionNotification : string {!!.12}
  373. read FDispositionNotify write FDispositionNotify; {!!.12}
  374. property FollowupTo : String {!!.12}
  375. read FFollowupTo Write FFollowupTo; {!!.12}
  376. property From : string
  377. read FFrom write FFrom;
  378. property Headers : TIpHeaderCollection {!!.12}
  379. read FHeaders write SetHeaders; {!!.12}
  380. property InReplyTo : string
  381. read FInReplyTo write FInReplyTo;
  382. property Keywords : string
  383. read FKeywords write FKeywords;
  384. property MessageID : string
  385. read FMessageID write FMessageID;
  386. property MessageStream : TIpAnsiTextStream {!!.03}
  387. read MsgStream; {!!.03}
  388. property MessageTag : Integer
  389. read FMessageTag write FMessageTag;
  390. property Newsgroups : TStringList
  391. read FNewsgroups write SetNewsgroups; {!!.01}
  392. property NNTPPostingHost : string
  393. read FNNTPPostingHost write FNNTPPostingHost;
  394. property Organization : string
  395. read FOrganization write FOrganization;
  396. property Path : TStringList
  397. read FPath write SetPath; {!!.01}
  398. property Position : Longint
  399. read GetPosition write SetPosition;
  400. property PostingHost : string
  401. read FPostingHost write FPostingHost;
  402. property Received : TStringList
  403. read FReceived write SetReceived; {!!.01}
  404. property Recipients : TStringList
  405. read FRecipients write SetRecipients; {!!.01}
  406. property References : TStringlist
  407. read FReferences write SetReferences; {!!.01}
  408. property ReplyTo : string
  409. read FReplyTo write FReplyTo;
  410. property ReturnPath : string
  411. read FReturnPath write FReturnPath;
  412. property Sender : string
  413. read FSender write FSender;
  414. property Size : Longint
  415. read GetSize;
  416. property Subject : string
  417. read FSubject write FSubject;
  418. property UserFields : TStringList
  419. read FUserFields write SetUserFields; {!!.01}
  420. end;
  421. { TIpMailMessage}
  422. type
  423. TIpMailMessage = class(TIpMessage)
  424. published {properties}
  425. property BCC;
  426. property CC;
  427. property ContentDescription;
  428. property ContentTransferEncoding;
  429. property ContentType;
  430. property Date;
  431. property From;
  432. property Keywords;
  433. property MailTo : TStringList
  434. read FRecipients write SetRecipients; {!!.01}
  435. property OnCodingProgress;
  436. property References;
  437. property ReplyTo;
  438. property Sender;
  439. property Subject;
  440. property UserFields;
  441. end;
  442. { TIpNewsArticle }
  443. type
  444. TIpNewsArticle = class(TIpMessage)
  445. published {properties}
  446. property ContentDescription;
  447. property ContentTransferEncoding;
  448. property ContentType;
  449. property Date;
  450. property From;
  451. property Keywords;
  452. property Newsgroups;
  453. property NNTPPostingHost;
  454. property OnCodingProgress;
  455. property Path;
  456. property References;
  457. property ReplyTo;
  458. property Sender;
  459. property Subject;
  460. property UserFields;
  461. end;
  462. { TIpFormDataEntity }
  463. type
  464. TIpFormDataEntity = class(TIpMimeEntity)
  465. protected
  466. FFilesEntity : TIpMimeEntity;
  467. public {methods}
  468. constructor Create(ParentEntity : TIpMimeEntity); override;
  469. destructor Destroy; override;
  470. procedure AddFormData(const aName, aText : string);
  471. procedure AddFile(const aFileName, aContentType, aSubtype : string;
  472. aEncoding : TIpMimeEncodingMethod);
  473. procedure SaveToStream(aStream : TStream);
  474. end;
  475. {$IFNDEF IP_LAZARUS}
  476. { dummy class so this unit will be added to the uses clause when an }
  477. { IpPop3Client, IpSmtpClient or IpNntpClient component is dropped on the form }
  478. (*** //JMN
  479. TIpCustomEmailClass = class(TIpCustomClient)
  480. end;
  481. **)
  482. {$ENDIF}
  483. function IpBase64EncodeString(const InStr: string): string; {!!.02}{!!.03}
  484. {Begin !!.12}
  485. const
  486. IpLgAttachSizeBoundry = 5 * 1024 * 1024;
  487. { Attachments over this size will be encoded using a TIpMemMapStream for
  488. greatly improved performance. This boundary also applies to the final
  489. encoding of messages with large attachments. }
  490. implementation
  491. const
  492. { standard headers }
  493. strBCC = 'BCC: ';
  494. strCC = 'CC: ';
  495. strDate = 'Date: ';
  496. strDispositionNotify = 'Disposition-Notification-To: ';
  497. strFrom = 'From: ';
  498. strInReplyTo = 'In-Reply-To: ';
  499. strKeywords = 'Keywords: ';
  500. strMessageID = 'Message-ID: ';
  501. strNewsgroups = 'Newsgroups: ';
  502. strNNTPPostingHost = 'NNTP-Posting-Host: ';
  503. strOrganization = 'Organization: ';
  504. strPath = 'Path: ';
  505. strPostingHost = 'Posting-Host: ';
  506. strReceived = 'Received: ';
  507. strReferences = 'References: ';
  508. strReplyTo = 'Reply-To: ';
  509. strReturnPath = 'Return-Path: ';
  510. strSender = 'Sender: ';
  511. strSubject = 'Subject: ';
  512. strTo = 'To: ';
  513. strUserFields = 'X-';
  514. strXIpro = 'X-Ipro: ';
  515. strFollowUp = 'Followup-To: '; {!!.12}
  516. strControl = 'Control: '; {!!.12}
  517. {Begin !!.13}
  518. IpMimeHeaders : array [0..5] of string =
  519. { List of MIME headers that must be marked as public properties in
  520. the message's Headers collection. Marking them as a public property
  521. prevents them from being written out twice if the message is saved
  522. to a file or stream. }
  523. (
  524. 'Content-Type',
  525. 'MIME-Version',
  526. 'Content-Transfer-Encoding',
  527. 'Content-Description',
  528. 'Content-ID',
  529. 'Content-Disposition'
  530. );
  531. {End !!.13}
  532. { MIME headers }
  533. strMimeVersion = 'MIME-Version: ';
  534. strContent = 'Content-';
  535. strContentBase = strContent + 'Base: ';
  536. strContentDescription = strContent + 'Description: ';
  537. strContentDisposition = strContent + 'Disposition: ';
  538. strContentID = strContent + 'ID: ';
  539. strContentLanguage = strContent + 'Language: ';
  540. strContentLocation = strContent + 'Location: ';
  541. strContentTransferEncoding = strContent + 'Transfer-Encoding: ';
  542. strContentType = strContent + 'Type: ';
  543. { MIME content types }
  544. strApplication = 'application';
  545. strAudio = 'audio';
  546. strFiles = 'files';
  547. strFormData = 'form-data';
  548. strImage = 'image';
  549. strMessage = 'message';
  550. strMultiPart = 'multipart';
  551. strText = 'text';
  552. strVideo = 'video';
  553. { MIME content subtypes and parameters }
  554. strBoundary = 'boundary=';
  555. strCharSet = 'charset=';
  556. strMixed = 'mixed';
  557. strName = 'name=';
  558. strPlain = 'plain';
  559. strHTML = 'html';
  560. strOctetStream = 'octet-stream';
  561. strAlternative = 'alternative';
  562. strRelated = 'related'; {!!.02}
  563. { MIME content disposition parameters }
  564. strAttachment = 'attachment';
  565. strInline = 'inline';
  566. strCreationDate = 'creation-date=';
  567. strFilename = 'filename=';
  568. strModificationDate = 'modification-date=';
  569. strReadDate = 'read-date=';
  570. strStart = 'start='; {!!.02}
  571. strStartInfo = 'start-info='; {!!.02}
  572. strSize = 'size=';
  573. strType = 'type='; {!!.02}
  574. { MIME encoding methods }
  575. str7Bit = '7bit';
  576. str8Bit = '8bit';
  577. strBase64 = 'base64';
  578. strBinary = 'binary';
  579. strBinHex = 'binhex';
  580. strQuoted = 'quoted-printable';
  581. strUUEncode = 'uuencoded';
  582. { default MIME content type information }
  583. {$I IPDEFCT.INC}
  584. type
  585. TIp6BitTable = array[0..63] of AnsiChar;
  586. const {- BinHex encoding table }
  587. IpBinHexTable : TIp6BitTable = (
  588. '!', '"', '#', '$', '%', '&', '''', '(',
  589. ')', '*', '+', ',', '-', '0', '1', '2',
  590. '3', '4', '5', '6', '8', '9', '@', 'A',
  591. 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
  592. 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R',
  593. 'S', 'T', 'U', 'V', 'X', 'Y', 'Z', '[',
  594. '`', 'a', 'b', 'c', 'd', 'e', 'f', 'h',
  595. 'i', 'j', 'k', 'l', 'm', 'p', 'q', 'r');
  596. const {-BinHex decoding table }
  597. IpHexBinTable : array[33..114] of Byte = (
  598. $00, $01, $02, $03, $04, $05, $06, $07,
  599. $08, $09, $0A, $0B, $0C, $FF, $FF, $0D,
  600. $0E, $0F, $10, $11, $12, $13, $FF, $14,
  601. $15, $FF, $FF, $FF, $FF, $FF, $FF, $16,
  602. $17, $18, $19, $1A, $1B, $1C, $1D, $1E,
  603. $1F, $20, $21, $22, $23, $24, $FF, $25,
  604. $26, $27, $28, $29, $2A, $2B, $FF, $2C,
  605. $2D, $2E, $2F, $FF, $FF, $FF, $FF, $30,
  606. $31, $32, $33, $34, $35, $36, $FF, $37,
  607. $38, $39, $3A, $3B, $3C, $FF, $FF, $3D,
  608. $3E, $3F);
  609. const { Base64 encoding table }
  610. Ip64Table : TIp6BitTable = (
  611. #065, #066, #067, #068, #069, #070, #071, #072,
  612. #073, #074, #075, #076, #077, #078, #079, #080,
  613. #081, #082, #083, #084, #085, #086, #087, #088,
  614. #089, #090, #097, #098, #099, #100, #101, #102,
  615. #103, #104, #105, #106, #107, #108, #109, #110,
  616. #111, #112, #113, #114, #115, #116, #117, #118,
  617. #119, #120, #121, #122, #048, #049, #050, #051,
  618. #052, #053, #054, #055, #056, #057, #043, #047);
  619. const { Base64 decoding table }
  620. IpD64Table : array[#43..#122] of Byte = ( {!!.12}
  621. $3E, $7F, $7F, $7F, $3F, $34, $35, $36,
  622. $37, $38, $39, $3A, $3B, $3C, $3D, $7F,
  623. $7F, $7F, $7F, $7F, $7F, $7F, $00, $01,
  624. $02, $03, $04, $05, $06, $07, $08, $09,
  625. $0A, $0B, $0C, $0D, $0E, $0F, $10, $11,
  626. $12, $13, $14, $15, $16, $17, $18, $19,
  627. $7F, $7F, $7F, $7F, $7F, $7F, $1A, $1B,
  628. $1C, $1D, $1E, $1F, $20, $21, $22, $23,
  629. $24, $25, $26, $27, $28, $29, $2A, $2B,
  630. $2C, $2D, $2E, $2F, $30, $31, $32, $33);
  631. const { UUEncode encoding table }
  632. IpUUTable : TIp6BitTable = (
  633. #96, #33, #34, #35, #36, #37, #38, #39,
  634. #40, #41, #42, #43, #44, #45, #46, #47,
  635. #48, #49, #50, #51, #52, #53, #54, #55,
  636. #56, #57, #58, #59, #60, #61, #62, #63,
  637. #64, #65, #66, #67, #68, #69, #70, #71,
  638. #72, #73, #74, #75, #76, #77, #78, #79,
  639. #80, #81, #82, #83, #84, #85, #86, #87,
  640. #88, #89, #90, #91, #92, #93, #94, #95);
  641. const
  642. HexDigits : array[0..$F] of AnsiChar = '0123456789ABCDEF';
  643. RLEChar : Byte = $90;
  644. BinHexFileType : array[0..3] of Byte = ($49, $42, $4D, $3F); { "IBM?" }
  645. CRLF = #13#10;
  646. MaxLine = 1000; {!!.12}
  647. MaxLineEncode = 77; {!!.13}
  648. { Maximum line length for QuotablePrintable & Base64 encoding. } {!!.13}
  649. type
  650. BinHexHeader = packed record
  651. Version : Byte;
  652. FileType : array[0..3] of Byte;
  653. Creator : array[0..3] of Byte;
  654. Flags : Word;
  655. DFLong : Longint;
  656. RFLong : Longint;
  657. end;
  658. function IsSameString (Str1 : string; {!!.12}
  659. Str2 : string; {!!.12}
  660. CaseSensitive : Boolean) : Boolean; {!!.12}
  661. begin {!!.12}
  662. if CaseSensitive then {!!.12}
  663. Result := (Str1 = Str2) {!!.12}
  664. else {!!.12}
  665. Result := StrIComp (PChar (Str1), PChar (Str2)) = 0; {!!.12}
  666. end; {!!.12}
  667. { Parse string into string list }
  668. procedure Parse(const Line : string; Delim : AnsiChar; var List : TStringList);
  669. var
  670. iPos, jPos : Integer;
  671. Term : string;
  672. begin
  673. iPos := 1;
  674. jPos := IpUtils.CharPos(Delim, Line);
  675. while (jPos > 0) do begin
  676. Term := Copy(Line, iPos, jPos - iPos); {!!.02}
  677. if (Term <> '') then
  678. List.Add(Trim(Term));
  679. iPos := jPos + 1;
  680. jPos := IpUtils.CharPosIdx(Delim, Line, iPos);
  681. end;
  682. if (iPos < Length(Line)) then
  683. List.Add(Trim(Copy(Line, iPos, Length(Line))));
  684. end;
  685. { Return a particular parameter from a parsed header parameter list }
  686. procedure DecodeSingleParameter(const ParamName : string;
  687. RawParams : TStringList;
  688. var ParamFieldStr : string);
  689. var
  690. S : string;
  691. i, j : Integer;
  692. begin
  693. ParamFieldStr := '';
  694. {find the line containing the parameter field name}
  695. for i := 1 to RawParams.Count do begin
  696. S := RawParams[i-1];
  697. if StrLIComp(PChar(ParamName), PChar(S), Length(ParamName)) = 0 then begin
  698. {strip off the parameter field name and remove quotes }
  699. ParamFieldStr := Copy(S, Length(ParamName) + 1, Length(S));
  700. j := IpUtils.CharPos('"', ParamFieldStr);
  701. while (j > 0) do begin
  702. Delete(ParamFieldStr, j, 1);
  703. j := IpUtils.CharPos('"', ParamFieldStr);
  704. end;
  705. Break;
  706. end;
  707. end;
  708. end;
  709. { Return a particular header as string }
  710. procedure DecodeSingleHeader(const HeaderName : string;
  711. RawHeaders : TStringList;
  712. var HeaderFieldStr : string);
  713. var
  714. S, S2 : string;
  715. i, j : Integer;
  716. begin
  717. HeaderFieldStr := '';
  718. {find the line containing the header field name}
  719. for i := 1 to RawHeaders.Count do begin
  720. S := RawHeaders[i-1];
  721. if StrLIComp(PChar(HeaderName), PChar(S), Length(HeaderName)) = 0 then begin
  722. {strip off the header field name}
  723. S := Copy(S, Length(HeaderName) + 1, Length(S));
  724. {unfold the header if continued on more than one line}
  725. if (i < RawHeaders.Count) then
  726. for j := i to Pred(RawHeaders.Count) do begin
  727. S2 := RawHeaders[j];
  728. if (Length(S2) > 0) and (S2[1] <> #09) and (S2[1] <> ' ') then
  729. Break
  730. else
  731. S := S + S2;
  732. end;
  733. HeaderFieldStr := S;
  734. Break;
  735. end;
  736. end;
  737. end;
  738. { Return a particular header as string list }
  739. (*procedure DecodeListHeader(const HeaderName : string;
  740. RawHeaders, HeaderFieldList : TStringList);
  741. var
  742. S : string;
  743. i, j : Integer;
  744. begin
  745. {find the line containing the header field name}
  746. for i := 1 to RawHeaders.Count do begin
  747. S := RawHeaders[i-1];
  748. if StrLIComp(PChar(HeaderName), PChar(S), Length(HeaderName)) = 0 then begin
  749. {strip off the header field name}
  750. HeaderFieldList.Add(Copy(S, Length(HeaderName) + 1, Length(S)));
  751. {unfold the header if continued on more than one line}
  752. if (i < RawHeaders.Count) then
  753. for j := i to Pred(RawHeaders.Count) do begin
  754. S := RawHeaders[j];
  755. if (Length(S) > 0) and (S[1] <> #09) and (S[1] <> ' ') then
  756. Break
  757. else
  758. HeaderFieldList.Add(S);
  759. end;
  760. Break;
  761. end;
  762. end;
  763. end;*)
  764. { Return multiple instance headers as string list }
  765. (*procedure DecodeMultiHeader(const HeaderName : string;
  766. RawHeaders, HeaderFieldList : TStringList);
  767. var
  768. S, S2 : string;
  769. i, j : Integer;
  770. begin
  771. {find the next line containing the header field name}
  772. for i := 1 to RawHeaders.Count do begin
  773. S := RawHeaders[i-1];
  774. if StrLIComp(PChar(HeaderName), PChar(S), Length(HeaderName)) = 0 then begin
  775. if HeaderName <> strUserFields then begin {!!.11}
  776. {strip off the header field name}
  777. S := Copy(S, Length(HeaderName) + 1, Length(S));
  778. {unfold the header if continued on more than one line}
  779. if (i < RawHeaders.Count) then
  780. for j := i to Pred(RawHeaders.Count) do begin
  781. S2 := RawHeaders[j];
  782. if (Length(S2) > 0) and (S2[1] <> #09) and (S2[1] <> ' ') then
  783. Break
  784. else
  785. S := S + S2;
  786. end;
  787. end; {!!.11}
  788. HeaderFieldList.Add(S);
  789. end;
  790. end;
  791. end;*)
  792. { Add header string to raw headers }
  793. procedure EncodeSingleHeader(const HeaderName : string;
  794. RawHeaders : TStringList;
  795. HeaderFieldStr : string);
  796. begin
  797. if (HeaderFieldStr <> '') then
  798. RawHeaders.Add(HeaderName + HeaderFieldStr);
  799. end;
  800. { Unfold multiple line header and add to raw headers }
  801. procedure EncodeListHeader(const HeaderName : string;
  802. RawHeaders, HeaderFieldList : TStringList;
  803. const Delim : string;
  804. Fold : Boolean);
  805. var
  806. S : string;
  807. i : Integer;
  808. begin
  809. if (HeaderFieldList.Count > 0) then begin
  810. S := HeaderName;
  811. for i := 0 to Pred(HeaderFieldList.Count) do begin
  812. if (Length(S + HeaderFieldList[i]) > MaxLine) then begin
  813. RawHeaders.Add(S);
  814. S := #09;
  815. end;
  816. S := S + HeaderFieldList[i];
  817. if (i < HeaderFieldList.Count - 1) and (S <> '') then begin
  818. S := S + Delim; {!!.14}
  819. if Fold then begin
  820. RawHeaders.Add(S);
  821. S := #09;
  822. end;
  823. end;
  824. end;
  825. RawHeaders.Add(S);
  826. end;
  827. end;
  828. { Add multiple instance header to raw headers }
  829. procedure EncodeMultiHeader(const HeaderName : string;
  830. RawHeaders, HeaderFieldList : TStringList;
  831. Delim : AnsiChar;
  832. Fold : Boolean);
  833. var
  834. i, j : Integer;
  835. SL : TStringList;
  836. S : string;
  837. begin
  838. if (HeaderFieldList.Count > 0) then
  839. for j := 1 to HeaderFieldList.Count do begin
  840. if not Fold then
  841. RawHeaders.Add(HeaderName + HeaderFieldList[j-1])
  842. else begin
  843. SL := TStringList.Create;
  844. try
  845. Parse(HeaderFieldList[j-1], Delim, SL);
  846. S := HeaderName;
  847. for i := 1 to SL.Count do begin
  848. S := S + SL[i-1];
  849. if (i < SL.Count) and (S <> '') then begin
  850. {Begin !!.13}
  851. RawHeaders.Add(S);
  852. S := Delim;
  853. {End !!.13}
  854. end;
  855. end;
  856. finally
  857. SL.Free;
  858. end;
  859. RawHeaders.Add(S);
  860. end;
  861. end;
  862. end;
  863. { Generate "unique" boundary string }
  864. function GenerateBoundary : string;
  865. var
  866. Temp : TDateTime;
  867. begin
  868. Temp := Now;
  869. Randomize;
  870. Result := '_NextPart_' + IntToHex(Trunc(Temp), 8) + '-' +
  871. IntToHex(Trunc(Frac(Temp) * 10000), 8) + '-' +
  872. IntToHex(GetTickCount64, 8) + '-' + IntToHex(Random($FFFF), 4);
  873. end;
  874. { 16-bit CRC of stream between starting and ending offset }
  875. function BinHexCRC(Stream : TStream; StartOffset, EndOffset : Longint) : Word;
  876. var
  877. Crc : Word;
  878. InByte : Byte;
  879. ByteStream : TIpByteStream;
  880. procedure DoCRC(b : Byte);
  881. {- carry CRC division on with next byte }
  882. var
  883. j : Byte;
  884. t : Boolean;
  885. begin
  886. for j := 1 to 8 do begin
  887. t := (Crc and $8000) <> 0;
  888. Crc := (Crc shl 1) xor (b shr 7);
  889. if t then
  890. Crc := Crc xor $1021;
  891. b := b shl 1;
  892. end;
  893. end;
  894. begin
  895. if (StartOffset > Stream.Size) or (EndOffset > Stream.Size) then
  896. raise EIpBaseException.Create(SBadOffset);
  897. Crc := 0;
  898. Stream.Position := StartOffset;
  899. ByteStream := TIpByteStream.Create(Stream);
  900. try
  901. while (ByteStream.Position < EndOffset) do begin
  902. if ByteStream.Read(InByte) then
  903. DoCrc(InByte);
  904. end;
  905. finally
  906. ByteStream.Free;
  907. end;
  908. DoCrc(0);
  909. DoCrc(0);
  910. Result := Swap(Crc);
  911. end;
  912. { Reverse bytes and words }
  913. function htonl(HostLong : Longint) : Longint;
  914. var
  915. dw : Longint;
  916. wa : array[0..1] of Word absolute dw;
  917. w : Word;
  918. begin
  919. dw := HostLong;
  920. w := wa[0];
  921. wa[0] := Swap(wa[1]);
  922. wa[1] := Swap(w);
  923. Result := dw;
  924. end;
  925. {Begin !!.12}
  926. { TIpHeaderItem ****************************************************** }
  927. constructor TIpHeaderItem.Create (Collection : TCollection);
  928. begin
  929. inherited Create (Collection);
  930. FCollection := TIpHeaderCollection.Create (
  931. TIpHeaderCollection(Collection).FOwner);
  932. FValue := TStringList.Create;
  933. FName := '';
  934. FProperty := False; {!!.13}
  935. end;
  936. destructor TIpHeaderItem.Destroy;
  937. begin
  938. FCollection.Free;
  939. FCollection := nil;
  940. FValue.Free;
  941. FValue := nil;
  942. inherited Destroy;
  943. end;
  944. procedure TIpHeaderItem.SetName(const Name : string);
  945. begin
  946. FName := Name;
  947. FNameL := LowerCase(Name);
  948. end;
  949. procedure TIpHeaderItem.SetValue (v : TStringList);
  950. begin
  951. FValue.Assign (v);
  952. end;
  953. { TIpHeaderCollection ************************************************ }
  954. constructor TIpHeaderCollection.Create(AOwner : TPersistent);
  955. begin
  956. inherited Create (TIpHeaderItem);
  957. FOwner := AOwner;
  958. end;
  959. {$IFNDEF VERSION5}
  960. procedure TIpHeaderCollection.Delete(Item: integer);
  961. begin
  962. GetItem(Item).Free;
  963. end;
  964. {$ENDIF}
  965. function TIpHeaderCollection.GetItem (Index : Integer) : TIpHeaderItem;
  966. begin
  967. Result := TIpHeaderItem (inherited GetItem (Index));
  968. end;
  969. function TIpHeaderCollection.GetOwner : TPersistent;
  970. begin
  971. Result := FOwner;
  972. end;
  973. function TIpHeaderCollection.HasHeader (AName : string) : Integer;
  974. var
  975. i : Integer;
  976. begin
  977. Result := -1;
  978. AName := LowerCase(AName);
  979. for i := 0 to Count - 1 do
  980. if Items[i].NameL = AName then begin
  981. Result := i;
  982. Break;
  983. end;
  984. end;
  985. procedure TIpHeaderCollection.HeaderByName (AName : string;
  986. Headers : TStringList);
  987. var
  988. HeaderPos : Integer;
  989. begin
  990. Headers.Clear;
  991. HeaderPos := HasHeader (AName);
  992. if HeaderPos >= 0 then
  993. Headers.Assign (Items[HeaderPos].Value);
  994. end;
  995. procedure TIpHeaderCollection.LoadHeaders (AHeaderList : TStringList;
  996. Append : Boolean);
  997. var
  998. CurPos : Integer;
  999. function ExtractHeaderName (const AName : string) : string;
  1000. {!!.15 - replaced local variable i with inx in order to avoid confusion with
  1001. variable i in parent routine. }
  1002. var
  1003. inx : Integer;
  1004. NameLen : Integer;
  1005. begin
  1006. Result := '';
  1007. CurPos := 0;
  1008. inx := 0;
  1009. NameLen := Length (AName);
  1010. while (inx < NameLen) and (AName[inx + 1] <> ':') and
  1011. (AName[inx + 1] >= #33) and (AName[inx + 1] <= #126) do
  1012. Inc (inx);
  1013. if (inx > 0) then
  1014. Result := Copy (AName, 1, inx);
  1015. CurPos := inx + 2;
  1016. end;
  1017. function IsWrappedLine (AHeaderList : TStringList;
  1018. LineToCheck : Integer) : Boolean;
  1019. begin
  1020. if LineToCheck < AHeaderList.Count then begin
  1021. if Length (AHeaderList[LineToCheck]) > 0 then begin
  1022. if (AHeaderList[LineToCheck][1] = ' ') or
  1023. (AHeaderList[LineToCheck][1] = #09) then
  1024. Result := True
  1025. else
  1026. Result := False;
  1027. end else
  1028. Result := False;
  1029. end else
  1030. Result := False;
  1031. end;
  1032. procedure GetFieldValue ( AHeaderList : TStringList;
  1033. var CurLine : Integer;
  1034. var NewField : TIpHeaderItem);
  1035. var
  1036. WorkLine : string;
  1037. LineLen : Integer;
  1038. begin
  1039. if CurLine >= AHeaderList.Count then
  1040. Exit;
  1041. LineLen := Length (AHeaderList[CurLine]);
  1042. while (CurPos < LineLen) and
  1043. ((AHeaderList[CurLine][CurPos] = ' ') or
  1044. (AHeaderList[CurLine][CurPos] = #09)) do
  1045. Inc (CurPos);
  1046. WorkLine := Copy (AHeaderList[CurLine],
  1047. CurPos, LineLen - CurPos + 1);
  1048. {Begin !!.13}
  1049. Inc(CurLine);
  1050. while IsWrappedLine (AHeaderList, CurLine) do begin
  1051. WorkLine := WorkLine + #9 + Trim(AHeaderList[CurLine]);
  1052. Inc(CurLine);
  1053. end;
  1054. NewField.Value.Add (Trim (WorkLine));
  1055. {End !!.13}
  1056. end;
  1057. var
  1058. i : Integer;
  1059. HeaderName : string;
  1060. NewHeader : TIpHeaderItem;
  1061. begin
  1062. if not Append then
  1063. Clear;
  1064. i := 0;
  1065. while i < AHeaderList.Count do begin
  1066. HeaderName := ExtractHeaderName (AHeaderList[i]);
  1067. if HeaderName <> '' then begin
  1068. NewHeader := TIpHeaderItem (Add);
  1069. NewHeader.Name := HeaderName;
  1070. GetFieldValue (AHeaderList, i, NewHeader);
  1071. {Begin !!.15}
  1072. end
  1073. else
  1074. Inc(i);
  1075. {End !!.15}
  1076. end;
  1077. end;
  1078. procedure TIpHeaderCollection.SetItem (Index : Integer;
  1079. Value : TIpHeaderItem);
  1080. begin
  1081. inherited SetItem (Index, Value);
  1082. end;
  1083. {End !!.12}
  1084. { TIpMimeParts }
  1085. constructor TIpMimeParts.Create;
  1086. begin
  1087. inherited Create;
  1088. Entitys := TList.Create;
  1089. end;
  1090. destructor TIpMimeParts.Destroy;
  1091. begin
  1092. Clear;
  1093. Entitys.Free;
  1094. inherited Destroy;
  1095. end;
  1096. { Add Mime block to list }
  1097. function TIpMimeParts.Add(aEntity : TIpMimeEntity) : Integer;
  1098. begin
  1099. Result := Entitys.Add(aEntity);
  1100. end;
  1101. { Clear list }
  1102. procedure TIpMimeParts.Clear;
  1103. var
  1104. i : Integer;
  1105. begin
  1106. for i := Pred(Entitys.Count) downto 0 do
  1107. Delete(i);
  1108. end;
  1109. { Delete block from list }
  1110. procedure TIpMimeParts.Delete(aIndex : Integer);
  1111. begin
  1112. if (aIndex >= 0) and (aIndex < Entitys.Count) then begin
  1113. TIpMimeEntity(Entitys[aIndex]).Free;
  1114. end;
  1115. end;
  1116. { Remove block from list }
  1117. function TIpMimeParts.Remove(aEntity : TIpMimeEntity) : Integer;
  1118. begin
  1119. Result := Entitys.Remove(Pointer(aEntity));
  1120. end;
  1121. { Count property read access method }
  1122. function TIpMimeParts.GetCount : Integer;
  1123. begin
  1124. Result := Entitys.Count;
  1125. end;
  1126. { Parts property read access method }
  1127. function TIpMimeParts.GetPart(aIndex : Integer) : TIpMimeEntity;
  1128. begin
  1129. if (aIndex >= 0) and (aIndex < Entitys.Count) then
  1130. Result := TIpMimeEntity(Entitys[aIndex])
  1131. else
  1132. Result := nil;
  1133. end;
  1134. { Returns list index of specified Mime block }
  1135. function TIpMimeParts.IndexOf(aEntity : TIpMimeEntity) : Integer;
  1136. begin
  1137. Result := Entitys.IndexOf(aEntity);
  1138. end;
  1139. { TIpMimeEntity }
  1140. constructor TIpMimeEntity.Create(ParentEntity : TIpMimeEntity);
  1141. begin
  1142. inherited Create;
  1143. FBody := TIpAnsiTextStream.CreateEmpty;
  1144. FBody.Stream := TMemoryStream.Create;
  1145. FMimeParts := TIpMimeParts.Create;
  1146. FParent := ParentEntity;
  1147. if (FParent <> nil) then
  1148. FParentBoundary := FParent.Boundary;
  1149. end;
  1150. destructor TIpMimeEntity.Destroy;
  1151. begin
  1152. FMimeParts.Free;
  1153. FBody.FreeStream;
  1154. FBody.Free;
  1155. if (FParent <> nil) then
  1156. FParent.MimeParts.Remove(Self);
  1157. inherited Destroy;
  1158. end;
  1159. { Clear Body property }
  1160. procedure TIpMimeEntity.ClearBody;
  1161. begin
  1162. FBody.FreeStream;
  1163. FBody.Stream := TMemoryStream.Create;
  1164. end;
  1165. {Begin !!.12}
  1166. { Clear Body property in preparation for large attachment }
  1167. procedure TIpMimeEntity.ClearBodyLargeAttach(const AttachmentSize : Longint);
  1168. var
  1169. FileName : string;
  1170. Strm : TIpMemMapStream;
  1171. begin
  1172. FBody.FreeStream;
  1173. FileName := GetTemporaryFile(GetTemporaryPath);
  1174. if FileExistsUTF8(FileName) then
  1175. DeleteFileUTF8(FileName);
  1176. Strm := TIpMemMapStream.Create(FileName, False, True);
  1177. Strm.Size := Trunc(AttachmentSize * 1.3695);
  1178. Strm.Open;
  1179. FBody.Stream := Strm;
  1180. end;
  1181. {End !!.12}
  1182. { Clear all properties }
  1183. procedure TIpMimeEntity.Clear;
  1184. begin
  1185. ClearBody;
  1186. FMimeParts.Clear;
  1187. FBoundary := '';
  1188. FCharacterSet := '';
  1189. FContentDescription := '';
  1190. FContentDispositionType := '';
  1191. FContentID := '';
  1192. FContentSubtype := '';
  1193. FContentType := '';
  1194. FContentTransferEncoding := emUnknown;
  1195. FFileName := '';
  1196. FIsMime := False;
  1197. FIsMultipart := False;
  1198. FMimeVersion := '';
  1199. FEntityName := '';
  1200. FRelatedType := ''; {!!.02}
  1201. FRelatedSubtype := ''; {!!.02}
  1202. FRelatedStart := ''; {!!.02}
  1203. FRelatedStartInfo := ''; {!!.02}
  1204. end;
  1205. { Build Mime (and nested Mime) block(s) from incoming text stream }
  1206. function TIpMimeEntity.DecodeEntity(InStream : TIpAnsiTextStream) : string;
  1207. var
  1208. Blk : TIpMimeEntity;
  1209. RawHeaders : TStringList;
  1210. Decoded : Boolean; {!!.12}
  1211. i, {!!.13}
  1212. LeadingBlankLines : Integer; {!!.13}
  1213. begin
  1214. Decoded := False; {!!.12}
  1215. LeadingBlankLines := 0; {!!.13}
  1216. { skip blank lines in front of mime headers or body }
  1217. Result := InStream.ReadLine;
  1218. while (Result = '') and not InStream.AtEndOfStream do begin
  1219. inc(LeadingBlankLines);
  1220. Result := InStream.ReadLine;
  1221. end;
  1222. { decode mime headers if any }
  1223. {Begin !!.15}
  1224. if (StrLIComp(PChar(strContent), PChar(Result), Length(strContent)) = 0) or
  1225. (StrLIComp(PChar(strMimeVersion), PChar(Result),
  1226. Length(strMimeVersion)) = 0) then begin
  1227. {End !!.15}
  1228. RawHeaders := TStringList.Create;
  1229. try
  1230. repeat
  1231. RawHeaders.Add(Result);
  1232. Result := InStream.ReadLine;
  1233. until (Result = '') or (InStream.AtEndOfStream);
  1234. DecodeMimeHeaders(RawHeaders);
  1235. finally
  1236. RawHeaders.Free;
  1237. end;
  1238. Result := InStream.ReadLine;
  1239. { skip blank lines between mime headers and mime body }
  1240. while (Result = '') and not InStream.AtEndOfStream do
  1241. Result := InStream.ReadLine;
  1242. end;
  1243. { decode body - main loop }
  1244. {Begin !!.15}
  1245. if (FParentBoundary <> '') and
  1246. (Result = '--' + FParentBoundary) then
  1247. { The body of this entity is empty & we are now positioned at the boundary
  1248. marker for the next entity. }
  1249. Decoded := True
  1250. else
  1251. {End !!.15}
  1252. while not (((FParentBoundary <> '') and {!!.12}
  1253. (Result = '--' + FParentBoundary) {!!.12}
  1254. ) or InStream.AtEndOfStream) do begin