@@ -81,7 +81,6 @@ TRESTDWMessageDecoderMIME = class(TRESTDWMessageDecoder)
8181 TRESTDWMessageEncoderInfoMIME = Class (TRESTDWMessageEncoderInfo)
8282 Public
8383 Constructor Create; Override;
84- Destructor Destroy; Override;
8584 Procedure InitializeHeaders (AMsg : TRESTDWMessage); Override;
8685 End ;
8786
@@ -284,158 +283,149 @@ destructor TRESTDWMessageDecoderMIME.Destroy;
284283
285284Function TRESTDWMessageDecoderMIME.ReadBody (ADestStream : TStream;
286285 Var VMsgEnd : Boolean) : TRESTDWMessageDecoder;
287- var
288- LContentType, LContentTransferEncoding: string;
289- LDecoder: TRESTDWDecoder;
290- LBytes : TRESTDWBytes;
291- LLine: string;
292- LBuffer: string; // Needed for binhex4 because cannot decode line-by-line.
293- LIsThisTheFirstLine: Boolean; // Needed for binary encoding
294- BoundaryStart, BoundaryEnd: string;
295- IsBinaryContentTransferEncoding: Boolean;
296- begin
297- LIsThisTheFirstLine := True;
298- VMsgEnd := False;
299- Result := nil ;
300- if FBodyEncoded then begin
301- LContentType := TRESTDWMessage(Owner).ContentType;
302- LContentTransferEncoding := TRESTDWMessage(Owner).ContentTransferEncoding;
303- end else begin
304- LContentType := FHeaders.Values[' Content-Type' ]; { Do not Localize}
305- LContentTransferEncoding := FHeaders.Values[' Content-Transfer-Encoding' ]; { Do not Localize}
306- end ;
307- if LContentTransferEncoding = ' ' then begin
308- if IsHeaderMediaType(LContentType, ' application/mac-binhex40' ) then begin { Do not Localize}
309- LContentTransferEncoding := ' binhex40' ; { do not localize}
310- end ;
311- end ;
312-
313- // RLebeau 08/17/09 - According to RFC 2045 Section 6.4:
314- // "If an entity is of type "multipart" the Content-Transfer-Encoding is not
315- // permitted to have any value other than "7bit", "8bit" or "binary"."
316- //
317- // However, came across one message where the "Content-Type" was set to
318- // "multipart/related" and the "Content-Transfer-Encoding" was set to
319- // "quoted-printable". Outlook and Thunderbird were apparently able to parse
320- // the message correctly, but Indy was not. So let's check for that scenario
321- // and ignore illegal "Content-Transfer-Encoding" values if present...
322-
323- if IsHeaderMediaType(LContentType, ' multipart' ) and (LContentTransferEncoding <> ' ' ) then { do not localize}
324- begin
325- if PosInStrArray(LContentTransferEncoding, [' 7bit' , ' 8bit' , ' binary' ], False) = -1 then begin { do not localize}
326- LContentTransferEncoding := ' ' ;
327- end ;
328- end ;
329-
330- if TextIsSame(LContentTransferEncoding, ' base64' ) then begin { Do not Localize}
331- LDecoder := TRESTDWDecoderMIMELineByLine.Create(nil );
332- end else if TextIsSame(LContentTransferEncoding, ' quoted-printable' ) then begin { Do not Localize}
333- LDecoder := TRESTDWDecoderQuotedPrintable.Create(nil );
334- end else if TextIsSame(LContentTransferEncoding, ' binhex40' ) then begin { Do not Localize}
335- LDecoder := TRESTDWDecoderBinHex4.Create(nil );
336- end else begin
337- LDecoder := nil ;
338- end ;
339- Try
340- if LDecoder <> nil then begin
341- LDecoder.DecodeBegin(ADestStream);
342- end ;
343-
344- if MIMEBoundary <> ' ' then begin
345- BoundaryStart := ' --' + MIMEBoundary; { Do not Localize}
346- BoundaryEnd := BoundaryStart + ' --' ; { Do not Localize}
347- end ;
348-
349- case PosInStrArray(LContentTransferEncoding, [' 7bit' , ' quoted-printable' , ' base64' , ' 8bit' , ' binary' ], False) of { do not localize}
350- 0 ..2 : IsBinaryContentTransferEncoding := False;
351- 3 ..4 : IsBinaryContentTransferEncoding := True;
352- else
353- // According to RFC 2045 Section 6.4:
354- // "Any entity with an unrecognized Content-Transfer-Encoding must be
355- // treated as if it has a Content-Type of "application/octet-stream",
356- // regardless of what the Content-Type header field actually says."
357- IsBinaryContentTransferEncoding := True;
358- end ;
359- Repeat
360- if not FProcessFirstLine then begin
361- if IsBinaryContentTransferEncoding then
362- LBytes := ReadLnRFCB(VMsgEnd, EOL, ' .' ) { do not localize}
363- Else
364- LLine := ReadLnRFC(VMsgEnd);
365- end else begin
366- LLine := FFirstLine;
367- FFirstLine := ' ' ; { Do not Localize}
368- FProcessFirstLine := False;
369- // Do not use ADELIM since always ends with . (standard)
370- if LLine = ' .' then begin { Do not Localize}
371- VMsgEnd := True;
372- Break;
373- end ;
374- if TextStartsWith(LLine, ' ..' ) then begin
375- Delete(LLine, 1 , 1 );
376- end ;
377- end ;
378- If (IsBinaryContentTransferEncoding) Then
379- Begin
380- If Length(LBytes) > 0 Then
381- ADestStream.WriteBuffer(LBytes[0 ], Length(LBytes));
382- SetLength(LBytes, 0 );
383- If (VMsgEnd) Then
384- Break;
385- End ;
386- // New boundary - end self and create new coder
387- if MIMEBoundary <> ' ' then begin
388- if TextIsSame(LLine, BoundaryStart) then begin
389- Result := TRESTDWMessageDecoderMIME.Create(Owner);
390- Break;
391- // End of all coders (not quite ALL coders)
392- end ;
393- if TextIsSame(LLine, BoundaryEnd) then begin
394- // POP the boundary
395- if Owner is TRESTDWMessage then begin
396- TRESTDWMessage(Owner).MIMEBoundary.Pop;
397- end ;
398- Break;
399- end ;
400- end ;
401- if Not Assigned(LDecoder) then
402- Begin
403- // Data to save, but not decode
404- If Not IsBinaryContentTransferEncoding then
405- If Assigned(ADestStream) then
406- WriteStringToStream(ADestStream, LLine + EOL);
407- end
408- else
409- begin
410- // Data to decode
411- // For TIdDecoderQuotedPrintable, we have to make sure all EOLs are
412- // intact
413- if LDecoder is TRESTDWDecoderQuotedPrintable then begin
414- // For TIdDecoderQuotedPrintable, we have to make sure all EOLs are intact
415- // LLine := LLine + EOF;
416- LDecoder.Decode(LLine);
417- end else if LDecoder is TRESTDWDecoderBinHex4 then begin
418- // We cannot decode line-by-line because lines don't have a whole
419- // number of 4-byte blocks due to the : inserted at the start of
420- // the first line, so buffer the file...
421- LBuffer := LBuffer + LLine;
422- end else if LLine <> ' ' then begin
423- LDecoder.Decode(LLine);
424- end ;
425- end ;
426- Until False;
427- If LDecoder <> Nil Then
286+ Var
287+ LContentType,
288+ LContentTransferEncoding,
289+ LLine,
290+ LBinaryLineBreak,
291+ LBuffer, // Needed for binhex4 because cannot decode line-by-line.
292+ LBoundaryStart,
293+ LBoundaryEnd : String;
294+ LIsThisTheFirstLine, // Needed for binary encoding
295+ LIsBinaryContentTransferEncoding : Boolean;
296+ LDecoder : TRESTDWDecoder;
297+ Begin
298+ LIsThisTheFirstLine := True;
299+ VMsgEnd := False;
300+ Result := Nil ;
301+ If FBodyEncoded Then
302+ Begin
303+ LContentType := TRESTDWMessage(Owner).ContentType;
304+ LContentTransferEncoding := TRESTDWMessage(Owner).ContentTransferEncoding;
305+ End
306+ Else
307+ Begin
308+ LContentType := FHeaders.Values[' Content-Type' ]; { Do not Localize}
309+ LContentTransferEncoding := FHeaders.Values[' Content-Transfer-Encoding' ]; { Do not Localize}
310+ End ;
311+ If LContentTransferEncoding = ' ' Then
312+ Begin
313+ If IsHeaderMediaType(LContentType, ' application/mac-binhex40' ) Then { Do not Localize}
314+ LContentTransferEncoding := ' binhex40' { do not localize}
315+ End
316+ Else If IsHeaderMediaType(LContentType, ' multipart' ) Then { do not localize}
317+ Begin
318+ If PosInStrArray(LContentTransferEncoding, [' 7bit' , ' 8bit' , ' binary' ], False) = -1 Then { do not localize}
319+ LContentTransferEncoding := ' ' ;
320+ End ;
321+ If TextIsSame(LContentTransferEncoding, ' base64' ) Then { Do not Localize}
322+ LDecoder := TRESTDWDecoderMIMELineByLine.Create(Nil )
323+ Else If TextIsSame(LContentTransferEncoding, ' quoted-printable' ) Then { Do not Localize}
324+ LDecoder := TRESTDWDecoderQuotedPrintable.Create(Nil )
325+ Else If TextIsSame(LContentTransferEncoding, ' binhex40' ) Then { Do not Localize}
326+ LDecoder := TRESTDWDecoderBinHex4.Create (Nil )
327+ Else
328+ LDecoder := nil ;
329+ Try
330+ If LDecoder <> Nil Then
331+ LDecoder.DecodeBegin(ADestStream);
332+ If MIMEBoundary <> ' ' Then
333+ Begin
334+ LBoundaryStart := ' --' + MIMEBoundary; { Do not Localize}
335+ LBoundaryEnd := LBoundaryStart + ' --' ; { Do not Localize}
336+ End ;
337+ If LContentTransferEncoding <> ' ' Then
338+ Begin
339+ Case PosInStrArray(LContentTransferEncoding, [' 7bit' , ' quoted-printable' , ' base64' , ' 8bit' , ' binary' ], False) Of { do not localize}
340+ 0 ..2 : LIsBinaryContentTransferEncoding := False;
341+ 3 ..4 : LIsBinaryContentTransferEncoding := True;
342+ Else
343+ LIsBinaryContentTransferEncoding := True;
344+ LContentTransferEncoding := ' ' ;
345+ End ;
346+ End
347+ Else
348+ LIsBinaryContentTransferEncoding := True;
349+ Repeat
350+ If Not FProcessFirstLine Then
351+ Begin
352+ If LIsBinaryContentTransferEncoding Then
353+ Begin
354+ LLine := ReadLnRFC(VMsgEnd, EOL, ' .' ); { do not localize}
355+ LBinaryLineBreak := EOL;
356+ End
357+ Else
358+ LLine := ReadLnRFC(VMsgEnd, LF, ' .' ); { do not localize}
359+ End
360+ Else
361+ Begin
362+ LLine := FFirstLine;
363+ FFirstLine := ' ' ; { Do not Localize}
364+ FProcessFirstLine := False;
365+ // Do not use ADELIM since always ends with . (standard)
366+ If LLine = ' .' Then
367+ Begin { Do not Localize}
368+ VMsgEnd := True;
369+ Break;
370+ End ;
371+ If TextStartsWith(LLine, ' ..' ) Then
372+ Delete(LLine, 1 , 1 );
373+ End ;
374+ If VMsgEnd Then
375+ Break;
376+ If MIMEBoundary <> ' ' Then
428377 Begin
429- If LDecoder Is TRESTDWDecoderBinHex4 Then
378+ If TextIsSame(LLine, LBoundaryStart) Then
379+ Begin
380+ Result := TRESTDWMessageDecoderMIME.Create(Owner);
381+ Break;
382+ End ;
383+ If TextIsSame(LLine, LBoundaryEnd) Then
430384 Begin
431- // Now decode the complete block...
432- LDecoder.Decode(LBuffer);
385+ If Owner is TRESTDWMessage Then
386+ TRESTDWMessage(Owner).MIMEBoundary.Pop;
387+ Break;
433388 End ;
434- LDecoder.DecodeEnd;
435389 End ;
436- Finally
437- FreeAndNil(LDecoder);
438- End ;
390+ If LDecoder = Nil Then
391+ Begin
392+ If LIsBinaryContentTransferEncoding Then
393+ Begin { do not localize}
394+ If LIsThisTheFirstLine Then
395+ LIsThisTheFirstLine := False
396+ Else
397+ Begin
398+ If Assigned(ADestStream) Then
399+ WriteStringToStream(ADestStream, LBinaryLineBreak, -1 , 1 );
400+ End ;
401+ If Assigned(ADestStream) Then
402+ WriteStringToStream(ADestStream, LLine, -1 , 1 );
403+ End
404+ Else
405+ Begin
406+ If Assigned(ADestStream) Then
407+ WriteStringToStream(ADestStream, LLine + EOL, -1 , 1 );
408+ End ;
409+ End
410+ Else
411+ Begin
412+ If LDecoder Is TRESTDWDecoderQuotedPrintable Then
413+ LDecoder.Decode(LLine + EOL)
414+ Else If LDecoder Is TRESTDWDecoderBinHex4 Then
415+ LBuffer := LBuffer + LLine
416+ Else If LLine <> ' ' Then
417+ LDecoder.Decode(LLine);
418+ End ;
419+ Until False;
420+ If LDecoder <> Nil Then
421+ Begin
422+ If LDecoder Is TRESTDWDecoderBinHex4 Then
423+ LDecoder.Decode(LBuffer);
424+ LDecoder.DecodeEnd;
425+ End ;
426+ Finally
427+ FreeAndNil(LDecoder);
428+ End ;
439429End ;
440430
441431Function TRESTDWMessageDecoderMIME.GetAttachmentFilename (Const AContentType,
@@ -565,11 +555,6 @@ destructor TRESTDWMessageDecoderMIME.Destroy;
565555 FMessageEncoderClass := TRESTDWMessageEncoderMIME;
566556End ;
567557
568- destructor TRESTDWMessageEncoderInfoMIME.Destroy;
569- begin
570- Inherited ;
571- end ;
572-
573558Procedure TRESTDWMessageEncoderInfoMIME.InitializeHeaders (AMsg : TRESTDWMessage);
574559Begin
575560 If AMsg.ContentType = ' ' Then
0 commit comments