utilada_2.8.0_0d266031/src/sys/encoders/util-encoders-quoted_printable.adb

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
-----------------------------------------------------------------------
--  util-encoders-quoted_printable -- Encode/Decode a stream in quoted-printable
--  Copyright (C) 2020 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--  SPDX-License-Identifier: Apache-2.0
-----------------------------------------------------------------------
with Ada.Characters.Handling;
with Util.Encoders.Base16;
package body Util.Encoders.Quoted_Printable is

   use Ada.Characters.Handling;

   --  ------------------------------
   --  Decode the Quoted-Printable string and return the result.
   --  When Strict is true, raises the Encoding_Error exception if the
   --  format is invalid.  Otherwise, ignore invalid encoding.
   --  ------------------------------
   function Decode (Content : in String;
                    Strict  : in Boolean := True) return String is
      Result    : String (1 .. Content'Length);
      Read_Pos  : Natural := Content'First;
      Write_Pos : Natural := Result'First - 1;
      C         : Character;
      C2        : Character;
   begin
      while Read_Pos <= Content'Last loop
         C := Content (Read_Pos);
         if C = '=' then
            exit when Read_Pos = Content'Last;
            if Read_Pos + 2 > Content'Last then
               exit when not Strict;
               raise Encoding_Error;
            end if;
            Read_Pos := Read_Pos + 1;
            C := Content (Read_Pos);
            if not Is_Hexadecimal_Digit (C) then
               exit when not Strict;
               raise Encoding_Error;
            end if;
            C2 := Content (Read_Pos + 1);
            if not Is_Hexadecimal_Digit (C) then
               exit when not Strict;
               raise Encoding_Error;
            end if;
            Write_Pos := Write_Pos + 1;
            Result (Write_Pos) := Base16.From_Hex (C, C2);
            Read_Pos := Read_Pos + 1;
         else
            Write_Pos := Write_Pos + 1;
            Result (Write_Pos) := C;
         end if;
         Read_Pos := Read_Pos + 1;
      end loop;
      return Result (1 .. Write_Pos);
   end Decode;

   --  ------------------------------
   --  Decode the "Q" encoding, similar to Quoted-Printable but with
   --  spaces that can be replaced by '_'.
   --  See RFC 2047.
   --  ------------------------------
   function Q_Decode (Content : in String) return String is
      Result    : String (1 .. Content'Length);
      Read_Pos  : Natural := Content'First;
      Write_Pos : Natural := Result'First - 1;
      C         : Character;
      C2        : Character;
   begin
      while Read_Pos <= Content'Last loop
         C := Content (Read_Pos);
         if C = '=' then
            exit when Read_Pos = Content'Last or else Read_Pos + 2 > Content'Last;
            Read_Pos := Read_Pos + 1;
            C := Content (Read_Pos);
            exit when not Is_Hexadecimal_Digit (C);
            C2 := Content (Read_Pos + 1);
            exit when  not Is_Hexadecimal_Digit (C);
            Write_Pos := Write_Pos + 1;
            Result (Write_Pos) := Base16.From_Hex (C, C2);
            Read_Pos := Read_Pos + 1;
         elsif C = '_' then
            Write_Pos := Write_Pos + 1;
            Result (Write_Pos) := ' ';
         else
            Write_Pos := Write_Pos + 1;
            Result (Write_Pos) := C;
         end if;
         Read_Pos := Read_Pos + 1;
      end loop;
      return Result (1 .. Write_Pos);
   end Q_Decode;

end Util.Encoders.Quoted_Printable;