mutf7.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <auth.h>
  5. #include "imap4d.h"
  6. /*
  7. * modified utf-7, as per imap4 spec
  8. * like utf-7, but substitues , for / in base 64,
  9. * does not allow escaped ascii characters.
  10. *
  11. * /lib/rfc/rfc2152 is utf-7
  12. * /lib/rfc/rfc1642 is obsolete utf-7
  13. *
  14. * test sequences from rfc1642
  15. * 'A≢Α.' 'A&ImIDkQ-.'
  16. * 'Hi Mom ☺!" 'Hi Mom &Jjo-!'
  17. * '日本語' '&ZeVnLIqe-'
  18. */
  19. static uchar mt64d[256];
  20. static char mt64e[64];
  21. static void
  22. initm64(void)
  23. {
  24. int c, i;
  25. memset(mt64d, 255, 256);
  26. memset(mt64e, '=', 64);
  27. i = 0;
  28. for(c = 'A'; c <= 'Z'; c++){
  29. mt64e[i] = c;
  30. mt64d[c] = i++;
  31. }
  32. for(c = 'a'; c <= 'z'; c++){
  33. mt64e[i] = c;
  34. mt64d[c] = i++;
  35. }
  36. for(c = '0'; c <= '9'; c++){
  37. mt64e[i] = c;
  38. mt64d[c] = i++;
  39. }
  40. mt64e[i] = '+';
  41. mt64d['+'] = i++;
  42. mt64e[i] = ',';
  43. mt64d[','] = i;
  44. }
  45. int
  46. encmutf7(char *out, int lim, char *in)
  47. {
  48. Rune rr;
  49. ulong r, b;
  50. char *start = out;
  51. char *e = out + lim;
  52. int nb;
  53. if(mt64e[0] == 0)
  54. initm64();
  55. for(;;){
  56. r = *(uchar*)in;
  57. if(r < ' ' || r >= Runeself){
  58. if(r == '\0')
  59. break;
  60. if(out + 1 >= e)
  61. return -1;
  62. *out++ = '&';
  63. b = 0;
  64. nb = 0;
  65. for(;;){
  66. in += chartorune(&rr, in);
  67. r = rr;
  68. if(r == '\0' || r >= ' ' && r < Runeself)
  69. break;
  70. b = (b << 16) | r;
  71. for(nb += 16; nb >= 6; nb -= 6){
  72. if(out + 1 >= e)
  73. return -1;
  74. *out++ = mt64e[(b>>(nb-6))&0x3f];
  75. }
  76. }
  77. for(; nb >= 6; nb -= 6){
  78. if(out + 1 >= e)
  79. return -1;
  80. *out++ = mt64e[(b>>(nb-6))&0x3f];
  81. }
  82. if(nb){
  83. if(out + 1 >= e)
  84. return -1;
  85. *out++ = mt64e[(b<<(6-nb))&0x3f];
  86. }
  87. if(out + 1 >= e)
  88. return -1;
  89. *out++ = '-';
  90. if(r == '\0')
  91. break;
  92. }else
  93. in++;
  94. if(out + 1 >= e)
  95. return -1;
  96. *out = r;
  97. out++;
  98. if(r == '&')
  99. *out++ = '-';
  100. }
  101. if(out >= e)
  102. return -1;
  103. *out = '\0';
  104. return out - start;
  105. }
  106. int
  107. decmutf7(char *out, int lim, char *in)
  108. {
  109. Rune rr;
  110. char *start = out;
  111. char *e = out + lim;
  112. int c, b, nb;
  113. if(mt64e[0] == 0)
  114. initm64();
  115. for(;;){
  116. c = *in;
  117. if(c < ' ' || c >= Runeself){
  118. if(c == '\0')
  119. break;
  120. return -1;
  121. }
  122. if(c != '&'){
  123. if(out + 1 >= e)
  124. return -1;
  125. *out++ = c;
  126. in++;
  127. continue;
  128. }
  129. in++;
  130. if(*in == '-'){
  131. if(out + 1 >= e)
  132. return -1;
  133. *out++ = '&';
  134. in++;
  135. continue;
  136. }
  137. b = 0;
  138. nb = 0;
  139. while((c = *in++) != '-'){
  140. c = mt64d[c];
  141. if(c >= 64)
  142. return -1;
  143. b = (b << 6) | c;
  144. nb += 6;
  145. if(nb >= 16){
  146. rr = b >> (nb - 16);
  147. nb -= 16;
  148. if(out + UTFmax + 1 >= e && out + runelen(rr) + 1 >= e)
  149. return -1;
  150. out += runetochar(out, &rr);
  151. }
  152. }
  153. if(b & ((1 << nb) - 1))
  154. return -1;
  155. }
  156. if(out >= e)
  157. return -1;
  158. *out = '\0';
  159. return out - start;
  160. }