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,76 @@
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
+ require 'time'
6
+ require 'fileutils'
7
+
8
+ $LOAD_PATH.unshift '..' unless $LOAD_PATH.include? '..'
9
+ require 'qwik/server-memory'
10
+ require 'qwik/pages'
11
+ require 'qwik/site-config'
12
+ require 'qwik/site-log'
13
+ require 'qwik/site-member'
14
+ require 'qwik/site-url'
15
+ require 'qwik/site-pages'
16
+ require 'qwik/site-group'
17
+ require 'qwik/site-files'
18
+ #require 'qwik/site-rrefs'
19
+ #require 'qwik/site-search'
20
+
21
+ module Qwik
22
+ class Site
23
+ include Enumerable
24
+
25
+ CACHE_DIR = '.cache'
26
+
27
+ def initialize(config, memory, sitename)
28
+ @config = config
29
+ @memory = memory
30
+
31
+ @sitename = sitename
32
+ @path = "#{@config.sites_dir}/#{sitename}".path
33
+ @pages = Pages.new(@config, @path)
34
+
35
+ @cache_path = @path + CACHE_DIR
36
+ @cache_path.check_directory
37
+
38
+ @cache = {}
39
+
40
+ init_group_config # site-group.rb
41
+
42
+ # init_site_search
43
+ end
44
+ attr_reader :sitename
45
+ attr_reader :path
46
+ attr_reader :cache_path
47
+ attr_reader :cache
48
+
49
+ def inspect
50
+ return "#<Site:#{@sitename}>"
51
+ end
52
+ end
53
+ end
54
+
55
+ if $0 == __FILE__
56
+ require 'qwik/test-module-session'
57
+ require 'qwik/farm'
58
+ $test = true
59
+ end
60
+
61
+ if defined?($test) && $test
62
+ class TestSite < Test::Unit::TestCase
63
+ include TestSession
64
+
65
+ def test_all
66
+ sitename = 'site_test'
67
+ pa = @config.sites_dir.path + sitename
68
+ pa.rmtree if pa.exist?
69
+ pa.mkdir
70
+ assert_equal false, (pa+sitename).exist?
71
+ site = Qwik::Site.new(@config, @memory, sitename)
72
+ assert_equal false, (pa+sitename).exist?
73
+ pa.rmtree
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,105 @@
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
+
7
+ module Qwik
8
+ class SmilTime < Time
9
+ def to_smil
10
+ str = self.strftime('%H:%M:%S')
11
+ frame = SmilTime.usec_to_frame(self.usec)
12
+ str += '.'+sprintf('%02d', frame) if 0 < frame
13
+ return str
14
+ end
15
+
16
+ def self.at_smil(arg)
17
+ raise 'arg must be String' unless arg.is_a?(String)
18
+ hour, min, sec, frame = SmilTime.parse_smil(arg)
19
+ return SmilTime.gm(1970, 1, 1, hour, min, sec, frame_to_usec(frame))
20
+ end
21
+
22
+ def self.frame_to_usec(frame)
23
+ return (1000000.0 * frame.to_f / 30.0).to_i
24
+ end
25
+
26
+ def self.usec_to_frame(usec)
27
+ return (30.0 * usec.to_f / 1000000.0 + 0.5).to_i # half adjust
28
+ end
29
+
30
+ def self.parse_smil(str)
31
+ hour = min = sec = frame = 0
32
+ if str.include?('.')
33
+ str, frame = str.split('.', 2)
34
+ frame = with_range(frame.to_i, 0, 29)
35
+ end
36
+ ar = str.split(/:/)
37
+ sec = with_range(ar.pop.to_i, 0, 59)
38
+ min = with_range(ar.pop.to_i, 0, 59)
39
+ hour = with_range(ar.pop.to_i, 0, 999999) # without max
40
+ return [hour, min, sec, frame]
41
+ end
42
+
43
+ def self.with_range(n, min, max)
44
+ n = min if n < min
45
+ n = max if max < n
46
+ return n
47
+ end
48
+ end
49
+ end
50
+
51
+ if $0 == __FILE__
52
+ require 'qwik/testunit'
53
+ $test = true
54
+ end
55
+
56
+ if defined?($test) && $test
57
+ class TestSmilTime < Test::Unit::TestCase
58
+ def test_all
59
+ c = Qwik::SmilTime
60
+
61
+ # test_to_smil
62
+ ok_eq('12:34:56.15', c.at_smil('12:34:56.15').to_smil)
63
+ ok_eq('12:34:56', c.at_smil('12:34:56').to_smil)
64
+ ok_eq('00:12:34', c.at_smil('12:34').to_smil)
65
+ ok_eq('00:00:12.15', c.at_smil('12.15').to_smil)
66
+ ok_eq('00:00:12.05', c.at_smil('12.05').to_smil)
67
+
68
+ # test_at_smil
69
+ t = c.at_smil('12')
70
+ ok_eq(12.0, t.to_f)
71
+ ok_eq(c.at(12), t) # same
72
+
73
+ t = c.at_smil('12.15')
74
+ ok_eq(12.5, t.to_f)
75
+ ok_eq(c.at(12.5), t) # same
76
+
77
+ # should test with range...
78
+ ok_eq(12.333333, c.at_smil('12.10').to_f)
79
+ ok_eq(45296.5, c.at_smil('12:34:56.15').to_f)
80
+
81
+ # test_frame_to_usec
82
+ ok_eq(500000, c.frame_to_usec(15))
83
+
84
+ # test_usec_to_frame
85
+ ok_eq(15, c.usec_to_frame(500000))
86
+
87
+ (0..30).each {|n|
88
+ usec = c.frame_to_usec(n)
89
+ frame = c.usec_to_frame(usec)
90
+ ok_eq(n, frame)
91
+ }
92
+
93
+ # test_parse_smil
94
+ ok_eq([ 0, 0, 12, 0], c.parse_smil('12'))
95
+ ok_eq([ 0, 12, 34, 0], c.parse_smil('12:34'))
96
+ ok_eq([12, 34, 56, 0], c.parse_smil('12:34:56'))
97
+ ok_eq([12, 34, 56, 15], c.parse_smil('12:34:56.15'))
98
+ ok_eq([ 0, 12, 34, 15], c.parse_smil('12:34.15'))
99
+
100
+ # test_with_range
101
+ ok_eq(0, c.with_range(-1, 0, 29))
102
+ ok_eq(29, c.with_range(30, 0, 29))
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,331 @@
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 << '..' unless $LOAD_PATH.include? '..'
12
+ require 'qwik/ml-gettext'
13
+ require 'qwik/mail'
14
+ require 'qwik/ml-exception'
15
+ #require 'qwik/util-basic'
16
+ require 'qwik/util-safe'
17
+ require 'qwik/util-string'
18
+ require 'qwik/util-time'
19
+ require 'time'
20
+
21
+ #require 'kconv'
22
+ #require 'net/smtp'
23
+ require 'socket'
24
+ require 'timeout'
25
+
26
+ class TCPSocket
27
+ def address
28
+ return peeraddr[3]
29
+ end
30
+
31
+ def hostname
32
+ return peeraddr[2]
33
+ end
34
+ end
35
+
36
+ module QuickML
37
+ class TooLargeMail < StandardError; end
38
+
39
+ class SmtpSession
40
+ include GetText
41
+
42
+ COMMAND_TABLE = [:helo, :ehlo, :noop, :quit, :rset, :rcpt, :mail, :data]
43
+
44
+ def initialize (config, logger, catalog, socket)
45
+ @config = config
46
+ @logger = logger
47
+ @catalog = catalog
48
+ @socket = socket
49
+
50
+ @server_name = 'QuickML'
51
+
52
+ @hello_host = 'hello.host.invalid'
53
+ @protocol = nil
54
+ @peer_hostname = @socket.hostname
55
+ @peer_address = @socket.address
56
+ @remote_host = (@peer_hostname or @peer_address)
57
+
58
+ @data_finished = false
59
+ @my_hostname = 'localhost'
60
+ @my_hostname = Socket.gethostname if @config.ml_port == 25
61
+ @message_charset = nil
62
+ end
63
+
64
+ def start
65
+ elapsed = calc_time {
66
+ _start
67
+ }
68
+ @logger.vlog "Session finished: #{elapsed} sec."
69
+ end
70
+
71
+ private
72
+
73
+ def calc_time
74
+ start_time = Time.now
75
+ yield
76
+ elapsed = Time.now - start_time
77
+ return elapsed
78
+ end
79
+
80
+ def _start
81
+ begin
82
+ def_puts(@socket)
83
+ connect
84
+ timeout(@config.timeout) {
85
+ process
86
+ }
87
+ rescue TimeoutError
88
+ @logger.vlog "Timeout: #{@remote_host}"
89
+ ensure
90
+ close
91
+ end
92
+ end
93
+
94
+ def def_puts(socket)
95
+ def socket.puts(*objs)
96
+ objs.each {|x|
97
+ begin
98
+ self.print x.xchomp, "\r\n"
99
+ rescue Errno::EPIPE
100
+ end
101
+ }
102
+ end
103
+ end
104
+
105
+ def connect
106
+ @socket.puts "220 #{@my_hostname} ESMTP #{@server_name}"
107
+ @logger.vlog "Connect: #{@remote_host}"
108
+ end
109
+
110
+ def process
111
+ until @socket.closed?
112
+ begin
113
+ mail = Mail.new
114
+ receive_mail(mail)
115
+ if mail.valid?
116
+ process_mail(@config, mail)
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
+ # Abstract
147
+ def process_mail(config, mail)
148
+ # do nothing.
149
+ end
150
+
151
+ def helo (mail, arg)
152
+ return if arg.nil?
153
+ @hello_host = arg.split.first
154
+ @socket.puts "250 #{@my_hostname}"
155
+ @protocol = 'SMTP'
156
+ end
157
+
158
+ def ehlo (mail, arg)
159
+ @hello_host = arg.split.first
160
+ @socket.puts "250-#{@my_hostname}"
161
+ @socket.puts '250 PIPELINING'
162
+ @protocol = 'ESMTP'
163
+ end
164
+
165
+ def noop (mail, arg)
166
+ @socket.puts '250 ok'
167
+ end
168
+
169
+ def quit (mail, arg)
170
+ @socket.puts '221 Bye'
171
+ close
172
+ end
173
+
174
+ def rset (mail, arg)
175
+ mail.mail_from = nil
176
+ mail.clear_recipients
177
+ @socket.puts '250 ok'
178
+ end
179
+
180
+ def rcpt (mail, arg)
181
+ if mail.mail_from.nil?
182
+ @socket.puts '503 Error: need MAIL command'
183
+ elsif /^To:\s*<(.*)>/i =~ arg or /^To:\s*(.*)/i =~ arg
184
+ address = $1
185
+ if Mail.address_of_domain?(address, @config.ml_domain)
186
+ mail.add_recipient(address)
187
+ @socket.puts '250 ok'
188
+ else
189
+ @socket.puts "554 <#{address}>: Recipient address rejected"
190
+ @logger.vlog "Unacceptable RCPT TO:<#{address}>"
191
+ end
192
+ else
193
+ @socket.puts "501 Syntax: RCPT TO: <address>"
194
+ end
195
+ end
196
+
197
+ def mail (mail, arg)
198
+ if @protocol.nil?
199
+ @socket.puts '503 Error: send HELO/EHLO first'
200
+ elsif /^From:\s*<(.*)>/i =~ arg or /^From:\s*(.*)/i =~ arg
201
+ mail.mail_from = $1
202
+ @socket.puts '250 ok'
203
+ else
204
+ @socket.puts "501 Syntax: MAIL FROM: <address>"
205
+ end
206
+ end
207
+
208
+ def data (mail, arg)
209
+ if mail.recipients.empty?
210
+ @socket.puts '503 Error: need RCPT command'
211
+ else
212
+ @socket.puts '354 send the mail data, end with .';
213
+ begin
214
+ read_mail(mail)
215
+ ensure
216
+ @message_charset = mail.charset
217
+ end
218
+ @socket.puts '250 ok'
219
+ end
220
+ end
221
+
222
+ def read_mail (mail)
223
+ len = 0
224
+ lines = []
225
+ while line = @socket.safe_gets
226
+ break if end_of_data?(line)
227
+ len += line.length
228
+ if @config.max_mail_length < len
229
+ mail.read(lines.join('')) # Generate a header for an error report.
230
+ raise TooLargeMail
231
+ end
232
+ line.sub!(/^\.\./, '.') # unescape
233
+ line = line.normalize_eol
234
+ lines << line
235
+ # I do not know why but constructing mail_string with
236
+ # String#<< here is very slow.
237
+ # mail_string << line
238
+ end
239
+ mail_string = lines.join('')
240
+ @data_finished = true
241
+ mail.read(mail_string)
242
+ mail.unshift_field('Received', received_field)
243
+ end
244
+
245
+ def end_of_data? (line)
246
+ #return line.xchomp == '.'
247
+ return line == ".\r\n"
248
+ end
249
+
250
+ def received_field
251
+ received_field_internal(@hello_host, @peer_hostname, @peer_address,
252
+ @my_hostname, @server_name, @protocol,
253
+ Time.now.rfc2822)
254
+ end
255
+
256
+ def received_field_internal(hello_host, peer_hostname, peer_address,
257
+ my_hostname, server_name, protocol, time)
258
+ "from #{hello_host} (#{peer_hostname} [#{peer_address}])
259
+ by #{my_hostname} (#{server_name}) with #{protocol};
260
+ #{time}%s"
261
+ end
262
+
263
+ def cleanup_connection
264
+ unless @data_finished
265
+ discard_data
266
+ end
267
+ @socket.puts '221 Bye'
268
+ close
269
+ end
270
+
271
+ def discard_data
272
+ begin
273
+ while line = @socket.safe_gets
274
+ break if end_of_data?(line)
275
+ end
276
+ rescue TooLongLine
277
+ retry
278
+ end
279
+ end
280
+
281
+ # Abstract
282
+ def report_too_large_mail (mail)
283
+ # do nothing.
284
+ end
285
+
286
+ def close
287
+ return if @socket.closed?
288
+ @socket.close
289
+ @logger.vlog "Closed: #{@remote_host}"
290
+ end
291
+ end
292
+ end
293
+
294
+ if $0 == __FILE__
295
+ require 'qwik/testunit'
296
+ require 'qwik/mock-socket'
297
+ require 'qwik/mock-logger'
298
+ require 'qwik/config'
299
+ require 'qwik/qp'
300
+ require 'pp'
301
+ $test = true
302
+ end
303
+
304
+ if defined?($test) && $test
305
+ class TestSmtpSession < Test::Unit::TestCase
306
+ def test_all
307
+ config = Qwik::Config.new
308
+ logger = QuickML::MockLogger.new
309
+ hash = {
310
+ :logger => logger,
311
+ :sites_dir => '.',
312
+ }
313
+ config.update(hash)
314
+
315
+ socket = QuickML::MockSocket.new "HELO localhost
316
+ MAIL FROM: user@example.net
317
+ RCPT TO: test@example.com
318
+ DATA
319
+ To: test@example.com
320
+ From: user@example.net
321
+ Subject: create
322
+
323
+ create new ML.
324
+ .
325
+ QUIT
326
+ "
327
+ session = QuickML::SmtpSession.new(config, logger, config.catalog, socket)
328
+ session.start
329
+ end
330
+ end
331
+ end