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,231 @@
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
+ require 'qwik/util-sendmail'
14
+ require 'qwik/util-basic'
15
+
16
+ module QuickML
17
+ class Group
18
+ def report_ml_close_soon
19
+ return if @members.active_empty?
20
+
21
+ name = @name
22
+
23
+ subject = Mail.encode_field(_("[%s] ML will be closed soon", name))
24
+
25
+ header = [
26
+ ['To', @address],
27
+ ['From', @address],
28
+ ['Subject', subject],
29
+ ['Reply-To', @address],
30
+ ['Content-Type', content_type]
31
+ ]
32
+ header.concat(quickml_fields)
33
+
34
+ time_to_close = @db.last_article_time + @group_config[:ml_life_time]
35
+ ndays = ((time_to_close - Time.now) / 86400.0).ceil
36
+ datefmt = __('%Y-%m-%d %H:%M')
37
+
38
+ body = _("ML will be closed if no article is posted for %d days.\n\n",
39
+ ndays)
40
+ body << _("Time to close: %s.\n\n", time_to_close.strftime(datefmt))
41
+ body << generate_footer(true)
42
+
43
+ mail = {
44
+ :mail_from => '',
45
+ :recipient => get_active_members,
46
+ :header => header,
47
+ :body => body,
48
+ }
49
+ Sendmail(@config.smtp_host, @config.smtp_port, @logger, mail)
50
+ @logger.log "[#{@name}]: Alert: ML will be closed soon"
51
+ close_alertedp_file
52
+ end
53
+
54
+ def submit (mail)
55
+ #p 'ml.submit ' if $ml_debug
56
+
57
+ return if @members.active_empty?
58
+
59
+ if @group_config[:max_mail_length] < mail.body.length
60
+ report_too_large_mail(mail)
61
+ @logger.log "[#{@name}]: Too Large Mail: #{mail.from}"
62
+ return
63
+ end
64
+
65
+ reset_error_member(mail.from)
66
+ start_time = Time.now
67
+ _submit(mail)
68
+ elapsed = Time.now - start_time
69
+ msg = "[#{@name}:#{@count}]: Send:"
70
+ msg += " #{@config.smtp_host} #{elapsed} sec." if ! $test
71
+ @logger.log msg
72
+ end
73
+
74
+ private
75
+
76
+ def _submit(mail)
77
+ site_post(mail)
78
+ _org_submit(mail)
79
+ end
80
+
81
+ def _org_submit (mail)
82
+ inc_count
83
+ save_charset(@message_charset)
84
+ remove_alertedp_file
85
+
86
+ subject = Mail.rewrite_subject(mail['Subject'], @name, @count)
87
+
88
+ body = rewrite_body(mail)
89
+
90
+ header = []
91
+ mail.each_field {|key, value|
92
+ k = key.downcase
93
+ next if k == 'subject' or k == 'reply-to'
94
+ header.push([key, value])
95
+ }
96
+ header.push(['Subject', subject],
97
+ ['Reply-To', @address],
98
+ ['X-Mail-Count',@count])
99
+ header.concat(quickml_fields)
100
+
101
+ mail = {
102
+ :mail_from => @return_address,
103
+ :recipient => get_active_members,
104
+ :header => header,
105
+ :body => body
106
+ }
107
+ Sendmail(@config.smtp_host, @config.smtp_port, @logger, mail)
108
+ end
109
+
110
+ def send_confirmation (creator_address)
111
+ header = []
112
+ subject = Mail.encode_field(_("[%s] Confirmation: %s", @name, @address))
113
+ header.push(['To', creator_address],
114
+ ['From', confirmation_address],
115
+ ['Subject', subject],
116
+ ['Content-Type', content_type])
117
+ body = confirmation_message(@address)
118
+ mail = {
119
+ :mail_from => '',
120
+ :recipient => creator_address,
121
+ :header => header,
122
+ :body => body,
123
+ }
124
+ Sendmail(@config.smtp_host, @config.smtp_port, @logger, mail)
125
+ @logger.log "[#{@name}]: Send confirmation: #{confirmation_address} #{creator_address}"
126
+ end
127
+
128
+ # FIXME: too similar to report_too_large_mail in ml-session.rb
129
+ def report_too_large_mail (mail)
130
+ header = []
131
+ subject = Mail.encode_field(_("[QuickML] Error: %s", mail['Subject']))
132
+ header.push(['To', mail.from],
133
+ ['From', @address],
134
+ ['Subject', subject],
135
+ ['Content-Type', content_type])
136
+ max = @group_config[:max_mail_length].commify
137
+ body = _("Sorry, your mail exceeds the length limitation.\n")
138
+ body << _("The max length is %s bytes.\n\n", max)
139
+ orig_subject = codeconv(Mail.decode_subject(mail['Subject']))
140
+ body << "Subject: #{orig_subject}\n"
141
+ body << "To: #{mail['To']}\n"
142
+ body << "From: #{mail['From']}\n"
143
+ body << "Date: #{mail['Date']}\n"
144
+
145
+ mail = {
146
+ :mail_from => '',
147
+ :recipient => mail.from,
148
+ :header => header,
149
+ :body => body,
150
+ }
151
+ Sendmail(@config.smtp_host, @config.smtp_port, @logger, mail)
152
+ end
153
+
154
+ def report_removed_member (error_address)
155
+ return if @members.active_empty?
156
+ subject = Mail.encode_field(_("[%s] Removed: <%s>",
157
+ @name, error_address))
158
+ header = [
159
+ ['To', @address],
160
+ ['From', @address],
161
+ ['Subject', subject],
162
+ ['Reply-To', @address],
163
+ ['Content-Type', content_type]
164
+ ]
165
+ header.concat(quickml_fields)
166
+ body = _("<%s> was removed from the mailing list:\n<%s>\n",
167
+ error_address, @address)
168
+ body << _("because the address was unreachable.\n")
169
+ body << generate_footer(true)
170
+
171
+ mail = {
172
+ :mail_from => '',
173
+ :recipient => get_active_members,
174
+ :header => header,
175
+ :body => body,
176
+ }
177
+ Sendmail(@config.smtp_host, @config.smtp_port, @logger, mail)
178
+ @logger.log "[#{@name}]: Notify: Remove #{error_address}"
179
+ end
180
+
181
+ def content_type
182
+ return Mail.content_type(@config.content_type, @message_charset)
183
+ end
184
+
185
+ def quickml_fields
186
+ return [
187
+ ['Precedence', 'bulk'],
188
+ ['X-ML-Address', @address],
189
+ ['X-ML-Name', @name],
190
+ ['X-ML-Info', @config.public_url],
191
+ ['X-QuickML', 'true']
192
+ ]
193
+ end
194
+
195
+ def confirmation_message(address)
196
+ body = ''
197
+ body += _("First, please read the agreement of this service.\n")
198
+
199
+ #body += _("http://example.com/qwikjpAgreementE.html\n")
200
+ body += _("http://qwik.jp/qwikjpAgreementE.html\n")
201
+ #body += "http://#{@cnfig.domain}/"+_('AgreementE.html')+"\n"
202
+
203
+ body += _("You must agree with this agreement to use the service.\n")
204
+ body += _("If you agree, then,\n")
205
+ body += _("Please simply reply to this mail to create ML <%s>.\n", address)
206
+ body
207
+ end
208
+ end
209
+ end
210
+
211
+ if $0 == __FILE__
212
+ require 'qwik/test-module-ml'
213
+ $test = true
214
+ end
215
+
216
+ if defined?($test) && $test
217
+ class TestGroupSendMail < Test::Unit::TestCase
218
+ include TestModuleML
219
+
220
+ def setup_qml
221
+ return QuickML::Group.new(@ml_config, 'test@example.com')
222
+ end
223
+
224
+ def test_class_method
225
+ c = QuickML::Group
226
+ end
227
+
228
+ def test_all
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,374 @@
1
+ # Copyright (C) 2003-2006 Kouichirou Eto, All rights reserved.
2
+ # This is free software with ABSOLUTELY NO WARRANTY.
3
+ # You can redistribute it and/or modify it under the terms of the GNU GPL 2.
4
+
5
+ $LOAD_PATH.unshift '..' unless $LOAD_PATH.include? '..'
6
+ require 'qwik/config'
7
+ require 'qwik/server-memory'
8
+ require 'qwik/farm'
9
+ require 'qwik/site-plan'
10
+ require 'qwik/page-title'
11
+ require 'qwik/util-string'
12
+ require 'qwik/util-charset'
13
+ require 'qwik/util-filename'
14
+ require 'qwik/ml-gettext'
15
+
16
+ module QuickML
17
+ class Group
18
+ private
19
+
20
+ def init_site
21
+ @groupsite = GroupSite.new(@config, @name)
22
+ @site = @groupsite.site
23
+ end
24
+
25
+ def site_post(mail, test=false)
26
+ begin # Do not raise exception when posting a message.
27
+ @groupsite.post(mail)
28
+ @logger.log("[#{@name}]: QwikPost: #{@groupsite.key}")
29
+ rescue
30
+ @logger.log("[#{@name}]: QwikPostError: "+$!.to_s+$!.backtrace.to_s)
31
+ end
32
+ end
33
+
34
+ def page_url
35
+ key = @groupsite.key
36
+ base = ''
37
+ base = "#{key}.html" if key
38
+ #return "http://#{@config.ml_domain}/#{@name}/#{base}"
39
+ return "#{@config.public_url}#{@name}/#{base}"
40
+ end
41
+
42
+ def site_footer
43
+ # Do not raise exception when generating a footer.
44
+ begin
45
+ now = Time.now
46
+ now = Time.at(0) if defined?($test) && $test
47
+ return @groupsite.get_footer(now).set_page_charset.to_mail_charset
48
+ rescue
49
+ @logger.log("[#{@name}]: QwikFooterError: "+$!.to_s+$!.backtrace.to_s)
50
+ return '' # Do not raise error
51
+ end
52
+ end
53
+
54
+ private
55
+ def total_file_size_exceeded?
56
+ @groupsite.total_file_size_exceeded
57
+ end
58
+
59
+ def total_file_size_reaching?
60
+ @groupsite.total_file_size_reaching
61
+ end
62
+ end
63
+
64
+ class GroupSite
65
+ include GetText
66
+ def initialize(ml_config, sitename, test=false)
67
+ @ml_config = ml_config
68
+
69
+ if test || defined?($test) && $test
70
+ @config = $test_config
71
+ @memory = $test_memory
72
+ else
73
+
74
+ =begin
75
+ hash = {:debug=>true}
76
+
77
+ # FIXME: Web Config should be inherited from the web server.
78
+ f = @ml_config[:config_file].path
79
+ if f.exist?
80
+ config = Qwik::Config.load_config_file(f.to_s)
81
+ hash.update(config)
82
+ end
83
+
84
+ @config = Qwik::Config.new
85
+ @config.update(hash)
86
+ =end
87
+ @config = @ml_config
88
+ @memory = Qwik::ServerMemory.new(@config)
89
+ end
90
+
91
+ @sitename = sitename
92
+ @site = @memory.farm.get_site(@sitename)
93
+ raise 'site does not exist' if @site.nil? # Check if the site is exist.
94
+ @key = nil
95
+ @total_file_size_exceeded = false
96
+ @total_file_size_reaching = false
97
+ end
98
+ attr_reader :key
99
+ attr_reader :site
100
+ attr_reader :total_file_size_exceeded
101
+ attr_reader :total_file_size_reaching
102
+
103
+ def post(mail)
104
+ # Parse page title.
105
+ title = mail.get_unified_subject(@sitename) # Get unified subject.
106
+ page_title, tags = Qwik::Page.parse_title(title)
107
+
108
+ page = @site.get_by_title(page_title)
109
+ if page.nil? # Create a new page.
110
+ if Qwik::Page.valid_as_pagekey?(page_title)
111
+ page = @site.create(page_title) # CREATE
112
+ else
113
+ page = @site.create_new # CREATE
114
+ end
115
+ page.store('* '+title+"\n") # Save title with tags.
116
+ end
117
+ @key = page.key # @key will be used at site_url
118
+
119
+ # Get body text.
120
+ now = $quickml_debug ? Time.at(0) : Time.now
121
+ content = make_content(@key, mail, now)
122
+ page.add(content)
123
+ end
124
+
125
+ def get_footer(now)
126
+ return '' if @site.nil?
127
+ footer = @site.get_footer(now)
128
+ return footer
129
+ end
130
+
131
+ private
132
+ def make_content(key, mail, now)
133
+ content = ''
134
+ mail_default_charset = 'ISO-2022-JP'
135
+ site_files_total = @site.files_total
136
+ max_total_file_size = @config[:max_total_file_size].to_i
137
+ max_total_warn_size = @config[:max_total_warn_size].to_i
138
+
139
+ mail.each_part {|sub_mail|
140
+ if sub_mail.plain_text_body?
141
+ c = sub_mail.decoded_body.normalize_eol
142
+ charset = c.guess_charset || mail_default_charset
143
+ c = c.set_charset(charset).to_page_charset
144
+ content << c
145
+ else
146
+ filename = sub_mail.filename
147
+ decoded_body = sub_mail.decoded_body
148
+ if filename && decoded_body
149
+ if max_total_file_size < site_files_total
150
+ #do not attach file
151
+ content << _("\nFile '%s' was not attached.\n",filename)
152
+ else
153
+ msg = GroupSite.attach(@site, key, filename, decoded_body)
154
+ content << msg
155
+ site_files_total += decoded_body.size
156
+ end
157
+ if max_total_file_size < site_files_total
158
+ @total_file_size_exceeded = true
159
+ elsif (max_total_file_size - max_total_warn_size) < site_files_total
160
+ @total_file_size_reaching = true
161
+ end
162
+ end
163
+ end
164
+ }
165
+ content.gsub!(/\n\n\z/, "\n") # FIXME: Why truncate newlines?
166
+ from = mail.mail_from
167
+ time = now.to_i
168
+ return "{{mail(#{from},#{time})
169
+ #{content}}}
170
+ "
171
+ end
172
+
173
+ def self.attach(site, key, filename, file_content)
174
+ files = site.files(key)
175
+
176
+ result_filename = files.fput(filename, file_content)
177
+ result_filename = result_filename.to_page_charset
178
+
179
+ addmessage = "\n{{file(#{filename})}}\n\n"
180
+ if result_filename != filename
181
+ addmessage = "\n{{file(#{result_filename})}}\n\n"
182
+ end
183
+
184
+ return addmessage
185
+ end
186
+
187
+ def self.file_with_num(filename, num)
188
+ return "#{num}-#{filename}"
189
+ end
190
+ end
191
+ end
192
+
193
+ if $0 == __FILE__
194
+ require 'qwik/test-module-ml'
195
+ require 'qwik/test-common'
196
+ $test = true
197
+ end
198
+
199
+ if defined?($test) && $test
200
+ require 'qwik/group'
201
+
202
+ class TestGroupSite < Test::Unit::TestCase
203
+ include TestModuleML
204
+
205
+ def setup_group
206
+ return QuickML::Group.new(@ml_config, 'test@example.com')
207
+ end
208
+
209
+ def test_class_method
210
+ c = QuickML::GroupSite
211
+
212
+ # test_file_with_num
213
+ eq '1-t', c.file_with_num('t', 1)
214
+ end
215
+
216
+ def test_all
217
+ c = QuickML::GroupSite
218
+
219
+ group = setup_group
220
+
221
+ t_make_readable(QuickML::Group, :groupsite)
222
+ groupsite = group.groupsite
223
+
224
+ # test_key
225
+ eq nil, groupsite.key
226
+
227
+ # test_make_content
228
+ message =
229
+ 'Date: Mon, 3 Feb 2001 12:34:56 +0900
230
+ From: user@e.com
231
+ To: test@example.com
232
+ Subject: test
233
+
234
+ test.
235
+ '
236
+ t_make_public(QuickML::GroupSite, :make_content)
237
+ mail = QuickML::Mail.generate { message }
238
+ eq "{{mail(user@e.com,0)\ntest.\n}}\n",
239
+ groupsite.make_content(nil, mail, Time.at(0))
240
+
241
+ # test_attach
242
+ eq '
243
+ {{file(t.txt)}}
244
+
245
+ ',
246
+ c.attach(@site, 'FrontPage', 't.txt', 'test.')
247
+ files = @site.files('FrontPage')
248
+ eq true, files.exist?('t.txt')
249
+ eq ['t.txt'], files.list
250
+
251
+ # test_attach_again
252
+ eq '
253
+ {{file(1-t.txt)}}
254
+
255
+ ',
256
+ c.attach(@site, 'FrontPage', 't.txt', 'test.')
257
+ eq true, files.exist?('1-t.txt')
258
+ eq ['1-t.txt', 't.txt'], files.list
259
+
260
+ # test_page_url
261
+ t_make_public(QuickML::Group, :page_url)
262
+ eq 'http://example.com/test/', group.page_url
263
+ groupsite.instance_eval {
264
+ @key = 't'
265
+ }
266
+ eq 'http://example.com/test/t.html', group.page_url
267
+
268
+ # test_attach
269
+ eq '
270
+ {{file(��.txt)}}
271
+
272
+ ',
273
+ c.attach(@site, 'FrontPage', '��.txt', 'test.')
274
+ eq true, files.exist?('t.txt')
275
+ #eq true, files.exist?('=82=A0.txt')
276
+ #eq ['1-t.txt', '=82=A0.txt', 't.txt'], files.list
277
+ end
278
+
279
+ def test_total_file_limit
280
+ c = QuickML::GroupSite
281
+
282
+ group = setup_group
283
+
284
+ t_make_readable(QuickML::Group, :groupsite)
285
+ groupsite = group.groupsite
286
+
287
+ #attach 712B file named 'ruby.png'
288
+ multi_part_message =
289
+ 'Date: Tue, 13 Jan 2009 21:51:41 +0900
290
+ From: user@e.com
291
+ To: test@example.com
292
+ Subject: test
293
+ Content-Type: multipart/mixed;
294
+ boundary="Multipart_Tue_Jan_13_21:58:38_2009-1"
295
+
296
+ --Multipart_Tue_Jan_13_21:58:38_2009-1
297
+ Content-Type: text/plain; charset=US-ASCII
298
+
299
+ ruby
300
+
301
+ --Multipart_Tue_Jan_13_21:58:38_2009-1
302
+ Content-Type: image/png
303
+ Content-Disposition: inline; filename="ruby.png"
304
+ Content-Transfer-Encoding: base64
305
+
306
+ iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAIAAACp9tltAAAAAXNSR0IArs4c6QAAAoJJREFUKM8F
307
+ wUlPE1EAAOC3zXSWbtMylBbaAEUsEKlQIkSlogkxRm9eSLx78Z94NSR6MzEuF42JejUx0URNMFAo
308
+ RUJtEUqBCp1pO0unM+/5ffBxfum8XMaSbBsGkWSPUQqA03UoAIAQj1IAodE2cvfu4KU+Nf9gJdKv
309
+ Dgyn9GJRxhjqWvbmjWQq1S4UFMEXQhBalokwMXRdGRk53NoeXpg/2ipKStgxTCJJA5MTWu0QEeJZ
310
+ Fg6HWxjjqyFlLDcTHUsfbRQwxyWy06FEghN8Xq/Xn7mYXlyUlPB5rWZQhgDGsqoW3r1P5mbFcFgI
311
+ BXm/zChzTKu2vr726nU0PXr+p0o4jjCEvj5ZbVT3TU33q31G4xRh7FgWdT29dgQRKn74yDyPIESs
312
+ VrsF2MTt5cHhZGw8bRta8dNn5guKgaDV1Ox2+7j0GxMMAUPB5ODcyn3QqO++eL79dDW9fLdvPndQ
313
+ KNT/VuO5LLUsSD2CEIIQX4vF7NLmWWUfCgIRJUi7zW9fui4oN/7F4nF4ckwwRJ7LIlHUOv3XdRw+
314
+ qrSbWmBy+mCjdHLaCfqD2Xxejcc41xIJFDHjEEQMY8jzRrOpZi/NP3rYYsgR5UrjTFYiEYHDXlck
315
+ QCKAQ5B4jLV0LZGZmLyeq755ptfrtb09JEu0Y3WOagGZI4RxPLMJIE7PHbqVT4VDWy/fYp8ojWda
316
+ rjs1O+M2dey2RR5gjjKXmRigyFAiMze39/OX4490bNozrJGFK/rJMXJtwTVFHokEiBwQOYSnMN8q
317
+ 7XQs2wTAJFhNj2KO7Hz/cXlmKqZVcM8UOSgxx/ZHSCSZKlf3BdHn2QaDQF/bQJQCKbS5W6lblNCA
318
+ ADFPoXIh8x8NLS3ZvcTDhQAAAABJRU5ErkJggg==
319
+
320
+ --Multipart_Tue_Jan_13_21:58:38_2009-1--
321
+ '
322
+
323
+ default_max_total_file_size = @config[:max_total_file_size]
324
+ default_max_total_warn_size = @config[:max_total_warn_size]
325
+
326
+ @config[:max_total_file_size] = 800 #total file size limit
327
+ @config[:max_total_warn_size] = 100 #warn if remaining is less than this
328
+
329
+ t_make_writable(QuickML::GroupSite, :total_file_size_exceeded)
330
+ t_make_writable(QuickML::GroupSite, :total_file_size_reaching)
331
+
332
+ mail = QuickML::Mail.generate { multi_part_message }
333
+
334
+
335
+ ##post first mail
336
+ groupsite.post(mail)
337
+ files = @site.files('test')
338
+
339
+ #check if attached file is saved on the web
340
+ eq ['ruby.png'], files.list
341
+
342
+ #check if warning is on
343
+ eq true, groupsite.total_file_size_reaching
344
+
345
+ ##post second mail
346
+ groupsite.total_file_size_reaching = false
347
+ groupsite.post(mail)
348
+
349
+ # check if attached file is save on the web
350
+ eq ['1-ruby.png','ruby.png'], files.list
351
+
352
+ #check if total file size is exceeded the limit(800)
353
+ eq true, groupsite.total_file_size_exceeded
354
+
355
+ ##post second mail
356
+ groupsite.total_file_size_exceeded = false
357
+ groupsite.post(mail)
358
+
359
+ #check if file is not attached
360
+ eq ['1-ruby.png','ruby.png'], files.list
361
+
362
+ #check if total file size is exceeded the limit(800)
363
+ eq true, groupsite.total_file_size_exceeded
364
+
365
+
366
+ #check if the warning message is inserted on the web
367
+ eq "{{mail(user@e.com,0)\nruby\n\n\n{{file(ruby.png)}}\n}}\n{{mail(user@e.com,0)\nruby\n\n\n{{file(1-ruby.png)}}\n}}\n{{mail(user@e.com,0)\nruby\n\n\nFile 'ruby.png' was not attached.\n}}\n", @site['test'].get_body
368
+
369
+
370
+ @config[:max_total_file_size] = default_max_total_file_size
371
+ @config[:max_total_warn_size] = default_max_total_warn_size
372
+ end
373
+ end
374
+ end