qwikdoc 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (335) hide show
  1. data/.gitignore +5 -0
  2. data/.rspec +2 -0
  3. data/CHANGES +3 -0
  4. data/COPYING +340 -0
  5. data/Gemfile +3 -0
  6. data/README.md +10 -0
  7. data/Rakefile +10 -0
  8. data/TextFormattingRules +137 -0
  9. data/TextFormattingRules.ja +143 -0
  10. data/bin/qwikdoc +34 -0
  11. data/lib/qwik_doc.rb +15 -0
  12. data/lib/qwik_doc/hack.rb +184 -0
  13. data/qwikdoc.gemspec +26 -0
  14. data/spec/qwik_doc_spec.rb +305 -0
  15. data/spec/spec_helper.rb +12 -0
  16. data/vendor/qwik/Makefile +63 -0
  17. data/vendor/qwik/Rakefile +17 -0
  18. data/vendor/qwik/act-aa.rb +83 -0
  19. data/vendor/qwik/act-archive.rb +386 -0
  20. data/vendor/qwik/act-attach.rb +304 -0
  21. data/vendor/qwik/act-backup.rb +236 -0
  22. data/vendor/qwik/act-basic.rb +325 -0
  23. data/vendor/qwik/act-book.rb +161 -0
  24. data/vendor/qwik/act-calc.rb +371 -0
  25. data/vendor/qwik/act-charset.rb +251 -0
  26. data/vendor/qwik/act-christel.rb +112 -0
  27. data/vendor/qwik/act-chronology.rb +149 -0
  28. data/vendor/qwik/act-code.rb +155 -0
  29. data/vendor/qwik/act-comment.rb +554 -0
  30. data/vendor/qwik/act-config.rb +49 -0
  31. data/vendor/qwik/act-counter.rb +125 -0
  32. data/vendor/qwik/act-day.rb +96 -0
  33. data/vendor/qwik/act-describe.rb +135 -0
  34. data/vendor/qwik/act-diary.rb +109 -0
  35. data/vendor/qwik/act-edit.rb +317 -0
  36. data/vendor/qwik/act-embed-html.rb +296 -0
  37. data/vendor/qwik/act-emode.rb +150 -0
  38. data/vendor/qwik/act-event.rb +187 -0
  39. data/vendor/qwik/act-file.rb +303 -0
  40. data/vendor/qwik/act-files.rb +771 -0
  41. data/vendor/qwik/act-getpass.rb +295 -0
  42. data/vendor/qwik/act-history.rb +136 -0
  43. data/vendor/qwik/act-html.rb +204 -0
  44. data/vendor/qwik/act-httpauth.rb +147 -0
  45. data/vendor/qwik/act-include.rb +142 -0
  46. data/vendor/qwik/act-interwiki.rb +189 -0
  47. data/vendor/qwik/act-isearch.rb +109 -0
  48. data/vendor/qwik/act-keywords.rb +137 -0
  49. data/vendor/qwik/act-lang.rb +81 -0
  50. data/vendor/qwik/act-license.rb +63 -0
  51. data/vendor/qwik/act-list.rb +287 -0
  52. data/vendor/qwik/act-login.rb +410 -0
  53. data/vendor/qwik/act-logout.rb +60 -0
  54. data/vendor/qwik/act-mail.rb +159 -0
  55. data/vendor/qwik/act-map.rb +292 -0
  56. data/vendor/qwik/act-md5.rb +42 -0
  57. data/vendor/qwik/act-mdlb.rb +741 -0
  58. data/vendor/qwik/act-media.rb +416 -0
  59. data/vendor/qwik/act-member.rb +157 -0
  60. data/vendor/qwik/act-menu.rb +142 -0
  61. data/vendor/qwik/act-metadata.rb +323 -0
  62. data/vendor/qwik/act-mlsubmitform.rb +49 -0
  63. data/vendor/qwik/act-monitor.rb +167 -0
  64. data/vendor/qwik/act-new.rb +418 -0
  65. data/vendor/qwik/act-pagelist.rb +248 -0
  66. data/vendor/qwik/act-password.rb +145 -0
  67. data/vendor/qwik/act-plan.rb +210 -0
  68. data/vendor/qwik/act-povray.rb +230 -0
  69. data/vendor/qwik/act-presen.rb +380 -0
  70. data/vendor/qwik/act-redirect.rb +133 -0
  71. data/vendor/qwik/act-ring.rb +1071 -0
  72. data/vendor/qwik/act-rrefs.rb +255 -0
  73. data/vendor/qwik/act-ruby.rb +116 -0
  74. data/vendor/qwik/act-sample.rb +170 -0
  75. data/vendor/qwik/act-save.rb +295 -0
  76. data/vendor/qwik/act-schedule.rb +374 -0
  77. data/vendor/qwik/act-search.rb +180 -0
  78. data/vendor/qwik/act-searchwords.rb +51 -0
  79. data/vendor/qwik/act-sendpass.rb +83 -0
  80. data/vendor/qwik/act-site.rb +89 -0
  81. data/vendor/qwik/act-sitebackup.rb +419 -0
  82. data/vendor/qwik/act-sitelog.rb +118 -0
  83. data/vendor/qwik/act-smil.rb +299 -0
  84. data/vendor/qwik/act-status.rb +220 -0
  85. data/vendor/qwik/act-style.rb +608 -0
  86. data/vendor/qwik/act-table.rb +263 -0
  87. data/vendor/qwik/act-tableform.rb +241 -0
  88. data/vendor/qwik/act-tag.rb +103 -0
  89. data/vendor/qwik/act-text.rb +70 -0
  90. data/vendor/qwik/act-textarea.rb +164 -0
  91. data/vendor/qwik/act-theme.rb +346 -0
  92. data/vendor/qwik/act-toc.rb +112 -0
  93. data/vendor/qwik/act-typekey.rb +198 -0
  94. data/vendor/qwik/act-under-const.rb +94 -0
  95. data/vendor/qwik/act-webservice.rb +321 -0
  96. data/vendor/qwik/act-wema.rb +558 -0
  97. data/vendor/qwik/act-wysiwyg.rb +238 -0
  98. data/vendor/qwik/action.rb +325 -0
  99. data/vendor/qwik/autoreload.rb +98 -0
  100. data/vendor/qwik/bench-bench.rb +28 -0
  101. data/vendor/qwik/bench-emode.rb +47 -0
  102. data/vendor/qwik/bench-format-xml.rb +70 -0
  103. data/vendor/qwik/bench-large-table.rb +62 -0
  104. data/vendor/qwik/bench-md5.rb +14 -0
  105. data/vendor/qwik/bench-module-session.rb +19 -0
  106. data/vendor/qwik/bench-page.rb +50 -0
  107. data/vendor/qwik/bench-s-md5.rb +28 -0
  108. data/vendor/qwik/bench-session.rb +25 -0
  109. data/vendor/qwik/bench-textformat.rb +31 -0
  110. data/vendor/qwik/catalog-factory.rb +91 -0
  111. data/vendor/qwik/catalog-ja.rb +479 -0
  112. data/vendor/qwik/catalog-ml-ja.rb +145 -0
  113. data/vendor/qwik/check-act-monitor.rb +112 -0
  114. data/vendor/qwik/check-act-monitor2.rb +46 -0
  115. data/vendor/qwik/check-act-theme.rb +27 -0
  116. data/vendor/qwik/check-event.rb +112 -0
  117. data/vendor/qwik/check-event2.rb +55 -0
  118. data/vendor/qwik/check-htree-rexml.rb +77 -0
  119. data/vendor/qwik/check-htree.rb +51 -0
  120. data/vendor/qwik/check-libxml.rb +135 -0
  121. data/vendor/qwik/check-many-pages.rb +47 -0
  122. data/vendor/qwik/check-monitor.rb +33 -0
  123. data/vendor/qwik/check-observer.rb +67 -0
  124. data/vendor/qwik/check-server.rb +61 -0
  125. data/vendor/qwik/check-uuencode.rb +33 -0
  126. data/vendor/qwik/check-webdav.rb +65 -0
  127. data/vendor/qwik/check-xml-xpath.rb +27 -0
  128. data/vendor/qwik/common-backtrace.rb +94 -0
  129. data/vendor/qwik/common-basic.rb +111 -0
  130. data/vendor/qwik/common-condition.rb +142 -0
  131. data/vendor/qwik/common-error.rb +48 -0
  132. data/vendor/qwik/common-gettext.rb +50 -0
  133. data/vendor/qwik/common-javascript.rb +45 -0
  134. data/vendor/qwik/common-notice.rb +132 -0
  135. data/vendor/qwik/common-plain.rb +105 -0
  136. data/vendor/qwik/common-plugin.rb +111 -0
  137. data/vendor/qwik/common-res.rb +76 -0
  138. data/vendor/qwik/common-resolve.rb +92 -0
  139. data/vendor/qwik/common-send.rb +171 -0
  140. data/vendor/qwik/common-session.rb +139 -0
  141. data/vendor/qwik/common-surface.rb +261 -0
  142. data/vendor/qwik/common-url.rb +90 -0
  143. data/vendor/qwik/compat/Makefile +12 -0
  144. data/vendor/qwik/compat/add_load_path.rb +1 -0
  145. data/vendor/qwik/config.rb +299 -0
  146. data/vendor/qwik/db-b-backup.rb +142 -0
  147. data/vendor/qwik/db-backup.rb +184 -0
  148. data/vendor/qwik/db-berkeley.rb +306 -0
  149. data/vendor/qwik/db-filesystem.rb +305 -0
  150. data/vendor/qwik/db-indexer.rb +154 -0
  151. data/vendor/qwik/db-searchwords.rb +238 -0
  152. data/vendor/qwik/description-ja.rb +267 -0
  153. data/vendor/qwik/description.rb +256 -0
  154. data/vendor/qwik/dev-add-copyright.rb +23 -0
  155. data/vendor/qwik/dev-backup.rb +24 -0
  156. data/vendor/qwik/dev-bench.rb +175 -0
  157. data/vendor/qwik/dev-calctime.rb +52 -0
  158. data/vendor/qwik/dev-css-compressor.rb +60 -0
  159. data/vendor/qwik/dev-extract-catalog.rb +102 -0
  160. data/vendor/qwik/dev-js-compressor.rb +73 -0
  161. data/vendor/qwik/dev-release.rb +235 -0
  162. data/vendor/qwik/dev-replace.rb +353 -0
  163. data/vendor/qwik/dev-sendmail.rb +25 -0
  164. data/vendor/qwik/farm.rb +283 -0
  165. data/vendor/qwik/gettext.rb +56 -0
  166. data/vendor/qwik/group-cond.rb +157 -0
  167. data/vendor/qwik/group-config.rb +247 -0
  168. data/vendor/qwik/group-confirm.rb +147 -0
  169. data/vendor/qwik/group-db.rb +326 -0
  170. data/vendor/qwik/group-mail.rb +195 -0
  171. data/vendor/qwik/group-member.rb +307 -0
  172. data/vendor/qwik/group-sendmail.rb +231 -0
  173. data/vendor/qwik/group-site.rb +374 -0
  174. data/vendor/qwik/group-sweep.rb +63 -0
  175. data/vendor/qwik/group.rb +157 -0
  176. data/vendor/qwik/helper.rb +6 -0
  177. data/vendor/qwik/html-generator.rb +104 -0
  178. data/vendor/qwik/html-to-wabisabi.rb +149 -0
  179. data/vendor/qwik/htree-diff.rb +87 -0
  180. data/vendor/qwik/htree-format-xml.rb +57 -0
  181. data/vendor/qwik/htree-generator.rb +144 -0
  182. data/vendor/qwik/htree-get.rb +251 -0
  183. data/vendor/qwik/htree-html-generator.rb +179 -0
  184. data/vendor/qwik/htree-template.rb +263 -0
  185. data/vendor/qwik/htree-to-wabisabi.rb +171 -0
  186. data/vendor/qwik/loadlib.rb +79 -0
  187. data/vendor/qwik/logger.rb +115 -0
  188. data/vendor/qwik/mail-body.rb +171 -0
  189. data/vendor/qwik/mail-header.rb +474 -0
  190. data/vendor/qwik/mail-multipart.rb +193 -0
  191. data/vendor/qwik/mail-parse.rb +147 -0
  192. data/vendor/qwik/mail.rb +341 -0
  193. data/vendor/qwik/mailaddress.rb +83 -0
  194. data/vendor/qwik/mdlb-model.rb +81 -0
  195. data/vendor/qwik/mdlb-sample.rb +324 -0
  196. data/vendor/qwik/ml-catalog-factory.rb +27 -0
  197. data/vendor/qwik/ml-exception.rb +15 -0
  198. data/vendor/qwik/ml-generator.rb +28 -0
  199. data/vendor/qwik/ml-gettext.rb +137 -0
  200. data/vendor/qwik/ml-logger.rb +82 -0
  201. data/vendor/qwik/ml-memory.rb +65 -0
  202. data/vendor/qwik/ml-msg-validator.rb +86 -0
  203. data/vendor/qwik/ml-processor.rb +609 -0
  204. data/vendor/qwik/ml-quickml-server.rb +122 -0
  205. data/vendor/qwik/ml-sendmail.rb +0 -0
  206. data/vendor/qwik/ml-server.rb +107 -0
  207. data/vendor/qwik/ml-session.rb +348 -0
  208. data/vendor/qwik/ml-sweeper.rb +101 -0
  209. data/vendor/qwik/mock-logger.rb +65 -0
  210. data/vendor/qwik/mock-sendmail.rb +78 -0
  211. data/vendor/qwik/mock-socket.rb +82 -0
  212. data/vendor/qwik/modulobe.rb +406 -0
  213. data/vendor/qwik/mongrel-server.rb +72 -0
  214. data/vendor/qwik/page-files.rb +249 -0
  215. data/vendor/qwik/page-generate.rb +82 -0
  216. data/vendor/qwik/page-get.rb +262 -0
  217. data/vendor/qwik/page-images.rb +168 -0
  218. data/vendor/qwik/page-put.rb +128 -0
  219. data/vendor/qwik/page-rrefs.rb +154 -0
  220. data/vendor/qwik/page-title.rb +0 -0
  221. data/vendor/qwik/page-wikidb.rb +234 -0
  222. data/vendor/qwik/page.rb +67 -0
  223. data/vendor/qwik/pages.rb +444 -0
  224. data/vendor/qwik/parse-plugin.rb +249 -0
  225. data/vendor/qwik/parser-emode.rb +116 -0
  226. data/vendor/qwik/parser-inline.rb +273 -0
  227. data/vendor/qwik/parser.rb +350 -0
  228. data/vendor/qwik/password.rb +183 -0
  229. data/vendor/qwik/periodic.rb +79 -0
  230. data/vendor/qwik/qp.rb +56 -0
  231. data/vendor/qwik/qwik-service.rb +341 -0
  232. data/vendor/qwik/qwik.rb +5 -0
  233. data/vendor/qwik/qwikweb-adduser.rb +34 -0
  234. data/vendor/qwik/qwikweb-catalog-validator.rb +110 -0
  235. data/vendor/qwik/qwikweb-incgen.rb +28 -0
  236. data/vendor/qwik/qwikweb-makesite.rb +41 -0
  237. data/vendor/qwik/qwikweb-server.rb +44 -0
  238. data/vendor/qwik/qwikweb-showpassword.rb +26 -0
  239. data/vendor/qwik/qwikweb-watchlog.rb +67 -0
  240. data/vendor/qwik/request-path.rb +304 -0
  241. data/vendor/qwik/request-ua.rb +76 -0
  242. data/vendor/qwik/request-webrick.rb +81 -0
  243. data/vendor/qwik/request.rb +91 -0
  244. data/vendor/qwik/resolve-tdiary.rb +292 -0
  245. data/vendor/qwik/resolve.rb +121 -0
  246. data/vendor/qwik/response.rb +228 -0
  247. data/vendor/qwik/server-memory.rb +57 -0
  248. data/vendor/qwik/server-webrick.rb +102 -0
  249. data/vendor/qwik/server.rb +252 -0
  250. data/vendor/qwik/site-config.rb +149 -0
  251. data/vendor/qwik/site-db.rb +136 -0
  252. data/vendor/qwik/site-event.rb +162 -0
  253. data/vendor/qwik/site-files.rb +86 -0
  254. data/vendor/qwik/site-group.rb +103 -0
  255. data/vendor/qwik/site-index.rb +47 -0
  256. data/vendor/qwik/site-log.rb +64 -0
  257. data/vendor/qwik/site-member.rb +230 -0
  258. data/vendor/qwik/site-monitor.rb +97 -0
  259. data/vendor/qwik/site-pages.rb +62 -0
  260. data/vendor/qwik/site-plan.rb +139 -0
  261. data/vendor/qwik/site-report.rb +282 -0
  262. data/vendor/qwik/site-resolve.rb +230 -0
  263. data/vendor/qwik/site-rrefs.rb +18 -0
  264. data/vendor/qwik/site-search.rb +180 -0
  265. data/vendor/qwik/site-timeline.rb +153 -0
  266. data/vendor/qwik/site-url.rb +189 -0
  267. data/vendor/qwik/site.rb +76 -0
  268. data/vendor/qwik/smil-time.rb +105 -0
  269. data/vendor/qwik/smtp-session.rb +331 -0
  270. data/vendor/qwik/template-generator.rb +149 -0
  271. data/vendor/qwik/template.rb +85 -0
  272. data/vendor/qwik/test-common.rb +10 -0
  273. data/vendor/qwik/test-ml-info.rb +225 -0
  274. data/vendor/qwik/test-module-ml.rb +142 -0
  275. data/vendor/qwik/test-module-path.rb +110 -0
  276. data/vendor/qwik/test-module-public.rb +70 -0
  277. data/vendor/qwik/test-module-server.rb +98 -0
  278. data/vendor/qwik/test-module-session.rb +264 -0
  279. data/vendor/qwik/test-module-suite.rb +91 -0
  280. data/vendor/qwik/test-ms-applemail.rb +59 -0
  281. data/vendor/qwik/test-ms-attach.rb +174 -0
  282. data/vendor/qwik/test-ms-basic.rb +40 -0
  283. data/vendor/qwik/test-ms-close.rb +35 -0
  284. data/vendor/qwik/test-ms-confirm.rb +75 -0
  285. data/vendor/qwik/test-ms-ignore-spam.rb +57 -0
  286. data/vendor/qwik/test-ms-japanese.rb +97 -0
  287. data/vendor/qwik/test-ms-jfilename.rb +82 -0
  288. data/vendor/qwik/test-ms-large.rb +58 -0
  289. data/vendor/qwik/test-ms-member.rb +103 -0
  290. data/vendor/qwik/test-ms-multipart.rb +84 -0
  291. data/vendor/qwik/test-ms-org.rb +129 -0
  292. data/vendor/qwik/test-ms-plan.rb +130 -0
  293. data/vendor/qwik/test-ms-post.rb +53 -0
  294. data/vendor/qwik/test-ms-quopri.rb +76 -0
  295. data/vendor/qwik/test-sub-quopri.rb +45 -0
  296. data/vendor/qwik/test-submit-base64.rb +59 -0
  297. data/vendor/qwik/test-submit-forward.rb +61 -0
  298. data/vendor/qwik/test-submit-html-mail.rb +52 -0
  299. data/vendor/qwik/test-submit-japanese.rb +135 -0
  300. data/vendor/qwik/test-submit-jfilename.rb +144 -0
  301. data/vendor/qwik/test-submit-uuencode.rb +71 -0
  302. data/vendor/qwik/test-suite-all.rb +8 -0
  303. data/vendor/qwik/test-suite-basic.rb +9 -0
  304. data/vendor/qwik/test-suite-ml.rb +9 -0
  305. data/vendor/qwik/test-typekey.rb +64 -0
  306. data/vendor/qwik/testunit.rb +45 -0
  307. data/vendor/qwik/tokenizer-inline.rb +294 -0
  308. data/vendor/qwik/tokenizer.rb +332 -0
  309. data/vendor/qwik/typekey.rb +160 -0
  310. data/vendor/qwik/util-basic.rb +135 -0
  311. data/vendor/qwik/util-charset.rb +332 -0
  312. data/vendor/qwik/util-css.rb +56 -0
  313. data/vendor/qwik/util-csv-tokenizer.rb +113 -0
  314. data/vendor/qwik/util-filename.rb +112 -0
  315. data/vendor/qwik/util-pathname.rb +202 -0
  316. data/vendor/qwik/util-pid.rb +58 -0
  317. data/vendor/qwik/util-safe.rb +67 -0
  318. data/vendor/qwik/util-sendmail.rb +273 -0
  319. data/vendor/qwik/util-string.rb +203 -0
  320. data/vendor/qwik/util-time.rb +125 -0
  321. data/vendor/qwik/util-webrick.rb +176 -0
  322. data/vendor/qwik/version.rb +11 -0
  323. data/vendor/qwik/wabisabi-basic.rb +163 -0
  324. data/vendor/qwik/wabisabi-diff.rb +130 -0
  325. data/vendor/qwik/wabisabi-format-xml.rb +310 -0
  326. data/vendor/qwik/wabisabi-generator.rb +262 -0
  327. data/vendor/qwik/wabisabi-index.rb +174 -0
  328. data/vendor/qwik/wabisabi-table.rb +212 -0
  329. data/vendor/qwik/wabisabi-template.rb +295 -0
  330. data/vendor/qwik/wabisabi-to-htree.rb +111 -0
  331. data/vendor/qwik/wabisabi-to-wiki.rb +690 -0
  332. data/vendor/qwik/wabisabi-traverse.rb +207 -0
  333. data/vendor/qwik/wabisabi-validator.rb +116 -0
  334. data/vendor/qwik/wabisabi.rb +5 -0
  335. metadata +416 -0
@@ -0,0 +1,193 @@
1
+ #
2
+ # Copyright (C) 2002-2004 Satoru Takabayashi <satoru@namazu.org>
3
+ # Copyright (C) 2003-2006 Kouichirou Eto
4
+ # All rights reserved.
5
+ # This is free software with ABSOLUTELY NO WARRANTY.
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of
8
+ # the GNU General Public License version 2.
9
+ #
10
+
11
+ $LOAD_PATH.unshift '..' unless $LOAD_PATH.include? '..'
12
+ require 'qwik/mail'
13
+
14
+ module QuickML
15
+ class Mail
16
+ # ==================== Multipart methods.
17
+ def multipart?
18
+ return !!boundary
19
+ end
20
+
21
+ def boundary
22
+ return Mail.boundary(self['Content-Type'])
23
+ end
24
+
25
+ def filename
26
+ return Mail.get_filename(self['Content-Disposition'])
27
+ end
28
+
29
+ def parts
30
+ return Mail.split_body(self.body, self.boundary)
31
+ end
32
+
33
+ def nuparts
34
+ boundary = self.boundary
35
+ return [self.body] if boundary.nil? || boundary.empty?
36
+ parts = @body.split(/^--#{Regexp.escape(boundary)}-*\n/)
37
+ parts.shift # Remove the first empty string.
38
+ return parts
39
+ end
40
+
41
+ def each_part(&block)
42
+ if multipart?
43
+ self.parts.each {|str|
44
+ submail = Mail.new
45
+ submail.read(str)
46
+ submail.each_part(&block) # Recursive.
47
+ }
48
+ else
49
+ yield(self)
50
+ end
51
+ end
52
+
53
+ # ==================== class method
54
+ def self.boundary(ct)
55
+ #if /^multipart\/\w+;\s*boundary=("?)(.*)\1/i =~ ct
56
+ if /^multipart\/\w+;/i =~ ct and /[\s;]boundary=("?)(.*)\1/i =~ ct
57
+ return $2
58
+ end
59
+ return nil
60
+ end
61
+
62
+ def self.split_body(body, boundary)
63
+ return [body] if boundary.nil? || boundary.empty?
64
+ parts = body.split(/^--#{Regexp.escape(boundary)}-*\n/)
65
+ parts.shift # Remove the first empty string.
66
+ parts.pop if /\A\s*\z/ =~ parts.last
67
+ return parts
68
+ end
69
+
70
+ def self.get_filename(disp)
71
+ return nil if disp.nil?
72
+ type, fdesc = disp.split(';', 2)
73
+ return nil if fdesc.nil?
74
+ fdesc = fdesc.strip
75
+ if /\Afilename=/ =~ fdesc
76
+ fdesc.sub!(/\Afilename=/, '')
77
+ fdesc.sub!(/\A\"/, '')
78
+ fdesc.sub!(/\"\z/, '')
79
+
80
+ # FIXME: It is not sure that the filename is encoded in JIS.
81
+ # FIXME: It is using nkf for decode MIME encode.
82
+ str = fdesc.set_mail_charset.to_page_charset
83
+ str = str.to_filename_charset
84
+
85
+ return str
86
+ end
87
+ return nil
88
+ end
89
+
90
+ end
91
+ end
92
+
93
+ if $0 == __FILE__
94
+ require 'qwik/testunit'
95
+ $test = true
96
+ end
97
+
98
+ if defined?($test) && $test
99
+ class TestMailMultipart < Test::Unit::TestCase
100
+ def test_class_method
101
+ c = QuickML::Mail
102
+
103
+ # test_boundary
104
+ ok_eq('b', c.boundary("multipart/mixed; boundary=\"b\""))
105
+ # ref. https://www.codeblog.org/blog/ryu/?date=20060112#p01
106
+ # Thanks to Mr. Sato.
107
+ ok_eq('b', c.boundary("multipart/signed; protocol=\"TYPE/STYPE\";
108
+ micalg=\"MICALG\"; boundary=\"b\""))
109
+
110
+ # test_split_body
111
+ ok_eq(['body'], c.split_body('body', ''))
112
+ ok_eq(["a\n", "b\n"], c.split_body('
113
+ --t
114
+ a
115
+ --t
116
+ b
117
+ ', 't'))
118
+
119
+ ok_eq(["a\n", "b\n"], c.split_body('
120
+ --t
121
+ a
122
+ --t
123
+ b
124
+ --t--
125
+ ', 't'))
126
+
127
+ ok_eq(["a\n", "b\n"], c.split_body('
128
+ --t
129
+ a
130
+ --t
131
+ b
132
+ --t--
133
+
134
+ ', 't'))
135
+
136
+ # example.
137
+ ok_eq(["a\n", "b\n"], c.split_body('
138
+ This is a multi-part message in MIME format.
139
+
140
+ ------=_NextPart_000_006A_01C5C34A.53A389F0
141
+ a
142
+ ------=_NextPart_000_006A_01C5C34A.53A389F0
143
+ b
144
+ ------=_NextPart_000_006A_01C5C34A.53A389F0--
145
+
146
+ ', '----=_NextPart_000_006A_01C5C34A.53A389F0'))
147
+
148
+ # test_get_filename
149
+ ok_eq("\e$B$\"\e(B", '��'.set_sourcecode_charset.to_mail_charset)
150
+ ok_eq('t', c.get_filename("Content-Disposition: attachment; filename=\"t\""))
151
+ ok_eq("\343\201\202", c.get_filename("Content-Disposition: attachment; filename=\"\e$B$\"\e(B\""))
152
+ ok_eq('sounds.zip', c.get_filename("Content-Disposition: attachment;
153
+ filename=sounds.zip"))
154
+ # $KCODE = 's'
155
+ ok_eq('17fy�\�Z�R�[�h�̎w��ɂ‚���.doc'.set_sourcecode_charset.to_filename_charset,
156
+ c.get_filename('Content-Disposition: attachment;
157
+ filename="=?ISO-2022-JP?B?MTdmeRskQk09OzslMyE8JUkkTjtYRGokSxsoQg==?=
158
+ =?ISO-2022-JP?B?GyRCJEQkJCRGGyhCLmRvYw==?="'))
159
+ ok_eq('��񗬃f�U�C���O���[�v.xls'.set_sourcecode_charset.to_filename_charset,
160
+ c.get_filename('Content-Disposition: attachment;
161
+ filename="=?ISO-2022-JP?B?GyRCPnBKc04uJUclNiUkJXMlMCVrITwlVxsoQg==?=
162
+ =?ISO-2022-JP?B?Lnhscw==?="'))
163
+ end
164
+
165
+ def test_all
166
+ mail = QuickML::Mail.new
167
+
168
+ # test_plain
169
+ mail.body = 'body'
170
+ ok_eq(['body'], mail.parts) # test_parts
171
+ ok_eq(false, mail.multipart?) # test_multipart?
172
+
173
+ # test_multi_part
174
+ mail['Content-Type'] = "multipart/mixed; boundary=\"b\""
175
+ ok_eq(true, mail.multipart?) # test_multipart?
176
+ ok_eq('b', mail.boundary) # test_boundary
177
+ ok_eq([], mail.parts) # test_parts
178
+
179
+ mail.body = '--b
180
+ 1
181
+ --b
182
+ 2
183
+ --b-
184
+ '
185
+ ok_eq(["1\n", "2\n"], mail.parts) # test_parts
186
+
187
+ # test_each_part
188
+ mail.each_part {|mail|
189
+ assert_match(/\A\d\n\z/, mail.bare)
190
+ }
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,147 @@
1
+ #
2
+ # Copyright (C) 2002-2004 Satoru Takabayashi <satoru@namazu.org>
3
+ # Copyright (C) 2003-2006 Kouichirou Eto
4
+ # All rights reserved.
5
+ # This is free software with ABSOLUTELY NO WARRANTY.
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of
8
+ # the GNU General Public License version 2.
9
+ #
10
+
11
+ $LOAD_PATH.unshift '..' unless $LOAD_PATH.include? '..'
12
+ require 'qwik/mail'
13
+
14
+ module QuickML
15
+ class Mail
16
+ # Construct a mail from a mail string.
17
+ def read (string)
18
+ @bare = string || ''
19
+
20
+ header, body = @bare.split(/\n\n/, 2)
21
+ @body = body || ''
22
+
23
+ attr = nil
24
+ header.split("\n").each {|line|
25
+ line = line.xchomp
26
+ if /^(\S+):\s*(.*)/ =~ line
27
+ attr = $1
28
+ push_field(attr, $2)
29
+ elsif attr
30
+ concat_field(line)
31
+ end
32
+ }
33
+ @charset = Mail.get_charset(self['Content-Type'])
34
+ @content_type = Mail.get_content_type(self['Content-Type'])
35
+ end
36
+
37
+ def store_addresses
38
+ @mail_from = self.from
39
+ (self.collect_to + self.collect_cc).each {|addr|
40
+ self.add_recipient(addr)
41
+ }
42
+ end
43
+
44
+ # Create a new mail
45
+ def self.create
46
+ mail = Mail.new
47
+ mail.read(yield)
48
+ mail.store_addresses
49
+ return mail
50
+ end
51
+
52
+ # Generate a mail for test.
53
+ def self.generate
54
+ mail = Mail.new
55
+ mail.read(yield.set_sourcecode_charset.to_mail_charset)
56
+ mail.store_addresses
57
+ return mail
58
+ end
59
+
60
+ private
61
+
62
+ def push_field (key, value)
63
+ # Use Array for preserving order of the header
64
+ field = [key, value]
65
+ @header.push(field)
66
+ end
67
+
68
+ def concat_field (value)
69
+ lastfield = @header.last
70
+ @header.pop
71
+ push_field(lastfield.first, lastfield.last + "\n" + value)
72
+ end
73
+ end
74
+ end
75
+
76
+ if $0 == __FILE__
77
+ require 'qwik/testunit'
78
+ $test = true
79
+ end
80
+
81
+ if defined?($test) && $test
82
+ class TestMailGenerate < Test::Unit::TestCase
83
+ def test_all
84
+ str = 'Date: Mon, 3 Feb 2001 12:34:56 +0900
85
+ From: "Test User" <user@e.com>
86
+ To: "Test Mailing List" <test@example.com>
87
+ Subject: Re: [test:1] Test Mail
88
+
89
+ This is a test.
90
+ '
91
+ # test_read
92
+ mail = QuickML::Mail.new
93
+ mail.read(str)
94
+
95
+ # test_bare
96
+ ok_eq(str, mail.bare)
97
+
98
+ # test_body
99
+ ok_eq("This is a test.\n", mail.body)
100
+
101
+ # test_charset
102
+ ok_eq(nil, mail.charset)
103
+
104
+ # test_content_type
105
+ ok_eq(nil, mail.content_type)
106
+
107
+ # test_from
108
+ ok_eq('user@e.com', mail.from)
109
+
110
+ # test_header
111
+ header = nil
112
+ mail.instance_eval {
113
+ header = @header
114
+ }
115
+ ok_eq([['Date', 'Mon, 3 Feb 2001 12:34:56 +0900'],
116
+ ['From', "\"Test User\" <user@e.com>"],
117
+ ['To', "\"Test Mailing List\" <test@example.com>"],
118
+ ['Subject', 'Re: [test:1] Test Mail']],
119
+ header)
120
+ end
121
+
122
+ def test_create
123
+ str = 'Date: Mon, 3 Feb 2001 12:34:56 +0900
124
+ From: "Test User" <user@e.com>
125
+ To: "Test Mailing List" <test@example.com>
126
+ Subject: Re: [test:1] Test Mail
127
+
128
+ ��
129
+ '
130
+ mail = QuickML::Mail.create { str }
131
+ ok_eq("\202\240\n", mail.body)
132
+ end
133
+
134
+ def test_generate
135
+ str = 'Date: Mon, 3 Feb 2001 12:34:56 +0900
136
+ From: "Test User" <user@e.com>
137
+ To: "Test Mailing List" <test@example.com>
138
+ Subject: Re: [test:1] Test Mail
139
+
140
+ ��
141
+ '
142
+ mail = QuickML::Mail.generate { str }
143
+ ok_eq("\e$B$\"\e(B\n", mail.body)
144
+ end
145
+
146
+ end
147
+ end
@@ -0,0 +1,341 @@
1
+ #
2
+ # Copyright (C) 2002-2004 Satoru Takabayashi <satoru@namazu.org>
3
+ # Copyright (C) 2003-2006 Kouichirou Eto
4
+ # All rights reserved.
5
+ # This is free software with ABSOLUTELY NO WARRANTY.
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of
8
+ # the GNU General Public License version 2.
9
+ #
10
+
11
+ $LOAD_PATH.unshift '..' unless $LOAD_PATH.include? '..'
12
+ require 'qwik/mail-parse'
13
+ require 'qwik/mail-header'
14
+ require 'qwik/mail-body'
15
+ require 'qwik/util-string'
16
+
17
+ module QuickML
18
+ class Mail
19
+ def initialize
20
+ @mail_from = nil
21
+ @recipients = []
22
+ @header = []
23
+ @body = ''
24
+ @charset = nil
25
+ @content_type = nil
26
+ @bare = nil
27
+ end
28
+
29
+ attr_accessor :mail_from
30
+ attr_reader :recipients
31
+ attr_accessor :body
32
+ attr_reader :charset
33
+ attr_reader :content_type
34
+ attr_accessor :bare
35
+ end
36
+ end
37
+
38
+ # TODO: Make special mode for Mr. Kaoru Misaki.
39
+ # Use the first line of the body as a subject.
40
+
41
+ if $0 == __FILE__
42
+ require 'qwik/testunit'
43
+ $test = true
44
+ end
45
+
46
+ if defined?($test) && $test
47
+ class TestMail < Test::Unit::TestCase
48
+ def gen_mail(&b)
49
+ return QuickML::Mail.generate(&b)
50
+ end
51
+
52
+ def test_basic
53
+ str = 'Date: Mon, 3 Feb 2001 12:34:56 +0900
54
+ From: "Test User" <user@e.com>
55
+ To: "Test Mailing List" <test@example.com>
56
+ Subject: Re: [test:1] Test Mail
57
+
58
+ This is a test.
59
+ '
60
+ mail = gen_mail { str }
61
+
62
+ # test_accessor
63
+ eq 'user@e.com', mail.mail_from
64
+ eq ['test@example.com'], mail.recipients
65
+ eq "This is a test.\n", mail.body
66
+ eq str, mail.bare
67
+
68
+ # test_to_s
69
+ eq str, mail.to_s
70
+
71
+ # test_looping?
72
+ eq false, mail.looping?
73
+
74
+ # test_from
75
+ eq 'user@e.com', mail.from
76
+
77
+ # test_collect
78
+ eq [], mail.collect_cc
79
+ eq ['test@example.com'], mail.collect_to
80
+
81
+ # test_decoded_body
82
+ eq "This is a test.\n", mail.decoded_body
83
+
84
+ # test_get_body
85
+ eq "This is a test.\n", mail.get_body
86
+
87
+ # test_parts
88
+ eq ["This is a test.\n"], mail.parts
89
+
90
+ eq nil, mail.filename # test_filename
91
+ assert(['test@example.com'], mail.valid?) # test_valid?
92
+ eq nil, mail.boundary # test_boundary
93
+ eq false, mail.multipart? # test_multipart?
94
+
95
+ # test_each_part
96
+ mail.each_part {|mail|
97
+ assert_instance_of(QuickML::Mail, mail)
98
+ }
99
+ end
100
+
101
+ def test_multipart
102
+ mail = gen_mail {
103
+ "Date: Mon, 3 Feb 2001 12:34:56 +0900
104
+ From: Test User <user@e.com>
105
+ To: test@example.com
106
+ Cc: guest@example.com
107
+ Subject: multipart test
108
+ MIME-Version: 1.0
109
+ Content-Type: multipart/mixed; boundary=\"boundary\"
110
+ Content-Transfer-Encoding: 7bit
111
+
112
+ --boundary
113
+ Content-Type: text/plain; charset=\"ascii\"
114
+ Content-Transfer-Encoding: 7bit
115
+
116
+ body1
117
+
118
+ --boundary
119
+ Content-Type: text/plain; charset=\"ascii\"
120
+ Content-Transfer-Encoding: 7bit
121
+
122
+ body2
123
+
124
+ --boundary--
125
+ " }
126
+
127
+ # test_accessor
128
+ eq ['test@example.com', 'guest@example.com'], mail.recipients
129
+
130
+ # test_collect
131
+ eq ['guest@example.com'], mail.collect_cc
132
+
133
+ # test_get_body
134
+ eq "body1\nbody2\n", mail.get_body
135
+
136
+ # test_parts
137
+ eq ["Content-Type: text/plain; charset=\"ascii\"
138
+ Content-Transfer-Encoding: 7bit
139
+
140
+ body1
141
+
142
+ ", "Content-Type: text/plain; charset=\"ascii\"
143
+ Content-Transfer-Encoding: 7bit
144
+
145
+ body2
146
+
147
+ "], mail.parts
148
+
149
+ # test_parts
150
+ mail0 = QuickML::Mail.new
151
+ mail0.read(mail.parts[0])
152
+ eq "body1\n\n", mail0.body
153
+
154
+ mail1 = QuickML::Mail.new
155
+ mail1.read(mail.parts[1])
156
+ eq "body2\n\n", mail1.body
157
+
158
+ # test_multipart
159
+ eq true, mail.multipart? # test_multipart?
160
+ eq 'boundary', mail.boundary # test_boundary
161
+
162
+ # test_multipart_alternative
163
+ mail['Content-Type'] = "multipart/alternative; boundary=\"b\""
164
+ mail.instance_eval {
165
+ @content_type = QuickML::Mail.get_content_type(self['Content-Type'])
166
+ }
167
+ eq 'multipart/alternative', mail.content_type
168
+ eq "multipart/alternative; boundary=\"b\"",
169
+ mail['Content-Type']
170
+ eq true, mail.multipart? # test_multipart?
171
+ eq 'b', mail.boundary # test_boundary
172
+ end
173
+
174
+ def test_mail_with_image
175
+ mail = gen_mail {
176
+ "Date: Mon, 3 Feb 2001 12:34:56 +0900
177
+ From: Test User <user@e.com>
178
+ To: test@example.com
179
+ Cc: guest@example.com
180
+ Subject: Attach Test
181
+ MIME-Version: 1.0
182
+ Content-Type: multipart/mixed; boundary=\"------_410DDC04C7AD046D3600_MULTIPART_MIXED_\"
183
+ Content-Transfer-Encoding: 7bit
184
+
185
+ --------_410DDC04C7AD046D3600_MULTIPART_MIXED_
186
+ Content-Type: text/plain; charset='ascii'
187
+ Content-Transfer-Encoding: 7bit
188
+
189
+ Test with image.
190
+
191
+ --------_410DDC04C7AD046D3600_MULTIPART_MIXED_
192
+ Content-Type: image/png; name=\"1x1.png\"
193
+ Content-Disposition: attachment;
194
+ filename=\"1x1.png\"
195
+ Content-Transfer-Encoding: base64
196
+
197
+ iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4//8/AAX+Av4zEpUU
198
+ AAAAAElFTkSuQmCC
199
+
200
+ --------_410DDC04C7AD046D3600_MULTIPART_MIXED_--
201
+ " }
202
+
203
+ # test_get_body
204
+ eq "Test with image.\n", mail.get_body
205
+
206
+ # test_parts
207
+ mail0 = QuickML::Mail.new
208
+ mail0.read(mail.parts[0])
209
+ eq 'text/plain', mail0.content_type
210
+ eq "Test with image.\n\n", mail0.body
211
+
212
+ mail1 = QuickML::Mail.new
213
+ mail1.read(mail.parts[1])
214
+ eq 'image/png', mail1.content_type
215
+ eq "attachment;
216
+ filename=\"1x1.png\"",
217
+ mail1['Content-Disposition']
218
+ eq '1x1.png', mail1.filename
219
+ eq 'base64', mail1['Content-Transfer-Encoding']
220
+ eq "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4//8/AAX+Av4zEpUU\nAAAAAElFTkSuQmCC\n\n", mail1.body
221
+ eq "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\000\001\000\000\000\001\010\002\000\000\000\220wS\336\000\000\000\fIDATx\332c\370\377\377?\000\005\376\002\3763\022\225\024\000\000\000\000IEND\256B`\202", mail1.decoded_body
222
+
223
+ eq nil, mail.parts[2]
224
+ end
225
+
226
+ def test_inline_disposition
227
+ mail = gen_mail {
228
+ "Date: Mon, 3 Feb 2001 12:34:56 +0900
229
+ From: user@e.com
230
+ To: test@example.com
231
+ Subject: This is an inline test.
232
+ MIME-Version: 1.0 (generated by SEMI 1.14.4 - Hosorogi)
233
+ Content-Type: multipart/mixed;
234
+ boundary=\"Multipart_Thu_Apr_14_21:22:30_2005-1\"
235
+
236
+ --Multipart_Thu_Apr_14_21:22:30_2005-1
237
+ Content-Type: text/plain; charset=ISO-2022-JP
238
+
239
+ I attached sample.jpg.
240
+ --Multipart_Thu_Apr_14_21:22:30_2005-1
241
+ Content-Type: image/jpeg
242
+ Content-Disposition: inline; filename=\"sample.jpg\"
243
+ Content-Transfer-Encoding: base64
244
+
245
+ iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4//8/AAX+Av4zEpUU
246
+ AAAAAElFTkSuQmCC
247
+
248
+ " }
249
+ mail1 = QuickML::Mail.new
250
+ mail1.read(mail.parts[1])
251
+ eq "inline; filename=\"sample.jpg\"", mail1['Content-Disposition']
252
+ eq 'sample.jpg', mail1.filename
253
+ end
254
+
255
+ def test_apple_mail
256
+ mail = gen_mail {
257
+ "Date: Mon, 3 Feb 2001 12:34:56 +0900
258
+ From: Test User <user@e.com>
259
+ To: test@example.com
260
+ Cc: guest@example.com
261
+ Subject: Apple Mail
262
+ Mime-Version: 1.0 (Apple Message framework v623)
263
+ Content-Type: multipart/mixed; boundary=Apple-Mail-1-134582006
264
+
265
+ --Apple-Mail-1-134582006
266
+ Content-Transfer-Encoding: 7bit
267
+ Content-Type: text/plain;
268
+ charset=ISO-2022-JP;
269
+ format=flowed
270
+
271
+ I attach a file using Apple Mail.
272
+ --Apple-Mail-1-134582006
273
+ Content-Transfer-Encoding: base64
274
+ Content-Type: application/zip;
275
+ x-mac-type=5A495020;
276
+ x-unix-mode=0755;
277
+ x-mac-creator=53495421;
278
+ name='sounds.zip'
279
+ Content-Disposition: attachment;
280
+ filename=sounds.zip
281
+
282
+ iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4//8/AAX+Av4zEpUU
283
+ AAAAAElFTkSuQmCC
284
+
285
+ --Apple-Mail-1-134582006--
286
+ " }
287
+
288
+ # test_get_body
289
+ eq "I attach a file using Apple Mail.\n", mail.get_body
290
+
291
+ # test_parts
292
+ mail0 = QuickML::Mail.new
293
+ mail0.read(mail.parts[0])
294
+ eq 'text/plain', mail0.content_type
295
+ eq "I attach a file using Apple Mail.\n", mail0.body
296
+
297
+ mail1 = QuickML::Mail.new
298
+ mail1.read(mail.parts[1])
299
+ eq 'application/zip', mail1.content_type
300
+ eq "attachment;\n\tfilename=sounds.zip", mail1['Content-Disposition']
301
+ eq 'sounds.zip', mail1.filename
302
+ end
303
+ end
304
+
305
+ class TestMLMailJapanese < Test::Unit::TestCase
306
+ def gen_mail(&b)
307
+ return QuickML::Mail.generate(&b)
308
+ end
309
+
310
+ def test_jmail
311
+ str =
312
+ 'Date: Mon, 3 Feb 2001 12:34:56 +0900
313
+ From: "Test User" <user@e.com>
314
+ To: "Test Mailing List" <test@example.com>
315
+ Subject: Re: [test:1] �e�X�g
316
+
317
+ ����̓e�X�g�ł��B
318
+ '
319
+ mail = gen_mail { str }
320
+ eq "����̓e�X�g�ł��B\n".set_sourcecode_charset.to_mail_charset, mail.body
321
+ eq str.set_sourcecode_charset.to_mail_charset, mail.bare
322
+ eq "Re: [test:1] �e�X�g ".set_sourcecode_charset.to_mail_charset, mail['Subject']
323
+ eq "����̓e�X�g�ł��B\n".set_sourcecode_charset.to_mail_charset, mail.get_body
324
+ end
325
+
326
+ def test_for_confirm
327
+ str = 'To: test@example.com
328
+ From: bob@example.net
329
+ Subject: test
330
+
331
+ test
332
+ '
333
+ mail = gen_mail { str }
334
+
335
+ # test_accessor
336
+ eq 'bob@example.net', mail.mail_from
337
+ eq ['test@example.com'], mail.recipients
338
+ eq "test\n", mail.body
339
+ end
340
+ end
341
+ end