pygments.rb-jruby 0.5.4

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 (473) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/CHANGELOG.md +71 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +17 -0
  6. data/README.md +118 -0
  7. data/Rakefile +66 -0
  8. data/bench.rb +22 -0
  9. data/cache-lexers.rb +8 -0
  10. data/lexers +0 -0
  11. data/lib/pygments.rb +8 -0
  12. data/lib/pygments/lexer.rb +148 -0
  13. data/lib/pygments/mentos.py +351 -0
  14. data/lib/pygments/popen.rb +404 -0
  15. data/lib/pygments/version.rb +3 -0
  16. data/pygments.rb.gemspec +24 -0
  17. data/test/test_data.c +2581 -0
  18. data/test/test_data.py +514 -0
  19. data/test/test_data_generated +2582 -0
  20. data/test/test_pygments.rb +287 -0
  21. data/vendor/custom_lexers/github.py +565 -0
  22. data/vendor/pygments-main/AUTHORS +153 -0
  23. data/vendor/pygments-main/CHANGES +889 -0
  24. data/vendor/pygments-main/LICENSE +25 -0
  25. data/vendor/pygments-main/MANIFEST.in +6 -0
  26. data/vendor/pygments-main/Makefile +59 -0
  27. data/vendor/pygments-main/REVISION +1 -0
  28. data/vendor/pygments-main/TODO +15 -0
  29. data/vendor/pygments-main/docs/generate.py +472 -0
  30. data/vendor/pygments-main/docs/pygmentize.1 +94 -0
  31. data/vendor/pygments-main/docs/src/api.txt +270 -0
  32. data/vendor/pygments-main/docs/src/authors.txt +5 -0
  33. data/vendor/pygments-main/docs/src/changelog.txt +5 -0
  34. data/vendor/pygments-main/docs/src/cmdline.txt +147 -0
  35. data/vendor/pygments-main/docs/src/filterdevelopment.txt +70 -0
  36. data/vendor/pygments-main/docs/src/filters.txt +42 -0
  37. data/vendor/pygments-main/docs/src/formatterdevelopment.txt +169 -0
  38. data/vendor/pygments-main/docs/src/formatters.txt +48 -0
  39. data/vendor/pygments-main/docs/src/index.txt +69 -0
  40. data/vendor/pygments-main/docs/src/installation.txt +71 -0
  41. data/vendor/pygments-main/docs/src/integrate.txt +48 -0
  42. data/vendor/pygments-main/docs/src/java.txt +70 -0
  43. data/vendor/pygments-main/docs/src/lexerdevelopment.txt +603 -0
  44. data/vendor/pygments-main/docs/src/lexers.txt +67 -0
  45. data/vendor/pygments-main/docs/src/moinmoin.txt +39 -0
  46. data/vendor/pygments-main/docs/src/plugins.txt +93 -0
  47. data/vendor/pygments-main/docs/src/quickstart.txt +202 -0
  48. data/vendor/pygments-main/docs/src/rstdirective.txt +22 -0
  49. data/vendor/pygments-main/docs/src/styles.txt +143 -0
  50. data/vendor/pygments-main/docs/src/tokens.txt +349 -0
  51. data/vendor/pygments-main/docs/src/unicode.txt +49 -0
  52. data/vendor/pygments-main/external/autopygmentize +64 -0
  53. data/vendor/pygments-main/external/lasso-builtins-generator-9.lasso +144 -0
  54. data/vendor/pygments-main/external/markdown-processor.py +67 -0
  55. data/vendor/pygments-main/external/moin-parser.py +112 -0
  56. data/vendor/pygments-main/external/pygments.bashcomp +38 -0
  57. data/vendor/pygments-main/external/rst-directive-old.py +77 -0
  58. data/vendor/pygments-main/external/rst-directive.py +83 -0
  59. data/vendor/pygments-main/ez_setup.py +276 -0
  60. data/vendor/pygments-main/pygmentize +7 -0
  61. data/vendor/pygments-main/pygments/__init__.py +91 -0
  62. data/vendor/pygments-main/pygments/cmdline.py +441 -0
  63. data/vendor/pygments-main/pygments/console.py +74 -0
  64. data/vendor/pygments-main/pygments/filter.py +74 -0
  65. data/vendor/pygments-main/pygments/filters/__init__.py +356 -0
  66. data/vendor/pygments-main/pygments/formatter.py +95 -0
  67. data/vendor/pygments-main/pygments/formatters/__init__.py +68 -0
  68. data/vendor/pygments-main/pygments/formatters/_mapping.py +92 -0
  69. data/vendor/pygments-main/pygments/formatters/bbcode.py +109 -0
  70. data/vendor/pygments-main/pygments/formatters/html.py +821 -0
  71. data/vendor/pygments-main/pygments/formatters/img.py +553 -0
  72. data/vendor/pygments-main/pygments/formatters/latex.py +378 -0
  73. data/vendor/pygments-main/pygments/formatters/other.py +115 -0
  74. data/vendor/pygments-main/pygments/formatters/rtf.py +136 -0
  75. data/vendor/pygments-main/pygments/formatters/svg.py +154 -0
  76. data/vendor/pygments-main/pygments/formatters/terminal.py +112 -0
  77. data/vendor/pygments-main/pygments/formatters/terminal256.py +222 -0
  78. data/vendor/pygments-main/pygments/lexer.py +765 -0
  79. data/vendor/pygments-main/pygments/lexers/__init__.py +240 -0
  80. data/vendor/pygments-main/pygments/lexers/_asybuiltins.py +1645 -0
  81. data/vendor/pygments-main/pygments/lexers/_clbuiltins.py +232 -0
  82. data/vendor/pygments-main/pygments/lexers/_lassobuiltins.py +5172 -0
  83. data/vendor/pygments-main/pygments/lexers/_luabuiltins.py +249 -0
  84. data/vendor/pygments-main/pygments/lexers/_mapping.py +354 -0
  85. data/vendor/pygments-main/pygments/lexers/_openedgebuiltins.py +562 -0
  86. data/vendor/pygments-main/pygments/lexers/_phpbuiltins.py +3787 -0
  87. data/vendor/pygments-main/pygments/lexers/_postgres_builtins.py +233 -0
  88. data/vendor/pygments-main/pygments/lexers/_robotframeworklexer.py +557 -0
  89. data/vendor/pygments-main/pygments/lexers/_scilab_builtins.py +40 -0
  90. data/vendor/pygments-main/pygments/lexers/_sourcemodbuiltins.py +1072 -0
  91. data/vendor/pygments-main/pygments/lexers/_stan_builtins.py +360 -0
  92. data/vendor/pygments-main/pygments/lexers/_vimbuiltins.py +13 -0
  93. data/vendor/pygments-main/pygments/lexers/agile.py +2290 -0
  94. data/vendor/pygments-main/pygments/lexers/asm.py +398 -0
  95. data/vendor/pygments-main/pygments/lexers/compiled.py +3723 -0
  96. data/vendor/pygments-main/pygments/lexers/dalvik.py +104 -0
  97. data/vendor/pygments-main/pygments/lexers/dotnet.py +671 -0
  98. data/vendor/pygments-main/pygments/lexers/foxpro.py +428 -0
  99. data/vendor/pygments-main/pygments/lexers/functional.py +2731 -0
  100. data/vendor/pygments-main/pygments/lexers/github.py +565 -0
  101. data/vendor/pygments-main/pygments/lexers/hdl.py +356 -0
  102. data/vendor/pygments-main/pygments/lexers/jvm.py +1112 -0
  103. data/vendor/pygments-main/pygments/lexers/math.py +1918 -0
  104. data/vendor/pygments-main/pygments/lexers/other.py +3778 -0
  105. data/vendor/pygments-main/pygments/lexers/parsers.py +778 -0
  106. data/vendor/pygments-main/pygments/lexers/shell.py +424 -0
  107. data/vendor/pygments-main/pygments/lexers/special.py +100 -0
  108. data/vendor/pygments-main/pygments/lexers/sql.py +559 -0
  109. data/vendor/pygments-main/pygments/lexers/templates.py +1742 -0
  110. data/vendor/pygments-main/pygments/lexers/text.py +1893 -0
  111. data/vendor/pygments-main/pygments/lexers/web.py +4045 -0
  112. data/vendor/pygments-main/pygments/modeline.py +40 -0
  113. data/vendor/pygments-main/pygments/plugin.py +74 -0
  114. data/vendor/pygments-main/pygments/scanner.py +104 -0
  115. data/vendor/pygments-main/pygments/style.py +117 -0
  116. data/vendor/pygments-main/pygments/styles/__init__.py +70 -0
  117. data/vendor/pygments-main/pygments/styles/autumn.py +65 -0
  118. data/vendor/pygments-main/pygments/styles/borland.py +51 -0
  119. data/vendor/pygments-main/pygments/styles/bw.py +49 -0
  120. data/vendor/pygments-main/pygments/styles/colorful.py +81 -0
  121. data/vendor/pygments-main/pygments/styles/default.py +73 -0
  122. data/vendor/pygments-main/pygments/styles/emacs.py +72 -0
  123. data/vendor/pygments-main/pygments/styles/friendly.py +72 -0
  124. data/vendor/pygments-main/pygments/styles/fruity.py +42 -0
  125. data/vendor/pygments-main/pygments/styles/manni.py +75 -0
  126. data/vendor/pygments-main/pygments/styles/monokai.py +106 -0
  127. data/vendor/pygments-main/pygments/styles/murphy.py +80 -0
  128. data/vendor/pygments-main/pygments/styles/native.py +65 -0
  129. data/vendor/pygments-main/pygments/styles/pastie.py +75 -0
  130. data/vendor/pygments-main/pygments/styles/perldoc.py +69 -0
  131. data/vendor/pygments-main/pygments/styles/rrt.py +33 -0
  132. data/vendor/pygments-main/pygments/styles/tango.py +141 -0
  133. data/vendor/pygments-main/pygments/styles/trac.py +63 -0
  134. data/vendor/pygments-main/pygments/styles/vim.py +63 -0
  135. data/vendor/pygments-main/pygments/styles/vs.py +38 -0
  136. data/vendor/pygments-main/pygments/token.py +195 -0
  137. data/vendor/pygments-main/pygments/unistring.py +140 -0
  138. data/vendor/pygments-main/pygments/util.py +277 -0
  139. data/vendor/pygments-main/scripts/check_sources.py +242 -0
  140. data/vendor/pygments-main/scripts/detect_missing_analyse_text.py +32 -0
  141. data/vendor/pygments-main/scripts/epydoc.css +280 -0
  142. data/vendor/pygments-main/scripts/find_codetags.py +205 -0
  143. data/vendor/pygments-main/scripts/find_error.py +170 -0
  144. data/vendor/pygments-main/scripts/get_vimkw.py +43 -0
  145. data/vendor/pygments-main/scripts/pylintrc +301 -0
  146. data/vendor/pygments-main/scripts/reindent.py +291 -0
  147. data/vendor/pygments-main/scripts/vim2pygments.py +933 -0
  148. data/vendor/pygments-main/setup.cfg +7 -0
  149. data/vendor/pygments-main/setup.py +90 -0
  150. data/vendor/pygments-main/tests/dtds/HTML4-f.dtd +37 -0
  151. data/vendor/pygments-main/tests/dtds/HTML4-s.dtd +869 -0
  152. data/vendor/pygments-main/tests/dtds/HTML4.dcl +88 -0
  153. data/vendor/pygments-main/tests/dtds/HTML4.dtd +1092 -0
  154. data/vendor/pygments-main/tests/dtds/HTML4.soc +9 -0
  155. data/vendor/pygments-main/tests/dtds/HTMLlat1.ent +195 -0
  156. data/vendor/pygments-main/tests/dtds/HTMLspec.ent +77 -0
  157. data/vendor/pygments-main/tests/dtds/HTMLsym.ent +241 -0
  158. data/vendor/pygments-main/tests/examplefiles/ANTLRv3.g +608 -0
  159. data/vendor/pygments-main/tests/examplefiles/AcidStateAdvanced.hs +209 -0
  160. data/vendor/pygments-main/tests/examplefiles/AlternatingGroup.mu +102 -0
  161. data/vendor/pygments-main/tests/examplefiles/BOM.js +1 -0
  162. data/vendor/pygments-main/tests/examplefiles/CPDictionary.j +611 -0
  163. data/vendor/pygments-main/tests/examplefiles/Config.in.cache +1973 -0
  164. data/vendor/pygments-main/tests/examplefiles/Constants.mo +158 -0
  165. data/vendor/pygments-main/tests/examplefiles/DancingSudoku.lhs +411 -0
  166. data/vendor/pygments-main/tests/examplefiles/Deflate.fs +578 -0
  167. data/vendor/pygments-main/tests/examplefiles/Errors.scala +18 -0
  168. data/vendor/pygments-main/tests/examplefiles/File.hy +174 -0
  169. data/vendor/pygments-main/tests/examplefiles/Get-CommandDefinitionHtml.ps1 +66 -0
  170. data/vendor/pygments-main/tests/examplefiles/IPDispatchC.nc +104 -0
  171. data/vendor/pygments-main/tests/examplefiles/IPDispatchP.nc +671 -0
  172. data/vendor/pygments-main/tests/examplefiles/Intro.java +1660 -0
  173. data/vendor/pygments-main/tests/examplefiles/Makefile +1131 -0
  174. data/vendor/pygments-main/tests/examplefiles/Object.st +4394 -0
  175. data/vendor/pygments-main/tests/examplefiles/OrderedMap.hx +584 -0
  176. data/vendor/pygments-main/tests/examplefiles/RoleQ.pm6 +23 -0
  177. data/vendor/pygments-main/tests/examplefiles/SmallCheck.hs +378 -0
  178. data/vendor/pygments-main/tests/examplefiles/Sorting.mod +470 -0
  179. data/vendor/pygments-main/tests/examplefiles/Sudoku.lhs +382 -0
  180. data/vendor/pygments-main/tests/examplefiles/addressbook.proto +30 -0
  181. data/vendor/pygments-main/tests/examplefiles/antlr_throws +1 -0
  182. data/vendor/pygments-main/tests/examplefiles/apache2.conf +393 -0
  183. data/vendor/pygments-main/tests/examplefiles/as3_test.as +143 -0
  184. data/vendor/pygments-main/tests/examplefiles/as3_test2.as +46 -0
  185. data/vendor/pygments-main/tests/examplefiles/as3_test3.as +3 -0
  186. data/vendor/pygments-main/tests/examplefiles/aspx-cs_example +27 -0
  187. data/vendor/pygments-main/tests/examplefiles/autoit_submit.au3 +25 -0
  188. data/vendor/pygments-main/tests/examplefiles/badcase.java +2 -0
  189. data/vendor/pygments-main/tests/examplefiles/batchfile.bat +49 -0
  190. data/vendor/pygments-main/tests/examplefiles/bigtest.nsi +308 -0
  191. data/vendor/pygments-main/tests/examplefiles/boot-9.scm +1557 -0
  192. data/vendor/pygments-main/tests/examplefiles/ca65_example +284 -0
  193. data/vendor/pygments-main/tests/examplefiles/cbmbas_example +9 -0
  194. data/vendor/pygments-main/tests/examplefiles/cells.ps +515 -0
  195. data/vendor/pygments-main/tests/examplefiles/ceval.c +2604 -0
  196. data/vendor/pygments-main/tests/examplefiles/cheetah_example.html +13 -0
  197. data/vendor/pygments-main/tests/examplefiles/classes.dylan +125 -0
  198. data/vendor/pygments-main/tests/examplefiles/condensed_ruby.rb +10 -0
  199. data/vendor/pygments-main/tests/examplefiles/coq_RelationClasses +447 -0
  200. data/vendor/pygments-main/tests/examplefiles/database.pytb +20 -0
  201. data/vendor/pygments-main/tests/examplefiles/de.MoinMoin.po +2461 -0
  202. data/vendor/pygments-main/tests/examplefiles/demo.ahk +181 -0
  203. data/vendor/pygments-main/tests/examplefiles/demo.cfm +38 -0
  204. data/vendor/pygments-main/tests/examplefiles/django_sample.html+django +68 -0
  205. data/vendor/pygments-main/tests/examplefiles/dwarf.cw +17 -0
  206. data/vendor/pygments-main/tests/examplefiles/erl_session +10 -0
  207. data/vendor/pygments-main/tests/examplefiles/escape_semicolon.clj +1 -0
  208. data/vendor/pygments-main/tests/examplefiles/evil_regex.js +48 -0
  209. data/vendor/pygments-main/tests/examplefiles/example.Rd +78 -0
  210. data/vendor/pygments-main/tests/examplefiles/example.bug +54 -0
  211. data/vendor/pygments-main/tests/examplefiles/example.c +2080 -0
  212. data/vendor/pygments-main/tests/examplefiles/example.ceylon +52 -0
  213. data/vendor/pygments-main/tests/examplefiles/example.clay +33 -0
  214. data/vendor/pygments-main/tests/examplefiles/example.cls +15 -0
  215. data/vendor/pygments-main/tests/examplefiles/example.cob +3556 -0
  216. data/vendor/pygments-main/tests/examplefiles/example.cpp +2363 -0
  217. data/vendor/pygments-main/tests/examplefiles/example.gs +106 -0
  218. data/vendor/pygments-main/tests/examplefiles/example.gst +7 -0
  219. data/vendor/pygments-main/tests/examplefiles/example.hx +142 -0
  220. data/vendor/pygments-main/tests/examplefiles/example.jag +48 -0
  221. data/vendor/pygments-main/tests/examplefiles/example.kt +47 -0
  222. data/vendor/pygments-main/tests/examplefiles/example.lagda +19 -0
  223. data/vendor/pygments-main/tests/examplefiles/example.lua +250 -0
  224. data/vendor/pygments-main/tests/examplefiles/example.monkey +152 -0
  225. data/vendor/pygments-main/tests/examplefiles/example.moo +26 -0
  226. data/vendor/pygments-main/tests/examplefiles/example.moon +629 -0
  227. data/vendor/pygments-main/tests/examplefiles/example.msc +43 -0
  228. data/vendor/pygments-main/tests/examplefiles/example.nim +1010 -0
  229. data/vendor/pygments-main/tests/examplefiles/example.ns2 +69 -0
  230. data/vendor/pygments-main/tests/examplefiles/example.p +34 -0
  231. data/vendor/pygments-main/tests/examplefiles/example.pas +2708 -0
  232. data/vendor/pygments-main/tests/examplefiles/example.prg +161 -0
  233. data/vendor/pygments-main/tests/examplefiles/example.rb +1852 -0
  234. data/vendor/pygments-main/tests/examplefiles/example.reg +19 -0
  235. data/vendor/pygments-main/tests/examplefiles/example.rexx +50 -0
  236. data/vendor/pygments-main/tests/examplefiles/example.rhtml +561 -0
  237. data/vendor/pygments-main/tests/examplefiles/example.rkt +95 -0
  238. data/vendor/pygments-main/tests/examplefiles/example.rpf +4 -0
  239. data/vendor/pygments-main/tests/examplefiles/example.sh-session +19 -0
  240. data/vendor/pygments-main/tests/examplefiles/example.shell-session +45 -0
  241. data/vendor/pygments-main/tests/examplefiles/example.sml +156 -0
  242. data/vendor/pygments-main/tests/examplefiles/example.snobol +15 -0
  243. data/vendor/pygments-main/tests/examplefiles/example.stan +108 -0
  244. data/vendor/pygments-main/tests/examplefiles/example.tea +34 -0
  245. data/vendor/pygments-main/tests/examplefiles/example.ts +28 -0
  246. data/vendor/pygments-main/tests/examplefiles/example.u +548 -0
  247. data/vendor/pygments-main/tests/examplefiles/example.weechatlog +9 -0
  248. data/vendor/pygments-main/tests/examplefiles/example.xhtml +376 -0
  249. data/vendor/pygments-main/tests/examplefiles/example.xtend +34 -0
  250. data/vendor/pygments-main/tests/examplefiles/example.yaml +302 -0
  251. data/vendor/pygments-main/tests/examplefiles/example2.aspx +29 -0
  252. data/vendor/pygments-main/tests/examplefiles/example2.msc +79 -0
  253. data/vendor/pygments-main/tests/examplefiles/example_elixir.ex +363 -0
  254. data/vendor/pygments-main/tests/examplefiles/example_file.fy +128 -0
  255. data/vendor/pygments-main/tests/examplefiles/firefox.mak +586 -0
  256. data/vendor/pygments-main/tests/examplefiles/flipflop.sv +19 -0
  257. data/vendor/pygments-main/tests/examplefiles/foo.sce +6 -0
  258. data/vendor/pygments-main/tests/examplefiles/format.ml +1213 -0
  259. data/vendor/pygments-main/tests/examplefiles/fucked_up.rb +77 -0
  260. data/vendor/pygments-main/tests/examplefiles/function.mu +1 -0
  261. data/vendor/pygments-main/tests/examplefiles/functional.rst +1472 -0
  262. data/vendor/pygments-main/tests/examplefiles/garcia-wachs.kk +133 -0
  263. data/vendor/pygments-main/tests/examplefiles/genclass.clj +510 -0
  264. data/vendor/pygments-main/tests/examplefiles/genshi_example.xml+genshi +193 -0
  265. data/vendor/pygments-main/tests/examplefiles/genshitext_example.genshitext +33 -0
  266. data/vendor/pygments-main/tests/examplefiles/glsl.frag +7 -0
  267. data/vendor/pygments-main/tests/examplefiles/glsl.vert +13 -0
  268. data/vendor/pygments-main/tests/examplefiles/grammar-test.p6 +22 -0
  269. data/vendor/pygments-main/tests/examplefiles/hello.smali +40 -0
  270. data/vendor/pygments-main/tests/examplefiles/hello.sp +9 -0
  271. data/vendor/pygments-main/tests/examplefiles/html+php_faulty.php +1 -0
  272. data/vendor/pygments-main/tests/examplefiles/http_request_example +15 -0
  273. data/vendor/pygments-main/tests/examplefiles/http_response_example +29 -0
  274. data/vendor/pygments-main/tests/examplefiles/import.hs +4 -0
  275. data/vendor/pygments-main/tests/examplefiles/inet_pton6.dg +71 -0
  276. data/vendor/pygments-main/tests/examplefiles/intro.ik +24 -0
  277. data/vendor/pygments-main/tests/examplefiles/ints.php +10 -0
  278. data/vendor/pygments-main/tests/examplefiles/intsyn.fun +675 -0
  279. data/vendor/pygments-main/tests/examplefiles/intsyn.sig +286 -0
  280. data/vendor/pygments-main/tests/examplefiles/irb_heredoc +8 -0
  281. data/vendor/pygments-main/tests/examplefiles/irc.lsp +214 -0
  282. data/vendor/pygments-main/tests/examplefiles/java.properties +16 -0
  283. data/vendor/pygments-main/tests/examplefiles/jbst_example1.jbst +28 -0
  284. data/vendor/pygments-main/tests/examplefiles/jbst_example2.jbst +45 -0
  285. data/vendor/pygments-main/tests/examplefiles/jinjadesignerdoc.rst +713 -0
  286. data/vendor/pygments-main/tests/examplefiles/json.lasso +301 -0
  287. data/vendor/pygments-main/tests/examplefiles/json.lasso9 +213 -0
  288. data/vendor/pygments-main/tests/examplefiles/lighttpd_config.conf +13 -0
  289. data/vendor/pygments-main/tests/examplefiles/linecontinuation.py +47 -0
  290. data/vendor/pygments-main/tests/examplefiles/livescript-demo.ls +41 -0
  291. data/vendor/pygments-main/tests/examplefiles/logos_example.xm +28 -0
  292. data/vendor/pygments-main/tests/examplefiles/ltmain.sh +2849 -0
  293. data/vendor/pygments-main/tests/examplefiles/main.cmake +42 -0
  294. data/vendor/pygments-main/tests/examplefiles/markdown.lsp +679 -0
  295. data/vendor/pygments-main/tests/examplefiles/matlab_noreturn +3 -0
  296. data/vendor/pygments-main/tests/examplefiles/matlab_sample +30 -0
  297. data/vendor/pygments-main/tests/examplefiles/matlabsession_sample.txt +37 -0
  298. data/vendor/pygments-main/tests/examplefiles/metagrammar.treetop +455 -0
  299. data/vendor/pygments-main/tests/examplefiles/mg_sample.pro +73 -0
  300. data/vendor/pygments-main/tests/examplefiles/minehunt.qml +112 -0
  301. data/vendor/pygments-main/tests/examplefiles/minimal.ns2 +4 -0
  302. data/vendor/pygments-main/tests/examplefiles/moin_SyntaxReference.txt +340 -0
  303. data/vendor/pygments-main/tests/examplefiles/multiline_regexes.rb +38 -0
  304. data/vendor/pygments-main/tests/examplefiles/nanomsg.intr +95 -0
  305. data/vendor/pygments-main/tests/examplefiles/nasm_aoutso.asm +96 -0
  306. data/vendor/pygments-main/tests/examplefiles/nasm_objexe.asm +30 -0
  307. data/vendor/pygments-main/tests/examplefiles/nemerle_sample.n +87 -0
  308. data/vendor/pygments-main/tests/examplefiles/nginx_nginx.conf +118 -0
  309. data/vendor/pygments-main/tests/examplefiles/numbers.c +12 -0
  310. data/vendor/pygments-main/tests/examplefiles/objc_example.m +32 -0
  311. data/vendor/pygments-main/tests/examplefiles/objc_example2.m +24 -0
  312. data/vendor/pygments-main/tests/examplefiles/perl_misc +62 -0
  313. data/vendor/pygments-main/tests/examplefiles/perl_perl5db +998 -0
  314. data/vendor/pygments-main/tests/examplefiles/perl_regex-delims +120 -0
  315. data/vendor/pygments-main/tests/examplefiles/perlfunc.1 +856 -0
  316. data/vendor/pygments-main/tests/examplefiles/phpMyAdmin.spec +163 -0
  317. data/vendor/pygments-main/tests/examplefiles/phpcomplete.vim +567 -0
  318. data/vendor/pygments-main/tests/examplefiles/pleac.in.rb +1223 -0
  319. data/vendor/pygments-main/tests/examplefiles/postgresql_test.txt +47 -0
  320. data/vendor/pygments-main/tests/examplefiles/pppoe.applescript +10 -0
  321. data/vendor/pygments-main/tests/examplefiles/psql_session.txt +122 -0
  322. data/vendor/pygments-main/tests/examplefiles/py3_test.txt +2 -0
  323. data/vendor/pygments-main/tests/examplefiles/py3tb_test.py3tb +4 -0
  324. data/vendor/pygments-main/tests/examplefiles/pycon_test.pycon +14 -0
  325. data/vendor/pygments-main/tests/examplefiles/pytb_test2.pytb +2 -0
  326. data/vendor/pygments-main/tests/examplefiles/pytb_test3.pytb +4 -0
  327. data/vendor/pygments-main/tests/examplefiles/python25-bsd.mak +234 -0
  328. data/vendor/pygments-main/tests/examplefiles/qsort.prolog +13 -0
  329. data/vendor/pygments-main/tests/examplefiles/r-console-transcript.Rout +38 -0
  330. data/vendor/pygments-main/tests/examplefiles/ragel-cpp_rlscan +280 -0
  331. data/vendor/pygments-main/tests/examplefiles/ragel-cpp_snippet +2 -0
  332. data/vendor/pygments-main/tests/examplefiles/regex.js +22 -0
  333. data/vendor/pygments-main/tests/examplefiles/reversi.lsp +427 -0
  334. data/vendor/pygments-main/tests/examplefiles/robotframework.txt +39 -0
  335. data/vendor/pygments-main/tests/examplefiles/ruby_func_def.rb +11 -0
  336. data/vendor/pygments-main/tests/examplefiles/rust_example.rs +233 -0
  337. data/vendor/pygments-main/tests/examplefiles/scilab.sci +30 -0
  338. data/vendor/pygments-main/tests/examplefiles/session.dylan-console +9 -0
  339. data/vendor/pygments-main/tests/examplefiles/sibling.prolog +19 -0
  340. data/vendor/pygments-main/tests/examplefiles/simple.md +747 -0
  341. data/vendor/pygments-main/tests/examplefiles/smarty_example.html +209 -0
  342. data/vendor/pygments-main/tests/examplefiles/source.lgt +343 -0
  343. data/vendor/pygments-main/tests/examplefiles/sources.list +62 -0
  344. data/vendor/pygments-main/tests/examplefiles/sphere.pov +18 -0
  345. data/vendor/pygments-main/tests/examplefiles/sqlite3.sqlite3-console +27 -0
  346. data/vendor/pygments-main/tests/examplefiles/squid.conf +30 -0
  347. data/vendor/pygments-main/tests/examplefiles/string.jl +1031 -0
  348. data/vendor/pygments-main/tests/examplefiles/string_delimiters.d +21 -0
  349. data/vendor/pygments-main/tests/examplefiles/stripheredoc.sh +3 -0
  350. data/vendor/pygments-main/tests/examplefiles/swig_java.swg +1329 -0
  351. data/vendor/pygments-main/tests/examplefiles/swig_std_vector.i +225 -0
  352. data/vendor/pygments-main/tests/examplefiles/test.R +153 -0
  353. data/vendor/pygments-main/tests/examplefiles/test.adb +211 -0
  354. data/vendor/pygments-main/tests/examplefiles/test.agda +102 -0
  355. data/vendor/pygments-main/tests/examplefiles/test.asy +131 -0
  356. data/vendor/pygments-main/tests/examplefiles/test.awk +121 -0
  357. data/vendor/pygments-main/tests/examplefiles/test.bas +29 -0
  358. data/vendor/pygments-main/tests/examplefiles/test.bb +95 -0
  359. data/vendor/pygments-main/tests/examplefiles/test.bmx +145 -0
  360. data/vendor/pygments-main/tests/examplefiles/test.boo +39 -0
  361. data/vendor/pygments-main/tests/examplefiles/test.bro +250 -0
  362. data/vendor/pygments-main/tests/examplefiles/test.cs +374 -0
  363. data/vendor/pygments-main/tests/examplefiles/test.css +54 -0
  364. data/vendor/pygments-main/tests/examplefiles/test.cu +36 -0
  365. data/vendor/pygments-main/tests/examplefiles/test.d +135 -0
  366. data/vendor/pygments-main/tests/examplefiles/test.dart +23 -0
  367. data/vendor/pygments-main/tests/examplefiles/test.dtd +89 -0
  368. data/vendor/pygments-main/tests/examplefiles/test.ebnf +31 -0
  369. data/vendor/pygments-main/tests/examplefiles/test.ec +605 -0
  370. data/vendor/pygments-main/tests/examplefiles/test.ecl +58 -0
  371. data/vendor/pygments-main/tests/examplefiles/test.eh +315 -0
  372. data/vendor/pygments-main/tests/examplefiles/test.erl +169 -0
  373. data/vendor/pygments-main/tests/examplefiles/test.evoque +33 -0
  374. data/vendor/pygments-main/tests/examplefiles/test.fan +818 -0
  375. data/vendor/pygments-main/tests/examplefiles/test.flx +57 -0
  376. data/vendor/pygments-main/tests/examplefiles/test.gdc +13 -0
  377. data/vendor/pygments-main/tests/examplefiles/test.groovy +97 -0
  378. data/vendor/pygments-main/tests/examplefiles/test.html +339 -0
  379. data/vendor/pygments-main/tests/examplefiles/test.ini +10 -0
  380. data/vendor/pygments-main/tests/examplefiles/test.java +653 -0
  381. data/vendor/pygments-main/tests/examplefiles/test.jsp +24 -0
  382. data/vendor/pygments-main/tests/examplefiles/test.maql +45 -0
  383. data/vendor/pygments-main/tests/examplefiles/test.mod +374 -0
  384. data/vendor/pygments-main/tests/examplefiles/test.moo +51 -0
  385. data/vendor/pygments-main/tests/examplefiles/test.myt +166 -0
  386. data/vendor/pygments-main/tests/examplefiles/test.nim +93 -0
  387. data/vendor/pygments-main/tests/examplefiles/test.opa +10 -0
  388. data/vendor/pygments-main/tests/examplefiles/test.p6 +252 -0
  389. data/vendor/pygments-main/tests/examplefiles/test.pas +743 -0
  390. data/vendor/pygments-main/tests/examplefiles/test.php +505 -0
  391. data/vendor/pygments-main/tests/examplefiles/test.plot +333 -0
  392. data/vendor/pygments-main/tests/examplefiles/test.ps1 +108 -0
  393. data/vendor/pygments-main/tests/examplefiles/test.pypylog +1839 -0
  394. data/vendor/pygments-main/tests/examplefiles/test.r3 +94 -0
  395. data/vendor/pygments-main/tests/examplefiles/test.rb +177 -0
  396. data/vendor/pygments-main/tests/examplefiles/test.rhtml +43 -0
  397. data/vendor/pygments-main/tests/examplefiles/test.scaml +8 -0
  398. data/vendor/pygments-main/tests/examplefiles/test.ssp +12 -0
  399. data/vendor/pygments-main/tests/examplefiles/test.tcsh +830 -0
  400. data/vendor/pygments-main/tests/examplefiles/test.vb +407 -0
  401. data/vendor/pygments-main/tests/examplefiles/test.vhdl +161 -0
  402. data/vendor/pygments-main/tests/examplefiles/test.xqy +138 -0
  403. data/vendor/pygments-main/tests/examplefiles/test.xsl +23 -0
  404. data/vendor/pygments-main/tests/examplefiles/test2.pypylog +120 -0
  405. data/vendor/pygments-main/tests/examplefiles/truncated.pytb +15 -0
  406. data/vendor/pygments-main/tests/examplefiles/type.lisp +1218 -0
  407. data/vendor/pygments-main/tests/examplefiles/underscore.coffee +603 -0
  408. data/vendor/pygments-main/tests/examplefiles/unicode.applescript +5 -0
  409. data/vendor/pygments-main/tests/examplefiles/unicodedoc.py +11 -0
  410. data/vendor/pygments-main/tests/examplefiles/unix-io.lid +37 -0
  411. data/vendor/pygments-main/tests/examplefiles/webkit-transition.css +3 -0
  412. data/vendor/pygments-main/tests/examplefiles/while.pov +13 -0
  413. data/vendor/pygments-main/tests/examplefiles/wiki.factor +384 -0
  414. data/vendor/pygments-main/tests/examplefiles/xml_example +1897 -0
  415. data/vendor/pygments-main/tests/examplefiles/zmlrpc.f90 +798 -0
  416. data/vendor/pygments-main/tests/old_run.py +138 -0
  417. data/vendor/pygments-main/tests/run.py +49 -0
  418. data/vendor/pygments-main/tests/support.py +15 -0
  419. data/vendor/pygments-main/tests/support/tags +36 -0
  420. data/vendor/pygments-main/tests/test_basic_api.py +295 -0
  421. data/vendor/pygments-main/tests/test_clexer.py +31 -0
  422. data/vendor/pygments-main/tests/test_cmdline.py +105 -0
  423. data/vendor/pygments-main/tests/test_examplefiles.py +99 -0
  424. data/vendor/pygments-main/tests/test_html_formatter.py +178 -0
  425. data/vendor/pygments-main/tests/test_latex_formatter.py +55 -0
  426. data/vendor/pygments-main/tests/test_lexers_other.py +68 -0
  427. data/vendor/pygments-main/tests/test_perllexer.py +137 -0
  428. data/vendor/pygments-main/tests/test_regexlexer.py +47 -0
  429. data/vendor/pygments-main/tests/test_token.py +46 -0
  430. data/vendor/pygments-main/tests/test_using_api.py +40 -0
  431. data/vendor/pygments-main/tests/test_util.py +135 -0
  432. data/vendor/simplejson/.gitignore +10 -0
  433. data/vendor/simplejson/.travis.yml +5 -0
  434. data/vendor/simplejson/CHANGES.txt +291 -0
  435. data/vendor/simplejson/LICENSE.txt +19 -0
  436. data/vendor/simplejson/MANIFEST.in +5 -0
  437. data/vendor/simplejson/README.rst +19 -0
  438. data/vendor/simplejson/conf.py +179 -0
  439. data/vendor/simplejson/index.rst +628 -0
  440. data/vendor/simplejson/scripts/make_docs.py +18 -0
  441. data/vendor/simplejson/setup.py +104 -0
  442. data/vendor/simplejson/simplejson/__init__.py +510 -0
  443. data/vendor/simplejson/simplejson/_speedups.c +2745 -0
  444. data/vendor/simplejson/simplejson/decoder.py +425 -0
  445. data/vendor/simplejson/simplejson/encoder.py +567 -0
  446. data/vendor/simplejson/simplejson/ordered_dict.py +119 -0
  447. data/vendor/simplejson/simplejson/scanner.py +77 -0
  448. data/vendor/simplejson/simplejson/tests/__init__.py +67 -0
  449. data/vendor/simplejson/simplejson/tests/test_bigint_as_string.py +55 -0
  450. data/vendor/simplejson/simplejson/tests/test_check_circular.py +30 -0
  451. data/vendor/simplejson/simplejson/tests/test_decimal.py +66 -0
  452. data/vendor/simplejson/simplejson/tests/test_decode.py +83 -0
  453. data/vendor/simplejson/simplejson/tests/test_default.py +9 -0
  454. data/vendor/simplejson/simplejson/tests/test_dump.py +67 -0
  455. data/vendor/simplejson/simplejson/tests/test_encode_basestring_ascii.py +46 -0
  456. data/vendor/simplejson/simplejson/tests/test_encode_for_html.py +32 -0
  457. data/vendor/simplejson/simplejson/tests/test_errors.py +34 -0
  458. data/vendor/simplejson/simplejson/tests/test_fail.py +91 -0
  459. data/vendor/simplejson/simplejson/tests/test_float.py +19 -0
  460. data/vendor/simplejson/simplejson/tests/test_indent.py +86 -0
  461. data/vendor/simplejson/simplejson/tests/test_item_sort_key.py +20 -0
  462. data/vendor/simplejson/simplejson/tests/test_namedtuple.py +121 -0
  463. data/vendor/simplejson/simplejson/tests/test_pass1.py +76 -0
  464. data/vendor/simplejson/simplejson/tests/test_pass2.py +14 -0
  465. data/vendor/simplejson/simplejson/tests/test_pass3.py +20 -0
  466. data/vendor/simplejson/simplejson/tests/test_recursion.py +67 -0
  467. data/vendor/simplejson/simplejson/tests/test_scanstring.py +117 -0
  468. data/vendor/simplejson/simplejson/tests/test_separators.py +42 -0
  469. data/vendor/simplejson/simplejson/tests/test_speedups.py +20 -0
  470. data/vendor/simplejson/simplejson/tests/test_tuple.py +49 -0
  471. data/vendor/simplejson/simplejson/tests/test_unicode.py +109 -0
  472. data/vendor/simplejson/simplejson/tool.py +39 -0
  473. metadata +557 -0
@@ -0,0 +1,161 @@
1
+ && This is a concatenation of all VFP examples on Wikipedia.
2
+ && Copyright 2013 Wikimedia, under the GFDL.
3
+
4
+ FOR i = 1 to 10
5
+ x = x + 6.5
6
+ ENDFOR
7
+
8
+ IF i = 25
9
+ i = i + 1
10
+ ELSE
11
+ i = i + 3
12
+ ENDIF
13
+
14
+ x = 1
15
+ DO WHILE x < 50
16
+ x = x + 1
17
+ ENDDO
18
+
19
+ x = 1
20
+ DO WHILE .T.
21
+ x = x + 1
22
+ IF x < 50
23
+ LOOP
24
+ ELSE
25
+ EXIT
26
+ ENDIF
27
+ ENDDO
28
+
29
+ nMonth = MONTH(DATE())
30
+ DO CASE
31
+ CASE nMonth <= 3
32
+ MESSAGEBOX("Q1")
33
+
34
+ CASE nMonth <= 6
35
+ MESSAGEBOX("Q2")
36
+
37
+ CASE nMonth <= 9
38
+ MESSAGEBOX("Q3")
39
+
40
+ OTHERWISE
41
+ MESSAGEBOX("Q4")
42
+ ENDCASE
43
+
44
+ FOR EACH oControl IN THISFORM.Controls
45
+ MESSAGEBOX(oControl.Name)
46
+ ENDFOR
47
+
48
+ f = Factorial(10)
49
+
50
+ FUNCTION Factorial(n)
51
+ LOCAL i,r
52
+ r = 1
53
+ FOR i = n TO 1 STEP -1
54
+ r = r * n
55
+ ENDFOR
56
+ RETURN r
57
+ ENDFUNC
58
+
59
+ loForm = CREATEOBJECT("HiForm")
60
+ loForm.Show(1)
61
+
62
+ DEFINE CLASS HiForm AS Form
63
+ AutoCenter = .T.
64
+ Caption = "Hello, World"
65
+
66
+ ADD OBJECT lblHi as Label WITH ;
67
+ Caption = "Hello, World!"
68
+ ENDDEFINE
69
+
70
+ loMine = CREATEOBJECT("MyClass")
71
+ ? loMine.cProp1 && This will work. (Double-ampersand marks an end-of-line comment)
72
+ ? loMine.cProp2 && Program Error: Property CPROP2 is not found.
73
+
74
+ ? loMine.MyMethod1() && This will work.
75
+ ? loMine.MyMethod2() && Program Error: Property MYMETHOD2 is not found.
76
+
77
+ DEFINE CLASS MyClass AS Custom
78
+ cProp1 = "My Property" && This is a public property
79
+ HIDDEN cProp2 && This is a private (hidden) property
80
+ dProp3 = {} && Another public property
81
+
82
+ PROCEDURE Init() && Class constructor
83
+ This.cProp2 = "This is a hidden property."
84
+ ENDPROC
85
+
86
+ PROCEDURE dProp3_Access && Property Getter
87
+ RETURN DATE()
88
+ ENDPROC
89
+ PROCEDURE dProp3_Assign(vNewVal) && Property Setter
90
+ IF VARTYPE(vNewVal) = "D"
91
+ THIS.dProp3 = vNewVal
92
+ ENDIF
93
+ ENDPROC
94
+
95
+ PROCEDURE MyMethod1()
96
+ * This is a public method, calling a hidden method that returns
97
+ * the value of a hidden property.
98
+ RETURN This.MyMethod2()
99
+ ENDPROC
100
+
101
+ HIDDEN PROCEDURE MyMethod2() && This is a private (hidden) method
102
+ RETURN This.cProp2
103
+ ENDPROC
104
+ ENDDEFINE
105
+
106
+ && Create a table
107
+ CREATE TABLE randData (iData I)
108
+
109
+ && Populate with random data using xBase and SQL DML commands
110
+ FOR i = 1 TO 50
111
+ APPEND BLANK
112
+ REPLACE iData WITH (RAND() * 100)
113
+
114
+ INSERT INTO randData (iData) VALUES (RAND() * 100)
115
+ ENDFOR
116
+
117
+ && Place a structural index on the data
118
+ INDEX ON iData TAG iData
119
+ CLOSE ALL
120
+
121
+ && Display ordered data using xBase-style commands
122
+ USE randData
123
+ SET ORDER TO iData
124
+ GO TOP
125
+ LIST NEXT 10 && First 10
126
+ GO BOTTOM
127
+ SKIP -10
128
+ LIST REST && Last 10
129
+ CLOSE ALL
130
+
131
+ && Browse ordered data using SQL DML commands
132
+ SELECT * ;
133
+ FROM randData ;
134
+ ORDER BY iData DESCENDING
135
+
136
+
137
+ && Connect to an ODBC data source
138
+ LOCAL nHnd
139
+ nHnd = SQLCONNECT ("ODBCDSN", "user", "pwd")
140
+
141
+ && Execute a SQL command
142
+ LOCAL nResult
143
+ nResult = SQLEXEC (nHnd, "USE master")
144
+ IF nResult < 0
145
+ MESSAGEBOX ("MASTER database does not exist!")
146
+ RETURN
147
+ ENDIF
148
+
149
+ && Retrieve data from the remote server and stores it in
150
+ && a local data cursor
151
+ nResult = SQLEXEC (nHnd, "SELECT * FROM authors", "QAUTHORS")
152
+
153
+ && Update a record in a remote table using parameters
154
+ PRIVATE cAuthorID, cAuthorName
155
+ cAuthorID = "1001"
156
+ cAuthorName = "New name"
157
+ nResult = SQLEXEC (nHnd, "UPDATE authors SET auth_name = ?cAuthorName WHERE auth_id = ?cAuthorID")
158
+
159
+ && Close the connection
160
+ SQLDISCONNECT(nHnd)
161
+
@@ -0,0 +1,1852 @@
1
+ module CodeRay
2
+ module Scanners
3
+
4
+ class Ruby < Scanner
5
+
6
+ RESERVED_WORDS = [
7
+ 'and', 'def', 'end', 'in', 'or', 'unless', 'begin',
8
+ 'defined?', 'ensure', 'module', 'redo', 'super', 'until',
9
+ 'BEGIN', 'break', 'do', 'next', 'rescue', 'then',
10
+ 'when', 'END', 'case', 'else', 'for', 'retry',
11
+ 'while', 'alias', 'class', 'elsif', 'if', 'not', 'return',
12
+ 'undef', 'yield',
13
+ ]
14
+
15
+ DEF_KEYWORDS = ['def']
16
+ MODULE_KEYWORDS = ['class', 'module']
17
+ DEF_NEW_STATE = WordList.new(:initial).
18
+ add(DEF_KEYWORDS, :def_expected).
19
+ add(MODULE_KEYWORDS, :module_expected)
20
+
21
+ WORDS_ALLOWING_REGEXP = [
22
+ 'and', 'or', 'not', 'while', 'until', 'unless', 'if', 'elsif', 'when'
23
+ ]
24
+ REGEXP_ALLOWED = WordList.new(false).
25
+ add(WORDS_ALLOWING_REGEXP, :set)
26
+
27
+ PREDEFINED_CONSTANTS = [
28
+ 'nil', 'true', 'false', 'self',
29
+ 'DATA', 'ARGV', 'ARGF', '__FILE__', '__LINE__',
30
+ ]
31
+
32
+ IDENT_KIND = WordList.new(:ident).
33
+ add(RESERVED_WORDS, :reserved).
34
+ add(PREDEFINED_CONSTANTS, :pre_constant)
35
+
36
+ METHOD_NAME = / #{IDENT} [?!]? /xo
37
+ METHOD_NAME_EX = /
38
+ #{METHOD_NAME} # common methods: split, foo=, empty?, gsub!
39
+ | \*\*? # multiplication and power
40
+ | [-+~]@? # plus, minus
41
+ | [\/%&|^`] # division, modulo or format strings, &and, |or, ^xor, `system`
42
+ | \[\]=? # array getter and setter
43
+ | <=?>? | >=? # comparison, rocket operator
44
+ | << | >> # append or shift left, shift right
45
+ | ===? # simple equality and case equality
46
+ /ox
47
+ GLOBAL_VARIABLE = / \$ (?: #{IDENT} | \d+ | [~&+`'=\/,;_.<>!@0$?*":F\\] | -[a-zA-Z_0-9] ) /ox
48
+
49
+ DOUBLEQ = / " [^"\#\\]* (?: (?: \#\{.*?\} | \#(?:$")? | \\. ) [^"\#\\]* )* "? /ox
50
+ SINGLEQ = / ' [^'\\]* (?: \\. [^'\\]* )* '? /ox
51
+ STRING = / #{SINGLEQ} | #{DOUBLEQ} /ox
52
+ SHELL = / ` [^`\#\\]* (?: (?: \#\{.*?\} | \#(?:$`)? | \\. ) [^`\#\\]* )* `? /ox
53
+ REGEXP = / \/ [^\/\#\\]* (?: (?: \#\{.*?\} | \#(?:$\/)? | \\. ) [^\/\#\\]* )* \/? /ox
54
+
55
+ DECIMAL = /\d+(?:_\d+)*/ # doesn't recognize 09 as octal error
56
+ OCTAL = /0_?[0-7]+(?:_[0-7]+)*/
57
+ HEXADECIMAL = /0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*/
58
+ BINARY = /0b[01]+(?:_[01]+)*/
59
+
60
+ EXPONENT = / [eE] [+-]? #{DECIMAL} /ox
61
+ FLOAT = / #{DECIMAL} (?: #{EXPONENT} | \. #{DECIMAL} #{EXPONENT}? ) /
62
+ INTEGER = /#{OCTAL}|#{HEXADECIMAL}|#{BINARY}|#{DECIMAL}/
63
+
64
+ def reset
65
+ super
66
+ @regexp_allowed = false
67
+ end
68
+
69
+ def next_token
70
+ return if @scanner.eos?
71
+
72
+ kind = :error
73
+ if @scanner.scan(/\s+/) # in every state
74
+ kind = :space
75
+ @regexp_allowed = :set if @regexp_allowed or @scanner.matched.index(?\n) # delayed flag setting
76
+
77
+ elsif @state == :def_expected
78
+ if @scanner.scan(/ (?: (?:#{IDENT}(?:\.|::))* | (?:@@?|$)? #{IDENT}(?:\.|::) ) #{METHOD_NAME_EX} /ox)
79
+ kind = :method
80
+ @state = :initial
81
+ else
82
+ @scanner.getch
83
+ end
84
+ @state = :initial
85
+
86
+ elsif @state == :module_expected
87
+ if @scanner.scan(/<</)
88
+ kind = :operator
89
+ else
90
+ if @scanner.scan(/ (?: #{IDENT} (?:\.|::))* #{IDENT} /ox)
91
+ kind = :method
92
+ else
93
+ @scanner.getch
94
+ end
95
+ @state = :initial
96
+ end
97
+
98
+ elsif # state == :initial
99
+ # IDENTIFIERS, KEYWORDS
100
+ if @scanner.scan(GLOBAL_VARIABLE)
101
+ kind = :global_variable
102
+ elsif @scanner.scan(/ @@ #{IDENT} /ox)
103
+ kind = :class_variable
104
+ elsif @scanner.scan(/ @ #{IDENT} /ox)
105
+ kind = :instance_variable
106
+ elsif @scanner.scan(/ __END__\n ( (?!\#CODE\#) .* )? | \#[^\n]* | =begin(?=\s).*? \n=end(?=\s|\z)(?:[^\n]*)? /mx)
107
+ kind = :comment
108
+ elsif @scanner.scan(METHOD_NAME)
109
+ if @last_token_dot
110
+ kind = :ident
111
+ else
112
+ matched = @scanner.matched
113
+ kind = IDENT_KIND[matched]
114
+ if kind == :ident and matched =~ /^[A-Z]/
115
+ kind = :constant
116
+ elsif kind == :reserved
117
+ @state = DEF_NEW_STATE[matched]
118
+ @regexp_allowed = REGEXP_ALLOWED[matched]
119
+ end
120
+ end
121
+
122
+ elsif @scanner.scan(STRING)
123
+ kind = :string
124
+ elsif @scanner.scan(SHELL)
125
+ kind = :shell
126
+ elsif @scanner.scan(/<<
127
+ (?:
128
+ ([a-zA-Z_0-9]+)
129
+ (?: .*? ^\1$ | .* )
130
+ |
131
+ -([a-zA-Z_0-9]+)
132
+ (?: .*? ^\s*\2$ | .* )
133
+ |
134
+ (["\'`]) (.+?) \3
135
+ (?: .*? ^\4$ | .* )
136
+ |
137
+ - (["\'`]) (.+?) \5
138
+ (?: .*? ^\s*\6$ | .* )
139
+ )
140
+ /mxo)
141
+ kind = :string
142
+ elsif @scanner.scan(/\//) and @regexp_allowed
143
+ @scanner.unscan
144
+ @scanner.scan(REGEXP)
145
+ kind = :regexp
146
+ /%(?:[Qqxrw](?:\([^)#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^)#\\\\]*)*\)?|\[[^\]#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^\]#\\\\]*)*\]?|\{[^}#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^}#\\\\]*)*\}?|<[^>#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^>#\\\\]*)*>?|([^a-zA-Z\\\\])(?:(?!\1)[^#\\\\])*(?:(?:#\{.*?\}|#|\\\\.)(?:(?!\1)[^#\\\\])*)*\1?)|\([^)#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^)#\\\\]*)*\)?|\[[^\]#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^\]#\\\\]*)*\]?|\{[^}#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^}#\\\\]*)*\}?|<[^>#\\\\]*(?:(?:#\{.*?\}|#|\\\\.)[^>#\\\\]*)*>?|([^a-zA-Z\s\\\\])(?:(?!\2)[^#\\\\])*(?:(?:#\{.*?\}|#|\\\\.)(?:(?!\2)[^#\\\\])*)*\2?|\\\\[^#\\\\]*(?:(?:#\{.*?\}|#)[^#\\\\]*)*\\\\?)/
147
+ elsif @scanner.scan(/:(?:#{GLOBAL_VARIABLE}|#{METHOD_NAME_EX}|#{STRING})/ox)
148
+ kind = :symbol
149
+ elsif @scanner.scan(/
150
+ \? (?:
151
+ [^\s\\]
152
+ |
153
+ \\ (?:M-\\C-|C-\\M-|M-\\c|c\\M-|c|C-|M-))? (?: \\ (?: . | [0-7]{3} | x[0-9A-Fa-f][0-9A-Fa-f] )
154
+ )
155
+ /mox)
156
+ kind = :integer
157
+
158
+ elsif @scanner.scan(/ [-+*\/%=<>;,|&!()\[\]{}~?] | \.\.?\.? | ::? /x)
159
+ kind = :operator
160
+ @regexp_allowed = :set if @scanner.matched[-1,1] =~ /[~=!<>|&^,\(\[+\-\/\*%]\z/
161
+ elsif @scanner.scan(FLOAT)
162
+ kind = :float
163
+ elsif @scanner.scan(INTEGER)
164
+ kind = :integer
165
+ else
166
+ @scanner.getch
167
+ end
168
+ end
169
+
170
+ token = Token.new @scanner.matched, kind
171
+
172
+ if kind == :regexp
173
+ token.text << @scanner.scan(/[eimnosux]*/)
174
+ end
175
+
176
+ @regexp_allowed = (@regexp_allowed == :set) # delayed flag setting
177
+
178
+ token
179
+ end
180
+ end
181
+
182
+ register Ruby, 'ruby', 'rb'
183
+
184
+ end
185
+ end
186
+ class Set
187
+ include Enumerable
188
+
189
+ # Creates a new set containing the given objects.
190
+ def self.[](*ary)
191
+ new(ary)
192
+ end
193
+
194
+ # Creates a new set containing the elements of the given enumerable
195
+ # object.
196
+ #
197
+ # If a block is given, the elements of enum are preprocessed by the
198
+ # given block.
199
+ def initialize(enum = nil, &block) # :yields: o
200
+ @hash ||= Hash.new
201
+
202
+ enum.nil? and return
203
+
204
+ if block
205
+ enum.each { |o| add(block[o]) }
206
+ else
207
+ merge(enum)
208
+ end
209
+ end
210
+
211
+ # Copy internal hash.
212
+ def initialize_copy(orig)
213
+ @hash = orig.instance_eval{@hash}.dup
214
+ end
215
+
216
+ # Returns the number of elements.
217
+ def size
218
+ @hash.size
219
+ end
220
+ alias length size
221
+
222
+ # Returns true if the set contains no elements.
223
+ def empty?
224
+ @hash.empty?
225
+ end
226
+
227
+ # Removes all elements and returns self.
228
+ def clear
229
+ @hash.clear
230
+ self
231
+ end
232
+
233
+ # Replaces the contents of the set with the contents of the given
234
+ # enumerable object and returns self.
235
+ def replace(enum)
236
+ if enum.class == self.class
237
+ @hash.replace(enum.instance_eval { @hash })
238
+ else
239
+ enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
240
+ clear
241
+ enum.each { |o| add(o) }
242
+ end
243
+
244
+ self
245
+ end
246
+
247
+ # Converts the set to an array. The order of elements is uncertain.
248
+ def to_a
249
+ @hash.keys
250
+ end
251
+
252
+ def flatten_merge(set, seen = Set.new)
253
+ set.each { |e|
254
+ if e.is_a?(Set)
255
+ if seen.include?(e_id = e.object_id)
256
+ raise ArgumentError, "tried to flatten recursive Set"
257
+ end
258
+
259
+ seen.add(e_id)
260
+ flatten_merge(e, seen)
261
+ seen.delete(e_id)
262
+ else
263
+ add(e)
264
+ end
265
+ }
266
+
267
+ self
268
+ end
269
+ protected :flatten_merge
270
+
271
+ # Returns a new set that is a copy of the set, flattening each
272
+ # containing set recursively.
273
+ def flatten
274
+ self.class.new.flatten_merge(self)
275
+ end
276
+
277
+ # Equivalent to Set#flatten, but replaces the receiver with the
278
+ # result in place. Returns nil if no modifications were made.
279
+ def flatten!
280
+ if detect { |e| e.is_a?(Set) }
281
+ replace(flatten())
282
+ else
283
+ nil
284
+ end
285
+ end
286
+
287
+ # Returns true if the set contains the given object.
288
+ def include?(o)
289
+ @hash.include?(o)
290
+ end
291
+ alias member? include?
292
+
293
+ # Returns true if the set is a superset of the given set.
294
+ def superset?(set)
295
+ set.is_a?(Set) or raise ArgumentError, "value must be a set"
296
+ return false if size < set.size
297
+ set.all? { |o| include?(o) }
298
+ end
299
+
300
+ # Returns true if the set is a proper superset of the given set.
301
+ def proper_superset?(set)
302
+ set.is_a?(Set) or raise ArgumentError, "value must be a set"
303
+ return false if size <= set.size
304
+ set.all? { |o| include?(o) }
305
+ end
306
+
307
+ # Returns true if the set is a subset of the given set.
308
+ def subset?(set)
309
+ set.is_a?(Set) or raise ArgumentError, "value must be a set"
310
+ return false if set.size < size
311
+ all? { |o| set.include?(o) }
312
+ end
313
+
314
+ # Returns true if the set is a proper subset of the given set.
315
+ def proper_subset?(set)
316
+ set.is_a?(Set) or raise ArgumentError, "value must be a set"
317
+ return false if set.size <= size
318
+ all? { |o| set.include?(o) }
319
+ end
320
+
321
+ # Calls the given block once for each element in the set, passing
322
+ # the element as parameter.
323
+ def each
324
+ @hash.each_key { |o| yield(o) }
325
+ self
326
+ end
327
+
328
+ # Adds the given object to the set and returns self. Use +merge+ to
329
+ # add several elements at once.
330
+ def add(o)
331
+ @hash[o] = true
332
+ self
333
+ end
334
+ alias << add
335
+
336
+ # Adds the given object to the set and returns self. If the
337
+ # object is already in the set, returns nil.
338
+ def add?(o)
339
+ if include?(o)
340
+ nil
341
+ else
342
+ add(o)
343
+ end
344
+ end
345
+
346
+ # Deletes the given object from the set and returns self. Use +subtract+ to
347
+ # delete several items at once.
348
+ def delete(o)
349
+ @hash.delete(o)
350
+ self
351
+ end
352
+
353
+ # Deletes the given object from the set and returns self. If the
354
+ # object is not in the set, returns nil.
355
+ def delete?(o)
356
+ if include?(o)
357
+ delete(o)
358
+ else
359
+ nil
360
+ end
361
+ end
362
+
363
+ # Deletes every element of the set for which block evaluates to
364
+ # true, and returns self.
365
+ def delete_if
366
+ @hash.delete_if { |o,| yield(o) }
367
+ self
368
+ end
369
+
370
+ # Do collect() destructively.
371
+ def collect!
372
+ set = self.class.new
373
+ each { |o| set << yield(o) }
374
+ replace(set)
375
+ end
376
+ alias map! collect!
377
+
378
+ # Equivalent to Set#delete_if, but returns nil if no changes were
379
+ # made.
380
+ def reject!
381
+ n = size
382
+ delete_if { |o| yield(o) }
383
+ size == n ? nil : self
384
+ end
385
+
386
+ # Merges the elements of the given enumerable object to the set and
387
+ # returns self.
388
+ def merge(enum)
389
+ if enum.is_a?(Set)
390
+ @hash.update(enum.instance_eval { @hash })
391
+ else
392
+ enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
393
+ enum.each { |o| add(o) }
394
+ end
395
+
396
+ self
397
+ end
398
+
399
+ # Deletes every element that appears in the given enumerable object
400
+ # and returns self.
401
+ def subtract(enum)
402
+ enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
403
+ enum.each { |o| delete(o) }
404
+ self
405
+ end
406
+
407
+ # Returns a new set built by merging the set and the elements of the
408
+ # given enumerable object.
409
+ def |(enum)
410
+ enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
411
+ dup.merge(enum)
412
+ end
413
+ alias + | ##
414
+ alias union | ##
415
+
416
+ # Returns a new set built by duplicating the set, removing every
417
+ # element that appears in the given enumerable object.
418
+ def -(enum)
419
+ enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
420
+ dup.subtract(enum)
421
+ end
422
+ alias difference - ##
423
+
424
+ # Returns a new array containing elements common to the set and the
425
+ # given enumerable object.
426
+ def &(enum)
427
+ enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
428
+ n = self.class.new
429
+ enum.each { |o| n.add(o) if include?(o) }
430
+ n
431
+ end
432
+ alias intersection & ##
433
+
434
+ # Returns a new array containing elements exclusive between the set
435
+ # and the given enumerable object. (set ^ enum) is equivalent to
436
+ # ((set | enum) - (set & enum)).
437
+ def ^(enum)
438
+ enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
439
+ n = dup
440
+ enum.each { |o| if n.include?(o) then n.delete(o) else n.add(o) end }
441
+ n
442
+ end
443
+
444
+ # Returns true if two sets are equal. The equality of each couple
445
+ # of elements is defined according to Object#eql?.
446
+ def ==(set)
447
+ equal?(set) and return true
448
+
449
+ set.is_a?(Set) && size == set.size or return false
450
+
451
+ hash = @hash.dup
452
+ set.all? { |o| hash.include?(o) }
453
+ end
454
+
455
+ def hash # :nodoc:
456
+ @hash.hash
457
+ end
458
+
459
+ def eql?(o) # :nodoc:
460
+ return false unless o.is_a?(Set)
461
+ @hash.eql?(o.instance_eval{@hash})
462
+ end
463
+
464
+ # Classifies the set by the return value of the given block and
465
+ # returns a hash of {value => set of elements} pairs. The block is
466
+ # called once for each element of the set, passing the element as
467
+ # parameter.
468
+ #
469
+ # e.g.:
470
+ #
471
+ # require 'set'
472
+ # files = Set.new(Dir.glob("*.rb"))
473
+ # hash = files.classify { |f| File.mtime(f).year }
474
+ # p hash # => {2000=>#<Set: {"a.rb", "b.rb"}>,
475
+ # # 2001=>#<Set: {"c.rb", "d.rb", "e.rb"}>,
476
+ # # 2002=>#<Set: {"f.rb"}>}
477
+ def classify # :yields: o
478
+ h = {}
479
+
480
+ each { |i|
481
+ x = yield(i)
482
+ (h[x] ||= self.class.new).add(i)
483
+ }
484
+
485
+ h
486
+ end
487
+
488
+ # Divides the set into a set of subsets according to the commonality
489
+ # defined by the given block.
490
+ #
491
+ # If the arity of the block is 2, elements o1 and o2 are in common
492
+ # if block.call(o1, o2) is true. Otherwise, elements o1 and o2 are
493
+ # in common if block.call(o1) == block.call(o2).
494
+ #
495
+ # e.g.:
496
+ #
497
+ # require 'set'
498
+ # numbers = Set[1, 3, 4, 6, 9, 10, 11]
499
+ # set = numbers.divide { |i,j| (i - j).abs == 1 }
500
+ # p set # => #<Set: {#<Set: {1}>,
501
+ # # #<Set: {11, 9, 10}>,
502
+ # # #<Set: {3, 4}>,
503
+ # # #<Set: {6}>}>
504
+ def divide(&func)
505
+ if func.arity == 2
506
+ require 'tsort'
507
+
508
+ class << dig = {} # :nodoc:
509
+ include TSort
510
+
511
+ alias tsort_each_node each_key
512
+ def tsort_each_child(node, &block)
513
+ fetch(node).each(&block)
514
+ end
515
+ end
516
+
517
+ each { |u|
518
+ dig[u] = a = []
519
+ each{ |v| func.call(u, v) and a << v }
520
+ }
521
+
522
+ set = Set.new()
523
+ dig.each_strongly_connected_component { |css|
524
+ set.add(self.class.new(css))
525
+ }
526
+ set
527
+ else
528
+ Set.new(classify(&func).values)
529
+ end
530
+ end
531
+
532
+ InspectKey = :__inspect_key__ # :nodoc:
533
+
534
+ # Returns a string containing a human-readable representation of the
535
+ # set. ("#<Set: {element1, element2, ...}>")
536
+ def inspect
537
+ ids = (Thread.current[InspectKey] ||= [])
538
+
539
+ if ids.include?(object_id)
540
+ return sprintf('#<%s: {...}>', self.class.name)
541
+ end
542
+
543
+ begin
544
+ ids << object_id
545
+ return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2])
546
+ ensure
547
+ ids.pop
548
+ end
549
+ end
550
+
551
+ def pretty_print(pp) # :nodoc:
552
+ pp.text sprintf('#<%s: {', self.class.name)
553
+ pp.nest(1) {
554
+ pp.seplist(self) { |o|
555
+ pp.pp o
556
+ }
557
+ }
558
+ pp.text "}>"
559
+ end
560
+
561
+ def pretty_print_cycle(pp) # :nodoc:
562
+ pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...')
563
+ end
564
+ end
565
+
566
+ # SortedSet implements a set which elements are sorted in order. See Set.
567
+ class SortedSet < Set
568
+ @@setup = false
569
+
570
+ class << self
571
+ def [](*ary) # :nodoc:
572
+ new(ary)
573
+ end
574
+
575
+ def setup # :nodoc:
576
+ @@setup and return
577
+
578
+ begin
579
+ require 'rbtree'
580
+
581
+ module_eval %{
582
+ def initialize(*args, &block)
583
+ @hash = RBTree.new
584
+ super
585
+ end
586
+ }
587
+ rescue LoadError
588
+ module_eval %{
589
+ def initialize(*args, &block)
590
+ @keys = nil
591
+ super
592
+ end
593
+
594
+ def clear
595
+ @keys = nil
596
+ super
597
+ end
598
+
599
+ def replace(enum)
600
+ @keys = nil
601
+ super
602
+ end
603
+
604
+ def add(o)
605
+ @keys = nil
606
+ @hash[o] = true
607
+ self
608
+ end
609
+ alias << add
610
+
611
+ def delete(o)
612
+ @keys = nil
613
+ @hash.delete(o)
614
+ self
615
+ end
616
+
617
+ def delete_if
618
+ n = @hash.size
619
+ @hash.delete_if { |o,| yield(o) }
620
+ @keys = nil if @hash.size != n
621
+ self
622
+ end
623
+
624
+ def merge(enum)
625
+ @keys = nil
626
+ super
627
+ end
628
+
629
+ def each
630
+ to_a.each { |o| yield(o) }
631
+ end
632
+
633
+ def to_a
634
+ (@keys = @hash.keys).sort! unless @keys
635
+ @keys
636
+ end
637
+ }
638
+ end
639
+
640
+ @@setup = true
641
+ end
642
+ end
643
+
644
+ def initialize(*args, &block) # :nodoc:
645
+ SortedSet.setup
646
+ initialize(*args, &block)
647
+ end
648
+ end
649
+
650
+ module Enumerable
651
+ # Makes a set from the enumerable object with given arguments.
652
+ def to_set(klass = Set, *args, &block)
653
+ klass.new(self, *args, &block)
654
+ end
655
+ end
656
+
657
+ # =begin
658
+ # == RestricedSet class
659
+ # RestricedSet implements a set with restrictions defined by a given
660
+ # block.
661
+ #
662
+ # === Super class
663
+ # Set
664
+ #
665
+ # === Class Methods
666
+ # --- RestricedSet::new(enum = nil) { |o| ... }
667
+ # --- RestricedSet::new(enum = nil) { |rset, o| ... }
668
+ # Creates a new restricted set containing the elements of the given
669
+ # enumerable object. Restrictions are defined by the given block.
670
+ #
671
+ # If the block's arity is 2, it is called with the RestrictedSet
672
+ # itself and an object to see if the object is allowed to be put in
673
+ # the set.
674
+ #
675
+ # Otherwise, the block is called with an object to see if the object
676
+ # is allowed to be put in the set.
677
+ #
678
+ # === Instance Methods
679
+ # --- restriction_proc
680
+ # Returns the restriction procedure of the set.
681
+ #
682
+ # =end
683
+ #
684
+ # class RestricedSet < Set
685
+ # def initialize(*args, &block)
686
+ # @proc = block or raise ArgumentError, "missing a block"
687
+ #
688
+ # if @proc.arity == 2
689
+ # instance_eval %{
690
+ # def add(o)
691
+ # @hash[o] = true if @proc.call(self, o)
692
+ # self
693
+ # end
694
+ # alias << add
695
+ #
696
+ # def add?(o)
697
+ # if include?(o) || !@proc.call(self, o)
698
+ # nil
699
+ # else
700
+ # @hash[o] = true
701
+ # self
702
+ # end
703
+ # end
704
+ #
705
+ # def replace(enum)
706
+ # enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
707
+ # clear
708
+ # enum.each { |o| add(o) }
709
+ #
710
+ # self
711
+ # end
712
+ #
713
+ # def merge(enum)
714
+ # enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
715
+ # enum.each { |o| add(o) }
716
+ #
717
+ # self
718
+ # end
719
+ # }
720
+ # else
721
+ # instance_eval %{
722
+ # def add(o)
723
+ # if @proc.call(o)
724
+ # @hash[o] = true
725
+ # end
726
+ # self
727
+ # end
728
+ # alias << add
729
+ #
730
+ # def add?(o)
731
+ # if include?(o) || !@proc.call(o)
732
+ # nil
733
+ # else
734
+ # @hash[o] = true
735
+ # self
736
+ # end
737
+ # end
738
+ # }
739
+ # end
740
+ #
741
+ # super(*args)
742
+ # end
743
+ #
744
+ # def restriction_proc
745
+ # @proc
746
+ # end
747
+ # end
748
+
749
+ if $0 == __FILE__
750
+ eval DATA.read, nil, $0, __LINE__+4
751
+ end
752
+
753
+ # = rweb - CGI Support Library
754
+ #
755
+ # Author:: Johannes Barre (mailto:rweb@igels.net)
756
+ # Copyright:: Copyright (c) 2003, 04 by Johannes Barre
757
+ # License:: GNU Lesser General Public License (COPYING, http://www.gnu.org/copyleft/lesser.html)
758
+ # Version:: 0.1.0
759
+ # CVS-ID:: $Id: example.rb 39 2005-11-05 03:33:55Z murphy $
760
+ #
761
+ # == What is Rweb?
762
+ # Rweb is a replacement for the cgi class included in the ruby distribution.
763
+ #
764
+ # == How to use
765
+ #
766
+ # === Basics
767
+ #
768
+ # This class is made to be as easy as possible to use. An example:
769
+ #
770
+ # require "rweb"
771
+ #
772
+ # web = Rweb.new
773
+ # web.out do
774
+ # web.puts "Hello world!"
775
+ # end
776
+ #
777
+ # The visitor will get a simple "Hello World!" in his browser. Please notice,
778
+ # that won't set html-tags for you, so you should better do something like this:
779
+ #
780
+ # require "rweb"
781
+ #
782
+ # web = Rweb.new
783
+ # web.out do
784
+ # web.puts "<html><body>Hello world!</body></html>"
785
+ # end
786
+ #
787
+ # === Set headers
788
+ # Of course, it's also possible to tell the browser, that the content of this
789
+ # page is plain text instead of html code:
790
+ #
791
+ # require "rweb"
792
+ #
793
+ # web = Rweb.new
794
+ # web.out do
795
+ # web.header("content-type: text/plain")
796
+ # web.puts "Hello plain world!"
797
+ # end
798
+ #
799
+ # Please remember, headers can't be set after the page content has been send.
800
+ # You have to set all nessessary headers before the first puts oder print. It's
801
+ # possible to cache the content until everything is complete. Doing it this
802
+ # way, you can set headers everywhere.
803
+ #
804
+ # If you set a header twice, the second header will replace the first one. The
805
+ # header name is not casesensitive, it will allways converted in to the
806
+ # capitalised form suggested by the w3c (http://w3.org)
807
+ #
808
+ # === Set cookies
809
+ # Setting cookies is quite easy:
810
+ # include 'rweb'
811
+ #
812
+ # web = Rweb.new
813
+ # Cookie.new("Visits", web.cookies['visits'].to_i +1)
814
+ # web.out do
815
+ # web.puts "Welcome back! You visited this page #{web.cookies['visits'].to_i +1} times"
816
+ # end
817
+ #
818
+ # See the class Cookie for more details.
819
+ #
820
+ # === Get form and cookie values
821
+ # There are four ways to submit data from the browser to the server and your
822
+ # ruby script: via GET, POST, cookies and file upload. Rweb doesn't support
823
+ # file upload by now.
824
+ #
825
+ # include 'rweb'
826
+ #
827
+ # web = Rweb.new
828
+ # web.out do
829
+ # web.print "action: #{web.get['action']} "
830
+ # web.puts "The value of the cookie 'visits' is #{web.cookies['visits']}"
831
+ # web.puts "The post parameter 'test['x']' is #{web.post['test']['x']}"
832
+ # end
833
+
834
+ RWEB_VERSION = "0.1.0"
835
+ RWEB = "rweb/#{RWEB_VERSION}"
836
+
837
+ #require 'rwebcookie' -> edit by bunny :-)
838
+
839
+ class Rweb
840
+ # All parameter submitted via the GET method are available in attribute
841
+ # get. This is Hash, where every parameter is available as a key-value
842
+ # pair.
843
+ #
844
+ # If your input tag has a name like this one, it's value will be available
845
+ # as web.get["fieldname"]
846
+ # <input name="fieldname">
847
+ # You can submit values as a Hash
848
+ # <input name="text['index']">
849
+ # <input name="text['index2']">
850
+ # will be available as
851
+ # web.get["text"]["index"]
852
+ # web.get["text"]["index2"]
853
+ # Integers are also possible
854
+ # <input name="int[2]">
855
+ # <input name="int[3]['hi']>
856
+ # will be available as
857
+ # web.get["int"][2]
858
+ # web.get["int"][3]["hi"]
859
+ # If you specify no index, the lowest unused index will be used:
860
+ # <input name="int[]"><!-- First Field -->
861
+ # <input name="int[]"><!-- Second one -->
862
+ # will be available as
863
+ # web.get["int"][0] # First Field
864
+ # web.get["int"][1] # Second one
865
+ # Please notice, this doesn'd work like you might expect:
866
+ # <input name="text[index]">
867
+ # It will not be available as web.get["text"]["index"] but
868
+ # web.get["text[index]"]
869
+ attr_reader :get
870
+
871
+ # All parameters submitted via POST are available in the attribute post. It
872
+ # works like the get attribute.
873
+ # <input name="text[0]">
874
+ # will be available as
875
+ # web.post["text"][0]
876
+ attr_reader :post
877
+
878
+ # All cookies submitted by the browser are available in cookies. This is a
879
+ # Hash, where every cookie is a key-value pair.
880
+ attr_reader :cookies
881
+
882
+ # The name of the browser identification is submitted as USER_AGENT and
883
+ # available in this attribute.
884
+ attr_reader :user_agent
885
+
886
+ # The IP address of the client.
887
+ attr_reader :remote_addr
888
+
889
+ # Creates a new Rweb object. This should only done once. You can set various
890
+ # options via the settings hash.
891
+ #
892
+ # "cache" => true: Everything you script send to the client will be cached
893
+ # until the end of the out block or until flush is called. This way, you
894
+ # can modify headers and cookies even after printing something to the client.
895
+ #
896
+ # "safe" => level: Changes the $SAFE attribute. By default, $SAFE will be set
897
+ # to 1. If $SAFE is already higher than this value, it won't be changed.
898
+ #
899
+ # "silend" => true: Normaly, Rweb adds automaticly a header like this
900
+ # "X-Powered-By: Rweb/x.x.x (Ruby/y.y.y)". With the silend option you can
901
+ # suppress this.
902
+ def initialize (settings = {})
903
+ # {{{
904
+ @header = {}
905
+ @cookies = {}
906
+ @get = {}
907
+ @post = {}
908
+
909
+ # Internal attributes
910
+ @status = nil
911
+ @reasonPhrase = nil
912
+ @setcookies = []
913
+ @output_started = false;
914
+ @output_allowed = false;
915
+
916
+ @mod_ruby = false
917
+ @env = ENV.to_hash
918
+
919
+ if defined?(MOD_RUBY)
920
+ @output_method = "mod_ruby"
921
+ @mod_ruby = true
922
+ elsif @env['SERVER_SOFTWARE'] =~ /^Microsoft-IIS/i
923
+ @output_method = "nph"
924
+ else
925
+ @output_method = "ph"
926
+ end
927
+
928
+ unless settings.is_a?(Hash)
929
+ raise TypeError, "settings must be a Hash"
930
+ end
931
+ @settings = settings
932
+
933
+ unless @settings.has_key?("safe")
934
+ @settings["safe"] = 1
935
+ end
936
+
937
+ if $SAFE < @settings["safe"]
938
+ $SAFE = @settings["safe"]
939
+ end
940
+
941
+ unless @settings.has_key?("cache")
942
+ @settings["cache"] = false
943
+ end
944
+
945
+ # mod_ruby sets no QUERY_STRING variable, if no GET-Parameters are given
946
+ unless @env.has_key?("QUERY_STRING")
947
+ @env["QUERY_STRING"] = ""
948
+ end
949
+
950
+ # Now we split the QUERY_STRING by the seperators & and ; or, if
951
+ # specified, settings['get seperator']
952
+ unless @settings.has_key?("get seperator")
953
+ get_args = @env['QUERY_STRING'].split(/[&;]/)
954
+ else
955
+ get_args = @env['QUERY_STRING'].split(@settings['get seperator'])
956
+ end
957
+
958
+ get_args.each do | arg |
959
+ arg_key, arg_val = arg.split(/=/, 2)
960
+ arg_key = Rweb::unescape(arg_key)
961
+ arg_val = Rweb::unescape(arg_val)
962
+
963
+ # Parse names like name[0], name['text'] or name[]
964
+ pattern = /^(.+)\[("[^\]]*"|'[^\]]*'|[0-9]*)\]$/
965
+ keys = []
966
+ while match = pattern.match(arg_key)
967
+ arg_key = match[1]
968
+ keys = [match[2]] + keys
969
+ end
970
+ keys = [arg_key] + keys
971
+
972
+ akt = @get
973
+ last = nil
974
+ lastkey = nil
975
+ keys.each do |key|
976
+ if key == ""
977
+ # No key specified (like in "test[]"), so we use the
978
+ # lowerst unused Integer as key
979
+ key = 0
980
+ while akt.has_key?(key)
981
+ key += 1
982
+ end
983
+ elsif /^[0-9]*$/ =~ key
984
+ # If the index is numerical convert it to an Integer
985
+ key = key.to_i
986
+ elsif key[0].chr == "'" || key[0].chr == '"'
987
+ key = key[1, key.length() -2]
988
+ end
989
+ if !akt.has_key?(key) || !akt[key].class == Hash
990
+ # create an empty Hash if there isn't already one
991
+ akt[key] = {}
992
+ end
993
+ last = akt
994
+ lastkey = key
995
+ akt = akt[key]
996
+ end
997
+ last[lastkey] = arg_val
998
+ end
999
+
1000
+ if @env['REQUEST_METHOD'] == "POST"
1001
+ if @env.has_key?("CONTENT_TYPE") && @env['CONTENT_TYPE'] == "application/x-www-form-urlencoded" && @env.has_key?('CONTENT_LENGTH')
1002
+ unless @settings.has_key?("post seperator")
1003
+ post_args = $stdin.read(@env['CONTENT_LENGTH'].to_i).split(/[&;]/)
1004
+ else
1005
+ post_args = $stdin.read(@env['CONTENT_LENGTH'].to_i).split(@settings['post seperator'])
1006
+ end
1007
+ post_args.each do | arg |
1008
+ arg_key, arg_val = arg.split(/=/, 2)
1009
+ arg_key = Rweb::unescape(arg_key)
1010
+ arg_val = Rweb::unescape(arg_val)
1011
+
1012
+ # Parse names like name[0], name['text'] or name[]
1013
+ pattern = /^(.+)\[("[^\]]*"|'[^\]]*'|[0-9]*)\]$/
1014
+ keys = []
1015
+ while match = pattern.match(arg_key)
1016
+ arg_key = match[1]
1017
+ keys = [match[2]] + keys
1018
+ end
1019
+ keys = [arg_key] + keys
1020
+
1021
+ akt = @post
1022
+ last = nil
1023
+ lastkey = nil
1024
+ keys.each do |key|
1025
+ if key == ""
1026
+ # No key specified (like in "test[]"), so we use
1027
+ # the lowerst unused Integer as key
1028
+ key = 0
1029
+ while akt.has_key?(key)
1030
+ key += 1
1031
+ end
1032
+ elsif /^[0-9]*$/ =~ key
1033
+ # If the index is numerical convert it to an Integer
1034
+ key = key.to_i
1035
+ elsif key[0].chr == "'" || key[0].chr == '"'
1036
+ key = key[1, key.length() -2]
1037
+ end
1038
+ if !akt.has_key?(key) || !akt[key].class == Hash
1039
+ # create an empty Hash if there isn't already one
1040
+ akt[key] = {}
1041
+ end
1042
+ last = akt
1043
+ lastkey = key
1044
+ akt = akt[key]
1045
+ end
1046
+ last[lastkey] = arg_val
1047
+ end
1048
+ else
1049
+ # Maybe we should print a warning here?
1050
+ $stderr.print("Unidentified form data recived and discarded.")
1051
+ end
1052
+ end
1053
+
1054
+ if @env.has_key?("HTTP_COOKIE")
1055
+ cookie = @env['HTTP_COOKIE'].split(/; ?/)
1056
+ cookie.each do | c |
1057
+ cookie_key, cookie_val = c.split(/=/, 2)
1058
+
1059
+ @cookies [Rweb::unescape(cookie_key)] = Rweb::unescape(cookie_val)
1060
+ end
1061
+ end
1062
+
1063
+ if defined?(@env['HTTP_USER_AGENT'])
1064
+ @user_agent = @env['HTTP_USER_AGENT']
1065
+ else
1066
+ @user_agent = nil;
1067
+ end
1068
+
1069
+ if defined?(@env['REMOTE_ADDR'])
1070
+ @remote_addr = @env['REMOTE_ADDR']
1071
+ else
1072
+ @remote_addr = nil
1073
+ end
1074
+ # }}}
1075
+ end
1076
+
1077
+ # Prints a String to the client. If caching is enabled, the String will
1078
+ # buffered until the end of the out block ends.
1079
+ def print(str = "")
1080
+ # {{{
1081
+ unless @output_allowed
1082
+ raise "You just can write to output inside of a Rweb::out-block"
1083
+ end
1084
+
1085
+ if @settings["cache"]
1086
+ @buffer += [str.to_s]
1087
+ else
1088
+ unless @output_started
1089
+ sendHeaders
1090
+ end
1091
+ $stdout.print(str)
1092
+ end
1093
+ nil
1094
+ # }}}
1095
+ end
1096
+
1097
+ # Prints a String to the client and adds a line break at the end. Please
1098
+ # remember, that a line break is not visible in HTML, use the <br> HTML-Tag
1099
+ # for this. If caching is enabled, the String will buffered until the end
1100
+ # of the out block ends.
1101
+ def puts(str = "")
1102
+ # {{{
1103
+ self.print(str + "\n")
1104
+ # }}}
1105
+ end
1106
+
1107
+ # Alias to print.
1108
+ def write(str = "")
1109
+ # {{{
1110
+ self.print(str)
1111
+ # }}}
1112
+ end
1113
+
1114
+ # If caching is enabled, all cached data are send to the cliend and the
1115
+ # cache emptied.
1116
+ def flush
1117
+ # {{{
1118
+ unless @output_allowed
1119
+ raise "You can't use flush outside of a Rweb::out-block"
1120
+ end
1121
+ buffer = @buffer.join
1122
+
1123
+ unless @output_started
1124
+ sendHeaders
1125
+ end
1126
+ $stdout.print(buffer)
1127
+
1128
+ @buffer = []
1129
+ # }}}
1130
+ end
1131
+
1132
+ # Sends one or more header to the client. All headers are cached just
1133
+ # before body data are send to the client. If the same header are set
1134
+ # twice, only the last value is send.
1135
+ #
1136
+ # Example:
1137
+ # web.header("Last-Modified: Mon, 16 Feb 2004 20:15:41 GMT")
1138
+ # web.header("Location: http://www.ruby-lang.org")
1139
+ #
1140
+ # You can specify more than one header at the time by doing something like
1141
+ # this:
1142
+ # web.header("Content-Type: text/plain\nContent-Length: 383")
1143
+ # or
1144
+ # web.header(["Content-Type: text/plain", "Content-Length: 383"])
1145
+ def header(str)
1146
+ # {{{
1147
+ if @output_started
1148
+ raise "HTTP-Headers are already send. You can't change them after output has started!"
1149
+ end
1150
+ unless @output_allowed
1151
+ raise "You just can set headers inside of a Rweb::out-block"
1152
+ end
1153
+ if str.is_a?Array
1154
+ str.each do | value |
1155
+ self.header(value)
1156
+ end
1157
+
1158
+ elsif str.split(/\n/).length > 1
1159
+ str.split(/\n/).each do | value |
1160
+ self.header(value)
1161
+ end
1162
+
1163
+ elsif str.is_a? String
1164
+ str.gsub!(/\r/, "")
1165
+
1166
+ if (str =~ /^HTTP\/1\.[01] [0-9]{3} ?.*$/) == 0
1167
+ pattern = /^HTTP\/1.[01] ([0-9]{3}) ?(.*)$/
1168
+
1169
+ result = pattern.match(str)
1170
+ self.setstatus(result[0], result[1])
1171
+ elsif (str =~ /^status: [0-9]{3} ?.*$/i) == 0
1172
+ pattern = /^status: ([0-9]{3}) ?(.*)$/i
1173
+
1174
+ result = pattern.match(str)
1175
+ self.setstatus(result[0], result[1])
1176
+ else
1177
+ a = str.split(/: ?/, 2)
1178
+
1179
+ @header[a[0].downcase] = a[1]
1180
+ end
1181
+ end
1182
+ # }}}
1183
+ end
1184
+
1185
+ # Changes the status of this page. There are several codes like "200 OK",
1186
+ # "302 Found", "404 Not Found" or "500 Internal Server Error". A list of
1187
+ # all codes is available at
1188
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10
1189
+ #
1190
+ # You can just send the code number, the reason phrase will be added
1191
+ # automaticly with the recommendations from the w3c if not specified. If
1192
+ # you set the status twice or more, only the last status will be send.
1193
+ # Examples:
1194
+ # web.status("401 Unauthorized")
1195
+ # web.status("410 Sad but true, this lonely page is gone :(")
1196
+ # web.status(206)
1197
+ # web.status("400")
1198
+ #
1199
+ # The default status is "200 OK". If a "Location" header is set, the
1200
+ # default status is "302 Found".
1201
+ def status(str)
1202
+ # {{{
1203
+ if @output_started
1204
+ raise "HTTP-Headers are already send. You can't change them after output has started!"
1205
+ end
1206
+ unless @output_allowed
1207
+ raise "You just can set headers inside of a Rweb::out-block"
1208
+ end
1209
+ if str.is_a?Integer
1210
+ @status = str
1211
+ elsif str.is_a?String
1212
+ p1 = /^([0-9]{3}) ?(.*)$/
1213
+ p2 = /^HTTP\/1\.[01] ([0-9]{3}) ?(.*)$/
1214
+ p3 = /^status: ([0-9]{3}) ?(.*)$/i
1215
+
1216
+ if (a = p1.match(str)) == nil
1217
+ if (a = p2.match(str)) == nil
1218
+ if (a = p3.match(str)) == nil
1219
+ raise ArgumentError, "Invalid argument", caller
1220
+ end
1221
+ end
1222
+ end
1223
+ @status = a[1].to_i
1224
+ if a[2] != ""
1225
+ @reasonPhrase = a[2]
1226
+ else
1227
+ @reasonPhrase = getReasonPhrase(@status)
1228
+ end
1229
+ else
1230
+ raise ArgumentError, "Argument of setstatus must be integer or string", caller
1231
+ end
1232
+ # }}}
1233
+ end
1234
+
1235
+ # Handles the output of your content and rescues all exceptions. Send all
1236
+ # data in the block to this method. For example:
1237
+ # web.out do
1238
+ # web.header("Content-Type: text/plain")
1239
+ # web.puts("Hello, plain world!")
1240
+ # end
1241
+ def out
1242
+ # {{{
1243
+ @output_allowed = true
1244
+ @buffer = []; # We use an array as buffer, because it's more performant :)
1245
+
1246
+ begin
1247
+ yield
1248
+ rescue Exception => exception
1249
+ $stderr.puts "Ruby exception rescued (#{exception.class}): #{exception.message}"
1250
+ $stderr.puts exception.backtrace.join("\n")
1251
+
1252
+ unless @output_started
1253
+ self.setstatus(500)
1254
+ @header = {}
1255
+ end
1256
+
1257
+ unless (@settings.has_key?("hide errors") and @settings["hide errors"] == true)
1258
+ unless @output_started
1259
+ self.header("Content-Type: text/html")
1260
+ self.puts "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Strict//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">"
1261
+ self.puts "<html>"
1262
+ self.puts "<head>"
1263
+ self.puts "<title>500 Internal Server Error</title>"
1264
+ self.puts "</head>"
1265
+ self.puts "<body>"
1266
+ end
1267
+ if @header.has_key?("content-type") and (@header["content-type"] =~ /^text\/html/i) == 0
1268
+ self.puts "<h1>Internal Server Error</h1>"
1269
+ self.puts "<p>The server encountered an exception and was unable to complete your request.</p>"
1270
+ self.puts "<p>The exception has provided the following information:</p>"
1271
+ self.puts "<pre style=\"background: #FFCCCC; border: black solid 2px; margin-left: 2cm; margin-right: 2cm; padding: 2mm;\"><b>#{exception.class}</b>: #{exception.message} <b>on</b>"
1272
+ self.puts
1273
+ self.puts "#{exception.backtrace.join("\n")}</pre>"
1274
+ self.puts "</body>"
1275
+ self.puts "</html>"
1276
+ else
1277
+ self.puts "The server encountered an exception and was unable to complete your request"
1278
+ self.puts "The exception has provided the following information:"
1279
+ self.puts "#{exception.class}: #{exception.message}"
1280
+ self.puts
1281
+ self.puts exception.backtrace.join("\n")
1282
+ end
1283
+ end
1284
+ end
1285
+
1286
+ if @settings["cache"]
1287
+ buffer = @buffer.join
1288
+
1289
+ unless @output_started
1290
+ unless @header.has_key?("content-length")
1291
+ self.header("content-length: #{buffer.length}")
1292
+ end
1293
+
1294
+ sendHeaders
1295
+ end
1296
+ $stdout.print(buffer)
1297
+ elsif !@output_started
1298
+ sendHeaders
1299
+ end
1300
+ @output_allowed = false;
1301
+ # }}}
1302
+ end
1303
+
1304
+ # Decodes URL encoded data, %20 for example stands for a space.
1305
+ def Rweb.unescape(str)
1306
+ # {{{
1307
+ if defined? str and str.is_a? String
1308
+ str.gsub!(/\+/, " ")
1309
+ str.gsub(/%.{2}/) do | s |
1310
+ s[1,2].hex.chr
1311
+ end
1312
+ end
1313
+ # }}}
1314
+ end
1315
+
1316
+ protected
1317
+ def sendHeaders
1318
+ # {{{
1319
+
1320
+ Cookie.disallow # no more cookies can be set or modified
1321
+ if !(@settings.has_key?("silent") and @settings["silent"] == true) and !@header.has_key?("x-powered-by")
1322
+ if @mod_ruby
1323
+ header("x-powered-by: #{RWEB} (Ruby/#{RUBY_VERSION}, #{MOD_RUBY})");
1324
+ else
1325
+ header("x-powered-by: #{RWEB} (Ruby/#{RUBY_VERSION})");
1326
+ end
1327
+ end
1328
+
1329
+ if @output_method == "ph"
1330
+ if ((@status == nil or @status == 200) and !@header.has_key?("content-type") and !@header.has_key?("location"))
1331
+ header("content-type: text/html")
1332
+ end
1333
+
1334
+ if @status != nil
1335
+ $stdout.print "Status: #{@status} #{@reasonPhrase}\r\n"
1336
+ end
1337
+
1338
+ @header.each do |key, value|
1339
+ key = key *1 # "unfreeze" key :)
1340
+ key[0] = key[0,1].upcase![0]
1341
+
1342
+ key = key.gsub(/-[a-z]/) do |char|
1343
+ "-" + char[1,1].upcase
1344
+ end
1345
+
1346
+ $stdout.print "#{key}: #{value}\r\n"
1347
+ end
1348
+ cookies = Cookie.getHttpHeader # Get all cookies as an HTTP Header
1349
+ if cookies
1350
+ $stdout.print cookies
1351
+ end
1352
+
1353
+ $stdout.print "\r\n"
1354
+
1355
+ elsif @output_method == "nph"
1356
+ elsif @output_method == "mod_ruby"
1357
+ r = Apache.request
1358
+
1359
+ if ((@status == nil or @status == 200) and !@header.has_key?("content-type") and !@header.has_key?("location"))
1360
+ header("text/html")
1361
+ end
1362
+
1363
+ if @status != nil
1364
+ r.status_line = "#{@status} #{@reasonPhrase}"
1365
+ end
1366
+
1367
+ r.send_http_header
1368
+ @header.each do |key, value|
1369
+ key = key *1 # "unfreeze" key :)
1370
+
1371
+ key[0] = key[0,1].upcase![0]
1372
+ key = key.gsub(/-[a-z]/) do |char|
1373
+ "-" + char[1,1].upcase
1374
+ end
1375
+ puts "#{key}: #{value.class}"
1376
+ #r.headers_out[key] = value
1377
+ end
1378
+ end
1379
+ @output_started = true
1380
+ # }}}
1381
+ end
1382
+
1383
+ def getReasonPhrase (status)
1384
+ # {{{
1385
+ if status == 100
1386
+ "Continue"
1387
+ elsif status == 101
1388
+ "Switching Protocols"
1389
+ elsif status == 200
1390
+ "OK"
1391
+ elsif status == 201
1392
+ "Created"
1393
+ elsif status == 202
1394
+ "Accepted"
1395
+ elsif status == 203
1396
+ "Non-Authoritative Information"
1397
+ elsif status == 204
1398
+ "No Content"
1399
+ elsif status == 205
1400
+ "Reset Content"
1401
+ elsif status == 206
1402
+ "Partial Content"
1403
+ elsif status == 300
1404
+ "Multiple Choices"
1405
+ elsif status == 301
1406
+ "Moved Permanently"
1407
+ elsif status == 302
1408
+ "Found"
1409
+ elsif status == 303
1410
+ "See Other"
1411
+ elsif status == 304
1412
+ "Not Modified"
1413
+ elsif status == 305
1414
+ "Use Proxy"
1415
+ elsif status == 307
1416
+ "Temporary Redirect"
1417
+ elsif status == 400
1418
+ "Bad Request"
1419
+ elsif status == 401
1420
+ "Unauthorized"
1421
+ elsif status == 402
1422
+ "Payment Required"
1423
+ elsif status == 403
1424
+ "Forbidden"
1425
+ elsif status == 404
1426
+ "Not Found"
1427
+ elsif status == 405
1428
+ "Method Not Allowed"
1429
+ elsif status == 406
1430
+ "Not Acceptable"
1431
+ elsif status == 407
1432
+ "Proxy Authentication Required"
1433
+ elsif status == 408
1434
+ "Request Time-out"
1435
+ elsif status == 409
1436
+ "Conflict"
1437
+ elsif status == 410
1438
+ "Gone"
1439
+ elsif status == 411
1440
+ "Length Required"
1441
+ elsif status == 412
1442
+ "Precondition Failed"
1443
+ elsif status == 413
1444
+ "Request Entity Too Large"
1445
+ elsif status == 414
1446
+ "Request-URI Too Large"
1447
+ elsif status == 415
1448
+ "Unsupported Media Type"
1449
+ elsif status == 416
1450
+ "Requested range not satisfiable"
1451
+ elsif status == 417
1452
+ "Expectation Failed"
1453
+ elsif status == 500
1454
+ "Internal Server Error"
1455
+ elsif status == 501
1456
+ "Not Implemented"
1457
+ elsif status == 502
1458
+ "Bad Gateway"
1459
+ elsif status == 503
1460
+ "Service Unavailable"
1461
+ elsif status == 504
1462
+ "Gateway Time-out"
1463
+ elsif status == 505
1464
+ "HTTP Version not supported"
1465
+ else
1466
+ raise "Unknown Statuscode. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1 for more information."
1467
+ end
1468
+ # }}}
1469
+ end
1470
+ end
1471
+
1472
+ class Cookie
1473
+ attr_reader :name, :value, :maxage, :path, :domain, :secure, :comment
1474
+
1475
+ # Sets a cookie. Please see below for details of the attributes.
1476
+ def initialize (name, value = nil, maxage = nil, path = nil, domain = nil, secure = false)
1477
+ # {{{
1478
+ # HTTP headers (Cookies are a HTTP header) can only set, while no content
1479
+ # is send. So an exception will be raised, when @@allowed is set to false
1480
+ # and a new cookie has set.
1481
+ unless defined?(@@allowed)
1482
+ @@allowed = true
1483
+ end
1484
+ unless @@allowed
1485
+ raise "You can't set cookies after the HTTP headers are send."
1486
+ end
1487
+
1488
+ unless defined?(@@list)
1489
+ @@list = []
1490
+ end
1491
+ @@list += [self]
1492
+
1493
+ unless defined?(@@type)
1494
+ @@type = "netscape"
1495
+ end
1496
+
1497
+ unless name.class == String
1498
+ raise TypeError, "The name of a cookie must be a string", caller
1499
+ end
1500
+ if value.class.superclass == Integer || value.class == Float
1501
+ value = value.to_s
1502
+ elsif value.class != String && value != nil
1503
+ raise TypeError, "The value of a cookie must be a string, integer, float or nil", caller
1504
+ end
1505
+ if maxage.class == Time
1506
+ maxage = maxage - Time.now
1507
+ elsif !maxage.class.superclass == Integer || !maxage == nil
1508
+ raise TypeError, "The maxage date of a cookie must be an Integer or Time object or nil.", caller
1509
+ end
1510
+ unless path.class == String || path == nil
1511
+ raise TypeError, "The path of a cookie must be nil or a string", caller
1512
+ end
1513
+ unless domain.class == String || domain == nil
1514
+ raise TypeError, "The value of a cookie must be nil or a string", caller
1515
+ end
1516
+ unless secure == true || secure == false
1517
+ raise TypeError, "The secure field of a cookie must be true or false", caller
1518
+ end
1519
+
1520
+ @name, @value, @maxage, @path, @domain, @secure = name, value, maxage, path, domain, secure
1521
+ @comment = nil
1522
+ # }}}
1523
+ end
1524
+
1525
+ # Modifies the value of this cookie. The information you want to store. If the
1526
+ # value is nil, the cookie will be deleted by the client.
1527
+ #
1528
+ # This attribute can be a String, Integer or Float object or nil.
1529
+ def value=(value)
1530
+ # {{{
1531
+ if value.class.superclass == Integer || value.class == Float
1532
+ value = value.to_s
1533
+ elsif value.class != String && value != nil
1534
+ raise TypeError, "The value of a cookie must be a string, integer, float or nil", caller
1535
+ end
1536
+ @value = value
1537
+ # }}}
1538
+ end
1539
+
1540
+ # Modifies the maxage of this cookie. This attribute defines the lifetime of
1541
+ # the cookie, in seconds. A value of 0 means the cookie should be discarded
1542
+ # imediatly. If it set to nil, the cookie will be deleted when the browser
1543
+ # will be closed.
1544
+ #
1545
+ # Attention: This is different from other implementations like PHP, where you
1546
+ # gives the seconds since 1/1/1970 0:00:00 GMT.
1547
+ #
1548
+ # This attribute must be an Integer or Time object or nil.
1549
+ def maxage=(maxage)
1550
+ # {{{
1551
+ if maxage.class == Time
1552
+ maxage = maxage - Time.now
1553
+ elsif maxage.class.superclass == Integer || !maxage == nil
1554
+ raise TypeError, "The maxage of a cookie must be an Interger or Time object or nil.", caller
1555
+ end
1556
+ @maxage = maxage
1557
+ # }}}
1558
+ end
1559
+
1560
+ # Modifies the path value of this cookie. The client will send this cookie
1561
+ # only, if the requested document is this directory or a subdirectory of it.
1562
+ #
1563
+ # The value of the attribute must be a String object or nil.
1564
+ def path=(path)
1565
+ # {{{
1566
+ unless path.class == String || path == nil
1567
+ raise TypeError, "The path of a cookie must be nil or a string", caller
1568
+ end
1569
+ @path = path
1570
+ # }}}
1571
+ end
1572
+
1573
+ # Modifies the domain value of this cookie. The client will send this cookie
1574
+ # only if it's connected with this domain (or a subdomain, if the first
1575
+ # character is a dot like in ".ruby-lang.org")
1576
+ #
1577
+ # The value of this attribute must be a String or nil.
1578
+ def domain=(domain)
1579
+ # {{{
1580
+ unless domain.class == String || domain == nil
1581
+ raise TypeError, "The domain of a cookie must be a String or nil.", caller
1582
+ end
1583
+ @domain = domain
1584
+ # }}}
1585
+ end
1586
+
1587
+ # Modifies the secure flag of this cookie. If it's true, the client will only
1588
+ # send this cookie if it is secured connected with us.
1589
+ #
1590
+ # The value od this attribute has to be true or false.
1591
+ def secure=(secure)
1592
+ # {{{
1593
+ unless secure == true || secure == false
1594
+ raise TypeError, "The secure field of a cookie must be true or false", caller
1595
+ end
1596
+ @secure = secure
1597
+ # }}}
1598
+ end
1599
+
1600
+ # Modifies the comment value of this cookie. The comment won't be send, if
1601
+ # type is "netscape".
1602
+ def comment=(comment)
1603
+ # {{{
1604
+ unless comment.class == String || comment == nil
1605
+ raise TypeError, "The comment of a cookie must be a string or nil", caller
1606
+ end
1607
+ @comment = comment
1608
+ # }}}
1609
+ end
1610
+
1611
+ # Changes the type of all cookies.
1612
+ # Allowed values are RFC2109 and netscape (default).
1613
+ def Cookie.type=(type)
1614
+ # {{{
1615
+ unless @@allowed
1616
+ raise "The cookies are allready send, so you can't change the type anymore."
1617
+ end
1618
+ unless type.downcase == "rfc2109" && type.downcase == "netscape"
1619
+ raise "The type of the cookies must be \"RFC2109\" or \"netscape\"."
1620
+ end
1621
+ @@type = type;
1622
+ # }}}
1623
+ end
1624
+
1625
+ # After sending this message, no cookies can be set or modified. Use it, when
1626
+ # HTTP-Headers are send. Rweb does this for you.
1627
+ def Cookie.disallow
1628
+ # {{{
1629
+ @@allowed = false
1630
+ true
1631
+ # }}}
1632
+ end
1633
+
1634
+ # Returns a HTTP header (type String) with all cookies. Rweb does this for
1635
+ # you.
1636
+ def Cookie.getHttpHeader
1637
+ # {{{
1638
+ if defined?(@@list)
1639
+ if @@type == "netscape"
1640
+ str = ""
1641
+ @@list.each do |cookie|
1642
+ if cookie.value == nil
1643
+ cookie.maxage = 0
1644
+ cookie.value = ""
1645
+ end
1646
+ # TODO: Name and value should be escaped!
1647
+ str += "Set-Cookie: #{cookie.name}=#{cookie.value}"
1648
+ unless cookie.maxage == nil
1649
+ expire = Time.now + cookie.maxage
1650
+ expire.gmtime
1651
+ str += "; Expire=#{expire.strftime("%a, %d-%b-%Y %H:%M:%S %Z")}"
1652
+ end
1653
+ unless cookie.domain == nil
1654
+ str += "; Domain=#{cookie.domain}"
1655
+ end
1656
+ unless cookie.path == nil
1657
+ str += "; Path=#{cookie.path}"
1658
+ end
1659
+ if cookie.secure
1660
+ str += "; Secure"
1661
+ end
1662
+ str += "\r\n"
1663
+ end
1664
+ return str
1665
+ else # type == "RFC2109"
1666
+ str = "Set-Cookie: "
1667
+ comma = false;
1668
+
1669
+ @@list.each do |cookie|
1670
+ if cookie.value == nil
1671
+ cookie.maxage = 0
1672
+ cookie.value = ""
1673
+ end
1674
+ if comma
1675
+ str += ","
1676
+ end
1677
+ comma = true
1678
+
1679
+ str += "#{cookie.name}=\"#{cookie.value}\""
1680
+ unless cookie.maxage == nil
1681
+ str += "; Max-Age=\"#{cookie.maxage}\""
1682
+ end
1683
+ unless cookie.domain == nil
1684
+ str += "; Domain=\"#{cookie.domain}\""
1685
+ end
1686
+ unless cookie.path == nil
1687
+ str += "; Path=\"#{cookie.path}\""
1688
+ end
1689
+ if cookie.secure
1690
+ str += "; Secure"
1691
+ end
1692
+ unless cookie.comment == nil
1693
+ str += "; Comment=\"#{cookie.comment}\""
1694
+ end
1695
+ str += "; Version=\"1\""
1696
+ end
1697
+ str
1698
+ end
1699
+ else
1700
+ false
1701
+ end
1702
+ # }}}
1703
+ end
1704
+ end
1705
+
1706
+ require 'strscan'
1707
+
1708
+ module BBCode
1709
+ DEBUG = true
1710
+
1711
+ use 'encoder', 'tags', 'tagstack', 'smileys'
1712
+
1713
+ =begin
1714
+ The Parser class takes care of the encoding.
1715
+ It scans the given BBCode (as plain text), finds tags
1716
+ and smilies and also makes links of urls in text.
1717
+
1718
+ Normal text is send directly to the encoder.
1719
+
1720
+ If a tag was found, an instance of a Tag subclass is created
1721
+ to handle the case.
1722
+
1723
+ The @tagstack manages tag nesting and ensures valid HTML.
1724
+ =end
1725
+
1726
+ class Parser
1727
+ class Attribute
1728
+ # flatten and use only one empty_arg
1729
+ def self.create attr
1730
+ attr = flatten attr
1731
+ return @@empty_attr if attr.empty?
1732
+ new attr
1733
+ end
1734
+
1735
+ private_class_method :new
1736
+
1737
+ # remove leading and trailing whitespace; concat lines
1738
+ def self.flatten attr
1739
+ attr.strip.gsub(/\n/, ' ')
1740
+ # -> ^ and $ can only match at begin and end now
1741
+ end
1742
+
1743
+ ATTRIBUTE_SCAN = /
1744
+ (?!$) # don't match at end
1745
+ \s*
1746
+ ( # $1 = key
1747
+ [^=\s\]"\\]*
1748
+ (?:
1749
+ (?: \\. | "[^"\\]*(?:\\.[^"\\]*)*"? )
1750
+ [^=\s\]"\\]*
1751
+ )*
1752
+ )
1753
+ (?:
1754
+ =
1755
+ ( # $2 = value
1756
+ [^\s\]"\\]*
1757
+ (?:
1758
+ (?: \\. | "[^"\\]*(?:\\.[^"\\]*)*"? )
1759
+ [^\s\]"\\]*
1760
+ )*
1761
+ )?
1762
+ )?
1763
+ \s*
1764
+ /x
1765
+
1766
+ def self.parse source
1767
+ source = source.dup
1768
+ # empty_tag: the tag looks like [... /]
1769
+ # slice!: this deletes the \s*/] at the end
1770
+ # \s+ because [url=http://rubybb.org/forum/] is NOT an empty tag.
1771
+ # In RubyBBCode, you can use [url=http://rubybb.org/forum/ /], and this has to be
1772
+ # interpreted correctly.
1773
+ empty_tag = source.sub!(/^:/, '=') or source.slice!(/\/$/)
1774
+ debug 'PARSE: ' + source.inspect + ' => ' + empty_tag.inspect
1775
+ #-> we have now an attr that's EITHER empty OR begins and ends with non-whitespace.
1776
+
1777
+ attr = Hash.new
1778
+ attr[:flags] = []
1779
+ source.scan(ATTRIBUTE_SCAN) { |key, value|
1780
+ if not value
1781
+ attr[:flags] << unescape(key)
1782
+ else
1783
+ next if value.empty? and key.empty?
1784
+ attr[unescape(key)] = unescape(value)
1785
+ end
1786
+ }
1787
+ debug attr.inspect
1788
+
1789
+ return empty_tag, attr
1790
+ end
1791
+
1792
+ def self.unescape_char esc
1793
+ esc[1]
1794
+ end
1795
+
1796
+ def self.unquote qt
1797
+ qt[1..-1].chomp('"').gsub(/\\./) { |esc| unescape_char esc }
1798
+ end
1799
+
1800
+ def self.unescape str
1801
+ str.gsub(/ (\\.) | (" [^"\\]* (?:\\.[^"\\]*)* "?) /x) {
1802
+ if $1
1803
+ unescape_char $1
1804
+ else
1805
+ unquote $2
1806
+ end
1807
+ }
1808
+ end
1809
+
1810
+ include Enumerable
1811
+ def each &block
1812
+ @args.each(&block)
1813
+ end
1814
+
1815
+ attr_reader :source, :args, :value
1816
+
1817
+ def initialize source
1818
+ @source = source
1819
+ debug 'Attribute#new(%p)' % source
1820
+ @empty_tag, @attr = Attribute.parse source
1821
+ @value = @attr[''].to_s
1822
+ end
1823
+
1824
+ def empty?
1825
+ self == @@empty_attr
1826
+ end
1827
+
1828
+ def empty_tag?
1829
+ @empty_tag
1830
+ end
1831
+
1832
+ def [] *keys
1833
+ res = @attr[*keys]
1834
+ end
1835
+
1836
+ def flags
1837
+ attr[:flags]
1838
+ end
1839
+
1840
+ def to_s
1841
+ @attr
1842
+ end
1843
+
1844
+ def inspect
1845
+ 'ATTR[' + @attr.inspect + (@empty_tag ? ' | empty tag' : '') + ']'
1846
+ end
1847
+ end
1848
+ class Attribute
1849
+ @@empty_attr = new ''
1850
+ end
1851
+ end
1852
+