- Timestamp:
- Feb 4, 2022, 11:30:24 AM (3 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Forms/UFormTest.pas
r96 r97 146 146 Input := VCardBegin + LineEnding + 147 147 VCardVersion + LineEnding + 148 'FN;ENCODING=QUOTED-PRINTABLE:Jm=C3=A9no P=C5=99=C3=ADjmen=C3=AD' + LineEnding + 148 'FN;ENCODING=QUOTED-PRINTABLE:Jm=C3=A9no=20P=C5=99=C3=ADjmen=C3=AD' + LineEnding + 149 VCardEnd + LineEnding; 150 Output := Input; 151 end; 152 with TTestCaseLoadSave(AddNew('Quoted-printable load-save multi-line', TTestCaseLoadSave)) do begin 153 Input := VCardBegin + LineEnding + 154 VCardVersion + LineEnding + 155 'FN;ENCODING=QUOTED-PRINTABLE:Jm=C3=A9no=20P=C5=99=C3=ADjmen=C3=AD=' + LineEnding + 156 'Jm=C3=A9no=20P=C5=99=C3=ADjmen=C3=AD' + LineEnding + 149 157 VCardEnd + LineEnding; 150 158 Output := Input; -
trunk/Languages/vCardStudio.cs.po
r95 r97 1323 1323 msgstr "Hodnota" 1324 1324 1325 #: uquotedprintable.s linelengtherr1326 msgid " Invalid line length for encoded text"1327 msgstr " Neplatná délka řádky kódovaného textu"1325 #: uquotedprintable.sdecodeerror 1326 msgid "Decode error" 1327 msgstr "Chyba dekódování" -
trunk/Languages/vCardStudio.pot
r95 r97 1292 1292 msgstr "" 1293 1293 1294 #: uquotedprintable.s linelengtherr1295 msgid " Invalid line length for encoded text"1296 msgstr "" 1297 1294 #: uquotedprintable.sdecodeerror 1295 msgid "Decode error" 1296 msgstr "" 1297 -
trunk/Samples/centrum.cz.vcf
r41 r97 21 21 EMAIL;INTERNET;ENCODING=QUOTED-PRINTABLE: 22 22 EMAIL;INTERNET;WORK;ENCODING=QUOTED-PRINTABLE:firma@neco.cz 23 NOTE;ENCODING=QUOTED-PRINTABLE:jkjlj=20=20kljklkl=20jl=20jlk 23 NOTE;ENCODING=QUOTED-PRINTABLE:jkjlj=20=20kljklkl=20jl=20jlk=20=C5=99=C4=8D=C5=99=C4=8D=C5=A1=C4=8D=C5=A1= 24 =20=C4=8D=C4=8D=C5=A1=C5=99=C4=8D=20=C5=99=C4=8D=C5=A1=0Affdfsdfsdfs=20f= 25 fsd=20fsd=20fsdfsdf=20sdfs=20;=20_=20/=20\=20$=20,=20'=20"=20.=20=3D=0Ad= 26 asdsaddsa=20a=20dsadsa=20sa=20dsadsa=20dsad=20sadsa=20da=C4=8D=C4=9B=C5=A1= 27 =C4=8D=C5=A1=C4=8D=C4=9B=C5=A1=0A 24 28 X-CENTRUM-CZ-ANNIVERSARY;ENCODING=QUOTED-PRINTABLE:89819393;1917-12-19;hjkhjkhjk 25 29 X-CENTRUM-CZ-ANNIVERSARY;ENCODING=QUOTED-PRINTABLE:89819393;; … … 33 37 X-CENTRUM-CZ-IM;ENCODING=QUOTED-PRINTABLE:jjhhjkhjkhjk;4 34 38 END:VCARD 35 -
trunk/UContact.pas
r93 r97 603 603 end else 604 604 if Encoding = 'QUOTED-PRINTABLE' then begin 605 Result := DecodeQuotedPrintable(Value );605 Result := DecodeQuotedPrintable(Value, True); 606 606 end 607 607 else Result := ''; … … 614 614 end else 615 615 if Encoding = 'QUOTED-PRINTABLE' then begin 616 Result := EncodeQuotedPrintable(Value );616 Result := EncodeQuotedPrintable(Value, True); 617 617 end 618 618 else Result := ''; … … 1164 1164 CutLength := ContactsFile.MaxLineLength; 1165 1165 if Encoding = 'QUOTED-PRINTABLE' then begin 1166 // Do not cut encoded items 1167 if ((CutLength - 2) >= 1) and (OutText[CutLength - 2] = '=') then 1166 Dec(CutLength); // There will be softline break at the end 1167 // Do not cut encoded items at the end of line 1168 if ((CutLength - 1) >= 1) and (OutText[CutLength - 1] = QuotedPrintableEscapeCharacter) then 1168 1169 Dec(CutLength, 2) 1169 else if ((CutLength - 1) >= 1) and (OutText[CutLength - 1] = '=')then1170 else if OutText[CutLength] = QuotedPrintableEscapeCharacter then 1170 1171 Dec(CutLength, 1); 1171 1172 end; 1173 1172 1174 CutText := UTF8Copy(OutText, 1, CutLength); 1175 System.Delete(OutText, 1, Length(CutText)); 1176 if Encoding = 'QUOTED-PRINTABLE' then 1177 CutText := CutText + QuotedPrintableEscapeCharacter; // Add soft line break 1173 1178 Add(LinePrefix + CutText); 1174 LinePrefix := ' ';1175 System.Delete(OutText, 1, Length(CutText));1179 if Encoding <> 'QUOTED-PRINTABLE' then 1180 LinePrefix := ' '; 1176 1181 Inc(LineIndex); 1177 1182 Continue; … … 1199 1204 CommandPart: string; 1200 1205 Names: string; 1206 QuotedPrintableMultiLine: Boolean; 1201 1207 begin 1202 1208 Result := False; … … 1228 1234 CommandPart := GetNext(Line, ':'); 1229 1235 Names := CommandPart; 1236 QuotedPrintableMultiLine := Pos('encoding=quoted-printable', LowerCase(CommandPart)) > 0; 1230 1237 Value := Line; 1231 1238 while True do begin … … 1237 1244 Value := Value + Copy(Line2, 2, MaxInt); 1238 1245 end else 1239 if (Length(Line2) > 0) and (Length(Value) > 0) and (Value[Length(Value)] = '=') and 1240 (Line2[1] = '=') then begin 1241 Value := Value + Copy(Line2, 2, MaxInt); 1246 if QuotedPrintableMultiLine and (Length(Value) > 0) and 1247 (Value[Length(Value)] = QuotedPrintableEscapeCharacter) then begin 1248 SetLength(Value, Length(Value) - 1); 1249 Value := Value + Line2; 1242 1250 end else begin 1243 1251 Dec(I); -
trunk/UQuotedPrintable.pas
r46 r97 8 8 Classes, SysUtils; 9 9 10 function DecodeQuotedPrintable(Text: string ): string;11 function EncodeQuotedPrintable(Text: string ): string;10 function DecodeQuotedPrintable(Text: string; IgnoreErrors: Boolean = False): string; 11 function EncodeQuotedPrintable(Text: string; EncodeSpaces: Boolean = False): string; 12 12 13 const 14 QuotedPrintableEscapeCharacter = '='; 13 15 14 16 implementation 15 17 18 uses 19 UCommon; 20 16 21 resourcestring 17 S LineLengthErr = 'Invalid line length for encoded text';22 SDecodeError = 'Decode error'; 18 23 19 const 20 MaxLine = 1000; 21 22 function DecodeQuotedPrintable(Text: string): string; 24 function DecodeQuotedPrintable(Text: string; IgnoreErrors: Boolean = False): string; 23 25 var 24 O, Count, WS: Integer; 25 I: integer; 26 InBuf: array[0..Pred(MaxLine)] of Byte; 27 OutBuf: array[0..Pred(MaxLine)] of Byte; 28 Decoding: Boolean; 29 Keeper: Boolean; 30 Abort: Boolean; 31 InStream: TMemoryStream; 32 OutStream: TMemoryStream; 26 I: Integer; 27 J: Integer; 28 C: Char; 29 IntValue: Integer; 33 30 begin 34 31 Result := ''; 35 InStream := TMemoryStream.Create; 36 OutStream := TMemoryStream.Create; 37 try 38 if Text <> '' then begin 39 InStream.Write(Text[1], Length(Text)); 40 InStream.Position := 0; 41 end; 42 Abort := False; 43 FillChar(InBuf, SizeOf(InBuf), #0); 44 WS := $FF; 45 Decoding := True; 46 Keeper := False; 47 48 { Skip any CR/LF's to get to the encoded stuff } 49 while True do begin 50 if InStream.Read(Char(InBuf[0]), 1) = 0then 51 Exit; 52 if ((InBuf[0] <> $0D) and (InBuf[0] <> $0A)) then begin 53 Keeper := True; 54 Break; 32 SetLength(Result, Length(Text)); 33 I := 1; 34 J := 1; 35 while I <= Length(Text) do begin 36 C := Text[I]; 37 if C = QuotedPrintableEscapeCharacter then begin 38 if ((I + 2) <= Length(Text)) and TryHexToInt(Text[I + 1] + Text[I + 2], IntValue) then begin 39 Result[J] := Chr(IntValue); 40 Inc(I, 2); 41 Inc(J); 42 SetLength(Result, Length(Result) - 2); 43 end else begin 44 if not IgnoreErrors then raise Exception.Create(SDecodeError) 45 else begin 46 Result[J] := '?'; 47 Inc(J); 48 end; 49 end; 50 end else begin 51 Result[J] := C; 52 Inc(J); 55 53 end; 56 end; 57 58 while Decoding and not Abort do begin 59 { Initialize } 60 if Keeper then begin 61 I := 1; 62 Keeper := False; 63 end else begin 64 I := 0; 65 end; 66 O := 0; 67 68 { Read in one line at a time - skipping over bad characters } 69 while True do begin 70 if (I > High(InBuf)) then 71 raise Exception.Create(SLineLengthErr); 72 if InStream.Read(Char(InBuf[I]), 1) = 0 then 73 Break; 74 case InBuf[I] of 75 $0A : Continue; 76 $0D : begin 77 Inc(I); 78 Break; 79 end; 80 { Test for potential end of data } 81 { '--' is probably the next Mime boundary } 82 { $2D : if (I = 1) and (InBuf[0] = $2D) then Exit;} 83 end; 84 Inc(I); 85 end; 86 87 if I = 0 then Break; 88 Count := I; 89 I := 0; 90 91 { Decode data to output stream } 92 while I < Count do begin 93 case InBuf[I] of 94 9 : begin 95 if WS = $FF then 96 WS := O; 97 OutBuf[O] := InBuf[I]; 98 Inc(O); 99 Inc(I); 100 end; 101 13 : if WS = $FF then begin 102 OutBuf[O] := 13; 103 OutBuf[O+1] := 10; 104 Inc(O, 2); 105 Inc(I); 106 end else begin 107 OutBuf[WS] := 13; 108 OutBuf[WS+1] := 10; 109 O := WS+2; 110 Inc(I); 111 end; 112 32 : begin 113 if WS = $FF then 114 WS := O; 115 OutBuf[O] := InBuf[I]; 116 Inc(O); 117 Inc(I); 118 end; 119 33..60 : begin 120 WS := $FF; 121 OutBuf[O] := InBuf[I]; 122 Inc(O); 123 Inc(I); 124 end; 125 61 : begin 126 WS := $FF; 127 if I+2 >= Count then Break; 128 case InBuf[I+1] of 129 48 : OutBuf[O] := 0; {0} 130 49 : OutBuf[O] := 16; {1} 131 50 : OutBuf[O] := 32; {2} 132 51 : OutBuf[O] := 48; {3} 133 52 : OutBuf[O] := 64; {4} 134 53 : OutBuf[O] := 80; {5} 135 54 : OutBuf[O] := 96; {6} 136 55 : OutBuf[O] := 112; {7} 137 56 : OutBuf[O] := 128; {8} 138 57 : OutBuf[O] := 144; {9} 139 65 : OutBuf[O] := 160; {A} 140 66 : OutBuf[O] := 176; {B} 141 67 : OutBuf[O] := 192; {C} 142 68 : OutBuf[O] := 208; {D} 143 69 : OutBuf[O] := 224; {E} 144 70 : OutBuf[O] := 240; {F} 145 97 : OutBuf[O] := 160; {a} 146 98 : OutBuf[O] := 176; {b} 147 99 : OutBuf[O] := 192; {c} 148 100 : OutBuf[O] := 208; {d} 149 101 : OutBuf[O] := 224; {e} 150 102 : OutBuf[O] := 240; {f} 151 end; 152 case InBuf[I+2] of 153 48 : ; {0} 154 49 : OutBuf[O] := OutBuf[O] + 1; {1} 155 50 : OutBuf[O] := OutBuf[O] + 2; {2} 156 51 : OutBuf[O] := OutBuf[O] + 3; {3} 157 52 : OutBuf[O] := OutBuf[O] + 4; {4} 158 53 : OutBuf[O] := OutBuf[O] + 5; {5} 159 54 : OutBuf[O] := OutBuf[O] + 6; {6} 160 55 : OutBuf[O] := OutBuf[O] + 7; {7} 161 56 : OutBuf[O] := OutBuf[O] + 8; {8} 162 57 : OutBuf[O] := OutBuf[O] + 9; {9} 163 65 : OutBuf[O] := OutBuf[O] + 10; {A} 164 66 : OutBuf[O] := OutBuf[O] + 11; {B} 165 67 : OutBuf[O] := OutBuf[O] + 12; {C} 166 68 : OutBuf[O] := OutBuf[O] + 13; {D} 167 69 : OutBuf[O] := OutBuf[O] + 14; {E} 168 70 : OutBuf[O] := OutBuf[O] + 15; {F} 169 97 : OutBuf[O] := OutBuf[O] + 10; {a} 170 98 : OutBuf[O] := OutBuf[O] + 11; {b} 171 99 : OutBuf[O] := OutBuf[O] + 12; {c} 172 100 : OutBuf[O] := OutBuf[O] + 13; {d} 173 101 : OutBuf[O] := OutBuf[O] + 14; {e} 174 102 : OutBuf[O] := OutBuf[O] + 15; {f} 175 end; 176 Inc(I, 3); 177 Inc(O); 178 end; 179 62..126 : begin 180 WS := $FF; 181 OutBuf[O] := InBuf[I]; 182 Inc(O); 183 Inc(I); 184 end; 185 else 186 Inc(I); 187 end; 188 end; 189 190 if O > 0 then 191 OutStream.Write(OutBuf, O) 192 else 193 Break; { OutBuf is empty } 194 end; 195 SetLength(Result, OutStream.Size); 196 OutStream.Position := 0; 197 if OutStream.Size > 0 then 198 OutStream.Read(Result[1], Length(Result)); 199 finally 200 OutStream.Free; 201 InStream.Free; 54 Inc(I); 202 55 end; 203 56 end; 204 57 205 function EncodeQuotedPrintable(Text: string ): string;58 function EncodeQuotedPrintable(Text: string; EncodeSpaces: Boolean): string; 206 59 var 207 O, W: Integer; 208 WordBuf, OutBuf: array[0..80] of AnsiChar; 209 CurChar: AnsiChar; 210 Abort: Boolean; 211 InStream: TStream; 212 OutStream: TMemoryStream; 213 214 procedure SendLine; 215 begin 216 if (OutBuf[O - 1] = #9) or (OutBuf[O - 1] = #32) then begin 217 OutBuf[O] := '='; 218 Inc(O); 60 I: Integer; 61 J: Integer; 62 C: Char; 63 LowerLimit: Char; 64 const 65 HexDigits : array[0..$F] of AnsiChar = '0123456789ABCDEF'; 66 begin 67 if EncodeSpaces then LowerLimit := #33 68 else LowerLimit := #32; 69 Result := ''; 70 SetLength(Result, Length(Text)); 71 I := 1; 72 J := 1; 73 while I <= Length(Text) do begin 74 C := Text[I]; 75 if (C = QuotedPrintableEscapeCharacter) or (C < LowerLimit) or (C > #126) then begin 76 SetLength(Result, Length(Result) + 2); 77 Result[J] := QuotedPrintableEscapeCharacter; 78 Result[J + 1] := HexDigits[Ord(C) shr 4]; 79 Result[J + 2] := HexDigits[Ord(C) and $f]; 80 Inc(J, 3); 81 end else begin 82 Result[J] := C; 83 Inc(J); 219 84 end; 220 OutStream.Write(OutBuf, O); 221 FillChar(OutBuf, SizeOf(OutBuf), #0); 222 O := 0; 223 end; 224 225 procedure AddWordToOutBuf; 226 var 227 J : Integer; 228 begin 229 if (O + W) > 74 then SendLine; 230 for J := 0 to (W - 1) do begin 231 OutBuf[O] := WordBuf[J]; 232 Inc(O); 233 end; 234 W := 0; 235 end; 236 237 procedure AddHexToWord(B : Byte); 238 const 239 HexDigits : array[0..$F] of AnsiChar = '0123456789ABCDEF'; 240 begin 241 if W > 73 then AddWordToOutBuf; 242 WordBuf[W] := '='; 243 WordBuf[W + 1] := HexDigits[B shr 4]; 244 WordBuf[W + 2] := HexDigits[B and $F]; 245 Inc(W, 3) 246 end; 247 248 begin 249 Result := ''; 250 InStream := TMemoryStream.Create; 251 OutStream := TMemoryStream.Create; 252 try 253 if Text <> '' then begin 254 InStream.Write(Text[1], Length(Text)); 255 InStream.Position := 0; 256 end; 257 258 Abort := False; 259 O := 0; 260 W := 0; 261 FillChar(OutBuf, SizeOf(OutBuf), #0); 262 while (InStream.Read(CurChar, 1) = 1) and not Abort do begin 263 if (Ord(CurChar) in [33..60, 62..126]) then begin 264 WordBuf[W] := CurChar; 265 Inc(W); 266 if W > 74 then AddWordToOutBuf; 267 end else if (CurChar = ' ') or (CurChar = #9) then begin 268 WordBuf[W] := CurChar; 269 Inc(W); 270 AddWordToOutBuf; 271 end else if (CurChar = #13) then begin 272 AddWordToOutBuf; 273 SendLine; 274 end else if (CurChar = #10) then begin 275 { Do nothing } 276 end else begin 277 AddHexToWord(Byte(CurChar)); 278 end; 279 end; 280 AddWordToOutBuf; 281 OutStream.Write(OutBuf, O); 282 SetLength(Result, OutStream.Size); 283 OutStream.Position := 0; 284 if OutStream.Size > 0 then 285 OutStream.Read(Result[1], Length(Result)); 286 finally 287 OutStream.Free; 288 InStream.Free; 85 Inc(I); 289 86 end; 290 87 end;
Note:
See TracChangeset
for help on using the changeset viewer.