IOWA 1.0.0
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.
- checksums.yaml +7 -0
- data/CONTRIBUTORS +14 -0
- data/README.md +23 -0
- data/RELEASE_NOTES +77 -0
- data/ToDo +21 -0
- data/components/CRUDList/CRUDList.html +13 -0
- data/components/CRUDList/CRUDList.iwa +136 -0
- data/components/Content/Content.html +0 -0
- data/components/Content/Content.iwa +143 -0
- data/components/Content/example/README +9 -0
- data/components/Content/example/cgi/iowa.cgi +10 -0
- data/components/Content/example/demo.rb +30 -0
- data/components/Content/example/doc/index.html +7 -0
- data/components/Content/example/iowa/Content.html +1 -0
- data/components/Content/example/iowa/Content.iwa +1 -0
- data/components/Content/example/iowa/Main.html +6 -0
- data/components/Content/example/iowa/Main.iwa +3 -0
- data/components/Content/example/iowa/_content/body +7 -0
- data/components/Content/example/iowa/_content/body2 +3 -0
- data/components/Content/example/iowa/_content/title +2 -0
- data/components/Content/example/iowa/app.cnf +8 -0
- data/components/Content/example/iowa/app.rb +8 -0
- data/components/Content/example/webrick.rb +38 -0
- data/components/Include/Include.html +1 -0
- data/components/Include/Include.iwa +30 -0
- data/components/Include/readme +5 -0
- data/components/JumpTo/JumpTo.html +8 -0
- data/components/JumpTo/JumpTo.iwa +8 -0
- data/components/JumpTo/readme +6 -0
- data/doc/Architecture.txt +6 -0
- data/doc/History.txt +33 -0
- data/doc/StandardDispatcher.txt +19 -0
- data/examples/blog/README +1 -0
- data/examples/hello_world/README +17 -0
- data/examples/hello_world/htdocs/hello_world_html.html +24 -0
- data/examples/hello_world/htdocs/hello_world_ruby.html +41 -0
- data/examples/hello_world/iowa/HelloWorld.html +14 -0
- data/examples/hello_world/iowa/HelloWorld.iwa +31 -0
- data/examples/hello_world/iowa/Index.html +16 -0
- data/examples/hello_world/iowa/Index.iwa +5 -0
- data/examples/hello_world/iowa/iowa_hello_world.cnf +19 -0
- data/examples/hello_world/iowa/iowa_hello_world.rb +5 -0
- data/examples/hello_world/iowa/mapfile.cnf +6 -0
- data/examples/hw1/iowa/Main.html +1 -0
- data/examples/hw1/iowa/README +9 -0
- data/examples/hw1/iowa/hw.rb +4 -0
- data/examples/hw2/iowa/Main.html +10 -0
- data/examples/hw2/iowa/Main.iwa +7 -0
- data/examples/hw2/iowa/README +16 -0
- data/examples/hw2/iowa/hw.rb +4 -0
- data/examples/hw3/iowa/Main.html +11 -0
- data/examples/hw3/iowa/Main.iwa +7 -0
- data/examples/hw3/iowa/README +22 -0
- data/examples/hw3/iowa/hw.rb +4 -0
- data/examples/hw4/iowa/Greetings.html +10 -0
- data/examples/hw4/iowa/Greetings.iwa +9 -0
- data/examples/hw4/iowa/Main.html +12 -0
- data/examples/hw4/iowa/Main.iwa +10 -0
- data/examples/hw4/iowa/README +28 -0
- data/examples/hw4/iowa/hw.rb +4 -0
- data/examples/hw5/iowa/Footer.html +2 -0
- data/examples/hw5/iowa/Greetings.html +4 -0
- data/examples/hw5/iowa/Greetings.iwa +12 -0
- data/examples/hw5/iowa/Header.html +6 -0
- data/examples/hw5/iowa/Main.html +12 -0
- data/examples/hw5/iowa/Main.iwa +13 -0
- data/examples/hw5/iowa/README +16 -0
- data/examples/hw5/iowa/hw.rb +4 -0
- data/examples/template_server/iowa/Content.iwa +121 -0
- data/examples/template_server/iowa/Content.view +0 -0
- data/examples/template_server/iowa/DBContentDispatcher.rb +112 -0
- data/examples/template_server/iowa/DBContentPage.html +3 -0
- data/examples/template_server/iowa/DBContentPage.iwa +85 -0
- data/examples/template_server/iowa/app.cnf +13 -0
- data/examples/template_server/iowa/app.rb +5 -0
- data/ext/Classifier/classifier.c +256 -0
- data/ext/Classifier/ext_help.h +14 -0
- data/ext/Classifier/extconf.rb +5 -0
- data/ext/Classifier/tst.h +40 -0
- data/ext/Classifier/tst_cleanup.c +24 -0
- data/ext/Classifier/tst_delete.c +146 -0
- data/ext/Classifier/tst_grow_node_free_list.c +38 -0
- data/ext/Classifier/tst_init.c +41 -0
- data/ext/Classifier/tst_insert.c +192 -0
- data/ext/Classifier/tst_search.c +68 -0
- data/ext/http11/README +11 -0
- data/ext/http11/ext_help.h +15 -0
- data/ext/http11/extconf.rb +5 -0
- data/ext/http11/http11.c +534 -0
- data/ext/http11/http11.c.dif +422 -0
- data/ext/http11/http11_parser.c +1243 -0
- data/ext/http11/http11_parser.c.dif +193 -0
- data/ext/http11/http11_parser.h +49 -0
- data/ext/http11/http11_parser.h.dif +20 -0
- data/ext/http11/http11_parser.rl +192 -0
- data/ext/httpmachine/Makefile +149 -0
- data/ext/httpmachine/extconf.rb +33 -0
- data/ext/httpmachine/http.cpp +430 -0
- data/ext/httpmachine/http.h +156 -0
- data/ext/httpmachine/rubyhttp.cpp +165 -0
- data/external/mime-types/LICENCE +18 -0
- data/external/mime-types/README +46 -0
- data/external/mime-types/doc/classes/MIME.html +120 -0
- data/external/mime-types/doc/classes/MIME/InvalidContentType.html +119 -0
- data/external/mime-types/doc/classes/MIME/Type.html +866 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000010.html +22 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000011.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000012.html +19 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000013.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000014.html +26 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000015.html +33 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000016.html +27 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000017.html +35 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000018.html +34 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000019.html +24 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000020.html +38 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000021.html +22 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000022.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000023.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000024.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000025.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000026.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000027.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000028.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000029.html +18 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000030.html +19 -0
- data/external/mime-types/doc/classes/MIME/Type.src/M000031.html +26 -0
- data/external/mime-types/doc/classes/MIME/Types.html +459 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000001.html +19 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000002.html +32 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000003.html +21 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000004.html +18 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000005.html +26 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000006.html +18 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000007.html +18 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000008.html +18 -0
- data/external/mime-types/doc/classes/MIME/Types.src/M000009.html +18 -0
- data/external/mime-types/doc/created.rid +1 -0
- data/external/mime-types/doc/files/ChangeLog.html +320 -0
- data/external/mime-types/doc/files/README.html +145 -0
- data/external/mime-types/doc/files/lib/mime/types_rb.html +101 -0
- data/external/mime-types/doc/fr_class_index.html +30 -0
- data/external/mime-types/doc/fr_file_index.html +29 -0
- data/external/mime-types/doc/fr_method_index.html +57 -0
- data/external/mime-types/doc/index.html +24 -0
- data/external/mime-types/doc/rdoc-style.css +208 -0
- data/external/mime-types/lib/mime/types.rb +1558 -0
- data/external/package.rb +672 -0
- data/external/test_support.rb +95 -0
- data/external/tmail/README +7 -0
- data/external/tmail/tmail.rb +4 -0
- data/external/tmail/tmail/address.rb +222 -0
- data/external/tmail/tmail/base64.rb +52 -0
- data/external/tmail/tmail/compat.rb +39 -0
- data/external/tmail/tmail/config.rb +50 -0
- data/external/tmail/tmail/encode.rb +447 -0
- data/external/tmail/tmail/header.rb +895 -0
- data/external/tmail/tmail/info.rb +14 -0
- data/external/tmail/tmail/loader.rb +1 -0
- data/external/tmail/tmail/mail.rb +869 -0
- data/external/tmail/tmail/mailbox.rb +386 -0
- data/external/tmail/tmail/mbox.rb +1 -0
- data/external/tmail/tmail/net.rb +260 -0
- data/external/tmail/tmail/obsolete.rb +123 -0
- data/external/tmail/tmail/parser.rb +1475 -0
- data/external/tmail/tmail/parser.y +372 -0
- data/external/tmail/tmail/port.rb +356 -0
- data/external/tmail/tmail/scanner.rb +17 -0
- data/external/tmail/tmail/scanner_r.rb +243 -0
- data/external/tmail/tmail/stringio.rb +256 -0
- data/external/tmail/tmail/textutils.rb +197 -0
- data/external/tmail/tmail/tmail.rb +1 -0
- data/external/tmail/tmail/utils.rb +23 -0
- data/external/win32-process/README +133 -0
- data/external/win32-process/lib/win32/process.rb +561 -0
- data/external/windows-pr/README +145 -0
- data/external/windows-pr/doc/conversion_guide.txt +25 -0
- data/external/windows-pr/lib/windows/clipboard.rb +72 -0
- data/external/windows-pr/lib/windows/console.rb +323 -0
- data/external/windows-pr/lib/windows/device_io.rb +88 -0
- data/external/windows-pr/lib/windows/directory.rb +80 -0
- data/external/windows-pr/lib/windows/error.rb +313 -0
- data/external/windows-pr/lib/windows/eventlog.rb +120 -0
- data/external/windows-pr/lib/windows/file.rb +349 -0
- data/external/windows-pr/lib/windows/filesystem.rb +16 -0
- data/external/windows-pr/lib/windows/handle.rb +31 -0
- data/external/windows-pr/lib/windows/library.rb +76 -0
- data/external/windows-pr/lib/windows/limits.rb +13 -0
- data/external/windows-pr/lib/windows/memory.rb +117 -0
- data/external/windows-pr/lib/windows/msvcrt/buffer.rb +48 -0
- data/external/windows-pr/lib/windows/msvcrt/file.rb +18 -0
- data/external/windows-pr/lib/windows/msvcrt/string.rb +46 -0
- data/external/windows-pr/lib/windows/national.rb +557 -0
- data/external/windows-pr/lib/windows/path.rb +296 -0
- data/external/windows-pr/lib/windows/pipe.rb +77 -0
- data/external/windows-pr/lib/windows/process.rb +171 -0
- data/external/windows-pr/lib/windows/registry.rb +238 -0
- data/external/windows-pr/lib/windows/security.rb +89 -0
- data/external/windows-pr/lib/windows/service.rb +183 -0
- data/external/windows-pr/lib/windows/shell.rb +88 -0
- data/external/windows-pr/lib/windows/sound.rb +52 -0
- data/external/windows-pr/lib/windows/synchronize.rb +161 -0
- data/external/windows-pr/lib/windows/system_info.rb +70 -0
- data/external/windows-pr/lib/windows/unicode.rb +138 -0
- data/external/windows-pr/lib/windows/window.rb +22 -0
- data/iowa.gemspec +45 -0
- data/microprojects/DiskCache/LICENSE +28 -0
- data/microprojects/DiskCache/README +17 -0
- data/microprojects/DiskCache/external/package.rb +608 -0
- data/microprojects/DiskCache/external/test_support.rb +8 -0
- data/microprojects/DiskCache/setup.rb +22 -0
- data/microprojects/DiskCache/src/iowa/Association.rb +67 -0
- data/microprojects/DiskCache/src/iowa/Constants.rb +159 -0
- data/microprojects/DiskCache/src/iowa/DiskStore.rb +377 -0
- data/microprojects/DiskCache/src/iowa/Hash.rb +63 -0
- data/microprojects/DiskCache/src/iowa/Lockfile.rb +575 -0
- data/microprojects/DiskCache/src/iowa/Mutex.rb +142 -0
- data/microprojects/DiskCache/src/iowa/caches/DiskCache.rb +605 -0
- data/microprojects/DiskCache/src/iowa/caches/LRUCache.rb +287 -0
- data/microprojects/DiskCache/test/TC_DiskCache.rb +218 -0
- data/microprojects/LRUCache/LICENSE +28 -0
- data/microprojects/LRUCache/README +13 -0
- data/microprojects/LRUCache/external/package.rb +608 -0
- data/microprojects/LRUCache/external/test_support.rb +8 -0
- data/microprojects/LRUCache/setup.rb +22 -0
- data/microprojects/LRUCache/src/iowa/Association.rb +57 -0
- data/microprojects/LRUCache/src/iowa/Constants.rb +159 -0
- data/microprojects/LRUCache/src/iowa/Hash.rb +63 -0
- data/microprojects/LRUCache/src/iowa/Mutex.rb +129 -0
- data/microprojects/LRUCache/src/iowa/caches/LRUCache.rb +287 -0
- data/microprojects/LRUCache/test/TC_LRUCache.rb +65 -0
- data/microprojects/LinkedList/LICENSE +28 -0
- data/microprojects/LinkedList/README +13 -0
- data/microprojects/LinkedList/external/package.rb +608 -0
- data/microprojects/LinkedList/external/test_support.rb +8 -0
- data/microprojects/LinkedList/setup.rb +22 -0
- data/microprojects/LinkedList/src/iowa/LinkedList.rb +165 -0
- data/microprojects/LinkedList/test/TC_LinkedList.rb +42 -0
- data/microprojects/README +8 -0
- data/setup.rb +116 -0
- data/share/iowa/app_skeleton/Main.html +8 -0
- data/share/iowa/app_skeleton/Main.iwa +15 -0
- data/share/iowa/app_skeleton/app.cnf +48 -0
- data/share/iowa/app_skeleton/app.rb +58 -0
- data/share/iowa/app_skeleton/models/model.rb +49 -0
- data/src/ihc.rb +223 -0
- data/src/iowa.cgi +29 -0
- data/src/iowa.rb +637 -0
- data/src/iowa/AbstractCache.rb +96 -0
- data/src/iowa/AcceptLanguage.rb +76 -0
- data/src/iowa/Application.rb +928 -0
- data/src/iowa/ApplicationStats.rb +72 -0
- data/src/iowa/Association.rb +67 -0
- data/src/iowa/BindingsParser.rb +62 -0
- data/src/iowa/Breakpoint.rb +273 -0
- data/src/iowa/CSS.rb +564 -0
- data/src/iowa/Client.rb +192 -0
- data/src/iowa/Component.rb +405 -0
- data/src/iowa/ComponentProxy.rb +26 -0
- data/src/iowa/Config.rb +21 -0
- data/src/iowa/Constants.rb +226 -0
- data/src/iowa/Context.rb +218 -0
- data/src/iowa/ContextLogger.rb +16 -0
- data/src/iowa/DbPool.rb +222 -0
- data/src/iowa/DetachedComponent.rb +18 -0
- data/src/iowa/Dispatcher.rb +27 -0
- data/src/iowa/DynamicElements.rb +471 -0
- data/src/iowa/Element.rb +100 -0
- data/src/iowa/Email.rb +287 -0
- data/src/iowa/Extensions/AllExtensions.rb +4 -0
- data/src/iowa/Extensions/Class.rb +94 -0
- data/src/iowa/Extensions/Date.rb +88 -0
- data/src/iowa/Extensions/DateTime.rb +88 -0
- data/src/iowa/Extensions/Hash.rb +22 -0
- data/src/iowa/Extensions/Kernel.rb +6 -0
- data/src/iowa/Extensions/Numeric.rb +47 -0
- data/src/iowa/Extensions/Object.rb +11 -0
- data/src/iowa/Extensions/String.rb +60 -0
- data/src/iowa/Extensions/Time.rb +89 -0
- data/src/iowa/Extensions/TimeExtensions.rb +6 -0
- data/src/iowa/Form.rb +368 -0
- data/src/iowa/Hash.rb +85 -0
- data/src/iowa/ISAAC.rb +175 -0
- data/src/iowa/ImageSize.rb +279 -0
- data/src/iowa/IowaComponentMixins.rb +7 -0
- data/src/iowa/JSON-lexer.rb +296 -0
- data/src/iowa/JSON-objects.rb +201 -0
- data/src/iowa/KeyValueCoding.rb +91 -0
- data/src/iowa/LinkedList.rb +175 -0
- data/src/iowa/Loader.rb +22 -0
- data/src/iowa/Lockfile.rb +575 -0
- data/src/iowa/Logger.rb +74 -0
- data/src/iowa/Monkey.rb +20 -0
- data/src/iowa/Mutex.rb +142 -0
- data/src/iowa/Policy.rb +70 -0
- data/src/iowa/Pool.rb +243 -0
- data/src/iowa/PrettyException.rb +1091 -0
- data/src/iowa/Request.rb +244 -0
- data/src/iowa/Response.rb +133 -0
- data/src/iowa/Session.rb +354 -0
- data/src/iowa/SessionStats.rb +78 -0
- data/src/iowa/String.rb +65 -0
- data/src/iowa/Tag.rb +101 -0
- data/src/iowa/TemplateParser.rb +236 -0
- data/src/iowa/Util.rb +314 -0
- data/src/iowa/Webcache.rb +122 -0
- data/src/iowa/caches/BiLevelCache.rb +65 -0
- data/src/iowa/caches/ClassLimitedCache.rb +67 -0
- data/src/iowa/caches/DiskCache.rb +609 -0
- data/src/iowa/caches/DiskStore.rb +380 -0
- data/src/iowa/caches/LRUCache-alternative.rb +155 -0
- data/src/iowa/caches/LRUCache.rb +290 -0
- data/src/iowa/caches/SimpleLRUCache.rb +112 -0
- data/src/iowa/dispatchers/StandardDispatcher.rb +396 -0
- data/src/iowa/dispatchers/StandardDispatcherWithClassifier.rb +93 -0
- data/src/iowa/js/iowa_jsonrpc.js +381 -0
- data/src/iowa/js/jsonrpc.js +187 -0
- data/src/iowa/js/jsonrpc_async.js +261 -0
- data/src/iowa/loaders/DiskLoader.rb +50 -0
- data/src/iowa/loggers/Analogger.rb +54 -0
- data/src/iowa/loggers/AsyncLogger.rb +54 -0
- data/src/iowa/loggers/BitBucket.rb +38 -0
- data/src/iowa/loggers/Log4R.rb +13 -0
- data/src/iowa/loggers/Log4rLogger.rb +48 -0
- data/src/iowa/loggers/Logger.rb +29 -0
- data/src/iowa/loggers/RubyLogger.rb +9 -0
- data/src/iowa/pools/DBConnectionPool.rb +53 -0
- data/src/iowa/request/Apache.rb +90 -0
- data/src/iowa/request/EMHybrid.rb +59 -0
- data/src/iowa/request/ENV.rb +80 -0
- data/src/iowa/request/FCGI.rb +68 -0
- data/src/iowa/request/HTTPMachine.rb +75 -0
- data/src/iowa/request/Mongrel.rb +68 -0
- data/src/iowa/request/WEBrick.rb +48 -0
- data/src/iowa/version.rb +3 -0
- data/src/iowa/webrick/HTTPServer.rb +43 -0
- data/src/iowa/webrick/WEBrickServlet.rb +28 -0
- data/src/iowa_fcgi_handler.rb +101 -0
- data/src/iowa_httpmachine.rb +141 -0
- data/src/iowa_hybrid.rb +193 -0
- data/src/iowa_hybrid_cluster.rb +231 -0
- data/src/iowa_mongrel.rb +136 -0
- data/src/iowa_webrick.rb +194 -0
- data/src/iowa_webrick_legacy.rb +104 -0
- data/src/mod_iowa.rb +104 -0
- data/tcss.rb +61 -0
- data/test/README.windows +12 -0
- data/test/TC_AcceptLanguage.rb +61 -0
- data/test/TC_AppConfig.rb +43 -0
- data/test/TC_AppConfig/cgi/iowa.cgi +7 -0
- data/test/TC_AppConfig/doc/index.html +1 -0
- data/test/TC_AppConfig/iowa/Main.html +4 -0
- data/test/TC_AppConfig/iowa/Main.iwa +17 -0
- data/test/TC_AppConfig/iowa/README +1 -0
- data/test/TC_AppConfig/iowa/app.cnf +19 -0
- data/test/TC_AppConfig/iowa/app.rb +8 -0
- data/test/TC_AppConfig/webrick.rb +38 -0
- data/test/TC_Association.rb +29 -0
- data/test/TC_BiLevelCache.rb +71 -0
- data/test/TC_CGI_Adaptor.rb +55 -0
- data/test/TC_CGI_Adaptor/cgi/iowa.cgi +7 -0
- data/test/TC_CGI_Adaptor/doc/index.html +1 -0
- data/test/TC_CGI_Adaptor/iowa/Main.html +8 -0
- data/test/TC_CGI_Adaptor/iowa/Main.iwa +14 -0
- data/test/TC_CGI_Adaptor/iowa/README +1 -0
- data/test/TC_CGI_Adaptor/iowa/app.cnf +8 -0
- data/test/TC_CGI_Adaptor/iowa/app.rb +8 -0
- data/test/TC_CGI_Adaptor/webrick.rb +38 -0
- data/test/TC_CSS.rb +660 -0
- data/test/TC_ClassLimitedCache.rb +89 -0
- data/test/TC_Classifier.rb +80 -0
- data/test/TC_DbPool.rb +127 -0
- data/test/TC_DiskCache.rb +218 -0
- data/test/TC_Hybrid.rb +58 -0
- data/test/TC_Hybrid/doc/thing.txt +1 -0
- data/test/TC_Hybrid/iowa/Main.html +3 -0
- data/test/TC_Hybrid/iowa/Main.iwa +7 -0
- data/test/TC_Hybrid/iowa/NewPage.html +1 -0
- data/test/TC_Hybrid/iowa/NewPage.iwa +5 -0
- data/test/TC_Hybrid/iowa/app.cnf +10 -0
- data/test/TC_Hybrid/iowa/app.rb +5 -0
- data/test/TC_IOWAFunctions/doc/Ajax1.html +1 -0
- data/test/TC_IOWAFunctions/doc/Ajax1.iwa +1 -0
- data/test/TC_IOWAFunctions/doc/index.html +1 -0
- data/test/TC_IOWAFunctions/doc/js/dojo.js +9686 -0
- data/test/TC_IOWAFunctions/iowa/Ajax1.html +40 -0
- data/test/TC_IOWAFunctions/iowa/Ajax1.iwa +23 -0
- data/test/TC_IOWAFunctions/iowa/AjaxWidget.iwa +19 -0
- data/test/TC_IOWAFunctions/iowa/AjaxWidget.view +22 -0
- data/test/TC_IOWAFunctions/iowa/DanielTest.html +9 -0
- data/test/TC_IOWAFunctions/iowa/DanielTest.iwa +10 -0
- data/test/TC_IOWAFunctions/iowa/IntervalWidget.html +1 -0
- data/test/TC_IOWAFunctions/iowa/IntervalWidget.iwa +14 -0
- data/test/TC_IOWAFunctions/iowa/Main.html +1 -0
- data/test/TC_IOWAFunctions/iowa/NestedRepeat1.html +12 -0
- data/test/TC_IOWAFunctions/iowa/NestedRepeat1.iwa +24 -0
- data/test/TC_IOWAFunctions/iowa/RPCResponse.iwa +7 -0
- data/test/TC_IOWAFunctions/iowa/RPCResponse.view +1 -0
- data/test/TC_IOWAFunctions/iowa/Repeat1.iwa +31 -0
- data/test/TC_IOWAFunctions/iowa/Repeat1.view +9 -0
- data/test/TC_IOWAFunctions/iowa/Repeat2.iwa +32 -0
- data/test/TC_IOWAFunctions/iowa/Repeat2.view +11 -0
- data/test/TC_IOWAFunctions/iowa/Repeat3.iwa +44 -0
- data/test/TC_IOWAFunctions/iowa/Repeat3.view +18 -0
- data/test/TC_IOWAFunctions/iowa/TesCon.html +1 -0
- data/test/TC_IOWAFunctions/iowa/TesCon.iwa +5 -0
- data/test/TC_IOWAFunctions/iowa/app.cnf +19 -0
- data/test/TC_IOWAFunctions/iowa/app.rb +9 -0
- data/test/TC_IOWAFunctions/iowa/mapfile.cnf +8 -0
- data/test/TC_ISAAC.rb +52 -0
- data/test/TC_ImageSize.rb +84 -0
- data/test/TC_ImageSize/img.bmp +0 -0
- data/test/TC_ImageSize/img.gif +0 -0
- data/test/TC_ImageSize/img.jpg +0 -0
- data/test/TC_ImageSize/img.pcx +0 -0
- data/test/TC_ImageSize/img.pgm +7144 -0
- data/test/TC_ImageSize/img.png +0 -0
- data/test/TC_ImageSize/img.ppm +0 -0
- data/test/TC_ImageSize/img.psd +0 -0
- data/test/TC_ImageSize/img.tiff +0 -0
- data/test/TC_ImageSize/img.xbm +22 -0
- data/test/TC_KeyValueCoding.rb +35 -0
- data/test/TC_LRUCache.rb +296 -0
- data/test/TC_LinkedList.rb +46 -0
- data/test/TC_Lockfile.rb +106 -0
- data/test/TC_Minimal.rb +45 -0
- data/test/TC_Minimal/app.cnf +8 -0
- data/test/TC_Minimal/cgi-bin/iowa.cgi +11 -0
- data/test/TC_Minimal/doc/index.html +1 -0
- data/test/TC_Minimal/iowa/Main.html +1 -0
- data/test/TC_Minimal/iowa/README +1 -0
- data/test/TC_Minimal/iowa/app.rb +3 -0
- data/test/TC_Minimal/webrick.rb +38 -0
- data/test/TC_Mongrel.rb +58 -0
- data/test/TC_Mongrel/doc/thing.txt +1 -0
- data/test/TC_Mongrel/iowa/Main.html +3 -0
- data/test/TC_Mongrel/iowa/Main.iwa +7 -0
- data/test/TC_Mongrel/iowa/NewPage.html +1 -0
- data/test/TC_Mongrel/iowa/NewPage.iwa +5 -0
- data/test/TC_Mongrel/iowa/app.cnf +10 -0
- data/test/TC_Mongrel/iowa/app.rb +5 -0
- data/test/TC_NoSubclass.rb +56 -0
- data/test/TC_NoSubclass/cgi/iowa.cgi +7 -0
- data/test/TC_NoSubclass/doc/index.html +1 -0
- data/test/TC_NoSubclass/iowa/Main.html +8 -0
- data/test/TC_NoSubclass/iowa/Main.iwa +14 -0
- data/test/TC_NoSubclass/iowa/README +1 -0
- data/test/TC_NoSubclass/iowa/app.cnf +8 -0
- data/test/TC_NoSubclass/iowa/app.rb +5 -0
- data/test/TC_NoSubclass/webrick.rb +38 -0
- data/test/TC_Pool.rb +139 -0
- data/test/TC_RenderedCache/doc/thing.txt +1 -0
- data/test/TC_RenderedCache/iowa/BigPage.html +1 -0
- data/test/TC_RenderedCache/iowa/BigPage.iwa +12 -0
- data/test/TC_RenderedCache/iowa/Main.html +3 -0
- data/test/TC_RenderedCache/iowa/Main.iwa +7 -0
- data/test/TC_RenderedCache/iowa/NewPage.html +1 -0
- data/test/TC_RenderedCache/iowa/NewPage.iwa +11 -0
- data/test/TC_RenderedCache/iowa/app.cnf +13 -0
- data/test/TC_RenderedCache/iowa/app.rb +5 -0
- data/test/TC_RenderedCache/iowa/mapfile.map +4 -0
- data/test/TC_ResourceURL.rb +73 -0
- data/test/TC_ResourceURL/iowa/Main.html +2 -0
- data/test/TC_ResourceURL/iowa/Main.iwa +10 -0
- data/test/TC_ResourceURL/iowa/app.cnf +10 -0
- data/test/TC_ResourceURL/iowa/app.rb +5 -0
- data/test/TC_SimpleDetached.rb +41 -0
- data/test/TC_StandardDispatcher.rb +362 -0
- data/test/TC_StandardDispatcherWithClassifier.rb +358 -0
- data/test/TC_String.rb +24 -0
- data/test/TC_Tag.rb +41 -0
- data/test/TC_Webrick.rb +56 -0
- data/test/TC_Webrick/doc/thing.txt +1 -0
- data/test/TC_Webrick/iowa/Main.html +3 -0
- data/test/TC_Webrick/iowa/Main.iwa +7 -0
- data/test/TC_Webrick/iowa/NewPage.html +1 -0
- data/test/TC_Webrick/iowa/NewPage.iwa +5 -0
- data/test/TC_Webrick/iowa/app.cnf +10 -0
- data/test/TC_Webrick/iowa/app.rb +5 -0
- data/test/tc_template.rb +15 -0
- data/test/tests.conf +19 -0
- data/utils/CVS/Entries +3 -0
- data/utils/CVS/Repository +1 -0
- data/utils/CVS/Root +1 -0
- data/utils/QuickCert-1.0.2.tar.gz +0 -0
- data/utils/QuickCert-1.0.2/InstalledFiles +7 -0
- data/utils/QuickCert-1.0.2/MANIFEST +10 -0
- data/utils/QuickCert-1.0.2/Makefile +15 -0
- data/utils/QuickCert-1.0.2/README +56 -0
- data/utils/QuickCert-1.0.2/bin/QuickCert +355 -0
- data/utils/QuickCert-1.0.2/config.save +12 -0
- data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/README +60 -0
- data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/drbssl_c.rb +26 -0
- data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/drbssl_s.rb +35 -0
- data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/qc_config +21 -0
- data/utils/QuickCert-1.0.2/lib/QuickCert/defaults.rb +28 -0
- data/utils/QuickCert-1.0.2/setup.rb +1312 -0
- data/utils/iowa_apps +422 -0
- data/utils/smtp_sink.rb +9 -0
- data/utils/startup_template.cnf +27 -0
- data/utils/startup_template.rb +73 -0
- metadata +551 -0
data/src/iowa/Request.rb
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
require 'iowa/Util'
|
|
2
|
+
|
|
3
|
+
module Iowa
|
|
4
|
+
|
|
5
|
+
# A DispatchDestination is a simple container for information on
|
|
6
|
+
# where a request is being dispatched to.
|
|
7
|
+
|
|
8
|
+
class DispatchDestination
|
|
9
|
+
attr_accessor :component, :method, :args
|
|
10
|
+
|
|
11
|
+
def initialize(c=nil, m=nil, a=[])
|
|
12
|
+
@component = c
|
|
13
|
+
@method = m
|
|
14
|
+
@args = a
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Class to encapsulate the data received from a file upload.
|
|
19
|
+
|
|
20
|
+
class FileData < Array
|
|
21
|
+
|
|
22
|
+
attr_accessor :name, :content_type
|
|
23
|
+
|
|
24
|
+
def initialize(name,content_type,*content)
|
|
25
|
+
@name = name
|
|
26
|
+
@content_type = content_type
|
|
27
|
+
self.concat(content)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_s
|
|
31
|
+
self.join
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Create a file with a path/name as in @name, and write the current
|
|
35
|
+
# data to it. Convenience method.
|
|
36
|
+
# After an Iowa app received an uploaded file and it checks/sets
|
|
37
|
+
# @name as appropriate, a single call to store() will write the file.
|
|
38
|
+
# If @name is blank or nil, the content will instead be written to
|
|
39
|
+
# an instance of Tempfile.
|
|
40
|
+
|
|
41
|
+
def store
|
|
42
|
+
handle = nil
|
|
43
|
+
|
|
44
|
+
# Make sure you know what is in @name before calling this!
|
|
45
|
+
@name = @name.to_s
|
|
46
|
+
|
|
47
|
+
if @name == ''
|
|
48
|
+
require 'tempfile'
|
|
49
|
+
handle = Tempfile.new('IowaFile','/tmp')
|
|
50
|
+
else
|
|
51
|
+
handle = File.new(@name,'w+')
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
if handle
|
|
55
|
+
handle.write self.join
|
|
56
|
+
handle.rewind
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
handle
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# A serializeable class that represents (most of) the contents of
|
|
65
|
+
# an Apache::Request object.
|
|
66
|
+
|
|
67
|
+
class Request
|
|
68
|
+
|
|
69
|
+
MIMERegexp = %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n
|
|
70
|
+
CR = "\015"
|
|
71
|
+
LF = "\012"
|
|
72
|
+
EOL = CR + LF
|
|
73
|
+
|
|
74
|
+
attr_accessor :hostname, :port, :unparsed_uri, :uri, :filename, :request_time,
|
|
75
|
+
:request_method, :header_only, :args, :params,
|
|
76
|
+
:status_line, :headers_out, :content_type, :content_encoding
|
|
77
|
+
attr_accessor :content, :auth_type, :auth_name, :remote_host,
|
|
78
|
+
:cache_resp, :content_encoding, :content_languages, :remote_addr,
|
|
79
|
+
:calculate_runtime, :headers_in, :context
|
|
80
|
+
|
|
81
|
+
def Request.Type
|
|
82
|
+
@request_type
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def Request.Type=(val)
|
|
86
|
+
@request_type = val
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def read_multipart(boundary, content_length,instream,user_agent)
|
|
90
|
+
content_length = content_length.to_i
|
|
91
|
+
params = Hash.new([])
|
|
92
|
+
boundary = "--" + boundary
|
|
93
|
+
buf = ""
|
|
94
|
+
bufsize = 10 * 1024
|
|
95
|
+
|
|
96
|
+
# start multipart/form-data
|
|
97
|
+
instream.binmode if defined? instream.binmode
|
|
98
|
+
boundary_size = boundary.size + EOL.size
|
|
99
|
+
content_length -= boundary_size
|
|
100
|
+
status = instream.read(boundary_size)
|
|
101
|
+
|
|
102
|
+
loop do
|
|
103
|
+
head = nil
|
|
104
|
+
body = ''
|
|
105
|
+
|
|
106
|
+
until head and /#{boundary}(?:#{EOL}|--)/n.match(buf)
|
|
107
|
+
if (not head) and /#{EOL}#{EOL}/n.match(buf)
|
|
108
|
+
buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
|
|
109
|
+
head = $1.dup
|
|
110
|
+
""
|
|
111
|
+
end
|
|
112
|
+
next
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
if head and ( (EOL + boundary + EOL).size < buf.size )
|
|
116
|
+
body << buf[0 ... (buf.size - (EOL + boundary + EOL).size)]
|
|
117
|
+
buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
c = if bufsize < content_length
|
|
121
|
+
instream.read(bufsize) or ''
|
|
122
|
+
else
|
|
123
|
+
instream.read(content_length) or ''
|
|
124
|
+
end
|
|
125
|
+
if c.nil? || c.empty?
|
|
126
|
+
raise EOFError, "bad content body"
|
|
127
|
+
end
|
|
128
|
+
buf.concat(c)
|
|
129
|
+
content_length -= c.size
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
buf = buf.sub(/\A((?:.|\n)*?)(?:#{EOL})?#{boundary}(#{EOL}|--)/n) do
|
|
133
|
+
body << $1
|
|
134
|
+
if "--" == $2
|
|
135
|
+
content_length = -1
|
|
136
|
+
end
|
|
137
|
+
""
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
/Content-Disposition:.* filename="?([^\";]*)"?/ni.match(head)
|
|
141
|
+
filename = ($1 or "")
|
|
142
|
+
if /Mac/ni.match(user_agent) and
|
|
143
|
+
/Mozilla/ni.match(user_agent) and
|
|
144
|
+
(not /MSIE/ni.match(user_agent))
|
|
145
|
+
filename = Iowa::Util.unescape(filename)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
/Content-type: (.*)/ni.match(head)
|
|
149
|
+
content_type = ($1 or "")
|
|
150
|
+
|
|
151
|
+
/Content-Disposition:.* name="?([^\";]*)"?/ni.match(head)
|
|
152
|
+
name = $1.dup
|
|
153
|
+
|
|
154
|
+
data = nil
|
|
155
|
+
if content_type.to_s != ''
|
|
156
|
+
data = Iowa::FileData.new(filename,content_type,body)
|
|
157
|
+
else
|
|
158
|
+
data = body
|
|
159
|
+
end
|
|
160
|
+
if params.has_key?(name)
|
|
161
|
+
if params[name].respond_to?(:push)
|
|
162
|
+
params[name].push data
|
|
163
|
+
else
|
|
164
|
+
params[name] = [params[name]] << data
|
|
165
|
+
end
|
|
166
|
+
else
|
|
167
|
+
params[name] = data
|
|
168
|
+
end
|
|
169
|
+
break if buf.size == 0
|
|
170
|
+
break if content_length === -1
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
params
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def parse_params(line)
|
|
177
|
+
line.split(/&|;/).each do |pairs|
|
|
178
|
+
key, value = pairs.split(Iowa::CR_equal,2).collect{|v| Iowa::Util.unescape(v) }
|
|
179
|
+
if @params.has_key?(key)
|
|
180
|
+
if @params[key].respond_to?(:push)
|
|
181
|
+
@params[key] << value || Iowa::C_empty
|
|
182
|
+
else
|
|
183
|
+
@params[key] = [@params[key], value || Iowa::C_empty]
|
|
184
|
+
end
|
|
185
|
+
else
|
|
186
|
+
@params[key] = value || Iowa::C_empty
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# If there is a prefered Type set, return an instance of that type.
|
|
192
|
+
# Otherwise, guess at a prefered Type, set it, then return an instance.
|
|
193
|
+
|
|
194
|
+
def Request.new_request(request=nil)
|
|
195
|
+
unless Iowa::Request.Type
|
|
196
|
+
if ENV['MOD_RUBY']
|
|
197
|
+
unless request
|
|
198
|
+
request = Apache.request if ENV['MOD_RUBY']
|
|
199
|
+
end
|
|
200
|
+
require 'iowa/request/Apache'
|
|
201
|
+
Iowa::Request.Type = Iowa::Request::Apache
|
|
202
|
+
elsif request.class.name.index('FCGI') == 0
|
|
203
|
+
require 'iowa/request/FCGI'
|
|
204
|
+
Iowa::Request.Type = Iowa::Request::FCGI
|
|
205
|
+
elsif Object.const_defined?(:Mongrel)
|
|
206
|
+
require 'iowa/request/Mongrel'
|
|
207
|
+
Iowa::Request.Type = Iowa::Request::Mongrel
|
|
208
|
+
elsif Object.const_defined?(:WEBrick)
|
|
209
|
+
require 'iowa/request/WEBrick'
|
|
210
|
+
Iowa::Request.Type = Iowa::Request::WEBrick
|
|
211
|
+
else
|
|
212
|
+
require 'iowa/request/ENV'
|
|
213
|
+
Iowa::Request.Type = Iowa::Request::ENV
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
Iowa::Request.Type.new(request)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def headers
|
|
221
|
+
@headers_in
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def headers=(val)
|
|
225
|
+
@headers_in = val
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def header_only?
|
|
229
|
+
return @header_only
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def [](k)
|
|
233
|
+
@params[k]
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def []=(k,v)
|
|
237
|
+
@params[k] = v
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
#Iowa::Request.Type = Iowa::Request
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
require 'mime/types'
|
|
2
|
+
require 'iowa/Util'
|
|
3
|
+
require 'iowa/String'
|
|
4
|
+
|
|
5
|
+
module Iowa
|
|
6
|
+
|
|
7
|
+
class Response
|
|
8
|
+
BINARY_TYPE = MIME::Types.type_for('bin') unless const_defined?(:BINARY_TYPE)
|
|
9
|
+
|
|
10
|
+
# Based on info at http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
|
11
|
+
unless const_defined?(:RESPONSE_CODES)
|
|
12
|
+
RESPONSE_CODES = {
|
|
13
|
+
100 => 'Continue',
|
|
14
|
+
101 => 'Switching Protocols',
|
|
15
|
+
200 => 'OK',
|
|
16
|
+
201 => 'Created',
|
|
17
|
+
202 => 'Accepted',
|
|
18
|
+
203 => 'Non-Authoritative Information',
|
|
19
|
+
204 => 'No Content',
|
|
20
|
+
205 => 'Reset Content',
|
|
21
|
+
206 => 'Partial Content',
|
|
22
|
+
300 => 'Multiple Choices',
|
|
23
|
+
301 => 'Moved Permanently',
|
|
24
|
+
302 => 'Moved Temporarily',
|
|
25
|
+
303 => 'See Other',
|
|
26
|
+
304 => 'Not Modified',
|
|
27
|
+
305 => 'Use Proxy',
|
|
28
|
+
307 => 'Temporary Redirect',
|
|
29
|
+
400 => 'Bad Request',
|
|
30
|
+
401 => 'Unauthorized',
|
|
31
|
+
402 => 'Payment Required',
|
|
32
|
+
403 => 'Forbidden',
|
|
33
|
+
404 => 'Not Found',
|
|
34
|
+
405 => 'Method Not Allowed',
|
|
35
|
+
406 => 'Not Acceptable',
|
|
36
|
+
407 => 'Proxy Authentication Required',
|
|
37
|
+
408 => 'Request Timeout',
|
|
38
|
+
409 => 'Conflict',
|
|
39
|
+
410 => 'Gone',
|
|
40
|
+
411 => 'Length Required',
|
|
41
|
+
412 => 'Precondition Failed',
|
|
42
|
+
413 => 'Request Entity Too Large',
|
|
43
|
+
414 => 'Request-URI Too Long',
|
|
44
|
+
415 => 'Unsupported Media Type',
|
|
45
|
+
416 => 'Requested Range Not Satisfiable',
|
|
46
|
+
417 => 'Expectation Failed',
|
|
47
|
+
500 => 'Internal Server Error',
|
|
48
|
+
501 => 'Not Implemented',
|
|
49
|
+
502 => 'Bad Gateway',
|
|
50
|
+
503 => 'Service Unavailable',
|
|
51
|
+
504 => 'Gateway Timeout',
|
|
52
|
+
505 => 'HTTP Version Not Supported'}
|
|
53
|
+
RESPONSE_CODES.each {|k,v| const_set(Iowa::String.new(v.gsub('-','_')).constant_case,k)}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
attr_accessor :body, :calculate_runtime
|
|
57
|
+
alias :content :body
|
|
58
|
+
alias :content= :body=
|
|
59
|
+
|
|
60
|
+
def initialize(code=200, out = '')
|
|
61
|
+
self.status = code
|
|
62
|
+
@content_type = Ctext_html
|
|
63
|
+
@body = out
|
|
64
|
+
@headers = Iowa::DataTable.new
|
|
65
|
+
@headers.set('Cache-Control','private, max-age=0, no-store')
|
|
66
|
+
@calculate_runtime = false
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def headers
|
|
70
|
+
@headers
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def headers_out
|
|
74
|
+
@headers
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def content_type
|
|
78
|
+
@content_type
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# If given a complete type, such as 'text/csv', the type will be set as it
|
|
82
|
+
# was given. If given an incomplete type, such as 'gif' or 'csv', the type
|
|
83
|
+
# will be deduced or, if it can't be deduced, set to application/octet-stream.
|
|
84
|
+
|
|
85
|
+
def content_type=(type)
|
|
86
|
+
if type.index(C_slash)
|
|
87
|
+
@content_type = type
|
|
88
|
+
else
|
|
89
|
+
@content_type = MIME::Types.type_for(type).first || BINARY_TYPE
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def status
|
|
94
|
+
@status
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def status=(code)
|
|
98
|
+
if (rc = RESPONSE_CODES[code])
|
|
99
|
+
@status_line = "#{code} #{rc}"
|
|
100
|
+
@status = code
|
|
101
|
+
else
|
|
102
|
+
@status = 200
|
|
103
|
+
@status_line = '200 OK'
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def status_line
|
|
108
|
+
@status_line
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def status_line=(s)
|
|
112
|
+
s.gsub(/^\s*(\d+)\s+/) {self.status = $1.to_i; ''}
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def <<(val)
|
|
116
|
+
@body << val
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def cookie(name, val, args = {:path => C_slash})
|
|
120
|
+
parts = ["#{name}=#{val}"]
|
|
121
|
+
args.each {|k,v| parts << ["#{k}=#{v}"]}
|
|
122
|
+
self['Set-Cookie'] = parts.join(C_semicolon)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def [](val)
|
|
126
|
+
@headers.get(val)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def []=(k,v)
|
|
130
|
+
@headers.set(k,v)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
data/src/iowa/Session.rb
ADDED
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
#require 'log4r'
|
|
3
|
+
#include Log4r
|
|
4
|
+
require 'iowa/SessionStats'
|
|
5
|
+
|
|
6
|
+
module Iowa
|
|
7
|
+
|
|
8
|
+
# Container for an inline generated resource.
|
|
9
|
+
|
|
10
|
+
class Resource
|
|
11
|
+
|
|
12
|
+
attr_accessor :body, :content_type, :headers
|
|
13
|
+
|
|
14
|
+
def initialize(body,content_type=Capplication_data,headers=nil)
|
|
15
|
+
@body = body
|
|
16
|
+
@content_type = content_type
|
|
17
|
+
@headers = headers
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Custom exception which is thrown if a request does not have a request ID.
|
|
22
|
+
|
|
23
|
+
class IgnoreRequest < Exception; end
|
|
24
|
+
|
|
25
|
+
class NoAction < Exception; end
|
|
26
|
+
|
|
27
|
+
# Custom exception which is thrown if a request asks for a page which has
|
|
28
|
+
# expired from the cache.
|
|
29
|
+
|
|
30
|
+
class PageExpired < Exception; end
|
|
31
|
+
|
|
32
|
+
# Represents a session between the application and the user.
|
|
33
|
+
|
|
34
|
+
class Session
|
|
35
|
+
|
|
36
|
+
# Default delay between the presentation of the page expired message
|
|
37
|
+
# (see this below) and the redirect to the top of the application.
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# Class variable which holds the class of a session.
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# Define an accessor to make the context object accessible to the
|
|
44
|
+
# application's code.
|
|
45
|
+
|
|
46
|
+
attr_accessor :context, :application, :currentPage, :requestCount, :pages,
|
|
47
|
+
:resourceCount, :notes, :access_time, :lock
|
|
48
|
+
|
|
49
|
+
@sessionClass = self
|
|
50
|
+
|
|
51
|
+
def Session.cachedPages
|
|
52
|
+
@cachedPages
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def Session.cachedPages=(val)
|
|
56
|
+
@cachedPages = val
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def Session.cacheTTL
|
|
60
|
+
@cacheTTL
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def Session.cacheTTL=(val)
|
|
64
|
+
@cacheTTL = val
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Constructor to return a new instance of @sessionClass.
|
|
68
|
+
|
|
69
|
+
def Session.newSession(*args)
|
|
70
|
+
@sessionClass.new(*args)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def Session.inherited(subclass)
|
|
74
|
+
@sessionClass = subclass
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def self.PageCache
|
|
78
|
+
@page_cache_class ? @page_cache_class.new(@page_class_args) : nil
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def self.PageCache=(args)
|
|
82
|
+
@page_cache_class, @page_class_args = Util.get_cache(args,nil,Iowa.config[Csession],Cpagecache,true)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
FCM = Iowa::Component.methods.inject({}) {|h,k| h[k] = true; h} unless const_defined?(:FCM)
|
|
86
|
+
|
|
87
|
+
# Initialize the state of the session.
|
|
88
|
+
|
|
89
|
+
def initialize
|
|
90
|
+
@cachedPages ||= 10
|
|
91
|
+
@cacheTTL ||= nil
|
|
92
|
+
@expiryDelay ||= 1
|
|
93
|
+
reset
|
|
94
|
+
#@lock = Iowa::Mutex.new
|
|
95
|
+
@lock = Mutex.new
|
|
96
|
+
@creation_time = Time.now
|
|
97
|
+
#@statistics = Iowa::SessionStats.new(@pages)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def statistics
|
|
101
|
+
@statistics
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Handles the current request from the browser. Essentially all that
|
|
105
|
+
# is happening is thread synchronizations along with some tests to make
|
|
106
|
+
# sure that all the data necessary to handle the request exists.
|
|
107
|
+
# Then the call to handleRequest gets passed on to the object representing
|
|
108
|
+
# the current page.
|
|
109
|
+
|
|
110
|
+
def handleRequest(context,dispatch_destination = nil)
|
|
111
|
+
dispatch_destination = Iowa::DispatchDestination.new(dispatch_destination) if dispatch_destination.is_a?(::String)
|
|
112
|
+
@fragment = nil
|
|
113
|
+
#@statistics.hit
|
|
114
|
+
@access_time = Time.now
|
|
115
|
+
mylog = Logger[Ciowa_log]
|
|
116
|
+
if @lock.locked?
|
|
117
|
+
mylog.info("Session collision. Waiting.")
|
|
118
|
+
end
|
|
119
|
+
#mylog.debug("Handle Session for #{dispatch_destination.inspect}")
|
|
120
|
+
# @lock.synchronize do
|
|
121
|
+
@lock.lock
|
|
122
|
+
# begin
|
|
123
|
+
context.session = self
|
|
124
|
+
requestPage = @currentPage
|
|
125
|
+
@context = context
|
|
126
|
+
unless !context.requestID || dispatch_destination
|
|
127
|
+
#begin
|
|
128
|
+
# If the request is for a resource, handle that.
|
|
129
|
+
return handle_resource(context) if @resources.has_key?("#{context.requestID}.#{context.actionID}")
|
|
130
|
+
# Bail out if that page is not in the cache. Remember that a request
|
|
131
|
+
# runs on the current page; it's the response that generates a new page.
|
|
132
|
+
raise PageExpired unless @pages.include?(context.requestID)
|
|
133
|
+
requestPage = @pages[context.requestID]
|
|
134
|
+
|
|
135
|
+
if @requestCount != context.requestID and !requestPage.replaceable?
|
|
136
|
+
requestPage.handleBacktrack
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
@currentPage = requestPage.replaceable? ? requestPage : requestPage.dup
|
|
140
|
+
|
|
141
|
+
# TODO: Make it a runtime option to reload modified or not.
|
|
142
|
+
@application.reloadModified(@currentPage.class.name)
|
|
143
|
+
|
|
144
|
+
context.phase = :handleRequest
|
|
145
|
+
@currentPage.session = self
|
|
146
|
+
@currentPage.handleRequest(context)
|
|
147
|
+
nextPage = context.invokeAction
|
|
148
|
+
if nextPage and nextPage.fragment
|
|
149
|
+
@fragment = nextPage
|
|
150
|
+
else
|
|
151
|
+
@currentPage = nextPage if nextPage
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
@requestCount = @requestCount.next
|
|
155
|
+
#end
|
|
156
|
+
else
|
|
157
|
+
@currentPage = requestPage
|
|
158
|
+
end
|
|
159
|
+
handleResponse(context, dispatch_destination)
|
|
160
|
+
rescue PageExpired => e
|
|
161
|
+
expired(@pages.queue.last,context)
|
|
162
|
+
rescue NoAction => e
|
|
163
|
+
mylog.info "Render last page seen because there is no action -- something is probably not right, here."
|
|
164
|
+
#expired(@pages.queue.last,context)
|
|
165
|
+
@currentPage = @pages[@pages.queue.last]
|
|
166
|
+
@currentPage.session = self
|
|
167
|
+
handleResponse(context)
|
|
168
|
+
ensure
|
|
169
|
+
@lock.unlock
|
|
170
|
+
# end
|
|
171
|
+
# end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Specify a starting page name.
|
|
175
|
+
def startingPageName; 'Main'; end
|
|
176
|
+
|
|
177
|
+
# Return a component for the starting page; should use startingPageName.
|
|
178
|
+
def startingPage
|
|
179
|
+
Component.pageNamed(startingPageName,self)
|
|
180
|
+
rescue Exception => e
|
|
181
|
+
Logger[Ciowa_log].error "Starting page selection failed with #{e}\n#{e.backtrace.join("\n")}"
|
|
182
|
+
raise e
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Invokes the handleResponse() method on the object representing the page
|
|
186
|
+
# and updates the page cache.
|
|
187
|
+
|
|
188
|
+
def handleResponse(context, dispatch_destination = nil)
|
|
189
|
+
context.phase = :handleResponse
|
|
190
|
+
return if context.do_not_render
|
|
191
|
+
@currentPage = Component.pageNamed(dispatch_destination.component,self,nil,nil,nil) if dispatch_destination and dispatch_destination.component
|
|
192
|
+
@currentPage = startingPage unless @currentPage
|
|
193
|
+
if !dispatch_destination.nil? and (ddm = dispatch_destination.method) and !FCM.has_key?(ddm)
|
|
194
|
+
context.phase = :handleRequest
|
|
195
|
+
verb_specific_method = "#{ddm}_#{context.request.request_method.upcase}"
|
|
196
|
+
ddm = verb_specific_method if @currentPage.respond_to?(verb_specific_method)
|
|
197
|
+
if @currentPage.respond_to?(ddm)
|
|
198
|
+
@application.reloadModified(@currentPage.class.name)
|
|
199
|
+
@currentPage = context.invokeAction(@currentPage,ddm,dispatch_destination.args) || @currentPage
|
|
200
|
+
else
|
|
201
|
+
@currentPage = startingPage
|
|
202
|
+
end
|
|
203
|
+
context.phase = :handleResponse
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
fp = @currentPage.fingerprint
|
|
207
|
+
if fp and @application.rendered_content.has_key?(fp)
|
|
208
|
+
rc = @application.rendered_content[fp]
|
|
209
|
+
context.response_buffer << rc[0]
|
|
210
|
+
context.response.content_type = rc[1]
|
|
211
|
+
rc[2].each do |k,v|
|
|
212
|
+
context.response.headers[k] = v
|
|
213
|
+
end
|
|
214
|
+
else
|
|
215
|
+
context.requestID = @requestCount unless @currentPage.replaceable? or (@fragment and @fragment.replaceable?)
|
|
216
|
+
unless @fragment
|
|
217
|
+
@currentPage.handleResponse(context)
|
|
218
|
+
else
|
|
219
|
+
@fragment.handleResponse(context)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# The Session delays creating the pagecache until it is needed.
|
|
223
|
+
# This is a performance boost for the most common case, which is
|
|
224
|
+
# a page with some dynamic content, but no form elements or
|
|
225
|
+
# dynamic urls that depend on a cached page for meaning.
|
|
226
|
+
|
|
227
|
+
context[:allow_docroot_caching] = @currentPage.allow_docroot_caching?
|
|
228
|
+
|
|
229
|
+
unless context[:skip_pagecache]
|
|
230
|
+
initialize_pagecache if !@pages
|
|
231
|
+
@pages[context.requestID] = @currentPage if @currentPage.cacheable?
|
|
232
|
+
@pages[context.requestID].session = nil if @pages[context.requestID].respond_to?(:session) and @currentPage.cacheable?
|
|
233
|
+
else
|
|
234
|
+
@application.rendered_content[fp] = [context.response_buffer,context.response.content_type,context.response.headers] if fp
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
rescue Exception => e
|
|
238
|
+
Logger[Ciowa_log].error "Application#handleResponse exception: #{e}\n#{e.backtrace.join("\n")}"
|
|
239
|
+
raise e
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# If one passes into resource_url content of some sort plus an optional
|
|
243
|
+
# content type (default is application/data if not specified), it will
|
|
244
|
+
# return a URL that can be used to access that content. If, on the
|
|
245
|
+
# other hand, one passes an arbitrary set of arguments and a block,
|
|
246
|
+
# a url will be returned that, when accesed, will cause the block to
|
|
247
|
+
# be executed. If the block returns an instance of Iowa::Resource,
|
|
248
|
+
# the content in the resource will be returned as a result of calling
|
|
249
|
+
# that URL, with the content type specified in the resource object.
|
|
250
|
+
# Any other return value will have that value returned as the result
|
|
251
|
+
# of calling the URL, with a content type of 'application/data'.
|
|
252
|
+
# The resources are tied to the page that created them, so they are
|
|
253
|
+
# available until the page expires. Once the page expires, the
|
|
254
|
+
# resource is deleted as well.
|
|
255
|
+
def resource_url(*args,&block)
|
|
256
|
+
if block_given?
|
|
257
|
+
resource = [block,args]
|
|
258
|
+
else
|
|
259
|
+
resource = Iowa::Resource.new(args[0], args[1], args[2])
|
|
260
|
+
end
|
|
261
|
+
resourceID = "r_#{@requestCount}.#{@resourceCount}"
|
|
262
|
+
@resources[resourceID] = resource
|
|
263
|
+
@resources_by_component[@context.requestID] ||= []
|
|
264
|
+
@resources_by_component[@context.requestID].push resourceID
|
|
265
|
+
@resourceCount = @resourceCount.next
|
|
266
|
+
return "#{@context.sessionURL}.#{resourceID}#{@context.locationFlag}"
|
|
267
|
+
end
|
|
268
|
+
alias :resourceUrl :resource_url
|
|
269
|
+
|
|
270
|
+
def handle_resource(context)
|
|
271
|
+
r = @resources["#{context.requestID}.#{context.actionID}"]
|
|
272
|
+
resource = r.kind_of?(Array) ? r[0].call(*r[1]) : r
|
|
273
|
+
if resource.kind_of? Iowa::Resource
|
|
274
|
+
context.response_buffer << resource.body
|
|
275
|
+
context.response.content_type = resource.content_type
|
|
276
|
+
if resource.headers
|
|
277
|
+
resource.headers.each do |k,v|
|
|
278
|
+
context.response.headers[k] = v
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
else
|
|
282
|
+
context.response << resource.to_s
|
|
283
|
+
context.response.content_type = Capplication_data
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# Redirects the browser to the given URL. Second optional param is a true/false
|
|
288
|
+
# flag to indicate whether the redirect should be presented as permanent (301) or
|
|
289
|
+
# not (302).
|
|
290
|
+
def redirect(url,permanent = false)
|
|
291
|
+
context.response.headers[CLocation] = url
|
|
292
|
+
context.response.status = permanent ? 301 : 302
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# Resets the session. Useful as part of logging someone out of an application.
|
|
296
|
+
# Once the page cache is cleared, they can not backtrack.
|
|
297
|
+
|
|
298
|
+
def reset
|
|
299
|
+
@currentPage = nil
|
|
300
|
+
@requestCount = 'a'
|
|
301
|
+
@resourceCount = 'a'
|
|
302
|
+
@resources = {}
|
|
303
|
+
@resources_by_component = {}
|
|
304
|
+
@notes = {C__keystack => []}
|
|
305
|
+
unless Iowa.config[Csession][Cpagecache][Cclass]
|
|
306
|
+
Iowa.config[Csession][Cpagecache][Cclass] = 'iowa/caches/LRUCache'
|
|
307
|
+
Iowa.config[Csession][Cpagecache][Cmaxsize] = @cachedPages
|
|
308
|
+
Iowa.config[Csession][Cpagecache][Cttl] = @cacheTTL
|
|
309
|
+
end
|
|
310
|
+
self.class.PageCache = nil unless self.class.PageCache
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
# Clears the page cache. Takes one optional argument. The
|
|
314
|
+
# first optional argument specifies how many entries to leave in the
|
|
315
|
+
# page cache; it defaults to 0.
|
|
316
|
+
def clear_history(leave = 0)
|
|
317
|
+
ps = @pages.size
|
|
318
|
+
@pages.size = leave
|
|
319
|
+
@pages.size = ps
|
|
320
|
+
GC.start
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def [](v)
|
|
324
|
+
@notes[v]
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def []=(k,v)
|
|
328
|
+
@notes[k] = v
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
private
|
|
332
|
+
|
|
333
|
+
def initialize_pagecache
|
|
334
|
+
@pages = self.class.PageCache
|
|
335
|
+
@pages.add_finalizer(@resources,@resources_by_component) do |key,obj,resources,resources_by_component|
|
|
336
|
+
if resources_by_component.has_key? key
|
|
337
|
+
resources_by_component[key].each do |res_id|
|
|
338
|
+
resources.delete res_id
|
|
339
|
+
end
|
|
340
|
+
resources_by_component.delete key
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# Returns an explanation that the page being requested has expired, then
|
|
346
|
+
# issues a redirect to the head of the app. It'd be neat if there were
|
|
347
|
+
# some easy way to configure the contents of this page for an app.
|
|
348
|
+
|
|
349
|
+
def expired(most_recent_page,context)
|
|
350
|
+
context.response << "<html><head><meta http-equiv=REFRESH content='#{@expiryDelay}; URL=#{context.sessionURL}.#{most_recent_page}.0#{context.locationFlag}'></head><body><b>That page has expired.<p>You are being forwarded to your <a href='#{context.sessionURL}.#{most_recent_page}.0#{context.locationFlag}'>current point</a> in the session. Please continue from there.</b></body></html>"
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
end
|