From 1c36a292c2279a8f2c44388a1b532fda5a25a85d Mon Sep 17 00:00:00 2001 From: "R. Tyler Croy" Date: Sat, 8 Dec 2012 16:04:12 -0800 Subject: [PATCH] Vendor gems to make installing the plugins work properly. The `gems:vendor` Rake task will properly pull everything needed into vendor/ruby --- Gemfile | 18 +- Gemfile.deploy | 8 + Gemfile.deploy.lock | 14 + Rakefile | 22 + init.rb | 1 + lib/sauce/heroku/cli.rb | 3 +- vendor/bundler/setup.rb | 4 + vendor/ruby/1.9.1/bin/httparty | 19 + vendor/ruby/1.9.1/cache/httparty-0.9.0.gem | Bin 0 -> 65024 bytes vendor/ruby/1.9.1/cache/multi_json-1.4.0.gem | Bin 0 -> 15360 bytes vendor/ruby/1.9.1/cache/multi_xml-0.5.1.gem | Bin 0 -> 15360 bytes .../ruby/1.9.1/gems/httparty-0.9.0/.gitignore | 10 + .../1.9.1/gems/httparty-0.9.0/.travis.yml | 8 + vendor/ruby/1.9.1/gems/httparty-0.9.0/Gemfile | 15 + .../ruby/1.9.1/gems/httparty-0.9.0/Guardfile | 16 + vendor/ruby/1.9.1/gems/httparty-0.9.0/History | 293 ++++++++ .../1.9.1/gems/httparty-0.9.0/MIT-LICENSE | 20 + .../ruby/1.9.1/gems/httparty-0.9.0/README.md | 79 ++ .../ruby/1.9.1/gems/httparty-0.9.0/Rakefile | 15 + .../1.9.1/gems/httparty-0.9.0/bin/httparty | 114 +++ .../1.9.1/gems/httparty-0.9.0/cucumber.yml | 1 + .../gems/httparty-0.9.0/examples/aaws.rb | 32 + .../gems/httparty-0.9.0/examples/basic.rb | 32 + .../gems/httparty-0.9.0/examples/crack.rb | 19 + .../httparty-0.9.0/examples/custom_parsers.rb | 67 ++ .../gems/httparty-0.9.0/examples/delicious.rb | 37 + .../gems/httparty-0.9.0/examples/google.rb | 16 + .../examples/headers_and_user_agents.rb | 6 + .../examples/nokogiri_html_parser.rb | 22 + .../gems/httparty-0.9.0/examples/rubyurl.rb | 14 + .../httparty-0.9.0/examples/tripit_sign_in.rb | 33 + .../gems/httparty-0.9.0/examples/twitter.rb | 31 + .../httparty-0.9.0/examples/whoismyrep.rb | 10 + .../features/basic_authentication.feature | 20 + .../features/command_line.feature | 7 + .../deals_with_http_error_codes.feature | 26 + .../features/digest_authentication.feature | 20 + .../handles_compressed_responses.feature | 19 + .../features/handles_multiple_formats.feature | 34 + .../gems/httparty-0.9.0/features/steps/env.rb | 22 + .../features/steps/httparty_response_steps.rb | 26 + .../features/steps/httparty_steps.rb | 27 + .../features/steps/mongrel_helper.rb | 94 +++ .../features/steps/remote_service_steps.rb | 69 ++ .../features/supports_redirection.feature | 22 + .../features/supports_timeout_option.feature | 13 + .../gems/httparty-0.9.0/httparty.gemspec | 24 + .../1.9.1/gems/httparty-0.9.0/lib/httparty.rb | 503 +++++++++++++ .../lib/httparty/connection_adapter.rb | 116 +++ .../lib/httparty/cookie_hash.rb | 22 + .../lib/httparty/core_extensions.rb | 32 + .../httparty-0.9.0/lib/httparty/exceptions.rb | 26 + .../lib/httparty/hash_conversions.rb | 51 ++ .../httparty/module_inheritable_attributes.rb | 44 ++ .../lib/httparty/net_digest_auth.rb | 84 +++ .../httparty-0.9.0/lib/httparty/parser.rb | 145 ++++ .../httparty-0.9.0/lib/httparty/request.rb | 239 ++++++ .../httparty-0.9.0/lib/httparty/response.rb | 62 ++ .../lib/httparty/response/headers.rb | 31 + .../httparty-0.9.0/lib/httparty/version.rb | 3 + .../spec/fixtures/delicious.xml | 23 + .../httparty-0.9.0/spec/fixtures/empty.xml | 0 .../httparty-0.9.0/spec/fixtures/google.html | 3 + .../spec/fixtures/ssl/generate.sh | 29 + .../spec/fixtures/ssl/generated/1fe462c2.0 | 16 + .../spec/fixtures/ssl/generated/bogushost.crt | 13 + .../spec/fixtures/ssl/generated/ca.crt | 16 + .../spec/fixtures/ssl/generated/ca.key | 15 + .../fixtures/ssl/generated/selfsigned.crt | 14 + .../spec/fixtures/ssl/generated/server.crt | 13 + .../spec/fixtures/ssl/generated/server.key | 15 + .../spec/fixtures/ssl/openssl-exts.cnf | 9 + .../httparty-0.9.0/spec/fixtures/twitter.json | 1 + .../httparty-0.9.0/spec/fixtures/twitter.xml | 403 ++++++++++ .../undefined_method_add_node_for_nil.xml | 2 + .../spec/httparty/connection_adapter_spec.rb | 206 +++++ .../spec/httparty/cookie_hash_spec.rb | 70 ++ .../spec/httparty/net_digest_auth_spec.rb | 115 +++ .../spec/httparty/parser_spec.rb | 171 +++++ .../spec/httparty/request_spec.rb | 495 ++++++++++++ .../spec/httparty/response_spec.rb | 214 ++++++ .../httparty-0.9.0/spec/httparty/ssl_spec.rb | 62 ++ .../gems/httparty-0.9.0/spec/httparty_spec.rb | 703 ++++++++++++++++++ .../1.9.1/gems/httparty-0.9.0/spec/spec.opts | 2 + .../gems/httparty-0.9.0/spec/spec_helper.rb | 30 + .../spec/support/ssl_test_helper.rb | 47 ++ .../spec/support/ssl_test_server.rb | 80 ++ .../spec/support/stub_response.rb | 43 ++ .../httparty-0.9.0/website/css/common.css | 47 ++ .../gems/httparty-0.9.0/website/index.html | 73 ++ .../1.9.1/gems/multi_json-1.4.0/.document | 5 + .../ruby/1.9.1/gems/multi_json-1.4.0/.rspec | 3 + .../1.9.1/gems/multi_json-1.4.0/.travis.yml | 10 + .../ruby/1.9.1/gems/multi_json-1.4.0/Gemfile | 7 + .../1.9.1/gems/multi_json-1.4.0/LICENSE.md | 20 + .../1.9.1/gems/multi_json-1.4.0/README.md | 72 ++ .../ruby/1.9.1/gems/multi_json-1.4.0/Rakefile | 20 + .../gems/multi_json-1.4.0/lib/multi_json.rb | 122 +++ .../lib/multi_json/adapters/json_common.rb | 25 + .../lib/multi_json/adapters/json_gem.rb | 12 + .../lib/multi_json/adapters/json_pure.rb | 12 + .../adapters/nsjsonserialization.rb | 34 + .../lib/multi_json/adapters/oj.rb | 26 + .../lib/multi_json/adapters/ok_json.rb | 48 ++ .../lib/multi_json/adapters/yajl.rb | 18 + .../lib/multi_json/vendor/okjson.rb | 602 +++++++++++++++ .../lib/multi_json/version.rb | 3 + .../gems/multi_json-1.4.0/multi_json.gemspec | 23 + .../spec/adapter_shared_example.rb | 123 +++ .../gems/multi_json-1.4.0/spec/helper.rb | 39 + .../multi_json-1.4.0/spec/multi_json_spec.rb | 89 +++ .../ruby/1.9.1/gems/multi_xml-0.5.1/.gemtest | 0 .../1.9.1/gems/multi_xml-0.5.1/.gitignore | 9 + vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.rspec | 2 + .../1.9.1/gems/multi_xml-0.5.1/.travis.yml | 9 + .../ruby/1.9.1/gems/multi_xml-0.5.1/.yardopts | 5 + .../ruby/1.9.1/gems/multi_xml-0.5.1/Gemfile | 9 + .../1.9.1/gems/multi_xml-0.5.1/LICENSE.md | 20 + .../ruby/1.9.1/gems/multi_xml-0.5.1/README.md | 126 ++++ .../ruby/1.9.1/gems/multi_xml-0.5.1/Rakefile | 21 + .../gems/multi_xml-0.5.1/lib/multi_xml.rb | 274 +++++++ .../lib/multi_xml/parsers/libxml.rb | 30 + .../lib/multi_xml/parsers/libxml2_parser.rb | 66 ++ .../lib/multi_xml/parsers/nokogiri.rb | 32 + .../lib/multi_xml/parsers/ox.rb | 97 +++ .../lib/multi_xml/parsers/rexml.rb | 113 +++ .../multi_xml-0.5.1/lib/multi_xml/version.rb | 3 + .../gems/multi_xml-0.5.1/multi_xml.gemspec | 21 + .../1.9.1/gems/multi_xml-0.5.1/spec/helper.rb | 7 + .../multi_xml-0.5.1/spec/multi_xml_spec.rb | 46 ++ .../spec/parser_shared_example.rb | 677 +++++++++++++++++ .../1.9.1/gems/multi_xml-0.5.1/spec/speed.rb | 63 ++ .../specifications/httparty-0.9.0.gemspec | 34 + .../specifications/multi_json-1.4.0.gemspec | 41 + .../specifications/multi_xml-0.5.1.gemspec | 40 + 135 files changed, 8741 insertions(+), 7 deletions(-) create mode 100644 Gemfile.deploy create mode 100644 Gemfile.deploy.lock create mode 100644 vendor/bundler/setup.rb create mode 100755 vendor/ruby/1.9.1/bin/httparty create mode 100644 vendor/ruby/1.9.1/cache/httparty-0.9.0.gem create mode 100644 vendor/ruby/1.9.1/cache/multi_json-1.4.0.gem create mode 100644 vendor/ruby/1.9.1/cache/multi_xml-0.5.1.gem create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/.gitignore create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/.travis.yml create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/Gemfile create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/Guardfile create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/History create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/MIT-LICENSE create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/README.md create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/Rakefile create mode 100755 vendor/ruby/1.9.1/gems/httparty-0.9.0/bin/httparty create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/cucumber.yml create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/aaws.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/basic.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/crack.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/custom_parsers.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/delicious.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/google.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/headers_and_user_agents.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/nokogiri_html_parser.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/rubyurl.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/tripit_sign_in.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/twitter.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/whoismyrep.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/basic_authentication.feature create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/command_line.feature create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/deals_with_http_error_codes.feature create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/digest_authentication.feature create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/handles_compressed_responses.feature create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/handles_multiple_formats.feature create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/env.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/httparty_response_steps.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/httparty_steps.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/mongrel_helper.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/remote_service_steps.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/supports_redirection.feature create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/features/supports_timeout_option.feature create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/httparty.gemspec create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/connection_adapter.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/cookie_hash.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/core_extensions.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/exceptions.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/hash_conversions.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/module_inheritable_attributes.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/net_digest_auth.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/parser.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/request.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/response.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/response/headers.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/version.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/delicious.xml create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/empty.xml create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/google.html create mode 100755 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generate.sh create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/1fe462c2.0 create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/bogushost.crt create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/ca.crt create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/ca.key create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/selfsigned.crt create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/server.crt create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/server.key create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/openssl-exts.cnf create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/twitter.json create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/twitter.xml create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/undefined_method_add_node_for_nil.xml create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/connection_adapter_spec.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/cookie_hash_spec.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/net_digest_auth_spec.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/parser_spec.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/request_spec.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/response_spec.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/ssl_spec.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty_spec.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/spec.opts create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/spec_helper.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/support/ssl_test_helper.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/support/ssl_test_server.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/support/stub_response.rb create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/website/css/common.css create mode 100644 vendor/ruby/1.9.1/gems/httparty-0.9.0/website/index.html create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/.document create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/.rspec create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/.travis.yml create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/Gemfile create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/LICENSE.md create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/README.md create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/Rakefile create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/json_common.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/json_gem.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/json_pure.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/nsjsonserialization.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/oj.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/ok_json.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/yajl.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/vendor/okjson.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/version.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/multi_json.gemspec create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/spec/adapter_shared_example.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/spec/helper.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_json-1.4.0/spec/multi_json_spec.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.gemtest create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.gitignore create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.rspec create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.travis.yml create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.yardopts create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/Gemfile create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/LICENSE.md create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/README.md create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/Rakefile create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/libxml.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/libxml2_parser.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/nokogiri.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/ox.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/rexml.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/version.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/multi_xml.gemspec create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/helper.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/multi_xml_spec.rb create mode 100644 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/parser_shared_example.rb create mode 100755 vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/speed.rb create mode 100644 vendor/ruby/1.9.1/specifications/httparty-0.9.0.gemspec create mode 100644 vendor/ruby/1.9.1/specifications/multi_json-1.4.0.gemspec create mode 100644 vendor/ruby/1.9.1/specifications/multi_xml-0.5.1.gemspec diff --git a/Gemfile b/Gemfile index 96c32f5..b088ce1 100644 --- a/Gemfile +++ b/Gemfile @@ -1,10 +1,16 @@ -source :gemcutter +source :rubygems -gem 'rake' -gem 'heroku' -gem 'sauce' -gem 'launchy' -gem 'httparty', :path => 'vendor/httparty' +# This group is for vendoring changes for a "release" +group :vendor do + gem 'httparty' +end + +group :development do + gem 'rake' + gem 'heroku' + gem 'sauce' + gem 'launchy' +end group :test do gem 'rspec' diff --git a/Gemfile.deploy b/Gemfile.deploy new file mode 100644 index 0000000..153a310 --- /dev/null +++ b/Gemfile.deploy @@ -0,0 +1,8 @@ +source :rubygems + +# This group is for vendoring changes for a "release" +group :vendor do + gem 'httparty' +end + +# vim: ft=ruby diff --git a/Gemfile.deploy.lock b/Gemfile.deploy.lock new file mode 100644 index 0000000..7c94879 --- /dev/null +++ b/Gemfile.deploy.lock @@ -0,0 +1,14 @@ +GEM + remote: http://rubygems.org/ + specs: + httparty (0.9.0) + multi_json (~> 1.0) + multi_xml + multi_json (1.4.0) + multi_xml (0.5.1) + +PLATFORMS + ruby + +DEPENDENCIES + httparty diff --git a/Rakefile b/Rakefile index f4f2317..0016d29 100644 --- a/Rakefile +++ b/Rakefile @@ -7,3 +7,25 @@ RSpec::Core::RakeTask.new('spec') do |t| end Cucumber::Rake::Task.new('cucumber') + + +BUNDLER_VARS = %w(BUNDLE_GEMFILE RUBYOPT GEM_HOME) + def with_clean_env + begin + bundled_env = ENV.to_hash + BUNDLER_VARS.each{ |var| ENV.delete(var) } + yield + ensure + ENV.replace(bundled_env.to_hash) + end + end + +namespace :gems do + desc 'Vendor the gems in Gemfile.deploy' + task :vendor do + with_clean_env do + sh 'bundle install --deployment --standalone=vendor --gemfile=Gemfile.deploy --path=vendor' + sh 'bundle install --no-deployment' + end + end +end diff --git a/init.rb b/init.rb index 28a188c..db05daf 100644 --- a/init.rb +++ b/init.rb @@ -1 +1,2 @@ +require File.expand_path(File.dirname(__FILE__) + '/vendor/bundler/setup.rb') require 'sauce/heroku/cli' diff --git a/lib/sauce/heroku/cli.rb b/lib/sauce/heroku/cli.rb index 6edffd9..1411739 100644 --- a/lib/sauce/heroku/cli.rb +++ b/lib/sauce/heroku/cli.rb @@ -1,7 +1,8 @@ require 'heroku' require 'heroku/command/base' require 'httparty' -require 'sauce' +require 'json' +#require 'sauce' require 'yaml' module Heroku diff --git a/vendor/bundler/setup.rb b/vendor/bundler/setup.rb new file mode 100644 index 0000000..829184f --- /dev/null +++ b/vendor/bundler/setup.rb @@ -0,0 +1,4 @@ +path = File.expand_path('..', __FILE__) +$:.unshift File.expand_path("#{path}/../ruby/1.9.1/gems/multi_json-1.4.0/lib") +$:.unshift File.expand_path("#{path}/../ruby/1.9.1/gems/multi_xml-0.5.1/lib") +$:.unshift File.expand_path("#{path}/../ruby/1.9.1/gems/httparty-0.9.0/lib") diff --git a/vendor/ruby/1.9.1/bin/httparty b/vendor/ruby/1.9.1/bin/httparty new file mode 100755 index 0000000..7c671f5 --- /dev/null +++ b/vendor/ruby/1.9.1/bin/httparty @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +# +# This file was generated by RubyGems. +# +# The application 'httparty' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'httparty', version +load Gem.bin_path('httparty', 'httparty', version) diff --git a/vendor/ruby/1.9.1/cache/httparty-0.9.0.gem b/vendor/ruby/1.9.1/cache/httparty-0.9.0.gem new file mode 100644 index 0000000000000000000000000000000000000000..62f851dff6bbbec5f40093477c9325df1175f96c GIT binary patch literal 65024 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 Wmrn8jt=4}d@ZSjhHv<2^2>cILFrD@Q literal 0 HcmV?d00001 diff --git a/vendor/ruby/1.9.1/cache/multi_json-1.4.0.gem b/vendor/ruby/1.9.1/cache/multi_json-1.4.0.gem new file mode 100644 index 0000000000000000000000000000000000000000..b5709ff77a895ff3870c4b14e193c9ea0dc43a63 GIT binary patch literal 15360 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 literal 0 HcmV?d00001 diff --git a/vendor/ruby/1.9.1/cache/multi_xml-0.5.1.gem b/vendor/ruby/1.9.1/cache/multi_xml-0.5.1.gem new file mode 100644 index 0000000000000000000000000000000000000000..27d7aa83013adcc90a75b8f5f66536876242e28c GIT binary patch literal 15360 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 Lzcujxp$7gNJ#1o- literal 0 HcmV?d00001 diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/.gitignore b/vendor/ruby/1.9.1/gems/httparty-0.9.0/.gitignore new file mode 100644 index 0000000..24953a8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/.gitignore @@ -0,0 +1,10 @@ +Gemfile.lock +.DS_Store +.yardoc/ +doc/ +tmp/ +log/ +pkg/ +*.swp +/.bundle +.rvmrc diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/.travis.yml b/vendor/ruby/1.9.1/gems/httparty-0.9.0/.travis.yml new file mode 100644 index 0000000..5d2b2c2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/.travis.yml @@ -0,0 +1,8 @@ +language: ruby +rvm: + - 1.8.7 + - ree + - 1.9.3 +notifications: + email: false +bundler_args: --without development diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/Gemfile b/vendor/ruby/1.9.1/gems/httparty-0.9.0/Gemfile new file mode 100644 index 0000000..0918e93 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/Gemfile @@ -0,0 +1,15 @@ +source :rubygems +gemspec + +gem 'rake' +gem 'cucumber', '~> 0.7' +gem 'fakeweb', '~> 1.2' +gem 'rspec', '~> 1.3' +gem 'mongrel', '1.2.0.pre2' +gem 'multi_json', '~> 1.3' + +group :development do + gem 'guard' + gem 'guard-rspec' + gem 'guard-bundler' +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/Guardfile b/vendor/ruby/1.9.1/gems/httparty-0.9.0/Guardfile new file mode 100644 index 0000000..fdb6013 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/Guardfile @@ -0,0 +1,16 @@ +rspec_options = { + :version => 1, + :all_after_pass => false, + :all_on_start => false, +} + +guard 'rspec', rspec_options do + watch(%r{^spec/.+_spec\.rb$}) + watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } + watch('spec/spec_helper.rb') { "spec" } +end + +guard 'bundler' do + watch('Gemfile') + watch(/^.+\.gemspec/) +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/History b/vendor/ruby/1.9.1/gems/httparty-0.9.0/History new file mode 100644 index 0000000..09c2049 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/History @@ -0,0 +1,293 @@ +== 0.9.0 2012-09-07 +* new + * [support for connection adapters](https://github.com/jnunemaker/httparty/pull/157) + * [allow ssl_version on ruby 1.9](https://github.com/jnunemaker/httparty/pull/159) + +* bug fixes + * [don't treat port 4430 as ssl](https://github.com/jnunemaker/httparty/commit/a296b1c97f83d7dcc6ef85720a43664c265685ac) + * [deep clone default options](https://github.com/jnunemaker/httparty/commit/f74227d30f9389b4b23a888c9af49fb9b8248e1f) + * a few net digest auth fixes + +== 0.8.3 2012-04-21 +* new + * [lazy parsing of responses](https://github.com/jnunemaker/httparty/commit/9fd5259c8dab00e426082b66af44ede2c9068f45) + * [add support for PATCH requests](https://github.com/jnunemaker/httparty/commit/7ab6641e37a9e31517e46f6124f38c615395d38a) +* bug fixes + * [subclasses no longer override superclass options](https://github.com/jnunemaker/httparty/commit/682af8fbf672e7b3009e650da776c85cdfe78d39) + +== 0.8.2 2012-04-12 +* new + * add -r to make CLI return failure code if status >= 400 + * allow blank username from CLI +* bug fixes + * return nil for null body + * automatically deflate responses with a Content-Encoding: x-gzip header + * Do not HEAD on POST request with digest authentication + * add support for proxy authentication + * fix posting data with CLI + * require rexml/document if xml format from CLI + * support for fragmented responses + +== 0.8.1 2011-10-05 +* bug fixes + * content-encoding header should be removed when automatically inflating the body + +== 0.8.0 2011-09-13 +* new + * switch to multi json/xml for parsing by default +* bug fixes + * fix redirects to relative uri's + +== 0.7.8 2011-06-06 +* bug fix + * Make response honor respond to + * net http timeout can also be a float + +== 0.7.7 2011-04-16 +* bug fix + * Fix NoMethodError when using the NON_RAILS_QUERY_STRING_NORMALIZER with a hash whose key is a symbol and value is nil + +== 0.7.5 2011-04-16 +* bug fix + * caused issue with latest rubygems + +== 0.7.4 2011-02-13 +* bug fixes + * Set VERIFY_NONE when using https. Ruby 1.9.2 no longer sets this for us. gh-67 + +== 0.7.3 2011-01-20 +* bug fixes + * Fix digest auth for unspecified quality of protection (bjoernalbers, mtrudel, dwo) + +== 0.7.2 2011-01-20 +* bug fixes + * Fix gem dependencies + +== 0.7.1 2011-01-19 +* bug fixes + * Fix uninitialized constant HTTParty::Response::Net in 1.9.2 (cap10morgan) + * Other fixes for 1.9.2, full suite still fails (cap10morgan) + +== 0.7.0 2011-01-18 +* minor enhancements + * Added query methods for HTTP status codes, i.e. response.success? + response.created? (thanks citizenparker) + * Added support for ssl_ca_file and ssl_ca_path (dlitz) + * Allow custom query string normalization. gh-8 + * Unlock private keys with password (freerange) + * Added high level request documentation (phildarnowsky) + * Added basic post example (pbuckley) + * Response object has access to its corresponding request object + * Added example of siginin into tripit.com + * Added option to follow redirects (rkj). gh-56 +* bug fixes + * Fixed superclass mismatch exception while running tests + (thanks dlitz http://github.com/dlitz/httparty/commit/48224f0615b32133afcff4718ad426df7a4b401b) + +== 0.6.1 2010-07-07 +* minor enhancements + * updated to crack 0.1.8 +* bug fixes + * subclasses always merge into the parent's default_options and + default_cookies (l4rk). + * subclasses play nicely with grand parents. gh-49 + +== 0.6.0 2010-06-13 +* major enhancements + * Digest Auth (bartiaco, sbecker, gilles, and aaronrussell) + * Maintain HTTP method across redirects (bartiaco and sbecker) + * HTTParty::Response#response returns the Net::HTTPResponse object + * HTTParty::Response#headers returns a HTTParty::Response::Headers object + which quacks like a Hash + Net::HTTPHeader. The #headers method continues + to be backwards-compatible with the old Hash return value but may become + deprecated in the future. + +* minor enhancements + * Update crack requirement to version 0.1.7 + You may still get a warning because Crack's version constant is out of date + * Timeout option can be set for all requests using HTTParty.default_timeout (taazza) + * Closed #38 "headers hash should downcase keys so canonical header name can be used" + * Closed #40 "Gzip response" wherein gziped and deflated responses are + automatically inflated. (carsonmcdonald) + +== 0.5.2 2010-01-31 +* minor enhancements + * Update crack requirement to version 0.1.6 + +== 0.5.1 2010-01-30 +* bug fixes + * Handle 304 response correctly by returning the HTTParty::Response object instead of redirecting (seth and hellvinz) + * Only redirect 300 responses if the header contains a Location + * Don't append empty query strings to the uri. Closes #31 + * When no_follow is enabled, only raise the RedirectionTooDeep exception when a response tries redirecting. Closes #28 + +* major enhancements + * Removed rubygems dependency. I suggest adding rubygems to RUBYOPT if this causes problems for you. + $ export RUBYOPT='rubygems' + * HTTParty#debug_output prints debugging information for the current request (iwarshak) + * HTTParty#no_follow now available as a class-level option. Sets whether or not to follow redirects. + +* minor enhancements + * HTTParty::VERSION now available + * Update crack requirement to version 0.1.5 + +== 0.5.0 2009-12-07 +* bug fixes + * inheritable attributes no longer mutable by subclasses (yyyc514) + * namespace BasicObject within HTTParty to avoid class name collisions (eric) + +* major enhancements + * Custom Parsers via class or proc + * Deprecation warning on HTTParty::AllowedFormats + moved to HTTParty::Parser::SupportedFormats + +* minor enhancements + * Curl inspired output when using the binary in verbose mode (alexvollmer) + * raise UnsupportedURIScheme when scheme is not HTTP or HTTPS (djspinmonkey) + * Allow SSL for ports other than 443 when scheme is HTTPS (stefankroes) + * Accept PEM certificates via HTTParty#pem (chrislo) + * Support HEAD and OPTION verbs (grempe) + * Verify SSL certificates when providing a PEM file (collectiveidea/danielmorrison) + +== 0.4.5 2009-09-12 +* bug fixes + * Fixed class-level headers overwritten by cookie management code. Closes #19 + * Fixed "superclass mismatch for class BlankSlate" error. Closes #20 + * Fixed reading files as post data from the command line (vesan) + +* minor enhancements + * Timeout option added; will raise a Timeout::Error after the timeout has elapsed (attack). Closes #17 + HTTParty.get "http://github.com", :timeout => 1 + * Building gem with Jeweler + +== 0.4.4 2009-07-19 +* 2 minor update + * :query no longer sets form data. Use body and set content type to application/x-www-form-urlencoded if you need it. :query was wrong for that. + * Fixed a bug in the cookies class method that caused cookies to be forgotten after the first request. + * Also, some general cleanup of tests and such. + +== 0.4.3 2009-04-23 +* 1 minor update + * added message to the response object + +== 0.4.2 2009-03-30 +* 2 minor changes + * response code now returns an integer instead of a string (jqr) + * rubyforge project setup for crack so i'm now depending on that instead of jnunemaker-crack + +== 0.4.1 2009-03-29 +* 1 minor fix + * gem 'jnunemaker-crack' instead of gem 'crack' + +== 0.4.0 2009-03-29 +* 1 minor change + * Switched xml and json parsing to crack (same code as before just moved to gem for easier reuse in other projects) + +== 0.3.1 2009-02-10 +* 1 minor fix, 1 minor enhancement + * Fixed unescaping umlauts (siebertm) + * Added yaml response parsing (Miha Filej) + +== 0.3.0 2009-01-31 +* 1 major enhancement, 1 bug fix + * JSON gem no longer a requirement. It was conflicting with rails json stuff so I just stole ActiveSupport's json decoding and bundled it with HTTParty. + * Fixed bug where query strings were being duplicated on redirects + * Added a bunch of specs and moved some code around. + +== 0.2.10 2009-01-29 +* 1 minor enhancement + * Made encoding on query parameters treat everything except URI::PATTERN::UNRESERVED as UNSAFE to force encoding of '+' character (Julian Russell) + +== 0.2.9 2009-01-29 +* 3 minor enhancements + * Added a 'headers' accessor to the response with a hash of any HTTP headers. (Don Peterson) + * Add support for a ":cookies" option to be used at the class level, or as an option on any individual call. It should be passed a hash, which will be converted to the proper format and added to the request headers when the call is made. (Don Peterson) + * Refactored several specs and added a full suite of cucumber features (Don Peterson) + +== 0.2.8 2009-01-28 +* 1 major fix + * fixed major bug with response where it wouldn't iterate or really work at all with parsed responses + +== 0.2.7 2009-01-28 +* 2 minor fixes, 2 minor enhancements, 2 major enhancements + * fixed undefined method add_node for nil class error that occasionally happened (juliocesar) + * Handle nil or unexpected values better when typecasting. (Brian Landau) + * More robust handling of mime types (Alex Vollmer) + * Fixed support for specifying headers and added support for basic auth to CLI. (Alex Vollmer) + * Added first class response object that includes original body and status code (Alex Vollmer) + * Now parsing all response types as some non-200 responses provide important information, this means no more exception raising (Alex Vollmer) + +== 0.2.6 2009-01-05 +* 1 minor bug fix + * added explicit require of time as Time#parse failed outside of rails (willcodeforfoo) + +== 0.2.5 2009-01-05 +* 1 major enhancement + * Add command line interface to HTTParty (Alex Vollmer) + +== 0.2.4 2008-12-23 +* 1 bug fix + * Fixed that mimetype detection was failing if no mimetype was returned from service (skippy) +== 0.2.3 2008-12-23 +* 1 bug fix + * Fixed typecasting class variable naming issue + +== 0.2.2 2008-12-08 +* 1 bug fix + * Added the missing core extension hash method to_xml_attributes + +== 0.2.1 2008-12-08 +* 1 bug fix + * Fixed that HTTParty was borking ActiveSupport and as such Rails (thanks to Rob Sanheim) + +== 0.2.0 2008-12-07 +* 1 major enhancement + * Removed ActiveSupport as a dependency. Now requires json gem for json deserialization and uses an included class to do the xml parsing. + +== 0.1.8 2008-11-30 +* 3 major enhancements + * Moved base_uri normalization into request class and out of httparty module, fixing + the problem where base_uri was not always being normalized. + * Stupid simple support for HTTParty.get/post/put/delete. (jqr) + * Switched gem management to Echoe from newgem. + +== 0.1.7 2008-11-30 +* 1 major enhancement + * fixed multiple class definitions overriding each others options + +== 0.1.6 2008-11-26 +* 1 major enhancement + * now passing :query to set_form_data if post request to avoid content length errors + +== 0.1.5 2008-11-14 +* 2 major enhancements + * Refactored send request method out into its own object. + * Added :html format if you just want to do that. + +== 0.1.4 2008-11-08 +* 3 major enhancements: + * Removed some cruft + * Added ability to follow redirects automatically and turn that off (Alex Vollmer) + +== 0.1.3 2008-08-22 + +* 3 major enhancements: + * Added http_proxy key for setting proxy server and port (francxk@gmail.com) + * Now raises exception when http error occurs (francxk@gmail.com) + * Changed auto format detection from file extension to response content type (Jay Pignata) + +== 0.1.2 2008-08-09 + +* 1 major enhancement: + * default_params were not being appended to query string if option[:query] was blank + +== 0.1.1 2008-07-30 + +* 2 major enhancement: + * Added :basic_auth key for options when making a request + * :query and :body both now work with query string or hash + +== 0.1.0 2008-07-27 + +* 1 major enhancement: + * Initial release diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/MIT-LICENSE b/vendor/ruby/1.9.1/gems/httparty-0.9.0/MIT-LICENSE new file mode 100644 index 0000000..ea4d340 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008 John Nunemaker + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/README.md b/vendor/ruby/1.9.1/gems/httparty-0.9.0/README.md new file mode 100644 index 0000000..3a0fb71 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/README.md @@ -0,0 +1,79 @@ +# httparty + +Makes http fun again! + +## Install + +``` +gem install httparty +``` + +## Requirements + +* multi_json and multi_xml +* You like to party! + +## Examples + +```ruby +# Use the class methods to get down to business quickly +response = HTTParty.get('http://twitter.com/statuses/public_timeline.json') +puts response.body, response.code, response.message, response.headers.inspect + +response.each do |item| + puts item['user']['screen_name'] +end + +# Or wrap things up in your own class +class Twitter + include HTTParty + base_uri 'twitter.com' + + def initialize(u, p) + @auth = {:username => u, :password => p} + end + + # which can be :friends, :user or :public + # options[:query] can be things like since, since_id, count, etc. + def timeline(which=:friends, options={}) + options.merge!({:basic_auth => @auth}) + self.class.get("/statuses/#{which}_timeline.json", options) + end + + def post(text) + options = { :body => {:status => text}, :basic_auth => @auth } + self.class.post('/statuses/update.json', options) + end +end + +twitter = Twitter.new(config['email'], config['password']) +pp twitter.timeline +``` + +See the [examples directory](http://github.com/jnunemaker/httparty/tree/master/examples) for even more goodies. + +## Command Line Interface + +httparty also includes the executable `httparty` which can be +used to query web services and examine the resulting output. By default +it will output the response as a pretty-printed Ruby object (useful for +grokking the structure of output). This can also be overridden to output +formatted XML or JSON. Execute `httparty --help` for all the +options. Below is an example of how easy it is. + +``` +httparty "http://twitter.com/statuses/public_timeline.json" +``` + +## Help and Docs + +* https://groups.google.com/forum/#!forum/httparty-gem +* http://rdoc.info/projects/jnunemaker/httparty + +## Contributing + +* Fork the project. +* Make your feature addition or bug fix. +* Add tests for it. This is important so I don't break it in a future version unintentionally. +* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself in another branch so I can ignore when I pull) +* Send me a pull request. Bonus points for topic branches. diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/Rakefile b/vendor/ruby/1.9.1/gems/httparty-0.9.0/Rakefile new file mode 100644 index 0000000..1cf504b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/Rakefile @@ -0,0 +1,15 @@ +require 'bundler' +Bundler::GemHelper.install_tasks + +require 'spec/rake/spectask' +Spec::Rake::SpecTask.new(:spec) do |spec| + spec.ruby_opts << '-rubygems' + spec.libs << 'lib' << 'spec' + spec.spec_files = FileList['spec/**/*_spec.rb'] + spec.spec_opts = ['--options', 'spec/spec.opts'] +end + +require 'cucumber/rake/task' +Cucumber::Rake::Task.new(:features) + +task :default => [:spec, :features] \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/bin/httparty b/vendor/ruby/1.9.1/gems/httparty-0.9.0/bin/httparty new file mode 100755 index 0000000..dbbfd0a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/bin/httparty @@ -0,0 +1,114 @@ +#!/usr/bin/env ruby + +require "optparse" +require "pp" + +$:.unshift(File.join(File.dirname(__FILE__), "/../lib")) +require "httparty" + +opts = { + :action => :get, + :headers => {}, + :verbose => false +} + +OptionParser.new do |o| + o.banner = "USAGE: #{$0} [options] [url]" + + o.on("-f", + "--format [FORMAT]", + "Output format to use instead of pretty-print ruby: " + + "plain, json or xml") do |f| + opts[:output_format] = f.downcase.to_sym + end + + o.on("-a", + "--action [ACTION]", + "HTTP action: get (default), post, put, delete, head, or options") do |a| + opts[:action] = a.downcase.to_sym + end + + o.on("-d", + "--data [BODY]", + "Data to put in request body (prefix with '@' for file)") do |d| + if d =~ /^@/ + opts[:body] = open(d[1..-1]).read + else + opts[:body] = d + end + end + + o.on("-H", "--header [NAME:VALUE]", "Additional HTTP headers in NAME:VALUE form") do |h| + abort "Invalid header specification, should be Name:Value" unless h =~ /.+:.+/ + name, value = h.split(':') + opts[:headers][name.strip] = value.strip + end + + o.on("-v", "--verbose", "If set, print verbose output") do |v| + opts[:verbose] = true + end + + o.on("-u", "--user [CREDS]", "Use basic authentication. Value should be user:password") do |u| + abort "Invalid credentials format. Must be user:password" unless u =~ /.*:.+/ + user, password = u.split(':') + opts[:basic_auth] = { :username => user, :password => password } + end + + o.on("-r", "--response-code", "Command fails if response code >= 400") do + opts[:response_code] = true + end + + o.on("-h", "--help", "Show help documentation") do |h| + puts o + exit + end +end.parse! + + +if ARGV.empty? + STDERR.puts "You need to provide a URL" + STDERR.puts "USAGE: #{$0} [options] [url]" +end + +def dump_headers(response) + resp_type = Net::HTTPResponse::CODE_TO_OBJ[response.code.to_s] + puts "#{response.code} #{resp_type.to_s.sub(/^Net::HTTP/, '')}" + response.headers.each do |n,v| + puts "#{n}: #{v}" + end + puts +end + +if opts[:verbose] + puts "#{opts[:action].to_s.upcase} #{ARGV.first}" + opts[:headers].each do |n,v| + puts "#{n}: #{v}" + end + puts +end + +response = HTTParty.send(opts[:action], ARGV.first, opts) +if opts[:output_format].nil? + dump_headers(response) if opts[:verbose] + pp response +else + print_format = opts[:output_format] + dump_headers(response) if opts[:verbose] + + case opts[:output_format] + when :json + begin + require 'json' + puts JSON.pretty_generate(response.delegate) + rescue LoadError + puts YAML.dump(response.delegate) + end + when :xml + require 'rexml/document' + REXML::Document.new(response.body).write(STDOUT, 2) + puts + else + puts response + end +end +exit false if opts[:response_code] && response.code >= 400 diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/cucumber.yml b/vendor/ruby/1.9.1/gems/httparty-0.9.0/cucumber.yml new file mode 100644 index 0000000..80df8ac --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/cucumber.yml @@ -0,0 +1 @@ +default: features --format progress diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/aaws.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/aaws.rb new file mode 100644 index 0000000..a1f4fb2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/aaws.rb @@ -0,0 +1,32 @@ +require 'rubygems' +require 'active_support' + +dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')) +require File.join(dir, 'httparty') +require 'pp' +config = YAML::load(File.read(File.join(ENV['HOME'], '.aaws'))) + +module AAWS + class Book + include HTTParty + base_uri 'http://ecs.amazonaws.com' + default_params :Service => 'AWSECommerceService', :Operation => 'ItemSearch', :SearchIndex => 'Books' + + def initialize(key) + self.class.default_params :AWSAccessKeyId => key + end + + def search(options={}) + raise ArgumentError, 'You must search for something' if options[:query].blank? + + # amazon uses nasty camelized query params + options[:query] = options[:query].inject({}) { |h, q| h[q[0].to_s.camelize] = q[1]; h } + + # make a request and return the items (NOTE: this doesn't handle errors at this point) + self.class.get('/onca/xml', options)['ItemSearchResponse']['Items'] + end + end +end + +aaws = AAWS::Book.new(config[:access_key]) +pp aaws.search(:query => {:title => 'Ruby On Rails'}) diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/basic.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/basic.rb new file mode 100644 index 0000000..d813795 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/basic.rb @@ -0,0 +1,32 @@ +dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')) +require File.join(dir, 'httparty') +require 'pp' + +# You can also use post, put, delete, head, options in the same fashion +response = HTTParty.get('http://twitter.com/statuses/public_timeline.json') +puts response.body, response.code, response.message, response.headers.inspect + +response.each do |item| + puts item['user']['screen_name'] +end + +# An example post to a minimal rails app in the development environment +# Note that "skip_before_filter :verify_authenticity_token" must be set in the +# "pears" controller for this example + +class Partay + include HTTParty + base_uri 'http://localhost:3000' +end + +options = { + :body => { + :pear => { # your resource + :foo => '123', # your columns/data + :bar => 'second', + :baz => 'last thing' + } + } +} + +pp Partay.post('/pears.xml', options) diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/crack.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/crack.rb new file mode 100644 index 0000000..63a2aaf --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/crack.rb @@ -0,0 +1,19 @@ +require 'rubygems' +require 'crack' + +dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')) +require File.join(dir, 'httparty') +require 'pp' + +class Rep + include HTTParty + + parser( + Proc.new do |body, format| + Crack::XML.parse(body) + end + ) +end + +pp Rep.get('http://whoismyrepresentative.com/whoismyrep.php?zip=46544') +pp Rep.get('http://whoismyrepresentative.com/whoismyrep.php', :query => {:zip => 46544}) diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/custom_parsers.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/custom_parsers.rb new file mode 100644 index 0000000..3a91813 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/custom_parsers.rb @@ -0,0 +1,67 @@ +class ParseAtom + include HTTParty + + # Support Atom along with the default parsers: xml, json, yaml, etc. + class Parser::Atom < HTTParty::Parser + SupportedFormats.merge!({"application/atom+xml" => :atom}) + + protected + + # perform atom parsing on body + def atom + body.to_atom + end + end + + parser Parser::Atom +end + + +class OnlyParseAtom + include HTTParty + + # Only support Atom + class Parser::OnlyAtom < HTTParty::Parser + SupportedFormats = {"application/atom+xml" => :atom} + + protected + + # perform atom parsing on body + def atom + body.to_atom + end + end + + parser Parser::OnlyAtom +end + + +class SkipParsing + include HTTParty + + # Parse the response body however you like + class Parser::Simple < HTTParty::Parser + def parse + body + end + end + + parser Parser::Simple +end + + +class AdHocParsing + include HTTParty + parser( + Proc.new do |body, format| + case format + when :json + body.to_json + when :xml + body.to_xml + else + body + end + end + ) +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/delicious.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/delicious.rb new file mode 100644 index 0000000..e6d6243 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/delicious.rb @@ -0,0 +1,37 @@ +dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')) +require File.join(dir, 'httparty') +require 'pp' +config = YAML::load(File.read(File.join(ENV['HOME'], '.delicious'))) + +class Delicious + include HTTParty + base_uri 'https://api.del.icio.us/v1' + + def initialize(u, p) + @auth = {:username => u, :password => p} + end + + # query params that filter the posts are: + # tag (optional). Filter by this tag. + # dt (optional). Filter by this date (CCYY-MM-DDThh:mm:ssZ). + # url (optional). Filter by this url. + # ie: posts(:query => {:tag => 'ruby'}) + def posts(options={}) + options.merge!({:basic_auth => @auth}) + self.class.get('/posts/get', options) + end + + # query params that filter the posts are: + # tag (optional). Filter by this tag. + # count (optional). Number of items to retrieve (Default:15, Maximum:100). + def recent(options={}) + options.merge!({:basic_auth => @auth}) + self.class.get('/posts/recent', options) + end +end + +delicious = Delicious.new(config['username'], config['password']) +pp delicious.posts(:query => {:tag => 'ruby'}) +pp delicious.recent + +delicious.recent['posts']['post'].each { |post| puts post['href'] } \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/google.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/google.rb new file mode 100644 index 0000000..f629b4d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/google.rb @@ -0,0 +1,16 @@ +dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')) +require File.join(dir, 'httparty') +require 'pp' + +class Google + include HTTParty + format :html +end + +# google.com redirects to www.google.com so this is live test for redirection +pp Google.get('http://google.com') + +puts '', '*'*70, '' + +# check that ssl is requesting right +pp Google.get('https://www.google.com') \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/headers_and_user_agents.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/headers_and_user_agents.rb new file mode 100644 index 0000000..8e55aff --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/headers_and_user_agents.rb @@ -0,0 +1,6 @@ +# To send custom user agents to identify your application to a web service (or mask as a specific browser for testing), send "User-Agent" as a hash to headers as shown below. + +require 'httparty' + +APPLICATION_NAME = "Httparty" +response = HTTParty.get('http://example.com', :headers => {"User-Agent" => APPLICATION_NAME}) diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/nokogiri_html_parser.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/nokogiri_html_parser.rb new file mode 100644 index 0000000..b45a2b8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/nokogiri_html_parser.rb @@ -0,0 +1,22 @@ +require 'rubygems' +require 'nokogiri' + + +dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')) +require File.join(dir, 'httparty') +require 'pp' + +class HtmlParserIncluded < HTTParty::Parser + SupportedFormats.merge!('text/html' => :html) + + def html + Nokogiri::HTML(body) + end +end + +class Page + include HTTParty + parser HtmlParserIncluded +end + +pp Page.get('http://www.google.com') diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/rubyurl.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/rubyurl.rb new file mode 100644 index 0000000..65808fb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/rubyurl.rb @@ -0,0 +1,14 @@ +dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')) +require File.join(dir, 'httparty') +require 'pp' + +class Rubyurl + include HTTParty + base_uri 'rubyurl.com' + + def self.shorten( website_url ) + post( '/api/links.json', :query => { :link => { :website_url => website_url } } ) + end +end + +pp Rubyurl.shorten( 'http://istwitterdown.com/') \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/tripit_sign_in.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/tripit_sign_in.rb new file mode 100644 index 0000000..f06617d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/tripit_sign_in.rb @@ -0,0 +1,33 @@ +dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')) +require File.join(dir, 'httparty') + +class TripIt + include HTTParty + base_uri 'http://www.tripit.com' + debug_output + + def initialize(email, password) + @email = email + response = self.class.get('/account/login') + response = self.class.post( + '/account/login', + :body => { + :login_email_address => email, + :login_password => password + }, + :headers => {'Cookie' => response.headers['Set-Cookie']} + ) + @cookie = response.request.options[:headers]['Cookie'] + end + + def account_settings + self.class.get('/account/edit', :headers => {'Cookie' => @cookie}) + end + + def logged_in? + account_settings.include? "You're logged in as #{@email}" + end +end + +tripit = TripIt.new('email', 'password') +puts "Logged in: #{tripit.logged_in?}" diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/twitter.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/twitter.rb new file mode 100644 index 0000000..c7794fa --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/twitter.rb @@ -0,0 +1,31 @@ +dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')) +require File.join(dir, 'httparty') +require 'pp' +config = YAML::load(File.read(File.join(ENV['HOME'], '.twitter'))) + +class Twitter + include HTTParty + base_uri 'twitter.com' + + def initialize(u, p) + @auth = {:username => u, :password => p} + end + + # which can be :friends, :user or :public + # options[:query] can be things like since, since_id, count, etc. + def timeline(which=:friends, options={}) + options.merge!({:basic_auth => @auth}) + self.class.get("/statuses/#{which}_timeline.json", options) + end + + def post(text) + options = { :query => {:status => text}, :basic_auth => @auth } + self.class.post('/statuses/update.json', options) + end +end + +twitter = Twitter.new(config['email'], config['password']) +pp twitter.timeline +# pp twitter.timeline(:friends, :query => {:since_id => 868482746}) +# pp twitter.timeline(:friends, :query => 'since_id=868482746') +# pp twitter.post('this is a test of 0.2.0') \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/whoismyrep.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/whoismyrep.rb new file mode 100644 index 0000000..b59473c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/examples/whoismyrep.rb @@ -0,0 +1,10 @@ +dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')) +require File.join(dir, 'httparty') +require 'pp' + +class Rep + include HTTParty +end + +pp Rep.get('http://whoismyrepresentative.com/whoismyrep.php?zip=46544') +pp Rep.get('http://whoismyrepresentative.com/whoismyrep.php', :query => {:zip => 46544}) \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/basic_authentication.feature b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/basic_authentication.feature new file mode 100644 index 0000000..b467237 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/basic_authentication.feature @@ -0,0 +1,20 @@ +Feature: Basic Authentication + + As a developer + I want to be able to use a service that requires Basic Authentication + Because that is not an uncommon requirement + + Scenario: Passing no credentials to a page requiring Basic Authentication + Given a restricted page at '/basic_auth.html' + When I call HTTParty#get with '/basic_auth.html' + Then it should return a response with a 401 response code + + Scenario: Passing proper credentials to a page requiring Basic Authentication + Given a remote service that returns 'Authenticated Page' + And that service is accessed at the path '/basic_auth.html' + And that service is protected by Basic Authentication + And that service requires the username 'jcash' with the password 'maninblack' + When I call HTTParty#get with '/basic_auth.html' and a basic_auth hash: + | username | password | + | jcash | maninblack | + Then the return value should match 'Authenticated Page' diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/command_line.feature b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/command_line.feature new file mode 100644 index 0000000..951e236 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/command_line.feature @@ -0,0 +1,7 @@ +Feature: Command Line + + As a developer + I want to be able to harness the power of HTTParty from the command line + Because that would make quick testing and debugging easy + And 'easy' is my middle name + And I'm kidding it's actually 'Danger'! diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/deals_with_http_error_codes.feature b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/deals_with_http_error_codes.feature new file mode 100644 index 0000000..bd6dd85 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/deals_with_http_error_codes.feature @@ -0,0 +1,26 @@ +Feature: Deals with HTTP error codes + + As a developer + I want to be informed of non-successful responses + Because sometimes thing explode + And I should probably know what happened + + Scenario: A response of '404 - Not Found' + Given a remote service that returns a 404 status code + And that service is accessed at the path '/404_service.html' + When I call HTTParty#get with '/404_service.html' + Then it should return a response with a 404 response code + + Scenario: A response of '500 - Internal Server Error' + Given a remote service that returns a 500 status code + And that service is accessed at the path '/500_service.html' + When I call HTTParty#get with '/500_service.html' + Then it should return a response with a 500 response code + + Scenario: A non-successful response where I need the body + Given a remote service that returns a 400 status code + And the response from the service has a body of 'Bad response' + And that service is accessed at the path '/400_service.html' + When I call HTTParty#get with '/400_service.html' + Then it should return a response with a 400 response code + And the return value should match 'Bad response' diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/digest_authentication.feature b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/digest_authentication.feature new file mode 100644 index 0000000..456a0a7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/digest_authentication.feature @@ -0,0 +1,20 @@ +Feature: Digest Authentication + + As a developer + I want to be able to use a service that requires Digest Authentication + Because that is not an uncommon requirement + + Scenario: Passing no credentials to a page requiring Digest Authentication + Given a restricted page at '/digest_auth.html' + When I call HTTParty#get with '/digest_auth.html' + Then it should return a response with a 401 response code + + Scenario: Passing proper credentials to a page requiring Digest Authentication + Given a remote service that returns 'Digest Authenticated Page' + And that service is accessed at the path '/digest_auth.html' + And that service is protected by Digest Authentication + And that service requires the username 'jcash' with the password 'maninblack' + When I call HTTParty#get with '/digest_auth.html' and a digest_auth hash: + | username | password | + | jcash | maninblack | + Then the return value should match 'Digest Authenticated Page' diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/handles_compressed_responses.feature b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/handles_compressed_responses.feature new file mode 100644 index 0000000..b20bba2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/handles_compressed_responses.feature @@ -0,0 +1,19 @@ +Feature: Handles Compressed Responses + + In order to save bandwidth + As a developer + I want to uncompress compressed responses + + Scenario: Supports deflate encoding + Given a remote deflate service + And the response from the service has a body of '

Some HTML

' + And that service is accessed at the path '/deflate_service.html' + When I call HTTParty#get with '/deflate_service.html' + Then the return value should match '

Some HTML

' + + Scenario: Supports gzip encoding + Given a remote gzip service + And the response from the service has a body of '

Some HTML

' + And that service is accessed at the path '/gzip_service.html' + When I call HTTParty#get with '/gzip_service.html' + Then the return value should match '

Some HTML

' diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/handles_multiple_formats.feature b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/handles_multiple_formats.feature new file mode 100644 index 0000000..438a6ba --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/handles_multiple_formats.feature @@ -0,0 +1,34 @@ +Feature: Handles Multiple Formats + + As a developer + I want to be able to consume remote services of many different formats + And I want those formats to be automatically detected and handled + Because web services take many forms + And I don't want to have to do any extra work + + Scenario: An HTML service + Given a remote service that returns '

Some HTML

' + And that service is accessed at the path '/html_service.html' + And the response from the service has a Content-Type of 'text/html' + When I call HTTParty#get with '/html_service.html' + Then it should return a String + And the return value should match '

Some HTML

' + + Scenario: A JSON service + Given a remote service that returns '{ "jennings": "waylon", "cash": "johnny" }' + And that service is accessed at the path '/service.json' + And the response from the service has a Content-Type of 'application/json' + When I call HTTParty#get with '/service.json' + Then it should return a Hash equaling: + | key | value | + | jennings | waylon | + | cash | johnny | + + Scenario: An XML Service + Given a remote service that returns 'waylon jennings' + And that service is accessed at the path '/service.xml' + And the response from the service has a Content-Type of 'text/xml' + When I call HTTParty#get with '/service.xml' + Then it should return a Hash equaling: + | key | value | + | singer | waylon jennings | diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/env.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/env.rb new file mode 100644 index 0000000..8bf4bb3 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/env.rb @@ -0,0 +1,22 @@ +require 'mongrel' +require './lib/httparty' +require 'spec/expectations' + +Before do + def new_port + server = TCPServer.new('0.0.0.0', nil) + port = server.addr[1] + ensure + server.close + end + + port = ENV["HTTPARTY_PORT"] || new_port + @host_and_port = "0.0.0.0:#{port}" + @server = Mongrel::HttpServer.new("0.0.0.0", port) + @server.run + @request_options = {} +end + +After do + @server.stop +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/httparty_response_steps.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/httparty_response_steps.rb new file mode 100644 index 0000000..bf535da --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/httparty_response_steps.rb @@ -0,0 +1,26 @@ +Then /it should return an? (\w+)$/ do |class_string| + @response_from_httparty.should be_an_instance_of(class_string.class) +end + +Then /the return value should match '(.*)'/ do |expected_text| + @response_from_httparty.should eql(expected_text) +end + +Then /it should return a Hash equaling:/ do |hash_table| + @response_from_httparty.should be_an_instance_of(Hash) + @response_from_httparty.keys.length.should eql(hash_table.rows.length) + hash_table.hashes.each do |pair| + key, value = pair["key"], pair["value"] + @response_from_httparty.keys.should include(key) + @response_from_httparty[key].should eql(value) + end +end + +Then /it should return a response with a (\d+) response code/ do |code| + @response_from_httparty.code.should eql(code.to_i) +end + +Then /it should raise (?:an|a) ([\w:]+) exception/ do |exception| + @exception_from_httparty.should_not be_nil + @exception_from_httparty.class.name.should eql(exception) +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/httparty_steps.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/httparty_steps.rb new file mode 100644 index 0000000..b9bd268 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/httparty_steps.rb @@ -0,0 +1,27 @@ +When /^I set my HTTParty timeout option to (\d+)$/ do |timeout| + @request_options[:timeout] = timeout.to_i +end + +When /I call HTTParty#get with '(.*)'$/ do |url| + begin + @response_from_httparty = HTTParty.get("http://#{@host_and_port}#{url}", @request_options) + rescue HTTParty::RedirectionTooDeep, Timeout::Error => e + @exception_from_httparty = e + end +end + +When /I call HTTParty#get with '(.*)' and a basic_auth hash:/ do |url, auth_table| + h = auth_table.hashes.first + @response_from_httparty = HTTParty.get( + "http://#{@host_and_port}#{url}", + :basic_auth => { :username => h["username"], :password => h["password"] } + ) +end + +When /I call HTTParty#get with '(.*)' and a digest_auth hash:/ do |url, auth_table| + h = auth_table.hashes.first + @response_from_httparty = HTTParty.get( + "http://#{@host_and_port}#{url}", + :digest_auth => { :username => h["username"], :password => h["password"] } + ) +end \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/mongrel_helper.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/mongrel_helper.rb new file mode 100644 index 0000000..8841c8e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/mongrel_helper.rb @@ -0,0 +1,94 @@ +require 'base64' +class BasicMongrelHandler < Mongrel::HttpHandler + attr_accessor :content_type, :custom_headers, :response_body, :response_code, :preprocessor, :username, :password + + def initialize + @content_type = "text/html" + @response_body = "" + @response_code = 200 + @custom_headers = {} + end + + def process(request, response) + instance_eval &preprocessor if preprocessor + reply_with(response, response_code, response_body) + end + + def reply_with(response, code, response_body) + response.start(code) do |head, body| + head["Content-Type"] = content_type + custom_headers.each { |k,v| head[k] = v } + body.write(response_body) + end + end +end + +class DeflateHandler < BasicMongrelHandler + def process(request, response) + response.start do |head, body| + head['Content-Encoding'] = 'deflate' + body.write Zlib::Deflate.deflate(response_body) + end + end +end + +class GzipHandler < BasicMongrelHandler + def process(request, response) + response.start do |head, body| + head['Content-Encoding'] = 'gzip' + body.write gzip(response_body) + end + end + + protected + + def gzip(string) + sio = StringIO.new('', 'r+') + gz = Zlib::GzipWriter.new sio + gz.write string + gz.finish + sio.rewind + sio.read + end +end + +module BasicAuthentication + def self.extended(base) + base.custom_headers["WWW-Authenticate"] = 'Basic Realm="Super Secret Page"' + end + + def process(request, response) + if authorized?(request) + super + else + reply_with(response, 401, "Incorrect. You have 20 seconds to comply.") + end + end + + def authorized?(request) + request.params["HTTP_AUTHORIZATION"] == "Basic " + Base64.encode64("#{@username}:#{@password}").strip + end +end + +module DigestAuthentication + def self.extended(base) + base.custom_headers["WWW-Authenticate"] = 'Digest realm="testrealm@host.com",qop="auth,auth-int",nonce="nonce",opaque="opaque"' + end + + def process(request, response) + if authorized?(request) + super + else + reply_with(response, 401, "Incorrect. You have 20 seconds to comply.") + end + end + + def authorized?(request) + request.params["HTTP_AUTHORIZATION"] =~ /Digest.*uri=/ + end +end + +def new_mongrel_redirector(target_url, relative_path = false) + target_url = "http://#{@host_and_port}#{target_url}" unless relative_path + Mongrel::RedirectHandler.new(target_url) +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/remote_service_steps.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/remote_service_steps.rb new file mode 100644 index 0000000..da0aee2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/steps/remote_service_steps.rb @@ -0,0 +1,69 @@ +Given /a remote service that returns '(.*)'/ do |response_body| + @handler = BasicMongrelHandler.new + Given "the response from the service has a body of '#{response_body}'" +end + +Given /a remote service that returns a (\d+) status code/ do |code| + @handler = BasicMongrelHandler.new + @handler.response_code = code +end + +Given /that service is accessed at the path '(.*)'/ do |path| + @server.register(path, @handler) +end + +Given /^that service takes (\d+) seconds to generate a response$/ do |time| + @server_response_time = time.to_i + @handler.preprocessor = Proc.new { sleep time.to_i } +end + +Given /^a remote deflate service$/ do + @handler = DeflateHandler.new +end + +Given /^a remote gzip service$/ do + @handler = GzipHandler.new +end + +Given /the response from the service has a Content-Type of '(.*)'/ do |content_type| + @handler.content_type = content_type +end + +Given /the response from the service has a body of '(.*)'/ do |response_body| + @handler.response_body = response_body +end + +Given /the url '(.*)' redirects to '(.*)'/ do |redirection_url, target_url| + @server.register redirection_url, new_mongrel_redirector(target_url) +end + +Given /that service is protected by Basic Authentication/ do + @handler.extend BasicAuthentication +end + +Given /that service is protected by Digest Authentication/ do + @handler.extend DigestAuthentication +end + +Given /that service requires the username '(.*)' with the password '(.*)'/ do |username, password| + @handler.username = username + @handler.password = password +end + +Given /a restricted page at '(.*)'/ do |url| + Given "a remote service that returns 'A response I will never see'" + And "that service is accessed at the path '#{url}'" + And "that service is protected by Basic Authentication" + And "that service requires the username 'something' with the password 'secret'" +end + +# This joins the server thread, and halts cucumber, so you can actually hit the +# server with a browser. Runs until you kill it with Ctrl-c +Given /I want to hit this in a browser/ do + @server.acceptor.join +end + +Then /I wait for the server to recover/ do + timeout = @request_options[:timeout] || 0 + sleep @server_response_time - timeout +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/supports_redirection.feature b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/supports_redirection.feature new file mode 100644 index 0000000..debc7b8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/supports_redirection.feature @@ -0,0 +1,22 @@ +Feature: Supports Redirection + + As a developer + I want to work with services that may redirect me + And I want it to follow a reasonable number of redirects + Because sometimes web services do that + + Scenario: A service that redirects once + Given a remote service that returns 'Service Response' + And that service is accessed at the path '/landing_service.html' + And the url '/redirector.html' redirects to '/landing_service.html' + When I call HTTParty#get with '/redirector.html' + Then the return value should match 'Service Response' + + # TODO: Look in to why this actually fails... + Scenario: A service that redirects to a relative URL + + Scenario: A service that redirects infinitely + Given the url '/first.html' redirects to '/second.html' + And the url '/second.html' redirects to '/first.html' + When I call HTTParty#get with '/first.html' + Then it should raise an HTTParty::RedirectionTooDeep exception diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/supports_timeout_option.feature b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/supports_timeout_option.feature new file mode 100644 index 0000000..db56463 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/features/supports_timeout_option.feature @@ -0,0 +1,13 @@ +Feature: Supports the timeout option + In order to handle inappropriately slow response times + As a developer + I want my request to raise an exception after my specified timeout as elapsed + + Scenario: A long running response + Given a remote service that returns '

Some HTML

' + And that service is accessed at the path '/long_running_service.html' + And that service takes 2 seconds to generate a response + When I set my HTTParty timeout option to 1 + And I call HTTParty#get with '/long_running_service.html' + Then it should raise a Timeout::Error exception + And I wait for the server to recover diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/httparty.gemspec b/vendor/ruby/1.9.1/gems/httparty-0.9.0/httparty.gemspec new file mode 100644 index 0000000..d9fe866 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/httparty.gemspec @@ -0,0 +1,24 @@ +# -*- encoding: utf-8 -*- +$:.push File.expand_path("../lib", __FILE__) +require "httparty/version" + +Gem::Specification.new do |s| + s.name = "httparty" + s.version = HTTParty::VERSION + s.platform = Gem::Platform::RUBY + s.authors = ["John Nunemaker", "Sandro Turriate"] + s.email = ["nunemaker@gmail.com"] + s.homepage = "http://jnunemaker.github.com/httparty" + s.summary = %q{Makes http fun! Also, makes consuming restful web services dead easy.} + s.description = %q{Makes http fun! Also, makes consuming restful web services dead easy.} + + s.add_dependency 'multi_json', "~> 1.0" + s.add_dependency 'multi_xml' + + s.post_install_message = "When you HTTParty, you must party hard!" + + s.files = `git ls-files`.split("\n") + s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") + s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } + s.require_paths = ["lib"] +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty.rb new file mode 100644 index 0000000..9885e58 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty.rb @@ -0,0 +1,503 @@ +require 'pathname' +require 'net/http' +require 'net/https' +require 'uri' +require 'zlib' +require 'multi_xml' +require 'multi_json' + +require 'httparty/module_inheritable_attributes' +require 'httparty/cookie_hash' +require 'httparty/net_digest_auth' +require 'httparty/version' +require 'httparty/connection_adapter' + +# @see HTTParty::ClassMethods +module HTTParty + module AllowedFormatsDeprecation + def const_missing(const) + if const.to_s =~ /AllowedFormats$/ + Kernel.warn("Deprecated: Use HTTParty::Parser::SupportedFormats") + HTTParty::Parser::SupportedFormats + else + super + end + end + end + + extend AllowedFormatsDeprecation + + def self.included(base) + base.extend ClassMethods + base.send :include, HTTParty::ModuleInheritableAttributes + base.send(:mattr_inheritable, :default_options) + base.send(:mattr_inheritable, :default_cookies) + base.instance_variable_set("@default_options", {}) + base.instance_variable_set("@default_cookies", CookieHash.new) + end + + # == Common Request Options + # Request methods (get, post, patch, put, delete, head, options) all take a common set of options. These are: + # + # [:+body+:] Body of the request. If passed a Hash, will try to normalize it first, by default passing it to ActiveSupport::to_params. Any other kind of object will get used as-is. + # [:+http_proxyaddr+:] Address of proxy server to use. + # [:+http_proxyport+:] Port of proxy server to use. + # [:+http_proxyuser+:] User for proxy server authentication. + # [:+http_proxypass+:] Password for proxy server authentication. + # [:+limit+:] Maximum number of redirects to follow. Takes precedences over :+no_follow+. + # [:+query+:] Query string, or a Hash representing it. Normalized according to the same rules as :+body+. If you specify this on a POST, you must use a Hash. See also HTTParty::ClassMethods.default_params. + # [:+timeout+:] Timeout for opening connection and reading data. + # + # There are also another set of options with names corresponding to various class methods. The methods in question are those that let you set a class-wide default, and the options override the defaults on a request-by-request basis. Those options are: + # * :+base_uri+: see HTTParty::ClassMethods.base_uri. + # * :+basic_auth+: see HTTParty::ClassMethods.basic_auth. Only one of :+basic_auth+ and :+digest_auth+ can be used at a time; if you try using both, you'll get an ArgumentError. + # * :+debug_output+: see HTTParty::ClassMethods.debug_output. + # * :+digest_auth+: see HTTParty::ClassMethods.digest_auth. Only one of :+basic_auth+ and :+digest_auth+ can be used at a time; if you try using both, you'll get an ArgumentError. + # * :+format+: see HTTParty::ClassMethods.format. + # * :+headers+: see HTTParty::ClassMethods.headers. Must be a Hash. + # * :+maintain_method_across_redirects+: see HTTParty::ClassMethods.maintain_method_across_redirects. + # * :+no_follow+: see HTTParty::ClassMethods.no_follow. + # * :+parser+: see HTTParty::ClassMethods.parser. + # * :+connection_adapter+: see HTTParty::ClassMethods.connection_adapter. + # * :+pem+: see HTTParty::ClassMethods.pem. + # * :+query_string_normalizer+: see HTTParty::ClassMethods.query_string_normalizer + # * :+ssl_ca_file+: see HTTParty::ClassMethods.ssl_ca_file. + # * :+ssl_ca_path+: see HTTParty::ClassMethods.ssl_ca_path. + + module ClassMethods + + extend AllowedFormatsDeprecation + + # Allows setting http proxy information to be used + # + # class Foo + # include HTTParty + # http_proxy 'http://foo.com', 80, 'user', 'pass' + # end + def http_proxy(addr=nil, port=nil, user=nil, pass=nil) + default_options[:http_proxyaddr] = addr + default_options[:http_proxyport] = port + default_options[:http_proxyuser] = user + default_options[:http_proxypass] = pass + end + + # Allows setting a base uri to be used for each request. + # Will normalize uri to include http, etc. + # + # class Foo + # include HTTParty + # base_uri 'twitter.com' + # end + def base_uri(uri=nil) + return default_options[:base_uri] unless uri + default_options[:base_uri] = HTTParty.normalize_base_uri(uri) + end + + # Allows setting basic authentication username and password. + # + # class Foo + # include HTTParty + # basic_auth 'username', 'password' + # end + def basic_auth(u, p) + default_options[:basic_auth] = {:username => u, :password => p} + end + + # Allows setting digest authentication username and password. + # + # class Foo + # include HTTParty + # digest_auth 'username', 'password' + # end + def digest_auth(u, p) + default_options[:digest_auth] = {:username => u, :password => p} + end + + # Do not send rails style query strings. + # Specically, don't use bracket notation when sending an array + # + # For a query: + # get '/', :query => {:selected_ids => [1,2,3]} + # + # The default query string looks like this: + # /?selected_ids[]=1&selected_ids[]=2&selected_ids[]=3 + # + # Call `disable_rails_query_string_format` to transform the query string + # into: + # /?selected_ids=1&selected_ids=2&selected_ids=3 + # + # @example + # class Foo + # include HTTParty + # disable_rails_query_string_format + # end + def disable_rails_query_string_format + query_string_normalizer Request::NON_RAILS_QUERY_STRING_NORMALIZER + end + + # Allows setting default parameters to be appended to each request. + # Great for api keys and such. + # + # class Foo + # include HTTParty + # default_params :api_key => 'secret', :another => 'foo' + # end + def default_params(h={}) + raise ArgumentError, 'Default params must be a hash' unless h.is_a?(Hash) + default_options[:default_params] ||= {} + default_options[:default_params].merge!(h) + end + + # Allows setting a default timeout for all HTTP calls + # Timeout is specified in seconds. + # + # class Foo + # include HTTParty + # default_timeout 10 + # end + def default_timeout(t) + raise ArgumentError, 'Timeout must be an integer or float' unless t && (t.is_a?(Integer) || t.is_a?(Float)) + default_options[:timeout] = t + end + + # Set an output stream for debugging, defaults to $stderr. + # The output stream is passed on to Net::HTTP#set_debug_output. + # + # class Foo + # include HTTParty + # debug_output $stderr + # end + def debug_output(stream = $stderr) + default_options[:debug_output] = stream + end + + # Allows setting HTTP headers to be used for each request. + # + # class Foo + # include HTTParty + # headers 'Accept' => 'text/html' + # end + def headers(h={}) + raise ArgumentError, 'Headers must be a hash' unless h.is_a?(Hash) + default_options[:headers] ||= {} + default_options[:headers].merge!(h) + end + + def cookies(h={}) + raise ArgumentError, 'Cookies must be a hash' unless h.is_a?(Hash) + default_cookies.add_cookies(h) + end + + # Proceed to the location header when an HTTP response dictates a redirect. + # Redirects are always followed by default. + # + # @example + # class Foo + # include HTTParty + # base_uri 'http://google.com' + # follow_redirects true + # end + def follow_redirects(value = true) + default_options[:follow_redirects] = value + end + + # Allows setting the format with which to parse. + # Must be one of the allowed formats ie: json, xml + # + # class Foo + # include HTTParty + # format :json + # end + def format(f = nil) + if f.nil? + default_options[:format] + else + parser(Parser) if parser.nil? + default_options[:format] = f + validate_format + end + end + + # Declare whether or not to follow redirects. When true, an + # {HTTParty::RedirectionTooDeep} error will raise upon encountering a + # redirect. You can then gain access to the response object via + # HTTParty::RedirectionTooDeep#response. + # + # @see HTTParty::ResponseError#response + # + # @example + # class Foo + # include HTTParty + # base_uri 'http://google.com' + # no_follow true + # end + # + # begin + # Foo.get('/') + # rescue HTTParty::RedirectionTooDeep => e + # puts e.response.body + # end + def no_follow(value = false) + default_options[:no_follow] = value + end + + # Declare that you wish to maintain the chosen HTTP method across redirects. + # The default behavior is to follow redirects via the GET method. + # If you wish to maintain the original method, you can set this option to true. + # + # @example + # class Foo + # include HTTParty + # base_uri 'http://google.com' + # maintain_method_across_redirects true + # end + + def maintain_method_across_redirects(value = true) + default_options[:maintain_method_across_redirects] = value + end + + # Allows setting a PEM file to be used + # + # class Foo + # include HTTParty + # pem File.read('/home/user/my.pem'), "optional password" + # end + def pem(pem_contents, password=nil) + default_options[:pem] = pem_contents + default_options[:pem_password] = password + end + + # Override the way query strings are normalized. + # Helpful for overriding the default rails normalization of Array queries. + # + # For a query: + # get '/', :query => {:selected_ids => [1,2,3]} + # + # The default query string normalizer returns: + # /?selected_ids[]=1&selected_ids[]=2&selected_ids[]=3 + # + # Let's change it to this: + # /?selected_ids=1&selected_ids=2&selected_ids=3 + # + # Pass a Proc to the query normalizer which accepts the yielded query. + # + # @example Modifying Array query strings + # class ServiceWrapper + # include HTTParty + # + # query_string_normalizer proc { |query| + # query.map do |key, value| + # value.map {|v| "#{key}=#{v}"} + # end.join('&') + # } + # end + # + # @param [Proc] normalizer custom query string normalizer. + # @yield [Hash, String] query string + # @yieldreturn [Array] an array that will later be joined with '&' + def query_string_normalizer(normalizer) + default_options[:query_string_normalizer] = normalizer + end + + # Allows setting of SSL version to use. This only works in Ruby 1.9. + # You can get a list of valid versions from OpenSSL::SSL::SSLContext::METHODS. + # + # class Foo + # include HTTParty + # ssl_version :SSLv3 + # end + def ssl_version(version) + default_options[:ssl_version] = version + end + + # Allows setting an OpenSSL certificate authority file + # + # class Foo + # include HTTParty + # ssl_ca_file '/etc/ssl/certs/ca-certificates.crt' + # end + def ssl_ca_file(path) + default_options[:ssl_ca_file] = path + end + + # Allows setting an OpenSSL certificate authority path (directory) + # + # class Foo + # include HTTParty + # ssl_ca_path '/etc/ssl/certs/' + # end + def ssl_ca_path(path) + default_options[:ssl_ca_path] = path + end + + # Allows setting a custom parser for the response. + # + # class Foo + # include HTTParty + # parser Proc.new {|data| ...} + # end + def parser(custom_parser = nil) + if custom_parser.nil? + default_options[:parser] + else + default_options[:parser] = custom_parser + validate_format + end + end + + # Allows setting a custom connection_adapter for the http connections + # + # @example + # class Foo + # include HTTParty + # connection_adapter Proc.new {|uri, options| ... } + # end + # + # @example provide optional configuration for your connection_adapter + # class Foo + # include HTTParty + # connection_adapter Proc.new {|uri, options| ... }, {:foo => :bar} + # end + # + # @see HTTParty::ConnectionAdapter + def connection_adapter(custom_adapter = nil, options = nil) + if custom_adapter.nil? + default_options[:connection_adapter] + else + default_options[:connection_adapter] = custom_adapter + default_options[:connection_adapter_options] = options + end + end + + # Allows making a get request to a url. + # + # class Foo + # include HTTParty + # end + # + # # Simple get with full url + # Foo.get('http://foo.com/resource.json') + # + # # Simple get with full url and query parameters + # # ie: http://foo.com/resource.json?limit=10 + # Foo.get('http://foo.com/resource.json', :query => {:limit => 10}) + def get(path, options={}, &block) + perform_request Net::HTTP::Get, path, options, &block + end + + # Allows making a post request to a url. + # + # class Foo + # include HTTParty + # end + # + # # Simple post with full url and setting the body + # Foo.post('http://foo.com/resources', :body => {:bar => 'baz'}) + # + # # Simple post with full url using :query option, + # # which gets set as form data on the request. + # Foo.post('http://foo.com/resources', :query => {:bar => 'baz'}) + def post(path, options={}, &block) + perform_request Net::HTTP::Post, path, options, &block + end + + # Perform a PATCH request to a path + def patch(path, options={}, &block) + perform_request Net::HTTP::Patch, path, options, &block + end + + # Perform a PUT request to a path + def put(path, options={}, &block) + perform_request Net::HTTP::Put, path, options, &block + end + + # Perform a DELETE request to a path + def delete(path, options={}, &block) + perform_request Net::HTTP::Delete, path, options, &block + end + + # Perform a HEAD request to a path + def head(path, options={}, &block) + perform_request Net::HTTP::Head, path, options, &block + end + + # Perform an OPTIONS request to a path + def options(path, options={}, &block) + perform_request Net::HTTP::Options, path, options, &block + end + + def default_options #:nodoc: + @default_options + end + + private + + def perform_request(http_method, path, options, &block) #:nodoc: + options = default_options.dup.merge(options) + process_cookies(options) + Request.new(http_method, path, options).perform(&block) + end + + def process_cookies(options) #:nodoc: + return unless options[:cookies] || default_cookies.any? + options[:headers] ||= headers.dup + options[:headers]["cookie"] = cookies.merge(options.delete(:cookies) || {}).to_cookie_string + end + + def validate_format + if format && parser.respond_to?(:supports_format?) && !parser.supports_format?(format) + raise UnsupportedFormat, "'#{format.inspect}' Must be one of: #{parser.supported_formats.map{|f| f.to_s}.sort.join(', ')}" + end + end + end + + def self.normalize_base_uri(url) #:nodoc: + normalized_url = url.dup + use_ssl = (normalized_url =~ /^https/) || (normalized_url =~ /:443\b/) + ends_with_slash = normalized_url =~ /\/$/ + + normalized_url.chop! if ends_with_slash + normalized_url.gsub!(/^https?:\/\//i, '') + + "http#{'s' if use_ssl}://#{normalized_url}" + end + + class Basement #:nodoc: + include HTTParty + end + + def self.get(*args, &block) + Basement.get(*args, &block) + end + + def self.post(*args, &block) + Basement.post(*args, &block) + end + + def self.patch(*args, &block) + Basement.patch(*args, &block) + end + + def self.put(*args, &block) + Basement.put(*args, &block) + end + + def self.delete(*args, &block) + Basement.delete(*args, &block) + end + + def self.head(*args, &block) + Basement.head(*args, &block) + end + + def self.options(*args, &block) + Basement.options(*args, &block) + end +end + +require 'httparty/core_extensions' +require 'httparty/hash_conversions' +require 'httparty/exceptions' +require 'httparty/parser' +require 'httparty/request' +require 'httparty/response' diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/connection_adapter.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/connection_adapter.rb new file mode 100644 index 0000000..df3e0cc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/connection_adapter.rb @@ -0,0 +1,116 @@ +module HTTParty + # Default connection adapter that returns a new Net::HTTP each time + # + # == Custom Connection Factories + # + # If you like to implement your own connection adapter, subclassing + # HTTPParty::ConnectionAdapter will make it easier. Just override + # the #connection method. The uri and options attributes will have + # all the info you need to construct your http connection. Whatever + # you return from your connection method needs to adhere to the + # Net::HTTP interface as this is what HTTParty expects. + # + # @example log the uri and options + # class LoggingConnectionAdapter < HTTParty::ConnectionAdapter + # def connection + # puts uri + # puts options + # Net::HTTP.new(uri) + # end + # end + # + # @example count number of http calls + # class CountingConnectionAdapter < HTTParty::ConnectionAdapter + # @@count = 0 + # + # self.count + # @@count + # end + # + # def connection + # self.count += 1 + # super + # end + # end + # + # === Configuration + # There is lots of configuration data available for your connection adapter + # in the #options attribute. It is up to you to interpret them within your + # connection adapter. Take a look at the implementation of + # HTTParty::ConnectionAdapter#connection for examples of how they are used. + # Something are probably interesting are as follows: + # * :+timeout+: timeout in seconds + # * :+debug_output+: see HTTParty::ClassMethods.debug_output. + # * :+pem+: contains pem data. see HTTParty::ClassMethods.pem. + # * :+ssl_ca_file+: see HTTParty::ClassMethods.ssl_ca_file. + # * :+ssl_ca_path+: see HTTParty::ClassMethods.ssl_ca_path. + # * :+connection_adapter_options+: contains the hash your passed to HTTParty.connection_adapter when you configured your connection adapter + class ConnectionAdapter + + def self.call(uri, options) + new(uri, options).connection + end + + attr_reader :uri, :options + + def initialize(uri, options={}) + raise ArgumentError, "uri must be a URI, not a #{uri.class}" unless uri.kind_of? URI + + @uri = uri + @options = options + end + + def connection + http = Net::HTTP.new(uri.host, uri.port, options[:http_proxyaddr], options[:http_proxyport], options[:http_proxyuser], options[:http_proxypass]) + + http.use_ssl = ssl_implied?(uri) + + attach_ssl_certificates(http, options) + + if options[:timeout] && (options[:timeout].is_a?(Integer) || options[:timeout].is_a?(Float)) + http.open_timeout = options[:timeout] + http.read_timeout = options[:timeout] + end + + if options[:debug_output] + http.set_debug_output(options[:debug_output]) + end + + return http + end + + private + def ssl_implied?(uri) + uri.port == 443 || uri.instance_of?(URI::HTTPS) + end + + def attach_ssl_certificates(http, options) + if http.use_ssl? + http.verify_mode = OpenSSL::SSL::VERIFY_NONE + + # Client certificate authentication + if options[:pem] + http.cert = OpenSSL::X509::Certificate.new(options[:pem]) + http.key = OpenSSL::PKey::RSA.new(options[:pem], options[:pem_password]) + http.verify_mode = OpenSSL::SSL::VERIFY_PEER + end + + # SSL certificate authority file and/or directory + if options[:ssl_ca_file] + http.ca_file = options[:ssl_ca_file] + http.verify_mode = OpenSSL::SSL::VERIFY_PEER + end + + if options[:ssl_ca_path] + http.ca_path = options[:ssl_ca_path] + http.verify_mode = OpenSSL::SSL::VERIFY_PEER + end + + # This is only Ruby 1.9+ + if options[:ssl_version] && http.respond_to?(:ssl_version=) + http.ssl_version = options[:ssl_version] + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/cookie_hash.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/cookie_hash.rb new file mode 100644 index 0000000..e9ea92d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/cookie_hash.rb @@ -0,0 +1,22 @@ +class HTTParty::CookieHash < Hash #:nodoc: + + CLIENT_COOKIES = %w{path expires domain path secure HTTPOnly} + + def add_cookies(value) + case value + when Hash + merge!(value) + when String + value.split('; ').each do |cookie| + array = cookie.split('=') + self[array[0].to_sym] = array[1] + end + else + raise "add_cookies only takes a Hash or a String" + end + end + + def to_cookie_string + delete_if { |k, v| CLIENT_COOKIES.include?(k.to_s) }.collect { |k, v| "#{k}=#{v}" }.join("; ") + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/core_extensions.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/core_extensions.rb new file mode 100644 index 0000000..b41c00e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/core_extensions.rb @@ -0,0 +1,32 @@ +module HTTParty + if defined?(::BasicObject) + BasicObject = ::BasicObject #:nodoc: + else + class BasicObject #:nodoc: + instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval/ } + end + end + + unless defined?(Net::HTTP::Patch) + class Net::HTTP + def patch(path, data, initheader = nil, dest = nil, &block) #:nodoc: + res = nil + request(Patch.new(path, initheader), data) {|r| + r.read_body dest, &block + res = r + } + unless @newimpl + res.value + return res, res.body + end + res + end + + class Patch < Net::HTTPRequest + METHOD = 'PATCH' + REQUEST_HAS_BODY = true + RESPONSE_HAS_BODY = true + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/exceptions.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/exceptions.rb new file mode 100644 index 0000000..512aec7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/exceptions.rb @@ -0,0 +1,26 @@ +module HTTParty + # Exception raised when you attempt to set a non-existant format + class UnsupportedFormat < StandardError; end + + # Exception raised when using a URI scheme other than HTTP or HTTPS + class UnsupportedURIScheme < StandardError; end + + # @abstract Exceptions which inherit from ResponseError contain the Net::HTTP + # response object accessible via the {#response} method. + class ResponseError < StandardError + # Returns the response of the last request + # @return [Net::HTTPResponse] A subclass of Net::HTTPResponse, e.g. + # Net::HTTPOK + attr_reader :response + + # Instantiate an instance of ResponseError with a Net::HTTPResponse object + # @param [Net::HTTPResponse] + def initialize(response) + @response = response + end + end + + # Exception that is raised when request has redirected too many times. + # Calling {#response} returns the Net:HTTP response object. + class RedirectionTooDeep < ResponseError; end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/hash_conversions.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/hash_conversions.rb new file mode 100644 index 0000000..87e08cf --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/hash_conversions.rb @@ -0,0 +1,51 @@ +module HTTParty + module HashConversions + # @return This hash as a query string + # + # @example + # { :name => "Bob", + # :address => { + # :street => '111 Ruby Ave.', + # :city => 'Ruby Central', + # :phones => ['111-111-1111', '222-222-2222'] + # } + # }.to_params + # #=> "name=Bob&address[city]=Ruby Central&address[phones][]=111-111-1111&address[phones][]=222-222-2222&address[street]=111 Ruby Ave." + def self.to_params(hash) + params = hash.map { |k,v| normalize_param(k,v) }.join + params.chop! # trailing & + params + end + + # @param key The key for the param. + # @param value The value for the param. + # + # @return This key value pair as a param + # + # @example normalize_param(:name, "Bob Jones") #=> "name=Bob%20Jones&" + def self.normalize_param(key, value) + param = '' + stack = [] + + if value.is_a?(Array) + param << value.map { |element| normalize_param("#{key}[]", element) }.join + elsif value.is_a?(Hash) + stack << [key,value] + else + param << "#{key}=#{URI.encode(value.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}&" + end + + stack.each do |parent, hash| + hash.each do |key, value| + if value.is_a?(Hash) + stack << ["#{parent}[#{key}]", value] + else + param << normalize_param("#{parent}[#{key}]", value) + end + end + end + + param + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/module_inheritable_attributes.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/module_inheritable_attributes.rb new file mode 100644 index 0000000..879ca25 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/module_inheritable_attributes.rb @@ -0,0 +1,44 @@ +module HTTParty + module ModuleInheritableAttributes #:nodoc: + def self.included(base) + base.extend(ClassMethods) + end + + # borrowed from Rails 3.2 ActiveSupport + def self.hash_deep_dup(h) + duplicate = h.dup + duplicate.each_pair do |k,v| + tv = duplicate[k] + duplicate[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? hash_deep_dup(tv) : v + end + duplicate + end + + module ClassMethods #:nodoc: + def mattr_inheritable(*args) + @mattr_inheritable_attrs ||= [:mattr_inheritable_attrs] + @mattr_inheritable_attrs += args + args.each do |arg| + module_eval %(class << self; attr_accessor :#{arg} end) + end + @mattr_inheritable_attrs + end + + def inherited(subclass) + super + @mattr_inheritable_attrs.each do |inheritable_attribute| + ivar = "@#{inheritable_attribute}" + subclass.instance_variable_set(ivar, instance_variable_get(ivar).clone) + if instance_variable_get(ivar).respond_to?(:merge) + method = <<-EOM + def self.#{inheritable_attribute} + #{ivar} = superclass.#{inheritable_attribute}.merge ModuleInheritableAttributes.hash_deep_dup(#{ivar}) + end + EOM + subclass.class_eval method + end + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/net_digest_auth.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/net_digest_auth.rb new file mode 100644 index 0000000..6e262d0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/net_digest_auth.rb @@ -0,0 +1,84 @@ +require 'digest/md5' +require 'net/http' + +module Net + module HTTPHeader + def digest_auth(username, password, response) + @header['Authorization'] = DigestAuthenticator.new(username, password, + @method, @path, response).authorization_header + end + + + class DigestAuthenticator + def initialize(username, password, method, path, response_header) + @username = username + @password = password + @method = method + @path = path + @response = parse(response_header) + end + + def authorization_header + @cnonce = md5(random) + header = [ + %Q(Digest username="#{@username}"), + %Q(realm="#{@response['realm']}"), + %Q(nonce="#{@response['nonce']}"), + %Q(uri="#{@path}"), + %Q(response="#{request_digest}"), + ] + + if qop_present? + fields = [ + %Q(cnonce="#{@cnonce}"), + %Q(qop="#{@response['qop']}"), + %Q(nc="00000001") + ] + fields.each { |field| header << field } + end + + header << %Q(opaque="#{@response['opaque']}") if opaque_present? + header + end + + private + + def parse(response_header) + response_header['www-authenticate'] =~ /^(\w+) (.*)/ + params = {} + $2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 } + params + end + + def opaque_present? + @response.has_key?('opaque') and not @response['opaque'].empty? + end + + def qop_present? + @response.has_key?('qop') and not @response['qop'].empty? + end + + def random + "%x" % (Time.now.to_i + rand(65535)) + end + + def request_digest + a = [md5(a1), @response['nonce'], md5(a2)] + a.insert(2, "00000001", @cnonce, @response['qop']) if qop_present? + md5(a.join(":")) + end + + def md5(str) + Digest::MD5.hexdigest(str) + end + + def a1 + [@username, @response['realm'], @password].join(":") + end + + def a2 + [@method, @path].join(":") + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/parser.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/parser.rb new file mode 100644 index 0000000..3b9e67e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/parser.rb @@ -0,0 +1,145 @@ +module HTTParty + # The default parser used by HTTParty, supports xml, json, html, yaml, and + # plain text. + # + # == Custom Parsers + # + # If you'd like to do your own custom parsing, subclassing HTTParty::Parser + # will make that process much easier. There are a few different ways you can + # utilize HTTParty::Parser as a superclass. + # + # @example Intercept the parsing for all formats + # class SimpleParser < HTTParty::Parser + # def parse + # perform_parsing + # end + # end + # + # @example Add the atom format and parsing method to the default parser + # class AtomParsingIncluded < HTTParty::Parser + # SupportedFormats.merge!( + # {"application/atom+xml" => :atom} + # ) + # + # def atom + # perform_atom_parsing + # end + # end + # + # @example Only support the atom format + # class ParseOnlyAtom < HTTParty::Parser + # SupportedFormats = {"application/atom+xml" => :atom} + # + # def atom + # perform_atom_parsing + # end + # end + # + # @abstract Read the Custom Parsers section for more information. + class Parser + SupportedFormats = { + 'text/xml' => :xml, + 'application/xml' => :xml, + 'application/json' => :json, + 'text/json' => :json, + 'application/javascript' => :json, + 'text/javascript' => :json, + 'text/html' => :html, + 'application/x-yaml' => :yaml, + 'text/yaml' => :yaml, + 'text/plain' => :plain + } + + # The response body of the request + # @return [String] + attr_reader :body + + # The intended parsing format for the request + # @return [Symbol] e.g. :json + attr_reader :format + + # Instantiate the parser and call {#parse}. + # @param [String] body the response body + # @param [Symbol] format the response format + # @return parsed response + def self.call(body, format) + new(body, format).parse + end + + # @return [Hash] the SupportedFormats hash + def self.formats + const_get(:SupportedFormats) + end + + # @param [String] mimetype response MIME type + # @return [Symbol] + # @return [nil] mime type not supported + def self.format_from_mimetype(mimetype) + formats[formats.keys.detect {|k| mimetype.include?(k)}] + end + + # @return [Array] list of supported formats + def self.supported_formats + formats.values.uniq + end + + # @param [Symbol] format e.g. :json, :xml + # @return [Boolean] + def self.supports_format?(format) + supported_formats.include?(format) + end + + def initialize(body, format) + @body = body + @format = format + end + + # @return [Object] the parsed body + # @return [nil] when the response body is nil, an empty string, spaces only or "null" + def parse + return nil if body.nil? || body.strip.empty? || body == "null" + if supports_format? + parse_supported_format + else + body + end + end + + protected + + def xml + MultiXml.parse(body) + end + + def json + # https://github.com/sferik/rails/commit/5e62670131dfa1718eaf21ff8dd3371395a5f1cc + if MultiJson.respond_to?(:adapter) + MultiJson.load(body) + else + MultiJson.decode(body) + end + end + + def yaml + YAML.load(body) + end + + def html + body + end + + def plain + body + end + + def supports_format? + self.class.supports_format?(format) + end + + def parse_supported_format + send(format) + rescue NoMethodError => e + raise NotImplementedError, "#{self.class.name} has not implemented a parsing method for the #{format.inspect} format.", e.backtrace + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/request.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/request.rb new file mode 100644 index 0000000..032de69 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/request.rb @@ -0,0 +1,239 @@ +module HTTParty + class Request #:nodoc: + SupportedHTTPMethods = [ + Net::HTTP::Get, + Net::HTTP::Post, + Net::HTTP::Patch, + Net::HTTP::Put, + Net::HTTP::Delete, + Net::HTTP::Head, + Net::HTTP::Options + ] + + SupportedURISchemes = [URI::HTTP, URI::HTTPS] + + NON_RAILS_QUERY_STRING_NORMALIZER = Proc.new do |query| + Array(query).map do |key, value| + if value.nil? + key.to_s + elsif value.is_a?(Array) + value.map {|v| "#{key}=#{URI.encode(v.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}"} + else + HashConversions.to_params(key => value) + end + end.flatten.sort.join('&') + end + + attr_accessor :http_method, :path, :options, :last_response, :redirect, :last_uri + + def initialize(http_method, path, o={}) + self.http_method = http_method + self.path = path + self.options = { + :limit => o.delete(:no_follow) ? 1 : 5, + :default_params => {}, + :follow_redirects => true, + :parser => Parser, + :connection_adapter => ConnectionAdapter + }.merge(o) + end + + def path=(uri) + @path = URI.parse(uri) + end + + def uri + new_uri = path.relative? ? URI.parse("#{base_uri}#{path}") : path + + # avoid double query string on redirects [#12] + unless redirect + new_uri.query = query_string(new_uri) + end + + unless SupportedURISchemes.include? new_uri.class + raise UnsupportedURIScheme, "'#{new_uri}' Must be HTTP or HTTPS" + end + + @last_uri = new_uri + end + + def base_uri + redirect ? "#{@last_uri.scheme}://#{@last_uri.host}" : options[:base_uri] + end + + def format + options[:format] || (format_from_mimetype(last_response['content-type']) if last_response) + end + + def parser + options[:parser] + end + + def connection_adapter + options[:connection_adapter] + end + + def perform(&block) + validate + setup_raw_request + chunked_body = nil + + self.last_response = http.request(@raw_request) do |http_response| + if block + chunks = [] + + http_response.read_body do |fragment| + chunks << fragment + block.call(fragment) + end + + chunked_body = chunks.join + end + end + + handle_deflation + handle_response(chunked_body) + end + + private + + def http + connection_adapter.call(uri, options) + end + + def body + options[:body].is_a?(Hash) ? normalize_query(options[:body]) : options[:body] + end + + def credentials + options[:basic_auth] || options[:digest_auth] + end + + def username + credentials[:username] + end + + def password + credentials[:password] + end + + def normalize_query(query) + if query_string_normalizer + query_string_normalizer.call(query) + else + HashConversions.to_params(query) + end + end + + def query_string_normalizer + options[:query_string_normalizer] + end + + def setup_raw_request + @raw_request = http_method.new(uri.request_uri) + @raw_request.body = body if body + @raw_request.initialize_http_header(options[:headers]) + @raw_request.basic_auth(username, password) if options[:basic_auth] + setup_digest_auth if options[:digest_auth] + end + + def setup_digest_auth + auth_request = http_method.new(uri.request_uri) + auth_request.initialize_http_header(options[:headers]) + res = http.request(auth_request) + + if res['www-authenticate'] != nil && res['www-authenticate'].length > 0 + @raw_request.digest_auth(username, password, res) + end + end + + def query_string(uri) + query_string_parts = [] + query_string_parts << uri.query unless uri.query.nil? + + if options[:query].is_a?(Hash) + query_string_parts << normalize_query(options[:default_params].merge(options[:query])) + else + query_string_parts << normalize_query(options[:default_params]) unless options[:default_params].empty? + query_string_parts << options[:query] unless options[:query].nil? + end + + query_string_parts.size > 0 ? query_string_parts.join('&') : nil + end + + def handle_response(body) + if response_redirects? + options[:limit] -= 1 + self.path = last_response['location'] + self.redirect = true + self.http_method = Net::HTTP::Get unless options[:maintain_method_across_redirects] + capture_cookies(last_response) + perform + else + body = body || last_response.body + Response.new(self, last_response, lambda { parse_response(body) }, :body => body) + end + end + + # Inspired by Ruby 1.9 + def handle_deflation + case last_response["content-encoding"] + when "gzip", "x-gzip" + body_io = StringIO.new(last_response.body) + last_response.body.replace Zlib::GzipReader.new(body_io).read + last_response.delete('content-encoding') + when "deflate" + last_response.body.replace Zlib::Inflate.inflate(last_response.body) + last_response.delete('content-encoding') + end + end + + def response_redirects? + case last_response + when Net::HTTPMultipleChoice, # 300 + Net::HTTPMovedPermanently, # 301 + Net::HTTPFound, # 302 + Net::HTTPSeeOther, # 303 + Net::HTTPUseProxy, # 305 + Net::HTTPTemporaryRedirect + options[:follow_redirects] && last_response.key?('location') + end + end + + def parse_response(body) + parser.call(body, format) + end + + def capture_cookies(response) + return unless response['Set-Cookie'] + cookies_hash = HTTParty::CookieHash.new() + cookies_hash.add_cookies(options[:headers]['Cookie']) if options[:headers] && options[:headers]['Cookie'] + cookies_hash.add_cookies(response['Set-Cookie']) + options[:headers] ||= {} + options[:headers]['Cookie'] = cookies_hash.to_cookie_string + end + + # Uses the HTTP Content-Type header to determine the format of the + # response It compares the MIME type returned to the types stored in the + # SupportedFormats hash + def format_from_mimetype(mimetype) + if mimetype && parser.respond_to?(:format_from_mimetype) + parser.format_from_mimetype(mimetype) + end + end + + def validate + raise HTTParty::RedirectionTooDeep.new(last_response), 'HTTP redirects too deep' if options[:limit].to_i <= 0 + raise ArgumentError, 'only get, post, patch, put, delete, head, and options methods are supported' unless SupportedHTTPMethods.include?(http_method) + raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].is_a?(Hash) + raise ArgumentError, 'only one authentication method, :basic_auth or :digest_auth may be used at a time' if options[:basic_auth] && options[:digest_auth] + raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].is_a?(Hash) + raise ArgumentError, ':digest_auth must be a hash' if options[:digest_auth] && !options[:digest_auth].is_a?(Hash) + raise ArgumentError, ':query must be hash if using HTTP Post' if post? && !options[:query].nil? && !options[:query].is_a?(Hash) + end + + def post? + Net::HTTP::Post == http_method + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/response.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/response.rb new file mode 100644 index 0000000..3193b99 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/response.rb @@ -0,0 +1,62 @@ +module HTTParty + class Response < HTTParty::BasicObject #:nodoc: + def self.underscore(string) + string.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z])([A-Z])/,'\1_\2').downcase + end + + attr_reader :request, :response, :body, :headers + + def initialize(request, response, parsed_block, options={}) + @request = request + @response = response + @body = response.body || options[:body] + @parsed_block = parsed_block + @headers = Headers.new(response.to_hash) + end + + def parsed_response + @parsed_response ||= @parsed_block.call + end + + def class + Response + end + + def code + response.code.to_i + end + + def inspect + inspect_id = "%x" % (object_id * 2) + %(#<#{self.class}:0x#{inspect_id} parsed_response=#{parsed_response.inspect}, @response=#{response.inspect}, @headers=#{headers.inspect}>) + end + + CODES_TO_OBJ = ::Net::HTTPResponse::CODE_CLASS_TO_OBJ.merge ::Net::HTTPResponse::CODE_TO_OBJ + + CODES_TO_OBJ.each do |response_code, klass| + name = klass.name.sub("Net::HTTP", '') + define_method("#{underscore(name)}?") do + klass === response + end + end + + def respond_to?(name) + return true if [:request, :response, :parsed_response, :body, :headers].include?(name) + parsed_response.respond_to?(name) || response.respond_to?(name) + end + + protected + + def method_missing(name, *args, &block) + if parsed_response.respond_to?(name) + parsed_response.send(name, *args, &block) + elsif response.respond_to?(name) + response.send(name, *args, &block) + else + super + end + end + end +end + +require 'httparty/response/headers' diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/response/headers.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/response/headers.rb new file mode 100644 index 0000000..c4ed90b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/response/headers.rb @@ -0,0 +1,31 @@ +module HTTParty + class Response #:nodoc: + class Headers + include ::Net::HTTPHeader + + def initialize(header = {}) + @header = header + end + + def ==(other) + @header == other + end + + def inspect + @header.inspect + end + + def method_missing(name, *args, &block) + if @header.respond_to?(name) + @header.send(name, *args, &block) + else + super + end + end + + def respond_to?(method) + super || @header.respond_to?(method) + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/version.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/version.rb new file mode 100644 index 0000000..65999b8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/lib/httparty/version.rb @@ -0,0 +1,3 @@ +module HTTParty + VERSION = "0.9.0" +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/delicious.xml b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/delicious.xml new file mode 100644 index 0000000..f93a1ee --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/delicious.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/empty.xml b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/empty.xml new file mode 100644 index 0000000..e69de29 diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/google.html b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/google.html new file mode 100644 index 0000000..1c4221d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/google.html @@ -0,0 +1,3 @@ +Google

Google

 
  Advanced Search
  Preferences
  Language Tools


Advertising Programs - Business Solutions - About Google

©2008 - Privacy

\ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generate.sh b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generate.sh new file mode 100755 index 0000000..1ef76e2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generate.sh @@ -0,0 +1,29 @@ +#!/bin/sh +set -e + +if [ -d "generated" ] ; then + echo >&2 "error: 'generated' directory already exists. Delete it first." + exit 1 +fi + +mkdir generated + +# Generate the CA private key and certificate +openssl req -batch -subj '/CN=INSECURE Test Certificate Authority' -newkey rsa:1024 -new -x509 -days 999999 -keyout generated/ca.key -nodes -out generated/ca.crt + +# Create symlinks for ssl_ca_path +c_rehash generated + +# Generate the server private key and self-signed certificate +openssl req -batch -subj '/CN=localhost' -newkey rsa:1024 -new -x509 -days 999999 -keyout generated/server.key -nodes -out generated/selfsigned.crt + +# Generate certificate signing request with bogus hostname +openssl req -batch -subj '/CN=bogo' -new -days 999999 -key generated/server.key -nodes -out generated/bogushost.csr + +# Sign the certificate requests +openssl x509 -CA generated/ca.crt -CAkey generated/ca.key -set_serial 1 -in generated/selfsigned.crt -out generated/server.crt -clrext -extfile openssl-exts.cnf -extensions cert -days 999999 +openssl x509 -req -CA generated/ca.crt -CAkey generated/ca.key -set_serial 1 -in generated/bogushost.csr -out generated/bogushost.crt -clrext -extfile openssl-exts.cnf -extensions cert -days 999999 + +# Remove certificate signing requests +rm -f generated/*.csr + diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/1fe462c2.0 b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/1fe462c2.0 new file mode 100644 index 0000000..215f366 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/1fe462c2.0 @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICbTCCAdagAwIBAgIJAIAeO9TXtJ45MA0GCSqGSIb3DQEBBQUAMC4xLDAqBgNV +BAMTI0lOU0VDVVJFIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MCAXDTEwMTAy +MDEzNDYyM1oYDzQ3NDgwOTE1MTM0NjIzWjAuMSwwKgYDVQQDEyNJTlNFQ1VSRSBU +ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEA3lkBcd352qiIIzqnyvvJj59cx1dnzMyjnuaK2cRH420rBfukLE2MbOVr +9nYq/7CdjqXpE8uFAF+UTSIK6MWZ/bidkr2xd/et/Ce2pVIVxH+rt3pJz3wZhC3H +Yz+HU4CD2iI9wAzsb6mMV7md1fjlYfir4SBGGPTkcqUJUp2/tQMCAwEAAaOBkDCB +jTAdBgNVHQ4EFgQUy0Lz6RgmtpywlBOXdPABQArp358wXgYDVR0jBFcwVYAUy0Lz +6RgmtpywlBOXdPABQArp35+hMqQwMC4xLDAqBgNVBAMTI0lOU0VDVVJFIFRlc3Qg +Q2VydGlmaWNhdGUgQXV0aG9yaXR5ggkAgB471Ne0njkwDAYDVR0TBAUwAwEB/zAN +BgkqhkiG9w0BAQUFAAOBgQCmi3JQm+EIWjkRlyz9sijkYS+Ps4opmd/weeaXwa4E +gVBWJGyiduB+kBnfv61+/tDjlrbjBDH5dP8suczHQL8gox4zGgjw64KH4o1ujZYR +cEPbhnUpwbXu7yItlajBZfpFefjF5P0Ao2iEzQldDy0D6nQ19h5QANvQxqweTPQp +pw== +-----END CERTIFICATE----- diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/bogushost.crt b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/bogushost.crt new file mode 100644 index 0000000..cf1e66d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/bogushost.crt @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICBTCCAW6gAwIBAgIBATANBgkqhkiG9w0BAQUFADAuMSwwKgYDVQQDEyNJTlNF +Q1VSRSBUZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0xMDEwMjAxMzQ2MjNa +GA80NzQ4MDkxNTEzNDYyM1owDzENMAsGA1UEAxMEYm9nbzCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAr6b0ZBrRrVvPmPbQv36Jnj5jv00ZkhimXrmbv9Z1AdIZ +WSsBpMd8TP7exE5OR5/DaxKmiZqVskgRyRkLm52/Dkt7Ncrzr5I3unHnMqsAv/28 +5fGlYoRxnkCGMse/6NOFgCemRFw/bglxPNAGrFYKStameBRbCm0dCgtlvcwzdf8C +AwEAAaNQME4wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUddLPFtGmb0aFWbTl2kAo +xD+fd6kwHwYDVR0jBBgwFoAUy0Lz6RgmtpywlBOXdPABQArp358wDQYJKoZIhvcN +AQEFBQADgYEAosqpPVsFu6cOIhGFT85Y1wwRUaihO0vWO7ghBU5ScuRU3tuvyJDZ +Z/HoAMXV6XZjVZzRosjtPjFbyWkZYjUqJJRMyEaRiGArWe6urKLzwnD6R9O3eNa5 +7bgFhzZ5WBldJmtq4A3oNqBuvgZkYM6NVKvS4UoakkTliHB21/mDOSY= +-----END CERTIFICATE----- diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/ca.crt b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/ca.crt new file mode 100644 index 0000000..215f366 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/ca.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICbTCCAdagAwIBAgIJAIAeO9TXtJ45MA0GCSqGSIb3DQEBBQUAMC4xLDAqBgNV +BAMTI0lOU0VDVVJFIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MCAXDTEwMTAy +MDEzNDYyM1oYDzQ3NDgwOTE1MTM0NjIzWjAuMSwwKgYDVQQDEyNJTlNFQ1VSRSBU +ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEA3lkBcd352qiIIzqnyvvJj59cx1dnzMyjnuaK2cRH420rBfukLE2MbOVr +9nYq/7CdjqXpE8uFAF+UTSIK6MWZ/bidkr2xd/et/Ce2pVIVxH+rt3pJz3wZhC3H +Yz+HU4CD2iI9wAzsb6mMV7md1fjlYfir4SBGGPTkcqUJUp2/tQMCAwEAAaOBkDCB +jTAdBgNVHQ4EFgQUy0Lz6RgmtpywlBOXdPABQArp358wXgYDVR0jBFcwVYAUy0Lz +6RgmtpywlBOXdPABQArp35+hMqQwMC4xLDAqBgNVBAMTI0lOU0VDVVJFIFRlc3Qg +Q2VydGlmaWNhdGUgQXV0aG9yaXR5ggkAgB471Ne0njkwDAYDVR0TBAUwAwEB/zAN +BgkqhkiG9w0BAQUFAAOBgQCmi3JQm+EIWjkRlyz9sijkYS+Ps4opmd/weeaXwa4E +gVBWJGyiduB+kBnfv61+/tDjlrbjBDH5dP8suczHQL8gox4zGgjw64KH4o1ujZYR +cEPbhnUpwbXu7yItlajBZfpFefjF5P0Ao2iEzQldDy0D6nQ19h5QANvQxqweTPQp +pw== +-----END CERTIFICATE----- diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/ca.key b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/ca.key new file mode 100644 index 0000000..49f22aa --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/ca.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDeWQFx3fnaqIgjOqfK+8mPn1zHV2fMzKOe5orZxEfjbSsF+6Qs +TYxs5Wv2dir/sJ2OpekTy4UAX5RNIgroxZn9uJ2SvbF39638J7alUhXEf6u3eknP +fBmELcdjP4dTgIPaIj3ADOxvqYxXuZ3V+OVh+KvhIEYY9ORypQlSnb+1AwIDAQAB +AoGBAL147VFCDlM1gGU865V+wIFCFQbNxedwjxGuda4io/v6oEoF6R3Tq5F0Y27v +va6Lq4fOe/LhYGI0EKU2GEPJd3F2wA21r+81InPKAkqYI5CDQtKDDNLviur8ZVKF +i3UzutjeYoCqmWeHaKPD6w5DtqeBieem7LTWRyXlFtHZV/nBAkEA8nsMOSd1+JTm +ZT4HDsEFQrN8mIFUUioFSHPut2CwzvTEW+hTkLQiog3bua4n7uQOFImR63X9qMsh +IjZRJQNmowJBAOq+mQdnRWYKl0SYb++Eb3uW6L4h1zsW375+caKo9omtpeqDW/y0 +BWyY0q4DPkm3yU26Yr+b2JijISrml9/8PiECQQDHuXyG8y7jktn3GFE94NURbL+6 +6gPnLX9ufzdoSjc4MDowrbtvHEDOlHWgioeP6L6EQhA0DtrhlnbzNCRARX3bAkEA +jQOsF+dwqAjKr/lGnMKY2cxgyf64NZXbGKsKhmUrnK9E0SjR9G8MJx1yyffGzi/q +bJf/xAzRw3eTcBsPtwznIQJAHq5MOK7oaUuO+6cbsZYpOYOOkKIvDLiOtdSr7LTI +DziH/fpzB0VhCmFhhEQwHhlB4t3m66A9TelHmhrCDsIaLA== +-----END RSA PRIVATE KEY----- diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/selfsigned.crt b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/selfsigned.crt new file mode 100644 index 0000000..435856a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/selfsigned.crt @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICHTCCAYagAwIBAgIJALT/G+ylQljIMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV +BAMTCWxvY2FsaG9zdDAgFw0xMDEwMjAxMzQ2MjNaGA80NzQ4MDkxNTEzNDYyM1ow +FDESMBAGA1UEAxMJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQCvpvRkGtGtW8+Y9tC/fomePmO/TRmSGKZeuZu/1nUB0hlZKwGkx3xM/t7ETk5H +n8NrEqaJmpWySBHJGQubnb8OS3s1yvOvkje6cecyqwC//bzl8aVihHGeQIYyx7/o +04WAJ6ZEXD9uCXE80AasVgpK1qZ4FFsKbR0KC2W9zDN1/wIDAQABo3UwczAdBgNV +HQ4EFgQUddLPFtGmb0aFWbTl2kAoxD+fd6kwRAYDVR0jBD0wO4AUddLPFtGmb0aF +WbTl2kAoxD+fd6mhGKQWMBQxEjAQBgNVBAMTCWxvY2FsaG9zdIIJALT/G+ylQljI +MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAlOCBO54S88mD3VYviER6 +V+lkd7iWmdas2wUUDeMKA9CxnirWi7ne2U7wQH/5FJ1j3ImSfjb4h/98xiVJE84e +Ld7mb61g/M4g4b62kt0HK8/cGUxfuz5zwIfi28qJq3ow6AFEq1fywbJvUAnnamwU +cZF/qoVfJhus2mXjYc4hFWg= +-----END CERTIFICATE----- diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/server.crt b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/server.crt new file mode 100644 index 0000000..327f269 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/server.crt @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICCjCCAXOgAwIBAgIBATANBgkqhkiG9w0BAQUFADAuMSwwKgYDVQQDEyNJTlNF +Q1VSRSBUZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0xMDEwMjAxMzQ2MjNa +GA80NzQ4MDkxNTEzNDYyM1owFDESMBAGA1UEAxMJbG9jYWxob3N0MIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQCvpvRkGtGtW8+Y9tC/fomePmO/TRmSGKZeuZu/ +1nUB0hlZKwGkx3xM/t7ETk5Hn8NrEqaJmpWySBHJGQubnb8OS3s1yvOvkje6cecy +qwC//bzl8aVihHGeQIYyx7/o04WAJ6ZEXD9uCXE80AasVgpK1qZ4FFsKbR0KC2W9 +zDN1/wIDAQABo1AwTjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBR10s8W0aZvRoVZ +tOXaQCjEP593qTAfBgNVHSMEGDAWgBTLQvPpGCa2nLCUE5d08AFACunfnzANBgkq +hkiG9w0BAQUFAAOBgQCR4Oor0YAvK0tNFrOLtqmC6D0F5IYCyu7komk7JGn9L4nn +7VyVxd4MXdc1r1v+WP5JtnA9ZjMmEmH9gl4gwR/Cu+TMkArsq0Z8mREOLNL8pwpx +Zxgk0CwacYR9RQcpuJ9nSDzVoO5ecYkb5C9q7gwgqbmCzr7oz/rwTqRwiUZCVQ== +-----END CERTIFICATE----- diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/server.key b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/server.key new file mode 100644 index 0000000..010aec2 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/generated/server.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQCvpvRkGtGtW8+Y9tC/fomePmO/TRmSGKZeuZu/1nUB0hlZKwGk +x3xM/t7ETk5Hn8NrEqaJmpWySBHJGQubnb8OS3s1yvOvkje6cecyqwC//bzl8aVi +hHGeQIYyx7/o04WAJ6ZEXD9uCXE80AasVgpK1qZ4FFsKbR0KC2W9zDN1/wIDAQAB +AoGALIdgkTgTS6VovVhklwcXEBy04LxE7Tp+gqj/COTvCKUgc/BpHELOCh7ajl1j +jti7i5tQyLV9mZKXn6lPvgWBd0w+p6VhM4NFA97CoodEJm2ckFC9zUABCh9dOpbm +8KzF7hdpYWgJJchwwZ60tbcP7K1DkiNX6Kk9qKQEWvitMBECQQDpOSzzLldcEU9l +ze/nG2+rf6ecaPnKeafY8R2qVils8I7ZJAW3+0bNT5gQs7rT7aWo8vMvrXq++lWb +JkNV6hK9AkEAwM5wsmg7REmAaDwgUBq5mNt963/uG2ihAODFS70lYT23UYl5Y3rD +s3qU4ntG4DvWIQgPdwdstzDh9fMBVXa1awJBAID1WoOE5k1ETRDP1I2HwDGmPnng +Ge75YfQ1LuAXEITqZzJuFrNqv/Waw0zI9M9moqlO3WVJmYusRFWrzKPe8EkCQEwC +FlN+275z63csHOD3aCtmfCGW8VtEyBP8iErvagkHt3khZQVepD/hF0ihqLNFY4jq +EI6wEp+1WZ8ICYKTpbkCQQDhl5QLdy5Xo3k3agCnB9nktSzs2iqFvsGvfOAW4628 +iThKTNua6bBvbdiG0Vh2Sv0XBYVJoHB3WnTVgFyPJaaF +-----END RSA PRIVATE KEY----- diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/openssl-exts.cnf b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/openssl-exts.cnf new file mode 100644 index 0000000..a7bf5fd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/ssl/openssl-exts.cnf @@ -0,0 +1,9 @@ +[ca] +basicConstraints=critical,CA:true +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer:always + +[cert] +basicConstraints=critical,CA:false +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/twitter.json b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/twitter.json new file mode 100644 index 0000000..642dd01 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/twitter.json @@ -0,0 +1 @@ +[{"user":{"followers_count":1,"description":null,"url":null,"profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png","protected":false,"location":"Opera Plaza, California","screen_name":"Pyk","name":"Pyk","id":"7694602"},"text":"@lapilofu If you need a faster transfer, target disk mode should work too :)","truncated":false,"favorited":false,"in_reply_to_user_id":6128642,"created_at":"Sat Dec 06 21:29:14 +0000 2008","source":"twitterrific","in_reply_to_status_id":1042497164,"id":"1042500587"},{"user":{"followers_count":278,"description":"しがないプログラマ\/とりあえず宮子は俺の嫁\u2026いや、娘だ!\/Delphi&Pythonプログラマ修行中\/bot製作にハマりつつある。三つほど製作&構想中\/[eof]","url":"http:\/\/logiq.orz.hm\/","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/59588711\/l_ワ_l↑_normal.png","protected":false,"location":"ひだまり荘202号室","screen_name":"feiz","name":"azkn3","id":"14310520"},"text":"@y_benjo ちょー遅レスですがただのはだいろすぎる・・・ ( ll ワ ll )","truncated":false,"favorited":false,"in_reply_to_user_id":8428752,"created_at":"Sat Dec 06 21:29:14 +0000 2008","source":"twit","in_reply_to_status_id":1042479758,"id":"1042500586"},{"user":{"followers_count":1233,"description":""to understand one life you must swallow the world." I run refine+focus: a marketing agency working w\/ brands, media and VCs. http:\/\/tinyurl.com\/63mrn","url":"http:\/\/www.quiverandquill.com","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/53684650\/539059005_2a3b462d20_normal.jpg","protected":false,"location":"Cambridge, MA ","screen_name":"quiverandquill","name":"zach Braiker","id":"6845872"},"text":"@18percentgrey I didn't see Damon on Palin. i'll look on youtube. thx .Z","truncated":false,"favorited":false,"in_reply_to_user_id":10529932,"created_at":"Sat Dec 06 21:29:12 +0000 2008","source":"web","in_reply_to_status_id":1042499331,"id":"1042500584"},{"user":{"followers_count":780,"description":"Mein Blog ist unter http:\/\/blog.helmschrott.de zu finden. Unter http:\/\/blogalm.de kannst Du Deinen Blog eintragen!","url":"http:\/\/helmschrott.de\/blog","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/60997686\/avatar-250_normal.jpg","protected":false,"location":"Münchner Straße","screen_name":"helmi","name":"Frank Helmschrott","id":"867641"},"text":"@gigold auch mist oder?ich glaub ich fangs jetzt dann einfach mal an - wird schon vernünftige update-prozesse geben.","truncated":false,"favorited":false,"in_reply_to_user_id":959931,"created_at":"Sat Dec 06 21:29:11 +0000 2008","source":"twhirl","in_reply_to_status_id":1042500095,"id":"1042500583"},{"user":{"followers_count":63,"description":"Liberation from Misconceptions","url":"http:\/\/sexorcism.blogspot.com","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/63897302\/having-sex-on-bed_normal.jpg","protected":false,"location":"USA","screen_name":"Sexorcism","name":"Sexorcism","id":"16929435"},"text":"@thursdays_child someecards might.","truncated":false,"favorited":false,"in_reply_to_user_id":14484963,"created_at":"Sat Dec 06 21:29:13 +0000 2008","source":"twittergadget","in_reply_to_status_id":1042499777,"id":"1042500581"},{"user":{"followers_count":106,"description":"Researcher. Maître de Conférences - Sémiologue - Spécialiste des médias audiovisuels. Analyste des médias, de la télévision et de la presse people (gossip). ","url":"http:\/\/semioblog.over-blog.org\/","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/57988482\/Thomas_et_Vic_pour_promo_2_058_normal.JPG","protected":false,"location":"France","screen_name":"semioblog","name":"Virginie Spies","id":"10078802"},"text":"@richardvonstern on reparle de tout cela bientôt, si vous voulez vraiment m'aider","truncated":false,"favorited":false,"in_reply_to_user_id":15835317,"created_at":"Sat Dec 06 21:29:13 +0000 2008","source":"twitterrific","in_reply_to_status_id":1042357537,"id":"1042500580"},{"user":{"followers_count":26,"description":"","url":"","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/63461084\/November2ndpics_125_normal.jpg","protected":false,"location":"Louisville, Ky","screen_name":"scrapaunt","name":"scrapaunt","id":"16660671"},"text":"@NKOTB4LIFE Hope your neck feels better after your nap.","truncated":false,"favorited":false,"in_reply_to_user_id":16041403,"created_at":"Sat Dec 06 21:29:10 +0000 2008","source":"web","in_reply_to_status_id":1042450159,"id":"1042500579"},{"user":{"followers_count":245,"description":"Maui HI Real Estate Salesperson specializing in off the grid lifestyle","url":"http:\/\/www.eastmaui.com","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/59558480\/face2_normal.jpg","protected":false,"location":"north shore maui hawaii","screen_name":"mauihunter","name":"Georgina M. Hunter ","id":"16161708"},"text":"@BeeRealty http:\/\/twitpic.com\/qpog - It's a good safe place to lay - no dogs up there.","truncated":false,"favorited":false,"in_reply_to_user_id":15781063,"created_at":"Sat Dec 06 21:29:13 +0000 2008","source":"twitpic","in_reply_to_status_id":1042497815,"id":"1042500578"},{"user":{"followers_count":95,"description":"","url":"","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/66581657\/nose-pick_normal.jpg","protected":false,"location":"zoetermeer","screen_name":"GsKlukkluk","name":"Klukkluk","id":"14218588"},"text":"twit \/off zalige nacht!","truncated":false,"favorited":false,"in_reply_to_user_id":null,"created_at":"Sat Dec 06 21:29:14 +0000 2008","source":"web","in_reply_to_status_id":null,"id":"1042500577"},{"user":{"followers_count":33,"description":"Living in denial that I live in a podunk town, I spend my time in search of good music in LA. Pure city-dweller and puma. That's about it.","url":"","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/56024131\/Photo_145_normal.jpg","protected":false,"location":"Santa Barbara, CA","screen_name":"pumainthemvmt","name":"Valerie","id":"15266837"},"text":"I love my parents with all my heart, but sometimes they make me want to scratch my eyes out.","truncated":false,"favorited":false,"in_reply_to_user_id":null,"created_at":"Sat Dec 06 21:29:10 +0000 2008","source":"sms","in_reply_to_status_id":null,"id":"1042500576"},{"user":{"followers_count":99,"description":"大学生ですよ。Ad[es]er。趣味で辭書とか編輯してゐます。JavaScriptでゲーム書きたいけど時間ねえ。","url":"http:\/\/greengablez.net\/diary\/","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/60269370\/zonu_1_normal.gif","protected":false,"location":"Sapporo, Hokkaido, Japan","screen_name":"tadsan","name":"船越次男","id":"11637282"},"text":"リトル・プリンセスとだけ書かれたら小公女を連想するだろ、常識的に考へて。","truncated":false,"favorited":false,"in_reply_to_user_id":null,"created_at":"Sat Dec 06 21:29:11 +0000 2008","source":"tiitan","in_reply_to_status_id":null,"id":"1042500575"},{"user":{"followers_count":68,"description":"I love all things beer. What goes better with beer than Porn, nothig I tell ya nothing.","url":"","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/66479069\/Picture_9_normal.jpg","protected":false,"location":"Durant","screen_name":"Jeffporn","name":"Jeffporn","id":"14065262"},"text":"At Lefthand having milk stout on cask - Photo: http:\/\/bkite.com\/02PeH","truncated":false,"favorited":false,"in_reply_to_user_id":null,"created_at":"Sat Dec 06 21:29:10 +0000 2008","source":"brightkite","in_reply_to_status_id":null,"id":"1042500574"},{"user":{"followers_count":7,"description":"","url":"http:\/\/www.PeteKinser.com","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/65572489\/PeteKinser-close_normal.jpg","protected":false,"location":"Denver, CO","screen_name":"pkinser","name":"pkinser","id":"15570525"},"text":"Snooze is where it's at for brunch if you're ever in Denver. Yum.","truncated":false,"favorited":false,"in_reply_to_user_id":null,"created_at":"Sat Dec 06 21:29:11 +0000 2008","source":"fring","in_reply_to_status_id":null,"id":"1042500572"},{"user":{"followers_count":75,"description":"I am a gamer and this is my gaming account, check out my other Twitter account for non-gaming tweets.","url":"http:\/\/twitter.com\/Nailhead","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/56881055\/nailhead_184x184_normal.jpg","protected":false,"location":"Huntsville, AL","screen_name":"Nailhead_Gamer","name":"Eric Fullerton","id":"15487663"},"text":"Completed the epic quest line for the Death Knight. Now what? Outlands? I wish to skip Outlands please, thanks.","truncated":false,"favorited":false,"in_reply_to_user_id":null,"created_at":"Sat Dec 06 21:29:13 +0000 2008","source":"twitterfox","in_reply_to_status_id":null,"id":"1042500571"},{"user":{"followers_count":111,"description":"","url":"http:\/\/www.ns-tech.com\/blog\/geldred.nsf","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/63865052\/brak2_normal.JPG","protected":false,"location":"Cleveland OH","screen_name":"geldred","name":"geldred","id":"14093394"},"text":"I'm at Target Store - Avon OH (35830 Detroit Rd, Avon, OH 44011, USA) - http:\/\/bkite.com\/02PeI","truncated":false,"favorited":false,"in_reply_to_user_id":null,"created_at":"Sat Dec 06 21:29:13 +0000 2008","source":"brightkite","in_reply_to_status_id":null,"id":"1042500570"},{"user":{"followers_count":16,"description":"Soundtrack Composer\/Musician\/Producer","url":"http:\/\/www.reverbnation\/musicbystratos","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/63311865\/logo-stratos_normal.png","protected":false,"location":"Grove City, Ohio 43123","screen_name":"Stratos","name":"Bryan K Borgman","id":"756062"},"text":"is reminded how beautiful the world can be when it's blanketed by clean white snow.","truncated":false,"favorited":false,"in_reply_to_user_id":null,"created_at":"Sat Dec 06 21:29:13 +0000 2008","source":"web","in_reply_to_status_id":null,"id":"1042500569"},{"user":{"followers_count":7,"description":null,"url":null,"profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png","protected":false,"location":null,"screen_name":"garrettromine","name":"garrettromine","id":"16120885"},"text":"Go Julio","truncated":false,"favorited":false,"in_reply_to_user_id":null,"created_at":"Sat Dec 06 21:29:10 +0000 2008","source":"sms","in_reply_to_status_id":null,"id":"1042500568"},{"user":{"followers_count":111,"description":"WHAT IS HAPPNING IN THE WORLD??? SEE DIFFERENT NEWS STORIES FROM MANY SOURCES.","url":"http:\/\/henrynews.wetpaint.com","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/65118112\/2008-election-map-nytimes_normal.png","protected":false,"location":"","screen_name":"HenryNews","name":"HenryNews","id":"17398510"},"text":"Svindal completes double at Beaver Creek: Read full story for latest details. http:\/\/tinyurl.com\/6qugub","truncated":false,"favorited":false,"in_reply_to_user_id":null,"created_at":"Sat Dec 06 21:29:13 +0000 2008","source":"twitterfeed","in_reply_to_status_id":null,"id":"1042500567"},{"user":{"followers_count":34,"description":"I am a man of many bio's, scott bio's!","url":"http:\/\/flickr.com\/photos\/giantcandy","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/25680382\/Icon_for_Twitter_normal.jpg","protected":false,"location":"Loves Park, IL, USA","screen_name":"Pychobj2001","name":"William Boehm Jr","id":"809103"},"text":"I have a 3rd break light and the license plate lights are out...just replacing 1 plate light...abide by law just enough","truncated":false,"favorited":false,"in_reply_to_user_id":null,"created_at":"Sat Dec 06 21:29:10 +0000 2008","source":"twidroid","in_reply_to_status_id":null,"id":"1042500566"},{"user":{"followers_count":61,"description":"Wife. Designer. Green Enthusiast. New Homeowner. Pet Owner. Internet Addict.","url":"http:\/\/confessionsofadesignjunkie.blogspot.com\/","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/66044439\/n27310459_33432814_6743-1_normal.jpg","protected":false,"location":"Indiana","screen_name":"smquaseb","name":"Stacy","id":"15530992"},"text":"@Indygardener We still had a few people shoveling in our neighborhood - I didn't think it was enough to shovel, but keeps the kids busy.","truncated":false,"favorited":false,"in_reply_to_user_id":12811482,"created_at":"Sat Dec 06 21:29:13 +0000 2008","source":"web","in_reply_to_status_id":1042488558,"id":"1042500565"}] \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/twitter.xml b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/twitter.xml new file mode 100644 index 0000000..24abaa8 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/twitter.xml @@ -0,0 +1,403 @@ + + + Sun Dec 07 00:36:16 +0000 2008 + 1042729116 + @sebbo Outlook not so good + web + false + 1042716367 + 2989541 + false + + 17656026 + Magic 8 Bot + magic8bot + ask me a question + + http://s3.amazonaws.com/twitter_production/profile_images/65565851/8ball_large_normal.jpg + + false + 90 + + + Sun Dec 07 00:36:14 +0000 2008 + 1042729115 + Azdel Slade :friends from midian city http://bloghud.com/id/27312 + web + false + + + false + + 801094 + BlogHUD + bloghud + + + http://s3.amazonaws.com/twitter_production/profile_images/25235272/bloghud_twitter_normal.jpg + + false + 313 + + + Sun Dec 07 00:36:14 +0000 2008 + 1042729114 + Reading: "The Reckoning - Debt Watchdogs - Tamed or Caught Napping? - Series - NYTimes.com" ( http://tinyurl.com/5754s6 ) + twitthat + false + + + false + + 3512101 + bill + niubi + in beijing learning socialism 2 prepare 4 return 2 us + beijing + http://s3.amazonaws.com/twitter_production/profile_images/53292616/realtwitterers_normal.jpg + + false + 710 + + + Sun Dec 07 00:36:14 +0000 2008 + 1042729113 + Fianlly done and headed home! + sms + false + + + false + + 13186842 + Okthirddayfan + Okthirddayfan + + Oklahoma! + http://s3.amazonaws.com/twitter_production/profile_images/61414367/mecropped_normal.jpg + http://thirddaypix.blogspot.com/ + false + 68 + + + Sun Dec 07 00:36:16 +0000 2008 + 1042729112 + Adobe Flashplayer 10 and Debug versions: http://www.adobe.com/support/flashplayer/downloads.html + toro + false + + + false + + 15243380 + cbrueggenolte + cbrueggenolte + 27, Male, Mac Geek, Developer Java &amp; Flex &amp; Air + Aachen + http://s3.amazonaws.com/twitter_production/profile_images/55929263/214508011845f026bfd407c_normal.jpg + http://my.opera.com/carstenbrueggenolte + false + 16 + + + Sun Dec 07 00:36:14 +0000 2008 + 1042729111 + Done and done. + twitterrific + false + + + false + + 10978752 + Sergey Safonov + iron_Lung + I have my fingers in many pies. + Moscow + http://s3.amazonaws.com/twitter_production/profile_images/57841057/eat38_normal.gif + http://www.flickr.com/photos/iron_Lung + false + 11 + + + Sun Dec 07 00:36:14 +0000 2008 + 1042729110 + Veja a tabela de preços do Acquaplay da Tecnisa aqui:http://tinyurl.com/acquaplaypreco + web + false + + + false + + 13735402 + Tecnisa S.A + Tecnisa + Mais construtora por m2 + Faria Lima, 3144 - SP + http://s3.amazonaws.com/twitter_production/profile_images/56572222/logo_normal.jpg + http://www.tecnisa.com.br + false + 77 + + + Sun Dec 07 00:36:16 +0000 2008 + 1042729108 + devin harris has the flu. always have the memory of jordan scoring 50 on the knicks at the garden with the flu + web + false + + + false + + 17930773 + 24 Seconds to Shoot + NBA24sts + NBA handicapping insight and analysis. + las vegas + http://s3.amazonaws.com/twitter_production/profile_images/66593862/fresno_normal.jpg + + false + 1 + + + Sun Dec 07 00:36:16 +0000 2008 + 1042729105 + At Brandon and Shannon's holiday party.. + twitterberry + false + + + false + + 5388602 + Mike J. (Telligent) + mjamrst + Video Game Account Manager + Palo Alto, CA + http://s3.amazonaws.com/twitter_production/profile_images/66375174/Thanksgiving_11272008-048_normal.jpg + http://www.telligent.com + false + 225 + + + Sun Dec 07 00:36:13 +0000 2008 + 1042729104 + Xinhua: Forty percent of Australian PM office' staff quit : CANBERRA, Dec. 7 (Xinhua) -- Only.. http://tinyurl.com/5gwotd + twitterfeed + false + + + false + + 11566502 + Headline News + headlinenews + + + http://s3.amazonaws.com/twitter_production/profile_images/41784602/1890_wires_normal.jpg + + false + 575 + + + Sun Dec 07 00:36:13 +0000 2008 + 1042729101 + @hilarycassman soo funnny + sms + false + 1042725825 + 17644455 + false + + 17887548 + katieballss + katieballss + + + http://s3.amazonaws.com/twitter_production/profile_images/66523737/th_Photo87_normal.jpg + http://www.myspace.com/xxpeachxx101 + false + 23 + + + Sun Dec 07 00:36:13 +0000 2008 + 1042729100 + d'ora in poi, oltre al ferragosto, odiera' anche il natale e tutto il mese che ci gira intorno.. =.='' + mobile + false + + + false + + 9719482 + trotto + trotto + sociologo di formazione... uno dei tanti attivisti! :) + Fano - Italy + http://s3.amazonaws.com/twitter_production/profile_images/55603933/mybob-calimetux-1526_normal.png + http://trotto1308.netsons.org/wordpress/ + false + 98 + + + Sun Dec 07 00:36:13 +0000 2008 + 1042729099 + Came across an ad on another site with a redneck looking santa... said "Bust Santa's zit and win a free ipod." Umm... disturbing much? + web + false + + + false + + 9937182 + froggybluesock + froggybluesock + + Indiana + http://s3.amazonaws.com/twitter_production/profile_images/35393032/about_me_normal.jpg + http://www.footprintsonthemoon.com + false + 82 + + + Sun Dec 07 00:36:17 +0000 2008 + 1042729098 + nothing + web + false + + + false + + 17932339 + treblehook + treblehook + + + http://static.twitter.com/images/default_profile_normal.png + + false + 0 + + + Sun Dec 07 00:36:13 +0000 2008 + 1042729095 + Setting up my new Windows Live profile + web + false + + + false + + 17906075 + Mark_Layton + Mark_Layton + + + http://static.twitter.com/images/default_profile_normal.png + + false + 2 + + + Sun Dec 07 00:36:13 +0000 2008 + 1042729092 + me voy a sobar, a ver si mañana estoy mejor, wenas noches a tod@s + web + false + + + false + + 14062655 + tmaniak + tmaniak + + + http://s3.amazonaws.com/twitter_production/profile_images/51680481/BF-109_normal.jpg + http://dhost.info/tmaniak + false + 10 + + + Sun Dec 07 00:36:14 +0000 2008 + 1042729090 + バイト延長戦入りましたー 店長が遅刻ってどうなんだ。しかも何回も + natsuliphone + false + + + false + + 15618846 + kabayaki + kabayaki + FPS(L4D、TF2、CS:S、BF)、TPS、RCG、マンガ、アニメ、デジモノが好きなとある学生 + tokyo + http://s3.amazonaws.com/twitter_production/profile_images/57305902/184_normal.jpg + http://kabayakiya.blog43.fc2.com/ + false + 20 + + + Sun Dec 07 00:36:13 +0000 2008 + 1042729089 + just drove to southern california and joy of children hugging grandparents made it all worthwhile. heading to imedia in la quinta tomorrow. + web + false + + + false + + 1630261 + mark silva + marksilva + digital media http://realbranding.com Principal, Managing Director + often san francisco + http://s3.amazonaws.com/twitter_production/profile_images/29807902/silvasimpson3th_normal.jpg + http://marksilva.com + false + 497 + + + Sun Dec 07 00:36:14 +0000 2008 + 1042729088 + @wholefoods would love to have a juicebar in one of your cambridge or boston locations + web + false + 1041125103 + 15131310 + false + + 15856582 + Maura McGovern + mmcgovern + photographer with a day job in venture capital; obsessed with design blogs, long walks, yoga, social networking, people watching. tea and music are essential! + Boston + http://s3.amazonaws.com/twitter_production/profile_images/66110383/DSCN1740_normal.JPG + http://lefteyephotography.blogspot.com + false + 244 + + + Sun Dec 07 00:36:15 +0000 2008 + 1042729087 + Going over the Advent lists. + web + false + + + false + + 17122107 + gsusan + gsusan + US American writer/sister/daughter/aunt/woman from New England living in SoCal. + San Diego, CA USA + http://s3.amazonaws.com/twitter_production/profile_images/63951854/susan_ocracoke_normal.jpg + + false + 6 + + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/undefined_method_add_node_for_nil.xml b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/undefined_method_add_node_for_nil.xml new file mode 100644 index 0000000..43d96a7 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/fixtures/undefined_method_add_node_for_nil.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/connection_adapter_spec.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/connection_adapter_spec.rb new file mode 100644 index 0000000..f405e0f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/connection_adapter_spec.rb @@ -0,0 +1,206 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) + +describe HTTParty::ConnectionAdapter do + + describe "initialization" do + let(:uri) { URI 'http://www.google.com' } + it "takes a URI as input" do + HTTParty::ConnectionAdapter.new(uri) + end + + it "raises an ArgumentError if the uri is nil" do + expect { HTTParty::ConnectionAdapter.new(nil) }.to raise_error ArgumentError + end + + it "raises an ArgumentError if the uri is a String" do + expect { HTTParty::ConnectionAdapter.new('http://www.google.com') }.to raise_error ArgumentError + end + + it "sets the uri" do + adapter = HTTParty::ConnectionAdapter.new(uri) + adapter.uri.should be uri + end + + it "also accepts an optional options hash" do + HTTParty::ConnectionAdapter.new(uri, {}) + end + + it "sets the options" do + options = {:foo => :bar} + adapter = HTTParty::ConnectionAdapter.new(uri, options) + adapter.options.should be options + end + end + + describe ".call" do + it "generates an HTTParty::ConnectionAdapter instance with the given uri and options" do + HTTParty::ConnectionAdapter.should_receive(:new).with(@uri, @options).and_return(stub(:connection => nil)) + HTTParty::ConnectionAdapter.call(@uri, @options) + end + + it "calls #connection on the connection adapter" do + adapter = mock('Adapter') + connection = mock('Connection') + adapter.should_receive(:connection).and_return(connection) + HTTParty::ConnectionAdapter.stub(:new => adapter) + HTTParty::ConnectionAdapter.call(@uri, @options).should be connection + end + end + + describe '#connection' do + let(:uri) { URI 'http://www.google.com' } + let(:options) { Hash.new } + let(:adapter) { HTTParty::ConnectionAdapter.new(uri, options) } + + describe "the resulting connection" do + subject { adapter.connection } + it { should be_an_instance_of Net::HTTP } + + context "using port 80" do + let(:uri) { URI 'http://foobar.com' } + it { should_not use_ssl } + end + + context "when dealing with ssl" do + let(:uri) { URI 'https://foobar.com' } + + context "using port 443 for ssl" do + let(:uri) { URI 'https://api.foo.com/v1:443' } + it { should use_ssl } + end + + context "https scheme with default port" do + it { should use_ssl } + end + + context "https scheme with non-standard port" do + let(:uri) { URI 'https://foobar.com:123456' } + it { should use_ssl } + end + + context "when ssl version is set" do + let(:options) { {:ssl_version => :TLSv1} } + + it "sets ssl version" do + subject.ssl_version.should == :TLSv1 + end + end if RUBY_VERSION > '1.9' + end + + context "when timeout is not set" do + it "doesn't set the timeout" do + http = mock("http", :null_object => true) + http.should_not_receive(:open_timeout=) + http.should_not_receive(:read_timeout=) + Net::HTTP.stub(:new => http) + + adapter.connection + end + end + + context "when setting timeout" do + context "to 5 seconds" do + let(:options) { {:timeout => 5} } + + its(:open_timeout) { should == 5 } + its(:read_timeout) { should == 5 } + end + + context "and timeout is a string" do + let(:options) { {:timeout => "five seconds"} } + + it "doesn't set the timeout" do + http = mock("http", :null_object => true) + http.should_not_receive(:open_timeout=) + http.should_not_receive(:read_timeout=) + Net::HTTP.stub(:new => http) + + adapter.connection + end + end + end + + context "when debug_output" do + let(:http) { Net::HTTP.new(uri) } + before do + Net::HTTP.stub(:new => http) + end + + context "is set to $stderr" do + let(:options) { {:debug_output => $stderr} } + it "has debug output set" do + http.should_receive(:set_debug_output).with($stderr) + adapter.connection + end + end + + context "is not provided" do + it "does not set_debug_output" do + http.should_not_receive(:set_debug_output) + adapter.connection + end + end + end + + context 'when providing proxy address and port' do + let(:options) { {:http_proxyaddr => '1.2.3.4', :http_proxyport => 8080} } + + it { should be_a_proxy } + its(:proxy_address) { should == '1.2.3.4' } + its(:proxy_port) { should == 8080 } + + context 'as well as proxy user and password' do + let(:options) do + {:http_proxyaddr => '1.2.3.4', :http_proxyport => 8080, + :http_proxyuser => 'user', :http_proxypass => 'pass'} + end + its(:proxy_user) { should == 'user' } + its(:proxy_pass) { should == 'pass' } + end + end + + context "when providing PEM certificates" do + let(:pem) { :pem_contents } + let(:options) { {:pem => pem, :pem_password => "password"} } + + context "when scheme is https" do + let(:uri) { URI 'https://google.com' } + let(:cert) { mock("OpenSSL::X509::Certificate") } + let(:key) { mock("OpenSSL::PKey::RSA") } + + before do + OpenSSL::X509::Certificate.should_receive(:new).with(pem).and_return(cert) + OpenSSL::PKey::RSA.should_receive(:new).with(pem, "password").and_return(key) + end + + it "uses the provided PEM certificate " do + subject.cert.should == cert + subject.key.should == key + end + + it "will verify the certificate" do + subject.verify_mode.should == OpenSSL::SSL::VERIFY_PEER + end + end + + context "when scheme is not https" do + let(:uri) { URI 'http://google.com' } + let(:http) { Net::HTTP.new(uri) } + + before do + Net::HTTP.stub(:new => http) + OpenSSL::X509::Certificate.should_not_receive(:new).with(pem) + OpenSSL::PKey::RSA.should_not_receive(:new).with(pem, "password") + http.should_not_receive(:cert=) + http.should_not_receive(:key=) + end + + it "has no PEM certificate " do + subject.cert.should be_nil + subject.key.should be_nil + end + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/cookie_hash_spec.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/cookie_hash_spec.rb new file mode 100644 index 0000000..3a754cc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/cookie_hash_spec.rb @@ -0,0 +1,70 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper')) + +describe HTTParty::CookieHash do + before(:each) do + @cookie_hash = HTTParty::CookieHash.new + end + + describe "#add_cookies" do + describe "with a hash" do + it "should add new key/value pairs to the hash" do + @cookie_hash.add_cookies(:foo => "bar") + @cookie_hash.add_cookies(:rofl => "copter") + @cookie_hash.length.should eql(2) + end + + it "should overwrite any existing key" do + @cookie_hash.add_cookies(:foo => "bar") + @cookie_hash.add_cookies(:foo => "copter") + @cookie_hash.length.should eql(1) + @cookie_hash[:foo].should eql("copter") + end + end + + describe "with a string" do + it "should add new key/value pairs to the hash" do + @cookie_hash.add_cookies("first=one; second=two; third") + @cookie_hash[:first].should == 'one' + @cookie_hash[:second].should == 'two' + @cookie_hash[:third].should == nil + end + + it "should overwrite any existing key" do + @cookie_hash[:foo] = 'bar' + @cookie_hash.add_cookies("foo=tar") + @cookie_hash.length.should eql(1) + @cookie_hash[:foo].should eql("tar") + end + end + + describe 'with other class' do + it "should error" do + lambda { + @cookie_hash.add_cookies(Array.new) + }.should raise_error + end + end + end + + # The regexen are required because Hashes aren't ordered, so a test against + # a hardcoded string was randomly failing. + describe "#to_cookie_string" do + before(:each) do + @cookie_hash.add_cookies(:foo => "bar") + @cookie_hash.add_cookies(:rofl => "copter") + @s = @cookie_hash.to_cookie_string + end + + it "should format the key/value pairs, delimited by semi-colons" do + @s.should match(/foo=bar/) + @s.should match(/rofl=copter/) + @s.should match(/^\w+=\w+; \w+=\w+$/) + end + + it "should not include client side only cookies" do + @cookie_hash.add_cookies(:path => "/") + @s = @cookie_hash.to_cookie_string + @s.should_not match(/path=\//) + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/net_digest_auth_spec.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/net_digest_auth_spec.rb new file mode 100644 index 0000000..8b7a4d9 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/net_digest_auth_spec.rb @@ -0,0 +1,115 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) + +describe Net::HTTPHeader::DigestAuthenticator do + def setup_digest(response) + digest = Net::HTTPHeader::DigestAuthenticator.new("Mufasa", + "Circle Of Life", "GET", "/dir/index.html", response) + digest.stub(:random).and_return("deadbeef") + Digest::MD5.stub(:hexdigest) { |str| "md5(#{str})" } + digest + end + + def authorization_header + @digest.authorization_header.join(", ") + end + + + context "with an opaque value in the response header" do + before do + @digest = setup_digest({ + 'www-authenticate' => 'Digest realm="myhost@testrealm.com", opaque="solid"' + }) + end + + it "should set opaque" do + authorization_header.should include(%Q(opaque="solid")) + end + end + + context "without an opaque valid in the response header" do + before do + @digest = setup_digest({ + 'www-authenticate' => 'Digest realm="myhost@testrealm.com"' + }) + end + + it "should not set opaque" do + authorization_header.should_not include(%Q(opaque=)) + end + end + + context "with specified quality of protection (qop)" do + before do + @digest = setup_digest({ + 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth"', + }) + end + + it "should set prefix" do + authorization_header.should =~ /^Digest / + end + + it "should set username" do + authorization_header.should include(%Q(username="Mufasa")) + end + + it "should set digest-uri" do + authorization_header.should include(%Q(uri="/dir/index.html")) + end + + it "should set qop" do + authorization_header.should include(%Q(qop="auth")) + end + + it "should set cnonce" do + authorization_header.should include(%Q(cnonce="md5(deadbeef)")) + end + + it "should set nonce-count" do + authorization_header.should include(%Q(nc="00000001")) + end + + it "should set response" do + request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:00000001:md5(deadbeef):auth:md5(GET:/dir/index.html))" + authorization_header.should include(%Q(response="#{request_digest}")) + end + end + + + context "with unspecified quality of protection (qop)" do + before do + @digest = setup_digest({ + 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE"', + }) + end + + it "should set prefix" do + authorization_header.should =~ /^Digest / + end + + it "should set username" do + authorization_header.should include(%Q(username="Mufasa")) + end + + it "should set digest-uri" do + authorization_header.should include(%Q(uri="/dir/index.html")) + end + + it "should not set qop" do + authorization_header.should_not include(%Q(qop=)) + end + + it "should not set cnonce" do + authorization_header.should_not include(%Q(cnonce=)) + end + + it "should not set nonce-count" do + authorization_header.should_not include(%Q(nc=)) + end + + it "should set response" do + request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:md5(GET:/dir/index.html))" + authorization_header.should include(%Q(response="#{request_digest}")) + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/parser_spec.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/parser_spec.rb new file mode 100644 index 0000000..a72bbfd --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/parser_spec.rb @@ -0,0 +1,171 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) + +describe HTTParty::Parser do + describe ".SupportedFormats" do + it "returns a hash" do + HTTParty::Parser::SupportedFormats.should be_instance_of(Hash) + end + end + + describe ".call" do + it "generates an HTTParty::Parser instance with the given body and format" do + HTTParty::Parser.should_receive(:new).with('body', :plain).and_return(stub(:parse => nil)) + HTTParty::Parser.call('body', :plain) + end + + it "calls #parse on the parser" do + parser = mock('Parser') + parser.should_receive(:parse) + HTTParty::Parser.stub(:new => parser) + parser = HTTParty::Parser.call('body', :plain) + end + end + + describe ".formats" do + it "returns the SupportedFormats constant" do + HTTParty::Parser.formats.should == HTTParty::Parser::SupportedFormats + end + + it "returns the SupportedFormats constant for subclasses" do + class MyParser < HTTParty::Parser + SupportedFormats = {"application/atom+xml" => :atom} + end + MyParser.formats.should == {"application/atom+xml" => :atom} + end + end + + describe ".format_from_mimetype" do + it "returns a symbol representing the format mimetype" do + HTTParty::Parser.format_from_mimetype("text/plain").should == :plain + end + + it "returns nil when the mimetype is not supported" do + HTTParty::Parser.format_from_mimetype("application/atom+xml").should be_nil + end + end + + describe ".supported_formats" do + it "returns a unique set of supported formats represented by symbols" do + HTTParty::Parser.supported_formats.should == HTTParty::Parser::SupportedFormats.values.uniq + end + end + + describe ".supports_format?" do + it "returns true for a supported format" do + HTTParty::Parser.stub(:supported_formats => [:json]) + HTTParty::Parser.supports_format?(:json).should be_true + end + + it "returns false for an unsupported format" do + HTTParty::Parser.stub(:supported_formats => []) + HTTParty::Parser.supports_format?(:json).should be_false + end + end + + describe "#parse" do + before do + @parser = HTTParty::Parser.new('body', :json) + end + + it "attempts to parse supported formats" do + @parser.stub(:supports_format? => true) + @parser.should_receive(:parse_supported_format) + @parser.parse + end + + it "returns the unparsed body when the format is unsupported" do + @parser.stub(:supports_format? => false) + @parser.parse.should == @parser.body + end + + it "returns nil for an empty body" do + @parser.stub(:body => '') + @parser.parse.should be_nil + end + + it "returns nil for a nil body" do + @parser.stub(:body => nil) + @parser.parse.should be_nil + end + + it "returns nil for a 'null' body" do + @parser.stub(:body => "null") + @parser.parse.should be_nil + end + + it "returns nil for a body with spaces only" do + @parser.stub(:body => " ") + @parser.parse.should be_nil + end + end + + describe "#supports_format?" do + it "utilizes the class method to determine if the format is supported" do + HTTParty::Parser.should_receive(:supports_format?).with(:json) + parser = HTTParty::Parser.new('body', :json) + parser.send(:supports_format?) + end + end + + describe "#parse_supported_format" do + it "calls the parser for the given format" do + parser = HTTParty::Parser.new('body', :json) + parser.should_receive(:json) + parser.send(:parse_supported_format) + end + + context "when a parsing method does not exist for the given format" do + it "raises an exception" do + parser = HTTParty::Parser.new('body', :atom) + expect do + parser.send(:parse_supported_format) + end.to raise_error(NotImplementedError, "HTTParty::Parser has not implemented a parsing method for the :atom format.") + end + + it "raises a useful exception message for subclasses" do + atom_parser = Class.new(HTTParty::Parser) do + def self.name; 'AtomParser'; end + end + parser = atom_parser.new 'body', :atom + expect do + parser.send(:parse_supported_format) + end.to raise_error(NotImplementedError, "AtomParser has not implemented a parsing method for the :atom format.") + end + end + end + + context "parsers" do + subject do + HTTParty::Parser.new('body', nil) + end + + it "parses xml with MultiXml" do + MultiXml.should_receive(:parse).with('body') + subject.send(:xml) + end + + it "parses json with MultiJson" do + MultiJson.should_receive(:load).with('body') + subject.send(:json) + end + + it "uses MultiJson.decode if MultiJson does not respond to adapter" do + MultiJson.should_receive(:respond_to?).with(:adapter).and_return(false) + MultiJson.should_receive(:decode).with('body') + subject.send(:json) + end + + it "parses yaml" do + YAML.should_receive(:load).with('body') + subject.send(:yaml) + end + + it "parses html by simply returning the body" do + subject.send(:html).should == 'body' + end + + it "parses plain text by simply returning the body" do + subject.send(:plain).should == 'body' + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/request_spec.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/request_spec.rb new file mode 100644 index 0000000..9db7b72 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/request_spec.rb @@ -0,0 +1,495 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) + +describe HTTParty::Request do + before do + @request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', :format => :xml) + end + + describe "::NON_RAILS_QUERY_STRING_NORMALIZER" do + let(:normalizer) { HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER } + + it "doesn't modify strings" do + query_string = normalizer["foo=bar&foo=baz"] + URI.unescape(query_string).should == "foo=bar&foo=baz" + end + + context "when the query is an array" do + + it "doesn't include brackets" do + query_string = normalizer[{:page => 1, :foo => %w(bar baz)}] + URI.unescape(query_string).should == "foo=bar&foo=baz&page=1" + end + + it "URI encodes array values" do + query_string = normalizer[{:people => ["Bob Marley", "Tim & Jon"]}] + query_string.should == "people=Bob%20Marley&people=Tim%20%26%20Jon" + end + end + + context "when the query is a hash" do + it "correctly handles nil values" do + query_string = normalizer[{:page => 1, :per_page => nil}] + query_string.should == "page=1&per_page" + end + end + end + + describe "initialization" do + it "sets parser to HTTParty::Parser" do + request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com') + request.parser.should == HTTParty::Parser + end + + it "sets parser to the optional parser" do + my_parser = lambda {} + request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', :parser => my_parser) + request.parser.should == my_parser + end + + it "sets connection_adapter to HTTPParty::ConnectionAdapter" do + request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com') + request.connection_adapter.should == HTTParty::ConnectionAdapter + end + + it "sets connection_adapter to the optional connection_adapter" do + my_adapter = lambda {} + request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', :connection_adapter => my_adapter) + request.connection_adapter.should == my_adapter + end + end + + describe "#format" do + context "request yet to be made" do + it "returns format option" do + request = HTTParty::Request.new 'get', '/', :format => :xml + request.format.should == :xml + end + + it "returns nil format" do + request = HTTParty::Request.new 'get', '/' + request.format.should be_nil + end + end + + context "request has been made" do + it "returns format option" do + request = HTTParty::Request.new 'get', '/', :format => :xml + request.last_response = stub + request.format.should == :xml + end + + it "returns the content-type from the last response when the option is not set" do + request = HTTParty::Request.new 'get', '/' + response = stub + response.should_receive(:[]).with('content-type').and_return('text/json') + request.last_response = response + request.format.should == :json + end + end + + end + + context "options" do + it "should use basic auth when configured" do + @request.options[:basic_auth] = {:username => 'foobar', :password => 'secret'} + @request.send(:setup_raw_request) + @request.instance_variable_get(:@raw_request)['authorization'].should_not be_nil + end + + it "should use digest auth when configured" do + FakeWeb.register_uri(:get, "http://api.foo.com/v1", + :www_authenticate => 'Digest realm="Log Viewer", qop="auth", nonce="2CA0EC6B0E126C4800E56BA0C0003D3C", opaque="5ccc069c403ebaf9f0171e9517f40e41", stale=false') + + @request.options[:digest_auth] = {:username => 'foobar', :password => 'secret'} + @request.send(:setup_raw_request) + + raw_request = @request.instance_variable_get(:@raw_request) + raw_request.instance_variable_get(:@header)['Authorization'].should_not be_nil + end + + it "should use the right http method for digest authentication" do + @post_request = HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', :format => :xml) + FakeWeb.register_uri(:post, "http://api.foo.com/v1", {}) + + http = @post_request.send(:http) + @post_request.should_receive(:http).and_return(http) + http.should_not_receive(:head).and_return({'www-authenticate' => nil}) + @post_request.options[:digest_auth] = {:username => 'foobar', :password => 'secret'} + @post_request.send(:setup_raw_request) + end + end + + describe "#uri" do + context "query strings" do + it "does not add an empty query string when default_params are blank" do + @request.options[:default_params] = {} + @request.uri.query.should be_nil + end + + it "respects the query string normalization proc" do + empty_proc = lambda {|qs| ""} + @request.options[:query_string_normalizer] = empty_proc + @request.options[:query] = {:foo => :bar} + URI.unescape(@request.uri.query).should == "" + end + + context "when representing an array" do + it "returns a Rails style query string" do + @request.options[:query] = {:foo => %w(bar baz)} + URI.unescape(@request.uri.query).should == "foo[]=bar&foo[]=baz" + end + end + + end + end + + describe "#setup_raw_request" do + context "when query_string_normalizer is set" do + it "sets the body to the return value of the proc" do + @request.options[:query_string_normalizer] = HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER + @request.options[:body] = {:page => 1, :foo => %w(bar baz)} + @request.send(:setup_raw_request) + body = @request.instance_variable_get(:@raw_request).body + URI.unescape(body).should == "foo=bar&foo=baz&page=1" + end + end + end + + describe 'http' do + it "should get a connection from the connection_adapter" do + http = Net::HTTP.new('google.com') + adapter = mock('adapter') + request = HTTParty::Request.new(Net::HTTP::Get, 'https://api.foo.com/v1:443', :connection_adapter => adapter) + adapter.should_receive(:call).with(request.uri, request.options).and_return(http) + request.send(:http).should be http + end + end + + describe '#format_from_mimetype' do + it 'should handle text/xml' do + ["text/xml", "text/xml; charset=iso8859-1"].each do |ct| + @request.send(:format_from_mimetype, ct).should == :xml + end + end + + it 'should handle application/xml' do + ["application/xml", "application/xml; charset=iso8859-1"].each do |ct| + @request.send(:format_from_mimetype, ct).should == :xml + end + end + + it 'should handle text/json' do + ["text/json", "text/json; charset=iso8859-1"].each do |ct| + @request.send(:format_from_mimetype, ct).should == :json + end + end + + it 'should handle application/json' do + ["application/json", "application/json; charset=iso8859-1"].each do |ct| + @request.send(:format_from_mimetype, ct).should == :json + end + end + + it 'should handle text/javascript' do + ["text/javascript", "text/javascript; charset=iso8859-1"].each do |ct| + @request.send(:format_from_mimetype, ct).should == :json + end + end + + it 'should handle application/javascript' do + ["application/javascript", "application/javascript; charset=iso8859-1"].each do |ct| + @request.send(:format_from_mimetype, ct).should == :json + end + end + + it "returns nil for an unrecognized mimetype" do + @request.send(:format_from_mimetype, "application/atom+xml").should be_nil + end + + it "returns nil when using a default parser" do + @request.options[:parser] = lambda {} + @request.send(:format_from_mimetype, "text/json").should be_nil + end + end + + describe 'parsing responses' do + it 'should handle xml automatically' do + xml = %q[1234Foo Bar!] + @request.options[:format] = :xml + @request.send(:parse_response, xml).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}} + end + + it 'should handle json automatically' do + json = %q[{"books": {"book": {"name": "Foo Bar!", "id": "1234"}}}] + @request.options[:format] = :json + @request.send(:parse_response, json).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}} + end + + it 'should handle yaml automatically' do + yaml = "books: \n book: \n name: Foo Bar!\n id: \"1234\"\n" + @request.options[:format] = :yaml + @request.send(:parse_response, yaml).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}} + end + + it "should include any HTTP headers in the returned response" do + @request.options[:format] = :html + response = stub_response "Content" + response.initialize_http_header("key" => "value") + + @request.perform.headers.should == { "key" => ["value"] } + end + + describe 'with non-200 responses' do + context "3xx responses" do + it 'returns a valid object for 304 not modified' do + stub_response '', 304 + resp = @request.perform + resp.code.should == 304 + resp.body.should == '' + resp.should be_nil + end + + it "redirects if a 300 contains a location header" do + redirect = stub_response '', 300 + redirect['location'] = 'http://foo.com/foo' + ok = stub_response('bar', 200) + @http.stub!(:request).and_return(redirect, ok) + response = @request.perform + response.request.base_uri.to_s.should == "http://foo.com" + response.request.path.to_s.should == "http://foo.com/foo" + response.request.uri.request_uri.should == "/foo" + response.request.uri.to_s.should == "http://foo.com/foo" + response.should == {"hash" => {"foo" => "bar"}} + end + + it "redirects if a 300 contains a relative location header" do + redirect = stub_response '', 300 + redirect['location'] = '/foo/bar' + ok = stub_response('bar', 200) + @http.stub!(:request).and_return(redirect, ok) + response = @request.perform + response.request.base_uri.to_s.should == "http://api.foo.com" + response.request.path.to_s.should == "/foo/bar" + response.request.uri.request_uri.should == "/foo/bar" + response.request.uri.to_s.should == "http://api.foo.com/foo/bar" + response.should == {"hash" => {"foo" => "bar"}} + end + + it "handles multiple redirects and relative location headers on different hosts" do + @request = HTTParty::Request.new(Net::HTTP::Get, 'http://test.com/redirect', :format => :xml) + FakeWeb.register_uri(:get, "http://test.com/redirect", :status => [300, "REDIRECT"], :location => "http://api.foo.com/v2") + FakeWeb.register_uri(:get, "http://api.foo.com/v2", :status => [300, "REDIRECT"], :location => "/v3") + FakeWeb.register_uri(:get, "http://api.foo.com/v3", :body => "bar") + response = @request.perform + response.request.base_uri.to_s.should == "http://api.foo.com" + response.request.path.to_s.should == "/v3" + response.request.uri.request_uri.should == "/v3" + response.request.uri.to_s.should == "http://api.foo.com/v3" + response.should == {"hash" => {"foo" => "bar"}} + end + + it "returns the HTTParty::Response when the 300 does not contain a location header" do + net_response = stub_response '', 300 + HTTParty::Response.should === @request.perform + end + end + + it 'should return a valid object for 4xx response' do + stub_response 'yes', 401 + resp = @request.perform + resp.code.should == 401 + resp.body.should == "yes" + resp['foo']['bar'].should == "yes" + end + + it 'should return a valid object for 5xx response' do + stub_response 'error', 500 + resp = @request.perform + resp.code.should == 500 + resp.body.should == "error" + resp['foo']['bar'].should == "error" + end + + it "parses response lazily so codes can be checked prior" do + stub_response 'not xml', 500 + @request.options[:format] = :xml + lambda { + response = @request.perform + response.code.should == 500 + response.body.should == 'not xml' + }.should_not raise_error + end + end + end + + it "should not attempt to parse empty responses" do + [204, 304].each do |code| + stub_response "", code + + @request.options[:format] = :xml + @request.perform.should be_nil + end + end + + it "should not fail for missing mime type" do + stub_response "Content for you" + @request.options[:format] = :html + @request.perform.should == 'Content for you' + end + + describe "a request that redirects" do + before(:each) do + @redirect = stub_response("", 302) + @redirect['location'] = '/foo' + + @ok = stub_response('bar', 200) + end + + describe "once" do + before(:each) do + @http.stub!(:request).and_return(@redirect, @ok) + end + + it "should be handled by GET transparently" do + @request.perform.should == {"hash" => {"foo" => "bar"}} + end + + it "should be handled by POST transparently" do + @request.http_method = Net::HTTP::Post + @request.perform.should == {"hash" => {"foo" => "bar"}} + end + + it "should be handled by DELETE transparently" do + @request.http_method = Net::HTTP::Delete + @request.perform.should == {"hash" => {"foo" => "bar"}} + end + + it "should be handled by PATCH transparently" do + @request.http_method = Net::HTTP::Patch + @request.perform.should == {"hash" => {"foo" => "bar"}} + end + + it "should be handled by PUT transparently" do + @request.http_method = Net::HTTP::Put + @request.perform.should == {"hash" => {"foo" => "bar"}} + end + + it "should be handled by HEAD transparently" do + @request.http_method = Net::HTTP::Head + @request.perform.should == {"hash" => {"foo" => "bar"}} + end + + it "should be handled by OPTIONS transparently" do + @request.http_method = Net::HTTP::Options + @request.perform.should == {"hash" => {"foo" => "bar"}} + end + + it "should keep track of cookies between redirects" do + @redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly' + @request.perform + @request.options[:headers]['Cookie'].should match(/foo=bar/) + @request.options[:headers]['Cookie'].should match(/name=value/) + end + + it 'should update cookies with rediects' do + @request.options[:headers] = {'Cookie'=> 'foo=bar;'} + @redirect['Set-Cookie'] = 'foo=tar;' + @request.perform + @request.options[:headers]['Cookie'].should match(/foo=tar/) + end + + it 'should keep cookies between rediects' do + @request.options[:headers] = {'Cookie'=> 'keep=me'} + @redirect['Set-Cookie'] = 'foo=tar;' + @request.perform + @request.options[:headers]['Cookie'].should match(/keep=me/) + end + + it 'should make resulting request a get request if it not already' do + @request.http_method = Net::HTTP::Delete + @request.perform.should == {"hash" => {"foo" => "bar"}} + @request.http_method.should == Net::HTTP::Get + end + + it 'should not make resulting request a get request if options[:maintain_method_across_redirects] is true' do + @request.options[:maintain_method_across_redirects] = true + @request.http_method = Net::HTTP::Delete + @request.perform.should == {"hash" => {"foo" => "bar"}} + @request.http_method.should == Net::HTTP::Delete + end + end + + describe "infinitely" do + before(:each) do + @http.stub!(:request).and_return(@redirect) + end + + it "should raise an exception" do + lambda { @request.perform }.should raise_error(HTTParty::RedirectionTooDeep) + end + end + end + + describe "#handle_deflation" do + context "context-encoding" do + before do + @request.options[:format] = :html + @last_response = mock() + @last_response.stub!(:body).and_return('') + end + + it "should inflate the gzipped body with content-encoding: gzip" do + @last_response.stub!(:[]).with("content-encoding").and_return("gzip") + @request.stub!(:last_response).and_return(@last_response) + Zlib::GzipReader.should_receive(:new).and_return(StringIO.new('')) + @request.last_response.should_receive(:delete).with('content-encoding') + @request.send(:handle_deflation) + end + + it "should inflate the gzipped body with content-encoding: x-gzip" do + @last_response.stub!(:[]).with("content-encoding").and_return("x-gzip") + @request.stub!(:last_response).and_return(@last_response) + Zlib::GzipReader.should_receive(:new).and_return(StringIO.new('')) + @request.last_response.should_receive(:delete).with('content-encoding') + @request.send(:handle_deflation) + end + + it "should inflate the deflated body" do + @last_response.stub!(:[]).with("content-encoding").and_return("deflate") + @request.stub!(:last_response).and_return(@last_response) + Zlib::Inflate.should_receive(:inflate).and_return('') + @request.last_response.should_receive(:delete).with('content-encoding') + @request.send(:handle_deflation) + end + end + end + + context "with POST http method" do + it "should raise argument error if query is not a hash" do + lambda { + HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', :format => :xml, :query => 'astring').perform + }.should raise_error(ArgumentError) + end + end + + describe "argument validation" do + it "should raise argument error if basic_auth and digest_auth are both present" do + lambda { + HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', :basic_auth => {}, :digest_auth => {}).perform + }.should raise_error(ArgumentError, "only one authentication method, :basic_auth or :digest_auth may be used at a time") + end + + it "should raise argument error if basic_auth is not a hash" do + lambda { + HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', :basic_auth => ["foo", "bar"]).perform + }.should raise_error(ArgumentError, ":basic_auth must be a hash") + end + + it "should raise argument error if digest_auth is not a hash" do + lambda { + HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', :digest_auth => ["foo", "bar"]).perform + }.should raise_error(ArgumentError, ":digest_auth must be a hash") + end + end +end + diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/response_spec.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/response_spec.rb new file mode 100644 index 0000000..35380d5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/response_spec.rb @@ -0,0 +1,214 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) + +describe HTTParty::Response do + before do + @last_modified = Date.new(2010, 1, 15).to_s + @content_length = '1024' + @request_object = HTTParty::Request.new Net::HTTP::Get, '/' + @response_object = Net::HTTPOK.new('1.1', 200, 'OK') + @response_object.stub(:body => "{foo:'bar'}") + @response_object['last-modified'] = @last_modified + @response_object['content-length'] = @content_length + @parsed_response = lambda { {"foo" => "bar"} } + @response = HTTParty::Response.new(@request_object, @response_object, @parsed_response) + end + + describe ".underscore" do + it "works with one capitalized word" do + HTTParty::Response.underscore("Accepted").should == "accepted" + end + + it "works with titlecase" do + HTTParty::Response.underscore("BadGateway").should == "bad_gateway" + end + + it "works with all caps" do + HTTParty::Response.underscore("OK").should == "ok" + end + end + + describe "initialization" do + it "should set the Net::HTTP Response" do + @response.response.should == @response_object + end + + it "should set body" do + @response.body.should == @response_object.body + end + + it "should set code" do + @response.code.should.to_s == @response_object.code + end + + it "should set code as a Fixnum" do + @response.code.should be_an_instance_of(Fixnum) + end + end + + it "returns response headers" do + response = HTTParty::Response.new(@request_object, @response_object, @parsed_response) + response.headers.should == {'last-modified' => [@last_modified], 'content-length' => [@content_length]} + end + + it "should send missing methods to delegate" do + response = HTTParty::Response.new(@request_object, @response_object, @parsed_response) + response['foo'].should == 'bar' + end + + it "response to request" do + response = HTTParty::Response.new(@request_object, @response_object, @parsed_response) + response.respond_to?(:request).should be_true + end + + it "responds to response" do + response = HTTParty::Response.new(@request_object, @response_object, @parsed_response) + response.respond_to?(:response).should be_true + end + + it "responds to body" do + response = HTTParty::Response.new(@request_object, @response_object, @parsed_response) + response.respond_to?(:body).should be_true + end + + it "responds to headers" do + response = HTTParty::Response.new(@request_object, @response_object, @parsed_response) + response.respond_to?(:headers).should be_true + end + + it "responds to parsed_response" do + response = HTTParty::Response.new(@request_object, @response_object, @parsed_response) + response.respond_to?(:parsed_response).should be_true + end + + it "responds to anything parsed_response responds to" do + response = HTTParty::Response.new(@request_object, @response_object, @parsed_response) + response.respond_to?(:[]).should be_true + end + + it "should be able to iterate if it is array" do + response = HTTParty::Response.new(@request_object, @response_object, lambda { [{'foo' => 'bar'}, {'foo' => 'baz'}] }) + response.size.should == 2 + expect { + response.each { |item| } + }.to_not raise_error + end + + it "allows headers to be accessed by mixed-case names in hash notation" do + response = HTTParty::Response.new(@request_object, @response_object, @parsed_response) + response.headers['Content-LENGTH'].should == @content_length + end + + it "returns a comma-delimited value when multiple values exist" do + @response_object.add_field 'set-cookie', 'csrf_id=12345; path=/' + @response_object.add_field 'set-cookie', '_github_ses=A123CdE; path=/' + response = HTTParty::Response.new(@request_object, @response_object, @parsed_response) + response.headers['set-cookie'].should == "csrf_id=12345; path=/, _github_ses=A123CdE; path=/" + end + + # Backwards-compatibility - previously, #headers returned a Hash + it "responds to hash methods" do + response = HTTParty::Response.new(@request_object, @response_object, @parsed_response) + hash_methods = {}.methods - response.headers.methods + hash_methods.each do |method_name| + response.headers.respond_to?(method_name).should be_true + end + end + + describe "semantic methods for response codes" do + def response_mock(klass) + response = klass.new('', '', '') + response.stub(:body) + response + end + + context "major codes" do + it "is information" do + net_response = response_mock(Net::HTTPInformation) + response = HTTParty::Response.new(@request_object, net_response, '') + response.information?.should be_true + end + + it "is success" do + net_response = response_mock(Net::HTTPSuccess) + response = HTTParty::Response.new(@request_object, net_response, '') + response.success?.should be_true + end + + it "is redirection" do + net_response = response_mock(Net::HTTPRedirection) + response = HTTParty::Response.new(@request_object, net_response, '') + response.redirection?.should be_true + end + + it "is client error" do + net_response = response_mock(Net::HTTPClientError) + response = HTTParty::Response.new(@request_object, net_response, '') + response.client_error?.should be_true + end + + it "is server error" do + net_response = response_mock(Net::HTTPServerError) + response = HTTParty::Response.new(@request_object, net_response, '') + response.server_error?.should be_true + end + end + + context "for specific codes" do + SPECIFIC_CODES = { + :accepted? => Net::HTTPAccepted, + :bad_gateway? => Net::HTTPBadGateway, + :bad_request? => Net::HTTPBadRequest, + :conflict? => Net::HTTPConflict, + :continue? => Net::HTTPContinue, + :created? => Net::HTTPCreated, + :expectation_failed? => Net::HTTPExpectationFailed, + :forbidden? => Net::HTTPForbidden, + :found? => Net::HTTPFound, + :gateway_time_out? => Net::HTTPGatewayTimeOut, + :gone? => Net::HTTPGone, + :internal_server_error? => Net::HTTPInternalServerError, + :length_required? => Net::HTTPLengthRequired, + :method_not_allowed? => Net::HTTPMethodNotAllowed, + :moved_permanently? => Net::HTTPMovedPermanently, + :multiple_choice? => Net::HTTPMultipleChoice, + :no_content? => Net::HTTPNoContent, + :non_authoritative_information? => Net::HTTPNonAuthoritativeInformation, + :not_acceptable? => Net::HTTPNotAcceptable, + :not_found? => Net::HTTPNotFound, + :not_implemented? => Net::HTTPNotImplemented, + :not_modified? => Net::HTTPNotModified, + :ok? => Net::HTTPOK, + :partial_content? => Net::HTTPPartialContent, + :payment_required? => Net::HTTPPaymentRequired, + :precondition_failed? => Net::HTTPPreconditionFailed, + :proxy_authentication_required? => Net::HTTPProxyAuthenticationRequired, + :request_entity_too_large? => Net::HTTPRequestEntityTooLarge, + :request_time_out? => Net::HTTPRequestTimeOut, + :request_uri_too_long? => Net::HTTPRequestURITooLong, + :requested_range_not_satisfiable? => Net::HTTPRequestedRangeNotSatisfiable, + :reset_content? => Net::HTTPResetContent, + :see_other? => Net::HTTPSeeOther, + :service_unavailable? => Net::HTTPServiceUnavailable, + :switch_protocol? => Net::HTTPSwitchProtocol, + :temporary_redirect? => Net::HTTPTemporaryRedirect, + :unauthorized? => Net::HTTPUnauthorized, + :unsupported_media_type? => Net::HTTPUnsupportedMediaType, + :use_proxy? => Net::HTTPUseProxy, + :version_not_supported? => Net::HTTPVersionNotSupported + }.each do |method, klass| + it "responds to #{method}" do + net_response = response_mock(klass) + response = HTTParty::Response.new(@request_object, net_response, '') + response.__send__(method).should be_true + end + end + end + end + + describe "headers" do + it "can initialize without headers" do + headers = HTTParty::Response::Headers.new + headers.should == {} + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/ssl_spec.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/ssl_spec.rb new file mode 100644 index 0000000..221c4c9 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty/ssl_spec.rb @@ -0,0 +1,62 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper')) + +describe HTTParty::Request do + context "SSL certificate verification" do + before do + FakeWeb.allow_net_connect = true + end + + after do + FakeWeb.allow_net_connect = false + end + + it "should work when no trusted CA list is specified" do + ssl_verify_test(nil, nil, "selfsigned.crt").should == {'success' => true} + end + + it "should work when no trusted CA list is specified, even with a bogus hostname" do + ssl_verify_test(nil, nil, "bogushost.crt").should == {'success' => true} + end + + it "should work when using ssl_ca_file with a self-signed CA" do + ssl_verify_test(:ssl_ca_file, "selfsigned.crt", "selfsigned.crt").should == {'success' => true} + end + + it "should work when using ssl_ca_file with a certificate authority" do + ssl_verify_test(:ssl_ca_file, "ca.crt", "server.crt").should == {'success' => true} + end + + it "should work when using ssl_ca_path with a certificate authority" do + http = Net::HTTP.new('www.google.com', 443, nil, nil, nil, nil) + response = stub(Net::HTTPResponse, :[] => '', :body => '', :to_hash => {}) + http.stub(:request).and_return(response) + Net::HTTP.should_receive(:new).with('www.google.com', 443, nil, nil, nil, nil).and_return(http) + http.should_receive(:ca_path=).with('/foo/bar') + HTTParty.get('https://www.google.com', :ssl_ca_path => '/foo/bar') + end + + it "should fail when using ssl_ca_file and the server uses an unrecognized certificate authority" do + lambda do + ssl_verify_test(:ssl_ca_file, "ca.crt", "selfsigned.crt") + end.should raise_error(OpenSSL::SSL::SSLError) + end + + it "should fail when using ssl_ca_path and the server uses an unrecognized certificate authority" do + lambda do + ssl_verify_test(:ssl_ca_path, ".", "selfsigned.crt") + end.should raise_error(OpenSSL::SSL::SSLError) + end + + it "should fail when using ssl_ca_file and the server uses a bogus hostname" do + lambda do + ssl_verify_test(:ssl_ca_file, "ca.crt", "bogushost.crt") + end.should raise_error(OpenSSL::SSL::SSLError) + end + + it "should fail when using ssl_ca_path and the server uses a bogus hostname" do + lambda do + ssl_verify_test(:ssl_ca_path, ".", "bogushost.crt") + end.should raise_error(OpenSSL::SSL::SSLError) + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty_spec.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty_spec.rb new file mode 100644 index 0000000..f62a322 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/httparty_spec.rb @@ -0,0 +1,703 @@ +require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper')) + +describe HTTParty do + before(:each) do + @klass = Class.new + @klass.instance_eval { include HTTParty } + end + + describe "AllowedFormats deprecated" do + before do + Kernel.stub(:warn) + end + + it "warns with a deprecation message" do + Kernel.should_receive(:warn).with("Deprecated: Use HTTParty::Parser::SupportedFormats") + HTTParty::AllowedFormats + end + + it "returns HTTPart::Parser::SupportedFormats" do + HTTParty::AllowedFormats.should == HTTParty::Parser::SupportedFormats + end + end + + describe "pem" do + it 'should set the pem content' do + @klass.pem 'PEM-CONTENT' + @klass.default_options[:pem].should == 'PEM-CONTENT' + end + + it "should set the password to nil if it's not provided" do + @klass.pem 'PEM-CONTENT' + @klass.default_options[:pem_password].should be_nil + end + + it 'should set the password' do + @klass.pem 'PEM-CONTENT', 'PASSWORD' + @klass.default_options[:pem_password].should == 'PASSWORD' + end + end + + describe 'ssl_version' do + it 'should set the ssl_version content' do + @klass.ssl_version :SSLv3 + @klass.default_options[:ssl_version].should == :SSLv3 + end + end + + describe 'http_proxy' do + it 'should set the address' do + @klass.http_proxy 'proxy.foo.com', 80 + options = @klass.default_options + options[:http_proxyaddr].should == 'proxy.foo.com' + options[:http_proxyport].should == 80 + end + + it 'should set the proxy user and pass when they are provided' do + @klass.http_proxy 'proxy.foo.com', 80, 'user', 'pass' + options = @klass.default_options + options[:http_proxyuser].should == 'user' + options[:http_proxypass].should == 'pass' + end + end + + describe "base uri" do + before(:each) do + @klass.base_uri('api.foo.com/v1') + end + + it "should have reader" do + @klass.base_uri.should == 'http://api.foo.com/v1' + end + + it 'should have writer' do + @klass.base_uri('http://api.foobar.com') + @klass.base_uri.should == 'http://api.foobar.com' + end + + it 'should not modify the parameter during assignment' do + uri = 'http://api.foobar.com' + @klass.base_uri(uri) + uri.should == 'http://api.foobar.com' + end + end + + describe ".disable_rails_query_string_format" do + it "sets the query string normalizer to HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER" do + @klass.disable_rails_query_string_format + @klass.default_options[:query_string_normalizer].should == HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER + end + end + + describe ".normalize_base_uri" do + it "should add http if not present for non ssl requests" do + uri = HTTParty.normalize_base_uri('api.foobar.com') + uri.should == 'http://api.foobar.com' + end + + it "should add https if not present for ssl requests" do + uri = HTTParty.normalize_base_uri('api.foo.com/v1:443') + uri.should == 'https://api.foo.com/v1:443' + end + + it "should not remove https for ssl requests" do + uri = HTTParty.normalize_base_uri('https://api.foo.com/v1:443') + uri.should == 'https://api.foo.com/v1:443' + end + + it 'should not modify the parameter' do + uri = 'http://api.foobar.com' + HTTParty.normalize_base_uri(uri) + uri.should == 'http://api.foobar.com' + end + + it "should not treat uri's with a port of 4430 as ssl" do + uri = HTTParty.normalize_base_uri('http://api.foo.com:4430/v1') + uri.should == 'http://api.foo.com:4430/v1' + end + end + + describe "headers" do + def expect_headers(header={}) + HTTParty::Request.should_receive(:new) \ + .with(anything, anything, hash_including({ :headers => header })) \ + .and_return(mock("mock response", :perform => nil)) + end + + it "should default to empty hash" do + @klass.headers.should == {} + end + + it "should be able to be updated" do + init_headers = {:foo => 'bar', :baz => 'spax'} + @klass.headers init_headers + @klass.headers.should == init_headers + end + + it "uses the class headers when sending a request" do + expect_headers(:foo => 'bar') + @klass.headers(:foo => 'bar') + @klass.get('') + end + + it "overwrites class headers when passing in headers" do + expect_headers(:baz => 'spax') + @klass.headers(:foo => 'bar') + @klass.get('', :headers => {:baz => 'spax'}) + end + + context "with cookies" do + it 'utilizes the class-level cookies' do + expect_headers(:foo => 'bar', 'cookie' => 'type=snickerdoodle') + @klass.headers(:foo => 'bar') + @klass.cookies(:type => 'snickerdoodle') + @klass.get('') + end + + it 'adds cookies to the headers' do + expect_headers(:foo => 'bar', 'cookie' => 'type=snickerdoodle') + @klass.headers(:foo => 'bar') + @klass.get('', :cookies => {:type => 'snickerdoodle'}) + end + + it 'adds optional cookies to the optional headers' do + expect_headers(:baz => 'spax', 'cookie' => 'type=snickerdoodle') + @klass.get('', :cookies => {:type => 'snickerdoodle'}, :headers => {:baz => 'spax'}) + end + end + end + + describe "cookies" do + def expect_cookie_header(s) + HTTParty::Request.should_receive(:new) \ + .with(anything, anything, hash_including({ :headers => { "cookie" => s } })) \ + .and_return(mock("mock response", :perform => nil)) + end + + it "should not be in the headers by default" do + HTTParty::Request.stub!(:new).and_return(stub(nil, :perform => nil)) + @klass.get("") + @klass.headers.keys.should_not include("cookie") + end + + it "should raise an ArgumentError if passed a non-Hash" do + lambda do + @klass.cookies("nonsense") + end.should raise_error(ArgumentError) + end + + it "should allow a cookie to be specified with a one-off request" do + expect_cookie_header "type=snickerdoodle" + @klass.get("", :cookies => { :type => "snickerdoodle" }) + end + + describe "when a cookie is set at the class level" do + before(:each) do + @klass.cookies({ :type => "snickerdoodle" }) + end + + it "should include that cookie in the request" do + expect_cookie_header "type=snickerdoodle" + @klass.get("") + end + + it "should pass the proper cookies when requested multiple times" do + 2.times do + expect_cookie_header "type=snickerdoodle" + @klass.get("") + end + end + + it "should allow the class defaults to be overridden" do + expect_cookie_header "type=chocolate_chip" + + @klass.get("", :cookies => { :type => "chocolate_chip" }) + end + end + + describe "in a class with multiple methods that use different cookies" do + before(:each) do + @klass.instance_eval do + def first_method + get("first_method", :cookies => { :first_method_cookie => "foo" }) + end + + def second_method + get("second_method", :cookies => { :second_method_cookie => "foo" }) + end + end + end + + it "should not allow cookies used in one method to carry over into other methods" do + expect_cookie_header "first_method_cookie=foo" + @klass.first_method + + expect_cookie_header "second_method_cookie=foo" + @klass.second_method + end + end + end + + describe "default params" do + it "should default to empty hash" do + @klass.default_params.should == {} + end + + it "should be able to be updated" do + new_defaults = {:foo => 'bar', :baz => 'spax'} + @klass.default_params new_defaults + @klass.default_params.should == new_defaults + end + end + + describe "default timeout" do + it "should default to nil" do + @klass.default_options[:timeout].should == nil + end + + it "should support updating" do + @klass.default_timeout 10 + @klass.default_options[:timeout].should == 10 + end + + it "should support floats" do + @klass.default_timeout 0.5 + @klass.default_options[:timeout].should == 0.5 + end + end + + describe "debug_output" do + it "stores the given stream as a default_option" do + @klass.debug_output $stdout + @klass.default_options[:debug_output].should == $stdout + end + + it "stores the $stderr stream by default" do + @klass.debug_output + @klass.default_options[:debug_output].should == $stderr + end + end + + describe "basic http authentication" do + it "should work" do + @klass.basic_auth 'foobar', 'secret' + @klass.default_options[:basic_auth].should == {:username => 'foobar', :password => 'secret'} + end + end + + describe "digest http authentication" do + it "should work" do + @klass.digest_auth 'foobar', 'secret' + @klass.default_options[:digest_auth].should == {:username => 'foobar', :password => 'secret'} + end + end + + describe "parser" do + class CustomParser + def self.parse(body) + return {:sexy => true} + end + end + + let(:parser) do + Proc.new{ |data, format| CustomParser.parse(data) } + end + + it "should set parser options" do + @klass.parser parser + @klass.default_options[:parser].should == parser + end + + it "should be able parse response with custom parser" do + @klass.parser parser + FakeWeb.register_uri(:get, 'http://twitter.com/statuses/public_timeline.xml', :body => 'tweets') + custom_parsed_response = @klass.get('http://twitter.com/statuses/public_timeline.xml') + custom_parsed_response[:sexy].should == true + end + + it "raises UnsupportedFormat when the parser cannot handle the format" do + @klass.format :json + class MyParser < HTTParty::Parser + SupportedFormats = {} + end unless defined?(MyParser) + expect do + @klass.parser MyParser + end.to raise_error(HTTParty::UnsupportedFormat) + end + + it 'does not validate format whe custom parser is a proc' do + expect do + @klass.format :json + @klass.parser lambda {|body, format|} + end.to_not raise_error(HTTParty::UnsupportedFormat) + end + end + + describe "connection_adapter" do + let(:uri) { 'http://google.com/api.json' } + let(:connection_adapter) { mock('CustomConnectionAdapter') } + + it "should set the connection_adapter" do + @klass.connection_adapter connection_adapter + @klass.default_options[:connection_adapter].should be connection_adapter + end + + it "should set the connection_adapter_options when provided" do + options = {:foo => :bar} + @klass.connection_adapter connection_adapter, options + @klass.default_options[:connection_adapter_options].should be options + end + + it "should not set the connection_adapter_options when not provided" do + @klass.connection_adapter connection_adapter + @klass.default_options[:connection_adapter_options].should be_nil + end + + it "should process a request with a connection from the adapter" do + connection_adapter_options = {:foo => :bar} + connection_adapter.should_receive(:call) do |u,o| + o[:connection_adapter_options].should == connection_adapter_options + HTTParty::ConnectionAdapter.call(u,o) + end.with(URI.parse(uri), kind_of(Hash)) + FakeWeb.register_uri(:get, uri, :body => 'stuff') + @klass.connection_adapter connection_adapter, connection_adapter_options + @klass.get(uri).should == 'stuff' + end + end + + describe "format" do + it "should allow xml" do + @klass.format :xml + @klass.default_options[:format].should == :xml + end + + it "should allow json" do + @klass.format :json + @klass.default_options[:format].should == :json + end + + it "should allow yaml" do + @klass.format :yaml + @klass.default_options[:format].should == :yaml + end + + it "should allow plain" do + @klass.format :plain + @klass.default_options[:format].should == :plain + end + + it 'should not allow funky format' do + lambda do + @klass.format :foobar + end.should raise_error(HTTParty::UnsupportedFormat) + end + + it 'should only print each format once with an exception' do + lambda do + @klass.format :foobar + end.should raise_error(HTTParty::UnsupportedFormat, "':foobar' Must be one of: html, json, plain, xml, yaml") + end + + it 'sets the default parser' do + @klass.default_options[:parser].should be_nil + @klass.format :json + @klass.default_options[:parser].should == HTTParty::Parser + end + + it 'does not reset parser to the default parser' do + my_parser = lambda {} + @klass.parser my_parser + @klass.format :json + @klass.parser.should == my_parser + end + end + + describe "#no_follow" do + it "sets no_follow to false by default" do + @klass.no_follow + @klass.default_options[:no_follow].should be_false + end + + it "sets the no_follow option to true" do + @klass.no_follow true + @klass.default_options[:no_follow].should be_true + end + end + + describe "#maintain_method_across_redirects" do + it "sets maintain_method_across_redirects to true by default" do + @klass.maintain_method_across_redirects + @klass.default_options[:maintain_method_across_redirects].should be_true + end + + it "sets the maintain_method_across_redirects option to false" do + @klass.maintain_method_across_redirects false + @klass.default_options[:maintain_method_across_redirects].should be_false + end + end + + describe ".follow_redirects" do + it "sets follow redirects to true by default" do + @klass.follow_redirects + @klass.default_options[:follow_redirects].should be_true + end + + it "sets the follow_redirects option to false" do + @klass.follow_redirects false + @klass.default_options[:follow_redirects].should be_false + end + end + + describe ".query_string_normalizer" do + it "sets the query_string_normalizer option" do + normalizer = proc {} + @klass.query_string_normalizer normalizer + @klass.default_options[:query_string_normalizer].should == normalizer + end + end + + describe "with explicit override of automatic redirect handling" do + before do + @request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', :format => :xml, :no_follow => true) + @redirect = stub_response 'first redirect', 302 + @redirect['location'] = 'http://foo.com/bar' + HTTParty::Request.stub(:new => @request) + end + + it "should fail with redirected GET" do + lambda do + @error = @klass.get('/foo', :no_follow => true) + end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'} + end + + it "should fail with redirected POST" do + lambda do + @klass.post('/foo', :no_follow => true) + end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'} + end + + it "should fail with redirected PATCH" do + lambda do + @klass.patch('/foo', :no_follow => true) + end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'} + end + + it "should fail with redirected DELETE" do + lambda do + @klass.delete('/foo', :no_follow => true) + end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'} + end + + it "should fail with redirected PUT" do + lambda do + @klass.put('/foo', :no_follow => true) + end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'} + end + + it "should fail with redirected HEAD" do + lambda do + @klass.head('/foo', :no_follow => true) + end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'} + end + + it "should fail with redirected OPTIONS" do + lambda do + @klass.options('/foo', :no_follow => true) + end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'} + end + end + + describe "with multiple class definitions" do + before(:each) do + @klass.instance_eval do + base_uri "http://first.com" + default_params :one => 1 + end + + @additional_klass = Class.new + @additional_klass.instance_eval do + include HTTParty + base_uri "http://second.com" + default_params :two => 2 + end + end + + it "should not run over each others options" do + @klass.default_options.should == { :base_uri => 'http://first.com', :default_params => { :one => 1 } } + @additional_klass.default_options.should == { :base_uri => 'http://second.com', :default_params => { :two => 2 } } + end + end + + describe "two child classes inheriting from one parent" do + before(:each) do + @parent = Class.new do + include HTTParty + def self.name + "Parent" + end + end + + @child1 = Class.new(@parent) + @child2 = Class.new(@parent) + end + + it "does not modify each others inherited attributes" do + @child1.default_params :joe => "alive" + @child2.default_params :joe => "dead" + + @child1.default_options.should == { :default_params => {:joe => "alive"} } + @child2.default_options.should == { :default_params => {:joe => "dead"} } + + @parent.default_options.should == { } + end + + it "inherits default_options from the superclass" do + @parent.basic_auth 'user', 'password' + @child1.default_options.should == {:basic_auth => {:username => 'user', :password => 'password'}} + @child1.basic_auth 'u', 'p' # modifying child1 has no effect on child2 + @child2.default_options.should == {:basic_auth => {:username => 'user', :password => 'password'}} + end + + it "doesn't modify the parent's default options" do + @parent.basic_auth 'user', 'password' + + @child1.basic_auth 'u', 'p' + @child1.default_options.should == {:basic_auth => {:username => 'u', :password => 'p'}} + + @child1.basic_auth 'email', 'token' + @child1.default_options.should == {:basic_auth => {:username => 'email', :password => 'token'}} + + @parent.default_options.should == {:basic_auth => {:username => 'user', :password => 'password'}} + end + + it "doesn't modify hashes in the parent's default options" do + @parent.headers 'Accept' => 'application/json' + @child1.headers 'Accept' => 'application/xml' + + @parent.default_options[:headers].should == {'Accept' => 'application/json'} + @child1.default_options[:headers].should == {'Accept' => 'application/xml'} + end + + it "inherits default_cookies from the parent class" do + @parent.cookies 'type' => 'chocolate_chip' + @child1.default_cookies.should == {"type" => "chocolate_chip"} + @child1.cookies 'type' => 'snickerdoodle' + @child1.default_cookies.should == {"type" => "snickerdoodle"} + @child2.default_cookies.should == {"type" => "chocolate_chip"} + end + + it "doesn't modify the parent's default cookies" do + @parent.cookies 'type' => 'chocolate_chip' + + @child1.cookies 'type' => 'snickerdoodle' + @child1.default_cookies.should == {"type" => "snickerdoodle"} + + @parent.default_cookies.should == {"type" => "chocolate_chip"} + end + end + + describe "grand parent with inherited callback" do + before do + @grand_parent = Class.new do + def self.inherited(subclass) + subclass.instance_variable_set(:@grand_parent, true) + end + end + @parent = Class.new(@grand_parent) do + include HTTParty + end + end + it "continues running the #inherited on the parent" do + child = Class.new(@parent) + child.instance_variable_get(:@grand_parent).should be_true + end + end + + describe "#get" do + it "should be able to get html" do + stub_http_response_with('google.html') + HTTParty.get('http://www.google.com').should == file_fixture('google.html') + end + + it "should be able to get chunked html" do + chunks = ["Chunk1", "Chunk2", "Chunk3", "Chunk4"] + stub_chunked_http_response_with(chunks) + + HTTParty.get('http://www.google.com') do |fragment| + chunks.should include(fragment) + end.should == chunks.join + end + + it "should be able parse response type json automatically" do + stub_http_response_with('twitter.json') + tweets = HTTParty.get('http://twitter.com/statuses/public_timeline.json') + tweets.size.should == 20 + tweets.first['user'].should == { + "name" => "Pyk", + "url" => nil, + "id" => "7694602", + "description" => nil, + "protected" => false, + "screen_name" => "Pyk", + "followers_count" => 1, + "location" => "Opera Plaza, California", + "profile_image_url" => "http://static.twitter.com/images/default_profile_normal.png" + } + end + + it "should be able parse response type xml automatically" do + stub_http_response_with('twitter.xml') + tweets = HTTParty.get('http://twitter.com/statuses/public_timeline.xml') + tweets['statuses'].size.should == 20 + tweets['statuses'].first['user'].should == { + "name" => "Magic 8 Bot", + "url" => nil, + "id" => "17656026", + "description" => "ask me a question", + "protected" => "false", + "screen_name" => "magic8bot", + "followers_count" => "90", + "profile_image_url" => "http://s3.amazonaws.com/twitter_production/profile_images/65565851/8ball_large_normal.jpg", + "location" => nil + } + end + + it "should not get undefined method add_node for nil class for the following xml" do + stub_http_response_with('undefined_method_add_node_for_nil.xml') + result = HTTParty.get('http://foobar.com') + result.should == {"Entities"=>{"href"=>"https://s3-sandbox.parature.com/api/v1/5578/5633/Account", "results"=>"0", "total"=>"0", "page_size"=>"25", "page"=>"1"}} + end + + it "should parse empty response fine" do + stub_http_response_with('empty.xml') + result = HTTParty.get('http://foobar.com') + result.should be_nil + end + + it "should accept http URIs" do + stub_http_response_with('google.html') + lambda do + HTTParty.get('http://google.com') + end.should_not raise_error(HTTParty::UnsupportedURIScheme) + end + + it "should accept https URIs" do + stub_http_response_with('google.html') + lambda do + HTTParty.get('https://google.com') + end.should_not raise_error(HTTParty::UnsupportedURIScheme) + end + + it "should raise an ArgumentError on URIs that are not http or https" do + lambda do + HTTParty.get("file:///there_is_no_party_on/my/filesystem") + end.should raise_error(HTTParty::UnsupportedURIScheme) + end + + it "should raise an InvalidURIError on URIs that can't be parsed at all" do + lambda do + HTTParty.get("It's the one that says 'Bad URI'") + end.should raise_error(URI::InvalidURIError) + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/spec.opts b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/spec.opts new file mode 100644 index 0000000..616c433 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/spec.opts @@ -0,0 +1,2 @@ +--colour +--backtrace diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/spec_helper.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/spec_helper.rb new file mode 100644 index 0000000..a85b2b1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/spec_helper.rb @@ -0,0 +1,30 @@ +$:.push File.expand_path("../lib", __FILE__) +require "httparty" + +require 'spec/autorun' +require 'fakeweb' + +def file_fixture(filename) + open(File.join(File.dirname(__FILE__), 'fixtures', "#{filename.to_s}")).read +end + +Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f} + +Spec::Runner.configure do |config| + config.include HTTParty::StubResponse + config.include HTTParty::SSLTestHelper + + config.before(:suite) do + FakeWeb.allow_net_connect = false + end + + config.after(:suite) do + FakeWeb.allow_net_connect = true + end +end + +Spec::Matchers.define :use_ssl do + match do |connection| + connection.use_ssl? + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/support/ssl_test_helper.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/support/ssl_test_helper.rb new file mode 100644 index 0000000..0aa6818 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/support/ssl_test_helper.rb @@ -0,0 +1,47 @@ +require 'pathname' + +module HTTParty + module SSLTestHelper + def ssl_verify_test(mode, ca_basename, server_cert_filename) + options = { + :format => :json, + :timeout => 30, + } + + if mode + ca_path = File.expand_path("../../fixtures/ssl/generated/#{ca_basename}", __FILE__) + raise ArgumentError.new("#{ca_path} does not exist") unless File.exist?(ca_path) + options[mode] = ca_path + end + + begin + test_server = SSLTestServer.new( + :rsa_key => File.read(File.expand_path("../../fixtures/ssl/generated/server.key", __FILE__)), + :cert => File.read(File.expand_path("../../fixtures/ssl/generated/#{server_cert_filename}", __FILE__))) + + test_server.start + + if mode + ca_path = File.expand_path("../../fixtures/ssl/generated/#{ca_basename}", __FILE__) + raise ArgumentError.new("#{ca_path} does not exist") unless File.exist?(ca_path) + return HTTParty.get("https://localhost:#{test_server.port}/", :format => :json, :timeout => 30, mode => ca_path) + else + return HTTParty.get("https://localhost:#{test_server.port}/", :format => :json, :timeout => 30) + end + ensure + test_server.stop if test_server + end + + test_server = SSLTestServer.new({ + :rsa_key => path.join('server.key').read, + :cert => path.join(server_cert_filename).read, + }) + + test_server.start + + HTTParty.get("https://localhost:#{test_server.port}/", options) + ensure + test_server.stop if test_server + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/support/ssl_test_server.rb b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/support/ssl_test_server.rb new file mode 100644 index 0000000..a2e2d73 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/spec/support/ssl_test_server.rb @@ -0,0 +1,80 @@ +require 'openssl' +require 'socket' +require 'thread' + +# NOTE: This code is garbage. It probably has deadlocks, it might leak +# threads, and otherwise cause problems in a real system. It's really only +# intended for testing HTTParty. +class SSLTestServer + attr_accessor :ctx # SSLContext object + attr_reader :port + + def initialize(options={}) + @ctx = OpenSSL::SSL::SSLContext.new + @ctx.cert = OpenSSL::X509::Certificate.new(options[:cert]) + @ctx.key = OpenSSL::PKey::RSA.new(options[:rsa_key]) + @ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE # Don't verify client certificate + @port = options[:port] || 0 + @thread = nil + @stopping_mutex = Mutex.new + @stopping = false + end + + def start + @raw_server = TCPServer.new(@port) + + if @port == 0 + @port = Socket::getnameinfo(@raw_server.getsockname, Socket::NI_NUMERICHOST|Socket::NI_NUMERICSERV)[1].to_i + end + + @ssl_server = OpenSSL::SSL::SSLServer.new(@raw_server, @ctx) + + @stopping_mutex.synchronize{ + return if @stopping + @thread = Thread.new{ thread_main } + } + + nil + end + + def stop + @stopping_mutex.synchronize{ + return if @stopping + @stopping = true + } + @thread.join + end + + private + + def thread_main + until @stopping_mutex.synchronize{ @stopping } + (rr,ww,ee) = select([@ssl_server.to_io], nil, nil, 0.1) + + next unless rr && rr.include?(@ssl_server.to_io) + + socket = @ssl_server.accept + + Thread.new{ + header = [] + + until (line = socket.readline).rstrip.empty? + header << line + end + + response =< format) + http_request.stub_chain(:http, :request).and_return(response) + + HTTParty::Request.should_receive(:new).and_return(http_request) + end + + def stub_chunked_http_response_with(chunks) + response = Net::HTTPResponse.new("1.1", 200, nil) + response.stub(:chunked_data).and_return(chunks) + def response.read_body(&block) + @body || chunked_data.each(&block) + end + + http_request = HTTParty::Request.new(Net::HTTP::Get, 'http://localhost', :format => "html") + http_request.stub_chain(:http, :request).and_yield(response).and_return(response) + + HTTParty::Request.should_receive(:new).and_return(http_request) + end + + def stub_response(body, code = 200) + @request.options[:base_uri] ||= 'http://localhost' + unless defined?(@http) && @http + @http = Net::HTTP.new('localhost', 80) + @request.stub!(:http).and_return(@http) + end + + response = Net::HTTPResponse::CODE_TO_OBJ[code.to_s].new("1.1", code, body) + response.stub!(:body).and_return(body) + + @http.stub!(:request).and_return(response) + response + end + end +end diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/website/css/common.css b/vendor/ruby/1.9.1/gems/httparty-0.9.0/website/css/common.css new file mode 100644 index 0000000..61f38ac --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/website/css/common.css @@ -0,0 +1,47 @@ +@media screen, projection { + /* + Copyright (c) 2007, Yahoo! Inc. All rights reserved. + Code licensed under the BSD License: + http://developer.yahoo.net/yui/license.txt + version: 2.2.0 + */ + body {font:13px arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}table {font-size:inherit;font:100%;}select, input, textarea {font:99% arial,helvetica,clean,sans-serif;}pre, code {font:115% monospace;*font-size:100%;}body * {line-height:1.22em;} + body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}/*ol,ul {list-style:none;}*/caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym {border:0;} + /* end of yahoo reset and fonts */ + + body {color:#333; background:#4b1a1a; line-height:1.3;} + p {margin:0 0 20px;} + a {color:#4b1a1a;} + a:hover {text-decoration:none;} + strong {font-weight:bold;} + em {font-style:italics;} + h1,h2,h3,h4,h5,h6 {font-weight:bold;} + h1 {font-size:197%; margin:30px 0; color:#4b1a1a;} + h2 {font-size:174%; margin:20px 0; color:#b8111a;} + h3 {font-size:152%; margin:10px 0;} + h4 {font-size:129%; margin:10px 0;} + pre {background:#eee; margin:0 0 20px; padding:20px; border:1px solid #ccc; font-size:100%; overflow:auto;} + code {font-size:100%; margin:0; padding:0;} + ul, ol {margin:10px 0 10px 25px;} + ol li {margin:0 0 10px;} + + + + + + div#wrapper {background:#fff; width:560px; margin:0 auto; padding:20px; border:10px solid #bc8c46; border-width:0 10px;} + div#header {position:relative; border-bottom:1px dotted; margin:0 0 10px; padding:0 0 10px;} + div#header p {margin:0; padding:0;} + div#header h1 {margin:0; padding:0;} + ul#nav {position:absolute; top:0; right:0; list-style:none; margin:0; padding:0;} + ul#nav li {display:inline; padding:0 0 0 5px;} + ul#nav li a {} + div#content {} + div#footer {margin:40px 0 0; border-top:1px dotted; padding:10px 0 0;} + + + + + + +} \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/httparty-0.9.0/website/index.html b/vendor/ruby/1.9.1/gems/httparty-0.9.0/website/index.html new file mode 100644 index 0000000..3b4c86f --- /dev/null +++ b/vendor/ruby/1.9.1/gems/httparty-0.9.0/website/index.html @@ -0,0 +1,73 @@ + + + + + HTTParty by John Nunemaker + + + + +
+ + +
+

Install

+
$ sudo gem install httparty
+ +

Some Quick Examples

+ +

The following is a simple example of wrapping Twitter's API for posting updates.

+ +
class Twitter
+  include HTTParty
+  base_uri 'twitter.com'
+  basic_auth 'username', 'password'
+end
+
+Twitter.post('/statuses/update.json', :query => {:status => "It's an HTTParty and everyone is invited!"})
+ +

That is really it! The object returned is a ruby hash that is decoded from Twitter's json response. JSON parsing is used because of the .json extension in the path of the request. You can also explicitly set a format (see the examples).

+ +

That works and all but what if you don't want to embed your username and password in the class? Below is an example to fix that:

+ +
class Twitter
+  include HTTParty
+  base_uri 'twitter.com'
+
+  def initialize(u, p)
+    @auth = {:username => u, :password => p}
+  end
+
+  def post(text)
+    options = { :query => {:status => text}, :basic_auth => @auth }
+    self.class.post('/statuses/update.json', options)
+  end
+end
+
+Twitter.new('username', 'password').post("It's an HTTParty and everyone is invited!")
+ +

More Examples: There are several examples in the gem itself.

+ +

Support

+

Conversations welcome in the google group and bugs/features over at Github.

+ + +
+ + +
+ + + \ No newline at end of file diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/.document b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/.document new file mode 100644 index 0000000..3b0c733 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/.document @@ -0,0 +1,5 @@ +LICENSE.md +README.md +bin/* +features/**/*.feature +lib/**/*.rb diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/.rspec b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/.rspec new file mode 100644 index 0000000..0ea59b0 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/.rspec @@ -0,0 +1,3 @@ +--color +--fail-fast +--order random diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/.travis.yml b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/.travis.yml new file mode 100644 index 0000000..0828e27 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/.travis.yml @@ -0,0 +1,10 @@ +language: ruby +rvm: + - rbx-18mode + - rbx-19mode + - jruby-18mode + - jruby-19mode + - 1.8.7 + - 1.9.2 + - 1.9.3 + - ruby-head diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/Gemfile b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/Gemfile new file mode 100644 index 0000000..d217dbb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/Gemfile @@ -0,0 +1,7 @@ +source 'https://rubygems.org' + +gem 'json', '~> 1.4', :require => nil +gem 'oj', '~> 1.0', :require => nil, :platforms => [:ruby, :mswin, :mingw] +gem 'yajl-ruby', '~> 1.0', :require => nil, :platforms => [:ruby, :mswin, :mingw] + +gemspec diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/LICENSE.md b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/LICENSE.md new file mode 100644 index 0000000..c925ac6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/LICENSE.md @@ -0,0 +1,20 @@ +Copyright (c) 2010 Michael Bleigh, Josh Kalderimis, Erik Michaels-Ober, and Intridea, Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/README.md b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/README.md new file mode 100644 index 0000000..988a574 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/README.md @@ -0,0 +1,72 @@ +# MultiJSON [![Build Status](https://secure.travis-ci.org/intridea/multi_json.png?branch=master)][travis] [![Dependency Status](https://gemnasium.com/intridea/multi_json.png?travis)][gemnasium] + +[travis]: http://travis-ci.org/intridea/multi_json +[gemnasium]: https://gemnasium.com/intridea/multi_json + +Lots of Ruby libraries parse JSON and everyone has their favorite JSON coder. +Instead of choosing a single JSON coder and forcing users of your library to be +stuck with it, you can use MultiJSON instead, which will simply choose the +fastest available JSON coder. Here's how to use it: + + require 'multi_json' + + MultiJson.load('{"abc":"def"}') #=> {"abc" => "def"} + MultiJson.load('{"abc":"def"}', :symbolize_keys => true) #=> {:abc => "def"} + MultiJson.dump({:abc => 'def'}) # convert Ruby back to JSON + MultiJson.dump({:abc => 'def'}, :pretty => true) # encoded in a pretty form (if supported by the coder) + +The `use` method, which sets the MultiJson adapter, takes either a symbol or a +class (to allow for custom JSON parsers) that responds to both `.load` and `.dump` +at the class level. + +MultiJSON tries to have intelligent defaulting. That is, if you have any of the +supported engines already loaded, it will utilize them before attempting to +load any. When loading, libraries are ordered by speed. First Oj, then Yajl, +then the JSON gem, then JSON pure. If no other JSON library is available, +MultiJSON falls back to [OkJson][], a simple, vendorable JSON parser. + +[okjson]: https://github.com/kr/okjson + +## Supported JSON Engines + +* [Oj](https://github.com/ohler55/oj) Optimized JSON by Peter Ohler +* [Yajl](https://github.com/brianmario/yajl-ruby) Yet Another JSON Library by Brian Lopez +* [JSON](https://github.com/flori/json) The default JSON gem with C-extensions (ships with Ruby 1.9) +* [JSON Pure](https://github.com/flori/json) A Ruby variant of the JSON gem +* [NSJSONSerialization](https://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html) Wrapper for Apple's NSJSONSerialization in the Cocoa Framework (MacRuby only) +* [OkJson][okjson] A simple, vendorable JSON parser + +## Supported Ruby Versions +This library aims to support and is [tested against][travis] the following Ruby +implementations: + +* Ruby 1.8.7 +* Ruby 1.9.2 +* Ruby 1.9.3 +* [JRuby][] +* [Rubinius][] +* [MacRuby][] (not tested on Travis CI) + +[jruby]: http://www.jruby.org/ +[rubinius]: http://rubini.us/ +[macruby]: http://www.macruby.org/ + +If something doesn't work on one of these interpreters, it should be considered +a bug. + +This library may inadvertently work (or seem to work) on other Ruby +implementations, however support will only be provided for the versions listed +above. + +If you would like this library to support another Ruby version, you may +volunteer to be a maintainer. Being a maintainer entails making sure all tests +run and pass on that implementation. When something breaks on your +implementation, you will be personally responsible for providing patches in a +timely fashion. If critical issues for a particular implementation exist at the +time of a major release, support for that Ruby version may be dropped. + +## Copyright +Copyright (c) 2010 Michael Bleigh, Josh Kalderimis, Erik Michaels-Ober, and Intridea, Inc. +See [LICENSE][] for details. + +[license]: https://github.com/intridea/multi_json/blob/master/LICENSE.md diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/Rakefile b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/Rakefile new file mode 100644 index 0000000..d9d4646 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/Rakefile @@ -0,0 +1,20 @@ +require 'bundler' +Bundler::GemHelper.install_tasks + +require 'rspec/core/rake_task' +desc "Run all examples" +RSpec::Core::RakeTask.new(:spec) + +task :default => :spec +task :test => :spec + +namespace :doc do + require 'rdoc/task' + require File.expand_path('../lib/multi_json/version', __FILE__) + RDoc::Task.new do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = "multi_json #{MultiJson::VERSION}" + rdoc.main = 'README.md' + rdoc.rdoc_files.include('README.md', 'LICENSE.md', 'lib/**/*.rb') + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json.rb new file mode 100644 index 0000000..a9a965e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json.rb @@ -0,0 +1,122 @@ +module MultiJson + class DecodeError < StandardError + attr_reader :data + def initialize(message="", backtrace=[], data="") + super(message) + self.set_backtrace(backtrace) + @data = data + end + end + + @adapter = nil + + REQUIREMENT_MAP = [ + ["oj", :oj], + ["yajl", :yajl], + ["json", :json_gem], + ["json/pure", :json_pure] + ] + + class << self + + # The default adapter based on what you currently + # have loaded and installed. First checks to see + # if any adapters are already loaded, then checks + # to see which are installed if none are loaded. + def default_adapter + return :oj if defined?(::Oj) + return :yajl if defined?(::Yajl) + return :json_gem if defined?(::JSON) + + REQUIREMENT_MAP.each do |(library, adapter)| + begin + require library + return adapter + rescue LoadError + next + end + end + + Kernel.warn "[WARNING] MultiJson is using the default adapter (ok_json). We recommend loading a different JSON library to improve performance." + :ok_json + end + # :nodoc: + alias :default_engine :default_adapter + + # Get the current adapter class. + def adapter + return @adapter if @adapter + self.use self.default_adapter + @adapter + end + # :nodoc: + alias :engine :adapter + + # Set the JSON parser utilizing a symbol, string, or class. + # Supported by default are: + # + # * :oj + # * :json_gem + # * :json_pure + # * :ok_json + # * :yajl + # * :nsjsonserialization (MacRuby only) + def use(new_adapter) + @adapter = load_adapter(new_adapter) + end + alias :adapter= :use + # :nodoc: + alias :engine= :use + + def load_adapter(new_adapter) + case new_adapter + when String, Symbol + require "multi_json/adapters/#{new_adapter}" + MultiJson::Adapters.const_get(:"#{new_adapter.to_s.split('_').map{|s| s.capitalize}.join('')}") + when NilClass, FalseClass + default_adapter = self.default_adapter + require "multi_json/adapters/#{default_adapter}" + MultiJson::Adapters.const_get(:"#{default_adapter.to_s.split('_').map{|s| s.capitalize}.join('')}") + when Class + new_adapter + else + raise "Did not recognize your adapter specification. Please specify either a symbol or a class." + end + end + + # Decode a JSON string into Ruby. + # + # Options + # + # :symbolize_keys :: If true, will use symbols instead of strings for the keys. + # :adapter :: If set, the selected engine will be used just for the call. + def load(string, options={}) + adapter = current_adapter(options) + begin + adapter.load(string, options) + rescue adapter::ParseError => exception + raise DecodeError.new(exception.message, exception.backtrace, string) + end + end + # :nodoc: + alias :decode :load + + def current_adapter(options) + if new_adapter = (options || {}).delete(:adapter) + load_adapter(new_adapter) + else + adapter + end + end + + # Encodes a Ruby object as JSON. + def dump(object, options={}) + adapter = current_adapter(options) + adapter.dump(object, options) + end + # :nodoc: + alias :encode :dump + + end + +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/json_common.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/json_common.rb new file mode 100644 index 0000000..992cc5a --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/json_common.rb @@ -0,0 +1,25 @@ +module MultiJson + module Adapters + module JsonCommon + + def load(string, options={}) + string = string.read if string.respond_to?(:read) + ::JSON.parse(string, :symbolize_names => options[:symbolize_keys], :quirks_mode => true) + end + + def dump(object, options={}) + object.to_json(process_options(options)) + end + + protected + + def process_options(options={}) + return options if options.empty? + opts = {} + opts.merge!(JSON::PRETTY_STATE_PROTOTYPE.to_h) if options.delete(:pretty) + opts.merge!(options) + end + + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/json_gem.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/json_gem.rb new file mode 100644 index 0000000..7b34e91 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/json_gem.rb @@ -0,0 +1,12 @@ +require 'json' unless defined?(::JSON) +require 'multi_json/adapters/json_common' + +module MultiJson + module Adapters + # Use the JSON gem to dump/load. + class JsonGem + ParseError = ::JSON::ParserError + extend JsonCommon + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/json_pure.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/json_pure.rb new file mode 100644 index 0000000..5d06ea6 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/json_pure.rb @@ -0,0 +1,12 @@ +require 'json/pure' unless defined?(::JSON) +require 'multi_json/adapters/json_common' + +module MultiJson + module Adapters + # Use JSON pure to dump/load. + class JsonPure + ParseError = ::JSON::ParserError + extend JsonCommon + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/nsjsonserialization.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/nsjsonserialization.rb new file mode 100644 index 0000000..77ae4f1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/nsjsonserialization.rb @@ -0,0 +1,34 @@ +framework 'Foundation' +require 'multi_json/adapters/ok_json' + +module MultiJson + module Adapters + class Nsjsonserialization < MultiJson::Adapters::OkJson + ParseError = ::MultiJson::OkJson::Error + + def self.load(string, options={}) + string = string.read if string.respond_to?(:read) + data = string.dataUsingEncoding(NSUTF8StringEncoding) + object = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves, error: nil) + if object + object = symbolize_keys(object) if options[:symbolize_keys] + object + else + super(string, options={}) + end + end + + def self.dump(object, options={}) + pretty = options[:pretty] ? NSJSONWritingPrettyPrinted : 0 + object = object.as_json if object.respond_to?(:as_json) + if NSJSONSerialization.isValidJSONObject(object) + data = NSJSONSerialization.dataWithJSONObject(object, options: pretty, error: nil) + NSMutableString.alloc.initWithData(data, encoding: NSUTF8StringEncoding) + else + super(object, options) + end + end + + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/oj.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/oj.rb new file mode 100644 index 0000000..4c5e7fb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/oj.rb @@ -0,0 +1,26 @@ +require 'oj' unless defined?(::Oj) + +module MultiJson + module Adapters + # Use the Oj library to dump/load. + class Oj + ParseError = if defined?(::Oj::ParseError) + ::Oj::ParseError + else + SyntaxError + end + + ::Oj.default_options = {:mode => :compat} + + def self.load(string, options={}) #:nodoc: + options.merge!(:symbol_keys => options[:symbolize_keys]) + ::Oj.load(string, options) + end + + def self.dump(object, options={}) #:nodoc: + options.merge!(:indent => 2) if options[:pretty] + ::Oj.dump(object, options) + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/ok_json.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/ok_json.rb new file mode 100644 index 0000000..6426179 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/ok_json.rb @@ -0,0 +1,48 @@ +require 'multi_json/vendor/okjson' + +module MultiJson + module Adapters + class OkJson + ParseError = ::MultiJson::OkJson::Error + + def self.load(string, options={}) #:nodoc: + string = string.read if string.respond_to?(:read) + result = ::MultiJson::OkJson.decode("[#{string}]").first + options[:symbolize_keys] ? symbolize_keys(result) : result + end + + def self.dump(object, options={}) #:nodoc: + ::MultiJson::OkJson.valenc(stringify_keys(object)) + end + + def self.symbolize_keys(object) #:nodoc: + modify_keys(object) do |key| + key.is_a?(String) ? key.to_sym : key + end + end + + def self.stringify_keys(object) #:nodoc: + modify_keys(object) do |key| + key.is_a?(Symbol) ? key.to_s : key + end + end + + def self.modify_keys(object, &modifier) #:nodoc: + case object + when Array + object.map do |value| + modify_keys(value, &modifier) + end + when Hash + object.inject({}) do |result, (key, value)| + new_key = modifier.call(key) + new_value = modify_keys(value, &modifier) + result.merge! new_key => new_value + end + else + object + end + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/yajl.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/yajl.rb new file mode 100644 index 0000000..3c0987d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/adapters/yajl.rb @@ -0,0 +1,18 @@ +require 'yajl' unless defined?(::Yajl) + +module MultiJson + module Adapters + # Use the Yajl-Ruby library to dump/load. + class Yajl + ParseError = ::Yajl::ParseError + + def self.load(string, options={}) #:nodoc: + ::Yajl::Parser.new(:symbolize_keys => options[:symbolize_keys]).parse(string) + end + + def self.dump(object, options={}) #:nodoc: + ::Yajl::Encoder.encode(object, options) + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/vendor/okjson.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/vendor/okjson.rb new file mode 100644 index 0000000..c18ed41 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/vendor/okjson.rb @@ -0,0 +1,602 @@ +# encoding: UTF-8 +# +# Copyright 2011, 2012 Keith Rarick +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +# See https://github.com/kr/okjson for updates. + +require 'stringio' + +# Some parts adapted from +# http://golang.org/src/pkg/json/decode.go and +# http://golang.org/src/pkg/utf8/utf8.go +module MultiJson + module OkJson + extend self + + + # Decodes a json document in string s and + # returns the corresponding ruby value. + # String s must be valid UTF-8. If you have + # a string in some other encoding, convert + # it first. + # + # String values in the resulting structure + # will be UTF-8. + def decode(s) + ts = lex(s) + v, ts = textparse(ts) + if ts.length > 0 + raise Error, 'trailing garbage' + end + v + end + + + # Parses a "json text" in the sense of RFC 4627. + # Returns the parsed value and any trailing tokens. + # Note: this is almost the same as valparse, + # except that it does not accept atomic values. + def textparse(ts) + if ts.length < 0 + raise Error, 'empty' + end + + typ, _, val = ts[0] + case typ + when '{' then objparse(ts) + when '[' then arrparse(ts) + else + raise Error, "unexpected #{val.inspect}" + end + end + + + # Parses a "value" in the sense of RFC 4627. + # Returns the parsed value and any trailing tokens. + def valparse(ts) + if ts.length < 0 + raise Error, 'empty' + end + + typ, _, val = ts[0] + case typ + when '{' then objparse(ts) + when '[' then arrparse(ts) + when :val,:str then [val, ts[1..-1]] + else + raise Error, "unexpected #{val.inspect}" + end + end + + + # Parses an "object" in the sense of RFC 4627. + # Returns the parsed value and any trailing tokens. + def objparse(ts) + ts = eat('{', ts) + obj = {} + + if ts[0][0] == '}' + return obj, ts[1..-1] + end + + k, v, ts = pairparse(ts) + obj[k] = v + + if ts[0][0] == '}' + return obj, ts[1..-1] + end + + loop do + ts = eat(',', ts) + + k, v, ts = pairparse(ts) + obj[k] = v + + if ts[0][0] == '}' + return obj, ts[1..-1] + end + end + end + + + # Parses a "member" in the sense of RFC 4627. + # Returns the parsed values and any trailing tokens. + def pairparse(ts) + (typ, _, k), ts = ts[0], ts[1..-1] + if typ != :str + raise Error, "unexpected #{k.inspect}" + end + ts = eat(':', ts) + v, ts = valparse(ts) + [k, v, ts] + end + + + # Parses an "array" in the sense of RFC 4627. + # Returns the parsed value and any trailing tokens. + def arrparse(ts) + ts = eat('[', ts) + arr = [] + + if ts[0][0] == ']' + return arr, ts[1..-1] + end + + v, ts = valparse(ts) + arr << v + + if ts[0][0] == ']' + return arr, ts[1..-1] + end + + loop do + ts = eat(',', ts) + + v, ts = valparse(ts) + arr << v + + if ts[0][0] == ']' + return arr, ts[1..-1] + end + end + end + + + def eat(typ, ts) + if ts[0][0] != typ + raise Error, "expected #{typ} (got #{ts[0].inspect})" + end + ts[1..-1] + end + + + # Scans s and returns a list of json tokens, + # excluding white space (as defined in RFC 4627). + def lex(s) + ts = [] + while s.length > 0 + typ, lexeme, val = tok(s) + if typ == nil + raise Error, "invalid character at #{s[0,10].inspect}" + end + if typ != :space + ts << [typ, lexeme, val] + end + s = s[lexeme.length..-1] + end + ts + end + + + # Scans the first token in s and + # returns a 3-element list, or nil + # if s does not begin with a valid token. + # + # The first list element is one of + # '{', '}', ':', ',', '[', ']', + # :val, :str, and :space. + # + # The second element is the lexeme. + # + # The third element is the value of the + # token for :val and :str, otherwise + # it is the lexeme. + def tok(s) + case s[0] + when ?{ then ['{', s[0,1], s[0,1]] + when ?} then ['}', s[0,1], s[0,1]] + when ?: then [':', s[0,1], s[0,1]] + when ?, then [',', s[0,1], s[0,1]] + when ?[ then ['[', s[0,1], s[0,1]] + when ?] then [']', s[0,1], s[0,1]] + when ?n then nulltok(s) + when ?t then truetok(s) + when ?f then falsetok(s) + when ?" then strtok(s) + when Spc then [:space, s[0,1], s[0,1]] + when ?\t then [:space, s[0,1], s[0,1]] + when ?\n then [:space, s[0,1], s[0,1]] + when ?\r then [:space, s[0,1], s[0,1]] + else numtok(s) + end + end + + + def nulltok(s); s[0,4] == 'null' ? [:val, 'null', nil] : [] end + def truetok(s); s[0,4] == 'true' ? [:val, 'true', true] : [] end + def falsetok(s); s[0,5] == 'false' ? [:val, 'false', false] : [] end + + + def numtok(s) + m = /-?([1-9][0-9]+|[0-9])([.][0-9]+)?([eE][+-]?[0-9]+)?/.match(s) + if m && m.begin(0) == 0 + if m[3] && !m[2] + [:val, m[0], Integer(m[1])*(10**Integer(m[3][1..-1]))] + elsif m[2] + [:val, m[0], Float(m[0])] + else + [:val, m[0], Integer(m[0])] + end + else + [] + end + end + + + def strtok(s) + m = /"([^"\\]|\\["\/\\bfnrt]|\\u[0-9a-fA-F]{4})*"/.match(s) + if ! m + raise Error, "invalid string literal at #{abbrev(s)}" + end + [:str, m[0], unquote(m[0])] + end + + + def abbrev(s) + t = s[0,10] + p = t['`'] + t = t[0,p] if p + t = t + '...' if t.length < s.length + '`' + t + '`' + end + + + # Converts a quoted json string literal q into a UTF-8-encoded string. + # The rules are different than for Ruby, so we cannot use eval. + # Unquote will raise an error if q contains control characters. + def unquote(q) + q = q[1...-1] + a = q.dup # allocate a big enough string + rubydoesenc = false + # In ruby >= 1.9, a[w] is a codepoint, not a byte. + if a.class.method_defined?(:force_encoding) + a.force_encoding('UTF-8') + rubydoesenc = true + end + r, w = 0, 0 + while r < q.length + c = q[r] + case true + when c == ?\\ + r += 1 + if r >= q.length + raise Error, "string literal ends with a \"\\\": \"#{q}\"" + end + + case q[r] + when ?",?\\,?/,?' + a[w] = q[r] + r += 1 + w += 1 + when ?b,?f,?n,?r,?t + a[w] = Unesc[q[r]] + r += 1 + w += 1 + when ?u + r += 1 + uchar = begin + hexdec4(q[r,4]) + rescue RuntimeError => e + raise Error, "invalid escape sequence \\u#{q[r,4]}: #{e}" + end + r += 4 + if surrogate? uchar + if q.length >= r+6 + uchar1 = hexdec4(q[r+2,4]) + uchar = subst(uchar, uchar1) + if uchar != Ucharerr + # A valid pair; consume. + r += 6 + end + end + end + if rubydoesenc + a[w] = '' << uchar + w += 1 + else + w += ucharenc(a, w, uchar) + end + else + raise Error, "invalid escape char #{q[r]} in \"#{q}\"" + end + when c == ?", c < Spc + raise Error, "invalid character in string literal \"#{q}\"" + else + # Copy anything else byte-for-byte. + # Valid UTF-8 will remain valid UTF-8. + # Invalid UTF-8 will remain invalid UTF-8. + # In ruby >= 1.9, c is a codepoint, not a byte, + # in which case this is still what we want. + a[w] = c + r += 1 + w += 1 + end + end + a[0,w] + end + + + # Encodes unicode character u as UTF-8 + # bytes in string a at position i. + # Returns the number of bytes written. + def ucharenc(a, i, u) + case true + when u <= Uchar1max + a[i] = (u & 0xff).chr + 1 + when u <= Uchar2max + a[i+0] = (Utag2 | ((u>>6)&0xff)).chr + a[i+1] = (Utagx | (u&Umaskx)).chr + 2 + when u <= Uchar3max + a[i+0] = (Utag3 | ((u>>12)&0xff)).chr + a[i+1] = (Utagx | ((u>>6)&Umaskx)).chr + a[i+2] = (Utagx | (u&Umaskx)).chr + 3 + else + a[i+0] = (Utag4 | ((u>>18)&0xff)).chr + a[i+1] = (Utagx | ((u>>12)&Umaskx)).chr + a[i+2] = (Utagx | ((u>>6)&Umaskx)).chr + a[i+3] = (Utagx | (u&Umaskx)).chr + 4 + end + end + + + def hexdec4(s) + if s.length != 4 + raise Error, 'short' + end + (nibble(s[0])<<12) | (nibble(s[1])<<8) | (nibble(s[2])<<4) | nibble(s[3]) + end + + + def subst(u1, u2) + if Usurr1 <= u1 && u1 < Usurr2 && Usurr2 <= u2 && u2 < Usurr3 + return ((u1-Usurr1)<<10) | (u2-Usurr2) + Usurrself + end + return Ucharerr + end + + + def surrogate?(u) + Usurr1 <= u && u < Usurr3 + end + + + def nibble(c) + case true + when ?0 <= c && c <= ?9 then c.ord - ?0.ord + when ?a <= c && c <= ?z then c.ord - ?a.ord + 10 + when ?A <= c && c <= ?Z then c.ord - ?A.ord + 10 + else + raise Error, "invalid hex code #{c}" + end + end + + + # Encodes x into a json text. It may contain only + # Array, Hash, String, Numeric, true, false, nil. + # (Note, this list excludes Symbol.) + # X itself must be an Array or a Hash. + # No other value can be encoded, and an error will + # be raised if x contains any other value, such as + # Nan, Infinity, Symbol, and Proc, or if a Hash key + # is not a String. + # Strings contained in x must be valid UTF-8. + def encode(x) + case x + when Hash then objenc(x) + when Array then arrenc(x) + else + raise Error, 'root value must be an Array or a Hash' + end + end + + + def valenc(x) + case x + when Hash then objenc(x) + when Array then arrenc(x) + when String then strenc(x) + when Numeric then numenc(x) + when true then "true" + when false then "false" + when nil then "null" + else + if x.respond_to?(:to_json) + x.to_json + else + raise Error, "cannot encode #{x.class}: #{x.inspect}" + end + end + end + + + def objenc(x) + '{' + x.map{|k,v| keyenc(k) + ':' + valenc(v)}.join(',') + '}' + end + + + def arrenc(a) + '[' + a.map{|x| valenc(x)}.join(',') + ']' + end + + + def keyenc(k) + case k + when String then strenc(k) + else + raise Error, "Hash key is not a string: #{k.inspect}" + end + end + + + def strenc(s) + t = StringIO.new + t.putc(?") + r = 0 + + # In ruby >= 1.9, s[r] is a codepoint, not a byte. + rubydoesenc = s.class.method_defined?(:encoding) + + while r < s.length + case s[r] + when ?" then t.print('\\"') + when ?\\ then t.print('\\\\') + when ?\b then t.print('\\b') + when ?\f then t.print('\\f') + when ?\n then t.print('\\n') + when ?\r then t.print('\\r') + when ?\t then t.print('\\t') + else + c = s[r] + case true + when rubydoesenc + begin + c.ord # will raise an error if c is invalid UTF-8 + t.write(c) + rescue + t.write(Ustrerr) + end + when Spc <= c && c <= ?~ + t.putc(c) + else + n = ucharcopy(t, s, r) # ensure valid UTF-8 output + r += n - 1 # r is incremented below + end + end + r += 1 + end + t.putc(?") + t.string + end + + + def numenc(x) + if ((x.nan? || x.infinite?) rescue false) + raise Error, "Numeric cannot be represented: #{x}" + end + "#{x}" + end + + + # Copies the valid UTF-8 bytes of a single character + # from string s at position i to I/O object t, and + # returns the number of bytes copied. + # If no valid UTF-8 char exists at position i, + # ucharcopy writes Ustrerr and returns 1. + def ucharcopy(t, s, i) + n = s.length - i + raise Utf8Error if n < 1 + + c0 = s[i].ord + + # 1-byte, 7-bit sequence? + if c0 < Utagx + t.putc(c0) + return 1 + end + + raise Utf8Error if c0 < Utag2 # unexpected continuation byte? + + raise Utf8Error if n < 2 # need continuation byte + c1 = s[i+1].ord + raise Utf8Error if c1 < Utagx || Utag2 <= c1 + + # 2-byte, 11-bit sequence? + if c0 < Utag3 + raise Utf8Error if ((c0&Umask2)<<6 | (c1&Umaskx)) <= Uchar1max + t.putc(c0) + t.putc(c1) + return 2 + end + + # need second continuation byte + raise Utf8Error if n < 3 + + c2 = s[i+2].ord + raise Utf8Error if c2 < Utagx || Utag2 <= c2 + + # 3-byte, 16-bit sequence? + if c0 < Utag4 + u = (c0&Umask3)<<12 | (c1&Umaskx)<<6 | (c2&Umaskx) + raise Utf8Error if u <= Uchar2max + t.putc(c0) + t.putc(c1) + t.putc(c2) + return 3 + end + + # need third continuation byte + raise Utf8Error if n < 4 + c3 = s[i+3].ord + raise Utf8Error if c3 < Utagx || Utag2 <= c3 + + # 4-byte, 21-bit sequence? + if c0 < Utag5 + u = (c0&Umask4)<<18 | (c1&Umaskx)<<12 | (c2&Umaskx)<<6 | (c3&Umaskx) + raise Utf8Error if u <= Uchar3max + t.putc(c0) + t.putc(c1) + t.putc(c2) + t.putc(c3) + return 4 + end + + raise Utf8Error + rescue Utf8Error + t.write(Ustrerr) + return 1 + end + + + class Utf8Error < ::StandardError + end + + + class Error < ::StandardError + end + + + Utagx = 0x80 # 1000 0000 + Utag2 = 0xc0 # 1100 0000 + Utag3 = 0xe0 # 1110 0000 + Utag4 = 0xf0 # 1111 0000 + Utag5 = 0xF8 # 1111 1000 + Umaskx = 0x3f # 0011 1111 + Umask2 = 0x1f # 0001 1111 + Umask3 = 0x0f # 0000 1111 + Umask4 = 0x07 # 0000 0111 + Uchar1max = (1<<7) - 1 + Uchar2max = (1<<11) - 1 + Uchar3max = (1<<16) - 1 + Ucharerr = 0xFFFD # unicode "replacement char" + Ustrerr = "\xef\xbf\xbd" # unicode "replacement char" + Usurrself = 0x10000 + Usurr1 = 0xd800 + Usurr2 = 0xdc00 + Usurr3 = 0xe000 + + Spc = ' '[0] + Unesc = {?b=>?\b, ?f=>?\f, ?n=>?\n, ?r=>?\r, ?t=>?\t} + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/version.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/version.rb new file mode 100644 index 0000000..ce4d229 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/lib/multi_json/version.rb @@ -0,0 +1,3 @@ +module MultiJson + VERSION = "1.4.0" unless defined?(MultiJson::VERSION) +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/multi_json.gemspec b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/multi_json.gemspec new file mode 100644 index 0000000..10d5e12 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/multi_json.gemspec @@ -0,0 +1,23 @@ +# encoding: utf-8 +require File.expand_path("../lib/multi_json/version", __FILE__) + +Gem::Specification.new do |gem| + gem.add_development_dependency 'rake', '~> 0.9' + gem.add_development_dependency 'rdoc', '~> 3.9' + gem.add_development_dependency 'rspec', '~> 2.6' + gem.add_development_dependency 'simplecov', '~> 0.4' + gem.authors = ["Michael Bleigh", "Josh Kalderimis", "Erik Michaels-Ober"] + gem.description = %q{A gem to provide easy switching between different JSON backends, including Oj, Yajl, the JSON gem (with C-extensions), the pure-Ruby JSON gem, and OkJson.} + gem.email = ['michael@intridea.com', 'josh.kalderimis@gmail.com', 'sferik@gmail.com'] + gem.extra_rdoc_files = ['LICENSE.md', 'README.md'] + gem.files = Dir['LICENSE.md', 'README.md', 'Rakefile', 'multi_json.gemspec', 'Gemfile', '.document', '.rspec', '.travis.yml' ,'spec/**/*', 'lib/**/*'] + gem.homepage = 'http://github.com/intridea/multi_json' + gem.licenses = ['MIT'] + gem.name = 'multi_json' + gem.rdoc_options = ["--charset=UTF-8"] + gem.require_paths = ['lib'] + gem.required_rubygems_version = Gem::Requirement.new(">= 1.3.6") + gem.summary = %q{A gem to provide swappable JSON backends.} + gem.test_files = Dir['spec/**/*'] + gem.version = MultiJson::VERSION +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/spec/adapter_shared_example.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/spec/adapter_shared_example.rb new file mode 100644 index 0000000..03edf0d --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/spec/adapter_shared_example.rb @@ -0,0 +1,123 @@ +shared_examples_for "an adapter" do |adapter| + + before do + begin + MultiJson.use adapter + rescue LoadError + pending "Adapter #{adapter} couldn't be loaded (not installed?)" + end + end + + describe '.dump' do + it 'writes decodable JSON' do + [ + {'abc' => 'def'}, + [1, 2, 3, "4"], + ].each do |example| + expect(MultiJson.load(MultiJson.dump(example))).to eq example + end + end + + it 'dumps symbol keys as strings' do + [ + [ + {:foo => {:bar => 'baz'}}, + {'foo' => {'bar' => 'baz'}}, + ], + [ + [{:foo => {:bar => 'baz'}}], + [{'foo' => {'bar' => 'baz'}}], + ], + [ + {:foo => [{:bar => 'baz'}]}, + {'foo' => [{'bar' => 'baz'}]}, + ] + ].each do |example, expected| + dumped_json = MultiJson.dump(example) + expect(MultiJson.load(dumped_json)).to eq expected + end + end + + it 'dumps rootless JSON' do + expect(MultiJson.dump("random rootless string")).to eq "\"random rootless string\"" + expect(MultiJson.dump(123)).to eq "123" + end + + it 'passes options to the adapter' do + MultiJson.adapter.should_receive(:dump).with('foo', {:bar => :baz}) + MultiJson.dump('foo', :bar => :baz) + end + + if adapter == 'json_gem' || adapter == 'json_pure' + describe 'with :pretty option set to true' do + it 'passes default pretty options' do + object = 'foo' + object.should_receive(:to_json).with(JSON::PRETTY_STATE_PROTOTYPE.to_h) + MultiJson.dump(object,:pretty => true) + end + end + end + + it 'dumps custom objects which implement as_json' do + expect(MultiJson.dump(TimeWithZone.new)).to eq "\"2005-02-01T15:15:10Z\"" + end + + it 'allow to dump JSON values' do + expect(MultiJson.dump(42)).to eq '42' + end + + end + + describe '.load' do + it 'properly loads valid JSON' do + expect(MultiJson.load('{"abc":"def"}')).to eq({'abc' => 'def'}) + end + + it 'raises MultiJson::DecodeError on invalid JSON' do + expect{MultiJson.load('{"abc"}')}.to raise_error(MultiJson::DecodeError) + end + + it 'raises MultiJson::DecodeError with data on invalid JSON' do + data = '{invalid}' + begin + MultiJson.load(data) + rescue MultiJson::DecodeError => de + expect(de.data).to eq data + end + end + + it 'stringifys symbol keys when encoding' do + dumped_json = MultiJson.dump(:a => 1, :b => {:c => 2}) + expect(MultiJson.load(dumped_json)).to eq({"a" => 1, "b" => {"c" => 2}}) + end + + it 'properly loads valid JSON in StringIOs' do + json = StringIO.new('{"abc":"def"}') + expect(MultiJson.load(json)).to eq({'abc' => 'def'}) + end + + it 'allows for symbolization of keys' do + [ + [ + '{"abc":{"def":"hgi"}}', + {:abc => {:def => 'hgi'}}, + ], + [ + '[{"abc":{"def":"hgi"}}]', + [{:abc => {:def => 'hgi'}}], + ], + [ + '{"abc":[{"def":"hgi"}]}', + {:abc => [{:def => 'hgi'}]}, + ], + ].each do |example, expected| + expect(MultiJson.load(example, :symbolize_keys => true)).to eq expected + end + end + + it 'allow to load JSON values' do + expect(MultiJson.load('42')).to eq 42 + end + + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/spec/helper.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/spec/helper.rb new file mode 100644 index 0000000..803cf78 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/spec/helper.rb @@ -0,0 +1,39 @@ +def jruby? + defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' +end + +def macruby? + defined?(RUBY_ENGINE) && RUBY_ENGINE == 'macruby' +end + +unless ENV['CI'] || macruby? + require 'simplecov' + SimpleCov.start do + add_filter 'spec' + end +end + +require 'multi_json' +require 'rspec' + +RSpec.configure do |config| + config.expect_with :rspec do |c| + c.syntax = :expect + end +end + +class MockDecoder + def self.load(string, options={}) + {'abc' => 'def'} + end + + def self.dump(string) + '{"abc":"def"}' + end +end + +class TimeWithZone + def to_json(options={}) + "\"2005-02-01T15:15:10Z\"" + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_json-1.4.0/spec/multi_json_spec.rb b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/spec/multi_json_spec.rb new file mode 100644 index 0000000..f445e93 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_json-1.4.0/spec/multi_json_spec.rb @@ -0,0 +1,89 @@ +require 'helper' +require 'adapter_shared_example' +require 'stringio' + +describe 'MultiJson' do + context 'adapters' do + before do + MultiJson.use nil + end + context 'when no other json implementations are available' do + before do + @old_map = MultiJson::REQUIREMENT_MAP + @old_json = Object.const_get :JSON if Object.const_defined?(:JSON) + @old_oj = Object.const_get :Oj if Object.const_defined?(:Oj) + @old_yajl = Object.const_get :Yajl if Object.const_defined?(:Yajl) + MultiJson::REQUIREMENT_MAP.each_with_index do |(library, adapter), index| + MultiJson::REQUIREMENT_MAP[index] = ["foo/#{library}", adapter] + end + Object.send :remove_const, :JSON if @old_json + Object.send :remove_const, :Oj if @old_oj + Object.send :remove_const, :Yajl if @old_yajl + end + + after do + @old_map.each_with_index do |(library, adapter), index| + MultiJson::REQUIREMENT_MAP[index] = [library, adapter] + end + Object.const_set :JSON, @old_json if @old_json + Object.const_set :Oj, @old_oj if @old_oj + Object.const_set :Yajl, @old_yajl if @old_yajl + end + + it 'defaults to ok_json if no other json implementions are available' do + expect(MultiJson.default_adapter).to eq :ok_json + end + + it 'prints a warning' do + Kernel.should_receive(:warn).with(/warning/i) + MultiJson.default_adapter + end + end + + it 'defaults to the best available gem' do + # Clear cache variable already set by previous tests + MultiJson.send(:remove_instance_variable, :@adapter) + unless jruby? + require 'oj' + expect(MultiJson.adapter.name).to eq 'MultiJson::Adapters::Oj' + else + require 'json' + expect(MultiJson.adapter.name).to eq 'MultiJson::Adapters::JsonGem' + end + end + + it 'is settable via a symbol' do + MultiJson.use :json_gem + expect(MultiJson.adapter.name).to eq 'MultiJson::Adapters::JsonGem' + end + + it 'is settable via a class' do + MultiJson.use MockDecoder + expect(MultiJson.adapter.name).to eq 'MockDecoder' + end + + context "using one-shot parser" do + before(:each) do + require 'multi_json/adapters/json_pure' + MultiJson::Adapters::JsonPure.should_receive(:dump).exactly(1).times.and_return('dump_something') + MultiJson::Adapters::JsonPure.should_receive(:load).exactly(1).times.and_return('load_something') + end + + it "should use the defined parser just for the call" do + MultiJson.use :json_gem + expect(MultiJson.dump('', :adapter => :json_pure)).to eq 'dump_something' + expect(MultiJson.load('', :adapter => :json_pure)).to eq 'load_something' + expect(MultiJson.adapter.to_s).to eq "MultiJson::Adapters::JsonGem" + end + end + end + + %w(json_gem json_pure nsjsonserialization oj ok_json yajl).each do |adapter| + next if !macruby? && adapter == 'nsjsonserialization' + next if jruby? && (adapter == 'oj' || adapter == 'yajl') + + context adapter do + it_behaves_like "an adapter", adapter + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.gemtest b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.gemtest new file mode 100644 index 0000000..e69de29 diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.gitignore b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.gitignore new file mode 100644 index 0000000..c6de9ad --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.gitignore @@ -0,0 +1,9 @@ +*.gem +*.rbc +.bundle +.yardoc +Gemfile.lock +coverage/* +doc/* +log/* +pkg/* diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.rspec b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.rspec new file mode 100644 index 0000000..0912718 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.rspec @@ -0,0 +1,2 @@ +--color +--order random diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.travis.yml b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.travis.yml new file mode 100644 index 0000000..d268672 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.travis.yml @@ -0,0 +1,9 @@ +language: ruby +matrix: + allow_failures: + - rvm: ruby-head +rvm: + - 1.8.7 + - 1.9.2 + - 1.9.3 + - ruby-head diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.yardopts b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.yardopts new file mode 100644 index 0000000..980a7c1 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/.yardopts @@ -0,0 +1,5 @@ +--no-private +--protected +--markup markdown +- +LICENSE.md diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/Gemfile b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/Gemfile new file mode 100644 index 0000000..f784d54 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/Gemfile @@ -0,0 +1,9 @@ +source 'https://rubygems.org' + +group :development, :test do + gem 'libxml-ruby', :require => nil, :platforms => :mri + gem 'nokogiri', :require => nil + gem 'ox', :require => nil +end + +gemspec diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/LICENSE.md b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/LICENSE.md new file mode 100644 index 0000000..0420edb --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/LICENSE.md @@ -0,0 +1,20 @@ +Copyright (c) 2010 Erik Michaels-Ober + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/README.md b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/README.md new file mode 100644 index 0000000..7cdab6e --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/README.md @@ -0,0 +1,126 @@ +# MultiXML [![Build Status](https://secure.travis-ci.org/sferik/multi_xml.png?branch=master)][travis] [![Dependency Status](https://gemnasium.com/sferik/multi_xml.png?travis)][gemnasium] +A generic swappable back-end for XML parsing + +[travis]: http://travis-ci.org/sferik/multi_xml +[gemnasium]: https://gemnasium.com/sferik/multi_xml + +## Installation + gem install multi_xml + +## Documentation +[http://rdoc.info/gems/multi_xml][documentation] + +[documentation]: http://rdoc.info/gems/multi_xml + +## Usage Examples +Lots of Ruby libraries utilize XML parsing in some form, and everyone has their +favorite XML library. In order to best support multiple XML parsers and +libraries, `multi_xml` is a general-purpose swappable XML backend library. You +use it like so: + + require 'multi_xml' + + MultiXml.parser = :ox MultiXml.parser = MultiXml::Parsers::Ox # Same as + above MultiXml.parse('This is the contents') # Parsed using Ox + + MultiXml.parser = :libxml MultiXml.parser = MultiXml::Parsers::Libxml # + Same as above MultiXml.parse('This is the contents') # Parsed + using LibXML + + MultiXml.parser = :nokogiri MultiXml.parser = MultiXml::Parsers::Nokogiri # + Same as above MultiXml.parse('This is the contents') # Parsed + using Nokogiri + + MultiXml.parser = :rexml MultiXml.parser = MultiXml::Parsers::Rexml # Same + as above MultiXml.parse('This is the contents') # Parsed using + REXML + +The `parser` setter takes either a symbol or a class (to allow for custom XML +parsers) that responds to `.parse` at the class level. + +MultiXML tries to have intelligent defaulting. That is, if you have any of the +supported parsers already loaded, it will utilize them before attempting to +load any. When loading, libraries are ordered by speed: first Ox, then LibXML, +then Nokogiri, and finally REXML. + +## Contributing +In the spirit of [free software][free-sw] , **everyone** is encouraged to help +improve this project. + +[free-sw]: http://www.fsf.org/licensing/essays/free-sw.html + +Here are some ways *you* can contribute: + +* by using alpha, beta, and prerelease versions +* by reporting bugs +* by suggesting new features +* by writing or editing documentation +* by writing specifications +* by writing code (**no patch is too small**: fix typos, add comments, clean up + inconsistent whitespace) +* by refactoring code +* by resolving [issues][] +* by reviewing patches + +[issues]: https://github.com/sferik/multi_xml/issues + +## Submitting an Issue +We use the [GitHub issue tracker][issues] to track bugs and features. Before +submitting a bug report or feature request, check to make sure it hasn't +already been submitted. When submitting a bug report, please include a [Gist][] +that includes a stack trace and any details that may be necessary to reproduce +the bug, including your gem version, Ruby version, and operating system. +Ideally, a bug report should include a pull request with failing specs. + +[gist]: https://gist.github.com/ + +## Submitting a Pull Request +1. [Fork the repository.][fork] +2. [Create a topic branch.][branch] +3. Add specs for your unimplemented feature or bug fix. +4. Run `bundle exec rake spec`. If your specs pass, return to step 3. +5. Implement your feature or bug fix. +6. Run `bundle exec rake spec`. If your specs fail, return to step 5. +7. Run `open coverage/index.html`. If your changes are not completely covered + by your tests, return to step 3. +8. Add documentation for your feature or bug fix. +9. Run `bundle exec rake yard`. If your changes are not 100% documented, go + back to step 8. +10. Add, commit, and push your changes. +11. [Submit a pull request.][pr] + +[fork]: http://help.github.com/fork-a-repo/ +[branch]: http://learn.github.com/p/branching.html +[pr]: http://help.github.com/send-pull-requests/ + +## Supported Ruby Versions +This library aims to support and is [tested against][travis] the following Ruby +implementations: + +* Ruby 1.8.7 +* Ruby 1.9.2 +* Ruby 1.9.3 + +If something doesn't work on one of these interpreters, it should be considered +a bug. + +This library may inadvertently work (or seem to work) on other Ruby +implementations, however support will only be provided for the versions listed +above. + +If you would like this library to support another Ruby version, you may +volunteer to be a maintainer. Being a maintainer entails making sure all tests +run and pass on that implementation. When something breaks on your +implementation, you will be personally responsible for providing patches in a +timely fashion. If critical issues for a particular implementation exist at the +time of a major release, support for that Ruby version may be dropped. + +## Inspiration +MultiXML was inspired by [MultiJSON][]. + +[multijson]: https://github.com/intridea/multi_json/ + +## Copyright +Copyright (c) 2010 Erik Michaels-Ober. See [LICENSE][] for details. + +[license]: https://github.com/sferik/multi_xml/blob/master/LICENSE.md diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/Rakefile b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/Rakefile new file mode 100644 index 0000000..0e3699b --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/Rakefile @@ -0,0 +1,21 @@ +require 'bundler' +Bundler::GemHelper.install_tasks + +require 'rspec/core/rake_task' +RSpec::Core::RakeTask.new(:spec) + +task :test => :spec +task :default => :spec + +namespace :doc do + require 'yard' + YARD::Rake::YardocTask.new do |task| + task.files = ['LICENSE.md', 'lib/**/*.rb'] + task.options = [ + '--no-private', + '--protected', + '--output-dir', 'doc/yard', + '--markup', 'markdown', + ] + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml.rb b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml.rb new file mode 100644 index 0000000..09c9d98 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml.rb @@ -0,0 +1,274 @@ +require 'base64' +require 'bigdecimal' +require 'date' +require 'stringio' +require 'time' +require 'yaml' + +module MultiXml + class ParseError < StandardError; end + + REQUIREMENT_MAP = [ + ['ox', :ox], + ['libxml', :libxml], + ['nokogiri', :nokogiri], + ['rexml/document', :rexml] + ] unless defined?(REQUIREMENT_MAP) + + CONTENT_ROOT = '__content__'.freeze unless defined?(CONTENT_ROOT) + + unless defined?(PARSING) + PARSING = { + 'symbol' => Proc.new{|symbol| symbol.to_sym}, + 'date' => Proc.new{|date| Date.parse(date)}, + 'datetime' => Proc.new{|time| Time.parse(time).utc rescue DateTime.parse(time).utc}, + 'integer' => Proc.new{|integer| integer.to_i}, + 'float' => Proc.new{|float| float.to_f}, + 'decimal' => Proc.new{|number| BigDecimal(number)}, + 'boolean' => Proc.new{|boolean| !%w(0 false).include?(boolean.strip)}, + 'string' => Proc.new{|string| string.to_s}, + 'yaml' => Proc.new{|yaml| YAML::load(yaml) rescue yaml}, + 'base64Binary' => Proc.new{|binary| ::Base64.decode64(binary)}, + 'binary' => Proc.new{|binary, entity| parse_binary(binary, entity)}, + 'file' => Proc.new{|file, entity| parse_file(file, entity)}, + } + + PARSING.update( + 'double' => PARSING['float'], + 'dateTime' => PARSING['datetime'] + ) + end + + TYPE_NAMES = { + 'Symbol' => 'symbol', + 'Fixnum' => 'integer', + 'Bignum' => 'integer', + 'BigDecimal' => 'decimal', + 'Float' => 'float', + 'TrueClass' => 'boolean', + 'FalseClass' => 'boolean', + 'Date' => 'date', + 'DateTime' => 'datetime', + 'Time' => 'datetime', + 'Array' => 'array', + 'Hash' => 'hash' + } unless defined?(TYPE_NAMES) + + class << self + # Get the current parser class. + def parser + return @@parser if defined?(@@parser) + self.parser = self.default_parser + @@parser + end + + # The default parser based on what you currently + # have loaded and installed. First checks to see + # if any parsers are already loaded, then checks + # to see which are installed if none are loaded. + def default_parser + return :ox if defined?(::Ox) + return :libxml if defined?(::LibXML) + return :nokogiri if defined?(::Nokogiri) + + REQUIREMENT_MAP.each do |(library, parser)| + begin + require library + return parser + rescue LoadError + next + end + end + end + + # Set the XML parser utilizing a symbol, string, or class. + # Supported by default are: + # + # * :libxml + # * :nokogiri + # * :ox + # * :rexml + def parser=(new_parser) + case new_parser + when String, Symbol + require "multi_xml/parsers/#{new_parser.to_s.downcase}" + @@parser = MultiXml::Parsers.const_get("#{new_parser.to_s.split('_').map{|s| s.capitalize}.join('')}") + when Class, Module + @@parser = new_parser + else + raise "Did not recognize your parser specification. Please specify either a symbol or a class." + end + end + + # Parse an XML string or IO into Ruby. + # + # Options + # + # :symbolize_keys :: If true, will use symbols instead of strings for the keys. + def parse(xml, options={}) + xml ||= '' + + xml.strip! if xml.respond_to?(:strip!) + begin + xml = StringIO.new(xml) unless xml.respond_to?(:read) + + char = xml.getc + return {} if char.nil? + xml.ungetc(char) + + hash = typecast_xml_value(undasherize_keys(parser.parse(xml))) || {} + rescue parser.parse_error => error + raise ParseError, error.to_s, error.backtrace + end + hash = symbolize_keys(hash) if options[:symbolize_keys] + hash + end + + # This module decorates files with the original_filename + # and content_type methods. + module FileLike #:nodoc: + attr_writer :original_filename, :content_type + + def original_filename + @original_filename || 'untitled' + end + + def content_type + @content_type || 'application/octet-stream' + end + end + + private + + # TODO: Add support for other encodings + def parse_binary(binary, entity) #:nodoc: + case entity['encoding'] + when 'base64' + Base64.decode64(binary) + else + binary + end + end + + def parse_file(file, entity) + f = StringIO.new(Base64.decode64(file)) + f.extend(FileLike) + f.original_filename = entity['name'] + f.content_type = entity['content_type'] + f + end + + def symbolize_keys(hash) + hash.inject({}) do |result, (key, value)| + new_key = case key + when String + key.to_sym + else + key + end + new_value = case value + when Hash + symbolize_keys(value) + else + value + end + result[new_key] = new_value + result + end + end + + def undasherize_keys(params) + case params + when Hash + params.inject({}) do |hash, (key, value)| + hash[key.to_s.tr('-', '_')] = undasherize_keys(value) + hash + end + when Array + params.map{|value| undasherize_keys(value)} + else + params + end + end + + def typecast_xml_value(value) + case value + when Hash + if value['type'] == 'array' + + # this commented-out suggestion helps to avoid the multiple attribute + # problem, but it breaks when there is only one item in the array. + # + # from: https://github.com/jnunemaker/httparty/issues/102 + # + # _, entries = value.detect { |k, v| k != 'type' && v.is_a?(Array) } + + # This attempt fails to consider the order that the detect method + # retrieves the entries. + #_, entries = value.detect {|key, _| key != 'type'} + + # This approach ignores attribute entries that are not convertable + # to an Array which allows attributes to be ignored. + _, entries = value.detect {|k, v| k != 'type' && (v.is_a?(Array) || v.is_a?(Hash)) } + + if entries.nil? || (entries.is_a?(String) && entries.strip.empty?) + [] + else + case entries + when Array + entries.map {|entry| typecast_xml_value(entry)} + when Hash + [typecast_xml_value(entries)] + else + raise "can't typecast #{entries.class.name}: #{entries.inspect}" + end + end + elsif value.has_key?(CONTENT_ROOT) + content = value[CONTENT_ROOT] + if block = PARSING[value['type']] + if block.arity == 1 + value.delete('type') if PARSING[value['type']] + if value.keys.size > 1 + value[CONTENT_ROOT] = block.call(content) + value + else + block.call(content) + end + else + block.call(content, value) + end + else + value.keys.size > 1 ? value : content + end + elsif value['type'] == 'string' && value['nil'] != 'true' + '' + # blank or nil parsed values are represented by nil + elsif value.empty? || value['nil'] == 'true' + nil + # If the type is the only element which makes it then + # this still makes the value nil, except if type is + # a XML node(where type['value'] is a Hash) + elsif value['type'] && value.size == 1 && !value['type'].is_a?(Hash) + nil + else + xml_value = value.inject({}) do |hash, (k, v)| + hash[k] = typecast_xml_value(v) + hash + end + + # Turn {:files => {:file => #} into {:files => #} so it is compatible with + # how multipart uploaded files from HTML appear + xml_value['file'].is_a?(StringIO) ? xml_value['file'] : xml_value + end + when Array + value.map!{|i| typecast_xml_value(i)} + value.length > 1 ? value : value.first + when String + value + else + raise "can't typecast #{value.class.name}: #{value.inspect}" + end + end + end + +end diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/libxml.rb b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/libxml.rb new file mode 100644 index 0000000..1fb6353 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/libxml.rb @@ -0,0 +1,30 @@ +require 'libxml' unless defined?(LibXML) +require 'multi_xml/parsers/libxml2_parser' + +module MultiXml + module Parsers + module Libxml #:nodoc: + include Libxml2Parser + + extend self + + def parse_error() ::LibXML::XML::Error end + + def parse(xml) + node_to_hash(LibXML::XML::Parser.io(xml).parse.root) + end + + def each_child(node, &block) + node.each_child(&block) + end + + def each_attr(node, &block) + node.each_attr(&block) + end + + def node_name(node) + node.name + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/libxml2_parser.rb b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/libxml2_parser.rb new file mode 100644 index 0000000..f51fbf5 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/libxml2_parser.rb @@ -0,0 +1,66 @@ +module MultiXml + module Parsers + module Libxml2Parser #:nodoc: + # Convert XML document to hash + # + # node:: + # The XML node object to convert to a hash. + # + # hash:: + # Hash to merge the converted element into. + def node_to_hash(node, hash={}) + node_hash = {MultiXml::CONTENT_ROOT => ''} + + name = node_name(node) + + # Insert node hash into parent hash correctly. + case hash[name] + when Array then hash[name] << node_hash + when Hash then hash[name] = [hash[name], node_hash] + when nil then hash[name] = node_hash + end + + # Handle child elements + each_child(node) do |c| + if c.element? + node_to_hash(c, node_hash) + elsif c.text? || c.cdata? + node_hash[MultiXml::CONTENT_ROOT] << c.content + end + end + + # Remove content node if it is empty + if node_hash[MultiXml::CONTENT_ROOT].strip.empty? + node_hash.delete(MultiXml::CONTENT_ROOT) + end + + # Handle attributes + each_attr(node) {|a| node_hash[node_name(a)] = a.value } + + hash + end + + # Parse an XML Document IO into a simple hash. + # xml:: + # XML Document IO to parse + def parse(xml) + raise NotImplementedError, "inheritor should define #{__method__}" + end + + # :stopdoc: + private + + def each_child(*args) + raise NotImplementedError, "inheritor should define #{__method__}" + end + + def each_attr(*args) + raise NotImplementedError, "inheritor should define #{__method__}" + end + + def node_name(*args) + raise NotImplementedError, "inheritor should define #{__method__}" + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/nokogiri.rb b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/nokogiri.rb new file mode 100644 index 0000000..bb546ee --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/nokogiri.rb @@ -0,0 +1,32 @@ +require 'nokogiri' unless defined?(Nokogiri) +require 'multi_xml/parsers/libxml2_parser' + +module MultiXml + module Parsers + module Nokogiri #:nodoc: + include Libxml2Parser + + extend self + + def parse_error() ::Nokogiri::XML::SyntaxError end + + def parse(xml) + doc = ::Nokogiri::XML(xml) + raise doc.errors.first if doc.errors.length > 0 + node_to_hash(doc.root) + end + + def each_child(node, &block) + node.children.each(&block) + end + + def each_attr(node, &block) + node.attribute_nodes.each(&block) + end + + def node_name(node) + node.node_name + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/ox.rb b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/ox.rb new file mode 100644 index 0000000..78d7643 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/ox.rb @@ -0,0 +1,97 @@ +require 'ox' unless defined?(Ox) + +# Each MultiXml parser is expected to parse an XML document into a Hash. The +# conversion rules are: +# +# - Each document starts out as an empty Hash. +# +# - Reading an element created an entry in the parent Hash that has a key of +# the element name and a value of a Hash with attributes as key value +# pairs. Children are added as described by this rule. +# +# - Text and CDATE is stored in the parent element Hash with a key of +# '__content__' and a value of the text itself. +# +# - If a key already exists in the Hash then the value associated with the key +# is converted to an Array with the old and new value in it. +# +# - Other elements such as the xml prolog, doctype, and comments are ignored. +# + +module MultiXml + module Parsers + module Ox #:nodoc: + + extend self + + def parse_error + Exception + end + + def parse(io) + handler = Handler.new + ::Ox.sax_parse(handler, io, :convert_special => true) + handler.doc + end + + class Handler + attr_accessor :stack + + def initialize() + @stack = [] + end + + def doc + @stack[0] + end + + def attr(name, value) + unless @stack.empty? + append(name, value) + end + end + + def text(value) + append('__content__', value) + end + + def cdata(value) + append('__content__', value) + end + + def start_element(name) + if @stack.empty? + @stack.push(Hash.new) + end + h = Hash.new + append(name, h) + @stack.push(h) + end + + def end_element(name) + @stack.pop() + end + + def error(message, line, column) + raise Exception.new("#{message} at #{line}:#{column}") + end + + def append(key, value) + key = key.to_s + h = @stack.last + if h.has_key?(key) + v = h[key] + if v.is_a?(Array) + v << value + else + h[key] = [v, value] + end + else + h[key] = value + end + end + + end # Handler + end # Ox + end # Parsers +end # MultiXml diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/rexml.rb b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/rexml.rb new file mode 100644 index 0000000..2713c89 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/parsers/rexml.rb @@ -0,0 +1,113 @@ +require 'rexml/document' unless defined?(REXML::Document) + +module MultiXml + module Parsers + module Rexml #:nodoc: + extend self + def parse_error; ::REXML::ParseException; end + + # Parse an XML Document IO into a simple hash using REXML + # + # xml:: + # XML Document IO to parse + def parse(xml) + doc = REXML::Document.new(xml) + if doc.root + merge_element!({}, doc.root) + else + raise REXML::ParseException, "The document #{doc.to_s.inspect} does not have a valid root" + end + end + + private + + # Convert an XML element and merge into the hash + # + # hash:: + # Hash to merge the converted element into. + # element:: + # XML element to merge into hash + def merge_element!(hash, element) + merge!(hash, element.name, collapse(element)) + end + + # Actually converts an XML document element into a data structure. + # + # element:: + # The document element to be collapsed. + def collapse(element) + hash = get_attributes(element) + + if element.has_elements? + element.each_element {|child| merge_element!(hash, child) } + merge_texts!(hash, element) unless empty_content?(element) + hash + else + merge_texts!(hash, element) + end + end + + # Merge all the texts of an element into the hash + # + # hash:: + # Hash to add the converted element to. + # element:: + # XML element whose texts are to me merged into the hash + def merge_texts!(hash, element) + unless element.has_text? + hash + else + # must use value to prevent double-escaping + texts = '' + element.texts.each { |t| texts << t.value } + merge!(hash, MultiXml::CONTENT_ROOT, texts) + end + end + + # Adds a new key/value pair to an existing Hash. If the key to be added + # already exists and the existing value associated with key is not + # an Array, it will be wrapped in an Array. Then the new value is + # appended to that Array. + # + # hash:: + # Hash to add key/value pair to. + # key:: + # Key to be added. + # value:: + # Value to be associated with key. + def merge!(hash, key, value) + if hash.has_key?(key) + if hash[key].instance_of?(Array) + hash[key] << value + else + hash[key] = [hash[key], value] + end + elsif value.instance_of?(Array) + hash[key] = [value] + else + hash[key] = value + end + hash + end + + # Converts the attributes array of an XML element into a hash. + # Returns an empty Hash if node has no attributes. + # + # element:: + # XML element to extract attributes from. + def get_attributes(element) + attributes = {} + element.attributes.each { |n,v| attributes[n] = v } + attributes + end + + # Determines if a document element has text content + # + # element:: + # XML element to be checked. + def empty_content?(element) + element.texts.join.strip.empty? + end + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/version.rb b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/version.rb new file mode 100644 index 0000000..9a579cc --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/lib/multi_xml/version.rb @@ -0,0 +1,3 @@ +module MultiXml + VERSION = "0.5.1" +end diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/multi_xml.gemspec b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/multi_xml.gemspec new file mode 100644 index 0000000..fdaa804 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/multi_xml.gemspec @@ -0,0 +1,21 @@ +# encoding: utf-8 +require File.expand_path('../lib/multi_xml/version', __FILE__) + +Gem::Specification.new do |gem| + gem.add_development_dependency 'maruku' + gem.add_development_dependency 'rake' + gem.add_development_dependency 'rspec' + gem.add_development_dependency 'simplecov' + gem.add_development_dependency 'yard' + gem.author = "Erik Michaels-Ober" + gem.description = %q{A gem to provide swappable XML backends utilizing LibXML, Nokogiri, Ox, or REXML.} + gem.email = 'sferik@gmail.com' + gem.files = `git ls-files`.split("\n") + gem.homepage = 'https://github.com/sferik/multi_xml' + gem.name = 'multi_xml' + gem.platform = Gem::Platform::RUBY + gem.require_paths = ['lib'] + gem.summary = %q{A generic swappable back-end for XML parsing} + gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") + gem.version = MultiXml::VERSION +end diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/helper.rb b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/helper.rb new file mode 100644 index 0000000..3e080ce --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/helper.rb @@ -0,0 +1,7 @@ +unless ENV['CI'] + require 'simplecov' + SimpleCov.start do + add_filter 'spec' + end +end +require 'multi_xml' diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/multi_xml_spec.rb b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/multi_xml_spec.rb new file mode 100644 index 0000000..782325c --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/multi_xml_spec.rb @@ -0,0 +1,46 @@ +require 'helper' +require 'parser_shared_example' + +class MockDecoder; end + +describe "MultiXml" do + context "Parsers" do + it "should pick a default parser" do + MultiXml.parser.should be_kind_of(Module) + MultiXml.parser.should respond_to(:parse) + end + + it "should default to the best available gem" do + pending + MultiXml.parser.name.should be == 'MultiXml::Parsers::Rexml' + require 'nokogiri' + MultiXml.parser.name.should be == 'MultiXml::Parsers::Nokogiri' + require 'libxml' + MultiXml.parser.name.should == 'MultiXml::Parsers::Libxml' + end + + it "should be settable via a symbol" do + MultiXml.parser = :nokogiri + MultiXml.parser.name.should == 'MultiXml::Parsers::Nokogiri' + end + + it "should be settable via a class" do + MultiXml.parser = MockDecoder + MultiXml.parser.name.should == 'MockDecoder' + end + end + + [['LibXML', 'libxml'], + ['REXML', 'rexml/document'], + ['Nokogiri', 'nokogiri'], + ['Ox', 'ox']].each do |parser| + begin + require parser.last + context "#{parser.first} parser" do + it_should_behave_like "a parser", parser.first + end + rescue LoadError => e + puts "Tests not run for #{parser.first} due to a LoadError" + end + end +end diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/parser_shared_example.rb b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/parser_shared_example.rb new file mode 100644 index 0000000..86e0ec9 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/parser_shared_example.rb @@ -0,0 +1,677 @@ +shared_examples_for "a parser" do |parser| + + before do + begin + MultiXml.parser = parser + rescue LoadError + pending "Parser #{parser} couldn't be loaded" + end + end + + describe ".parse" do + context "a blank string" do + before do + @xml = '' + end + + it "should return an empty Hash" do + MultiXml.parse(@xml).should == {} + end + end + + context "a whitespace string" do + before do + @xml = ' ' + end + + it "should return an empty Hash" do + MultiXml.parse(@xml).should == {} + end + end + + context "an invalid XML document" do + before do + @xml = '' + end + + it "should raise MultiXml::ParseError" do + lambda do + MultiXml.parse(@xml) + end.should raise_error(MultiXml::ParseError) + end + end + + context "a valid XML document" do + before do + @xml = '' + end + + it "should parse correctly" do + MultiXml.parse(@xml).should == {'user' => nil} + end + + context "with CDATA" do + before do + @xml = '' + end + + it "should return the correct CDATA" do + MultiXml.parse(@xml)['user'].should == "Erik Michaels-Ober" + end + end + + context "with content" do + before do + @xml = 'Erik Michaels-Ober' + end + + it "should return the correct content" do + MultiXml.parse(@xml)['user'].should == "Erik Michaels-Ober" + end + end + + context "with an attribute" do + before do + @xml = '' + end + + it "should return the correct attribute" do + MultiXml.parse(@xml)['user']['name'].should == "Erik Michaels-Ober" + end + end + + context "with multiple attributes" do + before do + @xml = '' + end + + it "should return the correct attributes" do + MultiXml.parse(@xml)['user']['name'].should be == "Erik Michaels-Ober" + MultiXml.parse(@xml)['user']['screen_name'].should be == "sferik" + end + end + + context "with :symbolize_keys => true" do + before do + @xml = 'Erik Michaels-Ober' + end + + it "should symbolize keys" do + MultiXml.parse(@xml, :symbolize_keys => true).should == {:user => {:name => "Erik Michaels-Ober"}} + end + end + + context "when value is true" do + before do + pending + @xml = 'true' + end + + it "should return true" do + MultiXml.parse(@xml)['tag'].should be_true + end + end + + context "when value is false" do + before do + pending + @xml = 'false' + end + + it "should return false" do + MultiXml.parse(@xml)['tag'].should be_false + end + end + + context "when key is id" do + before do + pending + @xml = '1' + end + + it "should return a Fixnum" do + MultiXml.parse(@xml)['id'].should be_a(Fixnum) + end + + it "should return the correct number" do + MultiXml.parse(@xml)['id'].should == 1 + end + end + + context "when key contains _id" do + before do + pending + @xml = '1' + end + + it "should return a Fixnum" do + MultiXml.parse(@xml)['tag_id'].should be_a(Fixnum) + end + + it "should return the correct number" do + MultiXml.parse(@xml)['tag_id'].should == 1 + end + end + + context "with an attribute type=\"boolean\"" do + %w(true false).each do |boolean| + context "when #{boolean}" do + it "should return #{boolean}" do + xml = "#{boolean}" + MultiXml.parse(xml)['tag'].should instance_eval("be_#{boolean}") + end + end + end + + context "when 1" do + before do + @xml = '1' + end + + it "should return true" do + MultiXml.parse(@xml)['tag'].should be_true + end + end + + context "when 0" do + before do + @xml = '0' + end + + it "should return false" do + MultiXml.parse(@xml)['tag'].should be_false + end + end + end + + context "with an attribute type=\"integer\"" do + context "with a positive integer" do + before do + @xml = '1' + end + + it "should return a Fixnum" do + MultiXml.parse(@xml)['tag'].should be_a(Fixnum) + end + + it "should return a positive number" do + MultiXml.parse(@xml)['tag'].should > 0 + end + + it "should return the correct number" do + MultiXml.parse(@xml)['tag'].should == 1 + end + end + + context "with a negative integer" do + before do + @xml = '-1' + end + + it "should return a Fixnum" do + MultiXml.parse(@xml)['tag'].should be_a(Fixnum) + end + + it "should return a negative number" do + MultiXml.parse(@xml)['tag'].should < 0 + end + + it "should return the correct number" do + MultiXml.parse(@xml)['tag'].should == -1 + end + end + end + + context "with an attribute type=\"string\"" do + before do + @xml = '' + end + + it "should return a String" do + MultiXml.parse(@xml)['tag'].should be_a(String) + end + + it "should return the correct string" do + MultiXml.parse(@xml)['tag'].should == "" + end + end + + context "with an attribute type=\"date\"" do + before do + @xml = '1970-01-01' + end + + it "should return a Date" do + MultiXml.parse(@xml)['tag'].should be_a(Date) + end + + it "should return the correct date" do + MultiXml.parse(@xml)['tag'].should == Date.parse('1970-01-01') + end + end + + context "with an attribute type=\"datetime\"" do + before do + @xml = '1970-01-01 00:00' + end + + it "should return a Time" do + MultiXml.parse(@xml)['tag'].should be_a(Time) + end + + it "should return the correct time" do + MultiXml.parse(@xml)['tag'].should == Time.parse('1970-01-01 00:00') + end + end + + context "with an attribute type=\"dateTime\"" do + before do + @xml = '1970-01-01 00:00' + end + + it "should return a Time" do + MultiXml.parse(@xml)['tag'].should be_a(Time) + end + + it "should return the correct time" do + MultiXml.parse(@xml)['tag'].should == Time.parse('1970-01-01 00:00') + end + end + + context "with an attribute type=\"double\"" do + before do + @xml = '3.14159265358979' + end + + it "should return a Float" do + MultiXml.parse(@xml)['tag'].should be_a(Float) + end + + it "should return the correct number" do + MultiXml.parse(@xml)['tag'].should == 3.14159265358979 + end + end + + context "with an attribute type=\"decimal\"" do + before do + @xml = '3.14159265358979' + end + + it "should return a BigDecimal" do + MultiXml.parse(@xml)['tag'].should be_a(BigDecimal) + end + + it "should return the correct number" do + MultiXml.parse(@xml)['tag'].should == 3.14159265358979 + end + end + + context "with an attribute type=\"base64Binary\"" do + before do + @xml = 'aW1hZ2UucG5n' + end + + it "should return a String" do + MultiXml.parse(@xml)['tag'].should be_a(String) + end + + it "should return the correct string" do + MultiXml.parse(@xml)['tag'].should == "image.png" + end + end + + context "with an attribute type=\"yaml\"" do + before do + @xml = "--- \n1: should return an integer\n:message: Have a nice day\narray: \n- should-have-dashes: true\n should_have_underscores: true\n" + end + + it "should return a Hash" do + MultiXml.parse(@xml)['tag'].should be_a(Hash) + end + + it "should return the correctly parsed YAML" do + MultiXml.parse(@xml)['tag'].should == {:message => "Have a nice day", 1 => "should return an integer", "array" => [{"should-have-dashes" => true, "should_have_underscores" => true}]} + end + end + + context "with an attribute type=\"file\"" do + before do + @xml = 'ZGF0YQ==' + end + + it "should return a StringIO" do + MultiXml.parse(@xml)['tag'].should be_a(StringIO) + end + + it "should be decoded correctly" do + MultiXml.parse(@xml)['tag'].string.should == 'data' + end + + it "should have the correct file name" do + MultiXml.parse(@xml)['tag'].original_filename.should == 'data.txt' + end + + it "should have the correct content type" do + MultiXml.parse(@xml)['tag'].content_type.should == 'text/plain' + end + + context "with missing name and content type" do + before do + @xml = 'ZGF0YQ==' + end + + it "should return a StringIO" do + MultiXml.parse(@xml)['tag'].should be_a(StringIO) + end + + it "should be decoded correctly" do + MultiXml.parse(@xml)['tag'].string.should == 'data' + end + + it "should have the default file name" do + MultiXml.parse(@xml)['tag'].original_filename.should == 'untitled' + end + + it "should have the default content type" do + MultiXml.parse(@xml)['tag'].content_type.should == 'application/octet-stream' + end + end + end + + context "with an attribute type=\"array\"" do + before do + @xml = 'Erik Michaels-OberWynn Netherland' + end + + it "should return an Array" do + MultiXml.parse(@xml)['users'].should be_a(Array) + end + + it "should return the correct array" do + MultiXml.parse(@xml)['users'].should == ["Erik Michaels-Ober", "Wynn Netherland"] + end + end + + context "with an attribute type=\"array\" in addition to other attributes" do + before do + @xml = 'Erik Michaels-OberWynn Netherland' + end + + it "should return an Array" do + MultiXml.parse(@xml)['users'].should be_a(Array) + end + + it "should return the correct array" do + MultiXml.parse(@xml)['users'].should == ["Erik Michaels-Ober", "Wynn Netherland"] + end + end + + context "with an attribute type=\"array\" containing only one item" do + before do + @xml = 'Erik Michaels-Ober' + end + + it "should return an Array" do + MultiXml.parse(@xml)['users'].should be_a(Array) + end + + it "should return the correct array" do + MultiXml.parse(@xml)['users'].should == ["Erik Michaels-Ober"] + end + end + + %w(integer boolean date datetime yaml file).each do |type| + context "with an empty attribute type=\"#{type}\"" do + before do + @xml = "" + end + + it "should return nil" do + MultiXml.parse(@xml)['tag'].should be_nil + end + end + end + + context "with an empty attribute type=\"array\"" do + before do + @xml = '' + end + + it "should return an empty Array" do + MultiXml.parse(@xml)['tag'].should == [] + end + + context "with whitespace" do + before do + @xml = ' ' + end + + it "should return an empty Array" do + MultiXml.parse(@xml)['tag'].should == [] + end + end + end + + context "with XML entities" do + before do + @xml_entities = { + "<" => "<", + ">" => ">", + '"' => """, + "'" => "'", + "&" => "&" + } + end + + context "in content" do + it "should return unescaped XML entities" do + @xml_entities.each do |key, value| + xml = "#{value}" + MultiXml.parse(xml)['tag'].should == key + end + end + end + + context "in attribute" do + it "should return unescaped XML entities" do + @xml_entities.each do |key, value| + xml = "" + MultiXml.parse(xml)['tag']['attribute'].should == key + end + end + end + end + + + context "with dasherized tag" do + before do + @xml = '' + end + + it "should return undasherize tag" do + MultiXml.parse(@xml).keys.should include('tag_1') + end + end + + context "with dasherized attribute" do + before do + @xml = '' + end + + it "should return undasherize attribute" do + MultiXml.parse(@xml)['tag'].keys.should include('attribute_1') + end + end + + context "with children" do + context "with attributes" do + before do + @xml = '' + end + + it "should return the correct attributes" do + MultiXml.parse(@xml)['users']['user']['name'].should == "Erik Michaels-Ober" + end + end + + context "with text" do + before do + @xml = 'Erik Michaels-Ober' + end + + it "should return the correct text" do + MultiXml.parse(@xml)['user']['name'].should == "Erik Michaels-Ober" + end + end + + context "with an unrecognized attribute type" do + before do + @xml = 'Erik Michaels-Ober' + end + + it "should pass through the type" do + MultiXml.parse(@xml)['user']['type'].should == 'admin' + end + end + + context "with attribute tags on content nodes" do + context "non 'type' attributes" do + before do + @xml = <<-XML + + 123 + 0.123 + + XML + @parsed_xml = MultiXml.parse(@xml) + end + + it "should add the attributes to the value hash" do + @parsed_xml['options']['value'][0]['__content__'].should == '123' + @parsed_xml['options']['value'][0]['currency'].should == 'USD' + @parsed_xml['options']['value'][1]['__content__'].should == '0.123' + @parsed_xml['options']['value'][1]['number'].should == 'percent' + end + end + + context "unrecognized type attributes" do + before do + @xml = <<-XML + + 123 + 0.123 + 123 + + XML + @parsed_xml = MultiXml.parse(@xml) + end + + it "should add the attributes to the value hash passing through the type" do + @parsed_xml['options']['value'][0]['__content__'].should == '123' + @parsed_xml['options']['value'][0]['type'].should == 'USD' + @parsed_xml['options']['value'][1]['__content__'].should == '0.123' + @parsed_xml['options']['value'][1]['type'].should == 'percent' + @parsed_xml['options']['value'][2]['__content__'].should == '123' + @parsed_xml['options']['value'][2]['currency'].should == 'USD' + end + end + + context "mixing attributes and non-attributes content nodes type attributes" do + before do + @xml = <<-XML + + 123 + 0.123 + 123 + + XML + @parsed_xml = MultiXml.parse(@xml) + end + + it "should add the attributes to the value hash passing through the type" do + @parsed_xml['options']['value'][0]['__content__'].should == '123' + @parsed_xml['options']['value'][0]['type'].should == 'USD' + @parsed_xml['options']['value'][1]['__content__'].should == '0.123' + @parsed_xml['options']['value'][1]['type'].should == 'percent' + @parsed_xml['options']['value'][2].should == '123' + end + end + + context "mixing recognized type attribute and non-type attributes on content nodes" do + before do + @xml = <<-XML + + 123 + + XML + @parsed_xml = MultiXml.parse(@xml) + end + + it "should add the the non-type attribute and remove the recognized type attribute and do the typecast" do + @parsed_xml['options']['value']['__content__'].should == 123 + @parsed_xml['options']['value']['number'].should == 'USD' + end + end + + context "mixing unrecognized type attribute and non-type attributes on content nodes" do + before do + @xml = <<-XML + + 123 + + XML + @parsed_xml = MultiXml.parse(@xml) + end + + it "should add the the non-type attributes and type attribute to the value hash" do + @parsed_xml['options']['value']['__content__'].should == '123' + @parsed_xml['options']['value']['number'].should == 'USD' + @parsed_xml['options']['value']['type'].should == 'currency' + end + end + end + + context "with newlines and whitespace" do + before do + @xml = <<-XML + + Erik Michaels-Ober + + XML + end + + it "should parse correctly" do + MultiXml.parse(@xml).should == {"user" => {"name" => "Erik Michaels-Ober"}} + end + end + + # Babies having babies + context "with children" do + before do + @xml = '' + end + + it "should parse correctly" do + MultiXml.parse(@xml).should == {"users" => {"user" => {"name" => "Erik Michaels-Ober", "status" => {"text" => "Hello"}}}} + end + end + end + + context "with sibling children" do + before do + @xml = 'Erik Michaels-OberWynn Netherland' + end + + it "should return an Array" do + MultiXml.parse(@xml)['users']['user'].should be_a(Array) + end + + it "should parse correctly" do + MultiXml.parse(@xml).should == {"users" => {"user" => ["Erik Michaels-Ober", "Wynn Netherland"]}} + end + end + + end + end + +end diff --git a/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/speed.rb b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/speed.rb new file mode 100755 index 0000000..284c2a3 --- /dev/null +++ b/vendor/ruby/1.9.1/gems/multi_xml-0.5.1/spec/speed.rb @@ -0,0 +1,63 @@ +#!/usr/bin/env ruby -wW1 + +$: << '.' +$: << '../lib' + +if __FILE__ == $0 + while (i = ARGV.index('-I')) + x,path = ARGV.slice!(i, 2) + $: << path + end +end + +require 'optparse' +require 'stringio' +require 'multi_xml' + +begin + require 'libxml' +rescue Exception => e +end +begin + require 'nokogiri' +rescue Exception => e +end +begin + require 'ox' +rescue Exception => e +end + +$verbose = 0 +$parsers = [] +$iter = 10 + +opts = OptionParser.new +opts.on("-v", "increase verbosity") { $verbose += 1 } +opts.on("-p", "--parser [String]", String, "parser to test") { |p| $parsers = [p] } +opts.on("-i", "--iterations [Int]", Integer, "iterations") { |i| $iter = i } +opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) } +files = opts.parse(ARGV) + +if $parsers.empty? + $parsers << 'libxml' if defined?(::LibXML) + $parsers << 'nokogiri' if defined?(::Nokogiri) + $parsers << 'ox' if defined?(::Ox) +end + +files.each do |filename| + times = { } + xml = File.read(filename) + $parsers.each do |p| + MultiXml.parser = p + start = Time.now + $iter.times do |i| + io = StringIO.new(xml) + MultiXml.parse(io) + end + dt = Time.now - start + times[p] = Time.now - start + end + times.each do |p,t| + puts "%8s took %0.3f seconds to parse %s %d times." % [p, t, filename, $iter] + end +end diff --git a/vendor/ruby/1.9.1/specifications/httparty-0.9.0.gemspec b/vendor/ruby/1.9.1/specifications/httparty-0.9.0.gemspec new file mode 100644 index 0000000..12f601c --- /dev/null +++ b/vendor/ruby/1.9.1/specifications/httparty-0.9.0.gemspec @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = "httparty" + s.version = "0.9.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["John Nunemaker", "Sandro Turriate"] + s.date = "2012-09-07" + s.description = "Makes http fun! Also, makes consuming restful web services dead easy." + s.email = ["nunemaker@gmail.com"] + s.executables = ["httparty"] + s.files = ["bin/httparty"] + s.homepage = "http://jnunemaker.github.com/httparty" + s.post_install_message = "When you HTTParty, you must party hard!" + s.require_paths = ["lib"] + s.rubygems_version = "1.8.10" + s.summary = "Makes http fun! Also, makes consuming restful web services dead easy." + + if s.respond_to? :specification_version then + s.specification_version = 3 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["~> 1.0"]) + s.add_runtime_dependency(%q, [">= 0"]) + else + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, [">= 0"]) + end + else + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, [">= 0"]) + end +end diff --git a/vendor/ruby/1.9.1/specifications/multi_json-1.4.0.gemspec b/vendor/ruby/1.9.1/specifications/multi_json-1.4.0.gemspec new file mode 100644 index 0000000..7bc79b9 --- /dev/null +++ b/vendor/ruby/1.9.1/specifications/multi_json-1.4.0.gemspec @@ -0,0 +1,41 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = "multi_json" + s.version = "1.4.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6") if s.respond_to? :required_rubygems_version= + s.authors = ["Michael Bleigh", "Josh Kalderimis", "Erik Michaels-Ober"] + s.date = "2012-11-30" + s.description = "A gem to provide easy switching between different JSON backends, including Oj, Yajl, the JSON gem (with C-extensions), the pure-Ruby JSON gem, and OkJson." + s.email = ["michael@intridea.com", "josh.kalderimis@gmail.com", "sferik@gmail.com"] + s.extra_rdoc_files = ["LICENSE.md", "README.md"] + s.files = ["LICENSE.md", "README.md"] + s.homepage = "http://github.com/intridea/multi_json" + s.licenses = ["MIT"] + s.rdoc_options = ["--charset=UTF-8"] + s.require_paths = ["lib"] + s.rubygems_version = "1.8.10" + s.summary = "A gem to provide swappable JSON backends." + + if s.respond_to? :specification_version then + s.specification_version = 3 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_development_dependency(%q, ["~> 0.9"]) + s.add_development_dependency(%q, ["~> 3.9"]) + s.add_development_dependency(%q, ["~> 2.6"]) + s.add_development_dependency(%q, ["~> 0.4"]) + else + s.add_dependency(%q, ["~> 0.9"]) + s.add_dependency(%q, ["~> 3.9"]) + s.add_dependency(%q, ["~> 2.6"]) + s.add_dependency(%q, ["~> 0.4"]) + end + else + s.add_dependency(%q, ["~> 0.9"]) + s.add_dependency(%q, ["~> 3.9"]) + s.add_dependency(%q, ["~> 2.6"]) + s.add_dependency(%q, ["~> 0.4"]) + end +end diff --git a/vendor/ruby/1.9.1/specifications/multi_xml-0.5.1.gemspec b/vendor/ruby/1.9.1/specifications/multi_xml-0.5.1.gemspec new file mode 100644 index 0000000..db74f1f --- /dev/null +++ b/vendor/ruby/1.9.1/specifications/multi_xml-0.5.1.gemspec @@ -0,0 +1,40 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = "multi_xml" + s.version = "0.5.1" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Erik Michaels-Ober"] + s.date = "2012-05-10" + s.description = "A gem to provide swappable XML backends utilizing LibXML, Nokogiri, Ox, or REXML." + s.email = "sferik@gmail.com" + s.homepage = "https://github.com/sferik/multi_xml" + s.require_paths = ["lib"] + s.rubygems_version = "1.8.10" + s.summary = "A generic swappable back-end for XML parsing" + + if s.respond_to? :specification_version then + s.specification_version = 3 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + else + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + end + else + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + end +end