PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/mel-b-ccl.el

http://github.com/wanderlust/flim
Emacs Lisp | 481 lines | 384 code | 59 blank | 38 comment | 3 complexity | bb6d49f5eefceac12c0af2aea7fc8714 MD5 | raw file
  1. ;;; mel-b-ccl.el --- Base64 encoder/decoder using CCL.
  2. ;; Copyright (C) 1998,1999,2000 Free Software Foundation, Inc.
  3. ;; Author: Tanaka Akira <akr@m17n.org>
  4. ;; Created: 1998/9/17
  5. ;; Keywords: MIME, Base64
  6. ;; This file is part of FLIM (Faithful Library about Internet Message).
  7. ;; This program is free software; you can redistribute it and/or
  8. ;; modify it under the terms of the GNU General Public License as
  9. ;; published by the Free Software Foundation; either version 2, or (at
  10. ;; your option) any later version.
  11. ;; This program is distributed in the hope that it will be useful, but
  12. ;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ;; General Public License for more details.
  15. ;; You should have received a copy of the GNU General Public License
  16. ;; along with this program; see the file COPYING. If not, write to the
  17. ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  18. ;; Boston, MA 02110-1301, USA.
  19. ;;; Code:
  20. (require 'ccl)
  21. (require 'pccl)
  22. (require 'mime-def)
  23. ;;; @ constants
  24. ;;;
  25. (eval-when-compile
  26. (defconst mel-ccl-4-table
  27. '( 0 1 2 3))
  28. (defconst mel-ccl-16-table
  29. '( 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
  30. (defconst mel-ccl-64-table
  31. '( 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  32. 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
  33. 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
  34. 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63))
  35. (defconst mel-ccl-256-table
  36. '( 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  37. 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
  38. 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
  39. 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
  40. 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
  41. 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  42. 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
  43. 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
  44. 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
  45. 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
  46. 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
  47. 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
  48. 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
  49. 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
  50. 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
  51. 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255))
  52. (defconst mel-ccl-256-to-64-table
  53. '(nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
  54. nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
  55. nil nil nil nil nil nil nil nil nil nil nil 62 nil nil nil 63
  56. 52 53 54 55 56 57 58 59 60 61 nil nil nil t nil nil
  57. nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  58. 15 16 17 18 19 20 21 22 23 24 25 nil nil nil nil nil
  59. nil 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
  60. 41 42 43 44 45 46 47 48 49 50 51 nil nil nil nil nil
  61. nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
  62. nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
  63. nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
  64. nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
  65. nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
  66. nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
  67. nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
  68. nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil))
  69. (defconst mel-ccl-64-to-256-table
  70. (mapcar
  71. 'char-int
  72. "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
  73. abcdefghijklmnopqrstuvwxyz\
  74. 0123456789\
  75. +/"))
  76. )
  77. ;;; @ CCL programs
  78. ;;;
  79. (eval-when-compile
  80. (defun mel-ccl-decode-b-bit-ex (v)
  81. (logior
  82. (lsh (logand v (lsh 255 16)) -16)
  83. (logand v (lsh 255 8))
  84. (lsh (logand v 255) 16)))
  85. )
  86. (eval-when-compile
  87. (defconst mel-ccl-decode-b-0-table
  88. (vconcat
  89. (mapcar
  90. (lambda (v)
  91. (if (integerp v)
  92. (mel-ccl-decode-b-bit-ex (lsh v 18))
  93. (lsh 1 24)))
  94. mel-ccl-256-to-64-table)))
  95. (defconst mel-ccl-decode-b-1-table
  96. (vconcat
  97. (mapcar
  98. (lambda (v)
  99. (if (integerp v)
  100. (mel-ccl-decode-b-bit-ex (lsh v 12))
  101. (lsh 1 25)))
  102. mel-ccl-256-to-64-table)))
  103. (defconst mel-ccl-decode-b-2-table
  104. (vconcat
  105. (mapcar
  106. (lambda (v)
  107. (if (integerp v)
  108. (mel-ccl-decode-b-bit-ex (lsh v 6))
  109. (lsh 1 26)))
  110. mel-ccl-256-to-64-table)))
  111. (defconst mel-ccl-decode-b-3-table
  112. (vconcat
  113. (mapcar
  114. (lambda (v)
  115. (if (integerp v)
  116. (mel-ccl-decode-b-bit-ex v)
  117. (lsh 1 27)))
  118. mel-ccl-256-to-64-table)))
  119. )
  120. (check-broken-facility ccl-cascading-read)
  121. (if-broken ccl-cascading-read
  122. (define-ccl-program mel-ccl-decode-b
  123. `(1
  124. (loop
  125. (loop
  126. (read-branch
  127. r1
  128. ,@(mapcar
  129. (lambda (v)
  130. (cond
  131. ((or (eq v nil) (eq v t)) '(repeat))
  132. (t `((r0 = ,(lsh v 2)) (break)))))
  133. mel-ccl-256-to-64-table)))
  134. (loop
  135. (read-branch
  136. r1
  137. ,@(mapcar
  138. (lambda (v)
  139. (cond
  140. ((or (eq v nil) (eq v t)) '(repeat))
  141. ((= (lsh v -4) 0) `((write r0) (r0 = ,(lsh (logand v 15) 4)) (break)))
  142. (t `((r0 |= ,(lsh v -4)) (write r0) (r0 = ,(lsh (logand v 15) 4)) (break)))))
  143. mel-ccl-256-to-64-table)))
  144. (loop
  145. (read-branch
  146. r1
  147. ,@(mapcar
  148. (lambda (v)
  149. (cond
  150. ((eq v nil) '(repeat))
  151. ((eq v t) '(end))
  152. ((= (lsh v -2) 0) `((write r0) (r0 = ,(lsh (logand v 3) 6)) (break)))
  153. (t `((r0 |= ,(lsh v -2)) (write r0) (r0 = ,(lsh (logand v 3) 6)) (break)))))
  154. mel-ccl-256-to-64-table)))
  155. (loop
  156. (read-branch
  157. r1
  158. ,@(mapcar
  159. (lambda (v)
  160. (cond
  161. ((eq v nil) '(repeat))
  162. ((eq v t) '(end))
  163. (t `((r0 |= ,v) (write r0) (break)))))
  164. mel-ccl-256-to-64-table)))
  165. (repeat))))
  166. (define-ccl-program mel-ccl-decode-b
  167. `(1
  168. (loop
  169. (read r0 r1 r2 r3)
  170. (r4 = r0 ,mel-ccl-decode-b-0-table)
  171. (r5 = r1 ,mel-ccl-decode-b-1-table)
  172. (r4 |= r5)
  173. (r5 = r2 ,mel-ccl-decode-b-2-table)
  174. (r4 |= r5)
  175. (r5 = r3 ,mel-ccl-decode-b-3-table)
  176. (r4 |= r5)
  177. (if (r4 & ,(lognot (1- (lsh 1 24))))
  178. ((loop
  179. (if (r4 & ,(lsh 1 24))
  180. ((r0 = r1) (r1 = r2) (r2 = r3) (read r3)
  181. (r4 >>= 1) (r4 &= ,(logior (lsh 7 24)))
  182. (r5 = r3 ,mel-ccl-decode-b-3-table)
  183. (r4 |= r5)
  184. (repeat))
  185. (break)))
  186. (loop
  187. (if (r4 & ,(lsh 1 25))
  188. ((r1 = r2) (r2 = r3) (read r3)
  189. (r4 >>= 1) (r4 &= ,(logior (lsh 7 24)))
  190. (r5 = r3 ,mel-ccl-decode-b-3-table)
  191. (r4 |= r5)
  192. (repeat))
  193. (break)))
  194. (loop
  195. (if (r2 != ?=)
  196. (if (r4 & ,(lsh 1 26))
  197. ((r2 = r3) (read r3)
  198. (r4 >>= 1) (r4 &= ,(logior (lsh 7 24)))
  199. (r5 = r3 ,mel-ccl-decode-b-3-table)
  200. (r4 |= r5)
  201. (repeat))
  202. ((r6 = 0)
  203. (break)))
  204. ((r6 = 1)
  205. (break))))
  206. (loop
  207. (if (r3 != ?=)
  208. (if (r4 & ,(lsh 1 27))
  209. ((read r3)
  210. (r4 = r3 ,mel-ccl-decode-b-3-table)
  211. (repeat))
  212. (break))
  213. ((r6 |= 2)
  214. (break))))
  215. (r4 = r0 ,mel-ccl-decode-b-0-table)
  216. (r5 = r1 ,mel-ccl-decode-b-1-table)
  217. (r4 |= r5)
  218. (branch
  219. r6
  220. ;; BBBB
  221. ((r5 = r2 ,mel-ccl-decode-b-2-table)
  222. (r4 |= r5)
  223. (r5 = r3 ,mel-ccl-decode-b-3-table)
  224. (r4 |= r5)
  225. (r4 >8= 0)
  226. (write r7)
  227. (r4 >8= 0)
  228. (write r7)
  229. (write-repeat r4))
  230. ;; error: BB=B
  231. ((write (r4 & 255))
  232. (end))
  233. ;; BBB=
  234. ((r5 = r2 ,mel-ccl-decode-b-2-table)
  235. (r4 |= r5)
  236. (r4 >8= 0)
  237. (write r7)
  238. (write (r4 & 255))
  239. (end) ; Excessive (end) is workaround for XEmacs 21.0.
  240. ; Without this, "AAA=" is converted to "^@^@^@".
  241. (end))
  242. ;; BB==
  243. ((write (r4 & 255))
  244. (end))))
  245. ((r4 >8= 0)
  246. (write r7)
  247. (r4 >8= 0)
  248. (write r7)
  249. (write-repeat r4))))))
  250. )
  251. (eval-when-compile
  252. ;; Generated CCL program works not properly on 20.2 because CCL_EOF_BLOCK
  253. ;; is not executed.
  254. (defun mel-ccl-encode-base64-generic
  255. (&optional quantums-per-line output-crlf terminate-with-newline)
  256. `(2
  257. ((r3 = 0)
  258. (r2 = 0)
  259. (read r1)
  260. (loop
  261. (branch
  262. r1
  263. ,@(mapcar
  264. (lambda (r1)
  265. `((write ,(nth (lsh r1 -2) mel-ccl-64-to-256-table))
  266. (r0 = ,(logand r1 3))))
  267. mel-ccl-256-table))
  268. (r2 = 1)
  269. (read-branch
  270. r1
  271. ,@(mapcar
  272. (lambda (r1)
  273. `((write r0 ,(vconcat
  274. (mapcar
  275. (lambda (r0)
  276. (nth (logior (lsh r0 4)
  277. (lsh r1 -4))
  278. mel-ccl-64-to-256-table))
  279. mel-ccl-4-table)))
  280. (r0 = ,(logand r1 15))))
  281. mel-ccl-256-table))
  282. (r2 = 2)
  283. (read-branch
  284. r1
  285. ,@(mapcar
  286. (lambda (r1)
  287. `((write r0 ,(vconcat
  288. (mapcar
  289. (lambda (r0)
  290. (nth (logior (lsh r0 2)
  291. (lsh r1 -6))
  292. mel-ccl-64-to-256-table))
  293. mel-ccl-16-table)))))
  294. mel-ccl-256-table))
  295. (r1 &= 63)
  296. (write r1 ,(vconcat
  297. (mapcar
  298. (lambda (r1)
  299. (nth r1 mel-ccl-64-to-256-table))
  300. mel-ccl-64-table)))
  301. (r3 += 1)
  302. (r2 = 0)
  303. (read r1)
  304. ,@(when quantums-per-line
  305. `((if (r3 == ,quantums-per-line)
  306. ((write ,(if output-crlf "\r\n" "\n"))
  307. (r3 = 0)))))
  308. (repeat)))
  309. (branch
  310. r2
  311. ,(if terminate-with-newline
  312. `(if (r3 > 0) (write ,(if output-crlf "\r\n" "\n")))
  313. `(r0 = 0))
  314. ((write r0 ,(vconcat
  315. (mapcar
  316. (lambda (r0)
  317. (nth (lsh r0 4) mel-ccl-64-to-256-table))
  318. mel-ccl-4-table)))
  319. (write ,(if terminate-with-newline
  320. (if output-crlf "==\r\n" "==\n")
  321. "==")))
  322. ((write r0 ,(vconcat
  323. (mapcar
  324. (lambda (r0)
  325. (nth (lsh r0 2) mel-ccl-64-to-256-table))
  326. mel-ccl-16-table)))
  327. (write ,(if terminate-with-newline
  328. (if output-crlf "=\r\n" "=\n")
  329. "="))))
  330. ))
  331. )
  332. (define-ccl-program mel-ccl-encode-b
  333. (mel-ccl-encode-base64-generic))
  334. ;; 19 * 4 = 76
  335. (define-ccl-program mel-ccl-encode-base64-crlf-crlf
  336. (mel-ccl-encode-base64-generic 19 t))
  337. (define-ccl-program mel-ccl-encode-base64-crlf-lf
  338. (mel-ccl-encode-base64-generic 19 nil))
  339. ;;; @ coding system
  340. ;;;
  341. (make-ccl-coding-system
  342. 'mel-ccl-b-rev ?B "MIME B-encoding (reversed)"
  343. 'mel-ccl-encode-b 'mel-ccl-decode-b)
  344. (make-ccl-coding-system
  345. 'mel-ccl-base64-crlf-rev
  346. ?B "MIME Base64-encoding (reversed)"
  347. 'mel-ccl-encode-base64-crlf-crlf
  348. 'mel-ccl-decode-b)
  349. (make-ccl-coding-system
  350. 'mel-ccl-base64-lf-rev
  351. ?B "MIME Base64-encoding (LF encoding) (reversed)"
  352. 'mel-ccl-encode-base64-crlf-lf
  353. 'mel-ccl-decode-b)
  354. ;;; @ B
  355. ;;;
  356. (check-broken-facility ccl-execute-eof-block-on-decoding-some)
  357. (unless-broken ccl-execute-eof-block-on-decoding-some
  358. (defun base64-ccl-encode-string (string &optional no-line-break)
  359. "Encode STRING with base64 encoding."
  360. (if no-line-break
  361. (decode-coding-string string 'mel-ccl-b-rev)
  362. (decode-coding-string string 'mel-ccl-base64-lf-rev)))
  363. (defalias-maybe 'base64-encode-string 'base64-ccl-encode-string)
  364. (defun base64-ccl-encode-region (start end &optional no-line-break)
  365. "Encode region from START to END with base64 encoding."
  366. (interactive "*r")
  367. (if no-line-break
  368. (decode-coding-region start end 'mel-ccl-b-rev)
  369. (decode-coding-region start end 'mel-ccl-base64-lf-rev)))
  370. (defalias-maybe 'base64-encode-region 'base64-ccl-encode-region)
  371. (defun base64-ccl-insert-encoded-file (filename)
  372. "Encode contents of file FILENAME to base64, and insert the result."
  373. (interactive "*fInsert encoded file: ")
  374. (insert
  375. (decode-coding-string
  376. (with-temp-buffer
  377. (set-buffer-multibyte nil)
  378. (insert-file-contents-as-binary filename)
  379. (buffer-string))
  380. 'mel-ccl-base64-lf-rev)))
  381. (mel-define-method-function (mime-encode-string string (nil "base64"))
  382. 'base64-ccl-encode-string)
  383. (mel-define-method-function (mime-encode-region start end (nil "base64"))
  384. 'base64-ccl-encode-region)
  385. (mel-define-method-function
  386. (mime-insert-encoded-file filename (nil "base64"))
  387. 'base64-ccl-insert-encoded-file)
  388. (mel-define-method-function (encoded-text-encode-string string (nil "B"))
  389. 'base64-ccl-encode-string)
  390. )
  391. (defun base64-ccl-decode-string (string)
  392. "Decode base64 encoded STRING"
  393. (encode-coding-string string 'mel-ccl-b-rev))
  394. (defalias-maybe 'base64-decode-string 'base64-ccl-decode-string)
  395. (defun base64-ccl-decode-region (start end)
  396. "Decode base64 encoded the region from START to END."
  397. (interactive "*r")
  398. (encode-coding-region start end 'mel-ccl-b-rev))
  399. (defalias-maybe 'base64-decode-region 'base64-ccl-decode-region)
  400. (defun base64-ccl-write-decoded-region (start end filename)
  401. "Decode the region from START to END and write out to FILENAME."
  402. (interactive "*r\nFWrite decoded region to file: ")
  403. (let ((coding-system-for-write 'mel-ccl-b-rev)
  404. jka-compr-compression-info-list jam-zcat-filename-list)
  405. (write-region start end filename)))
  406. (mel-define-method-function (mime-decode-string string (nil "base64"))
  407. 'base64-ccl-decode-string)
  408. (mel-define-method-function (mime-decode-region start end (nil "base64"))
  409. 'base64-ccl-decode-region)
  410. (mel-define-method-function
  411. (mime-write-decoded-region start end filename (nil "base64"))
  412. 'base64-ccl-write-decoded-region)
  413. (mel-define-method encoded-text-decode-string (string (nil "B"))
  414. (if (string-match (eval-when-compile
  415. (concat "\\`" B-encoded-text-regexp "\\'"))
  416. string)
  417. (base64-ccl-decode-string string)
  418. (error "Invalid encoded-text %s" string)))
  419. ;;; @ end
  420. ;;;
  421. (provide 'mel-b-ccl)
  422. ;;; mel-b-ccl.el ends here.