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,122 @@
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
+ $KCODE = 's' # FIXME: Remove $KCODE
12
+
13
+ require 'fileutils'
14
+
15
+ $LOAD_PATH.unshift '..' unless $LOAD_PATH.include? '..'
16
+ require 'qwik/config'
17
+ require 'qwik/ml-memory'
18
+ require 'qwik/ml-server'
19
+ require 'qwik/ml-sweeper'
20
+
21
+ $ml_debug = false
22
+ # $ml_debug = true
23
+
24
+ module QuickML
25
+ class QuickMLServer
26
+ def self.main(args)
27
+ server = QuickMLServer.new
28
+
29
+ config = Qwik::Config.new
30
+ Qwik::Config.load_args_and_config(config, $0, args)
31
+ config.update({:debug => true, :verbose_mode => true}) if $ml_debug
32
+
33
+ ServerMemory.init_logger(config, config)
34
+ ServerMemory.init_mutex(config)
35
+ ServerMemory.init_catalog(config)
36
+
37
+ server.run(config)
38
+ end
39
+
40
+ def initialize
41
+ # Do nothing.
42
+ end
43
+
44
+ def run (config)
45
+ QuickMLServer.check_directory(config.sites_dir)
46
+
47
+ if ! config.debug
48
+ QuickMLServer.be_daemon
49
+ QuickMLServer.be_secure(config)
50
+ end
51
+
52
+ server = Server.new(config)
53
+ sweeper = Sweeper.new(config)
54
+ trap(:TERM) { server.shutdown; sweeper.shutdown }
55
+ trap(:INT) { server.shutdown; sweeper.shutdown }
56
+ if Signal.list.key?("HUP")
57
+ trap(:HUP) { config.logger.reopen }
58
+ end
59
+ sweeper_thread = Thread.new { sweeper.start }
60
+ sweeper_thread.abort_on_exception = true
61
+
62
+ if config.debug
63
+ require 'qwik/autoreload'
64
+ AutoReload.start(1, true, 'ML') # auto reload every sec.
65
+ end
66
+
67
+ server.start
68
+ end
69
+
70
+ private
71
+
72
+ def self.check_directory(dir)
73
+ error("#{dir}: No such directory") if ! File.directory?(dir)
74
+ error("#{dir}: is not writable") if ! File.writable?(dir)
75
+ end
76
+
77
+ def self.error (msg)
78
+ STDERR.puts "#{$0}: #{msg}"
79
+ exit(1)
80
+ end
81
+
82
+ def self.be_daemon
83
+ exit!(0) if fork
84
+ Process::setsid
85
+ exit!(0) if fork
86
+ Dir::chdir('/')
87
+ File::umask(022)
88
+ STDIN.reopen('/dev/null', 'r+')
89
+ STDOUT.reopen('/dev/null', 'r+')
90
+ STDERR.reopen('/dev/null', 'r+')
91
+ end
92
+
93
+ def self.be_secure(config)
94
+ return unless Process.uid == 0
95
+ uid = Etc::getpwnam(config.user).uid
96
+ gid = Etc::getgrnam(config.group).gid
97
+ FileUtils.touch(config.ml_pid_file)
98
+ ml_log_file = (config[:log_dir].path + Logger::ML_LOG_FILE).to_s
99
+ FileUtils.touch(ml_log_file)
100
+ File.chown(uid, gid, config.sites_dir)
101
+ File.chown(uid, gid, config.ml_pid_file)
102
+ File.chown(uid, gid, ml_log_file)
103
+ Process.uid = uid
104
+ Process.gid = gid
105
+ Process.euid = uid
106
+ end
107
+ end
108
+ end
109
+
110
+ if $0 == __FILE__
111
+ require 'qwik/test-module-ml'
112
+ $test = true
113
+ end
114
+
115
+ if defined?($test) && $test
116
+ class TestMLQuickMLServer < Test::Unit::TestCase
117
+ def test_all
118
+ # Just create it.
119
+ qml_server = QuickML::QuickMLServer.new
120
+ end
121
+ end
122
+ end
File without changes
@@ -0,0 +1,107 @@
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
+ require 'socket'
12
+ require 'etc'
13
+ require 'thread'
14
+ require 'thwait'
15
+ require 'timeout'
16
+ require 'time'
17
+ require 'net/smtp' # FIXME: Which code uses smtp?
18
+
19
+ $LOAD_PATH.unshift '..' unless $LOAD_PATH.include? '..'
20
+ require 'qwik/ml-session'
21
+ require 'qwik/util-safe'
22
+ require 'qwik/util-pid'
23
+
24
+ module QuickML
25
+ class Server
26
+ include PidModule
27
+
28
+ def initialize (config)
29
+ @config = config
30
+ $ml_debug = true if @config.debug
31
+ @status = :stop
32
+ @logger = @config.logger
33
+ @server = TCPServer.new(@config.bind_address, @config.ml_port)
34
+ end
35
+
36
+ def start
37
+ raise 'server already started' if @status != :stop
38
+ write_pid_file(@config.ml_pid_file)
39
+ @logger.log sprintf('Server started at %s:%d [%d]',
40
+ 'localhost', @config.ml_port, Process.pid)
41
+ accept
42
+ @logger.log "Server exited [#{Process.pid}]"
43
+ remove_pid_file(@config.ml_pid_file)
44
+ end
45
+
46
+ def shutdown
47
+ begin
48
+ @server.shutdown
49
+ rescue Errno::ENOTCONN
50
+ p 'Already disconnected.'
51
+ end
52
+ @status = :shutdown
53
+ end
54
+
55
+ private
56
+
57
+ def accept
58
+ running_sessions = []
59
+ @status = :running
60
+ while @status == :running
61
+ begin
62
+ t = Thread.new(@server.accept) {|s|
63
+ process_session(s)
64
+ }
65
+ t.abort_on_exception = true
66
+ running_sessions.push(t)
67
+ rescue Errno::ECONNABORTED # caused by @server.shutdown
68
+ rescue Errno::EINVAL
69
+ end
70
+ running_sessions.delete_if {|t| t.status == false }
71
+ if running_sessions.length >= @config.max_threads
72
+ ThreadsWait.new(running_sessions).next_wait
73
+ end
74
+ end
75
+ running_sessions.each {|t| t.join }
76
+ end
77
+
78
+ def process_session (socket)
79
+ begin
80
+ c = @config
81
+ session = Session.new(c, c.logger, c.catalog, socket)
82
+ session.start
83
+ rescue Exception => e
84
+ @logger.log "Unknown Session Error: #{e.class}: #{e.message}"
85
+ @logger.log e.backtrace
86
+ end
87
+ end
88
+
89
+ end
90
+ end
91
+
92
+ if $0 == __FILE__
93
+ require 'qwik/test-module-ml'
94
+ require 'qwik/config'
95
+ $test = true
96
+ end
97
+
98
+ if defined?($test) && $test
99
+ class TestMLServer < Test::Unit::TestCase
100
+ def test_all
101
+ #return
102
+ config = Qwik::Config.new
103
+ config[:ml_port] = 9195
104
+ server = QuickML::Server.new(config)
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,348 @@
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/ml-gettext'
13
+ require 'qwik/mail'
14
+ require 'qwik/ml-processor'
15
+ require 'qwik/ml-exception'
16
+ require 'qwik/util-basic'
17
+ require 'qwik/util-safe'
18
+
19
+ require 'kconv'
20
+ require 'net/smtp'
21
+ require 'socket'
22
+ #require 'qwik/util-socket'
23
+
24
+ class TCPSocket
25
+ def address
26
+ return peeraddr[3]
27
+ end
28
+
29
+ def hostname
30
+ return peeraddr[2]
31
+ end
32
+ end
33
+
34
+ module QuickML
35
+ class TooLargeMail < QuickMLException; end
36
+
37
+ class Session
38
+ include GetText
39
+
40
+ COMMAND_TABLE = [:helo, :ehlo, :noop, :quit, :rset, :rcpt, :mail, :data]
41
+
42
+ # def initialize (config, socket)
43
+ def initialize (config, logger, catalog, socket)
44
+ @socket = socket
45
+ @config = config
46
+ # @logger = @config.logger
47
+ # @catalog = @config.catalog
48
+ @logger = logger
49
+ @catalog = catalog
50
+
51
+ @hello_host = 'hello.host.invalid'
52
+ @protocol = nil
53
+ @peer_hostname = @socket.hostname
54
+ @peer_address = @socket.address
55
+ @remote_host = (@peer_hostname or @peer_address)
56
+
57
+ @data_finished = false
58
+ @my_hostname = 'localhost'
59
+ @my_hostname = Socket.gethostname if @config.ml_port == 25
60
+ @message_charset = nil
61
+ end
62
+
63
+ def start
64
+ elapsed = calc_time {
65
+ _start
66
+ }
67
+ @logger.vlog "Session finished: #{elapsed} sec."
68
+ end
69
+
70
+ private
71
+
72
+ def calc_time
73
+ start_time = Time.now
74
+ yield
75
+ elapsed = Time.now - start_time
76
+ return elapsed
77
+ end
78
+
79
+ def _start
80
+ begin
81
+ def_puts(@socket)
82
+ connect
83
+ timeout(@config.timeout) {
84
+ process
85
+ }
86
+ rescue TimeoutError
87
+ @logger.vlog "Timeout: #{@remote_host}"
88
+ ensure
89
+ close
90
+ end
91
+ end
92
+
93
+ def def_puts(socket)
94
+ def socket.puts(*objs)
95
+ objs.each {|x|
96
+ begin
97
+ self.print x.xchomp, "\r\n"
98
+ rescue Errno::EPIPE
99
+ end
100
+ }
101
+ end
102
+ end
103
+
104
+ def connect
105
+ @socket.puts "220 #{@my_hostname} ESMTP QuickML"
106
+ @logger.vlog "Connect: #{@remote_host}"
107
+ end
108
+
109
+ def process
110
+ until @socket.closed?
111
+ begin
112
+ mail = Mail.new
113
+ receive_mail(mail)
114
+ if mail.valid?
115
+ processor = Processor.new(@config, mail)
116
+ processor.process
117
+ end
118
+ rescue TooLargeMail
119
+ cleanup_connection
120
+ report_too_large_mail(mail) if mail.valid?
121
+ @logger.log "Too Large Mail: #{mail.from}"
122
+ rescue TooLongLine
123
+ cleanup_connection
124
+ @logger.log "Too Long Line: #{mail.from}"
125
+ end
126
+ end
127
+ end
128
+
129
+ def receive_mail (mail)
130
+ while line = @socket.safe_gets
131
+ line = line.xchomp
132
+ command, arg = line.split(/\s+/, 2)
133
+ return if command.nil? || command.empty?
134
+ command = command.downcase.intern # 'HELO' => :helo
135
+ if COMMAND_TABLE.include?(command)
136
+ @logger.vlog "Command: #{line}"
137
+ send(command, mail, arg)
138
+ else
139
+ @logger.vlog "Unknown SMTP Command: #{command} #{arg}"
140
+ @socket.puts '502 Error: command not implemented'
141
+ end
142
+ break if command == :quit or command == :data
143
+ end
144
+ end
145
+
146
+ def helo (mail, arg)
147
+ return if arg.nil?
148
+ @hello_host = arg.split.first
149
+ @socket.puts "250 #{@my_hostname}"
150
+ @protocol = 'SMTP'
151
+ end
152
+
153
+ def ehlo (mail, arg)
154
+ @hello_host = arg.split.first
155
+ @socket.puts "250-#{@my_hostname}"
156
+ @socket.puts '250 PIPELINING'
157
+ @protocol = 'ESMTP'
158
+ end
159
+
160
+ def noop (mail, arg)
161
+ @socket.puts '250 ok'
162
+ end
163
+
164
+ def quit (mail, arg)
165
+ @socket.puts '221 Bye'
166
+ close
167
+ end
168
+
169
+ def rset (mail, arg)
170
+ mail.mail_from = nil
171
+ mail.clear_recipients
172
+ @socket.puts '250 ok'
173
+ end
174
+
175
+ def rcpt (mail, arg)
176
+ if mail.mail_from.nil?
177
+ @socket.puts '503 Error: need MAIL command'
178
+ elsif /^To:\s*<(.*)>/i =~ arg or /^To:\s*(.*)/i =~ arg
179
+ address = $1
180
+ if Mail.address_of_domain?(address, @config.ml_domain)
181
+ mail.add_recipient(address)
182
+ @socket.puts '250 ok'
183
+ else
184
+ @socket.puts "554 <#{address}>: Recipient address rejected"
185
+ @logger.vlog "Unacceptable RCPT TO:<#{address}>"
186
+ end
187
+ else
188
+ @socket.puts "501 Syntax: RCPT TO: <address>"
189
+ end
190
+ end
191
+
192
+ def mail (mail, arg)
193
+ if @protocol.nil?
194
+ @socket.puts '503 Error: send HELO/EHLO first'
195
+ elsif /^From:\s*<(.*)>/i =~ arg or /^From:\s*(.*)/i =~ arg
196
+ mail.mail_from = $1
197
+ @socket.puts '250 ok'
198
+ else
199
+ @socket.puts "501 Syntax: MAIL FROM: <address>"
200
+ end
201
+ end
202
+
203
+ def data (mail, arg)
204
+ if mail.recipients.empty?
205
+ @socket.puts '503 Error: need RCPT command'
206
+ else
207
+ @socket.puts '354 send the mail data, end with .';
208
+ begin
209
+ read_mail(mail)
210
+ ensure
211
+ @message_charset = mail.charset
212
+ end
213
+ @socket.puts '250 ok'
214
+ end
215
+ end
216
+
217
+ def read_mail (mail)
218
+ len = 0
219
+ lines = []
220
+ while line = @socket.safe_gets
221
+ break if end_of_data?(line)
222
+ len += line.length
223
+ if @config.max_mail_length < len
224
+ mail.read(lines.join('')) # Generate a header for an error report.
225
+ raise TooLargeMail
226
+ end
227
+ line.sub!(/^\.\./, '.') # unescape
228
+ line = line.normalize_eol
229
+ lines << line
230
+ # I do not know why but constructing mail_string with
231
+ # String#<< here is very slow.
232
+ # mail_string << line
233
+ end
234
+ mail_string = lines.join('')
235
+ @data_finished = true
236
+ mail.read(mail_string)
237
+ mail.unshift_field('Received', received_field)
238
+ end
239
+
240
+ def end_of_data? (line)
241
+ # line.xchomp == '.'
242
+ return line == ".\r\n"
243
+ end
244
+
245
+ def received_field
246
+ sprintf("from %s (%s [%s])\n" +
247
+ " by %s (QuickML) with %s;\n" +
248
+ " %s",
249
+ @hello_host,
250
+ @peer_hostname,
251
+ @peer_address,
252
+ @my_hostname,
253
+ @protocol,
254
+ Time.now.rfc2822)
255
+ end
256
+
257
+ def cleanup_connection
258
+ unless @data_finished
259
+ discard_data
260
+ end
261
+ @socket.puts '221 Bye'
262
+ close
263
+ end
264
+
265
+ def discard_data
266
+ begin
267
+ while line = @socket.safe_gets
268
+ break if end_of_data?(line)
269
+ end
270
+ rescue TooLongLine
271
+ retry
272
+ end
273
+ end
274
+
275
+ def report_too_large_mail (mail)
276
+ header = []
277
+ subject = Mail.encode_field(_("[QuickML] Error: %s", mail['Subject']))
278
+ header.push(['To', mail.from],
279
+ ['From', @config.ml_postmaster],
280
+ ['Subject', subject],
281
+ ['Content-Type', content_type])
282
+
283
+ max = @config.max_mail_length.commify
284
+ body = _("Sorry, your mail exceeds the length limitation.\n")
285
+ body << _("The max length is %s bytes.\n\n", max)
286
+ orig_subject = codeconv(Mail.decode_subject(mail['Subject']))
287
+ body << "Subject: #{orig_subject}\n"
288
+ body << "To: #{mail['To']}\n"
289
+ body << "From: #{mail['From']}\n"
290
+ body << "Date: #{mail['Date']}\n"
291
+ Sendmail.send_mail(@config.smtp_host, @config.smtp_port, @logger,
292
+ :mail_from => '',
293
+ :recipient => mail.from,
294
+ :header => header,
295
+ :body => body)
296
+ end
297
+
298
+ # FIXME: this is the same method of QuickML#content_type
299
+ def content_type
300
+ return Mail.content_type(@config.content_type, @message_charset)
301
+ end
302
+
303
+ def close
304
+ return if @socket.closed?
305
+ @socket.close
306
+ @logger.vlog "Closed: #{@remote_host}"
307
+ end
308
+ end
309
+ end
310
+
311
+ if $0 == __FILE__
312
+ require 'qwik/test-module-ml'
313
+ require 'qwik/config'
314
+ $test = true
315
+ end
316
+
317
+ if defined?($test) && $test
318
+ class TestMLSession < Test::Unit::TestCase
319
+ def test_all
320
+ return
321
+ config = Qwik::Config.new
322
+ hash = {
323
+ :logger => QuickML::MockLogger.new,
324
+ :sites_dir => '.',
325
+ }
326
+ config.update(hash)
327
+ QuickML::ServerMemory.init_mutex(config)
328
+ QuickML::ServerMemory.init_catalog(config)
329
+ old_test_memory = $test_memory
330
+ $test_memory = Qwik::ServerMemory.new(config) # FIXME: Ugly.
331
+ socket = QuickML::MockSocket.new "HELO localhost
332
+ MAIL FROM: user@example.net
333
+ RCPT TO: test@example.com
334
+ DATA
335
+ To: test@example.com
336
+ From: user@example.net
337
+ Subject: create
338
+
339
+ create new ML.
340
+ .
341
+ QUIT
342
+ "
343
+ session = QuickML::Session.new(config, socket)
344
+ session.start
345
+ $test_memory = old_test_memory
346
+ end
347
+ end
348
+ end