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,195 @@
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/group'
13
+
14
+ module QuickML
15
+ class Group
16
+ private
17
+
18
+ def rewrite_body (mail)
19
+ # body header
20
+ header = generate_header(@address, @added_members) if member_added?
21
+
22
+ # body footer
23
+ footer = generate_footer
24
+
25
+ if mail.multipart?
26
+ parts = mail.parts
27
+ sub_mail = Mail.new
28
+ sub_mail.read(parts.first)
29
+ cte = sub_mail['Content-Transfer-Encoding']
30
+ if sub_mail.content_type == 'text/plain' and cte.nil? or cte.empty? or cte =~ /^[78]bit$/
31
+ sub_mail.body = header + sub_mail.body if header
32
+ sub_mail.body += footer
33
+ end
34
+ parts[0] = sub_mail.to_s
35
+ mail.body = Mail.join_parts(parts, mail.boundary)
36
+ return mail.body
37
+ end
38
+
39
+ cte = mail['Content-Transfer-Encoding']
40
+ if mail.plain_text_body? and cte.nil? or cte.empty? or cte =~ /^[78]bit$/
41
+ mail.body = header + mail.body if header
42
+ mail.body += footer
43
+ return mail.body
44
+ end
45
+
46
+ return mail.body # abandon
47
+ end
48
+
49
+ def generate_header(address, added_members)
50
+ header = "ML: #{address}\n"
51
+ header << generate_new_member_list(added_members)
52
+ header << "\n"
53
+ return header
54
+ end
55
+
56
+ def generate_new_member_list(added_members)
57
+ return added_members.map {|address|
58
+ _("New Member: %s\n", MailAddress.obfuscate(address))
59
+ }.join
60
+ end
61
+
62
+ def generate_footer(member_list_p = false)
63
+ pu = page_url
64
+ sf = site_footer
65
+
66
+ footer = ''
67
+ footer << "\n-- \n"
68
+ footer << _('archive')+"-> " + pu + " \n"
69
+ footer << "ML-> #{@address}\n"
70
+ if sf && ! sf.empty?
71
+ footer << "\n" + sf
72
+ end
73
+ if member_added?
74
+ footer << generate_unsubscribe_info(@address)
75
+ end
76
+ if member_added? || member_list_p
77
+ footer << "\n" + generate_member_list(@address, @members.list)
78
+ end
79
+ if total_file_size_exceeded?
80
+ footer << generate_total_file_size_exceeded_info
81
+ elsif total_file_size_reaching?
82
+ footer << generate_total_file_size_reaching_info
83
+ end
84
+ return footer
85
+ end
86
+
87
+ def generate_unsubscribe_info(address)
88
+ return "\n" +
89
+ _("How to unsubscribe from the ML:\n") +
90
+ _("- Just send an empty message to <%s>.\n", address) +
91
+ _("- Alternatively, if you cannot send an empty message for some reason,\n") +
92
+ _(" please send a message just saying 'unsubscribe' to <%s>.\n", address) +
93
+ _(" (e.g., hotmail's advertisement, signature, etc.)\n") #'
94
+ end
95
+
96
+ def generate_member_list(address, list)
97
+ return _("Members of <%s>:\n", address) + list + "\n"
98
+ end
99
+
100
+ def generate_total_file_size_exceeded_info
101
+ return "\n" +
102
+ _('WARNING: Total attached file size exceeded.') + " " +
103
+ _('Files are not attached on the web.') + "\n"
104
+ end
105
+
106
+ def generate_total_file_size_reaching_info
107
+ return "\n" +
108
+ _("WARNING: Total attached file size is reaching to the limit.") +
109
+ " " +
110
+ _("%s left", (@config[:max_total_file_size] - @site.files_total).byte_format) +
111
+ "\n"
112
+ end
113
+
114
+ end
115
+ end
116
+
117
+ if $0 == __FILE__
118
+ require 'qwik/test-module-ml'
119
+ $test = true
120
+ end
121
+
122
+ if defined?($test) && $test
123
+ class TestGroupMail < Test::Unit::TestCase
124
+ include TestModuleML
125
+
126
+ def setup_group
127
+ return QuickML::Group.new(@ml_config, 'test@example.com')
128
+ end
129
+
130
+ def test_all
131
+ group = setup_group
132
+
133
+ # test_generate_header
134
+ t_make_public(QuickML::Group, :generate_header)
135
+ ok_eq("ML: test@example.com\n\n",
136
+ group.generate_header('test@example.com', []))
137
+ ok_eq("ML: test@example.com\nNew Member: user@e...\n\n",
138
+ group.generate_header('test@example.com', ['user@example.net']))
139
+
140
+ # test_generate_footer
141
+ t_make_public(QuickML::Group, :generate_footer)
142
+ ok_eq("
143
+ --
144
+ archive-> http://example.com/test/
145
+ ML-> test@example.com
146
+ ",
147
+ group.generate_footer)
148
+
149
+ # test_generate_member_list
150
+ t_make_public(QuickML::Group, :generate_member_list)
151
+ ok_eq("Members of <test@example.com>:\nlist\n",
152
+ group.generate_member_list('test@example.com', 'list'))
153
+
154
+ # test_generate_unsubscribe_info
155
+ t_make_public(QuickML::Group, :generate_unsubscribe_info)
156
+ ok_eq("\nHow to unsubscribe from the ML:\n- Just send an empty message to <test@example.com>.\n- Alternatively, if you cannot send an empty message for some reason,\n please send a message just saying 'unsubscribe' to <test@example.com>.\n (e.g., hotmail's advertisement, signature, etc.)\n",
157
+ group.generate_unsubscribe_info('test@example.com'))
158
+
159
+ end
160
+
161
+ def test_footer_with_file_limits
162
+ group = setup_group
163
+
164
+ t_make_readable(QuickML::Group,:groupsite)
165
+ groupsite = group.groupsite
166
+
167
+ t_make_writable(QuickML::GroupSite,:total_file_size_exceeded)
168
+ t_make_writable(QuickML::GroupSite,:total_file_size_reaching)
169
+
170
+ # test if generate_footer generates warning message
171
+ # when total file size exceeded
172
+ groupsite.total_file_size_exceeded = true
173
+ ok_eq("
174
+ --
175
+ archive-> http://example.com/test/
176
+ ML-> test@example.com
177
+
178
+ WARNING: Total attached file size exceeded. Files are not attached on the web.
179
+ " , group.generate_footer)
180
+
181
+ # test if generate_footer generates warning message
182
+ # when total file size reaching to the limit
183
+ groupsite.total_file_size_exceeded = false
184
+ groupsite.total_file_size_reaching = true
185
+ ok_eq("
186
+ --
187
+ archive-> http://example.com/test/
188
+ ML-> test@example.com
189
+
190
+ WARNING: Total attached file size is reaching to the limit. #{(@config[:max_total_file_size]-@site.files.total).byte_format} left
191
+ ", group.generate_footer)
192
+
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,307 @@
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/group'
13
+
14
+ module QuickML
15
+ class Group
16
+ def active_members_include?(address)
17
+ return @members.active_include?(address)
18
+ end
19
+
20
+ def former_members_include?(address)
21
+ return @members.former_include?(address)
22
+ end
23
+
24
+ def add_member (address)
25
+ if Group.exclude?(address, @config.ml_domain)
26
+ @logger.vlog "Excluded: #{address}"
27
+ return
28
+ end
29
+ return if @members.active_include?(address) # Already included.
30
+ @members.add_member(address)
31
+ @added_members.push(address)
32
+ @logger.log "[#{@name}]: Add: #{address}"
33
+ end
34
+
35
+ def self.exclude?(address, config_domain)
36
+ name, domain = address.split('@')
37
+ return true if domain.nil?
38
+ return Mail.address_of_domain?(address, config_domain)
39
+ end
40
+
41
+ def remove_member (address)
42
+ return if ! @members.active_include?(address)
43
+ @members.remove_member(address)
44
+ @logger.log "[#{@name}]: Remove: #{address}"
45
+ close if @members.active_empty?
46
+ end
47
+
48
+ def add_error_member (address)
49
+ return if ! @members.active_include?(address)
50
+ prev_count = @members.error_count(address)
51
+ count = @members.inc_error_count(address)
52
+ if prev_count == count
53
+ @logger.log "[#{@name}]: AddError: #{address} (not counted)"
54
+ else
55
+ @logger.log "[#{@name}]: AddError: #{address} #{count}"
56
+ end
57
+ @members.save
58
+
59
+ if @group_config[:auto_unsubscribe_count] <= @members.error_count(address)
60
+ remove_member(address)
61
+ report_removed_member(address)
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def reset_error_member (address)
68
+ return unless @members.error_include?(address)
69
+ @members.error_delete(address)
70
+ @logger.log "[#{@name}]: ResetError: #{address}"
71
+ @members.save
72
+ end
73
+
74
+ def init_members
75
+ @members = GroupMembers.new(@config, self, @db, @group_config)
76
+ end
77
+
78
+ def member_added?
79
+ return ! @added_members.empty?
80
+ end
81
+
82
+ def get_active_members
83
+ return @members.get_active
84
+ end
85
+ end
86
+
87
+ class GroupMembers
88
+ def initialize(config, group, db, group_config)
89
+ @config = config
90
+ @group = group
91
+ @db = db
92
+ @group_config = group_config
93
+
94
+ @active = IcaseArray.new
95
+ @former = IcaseArray.new
96
+ @error = IcaseHash.new
97
+
98
+ load
99
+ end
100
+
101
+ def save
102
+ str = GroupMembers.generate(@active, @former, @error)
103
+ @db.put(:Members, str)
104
+ end
105
+
106
+ def add_member(address)
107
+ raise TooManyMembers if too_many?
108
+ former_delete(address)
109
+ active_push(address)
110
+ save
111
+ end
112
+
113
+ def remove_member(address)
114
+ active_delete(address)
115
+ former_push(address)
116
+ error_delete(address)
117
+ save
118
+ end
119
+
120
+ # active
121
+ def get_active
122
+ return @active
123
+ end
124
+ def active_empty?
125
+ return @active.empty?
126
+ end
127
+ def active_include?(address)
128
+ return @active.include?(address)
129
+ end
130
+ def active_push(address)
131
+ @active.push(address)
132
+ end
133
+ def active_delete(address)
134
+ @active.delete(address)
135
+ end
136
+
137
+ # former
138
+ def former_include?(address)
139
+ return @former.include?(address)
140
+ end
141
+ def former_push(address)
142
+ @former.push(address)
143
+ end
144
+ def former_delete(address)
145
+ @former.delete(address)
146
+ end
147
+
148
+ # error
149
+ def error_include?(address)
150
+ return @error.include?(address)
151
+ end
152
+ def error_delete(address)
153
+ @error.delete(address)
154
+ end
155
+
156
+ # Old methods.
157
+ def too_many?
158
+ return false if @group_config.unlimited?
159
+ return @group_config[:max_members] <= @active.length
160
+ end
161
+
162
+ def list
163
+ return @active.map {|x| MailAddress.obfuscate(x) }.join("\n")
164
+ end
165
+
166
+ def inc_error_count (address)
167
+ if ! @error.include?(address)
168
+ @error[address] = ErrorInfo.new
169
+ end
170
+ if ! allowable_error_interval?(@error[address].last_error_time)
171
+ @error[address].inc_count
172
+ end
173
+ @error[address].count
174
+ end
175
+
176
+ def error_count (address)
177
+ return @error[address].count if @error.include?(address)
178
+ return 0
179
+ end
180
+
181
+ private
182
+
183
+ def load
184
+ content = @db.get(:Members) || ''
185
+ GroupMembers.parse(@active, @former, @error, content)
186
+ end
187
+
188
+ def self.parse(active, former, error, content)
189
+ content.each {|line|
190
+ line.chomp!
191
+ next if line.empty?
192
+ if /^# (.*)/ =~ line # removed address
193
+ former.push($1) if ! former.include?($1)
194
+ elsif /^; (.*?) (\d+)(?: (\d+))?/ =~ line
195
+ address = $1
196
+ count= $2.to_i
197
+ last_error_time = if $3 then Time.at($3.to_i) else Time.at(0) end
198
+ error[address]= ErrorInfo.new(count, last_error_time)
199
+ else
200
+ active.push(line) if ! active.include?(line)
201
+ end
202
+ }
203
+ end
204
+
205
+ def self.generate(active, former, error)
206
+ c = ''
207
+ active.each {|address| c << address+"\n" }
208
+ former.each {|address| c << "# "+address+"\n" }
209
+ error.each {|address, error_info|
210
+ t = error_info.last_error_time.to_i
211
+ c << "; #{address} #{error_info.count} #{t}\n"
212
+ }
213
+ return c
214
+ end
215
+
216
+ def allowable_error_interval? (time)
217
+ now = Time.now
218
+ past = now - @config.allowable_error_interval
219
+ return past < time && time <= now
220
+ end
221
+ end
222
+
223
+ class ErrorInfo
224
+ def initialize (count = 0, last_error_time = Time.at(0))
225
+ @count = count
226
+ @last_error_time = last_error_time
227
+ end
228
+ attr_reader :count
229
+ attr_reader :last_error_time
230
+
231
+ def inc_count
232
+ @count += 1
233
+ t = Time.now
234
+ t = Time.at(0) if defined?($test) && $test
235
+ @last_error_time = t
236
+ end
237
+ end
238
+ end
239
+
240
+ if $0 == __FILE__
241
+ require 'qwik/test-module-ml'
242
+ $test = true
243
+ end
244
+
245
+ if defined?($test) && $test
246
+ class TestGroup_members < Test::Unit::TestCase
247
+ include TestModuleML
248
+
249
+ def setup_group
250
+ return QuickML::Group.new(@ml_config, 'test@example.com')
251
+ end
252
+
253
+ def test_class_method
254
+ c = QuickML::Group
255
+
256
+ # test_exclude?
257
+ ok_eq(true, c.exclude?('user', 'example.net'))
258
+ ok_eq(true, c.exclude?('user@example.net', 'example.net'))
259
+ ok_eq(false, c.exclude?('user@example.com', 'example.net'))
260
+ end
261
+
262
+ end
263
+
264
+ class TestGroupMembers < Test::Unit::TestCase
265
+ include TestModuleML
266
+
267
+ def setup_group
268
+ return QuickML::Group.new(@ml_config, 'test@example.com')
269
+ end
270
+
271
+ def test_class_method
272
+ c = QuickML::GroupMembers
273
+
274
+ # test_generate
275
+ ok_eq('', c.generate([], [], []))
276
+
277
+ # test_parse
278
+ active, former, error = [], [], []
279
+ c.parse(active, former, error, "\n")
280
+ eq([[], [], []], [active, former, error])
281
+ end
282
+
283
+ def test_all
284
+ group = setup_group # init_members is already called here.
285
+
286
+ t_make_readable(QuickML::Group, :members)
287
+ members = group.members
288
+
289
+ members.save
290
+
291
+ t_make_readable(QuickML::Group, :db)
292
+ ok_eq(true, group.db.exist?(:Members))
293
+ ok_eq('', group.db.get(:Members))
294
+
295
+ group.add_member('user@e.com')
296
+ str = group.db.get(:Members)
297
+ ok_eq("user@e.com\n", str)
298
+
299
+ group.add_error_member('user@e.com')
300
+ str = group.db.get(:Members)
301
+ ok_eq("user@e.com\n; user@e.com 1 0\n", str)
302
+
303
+ ok_eq(true, group.db.exist?(:Members))
304
+ group.remove_member('user@e.com')
305
+ end
306
+ end
307
+ end