QuotePrintable编码原理

unit uQuotePrintable;
(************************************************)
(*                                              *)
(*              作者: Fengsh                   *)
(*           @Copy Right for fsh                *)
(*           QQ:19985430                        *)
(*                                              *)
(************************************************)

(*
                            ASCII 码对照表

二制制         八进制  十六进制  十进制  字符        二制制         八进制  十六进制    十进制  字符
0000 0000          00      00      0       nul      0100 0000         100       40        64      @
0000 0001          01      01      1       soh      0100 0001         101       41        65      A
0000 0010          02      02      2       stx      0100 0010         102       42        66      B
0000 0011          03      03      3       etx      0100 0011         103       43        67      C
0000 0100          04      04      4       eot      0100 0100         104       44        68      D
0000 0101          05      05      5       enq      0100 0101         105       45        69      E
0000 0110          06      06      6       ack      0100 0110         106       46        70      F
0000 0111          07      07      7       bel      0100 0111         107       47        71      G
0000 1000          10      08      8       bs       0100 1000         110       48        72      H
0000 1001          11      09      9       ht       0100 1001         111       49        73      I
0000 1010          12      0a      10      nl       0100 1010         112       4a        74      J
0000 1011          13      0b      11      vt       0100 1011         113       4b        75      K
0000 1100          14      0c      12      ff       0100 1100         114       4c        76      L
0000 1101          15      0d      13      er       0100 1101         115       4d        77      M
0000 1110          16      0e      14      so       0100 1110         116       4e        78      N
0000 1111          17      0f      15      si       0100 1111         117       4f        79      O
0001 0000          20      10      16      dle      0101 0000         120       50        80      P
0001 0001          21      11      17      dc1      0101 0001         121       51        81      Q
0001 0010          22      12      18      dc2      0101 0010         122       52        82      R
0001 0011          23      13      19      dc3      0101 0011         123       53        83      S
0001 0100          24      14      20      dc4      0101 0100         124       54        84      T
0001 0101          25      15      21      nak      0101 0101         125       55        85      U
0001 0110          26      16      22      syn      0101 0110         126       56        86      V
0001 0111          27      17      23      etb      0101 0111         127       57        87      W
0001 1000          30      18      24      can      0101 1000         130       58        88      X
0001 1001          31      19      25      em       0101 1001         131       59        89      Y
0001 1010          32      1a      26      sub      0101 1010         132       5a        90      Z
0001 1011          33      1b      27      esc      0101 1011         133       5b        91      [
0001 1100          34      1c      28      fs       0101 1100         134       5c        92      \
0001 1101          35      1d      29      gs       0101 1101         135       5d        93      ]
0001 1110          36      1e      30      re       0101 1110         136       5e        94      ^
0001 1111          37      1f      31      us       0101 1111         137       5f        95      _
0010 0000          40      20      32      sp       0110 0000         140       60        96      '
0010 0001          41      21      33      !        0110 0001         141       61        97      a
0010 0010          42      22      34      "        0110 0010         142       62        98      b
0010 0011          43      23      35      #        0110 0011         143       63        99      c
0010 0100          44      24      36      $        0110 0100         144       64        100     d
0010 0101          45      25      37      %        0110 0101         145       65        101     e
0010 0110          46      26      38      &        0110 0110         146       66        102     f
0010 0111          47      27      39      `        0110 0111         147       67        103     g
0010 1000          50      28      40      (        0110 1000         150       68        104     h
0010 1001          51      29      41      )        0110 1001         151       69        105     i
0010 1010          52      2a      42      *        0110 1010         152       6a        106     j
0010 1011          53      2b      43      +        0110 1011         153       6b        107     k
0010 1100          54      2c      44      ,        0110 1100         154       6c        108     l
0010 1101          55      2d      45      -        0110 1101         155       6d        109     m
0010 1110          56      2e      46      .        0110 1110         156       6e        110     n
0010 1111          57      2f      47      /        0110 1111         157       6f        111     o
0011 0000          60      30      48      0        0111 0000         160       70        112     p
0011 0001          61      31      49      1        0111 0001         161       71        113     q
0011 0010          62      32      50      2        0111 0010         162       72        114     r
0011 0011          63      33      51      3        0111 0011         163       73        115     s
0011 0100          64      34      52      4        0111 0100         164       74        116     t
0011 0101          65      35      53      5        0111 0101         165       75        117     u
0011 0110          66      36      54      6        0111 0110         166       76        118     v
0011 0111          67      37      55      7        0111 0111         167       77        119     w
0011 1000          70      38      56      8        0111 1000         170       78        120     x
0011 1001          71      39      57      9        0111 1001         171       79        121     y 
0011 1010          72      3a      58      :        0111 1010         172       7a        122     z
0011 1011          73      3b      59      ;        0111 1011         173       7b        123     {
0011 1100          74      3c      60      <        0111 1100         174       7c        124     |
0011 1101          75      3d      61      =        0111 1101         175       7d        125     }
0011 1110          76      3e      62      >        0111 1110         176       7e        126     ~
0011 1111          77      3f      63      ?        0111 1111         177       7f        127     del

*)

{

  Char = 1字节 = 8bit = 2^8 = 256  ASCII码正好为8bit 从0~255个值。
  一个汉字 = 2 字节 = 2 * 8bit = 2^16 

  Email中
  QP使用"="开头的转义字符. 一般限制行宽为76

  QP编码原理:
     任何8-bit字节值可编码为3个字符: 一个等号"="后跟随两个十六进制数字
     (0–9或A–F)表示该字节的数值。

     等号"="(十进制值为61)不可以这样直接表示。

    标准ASCII码中除了十进制33-60,62-126范围的字符不需要转换外,其它ASCII码值都
    需要转为"=XX"的形式,其中XX为两个十六进制的值(大写)。为保证输出行不超过规
    定长度,可在行尾加“=/r/n”序列作为软回车。

    注:
      ASCII的水平制表符(tab)与空格符, 十进制为9和32, 如果不出现在行尾则可以
      用其ASCII字符编码直接表示。如果这两个字符出现在行尾,必须QP编码表示为
      "=09" (tab)或"=20" (space).

      如果数据中包含有意义的行结束标志,必须转换为ASCII回车(CR)换行(LF)序列
      ,既不能用原来的ASCII字符也不能用QP编码的"="转义字符序列。 相反,如果
      字节值13与10有其它的不是行结束的含义,它们必须QP编码为=0D与=0A.

      quoted-printable编码的数据的每行长度不能超过76个字符. 为满足此要求又
      不改变被编码文本,在QP编码结果的每行末尾加上软换行(soft line break).
       即在每行末尾加上一个"=", 但并不会出现在解码得到的文本中.



  QP解码:
    碰到=号,并且后面1位字符和2位字符分别在0-9 ,A-F中时要将字符转为十六进制,
    然后求出该十六进制对应的十进制值,然后将得到的十进制值分转为对应的ASCII
    字符值。
}

interface

uses
    Sysutils,Classes,uBinTrans;

    { Quoted-Printable 解码 }
    function DecodeQuotedPrintable(Const EncodeString:String):String;
    { Quoted-Printable 编码 }
    function EncodeQuotedPrintable(Const Src:String;Const LineLen:Integer=76):String;

implementation


//for Mine QP Very Good
function EncodeQuotedPrintable(Const Src:String;Const LineLen:Integer):String;
Const
  SoftCRLF = '='; //QP编码后的软回车 非真实字符串的回车是为了MIME中长度限制为76而设
  CRLF = #13#10;
var
  Loop:Integer;
  sLen:Integer;
  encodeLen:Integer;
  RetStr:String;
  CurrentChar:Char;
  Rows:Integer;
  tLen:Integer;
begin
  sLen := Length(Src);
  RetStr := Emptystr;
  Rows := 1;
  for Loop := 1 to sLen do
  begin
      //取当前字符
      CurrentChar := Src[Loop];

      encodeLen := Length(RetStr);
      tLen := Rows*LineLen;
      
      if  tLen - encodeLen = 0 then
      begin
         RetStr := RetStr + CRLF;
         Inc(Rows);
      end;

      if (encodeLen < tLen) and (tLen - encodeLen < 3) then
      begin
        RetStr := RetStr + SoftCRLF + CRLF;
        Inc(Rows);
      end;
      
      if sLen-Loop>=2 then
      begin
        //碰到tab 和 space符 并且在行尾的要进行转码 =09(tab) =20(space)
        if (CurrentChar in [#9,#32]) and (Src[Loop+1] = #13) and (Src[Loop+2] = #10) then
        begin
           RetStr := RetStr + '=' + IntToHex(ord(CurrentChar),2);
           Continue;
        end;
      end;

      //最后一个字符是tab 和space时也是要转的
      if sLen = Loop then
      begin
         if CurrentChar in [#9,#32] then
         begin
           RetStr := RetStr + '=' + IntToHex(ord(CurrentChar),2);
           Continue;
         end;
      end;

      //不在33-60, 62-126的进行转码
      if CurrentChar in [#0..#8,#10..#31,#61,#127..#255] then
         RetStr := RetStr + '=' + IntToHex(ord(CurrentChar),2)
      else
         RetStr := RetStr + CurrentChar;
  end;
  Result := RetStr;
end;

//for Mime very good
function DecodeQuotedPrintable(Const EncodeString:String):String;
var
  Loop:Integer;
  sLen:Integer;
  RetStr:String;
  cChar : Char;
begin
  RetStr := EmptyStr;
  sLen := Length(EncodeString);
  Loop := 1;
  while Loop <= sLen do
  begin
      cChar := EncodeString[Loop];

      if (cChar = #13) or (cChar=#10) then
      begin
         Inc(Loop);
         Continue;
      end;

      //判断=号是否在行尾
      if sLen-Loop>=2 then
      begin
          //如果是软回车,把'='号掉弃
          if (cChar = #61) and (EncodeString[Loop+1]=#13) and (EncodeString[Loop+2]=#10) then
          begin
             Inc(Loop);
             Continue;
          end;

          //如果=后跟两个十六进制字符,则要斩为相应十进制的ASCII码
          if (cChar = #61)
          and (EncodeString[Loop+1] in ['0'..'9', 'A'..'F'])
           and (EncodeString[Loop+2] in ['0'..'9', 'A'..'F']) then
          begin
             RetStr := RetStr + Char(HexToInt(EncodeString[Loop+1] + EncodeString[Loop+2]));
             Inc(Loop,3);
             Continue;
          end
          else
             RetStr := RetStr + cChar;
      end
      else
         RetStr := RetStr + cChar;

      Inc(Loop);
  end;

  Result := RetStr;
end;

end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

边缘998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值