narf 0.5.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.
- data/ChangeLog +163 -0
- data/InstalledFiles +2227 -0
- data/README +124 -0
- data/TODO +88 -0
- data/bin/narftest +17 -0
- data/bug.rb +9 -0
- data/build.rb +314 -0
- data/build.rb~ +314 -0
- data/config.save +12 -0
- data/doc/apache_cgi.txt +17 -0
- data/doc/fastcgi.txt +19 -0
- data/doc/mod_ruby.txt +7 -0
- data/doc/rdoc/classes/Web.html +366 -0
- data/doc/rdoc/classes/Web.src/M000002.html +15 -0
- data/doc/rdoc/classes/Web.src/M000003.html +15 -0
- data/doc/rdoc/classes/Web.src/M000004.html +15 -0
- data/doc/rdoc/classes/Web.src/M000005.html +15 -0
- data/doc/rdoc/classes/Web.src/M000006.html +20 -0
- data/doc/rdoc/classes/Web.src/M000007.html +18 -0
- data/doc/rdoc/classes/Web.src/M000008.html +18 -0
- data/doc/rdoc/classes/Web.src/M000009.html +18 -0
- data/doc/rdoc/classes/Web.src/M000010.html +15 -0
- data/doc/rdoc/classes/Web.src/M000011.html +15 -0
- data/doc/rdoc/classes/Web.src/M000012.html +15 -0
- data/doc/rdoc/classes/Web/CGD.html +173 -0
- data/doc/rdoc/classes/Web/CGD.src/M000037.html +24 -0
- data/doc/rdoc/classes/Web/CGD.src/M000038.html +23 -0
- data/doc/rdoc/classes/Web/CGD.src/M000039.html +15 -0
- data/doc/rdoc/classes/Web/CGD.src/M000040.html +15 -0
- data/doc/rdoc/classes/Web/CGD.src/M000041.html +23 -0
- data/doc/rdoc/classes/Web/CGI.html +946 -0
- data/doc/rdoc/classes/Web/CGI.src/M000051.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000052.html +24 -0
- data/doc/rdoc/classes/Web/CGI.src/M000053.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000054.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000055.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000056.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000057.html +17 -0
- data/doc/rdoc/classes/Web/CGI.src/M000058.html +34 -0
- data/doc/rdoc/classes/Web/CGI.src/M000059.html +22 -0
- data/doc/rdoc/classes/Web/CGI.src/M000060.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000061.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000062.html +19 -0
- data/doc/rdoc/classes/Web/CGI.src/M000063.html +18 -0
- data/doc/rdoc/classes/Web/CGI.src/M000064.html +19 -0
- data/doc/rdoc/classes/Web/CGI.src/M000065.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000066.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000067.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000068.html +13 -0
- data/doc/rdoc/classes/Web/CGI.src/M000069.html +13 -0
- data/doc/rdoc/classes/Web/CGI.src/M000070.html +13 -0
- data/doc/rdoc/classes/Web/CGI.src/M000071.html +13 -0
- data/doc/rdoc/classes/Web/CGI.src/M000072.html +19 -0
- data/doc/rdoc/classes/Web/CGI.src/M000073.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000074.html +19 -0
- data/doc/rdoc/classes/Web/CGI.src/M000075.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000076.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000077.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000078.html +20 -0
- data/doc/rdoc/classes/Web/CGI.src/M000079.html +36 -0
- data/doc/rdoc/classes/Web/CGI.src/M000080.html +19 -0
- data/doc/rdoc/classes/Web/CGI.src/M000081.html +18 -0
- data/doc/rdoc/classes/Web/CGI.src/M000082.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000083.html +17 -0
- data/doc/rdoc/classes/Web/CGI.src/M000084.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000085.html +16 -0
- data/doc/rdoc/classes/Web/CGI.src/M000086.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000087.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000088.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000089.html +16 -0
- data/doc/rdoc/classes/Web/CGI.src/M000090.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000091.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000092.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000093.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000094.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000095.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000096.html +19 -0
- data/doc/rdoc/classes/Web/CGI.src/M000097.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000098.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000099.html +43 -0
- data/doc/rdoc/classes/Web/CGI.src/M000100.html +18 -0
- data/doc/rdoc/classes/Web/CGI.src/M000101.html +20 -0
- data/doc/rdoc/classes/Web/CGI.src/M000102.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000103.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000104.html +15 -0
- data/doc/rdoc/classes/Web/CGI.src/M000105.html +24 -0
- data/doc/rdoc/classes/Web/CGI.src/M000106.html +24 -0
- data/doc/rdoc/classes/Web/CGI.src/M000107.html +22 -0
- data/doc/rdoc/classes/Web/CaseInsensitiveHash.html +104 -0
- data/doc/rdoc/classes/Web/CaseInsensitiveHash.src/M000118.html +15 -0
- data/doc/rdoc/classes/Web/CaseInsensitiveHash.src/M000119.html +15 -0
- data/doc/rdoc/classes/Web/CaseInsensitiveHash.src/M000120.html +15 -0
- data/doc/rdoc/classes/Web/Mime.html +122 -0
- data/doc/rdoc/classes/Web/Mime.src/M000118.html +15 -0
- data/doc/rdoc/classes/Web/Mime.src/M000119.html +15 -0
- data/doc/rdoc/classes/Web/Mime.src/M000120.html +23 -0
- data/doc/rdoc/classes/Web/Mime.src/M000121.html +15 -0
- data/doc/rdoc/classes/Web/Mime.src/M000122.html +15 -0
- data/doc/rdoc/classes/Web/Mime.src/M000123.html +23 -0
- data/doc/rdoc/classes/Web/Mime.src/M000124.html +15 -0
- data/doc/rdoc/classes/Web/Narflates.html +132 -0
- data/doc/rdoc/classes/Web/Parser.html +219 -0
- data/doc/rdoc/classes/Web/Parser.src/M000013.html +21 -0
- data/doc/rdoc/classes/Web/Parser.src/M000014.html +19 -0
- data/doc/rdoc/classes/Web/Parser.src/M000015.html +21 -0
- data/doc/rdoc/classes/Web/Parser.src/M000016.html +15 -0
- data/doc/rdoc/classes/Web/Parser.src/M000017.html +30 -0
- data/doc/rdoc/classes/Web/Parser.src/M000018.html +15 -0
- data/doc/rdoc/classes/Web/Parser.src/M000019.html +19 -0
- data/doc/rdoc/classes/Web/Parser.src/M000020.html +27 -0
- data/doc/rdoc/classes/Web/Parser.src/M000021.html +15 -0
- data/doc/rdoc/classes/Web/Parser.src/M000022.html +16 -0
- data/doc/rdoc/classes/Web/Parser.src/M000023.html +18 -0
- data/doc/rdoc/classes/Web/Session.html +178 -0
- data/doc/rdoc/classes/Web/Session.src/M000042.html +20 -0
- data/doc/rdoc/classes/Web/Session.src/M000043.html +19 -0
- data/doc/rdoc/classes/Web/Session.src/M000044.html +21 -0
- data/doc/rdoc/classes/Web/Session.src/M000045.html +21 -0
- data/doc/rdoc/classes/Web/Session.src/M000046.html +15 -0
- data/doc/rdoc/classes/Web/Session.src/M000047.html +17 -0
- data/doc/rdoc/classes/Web/Session.src/M000048.html +15 -0
- data/doc/rdoc/classes/Web/Session.src/M000049.html +15 -0
- data/doc/rdoc/classes/Web/Session.src/M000050.html +16 -0
- data/doc/rdoc/classes/Web/Testing.html +474 -0
- data/doc/rdoc/classes/Web/Testing.src/M000024.html +15 -0
- data/doc/rdoc/classes/Web/Testing.src/M000025.html +25 -0
- data/doc/rdoc/classes/Web/Testing.src/M000026.html +15 -0
- data/doc/rdoc/classes/Web/Testing.src/M000027.html +28 -0
- data/doc/rdoc/classes/Web/Testing.src/M000028.html +58 -0
- data/doc/rdoc/classes/Web/Testing.src/M000029.html +15 -0
- data/doc/rdoc/classes/Web/Testing.src/M000030.html +15 -0
- data/doc/rdoc/classes/Web/Testing.src/M000031.html +15 -0
- data/doc/rdoc/classes/Web/Testing.src/M000032.html +15 -0
- data/doc/rdoc/classes/Web/Testing.src/M000033.html +15 -0
- data/doc/rdoc/classes/Web/Testing.src/M000034.html +15 -0
- data/doc/rdoc/classes/Web/Testing.src/M000035.html +15 -0
- data/doc/rdoc/classes/Web/Testing.src/M000036.html +18 -0
- data/doc/rdoc/classes/Web/Upload.html +160 -0
- data/doc/rdoc/classes/Web/Upload.src/M000108.html +25 -0
- data/doc/rdoc/classes/Web/Upload.src/M000109.html +18 -0
- data/doc/rdoc/classes/Web/Upload.src/M000110.html +16 -0
- data/doc/rdoc/classes/Web/Upload.src/M000111.html +16 -0
- data/doc/rdoc/classes/Web/Wiki.html +249 -0
- data/doc/rdoc/classes/Web/Wiki.src/M000112.html +25 -0
- data/doc/rdoc/classes/Web/Wiki.src/M000113.html +15 -0
- data/doc/rdoc/classes/Web/Wiki.src/M000114.html +26 -0
- data/doc/rdoc/classes/Web/Wiki.src/M000115.html +21 -0
- data/doc/rdoc/classes/Web/Wiki.src/M000116.html +18 -0
- data/doc/rdoc/classes/Web/Wiki.src/M000117.html +19 -0
- data/doc/rdoc/created.rid +1 -0
- data/doc/rdoc/files/README.html +226 -0
- data/doc/rdoc/files/doc/apache_cgi_txt.html +82 -0
- data/doc/rdoc/files/doc/fastcgi_txt.html +82 -0
- data/doc/rdoc/files/doc/mod_ruby_txt.html +62 -0
- data/doc/rdoc/files/doc/webrick_txt.html +79 -0
- data/doc/rdoc/files/examples/examples_rdoc.html +73 -0
- data/doc/rdoc/files/lib/web/cgi_rb.html +75 -0
- data/doc/rdoc/files/lib/web/mime_rb.html +67 -0
- data/doc/rdoc/files/lib/web/parser_rb.html +73 -0
- data/doc/rdoc/files/lib/web/session_rb.html +73 -0
- data/doc/rdoc/files/lib/web/template_rb.html +73 -0
- data/doc/rdoc/files/lib/web/testing_rb.html +67 -0
- data/doc/rdoc/files/lib/web/upload_rb.html +73 -0
- data/doc/rdoc/files/lib/web/wiki_rb.html +79 -0
- data/doc/rdoc/files/lib/web_rb.html +116 -0
- data/doc/rdoc/files/lib/web_rb.src/M000001.html +15 -0
- data/doc/rdoc/fr_class_index.html +47 -0
- data/doc/rdoc/fr_file_index.html +52 -0
- data/doc/rdoc/fr_method_index.html +158 -0
- data/doc/rdoc/index.html +22 -0
- data/doc/rdoc/rdoc-style.css +99 -0
- data/doc/webrick.txt +23 -0
- data/examples/admin.rb +8 -0
- data/examples/admin.rb~ +5 -0
- data/examples/cookbook.rdoc +247 -0
- data/examples/cookbook.rdoc~ +238 -0
- data/examples/examples.rdoc +19 -0
- data/examples/examples.rdoc~ +17 -0
- data/examples/hello.world.rb +5 -0
- data/examples/hello.world.rb~ +3 -0
- data/examples/session.rb +34 -0
- data/examples/session.rb~ +31 -0
- data/examples/test/test.hello.world.rb +9 -0
- data/examples/test/test.hello.world.rb~ +9 -0
- data/examples/test/test.session.rb +37 -0
- data/examples/test/test.session.rb~ +37 -0
- data/examples/webunit/COPYING +340 -0
- data/examples/webunit/Makefile +14 -0
- data/examples/webunit/TIPS-ja.html +126 -0
- data/examples/webunit/TIPS-ja.rd +154 -0
- data/examples/webunit/TODO-ja.html +35 -0
- data/examples/webunit/TODO-ja.rd +28 -0
- data/examples/webunit/changes.rd +185 -0
- data/examples/webunit/conv/digit-0.cgi +40 -0
- data/examples/webunit/conv/digit-0.rb +21 -0
- data/examples/webunit/conv/digit-1.cgi +44 -0
- data/examples/webunit/conv/digit-1.rb +17 -0
- data/examples/webunit/conv/digit.cgi +59 -0
- data/examples/webunit/conv/digit.rb +23 -0
- data/examples/webunit/conv/test_digit-0.rb +16 -0
- data/examples/webunit/conv/test_digit-1.rb +19 -0
- data/examples/webunit/conv/test_digit.rb +26 -0
- data/examples/webunit/conv/test_digit_view-0.rb +76 -0
- data/examples/webunit/conv/test_digit_view-1.rb +102 -0
- data/examples/webunit/conv/test_digit_view.rb +134 -0
- data/examples/webunit/example.rd +37 -0
- data/examples/webunit/index-en.html +263 -0
- data/examples/webunit/index-en.rd +60 -0
- data/examples/webunit/index-ja.html +263 -0
- data/examples/webunit/index-ja.rd +60 -0
- data/examples/wiki.rb +7 -0
- data/examples/wiki.rb~ +5 -0
- data/install.rb +1022 -0
- data/lib/web.rb +290 -0
- data/lib/web.rb~ +290 -0
- data/lib/web/#assertinclude.rb# +110 -0
- data/lib/web/action.rb +82 -0
- data/lib/web/assertinclude.rb +110 -0
- data/lib/web/assertinclude.rb~ +110 -0
- data/lib/web/buffer.rb +20 -0
- data/lib/web/cgi.rb +641 -0
- data/lib/web/cgi.rb~ +640 -0
- data/lib/web/formreader.rb +317 -0
- data/lib/web/forms.rb +104 -0
- data/lib/web/htmlparser/html-parser.rb +429 -0
- data/lib/web/htmlparser/html-parser.rb~ +429 -0
- data/lib/web/htmlparser/sgml-parser.rb +332 -0
- data/lib/web/htmlparser/sgml-parser.rb~ +332 -0
- data/lib/web/htmltools/element.rb +296 -0
- data/lib/web/htmltools/element.rb~ +296 -0
- data/lib/web/htmltools/stparser.rb +276 -0
- data/lib/web/htmltools/stparser.rb~ +276 -0
- data/lib/web/htmltools/tags.rb +286 -0
- data/lib/web/htmltools/tags.rb~ +286 -0
- data/lib/web/htmltools/tree.rb +139 -0
- data/lib/web/htmltools/tree.rb~ +139 -0
- data/lib/web/htmltools/xmltree.rb +160 -0
- data/lib/web/htmltools/xmltree.rb~ +160 -0
- data/lib/web/htmltools/xpath.rb +71 -0
- data/lib/web/htmltools/xpath.rb~ +71 -0
- data/lib/web/mime.rb +82 -0
- data/lib/web/parser.rb +266 -0
- data/lib/web/parser.rb~ +266 -0
- data/lib/web/request.rb~ +238 -0
- data/lib/web/resources/mime.types +483 -0
- data/lib/web/runner.rb +26 -0
- data/lib/web/runner.rb~ +26 -0
- data/lib/web/sapi/fastcgi.rb +26 -0
- data/lib/web/sapi/fastcgi.rb~ +25 -0
- data/lib/web/sapi/mod_ruby.rb +46 -0
- data/lib/web/sapi/mod_ruby.rb~ +46 -0
- data/lib/web/sapi/webrick.rb +91 -0
- data/lib/web/sapi/webrick.rb~ +89 -0
- data/lib/web/session.rb +75 -0
- data/lib/web/session.rb~ +75 -0
- data/lib/web/simpledispatcher.rb +155 -0
- data/lib/web/strscanparser.rb +24 -0
- data/lib/web/tagparser.rb +96 -0
- data/lib/web/tagparser.rb~ +96 -0
- data/lib/web/template.rb +613 -0
- data/lib/web/template.rb~ +613 -0
- data/lib/web/testing.rb +546 -0
- data/lib/web/testing.rb~ +546 -0
- data/lib/web/traceoutput.rb +32 -0
- data/lib/web/unit.rb +27 -0
- data/lib/web/unit/assert.rb +154 -0
- data/lib/web/unit/converter.rb +148 -0
- data/lib/web/unit/cookie.rb +120 -0
- data/lib/web/unit/domwalker.rb +187 -0
- data/lib/web/unit/exception.rb +15 -0
- data/lib/web/unit/form.rb +118 -0
- data/lib/web/unit/formatter.rb +314 -0
- data/lib/web/unit/frame.rb +39 -0
- data/lib/web/unit/html-parser.rb +432 -0
- data/lib/web/unit/htmlelem.rb +124 -0
- data/lib/web/unit/htmlrepair.rb +116 -0
- data/lib/web/unit/htmlsplit.rb +840 -0
- data/lib/web/unit/image.rb +27 -0
- data/lib/web/unit/jscript.rb +32 -0
- data/lib/web/unit/link.rb +35 -0
- data/lib/web/unit/params.rb +323 -0
- data/lib/web/unit/parser.rb +226 -0
- data/lib/web/unit/resources/assert.html +101 -0
- data/lib/web/unit/resources/auth/index.html +5 -0
- data/lib/web/unit/resources/badtags.html +7 -0
- data/lib/web/unit/resources/cookie.cgi +33 -0
- data/lib/web/unit/resources/document.xml +13 -0
- data/lib/web/unit/resources/form.html +150 -0
- data/lib/web/unit/resources/frame-0.html +10 -0
- data/lib/web/unit/resources/frame-1.html +10 -0
- data/lib/web/unit/resources/frame.html +10 -0
- data/lib/web/unit/resources/image.html +17 -0
- data/lib/web/unit/resources/images/x.gif +0 -0
- data/lib/web/unit/resources/images/y.gif +0 -0
- data/lib/web/unit/resources/jscript-0.html +10 -0
- data/lib/web/unit/resources/jscript-1.html +10 -0
- data/lib/web/unit/resources/jscript.html +19 -0
- data/lib/web/unit/resources/link.html +19 -0
- data/lib/web/unit/resources/multipart.cgi +28 -0
- data/lib/web/unit/resources/multipart.html +74 -0
- data/lib/web/unit/resources/params.html +65 -0
- data/lib/web/unit/resources/redirect.cgi +13 -0
- data/lib/web/unit/resources/response.html +67 -0
- data/lib/web/unit/resources/simple.cgi +14 -0
- data/lib/web/unit/resources/stock.cgi +35 -0
- data/lib/web/unit/resources/table.html +83 -0
- data/lib/web/unit/response.rb +469 -0
- data/lib/web/unit/response.rb~ +461 -0
- data/lib/web/unit/runtest.rb +44 -0
- data/lib/web/unit/sgml-parser.rb +336 -0
- data/lib/web/unit/table.rb +150 -0
- data/lib/web/unit/testcase.rb +49 -0
- data/lib/web/unit/ui/cui/testrunner.rb +52 -0
- data/lib/web/unit/ui/cui/testrunner.rb~ +50 -0
- data/lib/web/unit/utils.rb +70 -0
- data/lib/web/unit/webunit.rb +28 -0
- data/lib/web/upload.rb +55 -0
- data/lib/web/upload.rb~ +262 -0
- data/lib/web/wiki.rb +506 -0
- data/lib/web/wiki.rb~ +506 -0
- data/lib/web/wiki/linker.rb +72 -0
- data/lib/web/wiki/linker.rb~ +72 -0
- data/lib/web/wiki/mime.rb~ +68 -0
- data/lib/web/wiki/page.rb +192 -0
- data/lib/web/wiki/page.rb~ +192 -0
- data/lib/web/wiki/resources/#edit.html# +65 -0
- data/lib/web/wiki/resources/admin.html +13 -0
- data/lib/web/wiki/resources/admin.html~ +13 -0
- data/lib/web/wiki/resources/asset_history.html +3 -0
- data/lib/web/wiki/resources/basic.html +1 -0
- data/lib/web/wiki/resources/default-content_editor.html +1 -0
- data/lib/web/wiki/resources/default-content_editor.html~ +1 -0
- data/lib/web/wiki/resources/edit.html +1 -1
- data/lib/web/wiki/resources/edit.html~ +1 -1
- data/lib/web/wiki/resources/ekit-content_editor.html +1 -0
- data/lib/web/wiki/resources/home.html +10 -0
- data/lib/web/wiki/resources/home.html~ +10 -0
- data/lib/web/wiki/resources/htmlarea/ChangeLog +1185 -0
- data/lib/web/wiki/resources/htmlarea/dialog.js +72 -0
- data/lib/web/wiki/resources/htmlarea/examples/2-areas.cgi +16 -0
- data/lib/web/wiki/resources/htmlarea/examples/2-areas.html +158 -0
- data/lib/web/wiki/resources/htmlarea/examples/context-menu.html +95 -0
- data/lib/web/wiki/resources/htmlarea/examples/core.html +184 -0
- data/lib/web/wiki/resources/htmlarea/examples/css.html +88 -0
- data/lib/web/wiki/resources/htmlarea/examples/custom.css +29 -0
- data/lib/web/wiki/resources/htmlarea/examples/full-page.html +75 -0
- data/lib/web/wiki/resources/htmlarea/examples/fully-loaded.html +248 -0
- data/lib/web/wiki/resources/htmlarea/examples/index.html +40 -0
- data/lib/web/wiki/resources/htmlarea/examples/spell-checker.html +132 -0
- data/lib/web/wiki/resources/htmlarea/examples/table-operations.html +116 -0
- data/lib/web/wiki/resources/htmlarea/examples/test.cgi +21 -0
- data/lib/web/wiki/resources/htmlarea/htmlarea.css +180 -0
- data/lib/web/wiki/resources/htmlarea/htmlarea.js +2175 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_about.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_align_center.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_align_justify.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_align_left.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_align_right.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_blank.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_charmap.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_color_bg.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_color_fg.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_copy.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_custom.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_cut.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_delete.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_format_bold.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_format_italic.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_format_strike.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_format_sub.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_format_sup.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_format_underline.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_help.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_hr.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_html.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_image.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_indent_less.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_indent_more.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_left_to_right.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_link.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_list_bullet.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_list_num.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_paste.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_redo.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_right_to_left.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_save.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_show_border.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_splitcel.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/ed_undo.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/fullscreen_maximize.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/fullscreen_minimize.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/images/insert_table.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/index.html +199 -0
- data/lib/web/wiki/resources/htmlarea/lang/b5.js +36 -0
- data/lib/web/wiki/resources/htmlarea/lang/cz.js +63 -0
- data/lib/web/wiki/resources/htmlarea/lang/da.js +38 -0
- data/lib/web/wiki/resources/htmlarea/lang/de.js +54 -0
- data/lib/web/wiki/resources/htmlarea/lang/ee.js +63 -0
- data/lib/web/wiki/resources/htmlarea/lang/el.js +75 -0
- data/lib/web/wiki/resources/htmlarea/lang/en.js +88 -0
- data/lib/web/wiki/resources/htmlarea/lang/es.js +51 -0
- data/lib/web/wiki/resources/htmlarea/lang/fi.js +46 -0
- data/lib/web/wiki/resources/htmlarea/lang/fr.js +61 -0
- data/lib/web/wiki/resources/htmlarea/lang/gb.js +36 -0
- data/lib/web/wiki/resources/htmlarea/lang/he.js +63 -0
- data/lib/web/wiki/resources/htmlarea/lang/hu.js +63 -0
- data/lib/web/wiki/resources/htmlarea/lang/it.js +54 -0
- data/lib/web/wiki/resources/htmlarea/lang/ja-euc.js +37 -0
- data/lib/web/wiki/resources/htmlarea/lang/ja-jis.js +37 -0
- data/lib/web/wiki/resources/htmlarea/lang/ja-sjis.js +37 -0
- data/lib/web/wiki/resources/htmlarea/lang/ja-utf8.js +37 -0
- data/lib/web/wiki/resources/htmlarea/lang/lt.js +55 -0
- data/lib/web/wiki/resources/htmlarea/lang/lv.js +55 -0
- data/lib/web/wiki/resources/htmlarea/lang/nb.js +36 -0
- data/lib/web/wiki/resources/htmlarea/lang/nl.js +90 -0
- data/lib/web/wiki/resources/htmlarea/lang/no.js +79 -0
- data/lib/web/wiki/resources/htmlarea/lang/pl.js +36 -0
- data/lib/web/wiki/resources/htmlarea/lang/pt_br.js +37 -0
- data/lib/web/wiki/resources/htmlarea/lang/ro.js +80 -0
- data/lib/web/wiki/resources/htmlarea/lang/ru.js +63 -0
- data/lib/web/wiki/resources/htmlarea/lang/se.js +38 -0
- data/lib/web/wiki/resources/htmlarea/lang/si.js +63 -0
- data/lib/web/wiki/resources/htmlarea/lang/vn.js +51 -0
- data/lib/web/wiki/resources/htmlarea/license.txt +30 -0
- data/lib/web/wiki/resources/htmlarea/plugins/CSS/css.js +116 -0
- data/lib/web/wiki/resources/htmlarea/plugins/CSS/lang/en.js +2 -0
- data/lib/web/wiki/resources/htmlarea/plugins/ContextMenu/context-menu.js +416 -0
- data/lib/web/wiki/resources/htmlarea/plugins/ContextMenu/lang/de.js +59 -0
- data/lib/web/wiki/resources/htmlarea/plugins/ContextMenu/lang/el.js +57 -0
- data/lib/web/wiki/resources/htmlarea/plugins/ContextMenu/lang/en.js +66 -0
- data/lib/web/wiki/resources/htmlarea/plugins/ContextMenu/lang/nl.js +66 -0
- data/lib/web/wiki/resources/htmlarea/plugins/ContextMenu/menu.css +64 -0
- data/lib/web/wiki/resources/htmlarea/plugins/FullPage/full-page.js +143 -0
- data/lib/web/wiki/resources/htmlarea/plugins/FullPage/img/docprop.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/FullPage/lang/en.js +25 -0
- data/lib/web/wiki/resources/htmlarea/plugins/FullPage/lang/ro.js +25 -0
- data/lib/web/wiki/resources/htmlarea/plugins/FullPage/popups/docprop.html +131 -0
- data/lib/web/wiki/resources/htmlarea/plugins/FullPage/test.html +89 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/img/spell-check.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/cz.js +37 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/da.js +37 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/de.js +28 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/en.js +38 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/hu.js +37 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/it.js +28 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/ro.js +37 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/readme-tech.html +114 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/spell-check-logic.cgi +210 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/spell-check-style.css +10 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/spell-check-ui.html +122 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/spell-check-ui.js +397 -0
- data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/spell-checker.js +79 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/cell-delete.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/cell-insert-after.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/cell-insert-before.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/cell-merge.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/cell-prop.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/cell-split.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/col-delete.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/col-insert-after.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/col-insert-before.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/col-split.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/row-delete.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/row-insert-above.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/row-insert-under.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/row-prop.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/row-split.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/table-prop.gif +0 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/cz.js +90 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/da.js +90 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/de.js +81 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/el.js +81 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/en.js +90 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/fi.js +66 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/hu.js +63 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/it.js +81 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/nl.js +90 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/no.js +91 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/ro.js +90 -0
- data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/table-operations.js +1160 -0
- data/lib/web/wiki/resources/htmlarea/popupdiv.js +369 -0
- data/lib/web/wiki/resources/htmlarea/popups/about.html +378 -0
- data/lib/web/wiki/resources/htmlarea/popups/blank.html +2 -0
- data/lib/web/wiki/resources/htmlarea/popups/custom2.html +35 -0
- data/lib/web/wiki/resources/htmlarea/popups/editor_help.html +16 -0
- data/lib/web/wiki/resources/htmlarea/popups/fullscreen.html +133 -0
- data/lib/web/wiki/resources/htmlarea/popups/insert_image.html +191 -0
- data/lib/web/wiki/resources/htmlarea/popups/insert_table.html +174 -0
- data/lib/web/wiki/resources/htmlarea/popups/link.html +142 -0
- data/lib/web/wiki/resources/htmlarea/popups/old-fullscreen.html +131 -0
- data/lib/web/wiki/resources/htmlarea/popups/old_insert_image.html +206 -0
- data/lib/web/wiki/resources/htmlarea/popups/popup.js +109 -0
- data/lib/web/wiki/resources/htmlarea/popups/select_color.html +347 -0
- data/lib/web/wiki/resources/htmlarea/popupwin.js +139 -0
- data/lib/web/wiki/resources/htmlarea/reference.html +523 -0
- data/lib/web/wiki/resources/htmlarea/release-notes.html +165 -0
- data/lib/web/wiki/resources/ie-content_editor.html +1 -0
- data/lib/web/wiki/resources/ie-content_editor.js +196 -0
- data/lib/web/wiki/resources/illustration.html +1 -0
- data/lib/web/wiki/resources/illustration.html~ +1 -0
- data/lib/web/wiki/resources/images.html +1 -0
- data/lib/web/wiki/resources/index.html +4 -0
- data/lib/web/wiki/resources/index.html~ +4 -0
- data/lib/web/wiki/resources/more_news.html +5 -0
- data/lib/web/wiki/resources/more_news.html~ +5 -0
- data/lib/web/wiki/resources/more_news_rss_0.91.html +23 -0
- data/lib/web/wiki/resources/narf-logo.gif +0 -0
- data/lib/web/wiki/resources/page_history.html +19 -0
- data/lib/web/wiki/resources/page_history.html~ +19 -0
- data/lib/web/wiki/resources/template.html +13 -0
- data/lib/web/wiki/resources/template.html~ +13 -0
- data/lib/web/wiki/resources/test_upload.gif +0 -0
- data/lib/web/wiki/resources/text-styles.css +1 -0
- data/lib/web/writableio.rb +33 -0
- data/narf-0.5.1.gem +0 -0
- data/narf.gemspec +40 -0
- data/narf.gemspec~ +52 -0
- data/pre-setup.rb +5 -0
- data/sapi/apache_cgi/INSTALL.txt~ +9 -0
- data/sapi/apache_cgi/README~ +0 -0
- data/sapi/apache_cgi/src/narf.c +13 -0
- data/sapi/fastcgi/INSTALL.txt~ +17 -0
- data/sapi/mod_ruby/INSTALL.txt~ +5 -0
- data/sapi/webrick/INSTALL.txt~ +21 -0
- data/sapi/webrick/run_webrick.rb~ +16 -0
- data/scripts/dump.rb +14 -0
- data/scripts/makedist.rb +49 -0
- data/scripts/upload.html +5 -0
- data/scripts/uri.rb +41 -0
- data/scripts/uri/common.rb +432 -0
- data/scripts/uri/ftp.rb +149 -0
- data/scripts/uri/generic.rb +1106 -0
- data/scripts/uri/http.rb +76 -0
- data/scripts/uri/https.rb +26 -0
- data/scripts/uri/ldap.rb +238 -0
- data/scripts/uri/mailto.rb +260 -0
- data/scripts/urireg.rb +174 -0
- data/test/bufferedtestrunner.rb +112 -0
- data/test/mod_ruby_stub.rb +39 -0
- data/test/mod_ruby_stub.rb~ +38 -0
- data/test/stringio.rb +2 -0
- data/test/test.action.rb +142 -0
- data/test/test.action.rb~ +142 -0
- data/test/test.app.rb +0 -0
- data/test/test.assertinclude.rb +109 -0
- data/test/test.assertinclude.rb~ +109 -0
- data/test/test.formreader-2.0.rb +352 -0
- data/test/test.formreader.rb +465 -0
- data/test/test.mime-type.rb +23 -0
- data/test/test.narf.cgi.rb +101 -0
- data/test/test.narf.cgi.rb~ +105 -0
- data/test/test.request.rb +328 -0
- data/test/test.request.rb~ +318 -0
- data/test/test.response.rb +565 -0
- data/test/test.response.rb~ +556 -0
- data/test/test.session.rb +50 -0
- data/test/test.simpledispatcher.rb +188 -0
- data/test/test.tagparser.rb +65 -0
- data/test/test.template.rb +831 -0
- data/test/test.template.rb~ +832 -0
- data/test/test.testing2.rb +341 -0
- data/test/test.web.test.rb +463 -0
- data/test/test.web.test.rb~ +461 -0
- data/test/testfiles/basictemplate.tpl +1 -0
- data/test/testfiles/explorer5.multipart.data +9 -0
- data/test/testfiles/form.html +7 -0
- data/test/testfiles/mozilla.multipart.data +9 -0
- data/test/testfiles/netscape4.multipart.data +9 -0
- data/test/testfiles/pic hydra.png +1 -0
- data/test/testfiles/post.data +1 -0
- data/test/testfiles/print.text +1 -0
- data/test/testfiles/text +1 -0
- data/test/webunit/dont_get_it.test_webunit.rb +27 -0
- data/test/webunit/ref +38 -0
- data/test/webunit/resources/uploadfile1.txt +1 -0
- data/test/webunit/resources/uploadfile2.txt +1 -0
- data/test/webunit/test_assert.rb +169 -0
- data/test/webunit/test_cookie.rb +128 -0
- data/test/webunit/test_cookie.rb~ +128 -0
- data/test/webunit/test_domwalker.rb +83 -0
- data/test/webunit/test_form.rb +43 -0
- data/test/webunit/test_form.rb~ +43 -0
- data/test/webunit/test_frame.rb +43 -0
- data/test/webunit/test_htmlelem.rb +75 -0
- data/test/webunit/test_image.rb +46 -0
- data/test/webunit/test_jscript.rb +58 -0
- data/test/webunit/test_link.rb +87 -0
- data/test/webunit/test_multipart.rb +53 -0
- data/test/webunit/test_multipart.rb~ +53 -0
- data/test/webunit/test_params.rb +212 -0
- data/test/webunit/test_params.rb~ +211 -0
- data/test/webunit/test_parser.rb +31 -0
- data/test/webunit/test_response.rb +145 -0
- data/test/webunit/test_response.rb~ +145 -0
- data/test/webunit/test_site/assert.html +101 -0
- data/test/webunit/test_site/assert.html~ +1 -0
- data/test/webunit/test_site/auth/index.html +5 -0
- data/test/webunit/test_site/auth/index.html~ +1 -0
- data/test/webunit/test_site/badtags.html +7 -0
- data/test/webunit/test_site/badtags.html~ +1 -0
- data/test/webunit/test_site/cookie.cgi +37 -0
- data/test/webunit/test_site/cookie.cgi~ +35 -0
- data/test/webunit/test_site/document.xml +13 -0
- data/test/webunit/test_site/document.xml~ +1 -0
- data/test/webunit/test_site/form.html +150 -0
- data/test/webunit/test_site/form.html~ +1 -0
- data/test/webunit/test_site/frame-0.html +10 -0
- data/test/webunit/test_site/frame-0.html~ +1 -0
- data/test/webunit/test_site/frame-1.html +10 -0
- data/test/webunit/test_site/frame-1.html~ +1 -0
- data/test/webunit/test_site/frame.html +10 -0
- data/test/webunit/test_site/frame.html~ +1 -0
- data/test/webunit/test_site/image.html +17 -0
- data/test/webunit/test_site/image.html~ +1 -0
- data/test/webunit/test_site/images/x.gif +0 -0
- data/test/webunit/test_site/images/y.gif +0 -0
- data/test/webunit/test_site/include.cgi~ +10 -0
- data/test/webunit/test_site/jscript-0.html +10 -0
- data/test/webunit/test_site/jscript-0.html~ +1 -0
- data/test/webunit/test_site/jscript-1.html +10 -0
- data/test/webunit/test_site/jscript-1.html~ +1 -0
- data/test/webunit/test_site/jscript.html +19 -0
- data/test/webunit/test_site/jscript.html~ +1 -0
- data/test/webunit/test_site/link.html +19 -0
- data/test/webunit/test_site/link.html~ +1 -0
- data/test/webunit/test_site/multipart.cgi +27 -0
- data/test/webunit/test_site/multipart.cgi~ +25 -0
- data/test/webunit/test_site/multipart.html +74 -0
- data/test/webunit/test_site/multipart.html~ +1 -0
- data/test/webunit/test_site/params.html +65 -0
- data/test/webunit/test_site/params.html~ +1 -0
- data/test/webunit/test_site/redirect.cgi +14 -0
- data/test/webunit/test_site/redirect.cgi~ +14 -0
- data/test/webunit/test_site/response.html +67 -0
- data/test/webunit/test_site/response.html~ +1 -0
- data/test/webunit/test_site/simple.cgi +17 -0
- data/test/webunit/test_site/simple.cgi~ +17 -0
- data/test/webunit/test_site/stock.cgi +36 -0
- data/test/webunit/test_site/stock.cgi~ +34 -0
- data/test/webunit/test_site/table.html +83 -0
- data/test/webunit/test_site/table.html~ +1 -0
- data/test/webunit/test_site/test.cgi~ +25 -0
- data/test/webunit/test_table.rb +70 -0
- data/test/webunit/test_utils.rb +107 -0
- data/test/wiki/test.history.rb +277 -0
- data/test/wiki/test.history.rb~ +254 -0
- data/test/wiki/test.illustration_page.rb +287 -0
- data/test/wiki/test.illustration_page.rb~ +287 -0
- data/test/wiki/test.linker.rb +197 -0
- data/test/wiki/test.tarpit.rb +40 -0
- data/test/wiki/test.wiki.rb +295 -0
- data/test/wiki/test.wiki.rb~ +295 -0
- data/test/wikitestroot/big_image.jpg +0 -0
- data/test/wikitestroot/mime.types +483 -0
- data/test/wikitestroot/test_upload.gif +0 -0
- data/vandals.test.txt +3 -0
- metadata +768 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
class Array # :nodoc:
|
|
2
|
+
def has_key?(index)
|
|
3
|
+
index >= 0 && index < length
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def __index(key)
|
|
7
|
+
self[key]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def compare_includes? haystack, prefix=[]
|
|
11
|
+
message = ""
|
|
12
|
+
each_with_index{ |v, k|
|
|
13
|
+
fullname = prefix.clone
|
|
14
|
+
if fullname.length > 0
|
|
15
|
+
fullname[fullname.length-1] = "#{fullname.last}[#{k}]"
|
|
16
|
+
else
|
|
17
|
+
fullname[0] = "<Array>[#{k}]"
|
|
18
|
+
end
|
|
19
|
+
fullname_str = fullname.join(".")
|
|
20
|
+
message += do_thing(haystack, k, v, fullname, fullname_str)
|
|
21
|
+
}
|
|
22
|
+
message
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Object # :nodoc:
|
|
28
|
+
def has_key? key
|
|
29
|
+
respond_to? key.intern
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def __index(key)
|
|
33
|
+
send key.intern
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def do_thing haystack, k, v, fullname, fullname_str
|
|
37
|
+
message = ""
|
|
38
|
+
# get key
|
|
39
|
+
if !haystack.has_key?(k)
|
|
40
|
+
if v
|
|
41
|
+
message += "Missing from actual: #{fullname_str} => #{v.inspect}\n"
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
# inspect key
|
|
45
|
+
# if we are looking for a collection
|
|
46
|
+
if v.kind_of?(Hash) || v.kind_of?(Array)
|
|
47
|
+
# and the haystack has a collection
|
|
48
|
+
if !(haystack.__index(k).kind_of?(String) || haystack.__index(k).kind_of?(TrueClass) || haystack.__index(k).kind_of?(FalseClass) || haystack.__index(k).kind_of?(Fixnum) || haystack.__index(k).kind_of?(Bignum))
|
|
49
|
+
# recurse if both are collections
|
|
50
|
+
message += v.compare_includes?(haystack.__index(k),fullname)
|
|
51
|
+
|
|
52
|
+
# otherwise, complain that we aren't the same
|
|
53
|
+
else
|
|
54
|
+
message += "Difference: required <#{fullname_str} => #{v.inspect}> was <#{fullname_str} => #{haystack.__index(k).inspect}>\n"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# if we aren't looking for a collection, see if we aren't the same
|
|
58
|
+
else
|
|
59
|
+
haystack_value = haystack.__index(k)
|
|
60
|
+
if (haystack_value.kind_of? Array and
|
|
61
|
+
haystack_value.length == 1)
|
|
62
|
+
haystack_value = haystack_value.first
|
|
63
|
+
end
|
|
64
|
+
if (haystack_value != v)
|
|
65
|
+
message += "Difference: required <#{fullname_str} => #{v.inspect}> was <#{fullname_str} => #{haystack_value.inspect}>\n"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
message
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
�Á�
|
|
73
|
+
class Hash # :nodoc:
|
|
74
|
+
def __index(key)
|
|
75
|
+
self[key]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def compare_includes? haystack, prefix=[]
|
|
79
|
+
message = ""
|
|
80
|
+
# check that haystack is the same type?
|
|
81
|
+
|
|
82
|
+
# iterate over your self (particular to self)
|
|
83
|
+
self.each do |k,v|
|
|
84
|
+
|
|
85
|
+
# make a sensible name for each element of the needle (particular to self)
|
|
86
|
+
fullname = prefix.clone.push k
|
|
87
|
+
fullname_str = fullname.join(".")
|
|
88
|
+
|
|
89
|
+
message += do_thing(haystack, k, v, fullname, fullname_str)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
message
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
module Test # :nodoc: all
|
|
97
|
+
module Unit
|
|
98
|
+
module Assertions
|
|
99
|
+
def assert_includes needle, haystack, message=""
|
|
100
|
+
_wrap_assertion {
|
|
101
|
+
message = needle.compare_includes?( haystack )
|
|
102
|
+
unless( message == "")
|
|
103
|
+
flunk(message.chomp)
|
|
104
|
+
end
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
data/lib/web/action.rb
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module Web
|
|
2
|
+
class Action #:nodoc:
|
|
3
|
+
attr_reader :patterns
|
|
4
|
+
def initialize patterns={}, &function
|
|
5
|
+
@patterns = patterns
|
|
6
|
+
@function = function || lambda{}
|
|
7
|
+
@@all_actions.push self
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def run cgi=Web::CGI.create
|
|
11
|
+
@function.call( cgi )
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def old_applies? cgi
|
|
15
|
+
matches = false
|
|
16
|
+
patterns.each{ |key, pattern|
|
|
17
|
+
cgi.multiple_params[key].each{ |value|
|
|
18
|
+
if pattern.kind_of? Regexp
|
|
19
|
+
matches = true if value =~ pattern
|
|
20
|
+
else
|
|
21
|
+
matches = true if value == pattern
|
|
22
|
+
end
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
matches
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def applies? cgi
|
|
29
|
+
relevance = 0;
|
|
30
|
+
unmatched_terms = patterns.size;
|
|
31
|
+
patterns.each{ |key, pattern|
|
|
32
|
+
if pattern.kind_of? Regexp
|
|
33
|
+
if cgi.multiple_params[key].find{ |value| value =~ pattern }
|
|
34
|
+
unmatched_terms = unmatched_terms - 1
|
|
35
|
+
relevance += 1
|
|
36
|
+
end
|
|
37
|
+
else
|
|
38
|
+
if cgi.multiple_params[key].find{ |value| value == pattern }
|
|
39
|
+
unmatched_terms = unmatched_terms - 1
|
|
40
|
+
relevance += 10
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
}
|
|
44
|
+
if unmatched_terms == 0
|
|
45
|
+
relevance
|
|
46
|
+
else
|
|
47
|
+
false
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
@@all_actions = []
|
|
52
|
+
def Action.pick( cgi )
|
|
53
|
+
@@all_actions.find_all{ |action|
|
|
54
|
+
action.applies? cgi
|
|
55
|
+
}.sort{|a, b|
|
|
56
|
+
a.applies?(cgi) <=> b.applies?(cgi)
|
|
57
|
+
}.last ||
|
|
58
|
+
@@all_actions.find{ |action| action.patterns == {} } ||
|
|
59
|
+
blank_action
|
|
60
|
+
|
|
61
|
+
# (raise Web::Exception.new( "Could not locate action for #{ cgi.multiple_params.inspect }" ))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def Action.blank_action
|
|
65
|
+
blank = Action.new
|
|
66
|
+
@@all_actions.delete blank
|
|
67
|
+
blank
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def Action.run options={}
|
|
71
|
+
if options.kind_of? Hash
|
|
72
|
+
Web.process(options){ |cgi|
|
|
73
|
+
pick(cgi).run(cgi)
|
|
74
|
+
}
|
|
75
|
+
elsif options.kind_of? Web::CGI
|
|
76
|
+
pick(options).run(options)
|
|
77
|
+
options.close
|
|
78
|
+
options
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
class Array # :nodoc:
|
|
2
|
+
def has_key?(index)
|
|
3
|
+
index >= 0 && index < length
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def __index(key)
|
|
7
|
+
self[key]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def compare_includes? haystack, prefix=[]
|
|
11
|
+
message = ""
|
|
12
|
+
each_with_index{ |v, k|
|
|
13
|
+
fullname = prefix.clone
|
|
14
|
+
if fullname.length > 0
|
|
15
|
+
fullname[fullname.length-1] = "#{fullname.last}[#{k}]"
|
|
16
|
+
else
|
|
17
|
+
fullname[0] = "<Array>[#{k}]"
|
|
18
|
+
end
|
|
19
|
+
fullname_str = fullname.join(".")
|
|
20
|
+
message += do_thing(haystack, k, v, fullname, fullname_str)
|
|
21
|
+
}
|
|
22
|
+
message
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Object # :nodoc:
|
|
28
|
+
def has_key? key
|
|
29
|
+
respond_to? key.intern
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def __index(key)
|
|
33
|
+
send key.intern
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def do_thing haystack, k, v, fullname, fullname_str
|
|
37
|
+
message = ""
|
|
38
|
+
# get key
|
|
39
|
+
if !haystack.has_key?(k)
|
|
40
|
+
if v
|
|
41
|
+
message += "Missing from actual: #{fullname_str} => #{v.inspect}\n"
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
# inspect key
|
|
45
|
+
# if we are looking for a collection
|
|
46
|
+
if v.kind_of?(Hash) || v.kind_of?(Array)
|
|
47
|
+
# and the haystack has a collection
|
|
48
|
+
if !(haystack.__index(k).kind_of?(String) || haystack.__index(k).kind_of?(TrueClass) || haystack.__index(k).kind_of?(FalseClass) || haystack.__index(k).kind_of?(Fixnum) || haystack.__index(k).kind_of?(Bignum))
|
|
49
|
+
# recurse if both are collections
|
|
50
|
+
message += v.compare_includes?(haystack.__index(k),fullname)
|
|
51
|
+
|
|
52
|
+
# otherwise, complain that we aren't the same
|
|
53
|
+
else
|
|
54
|
+
message += "Difference: required <#{fullname_str} => #{v.inspect}> was <#{fullname_str} => #{haystack.__index(k).inspect}>\n"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# if we aren't looking for a collection, see if we aren't the same
|
|
58
|
+
else
|
|
59
|
+
haystack_value = haystack.__index(k)
|
|
60
|
+
if (haystack_value.kind_of? Array and
|
|
61
|
+
haystack_value.length == 1)
|
|
62
|
+
haystack_value = haystack_value.first
|
|
63
|
+
end
|
|
64
|
+
if (haystack_value != v)
|
|
65
|
+
message += "Difference: required <#{fullname_str} => #{v.inspect}> was <#{fullname_str} => #{haystack_value.inspect}>\n"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
message
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class Hash # :nodoc:
|
|
74
|
+
def __index(key)
|
|
75
|
+
self[key]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def compare_includes? haystack, prefix=[]
|
|
79
|
+
message = ""
|
|
80
|
+
# check that haystack is the same type?
|
|
81
|
+
|
|
82
|
+
# iterate over your self (particular to self)
|
|
83
|
+
self.each do |k,v|
|
|
84
|
+
|
|
85
|
+
# make a sensible name for each element of the needle (particular to self)
|
|
86
|
+
fullname = prefix.clone.push k
|
|
87
|
+
fullname_str = fullname.join(".")
|
|
88
|
+
|
|
89
|
+
message += do_thing(haystack, k, v, fullname, fullname_str)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
message
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
module Test # :nodoc: all
|
|
97
|
+
module Unit
|
|
98
|
+
module Assertions
|
|
99
|
+
def assert_includes needle, haystack, message=""
|
|
100
|
+
_wrap_assertion {
|
|
101
|
+
message = needle.compare_includes?( haystack )
|
|
102
|
+
unless( message == "")
|
|
103
|
+
flunk(message.chomp)
|
|
104
|
+
end
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
class Array # :nodoc:
|
|
2
|
+
def has_key?(index)
|
|
3
|
+
index >= 0 && index < length
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def __index(key)
|
|
7
|
+
self[key]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def compare_includes? haystack, prefix=[]
|
|
11
|
+
message = ""
|
|
12
|
+
each_with_index{ |v, k|
|
|
13
|
+
fullname = prefix.clone
|
|
14
|
+
if fullname.length > 0
|
|
15
|
+
fullname[fullname.length-1] = "#{fullname.last}[#{k}]"
|
|
16
|
+
else
|
|
17
|
+
fullname[0] = "<Array>[#{k}]"
|
|
18
|
+
end
|
|
19
|
+
fullname_str = fullname.join(".")
|
|
20
|
+
message += do_thing(haystack, k, v, fullname, fullname_str)
|
|
21
|
+
}
|
|
22
|
+
message
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Object # :nodoc:
|
|
28
|
+
def has_key? key
|
|
29
|
+
respond_to? key.intern
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def __index(key)
|
|
33
|
+
send key.intern
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def do_thing haystack, k, v, fullname, fullname_str
|
|
37
|
+
message = ""
|
|
38
|
+
# get key
|
|
39
|
+
if !haystack.has_key?(k)
|
|
40
|
+
if v
|
|
41
|
+
message += "Missing from actual: #{fullname_str} => #{v.inspect}\n"
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
# inspect key
|
|
45
|
+
# if we are looking for a collection
|
|
46
|
+
if v.kind_of?(Hash) || v.kind_of?(Array)
|
|
47
|
+
# and the haystack has a collection
|
|
48
|
+
if !(haystack.__index(k).kind_of?(String) || haystack.__index(k).kind_of?(TrueClass) || haystack.__index(k).kind_of?(FalseClass) || haystack.__index(k).kind_of?(Fixnum) || haystack.__index(k).kind_of?(Bignum))
|
|
49
|
+
# recurse if both are collections
|
|
50
|
+
message += v.compare_includes?(haystack.__index(k),fullname)
|
|
51
|
+
|
|
52
|
+
# otherwise, complain that we aren't the same
|
|
53
|
+
else
|
|
54
|
+
message += "Difference: required <#{fullname_str} => #{v.inspect}> was <#{fullname_str} => #{haystack.__index(k).inspect}>\n"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# if we aren't looking for a collection, see if we aren't the same
|
|
58
|
+
else
|
|
59
|
+
haystack_value = haystack.__index(k)
|
|
60
|
+
if (haystack_value.kind_of? Array and
|
|
61
|
+
haystack_value.length == 1)
|
|
62
|
+
haystack_value = haystack_value.first
|
|
63
|
+
end
|
|
64
|
+
if (haystack_value != v)
|
|
65
|
+
message += "Difference: required <#{fullname_str} => #{v.inspect}> was <#{fullname_str} => #{haystack_value.inspect}>\n"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
message
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class Hash # :nodoc:
|
|
74
|
+
def __index(key)
|
|
75
|
+
self[key]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def compare_includes? haystack, prefix=[]
|
|
79
|
+
message = ""
|
|
80
|
+
# check that haystack is the same type?
|
|
81
|
+
|
|
82
|
+
# iterate over your self (particular to self)
|
|
83
|
+
self.each do |k,v|
|
|
84
|
+
|
|
85
|
+
# make a sensible name for each element of the needle (particular to self)
|
|
86
|
+
fullname = prefix.clone.push k
|
|
87
|
+
fullname_str = fullname.join(".")
|
|
88
|
+
|
|
89
|
+
message += do_thing(haystack, k, v, fullname, fullname_str)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
message
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
module Test # :nodoc: all
|
|
97
|
+
module Unit
|
|
98
|
+
module Assertions
|
|
99
|
+
def assert_includes needle, haystack, message=""
|
|
100
|
+
_wrap_assertion {
|
|
101
|
+
message = needle.compare_includes?( haystack )
|
|
102
|
+
unless( message == "")
|
|
103
|
+
flunk(message)
|
|
104
|
+
end
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
data/lib/web/buffer.rb
ADDED
data/lib/web/cgi.rb
ADDED
|
@@ -0,0 +1,641 @@
|
|
|
1
|
+
module Web
|
|
2
|
+
# == Purpose
|
|
3
|
+
#
|
|
4
|
+
# Web::CGI is the core of Narf. You will find documentation for many
|
|
5
|
+
# useful methods here. I recommend calling these methods through the
|
|
6
|
+
# Web module, which will manage the current CGI object and delegate
|
|
7
|
+
# to it.
|
|
8
|
+
#
|
|
9
|
+
class CGI
|
|
10
|
+
|
|
11
|
+
@@__web__cgi = nil
|
|
12
|
+
|
|
13
|
+
# set the singleton cgi object for Web
|
|
14
|
+
def CGI.set_cgi cgi
|
|
15
|
+
@@__web__cgi = cgi
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# get the singleton cgi object for Web
|
|
19
|
+
def CGI.get_cgi( options={} )
|
|
20
|
+
unless @@__web__cgi
|
|
21
|
+
@@__web__cgi = Web::CGI.new(options)
|
|
22
|
+
|
|
23
|
+
at_exit {
|
|
24
|
+
@@__web__cgi.close if @@__web__cgi
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
@@__web__cgi
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def CGI.process( options={} ) #:nodoc:
|
|
33
|
+
cgi = Web::CGI.get_cgi( options )
|
|
34
|
+
yield cgi
|
|
35
|
+
cgi.close
|
|
36
|
+
cgi
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
include Test::Unit::Assertions
|
|
40
|
+
|
|
41
|
+
attr_reader :session, :options
|
|
42
|
+
|
|
43
|
+
def document_root
|
|
44
|
+
@cgd.env['document_root']
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def script_name
|
|
48
|
+
@cgd.env['script_name']
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def path_info
|
|
52
|
+
@cgd.env['path_info']
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def cgd
|
|
56
|
+
@cgd
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
@@cgi_instances = {}
|
|
60
|
+
def CGI::create(options={})
|
|
61
|
+
|
|
62
|
+
options[:out] ||= $stdout
|
|
63
|
+
@@cgi_instances[ options[:out].id ] ||= CGI.new(options)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Construct cgi with the given options. Defaults are in parenthesis.
|
|
67
|
+
# These options are alpha and due for change as narf supports
|
|
68
|
+
# different backends.
|
|
69
|
+
#
|
|
70
|
+
# [:session] set the session to the given hash (Web::Session).
|
|
71
|
+
# [:cgd] pass in a CGD driver
|
|
72
|
+
# [:env] pass in the ENV variables
|
|
73
|
+
# [:in] set the input stream to the given IO ($stdin).
|
|
74
|
+
# [:out] set the output stream to the given IO ($stdout).
|
|
75
|
+
# [:unbuffered] flag whether output should(n't) be buffered. (false)
|
|
76
|
+
# [:path_info] path_info is the part of the query that is after the script,
|
|
77
|
+
# i.e. the Narf.html in /wiki.rb/Narf.html (Request.path_info)
|
|
78
|
+
# [:document_root] Document root of website. (Request.document_root)
|
|
79
|
+
# [:script_name] Script name, ie /wiki.rb in /wiki.rb/Narf.html (Request.script_name)
|
|
80
|
+
def initialize(options={})
|
|
81
|
+
@options = options
|
|
82
|
+
@cgd = options[:cgd] || CGD.create( options )
|
|
83
|
+
|
|
84
|
+
ENV_KEYS.each { |symbol|
|
|
85
|
+
env[symbol.to_s.downcase] = options[symbol] if options[symbol]
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# set output buffer
|
|
89
|
+
@content = StringIO.new
|
|
90
|
+
if (unbuffered?)
|
|
91
|
+
@output = @cgd.output
|
|
92
|
+
else
|
|
93
|
+
@output = StringIO.new
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
@session = if (options.has_key? :session)
|
|
97
|
+
options[:session]
|
|
98
|
+
else
|
|
99
|
+
Session.new( self, options )
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def trace_output
|
|
104
|
+
templater = Narflates.new(CGI.trace_output_template,{})
|
|
105
|
+
templater.parse(self,{ "parameters" =>
|
|
106
|
+
multiple_params.collect { |key,value| { "key" => key, "value" => value } },
|
|
107
|
+
"cookies" =>
|
|
108
|
+
cookies.collect { |key,value| { "key" => key, "value" => value } },
|
|
109
|
+
"session" =>
|
|
110
|
+
session.collect { |key,value| { "key" => key, "value" => value } } })
|
|
111
|
+
flush
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# returns params as a hash of arrays
|
|
116
|
+
def multiple_params
|
|
117
|
+
@cgd.multiple_params
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# set multiple params, in case you want to change the state of your app
|
|
121
|
+
# without a round trip to the client.
|
|
122
|
+
def multiple_params= other
|
|
123
|
+
@cgd.multiple_params = other
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
MULTIPLE_KEY = /\[\]\z/
|
|
127
|
+
|
|
128
|
+
# access parameters. If the key is array-style,
|
|
129
|
+
# aka param[], return the array. Otherwise,
|
|
130
|
+
# return the joined string.
|
|
131
|
+
def [] (key)
|
|
132
|
+
if (MULTIPLE_KEY =~ key)
|
|
133
|
+
multiple_params[key]
|
|
134
|
+
else
|
|
135
|
+
single_param(key)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# set param at the given key. This is useful to change state
|
|
140
|
+
# in your app without asking the browser to redirect
|
|
141
|
+
def []= (key, value)
|
|
142
|
+
unless value.kind_of? Array
|
|
143
|
+
value = [value]
|
|
144
|
+
end
|
|
145
|
+
multiple_params[key] = value
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# If params[key][0] is a Web::Upload, returns that value.
|
|
149
|
+
# Otherwise it returns params[key].join( "," )
|
|
150
|
+
def single_param(key)
|
|
151
|
+
if (multiple_params[key].first.kind_of? Web::Upload)
|
|
152
|
+
multiple_params[key].first
|
|
153
|
+
else
|
|
154
|
+
multiple_params[key].join( "," )
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def split_params #:nodoc:
|
|
159
|
+
Web::Testing::MultiHashTree.new(multiple_params).fields
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# list the submitted params
|
|
163
|
+
def keys
|
|
164
|
+
multiple_params.keys
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# test whether a param was submitted
|
|
168
|
+
def key? (key)
|
|
169
|
+
multiple_params.has_key? key
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# array of cookies sent by the client
|
|
173
|
+
def cookies
|
|
174
|
+
@cgd.cookies
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
#----------------------------------
|
|
178
|
+
# Response methods
|
|
179
|
+
#----------------------------------
|
|
180
|
+
|
|
181
|
+
# these are documentation stubs for rdoc
|
|
182
|
+
|
|
183
|
+
# Append output to client
|
|
184
|
+
def << (*args) end
|
|
185
|
+
# Append output to client with line endings
|
|
186
|
+
def puts(*args) end
|
|
187
|
+
# Append output to client
|
|
188
|
+
def write(*args) end
|
|
189
|
+
# Append output to client
|
|
190
|
+
def print(*args) end
|
|
191
|
+
|
|
192
|
+
# Append output to client
|
|
193
|
+
[ :<<, :puts, :write, :print ].each{ |symbol|
|
|
194
|
+
define_method(symbol) { |*args|
|
|
195
|
+
send_header if (unbuffered?)
|
|
196
|
+
@content.send( symbol, args )
|
|
197
|
+
@output.send( symbol, args )
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
# Reset output buffer. Fails if headers have been sent.
|
|
202
|
+
def clear()
|
|
203
|
+
if header_sent?
|
|
204
|
+
raise( Exception.new( "Can't call Web::clear()" ) )
|
|
205
|
+
else
|
|
206
|
+
@output = StringIO.new
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def unbuffered?
|
|
211
|
+
@options[:unbuffered]
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# send header to the client, and flush any buffered output
|
|
215
|
+
def flush
|
|
216
|
+
unless unbuffered?
|
|
217
|
+
send_header
|
|
218
|
+
@cgd.output << @output.string
|
|
219
|
+
@output = StringIO.new
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# returns the body content of the response
|
|
224
|
+
# (sans headers).
|
|
225
|
+
def get_content
|
|
226
|
+
@content.string
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# for testing: raises Test::Unit exception if content
|
|
230
|
+
# is not set to the provided string.
|
|
231
|
+
def assert_content expected, message=""
|
|
232
|
+
assert_equal( expected, get_content, message );
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def get_formreader #:nodoc:
|
|
236
|
+
return @form_fields_cache ||= FormReader.new( get_content )
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def get_form( name ) #:nodoc:
|
|
240
|
+
get_formreader[name]
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def get_form_fields(name) #:nodoc:
|
|
244
|
+
get_formreader.get_fields(name)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def get_form_value formname, name #:nodoc:
|
|
248
|
+
form = get_form_fields(formname)
|
|
249
|
+
if form == nil
|
|
250
|
+
raise Web::Error.new("Form '#{formname}' does not exist")
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
value = form[name]
|
|
254
|
+
value
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# assert output content contains a form
|
|
258
|
+
# that includes the given hash of values. See Web::Testing
|
|
259
|
+
def assert_form_includes formname, vars
|
|
260
|
+
assert_includes vars, get_form_fields(formname)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# flushes the output and, if applicable, saves the session
|
|
264
|
+
def close
|
|
265
|
+
flush
|
|
266
|
+
if $DISPLAY_TRACE
|
|
267
|
+
trace_output
|
|
268
|
+
end
|
|
269
|
+
@session.save if (@session.respond_to? :save)
|
|
270
|
+
@cgd.close
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
# There's a bit of special casing in here, for the follow reasons:
|
|
274
|
+
# * some headers should only be sent once. If you add
|
|
275
|
+
# Content-Encoding, Location, or Status, it will overwrite the old headers
|
|
276
|
+
# instead of adding a second header
|
|
277
|
+
# * content-type is a strange header. It is a combination of the content-type
|
|
278
|
+
# and charset attributes. setting content-type will cause the content-type
|
|
279
|
+
# attribute to be set; setting charset will cause the charset attribute to
|
|
280
|
+
# be set.
|
|
281
|
+
#
|
|
282
|
+
# I don't know if this is the correct behavior. Should this method assume that
|
|
283
|
+
# the content-type set here is the full content type, and try to split the
|
|
284
|
+
# header into it's two parts?
|
|
285
|
+
#
|
|
286
|
+
# * If the headers have been sent, this will throw a Web::Error
|
|
287
|
+
def add_header(name , value )
|
|
288
|
+
unless header_sent?
|
|
289
|
+
if (/content-encoding/i =~ name )
|
|
290
|
+
header['Content-Encoding'] = [value]
|
|
291
|
+
elsif( /location/i =~ name )
|
|
292
|
+
header['Location'] = [value]
|
|
293
|
+
elsif( /status/i =~ name )
|
|
294
|
+
if /^\d*$/ =~ value.to_s
|
|
295
|
+
self.status = value
|
|
296
|
+
else
|
|
297
|
+
header['Status'] = [value]
|
|
298
|
+
end
|
|
299
|
+
elsif(/content-type/i =~ name)
|
|
300
|
+
header['Content-Type'] = [value]
|
|
301
|
+
elsif(/charset/i =~ name)
|
|
302
|
+
self.charset = value
|
|
303
|
+
else
|
|
304
|
+
header[name] ||= []
|
|
305
|
+
header[name].push value
|
|
306
|
+
end
|
|
307
|
+
else
|
|
308
|
+
raise Web::Error.new( "Can't add_header after header have been sent to client" )
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
# returns an array of header values set with the given name.
|
|
313
|
+
def get_header name
|
|
314
|
+
header.keys.find_all { |key|
|
|
315
|
+
key.downcase == name.downcase
|
|
316
|
+
}.collect{ |key|
|
|
317
|
+
header[key].dup
|
|
318
|
+
}.flatten
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
# Send header to the client. No more header values can be sent after this method is called!
|
|
323
|
+
def send_header
|
|
324
|
+
unless header_sent?
|
|
325
|
+
@cgd.send_header( self.header )
|
|
326
|
+
@header_sent = true
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def header_sent?
|
|
331
|
+
@header_sent
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def header
|
|
335
|
+
@header ||= {"Content-Type" => ["text/html"],
|
|
336
|
+
"Status" => ["200 OK"] }
|
|
337
|
+
@header
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# Raises Test::Unit::AssertionFailedError if the header
|
|
341
|
+
# has not been set to the provided value(s)
|
|
342
|
+
def assert_header( name, values, message="" )
|
|
343
|
+
assert_equal( [values].flatten, get_header(name), message )
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
# the default status is 200
|
|
347
|
+
def status
|
|
348
|
+
get_header( "Status" ).first =~ /^(\d+)( .*)?$/
|
|
349
|
+
$1
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def status= new_status
|
|
353
|
+
add_header( "Status", "#{ new_status } #{ Web::HTTP_STATUS[new_status.to_s] }" )
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def location
|
|
357
|
+
get_header( "Location" ).first
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# see set redirect
|
|
361
|
+
def location= location
|
|
362
|
+
add_header( "Location", location )
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
# Sets the status and the location appropriately.
|
|
366
|
+
def set_redirect( new_location )
|
|
367
|
+
self.status = "302"
|
|
368
|
+
self.location = new_location
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def encoding
|
|
372
|
+
get_header( "Content-Encoding" ).first
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def encoding=( new_encoding )
|
|
376
|
+
add_header( "Content-Encoding", new_encoding )
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def split_content_type( target = full_content_type )
|
|
380
|
+
target.split( Regexp.new('; charset=') )
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
# The content type header is a combination of the content_type and the charset.
|
|
384
|
+
# This method returns that combination.
|
|
385
|
+
def full_content_type
|
|
386
|
+
get_header( "Content-Type" ).first
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
def set_full_content_type( new_content, new_charset )
|
|
390
|
+
add_header( "Content-type", [ new_content, new_charset ].compact.join('; charset=') )
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
# the default content-type is "text/html"
|
|
394
|
+
def content_type
|
|
395
|
+
split_content_type[0]
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
def content_type= new_content_type
|
|
399
|
+
content1, charset1 = split_content_type
|
|
400
|
+
content2, charset2 = split_content_type( new_content_type )
|
|
401
|
+
|
|
402
|
+
set_full_content_type( content2 || content1,
|
|
403
|
+
charset2 || charset1 )
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def charset
|
|
407
|
+
split_content_type[1]
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
def charset= new_charset
|
|
411
|
+
set_full_content_type( content_type, new_charset )
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# Cookies require a name and a value. You can also use these
|
|
415
|
+
# optional keyword arguments:
|
|
416
|
+
# <b>:path</b> => <i>string<i>:: path (need better description)
|
|
417
|
+
# <b>:domain</b> => <i>string</i>:: domain (need better description)
|
|
418
|
+
# <b>:expires</b> => <i>date</i>:: date this cookie should expire
|
|
419
|
+
# <b>:secure</b> => <i>true || false </i>:: whether this cookie should be
|
|
420
|
+
# tagged as secure.
|
|
421
|
+
def set_cookie( name, value, options={} )
|
|
422
|
+
value = Array(value).collect{ |field|
|
|
423
|
+
Web::escape(field)
|
|
424
|
+
}.join("&")
|
|
425
|
+
|
|
426
|
+
cookie = "#{ name }=#{ value }"
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
path = if (options[:path])
|
|
430
|
+
options[:path]
|
|
431
|
+
else
|
|
432
|
+
%r|^(.*/)|.match(env["script_name"])
|
|
433
|
+
($1 or "")
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
cookie += "; path=#{ path }"
|
|
437
|
+
|
|
438
|
+
if (options[:domain])
|
|
439
|
+
cookie += "; domain=#{ options[:domain] }"
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
if (options[:expires])
|
|
443
|
+
cookie += "; expires=#{ Web::rfc1123_date( options[:expires] ) }"
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
if (options[:secure])
|
|
447
|
+
cookie += "; secure"
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
add_header( "Set-Cookie", cookie )
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
# returns an array of cookie values that have been set.
|
|
454
|
+
# path / expires / etc. info is currently not returned, should
|
|
455
|
+
# be added in?
|
|
456
|
+
def get_cookie key
|
|
457
|
+
get_header("Set-Cookie").collect{ |cookie|
|
|
458
|
+
/\A(#{ key })=([^;]*)/ =~ cookie
|
|
459
|
+
$2
|
|
460
|
+
}.compact
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
# returns a hash of all the cookie n/v pairs that have
|
|
464
|
+
# been set on the cgi
|
|
465
|
+
def cookies_sent
|
|
466
|
+
cookies = {}
|
|
467
|
+
get_header("Set-Cookie").each do |cookie|
|
|
468
|
+
/\A(.*?)=([^;]*)/ =~ cookie
|
|
469
|
+
cookies[$1] = $2
|
|
470
|
+
end
|
|
471
|
+
cookies
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
# Throws Test::Unit::AssertionFailedException if
|
|
475
|
+
# cookie values are not present.
|
|
476
|
+
def assert_cookie( name, values, message="" )
|
|
477
|
+
assert_equal( [values].flatten, get_cookie(name), message )
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
# Aside from when :nph is set in the options, scripts running in IIS always
|
|
481
|
+
# use nph mode. This code will probably be affected as cgi is re-organized
|
|
482
|
+
# to support multiple backends.
|
|
483
|
+
def nph?
|
|
484
|
+
@cgd.nph?
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
# ENV variables, scoped to the cgi (for in-process servers)
|
|
488
|
+
def env
|
|
489
|
+
@cgd.env
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
ENV_KEYS = [ :path_info, :document_root, :script_name ]
|
|
493
|
+
|
|
494
|
+
ENV_KEYS.each{ |symbol|
|
|
495
|
+
define_method( symbol ) {
|
|
496
|
+
env[symbol.to_s]
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
#------------------------------
|
|
501
|
+
# implementation details, aka
|
|
502
|
+
# refactoring targets below
|
|
503
|
+
#------------------------------
|
|
504
|
+
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
# == Purpose
|
|
508
|
+
# this is the implementation of the cgi interface.
|
|
509
|
+
# As dbi to dbd, cgi to cgd
|
|
510
|
+
class CGD
|
|
511
|
+
|
|
512
|
+
attr_accessor :options, :env, :input, :output, :cookies, :multiple_params
|
|
513
|
+
|
|
514
|
+
include Parser
|
|
515
|
+
|
|
516
|
+
def CGD::create(options={})
|
|
517
|
+
case CGI::server_sniff
|
|
518
|
+
when :fcgi
|
|
519
|
+
require 'web/sapi/fastcgi'
|
|
520
|
+
Web::CGD::Fastcgi.new( options )
|
|
521
|
+
when :mod_ruby
|
|
522
|
+
require 'web/sapi/mod_ruby'
|
|
523
|
+
Web::CGD::ModRuby.new( options )
|
|
524
|
+
else
|
|
525
|
+
CGD.new(options)
|
|
526
|
+
end
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def initialize(options={})
|
|
530
|
+
@options = options
|
|
531
|
+
|
|
532
|
+
@input = options[:in] || $stdin
|
|
533
|
+
@output = options[:out] || $stdout
|
|
534
|
+
@env = downcase_env( options[:env] || ENV )
|
|
535
|
+
|
|
536
|
+
@env['document_root'] = options[:document_root] || Web.get_docroot || @env['document_root']
|
|
537
|
+
@env['script_name' ] = options[:script_name] || @env['script_name']
|
|
538
|
+
|
|
539
|
+
parse_request
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
def close
|
|
543
|
+
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
# should this be server specific?
|
|
547
|
+
def nph?
|
|
548
|
+
@options[:nph] || /IIS/.match(env["server_software"])
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
def send_header( header )
|
|
552
|
+
send_nph_header( header ) if (nph?)
|
|
553
|
+
|
|
554
|
+
header.sort.each { |name, value|
|
|
555
|
+
value.each { |v|
|
|
556
|
+
output << "#{ name }: #{ v }\r\n"
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
output << "\r\n"
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
def send_nph_header( header ) #:nodoc:
|
|
564
|
+
output << "#{ env['server_protocol'] || 'HTTP/1.0' }: "
|
|
565
|
+
output << "#{ header['Status'] }\r\n"
|
|
566
|
+
output << "Date: #{ Web::rfc1123_date(Time.now) }\r\n"
|
|
567
|
+
|
|
568
|
+
header.delete("Status")
|
|
569
|
+
|
|
570
|
+
unless header.has_key? "Server"
|
|
571
|
+
header["Server"] = [ env["server_software"] || "" ]
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
class CGI
|
|
578
|
+
def report_error( err )
|
|
579
|
+
self.puts "<h3>ruby error:</h3>"
|
|
580
|
+
self.puts Dir.pwd
|
|
581
|
+
self.puts err.to_s.gsub(/\n/,"<br><br>")
|
|
582
|
+
self.puts "<blockquote>"
|
|
583
|
+
self.puts( if (err.backtrace.size > 3)
|
|
584
|
+
err.backtrace[0...-2]
|
|
585
|
+
else
|
|
586
|
+
err.backtrace
|
|
587
|
+
end).collect{ |string| string + "<br>" }
|
|
588
|
+
self.puts "</blockquote>"
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
# returns one of these values:
|
|
592
|
+
# :cgi, :fastcgi, :mod_ruby, :webrick
|
|
593
|
+
def CGI::server_sniff
|
|
594
|
+
if( Object.const_defined?( "Apache" ) \
|
|
595
|
+
&& Apache.const_defined?( "Request" ) \
|
|
596
|
+
&& $stdin.kind_of?( Apache::Request ) )
|
|
597
|
+
:mod_ruby
|
|
598
|
+
elsif ( Object.const_defined?( "FCGI" ) \
|
|
599
|
+
&& ! FCGI.is_cgi? )
|
|
600
|
+
:fcgi
|
|
601
|
+
else
|
|
602
|
+
:cgi
|
|
603
|
+
end
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
@@in_process = false
|
|
607
|
+
def CGI::basic_process( options={}) #:nodoc:
|
|
608
|
+
unless @@in_process
|
|
609
|
+
@@in_process = true
|
|
610
|
+
Web.set_cgi( CGI.new( options ) )
|
|
611
|
+
yield Web.get_cgi
|
|
612
|
+
Web.get_cgi.close
|
|
613
|
+
@@in_process = false
|
|
614
|
+
Web.get_cgi
|
|
615
|
+
else
|
|
616
|
+
yield Web.get_cgi
|
|
617
|
+
Web.get_cgi
|
|
618
|
+
end
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
# try to include fastcgi
|
|
623
|
+
begin
|
|
624
|
+
require 'fcgi'
|
|
625
|
+
rescue LoadError
|
|
626
|
+
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
def CGI::process( options={}, &block )
|
|
630
|
+
if CGI::server_sniff == :fcgi
|
|
631
|
+
FCGI::each_request{ |fcgi|
|
|
632
|
+
options[:fcgi] = fcgi
|
|
633
|
+
CGI::basic_process( options, &block )
|
|
634
|
+
}
|
|
635
|
+
else
|
|
636
|
+
CGI::basic_process(options, &block )
|
|
637
|
+
end
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
end
|
|
641
|
+
end
|