From 07dcbba0f4c80c2d7bfcea9e8c21d5eac8ac667a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ku=C5=BAma?= Date: Sat, 14 Feb 2009 01:25:23 +0100 Subject: [PATCH] fixed orange multi box gateway --- app/models/message.rb | 15 +- app/models/orange_multi_box.rb | 4 +- app/stylesheets/screen.sass | 7 +- app/views/gateways/show.html.haml | 2 - app/views/messages/_form.html.haml | 3 - app/views/users/_form.html.haml | 3 - app/views/users/new.html.haml | 4 +- config/environment.rb | 8 +- lib/gateways/orange_multi_box.rb | 72 +-- lib/gateways/voip_discount.rb | 65 +- lib/gateways/voip_discount_old.rb | 66 ++ public/javascripts/application.js | 8 +- vendor/gems/mechanize-0.9.0/.specification | 306 ++++++++++ vendor/gems/mechanize-0.9.0/EXAMPLES.txt | 171 ++++++ vendor/gems/mechanize-0.9.0/FAQ.txt | 11 + vendor/gems/mechanize-0.9.0/GUIDE.txt | 122 ++++ vendor/gems/mechanize-0.9.0/History.txt | 451 ++++++++++++++ vendor/gems/mechanize-0.9.0/LICENSE.txt | 340 +++++++++++ vendor/gems/mechanize-0.9.0/Manifest.txt | 168 +++++ vendor/gems/mechanize-0.9.0/README.txt | 51 ++ vendor/gems/mechanize-0.9.0/Rakefile | 41 ++ .../mechanize-0.9.0/examples/flickr_upload.rb | 23 + .../mechanize-0.9.0/examples/mech-dump.rb | 7 + .../mechanize-0.9.0/examples/proxy_req.rb | 9 + .../mechanize-0.9.0/examples/rubyforge.rb | 21 + .../gems/mechanize-0.9.0/examples/spider.rb | 11 + vendor/gems/mechanize-0.9.0/lib/mechanize.rb | 7 + .../gems/mechanize-0.9.0/lib/www/mechanize.rb | 572 ++++++++++++++++++ .../lib/www/mechanize/chain.rb | 34 ++ .../lib/www/mechanize/chain/auth_headers.rb | 80 +++ .../mechanize/chain/body_decoding_handler.rb | 43 ++ .../mechanize/chain/connection_resolver.rb | 78 +++ .../lib/www/mechanize/chain/custom_headers.rb | 23 + .../lib/www/mechanize/chain/handler.rb | 9 + .../www/mechanize/chain/header_resolver.rb | 48 ++ .../www/mechanize/chain/parameter_resolver.rb | 23 + .../www/mechanize/chain/post_connect_hook.rb | 0 .../www/mechanize/chain/pre_connect_hook.rb | 22 + .../www/mechanize/chain/request_resolver.rb | 32 + .../mechanize/chain/response_body_parser.rb | 40 ++ .../chain/response_header_handler.rb | 50 ++ .../www/mechanize/chain/response_reader.rb | 41 ++ .../lib/www/mechanize/chain/ssl_resolver.rb | 36 ++ .../lib/www/mechanize/chain/uri_resolver.rb | 72 +++ .../lib/www/mechanize/content_type_error.rb | 16 + .../lib/www/mechanize/cookie.rb | 64 ++ .../lib/www/mechanize/cookie_jar.rb | 191 ++++++ .../mechanize-0.9.0/lib/www/mechanize/file.rb | 73 +++ .../lib/www/mechanize/file_response.rb | 62 ++ .../lib/www/mechanize/file_saver.rb | 39 ++ .../mechanize-0.9.0/lib/www/mechanize/form.rb | 334 ++++++++++ .../lib/www/mechanize/form/button.rb | 8 + .../lib/www/mechanize/form/check_box.rb | 13 + .../lib/www/mechanize/form/field.rb | 28 + .../lib/www/mechanize/form/file_upload.rb | 24 + .../lib/www/mechanize/form/image_button.rb | 23 + .../www/mechanize/form/multi_select_list.rb | 69 +++ .../lib/www/mechanize/form/option.rb | 51 ++ .../lib/www/mechanize/form/radio_button.rb | 38 ++ .../lib/www/mechanize/form/select_list.rb | 45 ++ .../lib/www/mechanize/headers.rb | 12 + .../lib/www/mechanize/history.rb | 67 ++ .../lib/www/mechanize/inspect.rb | 90 +++ .../lib/www/mechanize/monkey_patch.rb | 37 ++ .../mechanize-0.9.0/lib/www/mechanize/page.rb | 133 ++++ .../lib/www/mechanize/page/base.rb | 10 + .../lib/www/mechanize/page/frame.rb | 22 + .../lib/www/mechanize/page/link.rb | 50 ++ .../lib/www/mechanize/page/meta.rb | 10 + .../lib/www/mechanize/pluggable_parsers.rb | 100 +++ .../mechanize/redirect_limit_reached_error.rb | 18 + .../redirect_not_get_or_head_error.rb | 20 + .../lib/www/mechanize/response_code_error.rb | 25 + .../www/mechanize/unsupported_scheme_error.rb | 10 + .../mechanize-0.9.0/lib/www/mechanize/util.rb | 29 + vendor/gems/mechanize-0.9.0/mechanize.gemspec | 38 ++ .../test/chain/test_argument_validator.rb | 14 + .../test/chain/test_custom_headers.rb | 18 + .../test/chain/test_parameter_resolver.rb | 35 ++ .../test/chain/test_request_resolver.rb | 29 + .../test/chain/test_response_reader.rb | 24 + .../gems/mechanize-0.9.0/test/data/htpasswd | 1 + .../gems/mechanize-0.9.0/test/data/server.crt | 16 + .../gems/mechanize-0.9.0/test/data/server.csr | 12 + .../gems/mechanize-0.9.0/test/data/server.key | 15 + .../gems/mechanize-0.9.0/test/data/server.pem | 15 + vendor/gems/mechanize-0.9.0/test/helper.rb | 127 ++++ .../mechanize-0.9.0/test/htdocs/alt_text.html | 10 + .../test/htdocs/bad_form_test.html | 9 + .../mechanize-0.9.0/test/htdocs/button.jpg | Bin 0 -> 983 bytes .../test/htdocs/empty_form.html | 6 + .../test/htdocs/file_upload.html | 26 + .../test/htdocs/find_link.html | 41 ++ .../test/htdocs/form_multi_select.html | 16 + .../test/htdocs/form_multival.html | 37 ++ .../test/htdocs/form_no_action.html | 18 + .../test/htdocs/form_no_input_name.html | 16 + .../test/htdocs/form_select.html | 16 + .../test/htdocs/form_select_all.html | 16 + .../test/htdocs/form_select_none.html | 17 + .../test/htdocs/form_select_noopts.html | 10 + .../test/htdocs/form_set_fields.html | 14 + .../test/htdocs/form_test.html | 175 ++++++ .../test/htdocs/frame_test.html | 30 + .../mechanize-0.9.0/test/htdocs/google.html | 13 + .../test/htdocs/iframe_test.html | 16 + .../mechanize-0.9.0/test/htdocs/index.html | 6 + .../test/htdocs/link with space.html | 5 + .../test/htdocs/meta_cookie.html | 11 + .../test/htdocs/no_title_test.html | 6 + .../htdocs/relative/tc_relative_links.html | 21 + .../test/htdocs/tc_bad_links.html | 5 + .../test/htdocs/tc_base_link.html | 8 + .../test/htdocs/tc_blank_form.html | 11 + .../test/htdocs/tc_checkboxes.html | 19 + .../test/htdocs/tc_encoded_links.html | 5 + .../test/htdocs/tc_follow_meta.html | 8 + .../test/htdocs/tc_form_action.html | 48 ++ .../mechanize-0.9.0/test/htdocs/tc_links.html | 18 + .../test/htdocs/tc_no_attributes.html | 16 + .../test/htdocs/tc_pretty_print.html | 17 + .../test/htdocs/tc_radiobuttons.html | 17 + .../test/htdocs/tc_referer.html | 10 + .../test/htdocs/tc_relative_links.html | 19 + .../test/htdocs/tc_textarea.html | 23 + .../test/htdocs/unusual______.html | 5 + vendor/gems/mechanize-0.9.0/test/servlets.rb | 339 +++++++++++ .../gems/mechanize-0.9.0/test/ssl_server.rb | 48 ++ .../mechanize-0.9.0/test/test_authenticate.rb | 71 +++ .../mechanize-0.9.0/test/test_bad_links.rb | 25 + .../mechanize-0.9.0/test/test_blank_form.rb | 16 + .../mechanize-0.9.0/test/test_checkboxes.rb | 61 ++ .../mechanize-0.9.0/test/test_content_type.rb | 13 + .../mechanize-0.9.0/test/test_cookie_class.rb | 329 ++++++++++ .../mechanize-0.9.0/test/test_cookie_jar.rb | 343 +++++++++++ .../gems/mechanize-0.9.0/test/test_cookies.rb | 123 ++++ .../test/test_encoded_links.rb | 20 + .../gems/mechanize-0.9.0/test/test_errors.rb | 49 ++ .../mechanize-0.9.0/test/test_follow_meta.rb | 69 +++ .../mechanize-0.9.0/test/test_form_action.rb | 44 ++ .../mechanize-0.9.0/test/test_form_as_hash.rb | 61 ++ .../mechanize-0.9.0/test/test_form_button.rb | 38 ++ .../test/test_form_no_inputname.rb | 15 + .../gems/mechanize-0.9.0/test/test_forms.rb | 532 ++++++++++++++++ .../gems/mechanize-0.9.0/test/test_frames.rb | 25 + .../mechanize-0.9.0/test/test_get_headers.rb | 52 ++ .../mechanize-0.9.0/test/test_gzipping.rb | 22 + .../mechanize-0.9.0/test/test_hash_api.rb | 45 ++ .../gems/mechanize-0.9.0/test/test_history.rb | 142 +++++ .../test/test_history_added.rb | 16 + .../test/test_html_unscape_forms.rb | 39 ++ .../test/test_if_modified_since.rb | 20 + .../mechanize-0.9.0/test/test_keep_alive.rb | 31 + .../gems/mechanize-0.9.0/test/test_links.rb | 120 ++++ vendor/gems/mechanize-0.9.0/test/test_mech.rb | 248 ++++++++ .../test/test_mechanize_file.rb | 47 ++ .../mechanize-0.9.0/test/test_multi_select.rb | 106 ++++ .../test/test_no_attributes.rb | 13 + .../gems/mechanize-0.9.0/test/test_option.rb | 18 + vendor/gems/mechanize-0.9.0/test/test_page.rb | 43 ++ .../test/test_pluggable_parser.rb | 145 +++++ .../mechanize-0.9.0/test/test_post_form.rb | 34 ++ .../mechanize-0.9.0/test/test_pretty_print.rb | 22 + .../mechanize-0.9.0/test/test_radiobutton.rb | 63 ++ .../test/test_redirect_limit_reached.rb | 41 ++ .../test/test_redirect_verb_handling.rb | 45 ++ .../gems/mechanize-0.9.0/test/test_referer.rb | 39 ++ .../test/test_relative_links.rb | 40 ++ .../test/test_response_code.rb | 52 ++ .../mechanize-0.9.0/test/test_save_file.rb | 48 ++ .../gems/mechanize-0.9.0/test/test_scheme.rb | 48 ++ .../gems/mechanize-0.9.0/test/test_select.rb | 106 ++++ .../mechanize-0.9.0/test/test_select_all.rb | 15 + .../mechanize-0.9.0/test/test_select_none.rb | 15 + .../test/test_select_noopts.rb | 16 + .../mechanize-0.9.0/test/test_set_fields.rb | 44 ++ .../mechanize-0.9.0/test/test_ssl_server.rb | 20 + .../mechanize-0.9.0/test/test_subclass.rb | 14 + .../mechanize-0.9.0/test/test_textarea.rb | 45 ++ .../gems/mechanize-0.9.0/test/test_upload.rb | 109 ++++ .../gems/mechanize-0.9.0/test/test_verbs.rb | 22 + 181 files changed, 10064 insertions(+), 120 deletions(-) create mode 100644 lib/gateways/voip_discount_old.rb create mode 100644 vendor/gems/mechanize-0.9.0/.specification create mode 100644 vendor/gems/mechanize-0.9.0/EXAMPLES.txt create mode 100644 vendor/gems/mechanize-0.9.0/FAQ.txt create mode 100644 vendor/gems/mechanize-0.9.0/GUIDE.txt create mode 100644 vendor/gems/mechanize-0.9.0/History.txt create mode 100644 vendor/gems/mechanize-0.9.0/LICENSE.txt create mode 100644 vendor/gems/mechanize-0.9.0/Manifest.txt create mode 100644 vendor/gems/mechanize-0.9.0/README.txt create mode 100644 vendor/gems/mechanize-0.9.0/Rakefile create mode 100644 vendor/gems/mechanize-0.9.0/examples/flickr_upload.rb create mode 100644 vendor/gems/mechanize-0.9.0/examples/mech-dump.rb create mode 100644 vendor/gems/mechanize-0.9.0/examples/proxy_req.rb create mode 100644 vendor/gems/mechanize-0.9.0/examples/rubyforge.rb create mode 100644 vendor/gems/mechanize-0.9.0/examples/spider.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/mechanize.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/auth_headers.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/body_decoding_handler.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/connection_resolver.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/custom_headers.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/handler.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/header_resolver.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/parameter_resolver.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/post_connect_hook.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/pre_connect_hook.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/request_resolver.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/response_body_parser.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/response_header_handler.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/response_reader.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/ssl_resolver.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/uri_resolver.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/content_type_error.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/cookie.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/cookie_jar.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/file.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/file_response.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/file_saver.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/form.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/button.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/check_box.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/field.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/file_upload.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/image_button.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/multi_select_list.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/option.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/radio_button.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/select_list.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/headers.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/history.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/inspect.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/monkey_patch.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/page.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/base.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/frame.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/link.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/meta.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/pluggable_parsers.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/redirect_limit_reached_error.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/redirect_not_get_or_head_error.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/response_code_error.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/unsupported_scheme_error.rb create mode 100644 vendor/gems/mechanize-0.9.0/lib/www/mechanize/util.rb create mode 100644 vendor/gems/mechanize-0.9.0/mechanize.gemspec create mode 100644 vendor/gems/mechanize-0.9.0/test/chain/test_argument_validator.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/chain/test_custom_headers.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/chain/test_parameter_resolver.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/chain/test_request_resolver.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/chain/test_response_reader.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/data/htpasswd create mode 100644 vendor/gems/mechanize-0.9.0/test/data/server.crt create mode 100644 vendor/gems/mechanize-0.9.0/test/data/server.csr create mode 100644 vendor/gems/mechanize-0.9.0/test/data/server.key create mode 100644 vendor/gems/mechanize-0.9.0/test/data/server.pem create mode 100644 vendor/gems/mechanize-0.9.0/test/helper.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/alt_text.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/bad_form_test.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/button.jpg create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/empty_form.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/file_upload.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/find_link.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/form_multi_select.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/form_multival.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/form_no_action.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/form_no_input_name.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/form_select.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/form_select_all.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/form_select_none.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/form_select_noopts.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/form_set_fields.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/form_test.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/frame_test.html create mode 100755 vendor/gems/mechanize-0.9.0/test/htdocs/google.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/iframe_test.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/index.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/link with space.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/meta_cookie.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/no_title_test.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/relative/tc_relative_links.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_bad_links.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_base_link.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_blank_form.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_checkboxes.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_encoded_links.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_follow_meta.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_form_action.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_links.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_no_attributes.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_pretty_print.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_radiobuttons.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_referer.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_relative_links.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/tc_textarea.html create mode 100644 vendor/gems/mechanize-0.9.0/test/htdocs/unusual______.html create mode 100644 vendor/gems/mechanize-0.9.0/test/servlets.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/ssl_server.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_authenticate.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_bad_links.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_blank_form.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_checkboxes.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_content_type.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_cookie_class.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_cookie_jar.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_cookies.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_encoded_links.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_errors.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_follow_meta.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_form_action.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_form_as_hash.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_form_button.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_form_no_inputname.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_forms.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_frames.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_get_headers.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_gzipping.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_hash_api.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_history.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_history_added.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_html_unscape_forms.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_if_modified_since.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_keep_alive.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_links.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_mech.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_mechanize_file.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_multi_select.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_no_attributes.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_option.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_page.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_pluggable_parser.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_post_form.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_pretty_print.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_radiobutton.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_redirect_limit_reached.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_redirect_verb_handling.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_referer.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_relative_links.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_response_code.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_save_file.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_scheme.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_select.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_select_all.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_select_none.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_select_noopts.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_set_fields.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_ssl_server.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_subclass.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_textarea.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_upload.rb create mode 100644 vendor/gems/mechanize-0.9.0/test/test_verbs.rb diff --git a/app/models/message.rb b/app/models/message.rb index 54252a6..71cc044 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -15,27 +15,28 @@ class Message < ActiveRecord::Base belongs_to :gateway has_and_belongs_to_many :telephone_numbers - validates_presence_of :content, :user - validates_presence_of :recipients, :gateway + validates_presence_of :content, :user, :recipients, :gateway validates_length_of :content, :maximum => 640 validate :acceptance_of_telephone_numbers - default_scope :order => "created_at DESC" - before_validation :associate_telephone_numbers @@per_page = 8 cattr_reader :per_page attr_accessible :recipients, :content, :deliver_at - attr_reader :recipients + default_scope :order => "created_at DESC" named_scope :awaiting, lambda { { :conditions => ["aasm_state = ? AND deliver_at < ?", "pending", Time.now.utc] } } def recipients=(recipients) @recipients = recipients.squeeze(" ").split(",").map(&:strip).delete_if(&:empty?).uniq.join(", ") end + def recipients + telephone_numbers.map(&:to_s) + end + protected def ensure_delivered @@ -54,8 +55,10 @@ def acceptance_of_telephone_numbers end def associate_telephone_numbers + return if @recipients.nil? telephone_numbers.clear - recipients.split(", ").each { |r| telephone_numbers << user.telephone_numbers.find_or_initialize_by_recipient(r) } if recipients + @recipients.split(", ").each { |r| telephone_numbers << user.telephone_numbers.find_or_initialize_by_recipient(r) } telephone_numbers.uniq! + @recipients = nil end end diff --git a/app/models/orange_multi_box.rb b/app/models/orange_multi_box.rb index 12b0b7a..0f03641 100644 --- a/app/models/orange_multi_box.rb +++ b/app/models/orange_multi_box.rb @@ -5,7 +5,7 @@ class OrangeMultiBox < Gateway def amount Rails.cache.fetch("gateway#{id}.amount") do amount = nil - Gateways::OrangeMultiBox.login(login, self.class.decrypt(crypted_password)) { |gateway| amount = gateway.amount } + Gateways::OrangeMultiBox.new(login, self.class.decrypt(crypted_password)) { |gateway| amount = gateway.amount } amount end end @@ -21,7 +21,7 @@ def allow_number?(number) def deliver(telephone_numbers, content) Rails.cache.delete("gateway#{id}.amount") result = false - Gateways::OrangeMultiBox.login(login, self.class.decrypt(crypted_password)) do |gateway| + Gateways::OrangeMultiBox.new(login, self.class.decrypt(crypted_password)) do |gateway| result = gateway.deliver(telephone_numbers.map(&:number).join(","), content) if gateway.amount >= telephone_numbers.size end result diff --git a/app/stylesheets/screen.sass b/app/stylesheets/screen.sass index 800fca3..c2b3942 100644 --- a/app/stylesheets/screen.sass +++ b/app/stylesheets/screen.sass @@ -95,14 +95,13 @@ body dt :float left :padding 1em 0 - :width 25% - :border-bottom solid 1px #ddd + :width 200px :clear left dd - :float left + :position relative + :padding-left 200px :padding 1em 0 :border-bottom solid 1px #ddd - :width 75% #actions :padding 0.75em 0 diff --git a/app/views/gateways/show.html.haml b/app/views/gateways/show.html.haml index e45a5f6..3103758 100644 --- a/app/views/gateways/show.html.haml +++ b/app/views/gateways/show.html.haml @@ -1,3 +1 @@ -%h1 Viewing gateway - = render :partial => @gateway diff --git a/app/views/messages/_form.html.haml b/app/views/messages/_form.html.haml index a90d99b..cd99437 100644 --- a/app/views/messages/_form.html.haml +++ b/app/views/messages/_form.html.haml @@ -8,9 +8,6 @@ %li = f.label :content, "Content*" = f.text_area :content -%fieldset - %legend Delivery - %ol %li = f.label :gateway_id, "Gateway*" = f.collection_select :gateway_id, @gateways, :id, :name diff --git a/app/views/users/_form.html.haml b/app/views/users/_form.html.haml index c96d5da..84c6256 100644 --- a/app/views/users/_form.html.haml +++ b/app/views/users/_form.html.haml @@ -16,9 +16,6 @@ %li = f.label :password_confirmation, "Confirm password*" = f.password_field :password_confirmation -%fieldset - %legend Settings - %ol %li = f.label :default_country_code, "Default country code*" = f.select :default_country_code, E164::COUNTRIES, :include_blank => true diff --git a/app/views/users/new.html.haml b/app/views/users/new.html.haml index 952cfff..9920fca 100644 --- a/app/views/users/new.html.haml +++ b/app/views/users/new.html.haml @@ -1,5 +1,5 @@ -%h1 Sign up - - form_for @user, :url => user_path do |f| = render :partial => 'form', :locals => { :f => f } = submit_tag 'Sign up' + or + = link_to "Back", new_user_session_path diff --git a/config/environment.rb b/config/environment.rb index 277693d..39c2b3a 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -10,8 +10,10 @@ config.gem "rubyist-aasm", :lib => "aasm", :source => "http://gems.github.com" config.gem "chriseppstein-compass", :lib => "compass", :source => "http://gems.github.com" config.gem "railsgarden-message_block", :lib => "message_block", :source => "http://gems.github.com" - config.gem 'rspec-rails', :lib => false - config.gem 'rspec', :lib => false + config.gem "rspec-rails", :lib => false + config.gem "rspec", :lib => false + config.gem "mechanize" + config.gem "hpricot" - config.time_zone = 'UTC' + config.time_zone = "UTC" end diff --git a/lib/gateways/orange_multi_box.rb b/lib/gateways/orange_multi_box.rb index 41f32d8..a312a8d 100644 --- a/lib/gateways/orange_multi_box.rb +++ b/lib/gateways/orange_multi_box.rb @@ -1,59 +1,51 @@ -require "net/http" -require "net/https" - -# MINI HOWTO -# Gateways.orange_multi_box("username", "password") do |orange_multi_box| -# amount = orange_multi_box.amount -# delivered = orange_multi_box.deliver("500555555", "test") -# end +require "hpricot" module Gateways class OrangeMultiBox - HOST = "orange.pl" - PORT = 443 - LOGIN_LOCATION = "/portal/map/map/homeog?_DARGS=/gear/static/home/login.jsp.loginFormId" - MESSAGE_LOCATION = "/portal/map/map/message_box?_DARGS=/gear/mapmessagebox/smsform.jsp" - MESSAGEBOX_LOCATION = "/portal/map/map/message_box" - LOGIN_DATA = "_dyncharset=UTF-8&%%2Famg%%2Fptk%%2Fmap%%2Fcore%%2Fformhandlers%%2FAdvancedProfileFormHandler.loginErrorURL=%%2Fportal%%2Fmap%%2Fmap%%2Fsignin&_D%%3A%%2Famg%%2Fptk%%2Fmap%%2Fcore%%2Fformhandlers%%2FAdvancedProfileFormHandler.loginErrorURL=+&%%2Famg%%2Fptk%%2Fmap%%2Fcore%%2Fformhandlers%%2FAdvancedProfileFormHandler.loginSuccessURL=http%%3A%%2F%%2Fwww.orange.pl%%2Fportal%%2Fmap%%2Fmap%%2Fyour_account&_D%%3A%%2Famg%%2Fptk%%2Fmap%%2Fcore%%2Fformhandlers%%2FAdvancedProfileFormHandler.loginSuccessURL=+&%%2Famg%%2Fptk%%2Fmap%%2Fcore%%2Fformhandlers%%2FAdvancedProfileFormHandler.value.login=%s&_D%%3A%%2Famg%%2Fptk%%2Fmap%%2Fcore%%2Fformhandlers%%2FAdvancedProfileFormHandler.value.login=+&%%2Famg%%2Fptk%%2Fmap%%2Fcore%%2Fformhandlers%%2FAdvancedProfileFormHandler.value.password=%s&_D%%3A%%2Famg%%2Fptk%%2Fmap%%2Fcore%%2Fformhandlers%%2FAdvancedProfileFormHandler.value.password=+&%%2Famg%%2Fptk%%2Fmap%%2Fcore%%2Fformhandlers%%2FAdvancedProfileFormHandler.login.x=99&%%2Famg%%2Fptk%%2Fmap%%2Fcore%%2Fformhandlers%%2FAdvancedProfileFormHandler.login.y=7&_D%%3A%%2Famg%%2Fptk%%2Fmap%%2Fcore%%2Fformhandlers%%2FAdvancedProfileFormHandler.login=+&_DARGS=%%2Fgear%%2Fstatic%%2Fhome%%2Flogin.jsp.loginFormId" - MESSAGE_DATA = "_dyncharset=UTF-8&%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.type=sms&_D%%3A%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.type=+&enabled=false&%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.errorURL=%%2Fportal%%2Fmap%%2Fmap%%2Fmessage_box%%3Fmbox_view%%3Dnewsms&_D%%3A%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.errorURL=+&%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.successURL=%%2Fportal%%2Fmap%%2Fmap%%2Fmessage_box%%3Fmbox_view%%3Dmessageslist&_D%%3A%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.successURL=+&smscounter=1&counter=640&%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.to=%s&_D%%3A%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.to=+&_D%%3A%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.body=+&%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.body=%s&%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.create.x=25&%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.create.y=5&%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.create=Wy%%C5%%9Blij&_D%%3A%%2Famg%%2Fptk%%2Fmap%%2Fmessagebox%%2Fformhandlers%%2FMessageFormHandler.create=+&_DARGS=%%2Fgear%%2Fmapmessagebox%%2Fsmsform.jsp" + def initialize(username, password) + login(username, password) + yield self if logged_in? and block_given? + rescue SocketError, Timeout::Error + end - def self.login(username, password, &block) - http = Net::HTTP.new(HOST, PORT) - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - http.use_ssl = true if PORT == 443 - http.read_timeout = 60 - http.open_timeout = 60 - http_header = { "User-Agent" => "Mozilla/5.0", "Content-Type" => "application/x-www-form-urlencoded" } - response = http.post(LOGIN_LOCATION, LOGIN_DATA % [CGI.escape(username), CGI.escape(password)], http_header) - cookies = [] - [/VisitorId=[^;]+/, /mapProfileCookie=[^;]+/, /JSESSIONID=[^;]+/, /SID=[^;]+/, /ATG_SESSION_ID=[^;]+/, /mapSecurityCookie=[^;]+/].each do |regexp| - cookies << $& if response["Set-cookie"] =~ regexp - end - if cookies.size == 6 - http_header = { "User-Agent" => "Mozilla/5.0", "Cookie" => cookies.join("; ") } - yield OrangeMultiBox.new(http, http_header) if block_given? - true - end - rescue SocketError, Timeout::Error - false + def logged_in? + @agent.cookies.detect { |cookie| cookie.name == "mapProfileCookie" } end def amount - response = @http.get(MESSAGEBOX_LOCATION, @http_header) - $1.to_i if response.body =~ /(\d+)<\/span>/ + @agent.get("http://www.orange.pl/portal/map/map/message_box") do |page| + values = Hpricot(page.body) / "span.value" + return values.inner_html.to_i + end end def deliver(to, content) initial_amount = amount - @http.post(MESSAGE_LOCATION, MESSAGE_DATA % [CGI.escape(to), CGI.escape(content)], @http_header) + @agent.get("http://www.orange.pl/portal/map/map/message_box?mbox_view=newsms") do |page| + sms_form = page.form_with(:name => "sendSMS") do |form| + form["/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.to"] = to + form["/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.body"] = content + form["/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.create.x"] = "0" + form["/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.create.y"] = "0" + end + sms_form.submit + end initial_amount > amount end protected - def initialize(http, http_header) - @http = http - @http_header = http_header + def login(username, password) + @agent = WWW::Mechanize.new + @agent.get("http://www.orange.pl/portal/map/map/signin") do |page| + login_form = page.form_with(:name => "loginForm") do |form| + form["/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.value.login"] = username + form["/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.value.password"] = password + form["/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.login.x"] = "0" + form["/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.login.y"] = "0" + end + login_form.submit + end end end end diff --git a/lib/gateways/voip_discount.rb b/lib/gateways/voip_discount.rb index ec3690e..1648468 100644 --- a/lib/gateways/voip_discount.rb +++ b/lib/gateways/voip_discount.rb @@ -3,64 +3,27 @@ module Gateways class VoipDiscount - HOST = "myaccount.voipdiscount.com" - PORT = 443 - LOGIN_LOCATION = "/clx/index.php" - LOGIN_DATA = "part=menu&username=%s&password=%s" - MESSAGE_LOCATION = "/clx/websms2.php" - MESSAGE_DATA = "action=send&panel=&message=%s&callerid=%s&bnrphonenumber=%s&sendscheduled=no" #&day=20&month=08&hour=11&minute=12&gmt=1" - AMOUNT_LOCATION = "/clx/index.php?part=menu" - LOGOUT_LOCATION = "/clx/index.php?part=logoff" - - def self.login(login, password, &block) - http = Net::HTTP.new(HOST, PORT) - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - http.use_ssl = true if PORT == 443 - http.read_timeout = 60 - http.open_timeout = 60 - http_header = { "User-Agent" => "Mozilla/5.0" } - response = http.post(LOGIN_LOCATION, LOGIN_DATA % [CGI.escape(login), CGI.escape(password)], http_header.merge("Content-Type" => "application/x-www-form-urlencoded")) - if response.body =~ /error/i - return false # cannot log in with given login and password - else - return false unless response["Set-cookie"] # no Set-cookie - return false unless http_header["Cookie"] = response["Set-cookie"].scan(/PHPSESSID=[^;]+/).last # no PHPSESSID in Set-cookie - yield VoipDiscount.new(http, http_header) if block_given? - http.get(LOGOUT_LOCATION, http_header) - true - end - rescue SocketError, Timeout::Error => e - false + def initialize(username, password) + login(username, password) + yield self if logged_in? and block_given? + rescue SocketError, Timeout::Error end - def deliver(from, to, content) - 10.times do - response = @http.post(MESSAGE_LOCATION, MESSAGE_DATA % [CGI.escape(self.class.translit(content)), CGI.escape(from), CGI.escape(to)], @http_header.merge("Content-Type" => "application/x-www-form-urlencoded")) - return true if response.body =~ /sent/i - break unless response.body =~ /session lost/i - end - false - end + def logged_in? - def amount - 10.times do - response = @http.get(AMOUNT_LOCATION, @http_header) - return $1.to_f if response.body =~ /€ (\d+\.\d\d)<\/b><\/span>/ - break unless response.body =~ /session lost/i - end - nil end protected - def initialize(http, http_header) - @http = http - @http_header = http_header - end - - def self.translit(string) - Iconv.iconv('ASCII//TRANSLIT', 'UTF-8', string).first # doesn't work at all - # %x{echo -n #{string} | iconv -t ASCII//TRANSLIT} # depends on iconv in system !UNSAFE! + def login(username, password) + @agent = WWW::Mechanize.new { |a| a.log = Logger.new(STDOUT) } + @agent.get("https://myaccount.voipdiscount.com/clx/loginpanel.php") do |page| + login_form = page.form_with(:name => "loginpanel") do |form| + form.user = username + form.pass = password + end + login_form.submit + end end end end diff --git a/lib/gateways/voip_discount_old.rb b/lib/gateways/voip_discount_old.rb new file mode 100644 index 0000000..ec3690e --- /dev/null +++ b/lib/gateways/voip_discount_old.rb @@ -0,0 +1,66 @@ +require "net/http" +require "net/https" + +module Gateways + class VoipDiscount + HOST = "myaccount.voipdiscount.com" + PORT = 443 + LOGIN_LOCATION = "/clx/index.php" + LOGIN_DATA = "part=menu&username=%s&password=%s" + MESSAGE_LOCATION = "/clx/websms2.php" + MESSAGE_DATA = "action=send&panel=&message=%s&callerid=%s&bnrphonenumber=%s&sendscheduled=no" #&day=20&month=08&hour=11&minute=12&gmt=1" + AMOUNT_LOCATION = "/clx/index.php?part=menu" + LOGOUT_LOCATION = "/clx/index.php?part=logoff" + + def self.login(login, password, &block) + http = Net::HTTP.new(HOST, PORT) + http.verify_mode = OpenSSL::SSL::VERIFY_NONE + http.use_ssl = true if PORT == 443 + http.read_timeout = 60 + http.open_timeout = 60 + http_header = { "User-Agent" => "Mozilla/5.0" } + response = http.post(LOGIN_LOCATION, LOGIN_DATA % [CGI.escape(login), CGI.escape(password)], http_header.merge("Content-Type" => "application/x-www-form-urlencoded")) + if response.body =~ /error/i + return false # cannot log in with given login and password + else + return false unless response["Set-cookie"] # no Set-cookie + return false unless http_header["Cookie"] = response["Set-cookie"].scan(/PHPSESSID=[^;]+/).last # no PHPSESSID in Set-cookie + yield VoipDiscount.new(http, http_header) if block_given? + http.get(LOGOUT_LOCATION, http_header) + true + end + rescue SocketError, Timeout::Error => e + false + end + + def deliver(from, to, content) + 10.times do + response = @http.post(MESSAGE_LOCATION, MESSAGE_DATA % [CGI.escape(self.class.translit(content)), CGI.escape(from), CGI.escape(to)], @http_header.merge("Content-Type" => "application/x-www-form-urlencoded")) + return true if response.body =~ /sent/i + break unless response.body =~ /session lost/i + end + false + end + + def amount + 10.times do + response = @http.get(AMOUNT_LOCATION, @http_header) + return $1.to_f if response.body =~ /€ (\d+\.\d\d)<\/b><\/span>/ + break unless response.body =~ /session lost/i + end + nil + end + + protected + + def initialize(http, http_header) + @http = http + @http_header = http_header + end + + def self.translit(string) + Iconv.iconv('ASCII//TRANSLIT', 'UTF-8', string).first # doesn't work at all + # %x{echo -n #{string} | iconv -t ASCII//TRANSLIT} # depends on iconv in system !UNSAFE! + end + end +end diff --git a/public/javascripts/application.js b/public/javascripts/application.js index 691be63..9e31feb 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -1,8 +1,8 @@ $().ready(function() { $("#message_recipients").autocomplete("/recipients.txt", {selectFirst: true, multiple: true, multipleSeparator: ", "}); $("#contact_number").autocomplete("/telephone_numbers.txt", {selectFirst: true}); - $(".pagination a").click(function() { - $("#messages").load($(this).attr("href")); - return false; - }); + // $(".pagination a").click(function() { + // $("#messages").load($(this).attr("href")); + // return false; + // }); }); diff --git a/vendor/gems/mechanize-0.9.0/.specification b/vendor/gems/mechanize-0.9.0/.specification new file mode 100644 index 0000000..b7b9ca6 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/.specification @@ -0,0 +1,306 @@ +--- !ruby/object:Gem::Specification +name: mechanize +version: !ruby/object:Gem::Version + version: 0.9.0 +platform: ruby +authors: +- Aaron Patterson +- Mike Dalessio +autorequire: +bindir: bin +cert_chain: [] + +date: 2008-12-21 00:00:00 +01:00 +default_executable: +dependencies: +- !ruby/object:Gem::Dependency + name: nokogiri + type: :runtime + version_requirement: + version_requirements: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: 1.0.7 + version: +- !ruby/object:Gem::Dependency + name: hoe + type: :development + version_requirement: + version_requirements: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: 1.8.2 + version: +description: The Mechanize library is used for automating interaction with websites. Mechanize automatically stores and sends cookies, follows redirects, can follow links, and submit forms. Form fields can be populated and submitted. Mechanize also keeps track of the sites that you have visited as a history. +email: +- aaronp@rubyforge.org +- mike.dalessio@gmail.com +executables: [] + +extensions: [] + +extra_rdoc_files: +- EXAMPLES.txt +- FAQ.txt +- GUIDE.txt +- History.txt +- LICENSE.txt +- Manifest.txt +- README.txt +files: +- EXAMPLES.txt +- FAQ.txt +- GUIDE.txt +- History.txt +- LICENSE.txt +- Manifest.txt +- README.txt +- Rakefile +- examples/flickr_upload.rb +- examples/mech-dump.rb +- examples/proxy_req.rb +- examples/rubyforge.rb +- examples/spider.rb +- lib/mechanize.rb +- lib/www/mechanize.rb +- lib/www/mechanize/chain.rb +- lib/www/mechanize/chain/auth_headers.rb +- lib/www/mechanize/chain/body_decoding_handler.rb +- lib/www/mechanize/chain/connection_resolver.rb +- lib/www/mechanize/chain/custom_headers.rb +- lib/www/mechanize/chain/handler.rb +- lib/www/mechanize/chain/header_resolver.rb +- lib/www/mechanize/chain/parameter_resolver.rb +- lib/www/mechanize/chain/post_connect_hook.rb +- lib/www/mechanize/chain/pre_connect_hook.rb +- lib/www/mechanize/chain/request_resolver.rb +- lib/www/mechanize/chain/response_body_parser.rb +- lib/www/mechanize/chain/response_header_handler.rb +- lib/www/mechanize/chain/response_reader.rb +- lib/www/mechanize/chain/ssl_resolver.rb +- lib/www/mechanize/chain/uri_resolver.rb +- lib/www/mechanize/content_type_error.rb +- lib/www/mechanize/cookie.rb +- lib/www/mechanize/cookie_jar.rb +- lib/www/mechanize/file.rb +- lib/www/mechanize/file_response.rb +- lib/www/mechanize/file_saver.rb +- lib/www/mechanize/form.rb +- lib/www/mechanize/form/button.rb +- lib/www/mechanize/form/check_box.rb +- lib/www/mechanize/form/field.rb +- lib/www/mechanize/form/file_upload.rb +- lib/www/mechanize/form/image_button.rb +- lib/www/mechanize/form/multi_select_list.rb +- lib/www/mechanize/form/option.rb +- lib/www/mechanize/form/radio_button.rb +- lib/www/mechanize/form/select_list.rb +- lib/www/mechanize/headers.rb +- lib/www/mechanize/history.rb +- lib/www/mechanize/inspect.rb +- lib/www/mechanize/monkey_patch.rb +- lib/www/mechanize/page.rb +- lib/www/mechanize/page/base.rb +- lib/www/mechanize/page/frame.rb +- lib/www/mechanize/page/link.rb +- lib/www/mechanize/page/meta.rb +- lib/www/mechanize/pluggable_parsers.rb +- lib/www/mechanize/redirect_limit_reached_error.rb +- lib/www/mechanize/redirect_not_get_or_head_error.rb +- lib/www/mechanize/response_code_error.rb +- lib/www/mechanize/unsupported_scheme_error.rb +- lib/www/mechanize/util.rb +- mechanize.gemspec +- test/chain/test_argument_validator.rb +- test/chain/test_custom_headers.rb +- test/chain/test_parameter_resolver.rb +- test/chain/test_request_resolver.rb +- test/chain/test_response_reader.rb +- test/data/htpasswd +- test/data/server.crt +- test/data/server.csr +- test/data/server.key +- test/data/server.pem +- test/helper.rb +- test/htdocs/alt_text.html +- test/htdocs/bad_form_test.html +- test/htdocs/button.jpg +- test/htdocs/empty_form.html +- test/htdocs/file_upload.html +- test/htdocs/find_link.html +- test/htdocs/form_multi_select.html +- test/htdocs/form_multival.html +- test/htdocs/form_no_action.html +- test/htdocs/form_no_input_name.html +- test/htdocs/form_select.html +- test/htdocs/form_select_all.html +- test/htdocs/form_select_none.html +- test/htdocs/form_select_noopts.html +- test/htdocs/form_set_fields.html +- test/htdocs/form_test.html +- test/htdocs/frame_test.html +- test/htdocs/google.html +- test/htdocs/iframe_test.html +- test/htdocs/index.html +- test/htdocs/link with space.html +- test/htdocs/meta_cookie.html +- test/htdocs/no_title_test.html +- test/htdocs/relative/tc_relative_links.html +- test/htdocs/tc_bad_links.html +- test/htdocs/tc_base_link.html +- test/htdocs/tc_blank_form.html +- test/htdocs/tc_checkboxes.html +- test/htdocs/tc_encoded_links.html +- test/htdocs/tc_follow_meta.html +- test/htdocs/tc_form_action.html +- test/htdocs/tc_links.html +- test/htdocs/tc_no_attributes.html +- test/htdocs/tc_pretty_print.html +- test/htdocs/tc_radiobuttons.html +- test/htdocs/tc_referer.html +- test/htdocs/tc_relative_links.html +- test/htdocs/tc_textarea.html +- test/htdocs/unusual______.html +- test/servlets.rb +- test/ssl_server.rb +- test/test_authenticate.rb +- test/test_bad_links.rb +- test/test_blank_form.rb +- test/test_checkboxes.rb +- test/test_content_type.rb +- test/test_cookie_class.rb +- test/test_cookie_jar.rb +- test/test_cookies.rb +- test/test_encoded_links.rb +- test/test_errors.rb +- test/test_follow_meta.rb +- test/test_form_action.rb +- test/test_form_as_hash.rb +- test/test_form_button.rb +- test/test_form_no_inputname.rb +- test/test_forms.rb +- test/test_frames.rb +- test/test_get_headers.rb +- test/test_gzipping.rb +- test/test_hash_api.rb +- test/test_history.rb +- test/test_history_added.rb +- test/test_html_unscape_forms.rb +- test/test_if_modified_since.rb +- test/test_keep_alive.rb +- test/test_links.rb +- test/test_mech.rb +- test/test_mechanize_file.rb +- test/test_multi_select.rb +- test/test_no_attributes.rb +- test/test_option.rb +- test/test_page.rb +- test/test_pluggable_parser.rb +- test/test_post_form.rb +- test/test_pretty_print.rb +- test/test_radiobutton.rb +- test/test_redirect_limit_reached.rb +- test/test_redirect_verb_handling.rb +- test/test_referer.rb +- test/test_relative_links.rb +- test/test_response_code.rb +- test/test_save_file.rb +- test/test_scheme.rb +- test/test_select.rb +- test/test_select_all.rb +- test/test_select_none.rb +- test/test_select_noopts.rb +- test/test_set_fields.rb +- test/test_ssl_server.rb +- test/test_subclass.rb +- test/test_textarea.rb +- test/test_upload.rb +- test/test_verbs.rb +has_rdoc: true +homepage: " http://mechanize.rubyforge.org/" +post_install_message: +rdoc_options: +- --main +- README.txt +require_paths: +- lib +required_ruby_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +required_rubygems_version: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: "0" + version: +requirements: [] + +rubyforge_project: mechanize +rubygems_version: 1.3.1 +signing_key: +specification_version: 2 +summary: Mechanize provides automated web-browsing +test_files: +- test/chain/test_argument_validator.rb +- test/chain/test_custom_headers.rb +- test/chain/test_parameter_resolver.rb +- test/chain/test_request_resolver.rb +- test/chain/test_response_reader.rb +- test/test_authenticate.rb +- test/test_bad_links.rb +- test/test_blank_form.rb +- test/test_checkboxes.rb +- test/test_content_type.rb +- test/test_cookie_class.rb +- test/test_cookie_jar.rb +- test/test_cookies.rb +- test/test_encoded_links.rb +- test/test_errors.rb +- test/test_follow_meta.rb +- test/test_form_action.rb +- test/test_form_as_hash.rb +- test/test_form_button.rb +- test/test_form_no_inputname.rb +- test/test_forms.rb +- test/test_frames.rb +- test/test_get_headers.rb +- test/test_gzipping.rb +- test/test_hash_api.rb +- test/test_history.rb +- test/test_history_added.rb +- test/test_html_unscape_forms.rb +- test/test_if_modified_since.rb +- test/test_keep_alive.rb +- test/test_links.rb +- test/test_mech.rb +- test/test_mechanize_file.rb +- test/test_multi_select.rb +- test/test_no_attributes.rb +- test/test_option.rb +- test/test_page.rb +- test/test_pluggable_parser.rb +- test/test_post_form.rb +- test/test_pretty_print.rb +- test/test_radiobutton.rb +- test/test_redirect_limit_reached.rb +- test/test_redirect_verb_handling.rb +- test/test_referer.rb +- test/test_relative_links.rb +- test/test_response_code.rb +- test/test_save_file.rb +- test/test_scheme.rb +- test/test_select.rb +- test/test_select_all.rb +- test/test_select_none.rb +- test/test_select_noopts.rb +- test/test_set_fields.rb +- test/test_ssl_server.rb +- test/test_subclass.rb +- test/test_textarea.rb +- test/test_upload.rb +- test/test_verbs.rb diff --git a/vendor/gems/mechanize-0.9.0/EXAMPLES.txt b/vendor/gems/mechanize-0.9.0/EXAMPLES.txt new file mode 100644 index 0000000..92ad40f --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/EXAMPLES.txt @@ -0,0 +1,171 @@ += WWW::Mechanize examples + +== Google + require 'rubygems' + require 'mechanize' + + a = WWW::Mechanize.new { |agent| + agent.user_agent_alias = 'Mac Safari' + } + + a.get('http://google.com/') do |page| + search_result = page.form_with(:name => 'f') do |search| + search.q = 'Hello world' + end.submit + + search_result.links.each do |link| + puts link.text + end + end + +== Rubyforge + + a = WWW::Mechanize.new + a.get('http://rubyforge.org/') do |page| + # Click the login link + login_page = a.click(page.links.text(/Log In/)) + + # Submit the login form + my_page = login_page.form_with(:action => '/account/login.php') do |f| + f.form_loginname = ARGV[0] + f.form_pw = ARGV[1] + end.click_button + + my_page.links.each do |link| + text = link.text.strip + next unless text.length > 0 + puts text + end + end + +== File Upload +Upload a file to flickr. + + a = WWW::Mechanize.new { |agent| + # Flickr refreshes after login + agent.follow_meta_refresh = true + } + + a.get('http://flickr.com/') do |home_page| + signin_page = a.click(home_page.links.text(/Sign In/)) + + my_page = signin_page.form_with(:name => 'login_form') do |form| + form.login = ARGV[0] + form.passwd = ARGV[1] + end.submit + + # Click the upload link + upload_page = a.click(my_page.links.text(/Upload/)) + + # We want the basic upload page. + upload_page = a.click(upload_page.links.text(/basic Uploader/)) + + # Upload the file + upload_page.form_with(:method => 'POST') do |upload_form| + upload_form.file_uploads.first.file_name = ARGV[2] + end.submit + end + +== Pluggable Parsers +Lets say you want html pages to automatically be parsed with Rubyful Soup. +This example shows you how: + + require 'rubygems' + require 'mechanize' + require 'rubyful_soup' + + class SoupParser < WWW::Mechanize::Page + attr_reader :soup + def initialize(uri = nil, response = nil, body = nil, code = nil) + @soup = BeautifulSoup.new(body) + super(uri, response, body, code) + end + end + + agent = WWW::Mechanize.new + agent.pluggable_parser.html = SoupParser + +Now all HTML pages will be parsed with the SoupParser class, and automatically +give you access to a method called 'soup' where you can get access to the +Beautiful Soup for that page. + +== Using a proxy + + require 'rubygems' + require 'mechanize' + + agent = WWW::Mechanize.new + agent.set_proxy('localhost', '8000') + page = agent.get(ARGV[0]) + puts page.body + +== The transact method + +transact runs the given block and then resets the page history. I.e. after the +block has been executed, you're back at the original page; no need count how +many times to call the back method at the end of a loop (while accounting for +possible exceptions). + +This example also demonstrates subclassing Mechanize. + + require 'mechanize' + + class TestMech < WWW::Mechanize + def process + get 'http://rubyforge.org/' + search_form = page.forms.first + search_form.words = 'WWW' + submit search_form + + page.links_with(:href => %r{/projects/} ).each do |link| + next if link.href =~ %r{/projects/support/} + + puts 'Loading %-30s %s' % [link.href, link.text] + begin + transact do + click link + # Do stuff, maybe click more links. + end + # Now we're back at the original page. + + rescue => e + $stderr.puts "#{e.class}: #{e.message}" + end + end + end + end + + TestMech.new.process + +== Client Certificate Authentication (Mutual Auth) + +In most cases a client certificate is created as an additional layer of security +for certain websites. The specific case that this was initially tested on was +for automating the download of archived images from a banks (Wachovia) lockbox +system. Once the certificate is installed into your browser you will have to +export it and split the certificate and private key into separate files. Exported +files are usually in .p12 format (IE 7 & Firefox 2.0) which stands for PKCS #12. +You can convert them from p12 to pem format by using the following commands: + +openssl.exe pkcs12 -in input_file.p12 -clcerts -out example.key -nocerts -nodes +openssl.exe pkcs12 -in input_file.p12 -clcerts -out example.cer -nokeys + + require 'rubygems' + require 'mechanize' + + # create Mechanize instance + agent = WWW::Mechanize.new + + # set the path of the certificate file + agent.cert = 'example.cer' + + # set the path of the private key file + agent.key = 'example.key' + + # get the login form & fill it out with the username/password + login_form = @agent.get("http://example.com/login_page").form('Login') + login_form.Userid = 'TestUser' + login_form.Password = 'TestPassword' + + # submit login form + agent.submit(login_form, login_form.buttons.first) diff --git a/vendor/gems/mechanize-0.9.0/FAQ.txt b/vendor/gems/mechanize-0.9.0/FAQ.txt new file mode 100644 index 0000000..7955aa4 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/FAQ.txt @@ -0,0 +1,11 @@ +Q: I keep getting an EOFError: + protocol.rb:133:in `sysread': end of file reached (EOFError) + +A: Some people have experienced an EOFError during normal mechanize usage. + Most of the time this occurs because the remote website claims to support + keep alives, but does not implement them correctly. Try turning off + keep alives on your mechanize object: + + mech.keep_alive = false + + diff --git a/vendor/gems/mechanize-0.9.0/GUIDE.txt b/vendor/gems/mechanize-0.9.0/GUIDE.txt new file mode 100644 index 0000000..da4ed94 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/GUIDE.txt @@ -0,0 +1,122 @@ += Getting Started With WWW::Mechanize +This guide is meant to get you started using Mechanize. By the end of this +guide, you should be able to fetch pages, click links, fill out and submit +forms, scrape data, and many other hopefully useful things. This guide +really just scratches the surface of what is available, but should be enough +information to get you really going! + +== Let's Fetch a Page! +First thing is first. Make sure that you've required mechanize and that you +instantiate a new mechanize object: + require 'rubygems' + require 'mechanize' + + agent = WWW::Mechanize.new +Now we'll use the agent we've created to fetch a page. Let's fetch google +with our mechanize agent: + page = agent.get('http://google.com/') +What just happened? We told mechanize to go pick up google's main page. +Mechanize stored any cookies that were set, and followed any redirects that +google may have sent. The agent gave us back a page that we can use to +scrape data, find links to click, or find forms to fill out. + +Next, lets try finding some links to click. + +== Finding Links +Mechanize returns a page object whenever you get a page, post, or submit a +form. When a page is fetched, the agent will parse the page and put a list +of links on the page object. + +Now that we've fetched google's homepage, lets try listing all of the links: + page.links.each do |link| + puts link.text + end +We can list the links, but Mechanize gives a few shortcuts to help us find a +link to click on. Lets say we wanted to click the link whose text is 'News'. +Normally, we would have to do this: + page = agent.click page.links.find { |l| l.text == 'News' } +But Mechanize gives us a shortcut. Instead we can say this: + page = agent.click page.link_with(:text => 'News') +That shortcut says "find all links with the name 'News'". You're probably +thinking "there could be multiple links with that text!", and you would be +correct! If you use the plural form, you can access the list. +If you wanted to click on the second news link, you could do this: + agent.click page.links_with(:text => 'News')[1] +We can even find a link with a certain href like so: + page.links_with(:href => '/something') +Or chain them together to find a link with certain text and certain href: + page.links_with(:text => 'News', :href => '/something') + +These shortcuts that mechanize provides are available on any list that you +can fetch like frames, iframes, or forms. Now that we know how to find and +click links, lets try something more complicated like filling out a form. + +== Filling Out Forms +Lets continue with our google example. Here's the code we have so far: + require 'rubygems' + require 'mechanize' + + agent = WWW::Mechanize.new + page = agent.get('http://google.com/') +If we pretty print the page, we can see that there is one form named 'f', +that has a couple buttons and a few fields: + pp page +Now that we know the name of the form, lets fetch it off the page: + google_form = page.form('f') +Mechanize lets you access form input fields in a few different ways, but the +most convenient is that you can access input fields as accessors on the +object. So lets set the form field named 'q' on the form to 'ruby mechanize': + google_form.q = 'ruby mechanize' +To make sure that we set the value, lets pretty print the form, and you should +see a line similar to this: + # +If you saw that the value of 'q' changed, you're on the right track! Now we +can submit the form and 'press' the submit button and print the results: + page = agent.submit(google_form, google_form.buttons.first) + pp page +What we just did was equivalent to putting text in the search field and +clicking the 'Google Search' button. If we had submitted the form without +a button, it would be like typing in the text field and hitting the return +button. + +Lets take a look at the code all together: + require 'rubygems' + require 'mechanize' + + agent = WWW::Mechanize.new + page = agent.get('http://google.com/') + google_form = page.form('f') + google_form.q = 'ruby mechanize' + page = agent.submit(google_form) + pp page + +Before we go on to screen scraping, lets take a look at forms a little more +in depth. Unless you want to skip ahead! + +== Advanced Form Techniques +In this section, I want to touch on using the different types in input fields +possible with a form. Password and textarea fields can be treated just like +text input fields. Select fields are very similar to text fields, but they +have many options associated with them. If you select one option, mechanize +will deselect the other options (unless it is a multi select!). + +For example, lets select an option on a list: + form.field_with(:name => 'list').options[0].select + +Now lets take a look at checkboxes and radio buttons. To select a checkbox, +just check it like this: + form.checkbox_with(:name => 'box').check +Radio buttons are very similar to checkboxes, but they know how to uncheck +other radio buttons of the same name. Just check a radio button like you +would a checkbox: + form.radiobuttons_with(:name => 'box')[1].check +Mechanize also makes file uploads easy! Just find the file upload field, and +tell it what file name you want to upload: + form.file_uploads.first.file_name = "somefile.jpg" + +== Scraping Data +Mechanize uses nokogiri[http://nokogiri.rubyforge.org/] to parse +html. What does this mean for you? You can treat a mechanize page like +an nokogiri object. After you have used Mechanize to navigate to the page +that you need to scrape, then scrape it using nokogiri methods: + agent.get('http://someurl.com/').search(".//p[@class='posted']") diff --git a/vendor/gems/mechanize-0.9.0/History.txt b/vendor/gems/mechanize-0.9.0/History.txt new file mode 100644 index 0000000..b142d6c --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/History.txt @@ -0,0 +1,451 @@ += Mechanize CHANGELOG + +=== 0.9.0 + +* Deprecations + * WWW::Mechanize::List is gone! + * Mechanize uses Nokogiri as it's HTML parser but you may switch to + Hpricot by using WWW::Mechanize.html_parser = Hpricot + +* Bug Fixes: + * Nil check on page when base tag is used #23021 + +=== 0.8.5 + +* Deprecations + * WWW::Mechanize::List will be deprecated in 0.9.0, and warnings have + been added to help you upgrade. + +* Bug Fixes: + * Stopped raising EOF exceptions on HEAD requests. ありがとう:HIRAKU Kuroda + * Fixed exceptions when a logger is set and file:// requests are made. + * Made Mechanize 1.9 compatible + * Not setting the port in the host header for SSL sites. + * Following refresh headers. Thanks Tim Connor! + * Cookie Jar handles cookie domains containing ports, like + 'mydomain.com:443' (Thanks Michal Ochman!) + * Fixing strange uri escaping problems [#22604] + * Making content-type determintation more robust. (thanks Han Holl!) + * Dealing with links that are query string only. [#22402] + * Nokogiri may be dropped in as a replacement. + WWW::Mechanize.html_parser = Nokogiri::HTML + * Making sure the correct page is added to the history on meta refresh. + [#22708] + * Mechanize#get requests no longer send a referer unless they are relative + requests. + +=== 0.8.4 + +* Bug Fixes: + * Setting the port number on the host header. + * Fixing Authorization headers for picky servers + +=== 0.8.3 + +* Bug Fixes: + * Making sure logger is set during SSL connections. + +=== 0.8.2 + +* Bug Fixes: + * Doh! I was accidentally setting headers twice. + +=== 0.8.1 + +* Bug Fixes: + * Fixed problem with nil pointer when logger is set + +=== 0.8.0 + +* New Features: + * Lifecycle hooks. Mechanize#pre_connect_hooks, Mechanize#post_connect_hooks + * file:/// urls are now supported + * Added Mechanize::Page#link_with, frame_with for searching for links using + +criteria+. + * Implementing PUT, DELETE, and HEAD requests + +* Bug Fixes: + * Fixed an infinite loop when content-length and body length don't match. + * Only setting headers once + * Adding IIS authentication support + +=== 0.7.8 + +* Bug Fixes: + * Fixed bug when receiving a 304 response (HTTPNotModified) on a page not + cached in history. + * #21428 Default to HTML parser for 'application/xhtml+xml' content-type. + * Fixed an issue where redirects were resending posted data + +=== 0.7.7 + +* New Features: + * Page#form_with takes a +criteria+ hash. + * Page#form is changed to Page#form_with + * Mechanize#get takes custom http headers. Thanks Mike Dalessio! + * Form#click_button submits a form defaulting to the current button. + * Form#set_fields now takes a hash. Thanks Tobi! + * Mechanize#redirection_limit= for setting the max number of redirects. + +* Bug Fixes: + * Added more examples. Thanks Robert Jackson. + * #20480 Making sure the Host header is set. + * #20672 Making sure cookies with weird semicolons work. + * Fixed bug with percent signs in urls. + http://d.hatena.ne.jp/kitamomonga/20080410/ruby_mechanize_percent_url_bug + * #21132 Not checking for EOF errors on redirect + * Fixed a weird gzipping error. + * #21233 Smarter multipart boundry. Thanks Todd Willey! + * #20097 Supporting meta tag cookies. + +=== 0.7.6 + +* New Features: + * Added support for reading Mozilla cookie jars. Thanks Chris Riddoch! + * Moving text, password, hidden, int to default. Thanks Tim Harper! + * Mechanize#history_added callback for page loads. Thanks Tobi Reif! + * Mechanize#scheme_handlers callbacks for handling unsupported schemes on + links. + +* Bug Fixes: + * Ignoring scheme case + http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=470642 + * Not encoding tildes in uris. Thanks Bruno. [#19380] + * Resetting request bodys when retrying form posts. Thanks Bruno. [#19379] + * Throwing away keep alive connections on EPIPE and ECONNRESET. + * Duplicating request headers when retrying a 401. Thanks Hiroshi Ichikawa. + * Simulating an EOF error when a response length is bad. Thanks Tobias Gruetzmacher. + http://rubyforge.org/tracker/index.php?func=detail&aid=19178&group_id=1453&atid=5711 + * Defaulting option tags to the inner text. + http://rubyforge.org/tracker/index.php?func=detail&aid=19976&group_id=1453&atid=5709 + * Supporting blank strings for option values. + http://rubyforge.org/tracker/index.php?func=detail&aid=19975&group_id=1453&atid=5709 + +=== 0.7.5 + +* Fixed a bug when fetching files and not pages. Thanks Mat Schaffer! + +=== 0.7.4 + +* doh! + +=== 0.7.3 + +* Pages are now yielded to a blocks given to WWW::Mechanize#get +* WWW::Mechanize#get now takes hash arguments for uri parameters. +* WWW::Mechanize#post takes an IO object as a parameter and posts correctly. +* Fixing a strange zlib inflate problem on windows + +=== 0.7.2 + +* Handling gzipped responses with no Content-Length header + +=== 0.7.1 + +* Added iPhone to the user agent aliases. [#17572] +* Fixed a bug with EOF errors in net/http. [#17570] +* Handling 0 length gzipped responses. [#17471] + +=== 0.7.0 + +* Removed Ruby 1.8.2 support +* Changed parser to lazily parse links +* Lazily parsing document +* Adding verify_callback for SSL requests. Thanks Mike Dalessio! +* Fixed a bug with Accept-Language header. Thanks Bill Siggelkow. + +=== 0.6.11 + +* Detecting single quotes in meta redirects. +* Adding pretty inspect for ruby versions > 1.8.4 (Thanks Joel Kociolek) + http://rubyforge.org/tracker/index.php?func=detail&aid=13150&group_id=1453&atid=5709 +* Fixed bug with file name in multipart posts + http://rubyforge.org/tracker/?func=detail&aid=15594&group_id=1453&atid=5709 +* Posting forms relative to the originating page. Thanks Mortee. +* Added a FAQ + http://rubyforge.org/tracker/?func=detail&aid=15772&group_id=1453&atid=5709 + +=== 0.6.10 + +* Made digest authentication work with POSTs. +* Made sure page was HTML before following meta refreshes. + http://rubyforge.org/tracker/index.php?func=detail&aid=12260&group_id=1453&atid=5709 +* Made sure that URLS with a host and no path would default to '/' for history + purposes. + http://rubyforge.org/tracker/index.php?func=detail&aid=12368&group_id=1453&atid=5709 +* Avoiding memory leaks with transact. Thanks Tobias Gruetzmacher! + http://rubyforge.org/tracker/index.php?func=detail&aid=12057&group_id=1453&atid=5711 +* Fixing a problem with # signs in the file name. Thanks Tobias Gruetzmacher! + http://rubyforge.org/tracker/index.php?func=detail&aid=12510&group_id=1453&atid=5711 +* Made sure that blank form values are submitted. + http://rubyforge.org/tracker/index.php?func=detail&aid=12505&group_id=1453&atid=5709 +* Mechanize now respects the base tag. Thanks Stephan Dale. + http://rubyforge.org/tracker/index.php?func=detail&aid=12468&group_id=1453&atid=5709 +* Aliasing inspect to pretty_inspect. Thanks Eric Promislow. + http://rubyforge.org/pipermail/mechanize-users/2007-July/000157.html + +=== 0.6.9 + +* Updating UTF-8 support for urls +* Adding AREA tags to the links list. + http://rubyforge.org/pipermail/mechanize-users/2007-May/000140.html +* WWW::Mechanize#follow_meta_refresh will allow you to automatically follow + meta refresh tags. [#10032] +* Adding x-gzip to accepted content-encoding. Thanks Simon Strandgaard + http://rubyforge.org/tracker/index.php?func=detail&aid=11167&group_id=1453&atid=5711 +* Added Digest Authentication support. Thanks to Ryan Davis and Eric Hodel, + you get a gold star! + +=== 0.6.8 + +* Keep alive can be shut off now with WWW::Mechanize#keep_alive +* Conditional requests can be shut off with WWW::Mechanize#conditional_requests +* Monkey patched Net::HTTP#keep_alive? +* [#9877] Moved last request time. Thanks Max Stepanov +* Added WWW::Mechanize::File#save +* Defaulting file name to URI or Content-Disposition +* Updating compatability with hpricot +* Added more unit tests + +=== 0.6.7 + +* Fixed a bug with keep-alive requests +* [#9549] fixed problem with cookie paths + +=== 0.6.6 + +* Removing hpricot overrides +* Fixed a bug where alt text can be nil. Thanks Yannick! +* Unparseable expiration dates in cookies are now treated as session cookies +* Caching connections +* Requests now default to keep alive +* [#9434] Fixed bug where html entities weren't decoded +* [#9150] Updated mechanize history to deal with redirects + +=== 0.6.5 + +* Copying headers to a hash to prevent memory leaks +* Speeding up page parsing +* Aliased fields to elements +* Adding If-Modified-Since header +* Added delete_field! to form. Thanks to Sava Chankov +* Updated uri escaping to support high order characters. Thanks to Henrik Nyh. +* Better handling relative URIs. Thanks to Henrik Nyh +* Now handles pipes in URLs + http://rubyforge.org/tracker/?func=detail&aid=7140&group_id=1453&atid=5709 +* Now escaping html entities in form fields. + http://rubyforge.org/tracker/?func=detail&aid=7563&group_id=1453&atid=5709 +* Added MSIE 7.0 user agent string + +=== 0.6.4 + +* Adding the "redirect_ok" method to Mechanize to stop mechanize from + following redirects. + http://rubyforge.org/tracker/index.php?func=detail&aid=6571&group_id=1453&atid=5712 +* Added protected method Mechanize#set_headers so that subclasses can set + custom headers. + http://rubyforge.org/tracker/?func=detail&aid=7208&group_id=1453&atid=5712 +* Aliased Page#referer to Page#page +* Fixed a bug when clicking relative urls + http://rubyforge.org/pipermail/mechanize-users/2006-November/000035.html +* Fixing a bug when bad version or max age is passed to Cookie::parse + http://rubyforge.org/pipermail/mechanize-users/2006-November/000033.html +* Fixing a bug with response codes. [#6526] +* Fixed bug [#6548]. Input type of 'button' was not being added as a button. +* Fixed bug [#7139]. REXML parser calls hpricot parser by accident + +=== 0.6.3 + +* Added keys and values methods to Form +* Added has_value? to Form +* Added a has_field? method to Form +* The add_field! method on Form now creates a field for you on the form. + Thanks to Mat Schaffer for the patch. + http://rubyforge.org/pipermail/mechanize-users/2006-November/000025.html +* Fixed a bug when form actions have html ecoded entities in them. + http://rubyforge.org/pipermail/mechanize-users/2006-October/000019.html +* Fixed a bug when links or frame sources have html encoded entities in the + href or src. +* Fixed a bug where '#' symbols are encoded + http://rubyforge.org/forum/message.php?msg_id=14747 + +=== 0.6.2 + +* Added a yield to Page#form so that dealing with forms can be more DSL like. +* Added the parsed page to the ResponseCodeError so that the parsed results + can be accessed even in the event of an error. + http://rubyforge.org/pipermail/mechanize-users/2006-September/000007.html +* Updated documentation (Thanks to Paul Smith) + +=== 0.6.1 + +* Added a method to Form called "submit". Now forms can be submitted by + calling a method on the form. +* Added a click method to links +* Added an REXML pluggable parser for backwards compatability. To use it, + just do this: + agent.pluggable_parser.html = WWW::Mechanize::REXMLPage +* Fixed a bug with referrers by adding a page attribute to forms and links. +* Fixed a bug where domain names were case sensitive. + http://tenderlovemaking.com/2006/09/04/road-to-ruby-mechanize-060/#comment-53 +* Fixed a bug with URI escaped links. + http://rubyforge.org/pipermail/mechanize-users/2006-September/000002.html +* Fixed a bug when options in select lists don't have a value. Thanks Dan Higham + [#5837] Code in lib/mechanize/form_elements.rb is incorrect. +* Fixed a bug with loading text in to links. + http://rubyforge.org/pipermail/mechanize-users/2006-September/000000.html + +=== 0.6.0 + +* Changed main parser to use hpricot +* Made WWW::Mechanize::Page class searchable like hpricot +* Updated WWW::Mechanize#click to support hpricot links like this: + @agent.click (page/"a").first +* Clicking a Frame is now possible: + @agent.click (page/"frame").first +* Removed deprecated attr_finder +* Removed REXML helper methods since the main parser is now hpricot +* Overhauled cookie parser to use WEBrick::Cookie + +=== 0.5.4 + +* Added WWW::Mechanize#trasact for saving history state between in a + transaction. See the EXAMPLES file. Thanks Johan Kiviniemi. +* Added support for gzip compressed pages +* Forms can now be accessed like a hash. For example, to set the value + of an input field named 'name' to "Aaron", you can do this: + form['name'] = "Aaron" + Or to get the value of a field named 'name', do this: + puts form['name'] +* File uploads will now read the file specified in FileUpload#file_name +* FileUpload can use an IO object in FileUpload#file_data +* Fixed a bug with saving files on windows +* Fixed a bug with the filename being set in forms + +=== 0.5.3 + +* Mechanize#click will now act on the first element of an array. So if an + array of links is passed to WWW::Mechanize#click, the first link is clicked. + That means the syntax for clicking links is shortened and still supports + selecting a link. The following are equivalent: + agent.click page.links.first + agent.click page.links +* Fixed a bug with spaces in href's and get's +* Added a tick, untick, and click method to radio buttons so that + radiobuttons can be "clicked" +* Added a tick, untick, and click method to check boxes so that + checkboxes can be "clicked" +* Options on Select lists can now be "tick"ed, and "untick"ed. +* Fixed a potential bug conflicting with rails. Thanks Eric Kolve +* Updated log4r support for a speed increase. Thanks Yinon Bentor +* Added inspect methods and pretty printing + +=== 0.5.2 + +* Fixed a bug with input names that are nil +* Added a warning when using attr_finder because attr_finder will be deprecated + in 0.6.0 in favor of method calls. So this syntax: + @agent.links(:text => 'foo') + should be changed to this: + @agent.links.text('foo') +* Added support for selecting multiple options in select tags that support + multiple options. See WWW::Mechanize::MultiSelectList. +* New select list methods have been added, select_all, select_none. +* Options for select lists can now be "clicked" which toggles their selection, + they can be "selected" and "unselected". See WWW::Mechanize::Option +* Added a method to set multiple fields at the same time, + WWW::Mechanize::Form#set_fields. Which can be used like so: + form.set_fields( :foo => 'bar', :name => 'Aaron' ) + +=== 0.5.1 + +* Fixed bug with file uploads +* Added performance tweaks to the cookie class + +=== 0.5.0 + +* Added pluggable parsers. (Thanks to Eric Kolve for the idea) +* Changed namespace so all classes are under WWW::Mechanize. +* Updating Forms so that fields can be used as accessors (Thanks Gregory Brown) +* Added WWW::Mechanize::File as default object used for unknown content types. +* Added 'save_as' method to Mechanize::File, so any page can be saved. +* Adding 'save_as' and 'load' to CookieJar so that cookies can be saved + between sessions. +* Added WWW::Mechanize::FileSaver pluggable parser to automatically save files. +* Added WWW::Mechanize::Page#title for page titles +* Added OpenSSL certificate support (Thanks Mike Dalessio) +* Removed support for body filters in favor of pluggable parsers. +* Fixed cookie bug adding a '/' when the url is missing one (Thanks Nick Dainty) + +=== 0.4.7 + +* Fixed bug with no action in forms. Thanks to Adam Wiggins +* Setting a default user-agent string +* Added house cleaning to the cookie jar so expired cookies don't stick around. +* Added new method WWW::Form#field to find the first field with a given name. + (thanks to Gregory Brown) +* Added WWW::Mechanize#get_file for fetching non text/html files + +=== 0.4.6 + +* Added support for proxies +* Added a uri field to WWW::Link +* Added a error class WWW::Mechanize::ContentTypeError +* Added image alt text to link text +* Added an visited? method to WWW::Mechanize +* Added Array#value= which will set the first value to the argument. That + allows syntax as such: form.fields.name('q').value = 'xyz' + Before it was like this: form.fields.name('q').first.value = 'xyz' + +=== 0.4.5 + +* Added support for multiple values of the same name +* Updated build_query_string to take an array of arrays (Thanks Michal Janeczek) +* Added WWW::Mechanize#body_filter= so that response bodies can be preprocessed +* Added WWW::Page#body_filter= so that response bodies can be preprocessed +* Added support for more date formats in the cookie parser +* Fixed a bug with empty select lists +* Fixing a problem with cookies not handling no spaces after semicolons + +=== 0.4.4 + +* Fixed error in method signature, basic_authetication is now basic_auth +* Fixed bug with encoding names in file uploads (Big thanks to Alex Young) +* Added options to the select list + +=== 0.4.3 + +* Added syntactic sugar for finding things +* Fixed bug with HttpOnly option in cookies +* Fixed a bug with cookie date parsing +* Defaulted dropdown lists to the first element +* Added unit tests + +=== 0.4.2 + +* Added support for iframes +* Made mechanize dependant on ruby-web rather than narf +* Added unit tests +* Fixed a bunch of warnings + +=== 0.4.1 + +* Added support for file uploading +* Added support for frames (Thanks Gabriel[mailto:leerbag@googlemail.com]) +* Added more unit tests +* Fixed some bugs + +=== 0.4.0 + +* Added more unit tests +* Added a cookie jar with better cookie support, included expiration of cookies + and general cookie security. +* Updated mechanize to use built in net/http if ruby version is new enough. +* Added support for meta refresh tags +* Defaulted form actions to 'GET' +* Fixed various bugs +* Added more unit tests +* Added a response code exception +* Thanks to Brian Ellin (brianellin@gmail.com) for: + Added support for CA files, and support for 301 response codes + diff --git a/vendor/gems/mechanize-0.9.0/LICENSE.txt b/vendor/gems/mechanize-0.9.0/LICENSE.txt new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/LICENSE.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/vendor/gems/mechanize-0.9.0/Manifest.txt b/vendor/gems/mechanize-0.9.0/Manifest.txt new file mode 100644 index 0000000..61064c7 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/Manifest.txt @@ -0,0 +1,168 @@ +EXAMPLES.txt +FAQ.txt +GUIDE.txt +History.txt +LICENSE.txt +Manifest.txt +README.txt +Rakefile +examples/flickr_upload.rb +examples/mech-dump.rb +examples/proxy_req.rb +examples/rubyforge.rb +examples/spider.rb +lib/mechanize.rb +lib/www/mechanize.rb +lib/www/mechanize/chain.rb +lib/www/mechanize/chain/auth_headers.rb +lib/www/mechanize/chain/body_decoding_handler.rb +lib/www/mechanize/chain/connection_resolver.rb +lib/www/mechanize/chain/custom_headers.rb +lib/www/mechanize/chain/handler.rb +lib/www/mechanize/chain/header_resolver.rb +lib/www/mechanize/chain/parameter_resolver.rb +lib/www/mechanize/chain/post_connect_hook.rb +lib/www/mechanize/chain/pre_connect_hook.rb +lib/www/mechanize/chain/request_resolver.rb +lib/www/mechanize/chain/response_body_parser.rb +lib/www/mechanize/chain/response_header_handler.rb +lib/www/mechanize/chain/response_reader.rb +lib/www/mechanize/chain/ssl_resolver.rb +lib/www/mechanize/chain/uri_resolver.rb +lib/www/mechanize/content_type_error.rb +lib/www/mechanize/cookie.rb +lib/www/mechanize/cookie_jar.rb +lib/www/mechanize/file.rb +lib/www/mechanize/file_response.rb +lib/www/mechanize/file_saver.rb +lib/www/mechanize/form.rb +lib/www/mechanize/form/button.rb +lib/www/mechanize/form/check_box.rb +lib/www/mechanize/form/field.rb +lib/www/mechanize/form/file_upload.rb +lib/www/mechanize/form/image_button.rb +lib/www/mechanize/form/multi_select_list.rb +lib/www/mechanize/form/option.rb +lib/www/mechanize/form/radio_button.rb +lib/www/mechanize/form/select_list.rb +lib/www/mechanize/headers.rb +lib/www/mechanize/history.rb +lib/www/mechanize/inspect.rb +lib/www/mechanize/monkey_patch.rb +lib/www/mechanize/page.rb +lib/www/mechanize/page/base.rb +lib/www/mechanize/page/frame.rb +lib/www/mechanize/page/link.rb +lib/www/mechanize/page/meta.rb +lib/www/mechanize/pluggable_parsers.rb +lib/www/mechanize/redirect_limit_reached_error.rb +lib/www/mechanize/redirect_not_get_or_head_error.rb +lib/www/mechanize/response_code_error.rb +lib/www/mechanize/unsupported_scheme_error.rb +lib/www/mechanize/util.rb +mechanize.gemspec +test/chain/test_argument_validator.rb +test/chain/test_custom_headers.rb +test/chain/test_parameter_resolver.rb +test/chain/test_request_resolver.rb +test/chain/test_response_reader.rb +test/data/htpasswd +test/data/server.crt +test/data/server.csr +test/data/server.key +test/data/server.pem +test/helper.rb +test/htdocs/alt_text.html +test/htdocs/bad_form_test.html +test/htdocs/button.jpg +test/htdocs/empty_form.html +test/htdocs/file_upload.html +test/htdocs/find_link.html +test/htdocs/form_multi_select.html +test/htdocs/form_multival.html +test/htdocs/form_no_action.html +test/htdocs/form_no_input_name.html +test/htdocs/form_select.html +test/htdocs/form_select_all.html +test/htdocs/form_select_none.html +test/htdocs/form_select_noopts.html +test/htdocs/form_set_fields.html +test/htdocs/form_test.html +test/htdocs/frame_test.html +test/htdocs/google.html +test/htdocs/iframe_test.html +test/htdocs/index.html +test/htdocs/link with space.html +test/htdocs/meta_cookie.html +test/htdocs/no_title_test.html +test/htdocs/relative/tc_relative_links.html +test/htdocs/tc_bad_links.html +test/htdocs/tc_base_link.html +test/htdocs/tc_blank_form.html +test/htdocs/tc_checkboxes.html +test/htdocs/tc_encoded_links.html +test/htdocs/tc_follow_meta.html +test/htdocs/tc_form_action.html +test/htdocs/tc_links.html +test/htdocs/tc_no_attributes.html +test/htdocs/tc_pretty_print.html +test/htdocs/tc_radiobuttons.html +test/htdocs/tc_referer.html +test/htdocs/tc_relative_links.html +test/htdocs/tc_textarea.html +test/htdocs/unusual______.html +test/servlets.rb +test/ssl_server.rb +test/test_authenticate.rb +test/test_bad_links.rb +test/test_blank_form.rb +test/test_checkboxes.rb +test/test_content_type.rb +test/test_cookie_class.rb +test/test_cookie_jar.rb +test/test_cookies.rb +test/test_encoded_links.rb +test/test_errors.rb +test/test_follow_meta.rb +test/test_form_action.rb +test/test_form_as_hash.rb +test/test_form_button.rb +test/test_form_no_inputname.rb +test/test_forms.rb +test/test_frames.rb +test/test_get_headers.rb +test/test_gzipping.rb +test/test_hash_api.rb +test/test_history.rb +test/test_history_added.rb +test/test_html_unscape_forms.rb +test/test_if_modified_since.rb +test/test_keep_alive.rb +test/test_links.rb +test/test_mech.rb +test/test_mechanize_file.rb +test/test_multi_select.rb +test/test_no_attributes.rb +test/test_option.rb +test/test_page.rb +test/test_pluggable_parser.rb +test/test_post_form.rb +test/test_pretty_print.rb +test/test_radiobutton.rb +test/test_redirect_limit_reached.rb +test/test_redirect_verb_handling.rb +test/test_referer.rb +test/test_relative_links.rb +test/test_response_code.rb +test/test_save_file.rb +test/test_scheme.rb +test/test_select.rb +test/test_select_all.rb +test/test_select_none.rb +test/test_select_noopts.rb +test/test_set_fields.rb +test/test_ssl_server.rb +test/test_subclass.rb +test/test_textarea.rb +test/test_upload.rb +test/test_verbs.rb diff --git a/vendor/gems/mechanize-0.9.0/README.txt b/vendor/gems/mechanize-0.9.0/README.txt new file mode 100644 index 0000000..8ab03af --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/README.txt @@ -0,0 +1,51 @@ += WWW::Mechanize + + http://mechanize.rubyforge.org/ + http://github.com/tenderlove/mechanize/tree/master + +== DESCRIPTION + +The Mechanize library is used for automating interaction with websites. +Mechanize automatically stores and sends cookies, follows redirects, +can follow links, and submit forms. Form fields can be populated and +submitted. Mechanize also keeps track of the sites that you have visited as +a history. + +== Dependencies + +* ruby 1.8.4 +* hpricot[http://code.whytheluckystiff.net/hpricot/] + + +== Examples + +If you are just starting, check out the GUIDE[link://files/GUIDE_txt.html]. +Also, check out the EXAMPLES[link://files/EXAMPLES_txt.html] file. + +== Authors + +Copyright (c) 2005 by Michael Neumann (mneumann@ntecs.de) + +Copyright (c) 2006-2008: + +* {Aaron Patterson}[http://tenderlovemaking.com] (aaronp@rubyforge.org) +* {Mike Dalessio}[http://mike.daless.io] (mike@csa.net) + +This library comes with a shameless plug for employing me +(Aaron[http://tenderlovemaking.com/]) programming +Ruby, my favorite language! + +== Acknowledgments + +This library was heavily influenced by its namesake in the perl world. A big +thanks goes to Andy Lester (andy@petdance.com), the author of the original +perl Mechanize which is available here[http://search.cpan.org/~petdance/WWW-Mechanize-1.20/]. Ruby Mechanize would not be around without you! + +Thank you to Michael Neumann for starting the Ruby version. Thanks to everyone +who's helped out in various ways. Finally, thank you to the people using this +library! + +== License + +This library is distributed under the GPL. Please see the LICENSE[link://files/LICENSE_txt.html] file. + diff --git a/vendor/gems/mechanize-0.9.0/Rakefile b/vendor/gems/mechanize-0.9.0/Rakefile new file mode 100644 index 0000000..d7f9895 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/Rakefile @@ -0,0 +1,41 @@ +require 'rubygems' +require 'hoe' + +$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "lib") +require 'mechanize' + +HOE = Hoe.new('mechanize', WWW::Mechanize::VERSION) do |p| + p.rubyforge_name = 'mechanize' + p.developer('Aaron Patterson','aaronp@rubyforge.org') + p.developer('Mike Dalessio','mike.dalessio@gmail.com') + p.summary = "Mechanize provides automated web-browsing" + p.extra_deps = [['nokogiri', '>= 1.0.7']] +end + +desc "Update SSL Certificate" +task('ssl_cert') do |p| + sh "openssl genrsa -des3 -out server.key 1024" + sh "openssl req -new -key server.key -out server.csr" + sh "cp server.key server.key.org" + sh "openssl rsa -in server.key.org -out server.key" + sh "openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt" + sh "cp server.key server.pem" + sh "mv server.key server.csr server.crt server.pem test/data/" + sh "rm server.key.org" +end + +namespace :gem do + desc 'Generate a gem spec' + task :spec do + File.open("#{HOE.name}.gemspec", 'w') do |f| + HOE.spec.version = "#{HOE.version}.#{Time.now.strftime("%Y%m%d%H%M%S")}" + f.write(HOE.spec.to_ruby) + end + end +end + +desc "Run code-coverage analysis" +task :coverage do + rm_rf "coverage" + sh "rcov -x Library -I lib:test #{Dir[*HOE.test_globs].join(' ')}" +end diff --git a/vendor/gems/mechanize-0.9.0/examples/flickr_upload.rb b/vendor/gems/mechanize-0.9.0/examples/flickr_upload.rb new file mode 100644 index 0000000..fe6fabe --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/examples/flickr_upload.rb @@ -0,0 +1,23 @@ +$:.unshift File.join(File.dirname(__FILE__), "..", "lib") + +require 'rubygems' +require 'mechanize' + +agent = WWW::Mechanize.new + +# Get the flickr sign in page +page = agent.get('http://flickr.com/signin/flickr/') + +# Fill out the login form +form = page.forms.name('flickrloginform').first +form.email = ARGV[0] +form.password = ARGV[1] +page = agent.submit(form) + +# Go to the upload page +page = agent.click page.links.text('Upload') + +# Fill out the form +form = page.forms.action('/photos_upload_process.gne').first +form.file_uploads.name('file1').first.file_name = ARGV[2] +agent.submit(form) diff --git a/vendor/gems/mechanize-0.9.0/examples/mech-dump.rb b/vendor/gems/mechanize-0.9.0/examples/mech-dump.rb new file mode 100644 index 0000000..65d52ce --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/examples/mech-dump.rb @@ -0,0 +1,7 @@ +$:.unshift File.join(File.dirname(__FILE__), "..", "lib") + +require 'rubygems' +require 'mechanize' + +agent = WWW::Mechanize.new +puts agent.get(ARGV[0]).inspect diff --git a/vendor/gems/mechanize-0.9.0/examples/proxy_req.rb b/vendor/gems/mechanize-0.9.0/examples/proxy_req.rb new file mode 100644 index 0000000..68e6002 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/examples/proxy_req.rb @@ -0,0 +1,9 @@ +$:.unshift File.join(File.dirname(__FILE__), "..", "lib") + +require 'rubygems' +require 'mechanize' + +agent = WWW::Mechanize.new +agent.set_proxy('localhost', '8000') +page = agent.get(ARGV[0]) +puts page.body diff --git a/vendor/gems/mechanize-0.9.0/examples/rubyforge.rb b/vendor/gems/mechanize-0.9.0/examples/rubyforge.rb new file mode 100644 index 0000000..33df213 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/examples/rubyforge.rb @@ -0,0 +1,21 @@ +$:.unshift File.join(File.dirname(__FILE__), "..", "lib") + +# This example logs a user in to rubyforge and prints out the body of the +# page after logging the user in. +require 'rubygems' +require 'mechanize' + +# Create a new mechanize object +agent = WWW::Mechanize.new { |a| a.log = Logger.new(STDERR) } + +# Load the rubyforge website +page = agent.get('http://rubyforge.org/') +page = agent.click page.links.text(/Log In/) # Click the login link +form = page.forms[1] # Select the first form +form.form_loginname = ARGV[0] +form.form_pw = ARGV[1] + +# Submit the form +page = agent.submit(form, form.buttons.first) + +puts page.body # Print out the body diff --git a/vendor/gems/mechanize-0.9.0/examples/spider.rb b/vendor/gems/mechanize-0.9.0/examples/spider.rb new file mode 100644 index 0000000..ef1f167 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/examples/spider.rb @@ -0,0 +1,11 @@ +$:.unshift File.join(File.dirname(__FILE__), "..", "lib") + +require 'rubygems' +require 'mechanize' + +agent = WWW::Mechanize.new +stack = agent.get(ARGV[0]).links +while l = stack.pop + next unless l.uri.host == agent.history.first.uri.host + stack.push(*(agent.click(l).links)) unless agent.visited? l.href +end diff --git a/vendor/gems/mechanize-0.9.0/lib/mechanize.rb b/vendor/gems/mechanize-0.9.0/lib/mechanize.rb new file mode 100644 index 0000000..9adea14 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/mechanize.rb @@ -0,0 +1,7 @@ +# Copyright (c) 2005 by Michael Neumann (mneumann@ntecs.de) +# Copyright (c) 2007 by Aaron Patterson (aaronp@rubyforge.org) +# +# Please see the LICENSE file for licensing. + + +require 'www/mechanize' diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize.rb new file mode 100644 index 0000000..55630c7 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize.rb @@ -0,0 +1,572 @@ +require 'net/http' +require 'net/https' +require 'uri' +require 'webrick/httputils' +require 'zlib' +require 'stringio' +require 'digest/md5' +require 'fileutils' +require 'nokogiri' +require 'forwardable' + +require 'www/mechanize/util' +require 'www/mechanize/content_type_error' +require 'www/mechanize/response_code_error' +require 'www/mechanize/unsupported_scheme_error' +require 'www/mechanize/redirect_limit_reached_error' +require 'www/mechanize/redirect_not_get_or_head_error' +require 'www/mechanize/cookie' +require 'www/mechanize/cookie_jar' +require 'www/mechanize/history' +require 'www/mechanize/form' +require 'www/mechanize/pluggable_parsers' +require 'www/mechanize/file_response' +require 'www/mechanize/inspect' +require 'www/mechanize/chain' +require 'www/mechanize/monkey_patch' + +module WWW + # = Synopsis + # The Mechanize library is used for automating interaction with a website. It + # can follow links, and submit forms. Form fields can be populated and + # submitted. A history of URL's is maintained and can be queried. + # + # == Example + # require 'rubygems' + # require 'mechanize' + # require 'logger' + # + # agent = WWW::Mechanize.new { |a| a.log = Logger.new("mech.log") } + # agent.user_agent_alias = 'Mac Safari' + # page = agent.get("http://www.google.com/") + # search_form = page.form_with(:name => "f") + # search_form.field_with(:name => "q").value = "Hello" + # search_results = agent.submit(search_form) + # puts search_results.body + class Mechanize + ## + # The version of Mechanize you are using. + VERSION = '0.9.0' + + ## + # User Agent aliases + AGENT_ALIASES = { + 'Windows IE 6' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)', + 'Windows IE 7' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)', + 'Windows Mozilla' => 'Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6', + 'Mac Safari' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418 (KHTML, like Gecko) Safari/417.9.3', + 'Mac FireFox' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3', + 'Mac Mozilla' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4a) Gecko/20030401', + 'Linux Mozilla' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624', + 'Linux Konqueror' => 'Mozilla/5.0 (compatible; Konqueror/3; Linux)', + 'iPhone' => 'Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1C28 Safari/419.3', + 'Mechanize' => "WWW-Mechanize/#{VERSION} (http://rubyforge.org/projects/mechanize/)" + } + + attr_accessor :cookie_jar + attr_accessor :open_timeout, :read_timeout + attr_accessor :user_agent + attr_accessor :watch_for_set + attr_accessor :ca_file + attr_accessor :key + attr_accessor :cert + attr_accessor :pass + attr_accessor :redirect_ok + attr_accessor :keep_alive_time + attr_accessor :keep_alive + attr_accessor :conditional_requests + attr_accessor :follow_meta_refresh + attr_accessor :verify_callback + attr_accessor :history_added + attr_accessor :scheme_handlers + attr_accessor :redirection_limit + + attr_reader :history + attr_reader :pluggable_parser + + alias :follow_redirect? :redirect_ok + + @html_parser = Nokogiri::HTML + class << self; attr_accessor :html_parser, :log end + + def initialize + # attr_accessors + @cookie_jar = CookieJar.new + @log = nil + @open_timeout = nil + @read_timeout = nil + @user_agent = AGENT_ALIASES['Mechanize'] + @watch_for_set = nil + @history_added = nil + @ca_file = nil # OpenSSL server certificate file + + # callback for OpenSSL errors while verifying the server certificate + # chain, can be used for debugging or to ignore errors by always + # returning _true_ + @verify_callback = nil + @cert = nil # OpenSSL Certificate + @key = nil # OpenSSL Private Key + @pass = nil # OpenSSL Password + @redirect_ok = true # Should we follow redirects? + + # attr_readers + @history = WWW::Mechanize::History.new + @pluggable_parser = PluggableParser.new + + # Auth variables + @user = nil # Auth User + @password = nil # Auth Password + @digest = nil # DigestAuth Digest + @auth_hash = {} # Keep track of urls for sending auth + + # Proxy settings + @proxy_addr = nil + @proxy_pass = nil + @proxy_port = nil + @proxy_user = nil + + @conditional_requests = true + + @follow_meta_refresh = false + @redirection_limit = 20 + + # Connection Cache & Keep alive + @connection_cache = {} + @keep_alive_time = 300 + @keep_alive = true + + @scheme_handlers = Hash.new { |h,k| + h[k] = lambda { |link, page| + raise UnsupportedSchemeError.new(k) + } + } + @scheme_handlers['http'] = lambda { |link, page| link } + @scheme_handlers['https'] = @scheme_handlers['http'] + @scheme_handlers['relative'] = @scheme_handlers['http'] + @scheme_handlers['file'] = @scheme_handlers['http'] + + @pre_connect_hook = Chain::PreConnectHook.new + @post_connect_hook = Chain::PostConnectHook.new + + yield self if block_given? + end + + def max_history=(length); @history.max_size = length end + def max_history; @history.max_size end + def log=(l); self.class.log = l end + def log; self.class.log end + + def pre_connect_hooks + @pre_connect_hook.hooks + end + + def post_connect_hooks + @post_connect_hook.hooks + end + + # Sets the proxy address, port, user, and password + # +addr+ should be a host, with no "http://" + def set_proxy(addr, port, user = nil, pass = nil) + @proxy_addr, @proxy_port, @proxy_user, @proxy_pass = addr, port, user, pass + end + + # Set the user agent for the Mechanize object. + # See AGENT_ALIASES + def user_agent_alias=(al) + self.user_agent = AGENT_ALIASES[al] || raise("unknown agent alias") + end + + # Returns a list of cookies stored in the cookie jar. + def cookies + @cookie_jar.to_a + end + + # Sets the user and password to be used for authentication. + def auth(user, password) + @user = user + @password = password + end + alias :basic_auth :auth + + # Fetches the URL passed in and returns a page. + def get(options, parameters = [], referer = nil) + unless options.is_a? Hash + url = options + unless parameters.respond_to?(:each) # FIXME: Remove this in 0.8.0 + referer = parameters + parameters = [] + end + else + raise ArgumentError.new("url must be specified") unless url = options[:url] + parameters = options[:params] || [] + referer = options[:referer] + headers = options[:headers] + end + + unless referer + if url =~ /^http/ + referer = Page.new(nil, {'content-type'=>'text/html'}) + else + referer = current_page || Page.new(nil, {'content-type'=>'text/html'}) + end + end + + # FIXME: Huge hack so that using a URI as a referer works. I need to + # refactor everything to pass around URIs but still support + # WWW::Mechanize::Page#base + unless referer.is_a?(WWW::Mechanize::File) + referer = referer.is_a?(String) ? + Page.new(URI.parse(referer), {'content-type' => 'text/html'}) : + Page.new(referer, {'content-type' => 'text/html'}) + end + + # fetch the page + page = fetch_page( :uri => url, + :referer => referer, + :headers => headers || {}, + :params => parameters + ) + add_to_history(page) + yield page if block_given? + page + end + + #### + # PUT to +url+ with +query_params+, and setting +options+: + # + # put('http://tenderlovemaking.com/', {'q' => 'foo'}, :headers => {}) + # + def put(url, query_params = {}, options = {}) + options = { + :uri => url, + :headers => {}, + :params => query_params, + :verb => :put + }.merge(options) + # fetch the page + page = fetch_page(options) + add_to_history(page) + yield page if block_given? + page + end + + #### + # DELETE to +url+ with +query_params+, and setting +options+: + # + # delete('http://tenderlovemaking.com/', {'q' => 'foo'}, :headers => {}) + # + def delete(url, query_params = {}, options = {}) + put(url, query_params, options.merge({:verb => :delete})) + end + + #### + # HEAD to +url+ with +query_params+, and setting +options+: + # + # head('http://tenderlovemaking.com/', {'q' => 'foo'}, :headers => {}) + # + def head(url, query_params = {}, options = {}) + put(url, query_params, options.merge({:verb => :head})) + end + + # Fetch a file and return the contents of the file. + def get_file(url) + get(url).body + end + + # Clicks the WWW::Mechanize::Link object passed in and returns the + # page fetched. + def click(link) + referer = link.page rescue referer = nil + href = link.respond_to?(:href) ? link.href : + (link['href'] || link['src']) + get(:url => href, :referer => (referer || current_page())) + end + + # Equivalent to the browser back button. Returns the most recent page + # visited. + def back + @history.pop + end + + # Posts to the given URL wht the query parameters passed in. Query + # parameters can be passed as a hash, or as an array of arrays. + # Example: + # agent.post('http://example.com/', "foo" => "bar") + # or + # agent.post('http://example.com/', [ ["foo", "bar"] ]) + def post(url, query={}) + node = {} + # Create a fake form + class << node + def search(*args); []; end + end + node['method'] = 'POST' + node['enctype'] = 'application/x-www-form-urlencoded' + + form = Form.new(node) + query.each { |k,v| + if v.is_a?(IO) + form.enctype = 'multipart/form-data' + ul = Form::FileUpload.new(k.to_s,::File.basename(v.path)) + ul.file_data = v.read + form.file_uploads << ul + else + form.fields << Form::Field.new(k.to_s,v) + end + } + post_form(url, form) + end + + # Submit a form with an optional button. + # Without a button: + # page = agent.get('http://example.com') + # agent.submit(page.forms.first) + # With a button + # agent.submit(page.forms.first, page.forms.first.buttons.first) + def submit(form, button=nil) + form.add_button_to_query(button) if button + case form.method.upcase + when 'POST' + post_form(form.action, form) + when 'GET' + get( :url => form.action.gsub(/\?[^\?]*$/, ''), + :params => form.build_query, + :referer => form.page + ) + else + raise "unsupported method: #{form.method.upcase}" + end + end + + # Returns the current page loaded by Mechanize + def current_page + @history.last + end + + # Returns whether or not a url has been visited + def visited?(url) + ! visited_page(url).nil? + end + + # Returns a visited page for the url passed in, otherwise nil + def visited_page(url) + if url.respond_to? :href + url = url.href + end + @history.visited_page(resolve(url)) + end + + # Runs given block, then resets the page history as it was before. self is + # given as a parameter to the block. Returns the value of the block. + def transact + history_backup = @history.dup + begin + yield self + ensure + @history = history_backup + end + end + + alias :page :current_page + + private + + def resolve(url, referer = current_page()) + hash = { :uri => url, :referer => referer } + chain = Chain.new([ + Chain::URIResolver.new(@scheme_handlers) + ]).handle(hash) + hash[:uri].to_s + end + + def post_form(url, form) + cur_page = form.page || current_page || + Page.new( nil, {'content-type'=>'text/html'}) + + request_data = form.request_data + + log.debug("query: #{ request_data.inspect }") if log + + # fetch the page + page = fetch_page( :uri => url, + :referer => cur_page, + :verb => :post, + :params => [request_data], + :headers => { + 'Content-Type' => form.enctype, + 'Content-Length' => request_data.size.to_s, + }) + add_to_history(page) + page + end + + # uri is an absolute URI + def fetch_page(params) + options = { + :request => nil, + :response => nil, + :connection => nil, + :referer => current_page(), + :uri => nil, + :verb => :get, + :agent => self, + :redirects => 0, + :params => [], + :headers => {}, + }.merge(params) + + before_connect = Chain.new([ + Chain::URIResolver.new(@scheme_handlers), + Chain::ParameterResolver.new, + Chain::RequestResolver.new, + Chain::ConnectionResolver.new( + @connection_cache, + @keep_alive, + @proxy_addr, + @proxy_port, + @proxy_user, + @proxy_pass + ), + Chain::SSLResolver.new(@ca_file, @verify_callback, @cert, @key, @pass), + Chain::AuthHeaders.new(@auth_hash, @user, @password, @digest), + Chain::HeaderResolver.new( @keep_alive, + @keep_alive_time, + @cookie_jar, + @user_agent), + Chain::CustomHeaders.new, + @pre_connect_hook, + ]) + before_connect.handle(options) + + uri = options[:uri] + request = options[:request] + cur_page = options[:referer] + request_data = options[:params] + redirects = options[:redirects] + http_obj = options[:connection] + + # Add If-Modified-Since if page is in history + if( (page = visited_page(uri)) && page.response['Last-Modified'] ) + request['If-Modified-Since'] = page.response['Last-Modified'] + end if(@conditional_requests) + + # Specify timeouts if given + http_obj.open_timeout = @open_timeout if @open_timeout + http_obj.read_timeout = @read_timeout if @read_timeout + http_obj.start unless http_obj.started? + + # Log specified headers for the request + log.info("#{ request.class }: #{ request.path }") if log + request.each_header do |k, v| + log.debug("request-header: #{ k } => #{ v }") + end if log + + # Send the request + attempts = 0 + begin + response = http_obj.request(request, *request_data) { |r| + connection_chain = Chain.new([ + Chain::ResponseReader.new(r), + Chain::BodyDecodingHandler.new, + ]) + connection_chain.handle(options) + } + rescue EOFError, Errno::ECONNRESET, Errno::EPIPE => x + log.error("Rescuing EOF error") if log + http_obj.finish + raise x if attempts >= 2 + request.body = nil + http_obj.start + attempts += 1 + retry + end + + after_connect = Chain.new([ + @post_connect_hook, + Chain::ResponseBodyParser.new(@pluggable_parser, @watch_for_set), + Chain::ResponseHeaderHandler.new(@cookie_jar, @connection_cache), + ]) + after_connect.handle(options) + + res_klass = options[:res_klass] + response_body = options[:response_body] + page = options[:page] + + log.info("status: #{ page.code }") if log + + if follow_meta_refresh + redirect_uri = nil + if (page.respond_to?(:meta) && (redirect = page.meta.first)) + redirect_uri = redirect.uri.to_s + elsif refresh = response['refresh'] + parsed_refresh = refresh.match(/^\s*(\d+\.?\d*);\s*(url|URL)=(\S*)\s*$/) + raise StandardError, "Invalid refresh http header" unless parsed_refresh + delay = parsed_refresh[1] + location = parsed_refresh[3] + location = "http://#{uri.host}#{location}" unless location.include?("http") + if redirects + 1 > redirection_limit + raise RedirectLimitReachedError.new(page, redirects) + end + sleep delay.to_i + redirect_uri = location + end + if redirect_uri + @history.push(page, page.uri) + return fetch_page( + :uri => redirect_uri, + :referer => page, + :params => [], + :verb => :get, + :redirects => redirects + 1 + ) + end + end + + return page if res_klass <= Net::HTTPSuccess + + if res_klass == Net::HTTPNotModified + log.debug("Got cached page") if log + return visited_page(uri) || page + elsif res_klass <= Net::HTTPRedirection + return page unless follow_redirect? + log.info("follow redirect to: #{ response['Location'] }") if log + from_uri = page.uri + raise RedirectLimitReachedError.new(page, redirects) if redirects + 1 > redirection_limit + redirect_verb = options[:verb] == :head ? :head : :get + page = fetch_page( :uri => response['Location'].to_s, + :referer => page, + :params => [], + :verb => redirect_verb, + :redirects => redirects + 1 + ) + @history.push(page, from_uri) + return page + elsif res_klass <= Net::HTTPUnauthorized + raise ResponseCodeError.new(page) unless @user || @password + raise ResponseCodeError.new(page) if @auth_hash.has_key?(uri.host) + if response['www-authenticate'] =~ /Digest/i + @auth_hash[uri.host] = :digest + if response['server'] =~ /Microsoft-IIS/ + @auth_hash[uri.host] = :iis_digest + end + @digest = response['www-authenticate'] + else + @auth_hash[uri.host] = :basic + end + return fetch_page( :uri => uri, + :referer => cur_page, + :verb => request.method.downcase.to_sym, + :params => request_data, + :headers => options[:headers] + ) + end + + raise ResponseCodeError.new(page), "Unhandled response", caller + end + + def add_to_history(page) + @history.push(page, resolve(page.uri)) + history_added.call(page) if history_added + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain.rb new file mode 100644 index 0000000..1b15fe1 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain.rb @@ -0,0 +1,34 @@ +require 'www/mechanize/chain/handler' +require 'www/mechanize/chain/uri_resolver' +require 'www/mechanize/chain/parameter_resolver' +require 'www/mechanize/chain/request_resolver' +require 'www/mechanize/chain/custom_headers' +require 'www/mechanize/chain/connection_resolver' +require 'www/mechanize/chain/ssl_resolver' +require 'www/mechanize/chain/pre_connect_hook' +require 'www/mechanize/chain/auth_headers' +require 'www/mechanize/chain/header_resolver' +require 'www/mechanize/chain/response_body_parser' +require 'www/mechanize/chain/response_header_handler' +require 'www/mechanize/chain/response_reader' +require 'www/mechanize/chain/body_decoding_handler' + +module WWW + class Mechanize + class Chain + def initialize(list) + @list = list + @list.each { |l| l.chain = self } + end + + def handle(request) + @list.first.handle(self, request) + end + + def pass(obj, request) + next_link = @list[@list.index(obj) + 1] + next_link.handle(self, request) if next_link + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/auth_headers.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/auth_headers.rb new file mode 100644 index 0000000..8b4cf85 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/auth_headers.rb @@ -0,0 +1,80 @@ +module WWW + class Mechanize + class Chain + class AuthHeaders + include WWW::Handler + + @@nonce_count = -1 + CNONCE = Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535))) + + def initialize(auth_hash, user, password, digest) + @auth_hash = auth_hash + @user = user + @password = password + @digest = digest + end + + def handle(ctx, params) + uri = params[:uri] + request = params[:request] + + if( @auth_hash[uri.host] ) + case @auth_hash[uri.host] + when :basic + request.basic_auth(@user, @password) + when :iis_digest + digest_response = self.gen_auth_header(uri,request, @digest, true) + request['Authorization'] = digest_response + when :digest + if @digest + digest_response = self.gen_auth_header(uri,request, @digest) + request['Authorization'] = digest_response + end + end + end + super + end + + def gen_auth_header(uri, request, auth_header, is_IIS = false) + @@nonce_count += 1 + + auth_header =~ /^(\w+) (.*)/ + + params = {} + $2.gsub(/(\w+)=("[^"]*"|[^,]*)/) { + params[$1] = $2.gsub(/^"/, '').gsub(/"$/, '') + } + + a_1 = "#{@user}:#{params['realm']}:#{@password}" + a_2 = "#{request.method}:#{uri.path}" + request_digest = '' + request_digest << Digest::MD5.hexdigest(a_1) + request_digest << ':' << params['nonce'] + request_digest << ':' << ('%08x' % @@nonce_count) + request_digest << ':' << CNONCE + request_digest << ':' << params['qop'] + request_digest << ':' << Digest::MD5.hexdigest(a_2) + + header = '' + header << "Digest username=\"#{@user}\", " + if is_IIS then + header << "qop=\"#{params['qop']}\", " + else + header << "qop=#{params['qop']}, " + end + header << "uri=\"#{uri.path}\", " + header << %w{ algorithm opaque nonce realm }.map { |field| + next unless params[field] + "#{field}=\"#{params[field]}\"" + }.compact.join(', ') + + header << "nc=#{'%08x' % @@nonce_count}, " + header << "cnonce=\"#{CNONCE}\", " + header << "response=\"#{Digest::MD5.hexdigest(request_digest)}\"" + + return header + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/body_decoding_handler.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/body_decoding_handler.rb new file mode 100644 index 0000000..f0ce5ad --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/body_decoding_handler.rb @@ -0,0 +1,43 @@ +module WWW + class Mechanize + class Chain + class BodyDecodingHandler + include WWW::Handler + + def handle(ctx, options) + body = options[:response_body] + response = options[:response] + + options[:response_body] = + if encoding = response['Content-Encoding'] + case encoding.downcase + when 'gzip' + Mechanize.log.debug('gunzip body') if Mechanize.log + if response['Content-Length'].to_i > 0 || body.length > 0 + begin + Zlib::GzipReader.new(body).read + rescue Zlib::BufError, Zlib::GzipFile::Error + if Mechanize.log + Mechanize.log.error('Caught a Zlib::BufError') + end + body.rewind + body.read(10) + Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(body.read) + end + else + '' + end + when 'x-gzip' + body.read + else + raise 'Unsupported content encoding' + end + else + body.read + end + super + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/connection_resolver.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/connection_resolver.rb new file mode 100644 index 0000000..a86f566 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/connection_resolver.rb @@ -0,0 +1,78 @@ +module WWW + class Mechanize + class Chain + class ConnectionResolver + include WWW::Handler + + def initialize( connection_cache, + keep_alive, + proxy_addr, + proxy_port, + proxy_user, + proxy_pass ) + + @connection_cache = connection_cache + @keep_alive = keep_alive + @proxy_addr = proxy_addr + @proxy_port = proxy_port + @proxy_user = proxy_user + @proxy_pass = proxy_pass + end + + def handle(ctx, params) + uri = params[:uri] + http_obj = nil + + case uri.scheme.downcase + when 'http', 'https' + cache_obj = (@connection_cache["#{uri.host}:#{uri.port}"] ||= { + :connection => nil, + :keep_alive_options => {}, + }) + http_obj = cache_obj[:connection] + if http_obj.nil? || ! http_obj.started? + http_obj = cache_obj[:connection] = + Net::HTTP.new( uri.host, + uri.port, + @proxy_addr, + @proxy_port, + @proxy_user, + @proxy_pass + ) + cache_obj[:keep_alive_options] = {} + end + + # If we're keeping connections alive and the last request time is too + # long ago, stop the connection. Or, if the max requests left is 1, + # reset the connection. + if @keep_alive && http_obj.started? + opts = cache_obj[:keep_alive_options] + if((opts[:timeout] && + Time.now.to_i - cache_obj[:last_request_time] > opts[:timeout].to_i) || + opts[:max] && opts[:max].to_i == 1) + + Mechanize.log.debug('Finishing stale connection') if Mechanize.log + http_obj.finish + + end + end + + cache_obj[:last_request_time] = Time.now.to_i + when 'file' + http_obj = Object.new + class << http_obj + def started?; true; end + def request(request, *args, &block) + response = FileResponse.new(request.uri.path) + yield response + end + end + end + + params[:connection] = http_obj + super + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/custom_headers.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/custom_headers.rb new file mode 100644 index 0000000..e97f24b --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/custom_headers.rb @@ -0,0 +1,23 @@ +module WWW + class Mechanize + class Chain + class CustomHeaders + include WWW::Handler + + def handle(ctx, params) + request = params[:request] + params[:headers].each do |k,v| + case k + when :etag then request.add_field("ETag", v) + when :if_modified_since then request.add_field("If-Modified-Since", v) + else + raise ArgumentError.new("unknown header symbol #{k}") if k.is_a? Symbol + request.add_field(k,v) + end + end + super + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/handler.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/handler.rb new file mode 100644 index 0000000..edb3e81 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/handler.rb @@ -0,0 +1,9 @@ +module WWW + module Handler + attr_accessor :chain + + def handle(ctx, request) + chain.pass(self, request) + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/header_resolver.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/header_resolver.rb new file mode 100644 index 0000000..ba763b0 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/header_resolver.rb @@ -0,0 +1,48 @@ +module WWW + class Mechanize + class Chain + class HeaderResolver + include WWW::Handler + def initialize(keep_alive, keep_alive_time, cookie_jar, user_agent) + @keep_alive = keep_alive + @keep_alive_time = keep_alive_time + @cookie_jar = cookie_jar + @user_agent = user_agent + end + + def handle(ctx, params) + uri = params[:uri] + referer = params[:referer] + request = params[:request] + + if @keep_alive + request['Connection'] = 'keep-alive' + request['Keep-Alive'] = @keep_alive_time.to_s + else + request['Connection'] = 'close' + end + request['Accept-Encoding'] = 'gzip,identity' + request['Accept-Language'] = 'en-us,en;q=0.5' + host = "#{uri.host}#{[80, 443].include?(uri.port.to_i) ? '' : ':' + uri.port.to_s}" + request['Host'] = host + request['Accept-Charset'] = 'ISO-8859-1,utf-8;q=0.7,*;q=0.7' + + unless @cookie_jar.empty?(uri) + cookies = @cookie_jar.cookies(uri) + cookie = cookies.length > 0 ? cookies.join("; ") : nil + request.add_field('Cookie', cookie) + end + + # Add Referer header to request + if referer && referer.uri + request['Referer'] = referer.uri.to_s + end + + # Add User-Agent header to request + request['User-Agent'] = @user_agent if @user_agent + super + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/parameter_resolver.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/parameter_resolver.rb new file mode 100644 index 0000000..848aea4 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/parameter_resolver.rb @@ -0,0 +1,23 @@ +module WWW + class Mechanize + class Chain + class ParameterResolver + include WWW::Handler + + def handle(ctx, params) + parameters = params[:params] + uri = params[:uri] + if params[:verb] == :get + if parameters.length > 0 + uri.query ||= '' + uri.query << '&' if uri.query.length > 0 + uri.query << Util.build_query_string(parameters) + end + params[:params] = [] + end + super + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/post_connect_hook.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/post_connect_hook.rb new file mode 100644 index 0000000..e69de29 diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/pre_connect_hook.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/pre_connect_hook.rb new file mode 100644 index 0000000..1e55b3e --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/pre_connect_hook.rb @@ -0,0 +1,22 @@ +module WWW + class Mechanize + class Chain + class PreConnectHook + include WWW::Handler + + attr_accessor :hooks + def initialize + @hooks = [] + end + + def handle(ctx, params) + @hooks.each { |hook| hook.call(params) } + super + end + end + + class PostConnectHook < PreConnectHook + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/request_resolver.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/request_resolver.rb new file mode 100644 index 0000000..19a33a1 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/request_resolver.rb @@ -0,0 +1,32 @@ +module WWW + class Mechanize + class Chain + class RequestResolver + include WWW::Handler + + def handle(ctx, params) + uri = params[:uri] + if %w{ http https }.include?(uri.scheme.downcase) + klass = Net::HTTP.const_get(params[:verb].to_s.capitalize) + params[:request] ||= klass.new(uri.request_uri) + end + + if %w{ file }.include?(uri.scheme.downcase) + o = Struct.new(:uri).new(uri) + class << o + def add_field(*args); end + alias :[]= :add_field + def path + uri.path + end + def each_header; end + end + params[:request] ||= o + end + + super + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/response_body_parser.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/response_body_parser.rb new file mode 100644 index 0000000..8895937 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/response_body_parser.rb @@ -0,0 +1,40 @@ +module WWW + class Mechanize + class Chain + class ResponseBodyParser + include WWW::Handler + + def initialize(pluggable_parser, watch_for_set) + @pluggable_parser = pluggable_parser + @watch_for_set = watch_for_set + end + + def handle(ctx, params) + response = params[:response] + response_body = params[:response_body] + uri = params[:uri] + + content_type = nil + unless response['Content-Type'].nil? + data = response['Content-Type'].match(/^([^;]*)/) + content_type = data[1].downcase.split(',')[0] unless data.nil? + end + + # Find our pluggable parser + params[:page] = @pluggable_parser.parser(content_type).new( + uri, + response, + response_body, + response.code + ) { |parser| + parser.mech = params[:agent] if parser.respond_to? :mech= + if parser.respond_to?(:watch_for_set=) && @watch_for_set + parser.watch_for_set = @watch_for_set + end + } + super + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/response_header_handler.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/response_header_handler.rb new file mode 100644 index 0000000..904e62d --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/response_header_handler.rb @@ -0,0 +1,50 @@ +module WWW + class Mechanize + class Chain + class ResponseHeaderHandler + include WWW::Handler + + def initialize(cookie_jar, connection_cache) + @cookie_jar = cookie_jar + @connection_cache = connection_cache + end + + def handle(ctx, params) + response = params[:response] + uri = params[:uri] + page = params[:page] + cache_obj = (@connection_cache["#{uri.host}:#{uri.port}"] ||= { + :connection => nil, + :keep_alive_options => {}, + }) + + # If the server sends back keep alive options, save them + if keep_alive_info = response['keep-alive'] + keep_alive_info.split(/,\s*/).each do |option| + k, v = option.split(/=/) + cache_obj[:keep_alive_options] ||= {} + cache_obj[:keep_alive_options][k.intern] = v + end + end + + if page.is_a?(Page) && page.body =~ /Set-Cookie/ + page.search('//meta[@http-equiv="Set-Cookie"]').each do |meta| + Cookie::parse(uri, meta['content']) { |c| + Mechanize.log.debug("saved cookie: #{c}") if Mechanize.log + @cookie_jar.add(uri, c) + } + end + end + + (response.get_fields('Set-Cookie')||[]).each do |cookie| + Cookie::parse(uri, cookie) { |c| + Mechanize.log.debug("saved cookie: #{c}") if Mechanize.log + @cookie_jar.add(uri, c) + } + end + super + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/response_reader.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/response_reader.rb new file mode 100644 index 0000000..4b91479 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/response_reader.rb @@ -0,0 +1,41 @@ +module WWW + class Mechanize + class Chain + class ResponseReader + include WWW::Handler + + def initialize(response) + @response = response + end + + def handle(ctx, params) + params[:response] = @response + body = StringIO.new + total = 0 + @response.read_body { |part| + total += part.length + body.write(part) + Mechanize.log.debug("Read #{total} bytes") if Mechanize.log + } + body.rewind + + res_klass = Net::HTTPResponse::CODE_TO_OBJ[@response.code.to_s] + raise ResponseCodeError.new(@response) unless res_klass + + # Net::HTTP ignores EOFError if Content-length is given, so we emulate it here. + unless res_klass <= Net::HTTPRedirection + raise EOFError if (!params[:request].is_a?(Net::HTTP::Head)) && @response.content_length() && @response.content_length() != total + end + + @response.each_header { |k,v| + Mechanize.log.debug("response-header: #{ k } => #{ v }") + } if Mechanize.log + + params[:response_body] = body + params[:res_klass] = res_klass + super + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/ssl_resolver.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/ssl_resolver.rb new file mode 100644 index 0000000..19d9bb2 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/ssl_resolver.rb @@ -0,0 +1,36 @@ +module WWW + class Mechanize + class Chain + class SSLResolver + include WWW::Handler + + def initialize(ca_file, verify_callback, cert, key, pass) + @ca_file = ca_file + @verify_callback = verify_callback + @cert = cert + @key = key + @pass = pass + end + + def handle(ctx, params) + uri = params[:uri] + http_obj = params[:connection] + if uri.scheme == 'https' && ! http_obj.started? && ! http_obj.frozen? + http_obj.use_ssl = true + http_obj.verify_mode = OpenSSL::SSL::VERIFY_NONE + if @ca_file + http_obj.ca_file = @ca_file + http_obj.verify_mode = OpenSSL::SSL::VERIFY_PEER + http_obj.verify_callback = @verify_callback if @verify_callback + end + if @cert && @key + http_obj.cert = OpenSSL::X509::Certificate.new(::File.read(@cert)) + http_obj.key = OpenSSL::PKey::RSA.new(::File.read(@key), @pass) + end + end + super + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/uri_resolver.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/uri_resolver.rb new file mode 100644 index 0000000..1a0e8d2 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/chain/uri_resolver.rb @@ -0,0 +1,72 @@ +module WWW + class Mechanize + class Chain + class URIResolver + include WWW::Handler + + def initialize(scheme_handlers) + @scheme_handlers = scheme_handlers + end + + def handle(ctx, params) + raise ArgumentError.new('uri must be specified') unless params[:uri] + uri = params[:uri] + referer = params[:referer] + unless uri.is_a?(URI) + uri = uri.to_s.strip.gsub(/[^#{0.chr}-#{126.chr}]/) { |match| + sprintf('%%%X', match.unpack($KCODE == 'UTF8' ? 'U' : 'c')[0]) + } + + escaped_uri = Util.html_unescape( + uri.split(/(?:%[0-9A-Fa-f]{2})+|#/).zip( + uri.scan(/(?:%[0-9A-Fa-f]{2})+|#/) + ).map { |x,y| + "#{URI.escape(x)}#{y}" + }.join('') + ) + + begin + uri = URI.parse(escaped_uri) + rescue + uri = URI.parse(URI.escape(escaped_uri)) + end + + end + uri = @scheme_handlers[ + uri.relative? ? 'relative' : uri.scheme.downcase + ].call(uri, params[:referer]) + + if params[:referer] && params[:referer].uri + if uri.path.length == 0 && uri.relative? + uri.path = params[:referer].uri.path + end + end + + uri.path = '/' if uri.path.length == 0 + + if uri.relative? + raise 'need absolute URL' unless referer && referer.uri + base = nil + if referer.respond_to?(:bases) && referer.parser + base = referer.bases.last + end + + uri = ((base && base.uri && base.uri.absolute?) ? + base.uri : + referer.uri) + uri + uri = referer.uri + uri + # Strip initial "/.." bits from the path + uri.path.sub!(/^(\/\.\.)+(?=\/)/, '') + end + + unless ['http', 'https', 'file'].include?(uri.scheme.downcase) + raise "unsupported scheme: #{uri.scheme}" + end + params[:uri] = uri + + super + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/content_type_error.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/content_type_error.rb new file mode 100644 index 0000000..19fc5ae --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/content_type_error.rb @@ -0,0 +1,16 @@ +module WWW + class Mechanize + # =Synopsis + # This class contains an error for when a pluggable parser tries to + # parse a content type that it does not know how to handle. For example + # if WWW::Mechanize::Page were to try to parse a PDF, a ContentTypeError + # would be thrown. + class ContentTypeError < RuntimeError + attr_reader :content_type + + def initialize(content_type) + @content_type = content_type + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/cookie.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/cookie.rb new file mode 100644 index 0000000..a4f9a1f --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/cookie.rb @@ -0,0 +1,64 @@ +require 'time' +require 'webrick/cookie' + +module WWW + class Mechanize + # This class is used to represent an HTTP Cookie. + class Cookie < WEBrick::Cookie + def self.parse(uri, str, log = Mechanize.log) + return str.split(/,(?=[^;,]*=)|,$/).collect { |c| + cookie_elem = c.split(/;+/) + first_elem = cookie_elem.shift + first_elem.strip! + key, value = first_elem.split(/=/, 2) + cookie = new(key, WEBrick::HTTPUtils.dequote(value)) + cookie_elem.each{|pair| + pair.strip! + key, value = pair.split(/=/, 2) + if value + value = WEBrick::HTTPUtils.dequote(value.strip) + end + case key.downcase + when "domain" then cookie.domain = value.sub(/^\./, '') + when "path" then cookie.path = value + when 'expires' + begin + cookie.expires = Time::parse(value) + rescue + if log + log.warn("Couldn't parse expires: #{value}") + end + end + when "max-age" then + begin + cookie.max_age = Integer(value) + rescue + log.warn("Couldn't parse max age '#{value}'") if log + cookie.max_age = nil + end + when "comment" then cookie.comment = value + when "version" then + begin + cookie.version = Integer(value) + rescue + log.warn("Couldn't parse version '#{value}'") if log + cookie.version = nil + end + when "secure" then cookie.secure = true + end + } + + cookie.path ||= uri.path.to_s.sub(/[^\/]*$/, '') + cookie.secure ||= false + cookie.domain ||= uri.host + # Move this in to the cookie jar + yield cookie if block_given? + } + end + + def to_s + "#{@name}=#{@value}" + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/cookie_jar.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/cookie_jar.rb new file mode 100644 index 0000000..a48f4cc --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/cookie_jar.rb @@ -0,0 +1,191 @@ +require 'yaml' + +module WWW + class Mechanize + # This class is used to manage the Cookies that have been returned from + # any particular website. + class CookieJar + attr_reader :jar + + def initialize + @jar = {} + end + + # Add a cookie to the Jar. + def add(uri, cookie) + return unless uri.host =~ /#{CookieJar.strip_port(cookie.domain)}$/i + normal_domain = cookie.domain.downcase + unless @jar.has_key?(normal_domain) + @jar[normal_domain] = Hash.new + end + + @jar[normal_domain][cookie.name] = cookie + cleanup() + cookie + end + + # Fetch the cookies that should be used for the URI object passed in. + def cookies(url) + cleanup + cookies = [] + url.path = '/' if url.path.empty? + @jar.each_key do |domain| + if url.host =~ /#{CookieJar.strip_port(domain)}$/i + @jar[domain].each_key do |name| + if url.path =~ /^#{@jar[domain][name].path}/ + if @jar[domain][name].expires.nil? + cookies << @jar[domain][name] + elsif Time.now < @jar[domain][name].expires + cookies << @jar[domain][name] + end + end + end + end + end + + cookies + end + + def empty?(url) + cookies(url).length > 0 ? false : true + end + + def to_a + cookies = [] + @jar.each_key do |domain| + @jar[domain].each_key do |name| + cookies << @jar[domain][name] + end + end + cookies + end + + # Save the cookie jar to a file in the format specified. + # + # Available formats: + # :yaml <- YAML structure + # :cookiestxt <- Mozilla's cookies.txt format + def save_as(file, format = :yaml) + ::File.open(file, "w") { |f| + case format + when :yaml then + YAML::dump(@jar, f) + when :cookiestxt then + dump_cookiestxt(f) + else + raise "Unknown cookie jar file format" + end + } + end + + # Load cookie jar from a file in the format specified. + # + # Available formats: + # :yaml <- YAML structure. + # :cookiestxt <- Mozilla's cookies.txt format + def load(file, format = :yaml) + @jar = ::File.open(file) { |f| + case format + when :yaml then + YAML::load(f) + when :cookiestxt then + load_cookiestxt(f) + else + raise "Unknown cookie jar file format" + end + } + end + + # Clear the cookie jar + def clear! + @jar = {} + end + + + # Read cookies from Mozilla cookies.txt-style IO stream + def load_cookiestxt(io) + now = Time.now + fakeuri = Struct.new(:host) # add_cookie wants something resembling a URI. + + io.each_line do |line| + line.chomp! + line.gsub!(/#.+/, '') + fields = line.split("\t") + + next if fields.length != 7 + + expires_seconds = fields[4].to_i + begin + expires = Time.at(expires_seconds) + rescue + next + # Just in case we ever decide to support DateTime... + # expires = DateTime.new(1970,1,1) + ((expires_seconds + 1) / (60*60*24.0)) + end + next if expires < now + + c = WWW::Mechanize::Cookie.new(fields[5], fields[6]) + c.domain = fields[0] + # Field 1 indicates whether the cookie can be read by other machines at the same domain. + # This is computed by the cookie implementation, based on the domain value. + c.path = fields[2] # Path for which the cookie is relevant + c.secure = (fields[3] == "TRUE") # Requires a secure connection + c.expires = expires # Time the cookie expires. + c.version = 0 # Conforms to Netscape cookie spec. + + add(fakeuri.new(c.domain), c) + end + @jar + end + + # Write cookies to Mozilla cookies.txt-style IO stream + def dump_cookiestxt(io) + @jar.each_pair do |domain, cookies| + cookies.each_pair do |name, cookie| + fields = [] + fields[0] = cookie.domain + + if cookie.domain =~ /^\./ + fields[1] = "TRUE" + else + fields[1] = "FALSE" + end + + fields[2] = cookie.path + + if cookie.secure == true + fields[3] = "TRUE" + else + fields[3] = "FALSE" + end + + fields[4] = cookie.expires.to_i.to_s + + fields[5] = cookie.name + fields[6] = cookie.value + io.puts(fields.join("\t")) + end + end + end + + private + # Remove expired cookies + def cleanup + @jar.each_key do |domain| + @jar[domain].each_key do |name| + unless @jar[domain][name].expires.nil? + if Time.now > @jar[domain][name].expires + @jar[domain].delete(name) + end + end + end + end + end + + def self.strip_port(host) + host.gsub(/:[0-9]+$/,'') + end + + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/file.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/file.rb new file mode 100644 index 0000000..687e238 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/file.rb @@ -0,0 +1,73 @@ +module WWW + class Mechanize + # = Synopsis + # This is the default (and base) class for the Pluggable Parsers. If + # Mechanize cannot find an appropriate class to use for the content type, + # this class will be used. For example, if you download a JPG, Mechanize + # will not know how to parse it, so this class will be instantiated. + # + # This is a good class to use as the base class for building your own + # pluggable parsers. + # + # == Example + # require 'rubygems' + # require 'mechanize' + # + # agent = WWW::Mechanize.new + # agent.get('http://example.com/foo.jpg').class #=> WWW::Mechanize::File + # + class File + attr_accessor :uri, :response, :body, :code, :filename + alias :header :response + + alias :content :body + + def initialize(uri=nil, response=nil, body=nil, code=nil) + @uri, @body, @code = uri, body, code + @response = Headers.new + + # Copy the headers in to a hash to prevent memory leaks + if response + response.each { |k,v| + @response[k] = v + } + end + + @filename = 'index.html' + + # Set the filename + if disposition = @response['content-disposition'] + disposition.split(/;\s*/).each do |pair| + k,v = pair.split(/=/, 2) + @filename = v if k.downcase == 'filename' + end + else + if @uri + @filename = @uri.path.split(/\//).last || 'index.html' + @filename << ".html" unless @filename =~ /\./ + end + end + + yield self if block_given? + end + + # Use this method to save the content of this object to filename + def save_as(filename = nil) + if filename.nil? + filename = @filename + number = 1 + while(::File.exists?(filename)) + filename = "#{@filename}.#{number}" + number += 1 + end + end + + ::File::open(filename, "wb") { |f| + f.write body + } + end + + alias :save :save_as + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/file_response.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/file_response.rb new file mode 100644 index 0000000..66b02e8 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/file_response.rb @@ -0,0 +1,62 @@ +module WWW + class Mechanize + ### + # Fake response for dealing with file:/// requests + class FileResponse + def initialize(file_path) + @file_path = file_path + end + + def read_body + if ::File.exists?(@file_path) + if directory? + yield dir_body + else + yield ::File.read(@file_path) + end + else + yield '' + end + end + + def code + ::File.exists?(@file_path) ? 200 : 400 + end + + def content_length + return dir_body.length if directory? + ::File.exists?(@file_path) ? ::File.stat(@file_path).size : 0 + end + + def each_header; end + + def [](key) + return nil unless key.downcase == 'content-type' + return 'text/html' if directory? + return 'text/html' if ['.html', '.xhtml'].any? { |extn| + @file_path =~ /#{extn}$/ + } + nil + end + + def each + end + + def get_fields(key) + [] + end + + private + def dir_body + '' + + Dir[::File.join(@file_path, '*')].map { |f| + "#{::File.basename(f)}" + }.join("\n") + '' + end + + def directory? + ::File.directory?(@file_path) + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/file_saver.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/file_saver.rb new file mode 100644 index 0000000..5f18a68 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/file_saver.rb @@ -0,0 +1,39 @@ +module WWW + class Mechanize + # = Synopsis + # This is a pluggable parser that automatically saves every file + # it encounters. It saves the files as a tree, reflecting the + # host and file path. + # + # == Example to save all PDF's + # require 'rubygems' + # require 'mechanize' + # + # agent = WWW::Mechanize.new + # agent.pluggable_parser.pdf = WWW::Mechanize::FileSaver + # agent.get('http://example.com/foo.pdf') + # + class FileSaver < File + attr_reader :filename + + def initialize(uri=nil, response=nil, body=nil, code=nil) + super(uri, response, body, code) + path = uri.path.empty? ? 'index.html' : uri.path.gsub(/^[\/]*/, '') + path += 'index.html' if path =~ /\/$/ + + split_path = path.split(/\//) + filename = split_path.length > 0 ? split_path.pop : 'index.html' + joined_path = split_path.join(::File::SEPARATOR) + path = if joined_path.empty? + uri.host + else + "#{uri.host}#{::File::SEPARATOR}#{joined_path}" + end + + @filename = "#{path}#{::File::SEPARATOR}#{filename}" + FileUtils.mkdir_p(path) + save_as(@filename) + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form.rb new file mode 100644 index 0000000..075e5b7 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form.rb @@ -0,0 +1,334 @@ +require 'www/mechanize/form/field' +require 'www/mechanize/form/file_upload' +require 'www/mechanize/form/button' +require 'www/mechanize/form/image_button' +require 'www/mechanize/form/radio_button' +require 'www/mechanize/form/check_box' +require 'www/mechanize/form/multi_select_list' +require 'www/mechanize/form/select_list' +require 'www/mechanize/form/option' + +module WWW + class Mechanize + # =Synopsis + # This class encapsulates a form parsed out of an HTML page. Each type + # of input fields available in a form can be accessed through this object. + # See GlobalForm for more methods. + # + # ==Example + # Find a form and print out its fields + # form = page.forms.first # => WWW::Mechanize::Form + # form.fields.each { |f| puts f.name } + # Set the input field 'name' to "Aaron" + # form['name'] = 'Aaron' + # puts form['name'] + class Form + attr_accessor :method, :action, :name + + attr_reader :fields, :buttons, :file_uploads, :radiobuttons, :checkboxes + attr_accessor :enctype + + alias :elements :fields + + attr_reader :form_node + attr_reader :page + + def initialize(node, mech=nil, page=nil) + @enctype = node['enctype'] || 'application/x-www-form-urlencoded' + @form_node = node + @action = Util.html_unescape(node['action']) + @method = (node['method'] || 'GET').upcase + @name = node['name'] + @clicked_buttons = [] + @page = page + @mech = mech + + parse + end + + # Returns whether or not the form contains a field with +field_name+ + def has_field?(field_name) + ! fields.find { |f| f.name.eql? field_name }.nil? + end + + alias :has_key? :has_field? + + def has_value?(value) + ! fields.find { |f| f.value.eql? value }.nil? + end + + def keys; fields.map { |f| f.name }; end + + def values; fields.map { |f| f.value }; end + + # Add a field with +field_name+ and +value+ + def add_field!(field_name, value = nil) + fields << Field.new(field_name, value) + end + + # This method sets multiple fields on the form. It takes a list of field + # name, value pairs. If there is more than one field found with the + # same name, this method will set the first one found. If you want to + # set the value of a duplicate field, use a value which is a Hash with + # the key as the index in to the form. The index + # is zero based. For example, to set the second field named 'foo', you + # could do the following: + # form.set_fields( :foo => { 1 => 'bar' } ) + def set_fields(fields = {}) + fields.each do |k,v| + case v + when Hash + v.each do |index, value| + self.fields_with(:name => k.to_s).[](index).value = value + end + else + value = nil + index = 0 + [v].flatten.each do |val| + index = val.to_i unless value.nil? + value = val if value.nil? + end + self.fields_with(:name => k.to_s).[](index).value = value + end + end + end + + # Fetch the value of the first input field with the name passed in + # ==Example + # Fetch the value set in the input field 'name' + # puts form['name'] + def [](field_name) + f = field(field_name) + f && f.value + end + + # Set the value of the first input field with the name passed in + # ==Example + # Set the value in the input field 'name' to "Aaron" + # form['name'] = 'Aaron' + def []=(field_name, value) + f = field(field_name) + if f.nil? + add_field!(field_name, value) + else + f.value = value + end + end + + # Treat form fields like accessors. + def method_missing(id,*args) + method = id.to_s.gsub(/=$/, '') + if field(method) + return field(method).value if args.empty? + return field(method).value = args[0] + end + super + end + + # Submit this form with the button passed in + def submit(button=nil) + @mech.submit(self, button) + end + + # Submit form using +button+. Defaults + # to the first button. + def click_button(button = buttons.first) + submit(button) + end + + # This method builds an array of arrays that represent the query + # parameters to be used with this form. The return value can then + # be used to create a query string for this form. + def build_query(buttons = []) + query = [] + + fields().each do |f| + query.push(*f.query_value) + end + + checkboxes().each do |f| + query.push(*f.query_value) if f.checked + end + + radio_groups = {} + radiobuttons().each do |f| + radio_groups[f.name] ||= [] + radio_groups[f.name] << f + end + + # take one radio button from each group + radio_groups.each_value do |g| + checked = g.select {|f| f.checked} + + if checked.size == 1 + f = checked.first + query.push(*f.query_value) + elsif checked.size > 1 + raise "multiple radiobuttons are checked in the same group!" + end + end + + @clicked_buttons.each { |b| + query.push(*b.query_value) + } + + query + end + + # This method adds a button to the query. If the form needs to be + # submitted with multiple buttons, pass each button to this method. + def add_button_to_query(button) + @clicked_buttons << button + end + + # This method calculates the request data to be sent back to the server + # for this form, depending on if this is a regular post, get, or a + # multi-part post, + def request_data + query_params = build_query() + case @enctype.downcase + when /^multipart\/form-data/ + boundary = rand_string(20) + @enctype = "multipart/form-data; boundary=#{boundary}" + params = [] + query_params.each { |k,v| params << param_to_multipart(k, v) } + @file_uploads.each { |f| params << file_to_multipart(f) } + params.collect { |p| "--#{boundary}\r\n#{p}" }.join('') + + "--#{boundary}--\r\n" + else + WWW::Mechanize::Util.build_query_string(query_params) + end + end + + # Removes all fields with name +field_name+. + def delete_field!(field_name) + @fields.delete_if{ |f| f.name == field_name} + end + + { :field => :fields, + :button => :buttons, + :file_upload => :file_uploads, + :radiobutton => :radiobuttons, + :checkbox => :checkboxes, + }.each do |singular,plural| + eval(<<-eomethod) + def #{plural}_with criteria = {} + criteria = {:name => criteria} if String === criteria + f = #{plural}.find_all do |thing| + criteria.all? { |k,v| v === thing.send(k) } + end + yield f if block_given? + f + end + + def #{singular}_with criteria = {} + f = #{plural}_with(criteria).first + yield f if block_given? + f + end + alias :#{singular} :#{singular}_with + eomethod + end + + private + def parse + @fields = [] + @buttons = [] + @file_uploads = [] + @radiobuttons = [] + @checkboxes = [] + + # Find all input tags + form_node.search('input').each do |node| + type = (node['type'] || 'text').downcase + name = node['name'] + next if name.nil? && !(type == 'submit' || type =='button') + case type + when 'radio' + @radiobuttons << RadioButton.new(node['name'], node['value'], !!node['checked'], self) + when 'checkbox' + @checkboxes << CheckBox.new(node['name'], node['value'], !!node['checked'], self) + when 'file' + @file_uploads << FileUpload.new(node['name'], nil) + when 'submit' + @buttons << Button.new(node['name'], node['value']) + when 'button' + @buttons << Button.new(node['name'], node['value']) + when 'image' + @buttons << ImageButton.new(node['name'], node['value']) + else + @fields << Field.new(node['name'], node['value'] || '') + end + end + + # Find all textarea tags + form_node.search('textarea').each do |node| + next if node['name'].nil? + @fields << Field.new(node['name'], node.inner_text) + end + + # Find all select tags + form_node.search('select').each do |node| + next if node['name'].nil? + if node.has_attribute? 'multiple' + @fields << MultiSelectList.new(node['name'], node) + else + @fields << SelectList.new(node['name'], node) + end + end + + # Find all submit button tags + # FIXME: what can I do with the reset buttons? + form_node.search('button').each do |node| + type = (node['type'] || 'submit').downcase + next if type == 'reset' + @buttons << Button.new(node['name'], node['value']) + end + end + + def rand_string(len = 10) + chars = ("a".."z").to_a + ("A".."Z").to_a + string = "" + 1.upto(len) { |i| string << chars[rand(chars.size-1)] } + string + end + + def mime_value_quote(str) + str.gsub(/(["\r\\])/){|s| '\\' + s} + end + + def param_to_multipart(name, value) + return "Content-Disposition: form-data; name=\"" + + "#{mime_value_quote(name)}\"\r\n" + + "\r\n#{value}\r\n" + end + + def file_to_multipart(file) + file_name = file.file_name ? ::File.basename(file.file_name) : '' + body = "Content-Disposition: form-data; name=\"" + + "#{mime_value_quote(file.name)}\"; " + + "filename=\"#{mime_value_quote(file_name)}\"\r\n" + + "Content-Transfer-Encoding: binary\r\n" + + if file.file_data.nil? and ! file.file_name.nil? + file.file_data = ::File.open(file.file_name, "rb") { |f| f.read } + file.mime_type = WEBrick::HTTPUtils.mime_type(file.file_name, + WEBrick::HTTPUtils::DefaultMimeTypes) + end + + if file.mime_type != nil + body << "Content-Type: #{file.mime_type}\r\n" + end + + body << + if file.file_data.respond_to? :read + "\r\n#{file.file_data.read}\r\n" + else + "\r\n#{file.file_data}\r\n" + end + + body + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/button.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/button.rb new file mode 100644 index 0000000..738e132 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/button.rb @@ -0,0 +1,8 @@ +module WWW + class Mechanize + class Form + # This class represents a Submit button in a form. + class Button < Field; end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/check_box.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/check_box.rb new file mode 100644 index 0000000..64553cd --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/check_box.rb @@ -0,0 +1,13 @@ +module WWW + class Mechanize + class Form + # This class represents a check box found in a Form. To activate the + # CheckBox in the Form, set the checked method to true. + class CheckBox < RadioButton + def query_value + [[@name, @value || "on"]] + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/field.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/field.rb new file mode 100644 index 0000000..5f8cf01 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/field.rb @@ -0,0 +1,28 @@ +module WWW + class Mechanize + class Form + # This class represents a field in a form. It handles the following input + # tags found in a form: + # text, password, hidden, int, textarea + # + # To set the value of a field, just use the value method: + # field.value = "foo" + class Field + attr_accessor :name, :value + + def initialize(name, value) + @name = Util.html_unescape(name) + @value = if value.is_a? String + Util.html_unescape(value) + else + value + end + end + + def query_value + [[@name, @value || '']] + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/file_upload.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/file_upload.rb new file mode 100644 index 0000000..8b0965d --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/file_upload.rb @@ -0,0 +1,24 @@ +module WWW + class Mechanize + class Form + # This class represents a file upload field found in a form. To use this + # class, set WWW::FileUpload#file_data= to the data of the file you want + # to upload and WWW::FileUpload#mime_type= to the appropriate mime type + # of the file. + # See the example in EXAMPLES[link://files/EXAMPLES_txt.html] + class FileUpload < Field + attr_accessor :file_name # File name + attr_accessor :mime_type # Mime Type (Optional) + + alias :file_data :value + alias :file_data= :value= + + def initialize(name, file_name) + @file_name = Util.html_unescape(file_name) + @file_data = nil + super(name, @file_data) + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/image_button.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/image_button.rb new file mode 100644 index 0000000..143b969 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/image_button.rb @@ -0,0 +1,23 @@ +module WWW + class Mechanize + class Form + # This class represents an image button in a form. Use the x and y methods + # to set the x and y positions for where the mouse "clicked". + class ImageButton < Button + attr_accessor :x, :y + + def initialize(name, value) + @x = nil + @y = nil + super(name, value) + end + + def query_value + super << + [@name + ".x", (@x || 0).to_s] << + [@name + ".y", (@y || 0).to_s] + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/multi_select_list.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/multi_select_list.rb new file mode 100644 index 0000000..2463204 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/multi_select_list.rb @@ -0,0 +1,69 @@ +module WWW + class Mechanize + class Form + # This class represents a select list where multiple values can be selected. + # MultiSelectList#value= accepts an array, and those values are used as + # values for the select list. For example, to select multiple values, + # simply do this: + # list.value = ['one', 'two'] + # Single values are still supported, so these two are the same: + # list.value = ['one'] + # list.value = 'one' + class MultiSelectList < Field + attr_accessor :options + + def initialize(name, node) + value = [] + @options = [] + + # parse + node.search('option').each do |n| + option = Option.new(n, self) + @options << option + end + super(name, value) + end + + def query_value + value ? value.collect { |v| [name, v] } : '' + end + + # Select no options + def select_none + @value = [] + options.each { |o| o.untick } + end + + # Select all options + def select_all + @value = [] + options.each { |o| o.tick } + end + + # Get a list of all selected options + def selected_options + @options.find_all { |o| o.selected? } + end + + def value=(values) + select_none + [values].flatten.each do |value| + option = options.find { |o| o.value == value } + if option.nil? + @value.push(value) + else + option.select + end + end + end + + def value + value = [] + value.push(*@value) + value.push(*selected_options.collect { |o| o.value }) + value + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/option.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/option.rb new file mode 100644 index 0000000..cb9fec7 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/option.rb @@ -0,0 +1,51 @@ +module WWW + class Mechanize + class Form + # This class contains option an option found within SelectList. A + # SelectList can have many Option classes associated with it. An option + # can be selected by calling Option#tick, or Option#click. For example, + # select the first option in a list: + # select_list.first.tick + class Option + attr_reader :value, :selected, :text, :select_list + + alias :to_s :value + alias :selected? :selected + + def initialize(node, select_list) + @text = node.inner_text + @value = Util.html_unescape(node['value'] || node.inner_text) + @selected = node.has_attribute? 'selected' + @select_list = select_list # The select list this option belongs to + end + + # Select this option + def select + unselect_peers + @selected = true + end + + # Unselect this option + def unselect + @selected = false + end + + alias :tick :select + alias :untick :unselect + + # Toggle the selection value of this option + def click + unselect_peers + @selected = !@selected + end + + private + def unselect_peers + if @select_list.instance_of? SelectList + @select_list.select_none + end + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/radio_button.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/radio_button.rb new file mode 100644 index 0000000..c14ff61 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/radio_button.rb @@ -0,0 +1,38 @@ +module WWW + class Mechanize + class Form + # This class represents a radio button found in a Form. To activate the + # RadioButton in the Form, set the checked method to true. + class RadioButton < Field + attr_accessor :checked + + def initialize(name, value, checked, form) + @checked = checked + @form = form + super(name, value) + end + + def check + uncheck_peers + @checked = true + end + + def uncheck + @checked = false + end + + def click + @checked = !@checked + end + + private + def uncheck_peers + @form.radiobuttons_with(:name => name).each do |b| + next if b.value == value + b.uncheck + end + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/select_list.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/select_list.rb new file mode 100644 index 0000000..41e31a7 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/form/select_list.rb @@ -0,0 +1,45 @@ +module WWW + class Mechanize + class Form + # This class represents a select list or drop down box in a Form. Set the + # value for the list by calling SelectList#value=. SelectList contains a + # list of Option that were found. After finding the correct option, set + # the select lists value to the option value: + # selectlist.value = selectlist.options.first.value + # Options can also be selected by "clicking" or selecting them. See Option + class SelectList < MultiSelectList + def initialize(name, node) + super(name, node) + if selected_options.length > 1 + selected_options.reverse[1..selected_options.length].each do |o| + o.unselect + end + end + end + + def value + value = super + if value.length > 0 + value.last + elsif @options.length > 0 + @options.first.value + else + nil + end + end + + def value=(new) + if new != new.to_s and new.respond_to? :first + super([new.first]) + else + super([new.to_s]) + end + end + + def query_value + value ? [[name, value]] : '' + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/headers.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/headers.rb new file mode 100644 index 0000000..ca5771b --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/headers.rb @@ -0,0 +1,12 @@ +module WWW + class Mechanize + class Headers < Hash + def [](key) + super(key.downcase) + end + def []=(key, value) + super(key.downcase, value) + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/history.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/history.rb new file mode 100644 index 0000000..d544e1c --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/history.rb @@ -0,0 +1,67 @@ +module WWW + class Mechanize + ## + # This class manages history for your mechanize object. + class History < Array + attr_accessor :max_size + + def initialize(max_size = nil) + @max_size = max_size + @history_index = {} + end + + def initialize_copy(orig) + super + @history_index = orig.instance_variable_get(:@history_index).dup + end + + def push(page, uri = nil) + super(page) + @history_index[(uri ? uri : page.uri).to_s] = page + if @max_size && self.length > @max_size + while self.length > @max_size + self.shift + end + end + self + end + alias :<< :push + + def visited?(url) + ! visited_page(url).nil? + end + + def visited_page(url) + @history_index[(url.respond_to?(:uri) ? url.uri : url).to_s] + end + + def clear + @history_index.clear + super + end + + def shift + return nil if length == 0 + page = self[0] + self[0] = nil + super + remove_from_index(page) + page + end + + def pop + return nil if length == 0 + page = super + remove_from_index(page) + page + end + + private + def remove_from_index(page) + @history_index.each do |k,v| + @history_index.delete(k) if v == page + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/inspect.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/inspect.rb new file mode 100644 index 0000000..da5bd2c --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/inspect.rb @@ -0,0 +1,90 @@ +require 'pp' + +module WWW + # :stopdoc: + class Mechanize + def pretty_print(q) + q.object_group(self) { + q.breakable + q.pp cookie_jar + q.breakable + q.pp current_page + } + end + + class Page + def pretty_print(q) + q.object_group(self) { + q.breakable + q.group(1, '{url', '}') {q.breakable; q.pp uri } + q.breakable + q.group(1, '{meta', '}') { + meta.each { |link| q.breakable; q.pp link } + } + q.breakable + q.group(1, '{title', '}') { q.breakable; q.pp title } + q.breakable + q.group(1, '{iframes', '}') { + iframes.each { |link| q.breakable; q.pp link } + } + q.breakable + q.group(1, '{frames', '}') { + frames.each { |link| q.breakable; q.pp link } + } + q.breakable + q.group(1, '{links', '}') { + links.each { |link| q.breakable; q.pp link } + } + q.breakable + q.group(1, '{forms', '}') { + forms.each { |form| q.breakable; q.pp form } + } + } + end + + class Link + def pretty_print(q) + q.object_group(self) { + q.breakable; q.pp text + q.breakable; q.pp href + } + end + end + end + + class Form + def pretty_print(q) + q.object_group(self) { + q.breakable; q.group(1, '{name', '}') { q.breakable; q.pp name } + q.breakable; q.group(1, '{method', '}') { q.breakable; q.pp method } + q.breakable; q.group(1, '{action', '}') { q.breakable; q.pp action } + q.breakable; q.group(1, '{fields', '}') { + fields.each do |field| + q.breakable + q.pp field + end + } + q.breakable; q.group(1, '{radiobuttons', '}') { + radiobuttons.each { |b| q.breakable; q.pp b } + } + q.breakable; q.group(1, '{checkboxes', '}') { + checkboxes.each { |b| q.breakable; q.pp b } + } + q.breakable; q.group(1, '{file_uploads', '}') { + file_uploads.each { |b| q.breakable; q.pp b } + } + q.breakable; q.group(1, '{buttons', '}') { + buttons.each { |b| q.breakable; q.pp b } + } + } + end + + class RadioButton + def pretty_print_instance_variables + [:@checked, :@name, :@value] + end + end + end + end + # :startdoc: +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/monkey_patch.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/monkey_patch.rb new file mode 100644 index 0000000..249e56f --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/monkey_patch.rb @@ -0,0 +1,37 @@ +module Net + class HTTP + alias :old_keep_alive? :keep_alive? + def keep_alive?(req, res) + return false if /close/i =~ req['connection'].to_s + return false if @seems_1_0_server + return false if /close/i =~ res['connection'].to_s + return true if /keep-alive/i =~ res['connection'].to_s + return false if /close/i =~ res['proxy-connection'].to_s + return true if /keep-alive/i =~ res['proxy-connection'].to_s + (@curr_http_version == '1.1') + end + end +end + +# Monkey patch for ruby 1.8.4 +unless RUBY_VERSION > "1.8.4" +module Net # :nodoc: + class HTTPResponse # :nodoc: + CODE_TO_OBJ['500'] = HTTPInternalServerError + end +end +else +module WWW + class Mechanize + class Form + alias :inspect :pretty_inspect + end + class Page + alias :inspect :pretty_inspect + class Link + alias :inspect :pretty_inspect + end + end + end +end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page.rb new file mode 100644 index 0000000..b3e0118 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page.rb @@ -0,0 +1,133 @@ +require 'www/mechanize/page/link' +require 'www/mechanize/page/meta' +require 'www/mechanize/page/base' +require 'www/mechanize/page/frame' +require 'www/mechanize/headers' + +module WWW + class Mechanize + # = Synopsis + # This class encapsulates an HTML page. If Mechanize finds a content + # type of 'text/html', this class will be instantiated and returned. + # + # == Example + # require 'rubygems' + # require 'mechanize' + # + # agent = WWW::Mechanize.new + # agent.get('http://google.com/').class #=> WWW::Mechanize::Page + # + class Page < WWW::Mechanize::File + extend Forwardable + + attr_accessor :mech + + def initialize(uri=nil, response=nil, body=nil, code=nil, mech=nil) + super(uri, response, body, code) + @mech ||= mech + + raise Mechanize::ContentTypeError.new(response['content-type']) unless + response['content-type'] =~ /^(text\/html)|(application\/xhtml\+xml)/ + + @parser = @links = @forms = @meta = @bases = @frames = @iframes = nil + end + + def title + @title ||= if parser && search('title').inner_text.length > 0 + search('title').inner_text + end + end + + def parser + return @parser if @parser + + if body && response + html_body = body.length > 0 ? body : '' + @parser = Mechanize.html_parser.parse(html_body) + end + + @parser + end + alias :root :parser + + # Get the content type + def content_type + response['content-type'] + end + + # Search through the page like HPricot + def_delegator :parser, :search, :search + def_delegator :parser, :/, :/ + def_delegator :parser, :at, :at + + # Find a form matching +criteria+. + # Example: + # page.form_with(:action => '/post/login.php') do |f| + # ... + # end + [:form, :link, :base, :frame, :iframe].each do |type| + eval(<<-eomethod) + def #{type}s_with(criteria) + criteria = {:name => criteria} if String === criteria + f = #{type}s.find_all do |thing| + criteria.all? { |k,v| v === thing.send(k) } + end + yield f if block_given? + f + end + + def #{type}_with(criteria) + f = #{type}s_with(criteria).first + yield f if block_given? + f + end + alias :#{type} :#{type}_with + eomethod + end + + def links + @links ||= %w{ a area }.map do |tag| + search(tag).map do |node| + Link.new(node, @mech, self) + end + end.flatten + end + + def forms + @forms ||= search('form').map do |html_form| + form = Form.new(html_form, @mech, self) + form.action ||= @uri.to_s + form + end + end + + def meta + @meta ||= search('meta').map do |node| + next unless node['http-equiv'] && node['content'] + (equiv, content) = node['http-equiv'], node['content'] + if equiv && equiv.downcase == 'refresh' + if content && content =~ /^\d+\s*;\s*url\s*=\s*'?([^\s']+)/i + node['href'] = $1 + Meta.new(node, @mech, self) + end + end + end.compact + end + + def bases + @bases ||= + search('base').map { |node| Base.new(node, @mech, self) } + end + + def frames + @frames ||= + search('frame').map { |node| Frame.new(node, @mech, self) } + end + + def iframes + @iframes ||= + search('iframe').map { |node| Frame.new(node, @mech, self) } + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/base.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/base.rb new file mode 100644 index 0000000..f86ead9 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/base.rb @@ -0,0 +1,10 @@ +module WWW + class Mechanize + class Page < WWW::Mechanize::File + # This class encapsulates a Base tag. Mechanize treats base tags just + # like 'a' tags. Base objects will contain links, but most likely will + # have no text. + class Base < Link; end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/frame.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/frame.rb new file mode 100644 index 0000000..c8d8d05 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/frame.rb @@ -0,0 +1,22 @@ +module WWW + class Mechanize + class Page < WWW::Mechanize::File + # This class encapsulates a 'frame' tag. Frame objects can be treated + # just like Link objects. They contain src, the link they refer to, + # name, the name of the frame. 'src' and 'name' are aliased to 'href' + # and 'text' respectively so that a Frame object can be treated just + # like a Link. + class Frame < Link + alias :src :href + alias :name :text + + def initialize(node, mech, referer) + super(node, mech, referer) + @node = node + @text = node['name'] + @href = node['src'] + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/link.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/link.rb new file mode 100644 index 0000000..0a664e1 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/link.rb @@ -0,0 +1,50 @@ +module WWW + class Mechanize + class Page < WWW::Mechanize::File + # This class encapsulates links. It contains the text and the URI for + # 'a' tags parsed out of an HTML page. If the link contains an image, + # the alt text will be used for that image. + # + # For example, the text for the following links with both be 'Hello World': + # + # Hello World + # Hello World + class Link + attr_reader :node + attr_reader :href + attr_reader :text + attr_reader :attributes + attr_reader :page + alias :to_s :text + alias :referer :page + + def initialize(node, mech, page) + @node = node + @href = node['href'] + @text = node.inner_text + @page = page + @mech = mech + @attributes = node + + # If there is no text, try to find an image and use it's alt text + if (@text.nil? || @text.length == 0) && node.search('img').length > 0 + @text = '' + node.search('img').each do |e| + @text << ( e['alt'] || '') + end + end + + end + + def uri + URI.parse(@href) + end + + # Click on this link + def click + @mech.click self + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/meta.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/meta.rb new file mode 100644 index 0000000..059bfc1 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/page/meta.rb @@ -0,0 +1,10 @@ +module WWW + class Mechanize + class Page < WWW::Mechanize::File + # This class encapsulates a Meta tag. Mechanize treats meta tags just + # like 'a' tags. Meta objects will contain links, but most likely will + # have no text. + class Meta < Link; end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/pluggable_parsers.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/pluggable_parsers.rb new file mode 100644 index 0000000..755c119 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/pluggable_parsers.rb @@ -0,0 +1,100 @@ +require 'www/mechanize/file' +require 'www/mechanize/file_saver' +require 'www/mechanize/page' + +module WWW + class Mechanize + # = Synopsis + # This class is used to register and maintain pluggable parsers for + # Mechanize to use. + # + # A Pluggable Parser is a parser that Mechanize uses for any particular + # content type. Mechanize will ask PluggableParser for the class it + # should initialize given any content type. This class allows users to + # register their own pluggable parsers, or modify existing pluggable + # parsers. + # + # PluggableParser returns a WWW::Mechanize::File object for content types + # that it does not know how to handle. WWW::Mechanize::File provides + # basic functionality for any content type, so it is a good class to + # extend when building your own parsers. + # == Example + # To create your own parser, just create a class that takes four + # parameters in the constructor. Here is an example of registering + # a pluggable parser that handles CSV files: + # class CSVParser < WWW::Mechanize::File + # attr_reader :csv + # def initialize(uri=nil, response=nil, body=nil, code=nil) + # super(uri, response, body, code) + # @csv = CSV.parse(body) + # end + # end + # agent = WWW::Mechanize.new + # agent.pluggable_parser.csv = CSVParser + # agent.get('http://example.com/test.csv') # => CSVParser + # Now any page that returns the content type of 'text/csv' will initialize + # a CSVParser and return that object to the caller. + # + # To register a pluggable parser for a content type that pluggable parser + # does not know about, just use the hash syntax: + # agent.pluggable_parser['text/something'] = SomeClass + # + # To set the default parser, just use the 'defaut' method: + # agent.pluggable_parser.default = SomeClass + # Now all unknown content types will be instances of SomeClass. + class PluggableParser + CONTENT_TYPES = { + :html => 'text/html', + :xhtml => 'application/xhtml+xml', + :pdf => 'application/pdf', + :csv => 'text/csv', + :xml => 'text/xml', + } + + attr_accessor :default + + def initialize + @parsers = { CONTENT_TYPES[:html] => Page, + CONTENT_TYPES[:xhtml] => Page } + @default = File + end + + def parser(content_type) + content_type.nil? ? default : @parsers[content_type] || default + end + + def register_parser(content_type, klass) + @parsers[content_type] = klass + end + + def html=(klass) + register_parser(CONTENT_TYPES[:html], klass) + register_parser(CONTENT_TYPES[:xhtml], klass) + end + + def xhtml=(klass) + register_parser(CONTENT_TYPES[:xhtml], klass) + end + + def pdf=(klass) + register_parser(CONTENT_TYPES[:pdf], klass) + end + + def csv=(klass) + register_parser(CONTENT_TYPES[:csv], klass) + end + + def xml=(klass) + register_parser(CONTENT_TYPES[:xml], klass) + end + + def [](content_type) + @parsers[content_type] + end + + def []=(content_type, klass) + @parsers[content_type] = klass + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/redirect_limit_reached_error.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/redirect_limit_reached_error.rb new file mode 100644 index 0000000..aff3e1a --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/redirect_limit_reached_error.rb @@ -0,0 +1,18 @@ +module WWW + class Mechanize + # Thrown when too many redirects are sent + class RedirectLimitReachedError < RuntimeError + attr_reader :page, :response_code, :redirects + def initialize(page, redirects) + @page = page + @redirects = redirects + @response_code = page.code + end + + def to_s + "Maximum redirect limit (#{redirects}) reached" + end + alias :inspect :to_s + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/redirect_not_get_or_head_error.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/redirect_not_get_or_head_error.rb new file mode 100644 index 0000000..3dadb99 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/redirect_not_get_or_head_error.rb @@ -0,0 +1,20 @@ +module WWW + class Mechanize + # Thrown when a POST, PUT, or DELETE request results in a redirect + # see RFC 2616 10.3.2, 10.3.3 http://www.ietf.org/rfc/rfc2616.txt + class RedirectNotGetOrHeadError < RuntimeError + attr_reader :page, :response_code, :verb, :uri + def initialize(page, verb) + @page = page + @verb = verb + @uri = page.uri + @response_code = page.code + end + + def to_s + "#{@response_code} redirect received after a #{@verb} request" + end + alias :inspect :to_s + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/response_code_error.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/response_code_error.rb new file mode 100644 index 0000000..0794da1 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/response_code_error.rb @@ -0,0 +1,25 @@ +module WWW + class Mechanize + # =Synopsis + # This error is thrown when Mechanize encounters a response code it does + # not know how to handle. Currently, this exception will be thrown + # if Mechanize encounters response codes other than 200, 301, or 302. + # Any other response code is up to the user to handle. + class ResponseCodeError < RuntimeError + attr_reader :response_code + attr_reader :page + + def initialize(page) + @page = page + @response_code = page.code + end + + def to_s + "#{response_code} => #{Net::HTTPResponse::CODE_TO_OBJ[response_code]}" + end + + def inspect; to_s; end + end + end +end + diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/unsupported_scheme_error.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/unsupported_scheme_error.rb new file mode 100644 index 0000000..5d433a1 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/unsupported_scheme_error.rb @@ -0,0 +1,10 @@ +module WWW + class Mechanize + class UnsupportedSchemeError < RuntimeError + attr_accessor :scheme + def initialize(scheme) + @scheme = scheme + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/lib/www/mechanize/util.rb b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/util.rb new file mode 100644 index 0000000..087e344 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/lib/www/mechanize/util.rb @@ -0,0 +1,29 @@ +module WWW + class Mechanize + class Util + class << self + def build_query_string(parameters) + parameters.map { |k,v| + k && + [WEBrick::HTTPUtils.escape_form(k.to_s), + WEBrick::HTTPUtils.escape_form(v.to_s)].join("=") + }.compact.join('&') + end + + def html_unescape(s) + return s unless s + s.gsub(/&(\w+|#[0-9]+);/) { |match| + number = case match + when /&(\w+);/ + Mechanize.html_parser::NamedCharacters[$1] + when /&#([0-9]+);/ + $1.to_i + end + + number ? ([number].pack('U') rescue match) : match + } + end + end + end + end +end diff --git a/vendor/gems/mechanize-0.9.0/mechanize.gemspec b/vendor/gems/mechanize-0.9.0/mechanize.gemspec new file mode 100644 index 0000000..b4b5294 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/mechanize.gemspec @@ -0,0 +1,38 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{mechanize} + s.version = "0.8.5.20081221192100" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Aaron Patterson", "Mike Dalessio"] + s.date = %q{2008-12-21} + s.description = %q{The Mechanize library is used for automating interaction with websites. Mechanize automatically stores and sends cookies, follows redirects, can follow links, and submit forms. Form fields can be populated and submitted. Mechanize also keeps track of the sites that you have visited as a history.} + s.email = ["aaronp@rubyforge.org", "mike.dalessio@gmail.com"] + s.extra_rdoc_files = ["EXAMPLES.txt", "FAQ.txt", "GUIDE.txt", "History.txt", "LICENSE.txt", "Manifest.txt", "README.txt"] + s.files = ["EXAMPLES.txt", "FAQ.txt", "GUIDE.txt", "History.txt", "LICENSE.txt", "Manifest.txt", "README.txt", "Rakefile", "examples/flickr_upload.rb", "examples/mech-dump.rb", "examples/proxy_req.rb", "examples/rubyforge.rb", "examples/spider.rb", "lib/mechanize.rb", "lib/www/mechanize.rb", "lib/www/mechanize/chain.rb", "lib/www/mechanize/chain/auth_headers.rb", "lib/www/mechanize/chain/body_decoding_handler.rb", "lib/www/mechanize/chain/connection_resolver.rb", "lib/www/mechanize/chain/custom_headers.rb", "lib/www/mechanize/chain/handler.rb", "lib/www/mechanize/chain/header_resolver.rb", "lib/www/mechanize/chain/parameter_resolver.rb", "lib/www/mechanize/chain/post_connect_hook.rb", "lib/www/mechanize/chain/pre_connect_hook.rb", "lib/www/mechanize/chain/request_resolver.rb", "lib/www/mechanize/chain/response_body_parser.rb", "lib/www/mechanize/chain/response_header_handler.rb", "lib/www/mechanize/chain/response_reader.rb", "lib/www/mechanize/chain/ssl_resolver.rb", "lib/www/mechanize/chain/uri_resolver.rb", "lib/www/mechanize/content_type_error.rb", "lib/www/mechanize/cookie.rb", "lib/www/mechanize/cookie_jar.rb", "lib/www/mechanize/file.rb", "lib/www/mechanize/file_response.rb", "lib/www/mechanize/file_saver.rb", "lib/www/mechanize/form.rb", "lib/www/mechanize/form/button.rb", "lib/www/mechanize/form/check_box.rb", "lib/www/mechanize/form/field.rb", "lib/www/mechanize/form/file_upload.rb", "lib/www/mechanize/form/image_button.rb", "lib/www/mechanize/form/multi_select_list.rb", "lib/www/mechanize/form/option.rb", "lib/www/mechanize/form/radio_button.rb", "lib/www/mechanize/form/select_list.rb", "lib/www/mechanize/headers.rb", "lib/www/mechanize/history.rb", "lib/www/mechanize/inspect.rb", "lib/www/mechanize/list.rb", "lib/www/mechanize/monkey_patch.rb", "lib/www/mechanize/page.rb", "lib/www/mechanize/page/base.rb", "lib/www/mechanize/page/frame.rb", "lib/www/mechanize/page/link.rb", "lib/www/mechanize/page/meta.rb", "lib/www/mechanize/pluggable_parsers.rb", "lib/www/mechanize/redirect_limit_reached_error.rb", "lib/www/mechanize/redirect_not_get_or_head_error.rb", "lib/www/mechanize/response_code_error.rb", "lib/www/mechanize/unsupported_scheme_error.rb", "lib/www/mechanize/util.rb", "mechanize.gemspec", "test/chain/test_argument_validator.rb", "test/chain/test_custom_headers.rb", "test/chain/test_parameter_resolver.rb", "test/chain/test_request_resolver.rb", "test/chain/test_response_reader.rb", "test/data/htpasswd", "test/data/server.crt", "test/data/server.csr", "test/data/server.key", "test/data/server.pem", "test/helper.rb", "test/htdocs/alt_text.html", "test/htdocs/bad_form_test.html", "test/htdocs/button.jpg", "test/htdocs/empty_form.html", "test/htdocs/file_upload.html", "test/htdocs/find_link.html", "test/htdocs/form_multi_select.html", "test/htdocs/form_multival.html", "test/htdocs/form_no_action.html", "test/htdocs/form_no_input_name.html", "test/htdocs/form_select.html", "test/htdocs/form_select_all.html", "test/htdocs/form_select_none.html", "test/htdocs/form_select_noopts.html", "test/htdocs/form_set_fields.html", "test/htdocs/form_test.html", "test/htdocs/frame_test.html", "test/htdocs/google.html", "test/htdocs/iframe_test.html", "test/htdocs/index.html", "test/htdocs/link with space.html", "test/htdocs/meta_cookie.html", "test/htdocs/no_title_test.html", "test/htdocs/relative/tc_relative_links.html", "test/htdocs/tc_bad_links.html", "test/htdocs/tc_base_link.html", "test/htdocs/tc_blank_form.html", "test/htdocs/tc_checkboxes.html", "test/htdocs/tc_encoded_links.html", "test/htdocs/tc_follow_meta.html", "test/htdocs/tc_form_action.html", "test/htdocs/tc_links.html", "test/htdocs/tc_no_attributes.html", "test/htdocs/tc_pretty_print.html", "test/htdocs/tc_radiobuttons.html", "test/htdocs/tc_referer.html", "test/htdocs/tc_relative_links.html", "test/htdocs/tc_textarea.html", "test/htdocs/unusual______.html", "test/servlets.rb", "test/ssl_server.rb", "test/test_authenticate.rb", "test/test_bad_links.rb", "test/test_blank_form.rb", "test/test_checkboxes.rb", "test/test_content_type.rb", "test/test_cookie_class.rb", "test/test_cookie_jar.rb", "test/test_cookies.rb", "test/test_encoded_links.rb", "test/test_errors.rb", "test/test_follow_meta.rb", "test/test_form_action.rb", "test/test_form_as_hash.rb", "test/test_form_button.rb", "test/test_form_no_inputname.rb", "test/test_forms.rb", "test/test_frames.rb", "test/test_get_headers.rb", "test/test_gzipping.rb", "test/test_hash_api.rb", "test/test_history.rb", "test/test_history_added.rb", "test/test_html_unscape_forms.rb", "test/test_if_modified_since.rb", "test/test_keep_alive.rb", "test/test_links.rb", "test/test_mech.rb", "test/test_mechanize_file.rb", "test/test_multi_select.rb", "test/test_no_attributes.rb", "test/test_option.rb", "test/test_page.rb", "test/test_pluggable_parser.rb", "test/test_post_form.rb", "test/test_pretty_print.rb", "test/test_radiobutton.rb", "test/test_redirect_limit_reached.rb", "test/test_redirect_verb_handling.rb", "test/test_referer.rb", "test/test_relative_links.rb", "test/test_response_code.rb", "test/test_save_file.rb", "test/test_scheme.rb", "test/test_select.rb", "test/test_select_all.rb", "test/test_select_none.rb", "test/test_select_noopts.rb", "test/test_set_fields.rb", "test/test_ssl_server.rb", "test/test_subclass.rb", "test/test_textarea.rb", "test/test_upload.rb", "test/test_verbs.rb"] + s.has_rdoc = true + s.homepage = %q{ http://mechanize.rubyforge.org/} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{mechanize} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Mechanize provides automated web-browsing} + s.test_files = ["test/chain/test_argument_validator.rb", "test/chain/test_custom_headers.rb", "test/chain/test_parameter_resolver.rb", "test/chain/test_request_resolver.rb", "test/chain/test_response_reader.rb", "test/test_authenticate.rb", "test/test_bad_links.rb", "test/test_blank_form.rb", "test/test_checkboxes.rb", "test/test_content_type.rb", "test/test_cookie_class.rb", "test/test_cookie_jar.rb", "test/test_cookies.rb", "test/test_encoded_links.rb", "test/test_errors.rb", "test/test_follow_meta.rb", "test/test_form_action.rb", "test/test_form_as_hash.rb", "test/test_form_button.rb", "test/test_form_no_inputname.rb", "test/test_forms.rb", "test/test_frames.rb", "test/test_get_headers.rb", "test/test_gzipping.rb", "test/test_hash_api.rb", "test/test_history.rb", "test/test_history_added.rb", "test/test_html_unscape_forms.rb", "test/test_if_modified_since.rb", "test/test_keep_alive.rb", "test/test_links.rb", "test/test_mech.rb", "test/test_mechanize_file.rb", "test/test_multi_select.rb", "test/test_no_attributes.rb", "test/test_option.rb", "test/test_page.rb", "test/test_pluggable_parser.rb", "test/test_post_form.rb", "test/test_pretty_print.rb", "test/test_radiobutton.rb", "test/test_redirect_limit_reached.rb", "test/test_redirect_verb_handling.rb", "test/test_referer.rb", "test/test_relative_links.rb", "test/test_response_code.rb", "test/test_save_file.rb", "test/test_scheme.rb", "test/test_select.rb", "test/test_select_all.rb", "test/test_select_none.rb", "test/test_select_noopts.rb", "test/test_set_fields.rb", "test/test_ssl_server.rb", "test/test_subclass.rb", "test/test_textarea.rb", "test/test_upload.rb", "test/test_verbs.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0.7"]) + s.add_development_dependency(%q, [">= 1.8.2"]) + else + s.add_dependency(%q, [">= 1.0.7"]) + s.add_dependency(%q, [">= 1.8.2"]) + end + else + s.add_dependency(%q, [">= 1.0.7"]) + s.add_dependency(%q, [">= 1.8.2"]) + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/chain/test_argument_validator.rb b/vendor/gems/mechanize-0.9.0/test/chain/test_argument_validator.rb new file mode 100644 index 0000000..f9bd1dc --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/chain/test_argument_validator.rb @@ -0,0 +1,14 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper")) + +class TestURIResolver < Test::Unit::TestCase + def test_handle + v = WWW::Mechanize::Chain.new([ + WWW::Mechanize::Chain::URIResolver.new(Hash.new { |h,k| + h[k] = lambda { |u,r| u } + }) + ]) + assert_raises(ArgumentError) { v.handle({}) } + assert_nothing_raised { v.handle({:uri => 'http://google.com/'}) } + assert_raises(RuntimeError) { v.handle({:uri => 'google'}) } + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/chain/test_custom_headers.rb b/vendor/gems/mechanize-0.9.0/test/chain/test_custom_headers.rb new file mode 100644 index 0000000..775e77f --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/chain/test_custom_headers.rb @@ -0,0 +1,18 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper")) + +class TestCustomHeaders < Test::Unit::TestCase + def test_handle + v = WWW::Mechanize::Chain.new([ + WWW::Mechanize::Chain::CustomHeaders.new + ]) + url = URI.parse('http://tenderlovemaking.com/') + hash = { + :request => Net::HTTP::Get.new(url.request_uri), + :headers => { 'Content-Length' => 300 } + } + v.handle(hash) + headers = hash[:request].to_hash + assert(headers.key?('content-length')) + assert_equal([300], headers['content-length']) + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/chain/test_parameter_resolver.rb b/vendor/gems/mechanize-0.9.0/test/chain/test_parameter_resolver.rb new file mode 100644 index 0000000..571e177 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/chain/test_parameter_resolver.rb @@ -0,0 +1,35 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper")) + +class TestParameterResolver < Test::Unit::TestCase + def test_handle_get + v = WWW::Mechanize::Chain.new([ + WWW::Mechanize::Chain::ParameterResolver.new + ]) + hash = { + :uri => URI.parse('http://google.com/'), + :params => { :q => 'hello' }, + :verb => :get + } + assert_nothing_raised { + v.handle(hash) + } + assert_equal('q=hello', hash[:uri].query) + assert_equal([], hash[:params]) + end + + def test_handle_post + v = WWW::Mechanize::Chain.new([ + WWW::Mechanize::Chain::ParameterResolver.new + ]) + hash = { + :uri => URI.parse('http://google.com/'), + :params => { :q => 'hello' }, + :verb => :post + } + assert_nothing_raised { + v.handle(hash) + } + assert_equal('', hash[:uri].query.to_s) + assert_equal({ :q => 'hello' }, hash[:params]) + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/chain/test_request_resolver.rb b/vendor/gems/mechanize-0.9.0/test/chain/test_request_resolver.rb new file mode 100644 index 0000000..e2d7f13 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/chain/test_request_resolver.rb @@ -0,0 +1,29 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper")) + +class TestRequestResolver < Test::Unit::TestCase + def test_handle_get + v = WWW::Mechanize::Chain.new([ + WWW::Mechanize::Chain::RequestResolver.new + ]) + hash = { + :uri => URI.parse('http://google.com'), + :verb => :get + } + assert_nothing_raised { v.handle(hash) } + assert_kind_of(Net::HTTP::Get, hash[:request]) + assert_equal('/', hash[:request].path) + end + + def test_handle_post + v = WWW::Mechanize::Chain.new([ + WWW::Mechanize::Chain::RequestResolver.new + ]) + hash = { + :uri => URI.parse('http://google.com'), + :verb => :post + } + assert_nothing_raised { v.handle(hash) } + assert_kind_of(Net::HTTP::Post, hash[:request]) + assert_equal('/', hash[:request].path) + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/chain/test_response_reader.rb b/vendor/gems/mechanize-0.9.0/test/chain/test_response_reader.rb new file mode 100644 index 0000000..ddfd99e --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/chain/test_response_reader.rb @@ -0,0 +1,24 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper")) + +class TestResponseReader < Test::Unit::TestCase + def test_handle_bad_response_code + response = Object.new + class << response + def read_body + end + def code; 999; end + end + + v = WWW::Mechanize::Chain.new([ + WWW::Mechanize::Chain::ResponseReader.new(response) + ]) + assert_raises(WWW::Mechanize::ResponseCodeError) { + begin + v.handle({}) + rescue Exception => x + assert_equal(999, x.response_code) + raise x + end + } + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/data/htpasswd b/vendor/gems/mechanize-0.9.0/test/data/htpasswd new file mode 100644 index 0000000..699f724 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/data/htpasswd @@ -0,0 +1 @@ +mech:44E/qORekFV0E diff --git a/vendor/gems/mechanize-0.9.0/test/data/server.crt b/vendor/gems/mechanize-0.9.0/test/data/server.crt new file mode 100644 index 0000000..a6f0769 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/data/server.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICmzCCAgQCCQDq2kM3TCIM0DANBgkqhkiG9w0BAQQFADCBkTELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1NlYXR0bGUxEjAQBgNV +BAoTCU1lY2hhbml6ZTESMBAGA1UECxMJTWVjaGFuaXplMQ4wDAYDVQQDEwVBYXJv +bjEjMCEGCSqGSIb3DQEJARYUYWFyb25wQHJ1Ynlmb3JnZS5vcmcwHhcNMDYwODIz +MDU0NTMwWhcNMDcwODIzMDU0NTMwWjCBkTELMAkGA1UEBhMCVVMxEzARBgNVBAgT +Cldhc2hpbmd0b24xEDAOBgNVBAcTB1NlYXR0bGUxEjAQBgNVBAoTCU1lY2hhbml6 +ZTESMBAGA1UECxMJTWVjaGFuaXplMQ4wDAYDVQQDEwVBYXJvbjEjMCEGCSqGSIb3 +DQEJARYUYWFyb25wQHJ1Ynlmb3JnZS5vcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0A +MIGJAoGBAKpnmI4Y4tBz3SJsHR28QoUr7IYxkqbD8qjqgIN0LXOslyFyiGzNKca5 +Ln2Au8CZLyCugt/vutjfV+Eq0bl0HwbKdo6HjP6RxmGX6EKWX7NOrsof+s96DhLm +JaWWbtvqP8eyy9PNInKjX6n/7wsVetQutjhNy/cAkrh6UOsjyCGvAgMBAAEwDQYJ +KoZIhvcNAQEEBQADgYEAGtqgxn1fh0X5MxDG1yMp5aGcZ6HhtEtlm5S0ZsRnMsqU +Hh6Bd57+zUQ66XnLCbQN2cwNeeSoqtI16Ccc1I5cAhQnIZESMsPG21i1BnpEhKph +HfNFNpWI/upT2EXNUM6Vx2Kk2aCw2ysrD2pHpsTo5bCOly00uK1ZkoJVQMTL4gU= +-----END CERTIFICATE----- diff --git a/vendor/gems/mechanize-0.9.0/test/data/server.csr b/vendor/gems/mechanize-0.9.0/test/data/server.csr new file mode 100644 index 0000000..8e57da8 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/data/server.csr @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIB0jCCATsCAQAwgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u +MRAwDgYDVQQHEwdTZWF0dGxlMRIwEAYDVQQKEwlNZWNoYW5pemUxEjAQBgNVBAsT +CU1lY2hhbml6ZTEOMAwGA1UEAxMFQWFyb24xIzAhBgkqhkiG9w0BCQEWFGFhcm9u +cEBydWJ5Zm9yZ2Uub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqZ5iO +GOLQc90ibB0dvEKFK+yGMZKmw/Ko6oCDdC1zrJchcohszSnGuS59gLvAmS8groLf +77rY31fhKtG5dB8GynaOh4z+kcZhl+hCll+zTq7KH/rPeg4S5iWllm7b6j/HssvT +zSJyo1+p/+8LFXrULrY4Tcv3AJK4elDrI8ghrwIDAQABoAAwDQYJKoZIhvcNAQEE +BQADgYEAT7SPe71NQvT2BYGEmbWb7FlSQrPh+rDQMHt/Akb8+r91NLkxZtbD1e/F +iyI9JloPCEwJXxHBl0VVRpFCRuJNN0z0E/G4NUWu6n+ZkihtnmV6uazzAQmD4pTl +SjoiyVLWU+r4Q4yXWXtJ9GR8Attv32fL3PcP+GGLeurXJAn0MNU= +-----END CERTIFICATE REQUEST----- diff --git a/vendor/gems/mechanize-0.9.0/test/data/server.key b/vendor/gems/mechanize-0.9.0/test/data/server.key new file mode 100644 index 0000000..014f9e6 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/data/server.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQCqZ5iOGOLQc90ibB0dvEKFK+yGMZKmw/Ko6oCDdC1zrJchcohs +zSnGuS59gLvAmS8groLf77rY31fhKtG5dB8GynaOh4z+kcZhl+hCll+zTq7KH/rP +eg4S5iWllm7b6j/HssvTzSJyo1+p/+8LFXrULrY4Tcv3AJK4elDrI8ghrwIDAQAB +AoGAC+iZfLS4hSDTv2gW0NErROtA6E/mk8j12GArAwTHeGIDXc8HQbNEzCJ84UBx +3o/V/06yzruOL0HMfmvjpDY9RLsH02xZb2F/lruw4MJLu50i/Zu8Sjmb1YPSfCh/ +3+8lREA3Uznlq+wHC3yPxQzMBy5jaEdH4IKxT0Bq8TeF0AECQQDSpL47YpRVRsLn +sS00ndEgQQmT5AJWJJtPpbHk6AA0a+zdNeuDRbdF42zG483YEqU7meZbPKR8QbkK +ZQPEBuevAkEAzxjGcz6NZesmN/NQOtOpylewEs1bdIJyBIBmcnmkimLBtdxd0t34 +wUKVHLDSj2aemuAHHwsyn/BNXs6F+obmAQJBALpbkAXAAFW1xefvo3vih8sOXyfd +WIfX2SRNBqbq7otyVFudQaChBDUrsOgBUPLyBAdH8DoV27wm9UuR9RPvu/cCQFRr +WgICXqtMFtE56tuACreD1S9k7MHqpsW0/Y3ujicnKKWUhd5+Q3esR5JhdgOkpkSl +y+FYtDNERpW+BBliwgECQA+Vc7pnxwDIOP8kFumdAUmRmhEZjuwArFcywPzrCUn9 +4/KBOp5wDN7kanBwNGZCZ/eQtkb6thAS8C9pufHD1lw= +-----END RSA PRIVATE KEY----- diff --git a/vendor/gems/mechanize-0.9.0/test/data/server.pem b/vendor/gems/mechanize-0.9.0/test/data/server.pem new file mode 100644 index 0000000..014f9e6 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/data/server.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQCqZ5iOGOLQc90ibB0dvEKFK+yGMZKmw/Ko6oCDdC1zrJchcohs +zSnGuS59gLvAmS8groLf77rY31fhKtG5dB8GynaOh4z+kcZhl+hCll+zTq7KH/rP +eg4S5iWllm7b6j/HssvTzSJyo1+p/+8LFXrULrY4Tcv3AJK4elDrI8ghrwIDAQAB +AoGAC+iZfLS4hSDTv2gW0NErROtA6E/mk8j12GArAwTHeGIDXc8HQbNEzCJ84UBx +3o/V/06yzruOL0HMfmvjpDY9RLsH02xZb2F/lruw4MJLu50i/Zu8Sjmb1YPSfCh/ +3+8lREA3Uznlq+wHC3yPxQzMBy5jaEdH4IKxT0Bq8TeF0AECQQDSpL47YpRVRsLn +sS00ndEgQQmT5AJWJJtPpbHk6AA0a+zdNeuDRbdF42zG483YEqU7meZbPKR8QbkK +ZQPEBuevAkEAzxjGcz6NZesmN/NQOtOpylewEs1bdIJyBIBmcnmkimLBtdxd0t34 +wUKVHLDSj2aemuAHHwsyn/BNXs6F+obmAQJBALpbkAXAAFW1xefvo3vih8sOXyfd +WIfX2SRNBqbq7otyVFudQaChBDUrsOgBUPLyBAdH8DoV27wm9UuR9RPvu/cCQFRr +WgICXqtMFtE56tuACreD1S9k7MHqpsW0/Y3ujicnKKWUhd5+Q3esR5JhdgOkpkSl +y+FYtDNERpW+BBliwgECQA+Vc7pnxwDIOP8kFumdAUmRmhEZjuwArFcywPzrCUn9 +4/KBOp5wDN7kanBwNGZCZ/eQtkb6thAS8C9pufHD1lw= +-----END RSA PRIVATE KEY----- diff --git a/vendor/gems/mechanize-0.9.0/test/helper.rb b/vendor/gems/mechanize-0.9.0/test/helper.rb new file mode 100644 index 0000000..7a81013 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/helper.rb @@ -0,0 +1,127 @@ +require 'test/unit' +$:.unshift(File.expand_path(File.join(File.dirname(__FILE__),'..','lib'))) +require 'rubygems' +require 'mechanize' +require 'webrick/httputils' +require File.join(File.dirname(__FILE__),'servlets') + +BASE_DIR = File.dirname(__FILE__) + +# Move this to a test base class +module MechTestHelper + def self.fake_page(agent) + html = <<-END + +
+ + END + html_response = { 'content-type' => 'text/html' } + page = WWW::Mechanize::Page.new( nil, html_response, html, 200, agent ) + end +end + +class Net::HTTP + alias :old_do_start :do_start + + def do_start + @started = true + end + + SERVLETS = { + '/gzip' => GzipServlet, + '/form_post' => FormTest, + '/basic_auth' => BasicAuthServlet, + '/form post' => FormTest, + '/response_code' => ResponseCodeTest, + '/http_refresh' => HttpRefreshTest, + '/bad_content_type' => BadContentTypeTest, + '/content_type_test' => ContentTypeTest, + '/referer' => RefererServlet, + '/file_upload' => FileUploadTest, + '/one_cookie' => OneCookieTest, + '/one_cookie_no_space' => OneCookieNoSpacesTest, + '/many_cookies' => ManyCookiesTest, + '/many_cookies_as_string' => ManyCookiesAsStringTest, + '/send_cookies' => SendCookiesTest, + '/if_modified_since' => ModifiedSinceServlet, + '/http_headers' => HeaderServlet, + '/infinite_redirect' => InfiniteRedirectTest, + '/infinite_refresh' => InfiniteRefreshTest, + '/redirect' => RedirectTest, + '/digest_auth' => DigestAuthServlet, + '/verb' => VerbServlet, + } + + PAGE_CACHE = {} + + alias :old_request :request + + def request(request, *data, &block) + url = URI.parse(request.path) + path = URI.unescape(url.path) + + path = '/index.html' if path == '/' + + res = Response.new + request.query = WEBrick::HTTPUtils.parse_query(url.query) + request.cookies = WEBrick::Cookie.parse(request['Cookie']) + if SERVLETS[path] + if request.method == "POST" + if request['Content-Type'] =~ /^multipart\/form-data/ + request.body = data.first + else + request.query = WEBrick::HTTPUtils.parse_query(data.first) + end + end + SERVLETS[path].new({}).send("do_#{request.method}", request, res) + else + filename = "htdocs#{path.gsub(/[^\/\\.\w_\s]/, '_')}" + unless PAGE_CACHE[filename] + File.open("#{BASE_DIR}/#{filename}", 'rb') { |file| + PAGE_CACHE[filename] = file.read + } + end + res.body = PAGE_CACHE[filename] + end + + res['Content-Type'] ||= 'text/html' + res['Content-Length'] ||= res.body.length.to_s + res.code ||= "200" + + res.cookies.each do |cookie| + res.add_field('Set-Cookie', cookie.to_s) + end + yield res if block_given? + res + end +end + +class Net::HTTPRequest + attr_accessor :query, :body, :cookies, :user +end + +class Response + include Net::HTTPHeader + + attr_reader :code + attr_accessor :body, :query, :cookies + + def code=(c) + @code = c.to_s + end + + alias :status :code + alias :status= :code= + + def initialize + @header = {} + @body = '' + @code = nil + @query = nil + @cookies = [] + end + + def read_body + yield body + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/alt_text.html b/vendor/gems/mechanize-0.9.0/test/htdocs/alt_text.html new file mode 100644 index 0000000..1037cb3 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/alt_text.html @@ -0,0 +1,10 @@ + + + + alt text + + + no image + + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/bad_form_test.html b/vendor/gems/mechanize-0.9.0/test/htdocs/bad_form_test.html new file mode 100644 index 0000000..3c0b5f2 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/bad_form_test.html @@ -0,0 +1,9 @@ + + Page Title + +
+ + +
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/button.jpg b/vendor/gems/mechanize-0.9.0/test/htdocs/button.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5659742f472618d853ca48c0d29eab4274fdaaca GIT binary patch literal 983 zcmex=O8CaQFSXh`@fdnfnD;qlx2Rjh(b8~a@2=WUF3GxdH z3X92z3yVmJ3JOXnN=V7d%FD|Oiz}%p$*IW5$;*KZVFYSrXJhB%;NX)J5fqUl8T>!M zAjrWW!jQtusKme|$jB_n`2PrlBm*M@GthTPfR&wtjRh#BA;7@M!UP12EX)vTMkZz! zRt7e9K_Nw9Lq`q~r9dO6g+P@es0M%(gG2>Uj0KC{V&GwB1lrCl$Y9TKv*MV6&354% zt5?iS*Z6Y8P3-sbUtU5X^$$)deE#-Ox^K0m(CIFz^r$)88VY+m^-gjYo@be|DZ+oE z`U~ctr@N9`cIzx}&TDPS(pPO~G6JuCKK-*JGfu-n<;&C+^V%11p3;w5G-vfZ z<8_y|+PQjvxtuH=nroQSwJljyPG5J4m#XeA{w-on9^cp>BxISFafvNI+wk^ocCo_o zzgLclYBHX9^Y#9TN7ZjRUjOZPw(R~F{rFb&+^SV^=VP{S6MP!CEoIxbDfcfFdUJjB z5^?kjz3-*ac#~a2&c%9*_r9`;;{D%lOUt&d*gAFn(REQb{?3a25wb<6IzF*>$^wo4 z%@??o*EKHpUH<%@RkLx#hUuP;OF9D6wsP#2@s(Zbc--ov`v*^j75yot-y1VC|7={4 zn-{lie(L(dUFzM%aWO558`#%R)YAHPy{>uwBmaw*mi+lwo&}uP-@YZtV@2=%^R_GB z>RHFu{qV7$W)lgbvsQe% zUn@Av$S!Ex?Lyyn>yQ4iQ|8B3{W}+OvDD=CoU41|LNmXWUMZ<67Wvw?X`#2#oRU9X z!JLeWUzhv}ci;C{$mrRlDv4eDC0~~aTvX(BTAR9WiSb9P&<9*y7jJ$D3{+XZ`Jzf$ PfmKbi1P=}*|NkZcXfJLy literal 0 HcmV?d00001 diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/empty_form.html b/vendor/gems/mechanize-0.9.0/test/htdocs/empty_form.html new file mode 100644 index 0000000..4f818b1 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/empty_form.html @@ -0,0 +1,6 @@ + + +
+
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/file_upload.html b/vendor/gems/mechanize-0.9.0/test/htdocs/file_upload.html new file mode 100644 index 0000000..39e697f --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/file_upload.html @@ -0,0 +1,26 @@ + + + File Upload Form + + +

File Upload Test

+
+ Your name:
+ File to process:
+ + + +
+
+ Your name:
+ File to process:
+ +
+
+ Your name:
+ File to process:
+ +
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/find_link.html b/vendor/gems/mechanize-0.9.0/test/htdocs/find_link.html new file mode 100644 index 0000000..1708e7a --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/find_link.html @@ -0,0 +1,41 @@ + + + + + + + + Testing the links + + + blargle + CPAN A + CPAN B + + + CPAN C + CPAN D + + MSNBC + + CNN + BBC + News + News + News + Rebuild Index + + + + + + + + + + NoWhere + NoWhere + Blongo! + + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/form_multi_select.html b/vendor/gems/mechanize-0.9.0/test/htdocs/form_multi_select.html new file mode 100644 index 0000000..cedc6dc --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/form_multi_select.html @@ -0,0 +1,16 @@ + + +
+ +
+ +
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/form_multival.html b/vendor/gems/mechanize-0.9.0/test/htdocs/form_multival.html new file mode 100644 index 0000000..27e19b0 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/form_multival.html @@ -0,0 +1,37 @@ + + Page Title + +
+ + + + + + + + + + + + + +
First Name
First Name Again
+
+
+ + + + + + + + + + + + + +
First Name
First Name Again
+
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/form_no_action.html b/vendor/gems/mechanize-0.9.0/test/htdocs/form_no_action.html new file mode 100644 index 0000000..70c2c0e --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/form_no_action.html @@ -0,0 +1,18 @@ + + Page Title + +
+ + + + + + + + + +
First Name
+
+ + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/form_no_input_name.html b/vendor/gems/mechanize-0.9.0/test/htdocs/form_no_input_name.html new file mode 100644 index 0000000..f6396ef --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/form_no_input_name.html @@ -0,0 +1,16 @@ + + Input with no name + +
+
+
+
+
+
+
+ + + +
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/form_select.html b/vendor/gems/mechanize-0.9.0/test/htdocs/form_select.html new file mode 100644 index 0000000..fbdc22d --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/form_select.html @@ -0,0 +1,16 @@ + + +
+ +
+ +
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/form_select_all.html b/vendor/gems/mechanize-0.9.0/test/htdocs/form_select_all.html new file mode 100644 index 0000000..ebb0cce --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/form_select_all.html @@ -0,0 +1,16 @@ + + +
+ +
+ +
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/form_select_none.html b/vendor/gems/mechanize-0.9.0/test/htdocs/form_select_none.html new file mode 100644 index 0000000..28cde6b --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/form_select_none.html @@ -0,0 +1,17 @@ + + +
+ +
+ +
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/form_select_noopts.html b/vendor/gems/mechanize-0.9.0/test/htdocs/form_select_noopts.html new file mode 100644 index 0000000..85945cf --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/form_select_noopts.html @@ -0,0 +1,10 @@ + + +
+ +
+ +
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/form_set_fields.html b/vendor/gems/mechanize-0.9.0/test/htdocs/form_set_fields.html new file mode 100644 index 0000000..aafc85c --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/form_set_fields.html @@ -0,0 +1,14 @@ + + + HTML for tc_set_fields + + +
+
+
+
+
+
+
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/form_test.html b/vendor/gems/mechanize-0.9.0/test/htdocs/form_test.html new file mode 100644 index 0000000..8d459b5 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/form_test.html @@ -0,0 +1,175 @@ + + Page Title + +

Post Form 1

+
+ + + + + + + + + + + + + + + + + + + + + +
First Name
Gender + M:
+ F:
+
Check this if you are cool:
Check this if you like green eggs:
Check this if you like ham:

+
+
+ +
+

Get Form 1

+
+ + + + + + + + + + + + + + + + + + + + + +
First Name
Gender + M:
+ F:
+
Check this if you are cool:
Check this if you like green eggs:
Check this if you like ham:

+ + +
+ + +

Post Form 2

+
+ + + + + + + + + + + + + + + + + +
First Name
Gender + M:
+ F:
+
Check this if you are cool:
Check this if you like ham:

+ +
+

Get Form 2

+
+ + + + + + + + + + + + + + + + + +
First Name
Gender + M:
+ F:
+
Check this if you are cool:
Check this if you like ham:

+ +
+ + +

Post Form 3

+
+ + + + + + + + + + + + + + + + + +
First Name
Gender + M:
+ F:
+
Check this if you are cool:
Check this if you like ham:

+ +
+

Get Form 3

+
+ + + + + + + + + + + + + + + + + +
First Name
Gender + M:
+ F:
+
Check this if you are cool:
Check this if you like ham:

+ +
+ form test + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/frame_test.html b/vendor/gems/mechanize-0.9.0/test/htdocs/frame_test.html new file mode 100644 index 0000000..3c85617 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/frame_test.html @@ -0,0 +1,30 @@ + + + +A simple frameset document + + + + + + + + + + + + <P>This frameset document contains: + <UL> + <LI><A href="/google.html">Some neat contents</A> + <LI><A href="/form_test.html" class="bar">Form Test</A> + <LI><A href="/file_upload.html">Some other neat contents</A> + </UL> + + + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/google.html b/vendor/gems/mechanize-0.9.0/test/htdocs/google.html new file mode 100755 index 0000000..6f389a8 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/google.html @@ -0,0 +1,13 @@ +Google + +
Personalized Home | Sign in
Google

+
Web    Images    Groups    News    Froogle    Local    more »
 
  Advanced Search
  Preferences
  Language Tools


Advertising Programs - Business Solutions - About Google

©2006 Google

diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/iframe_test.html b/vendor/gems/mechanize-0.9.0/test/htdocs/iframe_test.html new file mode 100644 index 0000000..f1aee28 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/iframe_test.html @@ -0,0 +1,16 @@ + + + +A simple frameset document + + + + + + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/index.html b/vendor/gems/mechanize-0.9.0/test/htdocs/index.html new file mode 100644 index 0000000..55513b7 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/index.html @@ -0,0 +1,6 @@ + + Page Title + +

Hello World!

+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/link with space.html b/vendor/gems/mechanize-0.9.0/test/htdocs/link with space.html new file mode 100644 index 0000000..af7cd09 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/link with space.html @@ -0,0 +1,5 @@ + + + This is a webpage that has a space in the filename. + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/meta_cookie.html b/vendor/gems/mechanize-0.9.0/test/htdocs/meta_cookie.html new file mode 100644 index 0000000..f43ae78 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/meta_cookie.html @@ -0,0 +1,11 @@ + + + + alt text + + + no image + + + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/no_title_test.html b/vendor/gems/mechanize-0.9.0/test/htdocs/no_title_test.html new file mode 100644 index 0000000..43274e3 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/no_title_test.html @@ -0,0 +1,6 @@ + + + + No title in the title tag + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/relative/tc_relative_links.html b/vendor/gems/mechanize-0.9.0/test/htdocs/relative/tc_relative_links.html new file mode 100644 index 0000000..3d370fc --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/relative/tc_relative_links.html @@ -0,0 +1,21 @@ + + + dot dot slash + too many dots + + + + + + + + + + + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/tc_bad_links.html b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_bad_links.html new file mode 100644 index 0000000..33d4365 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_bad_links.html @@ -0,0 +1,5 @@ + + + Alt Text + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/tc_base_link.html b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_base_link.html new file mode 100644 index 0000000..97b2558 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_base_link.html @@ -0,0 +1,8 @@ + + + + + + test + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/tc_blank_form.html b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_blank_form.html new file mode 100644 index 0000000..657a370 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_blank_form.html @@ -0,0 +1,11 @@ + + +
+ + + + + +
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/tc_checkboxes.html b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_checkboxes.html new file mode 100644 index 0000000..afeb902 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_checkboxes.html @@ -0,0 +1,19 @@ + + tc_checkboxbuttons.html + +
+ Gender:
+ M:
+ F:
+ Your one favorite color:
+ Green:
+ Green:
+ Red:
+ Blue:
+ Yellow:
+ Brown:
+ Purple:
+ +
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/tc_encoded_links.html b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_encoded_links.html new file mode 100644 index 0000000..a65430e --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_encoded_links.html @@ -0,0 +1,5 @@ + + + test link + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/tc_follow_meta.html b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_follow_meta.html new file mode 100644 index 0000000..2195625 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_follow_meta.html @@ -0,0 +1,8 @@ + + + + + + This page has a meta refresh. + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/tc_form_action.html b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_form_action.html new file mode 100644 index 0000000..e824cdb --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_form_action.html @@ -0,0 +1,48 @@ + + Page Title + +

Post Form 1

+
+ + + + + +
First Name

+ +
+ +

Post Form 2

+
+ + + + + +
First Name

+ +
+ +

Post Form 3

+
+ + + + + +
First Name

+ +
+ +

Post Form 4

+
+ + + + + +
First Name

+ +
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/tc_links.html b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_links.html new file mode 100644 index 0000000..e6812bd --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_links.html @@ -0,0 +1,18 @@ + + + Bold Dude + Dude + Aaron James Patterson + Aaron Patterson + Ruby Rocks! + + encoded space + not encoded space + + unusual characters + + javascript link + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/tc_no_attributes.html b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_no_attributes.html new file mode 100644 index 0000000..8575af6 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_no_attributes.html @@ -0,0 +1,16 @@ + + + + + Hello + +
+ + + +
+ + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/tc_pretty_print.html b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_pretty_print.html new file mode 100644 index 0000000..9e2c35d --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_pretty_print.html @@ -0,0 +1,17 @@ + + tc_pretty_print.html + + Google
+
+
+
+ + +
+
+ +
+ + + + + + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/tc_textarea.html b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_textarea.html new file mode 100644 index 0000000..d75c27d --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/tc_textarea.html @@ -0,0 +1,23 @@ + + tc_textarea.html + +
+ +
+ +
+
+
+ +
+ +
+
+
+ + +
+ +
+ + diff --git a/vendor/gems/mechanize-0.9.0/test/htdocs/unusual______.html b/vendor/gems/mechanize-0.9.0/test/htdocs/unusual______.html new file mode 100644 index 0000000..d546c75 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/htdocs/unusual______.html @@ -0,0 +1,5 @@ + + + This is a webpage that has a very unusual name. + + diff --git a/vendor/gems/mechanize-0.9.0/test/servlets.rb b/vendor/gems/mechanize-0.9.0/test/servlets.rb new file mode 100644 index 0000000..099774c --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/servlets.rb @@ -0,0 +1,339 @@ +require 'webrick' +require 'logger' +require 'date' +require 'zlib' +require 'stringio' +require 'base64' + +class VerbServlet < WEBrick::HTTPServlet::AbstractServlet + %w(HEAD GET POST PUT DELETE).each do |verb| + eval(<<-eomethod) + def do_#{verb}(req, res) + res.body = "method: #{verb}" + end + eomethod + end +end + +class BasicAuthServlet < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req,res) + htpd = WEBrick::HTTPAuth::Htpasswd.new('dot.htpasswd') + htpd.set_passwd('Blah', 'user', 'pass') + authenticator = WEBrick::HTTPAuth::BasicAuth.new({ + :UserDB => htpd, + :Realm => 'Blah', + :Logger => Logger.new(nil) + } + ) + begin + authenticator.authenticate(req,res) + res.body = 'You are authenticated' + rescue WEBrick::HTTPStatus::Unauthorized => ex + res.status = 401 + end + FileUtils.rm('dot.htpasswd') + end + alias :do_POST :do_GET +end + +class DigestAuthServlet < WEBrick::HTTPServlet::AbstractServlet + htpd = WEBrick::HTTPAuth::Htdigest.new('digest.htpasswd') + htpd.set_passwd('Blah', 'user', 'pass') + @@authenticator = WEBrick::HTTPAuth::DigestAuth.new({ + :UserDB => htpd, + :Realm => 'Blah', + :Algorithm => 'MD5', + :Logger => Logger.new(nil) + } + ) + def do_GET(req,res) + def req.request_time; Time.now; end + def req.request_uri; '/digest_auth'; end + def req.request_method; "GET"; end + + begin + @@authenticator.authenticate(req,res) + res.body = 'You are authenticated' + rescue WEBrick::HTTPStatus::Unauthorized => ex + res.status = 401 + end + FileUtils.rm('digest.htpasswd') if File.exists?('digest.htpasswd') + end + alias :do_POST :do_GET +end + +class HeaderServlet < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + res['Content-Type'] = "text/html" + + req.query.each do |x,y| + res[x] = y + end + + body = '' + req.each_header do |k,v| + body << "#{k}|#{v}\n" + end + res.body = body + end +end + +class RefererServlet < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + res['Content-Type'] = "text/html" + res.body = req['Referer'] || '' + end + + def do_POST(req, res) + res['Content-Type'] = "text/html" + res.body = req['Referer'] || '' + end +end + +class ModifiedSinceServlet < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + s_time = 'Fri, 04 May 2001 00:00:38 GMT' + + my_time = Time.parse(s_time) + + if req['If-Modified-Since'] + your_time = Time.parse(req['If-Modified-Since']) + if my_time > your_time + res.body = 'This page was updated since you requested' + else + res.status = 304 + end + else + res.body = 'You did not send an If-Modified-Since header' + end + + res['Last-Modified'] = s_time + end +end + +class GzipServlet < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + if req['Accept-Encoding'] =~ /gzip/ + if req.query['file'] + File.open("#{BASE_DIR}/htdocs/#{req.query['file']}", 'r') do |file| + string = "" + zipped = StringIO.new string, 'w' + gz = Zlib::GzipWriter.new(zipped) + gz.write file.read + gz.close + res.body = string + end + else + res.body = '' + end + res['Content-Encoding'] = 'gzip' + res['Content-Type'] = "text/html" + else + raise 'no gzip' + end + end +end + +class BadContentTypeTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + res['Content-Type'] = "text/xml" + res.body = "Hello World" + end +end + +class ContentTypeTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + ct = req.query['ct'] || "text/html; charset=utf-8" + res['Content-Type'] = ct + res.body = "Hello World" + end +end + +class FileUploadTest < WEBrick::HTTPServlet::AbstractServlet + def do_POST(req, res) + res.body = req.body + end +end + +class InfiniteRefreshTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + res['Content-Type'] = req.query['ct'] || "text/html" + res.status = req.query['code'] ? req.query['code'].to_i : '302' + number = req.query['q'] ? req.query['q'].to_i : 0 + res['Refresh'] = " 0;url=http://localhost/infinite_refresh?q=#{number + 1}\r\n"; + end +end + +class InfiniteRedirectTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + res['Content-Type'] = req.query['ct'] || "text/html" + res.status = req.query['code'] ? req.query['code'].to_i : '302' + number = req.query['q'] ? req.query['q'].to_i : 0 + res['Location'] = "/infinite_redirect?q=#{number + 1}" + end + alias :do_POST :do_GET +end + +class RedirectTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + res['Content-Type'] = req.query['ct'] || "text/html" + res.status = req.query['code'] ? req.query['code'].to_i : '302' + res['Location'] = "/verb" + end + + alias :do_POST :do_GET + alias :do_HEAD :do_GET + alias :do_PUT :do_GET + alias :do_DELETE :do_GET +end + +class ResponseCodeTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + res['Content-Type'] = req.query['ct'] || "text/html" + if req.query['code'] + code = req.query['code'].to_i + case code + when 300, 301, 302, 303, 304, 305, 307 + res['Location'] = "/index.html" + end + res.status = code + else + end + end +end + +class HttpRefreshTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + res['Content-Type'] = req.query['ct'] || "text/html" + refresh_time = req.query['refresh_time'] || 0 + refresh_url = req.query['refresh_url'] || '/index.html' + res['Refresh'] = " #{refresh_time};url=#{refresh_url}\r\n"; + end +end + +class FormTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + res.body = "" + req.query.each_key { |k| + req.query[k].each_data { |data| + res.body << "#{URI.unescape(k)}:#{URI.unescape(data)}
" + } + } + res.body << "" + res['Content-Type'] = "text/html" + end + + def do_POST(req, res) + res.body = "" + req.query.each_key { |k| + req.query[k].each_data { |data| + res.body << "#{k}:#{data}
" + } + } + res.body << "" + res['Content-Type'] = "text/html" + end +end + +class OneCookieTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + cookie = WEBrick::Cookie.new("foo", "bar") + cookie.path = "/" + cookie.expires = Time.now + 86400 + res.cookies << cookie + res['Content-Type'] = "text/html" + res.body = "hello" + end +end + +class OneCookieNoSpacesTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + cookie = WEBrick::Cookie.new("foo", "bar") + cookie.path = "/" + cookie.expires = Time.now + 86400 + res.cookies << cookie.to_s.gsub(/; /, ';') + res['Content-Type'] = "text/html" + res.body = "hello" + end +end + +class ManyCookiesTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + name_cookie = WEBrick::Cookie.new("name", "Aaron") + name_cookie.path = "/" + name_cookie.expires = Time.now + 86400 + res.cookies << name_cookie + res.cookies << name_cookie + res.cookies << name_cookie + res.cookies << name_cookie + + expired_cookie = WEBrick::Cookie.new("expired", "doh") + expired_cookie.path = "/" + expired_cookie.expires = Time.now - 86400 + res.cookies << expired_cookie + + different_path_cookie = WEBrick::Cookie.new("a_path", "some_path") + different_path_cookie.path = "/some_path" + different_path_cookie.expires = Time.now + 86400 + res.cookies << different_path_cookie + + no_path_cookie = WEBrick::Cookie.new("no_path", "no_path") + no_path_cookie.expires = Time.now + 86400 + res.cookies << no_path_cookie + + no_exp_path_cookie = WEBrick::Cookie.new("no_expires", "nope") + no_exp_path_cookie.path = "/" + res.cookies << no_exp_path_cookie + + res['Content-Type'] = "text/html" + res.body = "hello" + end +end + +class ManyCookiesAsStringTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + cookies = [] + name_cookie = WEBrick::Cookie.new("name", "Aaron") + name_cookie.path = "/" + name_cookie.expires = Time.now + 86400 + name_cookie.domain = 'localhost' + cookies << name_cookie + cookies << name_cookie + cookies << name_cookie + cookies << "#{name_cookie}; HttpOnly" + + expired_cookie = WEBrick::Cookie.new("expired", "doh") + expired_cookie.path = "/" + expired_cookie.expires = Time.now - 86400 + cookies << expired_cookie + + different_path_cookie = WEBrick::Cookie.new("a_path", "some_path") + different_path_cookie.path = "/some_path" + different_path_cookie.expires = Time.now + 86400 + cookies << different_path_cookie + + no_path_cookie = WEBrick::Cookie.new("no_path", "no_path") + no_path_cookie.expires = Time.now + 86400 + cookies << no_path_cookie + + no_exp_path_cookie = WEBrick::Cookie.new("no_expires", "nope") + no_exp_path_cookie.path = "/" + cookies << no_exp_path_cookie + + res['Set-Cookie'] = cookies.join(', ') + + res['Content-Type'] = "text/html" + res.body = "hello" + end +end + +class SendCookiesTest < WEBrick::HTTPServlet::AbstractServlet + def do_GET(req, res) + res['Content-Type'] = "text/html" + res.body = "" + req.cookies.each { |c| + res.body << "#{c.name}:#{c.value}" + } + res.body << "" + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/ssl_server.rb b/vendor/gems/mechanize-0.9.0/test/ssl_server.rb new file mode 100644 index 0000000..ff170c1 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/ssl_server.rb @@ -0,0 +1,48 @@ +require 'webrick' +require 'webrick/https' +require 'servlets' +require 'logger' + +base_dir = FileTest.exists?(Dir::pwd + '/test') ? Dir::pwd + '/test' : Dir::pwd + +s = WEBrick::HTTPServer.new( + :Port => 2002, + :DocumentRoot => base_dir + "/htdocs", + :SSLEnable => true, + :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE, + :SSLCertificate => OpenSSL::X509::Certificate.new( + File.read("data/server.crt") + ), + :SSLPrivateKey => OpenSSL::PKey::RSA.new( + File.read("data/server.pem") + ), + :Logger => Logger.new(nil), + :AccessLog => Logger.new(nil) +) +s.mount("/one_cookie", OneCookieTest) +s.mount("/one_cookie_no_space", OneCookieNoSpacesTest) +s.mount("/many_cookies", ManyCookiesTest) +s.mount("/many_cookies_as_string", ManyCookiesAsStringTest) +s.mount("/send_cookies", SendCookiesTest) +s.mount("/form_post", FormTest) +s.mount("/form post", FormTest) +s.mount("/response_code", ResponseCodeTest) +s.mount("/file_upload", FileUploadTest) +s.mount("/bad_content_type", BadContentTypeTest) +s.mount("/content_type_test", ContentTypeTest) + +htpasswd = WEBrick::HTTPAuth::Htpasswd.new(base_dir + '/data/htpasswd') +auth = WEBrick::HTTPAuth::BasicAuth.new( + :UserDB => htpasswd, + :Realm => 'mechanize', + :Logger => Logger.new(nil), + :AccessLog => Logger.new(nil) +) +s.mount_proc('/htpasswd_auth') { |req, res| + auth.authenticate(req, res) + res.body = "You are authenticated" +} + +trap("INT") { s.stop } + +s.start diff --git a/vendor/gems/mechanize-0.9.0/test/test_authenticate.rb b/vendor/gems/mechanize-0.9.0/test/test_authenticate.rb new file mode 100644 index 0000000..81a17fa --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_authenticate.rb @@ -0,0 +1,71 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) +require 'pp' + +class BasicAuthTest < Test::Unit::TestCase + def setup + @agent = WWW::Mechanize.new + end + + def test_auth_success + @agent.basic_auth('user', 'pass') + page = @agent.get("http://localhost/basic_auth") + assert_equal('You are authenticated', page.body) + end + + def test_digest_auth_success + @agent.basic_auth('user', 'pass') + page = @agent.get("http://localhost/digest_auth") + assert_equal('You are authenticated', page.body) + end + + def test_no_duplicate_headers + block_called = false + @agent.pre_connect_hooks << lambda { |params| + block_called = true + params[:request].to_hash.each do |k,v| + assert_equal(1, v.length) + end + } + @agent.basic_auth('user', 'pass') + page = @agent.get("http://localhost/digest_auth") + assert block_called + end + + def test_post_auth_success + class << @agent + alias :old_fetch_page :fetch_page + attr_accessor :requests + def fetch_page(args) + @requests ||= [] + x = old_fetch_page(args) + @requests << args[:verb] + x + end + end + @agent.basic_auth('user', 'pass') + page = @agent.post("http://localhost/basic_auth") + assert_equal('You are authenticated', page.body) + assert_equal(2, @agent.requests.length) + r1 = @agent.requests[0] + r2 = @agent.requests[1] + assert_equal(r1, r2) + end + + def test_auth_bad_user_pass + @agent.basic_auth('aaron', 'aaron') + begin + page = @agent.get("http://localhost/basic_auth") + rescue WWW::Mechanize::ResponseCodeError => e + assert_equal("401", e.response_code) + end + end + + def test_auth_failure + begin + page = @agent.get("http://localhost/basic_auth") + rescue WWW::Mechanize::ResponseCodeError => e + assert_equal("401", e.response_code) + end + end + +end diff --git a/vendor/gems/mechanize-0.9.0/test/test_bad_links.rb b/vendor/gems/mechanize-0.9.0/test/test_bad_links.rb new file mode 100644 index 0000000..1038e8d --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_bad_links.rb @@ -0,0 +1,25 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) + +class TestBadLinks < Test::Unit::TestCase + def setup + @agent = WWW::Mechanize.new + @page = @agent.get("http://localhost/tc_bad_links.html") + end + + def test_space_in_link + assert_nothing_raised do + @agent.click @page.links.first + end + assert_match(/alt_text.html$/, @agent.history.last.uri.to_s) + assert_equal(2, @agent.history.length) + end + + def test_space_in_url + page = nil + assert_nothing_raised do + page = @agent.get("http://localhost/tc_bad_links.html ") + end + assert_match(/tc_bad_links.html$/, @agent.history.last.uri.to_s) + assert_equal(2, @agent.history.length) + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/test_blank_form.rb b/vendor/gems/mechanize-0.9.0/test/test_blank_form.rb new file mode 100644 index 0000000..c77ff83 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_blank_form.rb @@ -0,0 +1,16 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) + +class BlankFormTest < Test::Unit::TestCase + def setup + @agent = WWW::Mechanize.new + end + + def test_blank_form_query_string + page = @agent.get('http://localhost/tc_blank_form.html') + form = page.forms.first + query = form.build_query + assert(query.length > 0) + assert query.all? { |x| x[1] == '' } + end +end + diff --git a/vendor/gems/mechanize-0.9.0/test/test_checkboxes.rb b/vendor/gems/mechanize-0.9.0/test/test_checkboxes.rb new file mode 100644 index 0000000..56f6360 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_checkboxes.rb @@ -0,0 +1,61 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) + +class TestCheckBoxes < Test::Unit::TestCase + def setup + @agent = WWW::Mechanize.new + @page = @agent.get('http://localhost/tc_checkboxes.html') + end + + def test_select_one + form = @page.forms.first + form.checkbox_with(:name => 'green').check + assert(form.checkbox_with(:name => 'green').checked) + %w{ red blue yellow brown }.each do |color| + assert_equal(false, form.checkbox_with(:name => color).checked) + end + end + + def test_select_all + form = @page.forms.first + form.checkboxes.each do |b| + b.check + end + form.checkboxes.each do |b| + assert_equal(true, b.checked) + end + end + + def test_select_none + form = @page.forms.first + form.checkboxes.each do |b| + b.uncheck + end + form.checkboxes.each do |b| + assert_equal(false, b.checked) + end + end + + def test_check_one + form = @page.forms.first + assert_equal(2, form.checkboxes_with(:name => 'green').length) + form.checkboxes_with(:name => 'green')[1].check + assert_equal(false, form.checkboxes_with(:name => 'green')[0].checked) + assert_equal(true, form.checkboxes_with(:name => 'green')[1].checked) + page = @agent.submit(form) + assert_equal(1, page.links.length) + assert_equal('green:on', page.links.first.text) + end + + def test_check_two + form = @page.forms.first + assert_equal(2, form.checkboxes_with(:name => 'green').length) + form.checkboxes_with(:name => 'green')[0].check + form.checkboxes_with(:name => 'green')[1].check + assert_equal(true, form.checkboxes_with(:name => 'green')[0].checked) + assert_equal(true, form.checkboxes_with(:name => 'green')[1].checked) + page = @agent.submit(form) + assert_equal(2, page.links.length) + assert_equal('green:on', page.links.first.text) + assert_equal('green:on', page.links[1].text) + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/test_content_type.rb b/vendor/gems/mechanize-0.9.0/test/test_content_type.rb new file mode 100644 index 0000000..b3ea8d6 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_content_type.rb @@ -0,0 +1,13 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) + +class TestContentType < Test::Unit::TestCase + def setup + @agent = WWW::Mechanize.new + end + + def test_application_xhtml_xml + url = 'http://localhost/content_type_test?ct=application/xhtml%2Bxml' + page = @agent.get url + assert_equal WWW::Mechanize::Page, page.class, "xhtml docs should return a Page" + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/test_cookie_class.rb b/vendor/gems/mechanize-0.9.0/test/test_cookie_class.rb new file mode 100644 index 0000000..41e3344 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_cookie_class.rb @@ -0,0 +1,329 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) + +module Enumerable + def combine + masks = inject([[], 1]){|(ar, m), e| [ar << m, m << 1 ] }[0] + all = masks.inject(0){ |al, m| al|m } + + result = [] + for i in 1..all do + tmp = [] + each_with_index do |e, idx| + tmp << e unless (masks[idx] & i) == 0 + end + result << tmp + end + result + end +end + +class CookieClassTest < Test::Unit::TestCase + def silently + warn_level = $VERBOSE + $VERBOSE = false + res = yield + $VERBOSE = warn_level + res + end + + def test_parse_dates + url = URI.parse('http://localhost/') + + yesterday = Time.now - 86400 + + dates = [ "14 Apr 89 03:20:12", + "14 Apr 89 03:20 GMT", + "Fri, 17 Mar 89 4:01:33", + "Fri, 17 Mar 89 4:01 GMT", + "Mon Jan 16 16:12 PDT 1989", + "Mon Jan 16 16:12 +0130 1989", + "6 May 1992 16:41-JST (Wednesday)", + #"22-AUG-1993 10:59:12.82", + "22-AUG-1993 10:59pm", + "22-AUG-1993 12:59am", + "22-AUG-1993 12:59 PM", + #"Friday, August 04, 1995 3:54 PM", + "06/21/95 04:24:34 PM", + #"20/06/95 21:07", + "95-06-08 19:32:48 EDT", + ] + + dates.each do |date| + cookie = "PREF=1; expires=#{date}" + silently do + WWW::Mechanize::Cookie.parse(url, cookie) { |c| + assert c.expires, "Tried parsing: #{date}" + assert_equal(true, c.expires < yesterday) + } + end + end + end + + def test_double_semicolon + double_semi = 'WSIDC=WEST;; domain=.williams-sonoma.com; path=/' + url = URI.parse('http://williams-sonoma.com/') + WWW::Mechanize::Cookie.parse(url, double_semi) { |cookie| + assert_equal('WSIDC', cookie.name) + assert_equal('WEST', cookie.value) + } + end + + def test_parse_bad_version + bad_cookie = 'PRETANET=TGIAqbFXtt; Name=/PRETANET; Path=/; Version=1.2; Content-type=text/html; Domain=192.168.6.196; expires=Friday, 13-November-2026 23:01:46 GMT;' + url = URI.parse('http://localhost/') + WWW::Mechanize::Cookie.parse(url, bad_cookie) { |cookie| + assert_nil(cookie.version) + } + end + + def test_parse_bad_max_age + bad_cookie = 'PRETANET=TGIAqbFXtt; Name=/PRETANET; Path=/; Max-Age=1.2; Content-type=text/html; Domain=192.168.6.196; expires=Friday, 13-November-2026 23:01:46 GMT;' + url = URI.parse('http://localhost/') + WWW::Mechanize::Cookie.parse(url, bad_cookie) { |cookie| + assert_nil(cookie.max_age) + } + end + + def test_parse_date_fail + url = URI.parse('http://localhost/') + + dates = [ + "20/06/95 21:07", + ] + + silently do + dates.each do |date| + cookie = "PREF=1; expires=#{date}" + WWW::Mechanize::Cookie.parse(url, cookie) { |c| + assert_equal(true, c.expires.nil?) + } + end + end + end + + def test_parse_valid_cookie + url = URI.parse('http://rubyforge.org/') + cookie_params = {} + cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT' + cookie_params['path'] = 'path=/' + cookie_params['domain'] = 'domain=.rubyforge.org' + cookie_params['httponly'] = 'HttpOnly' + cookie_value = '12345%7D=ASDFWEE345%3DASda' + + expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT') + + cookie_params.keys.combine.each do |c| + cookie_text = "#{cookie_value}; " + c.each_with_index do |key, idx| + if idx == (c.length - 1) + cookie_text << "#{cookie_params[key]}" + else + cookie_text << "#{cookie_params[key]}; " + end + end + cookie = nil + WWW::Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie } + assert_not_nil(cookie) + assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s) + assert_equal('/', cookie.path) + assert_equal('rubyforge.org', cookie.domain) + + # if expires was set, make sure we parsed it + if c.find { |k| k == 'expires' } + assert_equal(expires, cookie.expires) + else + assert_nil(cookie.expires) + end + end + end + + def test_parse_valid_cookie_empty_value + url = URI.parse('http://rubyforge.org/') + cookie_params = {} + cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT' + cookie_params['path'] = 'path=/' + cookie_params['domain'] = 'domain=.rubyforge.org' + cookie_params['httponly'] = 'HttpOnly' + cookie_value = '12345%7D=' + + expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT') + + cookie_params.keys.combine.each do |c| + cookie_text = "#{cookie_value}; " + c.each_with_index do |key, idx| + if idx == (c.length - 1) + cookie_text << "#{cookie_params[key]}" + else + cookie_text << "#{cookie_params[key]}; " + end + end + cookie = nil + WWW::Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie } + assert_not_nil(cookie) + assert_equal('12345%7D=', cookie.to_s) + assert_equal('', cookie.value) + assert_equal('/', cookie.path) + assert_equal('rubyforge.org', cookie.domain) + + # if expires was set, make sure we parsed it + if c.find { |k| k == 'expires' } + assert_equal(expires, cookie.expires) + else + assert_nil(cookie.expires) + end + end + end + + # If no path was given, use the one from the URL + def test_cookie_using_url_path + url = URI.parse('http://rubyforge.org/login.php') + cookie_params = {} + cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT' + cookie_params['path'] = 'path=/' + cookie_params['domain'] = 'domain=.rubyforge.org' + cookie_params['httponly'] = 'HttpOnly' + cookie_value = '12345%7D=ASDFWEE345%3DASda' + + expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT') + + cookie_params.keys.combine.each do |c| + next if c.find { |k| k == 'path' } + cookie_text = "#{cookie_value}; " + c.each_with_index do |key, idx| + if idx == (c.length - 1) + cookie_text << "#{cookie_params[key]}" + else + cookie_text << "#{cookie_params[key]}; " + end + end + cookie = nil + WWW::Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie } + assert_not_nil(cookie) + assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s) + assert_equal('rubyforge.org', cookie.domain) + assert_equal('/', cookie.path) + + # if expires was set, make sure we parsed it + if c.find { |k| k == 'expires' } + assert_equal(expires, cookie.expires) + else + assert_nil(cookie.expires) + end + end + end + + # Test using secure cookies + def test_cookie_with_secure + url = URI.parse('http://rubyforge.org/') + cookie_params = {} + cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT' + cookie_params['path'] = 'path=/' + cookie_params['domain'] = 'domain=.rubyforge.org' + cookie_params['secure'] = 'secure' + cookie_value = '12345%7D=ASDFWEE345%3DASda' + + expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT') + + cookie_params.keys.combine.each do |c| + next unless c.find { |k| k == 'secure' } + cookie_text = "#{cookie_value}; " + c.each_with_index do |key, idx| + if idx == (c.length - 1) + cookie_text << "#{cookie_params[key]}" + else + cookie_text << "#{cookie_params[key]}; " + end + end + cookie = nil + WWW::Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie } + assert_not_nil(cookie) + assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s) + assert_equal('rubyforge.org', cookie.domain) + assert_equal('/', cookie.path) + assert_equal(true, cookie.secure) + + # if expires was set, make sure we parsed it + if c.find { |k| k == 'expires' } + assert_equal(expires, cookie.expires) + else + assert_nil(cookie.expires) + end + end + end + + # If no domain was given, we must use the one from the URL + def test_cookie_with_url_domain + url = URI.parse('http://login.rubyforge.org/') + cookie_params = {} + cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT' + cookie_params['path'] = 'path=/' + cookie_params['domain'] = 'domain=.rubyforge.org' + cookie_params['httponly'] = 'HttpOnly' + cookie_value = '12345%7D=ASDFWEE345%3DASda' + + expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT') + + cookie_params.keys.combine.each do |c| + next if c.find { |k| k == 'domain' } + cookie_text = "#{cookie_value}; " + c.each_with_index do |key, idx| + if idx == (c.length - 1) + cookie_text << "#{cookie_params[key]}" + else + cookie_text << "#{cookie_params[key]}; " + end + end + cookie = nil + WWW::Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie } + assert_not_nil(cookie) + assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s) + assert_equal('/', cookie.path) + + assert_equal('login.rubyforge.org', cookie.domain) + + # if expires was set, make sure we parsed it + if c.find { |k| k == 'expires' } + assert_equal(expires, cookie.expires) + else + assert_nil(cookie.expires) + end + end + end + + def test_parse_cookie_no_spaces + url = URI.parse('http://rubyforge.org/') + cookie_params = {} + cookie_params['expires'] = 'expires=Sun, 27-Sep-2037 00:00:00 GMT' + cookie_params['path'] = 'path=/' + cookie_params['domain'] = 'domain=.rubyforge.org' + cookie_params['httponly'] = 'HttpOnly' + cookie_value = '12345%7D=ASDFWEE345%3DASda' + + expires = Time.parse('Sun, 27-Sep-2037 00:00:00 GMT') + + cookie_params.keys.combine.each do |c| + cookie_text = "#{cookie_value};" + c.each_with_index do |key, idx| + if idx == (c.length - 1) + cookie_text << "#{cookie_params[key]}" + else + cookie_text << "#{cookie_params[key]};" + end + end + cookie = nil + WWW::Mechanize::Cookie.parse(url, cookie_text) { |p_cookie| cookie = p_cookie } + assert_not_nil(cookie) + assert_equal('12345%7D=ASDFWEE345%3DASda', cookie.to_s) + assert_equal('/', cookie.path) + assert_equal('rubyforge.org', cookie.domain) + + # if expires was set, make sure we parsed it + if c.find { |k| k == 'expires' } + assert_equal(expires, cookie.expires) + else + assert_nil(cookie.expires) + end + end + end +end + diff --git a/vendor/gems/mechanize-0.9.0/test/test_cookie_jar.rb b/vendor/gems/mechanize-0.9.0/test/test_cookie_jar.rb new file mode 100644 index 0000000..36b7aae --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_cookie_jar.rb @@ -0,0 +1,343 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) + +class CookieJarTest < Test::Unit::TestCase + def cookie_from_hash(hash) + c = WWW::Mechanize::Cookie.new(hash[:name], hash[:value]) + hash.each { |k,v| + next if k == :name || k == :value + c.send("#{k}=", v) + } + c + end + + def test_domain_case + values = { :name => 'Foo', + :value => 'Bar', + :path => '/', + :expires => Time.now + (10 * 86400), + :domain => 'rubyforge.org' + } + url = URI.parse('http://rubyforge.org/') + + jar = WWW::Mechanize::CookieJar.new + assert_equal(0, jar.cookies(url).length) + + # Add one cookie with an expiration date in the future + cookie = cookie_from_hash(values) + jar.add(url, cookie) + assert_equal(1, jar.cookies(url).length) + + jar.add(url, cookie_from_hash( values.merge( :domain => 'RuByForge.Org', + :name => 'aaron' + ) ) ) + + assert_equal(2, jar.cookies(url).length) + + url2 = URI.parse('http://RuByFoRgE.oRg/') + assert_equal(2, jar.cookies(url2).length) + end + + def test_empty_value + values = { :name => 'Foo', + :value => '', + :path => '/', + :expires => Time.now + (10 * 86400), + :domain => 'rubyforge.org' + } + url = URI.parse('http://rubyforge.org/') + + jar = WWW::Mechanize::CookieJar.new + assert_equal(0, jar.cookies(url).length) + + # Add one cookie with an expiration date in the future + cookie = cookie_from_hash(values) + jar.add(url, cookie) + assert_equal(1, jar.cookies(url).length) + + jar.add(url, cookie_from_hash( values.merge( :domain => 'RuByForge.Org', + :name => 'aaron' + ) ) ) + + assert_equal(2, jar.cookies(url).length) + + url2 = URI.parse('http://RuByFoRgE.oRg/') + assert_equal(2, jar.cookies(url2).length) + end + + def test_add_future_cookies + values = { :name => 'Foo', + :value => 'Bar', + :path => '/', + :expires => Time.now + (10 * 86400), + :domain => 'rubyforge.org' + } + url = URI.parse('http://rubyforge.org/') + + jar = WWW::Mechanize::CookieJar.new + assert_equal(0, jar.cookies(url).length) + + # Add one cookie with an expiration date in the future + cookie = cookie_from_hash(values) + jar.add(url, cookie) + assert_equal(1, jar.cookies(url).length) + + # Add the same cookie, and we should still only have one + jar.add(url, cookie_from_hash(values)) + assert_equal(1, jar.cookies(url).length) + + # Make sure we can get the cookie from different paths + assert_equal(1, jar.cookies(URI.parse('http://rubyforge.org/login')).length) + + # Make sure we can't get the cookie from different domains + assert_equal(0, jar.cookies(URI.parse('http://google.com/')).length) + end + + def test_add_multiple_cookies + values = { :name => 'Foo', + :value => 'Bar', + :path => '/', + :expires => Time.now + (10 * 86400), + :domain => 'rubyforge.org' + } + url = URI.parse('http://rubyforge.org/') + + jar = WWW::Mechanize::CookieJar.new + assert_equal(0, jar.cookies(url).length) + + # Add one cookie with an expiration date in the future + cookie = cookie_from_hash(values) + jar.add(url, cookie) + assert_equal(1, jar.cookies(url).length) + + # Add the same cookie, and we should still only have one + jar.add(url, cookie_from_hash(values.merge( :name => 'Baz' ))) + assert_equal(2, jar.cookies(url).length) + + # Make sure we can get the cookie from different paths + assert_equal(2, jar.cookies(URI.parse('http://rubyforge.org/login')).length) + + # Make sure we can't get the cookie from different domains + assert_equal(0, jar.cookies(URI.parse('http://google.com/')).length) + end + + def test_clear_cookies + values = { :name => 'Foo', + :value => 'Bar', + :path => '/', + :expires => Time.now + (10 * 86400), + :domain => 'rubyforge.org' + } + url = URI.parse('http://rubyforge.org/') + + jar = WWW::Mechanize::CookieJar.new + assert_equal(0, jar.cookies(url).length) + + # Add one cookie with an expiration date in the future + cookie = cookie_from_hash(values) + jar.add(url, cookie) + jar.add(url, cookie_from_hash(values.merge( :name => 'Baz' ))) + assert_equal(2, jar.cookies(url).length) + + jar.clear! + + assert_equal(0, jar.cookies(url).length) + end + + def test_save_cookies + values = { :name => 'Foo', + :value => 'Bar', + :path => '/', + :expires => Time.now + (10 * 86400), + :domain => 'rubyforge.org' + } + url = URI.parse('http://rubyforge.org/') + + jar = WWW::Mechanize::CookieJar.new + assert_equal(0, jar.cookies(url).length) + + # Add one cookie with an expiration date in the future + cookie = cookie_from_hash(values) + jar.add(url, cookie) + jar.add(url, cookie_from_hash(values.merge( :name => 'Baz' ))) + assert_equal(2, jar.cookies(url).length) + + jar.save_as("cookies.yml") + jar.clear! + assert_equal(0, jar.cookies(url).length) + + jar.load("cookies.yml") + assert_equal(2, jar.cookies(url).length) + FileUtils.rm("cookies.yml") + end + + def test_expire_cookies + values = { :name => 'Foo', + :value => 'Bar', + :path => '/', + :expires => Time.now + (10 * 86400), + :domain => 'rubyforge.org' + } + url = URI.parse('http://rubyforge.org/') + + jar = WWW::Mechanize::CookieJar.new + assert_equal(0, jar.cookies(url).length) + + # Add one cookie with an expiration date in the future + cookie = cookie_from_hash(values) + jar.add(url, cookie) + assert_equal(1, jar.cookies(url).length) + + # Add a second cookie + jar.add(url, cookie_from_hash(values.merge( :name => 'Baz' ))) + assert_equal(2, jar.cookies(url).length) + + # Make sure we can get the cookie from different paths + assert_equal(2, jar.cookies(URI.parse('http://rubyforge.org/login')).length) + + # Expire the first cookie + jar.add(url, cookie_from_hash(values.merge( :expires => Time.now - (10 * 86400)))) + assert_equal(1, jar.cookies(url).length) + + # Expire the second cookie + jar.add(url, cookie_from_hash(values.merge( :name => 'Baz', + :expires => Time.now - (10 * 86400)))) + assert_equal(0, jar.cookies(url).length) + end + + def test_session_cookies + values = { :name => 'Foo', + :value => 'Bar', + :path => '/', + :expires => nil, + :domain => 'rubyforge.org' + } + url = URI.parse('http://rubyforge.org/') + + jar = WWW::Mechanize::CookieJar.new + assert_equal(0, jar.cookies(url).length) + + # Add one cookie with an expiration date in the future + cookie = cookie_from_hash(values) + jar.add(url, cookie) + assert_equal(1, jar.cookies(url).length) + + # Add a second cookie + jar.add(url, cookie_from_hash(values.merge( :name => 'Baz' ))) + assert_equal(2, jar.cookies(url).length) + + # Make sure we can get the cookie from different paths + assert_equal(2, jar.cookies(URI.parse('http://rubyforge.org/login')).length) + + # Expire the first cookie + jar.add(url, cookie_from_hash(values.merge( :expires => Time.now - (10 * 86400)))) + assert_equal(1, jar.cookies(url).length) + + # Expire the second cookie + jar.add(url, cookie_from_hash(values.merge( :name => 'Baz', + :expires => Time.now - (10 * 86400)))) + assert_equal(0, jar.cookies(url).length) + + # When given a URI with a blank path, CookieJar#cookies should return + # cookies with the path '/': + url = URI.parse('http://rubyforge.org') + assert_equal '', url.path + assert_equal(0, jar.cookies(url).length) + # Now add a cookie with the path set to '/': + jar.add(url, cookie_from_hash(values.merge( :name => 'has_root_path', + :path => '/'))) + assert_equal(1, jar.cookies(url).length) + end + + def test_paths + values = { :name => 'Foo', + :value => 'Bar', + :path => '/login', + :expires => nil, + :domain => 'rubyforge.org' + } + url = URI.parse('http://rubyforge.org/login') + + jar = WWW::Mechanize::CookieJar.new + assert_equal(0, jar.cookies(url).length) + + # Add one cookie with an expiration date in the future + cookie = cookie_from_hash(values) + jar.add(url, cookie) + assert_equal(1, jar.cookies(url).length) + + # Add a second cookie + jar.add(url, cookie_from_hash(values.merge( :name => 'Baz' ))) + assert_equal(2, jar.cookies(url).length) + + # Make sure we don't get the cookie in a different path + assert_equal(0, jar.cookies(URI.parse('http://rubyforge.org/hello')).length) + assert_equal(0, jar.cookies(URI.parse('http://rubyforge.org/')).length) + + # Expire the first cookie + jar.add(url, cookie_from_hash(values.merge( :expires => Time.now - (10 * 86400)))) + assert_equal(1, jar.cookies(url).length) + + # Expire the second cookie + jar.add(url, cookie_from_hash(values.merge( :name => 'Baz', + :expires => Time.now - (10 * 86400)))) + assert_equal(0, jar.cookies(url).length) + end + + + def test_save_and_read_cookiestxt + values = { :name => 'Foo', + :value => 'Bar', + :path => '/', + :expires => Time.now + (10 * 86400), + :domain => 'rubyforge.org' + } + url = URI.parse('http://rubyforge.org/') + + jar = WWW::Mechanize::CookieJar.new + assert_equal(0, jar.cookies(url).length) + + # Add one cookie with an expiration date in the future + cookie = cookie_from_hash(values) + jar.add(url, cookie) + jar.add(url, cookie_from_hash(values.merge( :name => 'Baz' ))) + assert_equal(2, jar.cookies(url).length) + + jar.save_as("cookies.txt", :cookiestxt) + jar.clear! + assert_equal(0, jar.cookies(url).length) + + jar.load("cookies.txt", :cookiestxt) + assert_equal(2, jar.cookies(url).length) + + FileUtils.rm("cookies.txt") + end + + def test_ssl_cookies + # thanks to michal "ocher" ochman for reporting the bug responsible for this test. + values = { :name => 'Foo', + :value => 'Bar', + :path => '/login', + :expires => nil, + :domain => 'rubyforge.org' + } + values_ssl = { :name => 'Foo', + :value => 'Bar', + :path => '/login', + :expires => nil, + :domain => 'rubyforge.org:443' + } + url = URI.parse('https://rubyforge.org/login') + + jar = WWW::Mechanize::CookieJar.new + assert_equal(0, jar.cookies(url).length) + + cookie = cookie_from_hash(values) + jar.add(url, cookie) + assert_equal(1, jar.cookies(url).length, "did not handle SSL cookie") + + cookie = cookie_from_hash(values_ssl) + jar.add(url, cookie) + assert_equal(2, jar.cookies(url).length, "did not handle SSL cookie with :443") + end + +end diff --git a/vendor/gems/mechanize-0.9.0/test/test_cookies.rb b/vendor/gems/mechanize-0.9.0/test/test_cookies.rb new file mode 100644 index 0000000..46f8cd6 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_cookies.rb @@ -0,0 +1,123 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) + +class CookiesMechTest < Test::Unit::TestCase + def setup + @agent = WWW::Mechanize.new + end + + def test_meta_tag_cookies + cookies = @agent.cookies.length + page = @agent.get("http://localhost/meta_cookie.html") + assert_equal(cookies + 1, @agent.cookies.length) + end + + def test_send_cookies + page = @agent.get("http://localhost/many_cookies") + page = @agent.get("http://localhost/send_cookies") + assert_equal(3, page.links.length) + assert_not_nil(page.links.find { |l| l.text == "name:Aaron" }) + assert_not_nil(page.links.find { |l| l.text == "no_expires:nope" }) + end + + def test_no_space_cookies + page = @agent.get("http://localhost/one_cookie_no_space") + assert_equal(1, @agent.cookies.length) + foo_cookie = @agent.cookies.find { |k| k.name == 'foo' } + assert_not_nil(foo_cookie, 'Foo cookie was nil') + assert_equal('bar', foo_cookie.value) + assert_equal('/', foo_cookie.path) + assert_equal(true, Time.now < foo_cookie.expires) + end + + def test_many_cookies_as_string + page = @agent.get("http://localhost/many_cookies_as_string") + assert_equal(4, @agent.cookies.length) + + name_cookie = @agent.cookies.find { |k| k.name == "name" } + assert_not_nil(name_cookie, "Name cookie was nil") + assert_equal("Aaron", name_cookie.value) + assert_equal("/", name_cookie.path) + assert_equal(true, Time.now < name_cookie.expires) + + expired_cookie = @agent.cookies.find { |k| k.name == "expired" } + assert_nil(expired_cookie, "Expired cookie was not nil") + + no_exp_cookie = @agent.cookies.find { |k| k.name == "no_expires" } + assert_not_nil(no_exp_cookie, "No expires cookie is nil") + assert_equal("nope", no_exp_cookie.value) + assert_equal("/", no_exp_cookie.path) + assert_nil(no_exp_cookie.expires) + + path_cookie = @agent.cookies.find { |k| k.name == "a_path" } + assert_not_nil(path_cookie, "Path cookie is nil") + assert_equal("some_path", path_cookie.value) + assert_equal(true, Time.now < path_cookie.expires) + + no_path_cookie = @agent.cookies.find { |k| k.name == "no_path" } + assert_not_nil(no_path_cookie, "No path cookie is nil") + assert_equal("no_path", no_path_cookie.value) + assert_equal("/", no_path_cookie.path) + assert_equal(true, Time.now < no_path_cookie.expires) + end + + def test_many_cookies + page = @agent.get("http://localhost/many_cookies") + assert_equal(4, @agent.cookies.length) + + name_cookie = @agent.cookies.find { |k| k.name == "name" } + assert_not_nil(name_cookie, "Name cookie was nil") + assert_equal("Aaron", name_cookie.value) + assert_equal("/", name_cookie.path) + assert_equal(true, Time.now < name_cookie.expires) + + expired_cookie = @agent.cookies.find { |k| k.name == "expired" } + assert_nil(expired_cookie, "Expired cookie was not nil") + + no_exp_cookie = @agent.cookies.find { |k| k.name == "no_expires" } + assert_not_nil(no_exp_cookie, "No expires cookie is nil") + assert_equal("nope", no_exp_cookie.value) + assert_equal("/", no_exp_cookie.path) + assert_nil(no_exp_cookie.expires) + + path_cookie = @agent.cookies.find { |k| k.name == "a_path" } + assert_not_nil(path_cookie, "Path cookie is nil") + assert_equal("some_path", path_cookie.value) + assert_equal(true, Time.now < path_cookie.expires) + + no_path_cookie = @agent.cookies.find { |k| k.name == "no_path" } + assert_not_nil(no_path_cookie, "No path cookie is nil") + assert_equal("no_path", no_path_cookie.value) + assert_equal("/", no_path_cookie.path) + assert_equal(true, Time.now < no_path_cookie.expires) + end + + def test_get_cookie + assert_equal(true, + @agent.cookie_jar.empty?( + URI::parse("http://localhost/one_cookie"))) + + assert_equal(0, @agent.cookies.length) + + page = @agent.get("http://localhost/one_cookie") + assert_equal(1, @agent.cookies.length) + + cookie = @agent.cookies.first + assert_equal("foo", cookie.name) + assert_equal("bar", cookie.value) + assert_equal("/", cookie.path) + assert_equal("localhost", cookie.domain) + + assert_equal(false, + @agent.cookie_jar.empty?( + URI::parse("http://localhost/one_cookie"))) + page = @agent.get("http://localhost/one_cookie") + + assert_equal(1, @agent.cookies.length) + + cookie = @agent.cookies.first + assert_equal("foo", cookie.name) + assert_equal("bar", cookie.value) + assert_equal("/", cookie.path) + assert_equal("localhost", cookie.domain) + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/test_encoded_links.rb b/vendor/gems/mechanize-0.9.0/test/test_encoded_links.rb new file mode 100644 index 0000000..cced078 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_encoded_links.rb @@ -0,0 +1,20 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) + +class TestEncodedLinks < Test::Unit::TestCase + def setup + @agent = WWW::Mechanize.new + @page = @agent.get("http://localhost/tc_encoded_links.html") + end + + def test_click_link + link = @page.links.first + assert_equal('/form_post?a=b&b=c', link.href) + page = @agent.click(link) + assert_equal("http://localhost/form_post?a=b&b=c", page.uri.to_s) + end + + def test_hpricot_link + page = @agent.click(@page.search('a').first) + assert_equal("http://localhost/form_post?a=b&b=c", page.uri.to_s) + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/test_errors.rb b/vendor/gems/mechanize-0.9.0/test/test_errors.rb new file mode 100644 index 0000000..c912c11 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_errors.rb @@ -0,0 +1,49 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) + +class MechErrorsTest < Test::Unit::TestCase + def setup + @agent = WWW::Mechanize.new + end + + def test_bad_form_method + page = @agent.get("http://localhost/bad_form_test.html") + assert_raise(RuntimeError) { + @agent.submit(page.forms.first) + } + end + + def test_non_exist + begin + page = @agent.get("http://localhost/bad_form_test.html") + rescue RuntimeError => ex + assert_equal("404", ex.inspect) + end + end + + def test_too_many_radio + page = @agent.get("http://localhost/form_test.html") + form = page.form_with(:name => 'post_form1') + form.radiobuttons.each { |r| r.checked = true } + assert_raise(RuntimeError) { + @agent.submit(form) + } + end + + def test_unknown_agent + assert_raise(RuntimeError) { + @agent.user_agent_alias = "Aaron's Browser" + } + end + + def test_bad_url + assert_raise(RuntimeError) { + @agent.get('/foo.html') + } + end + + def test_unsupported_scheme + assert_raise(WWW::Mechanize::UnsupportedSchemeError) { + @agent.get('ftp://server.com/foo.html') + } + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/test_follow_meta.rb b/vendor/gems/mechanize-0.9.0/test/test_follow_meta.rb new file mode 100644 index 0000000..8de0b0e --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_follow_meta.rb @@ -0,0 +1,69 @@ +require File.expand_path(File.join(File.dirname(__FILE__), 'helper')) + +class FollowMetaTest < Test::Unit::TestCase + def setup + @agent = WWW::Mechanize.new + end + + def test_dont_follow_meta_by_default + page = @agent.get('http://localhost/tc_follow_meta.html') + assert_equal('http://localhost/tc_follow_meta.html', page.uri.to_s) + assert_equal(1, page.meta.length) + end + + def test_follow_meta_if_set + @agent.follow_meta_refresh = true + + page = @agent.get('http://localhost/tc_follow_meta.html') + + assert_equal(2, @agent.history.length) + assert_equal('http://localhost/tc_follow_meta.html', + @agent.history[0].uri.to_s) + assert_equal('http://localhost/index.html', page.uri.to_s) + assert_equal('http://localhost/index.html', @agent.history.last.uri.to_s) + end + + def test_always_follow_302 + @agent.follow_meta_refresh = false + page = @agent.get('http://localhost/response_code?code=302&ct=test/xml') + assert_equal('http://localhost/index.html', page.uri.to_s) + assert_equal(2, @agent.history.length) + end + + def test_infinite_refresh_throws_exception + @agent.follow_meta_refresh = true + assert_raises(WWW::Mechanize::RedirectLimitReachedError) { + begin + @agent.get('http://localhost/infinite_refresh') + rescue WWW::Mechanize::RedirectLimitReachedError => ex + raise ex + end + } + end + + def test_dont_honor_http_refresh_by_default + page = @agent.get('http://localhost/http_refresh?refresh_time=0') + assert_equal('http://localhost/http_refresh?refresh_time=0', page.uri.to_s) + end + + def test_honor_http_refresh_if_set + @agent.follow_meta_refresh = true + page = @agent.get('http://localhost/http_refresh?refresh_time=0') + assert_equal('http://localhost/index.html', page.uri.to_s) + assert_equal(2, @agent.history.length) + end + + def test_honor_http_refresh_delay_if_set + @agent.follow_meta_refresh = true + class << @agent + attr_accessor :slept + def sleep *args + @slept = args + end + end + + page = @agent.get('http://localhost/http_refresh?refresh_time=1') + assert_equal [1], @agent.slept + end + +end diff --git a/vendor/gems/mechanize-0.9.0/test/test_form_action.rb b/vendor/gems/mechanize-0.9.0/test/test_form_action.rb new file mode 100644 index 0000000..3959bfc --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_form_action.rb @@ -0,0 +1,44 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) + +class TestFormAction < Test::Unit::TestCase + def setup + @agent = WWW::Mechanize.new + @page = @agent.get("http://localhost/tc_form_action.html") + end + + def test_post_encoded_action + form = @page.form(:name => 'post_form1') { |f| + f.first_name = "Aaron" + } + assert_equal('/form_post?a=b&b=c', form.action) + page = form.submit + assert_equal("http://localhost/form_post?a=b&b=c", page.uri.to_s) + end + + def test_get_encoded_action + form = @page.form('post_form2') { |f| + f.first_name = "Aaron" + } + assert_equal('/form_post?a=b&b=c', form.action) + page = form.submit + assert_equal("http://localhost/form_post?first_name=Aaron", page.uri.to_s) + end + + def test_post_nonencoded_action + form = @page.form('post_form3') { |f| + f.first_name = "Aaron" + } + assert_equal('/form_post?a=b&b=c', form.action) + page = form.submit + assert_equal("http://localhost/form_post?a=b&b=c", page.uri.to_s) + end + + def test_post_pound_sign + form = @page.form('post_form4') { |f| + f.first_name = "Aaron" + } + assert_equal('/form_post#1', form.action) + page = form.submit + assert_equal("http://localhost/form_post#1", page.uri.to_s) + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/test_form_as_hash.rb b/vendor/gems/mechanize-0.9.0/test/test_form_as_hash.rb new file mode 100644 index 0000000..3b276e5 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_form_as_hash.rb @@ -0,0 +1,61 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) + +class TestFormHash < Test::Unit::TestCase + def setup + @agent = WWW::Mechanize.new + @page = @agent.get('http://localhost/form_multival.html') + end + + def test_form_hash + form = @page.form_with(:name => 'post_form') + + assert_not_nil(form) + field_length = form.fields.length + assert_nil(form['intarweb']) + form['intarweb'] = 'Aaron' + + assert_not_nil(form['intarweb']) + assert_equal(field_length + 1, form.fields.length) + end + + def test_add_field_via_hash + form = @page.form_with(:name => 'post_form') + + assert_not_nil(form) + field_length = form.fields.length + assert_nil(form['intarweb']) + form['intarweb'] = 'Aaron' + + assert_not_nil(form['intarweb']) + assert_equal(field_length + 1, form.fields.length) + end + + def test_fields_as_hash + form = @page.form_with(:name => 'post_form') + + assert_not_nil(form) + assert_equal(2, form.fields_with(:name => 'first').length) + + form['first'] = 'Aaron' + assert_equal('Aaron', form['first']) + assert_equal('Aaron', form.field_with(:name => 'first').value) + end + + def test_keys + @page = @agent.get('http://localhost/empty_form.html') + form = @page.forms.first + + assert_not_nil(form) + assert_equal(false, form.has_field?('name')) + assert_equal(false, form.has_value?('Aaron')) + assert_equal(0, form.keys.length) + assert_equal(0, form.values.length) + form['name'] = 'Aaron' + assert_equal(true, form.has_field?('name')) + assert_equal(true, form.has_value?('Aaron')) + assert_equal(1, form.keys.length) + assert_equal(['name'], form.keys) + assert_equal(1, form.values.length) + assert_equal(['Aaron'], form.values) + end +end diff --git a/vendor/gems/mechanize-0.9.0/test/test_form_button.rb b/vendor/gems/mechanize-0.9.0/test/test_form_button.rb new file mode 100644 index 0000000..194fde6 --- /dev/null +++ b/vendor/gems/mechanize-0.9.0/test/test_form_button.rb @@ -0,0 +1,38 @@ +require File.expand_path(File.join(File.dirname(__FILE__), "helper")) + +class TestFormButtons < Test::Unit::TestCase + def setup + @agent = WWW::Mechanize.new + end + + def test_submit_input_tag + assert_form_contains_button('') + end + + def test_button_input_tag + assert_form_contains_button('') + end + + def test_submit_button_tag + assert_form_contains_button('