/src/smtp/rfc2047.erl

http://github.com/zotonic/zotonic · Erlang · 65 lines · 48 code · 11 blank · 6 comment · 0 complexity · b6213150aeac844333ab788e708484b9 MD5 · raw file

  1. %% Encode a string according to RFC 2047 using quoted-printable.
  2. %% Assumes UTF-8 as the character set.
  3. %%
  4. %% @copyright 2009 Marc Worrell
  5. -module(rfc2047).
  6. -author("Marc Worrell <marc@worrell.nl>").
  7. -export([encode/1, decode/1]).
  8. encode(B) when is_binary(B) ->
  9. encode(binary_to_list(B));
  10. encode([]) ->
  11. [];
  12. encode(Text) ->
  13. encode(Text, Text).
  14. %% Don't escape when all characters are ASCII printable
  15. encode([], Text) ->
  16. Text;
  17. encode([H|T], Text) when H >= 32 andalso H =< 126 andalso H /= $= ->
  18. encode(T, Text);
  19. encode(_, Text) ->
  20. "=?UTF-8?Q?" ++ encode(Text, [], 0) ++ "?=".
  21. encode([], Acc, _WordLen) ->
  22. lists:reverse(Acc);
  23. encode(T, Acc, WordLen) when WordLen >= 55 ->
  24. %% Make sure that the individual encoded words are not longer than 76 chars (including charset etc)
  25. encode(T, [$?,$Q,$?,$8,$-,$F,$T,$U,$?,$=,32,10,13,$=,$?|Acc], 0);
  26. encode([C|T], Acc, WordLen) when C > 32 andalso C < 127 andalso C /= 32
  27. andalso C /= $? andalso C /= $_ andalso C /= $= andalso C /= $. ->
  28. encode(T, [C|Acc], WordLen+1);
  29. encode([C|T], Acc, WordLen) ->
  30. encode(T, [hex(C rem 16), hex(C div 16), $= | Acc], WordLen+3).
  31. decode(B) when is_binary(B) ->
  32. decode(binary_to_list(B));
  33. decode(Text) ->
  34. decode(Text, in_text, []).
  35. decode([], _, Acc) ->
  36. lists:reverse(Acc);
  37. decode("=?UTF-8?Q?" ++ T, in_text, Acc) ->
  38. decode(T, in_utf8, Acc);
  39. decode("?= \r\n" ++ T, in_utf8, Acc) ->
  40. decode(T, in_text, Acc);
  41. decode("?=" ++ T, in_utf8, Acc) ->
  42. decode(T, in_text, Acc);
  43. decode([$=,C1,C2|T], in_utf8, Acc) ->
  44. decode(T, in_utf8, [unhex(C1)*16+unhex(C2)|Acc]);
  45. decode([H|T], State, Acc) ->
  46. decode(T, State, [H|Acc]).
  47. hex(N) when N >= 10 -> N + $A - 10;
  48. hex(N) -> N + $0.
  49. unhex(C) when C >= $a ->
  50. C - $a + 10;
  51. unhex(C) when C >= $A ->
  52. C - $A + 10;
  53. unhex(C) ->
  54. C - $0.