ÿØÿà JFIF    ÿÛ „ ( %!1!%*+...983,7(-.- PK% ]k爹%specifications/ruby-lsapi-5.5.gemspecnu[# -*- encoding: utf-8 -*- # stub: ruby-lsapi 5.5 ruby lib # stub: ext/lsapi/extconf.rb Gem::Specification.new do |s| s.name = "ruby-lsapi".freeze s.version = "5.5" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["LiteSpeed Technologies Inc.".freeze] s.date = "2023-06-08" s.description = "This is a ruby extension for fast communication with LiteSpeed Web Server.".freeze s.email = "info@litespeedtech.com".freeze s.extensions = ["ext/lsapi/extconf.rb".freeze] s.extra_rdoc_files = ["README".freeze] s.files = ["README".freeze, "ext/lsapi/extconf.rb".freeze] s.homepage = "http://www.litespeedtech.com/".freeze s.rubygems_version = "3.0.3".freeze s.summary = "A ruby extension for fast communication with LiteSpeed Web Server.".freeze s.installed_by_version = "3.0.3" if s.respond_to? :installed_by_version end PK% ]2 %specifications/ruby-lsapi-5.6.gemspecnu[# -*- encoding: utf-8 -*- # stub: ruby-lsapi 5.6 ruby lib # stub: ext/lsapi/extconf.rb Gem::Specification.new do |s| s.name = "ruby-lsapi".freeze s.version = "5.6" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["LiteSpeed Technologies Inc.".freeze] s.date = "2024-01-22" s.description = "This is a ruby extension for fast communication with LiteSpeed Web Server.".freeze s.email = "info@litespeedtech.com".freeze s.extensions = ["ext/lsapi/extconf.rb".freeze] s.extra_rdoc_files = ["README".freeze] s.files = ["README".freeze, "ext/lsapi/extconf.rb".freeze] s.homepage = "http://www.litespeedtech.com/".freeze s.rubygems_version = "3.0.3.1".freeze s.summary = "A ruby extension for fast communication with LiteSpeed Web Server.".freeze s.installed_by_version = "3.0.3.1" if s.respond_to? :installed_by_version end PK% ]&"V44#specifications/xmlrpc-0.3.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: xmlrpc 0.3.0 ruby lib Gem::Specification.new do |s| s.name = "xmlrpc".freeze s.version = "0.3.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["SHIBATA Hiroshi".freeze] s.bindir = "exe".freeze s.date = "2017-02-16" s.description = "XMLRPC is a lightweight protocol that enables remote procedure calls over HTTP.".freeze s.email = ["hsbt@ruby-lang.org".freeze] s.homepage = "https://github.com/ruby/xmlrpc".freeze s.licenses = ["Ruby".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "XMLRPC is a lightweight protocol that enables remote procedure calls over HTTP.".freeze s.installed_by_version = "3.0.3.1" if s.respond_to? :installed_by_version if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]Cض#specifications/rackup-2.1.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: rackup 2.1.0 ruby lib Gem::Specification.new do |s| s.name = "rackup".freeze s.version = "2.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Samuel Williams".freeze, "Jeremy Evans".freeze] s.date = "2023-01-27" s.executables = ["rackup".freeze] s.files = ["bin/rackup".freeze] s.homepage = "https://github.com/rack/rackup".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.4.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "A general server command for Rack applications.".freeze s.installed_by_version = "3.0.3.1" if s.respond_to? :installed_by_version if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q.freeze, [">= 3"]) s.add_runtime_dependency(%q.freeze, ["~> 1.8"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, ["~> 5.0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 3"]) s.add_dependency(%q.freeze, ["~> 1.8"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, ["~> 5.0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 3"]) s.add_dependency(%q.freeze, ["~> 1.8"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, ["~> 5.0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]R'specifications/net-telnet-0.2.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: net-telnet 0.2.0 ruby lib Gem::Specification.new do |s| s.name = "net-telnet".freeze s.version = "0.2.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["SHIBATA Hiroshi".freeze] s.bindir = "exe".freeze s.date = "2018-07-25" s.description = "Provides telnet client functionality.".freeze s.email = ["hsbt@ruby-lang.org".freeze] s.homepage = "https://github.com/ruby/net-telnet".freeze s.licenses = ["ruby".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Provides telnet client functionality.".freeze s.installed_by_version = "3.0.3.1" if s.respond_to? :installed_by_version if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]8~)specifications/did_you_mean-1.3.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: did_you_mean 1.3.0 ruby lib Gem::Specification.new do |s| s.name = "did_you_mean".freeze s.version = "1.3.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Yuki Nishijima".freeze] s.date = "2018-12-18" s.description = "The gem that has been saving people from typos since 2014.".freeze s.email = ["mail@yukinishijima.net".freeze] s.homepage = "https://github.com/yuki24/did_you_mean".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.5.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "\"Did you mean?\" experience in Ruby".freeze s.installed_by_version = "3.0.3.1" if s.respond_to? :installed_by_version if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]Vk&specifications/minitest-5.11.3.gemspecnu[# -*- encoding: utf-8 -*- # stub: minitest 5.11.3 ruby lib Gem::Specification.new do |s| s.name = "minitest".freeze s.version = "5.11.3" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Ryan Davis".freeze] s.cert_chain = ["-----BEGIN CERTIFICATE-----\nMIIDPjCCAiagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBFMRMwEQYDVQQDDApyeWFu\nZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB\nGRYDY29tMB4XDTE3MTEyMTIxMTExMFoXDTE4MTEyMTIxMTExMFowRTETMBEGA1UE\nAwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS\nJomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda\nb9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx\ntaCPaLmfYIaFcHHCSY4hYDJijRQkLxPeB3xbOfzfLoBDbjvx5JxgJxUjmGa7xhcT\noOvjtt5P8+GSK9zLzxQP0gVLS/D0FmoE44XuDr3iQkVS2ujU5zZL84mMNqNB1znh\nGiadM9GHRaDiaxuX0cIUBj19T01mVE2iymf9I6bEsiayK/n6QujtyCbTWsAS9Rqt\nqhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV\ngBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw\nHQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBBQUAA4IB\nAQAfAXSQpsW7YSxd1csRtA/M4Zt0AMXFMd76GJ8Lgtg8G0+VFbdChRyDuDb0kPlW\nh9QQX/YABfCW8vxmssbMGrP+VGBAn7BbdTcfTlgCWrvMX1uL5aRL74nA4urKXqdW\na0nP70K4958P3GffBdtE3KGkU5xstFnXGajxuBRnL66E15KU0BNehVxdG258bdPu\nEKN6MqBPftFiev3tuwqDV11r2GquDpniYcT+Mi8/PgeAgVT/afBeVgbB3KaZeTRR\nAhXhF6Wi2GTMezlj5jlI5XV7WsJUSwTp/YiVvcmT74ZaCRvexm6EnNhkrvJJ1Xeu\nV+HB+LYYhXWitInO/eXxDrFB\n-----END CERTIFICATE-----\n".freeze] s.date = "2018-01-26" s.description = "minitest provides a complete suite of testing facilities supporting\nTDD, BDD, mocking, and benchmarking.\n\n \"I had a class with Jim Weirich on testing last week and we were\n allowed to choose our testing frameworks. Kirk Haines and I were\n paired up and we cracked open the code for a few test\n frameworks...\n\n I MUST say that minitest is *very* readable / understandable\n compared to the 'other two' options we looked at. Nicely done and\n thank you for helping us keep our mental sanity.\"\n\n -- Wayne E. Seguin\n\nminitest/test is a small and incredibly fast unit testing framework.\nIt provides a rich set of assertions to make your tests clean and\nreadable.\n\nminitest/spec is a functionally complete spec engine. It hooks onto\nminitest/test and seamlessly bridges test assertions over to spec\nexpectations.\n\nminitest/benchmark is an awesome way to assert the performance of your\nalgorithms in a repeatable manner. Now you can assert that your newb\nco-worker doesn't replace your linear algorithm with an exponential\none!\n\nminitest/mock by Steven Baker, is a beautifully tiny mock (and stub)\nobject framework.\n\nminitest/pride shows pride in testing and adds coloring to your test\noutput. I guess it is an example of how to write IO pipes too. :P\n\nminitest/test is meant to have a clean implementation for language\nimplementors that need a minimal set of methods to bootstrap a working\ntest suite. For example, there is no magic involved for test-case\ndiscovery.\n\n \"Again, I can't praise enough the idea of a testing/specing\n framework that I can actually read in full in one sitting!\"\n\n -- Piotr Szotkowski\n\nComparing to rspec:\n\n rspec is a testing DSL. minitest is ruby.\n\n -- Adam Hawkins, \"Bow Before MiniTest\"\n\nminitest doesn't reinvent anything that ruby already provides, like:\nclasses, modules, inheritance, methods. This means you only have to\nlearn ruby to use minitest and all of your regular OO practices like\nextract-method refactorings still apply.".freeze s.email = ["ryand-ruby@zenspider.com".freeze] s.extra_rdoc_files = ["History.rdoc".freeze, "Manifest.txt".freeze, "README.rdoc".freeze] s.files = ["History.rdoc".freeze, "Manifest.txt".freeze, "README.rdoc".freeze] s.homepage = "https://github.com/seattlerb/minitest".freeze s.licenses = ["MIT".freeze] s.rdoc_options = ["--main".freeze, "README.rdoc".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "minitest provides a complete suite of testing facilities supporting TDD, BDD, mocking, and benchmarking".freeze s.installed_by_version = "3.0.3.1" if s.respond_to? :installed_by_version if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, ["~> 4.0"]) s.add_development_dependency(%q.freeze, ["~> 3.16"]) else s.add_dependency(%q.freeze, ["~> 4.0"]) s.add_dependency(%q.freeze, ["~> 3.16"]) end else s.add_dependency(%q.freeze, ["~> 4.0"]) s.add_dependency(%q.freeze, ["~> 3.16"]) end end PK% ]Z )specifications/power_assert-1.1.3.gemspecnu[# -*- encoding: utf-8 -*- # stub: power_assert 1.1.3 ruby lib Gem::Specification.new do |s| s.name = "power_assert".freeze s.version = "1.1.3" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Kazuki Tsujimoto".freeze] s.bindir = "exe".freeze s.date = "2018-06-24" s.description = "Power Assert for Ruby. Power Assert shows each value of variables and method calls in the expression. It is useful for testing, providing which value wasn't correct when the condition is not satisfied.".freeze s.email = ["kazuki@callcc.net".freeze] s.extra_rdoc_files = ["README.rdoc".freeze] s.files = ["README.rdoc".freeze] s.homepage = "https://github.com/k-tsj/power_assert".freeze s.licenses = ["2-clause BSDL".freeze, "Ruby's".freeze] s.rdoc_options = ["--main".freeze, "README.rdoc".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "Power Assert for Ruby".freeze s.installed_by_version = "3.0.3.1" if s.respond_to? :installed_by_version if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]"  ,specifications/default/openssl-2.1.2.gemspecnu[# -*- encoding: utf-8 -*- # stub: openssl 2.1.2 ruby lib # stub: ext/openssl/extconf.rb Gem::Specification.new do |s| s.name = "openssl".freeze s.version = "2.1.2" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "msys2_mingw_dependencies" => "openssl" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Martin Bosslet".freeze, "SHIBATA Hiroshi".freeze, "Zachary Scott".freeze, "Kazuki Yamaguchi".freeze] s.date = "2018-10-17" s.description = "It wraps the OpenSSL library.".freeze s.email = ["ruby-core@ruby-lang.org".freeze] s.extensions = ["ext/openssl/extconf.rb".freeze] s.extra_rdoc_files = ["README.md".freeze, "CONTRIBUTING.md".freeze, "History.md".freeze] s.files = ["CONTRIBUTING.md".freeze, "History.md".freeze, "README.md".freeze, "ext/openssl/extconf.rb".freeze, "openssl.rb".freeze, "openssl.so".freeze, "openssl/bn.rb".freeze, "openssl/buffering.rb".freeze, "openssl/cipher.rb".freeze, "openssl/config.rb".freeze, "openssl/digest.rb".freeze, "openssl/pkcs5.rb".freeze, "openssl/pkey.rb".freeze, "openssl/ssl.rb".freeze, "openssl/x509.rb".freeze] s.homepage = "https://github.com/ruby/openssl".freeze s.licenses = ["Ruby".freeze] s.rdoc_options = ["--main".freeze, "README.md".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "OpenSSL provides SSL, TLS and general purpose cryptography.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, ["~> 3.0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, ["~> 3.0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, ["~> 3.0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]!j(specifications/default/shell-0.7.gemspecnu[# -*- encoding: utf-8 -*- # stub: shell 0.7 ruby lib Gem::Specification.new do |s| s.name = "shell".freeze s.version = "0.7" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Keiju ISHITSUKA".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "An idiomatic Ruby interface for common UNIX shell commands.".freeze s.email = ["keiju@ruby-lang.org".freeze] s.files = ["shell.rb".freeze, "shell/builtin-command.rb".freeze, "shell/command-processor.rb".freeze, "shell/error.rb".freeze, "shell/filter.rb".freeze, "shell/process-controller.rb".freeze, "shell/system-command.rb".freeze, "shell/version.rb".freeze] s.homepage = "https://github.com/ruby/shell".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "An idiomatic Ruby interface for common UNIX shell commands.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]+specifications/default/e2mmap-0.1.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: e2mmap 0.1.0 ruby lib Gem::Specification.new do |s| s.name = "e2mmap".freeze s.version = "0.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Keiju ISHITSUKA".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Module for defining custom exceptions with specific messages.".freeze s.email = ["keiju@ruby-lang.org".freeze] s.files = ["e2mmap.rb".freeze] s.homepage = "https://github.com/ruby/e2mmap".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "Module for defining custom exceptions with specific messages.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, ["~> 1.16"]) s.add_development_dependency(%q.freeze, ["~> 10.0"]) else s.add_dependency(%q.freeze, ["~> 1.16"]) s.add_dependency(%q.freeze, ["~> 10.0"]) end else s.add_dependency(%q.freeze, ["~> 1.16"]) s.add_dependency(%q.freeze, ["~> 10.0"]) end end PK% ]"+specifications/default/logger-1.3.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: logger 1.3.0 ruby lib Gem::Specification.new do |s| s.name = "logger".freeze s.version = "1.3.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["SHIBATA Hiroshi".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Provides a simple logging utility for outputting messages.".freeze s.email = ["hsbt@ruby-lang.org".freeze] s.files = ["logger.rb".freeze] s.homepage = "https://github.com/ruby/logger".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "Provides a simple logging utility for outputting messages.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, ["~> 1.16"]) s.add_development_dependency(%q.freeze, ["~> 10.0"]) s.add_development_dependency(%q.freeze, ["~> 5.0"]) else s.add_dependency(%q.freeze, ["~> 1.16"]) s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, ["~> 5.0"]) end else s.add_dependency(%q.freeze, ["~> 1.16"]) s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, ["~> 5.0"]) end end PK% ]h`Ho o )specifications/default/json-2.1.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: json 2.1.0 ruby lib # stub: ext/json/ext/generator/extconf.rbext/json/ext/parser/extconf.rbext/json/extconf.rb Gem::Specification.new do |s| s.name = "json".freeze s.version = "2.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Florian Frank".freeze] s.date = "2017-04-18" s.description = "This is a JSON implementation as a Ruby extension in C.".freeze s.email = "flori@ping.de".freeze s.extensions = ["ext/json/ext/generator/extconf.rb".freeze, "ext/json/ext/parser/extconf.rb".freeze, "ext/json/extconf.rb".freeze] s.extra_rdoc_files = ["README.md".freeze] s.files = ["./tests/test_helper.rb".freeze, "README.md".freeze, "ext/json/ext/generator/extconf.rb".freeze, "ext/json/ext/parser/extconf.rb".freeze, "ext/json/extconf.rb".freeze, "json.rb".freeze, "json/add/bigdecimal.rb".freeze, "json/add/complex.rb".freeze, "json/add/core.rb".freeze, "json/add/date.rb".freeze, "json/add/date_time.rb".freeze, "json/add/exception.rb".freeze, "json/add/ostruct.rb".freeze, "json/add/range.rb".freeze, "json/add/rational.rb".freeze, "json/add/regexp.rb".freeze, "json/add/struct.rb".freeze, "json/add/symbol.rb".freeze, "json/add/time.rb".freeze, "json/common.rb".freeze, "json/ext.rb".freeze, "json/ext/generator.so".freeze, "json/ext/parser.so".freeze, "json/generic_object.rb".freeze, "json/version.rb".freeze] s.homepage = "http://flori.github.com/json".freeze s.licenses = ["Ruby".freeze] s.rdoc_options = ["--title".freeze, "JSON implemention for Ruby".freeze, "--main".freeze, "README.md".freeze] s.required_ruby_version = Gem::Requirement.new(">= 1.9".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "JSON Implementation for Ruby".freeze s.test_files = ["./tests/test_helper.rb".freeze] if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, ["~> 2.0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, ["~> 2.0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, ["~> 2.0"]) end end PK% ]-)specifications/default/gdbm-2.0.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: gdbm 2.0.0 ruby lib # stub: ext/gdbm/extconf.rb Gem::Specification.new do |s| s.name = "gdbm".freeze s.version = "2.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Yukihiro Matsumoto".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Ruby extension for GNU dbm.".freeze s.email = ["matz@ruby-lang.org".freeze] s.extensions = ["ext/gdbm/extconf.rb".freeze] s.files = ["ext/gdbm/extconf.rb".freeze, "gdbm.so".freeze] s.homepage = "https://github.com/ruby/gdbm".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Ruby extension for GNU dbm.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, ["~> 1.14"]) s.add_development_dependency(%q.freeze, ["~> 10.0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, ["~> 1.14"]) s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, ["~> 1.14"]) s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]C6j+specifications/default/ipaddr-1.2.2.gemspecnu[# -*- encoding: utf-8 -*- # stub: ipaddr 1.2.2 ruby lib Gem::Specification.new do |s| s.name = "ipaddr".freeze s.version = "1.2.2" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Akinori MUSHA".freeze, "Hajimu UMEMOTO".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "IPAddr provides a set of methods to manipulate an IP address.\nBoth IPv4 and IPv6 are supported.\n".freeze s.email = ["knu@idaemons.org".freeze, "ume@mahoroba.org".freeze] s.files = ["ipaddr.rb".freeze] s.homepage = "https://github.com/ruby/ipaddr".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "A class to manipulate an IP address in ruby".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, ["~> 1.15"]) s.add_development_dependency(%q.freeze, ["~> 10.0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, ["~> 1.15"]) s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, ["~> 1.15"]) s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]`P<<+specifications/default/matrix-0.1.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: matrix 0.1.0 ruby lib Gem::Specification.new do |s| s.name = "matrix".freeze s.version = "0.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Marc-Andre Lafortune".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "An implementation of Matrix and Vector classes.".freeze s.email = ["ruby-core@marc-andre.ca".freeze] s.files = ["matrix.rb".freeze, "matrix/eigenvalue_decomposition.rb".freeze, "matrix/lup_decomposition.rb".freeze] s.homepage = "https://github.com/ruby/matrix".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "An implementation of Matrix and Vector classes.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]:9gff*specifications/default/fcntl-1.0.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: fcntl 1.0.0 ruby lib # stub: ext/fcntl/extconf.rb Gem::Specification.new do |s| s.name = "fcntl".freeze s.version = "1.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Yukihiro Matsumoto".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Loads constants defined in the OS fcntl.h C header file".freeze s.email = ["matz@ruby-lang.org".freeze] s.extensions = ["ext/fcntl/extconf.rb".freeze] s.files = ["ext/fcntl/extconf.rb".freeze, "fcntl.so".freeze] s.homepage = "https://github.com/ruby/fcntl".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Loads constants defined in the OS fcntl.h C header file".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, ["~> 1.14"]) s.add_development_dependency(%q.freeze, ["~> 12"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, ["~> 1.14"]) s.add_dependency(%q.freeze, ["~> 12"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, ["~> 1.14"]) s.add_dependency(%q.freeze, ["~> 12"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]L L (specifications/default/irb-1.0.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: irb 1.0.0 ruby lib Gem::Specification.new do |s| s.name = "irb".freeze s.version = "1.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Keiju ISHITSUKA".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Interactive Ruby command-line tool for REPL (Read Eval Print Loop).".freeze s.email = ["keiju@ruby-lang.org".freeze] s.executables = ["irb".freeze] s.files = ["exe/irb".freeze, "irb.rb".freeze, "irb/cmd/chws.rb".freeze, "irb/cmd/fork.rb".freeze, "irb/cmd/help.rb".freeze, "irb/cmd/load.rb".freeze, "irb/cmd/nop.rb".freeze, "irb/cmd/pushws.rb".freeze, "irb/cmd/subirb.rb".freeze, "irb/completion.rb".freeze, "irb/context.rb".freeze, "irb/ext/change-ws.rb".freeze, "irb/ext/history.rb".freeze, "irb/ext/loader.rb".freeze, "irb/ext/multi-irb.rb".freeze, "irb/ext/save-history.rb".freeze, "irb/ext/tracer.rb".freeze, "irb/ext/use-loader.rb".freeze, "irb/ext/workspaces.rb".freeze, "irb/extend-command.rb".freeze, "irb/frame.rb".freeze, "irb/help.rb".freeze, "irb/init.rb".freeze, "irb/input-method.rb".freeze, "irb/inspector.rb".freeze, "irb/lc/error.rb".freeze, "irb/lc/ja/encoding_aliases.rb".freeze, "irb/lc/ja/error.rb".freeze, "irb/locale.rb".freeze, "irb/magic-file.rb".freeze, "irb/notifier.rb".freeze, "irb/output-method.rb".freeze, "irb/ruby-lex.rb".freeze, "irb/ruby-token.rb".freeze, "irb/slex.rb".freeze, "irb/src_encoding.rb".freeze, "irb/version.rb".freeze, "irb/workspace.rb".freeze, "irb/ws-for-case-2.rb".freeze, "irb/xmp.rb".freeze] s.homepage = "https://github.com/ruby/irb".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "Interactive Ruby command-line tool for REPL (Read Eval Print Loop).".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]D8 8 ,specifications/default/webrick-1.4.4.gemspecnu[# -*- encoding: utf-8 -*- # stub: webrick 1.4.4 ruby lib Gem::Specification.new do |s| s.name = "webrick".freeze s.version = "1.4.4" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "bug_tracker_uri" => "https://bugs.ruby-lang.org/projects/ruby-trunk/issues", "homepage_uri" => "https://www.ruby-lang.org", "source_code_uri" => "https://svn.ruby-lang.org/repos/ruby" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["TAKAHASHI Masayoshi".freeze, "GOTOU YUUZOU".freeze, "Eric Wong".freeze] s.date = "2023-07-26" s.description = "WEBrick is an HTTP server toolkit that can be configured as an HTTPS server, a proxy server, and a virtual-host server.".freeze s.email = [nil, nil, "normal@ruby-lang.org".freeze] s.files = ["webrick.rb".freeze, "webrick/accesslog.rb".freeze, "webrick/cgi.rb".freeze, "webrick/compat.rb".freeze, "webrick/config.rb".freeze, "webrick/cookie.rb".freeze, "webrick/htmlutils.rb".freeze, "webrick/httpauth.rb".freeze, "webrick/httpauth/authenticator.rb".freeze, "webrick/httpauth/basicauth.rb".freeze, "webrick/httpauth/digestauth.rb".freeze, "webrick/httpauth/htdigest.rb".freeze, "webrick/httpauth/htgroup.rb".freeze, "webrick/httpauth/htpasswd.rb".freeze, "webrick/httpauth/userdb.rb".freeze, "webrick/httpproxy.rb".freeze, "webrick/httprequest.rb".freeze, "webrick/httpresponse.rb".freeze, "webrick/https.rb".freeze, "webrick/httpserver.rb".freeze, "webrick/httpservlet.rb".freeze, "webrick/httpservlet/abstract.rb".freeze, "webrick/httpservlet/cgi_runner.rb".freeze, "webrick/httpservlet/cgihandler.rb".freeze, "webrick/httpservlet/erbhandler.rb".freeze, "webrick/httpservlet/filehandler.rb".freeze, "webrick/httpservlet/prochandler.rb".freeze, "webrick/httpstatus.rb".freeze, "webrick/httputils.rb".freeze, "webrick/httpversion.rb".freeze, "webrick/log.rb".freeze, "webrick/server.rb".freeze, "webrick/ssl.rb".freeze, "webrick/utils.rb".freeze, "webrick/version.rb".freeze] s.homepage = "https://www.ruby-lang.org".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "HTTP server toolkit".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]Q5tt*specifications/default/prime-0.1.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: prime 0.1.0 ruby lib Gem::Specification.new do |s| s.name = "prime".freeze s.version = "0.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Yuki Sonoda".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Prime numbers and factorization library.".freeze s.email = ["yugui@yugui.jp".freeze] s.files = ["prime.rb".freeze] s.homepage = "https://github.com/ruby/prime".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "Prime numbers and factorization library.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]@+specifications/default/thwait-0.1.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: thwait 0.1.0 ruby lib Gem::Specification.new do |s| s.name = "thwait".freeze s.version = "0.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Keiju ISHITSUKA".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Watches for termination of multiple threads.".freeze s.email = ["keiju@ruby-lang.org".freeze] s.files = ["thwait.rb".freeze, "thwait/version.rb".freeze] s.homepage = "https://github.com/ruby/thwait".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "Watches for termination of multiple threads.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, ["~> 1.16"]) s.add_development_dependency(%q.freeze, ["~> 10.0"]) else s.add_dependency(%q.freeze, ["~> 1.16"]) s.add_dependency(%q.freeze, ["~> 10.0"]) end else s.add_dependency(%q.freeze, ["~> 1.16"]) s.add_dependency(%q.freeze, ["~> 10.0"]) end end PK% ] : *specifications/default/psych-3.1.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: psych 3.1.0 ruby lib # stub: ext/psych/extconf.rb Gem::Specification.new do |s| s.name = "psych".freeze s.version = "3.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Aaron Patterson".freeze, "SHIBATA Hiroshi".freeze, "Charles Oliver Nutter".freeze] s.date = "2023-07-26" s.description = "Psych is a YAML parser and emitter. Psych leverages libyaml[https://pyyaml.org/wiki/LibYAML]\nfor its YAML parsing and emitting capabilities. In addition to wrapping libyaml,\nPsych also knows how to serialize and de-serialize most Ruby objects to and from the YAML format.\n".freeze s.email = ["aaron@tenderlovemaking.com".freeze, "hsbt@ruby-lang.org".freeze, "headius@headius.com".freeze] s.extensions = ["ext/psych/extconf.rb".freeze] s.extra_rdoc_files = ["CHANGELOG.rdoc".freeze, "README.md".freeze] s.files = ["CHANGELOG.rdoc".freeze, "README.md".freeze, "ext/psych/extconf.rb".freeze, "psych.rb".freeze, "psych.so".freeze, "psych/class_loader.rb".freeze, "psych/coder.rb".freeze, "psych/core_ext.rb".freeze, "psych/exception.rb".freeze, "psych/handler.rb".freeze, "psych/handlers/document_stream.rb".freeze, "psych/handlers/recorder.rb".freeze, "psych/json/ruby_events.rb".freeze, "psych/json/stream.rb".freeze, "psych/json/tree_builder.rb".freeze, "psych/json/yaml_events.rb".freeze, "psych/nodes.rb".freeze, "psych/nodes/alias.rb".freeze, "psych/nodes/document.rb".freeze, "psych/nodes/mapping.rb".freeze, "psych/nodes/node.rb".freeze, "psych/nodes/scalar.rb".freeze, "psych/nodes/sequence.rb".freeze, "psych/nodes/stream.rb".freeze, "psych/omap.rb".freeze, "psych/parser.rb".freeze, "psych/scalar_scanner.rb".freeze, "psych/set.rb".freeze, "psych/stream.rb".freeze, "psych/streaming.rb".freeze, "psych/syntax_error.rb".freeze, "psych/tree_builder.rb".freeze, "psych/versions.rb".freeze, "psych/visitors.rb".freeze, "psych/visitors/depth_first.rb".freeze, "psych/visitors/emitter.rb".freeze, "psych/visitors/json_tree.rb".freeze, "psych/visitors/to_ruby.rb".freeze, "psych/visitors/visitor.rb".freeze, "psych/visitors/yaml_tree.rb".freeze, "psych/y.rb".freeze] s.homepage = "https://github.com/ruby/psych".freeze s.licenses = ["MIT".freeze] s.rdoc_options = ["--main".freeze, "README.md".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.2.2".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Psych is a YAML parser and emitter".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0.4.1"]) s.add_development_dependency(%q.freeze, ["~> 5.0"]) s.add_development_dependency(%q.freeze, [">= 0.6.3"]) else s.add_dependency(%q.freeze, [">= 0.4.1"]) s.add_dependency(%q.freeze, ["~> 5.0"]) s.add_dependency(%q.freeze, [">= 0.6.3"]) end else s.add_dependency(%q.freeze, [">= 0.4.1"]) s.add_dependency(%q.freeze, ["~> 5.0"]) s.add_dependency(%q.freeze, [">= 0.6.3"]) end end PK% ]~b**-specifications/default/bundler-1.17.2.gemspecnu[# -*- encoding: utf-8 -*- # stub: bundler 1.17.2 ruby lib Gem::Specification.new do |s| s.name = "bundler".freeze s.version = "1.17.2" s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "bug_tracker_uri" => "http://github.com/bundler/bundler/issues", "changelog_uri" => "https://github.com/bundler/bundler/blob/master/CHANGELOG.md", "homepage_uri" => "https://bundler.io/", "source_code_uri" => "http://github.com/bundler/bundler/" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Andr\u00E9 Arko".freeze, "Samuel Giddins".freeze, "Colby Swandale".freeze, "Hiroshi Shibata".freeze, "David Rodr\u00EDguez".freeze, "Grey Baker".freeze, "Stephanie Morillo".freeze, "Chris Morris".freeze, "James Wen".freeze, "Tim Moore".freeze, "Andr\u00E9 Medeiros".freeze, "Jessica Lynn Suttles".freeze, "Terence Lee".freeze, "Carl Lerche".freeze, "Yehuda Katz".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably".freeze s.email = ["team@bundler.io".freeze] s.executables = ["bundle".freeze, "bundler".freeze] s.files = ["bundler.rb".freeze, "bundler/build_metadata.rb".freeze, "bundler/capistrano.rb".freeze, "bundler/cli.rb".freeze, "bundler/cli/add.rb".freeze, "bundler/cli/binstubs.rb".freeze, "bundler/cli/cache.rb".freeze, "bundler/cli/check.rb".freeze, "bundler/cli/clean.rb".freeze, "bundler/cli/common.rb".freeze, "bundler/cli/config.rb".freeze, "bundler/cli/console.rb".freeze, "bundler/cli/doctor.rb".freeze, "bundler/cli/exec.rb".freeze, "bundler/cli/gem.rb".freeze, "bundler/cli/info.rb".freeze, "bundler/cli/init.rb".freeze, "bundler/cli/inject.rb".freeze, "bundler/cli/install.rb".freeze, "bundler/cli/issue.rb".freeze, "bundler/cli/list.rb".freeze, "bundler/cli/lock.rb".freeze, "bundler/cli/open.rb".freeze, "bundler/cli/outdated.rb".freeze, "bundler/cli/package.rb".freeze, "bundler/cli/platform.rb".freeze, "bundler/cli/plugin.rb".freeze, "bundler/cli/pristine.rb".freeze, "bundler/cli/remove.rb".freeze, "bundler/cli/show.rb".freeze, "bundler/cli/update.rb".freeze, "bundler/cli/viz.rb".freeze, "bundler/compact_index_client.rb".freeze, "bundler/compact_index_client/cache.rb".freeze, "bundler/compact_index_client/updater.rb".freeze, "bundler/compatibility_guard.rb".freeze, "bundler/constants.rb".freeze, "bundler/current_ruby.rb".freeze, "bundler/definition.rb".freeze, "bundler/dep_proxy.rb".freeze, "bundler/dependency.rb".freeze, "bundler/deployment.rb".freeze, "bundler/deprecate.rb".freeze, "bundler/dsl.rb".freeze, "bundler/endpoint_specification.rb".freeze, "bundler/env.rb".freeze, "bundler/environment_preserver.rb".freeze, "bundler/errors.rb".freeze, "bundler/feature_flag.rb".freeze, "bundler/fetcher.rb".freeze, "bundler/fetcher/base.rb".freeze, "bundler/fetcher/compact_index.rb".freeze, "bundler/fetcher/dependency.rb".freeze, "bundler/fetcher/downloader.rb".freeze, "bundler/fetcher/index.rb".freeze, "bundler/friendly_errors.rb".freeze, "bundler/gem_helper.rb".freeze, "bundler/gem_helpers.rb".freeze, "bundler/gem_remote_fetcher.rb".freeze, "bundler/gem_tasks.rb".freeze, "bundler/gem_version_promoter.rb".freeze, "bundler/gemdeps.rb".freeze, "bundler/graph.rb".freeze, "bundler/index.rb".freeze, "bundler/injector.rb".freeze, "bundler/inline.rb".freeze, "bundler/installer.rb".freeze, "bundler/installer/gem_installer.rb".freeze, "bundler/installer/parallel_installer.rb".freeze, "bundler/installer/standalone.rb".freeze, "bundler/lazy_specification.rb".freeze, "bundler/lockfile_generator.rb".freeze, "bundler/lockfile_parser.rb".freeze, "bundler/match_platform.rb".freeze, "bundler/mirror.rb".freeze, "bundler/plugin.rb".freeze, "bundler/plugin/api.rb".freeze, "bundler/plugin/api/source.rb".freeze, "bundler/plugin/dsl.rb".freeze, "bundler/plugin/events.rb".freeze, "bundler/plugin/index.rb".freeze, "bundler/plugin/installer.rb".freeze, "bundler/plugin/installer/git.rb".freeze, "bundler/plugin/installer/rubygems.rb".freeze, "bundler/plugin/source_list.rb".freeze, "bundler/process_lock.rb".freeze, "bundler/psyched_yaml.rb".freeze, "bundler/remote_specification.rb".freeze, "bundler/resolver.rb".freeze, "bundler/resolver/spec_group.rb".freeze, "bundler/retry.rb".freeze, "bundler/ruby_dsl.rb".freeze, "bundler/ruby_version.rb".freeze, "bundler/rubygems_ext.rb".freeze, "bundler/rubygems_gem_installer.rb".freeze, "bundler/rubygems_integration.rb".freeze, "bundler/runtime.rb".freeze, "bundler/settings.rb".freeze, "bundler/settings/validator.rb".freeze, "bundler/setup.rb".freeze, "bundler/shared_helpers.rb".freeze, "bundler/similarity_detector.rb".freeze, "bundler/source.rb".freeze, "bundler/source/gemspec.rb".freeze, "bundler/source/git.rb".freeze, "bundler/source/git/git_proxy.rb".freeze, "bundler/source/metadata.rb".freeze, "bundler/source/path.rb".freeze, "bundler/source/path/installer.rb".freeze, "bundler/source/rubygems.rb".freeze, "bundler/source/rubygems/remote.rb".freeze, "bundler/source_list.rb".freeze, "bundler/spec_set.rb".freeze, "bundler/ssl_certs/certificate_manager.rb".freeze, "bundler/stub_specification.rb".freeze, "bundler/templates/gems.rb".freeze, "bundler/ui.rb".freeze, "bundler/ui/rg_proxy.rb".freeze, "bundler/ui/shell.rb".freeze, "bundler/ui/silent.rb".freeze, "bundler/uri_credentials_filter.rb".freeze, "bundler/vendor/fileutils/lib/fileutils.rb".freeze, "bundler/vendor/molinillo/lib/molinillo.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/compatibility.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/errors.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/modules/ui.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/resolution.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/resolver.rb".freeze, "bundler/vendor/molinillo/lib/molinillo/state.rb".freeze, "bundler/vendor/net-http-persistent/lib/net/http/faster.rb".freeze, "bundler/vendor/net-http-persistent/lib/net/http/persistent.rb".freeze, "bundler/vendor/net-http-persistent/lib/net/http/persistent/ssl_reuse.rb".freeze, "bundler/vendor/thor/lib/thor.rb".freeze, "bundler/vendor/thor/lib/thor/actions.rb".freeze, "bundler/vendor/thor/lib/thor/actions/create_file.rb".freeze, "bundler/vendor/thor/lib/thor/actions/create_link.rb".freeze, "bundler/vendor/thor/lib/thor/actions/directory.rb".freeze, "bundler/vendor/thor/lib/thor/actions/empty_directory.rb".freeze, "bundler/vendor/thor/lib/thor/actions/file_manipulation.rb".freeze, "bundler/vendor/thor/lib/thor/actions/inject_into_file.rb".freeze, "bundler/vendor/thor/lib/thor/base.rb".freeze, "bundler/vendor/thor/lib/thor/command.rb".freeze, "bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb".freeze, "bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb".freeze, "bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb".freeze, "bundler/vendor/thor/lib/thor/error.rb".freeze, "bundler/vendor/thor/lib/thor/group.rb".freeze, "bundler/vendor/thor/lib/thor/invocation.rb".freeze, "bundler/vendor/thor/lib/thor/line_editor.rb".freeze, "bundler/vendor/thor/lib/thor/line_editor/basic.rb".freeze, "bundler/vendor/thor/lib/thor/line_editor/readline.rb".freeze, "bundler/vendor/thor/lib/thor/parser.rb".freeze, "bundler/vendor/thor/lib/thor/parser/argument.rb".freeze, "bundler/vendor/thor/lib/thor/parser/arguments.rb".freeze, "bundler/vendor/thor/lib/thor/parser/option.rb".freeze, "bundler/vendor/thor/lib/thor/parser/options.rb".freeze, "bundler/vendor/thor/lib/thor/rake_compat.rb".freeze, "bundler/vendor/thor/lib/thor/runner.rb".freeze, "bundler/vendor/thor/lib/thor/shell.rb".freeze, "bundler/vendor/thor/lib/thor/shell/basic.rb".freeze, "bundler/vendor/thor/lib/thor/shell/color.rb".freeze, "bundler/vendor/thor/lib/thor/shell/html.rb".freeze, "bundler/vendor/thor/lib/thor/util.rb".freeze, "bundler/vendor/thor/lib/thor/version.rb".freeze, "bundler/vendored_fileutils.rb".freeze, "bundler/vendored_molinillo.rb".freeze, "bundler/vendored_persistent.rb".freeze, "bundler/vendored_thor.rb".freeze, "bundler/version.rb".freeze, "bundler/version_ranges.rb".freeze, "bundler/vlad.rb".freeze, "bundler/worker.rb".freeze, "bundler/yaml_serializer.rb".freeze, "exe/bundle".freeze, "exe/bundler".freeze] s.homepage = "http://bundler.io".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new(">= 1.8.7".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "The best way to manage your application's dependencies".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, ["~> 0.1.0"]) s.add_development_dependency(%q.freeze, ["= 0.99.6"]) s.add_development_dependency(%q.freeze, ["~> 10.0"]) s.add_development_dependency(%q.freeze, ["~> 2.2"]) s.add_development_dependency(%q.freeze, ["~> 0.7.3"]) s.add_development_dependency(%q.freeze, ["~> 3.6"]) else s.add_dependency(%q.freeze, ["~> 0.1.0"]) s.add_dependency(%q.freeze, ["= 0.99.6"]) s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, ["~> 2.2"]) s.add_dependency(%q.freeze, ["~> 0.7.3"]) s.add_dependency(%q.freeze, ["~> 3.6"]) end else s.add_dependency(%q.freeze, ["~> 0.1.0"]) s.add_dependency(%q.freeze, ["= 0.99.6"]) s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, ["~> 2.2"]) s.add_dependency(%q.freeze, ["~> 0.7.3"]) s.add_dependency(%q.freeze, ["~> 3.6"]) end end PK% ]Qli i /specifications/default/bigdecimal-1.4.1.gemspecnu[# -*- encoding: utf-8 -*- # stub: bigdecimal 1.4.1 ruby lib # stub: ext/bigdecimal/extconf.rbext/bigdecimal/util/extconf.rb Gem::Specification.new do |s| s.name = "bigdecimal".freeze s.version = "1.4.1" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Kenta Murata".freeze, "Zachary Scott".freeze, "Shigeo Kobayashi".freeze] s.date = "2023-07-26" s.description = "This library provides arbitrary-precision decimal floating-point number class.".freeze s.email = ["mrkn@mrkn.jp".freeze] s.extensions = ["ext/bigdecimal/extconf.rb".freeze, "ext/bigdecimal/util/extconf.rb".freeze] s.files = ["bigdecimal.rb".freeze, "bigdecimal.so".freeze, "bigdecimal/jacobian.rb".freeze, "bigdecimal/ludcmp.rb".freeze, "bigdecimal/math.rb".freeze, "bigdecimal/newton.rb".freeze, "bigdecimal/util.rb".freeze, "bigdecimal/util.so".freeze, "ext/bigdecimal/extconf.rb".freeze, "ext/bigdecimal/util/extconf.rb".freeze] s.homepage = "https://github.com/ruby/bigdecimal".freeze s.licenses = ["ruby".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Arbitrary-precision decimal floating-point number library.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, ["~> 10.0"]) s.add_development_dependency(%q.freeze, [">= 0.9"]) s.add_development_dependency(%q.freeze, [">= 0.6.1"]) s.add_development_dependency(%q.freeze, ["< 5.0.0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, [">= 0.9"]) s.add_dependency(%q.freeze, [">= 0.6.1"]) s.add_dependency(%q.freeze, ["< 5.0.0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, [">= 0.9"]) s.add_dependency(%q.freeze, [">= 0.6.1"]) s.add_dependency(%q.freeze, ["< 5.0.0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]5TA,specifications/default/strscan-1.0.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: strscan 1.0.0 ruby lib # stub: ext/strscan/extconf.rb Gem::Specification.new do |s| s.name = "strscan".freeze s.version = "1.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Minero Aoki".freeze] s.date = "2023-07-26" s.description = "Provides lexical scanning operations on a String.".freeze s.email = [nil] s.extensions = ["ext/strscan/extconf.rb".freeze] s.files = ["ext/strscan/extconf.rb".freeze, "strscan.so".freeze] s.homepage = "https://github.com/ruby/strscan".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.4.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Provides lexical scanning operations on a String.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) end end PK% ] ^)specifications/default/date-2.0.3.gemspecnu[# -*- encoding: utf-8 -*- # stub: date 2.0.3 ruby lib # stub: ext/date/extconf.rb Gem::Specification.new do |s| s.name = "date".freeze s.version = "2.0.3" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Tadayoshi Funaba".freeze] s.date = "2023-07-26" s.description = "A subclass of Object includes Comparable module for handling dates.".freeze s.email = [nil] s.extensions = ["ext/date/extconf.rb".freeze] s.files = ["date.rb".freeze, "ext/date/extconf.rb".freeze] s.homepage = "https://github.com/ruby/date".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.4.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "A subclass of Object includes Comparable module for handling dates.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) end end PK% ].440specifications/default/forwardable-1.2.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: forwardable 1.2.0 ruby lib Gem::Specification.new do |s| s.name = "forwardable".freeze s.version = "1.2.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Keiju ISHITSUKA".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Provides delegation of specified methods to a designated object.".freeze s.email = ["keiju@ruby-lang.org".freeze] s.files = ["forwardable.rb".freeze, "forwardable/impl.rb".freeze] s.homepage = "https://github.com/ruby/forwardable".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "Provides delegation of specified methods to a designated object.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]׷*specifications/default/cmath-1.0.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: cmath 1.0.0 ruby lib Gem::Specification.new do |s| s.name = "cmath".freeze s.version = "1.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Tadayoshi Funaba".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "CMath is a library that provides trigonometric and transcendental functions for complex numbers. The functions in this module accept integers, floating-point numbers or complex numbers as arguments.".freeze s.email = [nil] s.files = ["cmath.rb".freeze] s.homepage = "https://github.com/ruby/cmath".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Provides Trigonometric and Transcendental functions for complex numbers".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]@ 撛,specifications/default/mutex_m-0.1.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: mutex_m 0.1.0 ruby lib Gem::Specification.new do |s| s.name = "mutex_m".freeze s.version = "0.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Keiju ISHITSUKA".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Mixin to extend objects to be handled like a Mutex.".freeze s.email = ["keiju@ruby-lang.org".freeze] s.files = ["mutex_m.rb".freeze] s.homepage = "https://github.com/ruby/mutex_m".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "Mixin to extend objects to be handled like a Mutex.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]+specifications/default/fiddle-1.0.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: fiddle 1.0.0 ruby lib Gem::Specification.new do |s| s.name = "fiddle".freeze s.version = "1.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Aaron Patterson".freeze, "SHIBATA Hiroshi".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "A libffi wrapper for Ruby.".freeze s.email = ["aaron@tenderlovemaking.com".freeze, "hsbt@ruby-lang.org".freeze] s.files = ["fiddle.rb".freeze, "fiddle.so".freeze, "fiddle/closure.rb".freeze, "fiddle/cparser.rb".freeze, "fiddle/function.rb".freeze, "fiddle/import.rb".freeze, "fiddle/pack.rb".freeze, "fiddle/struct.rb".freeze, "fiddle/types.rb".freeze, "fiddle/value.rb".freeze] s.homepage = "https://github.com/ruby/fiddle".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "A libffi wrapper for Ruby.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ] o}})specifications/default/zlib-1.0.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: zlib 1.0.0 ruby lib # stub: ext/zlib/extconf.rb Gem::Specification.new do |s| s.name = "zlib".freeze s.version = "1.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Yukihiro Matsumoto".freeze, "UENO Katsuhiro".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Ruby interface for the zlib compression/decompression library".freeze s.email = ["matz@ruby-lang.org".freeze, nil] s.extensions = ["ext/zlib/extconf.rb".freeze] s.files = ["ext/zlib/extconf.rb".freeze, "zlib.so".freeze] s.homepage = "https://github.com/ruby/zlib".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Ruby interface for the zlib compression/decompression library".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]KjK+specifications/default/rdoc-6.1.2.1.gemspecnu[# -*- encoding: utf-8 -*- # stub: rdoc 6.1.2.1 ruby lib Gem::Specification.new do |s| s.name = "rdoc".freeze s.version = "6.1.2.1" s.required_rubygems_version = Gem::Requirement.new(">= 2.2".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Eric Hodel".freeze, "Dave Thomas".freeze, "Phil Hagelberg".freeze, "Tony Strauss".freeze, "Zachary Scott".freeze, "Hiroshi SHIBATA".freeze, "ITOYANAGI Sakura".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "RDoc produces HTML and command-line documentation for Ruby projects.\nRDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentation from the command-line.\n".freeze s.email = ["drbrain@segment7.net".freeze, "".freeze, "".freeze, "".freeze, "mail@zzak.io".freeze, "hsbt@ruby-lang.org".freeze, "aycabta@gmail.com".freeze] s.executables = ["rdoc".freeze, "ri".freeze] s.extra_rdoc_files = ["CVE-2013-0256.rdoc".freeze, "CONTRIBUTING.rdoc".freeze, "ExampleMarkdown.md".freeze, "ExampleRDoc.rdoc".freeze, "History.rdoc".freeze, "LEGAL.rdoc".freeze, "LICENSE.rdoc".freeze, "README.rdoc".freeze, "RI.rdoc".freeze, "TODO.rdoc".freeze] s.files = ["CONTRIBUTING.rdoc".freeze, "CVE-2013-0256.rdoc".freeze, "ExampleMarkdown.md".freeze, "ExampleRDoc.rdoc".freeze, "History.rdoc".freeze, "LEGAL.rdoc".freeze, "LICENSE.rdoc".freeze, "README.rdoc".freeze, "RI.rdoc".freeze, "TODO.rdoc".freeze, "exe/rdoc".freeze, "exe/ri".freeze, "rdoc.rb".freeze, "rdoc/alias.rb".freeze, "rdoc/anon_class.rb".freeze, "rdoc/any_method.rb".freeze, "rdoc/attr.rb".freeze, "rdoc/class_module.rb".freeze, "rdoc/code_object.rb".freeze, "rdoc/code_objects.rb".freeze, "rdoc/comment.rb".freeze, "rdoc/constant.rb".freeze, "rdoc/context.rb".freeze, "rdoc/context/section.rb".freeze, "rdoc/cross_reference.rb".freeze, "rdoc/encoding.rb".freeze, "rdoc/erb_partial.rb".freeze, "rdoc/erbio.rb".freeze, "rdoc/extend.rb".freeze, "rdoc/generator.rb".freeze, "rdoc/generator/darkfish.rb".freeze, "rdoc/generator/json_index.rb".freeze, "rdoc/generator/markup.rb".freeze, "rdoc/generator/pot.rb".freeze, "rdoc/generator/pot/message_extractor.rb".freeze, "rdoc/generator/pot/po.rb".freeze, "rdoc/generator/pot/po_entry.rb".freeze, "rdoc/generator/ri.rb".freeze, "rdoc/ghost_method.rb".freeze, "rdoc/i18n.rb".freeze, "rdoc/i18n/locale.rb".freeze, "rdoc/i18n/text.rb".freeze, "rdoc/include.rb".freeze, "rdoc/known_classes.rb".freeze, "rdoc/markdown.rb".freeze, "rdoc/markdown/entities.rb".freeze, "rdoc/markdown/literals.rb".freeze, "rdoc/markup.rb".freeze, "rdoc/markup/attr_changer.rb".freeze, "rdoc/markup/attr_span.rb".freeze, "rdoc/markup/attribute_manager.rb".freeze, "rdoc/markup/attributes.rb".freeze, "rdoc/markup/blank_line.rb".freeze, "rdoc/markup/block_quote.rb".freeze, "rdoc/markup/document.rb".freeze, "rdoc/markup/formatter.rb".freeze, "rdoc/markup/formatter_test_case.rb".freeze, "rdoc/markup/hard_break.rb".freeze, "rdoc/markup/heading.rb".freeze, "rdoc/markup/include.rb".freeze, "rdoc/markup/indented_paragraph.rb".freeze, "rdoc/markup/list.rb".freeze, "rdoc/markup/list_item.rb".freeze, "rdoc/markup/paragraph.rb".freeze, "rdoc/markup/parser.rb".freeze, "rdoc/markup/pre_process.rb".freeze, "rdoc/markup/raw.rb".freeze, "rdoc/markup/regexp_handling.rb".freeze, "rdoc/markup/rule.rb".freeze, "rdoc/markup/text_formatter_test_case.rb".freeze, "rdoc/markup/to_ansi.rb".freeze, "rdoc/markup/to_bs.rb".freeze, "rdoc/markup/to_html.rb".freeze, "rdoc/markup/to_html_crossref.rb".freeze, "rdoc/markup/to_html_snippet.rb".freeze, "rdoc/markup/to_joined_paragraph.rb".freeze, "rdoc/markup/to_label.rb".freeze, "rdoc/markup/to_markdown.rb".freeze, "rdoc/markup/to_rdoc.rb".freeze, "rdoc/markup/to_table_of_contents.rb".freeze, "rdoc/markup/to_test.rb".freeze, "rdoc/markup/to_tt_only.rb".freeze, "rdoc/markup/verbatim.rb".freeze, "rdoc/meta_method.rb".freeze, "rdoc/method_attr.rb".freeze, "rdoc/mixin.rb".freeze, "rdoc/normal_class.rb".freeze, "rdoc/normal_module.rb".freeze, "rdoc/options.rb".freeze, "rdoc/parser.rb".freeze, "rdoc/parser/c.rb".freeze, "rdoc/parser/changelog.rb".freeze, "rdoc/parser/markdown.rb".freeze, "rdoc/parser/rd.rb".freeze, "rdoc/parser/ripper_state_lex.rb".freeze, "rdoc/parser/ruby.rb".freeze, "rdoc/parser/ruby_tools.rb".freeze, "rdoc/parser/simple.rb".freeze, "rdoc/parser/text.rb".freeze, "rdoc/rd.rb".freeze, "rdoc/rd/block_parser.rb".freeze, "rdoc/rd/inline.rb".freeze, "rdoc/rd/inline_parser.rb".freeze, "rdoc/rdoc.rb".freeze, "rdoc/require.rb".freeze, "rdoc/ri.rb".freeze, "rdoc/ri/driver.rb".freeze, "rdoc/ri/formatter.rb".freeze, "rdoc/ri/paths.rb".freeze, "rdoc/ri/store.rb".freeze, "rdoc/ri/task.rb".freeze, "rdoc/rubygems_hook.rb".freeze, "rdoc/servlet.rb".freeze, "rdoc/single_class.rb".freeze, "rdoc/stats.rb".freeze, "rdoc/stats/normal.rb".freeze, "rdoc/stats/quiet.rb".freeze, "rdoc/stats/verbose.rb".freeze, "rdoc/store.rb".freeze, "rdoc/task.rb".freeze, "rdoc/text.rb".freeze, "rdoc/token_stream.rb".freeze, "rdoc/tom_doc.rb".freeze, "rdoc/top_level.rb".freeze, "rdoc/version.rb".freeze] s.homepage = "https://ruby.github.io/rdoc".freeze s.licenses = ["Ruby".freeze] s.rdoc_options = ["--main".freeze, "README.rdoc".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.2.2".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "RDoc produces HTML and command-line documentation for Ruby projects".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, ["> 1.4.10"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, ["~> 5"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, ["> 1.4.10"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, ["~> 5"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, ["> 1.4.10"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, ["~> 5"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]s(specifications/default/csv-3.0.9.gemspecnu[# -*- encoding: utf-8 -*- # stub: csv 3.0.9 ruby lib Gem::Specification.new do |s| s.name = "csv".freeze s.version = "3.0.9" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["James Edward Gray II".freeze, "Kouhei Sutou".freeze] s.date = "2023-07-26" s.description = "The CSV library provides a complete interface to CSV files and data. It offers tools to enable you to read and write to and from Strings or IO objects, as needed.".freeze s.email = [nil, "kou@cozmixng.org".freeze] s.files = ["csv.rb".freeze, "csv/core_ext/array.rb".freeze, "csv/core_ext/string.rb".freeze, "csv/delete_suffix.rb".freeze, "csv/fields_converter.rb".freeze, "csv/match_p.rb".freeze, "csv/parser.rb".freeze, "csv/row.rb".freeze, "csv/table.rb".freeze, "csv/version.rb".freeze, "csv/writer.rb".freeze] s.homepage = "https://github.com/ruby/csv".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "CSV Reading and Writing".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]dS(specifications/default/etc-1.0.1.gemspecnu[# -*- encoding: utf-8 -*- # stub: etc 1.0.1 ruby lib # stub: ext/etc/extconf.rb Gem::Specification.new do |s| s.name = "etc".freeze s.version = "1.0.1" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Yukihiro Matsumoto".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Provides access to information typically stored in UNIX /etc directory.".freeze s.email = ["matz@ruby-lang.org".freeze] s.extensions = ["ext/etc/extconf.rb".freeze] s.files = ["etc.so".freeze, "ext/etc/extconf.rb".freeze] s.homepage = "https://github.com/ruby/etc".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Provides access to information typically stored in UNIX /etc directory.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]g ,specifications/default/rexml-3.1.9.1.gemspecnu[# -*- encoding: utf-8 -*- # stub: rexml 3.1.9.1 ruby lib Gem::Specification.new do |s| s.name = "rexml".freeze s.version = "3.1.9.1" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Kouhei Sutou".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "An XML toolkit for Ruby".freeze s.email = ["kou@cozmixng.org".freeze] s.files = ["rexml/attlistdecl.rb".freeze, "rexml/attribute.rb".freeze, "rexml/cdata.rb".freeze, "rexml/child.rb".freeze, "rexml/comment.rb".freeze, "rexml/doctype.rb".freeze, "rexml/document.rb".freeze, "rexml/dtd/attlistdecl.rb".freeze, "rexml/dtd/dtd.rb".freeze, "rexml/dtd/elementdecl.rb".freeze, "rexml/dtd/entitydecl.rb".freeze, "rexml/dtd/notationdecl.rb".freeze, "rexml/element.rb".freeze, "rexml/encoding.rb".freeze, "rexml/entity.rb".freeze, "rexml/formatters/default.rb".freeze, "rexml/formatters/pretty.rb".freeze, "rexml/formatters/transitive.rb".freeze, "rexml/functions.rb".freeze, "rexml/instruction.rb".freeze, "rexml/light/node.rb".freeze, "rexml/namespace.rb".freeze, "rexml/node.rb".freeze, "rexml/output.rb".freeze, "rexml/parent.rb".freeze, "rexml/parseexception.rb".freeze, "rexml/parsers/baseparser.rb".freeze, "rexml/parsers/lightparser.rb".freeze, "rexml/parsers/pullparser.rb".freeze, "rexml/parsers/sax2parser.rb".freeze, "rexml/parsers/streamparser.rb".freeze, "rexml/parsers/treeparser.rb".freeze, "rexml/parsers/ultralightparser.rb".freeze, "rexml/parsers/xpathparser.rb".freeze, "rexml/quickpath.rb".freeze, "rexml/rexml.rb".freeze, "rexml/sax2listener.rb".freeze, "rexml/security.rb".freeze, "rexml/source.rb".freeze, "rexml/streamlistener.rb".freeze, "rexml/syncenumerator.rb".freeze, "rexml/text.rb".freeze, "rexml/undefinednamespaceexception.rb".freeze, "rexml/validation/relaxng.rb".freeze, "rexml/validation/validation.rb".freeze, "rexml/validation/validationexception.rb".freeze, "rexml/xmldecl.rb".freeze, "rexml/xmltokens.rb".freeze, "rexml/xpath.rb".freeze, "rexml/xpath_parser.rb".freeze] s.homepage = "https://github.com/ruby/rexml".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "An XML toolkit for Ruby".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]'&V  (specifications/default/rss-0.2.7.gemspecnu[# -*- encoding: utf-8 -*- # stub: rss 0.2.7 ruby lib Gem::Specification.new do |s| s.name = "rss".freeze s.version = "0.2.7" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Kouhei Sutou".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Family of libraries that support various formats of XML \"feeds\".".freeze s.email = ["kou@cozmixng.org".freeze] s.files = ["rss.rb".freeze, "rss/0.9.rb".freeze, "rss/1.0.rb".freeze, "rss/2.0.rb".freeze, "rss/atom.rb".freeze, "rss/content.rb".freeze, "rss/content/1.0.rb".freeze, "rss/content/2.0.rb".freeze, "rss/converter.rb".freeze, "rss/dublincore.rb".freeze, "rss/dublincore/1.0.rb".freeze, "rss/dublincore/2.0.rb".freeze, "rss/dublincore/atom.rb".freeze, "rss/image.rb".freeze, "rss/itunes.rb".freeze, "rss/maker.rb".freeze, "rss/maker/0.9.rb".freeze, "rss/maker/1.0.rb".freeze, "rss/maker/2.0.rb".freeze, "rss/maker/atom.rb".freeze, "rss/maker/base.rb".freeze, "rss/maker/content.rb".freeze, "rss/maker/dublincore.rb".freeze, "rss/maker/entry.rb".freeze, "rss/maker/feed.rb".freeze, "rss/maker/image.rb".freeze, "rss/maker/itunes.rb".freeze, "rss/maker/slash.rb".freeze, "rss/maker/syndication.rb".freeze, "rss/maker/taxonomy.rb".freeze, "rss/maker/trackback.rb".freeze, "rss/parser.rb".freeze, "rss/rexmlparser.rb".freeze, "rss/rss.rb".freeze, "rss/slash.rb".freeze, "rss/syndication.rb".freeze, "rss/taxonomy.rb".freeze, "rss/trackback.rb".freeze, "rss/utils.rb".freeze, "rss/xml-stylesheet.rb".freeze, "rss/xml.rb".freeze, "rss/xmlparser.rb".freeze, "rss/xmlscanner.rb".freeze] s.homepage = "https://github.com/ruby/rss".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "Family of libraries that support various formats of XML \"feeds\".".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ])m-specifications/default/stringio-0.0.2.gemspecnu[# -*- encoding: utf-8 -*- # stub: stringio 0.0.2 ruby lib # stub: ext/stringio/extconf.rb Gem::Specification.new do |s| s.name = "stringio".freeze s.version = "0.0.2" s.required_rubygems_version = Gem::Requirement.new(">= 2.6".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Nobu Nakada".freeze] s.date = "2023-07-26" s.description = "Pseudo `IO` class from/to `String`.".freeze s.email = "nobu@ruby-lang.org".freeze s.extensions = ["ext/stringio/extconf.rb".freeze] s.files = ["ext/stringio/extconf.rb".freeze, "stringio.so".freeze] s.homepage = "https://github.com/ruby/stringio".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.2".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Pseudo IO on String".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]Z/specifications/default/io-console-0.4.7.gemspecnu[# -*- encoding: utf-8 -*- # stub: io-console 0.4.7 ruby lib # stub: ext/io/console/extconf.rb Gem::Specification.new do |s| s.name = "io-console".freeze s.version = "0.4.7" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Nobu Nakada".freeze] s.cert_chain = ["certs/nobu.pem".freeze] s.date = "2018-12-25" s.description = "add console capabilities to IO instances.".freeze s.email = "nobu@ruby-lang.org".freeze s.extensions = ["ext/io/console/extconf.rb".freeze] s.files = ["ext/io/console/extconf.rb".freeze, "io/console.so".freeze, "io/console/size.rb".freeze] s.homepage = "https://github.com/ruby/io-console".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.2.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Console interface".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0.6.1"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0.6.1"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0.6.1"]) end end PK% ]a+specifications/default/tracer-0.1.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: tracer 0.1.0 ruby lib Gem::Specification.new do |s| s.name = "tracer".freeze s.version = "0.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Keiju ISHITSUKA".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Outputs a source level execution trace of a Ruby program.".freeze s.email = ["keiju@ruby-lang.org".freeze] s.files = ["tracer.rb".freeze, "tracer/version.rb".freeze] s.homepage = "https://github.com/ruby/tracer".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "Outputs a source level execution trace of a Ruby program.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]#{(specifications/default/dbm-1.0.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: dbm 1.0.0 ruby lib # stub: ext/dbm/extconf.rb Gem::Specification.new do |s| s.name = "dbm".freeze s.version = "1.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Yukihiro Matsumoto".freeze] s.date = "2023-07-26" s.description = "Provides a wrapper for the UNIX-style Database Manager Library".freeze s.email = ["matz@ruby-lang.org".freeze] s.extensions = ["ext/dbm/extconf.rb".freeze] s.files = ["dbm.so".freeze, "ext/dbm/extconf.rb".freeze] s.homepage = "https://github.com/ruby/dbm".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Provides a wrapper for the UNIX-style Database Manager Library".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]Z,specifications/default/ostruct-0.1.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: ostruct 0.1.0 ruby lib Gem::Specification.new do |s| s.name = "ostruct".freeze s.version = "0.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Marc-Andre Lafortune".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "Class to build custom data structures, similar to a Hash.".freeze s.email = ["ruby-core@marc-andre.ca".freeze] s.files = ["ostruct.rb".freeze] s.homepage = "https://github.com/ruby/ostruct".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "Class to build custom data structures, similar to a Hash.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]!u]*specifications/default/scanf-1.0.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: scanf 1.0.0 ruby lib Gem::Specification.new do |s| s.name = "scanf".freeze s.version = "1.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["David Alan Black".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "scanf is an implementation of the C function scanf(3).".freeze s.email = ["dblack@superlink.net".freeze] s.files = ["scanf.rb".freeze] s.homepage = "https://github.com/ruby/scanf".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "scanf is an implementation of the C function scanf(3).".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, ["~> 1.14"]) s.add_development_dependency(%q.freeze, ["~> 10.0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, ["~> 1.14"]) s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, ["~> 1.14"]) s.add_dependency(%q.freeze, ["~> 10.0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]oi5)specifications/default/sync-0.5.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: sync 0.5.0 ruby lib Gem::Specification.new do |s| s.name = "sync".freeze s.version = "0.5.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Keiju ISHITSUKA".freeze] s.bindir = "exe".freeze s.date = "2023-07-26" s.description = "A module that provides a two-phase lock with a counter.".freeze s.email = ["keiju@ruby-lang.org".freeze] s.files = ["sync.rb".freeze] s.homepage = "https://github.com/ruby/sync".freeze s.licenses = ["BSD-2-Clause".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "A module that provides a two-phase lock with a counter.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]Cj)specifications/default/sdbm-1.0.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: sdbm 1.0.0 ruby lib # stub: ext/sdbm/extconf.rb Gem::Specification.new do |s| s.name = "sdbm".freeze s.version = "1.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Yukihiro Matsumoto".freeze] s.date = "2023-07-26" s.description = "Provides a simple file-based key-value store with String keys and values.".freeze s.email = ["matz@ruby-lang.org".freeze] s.extensions = ["ext/sdbm/extconf.rb".freeze] s.files = ["ext/sdbm/extconf.rb".freeze, "sdbm.so".freeze] s.homepage = "https://github.com/ruby/sdbm".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Provides a simple file-based key-value store with String keys and values.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]&8.specifications/default/fileutils-1.1.0.gemspecnu[# -*- encoding: utf-8 -*- # stub: fileutils 1.1.0 ruby lib Gem::Specification.new do |s| s.name = "fileutils".freeze s.version = "1.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "source_code_uri" => "https://github.com/ruby/fileutils" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Minero Aoki".freeze] s.date = "2023-07-26" s.description = "Several file utility methods for copying, moving, removing, etc.".freeze s.email = [nil] s.files = ["fileutils.rb".freeze, "fileutils/version.rb".freeze] s.homepage = "https://github.com/ruby/fileutils".freeze s.licenses = ["BSD-2-Clause".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Several file utility methods for copying, moving, removing, etc.".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]+D D &specifications/test-unit-3.2.9.gemspecnu[# -*- encoding: utf-8 -*- # stub: test-unit 3.2.9 ruby lib Gem::Specification.new do |s| s.name = "test-unit".freeze s.version = "3.2.9" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "source_code_uri" => "https://github.com/test-unit/test-unit" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Kouhei Sutou".freeze, "Haruka Yoshihara".freeze] s.date = "2018-12-01" s.description = "test-unit (Test::Unit) is unit testing framework for Ruby, based on xUnit\nprinciples. These were originally designed by Kent Beck, creator of extreme\nprogramming software development methodology, for Smalltalk's SUnit. It allows\nwriting tests, checking results and automated testing in Ruby.\n".freeze s.email = ["kou@cozmixng.org".freeze, "yoshihara@clear-code.com".freeze] s.homepage = "http://test-unit.github.io/".freeze s.licenses = ["Ruby".freeze, "PSFL".freeze] s.rubygems_version = "3.0.3.1".freeze s.summary = "An xUnit family unit testing framework for Ruby.".freeze s.installed_by_version = "3.0.3.1" if s.respond_to? :installed_by_version if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]pc` !specifications/rack-3.0.8.gemspecnu[# -*- encoding: utf-8 -*- # stub: rack 3.0.8 ruby lib Gem::Specification.new do |s| s.name = "rack".freeze s.version = "3.0.8" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "bug_tracker_uri" => "https://github.com/rack/rack/issues", "changelog_uri" => "https://github.com/rack/rack/blob/main/CHANGELOG.md", "documentation_uri" => "https://rubydoc.info/github/rack/rack", "source_code_uri" => "https://github.com/rack/rack" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Leah Neukirchen".freeze] s.date = "2023-06-14" s.description = "Rack provides a minimal, modular and adaptable interface for developing\nweb applications in Ruby. By wrapping HTTP requests and responses in\nthe simplest way possible, it unifies and distills the API for web\nservers, web frameworks, and software in between (the so-called\nmiddleware) into a single method call.\n".freeze s.email = "leah@vuxu.org".freeze s.extra_rdoc_files = ["README.md".freeze, "CHANGELOG.md".freeze, "CONTRIBUTING.md".freeze] s.files = ["CHANGELOG.md".freeze, "CONTRIBUTING.md".freeze, "README.md".freeze] s.homepage = "https://github.com/rack/rack".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.4.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "A modular Ruby webserver interface.".freeze s.installed_by_version = "3.0.3.1" if s.respond_to? :installed_by_version if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, ["~> 5.0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, ["~> 5.0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, ["~> 5.0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]7 7 "specifications/rake-12.3.3.gemspecnu[# -*- encoding: utf-8 -*- # stub: rake 12.3.3 ruby lib Gem::Specification.new do |s| s.name = "rake".freeze s.version = "12.3.3" s.required_rubygems_version = Gem::Requirement.new(">= 1.3.2".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Hiroshi SHIBATA".freeze, "Eric Hodel".freeze, "Jim Weirich".freeze] s.bindir = "exe".freeze s.date = "2019-07-22" s.description = "Rake is a Make-like program implemented in Ruby. Tasks and dependencies are\nspecified in standard Ruby syntax.\nRake has the following features:\n * Rakefiles (rake's version of Makefiles) are completely defined in standard Ruby syntax.\n No XML files to edit. No quirky Makefile syntax to worry about (is that a tab or a space?)\n * Users can specify tasks with prerequisites.\n * Rake supports rule patterns to synthesize implicit tasks.\n * Flexible FileLists that act like arrays but know about manipulating file names and paths.\n * Supports parallel execution of tasks.\n".freeze s.email = ["hsbt@ruby-lang.org".freeze, "drbrain@segment7.net".freeze, "".freeze] s.executables = ["rake".freeze] s.files = ["exe/rake".freeze] s.homepage = "https://github.com/ruby/rake".freeze s.licenses = ["MIT".freeze] s.rdoc_options = ["--main".freeze, "README.rdoc".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.0.0".freeze) s.rubygems_version = "3.0.3.1".freeze s.summary = "Rake is a Make-like program implemented in Ruby".freeze s.installed_by_version = "3.0.3.1" if s.respond_to? :installed_by_version if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]%Bqqgems/power_assert-1.1.3/LEGALnu[LEGAL NOTICE INFORMATION ------------------------ All the files in this distribution are written by the author. PK% ]Vgems/power_assert-1.1.3/Gemfilenu[source "http://rubygems.org" gemspec # https://github.com/redmine/redmine/blob/3.0.4/Gemfile#L101 local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local") if File.exist?(local_gemfile) eval_gemfile local_gemfile end PK% ]X gems/power_assert-1.1.3/Rakefilenu[require "bundler/gem_tasks" require "rake/testtask" task :default => :test Rake::TestTask.new(:test) do |t| # helper(simplecov) must be required before loading power_assert helper_path = File.realpath("test/test_helper.rb") t.ruby_opts = ["-w", "-r#{helper_path}"] t.test_files = FileList["test/**/*_test.rb"].exclude do |i| begin next false unless defined?(RubyVM) RubyVM::InstructionSequence.compile(File.read(i)) false rescue SyntaxError true end end end # ruby/ruby:test/pathname/test_pathname.rb def has_symlink? begin File.symlink("", "") rescue NotImplementedError, Errno::EACCES return false rescue Errno::ENOENT end return true end SYMLINK_DIRS = ["lib", "test"] task :before_script do if ENV["TEST_SYMLINK"] == "yes" and has_symlink? SYMLINK_DIRS.each do |d| File.rename(d, ".#{d}") File.symlink(".#{d}", d) end end end task :after_script do SYMLINK_DIRS.each do |d| if File.symlink?(d) and File.directory?(".#{d}") File.unlink(d) File.rename(".#{d}", d) end unless File.directory?(d) raise "#{d} should be directory" end end end desc "Run the benchmark suite" task :benchmark do Dir.glob("benchmark/bm_*.rb").each do |f| load(f) end end PK% ]*Dgems/power_assert-1.1.3/BSDLnu[Copyright (C) 2014 Kazuki Tsujimoto Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PK% ]|m# # #gems/power_assert-1.1.3/README.rdocnu[= power_assert == About Power Assert for Ruby. Power Assert shows each value of variables and method calls in the expression. It is useful for testing, providing which value wasn't correct when the condition is not satisfied. Failure: assert { 3.times.to_a.include?(3) } | | | | | false | [0, 1, 2] # == Related Projects In general, you don't need to use this library directly. Use following test frameworks or extensions instead. * {test-unit}[https://github.com/test-unit/test-unit](>= 3.0.0) * {Document}[http://test-unit.github.io/test-unit/en/Test/Unit/Assertions.html#assert-instance_method] * {minitest-power_assert}[https://github.com/hsbt/minitest-power_assert] * {rspec-power_assert}[https://github.com/joker1007/rspec-power_assert] * {pry-power_assert}[https://github.com/yui-knk/pry-power_assert] * {pry-byebug-power_assert}[https://github.com/k-tsj/pry-byebug-power_assert] * {power_p}[https://github.com/k-tsj/power_p] == Requirement * CRuby 2.0.0 or later == Reference * {Power Assert in Ruby (at RubyKaigi 2014) // Speaker Deck}[https://speakerdeck.com/k_tsj/power-assert-in-ruby] == Known Limitations * Expressions must be put in one line. Expressions with folded long lines produce nothing report, e.g.: assert do # reported func(foo: 0123456789, bar: "abcdefg") end assert do # won't be reported func(foo: 0123456789, bar: "abcdefg") end * Expressions must have one or more method call. Expressions with no method call produce nothing report, e.g.: val = false assert do # reported val == true end assert do # won't be reported val end * Returned values from accessor methods, method missing, or "super" produce nothing report, e.g: class Foo attr_accessor :val end foo = Foo.new foo.val = false assert do # reported (only the value of "foo" and the literal "true") foo.val == true end assert do # won't be reported foo.val end * Expressions should not have conditional branches. Expressions with such conditional codes may produce nothing report, e.g.: condition = true expected = false actual = true assert do # this will fail but nothing reported condition ? expected == actual : expected == actual end == Travis Build Status {}[http://travis-ci.org/k-tsj/power_assert] PK% ] b gems/power_assert-1.1.3/COPYINGnu[Copyright (C) 2014 Kazuki Tsujimoto You can redistribute it and/or modify it under either the terms of the 2-clause BSDL (see the file BSDL), or the conditions below: 1. You may make and give away verbatim copies of the source form of the software without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may modify your copy of the software in any way, provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or by allowing the author to include your modifications in the software. b) use the modified software only within your corporation or organization. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 3. You may distribute the software in object code or binary form, provided that you do at least ONE of the following: a) distribute the binaries and library files of the software, together with instructions (in the manual page or equivalent) on where to get the original distribution. b) accompany the distribution with the machine-readable source of the software. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 4. You may modify and include the part of the software into any other software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under these terms. For the list of those files and their copying conditions, see the file LEGAL. 5. The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the copyright of the software, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this software. 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. PK% ]rD[ ,gems/power_assert-1.1.3/power_assert.gemspecnu[# -*- encoding: utf-8 -*- # stub: power_assert 1.1.3 ruby lib Gem::Specification.new do |s| s.name = "power_assert".freeze s.version = "1.1.3" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Kazuki Tsujimoto".freeze] s.bindir = "exe".freeze s.date = "2018-06-24" s.description = "Power Assert for Ruby. Power Assert shows each value of variables and method calls in the expression. It is useful for testing, providing which value wasn't correct when the condition is not satisfied.".freeze s.email = ["kazuki@callcc.net".freeze] s.extra_rdoc_files = ["README.rdoc".freeze] s.files = [".gitignore".freeze, ".travis.yml".freeze, "BSDL".freeze, "COPYING".freeze, "Gemfile".freeze, "LEGAL".freeze, "README.rdoc".freeze, "Rakefile".freeze, "bin/console".freeze, "bin/setup".freeze, "lib/power_assert.rb".freeze, "lib/power_assert/colorize.rb".freeze, "lib/power_assert/configuration.rb".freeze, "lib/power_assert/context.rb".freeze, "lib/power_assert/enable_tracepoint_events.rb".freeze, "lib/power_assert/inspector.rb".freeze, "lib/power_assert/parser.rb".freeze, "lib/power_assert/version.rb".freeze, "power_assert.gemspec".freeze] s.homepage = "https://github.com/k-tsj/power_assert".freeze s.licenses = ["2-clause BSDL".freeze, "Ruby's".freeze] s.rdoc_options = ["--main".freeze, "README.rdoc".freeze] s.rubygems_version = "3.1.2".freeze s.summary = "Power Assert for Ruby".freeze if s.respond_to? :specification_version then s.specification_version = 4 end if s.respond_to? :add_runtime_dependency then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]t/;JJ!gems/power_assert-1.1.3/bin/setupnu[#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' set -vx bundle install PK% ]9\#gems/power_assert-1.1.3/bin/consolenu[#!/usr/bin/env ruby require 'bundler/setup' require 'power_assert' begin require 'pry' Pry rescue LoadError require 'irb' IRB end.start PK% ]~553gems/power_assert-1.1.3/lib/power_assert/context.rbnu[require 'power_assert/configuration' require 'power_assert/enable_tracepoint_events' require 'power_assert/inspector' require 'power_assert/parser' module PowerAssert class Context Value = Struct.new(:name, :value, :lineno, :column, :display_offset) def initialize(base_caller_length) @fired = false @target_thread = Thread.current method_id_set = nil @return_values = [] trace_alias_method = PowerAssert.configuration._trace_alias_method @trace_return = TracePoint.new(:return, :c_return) do |tp| begin unless method_id_set next unless Thread.current == @target_thread method_id_set = @parser.method_id_set end method_id = SUPPORT_ALIAS_METHOD ? tp.callee_id : trace_alias_method && tp.event == :return ? tp.binding.eval('::Kernel.__callee__') : tp.method_id next if ! method_id_set[method_id] next if tp.event == :c_return and not (@parser.lineno == tp.lineno and @parser.path == tp.path) locs = PowerAssert.app_caller_locations diff = locs.length - base_caller_length if (tp.event == :c_return && diff == 1 || tp.event == :return && diff <= 2) and Thread.current == @target_thread idx = -(base_caller_length + 1) if @parser.path == locs[idx].path and @parser.lineno == locs[idx].lineno val = PowerAssert.configuration.lazy_inspection ? tp.return_value : InspectedValue.new(SafeInspectable.new(tp.return_value).inspect) @return_values << Value[method_id.to_s, val, locs[idx].lineno, nil] end end rescue Exception => e warn "power_assert: [BUG] Failed to trace: #{e.class}: #{e.message}" end end end def message raise 'call #yield or #enable at first' unless fired? @message ||= build_assertion_message(@parser, @return_values).freeze end def message_proc -> { message } end private def fired? @fired end def build_assertion_message(parser, return_values) if PowerAssert.configuration._colorize_message line = Pry::Code.new(parser.line).highlighted else line = parser.line end path = detect_path(parser, return_values) return line unless path c2d = column2display_offset(parser.line) return_values, methods_in_path = find_all_identified_calls(return_values, path) return_values.zip(methods_in_path) do |i, j| unless i.name == j.name warn "power_assert: [BUG] Failed to get column: #{i.name}" return line end i.display_offset = c2d[j.column] end refs_in_path = path.find_all {|i| i.type == :ref } ref_values = refs_in_path.map {|i| Value[i.name, parser.binding.eval(i.name), parser.lineno, i.column, c2d[i.column]] } vals = (return_values + ref_values).find_all(&:display_offset).sort_by(&:display_offset).reverse return line if vals.empty? fmt = (0..vals[0].display_offset).map do |i| if vals.find {|v| v.display_offset == i } "%<#{i}>s" else line[i] == "\t" ? "\t" : ' ' end end.join lines = [] lines << line.chomp lines << sprintf(fmt, vals.each_with_object({}) {|v, h| h[v.display_offset.to_s.to_sym] = '|' }).chomp vals.each do |i| inspected_val = SafeInspectable.new(Formatter.new(i.value, i.display_offset)).inspect inspected_val.each_line do |l| map_to = vals.each_with_object({}) do |j, h| h[j.display_offset.to_s.to_sym] = [l, '|', ' '][i.display_offset <=> j.display_offset] end lines << encoding_safe_rstrip(sprintf(fmt, map_to)) end end lines.join("\n") end def detect_path(parser, return_values) return parser.call_paths.flatten.uniq if parser.method_id_set.empty? all_paths = parser.call_paths return_value_names = return_values.map(&:name) uniq_calls = uniq_calls(all_paths) uniq_call = return_value_names.find {|i| uniq_calls.include?(i) } detected_paths = all_paths.find_all do |path| method_names = path.find_all {|ident| ident.type == :method }.map(&:name) break [path] if uniq_call and method_names.include?(uniq_call) return_value_names == method_names end return nil unless detected_paths.length == 1 detected_paths[0] end def uniq_calls(paths) all_calls = enum_count_by(paths.map {|path| path.find_all {|ident| ident.type == :method }.map(&:name).uniq }.flatten) {|i| i } all_calls.find_all {|_, call_count| call_count == 1 }.map {|name, _| name } end def find_all_identified_calls(return_values, path) return_value_num_of_calls = enum_count_by(return_values, &:name) path_num_of_calls = enum_count_by(path.find_all {|ident| ident.type == :method }, &:name) identified_calls = return_value_num_of_calls.find_all {|name, num| path_num_of_calls[name] == num }.map(&:first) [ return_values.find_all {|val| identified_calls.include?(val.name) }, path.find_all {|ident| ident.type == :method and identified_calls.include?(ident.name) } ] end def enum_count_by(enum, &blk) Hash[enum.group_by(&blk).map{|k, v| [k, v.length] }] end def encoding_safe_rstrip(str) str.rstrip rescue ArgumentError, Encoding::CompatibilityError enc = str.encoding if enc.ascii_compatible? str.b.rstrip.force_encoding(enc) else str end end def column2display_offset(str) display_offset = 0 str.each_char.with_object([]) do |c, r| c.bytesize.times do r << display_offset end display_offset += c.ascii_only? ? 1 : 2 # FIXME end end end private_constant :Context class BlockContext < Context def initialize(assertion_proc_or_source, assertion_method, source_binding) super(0) if assertion_proc_or_source.respond_to?(:to_proc) @assertion_proc = assertion_proc_or_source.to_proc line = nil else @assertion_proc = source_binding.eval "Proc.new {#{assertion_proc_or_source}}" line = assertion_proc_or_source end @parser = Parser::DUMMY @trace_call = TracePoint.new(:call, :c_call) do |tp| if PowerAssert.app_context? and Thread.current == @target_thread @trace_call.disable locs = PowerAssert.app_caller_locations path = locs.last.path lineno = locs.last.lineno if File.exist?(path) line ||= File.open(path) {|fp| fp.each_line.drop(lineno - 1).first } end if line @parser = Parser.new(line, path, lineno, @assertion_proc.binding, assertion_method.to_s, @assertion_proc) end end end end def yield @fired = true invoke_yield(&@assertion_proc) end private def invoke_yield @trace_return.enable do @trace_call.enable do yield end end end end private_constant :BlockContext class TraceContext < Context def initialize(binding) target_frame, *base = PowerAssert.app_caller_locations super(base.length) path = target_frame.path lineno = target_frame.lineno if File.exist?(path) line = File.open(path) {|fp| fp.each_line.drop(lineno - 1).first } @parser = Parser.new(line, path, lineno, binding) else @parser = Parser::DUMMY end end def enable @fired = true @trace_return.enable end def disable @trace_return.disable end def enabled? @trace_return.enabled? end end private_constant :TraceContext end PK% ]’2gems/power_assert-1.1.3/lib/power_assert/parser.rbnu[require 'ripper' module PowerAssert class Parser Ident = Struct.new(:type, :name, :column) attr_reader :line, :path, :lineno, :binding def initialize(line, path, lineno, binding, assertion_method_name = nil, assertion_proc = nil) @line = line @line_for_parsing = (valid_syntax?(line) ? line : slice_expression(line)).b @path = path @lineno = lineno @binding = binding @proc_local_variables = binding.eval('local_variables').map(&:to_s) @assertion_method_name = assertion_method_name @assertion_proc = assertion_proc end def idents @idents ||= extract_idents(Ripper.sexp(@line_for_parsing)) end def call_paths collect_paths(idents).uniq end def method_id_set methods = idents.flatten.find_all {|i| i.type == :method } @method_id_set ||= methods.map(&:name).map(&:to_sym).each_with_object({}) {|i, h| h[i] = true } end private def valid_syntax?(str) return true unless defined?(RubyVM) begin verbose, $VERBOSE = $VERBOSE, nil RubyVM::InstructionSequence.compile(str) true rescue SyntaxError false ensure $VERBOSE = verbose end end def slice_expression(str) str = str.chomp str.sub!(/\A\s*(?:if|unless|elsif|case|while|until) /) {|i| ' ' * i.length } str.sub!(/\A\s*(?:\}|\]|end)?\./) {|i| ' ' * i.length } str.sub!(/[\{\.\\]\z/, '') str.sub!(/(?:&&|\|\|)\z/, '') str.sub!(/ (?:do|and|or)\z/, '') str end class Branch < Array end AND_OR_OPS = %i(and or && ||) # # Returns idents as graph structure. # # +--c--b--+ # extract_idents(Ripper.sexp('a&.b(c).d')) #=> a--+ +--d # +--------+ # def extract_idents(sexp) tag, * = sexp case tag when :arg_paren, :assoc_splat, :fcall, :hash, :method_add_block, :string_literal, :return extract_idents(sexp[1]) when :assign, :massign extract_idents(sexp[2]) when :opassign _, _, (_, op_name, (_, op_column)), s0 = sexp extract_idents(s0) + [Ident[:method, op_name.sub(/=\z/, ''), op_column]] when :assoclist_from_args, :bare_assoc_hash, :dyna_symbol, :paren, :string_embexpr, :regexp_literal, :xstring_literal sexp[1].flat_map {|s| extract_idents(s) } when :command [sexp[2], sexp[1]].flat_map {|s| extract_idents(s) } when :assoc_new, :dot2, :dot3, :string_content sexp[1..-1].flat_map {|s| extract_idents(s) } when :unary handle_columnless_ident([], sexp[1], extract_idents(sexp[2])) when :binary op = sexp[2] if AND_OR_OPS.include?(op) extract_idents(sexp[1]) + [Branch[extract_idents(sexp[3]), []]] else handle_columnless_ident(extract_idents(sexp[1]), op, extract_idents(sexp[3])) end when :call _, recv, (op_sym, op_name, _), method = sexp with_safe_op = ((op_sym == :@op and op_name == '&.') or op_sym == :"&.") if method == :call handle_columnless_ident(extract_idents(recv), :call, [], with_safe_op) else extract_idents(recv) + (with_safe_op ? [Branch[extract_idents(method), []]] : extract_idents(method)) end when :array sexp[1] ? sexp[1].flat_map {|s| extract_idents(s) } : [] when :command_call [sexp[1], sexp[4], sexp[3]].flat_map {|s| extract_idents(s) } when :aref handle_columnless_ident(extract_idents(sexp[1]), :[], extract_idents(sexp[2])) when :method_add_arg idents = extract_idents(sexp[1]) if idents.empty? # idents may be empty(e.g. ->{}.()) extract_idents(sexp[2]) else if idents[-1].kind_of?(Branch) and idents[-1][1].empty? # Safe navigation operator is used. See :call clause also. idents[0..-2] + [Branch[extract_idents(sexp[2]) + idents[-1][0], []]] else idents[0..-2] + extract_idents(sexp[2]) + [idents[-1]] end end when :args_add_block _, (tag, ss0, *ss1), _ = sexp if tag == :args_add_star (ss0 + ss1).flat_map {|s| extract_idents(s) } else sexp[1].flat_map {|s| extract_idents(s) } end when :vcall _, (tag, name, (_, column)) = sexp if tag == :@ident [Ident[@proc_local_variables.include?(name) ? :ref : :method, name, column]] else [] end when :program _, ((tag0, (tag1, (tag2, (tag3, mname, _)), _), (tag4, _, ss))) = sexp if tag0 == :method_add_block and tag1 == :method_add_arg and tag2 == :fcall and (tag3 == :@ident or tag3 == :@const) and mname == @assertion_method_name and (tag4 == :brace_block or tag4 == :do_block) ss.flat_map {|s| extract_idents(s) } else _, (s0, *) = sexp extract_idents(s0) end when :ifop _, s0, s1, s2 = sexp [*extract_idents(s0), Branch[extract_idents(s1), extract_idents(s2)]] when :if, :unless _, s0, ss0, (_, ss1) = sexp [*extract_idents(s0), Branch[ss0.flat_map {|s| extract_idents(s) }, ss1 ? ss1.flat_map {|s| extract_idents(s) } : []]] when :if_mod, :unless_mod _, s0, s1 = sexp [*extract_idents(s0), Branch[extract_idents(s1), []]] when :var_ref, :var_field _, (tag, ref_name, (_, column)) = sexp case tag when :@kw if ref_name == 'self' [Ident[:ref, 'self', column]] else [] end when :@ident, :@const, :@cvar, :@ivar, :@gvar [Ident[:ref, ref_name, column]] else [] end when :@ident, :@const, :@op _, method_name, (_, column) = sexp [Ident[:method, method_name, column]] else [] end end def str_indices(str, re, offset, limit) idx = str.index(re, offset) if idx and idx <= limit [idx, *str_indices(str, re, idx + 1, limit)] else [] end end MID2SRCTXT = { :[] => '[', :+@ => '+', :-@ => '-', :call => '(' } def handle_columnless_ident(left_idents, mid, right_idents, with_safe_op = false) left_max = left_idents.flatten.max_by(&:column) right_min = right_idents.flatten.min_by(&:column) bg = left_max ? left_max.column + left_max.name.length : 0 ed = right_min ? right_min.column - 1 : @line_for_parsing.length - 1 mname = mid.to_s srctxt = MID2SRCTXT[mid] || mname re = / #{'\b' if /\A\w/ =~ srctxt} #{Regexp.escape(srctxt)} #{'\b' if /\w\z/ =~ srctxt} /x indices = str_indices(@line_for_parsing, re, bg, ed) if indices.length == 1 or !(right_idents.empty? and left_idents.empty?) ident = Ident[:method, mname, right_idents.empty? ? indices.first : indices.last] left_idents + right_idents + (with_safe_op ? [Branch[[ident], []]] : [ident]) else left_idents + right_idents end end def collect_paths(idents, prefixes = [[]], index = 0) if index < idents.length node = idents[index] if node.kind_of?(Branch) prefixes = node.flat_map {|n| collect_paths(n, prefixes, 0) } else prefixes = prefixes.map {|prefix| prefix + [node] } end collect_paths(idents, prefixes, index + 1) else prefixes end end class DummyParser < Parser def initialize super('', nil, nil, TOPLEVEL_BINDING) end def idents [] end def call_paths [] end end DUMMY = DummyParser.new end private_constant :Parser end PK% ]wY++3gems/power_assert-1.1.3/lib/power_assert/version.rbnu[module PowerAssert VERSION = "1.1.3" end PK% ]!4gems/power_assert-1.1.3/lib/power_assert/colorize.rbnu[warn 'power_assert/colorize is experimental' require 'power_assert/configuration' PowerAssert.configure do |c| c.lazy_inspection = true c._colorize_message = true c._use_pp = true end PK% ]{%}}WW9gems/power_assert-1.1.3/lib/power_assert/configuration.rbnu[module PowerAssert class << self def configuration @configuration ||= Configuration[false, false, true, false, false] end def configure yield configuration end end SUPPORT_ALIAS_METHOD = TracePoint.public_method_defined?(:callee_id) private_constant :SUPPORT_ALIAS_METHOD class Configuration < Struct.new(:lazy_inspection, :_trace_alias_method, :_redefinition, :_colorize_message, :_use_pp) def _trace_alias_method=(bool) super if SUPPORT_ALIAS_METHOD warn 'power_assert: _trace_alias_method option is obsolete. You no longer have to set it.' end end def _colorize_message=(bool) if bool require 'pry' end super end def lazy_inspection=(bool) unless bool raise 'lazy_inspection option must be enabled when using pp' if _use_pp end super end def _use_pp=(bool) if bool raise 'lazy_inspection option must be enabled when using pp' unless lazy_inspection require 'pp' end super end end private_constant :Configuration end PK% ]Wa]Dgems/power_assert-1.1.3/lib/power_assert/enable_tracepoint_events.rbnu[require 'power_assert/configuration' if defined?(RubyVM) if PowerAssert.configuration._redefinition if RUBY_VERSION == '2.3.2' warn 'power_assert: It is strongly recommended that you use Ruby 2.3.3 or later which fixes regression on 2.3.2.' warn 'power_assert: See https://www.ruby-lang.org/en/news/2016/11/21/ruby-2-3-3-released/ for more details.' end verbose = $VERBOSE begin $VERBOSE = nil module PowerAssert # set redefined flag basic_classes = [ Fixnum, Float, String, Array, Hash, Bignum, Symbol, Time, Regexp, NilClass, TrueClass, FalseClass ] basic_operators = [ :+, :-, :*, :/, :%, :==, :===, :<, :<=, :<<, :[], :[]=, :length, :size, :empty?, :succ, :>, :>=, :!, :!=, :=~, :freeze, :-@, :max, :min ] bug11182 = Class.new do def fixed? true end end refine bug11182 do def fixed? end end _ = Class.new(bug11182) do alias _fixed? fixed? protected :_fixed? end if (bug11182.new.fixed? rescue false) basic_classes.each do |klass| basic_operators.each do |bop| if klass.public_method_defined?(bop) refine(klass) do define_method(bop) {} end end end end else # workaround for https://bugs.ruby-lang.org/issues/11182 basic_classes.each do |klass| basic_operators.each do |bop| if klass.public_method_defined?(bop) klass.ancestors.find {|i| i.instance_methods(false).index(bop) }.module_eval do public bop end end end end refine Symbol do def == end end end # bypass check_cfunc refine BasicObject do def ! end def == end end refine Module do def == end end end ensure $VERBOSE = verbose end end # disable optimization RubyVM::InstructionSequence.compile_option = { specialized_instruction: false } end PK% ]\>5gems/power_assert-1.1.3/lib/power_assert/inspector.rbnu[require 'power_assert/configuration' module PowerAssert class InspectedValue def initialize(value) @value = value end def inspect @value end end private_constant :InspectedValue class SafeInspectable def initialize(value) @value = value end def inspect inspected = @value.inspect if Encoding.compatible?(Encoding.default_external, inspected) inspected else begin "#{inspected.encode(Encoding.default_external)}(#{inspected.encoding})" rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError inspected.force_encoding(Encoding.default_external) end end rescue => e "InspectionFailure: #{e.class}: #{e.message.each_line.first}" end end private_constant :SafeInspectable class Formatter def initialize(value, indent) @value = value @indent = indent end def inspect if PowerAssert.configuration._colorize_message if PowerAssert.configuration._use_pp width = [Pry::Terminal.width! - 1 - @indent, 10].max Pry::ColorPrinter.pp(@value, '', width) else Pry::Code.new(@value.inspect).highlighted end else if PowerAssert.configuration._use_pp PP.pp(@value, '') else @value.inspect end end end end private_constant :Formatter end PK% ]O3e: +gems/power_assert-1.1.3/lib/power_assert.rbnu[# power_assert.rb # # Copyright (C) 2014 Kazuki Tsujimoto begin unless defined?(Byebug) captured = false TracePoint.new(:return, :c_return) do |tp| captured = true unless tp.binding and tp.return_value raise '' end end.enable { __id__ } raise '' unless captured end rescue raise LoadError, 'Fully compatible TracePoint API required' end require 'power_assert/version' require 'power_assert/configuration' require 'power_assert/context' module PowerAssert POWER_ASSERT_LIB_DIR = File.dirname(caller_locations(1, 1).first.path) INTERNAL_LIB_DIRS = {PowerAssert => POWER_ASSERT_LIB_DIR} private_constant :POWER_ASSERT_LIB_DIR, :INTERNAL_LIB_DIRS # For backward compatibility IGNORED_LIB_DIRS = INTERNAL_LIB_DIRS private_constant :IGNORED_LIB_DIRS if respond_to?(:deprecate_constant) deprecate_constant :IGNORED_LIB_DIRS end class << self def start(assertion_proc_or_source, assertion_method: nil, source_binding: TOPLEVEL_BINDING) if respond_to?(:clear_global_method_cache, true) clear_global_method_cache end yield BlockContext.new(assertion_proc_or_source, assertion_method, source_binding) end def trace(frame) begin raise 'Byebug is not started yet' unless Byebug.started? rescue NameError raise "PowerAssert.#{__method__} requires Byebug" end ctx = TraceContext.new(frame._binding) ctx.enable ctx end def app_caller_locations caller_locations.drop_while {|i| internal_file?(i.path) }.take_while {|i| ! internal_file?(i.path) } end def app_context? top_frame = caller_locations.drop_while {|i| i.path.start_with?(POWER_ASSERT_LIB_DIR) }.first top_frame and ! internal_file?(top_frame.path) end private def internal_file?(file) setup_internal_lib_dir(Byebug, :attach, 2) if defined?(Byebug) setup_internal_lib_dir(PryByebug, :start_with_pry_byebug, 2, Pry) if defined?(PryByebug) INTERNAL_LIB_DIRS.find do |_, dir| file.start_with?(dir) end end def setup_internal_lib_dir(lib, mid, depth, lib_obj = lib) unless INTERNAL_LIB_DIRS.key?(lib) INTERNAL_LIB_DIRS[lib] = lib_dir(lib_obj, mid, depth) end rescue NameError end def lib_dir(obj, mid, depth) File.expand_path('../' * depth, obj.method(mid).source_location[0]) end if defined?(RubyVM) CLEAR_CACHE_ISEQ = RubyVM::InstructionSequence.compile('using PowerAssert.const_get(:Empty)') private_constant :CLEAR_CACHE_ISEQ def clear_global_method_cache CLEAR_CACHE_ISEQ.eval end end end module Empty end private_constant :Empty end PK% ]YE[hgems/rdoc-6.1.2.1/exe/rdocnuȯ#!/usr/bin/ruby # # RDoc: Documentation tool for source code # (see lib/rdoc/rdoc.rb for more information) # # Copyright (c) 2003 Dave Thomas # Released under the same terms as Ruby begin gem 'rdoc' rescue NameError => e # --disable-gems raise unless e.name == :gem rescue Gem::LoadError end require 'rdoc/rdoc' begin r = RDoc::RDoc.new r.document ARGV rescue Errno::ENOSPC $stderr.puts 'Ran out of space creating documentation' $stderr.puts $stderr.puts 'Please free up some space and try again' rescue SystemExit raise rescue Exception => e if $DEBUG_RDOC then $stderr.puts e.message $stderr.puts "#{e.backtrace.join "\n\t"}" $stderr.puts elsif Interrupt === e then $stderr.puts $stderr.puts 'Interrupted' else $stderr.puts "uh-oh! RDoc had a problem:" $stderr.puts e.message $stderr.puts $stderr.puts "run with --debug for full backtrace" end exit 1 end PK% ]ֳsgems/rdoc-6.1.2.1/exe/rinuȯ#!/usr/bin/ruby begin gem 'rdoc' rescue NameError => e # --disable-gems raise unless e.name == :gem rescue Gem::LoadError end require 'rdoc/ri/driver' RDoc::RI::Driver.run ARGV PK% ]z gems/rackup-2.1.0/license.mdnu[# MIT License Copyright, 2007-2009, by Leah Neukirchen. Copyright, 2008, by Marc-André Cournoyer. Copyright, 2009, by Aaron Pfeifer. Copyright, 2009-2010, by Megan Batty. Copyright, 2009-2010, by Michael Fellinger. Copyright, 2009, by Genki Takiuchi. Copyright, 2009, by Joshua Peek. Copyright, 2009, by Yehuda Katz + Carl Lerche. Copyright, 2009, by Carl Lerche. Copyright, 2010, by Julik Tarkhanov. Copyright, 2010-2016, by James Tucker. Copyright, 2010, by Timur Batyrshin. Copyright, 2010, by Loren Segal. Copyright, 2010, by Andrew Bortz. Copyright, 2010, by John Barnette. Copyright, 2010, by John Sumsion. Copyright, 2011-2018, by Aaron Patterson. Copyright, 2011, by Konstantin Haase. Copyright, 2011, by Blake Mizerany. Copyright, 2011, by Tsutomu Kuroda. Copyright, 2012, by Jean Boussier. Copyright, 2012, by Trevor Wennblom. Copyright, 2012, by Anurag Priyam. Copyright, 2012, by Hrvoje Šimić. Copyright, 2013, by Uchio KONDO. Copyright, 2013, by Tim Moore. Copyright, 2013, by Postmodern. Copyright, 2013, by Bas Vodde. Copyright, 2013, by Joe Fiorini. Copyright, 2014, by Wyatt Pan. Copyright, 2014, by Lenny Marks. Copyright, 2014, by Igor Bochkariov. Copyright, 2014, by Max Cantor. Copyright, 2014, by David Celis. Copyright, 2014, by Rafael Mendonça França. Copyright, 2014, by Jeremy Kemper. Copyright, 2014, by Richard Schneeman. Copyright, 2015, by Peter Wilmott. Copyright, 2015, by Sean McGivern. Copyright, 2015, by Tadashi Saito. Copyright, 2015, by deepj. Copyright, 2015, by Zachary Scott. Copyright, 2016, by Sophie Deziel. Copyright, 2016, by Kazuya Hotta. Copyright, 2017, by Ryunosuke Sato. Copyright, 2017-2023, by Samuel Williams. Copyright, 2018, by Dillon Welch. Copyright, 2018, by Yoshiyuki Hirano. Copyright, 2018, by Nick LaMuro. Copyright, 2019, by Rafael França. Copyright, 2019, by Krzysztof Rybka. Copyright, 2019, by Misaki Shioi. Copyright, 2020-2022, by Jeremy Evans. Copyright, 2021, by Katsuhiko YOSHIDA. Copyright, 2021, by KS. Copyright, 2021, by Stephen Paul Weber. Copyright, 2022, by Akira Matsuda. Copyright, 2022, by Andrew Hoglund. 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. PK% ]<dgems/rackup-2.1.0/readme.mdnu[# Rackup `rackup` provides a command line interface for running a Rack-compatible application. [![Development Status](https://github.com/rack/rackup/workflows/Test/badge.svg)](https://github.com/rack/rackup/actions?workflow=Test) ## Installation ``` bash $ gem install rackup ``` ## Usage In a directory with your `config.ru` simply run the command: ``` bash $ rackup ``` Your application should now be available locally, typically `http://localhost:9292`. ## Contributing We welcome contributions to this project. 1. Fork it. 2. Create your feature branch (`git checkout -b my-new-feature`). 3. Commit your changes (`git commit -am 'Add some feature'`). 4. Push to the branch (`git push origin my-new-feature`). 5. Create new Pull Request. PK% ]ǻiigems/rackup-2.1.0/bin/rackupnuȯ#!/usr/bin/env ruby # frozen_string_literal: true require_relative "../lib/rackup" Rackup::Server.start PK% ]e eegems/rackup-2.1.0/security.mdnu[# Security Policy Please see our main security policy: https://github.com/rack/rack/security/policy PK% ]/:44&gems/rackup-2.1.0/lib/rackup/server.rbnu[# frozen_string_literal: true # Released under the MIT License. # Copyright, 2022-2023, by Samuel Williams. require 'optparse' require 'fileutils' require 'rack/builder' require 'rack/common_logger' require 'rack/content_length' require 'rack/show_exceptions' require 'rack/lint' require 'rack/tempfile_reaper' require 'rack/version' require_relative 'version' require_relative 'handler' module Rackup class Server class Options def parse!(args) options = {} opt_parser = OptionParser.new("", 24, ' ') do |opts| opts.banner = "Usage: rackup [ruby options] [rack options] [rackup config]" opts.separator "" opts.separator "Ruby options:" lineno = 1 opts.on("-e", "--eval LINE", "evaluate a LINE of code") { |line| eval line, TOPLEVEL_BINDING, "-e", lineno lineno += 1 } opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") { options[:debug] = true } opts.on("-w", "--warn", "turn warnings on for your script") { options[:warn] = true } opts.on("-q", "--quiet", "turn off logging") { options[:quiet] = true } opts.on("-I", "--include PATH", "specify $LOAD_PATH (may be used more than once)") { |path| (options[:include] ||= []).concat(path.split(":")) } opts.on("-r", "--require LIBRARY", "require the library, before executing your script") { |library| (options[:require] ||= []) << library } opts.separator "" opts.separator "Rack options:" opts.on("-b", "--builder BUILDER_LINE", "evaluate a BUILDER_LINE of code as a builder script") { |line| options[:builder] = line } opts.on("-s", "--server SERVER", "serve using SERVER (thin/puma/webrick)") { |s| options[:server] = s } opts.on("-o", "--host HOST", "listen on HOST (default: localhost)") { |host| options[:Host] = host } opts.on("-p", "--port PORT", "use PORT (default: 9292)") { |port| options[:Port] = port } opts.on("-O", "--option NAME[=VALUE]", "pass VALUE to the server as option NAME. If no VALUE, sets it to true. Run '#{$0} -s SERVER -h' to get a list of options for SERVER") { |name| name, value = name.split('=', 2) value = true if value.nil? options[name.to_sym] = value } opts.on("-E", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: development)") { |e| options[:environment] = e } opts.on("-D", "--daemonize", "run daemonized in the background") { |d| options[:daemonize] ||= true } opts.on("--daemonize-noclose", "run daemonized in the background without closing stdout/stderr") { options[:daemonize] = :noclose } opts.on("-P", "--pid FILE", "file to store PID") { |f| options[:pid] = ::File.expand_path(f) } opts.separator "" opts.separator "Profiling options:" opts.on("--heap HEAPFILE", "Build the application, then dump the heap to HEAPFILE") do |e| options[:heapfile] = e end opts.on("--profile PROFILE", "Dump CPU or Memory profile to PROFILE (defaults to a tempfile)") do |e| options[:profile_file] = e end opts.on("--profile-mode MODE", "Profile mode (cpu|wall|object)") do |e| unless %w[cpu wall object].include?(e) raise OptionParser::InvalidOption, "unknown profile mode: #{e}" end options[:profile_mode] = e.to_sym end opts.separator "" opts.separator "Common options:" opts.on_tail("-h", "-?", "--help", "Show this message") do puts opts puts handler_opts(options) exit end opts.on_tail("--version", "Show version") do puts "Rack #{Rack::RELEASE}" exit end end begin opt_parser.parse! args rescue OptionParser::InvalidOption => e warn e.message abort opt_parser.to_s end options[:config] = args.last if args.last && !args.last.empty? options end def handler_opts(options) info = [] server = Rackup::Handler.get(options[:server]) || Rackup::Handler.default if server && server.respond_to?(:valid_options) info << "" info << "Server-specific options for #{server.name}:" has_options = false server.valid_options.each do |name, description| next if /^(Host|Port)[^a-zA-Z]/.match?(name.to_s) # ignore handler's host and port options, we do our own. info << sprintf(" -O %-21s %s", name, description) has_options = true end return "" if !has_options end info.join("\n") rescue NameError, LoadError return "Warning: Could not find handler specified (#{options[:server] || 'default'}) to determine handler-specific options" end end # Start a new rack server (like running rackup). This will parse ARGV and # provide standard ARGV rackup options, defaulting to load 'config.ru'. # # Providing an options hash will prevent ARGV parsing and will not include # any default options. # # This method can be used to very easily launch a CGI application, for # example: # # Rack::Server.start( # :app => lambda do |e| # [200, {'content-type' => 'text/html'}, ['hello world']] # end, # :server => 'cgi' # ) # # Further options available here are documented on Rack::Server#initialize def self.start(options = nil) new(options).start end attr_writer :options # Options may include: # * :app # a rack application to run (overrides :config and :builder) # * :builder # a string to evaluate a Rack::Builder from # * :config # a rackup configuration file path to load (.ru) # * :environment # this selects the middleware that will be wrapped around # your application. Default options available are: # - development: CommonLogger, ShowExceptions, and Lint # - deployment: CommonLogger # - none: no extra middleware # note: when the server is a cgi server, CommonLogger is not included. # * :server # choose a specific Rackup::Handler, e.g. cgi, fcgi, webrick # * :daemonize # if truthy, the server will daemonize itself (fork, detach, etc) # if :noclose, the server will not close STDOUT/STDERR # * :pid # path to write a pid file after daemonize # * :Host # the host address to bind to (used by supporting Rackup::Handler) # * :Port # the port to bind to (used by supporting Rackup::Handler) # * :AccessLog # webrick access log options (or supporting Rackup::Handler) # * :debug # turn on debug output ($DEBUG = true) # * :warn # turn on warnings ($-w = true) # * :include # add given paths to $LOAD_PATH # * :require # require the given libraries # # Additional options for profiling app initialization include: # * :heapfile # location for ObjectSpace.dump_all to write the output to # * :profile_file # location for CPU/Memory (StackProf) profile output (defaults to a tempfile) # * :profile_mode # StackProf profile mode (cpu|wall|object) def initialize(options = nil) @ignore_options = [] if options @use_default_options = false @options = options @app = options[:app] if options[:app] else @use_default_options = true @options = parse_options(ARGV) end end def options merged_options = @use_default_options ? default_options.merge(@options) : @options merged_options.reject { |k, v| @ignore_options.include?(k) } end def default_options environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : '0.0.0.0' { environment: environment, pid: nil, Port: 9292, Host: default_host, AccessLog: [], config: "config.ru" } end def app @app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config end class << self def logging_middleware lambda { |server| /CGI/.match?(server.server.name) || server.options[:quiet] ? nil : [Rack::CommonLogger, $stderr] } end def default_middleware_by_environment m = Hash.new {|h, k| h[k] = []} m["deployment"] = [ [Rack::ContentLength], logging_middleware, [Rack::TempfileReaper] ] m["development"] = [ [Rack::ContentLength], logging_middleware, [Rack::ShowExceptions], [Rack::Lint], [Rack::TempfileReaper] ] m end def middleware default_middleware_by_environment end end def middleware self.class.middleware end def start(&block) if options[:warn] $-w = true end if includes = options[:include] $LOAD_PATH.unshift(*includes) end Array(options[:require]).each do |library| require library end if options[:debug] $DEBUG = true require 'pp' p options[:server] pp wrapped_app pp app end check_pid! if options[:pid] # Touch the wrapped app, so that the config.ru is loaded before # daemonization (i.e. before chdir, etc). handle_profiling(options[:heapfile], options[:profile_mode], options[:profile_file]) do wrapped_app end daemonize_app if options[:daemonize] write_pid if options[:pid] trap(:INT) do if server.respond_to?(:shutdown) server.shutdown else exit end end server.run(wrapped_app, **options, &block) end def server @_server ||= Handler.get(options[:server]) || Handler.default end private def build_app_and_options_from_config if !::File.exist? options[:config] abort "configuration #{options[:config]} not found" end return Rack::Builder.parse_file(self.options[:config]) end def handle_profiling(heapfile, profile_mode, filename) if heapfile require "objspace" ObjectSpace.trace_object_allocations_start yield GC.start ::File.open(heapfile, "w") { |f| ObjectSpace.dump_all(output: f) } exit end if profile_mode require "stackprof" require "tempfile" make_profile_name(filename) do |filename| ::File.open(filename, "w") do |f| StackProf.run(mode: profile_mode, out: f) do yield end puts "Profile written to: #{filename}" end end exit end yield end def make_profile_name(filename) if filename yield filename else ::Dir::Tmpname.create("profile.dump") do |tmpname, _, _| yield tmpname end end end def build_app_from_string Rack::Builder.new_from_string(self.options[:builder]) end def parse_options(args) # Don't evaluate CGI ISINDEX parameters. args.clear if ENV.include?(Rack::REQUEST_METHOD) @options = opt_parser.parse!(args) @options[:config] = ::File.expand_path(options[:config]) ENV["RACK_ENV"] = options[:environment] @options end def opt_parser Options.new end def build_app(app) middleware[options[:environment]].reverse_each do |middleware| middleware = middleware.call(self) if middleware.respond_to?(:call) next unless middleware klass, *args = middleware app = klass.new(app, *args) end app end def wrapped_app @wrapped_app ||= build_app app end def daemonize_app # Cannot be covered as it forks # :nocov: Process.daemon(true, options[:daemonize] == :noclose) # :nocov: end def write_pid ::File.open(options[:pid], ::File::CREAT | ::File::EXCL | ::File::WRONLY ){ |f| f.write("#{Process.pid}") } at_exit { ::FileUtils.rm_f(options[:pid]) } rescue Errno::EEXIST check_pid! retry end def check_pid! return unless ::File.exist?(options[:pid]) pid = ::File.read(options[:pid]).to_i raise Errno::ESRCH if pid == 0 Process.kill(0, pid) exit_with_pid(pid) rescue Errno::ESRCH ::File.delete(options[:pid]) rescue Errno::EPERM exit_with_pid(pid) end def exit_with_pid(pid) $stderr.puts "A server is already running (pid: #{pid}, file: #{options[:pid]})." exit(1) end end end PK% ]'gems/rackup-2.1.0/lib/rackup/lobster.rbnu[# frozen_string_literal: true # Released under the MIT License. # Copyright, 2022-2023, by Samuel Williams. require 'zlib' require 'rack/constants' require 'rack/request' require 'rack/response' module Rackup # Paste has a Pony, Rack has a Lobster! class Lobster include Rack LobsterString = Zlib::Inflate.inflate("eJx9kEEOwyAMBO99xd7MAcytUhPlJyj2 P6jy9i4k9EQyGAnBarEXeCBqSkntNXsi/ZCvC48zGQoZKikGrFMZvgS5ZHd+aGWVuWwhVF0 t1drVmiR42HcWNz5w3QanT+2gIvTVCiE1lm1Y0eU4JGmIIbaKwextKn8rvW+p5PIwFl8ZWJ I8jyiTlhTcYXkekJAzTyYN6E08A+dk8voBkAVTJQ==".delete("\n ").unpack("m*")[0]) LambdaLobster = lambda { |env| if env[QUERY_STRING].include?("flip") lobster = LobsterString.split("\n"). map { |line| line.ljust(42).reverse }. join("\n") href = "?" else lobster = LobsterString href = "?flip" end content = ["Lobstericious!", "
", lobster, "
", "flip!"] length = content.inject(0) { |a, e| a + e.size }.to_s [200, { CONTENT_TYPE => "text/html", CONTENT_LENGTH => length }, content] } def call(env) req = Request.new(env) if req.GET["flip"] == "left" lobster = LobsterString.split("\n").map do |line| line.ljust(42).reverse. gsub('\\', 'TEMP'). gsub('/', '\\'). gsub('TEMP', '/'). gsub('{', '}'). gsub('(', ')') end.join("\n") href = "?flip=right" elsif req.GET["flip"] == "crash" raise "Lobster crashed" else lobster = LobsterString href = "?flip=left" end res = Response.new res.write "Lobstericious!" res.write "
"
      res.write lobster
      res.write "
" res.write "

flip!

" res.write "

crash!

" res.finish end end end if $0 == __FILE__ # :nocov: require_relative 'server' require_relative 'show_exceptions' require_relative 'lint' Rackup::Server.start( app: Rack::ShowExceptions.new(Rack::Lint.new(Rackup::Lobster.new)), Port: 9292 ) # :nocov: end PK% ]F; ; 'gems/rackup-2.1.0/lib/rackup/handler.rbnu[# frozen_string_literal: true # Released under the MIT License. # Copyright, 2022-2023, by Samuel Williams. module Rackup # *Handlers* connect web servers with Rack. # # Rackup includes Handlers for WEBrick and CGI. # # Handlers usually are activated by calling MyHandler.run(myapp). # A second optional hash can be passed to include server-specific # configuration. module Handler @handlers = {} # Register a named handler class. def self.register(name, klass) if klass.is_a?(String) warn "Calling Rackup::Handler.register with a string is deprecated, use the class/module itself.", uplevel: 1 klass = self.const_get(klass, false) end name = name.to_sym @handlers[name] = klass end def self.[](name) name = name.to_sym begin @handlers[name] || self.const_get(name, false) rescue NameError # Ignore. end end def self.get(name) return nil unless name name = name.to_sym if server = self[name] return server end begin require_handler("rackup/handler", name) rescue LoadError require_handler("rack/handler", name) end return self[name] end RACK_HANDLER = 'RACK_HANDLER' RACKUP_HANDLER = 'RACKUP_HANDLER' SERVER_NAMES = %i(puma falcon webrick).freeze private_constant :SERVER_NAMES # Select first available Rack handler given an `Array` of server names. # Raises `LoadError` if no handler was found. # # > pick ['puma', 'webrick'] # => Rackup::Handler::WEBrick def self.pick(server_names) server_names = Array(server_names) server_names.each do |server_name| begin server = self.get(server_name) return server if server rescue LoadError # Ignore. end end raise LoadError, "Couldn't find handler for: #{server_names.join(', ')}." end def self.default if rack_handler = ENV[RACKUP_HANDLER] self.get(rack_handler) elsif rack_handler = ENV[RACK_HANDLER] warn "RACK_HANDLER is deprecated, use RACKUP_HANDLER." self.get(rack_handler) else pick SERVER_NAMES end end # Transforms server-name constants to their canonical form as filenames, # then tries to require them but silences the LoadError if not found # # Naming convention: # # Foo # => 'foo' # FooBar # => 'foo_bar.rb' # FooBAR # => 'foobar.rb' # FOObar # => 'foobar.rb' # FOOBAR # => 'foobar.rb' # FooBarBaz # => 'foo_bar_baz.rb' def self.require_handler(prefix, const_name) file = const_name.to_s.gsub(/^[A-Z]+/) { |pre| pre.downcase }. gsub(/[A-Z]+[^A-Z]/, '_\&').downcase require(::File.join(prefix, file)) end end end PK% ]cϛ'gems/rackup-2.1.0/lib/rackup/version.rbnu[# frozen_string_literal: true # Released under the MIT License. # Copyright, 2022-2023, by Samuel Williams. module Rackup VERSION = "2.1.0" end PK% ]|/gems/rackup-2.1.0/lib/rackup/handler/webrick.rbnu[# frozen_string_literal: true # Released under the MIT License. # Copyright, 2022-2023, by Samuel Williams. # Copyright, 2022, by Jeremy Evans. require 'webrick' require 'stringio' require 'rack/constants' require_relative '../handler' require_relative '../version' require_relative '../stream' module Rackup module Handler class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet def self.run(app, **options) environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : nil if !options[:BindAddress] || options[:Host] options[:BindAddress] = options.delete(:Host) || default_host end options[:Port] ||= 8080 if options[:SSLEnable] require 'webrick/https' end @server = ::WEBrick::HTTPServer.new(options) @server.mount "/", Rackup::Handler::WEBrick, app yield @server if block_given? @server.start end def self.valid_options environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : '0.0.0.0' { "Host=HOST" => "Hostname to listen on (default: #{default_host})", "Port=PORT" => "Port to listen on (default: 8080)", } end def self.shutdown if @server @server.shutdown @server = nil end end def initialize(server, app) super server @app = app end # This handles mapping the WEBrick request to a Rack input stream. class Input include Stream::Reader def initialize(request) @request = request @reader = Fiber.new do @request.body do |chunk| Fiber.yield(chunk) end Fiber.yield(nil) # End of stream: @reader = nil end end def close @request = nil @reader = nil end private # Read one chunk from the request body. def read_next @reader&.resume end end def service(req, res) env = req.meta_vars env.delete_if { |k, v| v.nil? } input = Input.new(req) env.update( ::Rack::RACK_INPUT => input, ::Rack::RACK_ERRORS => $stderr, ::Rack::RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[::Rack::HTTPS]) ? "https" : "http", ::Rack::RACK_IS_HIJACK => true, ) env[::Rack::QUERY_STRING] ||= "" unless env[::Rack::PATH_INFO] == "" path, n = req.request_uri.path, env[::Rack::SCRIPT_NAME].length env[::Rack::PATH_INFO] = path[n, path.length - n] end env[::Rack::REQUEST_PATH] ||= [env[::Rack::SCRIPT_NAME], env[::Rack::PATH_INFO]].join status, headers, body = @app.call(env) begin res.status = status if value = headers[::Rack::RACK_HIJACK] io_lambda = value body = nil elsif !body.respond_to?(:to_path) && !body.respond_to?(:each) io_lambda = body body = nil end if value = headers.delete('set-cookie') res.cookies.concat(Array(value)) end headers.each do |key, value| # Skip keys starting with rack., per Rack SPEC next if key.start_with?('rack.') # Since WEBrick won't accept repeated headers, # merge the values per RFC 1945 section 4.2. value = value.join(", ") if Array === value res[key] = value end if io_lambda protocol = headers['rack.protocol'] || headers['upgrade'] if protocol # Set all the headers correctly for an upgrade response: res.upgrade!(protocol) end res.body = io_lambda elsif body.respond_to?(:to_path) res.body = ::File.open(body.to_path, 'rb') else buffer = String.new body.each do |part| buffer << part end res.body = buffer end ensure body.close if body.respond_to?(:close) end end end register :webrick, WEBrick end end PK% ]HH+gems/rackup-2.1.0/lib/rackup/handler/cgi.rbnu[# frozen_string_literal: true # Released under the MIT License. # Copyright, 2022-2023, by Samuel Williams. module Rackup module Handler class CGI include Rack def self.run(app, **options) $stdin.binmode serve app end def self.serve(app) env = ENV.to_hash env.delete "HTTP_CONTENT_LENGTH" env[SCRIPT_NAME] = "" if env[SCRIPT_NAME] == "/" env.update( RACK_INPUT => $stdin, RACK_ERRORS => $stderr, RACK_URL_SCHEME => ["yes", "on", "1"].include?(ENV[HTTPS]) ? "https" : "http" ) env[QUERY_STRING] ||= "" env[REQUEST_PATH] ||= "/" status, headers, body = app.call(env) begin send_headers status, headers send_body body ensure body.close if body.respond_to? :close end end def self.send_headers(status, headers) $stdout.print "Status: #{status}\r\n" headers.each { |k, vs| vs.split("\n").each { |v| $stdout.print "#{k}: #{v}\r\n" } } $stdout.print "\r\n" $stdout.flush end def self.send_body(body) body.each { |part| $stdout.print part $stdout.flush } end end register :cgi, CGI end end PK% ]lo| &gems/rackup-2.1.0/lib/rackup/stream.rbnu[# frozen_string_literal: true # Released under the MIT License. # Copyright, 2019-2022, by Samuel Williams. module Rackup # The input stream is an IO-like object which contains the raw HTTP POST data. When applicable, its external encoding must be “ASCII-8BIT” and it must be opened in binary mode, for Ruby 1.9 compatibility. The input stream must respond to gets, each, read and rewind. class Stream def initialize(input = nil, output = Buffered.new) @input = input @output = output raise ArgumentError, "Non-writable output!" unless output.respond_to?(:write) # Will hold remaining data in `#read`. @buffer = nil @closed = false end attr :input attr :output # This provides a read-only interface for data, which is surprisingly tricky to implement correctly. module Reader # rack.hijack_io must respond to: # read, write, read_nonblock, write_nonblock, flush, close, close_read, close_write, closed? # read behaves like IO#read. Its signature is read([length, [buffer]]). If given, length must be a non-negative Integer (>= 0) or nil, and buffer must be a String and may not be nil. If length is given and not nil, then this method reads at most length bytes from the input stream. If length is not given or nil, then this method reads all data until EOF. When EOF is reached, this method returns nil if length is given and not nil, or “” if length is not given or is nil. If buffer is given, then the read data will be placed into buffer instead of a newly created String object. # @param length [Integer] the amount of data to read # @param buffer [String] the buffer which will receive the data # @return a buffer containing the data def read(length = nil, buffer = nil) return '' if length == 0 buffer ||= String.new.force_encoding(Encoding::BINARY) # Take any previously buffered data and replace it into the given buffer. if @buffer buffer.replace(@buffer) @buffer = nil else buffer.clear end if length while buffer.bytesize < length and chunk = read_next buffer << chunk end # This ensures the subsequent `slice!` works correctly. buffer.force_encoding(Encoding::BINARY) # This will be at least one copy: @buffer = buffer.byteslice(length, buffer.bytesize) # This should be zero-copy: buffer.slice!(length, buffer.bytesize) if buffer.empty? return nil else return buffer end else while chunk = read_next buffer << chunk end return buffer end end # Read at most `length` bytes from the stream. Will avoid reading from the underlying stream if possible. def read_partial(length = nil) if @buffer buffer = @buffer @buffer = nil else buffer = read_next end if buffer and length if buffer.bytesize > length # This ensures the subsequent `slice!` works correctly. buffer.force_encoding(Encoding::BINARY) @buffer = buffer.byteslice(length, buffer.bytesize) buffer.slice!(length, buffer.bytesize) end end return buffer end def gets read_partial end def each while chunk = read_partial yield chunk end end def read_nonblock(length, buffer = nil) @buffer ||= read_next chunk = nil unless @buffer buffer&.clear return end if @buffer.bytesize > length chunk = @buffer.byteslice(0, length) @buffer = @buffer.byteslice(length, @buffer.bytesize) else chunk = @buffer @buffer = nil end if buffer buffer.replace(chunk) else buffer = chunk end return buffer end end include Reader def write(buffer) if @output @output.write(buffer) return buffer.bytesize else raise IOError, "Stream is not writable, output has been closed!" end end def write_nonblock(buffer) write(buffer) end def <<(buffer) write(buffer) end def flush end def close_read @input&.close @input = nil end # close must never be called on the input stream. huh? def close_write if @output.respond_to?(:close) @output&.close end @output = nil end # Close the input and output bodies. def close(error = nil) self.close_read self.close_write return nil ensure @closed = true end # Whether the stream has been closed. def closed? @closed end # Whether there are any output chunks remaining? def empty? @output.empty? end private def read_next if @input return @input.read else @input = nil raise IOError, "Stream is not readable, input has been closed!" end end end end PK% ]9$$gems/rackup-2.1.0/lib/rackup.rbnu[# frozen_string_literal: true # Released under the MIT License. # Copyright, 2022-2023, by Samuel Williams. require_relative 'rackup/handler' require_relative 'rackup/server' require_relative 'rackup/version' require_relative 'rackup/handler/webrick' require_relative 'rackup/handler/cgi' PK% ]G TTgems/rack-3.0.8/MIT-LICENSEnu[The MIT License (MIT) Copyright (C) 2007-2021 Leah Neukirchen 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 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. PK% ]==gems/rack-3.0.8/SPEC.rdocnu[This specification aims to formalize the Rack protocol. You can (and should) use Rack::Lint to enforce it. When you develop middleware, be sure to add a Lint before and after to catch all mistakes. = Rack applications A Rack application is a Ruby object (not a class) that responds to +call+. It takes exactly one argument, the *environment* and returns a non-frozen Array of exactly three values: The *status*, the *headers*, and the *body*. == The Environment The environment must be an unfrozen instance of Hash that includes CGI-like headers. The Rack application is free to modify the environment. The environment is required to include these variables (adopted from {PEP 333}[https://peps.python.org/pep-0333/]), except when they'd be empty, but see below. REQUEST_METHOD:: The HTTP request method, such as "GET" or "POST". This cannot ever be an empty string, and so is always required. SCRIPT_NAME:: The initial portion of the request URL's "path" that corresponds to the application object, so that the application knows its virtual "location". This may be an empty string, if the application corresponds to the "root" of the server. PATH_INFO:: The remainder of the request URL's "path", designating the virtual "location" of the request's target within the application. This may be an empty string, if the request URL targets the application root and does not have a trailing slash. This value may be percent-encoded when originating from a URL. QUERY_STRING:: The portion of the request URL that follows the ?, if any. May be empty, but is always required! SERVER_NAME:: When combined with SCRIPT_NAME and PATH_INFO, these variables can be used to complete the URL. Note, however, that HTTP_HOST, if present, should be used in preference to SERVER_NAME for reconstructing the request URL. SERVER_NAME can never be an empty string, and so is always required. SERVER_PORT:: An optional +Integer+ which is the port the server is running on. Should be specified if the server is running on a non-standard port. SERVER_PROTOCOL:: A string representing the HTTP version used for the request. HTTP_ Variables:: Variables corresponding to the client-supplied HTTP request headers (i.e., variables whose names begin with HTTP_). The presence or absence of these variables should correspond with the presence or absence of the appropriate HTTP header in the request. See {RFC3875 section 4.1.18}[https://tools.ietf.org/html/rfc3875#section-4.1.18] for specific behavior. In addition to this, the Rack environment must include these Rack-specific variables: rack.url_scheme:: +http+ or +https+, depending on the request URL. rack.input:: See below, the input stream. rack.errors:: See below, the error stream. rack.hijack?:: See below, if present and true, indicates that the server supports partial hijacking. rack.hijack:: See below, if present, an object responding to +call+ that is used to perform a full hijack. Additional environment specifications have approved to standardized middleware APIs. None of these are required to be implemented by the server. rack.session:: A hash-like interface for storing request session data. The store must implement: store(key, value) (aliased as []=); fetch(key, default = nil) (aliased as []); delete(key); clear; to_hash (returning unfrozen Hash instance); rack.logger:: A common object interface for logging messages. The object must implement: info(message, &block) debug(message, &block) warn(message, &block) error(message, &block) fatal(message, &block) rack.multipart.buffer_size:: An Integer hint to the multipart parser as to what chunk size to use for reads and writes. rack.multipart.tempfile_factory:: An object responding to #call with two arguments, the filename and content_type given for the multipart form field, and returning an IO-like object that responds to #<< and optionally #rewind. This factory will be used to instantiate the tempfile for each multipart form file upload field, rather than the default class of Tempfile. The server or the application can store their own data in the environment, too. The keys must contain at least one dot, and should be prefixed uniquely. The prefix rack. is reserved for use with the Rack core distribution and other accepted specifications and must not be used otherwise. The SERVER_PORT must be an Integer if set. The SERVER_NAME must be a valid authority as defined by RFC7540. The HTTP_HOST must be a valid authority as defined by RFC7540. The SERVER_PROTOCOL must match the regexp HTTP/\d(\.\d)?. If the HTTP_VERSION is present, it must equal the SERVER_PROTOCOL. The environment must not contain the keys HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH (use the versions without HTTP_). The CGI keys (named without a period) must have String values. If the string values for CGI keys contain non-ASCII characters, they should use ASCII-8BIT encoding. There are the following restrictions: * rack.url_scheme must either be +http+ or +https+. * There must be a valid input stream in rack.input. * There must be a valid error stream in rack.errors. * There may be a valid hijack callback in rack.hijack * The REQUEST_METHOD must be a valid token. * The SCRIPT_NAME, if non-empty, must start with / * The PATH_INFO, if non-empty, must start with / * The CONTENT_LENGTH, if given, must consist of digits only. * One of SCRIPT_NAME or PATH_INFO must be set. PATH_INFO should be / if SCRIPT_NAME is empty. SCRIPT_NAME never should be /, but instead be empty. rack.response_finished:: An array of callables run by the server after the response has been processed. This would typically be invoked after sending the response to the client, but it could also be invoked if an error occurs while generating the response or sending the response; in that case, the error argument will be a subclass of +Exception+. The callables are invoked with +env, status, headers, error+ arguments and should not raise any exceptions. They should be invoked in reverse order of registration. === The Input Stream The input stream is an IO-like object which contains the raw HTTP POST data. When applicable, its external encoding must be "ASCII-8BIT" and it must be opened in binary mode, for Ruby 1.9 compatibility. The input stream must respond to +gets+, +each+, and +read+. * +gets+ must be called without arguments and return a string, or +nil+ on EOF. * +read+ behaves like IO#read. Its signature is read([length, [buffer]]). If given, +length+ must be a non-negative Integer (>= 0) or +nil+, and +buffer+ must be a String and may not be nil. If +length+ is given and not nil, then this method reads at most +length+ bytes from the input stream. If +length+ is not given or nil, then this method reads all data until EOF. When EOF is reached, this method returns nil if +length+ is given and not nil, or "" if +length+ is not given or is nil. If +buffer+ is given, then the read data will be placed into +buffer+ instead of a newly created String object. * +each+ must be called without arguments and only yield Strings. * +close+ can be called on the input stream to indicate that the any remaining input is not needed. === The Error Stream The error stream must respond to +puts+, +write+ and +flush+. * +puts+ must be called with a single argument that responds to +to_s+. * +write+ must be called with a single argument that is a String. * +flush+ must be called without arguments and must be called in order to make the error appear for sure. * +close+ must never be called on the error stream. === Hijacking The hijacking interfaces provides a means for an application to take control of the HTTP connection. There are two distinct hijack interfaces: full hijacking where the application takes over the raw connection, and partial hijacking where the application takes over just the response body stream. In both cases, the application is responsible for closing the hijacked stream. Full hijacking only works with HTTP/1. Partial hijacking is functionally equivalent to streaming bodies, and is still optionally supported for backwards compatibility with older Rack versions. ==== Full Hijack Full hijack is used to completely take over an HTTP/1 connection. It occurs before any headers are written and causes the request to ignores any response generated by the application. It is intended to be used when applications need access to raw HTTP/1 connection. If +rack.hijack+ is present in +env+, it must respond to +call+ and return an +IO+ instance which can be used to read and write to the underlying connection using HTTP/1 semantics and formatting. ==== Partial Hijack Partial hijack is used for bi-directional streaming of the request and response body. It occurs after the status and headers are written by the server and causes the server to ignore the Body of the response. It is intended to be used when applications need bi-directional streaming. If +rack.hijack?+ is present in +env+ and truthy, an application may set the special response header +rack.hijack+ to an object that responds to +call+, accepting a +stream+ argument. After the response status and headers have been sent, this hijack callback will be invoked with a +stream+ argument which follows the same interface as outlined in "Streaming Body". Servers must ignore the +body+ part of the response tuple when the +rack.hijack+ response header is present. Using an empty +Array+ instance is recommended. The special response header +rack.hijack+ must only be set if the request +env+ has a truthy +rack.hijack?+. == The Response === The Status This is an HTTP status. It must be an Integer greater than or equal to 100. === The Headers The headers must be a unfrozen Hash. The header keys must be Strings. Special headers starting "rack." are for communicating with the server, and must not be sent back to the client. The header must not contain a +Status+ key. Header keys must conform to RFC7230 token specification, i.e. cannot contain non-printable ASCII, DQUOTE or "(),/:;<=>?@[\]{}". Header keys must not contain uppercase ASCII characters (A-Z). Header values must be either a String instance, or an Array of String instances, such that each String instance must not contain characters below 037. === The content-type There must not be a content-type header key when the +Status+ is 1xx, 204, or 304. === The content-length There must not be a content-length header key when the +Status+ is 1xx, 204, or 304. === The Body The Body is typically an +Array+ of +String+ instances, an enumerable that yields +String+ instances, a +Proc+ instance, or a File-like object. The Body must respond to +each+ or +call+. It may optionally respond to +to_path+ or +to_ary+. A Body that responds to +each+ is considered to be an Enumerable Body. A Body that responds to +call+ is considered to be a Streaming Body. A Body that responds to both +each+ and +call+ must be treated as an Enumerable Body, not a Streaming Body. If it responds to +each+, you must call +each+ and not +call+. If the Body doesn't respond to +each+, then you can assume it responds to +call+. The Body must either be consumed or returned. The Body is consumed by optionally calling either +each+ or +call+. Then, if the Body responds to +close+, it must be called to release any resources associated with the generation of the body. In other words, +close+ must always be called at least once; typically after the web server has sent the response to the client, but also in cases where the Rack application makes internal/virtual requests and discards the response. After calling +close+, the Body is considered closed and should not be consumed again. If the original Body is replaced by a new Body, the new Body must also consume the original Body by calling +close+ if possible. If the Body responds to +to_path+, it must return a +String+ path for the local file system whose contents are identical to that produced by calling +each+; this may be used by the server as an alternative, possibly more efficient way to transport the response. The +to_path+ method does not consume the body. ==== Enumerable Body The Enumerable Body must respond to +each+. It must only be called once. It must not be called after being closed. and must only yield String values. The Body itself should not be an instance of String, as this will break in Ruby 1.9. Middleware must not call +each+ directly on the Body. Instead, middleware can return a new Body that calls +each+ on the original Body, yielding at least once per iteration. If the Body responds to +to_ary+, it must return an +Array+ whose contents are identical to that produced by calling +each+. Middleware may call +to_ary+ directly on the Body and return a new Body in its place. In other words, middleware can only process the Body directly if it responds to +to_ary+. If the Body responds to both +to_ary+ and +close+, its implementation of +to_ary+ must call +close+. ==== Streaming Body The Streaming Body must respond to +call+. It must only be called once. It must not be called after being closed. It takes a +stream+ argument. The +stream+ argument must implement: read, write, <<, flush, close, close_read, close_write, closed? The semantics of these IO methods must be a best effort match to those of a normal Ruby IO or Socket object, using standard arguments and raising standard exceptions. Servers are encouraged to simply pass on real IO objects, although it is recognized that this approach is not directly compatible with HTTP/2. == Thanks Some parts of this specification are adopted from {PEP 333 – Python Web Server Gateway Interface v1.0}[https://peps.python.org/pep-0333/] I'd like to thank everyone involved in that effort. PK% ]t2gems/rack-3.0.8/CHANGELOG.mdnu[# Changelog All notable changes to this project will be documented in this file. For info on how to format all future additions to this file please reference [Keep A Changelog](https://keepachangelog.com/en/1.0.0/). ## [3.0.7] - 2023-03-16 - Make query parameters without `=` have `nil` values. ([#2059](https://github.com/rack/rack/pull/2059), [@jeremyevans]) ## [3.0.6.1] - 2023-03-13 - [CVE-2023-27539] Avoid ReDoS in header parsing ## [3.0.6] - 2023-03-13 - Add `QueryParser#missing_value` for handling missing values + tests. ([#2052](https://github.com/rack/rack/pull/2052), [@ioquatix]) ## [3.0.5] - 2023-03-13 - Split form/query parsing into two steps. ([#2038](https://github.com/rack/rack/pull/2038), [@matthewd](https://github.com/matthewd)) ## [3.0.4.1] - 2023-03-02 - [CVE-2023-27530] Introduce multipart_total_part_limit to limit total parts ## [3.0.4.1] - 2023-01-17 - [CVE-2022-44571] Fix ReDoS vulnerability in multipart parser - [CVE-2022-44570] Fix ReDoS in Rack::Utils.get_byte_ranges - [CVE-2022-44572] Forbid control characters in attributes (also ReDoS) ## [3.0.4] - 2023-01-17 - `Rack::Request#POST` should consistently raise errors. Cache errors that occur when invoking `Rack::Request#POST` so they can be raised again later. ([#2010](https://github.com/rack/rack/pull/2010), [@ioquatix]) - Fix `Rack::Lint` error message for `HTTP_CONTENT_TYPE` and `HTTP_CONTENT_LENGTH`. ([#2007](https://github.com/rack/rack/pull/2007), [@byroot](https://github.com/byroot)) - Extend `Rack::MethodOverride` to handle `QueryParser::ParamsTooDeepError` error. ([#2006](https://github.com/rack/rack/pull/2006), [@byroot](https://github.com/byroot)) ## [3.0.3] - 2022-12-27 ### Fixed - `Rack::URLMap` uses non-deprecated form of `Regexp.new`. ([#1998](https://github.com/rack/rack/pull/1998), [@weizheheng](https://github.com/weizheheng)) ## [3.0.2] - 2022-12-05 ### Fixed - `Utils.build_nested_query` URL-encodes nested field names including the square brackets. - Allow `Rack::Response` to pass through streaming bodies. ([#1993](https://github.com/rack/rack/pull/1993), [@ioquatix]) ## [3.0.1] - 2022-11-18 ### Fixed - `MethodOverride` does not look for an override if a request does not include form/parseable data. - `Rack::Lint::Wrapper` correctly handles `respond_to?` with `to_ary`, `each`, `call` and `to_path`, forwarding to the body. ([#1981](https://github.com/rack/rack/pull/1981), [@ioquatix]) ## [3.0.0] - 2022-09-06 - No changes ## [3.0.0.rc1] - 2022-09-04 ### SPEC Changes - Stream argument must implement `<<` https://github.com/rack/rack/pull/1959 - `close` may be called on `rack.input` https://github.com/rack/rack/pull/1956 - `rack.response_finished` may be used for executing code after the response has been finished https://github.com/rack/rack/pull/1952 ## [3.0.0.beta1] - 2022-08-08 ### Security - Do not use semicolon as GET parameter separator. ([#1733](https://github.com/rack/rack/pull/1733), [@jeremyevans]) ### SPEC Changes - Response array must now be non-frozen. - Response `status` must now be an integer greater than or equal to 100. - Response `headers` must now be an unfrozen hash. - Response header keys can no longer include uppercase characters. - Response header values can be an `Array` to handle multiple values (and no longer supports `\n` encoded headers). - Response body can now respond to `#call` (streaming body) instead of `#each` (enumerable body), for the equivalent of response hijacking in previous versions. - Middleware must no longer call `#each` on the body, but they can call `#to_ary` on the body if it responds to `#to_ary`. - `rack.input` is no longer required to be rewindable. - `rack.multithread`/`rack.multiprocess`/`rack.run_once`/`rack.version` are no longer required environment keys. - `SERVER_PROTOCOL` is now a required environment key, matching the HTTP protocol used in the request. - `rack.hijack?` (partial hijack) and `rack.hijack` (full hijack) are now independently optional. - `rack.hijack_io` has been removed completely. - `rack.response_finished` is an optional environment key which contains an array of callable objects that must accept `#call(env, status, headers, error)` and are invoked after the response is finished (either successfully or unsuccessfully). - It is okay to call `#close` on `rack.input` to indicate that you no longer need or care about the input. - The stream argument supplied to the streaming body and hijack must support `#<<` for writing output. ### Removed - Remove `rack.multithread`/`rack.multiprocess`/`rack.run_once`. These variables generally come too late to be useful. ([#1720](https://github.com/rack/rack/pull/1720), [@ioquatix], [@jeremyevans])) - Remove deprecated Rack::Request::SCHEME_WHITELIST. ([@jeremyevans]) - Remove internal cookie deletion using pattern matching, there are very few practical cases where it would be useful and browsers handle it correctly without us doing anything special. ([#1844](https://github.com/rack/rack/pull/1844), [@ioquatix]) - Remove `rack.version` as it comes too late to be useful. ([#1938](https://github.com/rack/rack/pull/1938), [@ioquatix]) - Extract `rackup` command, `Rack::Server`, `Rack::Handler` and related code into a separate gem. ([#1937](https://github.com/rack/rack/pull/1937), [@ioquatix]) ### Added - `Rack::Headers` added to support lower-case header keys. ([@jeremyevans]) - `Rack::Utils#set_cookie_header` now supports `escape_key: false` to avoid key escaping. ([@jeremyevans]) - `Rack::RewindableInput` supports size. ([@ahorek](https://github.com/ahorek)) - `Rack::RewindableInput::Middleware` added for making `rack.input` rewindable. ([@jeremyevans]) - The RFC 7239 Forwarded header is now supported and considered by default when looking for information on forwarding, falling back to the X-Forwarded-* headers. `Rack::Request.forwarded_priority` accessor has been added for configuring the priority of which header to check. ([#1423](https://github.com/rack/rack/issues/1423), [@jeremyevans]) - Allow response headers to contain array of values. ([#1598](https://github.com/rack/rack/issues/1598), [@ioquatix]) - Support callable body for explicit streaming support and clarify streaming response body behaviour. ([#1745](https://github.com/rack/rack/pull/1745), [@ioquatix], [#1748](https://github.com/rack/rack/pull/1748), [@wjordan]) - Allow `Rack::Builder#run` to take a block instead of an argument. ([#1942](https://github.com/rack/rack/pull/1942), [@ioquatix]) - Add `rack.response_finished` to `Rack::Lint`. ([#1802](https://github.com/rack/rack/pull/1802), [@BlakeWilliams], [#1952](https://github.com/rack/rack/pull/1952), [@ioquatix]) - The stream argument must implement `#<<`. ([#1959](https://github.com/rack/rack/pull/1959), [@ioquatix]) ### Changed - BREAKING CHANGE: Require `status` to be an Integer. ([#1662](https://github.com/rack/rack/pull/1662), [@olleolleolle](https://github.com/olleolleolle)) - BREAKING CHANGE: Query parsing now treats parameters without `=` as having the empty string value instead of nil value, to conform to the URL spec. ([#1696](https://github.com/rack/rack/issues/1696), [@jeremyevans]) - Relax validations around `Rack::Request#host` and `Rack::Request#hostname`. ([#1606](https://github.com/rack/rack/issues/1606), [@pvande](https://github.com/pvande)) - Removed antiquated handlers: FCGI, LSWS, SCGI, Thin. ([#1658](https://github.com/rack/rack/pull/1658), [@ioquatix]) - Removed options from `Rack::Builder.parse_file` and `Rack::Builder.load_file`. ([#1663](https://github.com/rack/rack/pull/1663), [@ioquatix]) - `Rack::HTTP_VERSION` has been removed and the `HTTP_VERSION` env setting is no longer set in the CGI and Webrick handlers. ([#970](https://github.com/rack/rack/issues/970), [@jeremyevans]) - `Rack::Request#[]` and `#[]=` now warn even in non-verbose mode. ([#1277](https://github.com/rack/rack/issues/1277), [@jeremyevans]) - Decrease default allowed parameter recursion level from 100 to 32. ([#1640](https://github.com/rack/rack/issues/1640), [@jeremyevans]) - Attempting to parse a multipart response with an empty body now raises Rack::Multipart::EmptyContentError. ([#1603](https://github.com/rack/rack/issues/1603), [@jeremyevans]) - `Rack::Utils.secure_compare` uses OpenSSL's faster implementation if available. ([#1711](https://github.com/rack/rack/pull/1711), [@bdewater](https://github.com/bdewater)) - `Rack::Request#POST` now caches an empty hash if input content type is not parseable. ([#749](https://github.com/rack/rack/pull/749), [@jeremyevans]) - BREAKING CHANGE: Updated `trusted_proxy?` to match full 127.0.0.0/8 network. ([#1781](https://github.com/rack/rack/pull/1781), [@snbloch](https://github.com/snbloch)) - Explicitly deprecate `Rack::File` which was an alias for `Rack::Files`. ([#1811](https://github.com/rack/rack/pull/1720), [@ioquatix]). - Moved `Rack::Session` into [separate gem](https://github.com/rack/rack-session). ([#1805](https://github.com/rack/rack/pull/1805), [@ioquatix]) - `rackup -D` option to daemonizes no longer changes the working directory to the root. ([#1813](https://github.com/rack/rack/pull/1813), [@jeremyevans]) - The `x-forwarded-proto` header is now considered before the `x-forwarded-scheme` header for determining the forwarded protocol. `Rack::Request.x_forwarded_proto_priority` accessor has been added for configuring the priority of which header to check. ([#1809](https://github.com/rack/rack/issues/1809), [@jeremyevans]) - `Rack::Request.forwarded_authority` (and methods that call it, such as `host`) now returns the last authority in the forwarded header, instead of the first, as earlier forwarded authorities can be forged by clients. This restores the Rack 2.1 behavior. ([#1829](https://github.com/rack/rack/issues/1809), [@jeremyevans]) - Use lower case cookie attributes when creating cookies, and fold cookie attributes to lower case when reading cookies (specifically impacting `secure` and `httponly` attributes). ([#1849](https://github.com/rack/rack/pull/1849), [@ioquatix]) - The response array must now be mutable (non-frozen) so middleware can modify it without allocating a new Array,therefore reducing object allocations. ([#1887](https://github.com/rack/rack/pull/1887), [#1927](https://github.com/rack/rack/pull/1927), [@amatsuda], [@ioquatix]) - `rack.hijack?` (partial hijack) and `rack.hijack` (full hijack) are now independently optional. `rack.hijack_io` is no longer required/specified. ([#1939](https://github.com/rack/rack/pull/1939), [@ioquatix]) - Allow calling close on `rack.input`. ([#1956](https://github.com/rack/rack/pull/1956), [@ioquatix]) ### Fixed - Make Rack::MockResponse handle non-hash headers. ([#1629](https://github.com/rack/rack/issues/1629), [@jeremyevans]) - TempfileReaper now deletes temp files if application raises an exception. ([#1679](https://github.com/rack/rack/issues/1679), [@jeremyevans]) - Handle cookies with values that end in '=' ([#1645](https://github.com/rack/rack/pull/1645), [@lukaso](https://github.com/lukaso)) - Make `Rack::NullLogger` respond to `#fatal!` [@jeremyevans]) - Fix multipart filename generation for filenames that contain spaces. Encode spaces as "%20" instead of "+" which will be decoded properly by the multipart parser. ([#1736](https://github.com/rack/rack/pull/1645), [@muirdm](https://github.com/muirdm)) - `Rack::Request#scheme` returns `ws` or `wss` when one of the `X-Forwarded-Scheme` / `X-Forwarded-Proto` headers is set to `ws` or `wss`, respectively. ([#1730](https://github.com/rack/rack/issues/1730), [@erwanst](https://github.com/erwanst)) ## [2.2.4] - 2022-06-30 - Better support for lower case headers in `Rack::ETag` middleware. ([#1919](https://github.com/rack/rack/pull/1919), [@ioquatix](https://github.com/ioquatix)) - Use custom exception on params too deep error. ([#1838](https://github.com/rack/rack/pull/1838), [@simi](https://github.com/simi)) ## [2.2.3.1] - 2022-05-27 - [CVE-2022-30123] Fix shell escaping issue in Common Logger - [CVE-2022-30122] Restrict parsing of broken MIME attachments ## [2.2.3] - 2020-06-15 ### Security - [[CVE-2020-8184](https://nvd.nist.gov/vuln/detail/CVE-2020-8184)] Do not allow percent-encoded cookie name to override existing cookie names. BREAKING CHANGE: Accessing cookie names that require URL encoding with decoded name no longer works. ([@fletchto99](https://github.com/fletchto99)) ## [2.2.2] - 2020-02-11 ### Fixed - Fix incorrect `Rack::Request#host` value. ([#1591](https://github.com/rack/rack/pull/1591), [@ioquatix]) - Revert `Rack::Handler::Thin` implementation. ([#1583](https://github.com/rack/rack/pull/1583), [@jeremyevans]) - Double assignment is still needed to prevent an "unused variable" warning. ([#1589](https://github.com/rack/rack/pull/1589), [@kamipo](https://github.com/kamipo)) - Fix to handle same_site option for session pool. ([#1587](https://github.com/rack/rack/pull/1587), [@kamipo](https://github.com/kamipo)) ## [2.2.1] - 2020-02-09 ### Fixed - Rework `Rack::Request#ip` to handle empty `forwarded_for`. ([#1577](https://github.com/rack/rack/pull/1577), [@ioquatix]) ## [2.2.0] - 2020-02-08 ### SPEC Changes - `rack.session` request environment entry must respond to `to_hash` and return unfrozen Hash. ([@jeremyevans]) - Request environment cannot be frozen. ([@jeremyevans]) - CGI values in the request environment with non-ASCII characters must use ASCII-8BIT encoding. ([@jeremyevans]) - Improve SPEC/lint relating to SERVER_NAME, SERVER_PORT and HTTP_HOST. ([#1561](https://github.com/rack/rack/pull/1561), [@ioquatix]) ### Added - `rackup` supports multiple `-r` options and will require all arguments. ([@jeremyevans]) - `Server` supports an array of paths to require for the `:require` option. ([@khotta](https://github.com/khotta)) - `Files` supports multipart range requests. ([@fatkodima](https://github.com/fatkodima)) - `Multipart::UploadedFile` supports an IO-like object instead of using the filesystem, using `:filename` and `:io` options. ([@jeremyevans]) - `Multipart::UploadedFile` supports keyword arguments `:path`, `:content_type`, and `:binary` in addition to positional arguments. ([@jeremyevans]) - `Static` supports a `:cascade` option for calling the app if there is no matching file. ([@jeremyevans]) - `Session::Abstract::SessionHash#dig`. ([@jeremyevans]) - `Response.[]` and `MockResponse.[]` for creating instances using status, headers, and body. ([@ioquatix]) - Convenient cache and content type methods for `Rack::Response`. ([#1555](https://github.com/rack/rack/pull/1555), [@ioquatix]) ### Changed - `Request#params` no longer rescues EOFError. ([@jeremyevans]) - `Directory` uses a streaming approach, significantly improving time to first byte for large directories. ([@jeremyevans]) - `Directory` no longer includes a Parent directory link in the root directory index. ([@jeremyevans]) - `QueryParser#parse_nested_query` uses original backtrace when reraising exception with new class. ([@jeremyevans]) - `ConditionalGet` follows RFC 7232 precedence if both If-None-Match and If-Modified-Since headers are provided. ([@jeremyevans]) - `.ru` files supports the `frozen-string-literal` magic comment. ([@eregon](https://github.com/eregon)) - Rely on autoload to load constants instead of requiring internal files, make sure to require 'rack' and not just 'rack/...'. ([@jeremyevans]) - BREAKING CHANGE: `Etag` will continue sending ETag even if the response should not be cached. Streaming no longer works without a workaround, see [#1619](https://github.com/rack/rack/issues/1619#issuecomment-848460528). ([@henm](https://github.com/henm)) - `Request#host_with_port` no longer includes a colon for a missing or empty port. ([@AlexWayfer](https://github.com/AlexWayfer)) - All handlers uses keywords arguments instead of an options hash argument. ([@ioquatix]) - `Files` handling of range requests no longer return a body that supports `to_path`, to ensure range requests are handled correctly. ([@jeremyevans]) - `Multipart::Generator` only includes `Content-Length` for files with paths, and `Content-Disposition` `filename` if the `UploadedFile` instance has one. ([@jeremyevans]) - `Request#ssl?` is true for the `wss` scheme (secure websockets). ([@jeremyevans]) - `Rack::HeaderHash` is memoized by default. ([#1549](https://github.com/rack/rack/pull/1549), [@ioquatix]) - `Rack::Directory` allow directory traversal inside root directory. ([#1417](https://github.com/rack/rack/pull/1417), [@ThomasSevestre](https://github.com/ThomasSevestre)) - Sort encodings by server preference. ([#1184](https://github.com/rack/rack/pull/1184), [@ioquatix], [@wjordan](https://github.com/wjordan)) - Rework host/hostname/authority implementation in `Rack::Request`. `#host` and `#host_with_port` have been changed to correctly return IPv6 addresses formatted with square brackets, as defined by [RFC3986](https://tools.ietf.org/html/rfc3986#section-3.2.2). ([#1561](https://github.com/rack/rack/pull/1561), [@ioquatix]) - `Rack::Builder` parsing options on first `#\` line is deprecated. ([#1574](https://github.com/rack/rack/pull/1574), [@ioquatix]) ### Removed - `Directory#path` as it was not used and always returned nil. ([@jeremyevans]) - `BodyProxy#each` as it was only needed to work around a bug in Ruby <1.9.3. ([@jeremyevans]) - `URLMap::INFINITY` and `URLMap::NEGATIVE_INFINITY`, in favor of `Float::INFINITY`. ([@ch1c0t](https://github.com/ch1c0t)) - Deprecation of `Rack::File`. It will be deprecated again in rack 2.2 or 3.0. ([@rafaelfranca](https://github.com/rafaelfranca)) - Support for Ruby 2.2 as it is well past EOL. ([@ioquatix]) - Remove `Rack::Files#response_body` as the implementation was broken. ([#1153](https://github.com/rack/rack/pull/1153), [@ioquatix]) - Remove `SERVER_ADDR` which was never part of the original SPEC. ([#1573](https://github.com/rack/rack/pull/1573), [@ioquatix]) ### Fixed - `Directory` correctly handles root paths containing glob metacharacters. ([@jeremyevans]) - `Cascade` uses a new response object for each call if initialized with no apps. ([@jeremyevans]) - `BodyProxy` correctly delegates keyword arguments to the body object on Ruby 2.7+. ([@jeremyevans]) - `BodyProxy#method` correctly handles methods delegated to the body object. ([@jeremyevans]) - `Request#host` and `Request#host_with_port` handle IPv6 addresses correctly. ([@AlexWayfer](https://github.com/AlexWayfer)) - `Lint` checks when response hijacking that `rack.hijack` is called with a valid object. ([@jeremyevans]) - `Response#write` correctly updates `Content-Length` if initialized with a body. ([@jeremyevans]) - `CommonLogger` includes `SCRIPT_NAME` when logging. ([@Erol](https://github.com/Erol)) - `Utils.parse_nested_query` correctly handles empty queries, using an empty instance of the params class instead of a hash. ([@jeremyevans]) - `Directory` correctly escapes paths in links. ([@yous](https://github.com/yous)) - `Request#delete_cookie` and related `Utils` methods handle `:domain` and `:path` options in same call. ([@jeremyevans]) - `Request#delete_cookie` and related `Utils` methods do an exact match on `:domain` and `:path` options. ([@jeremyevans]) - `Static` no longer adds headers when a gzipped file request has a 304 response. ([@chooh](https://github.com/chooh)) - `ContentLength` sets `Content-Length` response header even for bodies not responding to `to_ary`. ([@jeremyevans]) - Thin handler supports options passed directly to `Thin::Controllers::Controller`. ([@jeremyevans]) - WEBrick handler no longer ignores `:BindAddress` option. ([@jeremyevans]) - `ShowExceptions` handles invalid POST data. ([@jeremyevans]) - Basic authentication requires a password, even if the password is empty. ([@jeremyevans]) - `Lint` checks response is array with 3 elements, per SPEC. ([@jeremyevans]) - Support for using `:SSLEnable` option when using WEBrick handler. (Gregor Melhorn) - Close response body after buffering it when buffering. ([@ioquatix]) - Only accept `;` as delimiter when parsing cookies. ([@mrageh](https://github.com/mrageh)) - `Utils::HeaderHash#clear` clears the name mapping as well. ([@raxoft](https://github.com/raxoft)) - Support for passing `nil` `Rack::Files.new`, which notably fixes Rails' current `ActiveStorage::FileServer` implementation. ([@ioquatix]) ### Documentation - CHANGELOG updates. ([@aupajo](https://github.com/aupajo)) - Added [CONTRIBUTING](CONTRIBUTING.md). ([@dblock](https://github.com/dblock)) ## [2.0.9] - 2020-02-08 - Handle case where session id key is requested but missing ([@jeremyevans]) - Restore support for code relying on `SessionId#to_s`. ([@jeremyevans]) - Add support for `SameSite=None` cookie value. ([@hennikul](https://github.com/hennikul)) ## [2.1.2] - 2020-01-27 - Fix multipart parser for some files to prevent denial of service ([@aiomaster](https://github.com/aiomaster)) - Fix `Rack::Builder#use` with keyword arguments ([@kamipo](https://github.com/kamipo)) - Skip deflating in Rack::Deflater if Content-Length is 0 ([@jeremyevans]) - Remove `SessionHash#transform_keys`, no longer needed ([@pavel](https://github.com/pavel)) - Add to_hash to wrap Hash and Session classes ([@oleh-demyanyuk](https://github.com/oleh-demyanyuk)) - Handle case where session id key is requested but missing ([@jeremyevans]) ## [2.1.1] - 2020-01-12 - Remove `Rack::Chunked` from `Rack::Server` default middleware. ([#1475](https://github.com/rack/rack/pull/1475), [@ioquatix]) - Restore support for code relying on `SessionId#to_s`. ([@jeremyevans]) ## [2.1.0] - 2020-01-10 ### Added - Add support for `SameSite=None` cookie value. ([@hennikul](https://github.com/hennikul)) - Add trailer headers. ([@eileencodes](https://github.com/eileencodes)) - Add MIME Types for video streaming. ([@styd](https://github.com/styd)) - Add MIME Type for WASM. ([@buildrtech](https://github.com/buildrtech)) - Add `Early Hints(103)` to status codes. ([@egtra](https://github.com/egtra)) - Add `Too Early(425)` to status codes. ([@y-yagi]((https://github.com/y-yagi))) - Add `Bandwidth Limit Exceeded(509)` to status codes. ([@CJKinni](https://github.com/CJKinni)) - Add method for custom `ip_filter`. ([@svcastaneda](https://github.com/svcastaneda)) - Add boot-time profiling capabilities to `rackup`. ([@tenderlove](https://github.com/tenderlove)) - Add multi mapping support for `X-Accel-Mappings` header. ([@yoshuki](https://github.com/yoshuki)) - Add `sync: false` option to `Rack::Deflater`. (Eric Wong) - Add `Builder#freeze_app` to freeze application and all middleware instances. ([@jeremyevans]) - Add API to extract cookies from `Rack::MockResponse`. ([@petercline](https://github.com/petercline)) ### Changed - Don't propagate nil values from middleware. ([@ioquatix]) - Lazily initialize the response body and only buffer it if required. ([@ioquatix]) - Fix deflater zlib buffer errors on empty body part. ([@felixbuenemann](https://github.com/felixbuenemann)) - Set `X-Accel-Redirect` to percent-encoded path. ([@diskkid](https://github.com/diskkid)) - Remove unnecessary buffer growing when parsing multipart. ([@tainoe](https://github.com/tainoe)) - Expand the root path in `Rack::Static` upon initialization. ([@rosenfeld](https://github.com/rosenfeld)) - Make `ShowExceptions` work with binary data. ([@axyjo](https://github.com/axyjo)) - Use buffer string when parsing multipart requests. ([@janko-m](https://github.com/janko-m)) - Support optional UTF-8 Byte Order Mark (BOM) in config.ru. ([@mikegee](https://github.com/mikegee)) - Handle `X-Forwarded-For` with optional port. ([@dpritchett](https://github.com/dpritchett)) - Use `Time#httpdate` format for Expires, as proposed by RFC 7231. ([@nanaya](https://github.com/nanaya)) - Make `Utils.status_code` raise an error when the status symbol is invalid instead of `500`. ([@adambutler](https://github.com/adambutler)) - Rename `Request::SCHEME_WHITELIST` to `Request::ALLOWED_SCHEMES`. - Make `Multipart::Parser.get_filename` accept files with `+` in their name. ([@lucaskanashiro](https://github.com/lucaskanashiro)) - Add Falcon to the default handler fallbacks. ([@ioquatix]) - Update codebase to avoid string mutations in preparation for `frozen_string_literals`. ([@pat](https://github.com/pat)) - Change `MockRequest#env_for` to rely on the input optionally responding to `#size` instead of `#length`. ([@janko](https://github.com/janko)) - Rename `Rack::File` -> `Rack::Files` and add deprecation notice. ([@postmodern](https://github.com/postmodern)) - Prefer Base64 “strict encoding” for Base64 cookies. ([@ioquatix]) ### Removed - BREAKING CHANGE: Remove `to_ary` from Response ([@tenderlove](https://github.com/tenderlove)) - Deprecate `Rack::Session::Memcache` in favor of `Rack::Session::Dalli` from dalli gem ([@fatkodima](https://github.com/fatkodima)) ### Fixed - Eliminate warnings for Ruby 2.7. ([@osamtimizer](https://github.com/osamtimizer])) ### Documentation - Update broken example in `Session::Abstract::ID` documentation. ([tonytonyjan](https://github.com/tonytonyjan)) - Add Padrino to the list of frameworks implementing Rack. ([@wikimatze](https://github.com/wikimatze)) - Remove Mongrel from the suggested server options in the help output. ([@tricknotes](https://github.com/tricknotes)) - Replace `HISTORY.md` and `NEWS.md` with `CHANGELOG.md`. ([@twitnithegirl](https://github.com/twitnithegirl)) - CHANGELOG updates. ([@drenmi](https://github.com/Drenmi), [@p8](https://github.com/p8)) ## [2.0.8] - 2019-12-08 ### Security - [[CVE-2019-16782](https://nvd.nist.gov/vuln/detail/CVE-2019-16782)] Prevent timing attacks targeted at session ID lookup. BREAKING CHANGE: Session ID is now a SessionId instance instead of a String. ([@tenderlove](https://github.com/tenderlove), [@rafaelfranca](https://github.com/rafaelfranca)) ## [1.6.12] - 2019-12-08 ### Security - [[CVE-2019-16782](https://nvd.nist.gov/vuln/detail/CVE-2019-16782)] Prevent timing attacks targeted at session ID lookup. BREAKING CHANGE: Session ID is now a SessionId instance instead of a String. ([@tenderlove](https://github.com/tenderlove), [@rafaelfranca](https://github.com/rafaelfranca)) ## [2.0.7] - 2019-04-02 ### Fixed - Remove calls to `#eof?` on Rack input in `Multipart::Parser`, as this breaks the specification. ([@matthewd](https://github.com/matthewd)) - Preserve forwarded IP addresses for trusted proxy chains. ([@SamSaffron](https://github.com/SamSaffron)) ## [2.0.6] - 2018-11-05 ### Fixed - [[CVE-2018-16470](https://nvd.nist.gov/vuln/detail/CVE-2018-16470)] Reduce buffer size of `Multipart::Parser` to avoid pathological parsing. ([@tenderlove](https://github.com/tenderlove)) - Fix a call to a non-existing method `#accepts_html` in the `ShowExceptions` middleware. ([@tomelm](https://github.com/tomelm)) - [[CVE-2018-16471](https://nvd.nist.gov/vuln/detail/CVE-2018-16471)] Whitelist HTTP and HTTPS schemes in `Request#scheme` to prevent a possible XSS attack. ([@PatrickTulskie](https://github.com/PatrickTulskie)) ## [2.0.5] - 2018-04-23 ### Fixed - Record errors originating from invalid UTF8 in `MethodOverride` middleware instead of breaking. ([@mclark](https://github.com/mclark)) ## [2.0.4] - 2018-01-31 ### Changed - Ensure the `Lock` middleware passes the original `env` object. ([@lugray](https://github.com/lugray)) - Improve performance of `Multipart::Parser` when uploading large files. ([@tompng](https://github.com/tompng)) - Increase buffer size in `Multipart::Parser` for better performance. ([@jkowens](https://github.com/jkowens)) - Reduce memory usage of `Multipart::Parser` when uploading large files. ([@tompng](https://github.com/tompng)) - Replace ConcurrentRuby dependency with native `Queue`. ([@devmchakan](https://github.com/devmchakan)) ### Fixed - Require the correct digest algorithm in the `ETag` middleware. ([@matthewd](https://github.com/matthewd)) ### Documentation - Update homepage links to use SSL. ([@hugoabonizio](https://github.com/hugoabonizio)) ## [2.0.3] - 2017-05-15 ### Changed - Ensure `env` values are ASCII 8-bit encoded. ([@eileencodes](https://github.com/eileencodes)) ### Fixed - Prevent exceptions when a class with mixins inherits from `Session::Abstract::ID`. ([@jnraine](https://github.com/jnraine)) ## [2.0.2] - 2017-05-08 ### Added - Allow `Session::Abstract::SessionHash#fetch` to accept a block with a default value. ([@yannvanhalewyn](https://github.com/yannvanhalewyn)) - Add `Builder#freeze_app` to freeze application and all middleware. ([@jeremyevans]) ### Changed - Freeze default session options to avoid accidental mutation. ([@kirs](https://github.com/kirs)) - Detect partial hijack without hash headers. ([@devmchakan](https://github.com/devmchakan)) - Update tests to use MiniTest 6 matchers. ([@tonytonyjan](https://github.com/tonytonyjan)) - Allow 205 Reset Content responses to set a Content-Length, as RFC 7231 proposes setting this to 0. ([@devmchakan](https://github.com/devmchakan)) ### Fixed - Handle `NULL` bytes in multipart filenames. ([@casperisfine](https://github.com/casperisfine)) - Remove warnings due to miscapitalized global. ([@ioquatix]) - Prevent exceptions caused by a race condition on multi-threaded servers. ([@sophiedeziel](https://github.com/sophiedeziel)) - Add RDoc as an explicit dependency for `doc` group. ([@tonytonyjan](https://github.com/tonytonyjan)) - Record errors originating from `Multipart::Parser` in the `MethodOverride` middleware instead of letting them bubble up. ([@carlzulauf](https://github.com/carlzulauf)) - Remove remaining use of removed `Utils#bytesize` method from the `File` middleware. ([@brauliomartinezlm](https://github.com/brauliomartinezlm)) ### Removed - Remove `deflate` encoding support to reduce caching overhead. ([@devmchakan](https://github.com/devmchakan)) ### Documentation - Update broken example in `Deflater` documentation. ([@mwpastore](https://github.com/mwpastore)) ## [2.0.1] - 2016-06-30 ### Changed - Remove JSON as an explicit dependency. ([@mperham](https://github.com/mperham)) # History/News Archive Items below this line are from the previously maintained HISTORY.md and NEWS.md files. ## [2.0.0.rc1] 2016-05-06 - Rack::Session::Abstract::ID is deprecated. Please change to use Rack::Session::Abstract::Persisted ## [2.0.0.alpha] 2015-12-04 - First-party "SameSite" cookies. Browsers omit SameSite cookies from third-party requests, closing the door on many CSRF attacks. - Pass `same_site: true` (or `:strict`) to enable: response.set_cookie 'foo', value: 'bar', same_site: true or `same_site: :lax` to use Lax enforcement: response.set_cookie 'foo', value: 'bar', same_site: :lax - Based on version 7 of the Same-site Cookies internet draft: https://tools.ietf.org/html/draft-west-first-party-cookies-07 - Thanks to Ben Toews (@mastahyeti) and Bob Long (@bobjflong) for updating to drafts 5 and 7. - Add `Rack::Events` middleware for adding event based middleware: middleware that does not care about the response body, but only cares about doing work at particular points in the request / response lifecycle. - Add `Rack::Request#authority` to calculate the authority under which the response is being made (this will be handy for h2 pushes). - Add `Rack::Response::Helpers#cache_control` and `cache_control=`. Use this for setting cache control headers on your response objects. - Add `Rack::Response::Helpers#etag` and `etag=`. Use this for setting etag values on the response. - Introduce `Rack::Response::Helpers#add_header` to add a value to a multi-valued response header. Implemented in terms of other `Response#*_header` methods, so it's available to any response-like class that includes the `Helpers` module. - Add `Rack::Request#add_header` to match. - `Rack::Session::Abstract::ID` IS DEPRECATED. Please switch to `Rack::Session::Abstract::Persisted`. `Rack::Session::Abstract::Persisted` uses a request object rather than the `env` hash. - Pull `ENV` access inside the request object in to a module. This will help with legacy Request objects that are ENV based but don't want to inherit from Rack::Request - Move most methods on the `Rack::Request` to a module `Rack::Request::Helpers` and use public API to get values from the request object. This enables users to mix `Rack::Request::Helpers` in to their own objects so they can implement `(get|set|fetch|each)_header` as they see fit (for example a proxy object). - Files and directories with + in the name are served correctly. Rather than unescaping paths like a form, we unescape with a URI parser using `Rack::Utils.unescape_path`. Fixes #265 - Tempfiles are automatically closed in the case that there were too many posted. - Added methods for manipulating response headers that don't assume they're stored as a Hash. Response-like classes may include the Rack::Response::Helpers module if they define these methods: - Rack::Response#has_header? - Rack::Response#get_header - Rack::Response#set_header - Rack::Response#delete_header - Introduce Util.get_byte_ranges that will parse the value of the HTTP_RANGE string passed to it without depending on the `env` hash. `byte_ranges` is deprecated in favor of this method. - Change Session internals to use Request objects for looking up session information. This allows us to only allocate one request object when dealing with session objects (rather than doing it every time we need to manipulate cookies, etc). - Add `Rack::Request#initialize_copy` so that the env is duped when the request gets duped. - Added methods for manipulating request specific data. This includes data set as CGI parameters, and just any arbitrary data the user wants to associate with a particular request. New methods: - Rack::Request#has_header? - Rack::Request#get_header - Rack::Request#fetch_header - Rack::Request#each_header - Rack::Request#set_header - Rack::Request#delete_header - lib/rack/utils.rb: add a method for constructing "delete" cookie headers. This allows us to construct cookie headers without depending on the side effects of mutating a hash. - Prevent extremely deep parameters from being parsed. CVE-2015-3225 ## [1.6.1] 2015-05-06 - Fix CVE-2014-9490, denial of service attack in OkJson - Use a monotonic time for Rack::Runtime, if available - RACK_MULTIPART_LIMIT changed to RACK_MULTIPART_PART_LIMIT (RACK_MULTIPART_LIMIT is deprecated and will be removed in 1.7.0) ## [1.5.3] 2015-05-06 - Fix CVE-2014-9490, denial of service attack in OkJson - Backport bug fixes to 1.5 series ## [1.6.0] 2014-01-18 - Response#unauthorized? helper - Deflater now accepts an options hash to control compression on a per-request level - Builder#warmup method for app preloading - Request#accept_language method to extract HTTP_ACCEPT_LANGUAGE - Add quiet mode of rack server, rackup --quiet - Update HTTP Status Codes to RFC 7231 - Less strict header name validation according to RFC 2616 - SPEC updated to specify headers conform to RFC7230 specification - Etag correctly marks etags as weak - Request#port supports multiple x-http-forwarded-proto values - Utils#multipart_part_limit configures the maximum number of parts a request can contain - Default host to localhost when in development mode - Various bugfixes and performance improvements ## [1.5.2] 2013-02-07 - Fix CVE-2013-0263, timing attack against Rack::Session::Cookie - Fix CVE-2013-0262, symlink path traversal in Rack::File - Add various methods to Session for enhanced Rails compatibility - Request#trusted_proxy? now only matches whole strings - Add JSON cookie coder, to be default in Rack 1.6+ due to security concerns - URLMap host matching in environments that don't set the Host header fixed - Fix a race condition that could result in overwritten pidfiles - Various documentation additions ## [1.4.5] 2013-02-07 - Fix CVE-2013-0263, timing attack against Rack::Session::Cookie - Fix CVE-2013-0262, symlink path traversal in Rack::File ## [1.1.6, 1.2.8, 1.3.10] 2013-02-07 - Fix CVE-2013-0263, timing attack against Rack::Session::Cookie ## [1.5.1] 2013-01-28 - Rack::Lint check_hijack now conforms to other parts of SPEC - Added hash-like methods to Abstract::ID::SessionHash for compatibility - Various documentation corrections ## [1.5.0] 2013-01-21 - Introduced hijack SPEC, for before-response and after-response hijacking - SessionHash is no longer a Hash subclass - Rack::File cache_control parameter is removed, in place of headers options - Rack::Auth::AbstractRequest#scheme now yields strings, not symbols - Rack::Utils cookie functions now format expires in RFC 2822 format - Rack::File now has a default mime type - rackup -b 'run Rack::Files.new(".")', option provides command line configs - Rack::Deflater will no longer double encode bodies - Rack::Mime#match? provides convenience for Accept header matching - Rack::Utils#q_values provides splitting for Accept headers - Rack::Utils#best_q_match provides a helper for Accept headers - Rack::Handler.pick provides convenience for finding available servers - Puma added to the list of default servers (preferred over Webrick) - Various middleware now correctly close body when replacing it - Rack::Request#params is no longer persistent with only GET params - Rack::Request#update_param and #delete_param provide persistent operations - Rack::Request#trusted_proxy? now returns true for local unix sockets - Rack::Response no longer forces Content-Types - Rack::Sendfile provides local mapping configuration options - Rack::Utils#rfc2109 provides old netscape style time output - Updated HTTP status codes - Ruby 1.8.6 likely no longer passes tests, and is no longer fully supported ## [1.4.4, 1.3.9, 1.2.7, 1.1.5] 2013-01-13 - [SEC] Rack::Auth::AbstractRequest no longer symbolizes arbitrary strings - Fixed erroneous test case in the 1.3.x series ## [1.4.3] 2013-01-07 - Security: Prevent unbounded reads in large multipart boundaries ## [1.3.8] 2013-01-07 - Security: Prevent unbounded reads in large multipart boundaries ## [1.4.2] 2013-01-06 - Add warnings when users do not provide a session secret - Fix parsing performance for unquoted filenames - Updated URI backports - Fix URI backport version matching, and silence constant warnings - Correct parameter parsing with empty values - Correct rackup '-I' flag, to allow multiple uses - Correct rackup pidfile handling - Report rackup line numbers correctly - Fix request loops caused by non-stale nonces with time limits - Fix reloader on Windows - Prevent infinite recursions from Response#to_ary - Various middleware better conforms to the body close specification - Updated language for the body close specification - Additional notes regarding ECMA escape compatibility issues - Fix the parsing of multiple ranges in range headers - Prevent errors from empty parameter keys - Added PATCH verb to Rack::Request - Various documentation updates - Fix session merge semantics (fixes rack-test) - Rack::Static :index can now handle multiple directories - All tests now utilize Rack::Lint (special thanks to Lars Gierth) - Rack::File cache_control parameter is now deprecated, and removed by 1.5 - Correct Rack::Directory script name escaping - Rack::Static supports header rules for sophisticated configurations - Multipart parsing now works without a Content-Length header - New logos courtesy of Zachary Scott! - Rack::BodyProxy now explicitly defines #each, useful for C extensions - Cookies that are not URI escaped no longer cause exceptions ## [1.3.7] 2013-01-06 - Add warnings when users do not provide a session secret - Fix parsing performance for unquoted filenames - Updated URI backports - Fix URI backport version matching, and silence constant warnings - Correct parameter parsing with empty values - Correct rackup '-I' flag, to allow multiple uses - Correct rackup pidfile handling - Report rackup line numbers correctly - Fix request loops caused by non-stale nonces with time limits - Fix reloader on Windows - Prevent infinite recursions from Response#to_ary - Various middleware better conforms to the body close specification - Updated language for the body close specification - Additional notes regarding ECMA escape compatibility issues - Fix the parsing of multiple ranges in range headers ## [1.2.6] 2013-01-06 - Add warnings when users do not provide a session secret - Fix parsing performance for unquoted filenames ## [1.1.4] 2013-01-06 - Add warnings when users do not provide a session secret ## [1.4.1] 2012-01-22 - Alter the keyspace limit calculations to reduce issues with nested params - Add a workaround for multipart parsing where files contain unescaped "%" - Added Rack::Response::Helpers#method_not_allowed? (code 405) - Rack::File now returns 404 for illegal directory traversals - Rack::File now returns 405 for illegal methods (non HEAD/GET) - Rack::Cascade now catches 405 by default, as well as 404 - Cookies missing '--' no longer cause an exception to be raised - Various style changes and documentation spelling errors - Rack::BodyProxy always ensures to execute its block - Additional test coverage around cookies and secrets - Rack::Session::Cookie can now be supplied either secret or old_secret - Tests are no longer dependent on set order - Rack::Static no longer defaults to serving index files - Rack.release was fixed ## [1.4.0] 2011-12-28 - Ruby 1.8.6 support has officially been dropped. Not all tests pass. - Raise sane error messages for broken config.ru - Allow combining run and map in a config.ru - Rack::ContentType will not set Content-Type for responses without a body - Status code 205 does not send a response body - Rack::Response::Helpers will not rely on instance variables - Rack::Utils.build_query no longer outputs '=' for nil query values - Various mime types added - Rack::MockRequest now supports HEAD - Rack::Directory now supports files that contain RFC3986 reserved chars - Rack::File now only supports GET and HEAD requests - Rack::Server#start now passes the block to Rack::Handler::#run - Rack::Static now supports an index option - Added the Teapot status code - rackup now defaults to Thin instead of Mongrel (if installed) - Support added for HTTP_X_FORWARDED_SCHEME - Numerous bug fixes, including many fixes for new and alternate rubies ## [1.1.3] 2011-12-28 - Security fix. http://www.ocert.org/advisories/ocert-2011-003.html Further information here: http://jruby.org/2011/12/27/jruby-1-6-5-1 ## [1.3.5] 2011-10-17 - Fix annoying warnings caused by the backport in 1.3.4 ## [1.3.4] 2011-10-01 - Backport security fix from 1.9.3, also fixes some roundtrip issues in URI - Small documentation update - Fix an issue where BodyProxy could cause an infinite recursion - Add some supporting files for travis-ci ## [1.2.4] 2011-09-16 - Fix a bug with MRI regex engine to prevent XSS by malformed unicode ## [1.3.3] 2011-09-16 - Fix bug with broken query parameters in Rack::ShowExceptions - Rack::Request#cookies no longer swallows exceptions on broken input - Prevents XSS attacks enabled by bug in Ruby 1.8's regexp engine - Rack::ConditionalGet handles broken If-Modified-Since helpers ## [1.3.2] 2011-07-16 - Fix for Rails and rack-test, Rack::Utils#escape calls to_s ## [1.3.1] 2011-07-13 - Fix 1.9.1 support - Fix JRuby support - Properly handle $KCODE in Rack::Utils.escape - Make method_missing/respond_to behavior consistent for Rack::Lock, Rack::Auth::Digest::Request and Rack::Multipart::UploadedFile - Reenable passing rack.session to session middleware - Rack::CommonLogger handles streaming responses correctly - Rack::MockResponse calls close on the body object - Fix a DOS vector from MRI stdlib backport ## [1.2.3] 2011-05-22 - Pulled in relevant bug fixes from 1.3 - Fixed 1.8.6 support ## [1.3.0] 2011-05-22 - Various performance optimizations - Various multipart fixes - Various multipart refactors - Infinite loop fix for multipart - Test coverage for Rack::Server returns - Allow files with '..', but not path components that are '..' - rackup accepts handler-specific options on the command line - Request#params no longer merges POST into GET (but returns the same) - Use URI.encode_www_form_component instead. Use core methods for escaping. - Allow multi-line comments in the config file - Bug L#94 reported by Nikolai Lugovoi, query parameter unescaping. - Rack::Response now deletes Content-Length when appropriate - Rack::Deflater now supports streaming - Improved Rack::Handler loading and searching - Support for the PATCH verb - env['rack.session.options'] now contains session options - Cookies respect renew - Session middleware uses SecureRandom.hex ## [1.2.2, 1.1.2] 2011-03-13 - Security fix in Rack::Auth::Digest::MD5: when authenticator returned nil, permission was granted on empty password. ## [1.2.1] 2010-06-15 - Make CGI handler rewindable - Rename spec/ to test/ to not conflict with SPEC on lesser operating systems ## [1.2.0] 2010-06-13 - Removed Camping adapter: Camping 2.0 supports Rack as-is - Removed parsing of quoted values - Add Request.trace? and Request.options? - Add mime-type for .webm and .htc - Fix HTTP_X_FORWARDED_FOR - Various multipart fixes - Switch test suite to bacon ## [1.1.0] 2010-01-03 - Moved Auth::OpenID to rack-contrib. - SPEC change that relaxes Lint slightly to allow subclasses of the required types - SPEC change to document rack.input binary mode in greater detail - SPEC define optional rack.logger specification - File servers support X-Cascade header - Imported Config middleware - Imported ETag middleware - Imported Runtime middleware - Imported Sendfile middleware - New Logger and NullLogger middlewares - Added mime type for .ogv and .manifest. - Don't squeeze PATH_INFO slashes - Use Content-Type to determine POST params parsing - Update Rack::Utils::HTTP_STATUS_CODES hash - Add status code lookup utility - Response should call #to_i on the status - Add Request#user_agent - Request#host knows about forwarded host - Return an empty string for Request#host if HTTP_HOST and SERVER_NAME are both missing - Allow MockRequest to accept hash params - Optimizations to HeaderHash - Refactored rackup into Rack::Server - Added Utils.build_nested_query to complement Utils.parse_nested_query - Added Utils::Multipart.build_multipart to complement Utils::Multipart.parse_multipart - Extracted set and delete cookie helpers into Utils so they can be used outside Response - Extract parse_query and parse_multipart in Request so subclasses can change their behavior - Enforce binary encoding in RewindableInput - Set correct external_encoding for handlers that don't use RewindableInput ## [1.0.1] 2009-10-18 - Bump remainder of rack.versions. - Support the pure Ruby FCGI implementation. - Fix for form names containing "=": split first then unescape components - Fixes the handling of the filename parameter with semicolons in names. - Add anchor to nested params parsing regexp to prevent stack overflows - Use more compatible gzip write api instead of "<<". - Make sure that Reloader doesn't break when executed via ruby -e - Make sure WEBrick respects the :Host option - Many Ruby 1.9 fixes. ## [1.0.0] 2009-04-25 - SPEC change: Rack::VERSION has been pushed to [1,0]. - SPEC change: header values must be Strings now, split on "\n". - SPEC change: Content-Length can be missing, in this case chunked transfer encoding is used. - SPEC change: rack.input must be rewindable and support reading into a buffer, wrap with Rack::RewindableInput if it isn't. - SPEC change: rack.session is now specified. - SPEC change: Bodies can now additionally respond to #to_path with a filename to be served. - NOTE: String bodies break in 1.9, use an Array consisting of a single String instead. - New middleware Rack::Lock. - New middleware Rack::ContentType. - Rack::Reloader has been rewritten. - Major update to Rack::Auth::OpenID. - Support for nested parameter parsing in Rack::Response. - Support for redirects in Rack::Response. - HttpOnly cookie support in Rack::Response. - The Rakefile has been rewritten. - Many bugfixes and small improvements. ## [0.9.1] 2009-01-09 - Fix directory traversal exploits in Rack::File and Rack::Directory. ## [0.9] 2009-01-06 - Rack is now managed by the Rack Core Team. - Rack::Lint is stricter and follows the HTTP RFCs more closely. - Added ConditionalGet middleware. - Added ContentLength middleware. - Added Deflater middleware. - Added Head middleware. - Added MethodOverride middleware. - Rack::Mime now provides popular MIME-types and their extension. - Mongrel Header now streams. - Added Thin handler. - Official support for swiftiplied Mongrel. - Secure cookies. - Made HeaderHash case-preserving. - Many bugfixes and small improvements. ## [0.4] 2008-08-21 - New middleware, Rack::Deflater, by Christoffer Sawicki. - OpenID authentication now needs ruby-openid 2. - New Memcache sessions, by blink. - Explicit EventedMongrel handler, by Joshua Peek - Rack::Reloader is not loaded in rackup development mode. - rackup can daemonize with -D. - Many bugfixes, especially for pool sessions, URLMap, thread safety and tempfile handling. - Improved tests. - Rack moved to Git. ## [0.3] 2008-02-26 - LiteSpeed handler, by Adrian Madrid. - SCGI handler, by Jeremy Evans. - Pool sessions, by blink. - OpenID authentication, by blink. - :Port and :File options for opening FastCGI sockets, by blink. - Last-Modified HTTP header for Rack::File, by blink. - Rack::Builder#use now accepts blocks, by Corey Jewett. (See example/protectedlobster.ru) - HTTP status 201 can contain a Content-Type and a body now. - Many bugfixes, especially related to Cookie handling. ## [0.2] 2007-05-16 - HTTP Basic authentication. - Cookie Sessions. - Static file handler. - Improved Rack::Request. - Improved Rack::Response. - Added Rack::ShowStatus, for better default error messages. - Bug fixes in the Camping adapter. - Removed Rails adapter, was too alpha. ## [0.1] 2007-03-03 [@ioquatix]: https://github.com/ioquatix "Samuel Williams" [@jeremyevans]: https://github.com/jeremyevans "Jeremy Evans" [@amatsuda]: https://github.com/amatsuda "Akira Matsuda" [@wjordan]: https://github.com/wjordan "Will Jordan" [@BlakeWilliams]: https://github.com/BlakeWilliams "Blake Williams" PK% ]tz,,gems/rack-3.0.8/README.mdnu[# ![Rack](contrib/logo.webp) > **_NOTE:_** Rack v3.0.0 was recently released. Please check the [Upgrade > Guide](UPGRADE-GUIDE.md) for more details about migrating your existing > servers, middlewares and applications. For detailed information on specific > changes, check the [Change Log](CHANGELOG.md). Rack provides a minimal, modular, and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the bridge between web servers, web frameworks, and web application into a single method call. The exact details of this are described in the [Rack Specification], which all Rack applications should conform to. ## Installation Add the rack gem to your application bundle, or follow the instructions provided by a [supported web framework](#supported-web-frameworks): ```bash # Install it generally: $ gem install rack --pre # or, add it to your current application gemfile: $ bundle add rack --version 3.0.0 ``` If you need features from `Rack::Session` or `bin/rackup` please add those gems separately. ```bash $ gem install rack-session rackup ``` ## Usage Create a file called `config.ru` with the following contents: ```ruby run do |env| [200, {}, ["Hello World"]] end ``` Run this using the rackup gem or another [supported web server](#supported-web-servers). ```bash $ gem install rackup $ rackup $ curl http://localhost:9292 Hello World ``` ## Supported web servers Rack is supported by a wide range of servers, including: * [Agoo](https://github.com/ohler55/agoo) * [Falcon](https://github.com/socketry/falcon) **(Rack 3 Compatible)** * [Iodine](https://github.com/boazsegev/iodine) * [NGINX Unit](https://unit.nginx.org/) * [Phusion Passenger](https://www.phusionpassenger.com/) (which is mod_rack for Apache and for nginx) * [Puma](https://puma.io/) * [Thin](https://github.com/macournoyer/thin) * [Unicorn](https://yhbt.net/unicorn/) * [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/) * [Lamby](https://lamby.custominktech.com) (for AWS Lambda) You will need to consult the server documentation to find out what features and limitations they may have. In general, any valid Rack app will run the same on all these servers, without changing anything. ### Rackup Rack provides a separate gem, [rackup](https://github.com/rack/rackup) which is a generic interface for running a Rack application on supported servers, which include `WEBRick`, `Puma`, `Falcon` and others. ## Supported web frameworks These frameworks and many others support the [Rack Specification]: * [Camping](https://github.com/camping/camping) * [Hanami](https://hanamirb.org/) * [Padrino](https://padrinorb.com/) * [Roda](https://github.com/jeremyevans/roda) **(Rack 3 Compatible)** * [Ruby on Rails](https://rubyonrails.org/) * [Sinatra](https://sinatrarb.com/) * [Utopia](https://github.com/socketry/utopia) **(Rack 3 Compatible)** * [WABuR](https://github.com/ohler55/wabur) ### Older (possibly unsupported) web frameworks * [Ramaze](http://ramaze.net/) * [Rum](https://github.com/leahneukirchen/rum) ## Available middleware shipped with Rack Between the server and the framework, Rack can be customized to your applications needs using middleware. Rack itself ships with the following middleware: * `Rack::CommonLogger` for creating Apache-style logfiles. * `Rack::ConditionalGet` for returning [Not Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304) responses when the response has not changed. * `Rack::Config` for modifying the environment before processing the request. * `Rack::ContentLength` for setting a `content-length` header based on body size. * `Rack::ContentType` for setting a default `content-type` header for responses. * `Rack::Deflater` for compressing responses with gzip. * `Rack::ETag` for setting `etag` header on bodies that can be buffered. * `Rack::Events` for providing easy hooks when a request is received and when the response is sent. * `Rack::Files` for serving static files. * `Rack::Head` for returning an empty body for HEAD requests. * `Rack::Lint` for checking conformance to the [Rack Specification]. * `Rack::Lock` for serializing requests using a mutex. * `Rack::Logger` for setting a logger to handle logging errors. * `Rack::MethodOverride` for modifying the request method based on a submitted parameter. * `Rack::Recursive` for including data from other paths in the application, and for performing internal redirects. * `Rack::Reloader` for reloading files if they have been modified. * `Rack::Runtime` for including a response header with the time taken to process the request. * `Rack::Sendfile` for working with web servers that can use optimized file serving for file system paths. * `Rack::ShowException` for catching unhandled exceptions and presenting them in a nice and helpful way with clickable backtrace. * `Rack::ShowStatus` for using nice error pages for empty client error responses. * `Rack::Static` for more configurable serving of static files. * `Rack::TempfileReaper` for removing temporary files creating during a request. All these components use the same interface, which is described in detail in the [Rack Specification]. These optional components can be used in any way you wish. ### Convenience interfaces If you want to develop outside of existing frameworks, implement your own ones, or develop middleware, Rack provides many helpers to create Rack applications quickly and without doing the same web stuff all over: * `Rack::Request` which also provides query string parsing and multipart handling. * `Rack::Response` for convenient generation of HTTP replies and cookie handling. * `Rack::MockRequest` and `Rack::MockResponse` for efficient and quick testing of Rack application without real HTTP round-trips. * `Rack::Cascade` for trying additional Rack applications if an application returns a not found or method not supported response. * `Rack::Directory` for serving files under a given directory, with directory indexes. * `Rack::MediaType` for parsing content-type headers. * `Rack::Mime` for determining content-type based on file extension. * `Rack::RewindableInput` for making any IO object rewindable, using a temporary file buffer. * `Rack::URLMap` to route to multiple applications inside the same process. ## Configuration Rack exposes several configuration parameters to control various features of the implementation. ### `param_depth_limit` ```ruby Rack::Utils.param_depth_limit = 32 # default ``` The maximum amount of nesting allowed in parameters. For example, if set to 3, this query string would be allowed: ``` ?a[b][c]=d ``` but this query string would not be allowed: ``` ?a[b][c][d]=e ``` Limiting the depth prevents a possible stack overflow when parsing parameters. ### `multipart_file_limit` ```ruby Rack::Utils.multipart_file_limit = 128 # default ``` The maximum number of parts with a filename a request can contain. Accepting too many parts can lead to the server running out of file handles. The default is 128, which means that a single request can't upload more than 128 files at once. Set to 0 for no limit. Can also be set via the `RACK_MULTIPART_FILE_LIMIT` environment variable. (This is also aliased as `multipart_part_limit` and `RACK_MULTIPART_PART_LIMIT` for compatibility) ### `multipart_total_part_limit` The maximum total number of parts a request can contain of any type, including both file and non-file form fields. The default is 4096, which means that a single request can't contain more than 4096 parts. Set to 0 for no limit. Can also be set via the `RACK_MULTIPART_TOTAL_PART_LIMIT` environment variable. ## Changelog See [CHANGELOG.md](CHANGELOG.md). ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md) for specific details about how to make a contribution to Rack. Please post bugs, suggestions and patches to [GitHub Issues](https://github.com/rack/rack/issues). Please check our [Security Policy](https://github.com/rack/rack/security/policy) for responsible disclosure and security bug reporting process. Due to wide usage of the library, it is strongly preferred that we manage timing in order to provide viable patches at the time of disclosure. Your assistance in this matter is greatly appreciated. ## See Also ### `rack-contrib` The plethora of useful middleware created the need for a project that collects fresh Rack middleware. `rack-contrib` includes a variety of add-on components for Rack and it is easy to contribute new modules. * https://github.com/rack/rack-contrib ### `rack-session` Provides convenient session management for Rack. * https://github.com/rack/rack-session ## Thanks The Rack Core Team, consisting of * Aaron Patterson [tenderlove](https://github.com/tenderlove) * Samuel Williams [ioquatix](https://github.com/ioquatix) * Jeremy Evans [jeremyevans](https://github.com/jeremyevans) * Eileen Uchitelle [eileencodes](https://github.com/eileencodes) * Matthew Draper [matthewd](https://github.com/matthewd) * Rafael França [rafaelfranca](https://github.com/rafaelfranca) and the Rack Alumni * Ryan Tomayko [rtomayko](https://github.com/rtomayko) * Scytrin dai Kinthra [scytrin](https://github.com/scytrin) * Leah Neukirchen [leahneukirchen](https://github.com/leahneukirchen) * James Tucker [raggi](https://github.com/raggi) * Josh Peek [josh](https://github.com/josh) * José Valim [josevalim](https://github.com/josevalim) * Michael Fellinger [manveru](https://github.com/manveru) * Santiago Pastorino [spastorino](https://github.com/spastorino) * Konstantin Haase [rkh](https://github.com/rkh) would like to thank: * Adrian Madrid, for the LiteSpeed handler. * Christoffer Sawicki, for the first Rails adapter and `Rack::Deflater`. * Tim Fletcher, for the HTTP authentication code. * Luc Heinrich for the Cookie sessions, the static file handler and bugfixes. * Armin Ronacher, for the logo and racktools. * Alex Beregszaszi, Alexander Kahn, Anil Wadghule, Aredridel, Ben Alpert, Dan Kubb, Daniel Roethlisberger, Matt Todd, Tom Robinson, Phil Hagelberg, S. Brent Faulkner, Bosko Milekic, Daniel Rodríguez Troitiño, Genki Takiuchi, Geoffrey Grosenbach, Julien Sanchez, Kamal Fariz Mahyuddin, Masayoshi Takahashi, Patrick Aljordm, Mig, Kazuhiro Nishiyama, Jon Bardin, Konstantin Haase, Larry Siden, Matias Korhonen, Sam Ruby, Simon Chiang, Tim Connor, Timur Batyrshin, and Zach Brock for bug fixing and other improvements. * Eric Wong, Hongli Lai, Jeremy Kemper for their continuous support and API improvements. * Yehuda Katz and Carl Lerche for refactoring rackup. * Brian Candler, for `Rack::ContentType`. * Graham Batty, for improved handler loading. * Stephen Bannasch, for bug reports and documentation. * Gary Wright, for proposing a better `Rack::Response` interface. * Jonathan Buch, for improvements regarding `Rack::Response`. * Armin Röhrl, for tracking down bugs in the Cookie generator. * Alexander Kellett for testing the Gem and reviewing the announcement. * Marcus Rückert, for help with configuring and debugging lighttpd. * The WSGI team for the well-done and documented work they've done and Rack builds up on. * All bug reporters and patch contributors not mentioned above. ## License Rack is released under the [MIT License](MIT-LICENSE). [Rack Specification]: SPEC.rdoc PK% ]_* * gems/rack-3.0.8/CONTRIBUTING.mdnu[# Contributing to Rack Rack is work of [hundreds of contributors](https://github.com/rack/rack/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/rack/rack/pulls) and [propose features and discuss issues](https://github.com/rack/rack/issues). ## Fork the Project Fork the [project on GitHub](https://github.com/rack/rack) and check out your copy. ``` git clone https://github.com/(your-github-username)/rack.git cd rack git remote add upstream https://github.com/rack/rack.git ``` ## Create a Topic Branch Make sure your fork is up-to-date and create a topic branch for your feature or bug fix. ``` git checkout main git pull upstream main git checkout -b my-feature-branch ``` ## Bundle Install and Quick Test Ensure that you can build the project and run quick tests. ``` bundle install --without extra bundle exec rake test ``` ## Running All Tests Install all dependencies. ``` bundle install ``` Run all tests. ``` rake test ``` ## Write Tests Try to write a test that reproduces the problem you're trying to fix or describes a feature that you want to build. We definitely appreciate pull requests that highlight or reproduce a problem, even without a fix. ## Write Code Implement your feature or bug fix. Make sure that all tests pass: ``` bundle exec rake test ``` ## Write Documentation Document any external behavior in the [README](README.md). ## Update Changelog Add a line to [CHANGELOG](CHANGELOG.md). ## Commit Changes Make sure git knows your name and email address: ``` git config --global user.name "Your Name" git config --global user.email "contributor@example.com" ``` Writing good commit logs is important. A commit log should describe what changed and why. ``` git add ... git commit ``` ## Push ``` git push origin my-feature-branch ``` ## Make a Pull Request Go to your fork of rack on GitHub and select your feature branch. Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days. ## Rebase If you've been working on a change for a while, rebase with upstream/main. ``` git fetch upstream git rebase upstream/main git push origin my-feature-branch -f ``` ## Make Required Changes Amend your previous commit and force push the changes. ``` git commit --amend git push origin my-feature-branch -f ``` ## Check on Your Pull Request Go back to your pull request after a few minutes and see whether it passed tests with GitHub Actions. Everything should look green, otherwise fix issues and amend your commit as described above. ## Be Patient It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang in there! ## Thank You Please do know that we really appreciate and value your time and work. We love you, really. PK% ]um gems/rack-3.0.8/lib/rack.rbnu[# frozen_string_literal: true # Copyright (C) 2007-2019 Leah Neukirchen # # Rack is freely distributable under the terms of an MIT-style license. # See MIT-LICENSE or https://opensource.org/licenses/MIT. # The Rack main module, serving as a namespace for all core Rack # modules and classes. # # All modules meant for use in your application are autoloaded here, # so it should be enough just to require 'rack' in your code. require_relative 'rack/version' require_relative 'rack/constants' module Rack autoload :Builder, "rack/builder" autoload :BodyProxy, "rack/body_proxy" autoload :Cascade, "rack/cascade" autoload :Chunked, "rack/chunked" autoload :CommonLogger, "rack/common_logger" autoload :ConditionalGet, "rack/conditional_get" autoload :Config, "rack/config" autoload :ContentLength, "rack/content_length" autoload :ContentType, "rack/content_type" autoload :ETag, "rack/etag" autoload :Events, "rack/events" autoload :File, "rack/file" autoload :Files, "rack/files" autoload :Deflater, "rack/deflater" autoload :Directory, "rack/directory" autoload :ForwardRequest, "rack/recursive" autoload :Handler, "rack/handler" autoload :Head, "rack/head" autoload :Headers, "rack/headers" autoload :Lint, "rack/lint" autoload :Lock, "rack/lock" autoload :Logger, "rack/logger" autoload :MediaType, "rack/media_type" autoload :MethodOverride, "rack/method_override" autoload :Mime, "rack/mime" autoload :NullLogger, "rack/null_logger" autoload :QueryParser, "rack/query_parser" autoload :Recursive, "rack/recursive" autoload :Reloader, "rack/reloader" autoload :RewindableInput, "rack/rewindable_input" autoload :Runtime, "rack/runtime" autoload :Sendfile, "rack/sendfile" autoload :Server, "rack/server" autoload :ShowExceptions, "rack/show_exceptions" autoload :ShowStatus, "rack/show_status" autoload :Static, "rack/static" autoload :TempfileReaper, "rack/tempfile_reaper" autoload :URLMap, "rack/urlmap" autoload :Utils, "rack/utils" autoload :Multipart, "rack/multipart" autoload :MockRequest, "rack/mock_request" autoload :MockResponse, "rack/mock_response" autoload :Request, "rack/request" autoload :Response, "rack/response" module Auth autoload :Basic, "rack/auth/basic" autoload :AbstractRequest, "rack/auth/abstract/request" autoload :AbstractHandler, "rack/auth/abstract/handler" autoload :Digest, "rack/auth/digest" end end PK% ]:}= = "gems/rack-3.0.8/lib/rack/urlmap.rbnu[# frozen_string_literal: true require 'set' require_relative 'constants' module Rack # Rack::URLMap takes a hash mapping urls or paths to apps, and # dispatches accordingly. Support for HTTP/1.1 host names exists if # the URLs start with http:// or https://. # # URLMap modifies the SCRIPT_NAME and PATH_INFO such that the part # relevant for dispatch is in the SCRIPT_NAME, and the rest in the # PATH_INFO. This should be taken care of when you need to # reconstruct the URL in order to create links. # # URLMap dispatches in such a way that the longest paths are tried # first, since they are most specific. class URLMap def initialize(map = {}) remap(map) end def remap(map) @known_hosts = Set[] @mapping = map.map { |location, app| if location =~ %r{\Ahttps?://(.*?)(/.*)} host, location = $1, $2 @known_hosts << host else host = nil end unless location[0] == ?/ raise ArgumentError, "paths need to start with /" end location = location.chomp('/') match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", Regexp::NOENCODING) [host, location, match, app] }.sort_by do |(host, location, _, _)| [host ? -host.size : Float::INFINITY, -location.size] end end def call(env) path = env[PATH_INFO] script_name = env[SCRIPT_NAME] http_host = env[HTTP_HOST] server_name = env[SERVER_NAME] server_port = env[SERVER_PORT] is_same_server = casecmp?(http_host, server_name) || casecmp?(http_host, "#{server_name}:#{server_port}") is_host_known = @known_hosts.include? http_host @mapping.each do |host, location, match, app| unless casecmp?(http_host, host) \ || casecmp?(server_name, host) \ || (!host && is_same_server) \ || (!host && !is_host_known) # If we don't have a matching host, default to the first without a specified host next end next unless m = match.match(path.to_s) rest = m[1] next unless !rest || rest.empty? || rest[0] == ?/ env[SCRIPT_NAME] = (script_name + location) env[PATH_INFO] = rest return app.call(env) end [404, { CONTENT_TYPE => "text/plain", "x-cascade" => "pass" }, ["Not Found: #{path}"]] ensure env[PATH_INFO] = path env[SCRIPT_NAME] = script_name end private def casecmp?(v1, v2) # if both nil, or they're the same string return true if v1 == v2 # if either are nil... (but they're not the same) return false if v1.nil? return false if v2.nil? # otherwise check they're not case-insensitive the same v1.casecmp(v2).zero? end end end PK% ]М} gems/rack-3.0.8/lib/rack/file.rbnu[# frozen_string_literal: true require_relative 'files' module Rack warn "Rack::File is deprecated and will be removed in Rack 3.1", uplevel: 1 File = Files end PK% ];`ff#gems/rack-3.0.8/lib/rack/runtime.rbnu[# frozen_string_literal: true require_relative 'utils' module Rack # Sets an "x-runtime" response header, indicating the response # time of the request, in seconds # # You can put it right before the application to see the processing # time, or before all the other middlewares to include time for them, # too. class Runtime FORMAT_STRING = "%0.6f" # :nodoc: HEADER_NAME = "x-runtime" # :nodoc: def initialize(app, name = nil) @app = app @header_name = HEADER_NAME @header_name += "-#{name.to_s.downcase}" if name end def call(env) start_time = Utils.clock_time _, headers, _ = response = @app.call(env) request_time = Utils.clock_time - start_time unless headers.key?(@header_name) headers[@header_name] = FORMAT_STRING % request_time end response end end end PK% ]4 4 #gems/rack-3.0.8/lib/rack/chunked.rbnu[# frozen_string_literal: true require_relative 'constants' require_relative 'utils' module Rack warn "Rack::Chunked is deprecated and will be removed in Rack 3.1", uplevel: 1 # Middleware that applies chunked transfer encoding to response bodies # when the response does not include a content-length header. # # This supports the trailer response header to allow the use of trailing # headers in the chunked encoding. However, using this requires you manually # specify a response body that supports a +trailers+ method. Example: # # [200, { 'trailer' => 'expires'}, ["Hello", "World"]] # # error raised # # body = ["Hello", "World"] # def body.trailers # { 'expires' => Time.now.to_s } # end # [200, { 'trailer' => 'expires'}, body] # # No exception raised class Chunked include Rack::Utils # A body wrapper that emits chunked responses. class Body TERM = "\r\n" TAIL = "0#{TERM}" # Store the response body to be chunked. def initialize(body) @body = body end # For each element yielded by the response body, yield # the element in chunked encoding. def each(&block) term = TERM @body.each do |chunk| size = chunk.bytesize next if size == 0 yield [size.to_s(16), term, chunk.b, term].join end yield TAIL yield_trailers(&block) yield term end # Close the response body if the response body supports it. def close @body.close if @body.respond_to?(:close) end private # Do nothing as this class does not support trailer headers. def yield_trailers end end # A body wrapper that emits chunked responses and also supports # sending Trailer headers. Note that the response body provided to # initialize must have a +trailers+ method that returns a hash # of trailer headers, and the rack response itself should have a # Trailer header listing the headers that the +trailers+ method # will return. class TrailerBody < Body private # Yield strings for each trailer header. def yield_trailers @body.trailers.each_pair do |k, v| yield "#{k}: #{v}\r\n" end end end def initialize(app) @app = app end # Whether the HTTP version supports chunked encoding (HTTP 1.1 does). def chunkable_version?(ver) case ver # pre-HTTP/1.0 (informally "HTTP/0.9") HTTP requests did not have # a version (nor response headers) when 'HTTP/1.0', nil, 'HTTP/0.9' false else true end end # If the rack app returns a response that should have a body, # but does not have content-length or transfer-encoding headers, # modify the response to use chunked transfer-encoding. def call(env) status, headers, body = response = @app.call(env) if chunkable_version?(env[SERVER_PROTOCOL]) && !STATUS_WITH_NO_ENTITY_BODY.key?(status.to_i) && !headers[CONTENT_LENGTH] && !headers[TRANSFER_ENCODING] headers[TRANSFER_ENCODING] = 'chunked' if headers['trailer'] response[2] = TrailerBody.new(body) else response[2] = Body.new(body) end end response end end end PK% ]HSGbGb#gems/rack-3.0.8/lib/rack/request.rbnu[# frozen_string_literal: true require_relative 'constants' require_relative 'utils' require_relative 'media_type' module Rack # Rack::Request provides a convenient interface to a Rack # environment. It is stateless, the environment +env+ passed to the # constructor will be directly modified. # # req = Rack::Request.new(env) # req.post? # req.params["data"] class Request class << self attr_accessor :ip_filter # The priority when checking forwarded headers. The default # is [:forwarded, :x_forwarded], which means, check the # +Forwarded+ header first, followed by the appropriate # X-Forwarded-* header. You can revert the priority by # reversing the priority, or remove checking of either # or both headers by removing elements from the array. # # This should be set as appropriate in your environment # based on what reverse proxies are in use. If you are not # using reverse proxies, you should probably use an empty # array. attr_accessor :forwarded_priority # The priority when checking either the X-Forwarded-Proto # or X-Forwarded-Scheme header for the forwarded protocol. # The default is [:proto, :scheme], to try the # X-Forwarded-Proto header before the # X-Forwarded-Scheme header. Rack 2 had behavior # similar to [:scheme, :proto]. You can remove either or # both of the entries in array to ignore that respective header. attr_accessor :x_forwarded_proto_priority end @forwarded_priority = [:forwarded, :x_forwarded] @x_forwarded_proto_priority = [:proto, :scheme] valid_ipv4_octet = /\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])/ trusted_proxies = Regexp.union( /\A127#{valid_ipv4_octet}{3}\z/, # localhost IPv4 range 127.x.x.x, per RFC-3330 /\A::1\z/, # localhost IPv6 ::1 /\Af[cd][0-9a-f]{2}(?::[0-9a-f]{0,4}){0,7}\z/i, # private IPv6 range fc00 .. fdff /\A10#{valid_ipv4_octet}{3}\z/, # private IPv4 range 10.x.x.x /\A172\.(1[6-9]|2[0-9]|3[01])#{valid_ipv4_octet}{2}\z/, # private IPv4 range 172.16.0.0 .. 172.31.255.255 /\A192\.168#{valid_ipv4_octet}{2}\z/, # private IPv4 range 192.168.x.x /\Alocalhost\z|\Aunix(\z|:)/i, # localhost hostname, and unix domain sockets ) self.ip_filter = lambda { |ip| trusted_proxies.match?(ip) } ALLOWED_SCHEMES = %w(https http wss ws).freeze def initialize(env) @env = env @params = nil end def params @params ||= super end def update_param(k, v) super @params = nil end def delete_param(k) v = super @params = nil v end module Env # The environment of the request. attr_reader :env def initialize(env) @env = env # This module is included at least in `ActionDispatch::Request` # The call to `super()` allows additional mixed-in initializers are called super() end # Predicate method to test to see if `name` has been set as request # specific data def has_header?(name) @env.key? name end # Get a request specific value for `name`. def get_header(name) @env[name] end # If a block is given, it yields to the block if the value hasn't been set # on the request. def fetch_header(name, &block) @env.fetch(name, &block) end # Loops through each key / value pair in the request specific data. def each_header(&block) @env.each(&block) end # Set a request specific value for `name` to `v` def set_header(name, v) @env[name] = v end # Add a header that may have multiple values. # # Example: # request.add_header 'Accept', 'image/png' # request.add_header 'Accept', '*/*' # # assert_equal 'image/png,*/*', request.get_header('Accept') # # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 def add_header(key, v) if v.nil? get_header key elsif has_header? key set_header key, "#{get_header key},#{v}" else set_header key, v end end # Delete a request specific value for `name`. def delete_header(name) @env.delete name end def initialize_copy(other) @env = other.env.dup end end module Helpers # The set of form-data media-types. Requests that do not indicate # one of the media types present in this list will not be eligible # for form-data / param parsing. FORM_DATA_MEDIA_TYPES = [ 'application/x-www-form-urlencoded', 'multipart/form-data' ] # The set of media-types. Requests that do not indicate # one of the media types present in this list will not be eligible # for param parsing like soap attachments or generic multiparts PARSEABLE_DATA_MEDIA_TYPES = [ 'multipart/related', 'multipart/mixed' ] # Default ports depending on scheme. Used to decide whether or not # to include the port in a generated URI. DEFAULT_PORTS = { 'http' => 80, 'https' => 443, 'coffee' => 80 } # The address of the client which connected to the proxy. HTTP_X_FORWARDED_FOR = 'HTTP_X_FORWARDED_FOR' # The contents of the host/:authority header sent to the proxy. HTTP_X_FORWARDED_HOST = 'HTTP_X_FORWARDED_HOST' HTTP_FORWARDED = 'HTTP_FORWARDED' # The value of the scheme sent to the proxy. HTTP_X_FORWARDED_SCHEME = 'HTTP_X_FORWARDED_SCHEME' # The protocol used to connect to the proxy. HTTP_X_FORWARDED_PROTO = 'HTTP_X_FORWARDED_PROTO' # The port used to connect to the proxy. HTTP_X_FORWARDED_PORT = 'HTTP_X_FORWARDED_PORT' # Another way for specifying https scheme was used. HTTP_X_FORWARDED_SSL = 'HTTP_X_FORWARDED_SSL' def body; get_header(RACK_INPUT) end def script_name; get_header(SCRIPT_NAME).to_s end def script_name=(s); set_header(SCRIPT_NAME, s.to_s) end def path_info; get_header(PATH_INFO).to_s end def path_info=(s); set_header(PATH_INFO, s.to_s) end def request_method; get_header(REQUEST_METHOD) end def query_string; get_header(QUERY_STRING).to_s end def content_length; get_header('CONTENT_LENGTH') end def logger; get_header(RACK_LOGGER) end def user_agent; get_header('HTTP_USER_AGENT') end # the referer of the client def referer; get_header('HTTP_REFERER') end alias referrer referer def session fetch_header(RACK_SESSION) do |k| set_header RACK_SESSION, default_session end end def session_options fetch_header(RACK_SESSION_OPTIONS) do |k| set_header RACK_SESSION_OPTIONS, {} end end # Checks the HTTP request method (or verb) to see if it was of type DELETE def delete?; request_method == DELETE end # Checks the HTTP request method (or verb) to see if it was of type GET def get?; request_method == GET end # Checks the HTTP request method (or verb) to see if it was of type HEAD def head?; request_method == HEAD end # Checks the HTTP request method (or verb) to see if it was of type OPTIONS def options?; request_method == OPTIONS end # Checks the HTTP request method (or verb) to see if it was of type LINK def link?; request_method == LINK end # Checks the HTTP request method (or verb) to see if it was of type PATCH def patch?; request_method == PATCH end # Checks the HTTP request method (or verb) to see if it was of type POST def post?; request_method == POST end # Checks the HTTP request method (or verb) to see if it was of type PUT def put?; request_method == PUT end # Checks the HTTP request method (or verb) to see if it was of type TRACE def trace?; request_method == TRACE end # Checks the HTTP request method (or verb) to see if it was of type UNLINK def unlink?; request_method == UNLINK end def scheme if get_header(HTTPS) == 'on' 'https' elsif get_header(HTTP_X_FORWARDED_SSL) == 'on' 'https' elsif forwarded_scheme forwarded_scheme else get_header(RACK_URL_SCHEME) end end # The authority of the incoming request as defined by RFC3976. # https://tools.ietf.org/html/rfc3986#section-3.2 # # In HTTP/1, this is the `host` header. # In HTTP/2, this is the `:authority` pseudo-header. def authority forwarded_authority || host_authority || server_authority end # The authority as defined by the `SERVER_NAME` and `SERVER_PORT` # variables. def server_authority host = self.server_name port = self.server_port if host if port "#{host}:#{port}" else host end end end def server_name get_header(SERVER_NAME) end def server_port get_header(SERVER_PORT) end def cookies hash = fetch_header(RACK_REQUEST_COOKIE_HASH) do |key| set_header(key, {}) end string = get_header(HTTP_COOKIE) unless string == get_header(RACK_REQUEST_COOKIE_STRING) hash.replace Utils.parse_cookies_header(string) set_header(RACK_REQUEST_COOKIE_STRING, string) end hash end def content_type content_type = get_header('CONTENT_TYPE') content_type.nil? || content_type.empty? ? nil : content_type end def xhr? get_header("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest" end # The `HTTP_HOST` header. def host_authority get_header(HTTP_HOST) end def host_with_port(authority = self.authority) host, _, port = split_authority(authority) if port == DEFAULT_PORTS[self.scheme] host else authority end end # Returns a formatted host, suitable for being used in a URI. def host split_authority(self.authority)[0] end # Returns an address suitable for being to resolve to an address. # In the case of a domain name or IPv4 address, the result is the same # as +host+. In the case of IPv6 or future address formats, the square # brackets are removed. def hostname split_authority(self.authority)[1] end def port if authority = self.authority _, _, port = split_authority(authority) end port || forwarded_port&.last || DEFAULT_PORTS[scheme] || server_port end def forwarded_for forwarded_priority.each do |type| case type when :forwarded if forwarded_for = get_http_forwarded(:for) return(forwarded_for.map! do |authority| split_authority(authority)[1] end) end when :x_forwarded if value = get_header(HTTP_X_FORWARDED_FOR) return(split_header(value).map do |authority| split_authority(wrap_ipv6(authority))[1] end) end end end nil end def forwarded_port forwarded_priority.each do |type| case type when :forwarded if forwarded = get_http_forwarded(:for) return(forwarded.map do |authority| split_authority(authority)[2] end.compact) end when :x_forwarded if value = get_header(HTTP_X_FORWARDED_PORT) return split_header(value).map(&:to_i) end end end nil end def forwarded_authority forwarded_priority.each do |type| case type when :forwarded if forwarded = get_http_forwarded(:host) return forwarded.last end when :x_forwarded if value = get_header(HTTP_X_FORWARDED_HOST) return wrap_ipv6(split_header(value).last) end end end nil end def ssl? scheme == 'https' || scheme == 'wss' end def ip remote_addresses = split_header(get_header('REMOTE_ADDR')) external_addresses = reject_trusted_ip_addresses(remote_addresses) unless external_addresses.empty? return external_addresses.last end if (forwarded_for = self.forwarded_for) && !forwarded_for.empty? # The forwarded for addresses are ordered: client, proxy1, proxy2. # So we reject all the trusted addresses (proxy*) and return the # last client. Or if we trust everyone, we just return the first # address. return reject_trusted_ip_addresses(forwarded_for).last || forwarded_for.first end # If all the addresses are trusted, and we aren't forwarded, just return # the first remote address, which represents the source of the request. remote_addresses.first end # The media type (type/subtype) portion of the CONTENT_TYPE header # without any media type parameters. e.g., when CONTENT_TYPE is # "text/plain;charset=utf-8", the media-type is "text/plain". # # For more information on the use of media types in HTTP, see: # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7 def media_type MediaType.type(content_type) end # The media type parameters provided in CONTENT_TYPE as a Hash, or # an empty Hash if no CONTENT_TYPE or media-type parameters were # provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8", # this method responds with the following Hash: # { 'charset' => 'utf-8' } def media_type_params MediaType.params(content_type) end # The character set of the request body if a "charset" media type # parameter was given, or nil if no "charset" was specified. Note # that, per RFC2616, text/* media types that specify no explicit # charset are to be considered ISO-8859-1. def content_charset media_type_params['charset'] end # Determine whether the request body contains form-data by checking # the request content-type for one of the media-types: # "application/x-www-form-urlencoded" or "multipart/form-data". The # list of form-data media types can be modified through the # +FORM_DATA_MEDIA_TYPES+ array. # # A request body is also assumed to contain form-data when no # content-type header is provided and the request_method is POST. def form_data? type = media_type meth = get_header(RACK_METHODOVERRIDE_ORIGINAL_METHOD) || get_header(REQUEST_METHOD) (meth == POST && type.nil?) || FORM_DATA_MEDIA_TYPES.include?(type) end # Determine whether the request body contains data by checking # the request media_type against registered parse-data media-types def parseable_data? PARSEABLE_DATA_MEDIA_TYPES.include?(media_type) end # Returns the data received in the query string. def GET if get_header(RACK_REQUEST_QUERY_STRING) == query_string get_header(RACK_REQUEST_QUERY_HASH) else query_hash = parse_query(query_string, '&') set_header(RACK_REQUEST_QUERY_STRING, query_string) set_header(RACK_REQUEST_QUERY_HASH, query_hash) end end # Returns the data received in the request body. # # This method support both application/x-www-form-urlencoded and # multipart/form-data. def POST if error = get_header(RACK_REQUEST_FORM_ERROR) raise error.class, error.message, cause: error.cause end begin rack_input = get_header(RACK_INPUT) # If the form hash was already memoized: if form_hash = get_header(RACK_REQUEST_FORM_HASH) # And it was memoized from the same input: if get_header(RACK_REQUEST_FORM_INPUT).equal?(rack_input) return form_hash end end # Otherwise, figure out how to parse the input: if rack_input.nil? set_header RACK_REQUEST_FORM_INPUT, nil set_header(RACK_REQUEST_FORM_HASH, {}) elsif form_data? || parseable_data? unless set_header(RACK_REQUEST_FORM_HASH, parse_multipart) form_vars = get_header(RACK_INPUT).read # Fix for Safari Ajax postings that always append \0 # form_vars.sub!(/\0\z/, '') # performance replacement: form_vars.slice!(-1) if form_vars.end_with?("\0") set_header RACK_REQUEST_FORM_VARS, form_vars set_header RACK_REQUEST_FORM_HASH, parse_query(form_vars, '&') end set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT) get_header RACK_REQUEST_FORM_HASH else set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT) set_header(RACK_REQUEST_FORM_HASH, {}) end rescue => error set_header(RACK_REQUEST_FORM_ERROR, error) raise end end # The union of GET and POST data. # # Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params. def params self.GET.merge(self.POST) end # Destructively update a parameter, whether it's in GET and/or POST. Returns nil. # # The parameter is updated wherever it was previous defined, so GET, POST, or both. If it wasn't previously defined, it's inserted into GET. # # env['rack.input'] is not touched. def update_param(k, v) found = false if self.GET.has_key?(k) found = true self.GET[k] = v end if self.POST.has_key?(k) found = true self.POST[k] = v end unless found self.GET[k] = v end end # Destructively delete a parameter, whether it's in GET or POST. Returns the value of the deleted parameter. # # If the parameter is in both GET and POST, the POST value takes precedence since that's how #params works. # # env['rack.input'] is not touched. def delete_param(k) post_value, get_value = self.POST.delete(k), self.GET.delete(k) post_value || get_value end def base_url "#{scheme}://#{host_with_port}" end # Tries to return a remake of the original request URL as a string. def url base_url + fullpath end def path script_name + path_info end def fullpath query_string.empty? ? path : "#{path}?#{query_string}" end def accept_encoding parse_http_accept_header(get_header("HTTP_ACCEPT_ENCODING")) end def accept_language parse_http_accept_header(get_header("HTTP_ACCEPT_LANGUAGE")) end def trusted_proxy?(ip) Rack::Request.ip_filter.call(ip) end # shortcut for request.params[key] def [](key) warn("Request#[] is deprecated and will be removed in a future version of Rack. Please use request.params[] instead", uplevel: 1) params[key.to_s] end # shortcut for request.params[key] = value # # Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params. def []=(key, value) warn("Request#[]= is deprecated and will be removed in a future version of Rack. Please use request.params[]= instead", uplevel: 1) params[key.to_s] = value end # like Hash#values_at def values_at(*keys) keys.map { |key| params[key] } end private def default_session; {}; end # Assist with compatibility when processing `X-Forwarded-For`. def wrap_ipv6(host) # Even thought IPv6 addresses should be wrapped in square brackets, # sometimes this is not done in various legacy/underspecified headers. # So we try to fix this situation for compatibility reasons. # Try to detect IPv6 addresses which aren't escaped yet: if !host.start_with?('[') && host.count(':') > 1 "[#{host}]" else host end end def parse_http_accept_header(header) header.to_s.split(",").each(&:strip!).map do |part| attribute, parameters = part.split(";", 2).each(&:strip!) quality = 1.0 if parameters and /\Aq=([\d.]+)/ =~ parameters quality = $1.to_f end [attribute, quality] end end # Get an array of values set in the RFC 7239 `Forwarded` request header. def get_http_forwarded(token) Utils.forwarded_values(get_header(HTTP_FORWARDED))&.[](token) end def query_parser Utils.default_query_parser end def parse_query(qs, d = '&') query_parser.parse_nested_query(qs, d) end def parse_multipart Rack::Multipart.extract_multipart(self, query_parser) end def split_header(value) value ? value.strip.split(/[,\s]+/) : [] end # ipv6 extracted from resolv stdlib, simplified # to remove numbered match group creation. ipv6 = Regexp.union( /(?:[0-9A-Fa-f]{1,4}:){7} [0-9A-Fa-f]{1,4}/x, /(?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)? :: (?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?/x, /(?:[0-9A-Fa-f]{1,4}:){6,6} \d+\.\d+\.\d+\.\d+/x, /(?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)? :: (?:[0-9A-Fa-f]{1,4}:)* \d+\.\d+\.\d+\.\d+/x, /[Ff][Ee]80 (?::[0-9A-Fa-f]{1,4}){7} %[-0-9A-Za-z._~]+/x, /[Ff][Ee]80: (?: (?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)? :: (?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)? | :(?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)? )? :[0-9A-Fa-f]{1,4}%[-0-9A-Za-z._~]+/x) AUTHORITY = / \A (? # Match IPv6 as a string of hex digits and colons in square brackets \[(?
#{ipv6})\] | # Match any other printable string (except square brackets) as a hostname (?
[[[:graph:]&&[^\[\]]]]*?) ) (:(?\d+))? \z /x private_constant :AUTHORITY def split_authority(authority) return [] if authority.nil? return [] unless match = AUTHORITY.match(authority) return match[:host], match[:address], match[:port]&.to_i end def reject_trusted_ip_addresses(ip_addresses) ip_addresses.reject { |ip| trusted_proxy?(ip) } end FORWARDED_SCHEME_HEADERS = { proto: HTTP_X_FORWARDED_PROTO, scheme: HTTP_X_FORWARDED_SCHEME }.freeze private_constant :FORWARDED_SCHEME_HEADERS def forwarded_scheme forwarded_priority.each do |type| case type when :forwarded if (forwarded_proto = get_http_forwarded(:proto)) && (scheme = allowed_scheme(forwarded_proto.last)) return scheme end when :x_forwarded x_forwarded_proto_priority.each do |x_type| if header = FORWARDED_SCHEME_HEADERS[x_type] split_header(get_header(header)).reverse_each do |scheme| if allowed_scheme(scheme) return scheme end end end end end end nil end def allowed_scheme(header) header if ALLOWED_SCHEMES.include?(header) end def forwarded_priority Request.forwarded_priority end def x_forwarded_proto_priority Request.x_forwarded_proto_priority end end include Env include Helpers end end # :nocov: require_relative 'multipart' unless defined?(Rack::Multipart) # :nocov: PK% ]ʆ66+gems/rack-3.0.8/lib/rack/show_exceptions.rbnu[# frozen_string_literal: true require 'ostruct' require 'erb' require_relative 'constants' require_relative 'utils' require_relative 'request' module Rack # Rack::ShowExceptions catches all exceptions raised from the app it # wraps. It shows a useful backtrace with the sourcefile and # clickable context, the whole Rack environment and the request # data. # # Be careful when you use this on public-facing sites as it could # reveal information helpful to attackers. class ShowExceptions CONTEXT = 7 def initialize(app) @app = app end def call(env) @app.call(env) rescue StandardError, LoadError, SyntaxError => e exception_string = dump_exception(e) env[RACK_ERRORS].puts(exception_string) env[RACK_ERRORS].flush if accepts_html?(env) content_type = "text/html" body = pretty(env, e) else content_type = "text/plain" body = exception_string end [ 500, { CONTENT_TYPE => content_type, CONTENT_LENGTH => body.bytesize.to_s, }, [body], ] end def prefers_plaintext?(env) !accepts_html?(env) end def accepts_html?(env) Rack::Utils.best_q_match(env["HTTP_ACCEPT"], %w[text/html]) end private :accepts_html? def dump_exception(exception) if exception.respond_to?(:detailed_message) message = exception.detailed_message(highlight: false) else message = exception.message end string = "#{exception.class}: #{message}\n".dup string << exception.backtrace.map { |l| "\t#{l}" }.join("\n") string end def pretty(env, exception) req = Rack::Request.new(env) # This double assignment is to prevent an "unused variable" warning. # Yes, it is dumb, but I don't like Ruby yelling at me. path = path = (req.script_name + req.path_info).squeeze("/") # This double assignment is to prevent an "unused variable" warning. # Yes, it is dumb, but I don't like Ruby yelling at me. frames = frames = exception.backtrace.map { |line| frame = OpenStruct.new if line =~ /(.*?):(\d+)(:in `(.*)')?/ frame.filename = $1 frame.lineno = $2.to_i frame.function = $4 begin lineno = frame.lineno - 1 lines = ::File.readlines(frame.filename) frame.pre_context_lineno = [lineno - CONTEXT, 0].max frame.pre_context = lines[frame.pre_context_lineno...lineno] frame.context_line = lines[lineno].chomp frame.post_context_lineno = [lineno + CONTEXT, lines.size].min frame.post_context = lines[lineno + 1..frame.post_context_lineno] rescue end frame else nil end }.compact template.result(binding) end def template TEMPLATE end def h(obj) # :nodoc: case obj when String Utils.escape_html(obj) else Utils.escape_html(obj.inspect) end end # :stopdoc: # adapted from Django # Copyright (c) Django Software Foundation and individual contributors. # Used under the modified BSD license: # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 TEMPLATE = ERB.new(<<-'HTML'.gsub(/^ /, '')) <%=h exception.class %> at <%=h path %>

<%=h exception.class %> at <%=h path %>

<% if exception.respond_to?(:detailed_message) %>

<%=h exception.detailed_message(highlight: false) %>

<% else %>

<%=h exception.message %>

<% end %>
Ruby <% if first = frames.first %> <%=h first.filename %>: in <%=h first.function %>, line <%=h frames.first.lineno %> <% else %> unknown location <% end %>
Web <%=h req.request_method %> <%=h(req.host + path)%>

Jump to:

Traceback (innermost first)

    <% frames.each { |frame| %>
  • <%=h frame.filename %>: in <%=h frame.function %> <% if frame.context_line %>
    <% if frame.pre_context %>
      <% frame.pre_context.each { |line| %>
    1. <%=h line %>
    2. <% } %>
    <% end %>
    1. <%=h frame.context_line %>...
    <% if frame.post_context %>
      <% frame.post_context.each { |line| %>
    1. <%=h line %>
    2. <% } %>
    <% end %>
    <% end %>
  • <% } %>

Request information

GET

<% if req.GET and not req.GET.empty? %> <% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %> <% } %>
Variable Value
<%=h key %>
<%=h val.inspect %>
<% else %>

No GET data.

<% end %>

POST

<% if ((req.POST and not req.POST.empty?) rescue (no_post_data = "Invalid POST data"; nil)) %> <% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %> <% } %>
Variable Value
<%=h key %>
<%=h val.inspect %>
<% else %>

<%= no_post_data || "No POST data" %>.

<% end %> <% unless req.cookies.empty? %> <% req.cookies.each { |key, val| %> <% } %>
Variable Value
<%=h key %>
<%=h val.inspect %>
<% else %>

No cookie data.

<% end %>

Rack ENV

<% env.sort_by { |k, v| k.to_s }.each { |key, val| %> <% } %>
Variable Value
<%=h key %>
<%=h val.inspect %>

You're seeing this error because you use Rack::ShowExceptions.

HTML # :startdoc: end end PK% ][J$gems/rack-3.0.8/lib/rack/deflater.rbnu[# frozen_string_literal: true require "zlib" require "time" # for Time.httpdate require_relative 'constants' require_relative 'utils' require_relative 'request' require_relative 'body_proxy' module Rack # This middleware enables content encoding of http responses, # usually for purposes of compression. # # Currently supported encodings: # # * gzip # * identity (no transformation) # # This middleware automatically detects when encoding is supported # and allowed. For example no encoding is made when a cache # directive of 'no-transform' is present, when the response status # code is one that doesn't allow an entity body, or when the body # is empty. # # Note that despite the name, Deflater does not support the +deflate+ # encoding. class Deflater # Creates Rack::Deflater middleware. Options: # # :if :: a lambda enabling / disabling deflation based on returned boolean value # (e.g use Rack::Deflater, :if => lambda { |*, body| sum=0; body.each { |i| sum += i.length }; sum > 512 }). # However, be aware that calling `body.each` inside the block will break cases where `body.each` is not idempotent, # such as when it is an +IO+ instance. # :include :: a list of content types that should be compressed. By default, all content types are compressed. # :sync :: determines if the stream is going to be flushed after every chunk. Flushing after every chunk reduces # latency for time-sensitive streaming applications, but hurts compression and throughput. # Defaults to +true+. def initialize(app, options = {}) @app = app @condition = options[:if] @compressible_types = options[:include] @sync = options.fetch(:sync, true) end def call(env) status, headers, body = response = @app.call(env) unless should_deflate?(env, status, headers, body) return response end request = Request.new(env) encoding = Utils.select_best_encoding(%w(gzip identity), request.accept_encoding) # Set the Vary HTTP header. vary = headers["vary"].to_s.split(",").map(&:strip) unless vary.include?("*") || vary.any?{|v| v.downcase == 'accept-encoding'} headers["vary"] = vary.push("Accept-Encoding").join(",") end case encoding when "gzip" headers['content-encoding'] = "gzip" headers.delete(CONTENT_LENGTH) mtime = headers["last-modified"] mtime = Time.httpdate(mtime).to_i if mtime response[2] = GzipStream.new(body, mtime, @sync) response when "identity" response else # when nil # Only possible encoding values here are 'gzip', 'identity', and nil message = "An acceptable encoding for the requested resource #{request.fullpath} could not be found." bp = Rack::BodyProxy.new([message]) { body.close if body.respond_to?(:close) } [406, { CONTENT_TYPE => "text/plain", CONTENT_LENGTH => message.length.to_s }, bp] end end # Body class used for gzip encoded responses. class GzipStream BUFFER_LENGTH = 128 * 1_024 # Initialize the gzip stream. Arguments: # body :: Response body to compress with gzip # mtime :: The modification time of the body, used to set the # modification time in the gzip header. # sync :: Whether to flush each gzip chunk as soon as it is ready. def initialize(body, mtime, sync) @body = body @mtime = mtime @sync = sync end # Yield gzip compressed strings to the given block. def each(&block) @writer = block gzip = ::Zlib::GzipWriter.new(self) gzip.mtime = @mtime if @mtime # @body.each is equivalent to @body.gets (slow) if @body.is_a? ::File # XXX: Should probably be ::IO while part = @body.read(BUFFER_LENGTH) gzip.write(part) gzip.flush if @sync end else @body.each { |part| # Skip empty strings, as they would result in no output, # and flushing empty parts would raise Zlib::BufError. next if part.empty? gzip.write(part) gzip.flush if @sync } end ensure gzip.finish end # Call the block passed to #each with the gzipped data. def write(data) @writer.call(data) end # Close the original body if possible. def close @body.close if @body.respond_to?(:close) end end private # Whether the body should be compressed. def should_deflate?(env, status, headers, body) # Skip compressing empty entity body responses and responses with # no-transform set. if Utils::STATUS_WITH_NO_ENTITY_BODY.key?(status.to_i) || /\bno-transform\b/.match?(headers[CACHE_CONTROL].to_s) || headers['content-encoding']&.!~(/\bidentity\b/) return false end # Skip if @compressible_types are given and does not include request's content type return false if @compressible_types && !(headers.has_key?(CONTENT_TYPE) && @compressible_types.include?(headers[CONTENT_TYPE][/[^;]*/])) # Skip if @condition lambda is given and evaluates to false return false if @condition && !@condition.call(env, status, headers, body) # No point in compressing empty body, also handles usage with # Rack::Sendfile. return false if headers[CONTENT_LENGTH] == '0' true end end end PK% ]>== gems/rack-3.0.8/lib/rack/lock.rbnu[# frozen_string_literal: true require_relative 'body_proxy' module Rack # Rack::Lock locks every request inside a mutex, so that every request # will effectively be executed synchronously. class Lock def initialize(app, mutex = Mutex.new) @app, @mutex = app, mutex end def call(env) @mutex.lock begin response = @app.call(env) returned = response << BodyProxy.new(response.pop) { unlock } ensure unlock unless returned end end private def unlock @mutex.unlock end end end PK% ]/{{(gems/rack-3.0.8/lib/rack/mock_request.rbnu[# frozen_string_literal: true require 'uri' require 'stringio' require_relative 'constants' require_relative 'mock_response' module Rack # Rack::MockRequest helps testing your Rack application without # actually using HTTP. # # After performing a request on a URL with get/post/put/patch/delete, it # returns a MockResponse with useful helper methods for effective # testing. # # You can pass a hash with additional configuration to the # get/post/put/patch/delete. # :input:: A String or IO-like to be used as rack.input. # :fatal:: Raise a FatalWarning if the app writes to rack.errors. # :lint:: If true, wrap the application in a Rack::Lint. class MockRequest class FatalWarning < RuntimeError end class FatalWarner def puts(warning) raise FatalWarning, warning end def write(warning) raise FatalWarning, warning end def flush end def string "" end end DEFAULT_ENV = { RACK_INPUT => StringIO.new, RACK_ERRORS => StringIO.new, }.freeze def initialize(app) @app = app end # Make a GET request and return a MockResponse. See #request. def get(uri, opts = {}) request(GET, uri, opts) end # Make a POST request and return a MockResponse. See #request. def post(uri, opts = {}) request(POST, uri, opts) end # Make a PUT request and return a MockResponse. See #request. def put(uri, opts = {}) request(PUT, uri, opts) end # Make a PATCH request and return a MockResponse. See #request. def patch(uri, opts = {}) request(PATCH, uri, opts) end # Make a DELETE request and return a MockResponse. See #request. def delete(uri, opts = {}) request(DELETE, uri, opts) end # Make a HEAD request and return a MockResponse. See #request. def head(uri, opts = {}) request(HEAD, uri, opts) end # Make an OPTIONS request and return a MockResponse. See #request. def options(uri, opts = {}) request(OPTIONS, uri, opts) end # Make a request using the given request method for the given # uri to the rack application and return a MockResponse. # Options given are passed to MockRequest.env_for. def request(method = GET, uri = "", opts = {}) env = self.class.env_for(uri, opts.merge(method: method)) if opts[:lint] app = Rack::Lint.new(@app) else app = @app end errors = env[RACK_ERRORS] status, headers, body = app.call(env) MockResponse.new(status, headers, body, errors) ensure body.close if body.respond_to?(:close) end # For historical reasons, we're pinning to RFC 2396. # URI::Parser = URI::RFC2396_Parser def self.parse_uri_rfc2396(uri) @parser ||= URI::Parser.new @parser.parse(uri) end # Return the Rack environment used for a request to +uri+. # All options that are strings are added to the returned environment. # Options: # :fatal :: Whether to raise an exception if request outputs to rack.errors # :input :: The rack.input to set # :http_version :: The SERVER_PROTOCOL to set # :method :: The HTTP request method to use # :params :: The params to use # :script_name :: The SCRIPT_NAME to set def self.env_for(uri = "", opts = {}) uri = parse_uri_rfc2396(uri) uri.path = "/#{uri.path}" unless uri.path[0] == ?/ env = DEFAULT_ENV.dup env[REQUEST_METHOD] = (opts[:method] ? opts[:method].to_s.upcase : GET).b env[SERVER_NAME] = (uri.host || "example.org").b env[SERVER_PORT] = (uri.port ? uri.port.to_s : "80").b env[SERVER_PROTOCOL] = opts[:http_version] || 'HTTP/1.1' env[QUERY_STRING] = (uri.query.to_s).b env[PATH_INFO] = (uri.path).b env[RACK_URL_SCHEME] = (uri.scheme || "http").b env[HTTPS] = (env[RACK_URL_SCHEME] == "https" ? "on" : "off").b env[SCRIPT_NAME] = opts[:script_name] || "" if opts[:fatal] env[RACK_ERRORS] = FatalWarner.new else env[RACK_ERRORS] = StringIO.new end if params = opts[:params] if env[REQUEST_METHOD] == GET params = Utils.parse_nested_query(params) if params.is_a?(String) params.update(Utils.parse_nested_query(env[QUERY_STRING])) env[QUERY_STRING] = Utils.build_nested_query(params) elsif !opts.has_key?(:input) opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded" if params.is_a?(Hash) if data = Rack::Multipart.build_multipart(params) opts[:input] = data opts["CONTENT_LENGTH"] ||= data.length.to_s opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{Rack::Multipart::MULTIPART_BOUNDARY}" else opts[:input] = Utils.build_nested_query(params) end else opts[:input] = params end end end opts[:input] ||= String.new if String === opts[:input] rack_input = StringIO.new(opts[:input]) else rack_input = opts[:input] end rack_input.set_encoding(Encoding::BINARY) env[RACK_INPUT] = rack_input env["CONTENT_LENGTH"] ||= env[RACK_INPUT].size.to_s if env[RACK_INPUT].respond_to?(:size) opts.each { |field, value| env[field] = value if String === field } env end end end PK% ]gG&gems/rack-3.0.8/lib/rack/media_type.rbnu[# frozen_string_literal: true module Rack # Rack::MediaType parse media type and parameters out of content_type string class MediaType SPLIT_PATTERN = %r{\s*[;,]\s*} class << self # The media type (type/subtype) portion of the CONTENT_TYPE header # without any media type parameters. e.g., when CONTENT_TYPE is # "text/plain;charset=utf-8", the media-type is "text/plain". # # For more information on the use of media types in HTTP, see: # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7 def type(content_type) return nil unless content_type content_type.split(SPLIT_PATTERN, 2).first.tap(&:downcase!) end # The media type parameters provided in CONTENT_TYPE as a Hash, or # an empty Hash if no CONTENT_TYPE or media-type parameters were # provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8", # this method responds with the following Hash: # { 'charset' => 'utf-8' } def params(content_type) return {} if content_type.nil? content_type.split(SPLIT_PATTERN)[1..-1].each_with_object({}) do |s, hsh| k, v = s.split('=', 2) hsh[k.tap(&:downcase!)] = strip_doublequotes(v) end end private def strip_doublequotes(str) (str.start_with?('"') && str.end_with?('"')) ? str[1..-2] : str end end end end PK% ]/gems/rack-3.0.8/lib/rack/auth/digest/request.rbnu[require_relative '../digest' PK% ]+gems/rack-3.0.8/lib/rack/auth/digest/md5.rbnu[require_relative '../digest' PK% ]-gems/rack-3.0.8/lib/rack/auth/digest/nonce.rbnu[require_relative '../digest' PK% ].gems/rack-3.0.8/lib/rack/auth/digest/params.rbnu[require_relative '../digest' PK% ],UU1gems/rack-3.0.8/lib/rack/auth/abstract/request.rbnu[# frozen_string_literal: true require_relative '../../request' module Rack module Auth class AbstractRequest def initialize(env) @env = env end def request @request ||= Request.new(@env) end def provided? !authorization_key.nil? && valid? end def valid? !@env[authorization_key].nil? end def parts @parts ||= @env[authorization_key].split(' ', 2) end def scheme @scheme ||= parts.first&.downcase end def params @params ||= parts.last end private AUTHORIZATION_KEYS = ['HTTP_AUTHORIZATION', 'X-HTTP_AUTHORIZATION', 'X_HTTP_AUTHORIZATION'] def authorization_key @authorization_key ||= AUTHORIZATION_KEYS.detect { |key| @env.has_key?(key) } end end end end PK% ]lGRR1gems/rack-3.0.8/lib/rack/auth/abstract/handler.rbnu[# frozen_string_literal: true require_relative '../../constants' module Rack module Auth # Rack::Auth::AbstractHandler implements common authentication functionality. # # +realm+ should be set for all handlers. class AbstractHandler attr_accessor :realm def initialize(app, realm = nil, &authenticator) @app, @realm, @authenticator = app, realm, authenticator end private def unauthorized(www_authenticate = challenge) return [ 401, { CONTENT_TYPE => 'text/plain', CONTENT_LENGTH => '0', 'www-authenticate' => www_authenticate.to_s }, [] ] end def bad_request return [ 400, { CONTENT_TYPE => 'text/plain', CONTENT_LENGTH => '0' }, [] ] end end end end PK% ]&gems/rack-3.0.8/lib/rack/auth/basic.rbnu[# frozen_string_literal: true require_relative 'abstract/handler' require_relative 'abstract/request' require 'base64' module Rack module Auth # Rack::Auth::Basic implements HTTP Basic Authentication, as per RFC 2617. # # Initialize with the Rack application that you want protecting, # and a block that checks if a username and password pair are valid. class Basic < AbstractHandler def call(env) auth = Basic::Request.new(env) return unauthorized unless auth.provided? return bad_request unless auth.basic? if valid?(auth) env['REMOTE_USER'] = auth.username return @app.call(env) end unauthorized end private def challenge 'Basic realm="%s"' % realm end def valid?(auth) @authenticator.call(*auth.credentials) end class Request < Auth::AbstractRequest def basic? "basic" == scheme && credentials.length == 2 end def credentials @credentials ||= Base64.decode64(params).split(':', 2) end def username credentials.first end end end end end PK% ]  'gems/rack-3.0.8/lib/rack/auth/digest.rbnu[# frozen_string_literal: true require_relative 'abstract/handler' require_relative 'abstract/request' require 'digest/md5' require 'base64' module Rack warn "Rack::Auth::Digest is deprecated and will be removed in Rack 3.1", uplevel: 1 module Auth module Digest # Rack::Auth::Digest::Nonce is the default nonce generator for the # Rack::Auth::Digest::MD5 authentication handler. # # +private_key+ needs to set to a constant string. # # +time_limit+ can be optionally set to an integer (number of seconds), # to limit the validity of the generated nonces. class Nonce class << self attr_accessor :private_key, :time_limit end def self.parse(string) new(*Base64.decode64(string).split(' ', 2)) end def initialize(timestamp = Time.now, given_digest = nil) @timestamp, @given_digest = timestamp.to_i, given_digest end def to_s Base64.encode64("#{@timestamp} #{digest}").strip end def digest ::Digest::MD5.hexdigest("#{@timestamp}:#{self.class.private_key}") end def valid? digest == @given_digest end def stale? !self.class.time_limit.nil? && (Time.now.to_i - @timestamp) > self.class.time_limit end def fresh? !stale? end end class Params < Hash def self.parse(str) Params[*split_header_value(str).map do |param| k, v = param.split('=', 2) [k, dequote(v)] end.flatten] end def self.dequote(str) # From WEBrick::HTTPUtils ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup ret.gsub!(/\\(.)/, "\\1") ret end def self.split_header_value(str) str.scan(/\w+\=(?:"[^\"]+"|[^,]+)/n) end def initialize super() yield self if block_given? end def [](k) super k.to_s end def []=(k, v) super k.to_s, v.to_s end UNQUOTED = ['nc', 'stale'] def to_s map do |k, v| "#{k}=#{(UNQUOTED.include?(k) ? v.to_s : quote(v))}" end.join(', ') end def quote(str) # From WEBrick::HTTPUtils '"' + str.gsub(/[\\\"]/o, "\\\1") + '"' end end class Request < Auth::AbstractRequest def method @env[RACK_METHODOVERRIDE_ORIGINAL_METHOD] || @env[REQUEST_METHOD] end def digest? "digest" == scheme end def correct_uri? request.fullpath == uri end def nonce @nonce ||= Nonce.parse(params['nonce']) end def params @params ||= Params.parse(parts.last) end def respond_to?(sym, *) super or params.has_key? sym.to_s end def method_missing(sym, *args) return super unless params.has_key?(key = sym.to_s) return params[key] if args.size == 0 raise ArgumentError, "wrong number of arguments (#{args.size} for 0)" end end # Rack::Auth::Digest::MD5 implements the MD5 algorithm version of # HTTP Digest Authentication, as per RFC 2617. # # Initialize with the [Rack] application that you want protecting, # and a block that looks up a plaintext password for a given username. # # +opaque+ needs to be set to a constant base64/hexadecimal string. # class MD5 < AbstractHandler attr_accessor :opaque attr_writer :passwords_hashed def initialize(app, realm = nil, opaque = nil, &authenticator) @passwords_hashed = nil if opaque.nil? and realm.respond_to? :values_at realm, opaque, @passwords_hashed = realm.values_at :realm, :opaque, :passwords_hashed end super(app, realm, &authenticator) @opaque = opaque end def passwords_hashed? !!@passwords_hashed end def call(env) auth = Request.new(env) unless auth.provided? return unauthorized end if !auth.digest? || !auth.correct_uri? || !valid_qop?(auth) return bad_request end if valid?(auth) if auth.nonce.stale? return unauthorized(challenge(stale: true)) else env['REMOTE_USER'] = auth.username return @app.call(env) end end unauthorized end private QOP = 'auth' def params(hash = {}) Params.new do |params| params['realm'] = realm params['nonce'] = Nonce.new.to_s params['opaque'] = H(opaque) params['qop'] = QOP hash.each { |k, v| params[k] = v } end end def challenge(hash = {}) "Digest #{params(hash)}" end def valid?(auth) valid_opaque?(auth) && valid_nonce?(auth) && valid_digest?(auth) end def valid_qop?(auth) QOP == auth.qop end def valid_opaque?(auth) H(opaque) == auth.opaque end def valid_nonce?(auth) auth.nonce.valid? end def valid_digest?(auth) pw = @authenticator.call(auth.username) pw && Rack::Utils.secure_compare(digest(auth, pw), auth.response) end def md5(data) ::Digest::MD5.hexdigest(data) end alias :H :md5 def KD(secret, data) H "#{secret}:#{data}" end def A1(auth, password) "#{auth.username}:#{auth.realm}:#{password}" end def A2(auth) "#{auth.method}:#{auth.uri}" end def digest(auth, password) password_hash = passwords_hashed? ? password : H(A1(auth, password)) KD password_hash, "#{auth.nonce}:#{auth.nc}:#{auth.cnonce}:#{QOP}:#{H A2(auth)}" end end end end end PK% ]>Sf?"?"#gems/rack-3.0.8/lib/rack/builder.rbnu[# frozen_string_literal: true require_relative 'urlmap' module Rack # Rack::Builder provides a domain-specific language (DSL) to construct Rack # applications. It is primarily used to parse +config.ru+ files which # instantiate several middleware and a final application which are hosted # by a Rack-compatible web server. # # Example: # # app = Rack::Builder.new do # use Rack::CommonLogger # map "/ok" do # run lambda { |env| [200, {'content-type' => 'text/plain'}, ['OK']] } # end # end # # run app # # Or # # app = Rack::Builder.app do # use Rack::CommonLogger # run lambda { |env| [200, {'content-type' => 'text/plain'}, ['OK']] } # end # # run app # # +use+ adds middleware to the stack, +run+ dispatches to an application. # You can use +map+ to construct a Rack::URLMap in a convenient way. class Builder # https://stackoverflow.com/questions/2223882/whats-the-difference-between-utf-8-and-utf-8-without-bom UTF_8_BOM = '\xef\xbb\xbf' # Parse the given config file to get a Rack application. # # If the config file ends in +.ru+, it is treated as a # rackup file and the contents will be treated as if # specified inside a Rack::Builder block. # # If the config file does not end in +.ru+, it is # required and Rack will use the basename of the file # to guess which constant will be the Rack application to run. # # Examples: # # Rack::Builder.parse_file('config.ru') # # Rack application built using Rack::Builder.new # # Rack::Builder.parse_file('app.rb') # # requires app.rb, which can be anywhere in Ruby's # # load path. After requiring, assumes App constant # # contains Rack application # # Rack::Builder.parse_file('./my_app.rb') # # requires ./my_app.rb, which should be in the # # process's current directory. After requiring, # # assumes MyApp constant contains Rack application def self.parse_file(path) if path.end_with?('.ru') return self.load_file(path) else require path return Object.const_get(::File.basename(path, '.rb').split('_').map(&:capitalize).join('')) end end # Load the given file as a rackup file, treating the # contents as if specified inside a Rack::Builder block. # # Ignores content in the file after +__END__+, so that # use of +__END__+ will not result in a syntax error. # # Example config.ru file: # # $ cat config.ru # # use Rack::ContentLength # require './app.rb' # run App def self.load_file(path) config = ::File.read(path) config.slice!(/\A#{UTF_8_BOM}/) if config.encoding == Encoding::UTF_8 if config[/^#\\(.*)/] fail "Parsing options from the first comment line is no longer supported: #{path}" end config.sub!(/^__END__\n.*\Z/m, '') return new_from_string(config, path) end # Evaluate the given +builder_script+ string in the context of # a Rack::Builder block, returning a Rack application. def self.new_from_string(builder_script, file = "(rackup)") # We want to build a variant of TOPLEVEL_BINDING with self as a Rack::Builder instance. # We cannot use instance_eval(String) as that would resolve constants differently. binding, builder = TOPLEVEL_BINDING.eval('Rack::Builder.new.instance_eval { [binding, self] }') eval builder_script, binding, file return builder.to_app end # Initialize a new Rack::Builder instance. +default_app+ specifies the # default application if +run+ is not called later. If a block # is given, it is evaluated in the context of the instance. def initialize(default_app = nil, &block) @use = [] @map = nil @run = default_app @warmup = nil @freeze_app = false instance_eval(&block) if block_given? end # Create a new Rack::Builder instance and return the Rack application # generated from it. def self.app(default_app = nil, &block) self.new(default_app, &block).to_app end # Specifies middleware to use in a stack. # # class Middleware # def initialize(app) # @app = app # end # # def call(env) # env["rack.some_header"] = "setting an example" # @app.call(env) # end # end # # use Middleware # run lambda { |env| [200, { "content-type" => "text/plain" }, ["OK"]] } # # All requests through to this application will first be processed by the middleware class. # The +call+ method in this example sets an additional environment key which then can be # referenced in the application if required. def use(middleware, *args, &block) if @map mapping, @map = @map, nil @use << proc { |app| generate_map(app, mapping) } end @use << proc { |app| middleware.new(app, *args, &block) } end # :nocov: ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true) # :nocov: # Takes a block or argument that is an object that responds to #call and # returns a Rack response. # # You can use a block: # # run do |env| # [200, { "content-type" => "text/plain" }, ["Hello World!"]] # end # # You can also provide a lambda: # # run lambda { |env| [200, { "content-type" => "text/plain" }, ["OK"]] } # # You can also provide a class instance: # # class Heartbeat # def call(env) # [200, { "content-type" => "text/plain" }, ["OK"]] # end # end # # run Heartbeat.new # def run(app = nil, &block) raise ArgumentError, "Both app and block given!" if app && block_given? @run = app || block end # Takes a lambda or block that is used to warm-up the application. This block is called # before the Rack application is returned by to_app. # # warmup do |app| # client = Rack::MockRequest.new(app) # client.get('/') # end # # use SomeMiddleware # run MyApp def warmup(prc = nil, &block) @warmup = prc || block end # Creates a route within the application. Routes under the mapped path will be sent to # the Rack application specified by run inside the block. Other requests will be sent to the # default application specified by run outside the block. # # class App # def call(env) # [200, {'content-type' => 'text/plain'}, ["Hello World"]] # end # end # # class Heartbeat # def call(env) # [200, { "content-type" => "text/plain" }, ["OK"]] # end # end # # app = Rack::Builder.app do # map '/heartbeat' do # run Heartbeat.new # end # run App.new # end # # run app # # The +use+ method can also be used inside the block to specify middleware to run under a specific path: # # app = Rack::Builder.app do # map '/heartbeat' do # use Middleware # run Heartbeat.new # end # run App.new # end # # This example includes a piece of middleware which will run before +/heartbeat+ requests hit +Heartbeat+. # # Note that providing a +path+ of +/+ will ignore any default application given in a +run+ statement # outside the block. def map(path, &block) @map ||= {} @map[path] = block end # Freeze the app (set using run) and all middleware instances when building the application # in to_app. def freeze_app @freeze_app = true end # Return the Rack application generated by this instance. def to_app app = @map ? generate_map(@run, @map) : @run fail "missing run or map statement" unless app app.freeze if @freeze_app app = @use.reverse.inject(app) { |a, e| e[a].tap { |x| x.freeze if @freeze_app } } @warmup.call(app) if @warmup app end # Call the Rack application generated by this builder instance. Note that # this rebuilds the Rack application and runs the warmup code (if any) # every time it is called, so it should not be used if performance is important. def call(env) to_app.call(env) end private # Generate a URLMap instance by generating new Rack applications for each # map block in this instance. def generate_map(default_app, mapping) mapped = default_app ? { '/' => default_app } : {} mapping.each { |r, b| mapped[r] = self.class.new(default_app, &b).to_app } URLMap.new(mapped) end end end PK% ]O~%gems/rack-3.0.8/lib/rack/recursive.rbnu[# frozen_string_literal: true require 'uri' require_relative 'constants' module Rack # Rack::ForwardRequest gets caught by Rack::Recursive and redirects # the current request to the app at +url+. # # raise ForwardRequest.new("/not-found") # class ForwardRequest < Exception attr_reader :url, :env def initialize(url, env = {}) @url = URI(url) @env = env @env[PATH_INFO] = @url.path @env[QUERY_STRING] = @url.query if @url.query @env[HTTP_HOST] = @url.host if @url.host @env[HTTP_PORT] = @url.port if @url.port @env[RACK_URL_SCHEME] = @url.scheme if @url.scheme super "forwarding to #{url}" end end # Rack::Recursive allows applications called down the chain to # include data from other applications (by using # rack['rack.recursive.include'][...] or raise a # ForwardRequest to redirect internally. class Recursive def initialize(app) @app = app end def call(env) dup._call(env) end def _call(env) @script_name = env[SCRIPT_NAME] @app.call(env.merge(RACK_RECURSIVE_INCLUDE => method(:include))) rescue ForwardRequest => req call(env.merge(req.env)) end def include(env, path) unless path.index(@script_name) == 0 && (path[@script_name.size] == ?/ || path[@script_name.size].nil?) raise ArgumentError, "can only include below #{@script_name}, not #{path}" end env = env.merge(PATH_INFO => path, SCRIPT_NAME => @script_name, REQUEST_METHOD => GET, "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "", RACK_INPUT => StringIO.new("")) @app.call(env) end end end PK% ]ӎ cTcT!gems/rack-3.0.8/lib/rack/utils.rbnu[# -*- encoding: binary -*- # frozen_string_literal: true require 'uri' require 'fileutils' require 'set' require 'tempfile' require 'time' require_relative 'query_parser' require_relative 'mime' require_relative 'headers' require_relative 'constants' module Rack # Rack::Utils contains a grab-bag of useful methods for writing web # applications adopted from all kinds of Ruby libraries. module Utils ParameterTypeError = QueryParser::ParameterTypeError InvalidParameterError = QueryParser::InvalidParameterError ParamsTooDeepError = QueryParser::ParamsTooDeepError DEFAULT_SEP = QueryParser::DEFAULT_SEP COMMON_SEP = QueryParser::COMMON_SEP KeySpaceConstrainedParams = QueryParser::Params class << self attr_accessor :default_query_parser end # The default amount of nesting to allowed by hash parameters. # This helps prevent a rogue client from triggering a possible stack overflow # when parsing parameters. self.default_query_parser = QueryParser.make_default(32) module_function # URI escapes. (CGI style space to +) def escape(s) URI.encode_www_form_component(s) end # Like URI escaping, but with %20 instead of +. Strictly speaking this is # true URI escaping. def escape_path(s) ::URI::DEFAULT_PARSER.escape s end # Unescapes the **path** component of a URI. See Rack::Utils.unescape for # unescaping query parameters or form components. def unescape_path(s) ::URI::DEFAULT_PARSER.unescape s end # Unescapes a URI escaped string with +encoding+. +encoding+ will be the # target encoding of the string returned, and it defaults to UTF-8 def unescape(s, encoding = Encoding::UTF_8) URI.decode_www_form_component(s, encoding) end class << self attr_accessor :multipart_total_part_limit attr_accessor :multipart_file_limit # multipart_part_limit is the original name of multipart_file_limit, but # the limit only counts parts with filenames. alias multipart_part_limit multipart_file_limit alias multipart_part_limit= multipart_file_limit= end # The maximum number of file parts a request can contain. Accepting too # many parts can lead to the server running out of file handles. # Set to `0` for no limit. self.multipart_file_limit = (ENV['RACK_MULTIPART_PART_LIMIT'] || ENV['RACK_MULTIPART_FILE_LIMIT'] || 128).to_i # The maximum total number of parts a request can contain. Accepting too # many can lead to excessive memory use and parsing time. self.multipart_total_part_limit = (ENV['RACK_MULTIPART_TOTAL_PART_LIMIT'] || 4096).to_i def self.param_depth_limit default_query_parser.param_depth_limit end def self.param_depth_limit=(v) self.default_query_parser = self.default_query_parser.new_depth_limit(v) end def self.key_space_limit warn("`Rack::Utils.key_space_limit` is deprecated as this value no longer has an effect. It will be removed in Rack 3.1", uplevel: 1) 65536 end def self.key_space_limit=(v) warn("`Rack::Utils.key_space_limit=` is deprecated and no longer has an effect. It will be removed in Rack 3.1", uplevel: 1) end if defined?(Process::CLOCK_MONOTONIC) def clock_time Process.clock_gettime(Process::CLOCK_MONOTONIC) end else # :nocov: def clock_time Time.now.to_f end # :nocov: end def parse_query(qs, d = nil, &unescaper) Rack::Utils.default_query_parser.parse_query(qs, d, &unescaper) end def parse_nested_query(qs, d = nil) Rack::Utils.default_query_parser.parse_nested_query(qs, d) end def build_query(params) params.map { |k, v| if v.class == Array build_query(v.map { |x| [k, x] }) else v.nil? ? escape(k) : "#{escape(k)}=#{escape(v)}" end }.join("&") end def build_nested_query(value, prefix = nil) case value when Array value.map { |v| build_nested_query(v, "#{prefix}[]") }.join("&") when Hash value.map { |k, v| build_nested_query(v, prefix ? "#{prefix}[#{k}]" : k) }.delete_if(&:empty?).join('&') when nil escape(prefix) else raise ArgumentError, "value must be a Hash" if prefix.nil? "#{escape(prefix)}=#{escape(value)}" end end def q_values(q_value_header) q_value_header.to_s.split(/\s*,\s*/).map do |part| value, parameters = part.split(/\s*;\s*/, 2) quality = 1.0 if parameters && (md = /\Aq=([\d.]+)/.match(parameters)) quality = md[1].to_f end [value, quality] end end def forwarded_values(forwarded_header) return nil unless forwarded_header forwarded_header = forwarded_header.to_s.gsub("\n", ";") forwarded_header.split(/\s*;\s*/).each_with_object({}) do |field, values| field.split(/\s*,\s*/).each do |pair| return nil unless pair =~ /\A\s*(by|for|host|proto)\s*=\s*"?([^"]+)"?\s*\Z/i (values[$1.downcase.to_sym] ||= []) << $2 end end end module_function :forwarded_values # Return best accept value to use, based on the algorithm # in RFC 2616 Section 14. If there are multiple best # matches (same specificity and quality), the value returned # is arbitrary. def best_q_match(q_value_header, available_mimes) values = q_values(q_value_header) matches = values.map do |req_mime, quality| match = available_mimes.find { |am| Rack::Mime.match?(am, req_mime) } next unless match [match, quality] end.compact.sort_by do |match, quality| (match.split('/', 2).count('*') * -10) + quality end.last matches&.first end ESCAPE_HTML = { "&" => "&", "<" => "<", ">" => ">", "'" => "'", '"' => """, "/" => "/" } ESCAPE_HTML_PATTERN = Regexp.union(*ESCAPE_HTML.keys) # Escape ampersands, brackets and quotes to their HTML/XML entities. def escape_html(string) string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] } end def select_best_encoding(available_encodings, accept_encoding) # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html expanded_accept_encoding = [] accept_encoding.each do |m, q| preference = available_encodings.index(m) || available_encodings.size if m == "*" (available_encodings - accept_encoding.map(&:first)).each do |m2| expanded_accept_encoding << [m2, q, preference] end else expanded_accept_encoding << [m, q, preference] end end encoding_candidates = expanded_accept_encoding .sort_by { |_, q, p| [-q, p] } .map!(&:first) unless encoding_candidates.include?("identity") encoding_candidates.push("identity") end expanded_accept_encoding.each do |m, q| encoding_candidates.delete(m) if q == 0.0 end (encoding_candidates & available_encodings)[0] end # :call-seq: # parse_cookies_header(value) -> hash # # Parse cookies from the provided header +value+ according to RFC6265. The # syntax for cookie headers only supports semicolons. Returns a map of # cookie +key+ to cookie +value+. # # parse_cookies_header('myname=myvalue; max-age=0') # # => {"myname"=>"myvalue", "max-age"=>"0"} # def parse_cookies_header(value) return {} unless value value.split(/; */n).each_with_object({}) do |cookie, cookies| next if cookie.empty? key, value = cookie.split('=', 2) cookies[key] = (unescape(value) rescue value) unless cookies.key?(key) end end def add_cookie_to_header(header, key, value) warn("add_cookie_to_header is deprecated and will be removed in Rack 3.1", uplevel: 1) case header when nil, '' return set_cookie_header(key, value) when String [header, set_cookie_header(key, value)] when Array header + [set_cookie_header(key, value)] else raise ArgumentError, "Unrecognized cookie header value. Expected String, Array, or nil, got #{header.inspect}" end end # :call-seq: # parse_cookies(env) -> hash # # Parse cookies from the provided request environment using # parse_cookies_header. Returns a map of cookie +key+ to cookie +value+. # # parse_cookies({'HTTP_COOKIE' => 'myname=myvalue'}) # # => {'myname' => 'myvalue'} # def parse_cookies(env) parse_cookies_header env[HTTP_COOKIE] end # :call-seq: # set_cookie_header(key, value) -> encoded string # # Generate an encoded string using the provided +key+ and +value+ suitable # for the +set-cookie+ header according to RFC6265. The +value+ may be an # instance of either +String+ or +Hash+. # # If the cookie +value+ is an instance of +Hash+, it considers the following # cookie attribute keys: +domain+, +max_age+, +expires+ (must be instance # of +Time+), +secure+, +http_only+, +same_site+ and +value+. For more # details about the interpretation of these fields, consult # [RFC6265 Section 5.2](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2). # # An extra cookie attribute +escape_key+ can be provided to control whether # or not the cookie key is URL encoded. If explicitly set to +false+, the # cookie key name will not be url encoded (escaped). The default is +true+. # # set_cookie_header("myname", "myvalue") # # => "myname=myvalue" # # set_cookie_header("myname", {value: "myvalue", max_age: 10}) # # => "myname=myvalue; max-age=10" # def set_cookie_header(key, value) case value when Hash key = escape(key) unless value[:escape_key] == false domain = "; domain=#{value[:domain]}" if value[:domain] path = "; path=#{value[:path]}" if value[:path] max_age = "; max-age=#{value[:max_age]}" if value[:max_age] expires = "; expires=#{value[:expires].httpdate}" if value[:expires] secure = "; secure" if value[:secure] httponly = "; httponly" if (value.key?(:httponly) ? value[:httponly] : value[:http_only]) same_site = case value[:same_site] when false, nil nil when :none, 'None', :None '; SameSite=None' when :lax, 'Lax', :Lax '; SameSite=Lax' when true, :strict, 'Strict', :Strict '; SameSite=Strict' else raise ArgumentError, "Invalid SameSite value: #{value[:same_site].inspect}" end value = value[:value] else key = escape(key) end value = [value] unless Array === value return "#{key}=#{value.map { |v| escape v }.join('&')}#{domain}" \ "#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}" end # :call-seq: # set_cookie_header!(headers, key, value) -> header value # # Append a cookie in the specified headers with the given cookie +key+ and # +value+ using set_cookie_header. # # If the headers already contains a +set-cookie+ key, it will be converted # to an +Array+ if not already, and appended to. def set_cookie_header!(headers, key, value) if header = headers[SET_COOKIE] if header.is_a?(Array) header << set_cookie_header(key, value) else headers[SET_COOKIE] = [header, set_cookie_header(key, value)] end else headers[SET_COOKIE] = set_cookie_header(key, value) end end # :call-seq: # delete_set_cookie_header(key, value = {}) -> encoded string # # Generate an encoded string based on the given +key+ and +value+ using # set_cookie_header for the purpose of causing the specified cookie to be # deleted. The +value+ may be an instance of +Hash+ and can include # attributes as outlined by set_cookie_header. The encoded cookie will have # a +max_age+ of 0 seconds, an +expires+ date in the past and an empty # +value+. When used with the +set-cookie+ header, it will cause the client # to *remove* any matching cookie. # # delete_set_cookie_header("myname") # # => "myname=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT" # def delete_set_cookie_header(key, value = {}) set_cookie_header(key, value.merge(max_age: '0', expires: Time.at(0), value: '')) end def make_delete_cookie_header(header, key, value) warn("make_delete_cookie_header is deprecated and will be removed in Rack 3.1, use delete_set_cookie_header! instead", uplevel: 1) delete_set_cookie_header!(header, key, value) end def delete_cookie_header!(headers, key, value = {}) headers[SET_COOKIE] = delete_set_cookie_header!(headers[SET_COOKIE], key, value) return nil end def add_remove_cookie_to_header(header, key, value = {}) warn("add_remove_cookie_to_header is deprecated and will be removed in Rack 3.1, use delete_set_cookie_header! instead", uplevel: 1) delete_set_cookie_header!(header, key, value) end # :call-seq: # delete_set_cookie_header!(header, key, value = {}) -> header value # # Set an expired cookie in the specified headers with the given cookie # +key+ and +value+ using delete_set_cookie_header. This causes # the client to immediately delete the specified cookie. # # delete_set_cookie_header!(nil, "mycookie") # # => "mycookie=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT" # # If the header is non-nil, it will be modified in place. # # header = [] # delete_set_cookie_header!(header, "mycookie") # # => ["mycookie=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT"] # header # # => ["mycookie=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT"] # def delete_set_cookie_header!(header, key, value = {}) if header header = Array(header) header << delete_set_cookie_header(key, value) else header = delete_set_cookie_header(key, value) end return header end def rfc2822(time) time.rfc2822 end # Parses the "Range:" header, if present, into an array of Range objects. # Returns nil if the header is missing or syntactically invalid. # Returns an empty array if none of the ranges are satisfiable. def byte_ranges(env, size) get_byte_ranges env['HTTP_RANGE'], size end def get_byte_ranges(http_range, size) # See return nil unless http_range && http_range =~ /bytes=([^;]+)/ ranges = [] $1.split(/,\s*/).each do |range_spec| return nil unless range_spec.include?('-') range = range_spec.split('-') r0, r1 = range[0], range[1] if r0.nil? || r0.empty? return nil if r1.nil? # suffix-byte-range-spec, represents trailing suffix of file r0 = size - r1.to_i r0 = 0 if r0 < 0 r1 = size - 1 else r0 = r0.to_i if r1.nil? r1 = size - 1 else r1 = r1.to_i return nil if r1 < r0 # backwards range is syntactically invalid r1 = size - 1 if r1 >= size end end ranges << (r0..r1) if r0 <= r1 end ranges end # :nocov: if defined?(OpenSSL.fixed_length_secure_compare) # Constant time string comparison. # # NOTE: the values compared should be of fixed length, such as strings # that have already been processed by HMAC. This should not be used # on variable length plaintext strings because it could leak length info # via timing attacks. def secure_compare(a, b) return false unless a.bytesize == b.bytesize OpenSSL.fixed_length_secure_compare(a, b) end # :nocov: else def secure_compare(a, b) return false unless a.bytesize == b.bytesize l = a.unpack("C*") r, i = 0, -1 b.each_byte { |v| r |= v ^ l[i += 1] } r == 0 end end # Context allows the use of a compatible middleware at different points # in a request handling stack. A compatible middleware must define # #context which should take the arguments env and app. The first of which # would be the request environment. The second of which would be the rack # application that the request would be forwarded to. class Context attr_reader :for, :app def initialize(app_f, app_r) raise 'running context does not respond to #context' unless app_f.respond_to? :context @for, @app = app_f, app_r end def call(env) @for.context(env, @app) end def recontext(app) self.class.new(@for, app) end def context(env, app = @app) recontext(app).call(env) end end # A wrapper around Headers # header when set. # # @api private class HeaderHash < Hash # :nodoc: def self.[](headers) warn "Rack::Utils::HeaderHash is deprecated and will be removed in Rack 3.1, switch to Rack::Headers", uplevel: 1 if headers.is_a?(Headers) && !headers.frozen? return headers end new_headers = Headers.new headers.each{|k,v| new_headers[k] = v} new_headers end def self.new(hash = {}) warn "Rack::Utils::HeaderHash is deprecated and will be removed in Rack 3.1, switch to Rack::Headers", uplevel: 1 headers = Headers.new hash.each{|k,v| headers[k] = v} headers end def self.allocate raise TypeError, "cannot allocate HeaderHash" end end # Every standard HTTP code mapped to the appropriate message. # Generated with: # curl -s https://www.iana.org/assignments/http-status-codes/http-status-codes-1.csv | \ # ruby -ne 'm = /^(\d{3}),(?!Unassigned|\(Unused\))([^,]+)/.match($_) and \ # puts "#{m[1]} => \x27#{m[2].strip}\x27,"' HTTP_STATUS_CODES = { 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 103 => 'Early Hints', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', 208 => 'Already Reported', 226 => 'IM Used', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => '(Unused)', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Payload Too Large', 414 => 'URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Range Not Satisfiable', 417 => 'Expectation Failed', 421 => 'Misdirected Request', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Too Early', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable for Legal Reasons', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 509 => 'Bandwidth Limit Exceeded', 510 => 'Not Extended', 511 => 'Network Authentication Required' } # Responses with HTTP status codes that should not have an entity body STATUS_WITH_NO_ENTITY_BODY = Hash[((100..199).to_a << 204 << 304).product([true])] SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map { |code, message| [message.downcase.gsub(/\s|-|'/, '_').to_sym, code] }.flatten] def status_code(status) if status.is_a?(Symbol) SYMBOL_TO_STATUS_CODE.fetch(status) { raise ArgumentError, "Unrecognized status code #{status.inspect}" } else status.to_i end end PATH_SEPS = Regexp.union(*[::File::SEPARATOR, ::File::ALT_SEPARATOR].compact) def clean_path_info(path_info) parts = path_info.split PATH_SEPS clean = [] parts.each do |part| next if part.empty? || part == '.' part == '..' ? clean.pop : clean << part end clean_path = clean.join(::File::SEPARATOR) clean_path.prepend("/") if parts.empty? || parts.first.empty? clean_path end NULL_BYTE = "\0" def valid_path?(path) path.valid_encoding? && !path.include?(NULL_BYTE) end end end PK% ]&44,gems/rack-3.0.8/lib/rack/multipart/parser.rbnu[# frozen_string_literal: true require 'strscan' require_relative '../utils' module Rack module Multipart class MultipartPartLimitError < Errno::EMFILE; end class MultipartTotalPartLimitError < StandardError; end # Use specific error class when parsing multipart request # that ends early. class EmptyContentError < ::EOFError; end # Base class for multipart exceptions that do not subclass from # other exception classes for backwards compatibility. class Error < StandardError; end EOL = "\r\n" MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/ CONDISP = /Content-Disposition:\s*#{TOKEN}\s*/i VALUE = /"(?:\\"|[^"])*"|#{TOKEN}/ BROKEN = /^#{CONDISP}.*;\s*filename=(#{VALUE})/i MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{EOL}/ni MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:[^:]*;\s*name=(#{VALUE})/ni MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni # Updated definitions from RFC 2231 ATTRIBUTE_CHAR = %r{[^ \x00-\x1f\x7f)(><@,;:\\"/\[\]?='*%]} ATTRIBUTE = /#{ATTRIBUTE_CHAR}+/ SECTION = /\*[0-9]+/ REGULAR_PARAMETER_NAME = /#{ATTRIBUTE}#{SECTION}?/ REGULAR_PARAMETER = /(#{REGULAR_PARAMETER_NAME})=(#{VALUE})/ EXTENDED_OTHER_NAME = /#{ATTRIBUTE}\*[1-9][0-9]*\*/ EXTENDED_OTHER_VALUE = /%[0-9a-fA-F]{2}|#{ATTRIBUTE_CHAR}/ EXTENDED_OTHER_PARAMETER = /(#{EXTENDED_OTHER_NAME})=(#{EXTENDED_OTHER_VALUE}*)/ EXTENDED_INITIAL_NAME = /#{ATTRIBUTE}(?:\*0)?\*/ EXTENDED_INITIAL_VALUE = /[a-zA-Z0-9\-]*'[a-zA-Z0-9\-]*'#{EXTENDED_OTHER_VALUE}*/ EXTENDED_INITIAL_PARAMETER = /(#{EXTENDED_INITIAL_NAME})=(#{EXTENDED_INITIAL_VALUE})/ EXTENDED_PARAMETER = /#{EXTENDED_INITIAL_PARAMETER}|#{EXTENDED_OTHER_PARAMETER}/ DISPPARM = /;\s*(?:#{REGULAR_PARAMETER}|#{EXTENDED_PARAMETER})\s*/ RFC2183 = /^#{CONDISP}(#{DISPPARM})+$/i class Parser BUFSIZE = 1_048_576 TEXT_PLAIN = "text/plain" TEMPFILE_FACTORY = lambda { |filename, content_type| Tempfile.new(["RackMultipart", ::File.extname(filename.gsub("\0", '%00'))]) } class BoundedIO # :nodoc: def initialize(io, content_length) @io = io @content_length = content_length @cursor = 0 end def read(size, outbuf = nil) return if @cursor >= @content_length left = @content_length - @cursor str = if left < size @io.read left, outbuf else @io.read size, outbuf end if str @cursor += str.bytesize else # Raise an error for mismatching content-length and actual contents raise EOFError, "bad content body" end str end end MultipartInfo = Struct.new :params, :tmp_files EMPTY = MultipartInfo.new(nil, []) def self.parse_boundary(content_type) return unless content_type data = content_type.match(MULTIPART) return unless data data[1] end def self.parse(io, content_length, content_type, tmpfile, bufsize, qp) return EMPTY if 0 == content_length boundary = parse_boundary content_type return EMPTY unless boundary if boundary.length > 70 # RFC 1521 Section 7.2.1 imposes a 70 character maximum for the boundary. # Most clients use no more than 55 characters. raise Error, "multipart boundary size too large (#{boundary.length} characters)" end io = BoundedIO.new(io, content_length) if content_length parser = new(boundary, tmpfile, bufsize, qp) parser.parse(io) parser.result end class Collector class MimePart < Struct.new(:body, :head, :filename, :content_type, :name) def get_data data = body if filename == "" # filename is blank which means no file has been selected return elsif filename body.rewind if body.respond_to?(:rewind) # Take the basename of the upload's original filename. # This handles the full Windows paths given by Internet Explorer # (and perhaps other broken user agents) without affecting # those which give the lone filename. fn = filename.split(/[\/\\]/).last data = { filename: fn, type: content_type, name: name, tempfile: body, head: head } end yield data end end class BufferPart < MimePart def file?; false; end def close; end end class TempfilePart < MimePart def file?; true; end def close; body.close; end end include Enumerable def initialize(tempfile) @tempfile = tempfile @mime_parts = [] @open_files = 0 end def each @mime_parts.each { |part| yield part } end def on_mime_head(mime_index, head, filename, content_type, name) if filename body = @tempfile.call(filename, content_type) body.binmode if body.respond_to?(:binmode) klass = TempfilePart @open_files += 1 else body = String.new klass = BufferPart end @mime_parts[mime_index] = klass.new(body, head, filename, content_type, name) check_part_limits end def on_mime_body(mime_index, content) @mime_parts[mime_index].body << content end def on_mime_finish(mime_index) end private def check_part_limits file_limit = Utils.multipart_file_limit part_limit = Utils.multipart_total_part_limit if file_limit && file_limit > 0 if @open_files >= file_limit @mime_parts.each(&:close) raise MultipartPartLimitError, 'Maximum file multiparts in content reached' end end if part_limit && part_limit > 0 if @mime_parts.size >= part_limit @mime_parts.each(&:close) raise MultipartTotalPartLimitError, 'Maximum total multiparts in content reached' end end end end attr_reader :state def initialize(boundary, tempfile, bufsize, query_parser) @query_parser = query_parser @params = query_parser.make_params @bufsize = bufsize @state = :FAST_FORWARD @mime_index = 0 @collector = Collector.new tempfile @sbuf = StringScanner.new("".dup) @body_regex = /(?:#{EOL}|\A)--#{Regexp.quote(boundary)}(?:#{EOL}|--)/m @rx_max_size = boundary.bytesize + 6 # (\r\n-- at start, either \r\n or -- at finish) @head_regex = /(.*?#{EOL})#{EOL}/m end def parse(io) outbuf = String.new read_data(io, outbuf) loop do status = case @state when :FAST_FORWARD handle_fast_forward when :CONSUME_TOKEN handle_consume_token when :MIME_HEAD handle_mime_head when :MIME_BODY handle_mime_body else # when :DONE return end read_data(io, outbuf) if status == :want_read end end def result @collector.each do |part| part.get_data do |data| tag_multipart_encoding(part.filename, part.content_type, part.name, data) @query_parser.normalize_params(@params, part.name, data) end end MultipartInfo.new @params.to_params_hash, @collector.find_all(&:file?).map(&:body) end private def dequote(str) # From WEBrick::HTTPUtils ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup ret.gsub!(/\\(.)/, "\\1") ret end def read_data(io, outbuf) content = io.read(@bufsize, outbuf) handle_empty_content!(content) @sbuf.concat(content) end # This handles the initial parser state. We read until we find the starting # boundary, then we can transition to the next state. If we find the ending # boundary, this is an invalid multipart upload, but keep scanning for opening # boundary in that case. If no boundary found, we need to keep reading data # and retry. It's highly unlikely the initial read will not consume the # boundary. The client would have to deliberately craft a response # with the opening boundary beyond the buffer size for that to happen. def handle_fast_forward while true case consume_boundary when :BOUNDARY # found opening boundary, transition to next state @state = :MIME_HEAD return when :END_BOUNDARY # invalid multipart upload, but retry for opening boundary else # no boundary found, keep reading data return :want_read end end end def handle_consume_token tok = consume_boundary # break if we're at the end of a buffer, but not if it is the end of a field @state = if tok == :END_BOUNDARY || (@sbuf.eos? && tok != :BOUNDARY) :DONE else :MIME_HEAD end end def handle_mime_head if @sbuf.scan_until(@head_regex) head = @sbuf[1] content_type = head[MULTIPART_CONTENT_TYPE, 1] if name = head[MULTIPART_CONTENT_DISPOSITION, 1] name = dequote(name) else name = head[MULTIPART_CONTENT_ID, 1] end filename = get_filename(head) if name.nil? || name.empty? name = filename || "#{content_type || TEXT_PLAIN}[]".dup end @collector.on_mime_head @mime_index, head, filename, content_type, name @state = :MIME_BODY else :want_read end end def handle_mime_body if (body_with_boundary = @sbuf.check_until(@body_regex)) # check but do not advance the pointer yet body = body_with_boundary.sub(/#{@body_regex}\z/m, '') # remove the boundary from the string @collector.on_mime_body @mime_index, body @sbuf.pos += body.length + 2 # skip \r\n after the content @state = :CONSUME_TOKEN @mime_index += 1 else # Save what we have so far if @rx_max_size < @sbuf.rest_size delta = @sbuf.rest_size - @rx_max_size @collector.on_mime_body @mime_index, @sbuf.peek(delta) @sbuf.pos += delta @sbuf.string = @sbuf.rest end :want_read end end # Scan until the we find the start or end of the boundary. # If we find it, return the appropriate symbol for the start or # end of the boundary. If we don't find the start or end of the # boundary, clear the buffer and return nil. def consume_boundary if read_buffer = @sbuf.scan_until(@body_regex) read_buffer.end_with?(EOL) ? :BOUNDARY : :END_BOUNDARY else @sbuf.terminate nil end end def get_filename(head) filename = nil case head when RFC2183 params = Hash[*head.scan(DISPPARM).flat_map(&:compact)] if filename = params['filename*'] encoding, _, filename = filename.split("'", 3) elsif filename = params['filename'] filename = $1 if filename =~ /^"(.*)"$/ end when BROKEN filename = $1 filename = $1 if filename =~ /^"(.*)"$/ end return unless filename if filename.scan(/%.?.?/).all? { |s| /%[0-9a-fA-F]{2}/.match?(s) } filename = Utils.unescape_path(filename) end filename.scrub! if filename !~ /\\[^\\"]/ filename = filename.gsub(/\\(.)/, '\1') end if encoding filename.force_encoding ::Encoding.find(encoding) end filename end CHARSET = "charset" deprecate_constant :CHARSET def tag_multipart_encoding(filename, content_type, name, body) name = name.to_s encoding = Encoding::UTF_8 name.force_encoding(encoding) return if filename if content_type list = content_type.split(';') type_subtype = list.first type_subtype.strip! if TEXT_PLAIN == type_subtype rest = list.drop 1 rest.each do |param| k, v = param.split('=', 2) k.strip! v.strip! v = v[1..-2] if v.start_with?('"') && v.end_with?('"') if k == "charset" encoding = begin Encoding.find v rescue ArgumentError Encoding::BINARY end end end end end name.force_encoding(encoding) body.force_encoding(encoding) end def handle_empty_content!(content) if content.nil? || content.empty? raise EmptyContentError end end end end end PK% ]l /gems/rack-3.0.8/lib/rack/multipart/generator.rbnu[# frozen_string_literal: true require_relative 'uploaded_file' module Rack module Multipart class Generator def initialize(params, first = true) @params, @first = params, first if @first && !@params.is_a?(Hash) raise ArgumentError, "value must be a Hash" end end def dump return nil if @first && !multipart? return flattened_params unless @first flattened_params.map do |name, file| if file.respond_to?(:original_filename) if file.path ::File.open(file.path, 'rb') do |f| f.set_encoding(Encoding::BINARY) content_for_tempfile(f, file, name) end else content_for_tempfile(file, file, name) end else content_for_other(file, name) end end.join << "--#{MULTIPART_BOUNDARY}--\r" end private def multipart? query = lambda { |value| case value when Array value.any?(&query) when Hash value.values.any?(&query) when Rack::Multipart::UploadedFile true end } @params.values.any?(&query) end def flattened_params @flattened_params ||= begin h = Hash.new @params.each do |key, value| k = @first ? key.to_s : "[#{key}]" case value when Array value.map { |v| Multipart.build_multipart(v, false).each { |subkey, subvalue| h["#{k}[]#{subkey}"] = subvalue } } when Hash Multipart.build_multipart(value, false).each { |subkey, subvalue| h[k + subkey] = subvalue } else h[k] = value end end h end end def content_for_tempfile(io, file, name) length = ::File.stat(file.path).size if file.path filename = "; filename=\"#{Utils.escape_path(file.original_filename)}\"" <<-EOF --#{MULTIPART_BOUNDARY}\r content-disposition: form-data; name="#{name}"#{filename}\r content-type: #{file.content_type}\r #{"content-length: #{length}\r\n" if length}\r #{io.read}\r EOF end def content_for_other(file, name) <<-EOF --#{MULTIPART_BOUNDARY}\r content-disposition: form-data; name="#{name}"\r \r #{file}\r EOF end end end end PK% ]N$$3gems/rack-3.0.8/lib/rack/multipart/uploaded_file.rbnu[# frozen_string_literal: true require 'tempfile' require 'fileutils' module Rack module Multipart class UploadedFile # The filename, *not* including the path, of the "uploaded" file attr_reader :original_filename # The content type of the "uploaded" file attr_accessor :content_type def initialize(filepath = nil, ct = "text/plain", bin = false, path: filepath, content_type: ct, binary: bin, filename: nil, io: nil) if io @tempfile = io @original_filename = filename else raise "#{path} file does not exist" unless ::File.exist?(path) @original_filename = filename || ::File.basename(path) @tempfile = Tempfile.new([@original_filename, ::File.extname(path)], encoding: Encoding::BINARY) @tempfile.binmode if binary FileUtils.copy_file(path, @tempfile.path) end @content_type = content_type end def path @tempfile.path if @tempfile.respond_to?(:path) end alias_method :local_path, :path def respond_to?(*args) super or @tempfile.respond_to?(*args) end def method_missing(method_name, *args, &block) #:nodoc: @tempfile.__send__(method_name, *args, &block) end end end end PK% ] Cx x )gems/rack-3.0.8/lib/rack/common_logger.rbnu[# frozen_string_literal: true require_relative 'constants' require_relative 'utils' require_relative 'body_proxy' require_relative 'request' module Rack # Rack::CommonLogger forwards every request to the given +app+, and # logs a line in the # {Apache common log format}[http://httpd.apache.org/docs/1.3/logs.html#common] # to the configured logger. class CommonLogger # Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common # # lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 - # # %{%s - %s [%s] "%s %s%s %s" %d %s\n} % # # The actual format is slightly different than the above due to the # separation of SCRIPT_NAME and PATH_INFO, and because the elapsed # time in seconds is included at the end. FORMAT = %{%s - %s [%s] "%s %s%s%s %s" %d %s %0.4f\n} # +logger+ can be any object that supports the +write+ or +<<+ methods, # which includes the standard library Logger. These methods are called # with a single string argument, the log message. # If +logger+ is nil, CommonLogger will fall back env['rack.errors']. def initialize(app, logger = nil) @app = app @logger = logger end # Log all requests in common_log format after a response has been # returned. Note that if the app raises an exception, the request # will not be logged, so if exception handling middleware are used, # they should be loaded after this middleware. Additionally, because # the logging happens after the request body has been fully sent, any # exceptions raised during the sending of the response body will # cause the request not to be logged. def call(env) began_at = Utils.clock_time status, headers, body = response = @app.call(env) response[2] = BodyProxy.new(body) { log(env, status, headers, began_at) } response end private # Log the request to the configured logger. def log(env, status, response_headers, began_at) request = Rack::Request.new(env) length = extract_content_length(response_headers) msg = sprintf(FORMAT, request.ip || "-", request.get_header("REMOTE_USER") || "-", Time.now.strftime("%d/%b/%Y:%H:%M:%S %z"), request.request_method, request.script_name, request.path_info, request.query_string.empty? ? "" : "?#{request.query_string}", request.get_header(SERVER_PROTOCOL), status.to_s[0..3], length, Utils.clock_time - began_at) msg.gsub!(/[^[:print:]\n]/) { |c| sprintf("\\x%x", c.ord) } logger = @logger || request.get_header(RACK_ERRORS) # Standard library logger doesn't support write but it supports << which actually # calls to write on the log device without formatting if logger.respond_to?(:write) logger.write(msg) else logger << msg end end # Attempt to determine the content length for the response to # include it in the logged data. def extract_content_length(headers) value = headers[CONTENT_LENGTH] !value || value.to_s == '0' ? '-' : value end end end PK% ]YYd  +gems/rack-3.0.8/lib/rack/tempfile_reaper.rbnu[# frozen_string_literal: true require_relative 'constants' require_relative 'body_proxy' module Rack # Middleware tracks and cleans Tempfiles created throughout a request (i.e. Rack::Multipart) # Ideas/strategy based on posts by Eric Wong and Charles Oliver Nutter # https://groups.google.com/forum/#!searchin/rack-devel/temp/rack-devel/brK8eh-MByw/sw61oJJCGRMJ class TempfileReaper def initialize(app) @app = app end def call(env) env[RACK_TEMPFILES] ||= [] begin _, _, body = response = @app.call(env) rescue Exception env[RACK_TEMPFILES]&.each(&:close!) raise end response[2] = BodyProxy.new(body) do env[RACK_TEMPFILES]&.each(&:close!) end response end end end PK% ]Kbx  $gems/rack-3.0.8/lib/rack/reloader.rbnu[# frozen_string_literal: true # Copyright (C) 2009-2018 Michael Fellinger # Rack::Reloader is subject to the terms of an MIT-style license. # See MIT-LICENSE or https://opensource.org/licenses/MIT. require 'pathname' module Rack # High performant source reloader # # This class acts as Rack middleware. # # What makes it especially suited for use in a production environment is that # any file will only be checked once and there will only be made one system # call stat(2). # # Please note that this will not reload files in the background, it does so # only when actively called. # # It is performing a check/reload cycle at the start of every request, but # also respects a cool down time, during which nothing will be done. class Reloader def initialize(app, cooldown = 10, backend = Stat) @app = app @cooldown = cooldown @last = (Time.now - cooldown) @cache = {} @mtimes = {} @reload_mutex = Mutex.new extend backend end def call(env) if @cooldown and Time.now > @last + @cooldown if Thread.list.size > 1 @reload_mutex.synchronize{ reload! } else reload! end @last = Time.now end @app.call(env) end def reload!(stderr = $stderr) rotation do |file, mtime| previous_mtime = @mtimes[file] ||= mtime safe_load(file, mtime, stderr) if mtime > previous_mtime end end # A safe Kernel::load, issuing the hooks depending on the results def safe_load(file, mtime, stderr = $stderr) load(file) stderr.puts "#{self.class}: reloaded `#{file}'" file rescue LoadError, SyntaxError => ex stderr.puts ex ensure @mtimes[file] = mtime end module Stat def rotation files = [$0, *$LOADED_FEATURES].uniq paths = ['./', *$LOAD_PATH].uniq files.map{|file| next if /\.(so|bundle)$/.match?(file) # cannot reload compiled files found, stat = figure_path(file, paths) next unless found && stat && mtime = stat.mtime @cache[file] = found yield(found, mtime) }.compact end # Takes a relative or absolute +file+ name, a couple possible +paths+ that # the +file+ might reside in. Returns the full path and File::Stat for the # path. def figure_path(file, paths) found = @cache[file] found = file if !found and Pathname.new(file).absolute? found, stat = safe_stat(found) return found, stat if found paths.find do |possible_path| path = ::File.join(possible_path, file) found, stat = safe_stat(path) return ::File.expand_path(found), stat if found end return false, false end def safe_stat(file) return unless file stat = ::File.stat(file) return file, stat if stat.file? rescue Errno::ENOENT, Errno::ENOTDIR, Errno::ESRCH @cache.delete(file) and false end end end end PK% ]&{!{!(gems/rack-3.0.8/lib/rack/query_parser.rbnu[# frozen_string_literal: true require 'uri' module Rack class QueryParser DEFAULT_SEP = /[&] */n COMMON_SEP = { ";" => /[;] */n, ";," => /[;,] */n, "&" => /[&] */n } # ParameterTypeError is the error that is raised when incoming structural # parameters (parsed by parse_nested_query) contain conflicting types. class ParameterTypeError < TypeError; end # InvalidParameterError is the error that is raised when incoming structural # parameters (parsed by parse_nested_query) contain invalid format or byte # sequence. class InvalidParameterError < ArgumentError; end # ParamsTooDeepError is the error that is raised when params are recursively # nested over the specified limit. class ParamsTooDeepError < RangeError; end def self.make_default(_key_space_limit=(not_deprecated = true; nil), param_depth_limit) unless not_deprecated warn("`first argument `key_space limit` is deprecated and no longer has an effect. Please call with only one argument, which will be required in a future version of Rack", uplevel: 1) end new Params, param_depth_limit end attr_reader :param_depth_limit def initialize(params_class, _key_space_limit=(not_deprecated = true; nil), param_depth_limit) unless not_deprecated warn("`second argument `key_space limit` is deprecated and no longer has an effect. Please call with only two arguments, which will be required in a future version of Rack", uplevel: 1) end @params_class = params_class @param_depth_limit = param_depth_limit end # Stolen from Mongrel, with some small modifications: # Parses a query string by breaking it up at the '&'. You can also use this # to parse cookies by changing the characters used in the second parameter # (which defaults to '&'). def parse_query(qs, separator = nil, &unescaper) unescaper ||= method(:unescape) params = make_params (qs || '').split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p| next if p.empty? k, v = p.split('=', 2).map!(&unescaper) if cur = params[k] if cur.class == Array params[k] << v else params[k] = [cur, v] end else params[k] = v end end return params.to_h end # parse_nested_query expands a query string into structural types. Supported # types are Arrays, Hashes and basic value types. It is possible to supply # query strings with parameters of conflicting types, in this case a # ParameterTypeError is raised. Users are encouraged to return a 400 in this # case. def parse_nested_query(qs, separator = nil) params = make_params unless qs.nil? || qs.empty? (qs || '').split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |p| k, v = p.split('=', 2).map! { |s| unescape(s) } _normalize_params(params, k, v, 0) end end return params.to_h rescue ArgumentError => e raise InvalidParameterError, e.message, e.backtrace end # normalize_params recursively expands parameters into structural types. If # the structural types represented by two different parameter names are in # conflict, a ParameterTypeError is raised. The depth argument is deprecated # and should no longer be used, it is kept for backwards compatibility with # earlier versions of rack. def normalize_params(params, name, v, _depth=nil) _normalize_params(params, name, v, 0) end private def _normalize_params(params, name, v, depth) raise ParamsTooDeepError if depth >= param_depth_limit if !name # nil name, treat same as empty string (required by tests) k = after = '' elsif depth == 0 # Start of parsing, don't treat [] or [ at start of string specially if start = name.index('[', 1) # Start of parameter nesting, use part before brackets as key k = name[0, start] after = name[start, name.length] else # Plain parameter with no nesting k = name after = '' end elsif name.start_with?('[]') # Array nesting k = '[]' after = name[2, name.length] elsif name.start_with?('[') && (start = name.index(']', 1)) # Hash nesting, use the part inside brackets as the key k = name[1, start-1] after = name[start+1, name.length] else # Probably malformed input, nested but not starting with [ # treat full name as key for backwards compatibility. k = name after = '' end return if k.empty? if after == '' if k == '[]' && depth != 0 return [v] else params[k] = v end elsif after == "[" params[name] = v elsif after == "[]" params[k] ||= [] raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) params[k] << v elsif after.start_with?('[]') # Recognize x[][y] (hash inside array) parameters unless after[2] == '[' && after.end_with?(']') && (child_key = after[3, after.length-4]) && !child_key.empty? && !child_key.index('[') && !child_key.index(']') # Handle other nested array parameters child_key = after[2, after.length] end params[k] ||= [] raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) if params_hash_type?(params[k].last) && !params_hash_has_key?(params[k].last, child_key) _normalize_params(params[k].last, child_key, v, depth + 1) else params[k] << _normalize_params(make_params, child_key, v, depth + 1) end else params[k] ||= make_params raise ParameterTypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params_hash_type?(params[k]) params[k] = _normalize_params(params[k], after, v, depth + 1) end params end def make_params @params_class.new end def new_depth_limit(param_depth_limit) self.class.new @params_class, param_depth_limit end private def params_hash_type?(obj) obj.kind_of?(@params_class) end def params_hash_has_key?(hash, key) return false if /\[\]/.match?(key) key.split(/[\[\]]+/).inject(hash) do |h, part| next h if part == '' return false unless params_hash_type?(h) && h.key?(part) h[part] end true end def unescape(string, encoding = Encoding::UTF_8) URI.decode_www_form_component(string, encoding) end class Params def initialize @size = 0 @params = {} end def [](key) @params[key] end def []=(key, value) @params[key] = value end def key?(key) @params.key?(key) end # Recursively unwraps nested `Params` objects and constructs an object # of the same shape, but using the objects' internal representations # (Ruby hashes) in place of the objects. The result is a hash consisting # purely of Ruby primitives. # # Mutation warning! # # 1. This method mutates the internal representation of the `Params` # objects in order to save object allocations. # # 2. The value you get back is a reference to the internal hash # representation, not a copy. # # 3. Because the `Params` object's internal representation is mutable # through the `#[]=` method, it is not thread safe. The result of # getting the hash representation while another thread is adding a # key to it is non-deterministic. # def to_h @params.each do |key, value| case value when self # Handle circular references gracefully. @params[key] = @params when Params @params[key] = value.to_h when Array value.map! { |v| v.kind_of?(Params) ? v.to_h : v } else # Ignore anything that is not a `Params` object or # a collection that can contain one. end end @params end alias_method :to_params_hash, :to_h end end end PK% ]U``"%gems/rack-3.0.8/lib/rack/multipart.rbnu[# frozen_string_literal: true require_relative 'constants' require_relative 'utils' require_relative 'multipart/parser' require_relative 'multipart/generator' module Rack # A multipart form data parser, adapted from IOWA. # # Usually, Rack::Request#POST takes care of calling this. module Multipart MULTIPART_BOUNDARY = "AaB03x" class << self def parse_multipart(env, params = Rack::Utils.default_query_parser) io = env[RACK_INPUT] if content_length = env['CONTENT_LENGTH'] content_length = content_length.to_i end content_type = env['CONTENT_TYPE'] tempfile = env[RACK_MULTIPART_TEMPFILE_FACTORY] || Parser::TEMPFILE_FACTORY bufsize = env[RACK_MULTIPART_BUFFER_SIZE] || Parser::BUFSIZE info = Parser.parse(io, content_length, content_type, tempfile, bufsize, params) env[RACK_TEMPFILES] = info.tmp_files return info.params end def extract_multipart(request, params = Rack::Utils.default_query_parser) parse_multipart(request.env) end def build_multipart(params, first = true) Generator.new(params, first).dump end end end end PK% ]|Х!gems/rack-3.0.8/lib/rack/files.rbnu[# frozen_string_literal: true require 'time' require_relative 'constants' require_relative 'head' require_relative 'utils' require_relative 'request' require_relative 'mime' module Rack # Rack::Files serves files below the +root+ directory given, according to the # path info of the Rack request. # e.g. when Rack::Files.new("/etc") is used, you can access 'passwd' file # as http://localhost:9292/passwd # # Handlers can detect if bodies are a Rack::Files, and use mechanisms # like sendfile on the +path+. class Files ALLOWED_VERBS = %w[GET HEAD OPTIONS] ALLOW_HEADER = ALLOWED_VERBS.join(', ') MULTIPART_BOUNDARY = 'AaB03x' attr_reader :root def initialize(root, headers = {}, default_mime = 'text/plain') @root = (::File.expand_path(root) if root) @headers = headers @default_mime = default_mime @head = Rack::Head.new(lambda { |env| get env }) end def call(env) # HEAD requests drop the response body, including 4xx error messages. @head.call env end def get(env) request = Rack::Request.new env unless ALLOWED_VERBS.include? request.request_method return fail(405, "Method Not Allowed", { 'allow' => ALLOW_HEADER }) end path_info = Utils.unescape_path request.path_info return fail(400, "Bad Request") unless Utils.valid_path?(path_info) clean_path_info = Utils.clean_path_info(path_info) path = ::File.join(@root, clean_path_info) available = begin ::File.file?(path) && ::File.readable?(path) rescue SystemCallError # Not sure in what conditions this exception can occur, but this # is a safe way to handle such an error. # :nocov: false # :nocov: end if available serving(request, path) else fail(404, "File not found: #{path_info}") end end def serving(request, path) if request.options? return [200, { 'allow' => ALLOW_HEADER, CONTENT_LENGTH => '0' }, []] end last_modified = ::File.mtime(path).httpdate return [304, {}, []] if request.get_header('HTTP_IF_MODIFIED_SINCE') == last_modified headers = { "last-modified" => last_modified } mime_type = mime_type path, @default_mime headers[CONTENT_TYPE] = mime_type if mime_type # Set custom headers headers.merge!(@headers) if @headers status = 200 size = filesize path ranges = Rack::Utils.get_byte_ranges(request.get_header('HTTP_RANGE'), size) if ranges.nil? # No ranges: ranges = [0..size - 1] elsif ranges.empty? # Unsatisfiable. Return error, and file size: response = fail(416, "Byte range unsatisfiable") response[1]["content-range"] = "bytes */#{size}" return response else # Partial content partial_content = true if ranges.size == 1 range = ranges[0] headers["content-range"] = "bytes #{range.begin}-#{range.end}/#{size}" else headers[CONTENT_TYPE] = "multipart/byteranges; boundary=#{MULTIPART_BOUNDARY}" end status = 206 body = BaseIterator.new(path, ranges, mime_type: mime_type, size: size) size = body.bytesize end headers[CONTENT_LENGTH] = size.to_s if request.head? body = [] elsif !partial_content body = Iterator.new(path, ranges, mime_type: mime_type, size: size) end [status, headers, body] end class BaseIterator attr_reader :path, :ranges, :options def initialize(path, ranges, options) @path = path @ranges = ranges @options = options end def each ::File.open(path, "rb") do |file| ranges.each do |range| yield multipart_heading(range) if multipart? each_range_part(file, range) do |part| yield part end end yield "\r\n--#{MULTIPART_BOUNDARY}--\r\n" if multipart? end end def bytesize size = ranges.inject(0) do |sum, range| sum += multipart_heading(range).bytesize if multipart? sum += range.size end size += "\r\n--#{MULTIPART_BOUNDARY}--\r\n".bytesize if multipart? size end def close; end private def multipart? ranges.size > 1 end def multipart_heading(range) <<-EOF \r --#{MULTIPART_BOUNDARY}\r content-type: #{options[:mime_type]}\r content-range: bytes #{range.begin}-#{range.end}/#{options[:size]}\r \r EOF end def each_range_part(file, range) file.seek(range.begin) remaining_len = range.end - range.begin + 1 while remaining_len > 0 part = file.read([8192, remaining_len].min) break unless part remaining_len -= part.length yield part end end end class Iterator < BaseIterator alias :to_path :path end private def fail(status, body, headers = {}) body += "\n" [ status, { CONTENT_TYPE => "text/plain", CONTENT_LENGTH => body.size.to_s, "x-cascade" => "pass" }.merge!(headers), [body] ] end # The MIME type for the contents of the file located at @path def mime_type(path, default_mime) Mime.mime_type(::File.extname(path), default_mime) end def filesize(path) # We check via File::size? whether this file provides size info # via stat (e.g. /proc files often don't), otherwise we have to # figure it out by reading the whole file into memory. ::File.size?(path) || ::File.read(path).bytesize end end end PK% ]44"gems/rack-3.0.8/lib/rack/events.rbnu[# frozen_string_literal: true require_relative 'body_proxy' require_relative 'request' require_relative 'response' module Rack ### This middleware provides hooks to certain places in the request / # response lifecycle. This is so that middleware that don't need to filter # the response data can safely leave it alone and not have to send messages # down the traditional "rack stack". # # The events are: # # * on_start(request, response) # # This event is sent at the start of the request, before the next # middleware in the chain is called. This method is called with a request # object, and a response object. Right now, the response object is always # nil, but in the future it may actually be a real response object. # # * on_commit(request, response) # # The response has been committed. The application has returned, but the # response has not been sent to the webserver yet. This method is always # called with a request object and the response object. The response # object is constructed from the rack triple that the application returned. # Changes may still be made to the response object at this point. # # * on_send(request, response) # # The webserver has started iterating over the response body and presumably # has started sending data over the wire. This method is always called with # a request object and the response object. The response object is # constructed from the rack triple that the application returned. Changes # SHOULD NOT be made to the response object as the webserver has already # started sending data. Any mutations will likely result in an exception. # # * on_finish(request, response) # # The webserver has closed the response, and all data has been written to # the response socket. The request and response object should both be # read-only at this point. The body MAY NOT be available on the response # object as it may have been flushed to the socket. # # * on_error(request, response, error) # # An exception has occurred in the application or an `on_commit` event. # This method will get the request, the response (if available) and the # exception that was raised. # # ## Order # # `on_start` is called on the handlers in the order that they were passed to # the constructor. `on_commit`, on_send`, `on_finish`, and `on_error` are # called in the reverse order. `on_finish` handlers are called inside an # `ensure` block, so they are guaranteed to be called even if something # raises an exception. If something raises an exception in a `on_finish` # method, then nothing is guaranteed. class Events module Abstract def on_start(req, res) end def on_commit(req, res) end def on_send(req, res) end def on_finish(req, res) end def on_error(req, res, e) end end class EventedBodyProxy < Rack::BodyProxy # :nodoc: attr_reader :request, :response def initialize(body, request, response, handlers, &block) super(body, &block) @request = request @response = response @handlers = handlers end def each @handlers.reverse_each { |handler| handler.on_send request, response } super end end class BufferedResponse < Rack::Response::Raw # :nodoc: attr_reader :body def initialize(status, headers, body) super(status, headers) @body = body end def to_a; [status, headers, body]; end end def initialize(app, handlers) @app = app @handlers = handlers end def call(env) request = make_request env on_start request, nil begin status, headers, body = @app.call request.env response = make_response status, headers, body on_commit request, response rescue StandardError => e on_error request, response, e on_finish request, response raise end body = EventedBodyProxy.new(body, request, response, @handlers) do on_finish request, response end [response.status, response.headers, body] end private def on_error(request, response, e) @handlers.reverse_each { |handler| handler.on_error request, response, e } end def on_commit(request, response) @handlers.reverse_each { |handler| handler.on_commit request, response } end def on_start(request, response) @handlers.each { |handler| handler.on_start request, nil } end def on_finish(request, response) @handlers.reverse_each { |handler| handler.on_finish request, response } end def make_request(env) Rack::Request.new env end def make_response(status, headers, body) BufferedResponse.new status, headers, body end end end PK% ]A%gems/rack-3.0.8/lib/rack/directory.rbnu[# frozen_string_literal: true require 'time' require_relative 'constants' require_relative 'utils' require_relative 'head' require_relative 'mime' require_relative 'files' module Rack # Rack::Directory serves entries below the +root+ given, according to the # path info of the Rack request. If a directory is found, the file's contents # will be presented in an html based index. If a file is found, the env will # be passed to the specified +app+. # # If +app+ is not specified, a Rack::Files of the same +root+ will be used. class Directory DIR_FILE = "%s%s%s%s\n" DIR_PAGE_HEADER = <<-PAGE %s

%s


PAGE DIR_PAGE_FOOTER = <<-PAGE
Name Size Type Last Modified

PAGE # Body class for directory entries, showing an index page with links # to each file. class DirectoryBody < Struct.new(:root, :path, :files) # Yield strings for each part of the directory entry def each show_path = Utils.escape_html(path.sub(/^#{root}/, '')) yield(DIR_PAGE_HEADER % [ show_path, show_path ]) unless path.chomp('/') == root yield(DIR_FILE % DIR_FILE_escape(files.call('..'))) end Dir.foreach(path) do |basename| next if basename.start_with?('.') next unless f = files.call(basename) yield(DIR_FILE % DIR_FILE_escape(f)) end yield(DIR_PAGE_FOOTER) end private # Escape each element in the array of html strings. def DIR_FILE_escape(htmls) htmls.map { |e| Utils.escape_html(e) } end end # The root of the directory hierarchy. Only requests for files and # directories inside of the root directory are supported. attr_reader :root # Set the root directory and application for serving files. def initialize(root, app = nil) @root = ::File.expand_path(root) @app = app || Files.new(@root) @head = Head.new(method(:get)) end def call(env) # strip body if this is a HEAD call @head.call env end # Internals of request handling. Similar to call but does # not remove body for HEAD requests. def get(env) script_name = env[SCRIPT_NAME] path_info = Utils.unescape_path(env[PATH_INFO]) if client_error_response = check_bad_request(path_info) || check_forbidden(path_info) client_error_response else path = ::File.join(@root, path_info) list_path(env, path, path_info, script_name) end end # Rack response to use for requests with invalid paths, or nil if path is valid. def check_bad_request(path_info) return if Utils.valid_path?(path_info) body = "Bad Request\n" [400, { CONTENT_TYPE => "text/plain", CONTENT_LENGTH => body.bytesize.to_s, "x-cascade" => "pass" }, [body]] end # Rack response to use for requests with paths outside the root, or nil if path is inside the root. def check_forbidden(path_info) return unless path_info.include? ".." return if ::File.expand_path(::File.join(@root, path_info)).start_with?(@root) body = "Forbidden\n" [403, { CONTENT_TYPE => "text/plain", CONTENT_LENGTH => body.bytesize.to_s, "x-cascade" => "pass" }, [body]] end # Rack response to use for directories under the root. def list_directory(path_info, path, script_name) url_head = (script_name.split('/') + path_info.split('/')).map do |part| Utils.escape_path part end # Globbing not safe as path could contain glob metacharacters body = DirectoryBody.new(@root, path, ->(basename) do stat = stat(::File.join(path, basename)) next unless stat url = ::File.join(*url_head + [Utils.escape_path(basename)]) mtime = stat.mtime.httpdate if stat.directory? type = 'directory' size = '-' url << '/' if basename == '..' basename = 'Parent Directory' else basename << '/' end else type = Mime.mime_type(::File.extname(basename)) size = filesize_format(stat.size) end [ url, basename, size, type, mtime ] end) [ 200, { CONTENT_TYPE => 'text/html; charset=utf-8' }, body ] end # File::Stat for the given path, but return nil for missing/bad entries. def stat(path) ::File.stat(path) rescue Errno::ENOENT, Errno::ELOOP return nil end # Rack response to use for files and directories under the root. # Unreadable and non-file, non-directory entries will get a 404 response. def list_path(env, path, path_info, script_name) if (stat = stat(path)) && stat.readable? return @app.call(env) if stat.file? return list_directory(path_info, path, script_name) if stat.directory? end entity_not_found(path_info) end # Rack response to use for unreadable and non-file, non-directory entries. def entity_not_found(path_info) body = "Entity not found: #{path_info}\n" [404, { CONTENT_TYPE => "text/plain", CONTENT_LENGTH => body.bytesize.to_s, "x-cascade" => "pass" }, [body]] end # Stolen from Ramaze FILESIZE_FORMAT = [ ['%.1fT', 1 << 40], ['%.1fG', 1 << 30], ['%.1fM', 1 << 20], ['%.1fK', 1 << 10], ] # Provide human readable file sizes def filesize_format(int) FILESIZE_FORMAT.each do |format, size| return format % (int.to_f / size) if int >= size end "#{int}B" end end end PK% ]iZ&&*gems/rack-3.0.8/lib/rack/content_length.rbnu[# frozen_string_literal: true require_relative 'constants' require_relative 'utils' module Rack # Sets the content-length header on responses that do not specify # a content-length or transfer-encoding header. Note that this # does not fix responses that have an invalid content-length # header specified. class ContentLength include Rack::Utils def initialize(app) @app = app end def call(env) status, headers, body = response = @app.call(env) if !STATUS_WITH_NO_ENTITY_BODY.key?(status.to_i) && !headers[CONTENT_LENGTH] && !headers[TRANSFER_ENCODING] && body.respond_to?(:to_ary) response[2] = body = body.to_ary headers[CONTENT_LENGTH] = body.sum(&:bytesize).to_s end response end end end PK% ]ɸHO#gems/rack-3.0.8/lib/rack/version.rbnu[# frozen_string_literal: true # Copyright (C) 2007-2019 Leah Neukirchen # # Rack is freely distributable under the terms of an MIT-style license. # See MIT-LICENSE or https://opensource.org/licenses/MIT. # The Rack main module, serving as a namespace for all core Rack # modules and classes. # # All modules meant for use in your application are autoloaded here, # so it should be enough just to require 'rack' in your code. module Rack # The Rack protocol version number implemented. VERSION = [1, 3].freeze deprecate_constant :VERSION VERSION_STRING = "1.3".freeze deprecate_constant :VERSION_STRING # The Rack protocol version number implemented. def self.version warn "Rack.version is deprecated and will be removed in Rack 3.1!", uplevel: 1 VERSION end RELEASE = "3.0.8" # Return the Rack release as a dotted string. def self.release RELEASE end end PK% ]R  )gems/rack-3.0.8/lib/rack/mock_response.rbnu[# frozen_string_literal: true require 'cgi/cookie' require 'time' require_relative 'response' module Rack # Rack::MockResponse provides useful helpers for testing your apps. # Usually, you don't create the MockResponse on your own, but use # MockRequest. class MockResponse < Rack::Response class << self alias [] new end # Headers attr_reader :original_headers, :cookies # Errors attr_accessor :errors def initialize(status, headers, body, errors = nil) @original_headers = headers if errors @errors = errors.string if errors.respond_to?(:string) else @errors = "" end super(body, status, headers) @cookies = parse_cookies_from_header buffered_body! end def =~(other) body =~ other end def match(other) body.match other end def body return @buffered_body if defined?(@buffered_body) # FIXME: apparently users of MockResponse expect the return value of # MockResponse#body to be a string. However, the real response object # returns the body as a list. # # See spec_showstatus.rb: # # should "not replace existing messages" do # ... # res.body.should == "foo!" # end buffer = @buffered_body = String.new @body.each do |chunk| buffer << chunk end return buffer end def empty? [201, 204, 304].include? status end def cookie(name) cookies.fetch(name, nil) end private def parse_cookies_from_header cookies = Hash.new if headers.has_key? 'set-cookie' set_cookie_header = headers.fetch('set-cookie') Array(set_cookie_header).each do |header_value| header_value.split("\n").each do |cookie| cookie_name, cookie_filling = cookie.split('=', 2) cookie_attributes = identify_cookie_attributes cookie_filling parsed_cookie = CGI::Cookie.new( 'name' => cookie_name.strip, 'value' => cookie_attributes.fetch('value'), 'path' => cookie_attributes.fetch('path', nil), 'domain' => cookie_attributes.fetch('domain', nil), 'expires' => cookie_attributes.fetch('expires', nil), 'secure' => cookie_attributes.fetch('secure', false) ) cookies.store(cookie_name, parsed_cookie) end end end cookies end def identify_cookie_attributes(cookie_filling) cookie_bits = cookie_filling.split(';') cookie_attributes = Hash.new cookie_attributes.store('value', cookie_bits[0].strip) cookie_bits.drop(1).each do |bit| if bit.include? '=' cookie_attribute, attribute_value = bit.split('=', 2) cookie_attributes.store(cookie_attribute.strip.downcase, attribute_value.strip) end if bit.include? 'secure' cookie_attributes.store('secure', true) end end if cookie_attributes.key? 'max-age' cookie_attributes.store('expires', Time.now + cookie_attributes['max-age'].to_i) elsif cookie_attributes.key? 'expires' cookie_attributes.store('expires', Time.httpdate(cookie_attributes['expires'])) end cookie_attributes end end end PK% ]Y488$gems/rack-3.0.8/lib/rack/sendfile.rbnu[# frozen_string_literal: true require_relative 'constants' require_relative 'utils' require_relative 'body_proxy' module Rack # = Sendfile # # The Sendfile middleware intercepts responses whose body is being # served from a file and replaces it with a server specific x-sendfile # header. The web server is then responsible for writing the file contents # to the client. This can dramatically reduce the amount of work required # by the Ruby backend and takes advantage of the web server's optimized file # delivery code. # # In order to take advantage of this middleware, the response body must # respond to +to_path+ and the request must include an x-sendfile-type # header. Rack::Files and other components implement +to_path+ so there's # rarely anything you need to do in your application. The x-sendfile-type # header is typically set in your web servers configuration. The following # sections attempt to document # # === Nginx # # Nginx supports the x-accel-redirect header. This is similar to x-sendfile # but requires parts of the filesystem to be mapped into a private URL # hierarchy. # # The following example shows the Nginx configuration required to create # a private "/files/" area, enable x-accel-redirect, and pass the special # x-sendfile-type and x-accel-mapping headers to the backend: # # location ~ /files/(.*) { # internal; # alias /var/www/$1; # } # # location / { # proxy_redirect off; # # proxy_set_header Host $host; # proxy_set_header X-Real-IP $remote_addr; # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # # proxy_set_header x-sendfile-type x-accel-redirect; # proxy_set_header x-accel-mapping /var/www/=/files/; # # proxy_pass http://127.0.0.1:8080/; # } # # Note that the x-sendfile-type header must be set exactly as shown above. # The x-accel-mapping header should specify the location on the file system, # followed by an equals sign (=), followed name of the private URL pattern # that it maps to. The middleware performs a simple substitution on the # resulting path. # # See Also: https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile # # === lighttpd # # Lighttpd has supported some variation of the x-sendfile header for some # time, although only recent version support x-sendfile in a reverse proxy # configuration. # # $HTTP["host"] == "example.com" { # proxy-core.protocol = "http" # proxy-core.balancer = "round-robin" # proxy-core.backends = ( # "127.0.0.1:8000", # "127.0.0.1:8001", # ... # ) # # proxy-core.allow-x-sendfile = "enable" # proxy-core.rewrite-request = ( # "x-sendfile-type" => (".*" => "x-sendfile") # ) # } # # See Also: http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModProxyCore # # === Apache # # x-sendfile is supported under Apache 2.x using a separate module: # # https://tn123.org/mod_xsendfile/ # # Once the module is compiled and installed, you can enable it using # XSendFile config directive: # # RequestHeader Set x-sendfile-type x-sendfile # ProxyPassReverse / http://localhost:8001/ # XSendFile on # # === Mapping parameter # # The third parameter allows for an overriding extension of the # x-accel-mapping header. Mappings should be provided in tuples of internal to # external. The internal values may contain regular expression syntax, they # will be matched with case indifference. class Sendfile def initialize(app, variation = nil, mappings = []) @app = app @variation = variation @mappings = mappings.map do |internal, external| [/^#{internal}/i, external] end end def call(env) _, headers, body = response = @app.call(env) if body.respond_to?(:to_path) case type = variation(env) when /x-accel-redirect/i path = ::File.expand_path(body.to_path) if url = map_accel_path(env, path) headers[CONTENT_LENGTH] = '0' # '?' must be percent-encoded because it is not query string but a part of path headers[type.downcase] = ::Rack::Utils.escape_path(url).gsub('?', '%3F') obody = body response[2] = Rack::BodyProxy.new([]) do obody.close if obody.respond_to?(:close) end else env[RACK_ERRORS].puts "x-accel-mapping header missing" end when /x-sendfile|x-lighttpd-send-file/i path = ::File.expand_path(body.to_path) headers[CONTENT_LENGTH] = '0' headers[type.downcase] = path obody = body response[2] = Rack::BodyProxy.new([]) do obody.close if obody.respond_to?(:close) end when '', nil else env[RACK_ERRORS].puts "Unknown x-sendfile variation: '#{type}'.\n" end end response end private def variation(env) @variation || env['sendfile.type'] || env['HTTP_X_SENDFILE_TYPE'] end def map_accel_path(env, path) if mapping = @mappings.find { |internal, _| internal =~ path } path.sub(*mapping) elsif mapping = env['HTTP_X_ACCEL_MAPPING'] mapping.split(',').map(&:strip).each do |m| internal, external = m.split('=', 2).map(&:strip) new_path = path.sub(/^#{internal}/i, external) return new_path unless path == new_path end path end end end end PK% ]dP"gems/rack-3.0.8/lib/rack/logger.rbnu[# frozen_string_literal: true require 'logger' require_relative 'constants' module Rack # Sets up rack.logger to write to rack.errors stream class Logger def initialize(app, level = ::Logger::INFO) @app, @level = app, level end def call(env) logger = ::Logger.new(env[RACK_ERRORS]) logger.level = @level env[RACK_LOGGER] = logger @app.call(env) end end end PK% ]M}Y?? gems/rack-3.0.8/lib/rack/mock.rbnu[# frozen_string_literal: true require_relative 'mock_request' PK% ]K?33&gems/rack-3.0.8/lib/rack/body_proxy.rbnu[# frozen_string_literal: true module Rack # Proxy for response bodies allowing calling a block when # the response body is closed (after the response has been fully # sent to the client). class BodyProxy # Set the response body to wrap, and the block to call when the # response has been fully sent. def initialize(body, &block) @body = body @block = block @closed = false end # Return whether the wrapped body responds to the method. def respond_to_missing?(method_name, include_all = false) super or @body.respond_to?(method_name, include_all) end # If not already closed, close the wrapped body and # then call the block the proxy was initialized with. def close return if @closed @closed = true begin @body.close if @body.respond_to?(:close) ensure @block.call end end # Whether the proxy is closed. The proxy starts as not closed, # and becomes closed on the first call to close. def closed? @closed end # Delegate missing methods to the wrapped body. def method_missing(method_name, *args, &block) @body.__send__(method_name, *args, &block) end # :nocov: ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true) # :nocov: end end PK% ]ю "gems/rack-3.0.8/lib/rack/static.rbnu[# frozen_string_literal: true require_relative 'constants' require_relative 'files' require_relative 'mime' module Rack # The Rack::Static middleware intercepts requests for static files # (javascript files, images, stylesheets, etc) based on the url prefixes or # route mappings passed in the options, and serves them using a Rack::Files # object. This allows a Rack stack to serve both static and dynamic content. # # Examples: # # Serve all requests beginning with /media from the "media" folder located # in the current directory (ie media/*): # # use Rack::Static, :urls => ["/media"] # # Same as previous, but instead of returning 404 for missing files under # /media, call the next middleware: # # use Rack::Static, :urls => ["/media"], :cascade => true # # Serve all requests beginning with /css or /images from the folder "public" # in the current directory (ie public/css/* and public/images/*): # # use Rack::Static, :urls => ["/css", "/images"], :root => "public" # # Serve all requests to / with "index.html" from the folder "public" in the # current directory (ie public/index.html): # # use Rack::Static, :urls => {"/" => 'index.html'}, :root => 'public' # # Serve all requests normally from the folder "public" in the current # directory but uses index.html as default route for "/" # # use Rack::Static, :urls => [""], :root => 'public', :index => # 'index.html' # # Set custom HTTP Headers for based on rules: # # use Rack::Static, :root => 'public', # :header_rules => [ # [rule, {header_field => content, header_field => content}], # [rule, {header_field => content}] # ] # # Rules for selecting files: # # 1) All files # Provide the :all symbol # :all => Matches every file # # 2) Folders # Provide the folder path as a string # '/folder' or '/folder/subfolder' => Matches files in a certain folder # # 3) File Extensions # Provide the file extensions as an array # ['css', 'js'] or %w(css js) => Matches files ending in .css or .js # # 4) Regular Expressions / Regexp # Provide a regular expression # %r{\.(?:css|js)\z} => Matches files ending in .css or .js # /\.(?:eot|ttf|otf|woff2|woff|svg)\z/ => Matches files ending in # the most common web font formats (.eot, .ttf, .otf, .woff2, .woff, .svg) # Note: This Regexp is available as a shortcut, using the :fonts rule # # 5) Font Shortcut # Provide the :fonts symbol # :fonts => Uses the Regexp rule stated right above to match all common web font endings # # Rule Ordering: # Rules are applied in the order that they are provided. # List rather general rules above special ones. # # Complete example use case including HTTP header rules: # # use Rack::Static, :root => 'public', # :header_rules => [ # # Cache all static files in public caches (e.g. Rack::Cache) # # as well as in the browser # [:all, {'cache-control' => 'public, max-age=31536000'}], # # # Provide web fonts with cross-origin access-control-headers # # Firefox requires this when serving assets using a Content Delivery Network # [:fonts, {'access-control-allow-origin' => '*'}] # ] # class Static def initialize(app, options = {}) @app = app @urls = options[:urls] || ["/favicon.ico"] @index = options[:index] @gzip = options[:gzip] @cascade = options[:cascade] root = options[:root] || Dir.pwd # HTTP Headers @header_rules = options[:header_rules] || [] # Allow for legacy :cache_control option while prioritizing global header_rules setting @header_rules.unshift([:all, { CACHE_CONTROL => options[:cache_control] }]) if options[:cache_control] @file_server = Rack::Files.new(root) end def add_index_root?(path) @index && route_file(path) && path.end_with?('/') end def overwrite_file_path(path) @urls.kind_of?(Hash) && @urls.key?(path) || add_index_root?(path) end def route_file(path) @urls.kind_of?(Array) && @urls.any? { |url| path.index(url) == 0 } end def can_serve(path) route_file(path) || overwrite_file_path(path) end def call(env) path = env[PATH_INFO] if can_serve(path) if overwrite_file_path(path) env[PATH_INFO] = (add_index_root?(path) ? path + @index : @urls[path]) elsif @gzip && env['HTTP_ACCEPT_ENCODING'] && /\bgzip\b/.match?(env['HTTP_ACCEPT_ENCODING']) path = env[PATH_INFO] env[PATH_INFO] += '.gz' response = @file_server.call(env) env[PATH_INFO] = path if response[0] == 404 response = nil elsif response[0] == 304 # Do nothing, leave headers as is else response[1][CONTENT_TYPE] = Mime.mime_type(::File.extname(path), 'text/plain') response[1]['content-encoding'] = 'gzip' end end path = env[PATH_INFO] response ||= @file_server.call(env) if @cascade && response[0] == 404 return @app.call(env) end headers = response[1] applicable_rules(path).each do |rule, new_headers| new_headers.each { |field, content| headers[field] = content } end response else @app.call(env) end end # Convert HTTP header rules to HTTP headers def applicable_rules(path) @header_rules.find_all do |rule, new_headers| case rule when :all true when :fonts /\.(?:ttf|otf|eot|woff2|woff|svg)\z/.match?(path) when String path = ::Rack::Utils.unescape(path) path.start_with?(rule) || path.start_with?('/' + rule) when Array /\.(#{rule.join('|')})\z/.match?(path) when Regexp rule.match?(path) else false end end end end end PK% ]VMVww gems/rack-3.0.8/lib/rack/etag.rbnu[# frozen_string_literal: true require 'digest/sha2' require_relative 'constants' require_relative 'utils' module Rack # Automatically sets the etag header on all String bodies. # # The etag header is skipped if etag or last-modified headers are sent or if # a sendfile body (body.responds_to :to_path) is given (since such cases # should be handled by apache/nginx). # # On initialization, you can pass two parameters: a cache-control directive # used when etag is absent and a directive when it is present. The first # defaults to nil, while the second defaults to "max-age=0, private, must-revalidate" class ETag ETAG_STRING = Rack::ETAG DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate" def initialize(app, no_cache_control = nil, cache_control = DEFAULT_CACHE_CONTROL) @app = app @cache_control = cache_control @no_cache_control = no_cache_control end def call(env) status, headers, body = response = @app.call(env) if etag_status?(status) && body.respond_to?(:to_ary) && !skip_caching?(headers) body = body.to_ary digest = digest_body(body) headers[ETAG_STRING] = %(W/"#{digest}") if digest end unless headers[CACHE_CONTROL] if digest headers[CACHE_CONTROL] = @cache_control if @cache_control else headers[CACHE_CONTROL] = @no_cache_control if @no_cache_control end end response end private def etag_status?(status) status == 200 || status == 201 end def skip_caching?(headers) headers.key?(ETAG_STRING) || headers.key?('last-modified') end def digest_body(body) digest = nil body.each do |part| (digest ||= Digest::SHA256.new) << part unless part.empty? end digest && digest.hexdigest.byteslice(0,32) end end end PK% ];~ ~ ,gems/rack-3.0.8/lib/rack/rewindable_input.rbnu[# -*- encoding: binary -*- # frozen_string_literal: true require 'tempfile' require_relative 'constants' module Rack # Class which can make any IO object rewindable, including non-rewindable ones. It does # this by buffering the data into a tempfile, which is rewindable. # # Don't forget to call #close when you're done. This frees up temporary resources that # RewindableInput uses, though it does *not* close the original IO object. class RewindableInput # Makes rack.input rewindable, for compatibility with applications and middleware # designed for earlier versions of Rack (where rack.input was required to be # rewindable). class Middleware def initialize(app) @app = app end def call(env) env[RACK_INPUT] = RewindableInput.new(env[RACK_INPUT]) @app.call(env) end end def initialize(io) @io = io @rewindable_io = nil @unlinked = false end def gets make_rewindable unless @rewindable_io @rewindable_io.gets end def read(*args) make_rewindable unless @rewindable_io @rewindable_io.read(*args) end def each(&block) make_rewindable unless @rewindable_io @rewindable_io.each(&block) end def rewind make_rewindable unless @rewindable_io @rewindable_io.rewind end def size make_rewindable unless @rewindable_io @rewindable_io.size end # Closes this RewindableInput object without closing the originally # wrapped IO object. Cleans up any temporary resources that this RewindableInput # has created. # # This method may be called multiple times. It does nothing on subsequent calls. def close if @rewindable_io if @unlinked @rewindable_io.close else @rewindable_io.close! end @rewindable_io = nil end end private def make_rewindable # Buffer all data into a tempfile. Since this tempfile is private to this # RewindableInput object, we chmod it so that nobody else can read or write # it. On POSIX filesystems we also unlink the file so that it doesn't # even have a file entry on the filesystem anymore, though we can still # access it because we have the file handle open. @rewindable_io = Tempfile.new('RackRewindableInput') @rewindable_io.chmod(0000) @rewindable_io.set_encoding(Encoding::BINARY) @rewindable_io.binmode # :nocov: if filesystem_has_posix_semantics? raise 'Unlink failed. IO closed.' if @rewindable_io.closed? @unlinked = true end # :nocov: buffer = "".dup while @io.read(1024 * 4, buffer) entire_buffer_written_out = false while !entire_buffer_written_out written = @rewindable_io.write(buffer) entire_buffer_written_out = written == buffer.bytesize if !entire_buffer_written_out buffer.slice!(0 .. written - 1) end end end @rewindable_io.rewind end def filesystem_has_posix_semantics? RUBY_PLATFORM !~ /(mswin|mingw|cygwin|java)/ end end end PK% ]$**$gems/rack-3.0.8/lib/rack/response.rbnu[# frozen_string_literal: true require 'time' require_relative 'constants' require_relative 'utils' require_relative 'media_type' require_relative 'headers' module Rack # Rack::Response provides a convenient interface to create a Rack # response. # # It allows setting of headers and cookies, and provides useful # defaults (an OK response with empty headers and body). # # You can use Response#write to iteratively generate your response, # but note that this is buffered by Rack::Response until you call # +finish+. +finish+ however can take a block inside which calls to # +write+ are synchronous with the Rack response. # # Your application's +call+ should end returning Response#finish. class Response def self.[](status, headers, body) self.new(body, status, headers) end CHUNKED = 'chunked' STATUS_WITH_NO_ENTITY_BODY = Utils::STATUS_WITH_NO_ENTITY_BODY attr_accessor :length, :status, :body attr_reader :headers # Deprecated, use headers instead. def header warn 'Rack::Response#header is deprecated and will be removed in Rack 3.1', uplevel: 1 headers end # Initialize the response object with the specified +body+, +status+ # and +headers+. # # If the +body+ is +nil+, construct an empty response object with internal # buffering. # # If the +body+ responds to +to_str+, assume it's a string-like object and # construct a buffered response object containing using that string as the # initial contents of the buffer. # # Otherwise it is expected +body+ conforms to the normal requirements of a # Rack response body, typically implementing one of +each+ (enumerable # body) or +call+ (streaming body). # # The +status+ defaults to +200+ which is the "OK" HTTP status code. You # can provide any other valid status code. # # The +headers+ must be a +Hash+ of key-value header pairs which conform to # the Rack specification for response headers. The key must be a +String+ # instance and the value can be either a +String+ or +Array+ instance. def initialize(body = nil, status = 200, headers = {}) @status = status.to_i unless headers.is_a?(Hash) warn "Providing non-hash headers to Rack::Response is deprecated and will be removed in Rack 3.1", uplevel: 1 end @headers = Headers.new # Convert headers input to a plain hash with lowercase keys. headers.each do |k, v| @headers[k] = v end @writer = self.method(:append) @block = nil # Keep track of whether we have expanded the user supplied body. if body.nil? @body = [] @buffered = true @length = 0 elsif body.respond_to?(:to_str) @body = [body] @buffered = true @length = body.to_str.bytesize else @body = body @buffered = nil # undetermined as of yet. @length = 0 end yield self if block_given? end def redirect(target, status = 302) self.status = status self.location = target end def chunked? CHUNKED == get_header(TRANSFER_ENCODING) end def no_entity_body? # The response body is an enumerable body and it is not allowed to have an entity body. @body.respond_to?(:each) && STATUS_WITH_NO_ENTITY_BODY[@status] end # Generate a response array consistent with the requirements of the SPEC. # @return [Array] a 3-tuple suitable of `[status, headers, body]` # which is suitable to be returned from the middleware `#call(env)` method. def finish(&block) if no_entity_body? delete_header CONTENT_TYPE delete_header CONTENT_LENGTH close return [@status, @headers, []] else if block_given? @block = block return [@status, @headers, self] else return [@status, @headers, @body] end end end alias to_a finish # For *response def each(&callback) @body.each(&callback) @buffered = true if @block @writer = callback @block.call(self) end end # Append to body and update content-length. # # NOTE: Do not mix #write and direct #body access! # def write(chunk) buffered_body! @writer.call(chunk.to_s) end def close @body.close if @body.respond_to?(:close) end def empty? @block == nil && @body.empty? end def has_header?(key) raise ArgumentError unless key.is_a?(String) @headers.key?(key) end def get_header(key) raise ArgumentError unless key.is_a?(String) @headers[key] end def set_header(key, value) raise ArgumentError unless key.is_a?(String) @headers[key] = value end def delete_header(key) raise ArgumentError unless key.is_a?(String) @headers.delete key end alias :[] :get_header alias :[]= :set_header module Helpers def invalid?; status < 100 || status >= 600; end def informational?; status >= 100 && status < 200; end def successful?; status >= 200 && status < 300; end def redirection?; status >= 300 && status < 400; end def client_error?; status >= 400 && status < 500; end def server_error?; status >= 500 && status < 600; end def ok?; status == 200; end def created?; status == 201; end def accepted?; status == 202; end def no_content?; status == 204; end def moved_permanently?; status == 301; end def bad_request?; status == 400; end def unauthorized?; status == 401; end def forbidden?; status == 403; end def not_found?; status == 404; end def method_not_allowed?; status == 405; end def not_acceptable?; status == 406; end def request_timeout?; status == 408; end def precondition_failed?; status == 412; end def unprocessable?; status == 422; end def redirect?; [301, 302, 303, 307, 308].include? status; end def include?(header) has_header?(header) end # Add a header that may have multiple values. # # Example: # response.add_header 'vary', 'accept-encoding' # response.add_header 'vary', 'cookie' # # assert_equal 'accept-encoding,cookie', response.get_header('vary') # # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 def add_header(key, value) raise ArgumentError unless key.is_a?(String) if value.nil? return get_header(key) end value = value.to_s if header = get_header(key) if header.is_a?(Array) header << value else set_header(key, [header, value]) end else set_header(key, value) end end # Get the content type of the response. def content_type get_header CONTENT_TYPE end # Set the content type of the response. def content_type=(content_type) set_header CONTENT_TYPE, content_type end def media_type MediaType.type(content_type) end def media_type_params MediaType.params(content_type) end def content_length cl = get_header CONTENT_LENGTH cl ? cl.to_i : cl end def location get_header "location" end def location=(location) set_header "location", location end def set_cookie(key, value) add_header SET_COOKIE, Utils.set_cookie_header(key, value) end def delete_cookie(key, value = {}) set_header(SET_COOKIE, Utils.delete_set_cookie_header!( get_header(SET_COOKIE), key, value ) ) end def set_cookie_header get_header SET_COOKIE end def set_cookie_header=(value) set_header SET_COOKIE, value end def cache_control get_header CACHE_CONTROL end def cache_control=(value) set_header CACHE_CONTROL, value end # Specifies that the content shouldn't be cached. Overrides `cache!` if already called. def do_not_cache! set_header CACHE_CONTROL, "no-cache, must-revalidate" set_header EXPIRES, Time.now.httpdate end # Specify that the content should be cached. # @param duration [Integer] The number of seconds until the cache expires. # @option directive [String] The cache control directive, one of "public", "private", "no-cache" or "no-store". def cache!(duration = 3600, directive: "public") unless headers[CACHE_CONTROL] =~ /no-cache/ set_header CACHE_CONTROL, "#{directive}, max-age=#{duration}" set_header EXPIRES, (Time.now + duration).httpdate end end def etag get_header ETAG end def etag=(value) set_header ETAG, value end protected def buffered_body! if @buffered.nil? if @body.is_a?(Array) # The user supplied body was an array: @body = @body.compact @body.each do |part| @length += part.to_s.bytesize end elsif @body.respond_to?(:each) # Turn the user supplied body into a buffered array: body = @body @body = Array.new body.each do |part| @writer.call(part.to_s) end body.close if body.respond_to?(:close) @buffered = true else @buffered = false end end return @buffered end def append(chunk) @body << chunk unless chunked? @length += chunk.bytesize set_header(CONTENT_LENGTH, @length.to_s) end return chunk end end include Helpers class Raw include Helpers attr_reader :headers attr_accessor :status def initialize(status, headers) @status = status @headers = headers end def has_header?(key) headers.key?(key) end def get_header(key) headers[key] end def set_header(key, value) headers[key] = value end def delete_header(key) headers.delete(key) end end end end PK% ]3+gems/rack-3.0.8/lib/rack/method_override.rbnu[# frozen_string_literal: true require_relative 'constants' require_relative 'request' require_relative 'utils' module Rack class MethodOverride HTTP_METHODS = %w[GET HEAD PUT POST DELETE OPTIONS PATCH LINK UNLINK] METHOD_OVERRIDE_PARAM_KEY = "_method" HTTP_METHOD_OVERRIDE_HEADER = "HTTP_X_HTTP_METHOD_OVERRIDE" ALLOWED_METHODS = %w[POST] def initialize(app) @app = app end def call(env) if allowed_methods.include?(env[REQUEST_METHOD]) method = method_override(env) if HTTP_METHODS.include?(method) env[RACK_METHODOVERRIDE_ORIGINAL_METHOD] = env[REQUEST_METHOD] env[REQUEST_METHOD] = method end end @app.call(env) end def method_override(env) req = Request.new(env) method = method_override_param(req) || env[HTTP_METHOD_OVERRIDE_HEADER] begin method.to_s.upcase rescue ArgumentError env[RACK_ERRORS].puts "Invalid string for method" end end private def allowed_methods ALLOWED_METHODS end def method_override_param(req) req.POST[METHOD_OVERRIDE_PARAM_KEY] if req.form_data? || req.parseable_data? rescue Utils::InvalidParameterError, Utils::ParameterTypeError, QueryParser::ParamsTooDeepError req.get_header(RACK_ERRORS).puts "Invalid or incomplete POST params" rescue EOFError req.get_header(RACK_ERRORS).puts "Bad request content body" end end end PK% ]@j %gems/rack-3.0.8/lib/rack/constants.rbnu[# frozen_string_literal: true module Rack # Request env keys HTTP_HOST = 'HTTP_HOST' HTTP_PORT = 'HTTP_PORT' HTTPS = 'HTTPS' PATH_INFO = 'PATH_INFO' REQUEST_METHOD = 'REQUEST_METHOD' REQUEST_PATH = 'REQUEST_PATH' SCRIPT_NAME = 'SCRIPT_NAME' QUERY_STRING = 'QUERY_STRING' SERVER_PROTOCOL = 'SERVER_PROTOCOL' SERVER_NAME = 'SERVER_NAME' SERVER_PORT = 'SERVER_PORT' HTTP_COOKIE = 'HTTP_COOKIE' # Response Header Keys CACHE_CONTROL = 'cache-control' CONTENT_LENGTH = 'content-length' CONTENT_TYPE = 'content-type' ETAG = 'etag' EXPIRES = 'expires' SET_COOKIE = 'set-cookie' TRANSFER_ENCODING = 'transfer-encoding' # HTTP method verbs GET = 'GET' POST = 'POST' PUT = 'PUT' PATCH = 'PATCH' DELETE = 'DELETE' HEAD = 'HEAD' OPTIONS = 'OPTIONS' LINK = 'LINK' UNLINK = 'UNLINK' TRACE = 'TRACE' # Rack environment variables RACK_VERSION = 'rack.version' RACK_TEMPFILES = 'rack.tempfiles' RACK_ERRORS = 'rack.errors' RACK_LOGGER = 'rack.logger' RACK_INPUT = 'rack.input' RACK_SESSION = 'rack.session' RACK_SESSION_OPTIONS = 'rack.session.options' RACK_SHOWSTATUS_DETAIL = 'rack.showstatus.detail' RACK_URL_SCHEME = 'rack.url_scheme' RACK_HIJACK = 'rack.hijack' RACK_IS_HIJACK = 'rack.hijack?' RACK_RECURSIVE_INCLUDE = 'rack.recursive.include' RACK_MULTIPART_BUFFER_SIZE = 'rack.multipart.buffer_size' RACK_MULTIPART_TEMPFILE_FACTORY = 'rack.multipart.tempfile_factory' RACK_RESPONSE_FINISHED = 'rack.response_finished' RACK_REQUEST_FORM_INPUT = 'rack.request.form_input' RACK_REQUEST_FORM_HASH = 'rack.request.form_hash' RACK_REQUEST_FORM_VARS = 'rack.request.form_vars' RACK_REQUEST_FORM_ERROR = 'rack.request.form_error' RACK_REQUEST_COOKIE_HASH = 'rack.request.cookie_hash' RACK_REQUEST_COOKIE_STRING = 'rack.request.cookie_string' RACK_REQUEST_QUERY_HASH = 'rack.request.query_hash' RACK_REQUEST_QUERY_STRING = 'rack.request.query_string' RACK_METHODOVERRIDE_ORIGINAL_METHOD = 'rack.methodoverride.original_method' end PK% ]Oi #gems/rack-3.0.8/lib/rack/headers.rbnu[module Rack # Rack::Headers is a Hash subclass that downcases all keys. It's designed # to be used by rack applications that don't implement the Rack 3 SPEC # (by using non-lowercase response header keys), automatically handling # the downcasing of keys. class Headers < Hash def self.[](*items) if items.length % 2 != 0 if items.length == 1 && items.first.is_a?(Hash) new.merge!(items.first) else raise ArgumentError, "odd number of arguments for Rack::Headers" end else hash = new loop do break if items.length == 0 key = items.shift value = items.shift hash[key] = value end hash end end def [](key) super(downcase_key(key)) end def []=(key, value) super(key.downcase.freeze, value) end alias store []= def assoc(key) super(downcase_key(key)) end def compare_by_identity raise TypeError, "Rack::Headers cannot compare by identity, use regular Hash" end def delete(key) super(downcase_key(key)) end def dig(key, *a) super(downcase_key(key), *a) end def fetch(key, *default, &block) key = downcase_key(key) super end def fetch_values(*a) super(*a.map!{|key| downcase_key(key)}) end def has_key?(key) super(downcase_key(key)) end alias include? has_key? alias key? has_key? alias member? has_key? def invert hash = self.class.new each{|key, value| hash[value] = key} hash end def merge(hash, &block) dup.merge!(hash, &block) end def reject(&block) hash = dup hash.reject!(&block) hash end def replace(hash) clear update(hash) end def select(&block) hash = dup hash.select!(&block) hash end def to_proc lambda{|x| self[x]} end def transform_values(&block) dup.transform_values!(&block) end def update(hash, &block) hash.each do |key, value| self[key] = if block_given? && include?(key) block.call(key, self[key], value) else value end end self end alias merge! update def values_at(*keys) keys.map{|key| self[key]} end # :nocov: if RUBY_VERSION >= '2.5' # :nocov: def slice(*a) h = self.class.new a.each{|k| h[k] = self[k] if has_key?(k)} h end def transform_keys(&block) dup.transform_keys!(&block) end def transform_keys! hash = self.class.new each do |k, v| hash[yield k] = v end replace(hash) end end # :nocov: if RUBY_VERSION >= '3.0' # :nocov: def except(*a) super(*a.map!{|key| downcase_key(key)}) end end private def downcase_key(key) key.is_a?(String) ? key.downcase : key end end end PK% ]ѝo   gems/rack-3.0.8/lib/rack/head.rbnu[# frozen_string_literal: true require_relative 'constants' require_relative 'body_proxy' module Rack # Rack::Head returns an empty body for all HEAD requests. It leaves # all other requests unchanged. class Head def initialize(app) @app = app end def call(env) _, _, body = response = @app.call(env) if env[REQUEST_METHOD] == HEAD response[2] = Rack::BodyProxy.new([]) do body.close if body.respond_to? :close end end response end end end PK% ]՝[[ gems/rack-3.0.8/lib/rack/lint.rbnuȯ# frozen_string_literal: true require 'forwardable' require_relative 'constants' require_relative 'utils' module Rack # Rack::Lint validates your application and the requests and # responses according to the Rack spec. class Lint def initialize(app) @app = app end # :stopdoc: class LintError < RuntimeError; end # AUTHORS: n.b. The trailing whitespace between paragraphs is important and # should not be removed. The whitespace creates paragraphs in the RDoc # output. # ## This specification aims to formalize the Rack protocol. You ## can (and should) use Rack::Lint to enforce it. ## ## When you develop middleware, be sure to add a Lint before and ## after to catch all mistakes. ## ## = Rack applications ## ## A Rack application is a Ruby object (not a class) that ## responds to +call+. def call(env = nil) Wrapper.new(@app, env).response end class Wrapper def initialize(app, env) @app = app @env = env @response = nil @head_request = false @status = nil @headers = nil @body = nil @invoked = nil @content_length = nil @closed = false @size = 0 end def response ## It takes exactly one argument, the *environment* raise LintError, "No env given" unless @env check_environment(@env) @env[RACK_INPUT] = InputWrapper.new(@env[RACK_INPUT]) @env[RACK_ERRORS] = ErrorWrapper.new(@env[RACK_ERRORS]) ## and returns a non-frozen Array of exactly three values: @response = @app.call(@env) raise LintError, "response is not an Array, but #{@response.class}" unless @response.kind_of? Array raise LintError, "response is frozen" if @response.frozen? raise LintError, "response array has #{@response.size} elements instead of 3" unless @response.size == 3 @status, @headers, @body = @response ## The *status*, check_status(@status) ## the *headers*, check_headers(@headers) hijack_proc = check_hijack_response(@headers, @env) if hijack_proc @headers[RACK_HIJACK] = hijack_proc end ## and the *body*. check_content_type(@status, @headers) check_content_length(@status, @headers) @head_request = @env[REQUEST_METHOD] == HEAD @lint = (@env['rack.lint'] ||= []) << self if (@env['rack.lint.body_iteration'] ||= 0) > 0 raise LintError, "Middleware must not call #each directly" end return [@status, @headers, self] end ## ## == The Environment ## def check_environment(env) ## The environment must be an unfrozen instance of Hash that includes ## CGI-like headers. The Rack application is free to modify the ## environment. raise LintError, "env #{env.inspect} is not a Hash, but #{env.class}" unless env.kind_of? Hash raise LintError, "env should not be frozen, but is" if env.frozen? ## ## The environment is required to include these variables ## (adopted from {PEP 333}[https://peps.python.org/pep-0333/]), except when they'd be empty, but see ## below. ## REQUEST_METHOD:: The HTTP request method, such as ## "GET" or "POST". This cannot ever ## be an empty string, and so is ## always required. ## SCRIPT_NAME:: The initial portion of the request ## URL's "path" that corresponds to the ## application object, so that the ## application knows its virtual ## "location". This may be an empty ## string, if the application corresponds ## to the "root" of the server. ## PATH_INFO:: The remainder of the request URL's ## "path", designating the virtual ## "location" of the request's target ## within the application. This may be an ## empty string, if the request URL targets ## the application root and does not have a ## trailing slash. This value may be ## percent-encoded when originating from ## a URL. ## QUERY_STRING:: The portion of the request URL that ## follows the ?, if any. May be ## empty, but is always required! ## SERVER_NAME:: When combined with SCRIPT_NAME and ## PATH_INFO, these variables can be ## used to complete the URL. Note, however, ## that HTTP_HOST, if present, ## should be used in preference to ## SERVER_NAME for reconstructing ## the request URL. ## SERVER_NAME can never be an empty ## string, and so is always required. ## SERVER_PORT:: An optional +Integer+ which is the port the ## server is running on. Should be specified if ## the server is running on a non-standard port. ## SERVER_PROTOCOL:: A string representing the HTTP version used ## for the request. ## HTTP_ Variables:: Variables corresponding to the ## client-supplied HTTP request ## headers (i.e., variables whose ## names begin with HTTP_). The ## presence or absence of these ## variables should correspond with ## the presence or absence of the ## appropriate HTTP header in the ## request. See ## {RFC3875 section 4.1.18}[https://tools.ietf.org/html/rfc3875#section-4.1.18] ## for specific behavior. ## In addition to this, the Rack environment must include these ## Rack-specific variables: ## rack.url_scheme:: +http+ or +https+, depending on the ## request URL. ## rack.input:: See below, the input stream. ## rack.errors:: See below, the error stream. ## rack.hijack?:: See below, if present and true, indicates ## that the server supports partial hijacking. ## rack.hijack:: See below, if present, an object responding ## to +call+ that is used to perform a full ## hijack. ## Additional environment specifications have approved to ## standardized middleware APIs. None of these are required to ## be implemented by the server. ## rack.session:: A hash-like interface for storing ## request session data. ## The store must implement: if session = env[RACK_SESSION] ## store(key, value) (aliased as []=); unless session.respond_to?(:store) && session.respond_to?(:[]=) raise LintError, "session #{session.inspect} must respond to store and []=" end ## fetch(key, default = nil) (aliased as []); unless session.respond_to?(:fetch) && session.respond_to?(:[]) raise LintError, "session #{session.inspect} must respond to fetch and []" end ## delete(key); unless session.respond_to?(:delete) raise LintError, "session #{session.inspect} must respond to delete" end ## clear; unless session.respond_to?(:clear) raise LintError, "session #{session.inspect} must respond to clear" end ## to_hash (returning unfrozen Hash instance); unless session.respond_to?(:to_hash) && session.to_hash.kind_of?(Hash) && !session.to_hash.frozen? raise LintError, "session #{session.inspect} must respond to to_hash and return unfrozen Hash instance" end end ## rack.logger:: A common object interface for logging messages. ## The object must implement: if logger = env[RACK_LOGGER] ## info(message, &block) unless logger.respond_to?(:info) raise LintError, "logger #{logger.inspect} must respond to info" end ## debug(message, &block) unless logger.respond_to?(:debug) raise LintError, "logger #{logger.inspect} must respond to debug" end ## warn(message, &block) unless logger.respond_to?(:warn) raise LintError, "logger #{logger.inspect} must respond to warn" end ## error(message, &block) unless logger.respond_to?(:error) raise LintError, "logger #{logger.inspect} must respond to error" end ## fatal(message, &block) unless logger.respond_to?(:fatal) raise LintError, "logger #{logger.inspect} must respond to fatal" end end ## rack.multipart.buffer_size:: An Integer hint to the multipart parser as to what chunk size to use for reads and writes. if bufsize = env[RACK_MULTIPART_BUFFER_SIZE] unless bufsize.is_a?(Integer) && bufsize > 0 raise LintError, "rack.multipart.buffer_size must be an Integer > 0 if specified" end end ## rack.multipart.tempfile_factory:: An object responding to #call with two arguments, the filename and content_type given for the multipart form field, and returning an IO-like object that responds to #<< and optionally #rewind. This factory will be used to instantiate the tempfile for each multipart form file upload field, rather than the default class of Tempfile. if tempfile_factory = env[RACK_MULTIPART_TEMPFILE_FACTORY] raise LintError, "rack.multipart.tempfile_factory must respond to #call" unless tempfile_factory.respond_to?(:call) env[RACK_MULTIPART_TEMPFILE_FACTORY] = lambda do |filename, content_type| io = tempfile_factory.call(filename, content_type) raise LintError, "rack.multipart.tempfile_factory return value must respond to #<<" unless io.respond_to?(:<<) io end end ## The server or the application can store their own data in the ## environment, too. The keys must contain at least one dot, ## and should be prefixed uniquely. The prefix rack. ## is reserved for use with the Rack core distribution and other ## accepted specifications and must not be used otherwise. ## %w[REQUEST_METHOD SERVER_NAME QUERY_STRING SERVER_PROTOCOL rack.input rack.errors].each { |header| raise LintError, "env missing required key #{header}" unless env.include? header } ## The SERVER_PORT must be an Integer if set. server_port = env["SERVER_PORT"] unless server_port.nil? || (Integer(server_port) rescue false) raise LintError, "env[SERVER_PORT] is not an Integer" end ## The SERVER_NAME must be a valid authority as defined by RFC7540. unless (URI.parse("http://#{env[SERVER_NAME]}/") rescue false) raise LintError, "#{env[SERVER_NAME]} must be a valid authority" end ## The HTTP_HOST must be a valid authority as defined by RFC7540. unless (URI.parse("http://#{env[HTTP_HOST]}/") rescue false) raise LintError, "#{env[HTTP_HOST]} must be a valid authority" end ## The SERVER_PROTOCOL must match the regexp HTTP/\d(\.\d)?. server_protocol = env['SERVER_PROTOCOL'] unless %r{HTTP/\d(\.\d)?}.match?(server_protocol) raise LintError, "env[SERVER_PROTOCOL] does not match HTTP/\\d(\\.\\d)?" end ## If the HTTP_VERSION is present, it must equal the SERVER_PROTOCOL. if env['HTTP_VERSION'] && env['HTTP_VERSION'] != server_protocol raise LintError, "env[HTTP_VERSION] does not equal env[SERVER_PROTOCOL]" end ## The environment must not contain the keys ## HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH ## (use the versions without HTTP_). %w[HTTP_CONTENT_TYPE HTTP_CONTENT_LENGTH].each { |header| if env.include? header raise LintError, "env contains #{header}, must use #{header[5..-1]}" end } ## The CGI keys (named without a period) must have String values. ## If the string values for CGI keys contain non-ASCII characters, ## they should use ASCII-8BIT encoding. env.each { |key, value| next if key.include? "." # Skip extensions unless value.kind_of? String raise LintError, "env variable #{key} has non-string value #{value.inspect}" end next if value.encoding == Encoding::ASCII_8BIT unless value.b !~ /[\x80-\xff]/n raise LintError, "env variable #{key} has value containing non-ASCII characters and has non-ASCII-8BIT encoding #{value.inspect} encoding: #{value.encoding}" end } ## There are the following restrictions: ## * rack.url_scheme must either be +http+ or +https+. unless %w[http https].include?(env[RACK_URL_SCHEME]) raise LintError, "rack.url_scheme unknown: #{env[RACK_URL_SCHEME].inspect}" end ## * There must be a valid input stream in rack.input. check_input env[RACK_INPUT] ## * There must be a valid error stream in rack.errors. check_error env[RACK_ERRORS] ## * There may be a valid hijack callback in rack.hijack check_hijack env ## * The REQUEST_METHOD must be a valid token. unless env[REQUEST_METHOD] =~ /\A[0-9A-Za-z!\#$%&'*+.^_`|~-]+\z/ raise LintError, "REQUEST_METHOD unknown: #{env[REQUEST_METHOD].dump}" end ## * The SCRIPT_NAME, if non-empty, must start with / if env.include?(SCRIPT_NAME) && env[SCRIPT_NAME] != "" && env[SCRIPT_NAME] !~ /\A\// raise LintError, "SCRIPT_NAME must start with /" end ## * The PATH_INFO, if non-empty, must start with / if env.include?(PATH_INFO) && env[PATH_INFO] != "" && env[PATH_INFO] !~ /\A\// raise LintError, "PATH_INFO must start with /" end ## * The CONTENT_LENGTH, if given, must consist of digits only. if env.include?("CONTENT_LENGTH") && env["CONTENT_LENGTH"] !~ /\A\d+\z/ raise LintError, "Invalid CONTENT_LENGTH: #{env["CONTENT_LENGTH"]}" end ## * One of SCRIPT_NAME or PATH_INFO must be ## set. PATH_INFO should be / if ## SCRIPT_NAME is empty. unless env[SCRIPT_NAME] || env[PATH_INFO] raise LintError, "One of SCRIPT_NAME or PATH_INFO must be set (make PATH_INFO '/' if SCRIPT_NAME is empty)" end ## SCRIPT_NAME never should be /, but instead be empty. unless env[SCRIPT_NAME] != "/" raise LintError, "SCRIPT_NAME cannot be '/', make it '' and PATH_INFO '/'" end ## rack.response_finished:: An array of callables run by the server after the response has been ## processed. This would typically be invoked after sending the response to the client, but it could also be ## invoked if an error occurs while generating the response or sending the response; in that case, the error ## argument will be a subclass of +Exception+. ## The callables are invoked with +env, status, headers, error+ arguments and should not raise any ## exceptions. They should be invoked in reverse order of registration. if callables = env[RACK_RESPONSE_FINISHED] raise LintError, "rack.response_finished must be an array of callable objects" unless callables.is_a?(Array) callables.each do |callable| raise LintError, "rack.response_finished values must respond to call(env, status, headers, error)" unless callable.respond_to?(:call) end end end ## ## === The Input Stream ## ## The input stream is an IO-like object which contains the raw HTTP ## POST data. def check_input(input) ## When applicable, its external encoding must be "ASCII-8BIT" and it ## must be opened in binary mode, for Ruby 1.9 compatibility. if input.respond_to?(:external_encoding) && input.external_encoding != Encoding::ASCII_8BIT raise LintError, "rack.input #{input} does not have ASCII-8BIT as its external encoding" end if input.respond_to?(:binmode?) && !input.binmode? raise LintError, "rack.input #{input} is not opened in binary mode" end ## The input stream must respond to +gets+, +each+, and +read+. [:gets, :each, :read].each { |method| unless input.respond_to? method raise LintError, "rack.input #{input} does not respond to ##{method}" end } end class InputWrapper def initialize(input) @input = input end ## * +gets+ must be called without arguments and return a string, ## or +nil+ on EOF. def gets(*args) raise LintError, "rack.input#gets called with arguments" unless args.size == 0 v = @input.gets unless v.nil? or v.kind_of? String raise LintError, "rack.input#gets didn't return a String" end v end ## * +read+ behaves like IO#read. ## Its signature is read([length, [buffer]]). ## ## If given, +length+ must be a non-negative Integer (>= 0) or +nil+, ## and +buffer+ must be a String and may not be nil. ## ## If +length+ is given and not nil, then this method reads at most ## +length+ bytes from the input stream. ## ## If +length+ is not given or nil, then this method reads ## all data until EOF. ## ## When EOF is reached, this method returns nil if +length+ is given ## and not nil, or "" if +length+ is not given or is nil. ## ## If +buffer+ is given, then the read data will be placed ## into +buffer+ instead of a newly created String object. def read(*args) unless args.size <= 2 raise LintError, "rack.input#read called with too many arguments" end if args.size >= 1 unless args.first.kind_of?(Integer) || args.first.nil? raise LintError, "rack.input#read called with non-integer and non-nil length" end unless args.first.nil? || args.first >= 0 raise LintError, "rack.input#read called with a negative length" end end if args.size >= 2 unless args[1].kind_of?(String) raise LintError, "rack.input#read called with non-String buffer" end end v = @input.read(*args) unless v.nil? or v.kind_of? String raise LintError, "rack.input#read didn't return nil or a String" end if args[0].nil? unless !v.nil? raise LintError, "rack.input#read(nil) returned nil on EOF" end end v end ## * +each+ must be called without arguments and only yield Strings. def each(*args) raise LintError, "rack.input#each called with arguments" unless args.size == 0 @input.each { |line| unless line.kind_of? String raise LintError, "rack.input#each didn't yield a String" end yield line } end ## * +close+ can be called on the input stream to indicate that the ## any remaining input is not needed. def close(*args) @input.close(*args) end end ## ## === The Error Stream ## def check_error(error) ## The error stream must respond to +puts+, +write+ and +flush+. [:puts, :write, :flush].each { |method| unless error.respond_to? method raise LintError, "rack.error #{error} does not respond to ##{method}" end } end class ErrorWrapper def initialize(error) @error = error end ## * +puts+ must be called with a single argument that responds to +to_s+. def puts(str) @error.puts str end ## * +write+ must be called with a single argument that is a String. def write(str) raise LintError, "rack.errors#write not called with a String" unless str.kind_of? String @error.write str end ## * +flush+ must be called without arguments and must be called ## in order to make the error appear for sure. def flush @error.flush end ## * +close+ must never be called on the error stream. def close(*args) raise LintError, "rack.errors#close must not be called" end end ## ## === Hijacking ## ## The hijacking interfaces provides a means for an application to take ## control of the HTTP connection. There are two distinct hijack ## interfaces: full hijacking where the application takes over the raw ## connection, and partial hijacking where the application takes over ## just the response body stream. In both cases, the application is ## responsible for closing the hijacked stream. ## ## Full hijacking only works with HTTP/1. Partial hijacking is functionally ## equivalent to streaming bodies, and is still optionally supported for ## backwards compatibility with older Rack versions. ## ## ==== Full Hijack ## ## Full hijack is used to completely take over an HTTP/1 connection. It ## occurs before any headers are written and causes the request to ## ignores any response generated by the application. ## ## It is intended to be used when applications need access to raw HTTP/1 ## connection. ## def check_hijack(env) ## If +rack.hijack+ is present in +env+, it must respond to +call+ if original_hijack = env[RACK_HIJACK] raise LintError, "rack.hijack must respond to call" unless original_hijack.respond_to?(:call) env[RACK_HIJACK] = proc do io = original_hijack.call ## and return an +IO+ instance which can be used to read and write ## to the underlying connection using HTTP/1 semantics and ## formatting. raise LintError, "rack.hijack must return an IO instance" unless io.is_a?(IO) io end end end ## ## ==== Partial Hijack ## ## Partial hijack is used for bi-directional streaming of the request and ## response body. It occurs after the status and headers are written by ## the server and causes the server to ignore the Body of the response. ## ## It is intended to be used when applications need bi-directional ## streaming. ## def check_hijack_response(headers, env) ## If +rack.hijack?+ is present in +env+ and truthy, if env[RACK_IS_HIJACK] ## an application may set the special response header +rack.hijack+ if original_hijack = headers[RACK_HIJACK] ## to an object that responds to +call+, unless original_hijack.respond_to?(:call) raise LintError, 'rack.hijack header must respond to #call' end ## accepting a +stream+ argument. return proc do |io| original_hijack.call StreamWrapper.new(io) end end ## ## After the response status and headers have been sent, this hijack ## callback will be invoked with a +stream+ argument which follows the ## same interface as outlined in "Streaming Body". Servers must ## ignore the +body+ part of the response tuple when the ## +rack.hijack+ response header is present. Using an empty +Array+ ## instance is recommended. else ## ## The special response header +rack.hijack+ must only be set ## if the request +env+ has a truthy +rack.hijack?+. if headers.key?(RACK_HIJACK) raise LintError, 'rack.hijack header must not be present if server does not support hijacking' end end nil end ## == The Response ## ## === The Status ## def check_status(status) ## This is an HTTP status. It must be an Integer greater than or equal to ## 100. unless status.is_a?(Integer) && status >= 100 raise LintError, "Status must be an Integer >=100" end end ## ## === The Headers ## def check_headers(headers) ## The headers must be a unfrozen Hash. unless headers.kind_of?(Hash) raise LintError, "headers object should be a hash, but isn't (got #{headers.class} as headers)" end if headers.frozen? raise LintError, "headers object should not be frozen, but is" end headers.each do |key, value| ## The header keys must be Strings. unless key.kind_of? String raise LintError, "header key must be a string, was #{key.class}" end ## Special headers starting "rack." are for communicating with the ## server, and must not be sent back to the client. next if key.start_with?("rack.") ## The header must not contain a +Status+ key. raise LintError, "header must not contain status" if key == "status" ## Header keys must conform to RFC7230 token specification, i.e. cannot ## contain non-printable ASCII, DQUOTE or "(),/:;<=>?@[\]{}". raise LintError, "invalid header name: #{key}" if key =~ /[\(\),\/:;<=>\?@\[\\\]{}[:cntrl:]]/ ## Header keys must not contain uppercase ASCII characters (A-Z). raise LintError, "uppercase character in header name: #{key}" if key =~ /[A-Z]/ ## Header values must be either a String instance, if value.kind_of?(String) check_header_value(key, value) elsif value.kind_of?(Array) ## or an Array of String instances, value.each{|value| check_header_value(key, value)} else raise LintError, "a header value must be a String or Array of Strings, but the value of '#{key}' is a #{value.class}" end end end def check_header_value(key, value) ## such that each String instance must not contain characters below 037. if value =~ /[\000-\037]/ raise LintError, "invalid header value #{key}: #{value.inspect}" end end ## ## === The content-type ## def check_content_type(status, headers) headers.each { |key, value| ## There must not be a content-type header key when the +Status+ is 1xx, ## 204, or 304. if key == "content-type" if Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.key? status.to_i raise LintError, "content-type header found in #{status} response, not allowed" end return end } end ## ## === The content-length ## def check_content_length(status, headers) headers.each { |key, value| if key == 'content-length' ## There must not be a content-length header key when the ## +Status+ is 1xx, 204, or 304. if Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.key? status.to_i raise LintError, "content-length header found in #{status} response, not allowed" end @content_length = value end } end def verify_content_length(size) if @head_request unless size == 0 raise LintError, "Response body was given for HEAD request, but should be empty" end elsif @content_length unless @content_length == size.to_s raise LintError, "content-length header was #{@content_length}, but should be #{size}" end end end ## ## === The Body ## ## The Body is typically an +Array+ of +String+ instances, an enumerable ## that yields +String+ instances, a +Proc+ instance, or a File-like ## object. ## ## The Body must respond to +each+ or +call+. It may optionally respond ## to +to_path+ or +to_ary+. A Body that responds to +each+ is considered ## to be an Enumerable Body. A Body that responds to +call+ is considered ## to be a Streaming Body. ## ## A Body that responds to both +each+ and +call+ must be treated as an ## Enumerable Body, not a Streaming Body. If it responds to +each+, you ## must call +each+ and not +call+. If the Body doesn't respond to ## +each+, then you can assume it responds to +call+. ## ## The Body must either be consumed or returned. The Body is consumed by ## optionally calling either +each+ or +call+. ## Then, if the Body responds to +close+, it must be called to release ## any resources associated with the generation of the body. ## In other words, +close+ must always be called at least once; typically ## after the web server has sent the response to the client, but also in ## cases where the Rack application makes internal/virtual requests and ## discards the response. ## def close ## ## After calling +close+, the Body is considered closed and should not ## be consumed again. @closed = true ## If the original Body is replaced by a new Body, the new Body must ## also consume the original Body by calling +close+ if possible. @body.close if @body.respond_to?(:close) index = @lint.index(self) unless @env['rack.lint'][0..index].all? {|lint| lint.instance_variable_get(:@closed)} raise LintError, "Body has not been closed" end end def verify_to_path ## ## If the Body responds to +to_path+, it must return a +String+ ## path for the local file system whose contents are identical ## to that produced by calling +each+; this may be used by the ## server as an alternative, possibly more efficient way to ## transport the response. The +to_path+ method does not consume ## the body. if @body.respond_to?(:to_path) unless ::File.exist? @body.to_path raise LintError, "The file identified by body.to_path does not exist" end end end ## ## ==== Enumerable Body ## def each ## The Enumerable Body must respond to +each+. raise LintError, "Enumerable Body must respond to each" unless @body.respond_to?(:each) ## It must only be called once. raise LintError, "Response body must only be invoked once (#{@invoked})" unless @invoked.nil? ## It must not be called after being closed. raise LintError, "Response body is already closed" if @closed @invoked = :each @body.each do |chunk| ## and must only yield String values. unless chunk.kind_of? String raise LintError, "Body yielded non-string value #{chunk.inspect}" end ## ## The Body itself should not be an instance of String, as this will ## break in Ruby 1.9. ## ## Middleware must not call +each+ directly on the Body. ## Instead, middleware can return a new Body that calls +each+ on the ## original Body, yielding at least once per iteration. if @lint[0] == self @env['rack.lint.body_iteration'] += 1 else if (@env['rack.lint.body_iteration'] -= 1) > 0 raise LintError, "New body must yield at least once per iteration of old body" end end @size += chunk.bytesize yield chunk end verify_content_length(@size) verify_to_path end BODY_METHODS = {to_ary: true, each: true, call: true, to_path: true} def to_path @body.to_path end def respond_to?(name, *) if BODY_METHODS.key?(name) @body.respond_to?(name) else super end end ## ## If the Body responds to +to_ary+, it must return an +Array+ whose ## contents are identical to that produced by calling +each+. ## Middleware may call +to_ary+ directly on the Body and return a new ## Body in its place. In other words, middleware can only process the ## Body directly if it responds to +to_ary+. If the Body responds to both ## +to_ary+ and +close+, its implementation of +to_ary+ must call ## +close+. def to_ary @body.to_ary.tap do |content| unless content == @body.enum_for.to_a raise LintError, "#to_ary not identical to contents produced by calling #each" end end ensure close end ## ## ==== Streaming Body ## def call(stream) ## The Streaming Body must respond to +call+. raise LintError, "Streaming Body must respond to call" unless @body.respond_to?(:call) ## It must only be called once. raise LintError, "Response body must only be invoked once (#{@invoked})" unless @invoked.nil? ## It must not be called after being closed. raise LintError, "Response body is already closed" if @closed @invoked = :call ## It takes a +stream+ argument. ## ## The +stream+ argument must implement: ## read, write, <<, flush, close, close_read, close_write, closed? ## @body.call(StreamWrapper.new(stream)) end class StreamWrapper extend Forwardable ## The semantics of these IO methods must be a best effort match to ## those of a normal Ruby IO or Socket object, using standard arguments ## and raising standard exceptions. Servers are encouraged to simply ## pass on real IO objects, although it is recognized that this approach ## is not directly compatible with HTTP/2. REQUIRED_METHODS = [ :read, :write, :<<, :flush, :close, :close_read, :close_write, :closed? ] def_delegators :@stream, *REQUIRED_METHODS def initialize(stream) @stream = stream REQUIRED_METHODS.each do |method_name| raise LintError, "Stream must respond to #{method_name}" unless stream.respond_to?(method_name) end end end # :startdoc: end end end ## ## == Thanks ## Some parts of this specification are adopted from {PEP 333 – Python Web Server Gateway Interface v1.0}[https://peps.python.org/pep-0333/] ## I'd like to thank everyone involved in that effort. PK% ]|| +gems/rack-3.0.8/lib/rack/conditional_get.rbnu[# frozen_string_literal: true require_relative 'constants' require_relative 'utils' require_relative 'body_proxy' module Rack # Middleware that enables conditional GET using if-none-match and # if-modified-since. The application should set either or both of the # last-modified or etag response headers according to RFC 2616. When # either of the conditions is met, the response body is set to be zero # length and the response status is set to 304 Not Modified. # # Applications that defer response body generation until the body's each # message is received will avoid response body generation completely when # a conditional GET matches. # # Adapted from Michael Klishin's Merb implementation: # https://github.com/wycats/merb/blob/master/merb-core/lib/merb-core/rack/middleware/conditional_get.rb class ConditionalGet def initialize(app) @app = app end # Return empty 304 response if the response has not been # modified since the last request. def call(env) case env[REQUEST_METHOD] when "GET", "HEAD" status, headers, body = response = @app.call(env) if status == 200 && fresh?(env, headers) response[0] = 304 headers.delete(CONTENT_TYPE) headers.delete(CONTENT_LENGTH) response[2] = Rack::BodyProxy.new([]) do body.close if body.respond_to?(:close) end end response else @app.call(env) end end private # Return whether the response has not been modified since the # last request. def fresh?(env, headers) # if-none-match has priority over if-modified-since per RFC 7232 if none_match = env['HTTP_IF_NONE_MATCH'] etag_matches?(none_match, headers) elsif (modified_since = env['HTTP_IF_MODIFIED_SINCE']) && (modified_since = to_rfc2822(modified_since)) modified_since?(modified_since, headers) end end # Whether the etag response header matches the if-none-match request header. # If so, the request has not been modified. def etag_matches?(none_match, headers) headers[ETAG] == none_match end # Whether the last-modified response header matches the if-modified-since # request header. If so, the request has not been modified. def modified_since?(modified_since, headers) last_modified = to_rfc2822(headers['last-modified']) and modified_since >= last_modified end # Return a Time object for the given string (which should be in RFC2822 # format), or nil if the string cannot be parsed. def to_rfc2822(since) # shortest possible valid date is the obsolete: 1 Nov 97 09:55 A # anything shorter is invalid, this avoids exceptions for common cases # most common being the empty string if since && since.length >= 16 # NOTE: there is no trivial way to write this in a non exception way # _rfc2822 returns a hash but is not that usable Time.rfc2822(since) rescue nil end end end end PK% ]N4q(gems/rack-3.0.8/lib/rack/content_type.rbnu[# frozen_string_literal: true require_relative 'constants' require_relative 'utils' module Rack # Sets the content-type header on responses which don't have one. # # Builder Usage: # use Rack::ContentType, "text/plain" # # When no content type argument is provided, "text/html" is the # default. class ContentType include Rack::Utils def initialize(app, content_type = "text/html") @app = app @content_type = content_type end def call(env) status, headers, _ = response = @app.call(env) unless STATUS_WITH_NO_ENTITY_BODY.key?(status.to_i) headers[CONTENT_TYPE] ||= @content_type end response end end end PK% ]dNN'gems/rack-3.0.8/lib/rack/show_status.rbnu[# frozen_string_literal: true require 'erb' require_relative 'constants' require_relative 'utils' require_relative 'request' require_relative 'body_proxy' module Rack # Rack::ShowStatus catches all empty responses and replaces them # with a site explaining the error. # # Additional details can be put into rack.showstatus.detail # and will be shown as HTML. If such details exist, the error page # is always rendered, even if the reply was not empty. class ShowStatus def initialize(app) @app = app @template = ERB.new(TEMPLATE) end def call(env) status, headers, body = response = @app.call(env) empty = headers[CONTENT_LENGTH].to_i <= 0 # client or server error, or explicit message if (status.to_i >= 400 && empty) || env[RACK_SHOWSTATUS_DETAIL] # This double assignment is to prevent an "unused variable" warning. # Yes, it is dumb, but I don't like Ruby yelling at me. req = req = Rack::Request.new(env) message = Rack::Utils::HTTP_STATUS_CODES[status.to_i] || status.to_s # This double assignment is to prevent an "unused variable" warning. # Yes, it is dumb, but I don't like Ruby yelling at me. detail = detail = env[RACK_SHOWSTATUS_DETAIL] || message html = @template.result(binding) size = html.bytesize response[2] = Rack::BodyProxy.new([html]) do body.close if body.respond_to?(:close) end headers[CONTENT_TYPE] = "text/html" headers[CONTENT_LENGTH] = size.to_s end response end def h(obj) # :nodoc: case obj when String Utils.escape_html(obj) else Utils.escape_html(obj.inspect) end end # :stopdoc: # adapted from Django # Copyright (c) Django Software Foundation and individual contributors. # Used under the modified BSD license: # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5 TEMPLATE = <<'HTML' <%=h message %> at <%=h req.script_name + req.path_info %>

<%=h message %> (<%= status.to_i %>)

Request Method: <%=h req.request_method %>
Request URL: <%=h req.url %>

<%=h detail %>

You're seeing this error because you use Rack::ShowStatus.

HTML # :startdoc: end end PK% ]?6/ gems/rack-3.0.8/lib/rack/mime.rbnu[# frozen_string_literal: true module Rack module Mime # Returns String with mime type if found, otherwise use +fallback+. # +ext+ should be filename extension in the '.ext' format that # File.extname(file) returns. # +fallback+ may be any object # # Also see the documentation for MIME_TYPES # # Usage: # Rack::Mime.mime_type('.foo') # # This is a shortcut for: # Rack::Mime::MIME_TYPES.fetch('.foo', 'application/octet-stream') def mime_type(ext, fallback = 'application/octet-stream') MIME_TYPES.fetch(ext.to_s.downcase, fallback) end module_function :mime_type # Returns true if the given value is a mime match for the given mime match # specification, false otherwise. # # Rack::Mime.match?('text/html', 'text/*') => true # Rack::Mime.match?('text/plain', '*') => true # Rack::Mime.match?('text/html', 'application/json') => false def match?(value, matcher) v1, v2 = value.split('/', 2) m1, m2 = matcher.split('/', 2) (m1 == '*' || v1 == m1) && (m2.nil? || m2 == '*' || m2 == v2) end module_function :match? # List of most common mime-types, selected various sources # according to their usefulness in a webserving scope for Ruby # users. # # To amend this list with your local mime.types list you can use: # # require 'webrick/httputils' # list = WEBrick::HTTPUtils.load_mime_types('/etc/mime.types') # Rack::Mime::MIME_TYPES.merge!(list) # # N.B. On Ubuntu the mime.types file does not include the leading period, so # users may need to modify the data before merging into the hash. MIME_TYPES = { ".123" => "application/vnd.lotus-1-2-3", ".3dml" => "text/vnd.in3d.3dml", ".3g2" => "video/3gpp2", ".3gp" => "video/3gpp", ".a" => "application/octet-stream", ".acc" => "application/vnd.americandynamics.acc", ".ace" => "application/x-ace-compressed", ".acu" => "application/vnd.acucobol", ".aep" => "application/vnd.audiograph", ".afp" => "application/vnd.ibm.modcap", ".ai" => "application/postscript", ".aif" => "audio/x-aiff", ".aiff" => "audio/x-aiff", ".ami" => "application/vnd.amiga.ami", ".apng" => "image/apng", ".appcache" => "text/cache-manifest", ".apr" => "application/vnd.lotus-approach", ".asc" => "application/pgp-signature", ".asf" => "video/x-ms-asf", ".asm" => "text/x-asm", ".aso" => "application/vnd.accpac.simply.aso", ".asx" => "video/x-ms-asf", ".atc" => "application/vnd.acucorp", ".atom" => "application/atom+xml", ".atomcat" => "application/atomcat+xml", ".atomsvc" => "application/atomsvc+xml", ".atx" => "application/vnd.antix.game-component", ".au" => "audio/basic", ".avi" => "video/x-msvideo", ".avif" => "image/avif", ".bat" => "application/x-msdownload", ".bcpio" => "application/x-bcpio", ".bdm" => "application/vnd.syncml.dm+wbxml", ".bh2" => "application/vnd.fujitsu.oasysprs", ".bin" => "application/octet-stream", ".bmi" => "application/vnd.bmi", ".bmp" => "image/bmp", ".box" => "application/vnd.previewsystems.box", ".btif" => "image/prs.btif", ".bz" => "application/x-bzip", ".bz2" => "application/x-bzip2", ".c" => "text/x-c", ".c4g" => "application/vnd.clonk.c4group", ".cab" => "application/vnd.ms-cab-compressed", ".cc" => "text/x-c", ".ccxml" => "application/ccxml+xml", ".cdbcmsg" => "application/vnd.contact.cmsg", ".cdkey" => "application/vnd.mediastation.cdkey", ".cdx" => "chemical/x-cdx", ".cdxml" => "application/vnd.chemdraw+xml", ".cdy" => "application/vnd.cinderella", ".cer" => "application/pkix-cert", ".cgm" => "image/cgm", ".chat" => "application/x-chat", ".chm" => "application/vnd.ms-htmlhelp", ".chrt" => "application/vnd.kde.kchart", ".cif" => "chemical/x-cif", ".cii" => "application/vnd.anser-web-certificate-issue-initiation", ".cil" => "application/vnd.ms-artgalry", ".cla" => "application/vnd.claymore", ".class" => "application/octet-stream", ".clkk" => "application/vnd.crick.clicker.keyboard", ".clkp" => "application/vnd.crick.clicker.palette", ".clkt" => "application/vnd.crick.clicker.template", ".clkw" => "application/vnd.crick.clicker.wordbank", ".clkx" => "application/vnd.crick.clicker", ".clp" => "application/x-msclip", ".cmc" => "application/vnd.cosmocaller", ".cmdf" => "chemical/x-cmdf", ".cml" => "chemical/x-cml", ".cmp" => "application/vnd.yellowriver-custom-menu", ".cmx" => "image/x-cmx", ".com" => "application/x-msdownload", ".conf" => "text/plain", ".cpio" => "application/x-cpio", ".cpp" => "text/x-c", ".cpt" => "application/mac-compactpro", ".crd" => "application/x-mscardfile", ".crl" => "application/pkix-crl", ".crt" => "application/x-x509-ca-cert", ".csh" => "application/x-csh", ".csml" => "chemical/x-csml", ".csp" => "application/vnd.commonspace", ".css" => "text/css", ".csv" => "text/csv", ".curl" => "application/vnd.curl", ".cww" => "application/prs.cww", ".cxx" => "text/x-c", ".daf" => "application/vnd.mobius.daf", ".davmount" => "application/davmount+xml", ".dcr" => "application/x-director", ".dd2" => "application/vnd.oma.dd2+xml", ".ddd" => "application/vnd.fujixerox.ddd", ".deb" => "application/x-debian-package", ".der" => "application/x-x509-ca-cert", ".dfac" => "application/vnd.dreamfactory", ".diff" => "text/x-diff", ".dis" => "application/vnd.mobius.dis", ".djv" => "image/vnd.djvu", ".djvu" => "image/vnd.djvu", ".dll" => "application/x-msdownload", ".dmg" => "application/octet-stream", ".dna" => "application/vnd.dna", ".doc" => "application/msword", ".docm" => "application/vnd.ms-word.document.macroEnabled.12", ".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".dot" => "application/msword", ".dotm" => "application/vnd.ms-word.template.macroEnabled.12", ".dotx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.template", ".dp" => "application/vnd.osgi.dp", ".dpg" => "application/vnd.dpgraph", ".dsc" => "text/prs.lines.tag", ".dtd" => "application/xml-dtd", ".dts" => "audio/vnd.dts", ".dtshd" => "audio/vnd.dts.hd", ".dv" => "video/x-dv", ".dvi" => "application/x-dvi", ".dwf" => "model/vnd.dwf", ".dwg" => "image/vnd.dwg", ".dxf" => "image/vnd.dxf", ".dxp" => "application/vnd.spotfire.dxp", ".ear" => "application/java-archive", ".ecelp4800" => "audio/vnd.nuera.ecelp4800", ".ecelp7470" => "audio/vnd.nuera.ecelp7470", ".ecelp9600" => "audio/vnd.nuera.ecelp9600", ".ecma" => "application/ecmascript", ".edm" => "application/vnd.novadigm.edm", ".edx" => "application/vnd.novadigm.edx", ".efif" => "application/vnd.picsel", ".ei6" => "application/vnd.pg.osasli", ".eml" => "message/rfc822", ".eol" => "audio/vnd.digital-winds", ".eot" => "application/vnd.ms-fontobject", ".eps" => "application/postscript", ".es3" => "application/vnd.eszigno3+xml", ".esf" => "application/vnd.epson.esf", ".etx" => "text/x-setext", ".exe" => "application/x-msdownload", ".ext" => "application/vnd.novadigm.ext", ".ez" => "application/andrew-inset", ".ez2" => "application/vnd.ezpix-album", ".ez3" => "application/vnd.ezpix-package", ".f" => "text/x-fortran", ".f77" => "text/x-fortran", ".f90" => "text/x-fortran", ".fbs" => "image/vnd.fastbidsheet", ".fdf" => "application/vnd.fdf", ".fe_launch" => "application/vnd.denovo.fcselayout-link", ".fg5" => "application/vnd.fujitsu.oasysgp", ".fli" => "video/x-fli", ".flif" => "image/flif", ".flo" => "application/vnd.micrografx.flo", ".flv" => "video/x-flv", ".flw" => "application/vnd.kde.kivio", ".flx" => "text/vnd.fmi.flexstor", ".fly" => "text/vnd.fly", ".fm" => "application/vnd.framemaker", ".fnc" => "application/vnd.frogans.fnc", ".for" => "text/x-fortran", ".fpx" => "image/vnd.fpx", ".fsc" => "application/vnd.fsc.weblaunch", ".fst" => "image/vnd.fst", ".ftc" => "application/vnd.fluxtime.clip", ".fti" => "application/vnd.anser-web-funds-transfer-initiation", ".fvt" => "video/vnd.fvt", ".fzs" => "application/vnd.fuzzysheet", ".g3" => "image/g3fax", ".gac" => "application/vnd.groove-account", ".gdl" => "model/vnd.gdl", ".gem" => "application/octet-stream", ".gemspec" => "text/x-script.ruby", ".ghf" => "application/vnd.groove-help", ".gif" => "image/gif", ".gim" => "application/vnd.groove-identity-message", ".gmx" => "application/vnd.gmx", ".gph" => "application/vnd.flographit", ".gqf" => "application/vnd.grafeq", ".gram" => "application/srgs", ".grv" => "application/vnd.groove-injector", ".grxml" => "application/srgs+xml", ".gtar" => "application/x-gtar", ".gtm" => "application/vnd.groove-tool-message", ".gtw" => "model/vnd.gtw", ".gv" => "text/vnd.graphviz", ".gz" => "application/x-gzip", ".h" => "text/x-c", ".h261" => "video/h261", ".h263" => "video/h263", ".h264" => "video/h264", ".hbci" => "application/vnd.hbci", ".hdf" => "application/x-hdf", ".heic" => "image/heic", ".heics" => "image/heic-sequence", ".heif" => "image/heif", ".heifs" => "image/heif-sequence", ".hh" => "text/x-c", ".hlp" => "application/winhlp", ".hpgl" => "application/vnd.hp-hpgl", ".hpid" => "application/vnd.hp-hpid", ".hps" => "application/vnd.hp-hps", ".hqx" => "application/mac-binhex40", ".htc" => "text/x-component", ".htke" => "application/vnd.kenameaapp", ".htm" => "text/html", ".html" => "text/html", ".hvd" => "application/vnd.yamaha.hv-dic", ".hvp" => "application/vnd.yamaha.hv-voice", ".hvs" => "application/vnd.yamaha.hv-script", ".icc" => "application/vnd.iccprofile", ".ice" => "x-conference/x-cooltalk", ".ico" => "image/vnd.microsoft.icon", ".ics" => "text/calendar", ".ief" => "image/ief", ".ifb" => "text/calendar", ".ifm" => "application/vnd.shana.informed.formdata", ".igl" => "application/vnd.igloader", ".igs" => "model/iges", ".igx" => "application/vnd.micrografx.igx", ".iif" => "application/vnd.shana.informed.interchange", ".imp" => "application/vnd.accpac.simply.imp", ".ims" => "application/vnd.ms-ims", ".ipk" => "application/vnd.shana.informed.package", ".irm" => "application/vnd.ibm.rights-management", ".irp" => "application/vnd.irepository.package+xml", ".iso" => "application/octet-stream", ".itp" => "application/vnd.shana.informed.formtemplate", ".ivp" => "application/vnd.immervision-ivp", ".ivu" => "application/vnd.immervision-ivu", ".jad" => "text/vnd.sun.j2me.app-descriptor", ".jam" => "application/vnd.jam", ".jar" => "application/java-archive", ".java" => "text/x-java-source", ".jisp" => "application/vnd.jisp", ".jlt" => "application/vnd.hp-jlyt", ".jnlp" => "application/x-java-jnlp-file", ".joda" => "application/vnd.joost.joda-archive", ".jp2" => "image/jp2", ".jpeg" => "image/jpeg", ".jpg" => "image/jpeg", ".jpgv" => "video/jpeg", ".jpm" => "video/jpm", ".js" => "application/javascript", ".json" => "application/json", ".karbon" => "application/vnd.kde.karbon", ".kfo" => "application/vnd.kde.kformula", ".kia" => "application/vnd.kidspiration", ".kml" => "application/vnd.google-earth.kml+xml", ".kmz" => "application/vnd.google-earth.kmz", ".kne" => "application/vnd.kinar", ".kon" => "application/vnd.kde.kontour", ".kpr" => "application/vnd.kde.kpresenter", ".ksp" => "application/vnd.kde.kspread", ".ktz" => "application/vnd.kahootz", ".kwd" => "application/vnd.kde.kword", ".latex" => "application/x-latex", ".lbd" => "application/vnd.llamagraphics.life-balance.desktop", ".lbe" => "application/vnd.llamagraphics.life-balance.exchange+xml", ".les" => "application/vnd.hhe.lesson-player", ".link66" => "application/vnd.route66.link66+xml", ".log" => "text/plain", ".lostxml" => "application/lost+xml", ".lrm" => "application/vnd.ms-lrm", ".ltf" => "application/vnd.frogans.ltf", ".lvp" => "audio/vnd.lucent.voice", ".lwp" => "application/vnd.lotus-wordpro", ".m3u" => "audio/x-mpegurl", ".m3u8" => "application/x-mpegurl", ".m4a" => "audio/mp4a-latm", ".m4v" => "video/mp4", ".ma" => "application/mathematica", ".mag" => "application/vnd.ecowin.chart", ".man" => "text/troff", ".manifest" => "text/cache-manifest", ".mathml" => "application/mathml+xml", ".mbk" => "application/vnd.mobius.mbk", ".mbox" => "application/mbox", ".mc1" => "application/vnd.medcalcdata", ".mcd" => "application/vnd.mcd", ".mdb" => "application/x-msaccess", ".mdi" => "image/vnd.ms-modi", ".mdoc" => "text/troff", ".me" => "text/troff", ".mfm" => "application/vnd.mfmp", ".mgz" => "application/vnd.proteus.magazine", ".mid" => "audio/midi", ".midi" => "audio/midi", ".mif" => "application/vnd.mif", ".mime" => "message/rfc822", ".mj2" => "video/mj2", ".mlp" => "application/vnd.dolby.mlp", ".mmd" => "application/vnd.chipnuts.karaoke-mmd", ".mmf" => "application/vnd.smaf", ".mml" => "application/mathml+xml", ".mmr" => "image/vnd.fujixerox.edmics-mmr", ".mng" => "video/x-mng", ".mny" => "application/x-msmoney", ".mov" => "video/quicktime", ".movie" => "video/x-sgi-movie", ".mp3" => "audio/mpeg", ".mp4" => "video/mp4", ".mp4a" => "audio/mp4", ".mp4s" => "application/mp4", ".mp4v" => "video/mp4", ".mpc" => "application/vnd.mophun.certificate", ".mpd" => "application/dash+xml", ".mpeg" => "video/mpeg", ".mpg" => "video/mpeg", ".mpga" => "audio/mpeg", ".mpkg" => "application/vnd.apple.installer+xml", ".mpm" => "application/vnd.blueice.multipass", ".mpn" => "application/vnd.mophun.application", ".mpp" => "application/vnd.ms-project", ".mpy" => "application/vnd.ibm.minipay", ".mqy" => "application/vnd.mobius.mqy", ".mrc" => "application/marc", ".ms" => "text/troff", ".mscml" => "application/mediaservercontrol+xml", ".mseq" => "application/vnd.mseq", ".msf" => "application/vnd.epson.msf", ".msh" => "model/mesh", ".msi" => "application/x-msdownload", ".msl" => "application/vnd.mobius.msl", ".msty" => "application/vnd.muvee.style", ".mts" => "model/vnd.mts", ".mus" => "application/vnd.musician", ".mvb" => "application/x-msmediaview", ".mwf" => "application/vnd.mfer", ".mxf" => "application/mxf", ".mxl" => "application/vnd.recordare.musicxml", ".mxml" => "application/xv+xml", ".mxs" => "application/vnd.triscape.mxs", ".mxu" => "video/vnd.mpegurl", ".n" => "application/vnd.nokia.n-gage.symbian.install", ".nc" => "application/x-netcdf", ".ngdat" => "application/vnd.nokia.n-gage.data", ".nlu" => "application/vnd.neurolanguage.nlu", ".nml" => "application/vnd.enliven", ".nnd" => "application/vnd.noblenet-directory", ".nns" => "application/vnd.noblenet-sealer", ".nnw" => "application/vnd.noblenet-web", ".npx" => "image/vnd.net-fpx", ".nsf" => "application/vnd.lotus-notes", ".oa2" => "application/vnd.fujitsu.oasys2", ".oa3" => "application/vnd.fujitsu.oasys3", ".oas" => "application/vnd.fujitsu.oasys", ".obd" => "application/x-msbinder", ".oda" => "application/oda", ".odc" => "application/vnd.oasis.opendocument.chart", ".odf" => "application/vnd.oasis.opendocument.formula", ".odg" => "application/vnd.oasis.opendocument.graphics", ".odi" => "application/vnd.oasis.opendocument.image", ".odp" => "application/vnd.oasis.opendocument.presentation", ".ods" => "application/vnd.oasis.opendocument.spreadsheet", ".odt" => "application/vnd.oasis.opendocument.text", ".oga" => "audio/ogg", ".ogg" => "application/ogg", ".ogv" => "video/ogg", ".ogx" => "application/ogg", ".org" => "application/vnd.lotus-organizer", ".otc" => "application/vnd.oasis.opendocument.chart-template", ".otf" => "application/vnd.oasis.opendocument.formula-template", ".otg" => "application/vnd.oasis.opendocument.graphics-template", ".oth" => "application/vnd.oasis.opendocument.text-web", ".oti" => "application/vnd.oasis.opendocument.image-template", ".otm" => "application/vnd.oasis.opendocument.text-master", ".ots" => "application/vnd.oasis.opendocument.spreadsheet-template", ".ott" => "application/vnd.oasis.opendocument.text-template", ".oxt" => "application/vnd.openofficeorg.extension", ".p" => "text/x-pascal", ".p10" => "application/pkcs10", ".p12" => "application/x-pkcs12", ".p7b" => "application/x-pkcs7-certificates", ".p7m" => "application/pkcs7-mime", ".p7r" => "application/x-pkcs7-certreqresp", ".p7s" => "application/pkcs7-signature", ".pas" => "text/x-pascal", ".pbd" => "application/vnd.powerbuilder6", ".pbm" => "image/x-portable-bitmap", ".pcl" => "application/vnd.hp-pcl", ".pclxl" => "application/vnd.hp-pclxl", ".pcx" => "image/x-pcx", ".pdb" => "chemical/x-pdb", ".pdf" => "application/pdf", ".pem" => "application/x-x509-ca-cert", ".pfr" => "application/font-tdpfr", ".pgm" => "image/x-portable-graymap", ".pgn" => "application/x-chess-pgn", ".pgp" => "application/pgp-encrypted", ".pic" => "image/x-pict", ".pict" => "image/pict", ".pkg" => "application/octet-stream", ".pki" => "application/pkixcmp", ".pkipath" => "application/pkix-pkipath", ".pl" => "text/x-script.perl", ".plb" => "application/vnd.3gpp.pic-bw-large", ".plc" => "application/vnd.mobius.plc", ".plf" => "application/vnd.pocketlearn", ".pls" => "application/pls+xml", ".pm" => "text/x-script.perl-module", ".pml" => "application/vnd.ctc-posml", ".png" => "image/png", ".pnm" => "image/x-portable-anymap", ".pntg" => "image/x-macpaint", ".portpkg" => "application/vnd.macports.portpkg", ".pot" => "application/vnd.ms-powerpoint", ".potm" => "application/vnd.ms-powerpoint.template.macroEnabled.12", ".potx" => "application/vnd.openxmlformats-officedocument.presentationml.template", ".ppa" => "application/vnd.ms-powerpoint", ".ppam" => "application/vnd.ms-powerpoint.addin.macroEnabled.12", ".ppd" => "application/vnd.cups-ppd", ".ppm" => "image/x-portable-pixmap", ".pps" => "application/vnd.ms-powerpoint", ".ppsm" => "application/vnd.ms-powerpoint.slideshow.macroEnabled.12", ".ppsx" => "application/vnd.openxmlformats-officedocument.presentationml.slideshow", ".ppt" => "application/vnd.ms-powerpoint", ".pptm" => "application/vnd.ms-powerpoint.presentation.macroEnabled.12", ".pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation", ".prc" => "application/vnd.palm", ".pre" => "application/vnd.lotus-freelance", ".prf" => "application/pics-rules", ".ps" => "application/postscript", ".psb" => "application/vnd.3gpp.pic-bw-small", ".psd" => "image/vnd.adobe.photoshop", ".ptid" => "application/vnd.pvi.ptid1", ".pub" => "application/x-mspublisher", ".pvb" => "application/vnd.3gpp.pic-bw-var", ".pwn" => "application/vnd.3m.post-it-notes", ".py" => "text/x-script.python", ".pya" => "audio/vnd.ms-playready.media.pya", ".pyv" => "video/vnd.ms-playready.media.pyv", ".qam" => "application/vnd.epson.quickanime", ".qbo" => "application/vnd.intu.qbo", ".qfx" => "application/vnd.intu.qfx", ".qps" => "application/vnd.publishare-delta-tree", ".qt" => "video/quicktime", ".qtif" => "image/x-quicktime", ".qxd" => "application/vnd.quark.quarkxpress", ".ra" => "audio/x-pn-realaudio", ".rake" => "text/x-script.ruby", ".ram" => "audio/x-pn-realaudio", ".rar" => "application/x-rar-compressed", ".ras" => "image/x-cmu-raster", ".rb" => "text/x-script.ruby", ".rcprofile" => "application/vnd.ipunplugged.rcprofile", ".rdf" => "application/rdf+xml", ".rdz" => "application/vnd.data-vision.rdz", ".rep" => "application/vnd.businessobjects", ".rgb" => "image/x-rgb", ".rif" => "application/reginfo+xml", ".rl" => "application/resource-lists+xml", ".rlc" => "image/vnd.fujixerox.edmics-rlc", ".rld" => "application/resource-lists-diff+xml", ".rm" => "application/vnd.rn-realmedia", ".rmp" => "audio/x-pn-realaudio-plugin", ".rms" => "application/vnd.jcp.javame.midlet-rms", ".rnc" => "application/relax-ng-compact-syntax", ".roff" => "text/troff", ".rpm" => "application/x-redhat-package-manager", ".rpss" => "application/vnd.nokia.radio-presets", ".rpst" => "application/vnd.nokia.radio-preset", ".rq" => "application/sparql-query", ".rs" => "application/rls-services+xml", ".rsd" => "application/rsd+xml", ".rss" => "application/rss+xml", ".rtf" => "application/rtf", ".rtx" => "text/richtext", ".ru" => "text/x-script.ruby", ".s" => "text/x-asm", ".saf" => "application/vnd.yamaha.smaf-audio", ".sbml" => "application/sbml+xml", ".sc" => "application/vnd.ibm.secure-container", ".scd" => "application/x-msschedule", ".scm" => "application/vnd.lotus-screencam", ".scq" => "application/scvp-cv-request", ".scs" => "application/scvp-cv-response", ".sdkm" => "application/vnd.solent.sdkm+xml", ".sdp" => "application/sdp", ".see" => "application/vnd.seemail", ".sema" => "application/vnd.sema", ".semd" => "application/vnd.semd", ".semf" => "application/vnd.semf", ".setpay" => "application/set-payment-initiation", ".setreg" => "application/set-registration-initiation", ".sfd" => "application/vnd.hydrostatix.sof-data", ".sfs" => "application/vnd.spotfire.sfs", ".sgm" => "text/sgml", ".sgml" => "text/sgml", ".sh" => "application/x-sh", ".shar" => "application/x-shar", ".shf" => "application/shf+xml", ".sig" => "application/pgp-signature", ".sit" => "application/x-stuffit", ".sitx" => "application/x-stuffitx", ".skp" => "application/vnd.koan", ".slt" => "application/vnd.epson.salt", ".smi" => "application/smil+xml", ".snd" => "audio/basic", ".so" => "application/octet-stream", ".spf" => "application/vnd.yamaha.smaf-phrase", ".spl" => "application/x-futuresplash", ".spot" => "text/vnd.in3d.spot", ".spp" => "application/scvp-vp-response", ".spq" => "application/scvp-vp-request", ".src" => "application/x-wais-source", ".srt" => "text/srt", ".srx" => "application/sparql-results+xml", ".sse" => "application/vnd.kodak-descriptor", ".ssf" => "application/vnd.epson.ssf", ".ssml" => "application/ssml+xml", ".stf" => "application/vnd.wt.stf", ".stk" => "application/hyperstudio", ".str" => "application/vnd.pg.format", ".sus" => "application/vnd.sus-calendar", ".sv4cpio" => "application/x-sv4cpio", ".sv4crc" => "application/x-sv4crc", ".svd" => "application/vnd.svd", ".svg" => "image/svg+xml", ".svgz" => "image/svg+xml", ".swf" => "application/x-shockwave-flash", ".swi" => "application/vnd.arastra.swi", ".t" => "text/troff", ".tao" => "application/vnd.tao.intent-module-archive", ".tar" => "application/x-tar", ".tbz" => "application/x-bzip-compressed-tar", ".tcap" => "application/vnd.3gpp2.tcap", ".tcl" => "application/x-tcl", ".tex" => "application/x-tex", ".texi" => "application/x-texinfo", ".texinfo" => "application/x-texinfo", ".text" => "text/plain", ".tif" => "image/tiff", ".tiff" => "image/tiff", ".tmo" => "application/vnd.tmobile-livetv", ".torrent" => "application/x-bittorrent", ".tpl" => "application/vnd.groove-tool-template", ".tpt" => "application/vnd.trid.tpt", ".tr" => "text/troff", ".tra" => "application/vnd.trueapp", ".trm" => "application/x-msterminal", ".ts" => "video/mp2t", ".tsv" => "text/tab-separated-values", ".ttf" => "application/octet-stream", ".twd" => "application/vnd.simtech-mindmapper", ".txd" => "application/vnd.genomatix.tuxedo", ".txf" => "application/vnd.mobius.txf", ".txt" => "text/plain", ".ufd" => "application/vnd.ufdl", ".umj" => "application/vnd.umajin", ".unityweb" => "application/vnd.unity", ".uoml" => "application/vnd.uoml+xml", ".uri" => "text/uri-list", ".ustar" => "application/x-ustar", ".utz" => "application/vnd.uiq.theme", ".uu" => "text/x-uuencode", ".vcd" => "application/x-cdlink", ".vcf" => "text/x-vcard", ".vcg" => "application/vnd.groove-vcard", ".vcs" => "text/x-vcalendar", ".vcx" => "application/vnd.vcx", ".vis" => "application/vnd.visionary", ".viv" => "video/vnd.vivo", ".vrml" => "model/vrml", ".vsd" => "application/vnd.visio", ".vsf" => "application/vnd.vsf", ".vtt" => "text/vtt", ".vtu" => "model/vnd.vtu", ".vxml" => "application/voicexml+xml", ".war" => "application/java-archive", ".wasm" => "application/wasm", ".wav" => "audio/x-wav", ".wax" => "audio/x-ms-wax", ".wbmp" => "image/vnd.wap.wbmp", ".wbs" => "application/vnd.criticaltools.wbs+xml", ".wbxml" => "application/vnd.wap.wbxml", ".webm" => "video/webm", ".webp" => "image/webp", ".wm" => "video/x-ms-wm", ".wma" => "audio/x-ms-wma", ".wmd" => "application/x-ms-wmd", ".wmf" => "application/x-msmetafile", ".wml" => "text/vnd.wap.wml", ".wmlc" => "application/vnd.wap.wmlc", ".wmls" => "text/vnd.wap.wmlscript", ".wmlsc" => "application/vnd.wap.wmlscriptc", ".wmv" => "video/x-ms-wmv", ".wmx" => "video/x-ms-wmx", ".wmz" => "application/x-ms-wmz", ".woff" => "application/font-woff", ".woff2" => "application/font-woff2", ".wpd" => "application/vnd.wordperfect", ".wpl" => "application/vnd.ms-wpl", ".wps" => "application/vnd.ms-works", ".wqd" => "application/vnd.wqd", ".wri" => "application/x-mswrite", ".wrl" => "model/vrml", ".wsdl" => "application/wsdl+xml", ".wspolicy" => "application/wspolicy+xml", ".wtb" => "application/vnd.webturbo", ".wvx" => "video/x-ms-wvx", ".x3d" => "application/vnd.hzn-3d-crossword", ".xar" => "application/vnd.xara", ".xbd" => "application/vnd.fujixerox.docuworks.binder", ".xbm" => "image/x-xbitmap", ".xdm" => "application/vnd.syncml.dm+xml", ".xdp" => "application/vnd.adobe.xdp+xml", ".xdw" => "application/vnd.fujixerox.docuworks", ".xenc" => "application/xenc+xml", ".xer" => "application/patch-ops-error+xml", ".xfdf" => "application/vnd.adobe.xfdf", ".xfdl" => "application/vnd.xfdl", ".xhtml" => "application/xhtml+xml", ".xif" => "image/vnd.xiff", ".xla" => "application/vnd.ms-excel", ".xlam" => "application/vnd.ms-excel.addin.macroEnabled.12", ".xls" => "application/vnd.ms-excel", ".xlsb" => "application/vnd.ms-excel.sheet.binary.macroEnabled.12", ".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ".xlsm" => "application/vnd.ms-excel.sheet.macroEnabled.12", ".xlt" => "application/vnd.ms-excel", ".xltx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.template", ".xml" => "application/xml", ".xo" => "application/vnd.olpc-sugar", ".xop" => "application/xop+xml", ".xpm" => "image/x-xpixmap", ".xpr" => "application/vnd.is-xpr", ".xps" => "application/vnd.ms-xpsdocument", ".xpw" => "application/vnd.intercon.formnet", ".xsl" => "application/xml", ".xslt" => "application/xslt+xml", ".xsm" => "application/vnd.syncml+xml", ".xspf" => "application/xspf+xml", ".xul" => "application/vnd.mozilla.xul+xml", ".xwd" => "image/x-xwindowdump", ".xyz" => "chemical/x-xyz", ".yaml" => "text/yaml", ".yml" => "text/yaml", ".zaz" => "application/vnd.zzazz.deck+xml", ".zip" => "application/zip", ".zmm" => "application/vnd.handheld-entertainment+xml", } end end PK% ]i\"gems/rack-3.0.8/lib/rack/config.rbnu[# frozen_string_literal: true module Rack # Rack::Config modifies the environment using the block given during # initialization. # # Example: # use Rack::Config do |env| # env['my-key'] = 'some-value' # end class Config def initialize(app, &block) @app = app @block = block end def call(env) @block.call(env) @app.call(env) end end end PK% ]Y  #gems/rack-3.0.8/lib/rack/cascade.rbnu[# frozen_string_literal: true require_relative 'constants' module Rack # Rack::Cascade tries a request on several apps, and returns the # first response that is not 404 or 405 (or in a list of configured # status codes). If all applications tried return one of the configured # status codes, return the last response. class Cascade # deprecated, no longer used NotFound = [404, { CONTENT_TYPE => "text/plain" }, []] # An array of applications to try in order. attr_reader :apps # Set the apps to send requests to, and what statuses result in # cascading. Arguments: # # apps: An enumerable of rack applications. # cascade_for: The statuses to use cascading for. If a response is received # from an app, the next app is tried. def initialize(apps, cascade_for = [404, 405]) @apps = [] apps.each { |app| add app } @cascade_for = {} [*cascade_for].each { |status| @cascade_for[status] = true } end # Call each app in order. If the responses uses a status that requires # cascading, try the next app. If all responses require cascading, # return the response from the last app. def call(env) return [404, { CONTENT_TYPE => "text/plain" }, []] if @apps.empty? result = nil last_body = nil @apps.each do |app| # The SPEC says that the body must be closed after it has been iterated # by the server, or if it is replaced by a middleware action. Cascade # replaces the body each time a cascade happens. It is assumed that nil # does not respond to close, otherwise the previous application body # will be closed. The final application body will not be closed, as it # will be passed to the server as a result. last_body.close if last_body.respond_to? :close result = app.call(env) return result unless @cascade_for.include?(result[0].to_i) last_body = result[2] end result end # Append an app to the list of apps to cascade. This app will # be tried last. def add(app) @apps << app end # Whether the given app is one of the apps to cascade to. def include?(app) @apps.include?(app) end alias_method :<<, :add end end PK% ]_l'gems/rack-3.0.8/lib/rack/null_logger.rbnu[# frozen_string_literal: true require_relative 'constants' module Rack class NullLogger def initialize(app) @app = app end def call(env) env[RACK_LOGGER] = self @app.call(env) end def info(progname = nil, &block); end def debug(progname = nil, &block); end def warn(progname = nil, &block); end def error(progname = nil, &block); end def fatal(progname = nil, &block); end def unknown(progname = nil, &block); end def info? ; end def debug? ; end def warn? ; end def error? ; end def fatal? ; end def debug! ; end def error! ; end def fatal! ; end def info! ; end def warn! ; end def level ; end def progname ; end def datetime_format ; end def formatter ; end def sev_threshold ; end def level=(level); end def progname=(progname); end def datetime_format=(datetime_format); end def formatter=(formatter); end def sev_threshold=(sev_threshold); end def close ; end def add(severity, message = nil, progname = nil, &block); end def log(severity, message = nil, progname = nil, &block); end def <<(msg); end def reopen(logdev = nil); end end end PK% ]/gems/ruby-lsapi-5.5/ext/lsapi/.sitearchdir.timenu[PK% ]Y//(gems/ruby-lsapi-5.5/ext/lsapi/lsapilib.hnu[/* Copyright (c) 2002-2018, Lite Speed Technologies Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Lite Speed Technologies Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _LSAPILIB_H_ #define _LSAPILIB_H_ #if defined (c_plusplus) || defined (__cplusplus) extern "C" { #endif #include "lsapidef.h" #include #include #include struct LSAPI_key_value_pair { char * pKey; char * pValue; int keyLen; int valLen; }; struct lsapi_child_status; #define LSAPI_MAX_RESP_HEADERS 1000 typedef struct lsapi_request { int m_fdListen; int m_fd; long m_lLastActive; long m_lReqBegin; char * m_pReqBuf; int m_reqBufSize; char * m_pRespBuf; char * m_pRespBufEnd; char * m_pRespBufPos; char * m_pRespHeaderBuf; char * m_pRespHeaderBufEnd; char * m_pRespHeaderBufPos; struct lsapi_child_status * child_status; struct iovec * m_pIovec; struct iovec * m_pIovecEnd; struct iovec * m_pIovecCur; struct iovec * m_pIovecToWrite; struct lsapi_packet_header * m_respPktHeaderEnd; struct lsapi_req_header * m_pHeader; struct LSAPI_key_value_pair * m_pEnvList; struct LSAPI_key_value_pair * m_pSpecialEnvList; int m_envListSize; int m_specialEnvListSize; struct lsapi_http_header_index * m_pHeaderIndex; struct lsapi_header_offset * m_pUnknownHeader; char * m_pScriptFile; char * m_pScriptName; char * m_pQueryString; char * m_pHttpHeader; char * m_pRequestMethod; int m_totalLen; int m_reqState; off_t m_reqBodyLen; off_t m_reqBodyRead; int m_bufProcessed; int m_bufRead; struct lsapi_packet_header m_respPktHeader[5]; struct lsapi_resp_header m_respHeader; short m_respHeaderLen[LSAPI_MAX_RESP_HEADERS]; void * m_pAppData; }LSAPI_Request; extern LSAPI_Request g_req; /* return: >0 continue, ==0 stop, -1 failed */ typedef int (*LSAPI_CB_EnvHandler )( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ); int LSAPI_Init(void); void LSAPI_Stop(void); int LSAPI_Is_Listen_r( LSAPI_Request * pReq); int LSAPI_InitRequest( LSAPI_Request * pReq, int fd ); int LSAPI_Accept_r( LSAPI_Request * pReq ); void LSAPI_Reset_r( LSAPI_Request * pReq ); int LSAPI_Finish_r( LSAPI_Request * pReq ); int LSAPI_Release_r( LSAPI_Request * pReq ); char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex ); int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); int LSAPI_ForeachEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name ); ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t len ); int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq ); int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF ); int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq ); ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ); ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size ); ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len ); int LSAPI_Flush_r( LSAPI_Request * pReq ); int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len ); int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, const char * pHeaderValue ); int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders, const char * pBody, int bodyLen ); static inline int LSAPI_SetRespStatus_r( LSAPI_Request * pReq, int code ) { if ( !pReq ) return -1; pReq->m_respHeader.m_respInfo.m_status = code; return 0; } static inline int LSAPI_SetAppData_r( LSAPI_Request * pReq, void * data ) { if ( !pReq ) return -1; pReq->m_pAppData = data; return 0; } static inline void * LSAPI_GetAppData_r( LSAPI_Request * pReq ) { if ( !pReq ) return NULL; return pReq->m_pAppData; } static inline char * LSAPI_GetQueryString_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_pQueryString; return NULL; } static inline char * LSAPI_GetScriptFileName_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_pScriptFile; return NULL; } static inline char * LSAPI_GetScriptName_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_pScriptName; return NULL; } static inline char * LSAPI_GetRequestMethod_r( LSAPI_Request * pReq) { if ( pReq ) return pReq->m_pRequestMethod; return NULL; } static inline off_t LSAPI_GetReqBodyLen_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_reqBodyLen; return -1; } static inline off_t LSAPI_GetReqBodyRemain_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_reqBodyLen - pReq->m_reqBodyRead; return -1; } int LSAPI_End_Response_r(LSAPI_Request * pReq); int LSAPI_Is_Listen(void); static inline int LSAPI_Accept( void ) { return LSAPI_Accept_r( &g_req ); } static inline int LSAPI_Finish(void) { return LSAPI_Finish_r( &g_req ); } static inline char * LSAPI_GetHeader( int headerIndex ) { return LSAPI_GetHeader_r( &g_req, headerIndex ); } static inline int LSAPI_ForeachHeader( LSAPI_CB_EnvHandler fn, void * arg ) { return LSAPI_ForeachHeader_r( &g_req, fn, arg ); } static inline int LSAPI_ForeachOrgHeader( LSAPI_CB_EnvHandler fn, void * arg ) { return LSAPI_ForeachOrgHeader_r( &g_req, fn, arg ); } static inline int LSAPI_ForeachEnv( LSAPI_CB_EnvHandler fn, void * arg ) { return LSAPI_ForeachEnv_r( &g_req, fn, arg ); } static inline int LSAPI_ForeachSpecialEnv( LSAPI_CB_EnvHandler fn, void * arg ) { return LSAPI_ForeachSpecialEnv_r( &g_req, fn, arg ); } static inline char * LSAPI_GetEnv( const char * name ) { return LSAPI_GetEnv_r( &g_req, name ); } static inline char * LSAPI_GetQueryString(void) { return LSAPI_GetQueryString_r( &g_req ); } static inline char * LSAPI_GetScriptFileName(void) { return LSAPI_GetScriptFileName_r( &g_req ); } static inline char * LSAPI_GetScriptName(void) { return LSAPI_GetScriptName_r( &g_req ); } static inline char * LSAPI_GetRequestMethod(void) { return LSAPI_GetRequestMethod_r( &g_req ); } static inline off_t LSAPI_GetReqBodyLen(void) { return LSAPI_GetReqBodyLen_r( &g_req ); } static inline off_t LSAPI_GetReqBodyRemain(void) { return LSAPI_GetReqBodyRemain_r( &g_req ); } static inline ssize_t LSAPI_ReadReqBody( char * pBuf, size_t len ) { return LSAPI_ReadReqBody_r( &g_req, pBuf, len ); } static inline int LSAPI_ReqBodyGetChar(void) { return LSAPI_ReqBodyGetChar_r( &g_req ); } static inline int LSAPI_ReqBodyGetLine( char * pBuf, int len, int *getLF ) { return LSAPI_ReqBodyGetLine_r( &g_req, pBuf, len, getLF ); } static inline int LSAPI_FinalizeRespHeaders(void) { return LSAPI_FinalizeRespHeaders_r( &g_req ); } static inline ssize_t LSAPI_Write( const char * pBuf, ssize_t len ) { return LSAPI_Write_r( &g_req, pBuf, len ); } static inline ssize_t LSAPI_sendfile( int fdIn, off_t* off, size_t size ) { return LSAPI_sendfile_r(&g_req, fdIn, off, size ); } static inline ssize_t LSAPI_Write_Stderr( const char * pBuf, ssize_t len ) { return LSAPI_Write_Stderr_r( &g_req, pBuf, len ); } static inline int LSAPI_Flush(void) { return LSAPI_Flush_r( &g_req ); } static inline int LSAPI_AppendRespHeader( char * pBuf, int len ) { return LSAPI_AppendRespHeader_r( &g_req, pBuf, len ); } static inline int LSAPI_SetRespStatus( int code ) { return LSAPI_SetRespStatus_r( &g_req, code ); } static inline int LSAPI_ErrResponse( int code, const char ** pRespHeaders, const char * pBody, int bodyLen ) { return LSAPI_ErrResponse_r( &g_req, code, pRespHeaders, pBody, bodyLen ); } static inline int LSAPI_End_Response(void) { return LSAPI_End_Response_r( &g_req ); } int LSAPI_IsRunning(void); int LSAPI_CreateListenSock( const char * pBind, int backlog ); typedef int (*fn_select_t)( int, fd_set *, fd_set *, fd_set *, struct timeval * ); int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ); void LSAPI_Set_Server_fd( int fd ); int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ); void LSAPI_No_Check_ppid(void); void LSAPI_Set_Max_Reqs( int reqs ); void LSAPI_Set_Max_Idle( int secs ); void LSAPI_Set_Max_Children( int maxChildren ); void LSAPI_Set_Max_Idle_Children( int maxIdleChld ); void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle ); void LSAPI_Set_Max_Process_Time( int secs ); int LSAPI_Init_Env_Parameters( fn_select_t fp ); void LSAPI_Set_Slow_Req_Msecs( int msecs ); int LSAPI_Get_Slow_Req_Msecs(void); int LSAPI_is_suEXEC_Daemon(void); int LSAPI_Set_Restored_Parent_Pid(int pid); typedef void (*LSAPI_On_Timer_pf)(int *forked_child_pid); void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf); int LSAPI_Inc_Req_Processed(int cnt); int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq); int LSAPI_Postfork_Child(LSAPI_Request * pReq); int LSAPI_Postfork_Parent(LSAPI_Request * pReq); #define LSAPI_LOG_LEVEL_BITS 0xff #define LSAPI_LOG_FLAG_NONE 0 #define LSAPI_LOG_FLAG_DEBUG 1 #define LSAPI_LOG_FLAG_INFO 2 #define LSAPI_LOG_FLAG_NOTICE 3 #define LSAPI_LOG_FLAG_WARN 4 #define LSAPI_LOG_FLAG_ERROR 5 #define LSAPI_LOG_FLAG_CRIT 6 #define LSAPI_LOG_FLAG_FATAL 7 #define LSAPI_LOG_TIMESTAMP_BITS (0xff00) #define LSAPI_LOG_TIMESTAMP_FULL (0x100) #define LSAPI_LOG_TIMESTAMP_HMS (0x200) #define LSAPI_LOG_TIMESTAMP_STDERR (0x400) #define LSAPI_LOG_PID (0x10000) void LSAPI_Log(int flag, const char * fmt, ...) #if __GNUC__ __attribute__((format(printf, 2, 3))) #endif ; #if defined (c_plusplus) || defined (__cplusplus) } #endif #endif PK% ]7Zw(gems/ruby-lsapi-5.5/ext/lsapi/extconf.rbnu[require 'mkmf' dir_config( 'lsapi' ) if ( have_library( "socket" )) have_library( "nsl" ) end if RUBY_VERSION =~ /1.9/ then $CPPFLAGS += " -DRUBY_19" end if RUBY_VERSION =~ /2/ then $CPPFLAGS += " -DRUBY_2" end create_makefile( "lsapi" ) PK% ].ZZ&gems/ruby-lsapi-5.5/ext/lsapi/lsruby.cnu[ #include "ruby.h" #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 #include "util.h" #else #include #include #endif #include "lsapilib.h" #include #include #include #include #include #include #include #include #include #ifndef RUBY_API_VERSION_CODE #define RUBY_API_VERSION_CODE (RUBY_API_VERSION_MAJOR*10000+RUBY_API_VERSION_MINOR*100+RUBY_API_VERSION_TEENY) #endif /* RUBY_EXTERN VALUE ruby_errinfo; */ RUBY_EXTERN VALUE rb_stdin; RUBY_EXTERN VALUE rb_stdout; #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 RUBY_EXTERN VALUE rb_defout; #endif static VALUE orig_stdin; static VALUE orig_stdout; static VALUE orig_stderr; #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 static VALUE orig_defout; #endif static VALUE orig_env; static VALUE env_copy; static VALUE lsapi_env; static int MAX_BODYBUF_LENGTH = (10 * 1024 * 1024); /* static VALUE lsapi_objrefs; */ typedef struct lsapi_data { LSAPI_Request * req; VALUE env; ssize_t (* fn_write)( LSAPI_Request *, const char * , size_t ); }lsapi_data; static VALUE cLSAPI; static VALUE s_req = Qnil; static lsapi_data * s_req_data; static VALUE s_req_stderr = Qnil; static lsapi_data * s_stderr_data; static pid_t s_pid = 0; typedef struct lsapi_body { char *bodyBuf; //we put small one into memory, otherwise, into a memory mapping file, and we still use the bodyBuf to access this mapping int bodyLen; //expected length got form content-length int bodyCurrentLen; //current length by read() readBodyToReqBuf int curPos; }lsapi_body; static lsapi_body s_body; static char sTempFile[1024] = {0}; /* * static void lsapi_ruby_setenv(const char *name, const char *value) * { * if (!name) return; * * if (value && *value) * ruby_setenv(name, value); * else * ruby_unsetenv(name); } * * */ static void lsapi_mark( lsapi_data * data ) { rb_gc_mark( data->env ); } /* * static void lsapi_free_data( lsapi_data * data ) * { * free( data ); } * * */ static int add_env_rails( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ) { char * p; int len; /* Fixup some environment variables for rails */ switch( *pKey ) { case 'Q': if ( strcmp( pKey, "QUERY_STRING" ) == 0 ) { if ( !*pValue ) return 1; } break; case 'R': if (( *(pKey+8) == 'U' )&&( strcmp( pKey, "REQUEST_URI" ) == 0 )) { p = strchr( pValue, '?' ); if ( p ) { len = valLen - ( p - pValue ) - 1; /* * valLen = p - pValue; *p++ = 0; */ } else { p = (char *)pValue + valLen; len = 0; } rb_hash_aset( lsapi_env,rb_tainted_str_new("PATH_INFO", 9), rb_tainted_str_new(pValue, p - pValue)); rb_hash_aset( lsapi_env,rb_tainted_str_new("REQUEST_PATH", 12), rb_tainted_str_new(pValue, p - pValue)); if ( *p == '?' ) ++p; rb_hash_aset( lsapi_env,rb_tainted_str_new("QUERY_STRING", 12), rb_tainted_str_new(p, len)); } break; case 'S': if ( strcmp( pKey, "SCRIPT_NAME" ) == 0 ) { pValue = "/"; valLen = 1; } break; case 'P': if ( strcmp( pKey, "PATH_INFO" ) == 0 ) return 1; default: break; } /* lsapi_ruby_setenv(pKey, pValue ); */ rb_hash_aset( lsapi_env,rb_tainted_str_new(pKey, keyLen), rb_tainted_str_new(pValue, valLen)); return 1; } static int add_env_no_fix( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ) { rb_hash_aset( lsapi_env,rb_tainted_str_new(pKey, keyLen), rb_tainted_str_new(pValue, valLen)); return 1; } typedef int (*fn_add_env)( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ); fn_add_env s_fn_add_env = add_env_no_fix; static void clear_env() { /* rb_funcall( lsapi_env, rb_intern( "clear" ), 0 ); */ rb_funcall( lsapi_env, rb_intern( "replace" ), 1, env_copy ); } static void setup_cgi_env( lsapi_data * data ) { clear_env(); LSAPI_ForeachHeader_r( data->req, s_fn_add_env, data ); LSAPI_ForeachEnv_r( data->req, s_fn_add_env, data ); } static VALUE lsapi_s_accept( VALUE self ) { int pid; if ( LSAPI_Prefork_Accept_r( &g_req ) == -1 ) return Qnil; else { if (s_body.bodyBuf != NULL) free (s_body.bodyBuf); s_body.bodyBuf = NULL; s_body.bodyLen = -1; s_body.bodyCurrentLen = 0; s_body.curPos = 0; pid = getpid(); if ( pid != s_pid ) { s_pid = pid; rb_funcall( Qnil, rb_intern( "srand" ), 0 ); } setup_cgi_env( s_req_data ); return s_req; } } static VALUE lsapi_s_accept_new_conn(VALUE self) { if (LSAPI_Accept_Before_Fork(&g_req) == -1 ) return Qnil; else return s_req; } static VALUE lsapi_s_postfork_child(VALUE self) { LSAPI_Postfork_Child(&g_req); return s_req; } static VALUE lsapi_s_postfork_parent(VALUE self) { LSAPI_Postfork_Parent(&g_req); return s_req; } /* * static int chdir_file( const char * pFile ) * { * char * p = strrchr( pFile, '/' ); * int ret; * if ( !p ) * return -1; *p = 0; ret = chdir( pFile ); *p = '/'; return ret; } */ static VALUE lsapi_eval_string_wrap(VALUE self, VALUE str) { #if RUBY_API_VERSION_CODE < 20700 if (rb_safe_level() >= 4) { Check_Type(str, T_STRING); } else #endif { SafeStringValue(str); } return rb_eval_string_wrap(StringValuePtr(str), NULL); } static VALUE lsapi_process( VALUE self ) { /* lsapi_data *data; const char * pScriptPath; Data_Get_Struct(self,lsapi_data, data); pScriptPath = LSAPI_GetScriptFileName_r( data->req ); */ /* * if ( chdir_file( pScriptPath ) == -1 ) * { * lsapi_send_error( 404 ); * } * rb_load_file( pScriptPath ); */ return Qnil; } static VALUE lsapi_putc(VALUE self, VALUE c) { char ch = NUM2CHR(c); lsapi_data *data; Data_Get_Struct(self,lsapi_data, data); if ( (*data->fn_write)( data->req, &ch, 1 ) == 1 ) return c; else return INT2NUM( EOF ); } static VALUE lsapi_write( VALUE self, VALUE str ) { lsapi_data *data; int len; Data_Get_Struct(self,lsapi_data, data); /* len = LSAPI_Write_r( data->req, RSTRING_PTR(str), RSTRING_LEN(str) ); */ if (TYPE(str) != T_STRING) str = rb_obj_as_string(str); len = (*data->fn_write)( data->req, RSTRING_PTR(str), RSTRING_LEN(str) ); return INT2NUM( len ); } static VALUE lsapi_print( int argc, VALUE *argv, VALUE out ) { int i; VALUE line; /* if no argument given, print `$_' */ if (argc == 0) { argc = 1; line = rb_lastline_get(); argv = &line; } for (i = 0; i0) { lsapi_write(out, rb_output_fs); } switch (TYPE(argv[i])) { case T_NIL: lsapi_write(out, rb_str_new2("nil")); break; default: lsapi_write(out, argv[i]); break; } } if (!NIL_P(rb_output_rs)) { lsapi_write(out, rb_output_rs); } return Qnil; } static VALUE lsapi_printf(int argc, VALUE *argv, VALUE out) { lsapi_write(out, rb_f_sprintf(argc, argv)); return Qnil; } static VALUE lsapi_puts _((int, VALUE*, VALUE)); #if RUBY_API_VERSION_CODE >= 10900 static VALUE lsapi_puts_ary(VALUE ary, VALUE out, int recur ) { VALUE tmp; long i; if (recur) { tmp = rb_str_new2("[...]"); rb_io_puts(1, &tmp, out); return Qnil; } for (i=0; i= 10900 rb_exec_recursive(lsapi_puts_ary, argv[i], out); #else rb_protect_inspect(lsapi_puts_ary, argv[i], out); #endif continue; default: line = argv[i]; break; } line = rb_obj_as_string(line); lsapi_write(out, line); if (*( RSTRING_PTR(line) + RSTRING_LEN(line) - 1 ) != '\n') { lsapi_write(out, rb_default_rs); } } return Qnil; } static VALUE lsapi_addstr(VALUE out, VALUE str) { lsapi_write(out, str); return out; } static VALUE lsapi_flush( VALUE self ) { /* * lsapi_data *data; * Data_Get_Struct(self,lsapi_data, data); */ LSAPI_Flush_r( &g_req ); return Qnil; } static VALUE lsapi_getc( VALUE self ) { int ch; /* * lsapi_data *data; * Data_Get_Struct(self,lsapi_data, data); */ #if RUBY_API_VERSION_CODE < 20700 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) { rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO"); } #endif ch = LSAPI_ReqBodyGetChar_r( &g_req ); if ( ch == EOF ) return Qnil; return INT2NUM( ch ); } static inline int isBodyWriteToFile() { return ((s_body.bodyLen >= MAX_BODYBUF_LENGTH)? (1): (0)); } //create a temp file and open it, if failed, fd = -1 static inline int createTempFile() { int fd = -1; char *sfn = strdup(sTempFile); if ((fd = mkstemp(sfn)) == -1) { fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); } else unlink(sfn); free(sfn); return fd; } //return 1 if error occured! //if already created, always OK (0) static int createBodyBuf() { int fd = -1; if (s_body.bodyLen == -1) { s_body.bodyLen = LSAPI_GetReqBodyLen_r(&g_req); //Error if get a zeor length, should not happen if (s_body.bodyLen < 0) { //Wrong bode length will be treated as 0 s_body.bodyLen = 0; } if (s_body.bodyLen > 0) { if (isBodyWriteToFile()) { //create file mapping fd = createTempFile(); if (fd == -1) { return 1; } if (ftruncate(fd, s_body.bodyLen) == 0) { perror("ftruncate() failed. \n"); close(fd); return 1; } s_body.bodyBuf = mmap(NULL, s_body.bodyLen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (s_body.bodyBuf == MAP_FAILED) { perror("File mapping failed. \n"); close(fd); return 1; } close(fd); //close since needn't it anymore } else { s_body.bodyBuf = (char *)calloc(s_body.bodyLen, sizeof(char)); if (s_body.bodyBuf == NULL) { perror("Memory calloc error"); return 1; } } } } return 0; } static inline int isAllBodyRead() { return (s_body.bodyCurrentLen < s_body.bodyLen)? 0 : 1; } static inline int isEofBodyBuf() { return (s_body.curPos < s_body.bodyLen) ? 0 : 1; } //try to read length as times pagesize (such as 8KB * N) static int readBodyBuf(const int needRead) { const int blockSize = 8192; char *buff = s_body.bodyBuf + s_body.bodyCurrentLen; int nRead; int readMore = (needRead + blockSize -1) / blockSize * blockSize; int remain = LSAPI_GetReqBodyRemain_r( &g_req ); //Only when not enough left, needReadChange will be changed!!! if (remain < readMore) readMore = remain; if ( readMore <= 0 ) return 0; nRead = LSAPI_ReadReqBody_r(&g_req, buff, readMore); if ( nRead > 0 ) s_body.bodyCurrentLen += nRead; return nRead; } static VALUE lsapi_gets( VALUE self ) { VALUE str; const int blkSize = 4096; int n; char *p = NULL; #if RUBY_API_VERSION_CODE < 20700 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) { rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO"); } #endif if (createBodyBuf() == 1) { return Qnil; } //comment: while((p = memmem(s_body.bodyBuf + s_body.curPos, s_body.bodyCurrentLen - s_body.curPos, "\n", 1)) == NULL) { if (isAllBodyRead() == 1) break; //read one page and check, then reply readBodyBuf(blkSize); } p = memmem(s_body.bodyBuf + s_body.curPos, s_body.bodyCurrentLen - s_body.curPos, "\n", 1); if (p != NULL) n = p - s_body.bodyBuf - s_body.curPos + 1; else n = s_body.bodyCurrentLen - s_body.curPos; str = rb_str_buf_new( n ); #if RUBY_API_VERSION_CODE < 20700 OBJ_TAINT(str); #endif if (n > 0) { rb_str_buf_cat( str, s_body.bodyBuf + s_body.curPos, n ); s_body.curPos += n; } return str; } static VALUE lsapi_read(int argc, VALUE *argv, VALUE self) { VALUE str; int n; int needRead; int nRead; #if RUBY_API_VERSION_CODE < 20700 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) { rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO"); } #endif if (createBodyBuf() == 1) { return Qnil; } //we need to consider these 4 cases: //1, need all data since argc == 0, we may have all data 2, or not //3, need a length of data (argv >= 1), we may have enough data already read, 4, or not if (argc == 0) n = s_body.bodyLen - s_body.curPos; else { n = NUM2INT(argv[0]); //request that length from currentpos if (n < 0) return Qnil; if (n > s_body.bodyLen - s_body.curPos) n = s_body.bodyLen - s_body.curPos; } needRead = s_body.curPos + n - s_body.bodyCurrentLen; if (needRead < 0) needRead = 0; str = rb_str_buf_new( n ); #if RUBY_API_VERSION_CODE < 20700 OBJ_TAINT(str); #endif if (n == 0) return str; //copy already have part first if (n - needRead != 0) { rb_str_buf_cat( str, s_body.bodyBuf + s_body.curPos, n - needRead); s_body.curPos += (n - needRead); } if (needRead > 0) { //try to read needRead, but may be less (changed) when read the end of the data nRead = readBodyBuf(needRead); if (nRead > 0) { n = ((nRead < needRead) ? nRead : needRead); rb_str_buf_cat( str, s_body.bodyBuf + s_body.curPos, n ); s_body.curPos += n; } } return str; } static VALUE lsapi_rewind(VALUE self) { s_body.curPos = 0; return self; } static VALUE lsapi_each(VALUE self) { VALUE str; lsapi_rewind(self); while(isEofBodyBuf() != 1) { str = lsapi_gets(self); rb_yield(str); } return self; } static VALUE lsapi_eof(VALUE self) { return (LSAPI_GetReqBodyRemain_r( &g_req ) <= 0) ? Qtrue : Qfalse; } static VALUE lsapi_binmode(VALUE self) { return self; } static VALUE lsapi_isatty(VALUE self) { return Qfalse; } static VALUE lsapi_sync(VALUE self) { return Qfalse; } static VALUE lsapi_setsync(VALUE self,VALUE sync) { return Qfalse; } static VALUE lsapi_close(VALUE self) { LSAPI_Flush_r( &g_req ); if (isBodyWriteToFile()) { //msync(s_body.bodyBuf, s_body.bodyLen, MS_SYNC); //sleep(5); munmap(s_body.bodyBuf, s_body.bodyLen); } else free(s_body.bodyBuf); s_body.bodyBuf = NULL; s_body.bodyLen = -1; s_body.bodyCurrentLen = 0; s_body.curPos = 0; //Should the temp be deleted here?! return Qnil; } static VALUE lsapi_reopen( int argc, VALUE *argv, VALUE self) { VALUE orig_verbose; if ( self == s_req_stderr ) { /* constant silence hack */ orig_verbose = (VALUE)ruby_verbose; ruby_verbose = Qnil; rb_define_global_const("STDERR", orig_stderr); ruby_verbose = (VALUE)orig_verbose; return rb_funcall2( orig_stderr, rb_intern( "reopen" ), argc, argv ); } return self; } static void readMaxBodyBufLength() { int n; const char *p = getenv( "LSAPI_MAX_BODYBUF_LENGTH" ); if ( p ) { n = atoi( p ); if (n > 0) { if (strstr(p, "M") || strstr(p, "m")) MAX_BODYBUF_LENGTH = n * 1024 * 1024; else if (strstr(p, "K") || strstr(p, "k")) MAX_BODYBUF_LENGTH = n * 1024; else MAX_BODYBUF_LENGTH = n; } } } static void readTempFileTemplate() { const char *p = getenv( "LSAPI_TEMPFILE" ); if (p == NULL || strlen(p) > 1024 - 7) p = "/tmp/lsapi.XXXXXX"; strcpy(sTempFile, p); if (strlen(p) <= 6 || strcmp(p + (strlen(p) - 6), "XXXXXX") != 0) strcat(sTempFile, ".XXXXXX"); } static void initBodyBuf() { s_body.bodyBuf = NULL; s_body.bodyLen = -1; s_body.bodyCurrentLen = 0; s_body.curPos = 0; } void Init_lsapi() { VALUE orig_verbose; char * p; int prefork = 0; LSAPI_Init(); initBodyBuf(); readMaxBodyBufLength(); readTempFileTemplate(); p = getenv("LSAPI_CHILDREN"); if (p && atoi(p) > 1) prefork = 1; #ifdef rb_thread_select LSAPI_Init_Env_Parameters( rb_thread_select ); #else LSAPI_Init_Env_Parameters( select ); #endif s_pid = getpid(); p = getenv( "RACK_ROOT" ); if ( p ) { if ( chdir( p ) == -1 ) perror( "chdir()" ); } if ( p || getenv( "RACK_ENV" ) ) s_fn_add_env = add_env_rails; orig_stdin = rb_stdin; orig_stdout = rb_stdout; orig_stderr = rb_stderr; #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 orig_defout = rb_defout; #endif orig_env = rb_const_get( rb_cObject, rb_intern("ENV") ); env_copy = rb_funcall( orig_env, rb_intern( "to_hash" ), 0 ); /* tell the garbage collector it is a global variable, do not recycle it. */ rb_global_variable(&env_copy); rb_hash_aset( env_copy,rb_tainted_str_new("GATEWAY_Irewindable_input.rbNTERFACE", 17), rb_tainted_str_new("CGI/1.2", 7)); rb_define_global_function("eval_string_wrap", lsapi_eval_string_wrap, 1); cLSAPI = rb_define_class("LSAPI", rb_cObject); rb_define_singleton_method(cLSAPI, "accept", lsapi_s_accept, 0); if (prefork) { rb_define_singleton_method(cLSAPI, "accept_new_connection", lsapi_s_accept_new_conn, 0); rb_define_singleton_method(cLSAPI, "postfork_child", lsapi_s_postfork_child, 0); rb_define_singleton_method(cLSAPI, "postfork_parent", lsapi_s_postfork_parent, 0); } rb_define_method(cLSAPI, "process", lsapi_process, 0 ); /* rb_define_method(cLSAPI, "initialize", lsapi_initialize, 0); */ rb_define_method(cLSAPI, "putc", lsapi_putc, 1); rb_define_method(cLSAPI, "write", lsapi_write, 1); rb_define_method(cLSAPI, "print", lsapi_print, -1); rb_define_method(cLSAPI, "printf", lsapi_printf, -1); rb_define_method(cLSAPI, "puts", lsapi_puts, -1); rb_define_method(cLSAPI, "<<", lsapi_addstr, 1); rb_define_method(cLSAPI, "flush", lsapi_flush, 0); rb_define_method(cLSAPI, "getc", lsapi_getc, 0); /* rb_define_method(cLSAPI, "ungetc", lsapi_ungetc, 1); */ rb_define_method(cLSAPI, "gets", lsapi_gets, 0); //TEST: adding readline function to make irb happy? /*rb_define_method(cLSAPI, "readline", lsapi_gets, 0); */ rb_define_method(cLSAPI, "read", lsapi_read, -1); rb_define_method(cLSAPI, "rewind", lsapi_rewind, 0); rb_define_method(cLSAPI, "each", lsapi_each, 0); rb_define_method(cLSAPI, "eof", lsapi_eof, 0); rb_define_method(cLSAPI, "eof?", lsapi_eof, 0); rb_define_method(cLSAPI, "close", lsapi_close, 0); /* rb_define_method(cLSAPI, "closed?", lsapi_closed, 0); */ rb_define_method(cLSAPI, "binmode", lsapi_binmode, 0); rb_define_method(cLSAPI, "isatty", lsapi_isatty, 0); rb_define_method(cLSAPI, "tty?", lsapi_isatty, 0); rb_define_method(cLSAPI, "sync", lsapi_sync, 0); rb_define_method(cLSAPI, "sync=", lsapi_setsync, 1); rb_define_method(cLSAPI, "reopen", lsapi_reopen, -1 ); s_req = Data_Make_Struct( cLSAPI, lsapi_data, lsapi_mark, free, s_req_data ); s_req_data->req = &g_req; s_req_data->fn_write = LSAPI_Write_r; rb_stdin = rb_stdout = s_req; #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 rb_defout = s_req; #endif rb_global_variable(&s_req ); s_req_stderr = Data_Make_Struct( cLSAPI, lsapi_data, lsapi_mark, free, s_stderr_data ); s_stderr_data->req = &g_req; s_stderr_data->fn_write = LSAPI_Write_Stderr_r; rb_stderr = s_req_stderr; rb_global_variable(&s_req_stderr ); /* constant silence hack */ orig_verbose = (VALUE)ruby_verbose; ruby_verbose = Qnil; lsapi_env = rb_hash_new(); clear_env(); /* redefine ENV using a hash table, should be faster than char **environment */ rb_define_global_const("ENV", lsapi_env); rb_define_global_const("STDERR", rb_stderr); ruby_verbose = (VALUE)orig_verbose; return; } PK% ]W q,,(gems/ruby-lsapi-5.5/ext/lsapi/lsapidef.hnu[/* Copyright (c) 2002-2018, Lite Speed Technologies Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Lite Speed Technologies Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _LSAPIDEF_H_ #define _LSAPIDEF_H_ #include #if defined (c_plusplus) || defined (__cplusplus) extern "C" { #endif enum { H_ACCEPT = 0, H_ACC_CHARSET, H_ACC_ENCODING, H_ACC_LANG, H_AUTHORIZATION, H_CONNECTION, H_CONTENT_TYPE, H_CONTENT_LENGTH, H_COOKIE, H_COOKIE2, H_HOST, H_PRAGMA, H_REFERER, H_USERAGENT, H_CACHE_CTRL, H_IF_MODIFIED_SINCE, H_IF_MATCH, H_IF_NO_MATCH, H_IF_RANGE, H_IF_UNMOD_SINCE, H_KEEP_ALIVE, H_RANGE, H_X_FORWARDED_FOR, H_VIA, H_TRANSFER_ENCODING }; #define LSAPI_SOCK_FILENO 0 #define LSAPI_VERSION_B0 'L' #define LSAPI_VERSION_B1 'S' /* Values for m_flag in lsapi_packet_header */ #define LSAPI_ENDIAN_LITTLE 0 #define LSAPI_ENDIAN_BIG 1 #define LSAPI_ENDIAN_BIT 1 #if defined(__i386__)||defined( __x86_64 )||defined( __x86_64__ ) #define LSAPI_ENDIAN LSAPI_ENDIAN_LITTLE #else #define LSAPI_ENDIAN LSAPI_ENDIAN_BIG #endif /* Values for m_type in lsapi_packet_header */ #define LSAPI_BEGIN_REQUEST 1 #define LSAPI_ABORT_REQUEST 2 #define LSAPI_RESP_HEADER 3 #define LSAPI_RESP_STREAM 4 #define LSAPI_RESP_END 5 #define LSAPI_STDERR_STREAM 6 #define LSAPI_REQ_RECEIVED 7 #define LSAPI_CONN_CLOSE 8 #define LSAPI_INTERNAL_ERROR 9 #define LSAPI_MAX_HEADER_LEN 65535 #define LSAPI_MAX_DATA_PACKET_LEN 16384 #define LSAPI_RESP_HTTP_HEADER_MAX 32768 #define LSAPI_PACKET_HEADER_LEN 8 struct lsapi_packet_header { char m_versionB0; /* LSAPI protocol version */ char m_versionB1; char m_type; char m_flag; union { int32_t m_iLen; /* include this header */ char m_bytes[4]; }m_packetLen; }; /* LSAPI request header packet 1. struct lsapi_req_header 2. struct lsapi_http_header_index 3. lsapi_header_offset * unknownHeaders 4. org http request header 5. request body if available */ struct lsapi_req_header { struct lsapi_packet_header m_pktHeader; int32_t m_httpHeaderLen; int32_t m_reqBodyLen; int32_t m_scriptFileOff; /* path to the script file. */ int32_t m_scriptNameOff; /* decrypted URI, without pathinfo, */ int32_t m_queryStringOff; /* Query string inside env */ int32_t m_requestMethodOff; int32_t m_cntUnknownHeaders; int32_t m_cntEnv; int32_t m_cntSpecialEnv; } ; struct lsapi_http_header_index { uint16_t m_headerLen[H_TRANSFER_ENCODING+1]; int32_t m_headerOff[H_TRANSFER_ENCODING+1]; } ; struct lsapi_header_offset { int32_t nameOff; int32_t nameLen; int32_t valueOff; int32_t valueLen; } ; struct lsapi_resp_info { int32_t m_cntHeaders; int32_t m_status; }; struct lsapi_resp_header { struct lsapi_packet_header m_pktHeader; struct lsapi_resp_info m_respInfo; }; #if defined (c_plusplus) || defined (__cplusplus) } #endif #endif PK% ]T(((gems/ruby-lsapi-5.5/ext/lsapi/lsapilib.onu[ELF>@@=< 02/3.4-5ff.ÐHGH+FHcAVIH@AUATL$USHtQHHtIHIL9r 0HI9v'KHSMsH;Յ[]A\A]A^[D]A\A]A^øff.f=DÐO AWDD_AVAUATUSD6^nAxj׋G3G D!3G V\$ЋW^$DD1\$!3WAʋN Fp $E‰L$A1A1DD^ !D1G;νD\$DEDVDT$A!A1EE|A 1AD!E1DD*ƇGD1D!A1A1DDN DL$E F0D!DnA1D1DGFEDf Dd$D^(A!A1EEؘiA 1AD!1DDDʋ^0D1D!A1DE [D 1!D1DDN,A1DL$G\EA!Df8A1ED"kA 1AD!1DDN4EqDD1!1DE CyD 1!D1DDV<1G!I!1DDD$ Eb%1!1DDD$E@@1!1DDD$ EQZ^&1!1DE6Ƕ1!1DD]/։ 1!1DESD1!1DE ؉ 1!1DDD$E01!1DDD$ E!1!1DE7É1!1DDD$ E 1!1DDD$A0ZEAA1A!A1AA㩉A AD1!1t$DD1!A ogD1 1D!FL*1DD$Ή1AA!B9A1DD$A AD1D$qDD11‹D$ 0"amD1G 81Ɖ11DDD$ ED꾤11DDD$AKAA1A5`KA1AЉApA 1AD1D1D1A ~(D 1G'111DDD$ A0AA1A1AЋT$A2A1D1֋T$ 9ىDD11D11C|A A1A1AD$A0eVĉA1D1AD")Dt$ D D1A *CDG# 1  1DD9Ή 1DDY[e\$  1DE Dt$ щ1DE3}D\$  1DDD$E] 1DEO~oA AD 1DE ,DT$ A1ADE6CDt$ AN 1A~SADEAA A1A5:ADA AD 1Љ3*\$D D1DFӆ[ ]A\A]A^ 1։ 1DƉA4A_ OW GOW ATI1USHdH%(H$1HHH<$t)H$dH3%(u TH=1tIH=HcH5HH[ÉD1?H=HW(Hw`HLJHHLJ0HHWHVHWHWHWHWH)81HSHHHtHHtHHtH{@Ht1[fDHtGwBLHcAT4t/HcApHHH€:t HH1ff.fHtPtJSHcH;}HSHH[~ Hcи[ÃAWAVAUATUSHZHHHD$H:GH%HIHIIILfDA)HcHL9HcIOIvI HLHtML)HLHXHHAIA$D)EH[]A\A]A^A_LHHHAL|$II)AM?DLLHcH~A-H1|v@AVAUATUSHIHHHHHH+E1HH9HcHO؋)HH~)H9HwHHNHHIELL)Ht6Eu@HHDHu48u uMt-M[L]A\A]A^H~IHH)uIDHO(HW8HLJLSH)ʍBHGpH0HpH@Hwp~HcHHH HPHO8HGpAWAVAUATUSHHHT$HHH<$IH=HcB$HH@H,H9rZf.HH9vGH3LuHCH[]A\A]A^A_HD$L9IM9f.1H[]A\A]A^A_H$1L=L@Al4tI4LHHuHD$HcP 1~H $HLMtM9sHH$ID$HD$@IcMIcmH,$L| L9)A\$)H8HD$'-t _HHI9tHU:t8IcU IcEH$H€:H $HcHcAVHH€:@AVAUATUSL$HH $L9uHdH%(H$@1HHHHHHE1L LfHHcHcT4t7 qHM HIcAHL EHT DT t HHuHHcP HHL L9IcIHLfHH I9HcHHc0AHLcP IHcHHBDBHJH H2JAuH L$DIH Ic LEtaE1@AI E9~CAMIUIAuI}ӅH$@dH3%(u6H@[]A\A]A^D1@IcUff.AWAVAUATUSHXHt$ HT$dH%(H$H1HIH1E1L-HL%HHHcHcT4t/HHAAtIL{8IHC0L)H9>Lt$L+{(LA@LLfIM)MK H@σLSLCpNIHDI0HI@HKpM~HC(MxIH E1I@HC8HL1HMLIHHKpH9eHthILM)MUI9t HtDL+t$HL[]A\A]A^A_DM@@M)(IHt$HLHk8f.HAVLAUIATIUSHu\H߉AD${LǃLSHu0{L[L]A\A]A^[H]A\A]A^Hff.AWAVAUATUSHHHHD$ 0xIHIHLc\CHcT t u(HDLcLH t tLÅ~6HcAT t u#H@Å~ALH t tE<AG=I|$PHHTI9T$Hs7HI+t$@L2%))I|$PLHHcAMt$PHLIFID$PA:I|$PMD$PII@ID$PAIc$0fET8HЃA$0D$ H[]A\A]A^A_D$ ff.H HB=0AUATUSHcHfDA< t< uH؅uH[]A\A]IHPHHDI9D$Hs3HI+t$@L2%))tQI|$PHHAI\$PHCID$PIc$0fET8HЃA$0H1[]A\A]øSDAUATAUHSH?dH%(HD$1D$ff t1fHL$dH3 %(H[]A\A]ÐA1ҾÃtʼnǺ1HL$Aߺu#DHuDo߻D HDeOAkDH}An}NHtff.USHdH%(H$1HHu/HH$dH3%(uHĘ[]@1H=tAUATA'USH'DNuDH@AHHHHtH-ƉljUDk HDcEufH H IGAG IPH f@ f@ HHP P H HPPHHPPHHPPHHPPf@f@f@HH#PP H H'P#P$H$H+P'P(f@f@!f@%H(P+f@)I1 fDIHcȋL4t#fBIHT4 rfB@2JHHuMIcP IHHH9pH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@pHH9wMApIbIc@ IH0ALJt` A1LHcIHIGAo IuID%D-B(AA1IcH4IILI 9HqH= IJDB(9xHqH= XIJB($AD$IKAzHL$;MbfoLt$ LAoL$AT$Ml$)$ LLHL$LHLLH$ID$H$I3L$H1H D$$Dl$EDDl$H=IHIDMH=t"LDLŃP|$Et$A9uHt$DŃ5$A?D5t AH5LHtHHf)#AH51H@H51LH 1HIH51H51D%DD$H=IHtZEW7E1111H=H51E|$M2;|$E1H5LuI}Ń1H5LKfD=-ED$AIFH51HH)H5H11H5L 1H5LA#LH H1H5Laff.AVAUATUSHdH%(H$1D$ HH ;1Ll$Ld$Lt$ Hkl{ul;LLD$CHHt@HHt{1f|$=u|H4tH舴Hd1H$dH3 %(u}HĠ[]A\A]A^D {H5Hfы{LA;ff.AWAVAUATUSHD=dH%(H$1ExHH-H};DH-Ht 1HEDEH$L|$PDcA:E1AfD EDEtHHt @fLH1HIcDHD$PHD$XA ?)ѺHH D9#11A|$MHD9#HHt @D9#AD91葳fH$dH34%(' H[]A\A]A^A_KL$HDŽ$hMl$H$LH$LHHD$@AHLDŽ$hH$H$LHHD$0PH$LHHD$8+H$`L HHD$(H$ LHHD$HADžHD$PE1Ll$`HD$H$HD$H$`HD$fD%EHHt H=1IL9t<1ձL5EDu EME1VHLH1HHc}}LD$LHD$PHD$X ?)ѺH1H T`1 8Ht$(1ҿ x=_5tHHt @f,D9# DCHHt@HHtDc1DN ={H5HHHt*HHB(@HHt@HH@8B-DAD9M==H HtDHHt A9HHtD҉T$$DE ~:E~5T$$AAAuDE UM D9vHAHtDH51D$0 H=T$fD}蠩C1mH|$IH|$HT$Ht$161E Mt AMgMg{E1CHt$1ҿH=f;>fDD$$0d T$$WH=T$T$fDD#AfDRDEBHH29{H5H{wH=H=0MAH… H{HH=Ht$1ҿHL=HHHtH11L=AGHHt{1蝦D-EuHHt!E9~;t Ht$@1ҿL$Ht$01ҿHt$H1ҿHt$81ҿHt$(1ҿ kHLSH$$L$H=%,H=QHHt*fC1CD$CCT$HC(HC fD=ff.@H,LSLSLSLS GA$3p1067GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA$3p1067GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1067GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1067GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1067GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realignAnonymous mmap() failedlocalhost%02d:%02d:%02d [%s] [UID:%d][%d] %.*syesnosystem()%s, errno: %d (%s) /dev/nulllibpthread.sopthread_atforkHTTP_[UID:%d][%d] %s:%s: %s LSAPI: jail() failure./etc/Can't set signalsaccept() failedLSAPI_STDERR_LOGPHP_LSAPI_MAX_REQUESTSLSAPI_MAX_REQSLSAPI_KEEP_LISTENLSAPI_AVOID_FORKLSAPI_ACCEPT_NOTIFYLSAPI_SLOW_REQ_MSECSLSAPI_ALLOW_CORE_DUMPLSAPI_MAX_IDLEPHP_LSAPI_CHILDRENLSAPI_CHILDRENLSAPI_EXTRA_CHILDRENLSAPI_MAX_IDLE_CHILDRENLSAPI_PGRP_MAX_IDLELSAPI_MAX_PROCESS_TIMELSAPI_PPID_NO_CHECKLSAPI_MAX_BUSY_WORKERLSAPI_DUMP_DEBUG_INFOnobodyLSAPI_DEFAULT_UIDLSAPI_DEFAULT_GIDLSAPI_SECRETLSAPI_LVE_ENABLELVE_ENABLEliblve.so.0lve_is_availablelve_instance_initlve_destroylve_enterlve_leavejailLSAPI_PHP_LSAPI_PHPRC=packetLen < 0 packetLen > %d Bad request header - ERROR#1 ParseRequest error SUEXEC_AUTHSUEXEC_UGIDLSAPI: setgid()LSAPI: initgroups()LSAPI: setgroups()LSAPI: setuid()Bad request header - ERROR#2 lsapi_accept() errorPragma: no-cacheRetry-After: 60Content-Type: text/htmlDEBUGINFONOTICEWARNERRORCRITFATALAcceptAccept-CharsetAccept-EncodingAccept-LanguageAuthorizationConnectionContent-TypeContent-LengthCookieCookie2HostPragmaRefererUser-AgentCache-ControlIf-Modified-SinceIf-MatchIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveRangeX-Forwarded-ForViaTransfer-EncodingHTTP_ACCEPTHTTP_ACCEPT_CHARSETHTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_AUTHORIZATIONHTTP_CONNECTIONCONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_COOKIE2HTTP_HOSTHTTP_PRAGMAHTTP_REFERERHTTP_USER_AGENTHTTP_CACHE_CONTROLHTTP_IF_MODIFIED_SINCEHTTP_IF_MATCHHTTP_IF_NONE_MATCHHTTP_IF_RANGEHTTP_IF_UNMODIFIED_SINCEHTTP_KEEP_ALIVEHTTP_RANGEHTTP_X_FORWARDED_FORHTTP_VIAHTTP_TRANSFER_ENCODING%04d-%02d-%02d %02d:%02d:%02d.%06d Child process with pid: %d was killed by signal: %d, core dumped: %s Possible runaway process, UID: %d, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld gdb --batch -ex "attach %d" -ex "set height 0" -ex "bt" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2Force killing runaway process PID: %d with SIGKILL Killing runaway process PID: %d with SIGTERM Children tracking is wrong: Cur Children: %d, count: %d, idle: %d, dying: %d LSAPI: LVE jail(%d) result: %d, error: %s ! Invalid custom stderr log pathFailed to open custom stderr logCan't set signal handler for SIGCHILDReached max children process limit: %d, extra: %d, current: %d, busy: %d, please increase LSAPI_CHILDREN. LSAPI: failed to open secret file: %s! LSAPI: failed to check state of file: %s! LSAPI: file permission check failure: %s LSAPI: failed to read secret from secret file: %s LSAPI: Unable to initialize LVERequest header does match total size, total: %d, real: %ld LSAPI: missing SUEXEC_UGID env, use default user! LSAPI: SUEXEC_AUTH authentication failed, use default user! LSAPI: lve_enter() failure, reached resource limit.prctl: Failed to set dumpable, core dump may not be available!sigprocmask(SIG_BLOCK) to block SIGCHLDsigprocmask( SIG_SETMASK ) to restore SIGMASK in childfork() failed, please increase process limitsigprocmask( SIG_SETMASK ) to restore SIGMASKCache-Control: private, no-cache, no-store, must-revalidate, max-age=0PID 508 Resource Limit Is Reached

Resource Limit Is Reached

The website is temporarily unable to service your request as it exceeded resource limit. Please try again later.
          ^ d/4-//// %-/Ga '9 (_intG )@/G G @ @ G @ G     G  `@ A C $E (J 0NL8PX@[+H\+X]+hj$xp4G- - N1 ooGGXa&& E18: ;1?A B C1GOI JK1 OQ RS TU1ac Ed EC^&e&g1 Y[ E]ah 1l5no 1tfv Ew x@ Cp3&5&<&Db_rtL&VO&i&p&y5G1$ +& ( * 0 { f|HCIRT Cv&"7&$ R  E+v"&T.1 4 c G@4HH//-Gldy"m - 911; CmGFy<d(eGfI@I@IEIE"1 36 |7 |8 |9 | : |(; |0< |8= |@@ |HA |PB |XD `F hHpItJ xM9NNO Q Y [ \ ] ^ E_ `b g+J  G J J  G4'  < ' ' '   T h4I ' T X@!      !!"! ! ! ""F " E" #!X@$  i0%9"# # # 4  G  "&4 &6 &7  < |"0'1 '3 |'4 |'6 '7 '8 |'9 | ': |(jtm8(, ( ( ( (  ( (((( ( ((0|< G'), ') ')'), ') ')H*! B@,H      !"#$%&'()*+,-./0123456789:;<<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'-$|'-2 '-7 '-; .U.m.4/"/*/!B@/) !)./23\^bgl00/{C/&/ &/ -&/ =-G=GMG"/h/ 4M'/h'/h"// ///-GK/,/ ///M/K0050708090: 0; F 0<0= | 0>( ,"n11 1 GkB@2,     C2q&2s9&2t"2k2m 2n 2o 2p 2u",22 2 92 9 2 92 92 92 92 9 2 9$2 9("222 4G9G"22 92 92 92 9 "2G2 92 9"2o2"2"/" / 1 | 2 | 3  4 k : < = ? @ B| C  E|( F|0 G|8 I|@ J|H K|P L!VX O ` P h Q p R x T'\ V'b W'h X'h Y' Z' \'n ]'t _| `| a| b| c| d e f g h iL k'zL m'G(L n'8L oE "0pVr s uhvwxz{ |(vGa=G q' s w9   EM X9    $EM x7=RH H"XOYbufP =Q YinRG-G?]!NB@j~            9     H  H  H  |      l "G * ^GN G t N  t G M>CQ L L @  J l E m  9    9#!  9 9 #! @! !9Z! #!  g!F!9! ! |'  ! m!        # # *"G&%" K "  K@ V#          ( 0 8M " z# V# @      #  -     H! x$2cnt!U$2pid'U  : YO%2buf'#!U#in>74r"4TsUs]4U T 4UsT  [5m4UsT 5UsT ,5UsT Q5UsT v5UsT 5U ʳY5U YU ;W6%;O";#;Y2x6k%2w~}׳6U2T~QwY7U 9Y,7U YK7U Yj7U Y7U Y7U ;Y7U Y7U <ytY,8U YK8U G<Yw8U ;Y8U ;Y8U <Y8U Q;Y'9U YF9U ^9Us<Y9U Y9U Q;{X9TvQ | $0.MX] ":!p], _ ":3:=GE `: E- G % :!p%) %2| %= ' :len( end) |:=G ;i pw!)p7 2;env ! )del! D TD ( ;*$U(;**U(<*'U(G<*&U(v<*$U(<*"U( <*U( =   H  -5+fd ret    ~ Et;=   5 >__d U| $ &585> 8! O EOOOOw PyPz%P{2P|?P~LPYPfPsPPPPtPtPuPvNPP p?P>QT?Q?U  y @y!y 9C@7@Ä*UvT|Q@T7@U}C AUAT|Qt7"AU}CGAU?T|QtClAU2T|QtCAU:T|QtCAU3T|Qt3AU OAU0KQ BU|[%BUV3KBT}Q0R0XtC|BU:TtQ0BU T BU [WVBUu7BUthCUtTAtDCU0TtQtLtCU2TtQCU  CU CU  DU 8DU tiDU2TtQ03DU0T0Q DT0LCDUATtQ0CEU?TtQ0C8EU3TtQ0C\EU2TtQ0CEU:TtQ0EU QU  ?yj"FQy-?y+Qy+y #/ y+y #  yy*T Q8ly 9G~y+y yy*T Q8zqQGUsOhGU03GU|TvQ0R0X[WGU|GU|T0Q HU LGHUs?Ãsx_HUsHUs?ÃsqpHUsOHU0M M M .5+ O 4 P 4Q }R E} S retT  V z#EactX ~;I   5I__d ;1J  #JU T7VJU|CJUATvQ 7JU|CJU?TvQ CJU2TvQ CKU:TvQ C@KU3TvQ 3[KU OrKU0KQKU}[KUV3KT|Q0R0XC LUAT Q0C2LU?T Q0C[LU3T Q0CLU2T Q0CLU:T Q0LU T LU [W )MU HMU gMU VMUu> @N > +5+5N C 4OU0L pO  *5+  y6 GOy!y@ 7NÄ 9O*UsTwQ@3OU0T0Q OT0LQ: Q : @z# ; 95+act=  =  = % = / >  >  ?  @ retA pidB  C 4 D 4 E  F E H  I FP   FQ__d )  D/ 1T+ : 6R  ,        %RU T   F lY  *  5 =X~ret pfd YSYUUTsZqYUsTv88 Z 8 ' 8 @ : Zp; | < |res=  = , > ? ZG -[  6[  Gret fd  D  ZT1Q0ZUsT2Q1[UsT1Q2RDX4?[UsTvQ} ][UsT|L,[Uv 8 [  /5+  B!len LF[ch )   ^  05+  C  ,   len ;\ch ;\ch 57]  U|  x]TTQ~  ]T}Qv]UvU} t^* 25+U- Ä F^  05+#fn !#arg ,E@p_QTRQt Fp_ t )5+#fnu !#argu ,E@p_QTRQ6a s` a 6h#nb #fnb (#argb 3E d #hrete qX} b  ,5+#fn !#arg ,Ei len! " |ret# $ ;Zb7 Z}p8 | 9 | : | ;  < &t < -t5(achK % O Fa__cO 9 ̋F 1b݋r}U~T}#X|3bUv3$|"T v2$}"X|$_d /5+#fn!#arg,Ei len  |ret  _d~5c |  &t -tEdUwQ R E=dUwT| $ &Q R 3QdXvA"pd=G d2v1'U2v27T|'f (5+ ; #h #h['ff$Ff$9fSf^fNkfelfwfffffUffUff9RU|Ts3$"RU|q|f q-5+ q@is t |)p | |  &t -t)ch) )__c8< -g </5+ <B!len<O >  ?p@ A - B -retC iovDg E  gGh $5+ret n .ph6$)CP]qTshhUshUs?Ãs^(iNi*'5+U "\  -Ä -j +5+ 5#offBj N "\ jÄg5jUs*RjT~Q8Z^yjTTQQRR^8 - k (5+ ;!lenH "\  p! " - # - $ - %  - l .5+ ;| Hlen -    l$UvQ|-o ʊlۊ@U~TvQsln -5+ :| G THlen -  -  |  |  |p |  >n#nTQsTQsmo no% ooU~jUT:Qs]mo -5++moo%ooUs o .5+  len -|Sp*+5+U 5off yJqp y&5+(nYp n%5+-`t}$qKzq K*5+h-qUsgEqUseqUs?Ãs^Us-r -%5+hqUsgqUsqpqUs^Ft %5+=X~ElenF ~~ ?yPsQy-?y+Qy+y / y+y   yy*T Q8zqhsUssT0sT|Q}sT0xsUssUv?ÃsqptUs8tT6Q1R~X4 yt*(5+Ut@FtU %w (5+#fd2  `Tu}$q  uvT Y' >vk%'w~~׳/vUvT~Q~ HveY'U T2ʳvU vUsT vUvT1wU0wT0( Sw2cb;*UD Tx EۄwU=T ۄxU:T ;xUIT1WxU2T1t{xU T0xU T1T A y A%5+lenC D 4/y!fd4) 6 /y?yG+^y!fd+,s y!fd5 y!fd 7y!fd.!pktN\ *z *5+ 4   |  | Wz 65+ D z D.5+uidF gidG H I J#h K#hiL 1 >{ 1.5+ 2|!len2 2+| 26 4 5>{-N{G { '5+!uid3L!gid>@ Prv pw! { 6 | +5+#uid7L#pwL!ret  Tw3o|UQTs|U T Q|Xs}|UvT Q0 $} ,5+!uid8L) ret  r} -5+r} } }G}=G#4}6{  {,5+ {? {R} ":_n~ i~ ~$zUvT Q1R X rf~U|Tv*~U2DrJ [ J%stLSfdM ) zrc+   )uid  -5+  i ) &t -t7 O 35+i F2bp|) &t -t7v /5+pb7 )Hp |b6t Y t4h tB*u! Q u#| w#h x xh!fdh j=XlenkF R ف R<ف SH S+ U#hh> >>\ >L)bF62 G 235+ 2=p4 |vTv$ Ă $+5+!n$5p&  05+ :  | i!fd 2i < Gret  n  -!fd' 2E!len?ret -7 у 35+ !fdret 6 U#fd# +val UsT3Q0@UUT47wф wJ\ x&!lenx0tR :A  A A2EsaC~CWUvT0Qs7oUsCUvTsQ0:8 υ2sig8!U:3 2sig3 Uu (7   .mUs@U T QURTvvwxfmt'PVbuf Tvyp |z Eap  u5VtvEuVtm u{iևzU|T Q1R X \i/XzU|T Q1R X õuUsT0ϵUsTu +۵T1Q}Ru\i-zUsTdQ1R X Yv3$" izUsTdQ1R X  > [[OT1Q X|rW  :5+ D.|ʊ|."-" "E"%.k|6kkk.\|`\\.>E>E>>.'E̋'E''.EG.8 18.did d<P.A]__sA]__nAAP.%|Ռ%%|sz' 8n n8i i8 B  BS.)s))PW11W"m"m,moooo-o ʊۊ@U~TvQ|,aq$ÃSу G$% L8Us+ $Ã, )6CP]UvQ|,Ot  OfT0,YYYYY}YYY}Y}YYG g)U|TsQ N ʑ)UvT|Ql  UsT0Q: ` T}q ̋ ݋ Uv 6\ SG) U|T:51U|T )OU}T]AzU}T0Q}R}NU|[U},UUUUQUQVV[UC ה$UUUUVVNVV+VU T|QgU TvQ3VUu,flEfggg,g9gDgQg^gkgxgf< ggf%g,g9gDgQg^gkgxg e6)CP]qTwQ2R} Z ÄgU~U~?Ã~*7U2T~,9= ::п `:b :}:r::_:: , 2sUwT 9 %ɌUsT|Q јTvQ0 3:g 6E:R:HGeY'UsT AQ UsڙUvT2LUvU2T1}U0T Qs9 ]  :% :}U0T QU,jjjjjjjjjkQk j jjjjjjjjkk S $Ä? cUTQvg{UsgUs^,[[[[}[ [$[$[>[,[>[3g[U|- TvQs,Y8YYYYYYYQYY@tUUTT,{X!#XXX-{X XXX՞U@T1[UU,x xxx oO/ʊ  ۊ@UsTvQ| xA hxxx߁1V۠O  o@iš%8ʊۊ@U}T|Qv yn yyzz~zA %Aˁ+5R %5ˁvT v $ &33$A %Aˁ+5R %5ˁvT v $ &33$  wODO X]%j v v[ v v v6 v vȦ v-vS K$% >#)&+v %O23@ v  v ڨ$ v $-v $*z1 ԩ"?o363A* @ 'n* A * A B1B( 1 : ; 9 I8 41B11 4: ;9 I 1RBUX YW  : ;9 IB 4: ;9 IB : ;9 I I: ; 9 I4: ;9 I1RBX YW .?<n: ; 9 4: ;9 I4: ;9 IBI41 U.: ;9 'I : ; 9 I!I/ .?: ;9 'I@B4: ; 9 I41 : ;9 I8 .?<n: ;9 I!: ;9 I" : ; 9 #: ;9 IB$1% & : ; 9 I'4: ; 9 I?<(.?: ;9 '@B) *: ;9 I+1RBX YW ,.1@B-1RBUX YW ..?: ; 9 'I 4/$ > 0(1 : ; 9 2: ;9 I34&I5 6.: ;9 'I@B7.: ;9 ' 8.?: ;9 'I 9'I:.: ;9 '@B; U<7I=!I/> 1?1B@B1A.?<n: ; B> I: ; 9 C : ; 9 D.?: ;9 'I@BE4: ;9 IF G5IH4: ;9 I?<I : ; I8 J<K : ;9 L : ; 9 I8M: ;9 IN 1UO 1PQ41 R'S1X YW T.?: ;9 '@BU 1UV4: ; 9 IW.: ; 9 'I X> I: ; 9 Y : ; 9 I8 ZB1[1UX YW \1RBX Y W ]: ; 9 I^% _$ > ` a : ; 9 b : ; 9 Ic'd&eIf : ; g: ; 9 h!i(j : ; 9 k : ; 9 l4G: ; 9 m'InB1o.?: ;9 'I@Bp4: ;9 I qrBs.: ;9 'I t.: ;9 ' u.: ;9 I v.?: ; 9 '@Bw: ; 9 IBx: ; 9 IBy4: ; 9 IBz4: ; 9 IB{1RBUX Y W |4: ; 9 I}1UX YW ~.?<n.?<n: ;9 6ddqd T)TuPPP(PPsPPKP[P"R+RRJQ^Q5Q5<v <Q{ PTt _X ~XX[TiT2TAXX[P[aQxT4T@PP{P{t XRr t;# $  %!r"p;# $  %!r"u?[gRSRbRHRQRR {RTKTiQX%vXvzr TiTTQq Ru .Q2QHQ+Q4QQoQQ;QQXP iR~Rv FRFW{ _Rz QK$KU$KKVKKUKIKTIKKSKK|hKKTK.KP.KPKQpKuKQuK}K?p K$KQ$KLKUpK}KU3KFK q 3KFK03KFKUQKpK8QKpK0QKpK\pKyK 7p yK}KQpK~K0pK}KUKK@KKUKKSKKVKKXKK0KKSKK|hJlJUlJJ]JJUJJ]JJUJJUJ0JT0JJSJJTJJTJJSJJTJJs@JJSJJSJJQJJ^JJQJJQJJ^JJ^7JTJPWJZJp?ZJaJPaJtJ\tJJPJJ_lJJUJJ | v"|JJ_|JJSJJTJJT|JJUJJ | v"JJ@JJSJJTJJs@JJ}JJ ~ JJQJJ\JJu`IIUII\IIUII\`IITIIT`IIQIIVIIvxIIVIIV`IIRII^IIRII^`IIXII]IIXII]dIITdIIUP@c@Uc@CVCrDUrDEVE.EU.EeEVeElFUlF;GV;GTIU@@P@@P@@P@APA0AS0ACAPVAiAP}AAPAAPAAPABP$B7BPKB^BPrBBPBBPBBPrDDSDDPDEPEEPEESlFFPDDsp"1DDP@@P@@PjApAPAAPAA0AAPBBPDDPDD0.E4EP:EQEP~@A0A!AP$AC\rDDPDD\DD0DD\DE0EE\lFF\FF0FH\H@I\EITI\@@P@@PAAPAAS5ACAP[AiAPAAPAAPBBP)B7BPPB^BPwBBPBBPBBPFGP"G,GP'CQCPE#EP HQHPFFPG!GP;GPGPPGTGUTGGVHHVHHQHHVI;IVEITIVFFPG!GPDGPGPPGTGUTGGVHHVHHQHHVI;IVEITIVWGpGPpGGSHHSI%IS%I6IP6I@ISEITISDGWG0DGPGPPGTGUTGWGV`GeG}eGpGQpGqG}`GpGPpGqGSGG@GG GGS]CtCP{C}C0G HP H HPfCtCPHHPHIS]>,?0,?C?]p;u<0<<P<=]=>]>,?0,?C?]p;u<0u<`=}=>}>>T>>}>,?0,?,?},?C?0p;u<0u<@=V@=V=PV==V==P=>V>>V>,?0,?0?V>?C?0p;`=S=:?S<< s $ &<<U=>0Z>c>0c>{>^{>>~>>~~>>~: ;U ;/;S/;0;U;;P99U9:S::U::S::U9S:\::S::@::6::W::4:: ::H4U4U U $$6U404^^ $^$6040000T9r0? $0404_\_\mm_ $_$60404K\KV\V\ $V$60SS 6S]] 6]USUSUST.V.T  wS  P ' S' W v(d r Pr x S     p`# p`# <$ c ~`# <$d x ~`# <$ vv" P c ^d x ^  \  0  P  S89P8:9QP+ PQQ + Q # 0 # 0 # P  U s U ) P) > S> k Pk n Sn r Pr s S 7L7UL77U 7H7TH7w7Vw7x7Tx77VM7Z7Px77P55U56V6?6U?66V66U66V66U56T6?6T?6F6TF66\66T66T66\66T66P66P66\T6g6Pg66S66UF66]66n2(3U(34\44U223T23(4V(404T044T223Q234]44Q63Y3PY3c3pc3t3Pt3~3^33p33P33S34P4,4,4h4L3p3Qp3~3R33Q33R3 4T 4 4tp 44T414^4(4V(404T0414T404|I4R4QR4S4VI4R4TR4S4]I4R4|_(l(Pl(v(u_(v(3_(l(ul(v(P''U''U''U''T''Q''T''T''Q''R''Q''QP''U''U''UP''T''Q''T''TP''Q''R''Q''Q0`U`SSU0`T`^TT0`Q`VQVQQ0`R`]R]RRD\~1$~"3$U"T $ &33$U"\~1$~"3$U"T $ &33$U"\`iP{P0%%U%&S&&}&+'U+'9'}9'@'U@'E'U0%%T%&_&9'}9'@'T@'E'}0%%Q%9'|9'@'Q@'E'|%%V%%vb%%0%%p 9'@'0%%Q&&Q%%P&&Pb%%0%%^%%~%&^&'}+'9'}9'@'0c&u&}u&&]&&}&&}&&]+'9'}K&&_+'9'_c&&S+'9'SK&X&V_&u&Vu&&}&&t&&T&&}#+'9'V%'\+'9'\&&P&'}+'9'}&&V&&v8$8&2$p"&& v8$8&2$p"c&c&5c&c& c&c&^#|$U|$$U$$U$ %U %%U%$%U#w#Tw#$S$$T$%S%%T%$%T#w#Qw#$V$$Q$%V% %Q %%V%%Q%$%Q##P##p$$0$$0$$^$%^<#w#0##r ##t %%0##Q$$q$!$qpI$Y$RY$m$q %%qp$$P$$P$%P<#w#0w##\##|#,$\,$_$|_$$\$%\ %%\%%0$!$T3$m$T %%T%%q`$!$X>$B$RB$$X %%X#$P %%P#$Y %%Y !U!7!S7!p!wp!{!{!!U!!S!*"w*""U""w !T uF!q!S!!S!!s""S""P""P{!!|I"o"|o""P{!!VD""V""v""V{!!_I""_{!!}D"d"}{!!]""]{!!^""^o""q2$u"""q2$u"o""v8$8&2$u"""v8$8&2$u"""v8$8&2$u"((U(=)S=)>)U>)Q)UQ)b)Sb))U()0) )P!)&) &)<)P>))0(( uu@()Q>)Q) uu@b)|) uu@()P( )s ))T))s()s()Pt u T p p# p`# tp# Q P 4 T2D2UD22S22~~22U22S22~~22U22U2D2TD22V22T22T22T22V22T22T2D2QD22]22Q22Q22Q22]22Q22Q2D2RD22\22R22R22R22\22R22R2)2u)22^22U#22^22U#22uU2Z2|Z2u2PU2u24U2u2^`U< ]< H UH b ]b k U`T< VH b V`Q5 SH [ S[ ^ sp^ b SP}q $ &}} $ &P\H b PP0< \H b \P\V 0 SH H S 0 VH H V 0 ^H H ^ PH b P  S  V  ^ZUZ^UH^H\UQTQ]TH]H\TZQZHQH\QZRZ\RH\H\RlSHS?ZSZ_H_HRSP\QTQZ]ZVUVVUHVH\TT__PPSS__UVU(4^(3 p $ &37 s $ &USUSUUSss $ &0yTyTMYQYn t2$x"#4nyRU)S)*UUPU0//U/0S0 0U 0#0S#0)0U./U/[/S[/\/U\/a/Ua/o/So/u/UWWUWXSXXUXYSYYUYPYSPYUYUY#YsY#YsY#YsY0Y Y#Ys U S"U"rSrU'T'V"]V]_P_rVrTdlP3  303}@3}S?LPL}\V]d2]d 3JP,2,U2,h,Vh,k,Uk,,V,<,T<,j,\j,k,Tk,,\,G,QG,,Q-,H,0H,L,Pk,,P,,R+:+U:++\++U++\+:+T:++^++T++^+:+Q:+V+SV++Q++P++p $  $-(q++ q++  U uh U T T q Rq w Rw y Ry R q Zw Z 0  [  p * X- q [q 0 0 T t  u|#- 4 T4 7 pD W T^ b tb q u|#q 00 C UC n Sn p Up w S0 G TG o Vo w TH _ P_ i sp u P U S U S U U S T V T V T V P P P0_U_VUV07T7\T\@JUJrVrvQvwU@UTUcScvRvwT@UV}U}V.U.VU@T|]|}T}.].5T5]v\S} S R.:v:\S\S P}Pv  \c c c\SWRWXuSWQWX]SWs} }d}S dUS.  (s U  S  U  S $ U$ * U Q$ * Q P ) P) * u t $ & P  \  \ T  V  V  ^  ^ P ] $ P \ V ^G P P U V U VU T _ T _T Q \ Q \Q R ^ R z^zRR P S %P%XSXdPdS R ] ]R U SS(S T VT9V 4}4]}*\kPS(P(QS*S04^0QTPThSsS'<'<S',},<\l\UvFQSs0s0s}Q | Q|V\dUdU}P_U_/0/LPLn__UdSPnSSPSdnPPQQRX))U)*^**U**U**U**U))T)*~**T**~**T**~))Q))w)*Q**Q**Q**Q**Q))Q))w)*Q))T)*~))U)*^**S)*~*`*_`*v*v**_&*f*Qf****}x**Qj**]**P{**P**]{**2{**w{**~{**P**]{**2D*T*qT*j*PD*j*6D*j*\,-U--V-T.UT..V..Q..U..U..V..U..V..U,- T.q. .. .. .. ,-W--ST.q.S..S..S..S,-U-{-V{--ST.q.S..U..V..S..V,V-0V-h-U..0r--P..P- - - -W{--_--\{--S{-- -.S*.T.S..S--P--V*.;.P;.T.V..P..V-- A--Sq..V..Q..U000U01S11U11S11U11S000T0111T1111T1111T11000Q00V01Q11Q11V11Q11V00V01Q11Q11V01111101S11S11S00]0 1T 11x1b1Tn11T11T01V11V000F1^F1R1rpR11^11^0-1_-151x511_11_0b1Yq11Y11Y11Y00R11R11 @00400T11V1111_45U5%5U%5/5U/55\55U55\55U45T5%5T%5F5TF55V55T55V55T45Q5%5Q%5P5QP55Q55Q55S55s55}%55S55}55S55P55st"%575P75F5st"1F5f5vs"1K5`5T`5b5tpb5f5Tq55Sq55Vq55|7 7U 77U77U7 7T 77T77T77U78U88U88U77T78V88T88V88T88V77Q78]88Q88]88Q88]77Q78]88Q88]88]77T78V88T88V88V77U7^8\88\K LU LWL_WLLULP_P$PU$POW_OWTWUTWW_LLP,LWL\LL\,LWLVLLV,LWLSLLS=LGLPLLP,L=L\,L=LV,L=LSLP_OPOW_TWW_qMMPLPSOPDUS\UOWSTWWSLL1LLPLLQ8MqMV8MqM\.MqM]NMXMPqMMP8MNMV8MNM\8MNM]MPSOP,RS\UUSV0VSW/WSMP_OP,R_\UU_V0V_W/W_MM p1OPQ p1MP\OP,R\\UU\V0V\W/W\MNVMNMNMNVMNMNMNPNONVNONNON!NONV!NON!NON8NONPyOO_RiR_RDU_\UV_5VV_4WOW_TWW_yOO#R,R#\UhU#yO{O0{OOPOOpOOPOOROPQ_OPQPOPkPpOPQpSPkPQkPyPp kPQp oPyPQyPPpyPQp}PPQPPpPPpPQp PPpPPpPQp PPpPPpPQpPPQPPpPPp PQp PPp!PPp$PQp$ PPp%PPp(PQp(PPQPPp)QEQPEQIQp"Q'Qp1$q""Q.Qp1$q"3QEQQ3QEQQ6QEQRiQQPQQppQRPpQRQQQPQQppQQPQRppQQRQQRQQRQQR\UU_iUUPvRRVvRR_RRPRU_UV_5VV_4WOW_TWW_RDS\DSGSPGSSwST\UU\UU0UU\RKS]KSSPSS~ST]UU]TUPRU0UV05VV04WOW0TWW0R SZ SSzhUUzhUU0 SSZUUZRRpRSXUUX_SS__SSz|_SSRSS~_SSz_SSzSS\SS}pSS@SS SS]TT0UV05VV0VV04WJW0TWW0WW0T T~UUP8VXV\VVVTT_UV_5VV_VV_4WJW_TWW_WW_^TpTPyTTPTTPTTPUUPUVVAVXVPiVVPVVPVVPVVVVVP4WIWPWWPWWVT2TP2TT]UUP5V@VP@VXV]XVzV0VV]VV]VVPTWW] TT_UU_XVzV_VV_TWW_ T3T 3T;TPTWgWPhWW_UUHUU0UU U4UU4UU4UUDU U4UPJP P$PU$PJP_.PJPP,d       9>ACFQxx| *)SX 05:@nOh"'3"'3TY}O[]dRV] 0 P P  0 P P {!!!"""{!!""`"h"p""""`"h"""%'0'9'.&5&B&G&c&c&_(e(l(v(((() )))* **`*f*{**D*D*I*Q*;+>+c+n+q++,,,-X.x.....,,- --.0.X...0111110000U2U2`2j2D3c3k3~333334%4,41464<4I4S455+5555q5w5{55777 8 888888s:}:::s:}:::::::::O<T<<<<<=>`>>@@@@BQC E0EFH HXHHHI;IEITIFGHHI;IEITIDGGHHI;IEITIQCChEpFH HXHHHIhEEXHHHIEpFHHdIdIxII_JJJJ|J|JJJJJJJJJJJJJJJpKpKuKwKyK~KKKKKKKKK,LWLLL0LWLLLWL\LL POPiSiSUUUUOWTWWMPOP,R\UUV5VW4WyOyOOOOP\PaPdPhPkP\PaPdPhPkPrPvPyPrPvPyPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPQQQQQQQQQQQQQQQQQQQQQQQRiSiSUUV5VV4W@WEWOWTW`WcWWUSeSiSiSiSSSSUS_S_SeSiSiSiSSSSiSqSSSSSTTUV8VV4W@WEWOWTW`WcWWTTTTUUUV8VV4W@WEWOWTW`WcWW T;TUUTW`WcWW T;TTW`WcWWUUUUUDUYYYYY0YYYZ ZUZaZZZ@[]^_`_`8`` aHaaa0bstruct_FILE.hFILE.hstdio.hsys_errlist.hresource.hstruct_iovec.hsocket.hsocket_type.hsockaddr.htime.hpwd.hstruct_tm.htime.hunistd.hctype.hconfname.hgetopt_core.hstdint-uintn.hin.hnetdb.hun.hlsapidef.hstring.hresource.hdlfcn.hsocket.herrno.hselect2.hsched.hmman.hsendfile.huio.hstrings.hinet.hwait.hprctl.hgrp.h KK.K5J/I#KK1 0 z zJ Z " OJJ = ...v <K gfJ.T2KxJ.n=@<YDw<<=:/;<;/u;=IK=H</փ-K-=>:X-=;=0:/;=I<//sf=H</[G-K-=18=;=0:X;=-/I=;/?Gf-K-=I<-=;=-/e=-/t0//-</-</-</-<///-<///-J=t=Y-</ȑ-</J>Xtu-=ttu;/K-=-/X-/t;/gK-=Y-=;=J;=/K-=-/X;/u-=ttu-=K;</f;=;/fu-=t.V>,>t;=/.K-=-/t-=-//-/-X.I</t.W=-/0,0,<.W=-/t/t;=;/H ># K# = l Z< < h u$I$K="IY<IJ =$J$<=;"<J = vXF.L L = /d f.L u /O7@p$tik<=<>V L a$f mX Xm< .>m<X N1+ pk " kJJ k.XX"~K k  [ X O(kX  < kX  b>= E<>:<Y<; = vk<q R< !l   l<lz/ f X< Kffkv ~*~ X$ rJ~ # .?f h ~~<  .<1 ~) < ~t)X ~<= jtt        Z-JJXft X L!s gf  fF J Y Y :"foXXXJlt0 hd/ L. XN6g J yi< X$   Z  4tKK  ;:|". < Z IY6t(f+K"JMX"X< mJ< & AJX0J XXXV$J)I!4f<9X!Jh  .$r.XX`KJ Jt5<uY"J q<% 3$x.`XYBW[$g   F x \ *2. F^ \t;:j KK-uYIX Ki+JJK2KKu\/ u  u  (tX |  x(9?JL6J9xX<u1tu6,XJK,@g L,K /sJK u XQy  X KEW \ g x. < %  /s u Z ptt  /t.X  o tK !f J/ kt Zs gY  Z Y g Y  #!xwJKxJK K!JK sJ  s< ! KJ9J!JK!s  f K =J YYt YYt YYJ YY<xK t<YL ,<W ue [A<v v .KXe#!CJ;Cg K E dX ` x DNK$ JG MY<," g <    =  &> t u X   Y r< f Kr  < r rJ huJL |   fX.X  ]u u<   Z = = y<kJK,&J"Irt &s=r< !rff  "yJD!IK L%; K%H K KKK.7 .XB#I1u#J Q  F Z  KNJ U  X  hJ.$ .Xhr / X L*~Jf-S. LKI u YZ .HJ K Y)%fX80JJ )X%<XX$%4HJL<0YBL=;B=Vv<)/Mt z0<6u  zt/  L4K"vI4H =" @"F %#K%W Yz Q*uJf  uJ K mJJ .I  <vJ uMF =0J u) Y%#K,K"9 =& =X YsJY FX:JJ Z L N*<xX<JX>tJ e < 7/t  L4K xH4 = K *vJfJ  uJ  Y.W mJt mX K t Km \x JYKWiX<JJz NS =;0WX Y)? K  LeJf<Ki*_8tK )^ ~tf<_K z.` ztf< XKJZfv*=gJ Z AK=%, =%H KM, tY,Lho!(fot(= -K l X|K<x < o.K Ms f sf tJt    Z 93JJM _< . jy 93JJ Kw ' K"f/ s XM X X mXL  f   yr rX' =P Yr J:h6t YGu  uf>= . f  K  ^tj  !tJ<   jF % =%H K  Z7)K LK)8 K! K 2%o = K%: K2 GK  _X#< ]< <& Y ZX [f<Ȃ _Xy q   KK&,N>:hZs"  [sf  "Ui Xi g Y .. - sX ... K fh00< =  h+< Y  u<   Y Jz   . L+< g  /.  L g J JK*X.X v6= Y; u/ Xl f? lJXY lf"Kl "K8G8=P.4XK%      J.Jp<J*<X v6= Y;. / Xl f lJXY"=8G8= I/..c<<jBz<  sX&`" f [Z M   L  Y 0 U= =Y K ^f 4I gYK$/ fY L y^ /K-%]  K+/X>0XX<uj Yv Xg Y IgZ$Hv&L<X(.= /.u.Z .fJOwX(WuO=.ft"<*w  <K t Y /?N&tuKK  h g G] t Y t YtM   t  Y IgYJvYY g r Y >v t YK, <Y ._ho<x }KYWJtbXK X 9    ft "u ; <u WY rXu WY X"0", XX LXJ<f?JfjK t Y*=K t ,=K t 0=K t .=K t Y,=KgjKK 2K zt/ Y Z  c    Zc  cf  Zc <<   a,<  Zci  Zc x    Zc w X     c       Yc  v    Yc  v    Zc  w    Yc  v  Z [    Zc   g     Yb  f }r       g {  g1J }  <1-u-).K.X UJ.< Z .)J KIK XxK +zz< O=>;g< 0:>< Y6 2 _< < Z    \_<   _X<   _ @ /        J       f :v ZYw Yu    Zv  .X t   tXI/ /    u ~ft  Zr> Z J  z  X/X < zX   tX /  `ggWK>X u ~X~ }XYX |X |<Y ^  X ./ XR XUJ Y   h.eX> tYvtYK   M U -/](tq $~Zv <Qyt/Z t   t Z*(t N   bX J| < y  !#J Y  Z+KZ)=1K- M< <Y v.u. }Jt ZY< gJ f"<  /  np < }2NX)     ~ |X}Y"Xg![qg!p'Y>tYK&CXK%.ZY&i fYp<x u   Zv X w ~9}5Xl t.Z7j.+"<g7/W5K/I Mu_Kg\K _SC_THREAD_SPORADIC_SERVERpthread_atfork_functotalLSAPI_Set_Max_Process_Timelsapi_parent_dead__fxstatparseContentLenFromHeaderugidLen_SC_2_SW_DEVm_pScriptFileLSAPI_Stopsi_addr_lsb_unused2_SC_TIMERSm_iReqCounter_fileno_SC_SHELL_SC_MEMORY_PROTECTION_SC_SCHAR_MAX__pathtm_secH_AUTHORIZATION_SC_THREAD_SAFE_FUNCTIONS_SC_UCHAR_MAXmax_lenfreeaddrinfogid_tverifyHeader_SC_C_LANG_SUPPORTm_pIovecEndstrcpy__uint8_tIPPROTO_TPpw_uidwaitpidHTTP_HEADER_LEN_SC_TTY_NAME_MAX_SC_PASS_MAXLSAPI_ErrResponse_rsi_uidm_bytes_SC_2_PBS_TRACKfp_lve_destroym_pHeader_IO_buf_end__RLIM_NLIMITS_SC_SELECT_shortbufrlimitsockaddr_insa_family_tSOCK_DCCP_SC_BC_STRING_MAX_ISpunctis_enough_free_meminet_addr_SC_TRACE_INHERITinit_lve_exnewSizem_tmStartliblvesetgroups_SC_SEMAPHORES_SC_EQUIV_CLASS_MAXread__environ_sigpollsa_datauint16_t__builtin_memmoveai_protocol_valuem_pChildrenStatusCurIPPROTO_UDPoverflow_arg_areatime_tsin_zero_SC_DEVICE_SPECIFICin_port_t_flagsachMD5_SC_THREAD_THREADS_MAXerror_msg_SC_LEVEL3_CACHE_SIZE_SC_TRACEreg_save_areacalloc_archm_respPktHeaderg_running__off_t_addr_bndlsapi_cleanupachHeaderNamest_size_SC_THREAD_PROCESS_SHAREDallocateBuf_SC_JOB_CONTROLgetppidtm_isdstswapIntEndianlsapi_check_child_statussignal_locks_max_idle_secslsapi_set_nblockenvirons_schedule_notifysetUID_LVE_SC_NL_NMAX__RLIMIT_NPROCRLIMIT_DATApServeratoluint32_tinitgroups_SC_POLLm_pHttpHeader_SC_V6_ILP32_OFF32_SC_TRACE_SYS_MAXm_pScriptName__builtin_va_listst_blksizeRLIMIT_NOFILEm_pEnvList_SC_BASE_sigchldLSAPI_Set_Max_Idle_Childrenint32_t_SC_LONG_BITfixEndianLSAPI_GetEnv_r_upper__fmtsa_familym_specialEnvListSizepw_passwd_SC_CLOCK_SELECTIONmasklsapi_resp_infosigaction__RLIMIT_RTTIME_SC_V7_LPBIG_OFFBIGbodyLeftfcntllastTime_SC_AIO_LISTIO_MAXLSAPI_Init_Prefork_ServerpErr1pErr2st_gidm_cntHeaderss_notify_scheduledm_envListSizeacceptinggettimeofdaypBufai_addrm_iAvoidForks_secret_timerlsapi_MD5Context__syscall_slong_t__builtin_memset_SC_FILE_SYSTEMsa_restorerm_pChildrenStatusEnd_IO_write_endtype_SC_SCHAR_MIN_SC_LINE_MAXLSAPI_SetRespStatus_rlsapi_MD5_CTX__resst_nlinks_addr_SC_TZNAME_MAX__va_list_tag_syscallst_ctimnameLen__builtin___snprintf_chkLSAPI_Postfork_Child_SC_2_VERSIONfree_SC_2_PBS_CHECKPOINTIPPROTO_MPLS__sigset_tm_requestMethodOffm_tmWaitBeginreadSecretreadReq__tznameatoig_initedgetaddrinfovalLens_acklsapi_jailLVE__d0_SC_LEVEL4_CACHE_ASSOClsapi_MD5Final_SC_NL_LANGMAXdoAddrInfo__stack_chk_failmemcpy_killcurSizeRLIMIT_STACKIPPROTO_IPIPdlopenbacklogsin_family_SC_LEVEL1_ICACHE_ASSOCpIovrlim_maxm_iKillSentm_fdListen_SC_AIO_PRIO_DELTA_MAXvalidateHeadersst_atimm_statusm_reqBodyLensig_numoptargSOCK_RAWsnprintfold_int_SC_2_C_BINDs_enable_lve__clock_tparseRequestIPPROTO_RAWstrdupbufLen_SC_PRIORITY_SCHEDULING_SC_SS_REPL_MAXsys_errlistsival_ptrpStderrLogsetpgid__uid_tdaylightsi_stimeoptoptLSAPI_ReqBodyGetChar_rpKeysun_family__uint16_t_SC_FSYNCsin_portgetpeernameLSAPI_is_suEXEC_DaemonLSAPI_Is_Listen_rLSAPI_End_Response_r_SC_FILE_ATTRIBUTESsetreuidserverAddr_SC_NZEROm_pQueryString__gnuc_va_list_SC_2_C_DEV_chainpContentLen_call_addrEnvForeachnewfdm_iServerMaxIdleSOCK_NONBLOCKusleepSOCK_RDM_SC_SYMLOOP_MAXsockaddr_un_ISblankunsigned charIPPROTO_MAX_SC_MQ_OPEN_MAXSOCK_DGRAMm_tmReqBegin__fd_mask__blkcnt_tlsapi_enterLVE__builtin_calloc_IO_lock_tLSAPI_Is_ListenIPPROTO_COMPLSAPI_key_value_pairlsapi_check_pathLSAPI_ForeachHeader_rpHeaderName_SC_SEM_NSEMS_MAX_SC_USHRT_MAXLSAPI_FinalizeRespHeaders_r__read_alias__fdelt_chkshouldFixEndianpBody_SC_STREAM_MAX_SC_ASYNCHRONOUS_IOserverMaxIdle__open_alias_SC_READER_WRITER_LOCKS_SC_CPUTIME__getcwd_alias_SC_2_PBS_LOCATE_SC_DEVICE_IOsa_flagspVecgeteuid_SC_SIGNALS__ctype_b_loc_SC_V7_ILP32_OFFBIGstatusoff_tchild_statuss_notified_pids_max_reqsH_X_FORWARDED_FORs_pid_dump_debug_info_ISalpha__fprintf_chktm_zone__mode_tm_queryStringOff_SC_V7_LP64_OFF64_SC_NPROCESSORS_CONF__RLIMIT_SIGPENDINGfdInlsapi_changeUGidtv_usec_SC_XOPEN_XCU_VERSIONold_childold_termLSAPI_sendfile_rlsapi_lve_erroraccept_SC_MEMLOCKallocateRespHeaderBuf_ISprintsched_yieldpMessages_liblvepValueH_CONTENT_LENGTHm_tmLastCheckPoint__vfprintf_chk_ISalnum_SC_SEM_VALUE_MAXs_req_processedstrtollopen_SC_XOPEN_XPG2_SC_XOPEN_XPG3_SC_XOPEN_XPG4LSAPI_STATE_CONNECTED_IO_write_ptr_SC_REALTIME_SIGNALSsystemlsapi_packet_headerIPPROTO_ENCAP_ISspacelsapi_suexec_authgetLFg_prefork_serverva_list__suseconds_treqsexitLSAPI_CreateListenSock2__rlim_ts_ignore_pid__RLIMIT_MEMLOCKpCurpHeaderValue__sizesizes_slow_req_msecslsapi_init_children_statusgetuidFILEH_COOKIELSAPI_ParseSockAddrdlsympthread_lib_SC_PII_INTERNET_DGRAM_SC_SINGLE_PROCESSbyteReversedump_debug_infoLSAPI_Accept_Before_Fork_SC_SHRT_MAX_ISxdigit_SC_RAW_SOCKETSfp_lve_enterLSAPI_AppendRespHeader_rsize_tH_CONNECTIONLSAPI_GetHeader_r_SC_XBS5_LPBIG_OFFBIG_SC_MULTI_PROCESSs_stderr_log_pathm_statefp_lve_instance_init_SC_BC_BASE_MAXH_CONTENT_TYPELSAPI_STATE_ACCEPTING_SC_RTSIG_MAX_SC_NETWORKINGachCmdH_ACCEPT_SC_GETGR_R_SIZE_MAXperrorcompareValueLocation_SC_THREAD_ATTR_STACKADDR_SC_LEVEL2_CACHE_ASSOC_SC_IOV_MAX_SC_TRACE_EVENT_NAME_MAX_SC_PII_INTERNETIPPROTO_IGMPpServerAddrlsapi_acceptlsapi_initLVE_IO_save_baseLSAPI_Release_riovecold_usr1maxIdleChldsocklen_tm_iMaxChildren_SC_2_UPEai_canonnameIPPROTO_IPV6_SC_DELAYTIMER_MAXpw_dirsa_mask__sigval_tLSAPI_Set_Extra_Childrens_restored_ppidsin6_flowinfototalLenm_pid_SC_SYSTEM_DATABASElsapi_prefork_server_acceptm_pIovecToWritecodem_respHeaderLen_wide_dataH_IF_MATCHai_family__nlink_tsi_addrst_inost_modeLSAPI_IsRunning_SC_T_IOV_MAXCGI_HEADER_LENIPPROTO_DCCP__in6_uGNU C17 8.5.0 20210514 (Red Hat 8.5.0-18) -mtune=generic -m64 -march=x86-64 -g -O2 -fPIC -fexceptions -fstack-protector-strong -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection=full -fplugin=gcc-annobinGetHeaderVarH_ACC_CHARSET__stream_SC_XOPEN_STREAMSm_iMaxIdleChildrensendfile_IScntrlm_reqBufSizelsapi_child_statusprctlallocateEnvList_ISupperpStatuserr_nosival_intsi_codem_pReqBufwait_timestrcasecmpH_IF_UNMOD_SINCEpw_name_SC_TRACE_USER_EVENT_MAX__socklen_tsend_notification_pktlsapi_requestpKeyEndcurTimefprintflsapi_writev__ssize_t__srclsapi_closepChrootH_IF_RANGEtimespecnameOff__u6_addr8strerror__RLIMIT_RSSavoidForkm_packetLenLSAPI_ReadReqBody_rIPPROTO_MPTCP_SC_2_FORT_RUNbindfp_lve_leave__valin6_addr_SC_ADVISORY_INFOpacketLen__timezone__ctype_toupper_locsin6_addr_SC_TIMER_MAXpBufCur_SC_THREADSunset_lsapi_envs__sighandler_t_SC_USER_GROUPS_RLSAPI_Set_Server_fdLSAPI_CreateListenSock__RLIMIT_LOCKSm_respPktHeaderEndLSAPI_On_Timer_pfLSAPI_Set_Max_Reqs_SC_UINT_MAXst_uids_conn_close_pktLSAPI_Postfork_ParentpEndpktTypelsapilib.cset_skip_write_SC_TRACE_NAME_MAX_lowers_busy_workers_SC_THREAD_DESTRUCTOR_ITERATIONSm_flagmemsetlevelstderrm_pHeaderIndexnameidle_SC_CHILD_MAXlsapi_reopen_stderr2_IO_save_endtm_min__nptrLSAPI_InitLSAPI_Request_SC_V6_LP64_OFF64flag_SC_NGROUPS_MAXm_bufProcessedfixHeaderIndexEndianstdoutfp_offsetlsapi_MD5TransformLSAPI_Write_Stderr_r__time_t_SC_THREAD_ROBUST_PRIO_INHERITgp_offset_padLSAPI_ForeachOrgHeader_rsigaddsetLSAPI_Inc_Req_Processedm_httpHeaderLendyingrealpathtm_yday_SC_SSIZE_MAX_SC_PII_OSI_CLTS_SC_SYSTEM_DATABASE_RmsecspAuth_SC_LEVEL1_DCACHE_SIZEkeyLenextraChildrenLSAPI_Flush_rshort unsigned intrlim_cursigned charLSAPI_Reset_rs_lveold_ppidLSAPI_CB_EnvHandler_valueLen__blksize_t_SC_STREAMSSOCK_STREAMdigestpBufEnd_SC_PAGESIZE_SC_THREAD_PRIORITY_SCHEDULINGcountsi_pidIPPROTO_MTPs_stop_SC_CHARCLASS_NAME_MAXlsapi_header_offsetstrchrvfprintfsetgid_boundstm_wday__off64_t__fd__lenachBuf_sigsys_IO_read_base_SC_XBS5_ILP32_OFFBIGsend_req_received_notification_offsetIPPROTO_EGPLSAPI_reset_server_statesockaddrsigset_ts_defaultGids_keep_listenersecsm_cntUnknownHeadersreadfdsai_addrlenlongsopterr_SC_DEVICE_SPECIFIC_RLSAPI_Set_Restored_Parent_Pidpw_gecos_modem_iExtraChildrenLSAPI_No_Check_ppid_SC_PIPE_IO_write_base_SC_XOPEN_CRYPTvalueLenm_respInfotz_dsttime_SC_PHYS_PAGESlsapi_enable_core_dumpH_CACHE_CTRLH_COOKIE2_SC_ATEXIT_MAX__desttm_monclose_SC_SHRT_MIN_SC_FIFObitstimeH_USERAGENTs_min_avail_pages_SC_USER_GROUPSm_lLastActiveLSAPI_ForeachEnv_rlong intSOCK_PACKETsa_sigactionnotify_req_received_SC_XBS5_ILP32_OFF32dumps_worker_status_IO_marker__builtin_strncpys_ppidtm_yearlimitmax_children_SC_2_PBS_MESSAGEm_pRespBufEndtimevalorig_masktmCur_SC_XOPEN_REALTIME_THREADSfp_lve_is_availablepAddrs_defaultUidm_pChildrenStatus__fds_bits_SC_SPIN_LOCKSLSAPI_Set_Server_Max_Idle_Secswritem_bufRead_SC_SPORADIC_SERVERlsapi_close_connectionuint8_t_SC_LEVEL1_DCACHE_LINESIZE__sigaction_handlerlsapi_signal_SC_PRIORITIZED_IOin_addrSOCK_SEQPACKET__pid_t_IO_codecvt_SC_GETPW_R_SIZE_MAXpUgidheadershints_SC_XOPEN_VERSIONH_RANGE_SC_BC_SCALE_MAX_SC_2_C_VERSIONdup2strtolg_reqlong doubleparseEnvai_socktype_SC_THREAD_KEYS_MAXiov_len_SC_LEVEL4_CACHE_LINESIZEfd_setlsapi_MD5Init_SC_NL_TEXTMAXnonblocklong unsigned intlsapi_req_header_SC_LOGIN_NAME_MAXfind_child_statusIPPROTO_PIM_SC_XBS5_LP64_OFF64_SC_SPAWNmaxChildrennewlensi_statussigemptyset_pkeym_headerOff__RLIMIT_OFILEHTTP_HEADERS_SC_2_PBSs_proc_group_timer_cbpw_gid__errno_location/builddir/build/BUILD/opt/alt/ruby26/lib64/ruby/gems/2.6.0/gems/ruby-lsapi-5.5/ext/lsapi_SC_WORD_BITchar_SC_2_PBS_ACCOUNTINGm_pSpecialEnvListsin6_scope_idstdin_SC_AIO_MAX__oflag_SC_2_CHAR_TERMresolved_path_SC_LEVEL1_ICACHE_LINESIZE_IO_buf_baseai_flagsrealloc_SC_XOPEN_SHM__dev_t_SC_XOPEN_ENH_I18Nold_quitRLIMIT_CPU__glibc_reserved_IO_read_end_SC_ULONG_MAX_SC_TYPED_MEMORY_OBJECTS_SC_TIMEOUTS_SC_LEVEL2_CACHE_SIZEfinal_SC_XOPEN_UNIXm_pRespBufPos_IO_FILEin_addr_tm_fdH_HOST_IO_wide_datacookiestrlentzname_sifields_SC_LEVEL2_CACHE_LINESIZE__u6_addr16s_pidIPPROTO_AHLSAPI_ReqBodyGetLine_rtm_hoursetsidFlush_RespBuf_r_SC_THREAD_STACK_MINisPipe_SC_PII_OSI_Mm_respHeaders_global_counterRLIMIT_AS_SC_NL_MSGMAXsi_signom_pAppData__RLIMIT_MSGQUEUEachAddrm_inProcess_SC_THREAD_ROBUST_PRIO_PROTECT_ISgraph_lsapi_prefork_servertm_mdaypIntegerlsapi_siguser1__pad0_SC_BC_DIM_MAX__pad5_SC_LEVEL1_DCACHE_ASSOCmallocs_dump_debug_infos_avail_pages__u6_addr32_headerInfom_typesi_errnofinish_closelistensigno_SC_XOPEN_REALTIME_markersLSAPI_InitRequest_SC_SAVED_IDSpBindm_scriptFileOff_SC_INT_MAXsi_bands_log_level_namess_skip_writeH_VIAmemccpy_codecvtforkIPPROTO_ESPm_pRespHeaderBufEnd_SC_TRACE_LOGgetpwnamtimeout_SC_THREAD_PRIO_PROTECTg_fnSelectRLIMIT_FSIZE__builtin_memcpyst_rdevlsapi_http_header_indexpEnv_SC_OPEN_MAXst_devssize_tdlerrorheaderIndex_SC_UIO_MAXIOVLSAPI_Logm_pRespHeaderBuf__int32_tH_PRAGMA__uint32_tqsortpSecretFile__RLIMIT_NLIMITS__daylightIPPROTO_RSVPstrncpyH_REFERERIPPROTO_UDPLITESOCK_CLOEXECLSAPI_Set_Slow_Req_MsecsLSAPI_Prefork_Accept_r_sys_siglisthandler_SC_CHAR_MAXLSAPI_Get_ppid_ISlowerpEnvEndsigprocmaskm_pUnknownHeadergetpwuidm_reqState_SC_PII_XTIpRespHeadersleftkillsysconfm_pRespBufm_iCurChildrensocketLSAPI_Write_r_SC_PII_OSI_COTSm_totalLenpasswdm_pIovecs_stderr_is_pipefstat__snprintf_chk_SC_PII_SOCKET__gid_tlsapi_sigpipe_SC_V6_LPBIG_OFFBIG_SC_MQ_PRIO_MAXgetcwdH_TRANSFER_ENCODINGH_IF_MODIFIED_SINCE__bsxai_nexts_enable_core_dump_SC_TRACE_EVENT_FILTERnodelaysin6_family__resolved_freeres_buf_sigfaultm_iChildrenMaxIdleTime_SC_THREAD_CPUTIMEsi_utimetv_sec_SC_VERSIONm_cntSpecialEnv_SC_C_LANG_SUPPORT_Rlong long unsigned intmemmovesa_handlersin_addr_cur_columnlsapi_load_lve_libtoWriteuid_t_SC_PIIsi_fd_SC_MAPPED_FILES_SC_LEVEL4_CACHE_SIZEIPPROTO_BEETPHfp_lve_jail_SC_2_FORT_DEVIPPROTO_IPm_pRespHeaderBufPosst_blockslsapi_initSuEXEC__bswap_16getpid__buf_SC_2_LOCALEDEFm_cntEnvlocaltime_r_SC_LEVEL1_ICACHE_SIZEreadBodyToReqBuftm_gmtoffIPPROTO_PUP_namesigval_IO_backup_baseH_KEEP_ALIVE_IO_read_ptr_SC_CHAR_BITLSAPI_Register_Pgrp_Timer_Callbackmd5ctx__socket_type__nbytes_nameLengetenv_freeres_list__aps_max_busy_workersIPPROTO_ETHERNETH_IF_NO_MATCHpEnvListrlim_tlsapi_readsun_pathtimezoneCGI_HEADERSsi_overrun__bswap_32pReq_SC_INT_MINlsapi_MD5Update_SC_RE_DUP_MAX_SC_PII_INTERNET_STREAMachBodyachPeerheader_SC_THREAD_ATTR_STACKSIZEfull_path_old_offset_SC_SIGQUEUE_MAXsiginfo_t_SC_FD_MGMTexpect_connected_SC_SYNCHRONIZED_IOLSAPI_STATE_IDLEvalueOffsighandler_t_SC_V7_ILP32_OFF32skipunlinksend_conn_close_notificationoptinds_accept_notifywritevH_ACC_LANG_SC_EXPR_NEST_MAX_SC_LEVEL3_CACHE_LINESIZElong long intm_pktHeaderin6addr_loopbackports_accepting_workersIPPROTO_IDP_flags2lsapi_prefork_serverallocateIovec_SC_MESSAGE_PASSING__ch_SC_REGEX_VERSIONm_iLenLSAPI_Set_Max_Children__d1setuidtv_nsecm_scriptNameOfflsapi_perror_SC_FILE_LOCKING_SC_AVPHYS_PAGES_SC_MB_LEN_MAXpHeader_ISdigitsockaddr_in6IPPROTO_SCTP_SC_PII_OSI_SC_ARG_MAX__ino_tsetsockopt_SC_MEMLOCK_RANGELSAPI_Finish_r_SC_SHARED_MEMORY_OBJECTSlsapi_resp_headersys_nerrin6addr_anym_pRequestMethodachError_SC_CHAR_MIN__realpath_chkiov_basem_lReqBegins_uids_total_pagespw_shell__namem_versionB0m_versionB1IPPROTO_GRE_SC_XOPEN_LEGACY_SC_NL_ARGMAXRLIMIT_COREsi_tidtobekilled_SC_THREAD_PRIO_INHERIT_SC_LEVEL3_CACHE_ASSOC_SC_NPROCESSORS_ONLNm_headerLenexpect_acceptingm_pIovecCurfdListenLSAPI_Init_Env_Parametersaddr_len_SC_HOST_NAME_MAXIPPROTO_TCPLSAPI_AppendRespHeader2_r_SC_COLL_WEIGHTS_MAX_SC_MONOTONIC_CLOCK__rlimit_resourcem_reqBodyReadLSAPI_Set_Max_Idle_SC_CLK_TCKLSAPI_ForeachSpecialEnv_rlsapi_buildPacketHeaderLSAPI_perror_r_SC_NL_SETMAXunsigned int_SC_BARRIERSbodyLenpBeginLSAPI_Accept_rwait_secslsapi_reopen_stderrstrcmpst_mtim__statbuf__RLIMIT_NICEfn_select_tshort intlsapi_notify_pidsi_sigvalsetrlimit_vtable_offsetaddrinfo_SC_IPV6mmapIPPROTO_ICMPlsapi_sigchild_SC_REGEXPlsapi_schedule_notifyLSAPI_Get_Slow_Req_Msecs_SC_V6_ILP32_OFFBIGstatmemchrtz_minuteswestsys_siglistH_ACC_ENCODINGsin6_portm_iMaxReqProcessTime__RLIMIT_RTPRIOGCC: (GNU) 8.5.0 20210514 (Red Hat 8.5.0-18)GNUzRx 0D LXsEIB E(A0z (A BBBI A (D BBBA  @YGJB B(A0A80F(B DBb0BFC G  AABK Hk(\GADJ n AAA 4UAGK R CAG L JCG AG] AJ t C KFLBBE A(H0H (D BBBD  (D BBBA PXvFB A(D0D (A BBBB L(A BBBA$aAAD XAAHBBB B(A0A8D@N 8C0A(B BBBH $ OAf Q C E H@HYBBB A(D0J 0A(A BBBF xFEA C(G   (A ABBD M I c A  E M A k E E E E H V HFBB B(A0A8D`` 8A0A(B BBBD lT+BBB B(A0D8JYHPC Mi 8A0A(B BBBE LTMDd6BBB B(A0A8DP 8A0A(B BBBG  8J0H(G DBBK $,7EFF IIOTh|  4FAA G>  AABG EO D  A  (Y<JEDXS l]Ph H XAHlFBB B(A0A8LP 8A0A(B BBBH < FBB A(A0 (D BBBI i`0FBB B(A0A8DP~ 8A0A(B BBBA k 8A0A(B BBBH L$FBB A(A0H Q D 0A(A BBBH LFBB B(A0A8G 8A0A(B BBBF 4FHF\$pnCXJLlFBB B(A0A8DA 8A0A(B BBBA `BBB B(A0A8G I K I L N N w 8A0A(B BBBI 0L BMD GL  AABA < =BAA G L@I@U  AABG $ TWEHG ag H SH FBB B(A0A8DPS 8D0A(B BBBF TX bIE D(C0P (F BBBM Q(H BBBAH FBB B(A0A8DP 8A0A(B BBBA T CBA A(G0` (A ABBD  (C ABBA J8T -FBD D(D@T (A ABBB  ( lECGF AAI L !cBG A(D0 (A ABBE XD0 4 ZH 10\ pFAA G@7  AABF  @LsL FBB B(A0A8G 8A0A(B BBBG   $ 8 L ` t     <  FBA K(G (A ABBG <FEE D(D0M (C BBBB X(HlFBH E(A0E8I@ 8A0A(B BBBE (FED ABH BBB B(A0A8G 8A0A(B BBBJ D0FBB A(A0G 0A(A BBBF Lx FBB B(A0A8G  8A0A(B BBBA    1 -  E2a~345.IWul -- "0s-Je s z )Y)2L0Yz+ k + w 0 Gw : X Ui s  s    x 5 P _ s(0x *  * # N0 al |  O& - =h9Y9 @ $@O e` rU+66 %  7 6S wm w   l      4 f   x    ]  '  ; ]\ m{ m     *+ *L k    \ \" k C k b    "   " $%@ `d0$%UE'xdE'''''D(m())* *+7+F+c,~, 0,.,=.u/*7u/[)0})011224C4k55667!7G7k78d X 8 8+8S:9y:9q9P q9: #h 3 (B:g0;0;H?   @  H?'^?GR^?tk?k????,?V?~???@,@T@z @+@+@?@?@;K@WK@TI ) p h d ` P H @# 80 X6TIYIzIJJJJ K(K?WTK \(b $o(|WUYUYZd Zd>qdiqdd!#$&()+2345671828F"KO(pRP [oy#)/5;AG8MXSY_ekqw+}=Nbw*@V %]+o17=CpIO@U[Tahgtms8yp6&(P,-./0) >Mcmy 1   " / 9 @C R a h v      @7      ! !'! #S!3!8!C!RK!@ Q!X!^!` p!p!Y!J!!0S!]!l!!!` "p i" %","@"#$Y"_"0%u"P'F"'F"'"(")l""""# #.#/1#00?#2P#Y#2s#z#4#5-#####7# 7l#7! $$$!$85$8ZN$@91a$9pv$:@$$0;$$$$P?$`? $p?%?%?:%?V%?u%@ % @ %0@%@@ %P@ %%%%&&& &`I4&I(B&JR&Ka&j&q&{&&&&&W&`Y &&&`d&d '.annobin_lsapilib.c.annobin_lsapilib.c_end.annobin_lsapilib.c.hot.annobin_lsapilib.c_end.hot.annobin_lsapilib.c.unlikely.annobin_lsapilib.c_end.unlikely.annobin_lsapilib.c.startup.annobin_lsapilib.c_end.startup.annobin_lsapilib.c.exit.annobin_lsapilib.c_end.exit.annobin_lsapi_sigpipe.start.annobin_lsapi_sigpipe.endlsapi_sigpipe.annobin_lsapi_siguser1.start.annobin_lsapi_siguser1.endlsapi_siguser1g_running.annobin_compareValueLocation.start.annobin_compareValueLocation.end.annobin_EnvForeach.start.annobin_EnvForeach.endEnvForeach.annobin_lsapi_cleanup.start.annobin_lsapi_cleanup.endlsapi_cleanups_stop.annobin_set_skip_write.start.annobin_set_skip_write.ends_skip_write.annobin_lsapi_MD5Transform.start.annobin_lsapi_MD5Transform.endlsapi_MD5Transform.annobin_lsapi_signal.start.annobin_lsapi_signal.endlsapi_signal.annobin_find_child_status.start.annobin_find_child_status.endfind_child_statusg_prefork_server.annobin_allocateRespHeaderBuf.start.annobin_allocateRespHeaderBuf.endallocateRespHeaderBuf.annobin_lsapi_set_nblock.start.annobin_lsapi_set_nblock.endlsapi_set_nblock.annobin_lsapi_accept.start.annobin_lsapi_accept.endlsapi_accept.annobin_parseEnv.start.annobin_parseEnv.endparseEnv.annobin_lsapi_init_children_status.start.annobin_lsapi_init_children_status.endlsapi_init_children_statuss_busy_workerss_accepting_workerss_avail_pagess_global_counter.annobin_readBodyToReqBuf.part.2.start.annobin_readBodyToReqBuf.part.2.endreadBodyToReqBuf.part.2.annobin_lsapi_close_connection.isra.4.start.annobin_lsapi_close_connection.isra.4.endlsapi_close_connection.isra.4s_worker_status.annobin_lsapi_writev.part.6.start.annobin_lsapi_writev.part.6.endlsapi_writev.part.6.annobin_lsapi_parent_dead.start.annobin_lsapi_parent_dead.endlsapi_parent_deads_ppids_restored_ppid.annobin_LSAPI_ParseSockAddr.part.13.start.annobin_LSAPI_ParseSockAddr.part.13.endLSAPI_ParseSockAddr.part.13.annobin_LSAPI_Log.start.annobin_LSAPI_Log.ends_stderr_is_pipes_log_level_namess_pid.annobin_lsapi_sigchild.start.annobin_lsapi_sigchild.endlsapi_sigchilds_pid_dump_debug_infos_ignore_pid.annobin_dump_debug_info.start.annobin_dump_debug_info.end.annobin_lsapi_check_child_status.start.annobin_lsapi_check_child_status.endlsapi_check_child_statuss_max_idle_secss_dump_debug_info.annobin_lsapi_perror.start.annobin_lsapi_perror.end.annobin_LSAPI_is_suEXEC_Daemon.start.annobin_LSAPI_is_suEXEC_Daemon.ends_uids_secret.annobin_LSAPI_Stop.start.annobin_LSAPI_Stop.end.annobin_LSAPI_IsRunning.start.annobin_LSAPI_IsRunning.end.annobin_LSAPI_Register_Pgrp_Timer_Callback.start.annobin_LSAPI_Register_Pgrp_Timer_Callback.ends_proc_group_timer_cb.annobin_LSAPI_InitRequest.start.annobin_LSAPI_InitRequest.end.annobin_LSAPI_Init.start.annobin_LSAPI_Init.endg_initedpthread_atfork_func.annobin_LSAPI_Is_Listen_r.start.annobin_LSAPI_Is_Listen_r.end.annobin_LSAPI_Is_Listen.start.annobin_LSAPI_Is_Listen.end.annobin_LSAPI_Reset_r.start.annobin_LSAPI_Reset_r.end.annobin_LSAPI_Release_r.start.annobin_LSAPI_Release_r.end.annobin_LSAPI_GetHeader_r.start.annobin_LSAPI_GetHeader_r.end.annobin_LSAPI_ReqBodyGetChar_r.start.annobin_LSAPI_ReqBodyGetChar_r.end.annobin_LSAPI_ReqBodyGetLine_r.start.annobin_LSAPI_ReqBodyGetLine_r.end.annobin_LSAPI_ReadReqBody_r.start.annobin_LSAPI_ReadReqBody_r.end.annobin_Flush_RespBuf_r.start.annobin_Flush_RespBuf_r.end.annobin_LSAPI_GetEnv_r.start.annobin_LSAPI_GetEnv_r.endCGI_HEADERS.annobin_LSAPI_ForeachOrgHeader_r.start.annobin_LSAPI_ForeachOrgHeader_r.endHTTP_HEADERSHTTP_HEADER_LEN.annobin_LSAPI_ForeachHeader_r.start.annobin_LSAPI_ForeachHeader_r.endCGI_HEADER_LEN.annobin_LSAPI_ForeachEnv_r.start.annobin_LSAPI_ForeachEnv_r.end.annobin_LSAPI_ForeachSpecialEnv_r.start.annobin_LSAPI_ForeachSpecialEnv_r.end.annobin_LSAPI_FinalizeRespHeaders_r.start.annobin_LSAPI_FinalizeRespHeaders_r.end.annobin_LSAPI_Flush_r.start.annobin_LSAPI_Flush_r.end.annobin_LSAPI_Write_Stderr_r.start.annobin_LSAPI_Write_Stderr_r.ends_stderr_log_path.annobin_LSAPI_perror_r.start.annobin_LSAPI_perror_r.endLSAPI_perror_r.annobin_lsapi_jailLVE.start.annobin_lsapi_jailLVE.endlsapi_jailLVEfp_lve_jail.annobin_lsapi_reopen_stderr.start.annobin_lsapi_reopen_stderr.endlsapi_reopen_stderr.annobin_LSAPI_Finish_r.start.annobin_LSAPI_Finish_r.endfinish_close.annobin_LSAPI_End_Response_r.start.annobin_LSAPI_End_Response_r.end.annobin_LSAPI_Write_r.start.annobin_LSAPI_Write_r.end.annobin_LSAPI_sendfile_r.start.annobin_LSAPI_sendfile_r.end.annobin_LSAPI_AppendRespHeader2_r.start.annobin_LSAPI_AppendRespHeader2_r.end.annobin_LSAPI_AppendRespHeader_r.start.annobin_LSAPI_AppendRespHeader_r.end.annobin_LSAPI_CreateListenSock2.start.annobin_LSAPI_CreateListenSock2.end.annobin_LSAPI_ParseSockAddr.start.annobin_LSAPI_ParseSockAddr.end.annobin_LSAPI_CreateListenSock.start.annobin_LSAPI_CreateListenSock.end.annobin_LSAPI_Init_Prefork_Server.start.annobin_LSAPI_Init_Prefork_Server.ends_max_busy_workersg_fnSelects_total_pages.annobin_LSAPI_Set_Server_fd.start.annobin_LSAPI_Set_Server_fd.end.annobin_LSAPI_reset_server_state.start.annobin_LSAPI_reset_server_state.end.annobin_is_enough_free_mem.start.annobin_is_enough_free_mem.ends_min_avail_pages.annobin_LSAPI_Postfork_Child.start.annobin_LSAPI_Postfork_Child.ends_req_processeds_keep_listeners_notified_pid.annobin_LSAPI_Postfork_Parent.start.annobin_LSAPI_Postfork_Parent.end.annobin_LSAPI_Accept_Before_Fork.start.annobin_LSAPI_Accept_Before_Fork.endold_childold_termold_intold_usr1old_quit.annobin_LSAPI_Set_Max_Reqs.start.annobin_LSAPI_Set_Max_Reqs.ends_max_reqs.annobin_LSAPI_Set_Max_Idle.start.annobin_LSAPI_Set_Max_Idle.end.annobin_LSAPI_Set_Max_Children.start.annobin_LSAPI_Set_Max_Children.end.annobin_LSAPI_Set_Extra_Children.start.annobin_LSAPI_Set_Extra_Children.end.annobin_LSAPI_Set_Max_Process_Time.start.annobin_LSAPI_Set_Max_Process_Time.end.annobin_LSAPI_Set_Max_Idle_Children.start.annobin_LSAPI_Set_Max_Idle_Children.end.annobin_LSAPI_Set_Server_Max_Idle_Secs.start.annobin_LSAPI_Set_Server_Max_Idle_Secs.end.annobin_LSAPI_Set_Slow_Req_Msecs.start.annobin_LSAPI_Set_Slow_Req_Msecs.ends_slow_req_msecs.annobin_LSAPI_Get_Slow_Req_Msecs.start.annobin_LSAPI_Get_Slow_Req_Msecs.end.annobin_LSAPI_No_Check_ppid.start.annobin_LSAPI_No_Check_ppid.end.annobin_LSAPI_Get_ppid.start.annobin_LSAPI_Get_ppid.end.annobin_LSAPI_Init_Env_Parameters.start.annobin_LSAPI_Init_Env_Parameters.ends_accept_notifys_enable_core_dumps_defaultUids_defaultGids_enable_lves_liblvefp_lve_is_availablefp_lve_instance_initfp_lve_enters_lve.annobin_LSAPI_ErrResponse_r.start.annobin_LSAPI_ErrResponse_r.end.annobin_lsapi_MD5Init.start.annobin_lsapi_MD5Init.end.annobin_lsapi_MD5Update.start.annobin_lsapi_MD5Update.end.annobin_lsapi_MD5Final.start.annobin_lsapi_MD5Final.end.annobin_readReq.start.annobin_readReq.endreadReqs_ackachBody.7025headers.7024.annobin_LSAPI_Accept_r.start.annobin_LSAPI_Accept_r.end.annobin_LSAPI_Prefork_Accept_r.start.annobin_LSAPI_Prefork_Accept_r.ends_conn_close_pkt.annobin_LSAPI_Set_Restored_Parent_Pid.start.annobin_LSAPI_Set_Restored_Parent_Pid.end.annobin_LSAPI_Inc_Req_Processed.start.annobin_LSAPI_Inc_Req_Processed.end.LC0.LC1.LC4.LC5.LC6.LC3.LC2.LC7.LC8.LC9.LC10.LC11.LC12.LC13.LC14.LC15.LC16.LC17.LC18.LC19.LC20.LC21.LC22.LC23.LC24.LC25.LC26.LC27.LC31.LC32.LC30.LC29.LC33.LC34.LC36.LC37.LC38.LC39.LC40.LC41.LC42.LC44.LC45.LC46.LC47.LC48.LC49.LC50.LC51.LC59.LC69.LC70.LC71.LC43.LC35.LC61.LC62.LC63.LC64.LC65.LC66.LC67.LC68.LC52.LC53.LC54.LC60.LC58.LC57.LC55.LC56.LC87.LC76.LC77.LC78.LC72.LC79.LC80.LC86.LC74.LC84.LC83.LC73.LC75.LC82.LC81.LC85.LC92.LC91.LC88.LC90.LC89.text.group.text.hot.group.text.unlikely.group.text.startup.group.text.exit.groupcompareValueLocationset_skip_write_GLOBAL_OFFSET_TABLE_sigactionsigemptyset__stack_chk_failreallocfcntlsetsockoptmmapmemsetsetsidread__errno_locationwritevkillgetppid__ctype_b_locstrncpystrchrstrcasecmpstrtolgetaddrinfomemcpyfreeaddrinfoinet_addrLSAPI_Log__vfprintf_chk__snprintf_chkgetuid__fprintf_chkgettimeofdaylocaltime_rwaitpidforksystemlsapi_perrorstrerrorLSAPI_is_suEXEC_DaemonLSAPI_StopLSAPI_IsRunningLSAPI_Register_Pgrp_Timer_CallbackLSAPI_InitRequestmallocgetpeernamedup2LSAPI_Initgeteuidg_reqdlopendlsymLSAPI_Is_Listen_rLSAPI_Is_ListenLSAPI_Reset_rLSAPI_Release_rfreeLSAPI_GetHeader_rLSAPI_ReqBodyGetChar_rLSAPI_ReqBodyGetLine_rmemchrmemmoveLSAPI_ReadReqBody_rFlush_RespBuf_rLSAPI_GetEnv_rstrcmp__ctype_toupper_locLSAPI_ForeachOrgHeader_rqsortLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rLSAPI_ForeachSpecialEnv_rLSAPI_FinalizeRespHeaders_rLSAPI_Flush_rLSAPI_Write_Stderr_rgetpidgetcwdmemccpy__realpath_chkstrdupLSAPI_Finish_rLSAPI_End_Response_rLSAPI_Write_rLSAPI_sendfile_rsendfileLSAPI_AppendRespHeader2_rstrlenLSAPI_AppendRespHeader_rLSAPI_CreateListenSock2socketbindlistenunlinkLSAPI_ParseSockAddrLSAPI_CreateListenSockLSAPI_Init_Prefork_ServercallocsetpgidsysconfLSAPI_Set_Server_fdLSAPI_reset_server_stateis_enough_free_memLSAPI_Postfork_ChildLSAPI_Postfork_ParenttimeLSAPI_Accept_Before_Fork__fdelt_chkusleepsched_yieldLSAPI_Set_Max_ReqsLSAPI_Set_Max_IdleLSAPI_Set_Max_ChildrenLSAPI_Set_Extra_ChildrenLSAPI_Set_Max_Process_TimeLSAPI_Set_Max_Idle_ChildrenLSAPI_Set_Server_Max_Idle_SecsLSAPI_Set_Slow_Req_MsecsLSAPI_Get_Slow_Req_MsecsLSAPI_No_Check_ppidLSAPI_Get_ppidLSAPI_Init_Env_Parametersgetenvgetpwnamenvirondlerrorsetrlimit__fxstatsetreuidLSAPI_ErrResponse_rlsapi_MD5Initlsapi_MD5Updatelsapi_MD5FinalgetpwuidsetgidsetgroupssetuidstrtollprctlinitgroupsLSAPI_Accept_rLSAPI_Prefork_Accept_rsigaddsetsigprocmaskLSAPI_Set_Restored_Parent_PidLSAPI_Inc_Req_Processedselectd \D   h o    2 9 H $O ,T g -o    h C M X h c z  h  h h a 8g.J5*T/0 *1%>Kw235R4Y5`6v\  "X 3/8M7`io89p3:?K_;<Rf=h{d h t8~KW>`i{h*$?*/?@GNw*"  ( h !A`!!!a"j#<q#\p$*}$$*$ %%%&A'((Y)))b***7+A+N+BW+_+}+C++++D,,{,D,,E,,h -n---F----.8.?.N.Y.~.G...H./*/ L/T/i/// /0_1111Q2v22/33-4O4|5N6h66666666I7W7777` 7` 77888#8-828<8G8T {8889'9G9$Q9L f9T 99999999999p:*:#:<:d G:Z:` d:h::::#:::: ;!;H;;;;;;|;;<<<<,<9<V<x<t<\ <<<$< :=S=e=o=}=|====<====>/>I6>@> F>w> > >>J>?K ??L#?D?Y?f?w?????@&@6@F@_@M@@@N@@@O@@@d @P@A'AQ,A@AFA%MARRAfAmAtASyAAhATAAAAAUAAAVA BBBW B4B;BBBXGB[BbBiBYnBBBBZBBB[BBB` B\BBBBhC` C\C]#C2Cd?CdEC`TC^YCqCwC\ChC*ChC_C`CazD` DDL D DbDDcE%E`1ENEUE*\EpEduEELEeEEDEE\EfEEgE<EEhEEiF4 FFjF%F,,FTGFkLFSFTXF_FPFFFFFlFFFdGm GG(G`/Gn4GQGmGG|GGGGdG`HoHH\"Hd,H`6H`DH\ZHXyHLHpHHHH<HTHHhHHDHXIh IIq+Ir7IAIKIsIIIIJJzK9LDLOLh JMUMdMh M4NOtOPuP*P.RhDR%JR$]R#}RRdR`RvSwmS|S!S"S"S# T$TT/T4GT+uT%T&T'TlThTTMTUU|*U$1UGUxSUeU}U(UyUUzUUdU`U$UTU)V{V V|,V=V%eV%V}V*V~V[VdV`V$VWW+W9WPWYWyWWW WWXh BXUXhXX$XXh XY$ YGYQYxYYYYYYYYh #Zh 3Z?ZeZ ZZZp[[[[[\C\\\t\\ \\\$] ^]u]]]]^^4^d B^$X^$]^s^^^^^_d __c +_D_c__ _ _ __I__ ` `%`\`k`-|`.```.``` a,aJ5abaqa` aa` aaaaaaabbh 3bK8bGbXb.gbpbvb{bbbbbbpb*bbbd bc` ch$cCcTcecvcccccc#ccLccd dd9dKdVdfdldd, s|2J +$,PX---D-Lpx 08)dl)))+ $,+ P+ Xw + w w  w   s D Ls ps x s   x  x 0x 8* dx l* *  *   $ ,PX99 9 D 9L p x       0 8 6d l 6 6 w 6 w w $ w, P X         D L p x     ]  ]0 ]8 md ]l m m  m   $,PX****DLpx\\\k \ k 0k 8 dk l  " ""$%$",$%P$%XE'$%E'E''E''''D'L'p'x('(()( )0)8*d)l**+*++,$+,,P,X.,..u/.u/u/)0Du/L)0p)0x1)01121 20284d2l4454556$5,6P6X767777778D7L8p8x8888:98 :90:98q9d:9lq9q9:q9::0;$:,0;P0;XH?0;H?H?^?H?^?^?k?D^?Lk?pk?x?k????? ?0?8?d?l??????@$?,@P@X@@@@+@@+@+@?@D+@L?@p?@xK@?@K@K@TIK@ TI0TI8IdTIlIIJIJJJ$ J, JP JX K J K K W K W!W!UYD!WL!UYp!UYx!Zd!UY!Zd!Zd!qd"Zd "qd0"qd8"dd"qdl"d % & ' (]CC C(X 01CC3C9C> CE(CJ0CP8CU@C[HCbPCqXC`ChCpCxCCCCCCCCCCCC+C4CHCSCYCiCm C(C0C8C@CHCPCXC`ChCpC!xC+C7CDCTCgC~CCCCCCCC  $ $q $%) #0 $8 < $C $7J $$Q $V $d $7n $ z $+ $+ $! $& $ $p- $K4 $ $ $q $,  $# $' " $Q. $: $!M $[Y $ e $Uq $ $(& $ $ $s, $ $4 $i $ $ $ ) $/  $F $ $  $  $e, $9 $z.F $3T $`8a $=+n ${ $ $ $6 $j $L) $ + $ $  $/ $  $u7  $ $'5 $A $rM $ /b $ $F  $ $,0 $ $  $ $ $ $~5 $91 $7( $5 $B $7Y $f $s $F% $q. $  $ $ $y $\% $ $ $ $H*( $/? $ L $Y $Qp $| $  $ $9 $=. $M $H $( $) $ $L) $', $18 $^ $.j $! $ $h# $ $ $$ $B, ${8 $2 $.. $D+: $^F $e"S $z.` $Dn $z  $" $$ $  $ $ $  $ $ $< $'( $5 $P0B $!'O $P\ $ i $v $E $& $I $T $30 $, $) $  $ $23 $1 $. $7 $o, $9 $F $}*S $` $0m $0.z $b) $e $ $ $ $" $# $' $ $b&& $2 $> $4Z $ f $6x $'~ $* $ $. $r5 $ $ $n% $( $t $g $ $ $( $7 $8 $ $+ $U $ 1 $y $  $  $r, $49 $r$G $S $0e $sk $b q $ w $ } $# $ $! $, $ $ $ $ $V $$1 $l8 $ ( $+-5 $B $O $\ $%i $\ v $ $5 $ $9 $5( $,) $*! $*" $$ $u $ $0 $= $ I $+U $:a $'m $ y $$1 $C $?4 $  $6 $w $0+ $ $ $ $* $ $X $ $ $# $2 $  $ / $  $^4 $ $]3 $$ $4* $10 $h&6 $ < $B $R H $-N $.T $Z $[` $f $)l $1r $cx $&~ $S) $ $ $ $a6 $* $2 $f $p1 $ $  $  $  $b/ $ $ $/ $/ $, $a- $ $34 $ $d $`+ $ $1 $  $-& $, $p(2 $8 $y> $5D $J $#P $$V $\ $b $^$h $T(n $t $z $1 $ $5 $* $ $ $5 $  $3 $! $ $# $L $~' $  $& $& $|& $$ $ $X $g $v $]0  $W, $4 $<* $T1" $f( $&. $34 $ : $}@ $ F $XL $\R $7!X $O^ $)d $.'j $1p $d5v $ | $( $h $ 7 $$ $! $^ $% $ $S5 $) $}" $ $%7 $0 $ $. $ $ $^. $  $ $(  $1 $D!  $  $Y  $3 $$ $v6* $0 $6 $i< $B $"H $8N $v3T $Z $0` $)%f $#l $r $=x $~ $U' $<' $u! $ $% $-& $ $E" $  $  $g $$  $ $L8 $` $- $)6 $2 $- $ $* $/ $b  $& $ $i) $M#  $b'& $, $'2 $8 $5> $2D $1/J $ P $z$V $7\ $sb $Q2h $Jn $t $z $p  $ $ $ $ $ $ $( $  $2 $!  $  $E# $^ $ $' $# $9 $q/? $7E $ K $; Q $;6W $] $0c $i $&3o $u ${ $ $+ $G5 $* $( $ $G/ $ $ % $  $&4 $+ $9  $0 $>  $ $F  $ $ $( $)N $[ $ n $4z $2 $ $W  $  $. $ $4 $. $8 $  $Y $T&- $7; $&I $W $R$e $ys $  $ $ $- $#  $  $1 $ $  $8 $2 $% $" $6( $. $4 $ !: $'@ $+F $+L $W!R $ X $-^ $d $0j $yp $v $C0| $$ $ $o* $- $3 $ $ $/5 $;5 $) $ $ $$ $2  $V- $ : $,*G $3T $a $Q n ${ $/ $. $+ $5 $b% $ $ $ $;2 $  $- $q: $ H $4U $2b $ r $=$w $  $  $ $ $  $" $  $' $! $4 $ $O $," $W"/ $'< $y+I $*V $|/c $kp $2-} $ $5 $m $ $? $% $B& $ $ $ $,  $ $& $ 3 $@ $4M $ -Z $,g $ t $6 $ $# $W $~( $ $( $\ $7 $ $  $( $ " $/ $d < $m I $ $R $7$ $= $7+ $O $i $M! $ $*2 $ $E $\ $! $  $gl $ $#"1: $GP $ (]f $s| $h  $) $ $; $b* $ $,5 $3BK $(X0a $0nd w $ $;- $Z`  $5X  $c!P  $)( # $09 $%Fx_ $-1l  $ $}%@ $` $P* $D2 $- p $ 5 l( $"6 h? $M dV $ d `m $ r $. X $ P $" H $ @ $0*! $8!8[! $! $V/!0! $2!)! $K! $~! $x!(! $ !(" $=" +" $)9"B" $)P" $&0^" $0l" $z" $Q" $*"" $)" $'" $" $k " $," $*" $ # $G.# $8# $,# $":# $H# $0W# $:3d# $r# # $## $"## $## $l## $&## $ $@ $ $x$"$ $b0$9$ $CF$ $>R$dy$ $> $`d$ $4$ $ $ $$$ 1$ - % % j % ~$% R3% 7% pF% hJ% @V% $ ^%Ku% $% % % X% P% $% % % ( % " %3K%3K% s % q %  &  &  &  &QK$&QKA&  E&  N&  R&  [& 8 _& 6 i&pKs& " & _ & [ &  &  &  &  &~K&K& "`&  &  &  &  & M & K 'K ' "' r !' p *'  .'  7'  ;'  A'QK_'K' $`1'J'  '  '  '  ' h ' \ '  '  ' "@ ( ( (dJD(|JN( "p_( c( l( p( y( @}( <(J(J(J( "( ( ( ( ) )  )J/)J9) "J) $N)  W) d[) bd) h) m)J{)J) $$)I) $') $ ) $ *`I"* $O1.* 2* 7* $}C* G* L* $,X* \\* Ra* $m* q* v* $27* <* 4*dI* "* * * * *I*I*I+IB+ $6N+P@p+ t+ + + + + + + + $+ + +pF+ $2"+F ,@,@3, 7, <,@Y,@c, " t, 6x, 4},@,A,A, ], Y,A,5A,5A- - -DA:-[AD-[Aa- e- j-jA-A-A- - -A-A-A- - .A!.B+.BH. )L. 'Q.Bn.)Bx.)B. N. L.8B.PB.PB. s. q._B/wB/wB// 3/ 8/BU/B_/B|/ / /B/B/B/ / /B/B/ " 0 " 0  0 0 E 0 ?)0 " 60 :0 C0FM0Fj0 rn0 ps0F0G0G0 0 0"G0DG0 " 0 0 1 " 1 1 r 1DG*1DGG1 K1 T1 AX1 ;]1UG1`G1`G1 1 1 1 1qG1G1G 2 2 2 A2 ?%2 o)2 m.2GE2U2Gm2H2H2;I2]2F2C]2G3Co 38G3C&3'C73CVG3QCQ3 "@ ^3 "@ g3 k3 t3fC~3fC3 3 3uC3hE3 " 3H3  3 3H 4H#4I84yEM4C^4Ey4C4E4E4 " 4 " 4 Z4 V4E4C4E4C5E#5C-5FH5CR5"Fm5Cw5PF5]5\F5H5]C5C5 H5C5C5C6C*6 .6 760DL6 P6 \6Ff6F6 4 6 2 6F6F6F6@6C7@7@#7C-7@B7C+L7@a7C=k70A7CN7VA7Cb7qA7}A7Cw7A7C7A8A8A#8C-8AB8CL8BY8$Bn8Cx8?B8KB8C8fB8rB8C8B8B8C8B 9B9C*(9B=9C@G9D_9Dl9D9C9E9C95E9RE9`E9EI9 $Z7: $14: $F: $1S: $ a: $ ~: $x': $]: $&: $/; $3; $d,?;@@R; $| Z;0@m; $38y; @; $,;@; $; $";?; $; $B;? < $< $5!<?8< $H< $P<?g< $w< $3<p?< $3%< $6<`?< $< $<P?< $/= \ = X = $+,=`Y-= $O19=  ==  M= !!Q= !b= !f= !k= $P7w= ="{= /"= $ = $*= "= $ = $3=aZ= "= "=iZ >(_ > $,> #0> #:>@[D> "U> ($Y> $b> ($f> $o> $s> $x> "> %> %> 0&> &> 5'> +'> '> '> (> '> I)> /))? "A?]Z? W*^? S*c?]u?`_? *? *?_?_?_?c? "? +? +? "@c@ " @ +$@ +-@ +1@ +:@  ,>@ ,H@cR@co@ 1,s@ /,|@ W,@ U,@ },@ {,@c@c@E[@t[@[ A[#A[HA[mA"\AG\A\A` A\A\A\B\&Bb]LBy]YB]}B_B]B_B@`BS`B``Bo`C`EC`RC`_C`C`C]CaC9aCCCaC](CaCaD]D$J>2Ju;?J;WJ;wJJ;J;JJ<J@J!< KK=<7KAK<RK` \K<sK<K<K<K>=KW=Ks=K L=$L3L=ML\L=vL@L=LL:>L]LD>L>L> M> MC*M??MCIM'?^M]hM5?MH?M $NM:M $O1M 2M  2M ;M $8M a2M _2M;N%;N $N95N $O1AN 2EN 2JN $8"VN 3ZN 3cN:mN " ~N *3N (3N " N:N " N O3N M3N u3N s3N 3N 3N:N "P N 3N 3O 3O 3O 4O 4O:'O:HO9UO9bO9oO:OO::O:O:O:O $QO $O $O1 P $lP $&&P $ 3P $x@P $bMP $kZP $P7P $(P $8P $ P $*P $P $m"P $ P $3Q $Q $Q@91Q $|9QLQ $TQkQ $w"wQ G4{Q 94Q $Q 4Q 4Q $5Q o5Q c5Q $fQ 6Q 5Q $Q 6Q 6Q $Q ^7Q X7Q $dQ 7Q 7QCR]P&RO=R[R]eR|RR R]RR $3RR $R 8R 7S $w"S 8S 8S $x,S6SSS 8WS 8`S  9dS  9mS 69qS 29vSS]S S3S<SdS]pTm&T>TUTjTCRtTT $T T $T y9T o9T $T 9T 9T $8"T :T :T U U ;$U ;-U B;1U @;:U j;>U f;CU dU UX Us UCU $8U $U $^U $2V $5V $kV $ ,V $!;V $CV8ZV $fV ;jV ;oV $d{V ;V ;V $$VV $V ;V ;V $dV *<V $<V V W u< W s<W <W <"W <&W <-W $5WLW $\W $9hW W $5W <W <W .=W "=W $.W $1W Xl 0Xs NX $VX8|X $DX $8"X $X $X 7X $&*X =X =X $O X =X =Y $v Y X>#Y T>5YM7TY[7rY7Y $Y $&*Y $"Y $(Y $dY $#Y $ Y $ 3Z $9"Z59Z $-EZ >IZ >NZ $O ZZ J?^Z :?oZ @sZ ?Z P@Z J@Z $rZ $ 6Z @Z @ZR6Zl6Z6[6@[6^[6k[6x[6[6[ $[ $O1[ $[ $?%[ $G6 \2"\ $O1.\ @2\ @7\ $C\ /AG\ 'AL\ $}X\ A\\ Aa\ $m\ Aq\ Av\ $ \ LB\ FB\ B\ B\ "P \ B\ B\ " \ (C\ $C\3\ $?%\ dC] ^C]4]4)] " :] C>] CG] CK] CT] +DX] )D]]14}]I4] " ] TD] PD] D] D] D] D]S4]33]3^ $?^'&^ $O19^_(C^ "P^ DT^ D]^ )Ea^ 'Ej^ QEn^ MEu^ $6^'^ $O1^ E^ E^ E^ E^ KF^ CF^'^ $!^P'_ $O1"_ F&_ F6_ G:_ FK_ kGO_ cGT_'q_ $ }_0_ $++_ G_ G_ 6H_ .H_ H_ H_ 5I_ )I_ $d_ I_ I` J ` J`{ ` $ ,`0%C` $O1O` JS` Jc` Kg` Kx` L|` L` lL` hL` L` L` $` L` L` 9M` 5M` $` }M` oM` "@` $ a &Na Na $ !a N%a N*a $06a N:a N?a $Ka 4OOa &OTa $x`a Oda Oia $dua Pya P~ax&a cPa aPa&a $a Pa Pa&ac&a "pb Pb Pb Qb P(b /Q,b -Q2b&[b%bE'b $b#b $O1b ^Qb RQb Qb Qb Rb }Rc JSc >Sc Sc S!c $-c NT1c BTBc TFc TKc $Wc 5U[c #U`c $#rc#c $ c Uc Uc $c cVc [Vc $xc Vc Vc $dc Vc Vc$cd$4d>d$Rd$%qd $}d d $}d d $O1d EWd 3Wd $d  Xd  Xd $:7 e 4Xe 0Xe $d$e "`;e "`De rXHe lXQe XUe X^e "ke Xoe Xxe RY|e JYe Ye Ye Ye Ye *Ze &Ze dZe `Ze "e Ze Ze "e Ze Zee"e!fd!(f $:f $O1Gf $_f $xf $ f $0f $f $xf $df $f $f $O1g $ g $1-g $dEg $0Rg $.yg $z g $g(g $O1g e[g Y[g [g [g o\g g\g(h "h \h \(h ],h ]5h h]9h f]>h "Lh ]Ph ]Zh)qh(h!)h])h $D(hp h $O1h $4h ]h ]h $Q i T^ i R^i i " *i y^.i w^7i ^;i ^Di ^Hi ^Oi $u[i2ri $O1~i ^i ^i $.i _i _i y`i i`i $i 7ai 'ai $4i ai aiU2i " i bi bj b j bj bj bjU26jz2Sj2zj2j $-j $O1j $j $4j $dj $Q j $/k $0k $d2!k $-k`Dk $O1Pk cTk  cYk $ek cik cnk $Q zk c~k ck ddk Xdk $/k  ek ekk "k nek jek ek ekl l "l e!l e*l f.l f7l Af;l =f@l "Il {fMl wfVl `l }l fl fl fl fl fl fl l! l $(ll $O1m *gm  g m $m gm gm $Q *m h.m h3m $?m thCm jhTm hXm h]m $,im (imm  irm $~m im im $qm im im $xm jm jm jm jmm " m km km Tkm Pkm kn kn$nCn(Mn(jn knn ksn(n ln kn4nn $ nn $O1n Tln Hloo+o l/o l4oNo mRo mWono $/o $O1o $o $o0o $O1o $T+o ;mo 7mo zmo tmp $bp(p $O14p m8p m=pJpWpdp&rp $ zpp $O1p #np npp "p qnp onp np np $D p/q $O1 q nq nq/.q/Fq/fq!0{q $p4q.q $O1q Doq 8oq#/qP/qX/qm/ r $A7rW,r $O18r os(QsWisXsFXsXsXsXsXtXtKY9tUYGt $2 St`jt $O1zt $ tpttt $*tt $O1t Eqt ;qt qu qu $ u Mru Kru(u "9u rr=u prFu rJu rYu3cu "@tu rxu ru ru ru "@u  su  su<uuu Esu Csu v0vCv]Mv "^v jsbv hskv sov stvdvCovvv=vOwmw&w $j0.wTw $`wsw ${ww $Gww "w $w sw swwwwx x~ vB~ vK~ vO~ vY~+~C~;+~E+~[+~c+~+~+~+ $ $ $r 6 $+\ ${ $. $  $O1 $. $x $d $ $O14 $xA $dP $s^ $O1w $ $4) $I$ ̀ $1؀ w܀ w $ jw fw $:7 $d w w $|,& x*  x/ $; Sx? GxD $ P xT xZ $i(x $1 $u $1 $& $́ $ $x $4 $i $&0 = $O1I yM yR $^ Fzb @zq zu zzH $O3 $O1ł $ׂ $O1 $ $ $H $#* $7 $.Q $,p $1 $ $.#ă $O1҃ $e $2  , z0 z5 $$A {E {V &|Z  |_  $6 $4 $S҄ $ ܄ $|#0 $) w| o| $O, | |5`Xp $=)Ѕ $x-؅ $P $3@, $8 E}< =}A $M }Q }VVnwC[ $o+@ $rʆ ~Ά  ~ކ ~ ~ \ H $ 6 0.0eo "P     ܀ ڀ̇]ۇcc   / - W U$NC"YBvOS " ~ z ˆ ˈ ψ ԈX # , G0 E9 n= lBjC2~ "    ĉ ȉ ͉C8 " "#  , P0 N5)KCF\iw $s $O1 $} $- $/ $ˊ $>܊ $6 $/ $0 $+ $#! $_* $;7 $H $#!T $_a $r $#!~ $q3 $; $. $#! $_ $;͋ $ ދ $#! $_ $; $  $ $, $0? $@P $\ $j $ $ $l $(5 $%.֌ $ $@ $  $@ $L-( $65 $}7I $SZ $f $t&t $D1 $- $/ $- ύ Ӎ t܍   H B "    ' @+ <0 "09 |= vF P m Džq Ņz ~     Ŏ0 @ @  6 4!G 9Q Lw Vw v c Y ߆ Ն [ Q ه ͇ŏ mɏ aҏ ֏  e+5 "`BPgy [ S   & Đ Ȑ    X R''$ ( 1 ʋ5 ȋ> B G<lv " , * S Q z vϑFّ "  Nx "1 ٌ5 ׌> B K (O $Yc "Pt ex a   ͍ ˍ "˒ ϒ ؒ ܒ  k (C2P{9ؓ Cܓ ? " "$ ( |1 V5 J> B ؏K vO pX "e i r v {z”ؔ)      ?# 1T)^){  ޒ 5 1 q m)  ɕ ԓ͕ ̓֕ <ڕ 4   Ô {* " * . 7 ";  D HH FQ nU lZ " h l u Εy ̕~*D* "p Ö ̖ 0Ж .ٖ Vݖ T)**8*J,e i y|, "  y     "̗ MЗ Gٗ ݗ - "@ ԙ ҙ   -7{-A{-^ #b k ^o \t{-  -r-Ҙ].ߘ..- "p  # "p, 0 9-C-` d m q v---<.ۙC.R..%]X;x.Ex.b ٛf ӛkx..]8.00ך 1ۚ % ɜ   "0, "= 0A (J N W [ ` "i Bm 6v ɟz ş    {   J D0ƛ "ܛ    11 " + / 8 /< -A1dc1|114 `Ü R̜  М ٜ ݜ  " / # 5# ' 1>5J FN @Sg5lq5v "P      ޥ5ǝ7   ] W7=7X \ e i r v 7 " ? 5   3 -7֞8'868@88(KC G |P <T :b,Ll "} c _   ת Ӫ "   0L0Lݟ I G n l  =L!HL4L> " O S X " a e n 2r *{LL    LѠ ۬ՠ ٬8M8M   % #! J% H*@M? qC mL@MV@Ms w  έ ̭  NMYMʡMԡ "     "    ^ T'M1MN ϯR ͯ[ _ h l qMMM D B i gȢ ̢ ѢM  MNN< ް@ ܰI M V +Z )_Ny!N!N S Q x v  !Nԣ ȱأ Ʊݣ8NyO " " ' "0 4 = A JO_ @c >l ep c|OPOP  OP Ť ΤOPؤ "0 Գ ҳ "0   "  kP! "p2 G6 E; "pD nH lQ U `yPj "{   "  ߴ  P "ĥ Cȥ Aͥ "֥ jڥ h  P "`   "` ޵# ܵ, 0 ;PE "V +Z )_ "h Rl Pu {y wP "   " ۶ ٶ ¦ ͦPצ "` ( & "` O M v tP "- 1 6 "? ÷C L P ]Q{Q ' #"Q a _ç ǧ Ч3Qڧ3Q  3Q ݸ ۸ " .bQC +G %P xT v]Qg "x |  " ۹ ׹  Q "0¨ "0Ш :Ԩ 8ߨQ "p "p _ ]Q" "0 "> B P\UZ\Uw { \U κ ̺iUUթpNN P)C30VQC6[/Wu]vRvR   ê ȪvRݪ = ;R R "' j+ `0 "9 = ٻF J ~S W ` (d m q z  ~  E ?_S "p    ɫ ߾ͫ ۾֫ ګ  C = "S " " & / 3 < @ FS^SSSǬTѬ "`       6 ( "  ( *, 5U? "U Y b "t xx rhWhW  hW­W 3T&hW=]RU\UuVV] TϮ\TyTTT6UNAV[iVhVCVVCɯVJWC W"C3T@T[CeUrU]8U]pİUΰU     6 4U ". d2 b;UE " R V _UiU  UU   ñ ȱ5Uٱ(P CTWU2C< WVC&m Pw P * ( T P P ò Ȳ.P߲TW $ $ $. $g $' $' $7 $7 $0$ $0$( $S, $4 $b8 $bA $>E $[M $1!Q $1!Z $0^ $0g $*k $*s $w $ $m $m $H $H $ $ $L+ $L+ $ $ $ ³ $ ˳ $)ϳ $)س $ ܳ $ $% $% $ $ $h $h $ $  $ $ $/" $/+ $ #/ $ #8 $P%< $P%D $H $P $R!T $R!\ $,` $,i $4m $4u $,y $, $* $* $=( $=( $ $ $, $, $R- $ $ô $̴ $4д $4ٴ $7ݴ $7 $ $ $S4 $S4 $, $, $" $" $ $! $)% $)- $i21 $i2: $E> $EF $+J $+S $n7W $n7_ $=c $=k $e8o $e8w $&{ $& $+$ $+$ $( $( $ $ $ $ĵ $ȵ $е $/Ե $/ܵ $ $ $ $ $2 $2 $+ $" $  $* $<" $<* $. $6 $: $B $ F $ O $eS $e\ $` $h $l $t $-x $ $4 $4 $u* $u* $J $J $J $ $ $ $K $Kȶ $o̶ $oԶ $,ض $, $ $ $ $ $3 $3 $ $T+'-(- 38]QCp(sCovC]C",C2C85CF ʿI(   4H \00L`0     \ 0  $L@ X0@Xl`p,@\0p` p 4 #0%8P'L'`'t()+P , , . / 00\ 2 2 4X 5 7  7 7$ 88 8L @9` 9 : 0; P? `?( p?< ?P ?d ?x ? @  @ 0@ @@ P@`I\IpJKK4W|`Y`dd.symtab.strtab.shstrtab.rela.text.data.bss.rela.gnu.build.attributes.text.hot.rela.gnu.build.attributes.hot.text.unlikely.rela.gnu.build.attributes.unlikely.text.startup.rela.gnu.build.attributes.startup.text.exit.rela.gnu.build.attributes.exit.rodata.str1.1.rodata.str1.8.rodata.rela.data.rel.local.rela.data.rel.rela.data.rel.ro.local.rela.debug_info.debug_abbrev.rela.debug_loc.rela.debug_aranges.debug_ranges.rela.debug_line.debug_str.comment.text.hot.zzz.text.unlikely.zzz.text.startup.zzz.text.exit.zzz.note.GNU-stack.note.gnu.property.rela.eh_frame.groupP@:PT:Pl:P:P: d@HA@G:&`ep ,n 6nt"1@ : LT[TV@X0: u((@0:@0:ЖЖ@0:22/"D /`8 *@:D?@:S N@p:kf@0\:!wa-i@ :$/0@0:& 0`lJR@H:)0}80B.ppupLp pppppp.p FA@0(:84; 0'XWPK% ]p K#K#&gems/ruby-lsapi-5.5/ext/lsapi/Makefilenu[ SHELL = /bin/sh # V=0 quiet, V=1 verbose. other values don't work. V = 0 Q1 = $(V:1=) Q = $(Q1:0=@) ECHO1 = $(V:1=@ :) ECHO = $(ECHO1:0=@ echo) NULLCMD = : #### Start of system configuration section. #### srcdir = . topdir = /opt/alt/ruby26/include/ruby-2.6.0 hdrdir = $(topdir) arch_hdrdir = /opt/alt/ruby26/include/ruby-2.6.0/x86_64-linux PATH_SEPARATOR = : VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby prefix = $(DESTDIR)/opt/alt/ruby26 rubysitearchprefix = $(rubylibprefix)/$(sitearch) rubyarchprefix = $(rubylibprefix)/$(arch) rubylibprefix = $(libdir)/$(RUBY_BASE_NAME) exec_prefix = $(DESTDIR)/opt/alt/ruby26 vendorarchhdrdir = $(vendorhdrdir)/$(sitearch) sitearchhdrdir = $(sitehdrdir)/$(sitearch) rubyarchhdrdir = $(rubyhdrdir)/$(arch) vendorhdrdir = $(rubyhdrdir)/vendor_ruby sitehdrdir = $(rubyhdrdir)/site_ruby rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME) vendorarchdir = $(vendorlibdir)/$(sitearch) vendorlibdir = $(vendordir)/$(ruby_version) vendordir = $(rubylibprefix)/vendor_ruby sitearchdir = $(DESTDIR)./.gem.20230713-3059785-85yclf sitelibdir = $(DESTDIR)./.gem.20230713-3059785-85yclf sitedir = $(rubylibprefix)/site_ruby rubyarchdir = $(rubylibdir)/$(arch) rubylibdir = $(rubylibprefix)/$(ruby_version) sitearchincludedir = $(includedir)/$(sitearch) archincludedir = $(includedir)/$(arch) sitearchlibdir = $(libdir)/$(sitearch) archlibdir = $(libdir)/$(arch) ridir = $(datarootdir)/$(RI_BASE_NAME) mandir = $(DESTDIR)/opt/alt/ruby26/share/man localedir = $(datarootdir)/locale libdir = $(exec_prefix)/lib64 psdir = $(docdir) pdfdir = $(docdir) dvidir = $(docdir) htmldir = $(docdir) infodir = $(DESTDIR)/opt/alt/ruby26/share/info docdir = $(datarootdir)/doc/$(PACKAGE) oldincludedir = $(DESTDIR)/usr/include includedir = $(DESTDIR)/opt/alt/ruby26/include localstatedir = $(DESTDIR)/var sharedstatedir = $(DESTDIR)/var/lib sysconfdir = $(DESTDIR)/etc datadir = $(DESTDIR)/opt/alt/ruby26/share datarootdir = $(prefix)/share libexecdir = $(DESTDIR)/opt/alt/ruby26/libexec sbindir = $(DESTDIR)/opt/alt/ruby26/sbin bindir = $(exec_prefix)/bin archdir = $(rubyarchdir) CC_WRAPPER = CC = gcc CXX = g++ LIBRUBY = $(LIBRUBY_SO) LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a LIBRUBYARG_SHARED = -Wl,-rpath,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME) LIBRUBYARG_STATIC = -Wl,-rpath,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)-static $(MAINLIBS) empty = OUTFLAG = -o $(empty) COUTFLAG = -o $(empty) CSRCFLAG = $(empty) RUBY_EXTCONF_H = cflags = $(optflags) $(debugflags) $(warnflags) cxxflags = $(optflags) $(debugflags) $(warnflags) optflags = -O3 debugflags = -ggdb3 warnflags = -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wduplicated-cond -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wrestrict -Wwrite-strings -Wimplicit-fallthrough=0 -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-packed-bitfield-compat -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wunused-variable cppflags = CCDLFLAGS = -fPIC CFLAGS = $(CCDLFLAGS) -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection $(ARCH_FLAG) INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir) DEFS = CPPFLAGS = $(DEFS) $(cppflags) -DRUBY_2 CXXFLAGS = $(CCDLFLAGS) -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection $(ARCH_FLAG) ldflags = -L. -Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -fstack-protector-strong -rdynamic -Wl,-export-dynamic dldflags = -Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld ARCH_FLAG = -m64 DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG) LDSHARED = $(CC) -shared LDSHAREDXX = $(CXX) -shared AR = ar EXEEXT = RUBY_INSTALL_NAME = $(RUBY_BASE_NAME) RUBY_SO_NAME = ruby RUBYW_INSTALL_NAME = RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version) RUBYW_BASE_NAME = rubyw RUBY_BASE_NAME = ruby arch = x86_64-linux sitearch = $(arch) ruby_version = 2.6.0 ruby = $(bindir)/$(RUBY_BASE_NAME) RUBY = $(ruby) ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/backward.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h RM = rm -f RM_RF = $(RUBY) -run -e rm -- -rf RMDIRS = rmdir --ignore-fail-on-non-empty -p MAKEDIRS = /usr/bin/mkdir -p INSTALL = /usr/bin/install -c INSTALL_PROG = $(INSTALL) -m 0755 INSTALL_DATA = $(INSTALL) -m 644 COPY = cp TOUCH = exit > #### End of system configuration section. #### preload = libpath = . $(libdir) LIBPATH = -L. -L$(libdir) -Wl,-rpath,$(libdir) DEFFILE = CLEANFILES = mkmf.log DISTCLEANFILES = DISTCLEANDIRS = extout = extout_prefix = target_prefix = LOCAL_LIBS = LIBS = $(LIBRUBYARG_SHARED) -lm -lc ORIG_SRCS = lsapilib.c lsruby.c SRCS = $(ORIG_SRCS) OBJS = lsapilib.o lsruby.o HDRS = $(srcdir)/lsapidef.h $(srcdir)/lsapilib.h LOCAL_HDRS = TARGET = lsapi TARGET_NAME = lsapi TARGET_ENTRY = Init_$(TARGET_NAME) DLLIB = $(TARGET).so EXTSTATIC = STATIC_LIB = TIMESTAMP_DIR = . BINDIR = $(bindir) RUBYCOMMONDIR = $(sitedir)$(target_prefix) RUBYLIBDIR = $(sitelibdir)$(target_prefix) RUBYARCHDIR = $(sitearchdir)$(target_prefix) HDRDIR = $(rubyhdrdir)/ruby$(target_prefix) ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix) TARGET_SO_DIR = TARGET_SO = $(TARGET_SO_DIR)$(DLLIB) CLEANLIBS = $(TARGET_SO) CLEANOBJS = *.o *.bak all: $(DLLIB) static: $(STATIC_LIB) .PHONY: all install static install-so install-rb .PHONY: clean clean-so clean-static clean-rb clean-static:: clean-rb-default:: clean-rb:: clean-so:: clean: clean-so clean-static clean-rb-default clean-rb -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time distclean-rb-default:: distclean-rb:: distclean-so:: distclean-static:: distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true realclean: distclean install: install-so install-rb install-so: $(DLLIB) $(TIMESTAMP_DIR)/.sitearchdir.time $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR) clean-static:: -$(Q)$(RM) $(STATIC_LIB) install-rb: pre-install-rb do-install-rb install-rb-default install-rb-default: pre-install-rb-default do-install-rb-default pre-install-rb: Makefile pre-install-rb-default: Makefile do-install-rb: do-install-rb-default: pre-install-rb-default: @$(NULLCMD) $(TIMESTAMP_DIR)/.sitearchdir.time: $(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR) $(Q) $(TOUCH) $@ site-install: site-install-so site-install-rb site-install-so: install-so site-install-rb: install-rb .SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S .cc.o: $(ECHO) compiling $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< .cc.S: $(ECHO) translating $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< .mm.o: $(ECHO) compiling $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< .mm.S: $(ECHO) translating $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< .cxx.o: $(ECHO) compiling $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< .cxx.S: $(ECHO) translating $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< .cpp.o: $(ECHO) compiling $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< .cpp.S: $(ECHO) translating $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< .c.o: $(ECHO) compiling $(<) $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< .c.S: $(ECHO) translating $(<) $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< .m.o: $(ECHO) compiling $(<) $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< .m.S: $(ECHO) translating $(<) $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< $(TARGET_SO): $(OBJS) Makefile $(ECHO) linking shared-object $(DLLIB) -$(Q)$(RM) $(@) $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS) $(OBJS): $(HDRS) $(ruby_headers) PK% ] 3O8aa(gems/ruby-lsapi-5.5/ext/lsapi/lsapilib.cnu[//#define LSAPI_DEBUG /* Copyright (c) 2002-2018, Lite Speed Technologies Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Lite Speed Technologies Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lsapilib.h" #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) #include #endif #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) #include #endif #include #ifndef uint32 #define uint32 uint32_t #endif struct lsapi_MD5Context { uint32 buf[4]; uint32 bits[2]; unsigned char in[64]; }; void lsapi_MD5Init(struct lsapi_MD5Context *context); void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf, unsigned len); void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context); /* * This is needed to make RSAREF happy on some MS-DOS compilers. */ typedef struct lsapi_MD5Context lsapi_MD5_CTX; #define LSAPI_ST_REQ_HEADER 1 #define LSAPI_ST_REQ_BODY 2 #define LSAPI_ST_RESP_HEADER 4 #define LSAPI_ST_RESP_BODY 8 #define LSAPI_ST_BACKGROUND 16 #define LSAPI_RESP_BUF_SIZE 8192 #define LSAPI_INIT_RESP_HEADER_LEN 4096 enum { LSAPI_STATE_IDLE, LSAPI_STATE_CONNECTED, LSAPI_STATE_ACCEPTING, }; typedef struct lsapi_child_status { int m_pid; long m_tmStart; volatile short m_iKillSent; volatile char m_inProcess; volatile char m_state; volatile int m_iReqCounter; volatile long m_tmWaitBegin; volatile long m_tmReqBegin; volatile long m_tmLastCheckPoint; } lsapi_child_status; static lsapi_child_status * s_worker_status = NULL; static int g_inited = 0; static int g_running = 1; static int s_ppid; static int s_restored_ppid = 0; static int s_pid = 0; static int s_slow_req_msecs = 0; static int s_keep_listener = 1; static int s_dump_debug_info = 0; static int s_pid_dump_debug_info = 0; static int s_req_processed = 0; static int s_skip_write = 0; static int (*pthread_atfork_func)(void (*prepare)(void), void (*parent)(void), void (*child)(void)) = NULL; static int *s_busy_workers = NULL; static int *s_accepting_workers = NULL; static int *s_global_counter = &s_req_processed; static int s_max_busy_workers = -1; static char *s_stderr_log_path = NULL; static int s_stderr_is_pipe = 0; static int s_ignore_pid = -1; static size_t s_total_pages = 1; static size_t s_min_avail_pages = 256 * 1024; static size_t *s_avail_pages = &s_total_pages; LSAPI_Request g_req = { .m_fdListen = -1, .m_fd = -1 }; static char s_secret[24]; static LSAPI_On_Timer_pf s_proc_group_timer_cb = NULL; void Flush_RespBuf_r( LSAPI_Request * pReq ); static int lsapi_reopen_stderr(const char *p); static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] = { "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING", "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION", "HTTP_CONNECTION", "CONTENT_TYPE", "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2", "HTTP_HOST", "HTTP_PRAGMA", "HTTP_REFERER", "HTTP_USER_AGENT", "HTTP_CACHE_CONTROL", "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH", "HTTP_IF_NONE_MATCH", "HTTP_IF_RANGE", "HTTP_IF_UNMODIFIED_SINCE", "HTTP_KEEP_ALIVE", "HTTP_RANGE", "HTTP_X_FORWARDED_FOR", "HTTP_VIA", "HTTP_TRANSFER_ENCODING" }; static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] = { 11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18, 22, 13, 18, 13, 24, 15, 10, 20, 8, 22 }; static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] = { "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language", "Authorization", "Connection", "Content-Type", "Content-Length", "Cookie", "Cookie2", "Host", "Pragma", "Referer", "User-Agent", "Cache-Control", "If-Modified-Since", "If-Match", "If-None-Match", "If-Range", "If-Unmodified-Since", "Keep-Alive", "Range", "X-Forwarded-For", "Via", "Transfer-Encoding" }; static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] = { 6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent 13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17 }; static const char *s_log_level_names[8] = { "", "DEBUG","INFO", "NOTICE", "WARN", "ERROR", "CRIT", "FATAL" }; void LSAPI_Log(int flag, const char * fmt, ...) { char buf[1024]; char *p = buf; if ((flag & LSAPI_LOG_TIMESTAMP_BITS) && !(s_stderr_is_pipe)) { struct timeval tv; struct tm tm; gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &tm); if (flag & LSAPI_LOG_TIMESTAMP_FULL) { p += snprintf(p, 1024, "%04d-%02d-%02d %02d:%02d:%02d.%06d ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (int)tv.tv_usec); } else if (flag & LSAPI_LOG_TIMESTAMP_HMS) { p += snprintf(p, 1024, "%02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec); } } int level = flag & LSAPI_LOG_LEVEL_BITS; if (level && level <= LSAPI_LOG_FLAG_FATAL) { p += snprintf(p, 100, "[%s] ", s_log_level_names[level]); } if (flag & LSAPI_LOG_PID) { p += snprintf(p, 100, "[UID:%d][%d] ", getuid(), s_pid); } if (p > buf) fprintf(stderr, "%.*s", (int)(p - buf), buf); va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } #ifdef LSAPI_DEBUG #define DBGLOG_FLAG (LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_FLAG_DEBUG|LSAPI_LOG_PID) #define lsapi_dbg(...) LSAPI_Log(DBGLOG_FLAG, __VA_ARGS__) #else #define lsapi_dbg(...) #endif #define lsapi_log(...) LSAPI_Log(LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_PID, __VA_ARGS__) void lsapi_perror(const char * pMessage, int err_no) { lsapi_log("%s, errno: %d (%s)\n", pMessage, err_no, strerror(err_no)); } static int lsapi_parent_dead() { // Return non-zero if the parent is dead. 0 if still alive. if (!s_ppid) { // not checking, so not dead return(0); } if (s_restored_ppid) { if (kill(s_restored_ppid,0) == -1) { if (errno == EPERM) { return(0); // no permission, but it's still there. } return(1); // Dead } return(0); // it worked, so it's not dead } return(s_ppid != getppid()); } static void lsapi_sigpipe( int sig ) { } static void lsapi_siguser1( int sig ) { g_running = 0; } #ifndef sighandler_t typedef void (*sighandler_t)(int); #endif static void lsapi_signal(int signo, sighandler_t handler) { struct sigaction sa; sigaction(signo, NULL, &sa); if (sa.sa_handler == SIG_DFL) { sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = handler; sigaction(signo, &sa, NULL); } } static int s_enable_core_dump = 0; static void lsapi_enable_core_dump(void) { #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) int mib[2]; size_t len; #if !defined(__OpenBSD__) len = 2; if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 ) { len = sizeof(s_enable_core_dump); if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1) perror( "sysctl: Failed to set 'kern.sugid_coredump', " "core dump may not be available!"); } #else int set = 3; len = sizeof(set); mib[0] = CTL_KERN; mib[1] = KERN_NOSUIDCOREDUMP; if (sysctl(mib, 2, NULL, 0, &set, len) == 0) { s_enable_core_dump = 1; } #endif #endif #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1) perror( "prctl: Failed to set dumpable, " "core dump may not be available!"); #endif } static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader, char type, int len ) { pHeader->m_versionB0 = LSAPI_VERSION_B0; /* LSAPI protocol version */ pHeader->m_versionB1 = LSAPI_VERSION_B1; pHeader->m_type = type; pHeader->m_flag = LSAPI_ENDIAN; pHeader->m_packetLen.m_iLen = len; } static int lsapi_set_nblock( int fd, int nonblock ) { int val = fcntl( fd, F_GETFL, 0 ); if ( nonblock ) { if (!( val & O_NONBLOCK )) { return fcntl( fd, F_SETFL, val | O_NONBLOCK ); } } else { if ( val & O_NONBLOCK ) { return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) ); } } return 0; } static int lsapi_close( int fd ) { int ret; while( 1 ) { ret = close( fd ); if (( ret == -1 )&&( errno == EINTR )&&(g_running)) continue; return ret; } } static void lsapi_close_connection(LSAPI_Request *pReq) { if (pReq->m_fd == -1) return; lsapi_close(pReq->m_fd); pReq->m_fd = -1; if (s_busy_workers) __atomic_fetch_sub(s_busy_workers, 1, __ATOMIC_SEQ_CST); if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_IDLE, __ATOMIC_SEQ_CST); } static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len ) { ssize_t ret; while( 1 ) { ret = read( fd, (char *)pBuf, len ); if (( ret == -1 )&&( errno == EINTR )&&(g_running)) continue; return ret; } } /* static int lsapi_write( int fd, const void * pBuf, int len ) { int ret; const char * pCur; const char * pEnd; if ( len == 0 ) return 0; pCur = (const char *)pBuf; pEnd = pCur + len; while( g_running && (pCur < pEnd) ) { ret = write( fd, pCur, pEnd - pCur ); if ( ret >= 0) pCur += ret; else if (( ret == -1 )&&( errno != EINTR )) return ret; } return pCur - (const char *)pBuf; } */ static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen ) { int ret; int left = totalLen; int n = count; if (s_skip_write) return totalLen; while(( left > 0 )&&g_running ) { ret = writev( fd, *pVec, n ); if ( ret > 0 ) { left -= ret; if (( left <= 0)||( !g_running )) return totalLen - left; while( ret > 0 ) { if ( (*pVec)->iov_len <= (unsigned int )ret ) { ret -= (*pVec)->iov_len; ++(*pVec); } else { (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret; (*pVec)->iov_len -= ret; break; } } } else if ( ret == -1 ) { if ( errno == EAGAIN ) { if ( totalLen - left > 0 ) return totalLen - left; else return -1; } else if ( errno != EINTR ) return ret; } } return totalLen - left; } /* static int getTotalLen( struct iovec * pVec, int count ) { struct iovec * pEnd = pVec + count; int total = 0; while( pVec < pEnd ) { total += pVec->iov_len; ++pVec; } return total; } */ static inline int allocateBuf( LSAPI_Request * pReq, int size ) { char * pBuf = (char *)realloc( pReq->m_pReqBuf, size ); if ( pBuf ) { pReq->m_pReqBuf = pBuf; pReq->m_reqBufSize = size; pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf; return 0; } return -1; } static int allocateIovec( LSAPI_Request * pReq, int n ) { struct iovec * p = (struct iovec *)realloc( pReq->m_pIovec, sizeof(struct iovec) * n ); if ( !p ) return -1; pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec ); pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec ); pReq->m_pIovec = p; pReq->m_pIovecEnd = p + n; return 0; } static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size ) { char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size ); if ( !p ) return -1; pReq->m_pRespHeaderBufPos = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf ); pReq->m_pRespHeaderBuf = p; pReq->m_pRespHeaderBufEnd = p + size; return 0; } static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType ) { if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )|| ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )|| ( pktType != pHeader->m_type )) return -1; if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT )) { register char b; b = pHeader->m_packetLen.m_bytes[0]; pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3]; pHeader->m_packetLen.m_bytes[3] = b; b = pHeader->m_packetLen.m_bytes[1]; pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2]; pHeader->m_packetLen.m_bytes[2] = b; } return pHeader->m_packetLen.m_iLen; } static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList, int *curSize, int newSize ) { struct LSAPI_key_value_pair * pBuf; if ( *curSize >= newSize ) return 0; if ( newSize > 8192 ) return -1; pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize * sizeof(struct LSAPI_key_value_pair) ); if ( pBuf ) { *pEnvList = pBuf; *curSize = newSize; return 0; } else return -1; } static inline int isPipe( int fd ) { char achPeer[128]; socklen_t len = 128; if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&& ( errno == ENOTCONN )) return 0; else return 1; } static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count, char **pBegin, char * pEnd ) { struct LSAPI_key_value_pair * pEnvEnd; int keyLen = 0, valLen = 0; if ( count > 8192 ) return -1; pEnvEnd = pEnvList + count; while( pEnvList != pEnvEnd ) { if ( pEnd - *pBegin < 4 ) return -1; keyLen = *((unsigned char *)((*pBegin)++)); keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++)); valLen = *((unsigned char *)((*pBegin)++)); valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++)); if ( *pBegin + keyLen + valLen > pEnd ) return -1; if (( !keyLen )||( !valLen )) return -1; pEnvList->pKey = *pBegin; *pBegin += keyLen; pEnvList->pValue = *pBegin; *pBegin += valLen; pEnvList->keyLen = keyLen - 1; pEnvList->valLen = valLen - 1; ++pEnvList; } if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 ) return -1; *pBegin += 4; return 0; } static inline void swapIntEndian( int * pInteger ) { char * p = (char *)pInteger; register char b; b = p[0]; p[0] = p[3]; p[3] = b; b = p[1]; p[1] = p[2]; p[2] = b; } static inline void fixEndian( LSAPI_Request * pReq ) { struct lsapi_req_header *p= pReq->m_pHeader; swapIntEndian( &p->m_httpHeaderLen ); swapIntEndian( &p->m_reqBodyLen ); swapIntEndian( &p->m_scriptFileOff ); swapIntEndian( &p->m_scriptNameOff ); swapIntEndian( &p->m_queryStringOff ); swapIntEndian( &p->m_requestMethodOff ); swapIntEndian( &p->m_cntUnknownHeaders ); swapIntEndian( &p->m_cntEnv ); swapIntEndian( &p->m_cntSpecialEnv ); } static void fixHeaderIndexEndian( LSAPI_Request * pReq ) { int i; for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { register char b; char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]); b = p[0]; p[0] = p[1]; p[1] = b; swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] ); } } if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { swapIntEndian( &pCur->nameOff ); swapIntEndian( &pCur->nameLen ); swapIntEndian( &pCur->valueOff ); swapIntEndian( &pCur->valueLen ); ++pCur; } } } static int validateHeaders( LSAPI_Request * pReq ) { int totalLen = pReq->m_pHeader->m_httpHeaderLen; int i; for(i = 0; i < H_TRANSFER_ENCODING; ++i) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { if (pReq->m_pHeaderIndex->m_headerOff[i] > totalLen || pReq->m_pHeaderIndex->m_headerLen[i] + pReq->m_pHeaderIndex->m_headerOff[i] > totalLen) return -1; } } if (pReq->m_pHeader->m_cntUnknownHeaders > 0) { struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { if (pCur->nameOff > totalLen || pCur->nameOff + pCur->nameLen > totalLen || pCur->valueOff > totalLen || pCur->valueOff + pCur->valueLen > totalLen) return -1; ++pCur; } } return 0; } static uid_t s_uid = 0; static uid_t s_defaultUid; //web server need set this static gid_t s_defaultGid; #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) #define LSAPI_LVE_DISABLED 0 #define LSAPI_LVE_ENABLED 1 #define LSAPI_CAGEFS_ENABLED 2 #define LSAPI_CAGEFS_NO_SUEXEC 3 struct liblve; static int s_enable_lve = LSAPI_LVE_DISABLED; static struct liblve * s_lve = NULL; static void *s_liblve; static int (*fp_lve_is_available)(void) = NULL; static int (*fp_lve_instance_init)(struct liblve *) = NULL; static int (*fp_lve_destroy)(struct liblve *) = NULL; static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL; static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL; static int (*fp_lve_jail)( struct passwd *, char *) = NULL; static int lsapi_load_lve_lib(void) { s_liblve = dlopen("liblve.so.0", RTLD_NOW | RTLD_GLOBAL); if (s_liblve) { fp_lve_is_available = dlsym(s_liblve, "lve_is_available"); if (dlerror() == NULL) { if ( !(*fp_lve_is_available)() ) { int uid = getuid(); if ( uid ) { if (setreuid( s_uid, uid )) {}; if ( !(*fp_lve_is_available)() ) s_enable_lve = 0; if (setreuid( uid, s_uid )) {}; } } } } else { s_enable_lve = LSAPI_LVE_DISABLED; } return (s_liblve)? 0 : -1; } static int init_lve_ex(void) { int rc; if ( !s_liblve ) return -1; fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init"); fp_lve_destroy = dlsym(s_liblve, "lve_destroy"); fp_lve_enter = dlsym(s_liblve, "lve_enter"); fp_lve_leave = dlsym(s_liblve, "lve_leave"); if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED ) fp_lve_jail = dlsym(s_liblve, "jail" ); if ( s_lve == NULL ) { rc = (*fp_lve_instance_init)(NULL); s_lve = malloc(rc); } rc = (*fp_lve_instance_init)(s_lve); if (rc != 0) { perror( "LSAPI: Unable to initialize LVE" ); free( s_lve ); s_lve = NULL; return -1; } return 0; } #endif static int readSecret( const char * pSecretFile ) { struct stat st; int fd = open( pSecretFile, O_RDONLY , 0600 ); if ( fd == -1 ) { lsapi_log("LSAPI: failed to open secret file: %s!\n", pSecretFile ); return -1; } if ( fstat( fd, &st ) == -1 ) { lsapi_log("LSAPI: failed to check state of file: %s!\n", pSecretFile ); close( fd ); return -1; } /* if ( st.st_uid != s_uid ) { lsapi_log("LSAPI: file owner check failure: %s!\n", pSecretFile ); close( fd ); return -1; } */ if ( st.st_mode & 0077 ) { lsapi_log("LSAPI: file permission check failure: %s\n", pSecretFile ); close( fd ); return -1; } if ( read( fd, s_secret, 16 ) < 16 ) { lsapi_log("LSAPI: failed to read secret from secret file: %s\n", pSecretFile ); close( fd ); return -1; } close( fd ); return 0; } int LSAPI_is_suEXEC_Daemon(void) { if (( !s_uid )&&( s_secret[0] )) return 1; else return 0; } static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 ) { char achError[4096]; int n = snprintf(achError, sizeof(achError), "[UID:%d][%d] %s:%s: %s\n", getuid(), getpid(), pErr1, (pErr2)?pErr2:"", strerror(errno)); if (n > (int)sizeof(achError)) n = sizeof(achError); if ( pReq ) LSAPI_Write_Stderr_r( pReq, achError, n ); else if (write( STDERR_FILENO, achError, n )) {}; return 0; } #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) static int lsapi_lve_error( LSAPI_Request * pReq ) { static const char * headers[] = { "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0", "Pragma: no-cache", "Retry-After: 60", "Content-Type: text/html", NULL }; static const char achBody[] = "\n" "\n508 Resource Limit Is Reached\n" "\n" "

Resource Limit Is Reached

\n" "The website is temporarily unable to service your request as it exceeded resource limit.\n" "Please try again later.\n" "
\n" "\n"; LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 ); return 0; } static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid ) { if ( s_lve && uid ) //root user should not do that { uint32_t cookie; int ret = -1; ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie); if ( ret < 0 ) { //lsapi_log("enter LVE (%d) : result: %d !\n", uid, ret ); LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL ); lsapi_lve_error( pReq ); return -1; } } return 0; } static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw ) { int ret = 0; char error_msg[1024] = ""; ret = (*fp_lve_jail)( pw, error_msg ); if ( ret < 0 ) { lsapi_log("LSAPI: LVE jail(%d) result: %d, error: %s !\n", uid, ret, error_msg ); LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL ); return -1; } return ret; } static int lsapi_initLVE(void) { const char * pEnv; if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL ) { s_enable_lve = atol( pEnv ); pEnv = NULL; } else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL ) { s_enable_lve = atol( pEnv ); pEnv = NULL; } if ( s_enable_lve && !s_uid ) { lsapi_load_lve_lib(); if ( s_enable_lve ) { return init_lve_ex(); } } return 0; } #endif static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot) { int rv; struct passwd * pw; pw = getpwuid( uid ); #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) if ( s_lve ) { if( lsapi_enterLVE( pReq, uid ) == -1 ) return -1; if ( pw && fp_lve_jail) { rv = lsapi_jailLVE( pReq, uid, pw ); if ( rv == -1 ) return -1; if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC )) //this mode only use cageFS, does not use suEXEC { uid = s_defaultUid; gid = s_defaultGid; pw = getpwuid( uid ); } } } #endif //if ( !uid || !gid ) //do not allow root //{ // return -1; //} #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) if ( s_enable_core_dump ) lsapi_enable_core_dump(); #endif rv = setgid(gid); if (rv == -1) { LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL); return -1; } if ( pw && (pw->pw_gid == gid )) { rv = initgroups( pw->pw_name, gid ); if (rv == -1) { LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL); return -1; } } else { rv = setgroups(1, &gid); if (rv == -1) { LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL); } } if ( pChroot ) { rv = chroot( pChroot ); if ( rv == -1 ) { LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL); return -1; } } rv = setuid(uid); if (rv == -1) { LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL); return -1; } #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) if ( s_enable_core_dump ) lsapi_enable_core_dump(); #endif return 0; } static int lsapi_suexec_auth( LSAPI_Request *pReq, char * pAuth, int len, char * pUgid, int ugidLen ) { lsapi_MD5_CTX md5ctx; unsigned char achMD5[16]; if ( len < 32 ) return -1; memmove( achMD5, pAuth + 16, 16 ); memmove( pAuth + 16, s_secret, 16 ); lsapi_MD5Init( &md5ctx ); lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 ); lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 ); lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx); if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 ) return 0; return 1; } static int lsapi_changeUGid( LSAPI_Request * pReq ) { int uid = s_defaultUid; int gid = s_defaultGid; const char *pStderrLog; const char *pChroot = NULL; struct LSAPI_key_value_pair * pEnv; struct LSAPI_key_value_pair * pAuth; int i; if ( s_uid ) return 0; //with special ID 0x00 //authenticate the suEXEC request; //first one should be MD5( nonce + lscgid secret ) //remember to clear the secret after verification //it should be set at the end of special env i = pReq->m_pHeader->m_cntSpecialEnv - 1; if ( i >= 0 ) { pEnv = pReq->m_pSpecialEnvList + i; if (( *pEnv->pKey == '\000' )&& ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 )) { --pReq->m_pHeader->m_cntSpecialEnv; pAuth = pEnv--; if (( *pEnv->pKey == '\000' )&& ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 )) { --pReq->m_pHeader->m_cntSpecialEnv; uid = *(uint32_t *)pEnv->pValue; gid = *(((uint32_t *)pEnv->pValue) + 1 ); //lsapi_log("LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid ); } else { lsapi_log("LSAPI: missing SUEXEC_UGID env, use default user!\n" ); pEnv = NULL; } if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 ) { //read UID, GID from specialEnv } else { //authentication error lsapi_log("LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" ); uid = 0; } } else { //lsapi_log("LSAPI: no SUEXEC_AUTH env, use default user!\n" ); } } if ( !uid ) { uid = s_defaultUid; gid = s_defaultGid; } //change uid if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 ) { return -1; } s_uid = uid; if ( pReq->m_fdListen != -1 ) { close( pReq->m_fdListen ); pReq->m_fdListen = -1; } pStderrLog = LSAPI_GetEnv_r( pReq, "LSAPI_STDERR_LOG"); if (pStderrLog) lsapi_reopen_stderr(pStderrLog); return 0; } static int parseContentLenFromHeader(LSAPI_Request * pReq) { const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH ); if ( pContentLen ) pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 ); return 0; } static int parseRequest( LSAPI_Request * pReq, int totalLen ) { int shouldFixEndian; char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header ); char * pEnd = pReq->m_pReqBuf + totalLen; shouldFixEndian = ( LSAPI_ENDIAN != ( pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) ); if ( shouldFixEndian ) { fixEndian( pReq ); } if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&& allocateEnvList( &pReq->m_pSpecialEnvList, &pReq->m_specialEnvListSize, pReq->m_pHeader->m_cntSpecialEnv ) == -1 ) return -1; if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&& allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize, pReq->m_pHeader->m_cntEnv ) == -1 ) return -1; if ( parseEnv( pReq->m_pSpecialEnvList, pReq->m_pHeader->m_cntSpecialEnv, &pBegin, pEnd ) == -1 ) return -1; if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv, &pBegin, pEnd ) == -1 ) return -1; if (pReq->m_pHeader->m_scriptFileOff < 0 || pReq->m_pHeader->m_scriptFileOff >= totalLen || pReq->m_pHeader->m_scriptNameOff < 0 || pReq->m_pHeader->m_scriptNameOff >= totalLen || pReq->m_pHeader->m_queryStringOff < 0 || pReq->m_pHeader->m_queryStringOff >= totalLen || pReq->m_pHeader->m_requestMethodOff < 0 || pReq->m_pHeader->m_requestMethodOff >= totalLen) { lsapi_log("Bad request header - ERROR#1\n"); return -1; } pReq->m_pScriptFile = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff; pReq->m_pScriptName = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff; pReq->m_pQueryString = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff; pReq->m_pRequestMethod = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff; pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7)); pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin; pBegin += sizeof( struct lsapi_http_header_index ); pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin; pBegin += sizeof( struct lsapi_header_offset) * pReq->m_pHeader->m_cntUnknownHeaders; pReq->m_pHttpHeader = pBegin; pBegin += pReq->m_pHeader->m_httpHeaderLen; if ( pBegin != pEnd ) { lsapi_log("Request header does match total size, total: %d, " "real: %ld\n", totalLen, pBegin - pReq->m_pReqBuf ); return -1; } if ( shouldFixEndian ) { fixHeaderIndexEndian( pReq ); } if (validateHeaders(pReq) == -1) { lsapi_log("Bad request header - ERROR#2\n"); return -1; } pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen; if ( pReq->m_reqBodyLen == -2 ) { parseContentLenFromHeader(pReq); } return 0; } //OPTIMIZATION static char s_accept_notify = 0; static char s_schedule_notify = 0; static char s_notify_scheduled = 0; static char s_notified_pid = 0; static struct lsapi_packet_header s_ack = {'L', 'S', LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }; static struct lsapi_packet_header s_conn_close_pkt = {'L', 'S', LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }; static inline int send_notification_pkt( int fd, struct lsapi_packet_header *pkt ) { if ( write( fd, pkt, LSAPI_PACKET_HEADER_LEN ) < LSAPI_PACKET_HEADER_LEN ) return -1; return 0; } static inline int send_req_received_notification( int fd ) { return send_notification_pkt(fd, &s_ack); } static inline int send_conn_close_notification( int fd ) { return send_notification_pkt(fd, &s_conn_close_pkt); } //static void lsapi_sigalarm( int sig ) //{ // if ( s_notify_scheduled ) // { // s_notify_scheduled = 0; // if ( g_req.m_fd != -1 ) // write_req_received_notification( g_req.m_fd ); // } //} static inline int lsapi_schedule_notify(void) { if ( !s_notify_scheduled ) { alarm( 2 ); s_notify_scheduled = 1; } return 0; } static inline int notify_req_received( int fd ) { if ( s_schedule_notify ) return lsapi_schedule_notify(); return send_req_received_notification( fd ); } static inline int lsapi_notify_pid( int fd ) { char achBuf[16]; lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM, 8 + LSAPI_PACKET_HEADER_LEN ); memmove( &achBuf[8], "\0PID", 4 ); *((int *)&achBuf[12]) = getpid(); if ( write( fd, achBuf, 16 ) < 16 ) return -1; return 0; } static int readReq( LSAPI_Request * pReq ) { int len; int packetLen; if ( !pReq ) return -1; if ( pReq->m_reqBufSize < 8192 ) { if ( allocateBuf( pReq, 8192 ) == -1 ) return -1; } while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN ) { len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize ); if ( len <= 0 ) return -1; pReq->m_bufRead += len; } pReq->m_reqState = LSAPI_ST_REQ_HEADER; packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST ); if ( packetLen < 0 ) { lsapi_log("packetLen < 0\n"); return -1; } if ( packetLen > LSAPI_MAX_HEADER_LEN ) { lsapi_log("packetLen > %d\n", LSAPI_MAX_HEADER_LEN ); return -1; } if ( packetLen + 1024 > pReq->m_reqBufSize ) { if ( allocateBuf( pReq, packetLen + 1024 ) == -1 ) return -1; } while( packetLen > pReq->m_bufRead ) { len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead ); if ( len <= 0 ) return -1; pReq->m_bufRead += len; } if ( parseRequest( pReq, packetLen ) < 0 ) { lsapi_log("ParseRequest error\n"); return -1; } pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER; if ( !s_uid ) { if ( lsapi_changeUGid( pReq ) ) return -1; memset(s_secret, 0, sizeof(s_secret)); } pReq->m_bufProcessed = packetLen; //OPTIMIZATION if ( !s_accept_notify && !s_notified_pid ) return notify_req_received( pReq->m_fd ); else { s_notified_pid = 0; return 0; } } int LSAPI_Init(void) { if ( !g_inited ) { s_uid = geteuid(); s_secret[0] = 0; lsapi_signal(SIGPIPE, lsapi_sigpipe); lsapi_signal(SIGUSR1, lsapi_siguser1); #if defined(SIGXFSZ) && defined(SIG_IGN) signal(SIGXFSZ, SIG_IGN); #endif /* let STDOUT function as STDERR, just in case writing to STDOUT directly */ dup2( 2, 1 ); if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 ) return -1; g_inited = 1; s_ppid = getppid(); void *pthread_lib = dlopen("libpthread.so", RTLD_LAZY); if (pthread_lib) pthread_atfork_func = dlsym(pthread_lib, "pthread_atfork"); } return 0; } void LSAPI_Stop(void) { g_running = 0; } int LSAPI_IsRunning(void) { return g_running; } void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb) { s_proc_group_timer_cb = cb; } int LSAPI_InitRequest( LSAPI_Request * pReq, int fd ) { int newfd; if ( !pReq ) return -1; memset( pReq, 0, sizeof( LSAPI_Request ) ); if ( allocateIovec( pReq, 16 ) == -1 ) return -1; pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE ); if ( !pReq->m_pRespBuf ) return -1; pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1; pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5]; if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 ) return -1; if ( fd == STDIN_FILENO ) { fd = dup( fd ); newfd = open( "/dev/null", O_RDWR ); dup2( newfd, STDIN_FILENO ); } if ( isPipe( fd ) ) { pReq->m_fdListen = -1; pReq->m_fd = fd; } else { pReq->m_fdListen = fd; pReq->m_fd = -1; lsapi_set_nblock( fd, 1 ); } return 0; } int LSAPI_Is_Listen( void ) { return LSAPI_Is_Listen_r( &g_req ); } int LSAPI_Is_Listen_r( LSAPI_Request * pReq) { return pReq->m_fdListen != -1; } int LSAPI_Accept_r( LSAPI_Request * pReq ) { char achPeer[128]; socklen_t len; int nodelay = 1; if ( !pReq ) return -1; if ( LSAPI_Finish_r( pReq ) == -1 ) return -1; lsapi_set_nblock( pReq->m_fdListen , 0 ); while( g_running ) { if ( pReq->m_fd == -1 ) { if ( pReq->m_fdListen != -1) { len = sizeof( achPeer ); pReq->m_fd = accept( pReq->m_fdListen, (struct sockaddr *)&achPeer, &len ); if ( pReq->m_fd == -1 ) { if (( errno == EINTR )||( errno == EAGAIN)) continue; else return -1; } else { if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST); if (s_busy_workers) __atomic_fetch_add(s_busy_workers, 1, __ATOMIC_SEQ_CST); lsapi_set_nblock( pReq->m_fd , 0 ); if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) { setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); } //init_conn_key( pReq->m_fd ); //OPTIMIZATION if ( s_accept_notify ) if ( notify_req_received( pReq->m_fd ) == -1 ) return -1; } } else return -1; } if ( !readReq( pReq ) ) break; //abort(); lsapi_close_connection(pReq); LSAPI_Reset_r( pReq ); } return 0; } static struct lsapi_packet_header finish_close[2] = { {'L', 'S', LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }, {'L', 'S', LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} } }; int LSAPI_Finish_r( LSAPI_Request * pReq ) { /* finish req body */ if ( !pReq ) return -1; if (pReq->m_reqState) { if ( pReq->m_fd != -1 ) { if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { LSAPI_FinalizeRespHeaders_r( pReq ); } if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { Flush_RespBuf_r( pReq ); } pReq->m_pIovecCur->iov_base = (void *)finish_close; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN; pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN; ++pReq->m_pIovecCur; LSAPI_Flush_r( pReq ); } LSAPI_Reset_r( pReq ); } return 0; } int LSAPI_End_Response_r(LSAPI_Request * pReq) { if (!pReq) return -1; if (pReq->m_reqState & LSAPI_ST_BACKGROUND) return 0; if (pReq->m_reqState) { if ( pReq->m_fd != -1 ) { if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { if ( pReq->m_pRespHeaderBufPos <= pReq->m_pRespHeaderBuf ) return 0; LSAPI_FinalizeRespHeaders_r( pReq ); } if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { Flush_RespBuf_r( pReq ); } pReq->m_pIovecCur->iov_base = (void *)finish_close; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN << 1; pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN << 1; ++pReq->m_pIovecCur; LSAPI_Flush_r( pReq ); lsapi_close_connection(pReq); } pReq->m_reqState |= LSAPI_ST_BACKGROUND; } return 0; } void LSAPI_Reset_r( LSAPI_Request * pReq ) { pReq->m_pRespBufPos = pReq->m_pRespBuf; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1; pReq->m_pRespHeaderBufPos = pReq->m_pRespHeaderBuf; memset( &pReq->m_pHeaderIndex, 0, (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex ); } int LSAPI_Release_r( LSAPI_Request * pReq ) { if ( pReq->m_pReqBuf ) free( pReq->m_pReqBuf ); if ( pReq->m_pSpecialEnvList ) free( pReq->m_pSpecialEnvList ); if ( pReq->m_pEnvList ) free( pReq->m_pEnvList ); if ( pReq->m_pRespHeaderBuf ) free( pReq->m_pRespHeaderBuf ); return 0; } char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex ) { int off; if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) ) return NULL; off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ]; if ( !off ) return NULL; if ( *(pReq->m_pHttpHeader + off + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) ) { *( pReq->m_pHttpHeader + off + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0; } return pReq->m_pHttpHeader + off; } static int readBodyToReqBuf( LSAPI_Request * pReq ) { off_t bodyLeft; ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed; if ( len > 0 ) return len; pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen; bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead; len = pReq->m_reqBufSize - pReq->m_bufRead; if ( len < 0 ) return -1; if ( len > bodyLeft ) len = bodyLeft; len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len ); if ( len > 0 ) pReq->m_bufRead += len; return len; } int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq ) { if (!pReq || (pReq->m_fd ==-1) ) return EOF; if ( pReq->m_bufProcessed >= pReq->m_bufRead ) { if ( readBodyToReqBuf( pReq ) <= 0 ) return EOF; } ++pReq->m_reqBodyRead; return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++); } int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF ) { ssize_t len; ssize_t left; char * pBufEnd = pBuf + bufLen - 1; char * pBufCur = pBuf; char * pCur; char * p; if (!pReq || pReq->m_fd == -1 || !pBuf || !getLF) return -1; *getLF = 0; while( (left = pBufEnd - pBufCur ) > 0 ) { len = pReq->m_bufRead - pReq->m_bufProcessed; if ( len <= 0 ) { if ( (len = readBodyToReqBuf( pReq )) <= 0 ) { *getLF = 1; break; } } if ( len > left ) len = left; pCur = pReq->m_pReqBuf + pReq->m_bufProcessed; p = memchr( pCur, '\n', len ); if ( p ) len = p - pCur + 1; memmove( pBufCur, pCur, len ); pBufCur += len; pReq->m_bufProcessed += len; pReq->m_reqBodyRead += len; if ( p ) { *getLF = 1; break; } } *pBufCur = 0; return pBufCur - pBuf; } ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen ) { ssize_t len; off_t total; /* char *pOldBuf = pBuf; */ if (!pReq || pReq->m_fd == -1 || !pBuf || (ssize_t)bufLen < 0) return -1; total = pReq->m_reqBodyLen - pReq->m_reqBodyRead; if ( total <= 0 ) return 0; if ( total < (ssize_t)bufLen ) bufLen = total; total = 0; len = pReq->m_bufRead - pReq->m_bufProcessed; if ( len > 0 ) { if ( len > (ssize_t)bufLen ) len = bufLen; memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len ); pReq->m_bufProcessed += len; total += len; pBuf += len; bufLen -= len; } while( bufLen > 0 ) { len = lsapi_read( pReq->m_fd, pBuf, bufLen ); if ( len > 0 ) { total += len; pBuf += len; bufLen -= len; } else if ( len <= 0 ) { if ( !total) return -1; break; } } pReq->m_reqBodyRead += total; return total; } ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) { struct lsapi_packet_header * pHeader; const char * pEnd; const char * p; ssize_t bufLen; ssize_t toWrite; ssize_t packetLen; int skip = 0; if (!pReq || !pBuf) return -1; if (pReq->m_reqState & LSAPI_ST_BACKGROUND) return len; if (pReq->m_fd == -1) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { LSAPI_FinalizeRespHeaders_r( pReq ); /* if ( *pBuf == '\r' ) { ++skip; } if ( *pBuf == '\n' ) { ++skip; } */ } pReq->m_reqState |= LSAPI_ST_RESP_BODY; if ( ((ssize_t)len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos ) { memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip ); pReq->m_pRespBufPos += len - skip; return len; } pHeader = pReq->m_respPktHeader; p = pBuf + skip; pEnd = pBuf + len; bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf; while( ( toWrite = pEnd - p ) > 0 ) { packetLen = toWrite + bufLen; if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) { packetLen = LSAPI_MAX_DATA_PACKET_LEN; toWrite = packetLen - bufLen; } lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM, packetLen + LSAPI_PACKET_HEADER_LEN ); pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN; pReq->m_pIovecCur->iov_base = (void *)pHeader; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN; ++pReq->m_pIovecCur; ++pHeader; if ( bufLen > 0 ) { pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf; pReq->m_pIovecCur->iov_len = bufLen; pReq->m_pRespBufPos = pReq->m_pRespBuf; ++pReq->m_pIovecCur; bufLen = 0; } pReq->m_pIovecCur->iov_base = (void *)p; pReq->m_pIovecCur->iov_len = toWrite; ++pReq->m_pIovecCur; p += toWrite; if ( pHeader >= pReq->m_respPktHeaderEnd - 1) { if ( LSAPI_Flush_r( pReq ) == -1 ) return -1; pHeader = pReq->m_respPktHeader; } } if ( pHeader != pReq->m_respPktHeader ) if ( LSAPI_Flush_r( pReq ) == -1 ) return -1; return p - pBuf; } #if defined(__FreeBSD__ ) ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) { ssize_t ret; off_t written; ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 ); if ( written > 0 ) { ret = written; *off += ret; } return ret; } #endif #if defined(__OpenBSD__) || defined(__NetBSD__) ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) { ssize_t ret; off_t written = 0; const size_t bufsiz = 16384; unsigned char in[bufsiz] = {0}; if (lseek(fdIn, *off, SEEK_SET) == -1) { return -1; } while (size > 0) { size_t tor = size > sizeof(in) ? sizeof(in) : size; ssize_t c = read(fdIn, in, tor); if (c <= 0) { goto end; } ssize_t w = write(fdOut, in, c); if (w > 0) written += w; if (w != c) { goto end; } size -= c; } end: *off += written; return 0; } #endif #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) { ssize_t ret; off_t len = size; ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 ); if (( ret == 0 )&&( len > 0 )) { ret = len; *off += len; } return ret; } #endif #if defined(sun) || defined(__sun) #include ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size ) { int n = 0 ; sendfilevec_t vec[1]; vec[n].sfv_fd = fdIn; vec[n].sfv_flag = 0; vec[n].sfv_off = *off; vec[n].sfv_len = size; ++n; size_t written; ssize_t ret = sendfilev( fdOut, vec, n, &written ); if (( !ret )||( errno == EAGAIN )) ret = written; if ( ret > 0 ) *off += ret; return ret; } #endif #if defined(linux) || defined(__linux) || defined(__linux__) || \ defined(__gnu_linux__) #include #define gsendfile sendfile #endif #if defined(HPUX) ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size ) { return sendfile( fdOut, fdIn, off, size, NULL, 0 ); } #endif ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size ) { struct lsapi_packet_header * pHeader = pReq->m_respPktHeader; if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 ) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { LSAPI_FinalizeRespHeaders_r( pReq ); } pReq->m_reqState |= LSAPI_ST_RESP_BODY; LSAPI_Flush_r(pReq); lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM, size + LSAPI_PACKET_HEADER_LEN ); if (write(pReq->m_fd, (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN) return -1; return gsendfile( pReq->m_fd, fdIn, off, size ); } void Flush_RespBuf_r( LSAPI_Request * pReq ) { struct lsapi_packet_header * pHeader = pReq->m_respPktHeader; int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf; pReq->m_reqState |= LSAPI_ST_RESP_BODY; lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM, bufLen + LSAPI_PACKET_HEADER_LEN ); pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN; pReq->m_pIovecCur->iov_base = (void *)pHeader; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN; ++pReq->m_pIovecCur; ++pHeader; if ( bufLen > 0 ) { pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf; pReq->m_pIovecCur->iov_len = bufLen; pReq->m_pRespBufPos = pReq->m_pRespBuf; ++pReq->m_pIovecCur; bufLen = 0; } } int LSAPI_Flush_r( LSAPI_Request * pReq ) { int ret = 0; int n; if ( !pReq ) return -1; n = pReq->m_pIovecCur - pReq->m_pIovecToWrite; if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf )) return 0; if ( pReq->m_fd == -1 ) { pReq->m_pRespBufPos = pReq->m_pRespBuf; pReq->m_totalLen = 0; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec; return -1; } if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { LSAPI_FinalizeRespHeaders_r( pReq ); } if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { Flush_RespBuf_r( pReq ); } n = pReq->m_pIovecCur - pReq->m_pIovecToWrite; if ( n > 0 ) { ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite, n, pReq->m_totalLen ); if ( ret < pReq->m_totalLen ) { lsapi_close_connection(pReq); ret = -1; } pReq->m_totalLen = 0; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec; } return ret; } ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) { struct lsapi_packet_header header; const char * pEnd; const char * p; ssize_t packetLen; ssize_t totalLen; int ret; struct iovec iov[2]; struct iovec *pIov; if ( !pReq ) return -1; if (s_stderr_log_path || pReq->m_fd == -1 || pReq->m_fd == pReq->m_fdListen) return write( 2, pBuf, len ); if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { LSAPI_Flush_r( pReq ); } p = pBuf; pEnd = pBuf + len; while( ( packetLen = pEnd - p ) > 0 ) { if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) { packetLen = LSAPI_MAX_DATA_PACKET_LEN; } lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM, packetLen + LSAPI_PACKET_HEADER_LEN ); totalLen = packetLen + LSAPI_PACKET_HEADER_LEN; iov[0].iov_base = (void *)&header; iov[0].iov_len = LSAPI_PACKET_HEADER_LEN; iov[1].iov_base = (void *)p; iov[1].iov_len = packetLen; p += packetLen; pIov = iov; ret = lsapi_writev( pReq->m_fd, &pIov, 2, totalLen ); if ( ret < totalLen ) { lsapi_close_connection(pReq); ret = -1; } } return p - pBuf; } static char * GetHeaderVar( LSAPI_Request * pReq, const char * name ) { int i; char * pValue; for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { if ( strcmp( name, CGI_HEADERS[i] ) == 0 ) { pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i]; if ( *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) != '\0') { *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) = '\0'; } return pValue; } } } if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { const char *p; char *pKey; char *pKeyEnd; int keyLen; struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { pKey = pReq->m_pHttpHeader + pCur->nameOff; keyLen = pCur->nameLen; pKeyEnd = pKey + keyLen; p = &name[5]; while(( pKey < pKeyEnd )&&( *p )) { char ch = toupper( *pKey ); if ((ch != *p )||(( *p == '_' )&&( ch != '-'))) break; ++p; ++pKey; } if (( pKey == pKeyEnd )&& (!*p )) { pValue = pReq->m_pHttpHeader + pCur->valueOff; if ( *(pValue + pCur->valueLen) != '\0') { *(pValue + pCur->valueLen) = '\0'; } return pValue; } ++pCur; } } return NULL; } char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name ) { struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList; struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv; if ( !pReq || !name ) return NULL; if ( strncmp( name, "HTTP_", 5 ) == 0 ) { return GetHeaderVar( pReq, name ); } while( pBegin < pEnd ) { if ( strcmp( name, pBegin->pKey ) == 0 ) return pBegin->pValue; ++pBegin; } return NULL; } struct _headerInfo { const char * _name; int _nameLen; const char * _value; int _valueLen; }; int compareValueLocation(const void * v1, const void *v2 ) { return ((const struct _headerInfo *)v1)->_value - ((const struct _headerInfo *)v2)->_value; } int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { int i; int len = 0; char * pValue; int ret; int count = 0; struct _headerInfo headers[512]; if ( !pReq || !fn ) return -1; if ( !pReq->m_pHeaderIndex ) return 0; for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { len = pReq->m_pHeaderIndex->m_headerLen[i]; pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i]; *(pValue + len ) = 0; headers[count]._name = HTTP_HEADERS[i]; headers[count]._nameLen = HTTP_HEADER_LEN[i]; headers[count]._value = pValue; headers[count]._valueLen = len; ++count; //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i], // pValue, len, arg ); //if ( ret <= 0 ) // return ret; } } if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { char *pKey; int keyLen; struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { pKey = pReq->m_pHttpHeader + pCur->nameOff; keyLen = pCur->nameLen; *(pKey + keyLen ) = 0; pValue = pReq->m_pHttpHeader + pCur->valueOff; *(pValue + pCur->valueLen ) = 0; headers[count]._name = pKey; headers[count]._nameLen = keyLen; headers[count]._value = pValue; headers[count]._valueLen = pCur->valueLen; ++count; if ( count == 512 ) break; //ret = (*fn)( pKey, keyLen, // pValue, pCur->valueLen, arg ); //if ( ret <= 0 ) // return ret; ++pCur; } } qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation ); for( i = 0; i < count; ++i ) { ret = (*fn)( headers[i]._name, headers[i]._nameLen, headers[i]._value, headers[i]._valueLen, arg ); if ( ret <= 0 ) return ret; } return count; } int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { int i; int len = 0; char * pValue; int ret; int count = 0; if ( !pReq || !fn ) return -1; for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { len = pReq->m_pHeaderIndex->m_headerLen[i]; pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i]; *(pValue + len ) = 0; ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i], pValue, len, arg ); ++count; if ( ret <= 0 ) return ret; } } if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { char achHeaderName[256]; char *p; char *pKey; char *pKeyEnd ; int keyLen; struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { pKey = pReq->m_pHttpHeader + pCur->nameOff; keyLen = pCur->nameLen; if ( keyLen > 250 ) keyLen = 250; pKeyEnd = pKey + keyLen; memcpy( achHeaderName, "HTTP_", 5 ); p = &achHeaderName[5]; while( pKey < pKeyEnd ) { char ch = *pKey++; if ( ch == '-' ) *p++ = '_'; else *p++ = toupper( ch ); } *p = 0; keyLen += 5; pValue = pReq->m_pHttpHeader + pCur->valueOff; *(pValue + pCur->valueLen ) = 0; ret = (*fn)( achHeaderName, keyLen, pValue, pCur->valueLen, arg ); if ( ret <= 0 ) return ret; ++pCur; } } return count + pReq->m_pHeader->m_cntUnknownHeaders; } static int EnvForeach( struct LSAPI_key_value_pair * pEnv, int n, LSAPI_CB_EnvHandler fn, void * arg ) { struct LSAPI_key_value_pair * pEnd = pEnv + n; int ret; if ( !pEnv || !fn ) return -1; while( pEnv < pEnd ) { ret = (*fn)( pEnv->pKey, pEnv->keyLen, pEnv->pValue, pEnv->valLen, arg ); if ( ret <= 0 ) return ret; ++pEnv; } return n; } int LSAPI_ForeachEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { if ( !pReq || !fn ) return -1; if ( pReq->m_pHeader->m_cntEnv > 0 ) { return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv, fn, arg ); } return 0; } int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { if ( !pReq || !fn ) return -1; if ( pReq->m_pHeader->m_cntSpecialEnv > 0 ) { return EnvForeach( pReq->m_pSpecialEnvList, pReq->m_pHeader->m_cntSpecialEnv, fn, arg ); } return 0; } int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq ) { if ( !pReq || !pReq->m_pIovec ) return -1; if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) ) return 0; pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER; if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf ) { pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf; pReq->m_pIovecCur->iov_len = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf; pReq->m_totalLen += pReq->m_pIovecCur->iov_len; ++pReq->m_pIovecCur; } pReq->m_pIovec->iov_len = sizeof( struct lsapi_resp_header) + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short ); pReq->m_totalLen += pReq->m_pIovec->iov_len; lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader, LSAPI_RESP_HEADER, pReq->m_totalLen ); pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader; pReq->m_pIovecToWrite = pReq->m_pIovec; return 0; } int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, const char * pHeaderValue ) { int nameLen, valLen, len; if ( !pReq || !pHeaderName || !pHeaderValue ) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) return -1; if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) return -1; nameLen = strlen( pHeaderName ); valLen = strlen( pHeaderValue ); if ( nameLen == 0 ) return -1; while( nameLen > 0 ) { char ch = *(pHeaderName + nameLen - 1 ); if (( ch == '\n' )||( ch == '\r' )) --nameLen; else break; } if ( nameLen <= 0 ) return 0; while( valLen > 0 ) { char ch = *(pHeaderValue + valLen - 1 ); if (( ch == '\n' )||( ch == '\r' )) --valLen; else break; } len = nameLen + valLen + 1; if ( len > LSAPI_RESP_HTTP_HEADER_MAX ) return -1; if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) { int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf; newlen -= newlen % 4096; if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) return -1; } memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen ); pReq->m_pRespHeaderBufPos += nameLen; *pReq->m_pRespHeaderBufPos++ = ':'; memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen ); pReq->m_pRespHeaderBufPos += valLen; *pReq->m_pRespHeaderBufPos++ = 0; ++len; /* add one byte padding for \0 */ pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len; ++pReq->m_respHeader.m_respInfo.m_cntHeaders; return 0; } int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len ) { if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX ) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) return -1; if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) return -1; while( len > 0 ) { char ch = *(pBuf + len - 1 ); if (( ch == '\n' )||( ch == '\r' )) --len; else break; } if ( len <= 0 ) return 0; if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) { int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf; newlen -= newlen % 4096; if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) return -1; } memmove( pReq->m_pRespHeaderBufPos, pBuf, len ); pReq->m_pRespHeaderBufPos += len; *pReq->m_pRespHeaderBufPos++ = 0; ++len; /* add one byte padding for \0 */ pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len; ++pReq->m_respHeader.m_respInfo.m_cntHeaders; return 0; } int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog ) { int ret; int fd; int flag = 1; int addr_len; switch( pServerAddr->sa_family ) { case AF_INET: addr_len = 16; break; case AF_INET6: addr_len = sizeof( struct sockaddr_in6 ); break; case AF_UNIX: addr_len = sizeof( struct sockaddr_un ); unlink( ((struct sockaddr_un *)pServerAddr)->sun_path ); break; default: return -1; } fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 ); if ( fd == -1 ) return -1; fcntl( fd, F_SETFD, FD_CLOEXEC ); if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (char *)( &flag ), sizeof(flag)) == 0) { ret = bind( fd, pServerAddr, addr_len ); if ( !ret ) { ret = listen( fd, backlog ); if ( !ret ) return fd; } } ret = errno; close(fd); errno = ret; return -1; } int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) { char achAddr[256]; char * p = achAddr; char * pEnd; struct addrinfo *res, hints; int doAddrInfo = 0; int port; if ( !pBind ) return -1; while( isspace( *pBind ) ) ++pBind; strncpy(achAddr, pBind, 255); achAddr[255] = 0; switch( *p ) { case '/': pAddr->sa_family = AF_UNIX; strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p, sizeof(((struct sockaddr_un *)pAddr)->sun_path) ); return 0; case '[': pAddr->sa_family = AF_INET6; ++p; pEnd = strchr( p, ']' ); if ( !pEnd ) return -1; *pEnd++ = 0; if ( *p == '*' ) { strcpy( achAddr, "::" ); p = achAddr; } doAddrInfo = 1; break; default: pAddr->sa_family = AF_INET; pEnd = strchr( p, ':' ); if ( !pEnd ) return -1; *pEnd++ = 0; doAddrInfo = 0; if ( *p == '*' ) { ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY); } else if (!strcasecmp( p, "localhost" ) ) ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK ); else { #ifdef HAVE_INET_PTON if (!inet_pton(AF_INET, p, &((struct sockaddr_in *)pAddr)->sin_addr)) #else ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p ); if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST) #endif { doAddrInfo = 1; } } break; } if ( *pEnd == ':' ) ++pEnd; port = atoi( pEnd ); if (( port <= 0 )||( port > 65535 )) return -1; if ( doAddrInfo ) { memset(&hints, 0, sizeof(hints)); hints.ai_family = pAddr->sa_family; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if ( getaddrinfo(p, NULL, &hints, &res) ) { return -1; } memcpy(pAddr, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); } if ( pAddr->sa_family == AF_INET ) ((struct sockaddr_in *)pAddr)->sin_port = htons( port ); else ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port ); return 0; } int LSAPI_CreateListenSock( const char * pBind, int backlog ) { char serverAddr[128]; int ret; int fd = -1; ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr ); if ( !ret ) { fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog ); } return fd; } static fn_select_t g_fnSelect = select; typedef struct _lsapi_prefork_server { int m_fd; int m_iMaxChildren; int m_iExtraChildren; int m_iCurChildren; int m_iMaxIdleChildren; int m_iServerMaxIdle; int m_iChildrenMaxIdleTime; int m_iMaxReqProcessTime; int m_iAvoidFork; lsapi_child_status * m_pChildrenStatus; lsapi_child_status * m_pChildrenStatusCur; lsapi_child_status * m_pChildrenStatusEnd; }lsapi_prefork_server; static lsapi_prefork_server * g_prefork_server = NULL; int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ) { if ( g_prefork_server ) return 0; if ( max_children <= 1 ) return -1; if ( max_children >= 10000) max_children = 10000; if (s_max_busy_workers == 0) s_max_busy_workers = max_children / 2 + 1; g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) ); if ( !g_prefork_server ) return -1; memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) ); if ( fp != NULL ) g_fnSelect = fp; s_ppid = getppid(); s_pid = getpid(); setpgid( s_pid, s_pid ); #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) s_total_pages = sysconf(_SC_PHYS_PAGES); #endif g_prefork_server->m_iAvoidFork = avoidFork; g_prefork_server->m_iMaxChildren = max_children; g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ; g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3); if ( g_prefork_server->m_iMaxIdleChildren == 0 ) g_prefork_server->m_iMaxIdleChildren = 1; g_prefork_server->m_iChildrenMaxIdleTime = 300; g_prefork_server->m_iMaxReqProcessTime = 3600; setsid(); return 0; } void LSAPI_Set_Server_fd( int fd ) { if( g_prefork_server ) g_prefork_server->m_fd = fd; } static int lsapi_accept( int fdListen ) { int fd; int nodelay = 1; socklen_t len; char achPeer[128]; len = sizeof( achPeer ); fd = accept( fdListen, (struct sockaddr *)&achPeer, &len ); if ( fd != -1 ) { if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) { setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); } //OPTIMIZATION //if ( s_accept_notify ) // notify_req_received( fd ); } return fd; } static unsigned int s_max_reqs = UINT_MAX; static int s_max_idle_secs = 300; static int s_stop; static void lsapi_cleanup(int signal) { s_stop = signal; } static lsapi_child_status * find_child_status( int pid ) { lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd; while( pStatus < pEnd ) { if ( pStatus->m_pid == pid ) { if (pid == 0) { memset(pStatus, 0, sizeof( *pStatus ) ); pStatus->m_pid = -1; } if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur ) g_prefork_server->m_pChildrenStatusCur = pStatus + 1; return pStatus; } ++pStatus; } return NULL; } void LSAPI_reset_server_state( void ) { /* Reset child status */ g_prefork_server->m_iCurChildren = 0; lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd; while( pStatus < pEnd ) { pStatus->m_pid = 0; ++pStatus; } if (s_busy_workers) __atomic_store_n(s_busy_workers, 0, __ATOMIC_SEQ_CST); if (s_accepting_workers) __atomic_store_n(s_accepting_workers, 0, __ATOMIC_SEQ_CST); } static void lsapi_sigchild( int signal ) { int status, pid; char expect_connected = LSAPI_STATE_CONNECTED; char expect_accepting = LSAPI_STATE_ACCEPTING; lsapi_child_status * child_status; if (g_prefork_server == NULL) return; while( 1 ) { pid = waitpid( -1, &status, WNOHANG|WUNTRACED ); if ( pid <= 0 ) { break; } if ( WIFSIGNALED( status )) { int sig_num = WTERMSIG( status ); #ifdef WCOREDUMP const char * dump = WCOREDUMP( status ) ? "yes" : "no"; #else const char * dump = "unknown"; #endif lsapi_log("Child process with pid: %d was killed by signal: " "%d, core dumped: %s\n", pid, sig_num, dump ); } if ( pid == s_pid_dump_debug_info ) { pid = 0; continue; } if ( pid == s_ignore_pid ) { pid = 0; s_ignore_pid = -1; continue; } child_status = find_child_status( pid ); if ( child_status ) { if (__atomic_compare_exchange_n(&child_status->m_state, &expect_connected, LSAPI_STATE_IDLE, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { if (s_busy_workers) __atomic_fetch_sub(s_busy_workers, 1, __ATOMIC_SEQ_CST); } else if (__atomic_compare_exchange_n(&child_status->m_state, &expect_accepting, LSAPI_STATE_IDLE, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { if (s_accepting_workers) __atomic_fetch_sub(s_accepting_workers, 1, __ATOMIC_SEQ_CST); } child_status->m_pid = 0; --g_prefork_server->m_iCurChildren; } } while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus ) &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 )) --g_prefork_server->m_pChildrenStatusCur; } static int lsapi_init_children_status(void) { char * pBuf; int size = 4096; int max_children; if (g_prefork_server->m_pChildrenStatus) return 0; max_children = g_prefork_server->m_iMaxChildren + g_prefork_server->m_iExtraChildren; size = max_children * sizeof( lsapi_child_status ) * 2 + 3 * sizeof(int); size = (size + 4095) / 4096 * 4096; pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0 ); if ( pBuf == MAP_FAILED ) { perror( "Anonymous mmap() failed" ); return -1; } memset( pBuf, 0, size ); g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf; g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf; g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + max_children; s_busy_workers = (int *)g_prefork_server->m_pChildrenStatusEnd; s_accepting_workers = s_busy_workers + 1; s_global_counter = s_accepting_workers + 1; s_avail_pages = (size_t *)(s_global_counter + 1); setsid(); return 0; } static void dump_debug_info( lsapi_child_status * pStatus, long tmCur ) { char achCmd[1024]; if ( s_pid_dump_debug_info ) { if ( kill( s_pid_dump_debug_info, 0 ) == 0 ) return; } lsapi_log("Possible runaway process, UID: %d, PPID: %d, PID: %d, " "reqCount: %d, process time: %ld, checkpoint time: %ld, start " "time: %ld\n", getuid(), getppid(), pStatus->m_pid, pStatus->m_iReqCounter, tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart ); s_pid_dump_debug_info = fork(); if (s_pid_dump_debug_info == 0) { snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" " "-ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2", pStatus->m_pid, pStatus->m_pid ); if ( system( achCmd ) == -1 ) perror( "system()" ); exit( 0 ); } } static void lsapi_check_child_status( long tmCur ) { int idle = 0; int tobekilled; int dying = 0; int count = 0; lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur; while( pStatus < pEnd ) { tobekilled = 0; if ( pStatus->m_pid != 0 && pStatus->m_pid != -1) { ++count; if ( !pStatus->m_inProcess ) { if (g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren || idle > g_prefork_server->m_iMaxIdleChildren) { ++pStatus->m_iKillSent; //tobekilled = SIGUSR1; } else { if (s_max_idle_secs> 0 && tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5) { ++pStatus->m_iKillSent; //tobekilled = SIGUSR1; } } if (!pStatus->m_iKillSent) ++idle; } else { if (tmCur - pStatus->m_tmReqBegin > g_prefork_server->m_iMaxReqProcessTime) { if ((pStatus->m_iKillSent % 5) == 0 && s_dump_debug_info) dump_debug_info( pStatus, tmCur ); if ( pStatus->m_iKillSent > 5 ) { tobekilled = SIGKILL; lsapi_log("Force killing runaway process PID: %d" " with SIGKILL\n", pStatus->m_pid ); } else { tobekilled = SIGTERM; lsapi_log("Killing runaway process PID: %d with " "SIGTERM\n", pStatus->m_pid ); } } } if ( tobekilled ) { if (( kill( pStatus->m_pid, tobekilled ) == -1 ) && ( errno == ESRCH )) { pStatus->m_pid = 0; --count; } else { ++pStatus->m_iKillSent; ++dying; } } } ++pStatus; } if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 ) { lsapi_log("Children tracking is wrong: Cur Children: %d," " count: %d, idle: %d, dying: %d\n", g_prefork_server->m_iCurChildren, count, idle, dying ); } } //static int lsapi_all_children_must_die(void) //{ // int maxWait; // int sec =0; // g_prefork_server->m_iMaxReqProcessTime = 10; // g_prefork_server->m_iMaxIdleChildren = -1; // maxWait = 15; // // while( g_prefork_server->m_iCurChildren && (sec < maxWait) ) // { // lsapi_check_child_status(time(NULL)); // sleep( 1 ); // sec++; // } // if ( g_prefork_server->m_iCurChildren != 0 ) // kill( -getpgrp(), SIGKILL ); // return 0; //} void set_skip_write(void) { s_skip_write = 1; } int is_enough_free_mem(void) { #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) //minimum 1GB or 10% available free memory return (*s_avail_pages > s_min_avail_pages || (*s_avail_pages * 10) / s_total_pages > 0); #endif return 1; } static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Request * pReq ) { struct sigaction act, old_term, old_quit, old_int, old_usr1, old_child; lsapi_child_status * child_status; int wait_secs = 0; int ret = 0; int pid; time_t lastTime = 0; time_t curTime = 0; fd_set readfds; struct timeval timeout; sigset_t mask; sigset_t orig_mask; lsapi_init_children_status(); act.sa_flags = 0; act.sa_handler = lsapi_sigchild; sigemptyset(&(act.sa_mask)); if( sigaction( SIGCHLD, &act, &old_child ) ) { perror( "Can't set signal handler for SIGCHILD" ); return -1; } /* Set up handler to kill children upon exit */ act.sa_flags = 0; act.sa_handler = lsapi_cleanup; sigemptyset(&(act.sa_mask)); if( sigaction( SIGTERM, &act, &old_term ) || sigaction( SIGINT, &act, &old_int ) || sigaction( SIGUSR1, &act, &old_usr1 ) || sigaction( SIGQUIT, &act, &old_quit )) { perror( "Can't set signals" ); return -1; } while( !s_stop ) { if (s_proc_group_timer_cb != NULL) { s_proc_group_timer_cb(&s_ignore_pid); } curTime = time( NULL ); if (curTime != lastTime ) { lastTime = curTime; if (lsapi_parent_dead()) break; lsapi_check_child_status(curTime ); if (pServer->m_iServerMaxIdle) { if ( pServer->m_iCurChildren <= 0 ) { ++wait_secs; if ( wait_secs > pServer->m_iServerMaxIdle ) return -1; } else wait_secs = 0; } } #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) *s_avail_pages = sysconf(_SC_AVPHYS_PAGES); // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n", // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages); #endif FD_ZERO( &readfds ); FD_SET( pServer->m_fd, &readfds ); timeout.tv_sec = 1; timeout.tv_usec = 0; ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout); if (ret == 1 ) { int accepting = 0; if (s_accepting_workers) accepting = __atomic_load_n(s_accepting_workers, __ATOMIC_SEQ_CST); if (pServer->m_iCurChildren > 0 && accepting > 0) { usleep(400); while(accepting-- > 0) sched_yield(); continue; } } else if ( ret == -1 ) { if ( errno == EINTR ) continue; /* perror( "select()" ); */ break; } else { continue; } if (pServer->m_iCurChildren >= pServer->m_iMaxChildren + pServer->m_iExtraChildren) { lsapi_log("Reached max children process limit: %d, extra: %d," " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n", pServer->m_iMaxChildren, pServer->m_iExtraChildren, pServer->m_iCurChildren, s_busy_workers ? *s_busy_workers : -1 ); usleep( 100000 ); continue; } pReq->m_fd = lsapi_accept( pServer->m_fd ); if ( pReq->m_fd != -1 ) { wait_secs = 0; child_status = find_child_status( 0 ); sigemptyset( &mask ); sigaddset( &mask, SIGCHLD ); if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 ) { perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" ); } pid = fork(); if ( !pid ) { setsid(); if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" ); g_prefork_server = NULL; s_ppid = getppid(); s_pid = getpid(); s_req_processed = 0; s_proc_group_timer_cb = NULL; s_worker_status = child_status; if (pthread_atfork_func) (*pthread_atfork_func)(NULL, NULL, set_skip_write); __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST); if (s_busy_workers) __atomic_add_fetch(s_busy_workers, 1, __ATOMIC_SEQ_CST); lsapi_set_nblock( pReq->m_fd, 0 ); //keep it open if busy_count is used. if (!s_keep_listener && s_busy_workers && *s_busy_workers > (pServer->m_iMaxChildren >> 1)) s_keep_listener = 1; if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem()) && pReq->m_fdListen != -1 ) { close( pReq->m_fdListen ); pReq->m_fdListen = -1; } /* don't catch our signals */ sigaction( SIGCHLD, &old_child, 0 ); sigaction( SIGTERM, &old_term, 0 ); sigaction( SIGQUIT, &old_quit, 0 ); sigaction( SIGINT, &old_int, 0 ); sigaction( SIGUSR1, &old_usr1, 0 ); //init_conn_key( pReq->m_fd ); lsapi_notify_pid( pReq->m_fd ); s_notified_pid = 1; //if ( s_accept_notify ) // return notify_req_received( pReq->m_fd ); return 0; } else if ( pid == -1 ) { lsapi_perror("fork() failed, please increase process limit", errno); if (child_status) child_status->m_pid = 0; } else { ++pServer->m_iCurChildren; if ( child_status ) { child_status->m_pid = pid; child_status->m_tmWaitBegin = curTime; child_status->m_tmStart = curTime; } } close( pReq->m_fd ); pReq->m_fd = -1; if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" ); } else { if (( errno == EINTR )||( errno == EAGAIN)) continue; lsapi_perror("accept() failed", errno); return -1; } } sigaction( SIGUSR1, &old_usr1, 0 ); //kill( -getpgrp(), SIGUSR1 ); //lsapi_all_children_must_die(); /* Sorry, children ;-) */ return -1; } static struct sigaction old_term, old_quit, old_int, old_usr1, old_child; int LSAPI_Postfork_Child(LSAPI_Request * pReq) { int max_children = g_prefork_server->m_iMaxChildren; s_pid = getpid(); __atomic_store_n(&pReq->child_status->m_pid, s_pid, __ATOMIC_SEQ_CST); s_worker_status = pReq->child_status; setsid(); g_prefork_server = NULL; s_ppid = getppid(); s_req_processed = 0; s_proc_group_timer_cb = NULL; if (pthread_atfork_func) (*pthread_atfork_func)(NULL, NULL, set_skip_write); __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST); if (s_busy_workers) __atomic_add_fetch(s_busy_workers, 1, __ATOMIC_SEQ_CST); lsapi_set_nblock( pReq->m_fd, 0 ); //keep it open if busy_count is used. if (!s_keep_listener && s_busy_workers && *s_busy_workers > (max_children >> 1)) s_keep_listener = 1; if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem()) && pReq->m_fdListen != -1 ) { close(pReq->m_fdListen); pReq->m_fdListen = -1; } //init_conn_key( pReq->m_fd ); lsapi_notify_pid(pReq->m_fd); s_notified_pid = 1; //if ( s_accept_notify ) // return notify_req_received( pReq->m_fd ); return 0; } int LSAPI_Postfork_Parent(LSAPI_Request * pReq) { ++g_prefork_server->m_iCurChildren; if (pReq->child_status) { time_t curTime = time( NULL ); pReq->child_status->m_tmWaitBegin = curTime; pReq->child_status->m_tmStart = curTime; } close(pReq->m_fd); pReq->m_fd = -1; return 0; } int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq) { time_t lastTime = 0; time_t curTime = 0; fd_set readfds; struct timeval timeout; int wait_secs = 0; int ret = 0; lsapi_prefork_server * pServer = g_prefork_server; struct sigaction act; lsapi_init_children_status(); act.sa_flags = 0; act.sa_handler = lsapi_sigchild; sigemptyset(&(act.sa_mask)); if (sigaction(SIGCHLD, &act, &old_child)) { perror( "Can't set signal handler for SIGCHILD" ); return -1; } /* Set up handler to kill children upon exit */ act.sa_flags = 0; act.sa_handler = lsapi_cleanup; sigemptyset(&(act.sa_mask)); if (sigaction(SIGTERM, &act, &old_term) || sigaction(SIGINT, &act, &old_int ) || sigaction(SIGUSR1, &act, &old_usr1) || sigaction(SIGQUIT, &act, &old_quit)) { perror( "Can't set signals" ); return -1; } s_stop = 0; pReq->m_reqState = 0; while(!s_stop) { if (s_proc_group_timer_cb != NULL) { s_proc_group_timer_cb(&s_ignore_pid); } curTime = time(NULL); if (curTime != lastTime) { lastTime = curTime; if (lsapi_parent_dead()) break; lsapi_check_child_status(curTime); if (pServer->m_iServerMaxIdle) { if (pServer->m_iCurChildren <= 0) { ++wait_secs; if ( wait_secs > pServer->m_iServerMaxIdle ) return -1; } else wait_secs = 0; } } #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) *s_avail_pages = sysconf(_SC_AVPHYS_PAGES); // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n", // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages); #endif FD_ZERO(&readfds); FD_SET(pServer->m_fd, &readfds); timeout.tv_sec = 1; timeout.tv_usec = 0; ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout); if (ret == 1 ) { int accepting = 0; if (s_accepting_workers) accepting = __atomic_load_n(s_accepting_workers, __ATOMIC_SEQ_CST); if (pServer->m_iCurChildren > 0 && accepting > 0) { usleep( 400); while(accepting-- > 0) sched_yield(); continue; } } else if (ret == -1) { if (errno == EINTR) continue; /* perror( "select()" ); */ break; } else { continue; } if (pServer->m_iCurChildren >= pServer->m_iMaxChildren + pServer->m_iExtraChildren) { lsapi_log("Reached max children process limit: %d, extra: %d," " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n", pServer->m_iMaxChildren, pServer->m_iExtraChildren, pServer->m_iCurChildren, s_busy_workers ? *s_busy_workers : -1); usleep(100000); continue; } pReq->m_fd = lsapi_accept(pServer->m_fd); if (pReq->m_fd != -1) { wait_secs = 0; pReq->child_status = find_child_status(0); ret = 0; break; } else { if ((errno == EINTR) || (errno == EAGAIN)) continue; lsapi_perror("accept() failed", errno); ret = -1; break; } } sigaction(SIGCHLD, &old_child, 0); sigaction(SIGTERM, &old_term, 0); sigaction(SIGQUIT, &old_quit, 0); sigaction(SIGINT, &old_int, 0); sigaction(SIGUSR1, &old_usr1, 0); return ret; } int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) { int fd; int ret; int wait_secs; fd_set readfds; struct timeval timeout; if (s_skip_write) return -1; LSAPI_Finish_r( pReq ); if ( g_prefork_server ) { if ( g_prefork_server->m_fd != -1 ) if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 ) return -1; } else if (s_req_processed > 0 && s_max_busy_workers > 0 && s_busy_workers) { ret = __atomic_load_n(s_busy_workers, __ATOMIC_SEQ_CST); if (ret >= s_max_busy_workers) { send_conn_close_notification(pReq->m_fd); lsapi_close_connection(pReq); } } if ( (unsigned int)s_req_processed > s_max_reqs ) return -1; if ( s_worker_status ) { s_worker_status->m_tmWaitBegin = time( NULL ); } while( g_running ) { if ( pReq->m_fd != -1 ) { fd = pReq->m_fd; } else if ( pReq->m_fdListen != -1 ) fd = pReq->m_fdListen; else { break; } wait_secs = 0; while( 1 ) { if ( !g_running ) return -1; if (s_req_processed && s_worker_status && s_worker_status->m_iKillSent) return -1; FD_ZERO( &readfds ); FD_SET( fd, &readfds ); timeout.tv_sec = 1; timeout.tv_usec = 0; if (fd == pReq->m_fdListen) { if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_ACCEPTING, __ATOMIC_SEQ_CST); if (s_accepting_workers) __atomic_fetch_add(s_accepting_workers, 1, __ATOMIC_SEQ_CST); } ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout); if (fd == pReq->m_fdListen) { if (s_accepting_workers) __atomic_fetch_sub(s_accepting_workers, 1, __ATOMIC_SEQ_CST); if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_IDLE, __ATOMIC_SEQ_CST); } if ( ret == 0 ) { if ( s_worker_status ) { s_worker_status->m_inProcess = 0; if (fd == pReq->m_fdListen) { if (s_keep_listener == 0 || !is_enough_free_mem()) return -1; if (s_keep_listener == 1) { int wait_time = 10; if (s_busy_workers) wait_time += *s_busy_workers * 10; if (s_accepting_workers) wait_time >>= (*s_accepting_workers); if (wait_secs >= wait_time) return -1; } } } ++wait_secs; if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs )) return -1; if ( lsapi_parent_dead() ) return -1; } else if ( ret == -1 ) { if ( errno == EINTR ) continue; else return -1; } else if ( ret >= 1 ) { if (s_req_processed && s_worker_status && s_worker_status->m_iKillSent) return -1; if ( fd == pReq->m_fdListen ) { pReq->m_fd = lsapi_accept( pReq->m_fdListen ); if ( pReq->m_fd != -1 ) { if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST); if (s_busy_workers) __atomic_fetch_add(s_busy_workers, 1, __ATOMIC_SEQ_CST); fd = pReq->m_fd; lsapi_set_nblock( fd, 0 ); //init_conn_key( pReq->m_fd ); if (!s_keep_listener) { close( pReq->m_fdListen ); pReq->m_fdListen = -1; } if ( s_accept_notify ) if ( notify_req_received( pReq->m_fd ) == -1 ) return -1; } else { if (( errno == EINTR )||( errno == EAGAIN)) continue; lsapi_perror( "lsapi_accept() error", errno ); return -1; } } else break; } } if ( !readReq( pReq ) ) { if ( s_worker_status ) { s_worker_status->m_iKillSent = 0; s_worker_status->m_inProcess = 1; ++s_worker_status->m_iReqCounter; s_worker_status->m_tmReqBegin = s_worker_status->m_tmLastCheckPoint = time(NULL); } ++s_req_processed; return 0; } lsapi_close_connection(pReq); LSAPI_Reset_r( pReq ); } return -1; } void LSAPI_Set_Max_Reqs( int reqs ) { s_max_reqs = reqs - 1; } void LSAPI_Set_Max_Idle( int secs ) { s_max_idle_secs = secs; } void LSAPI_Set_Max_Children( int maxChildren ) { if ( g_prefork_server ) g_prefork_server->m_iMaxChildren = maxChildren; } void LSAPI_Set_Extra_Children( int extraChildren ) { if (( g_prefork_server )&&( extraChildren >= 0 )) g_prefork_server->m_iExtraChildren = extraChildren; } void LSAPI_Set_Max_Process_Time( int secs ) { if (( g_prefork_server )&&( secs > 0 )) g_prefork_server->m_iMaxReqProcessTime = secs; } void LSAPI_Set_Max_Idle_Children( int maxIdleChld ) { if (( g_prefork_server )&&( maxIdleChld > 0 )) g_prefork_server->m_iMaxIdleChildren = maxIdleChld; } void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle ) { if ( g_prefork_server ) g_prefork_server->m_iServerMaxIdle = serverMaxIdle; } void LSAPI_Set_Slow_Req_Msecs( int msecs ) { s_slow_req_msecs = msecs; } int LSAPI_Get_Slow_Req_Msecs(void) { return s_slow_req_msecs; } void LSAPI_No_Check_ppid(void) { s_ppid = 0; } int LSAPI_Get_ppid(void) { return(s_ppid); } #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) #include #else extern char ** environ; #endif static void unset_lsapi_envs(void) { char **env; #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) env = *_NSGetEnviron(); #else env = environ; #endif while( env != NULL && *env != NULL ) { if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 ) || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid))) { char ** del = env; do *del = del[1]; while( *del++ ); } else ++env; } } static int lsapi_initSuEXEC(void) { int i; struct passwd * pw; s_defaultUid = 0; s_defaultGid = 0; if ( s_uid == 0 ) { const char * p = getenv( "LSAPI_DEFAULT_UID" ); if ( p ) { i = atoi( p ); if ( i > 0 ) s_defaultUid = i; } p = getenv( "LSAPI_DEFAULT_GID" ); if ( p ) { i = atoi( p ); if ( i > 0 ) s_defaultGid = i; } p = getenv( "LSAPI_SECRET" ); if (( !p )||( readSecret(p) == -1 )) return -1; if ( g_prefork_server ) { if ( g_prefork_server->m_iMaxChildren < 100 ) g_prefork_server->m_iMaxChildren = 100; if ( g_prefork_server->m_iExtraChildren < 1000 ) g_prefork_server->m_iExtraChildren = 1000; } } if ( !s_defaultUid || !s_defaultGid ) { pw = getpwnam( "nobody" ); if ( pw ) { if ( !s_defaultUid ) s_defaultUid = pw->pw_uid; if ( !s_defaultGid ) s_defaultGid = pw->pw_gid; } else { if ( !s_defaultUid ) s_defaultUid = 10000; if ( !s_defaultGid ) s_defaultGid = 10000; } } return 0; } static int lsapi_check_path(const char *p, char *final, int max_len) { char resolved_path[PATH_MAX+1]; int len = 0; char *end; if (*p != '/') { if (getcwd(final, max_len) == NULL) return -1; len = strlen(final); *(final + len) = '/'; ++len; } end = memccpy(&final[len], p, '\0', PATH_MAX - len); if (!end) { errno = EINVAL; return -1; } p = final; if (realpath(p, resolved_path) == NULL && errno != ENOENT && errno != EACCES) return -1; if (strncmp(resolved_path, "/etc/", 5) == 0) { errno = EPERM; return -1; } return 0; } static int lsapi_reopen_stderr2(const char *full_path) { int newfd = open(full_path, O_WRONLY | O_CREAT | O_APPEND, 0644); if (newfd == -1) { LSAPI_perror_r(NULL, "Failed to open custom stderr log", full_path); return -1; } if (newfd != 2) { dup2(newfd, 2); close(newfd); dup2(2, 1); } if (s_stderr_log_path && full_path != s_stderr_log_path) { free(s_stderr_log_path); s_stderr_log_path = NULL; } s_stderr_log_path = strdup(full_path); return 0; } static int lsapi_reopen_stderr(const char *p) { char full_path[PATH_MAX]; if (s_uid == 0) return -1; if (lsapi_check_path(p, full_path, PATH_MAX) == -1) { LSAPI_perror_r(NULL, "Invalid custom stderr log path", p); return -1; } return lsapi_reopen_stderr2(full_path); } int LSAPI_Init_Env_Parameters( fn_select_t fp ) { const char *p; char ch; int n; int avoidFork = 0; p = getenv("LSAPI_STDERR_LOG"); if (p) { lsapi_reopen_stderr(p); } if (!s_stderr_log_path) s_stderr_is_pipe = isPipe(STDERR_FILENO); p = getenv( "PHP_LSAPI_MAX_REQUESTS" ); if ( !p ) p = getenv( "LSAPI_MAX_REQS" ); if ( p ) { n = atoi( p ); if ( n > 0 ) LSAPI_Set_Max_Reqs( n ); } p = getenv( "LSAPI_KEEP_LISTEN" ); if ( p ) { n = atoi( p ); s_keep_listener = n; } p = getenv( "LSAPI_AVOID_FORK" ); if ( p ) { avoidFork = atoi( p ); if (avoidFork) { s_keep_listener = 2; ch = *(p + strlen(p) - 1); if ( ch == 'G' || ch == 'g' ) avoidFork *= 1024 * 1024 * 1024; else if ( ch == 'M' || ch == 'm' ) avoidFork *= 1024 * 1024; if (avoidFork >= 1024 * 10240) s_min_avail_pages = avoidFork / 4096; } } p = getenv( "LSAPI_ACCEPT_NOTIFY" ); if ( p ) { s_accept_notify = atoi( p ); } p = getenv( "LSAPI_SLOW_REQ_MSECS" ); if ( p ) { n = atoi( p ); LSAPI_Set_Slow_Req_Msecs( n ); } #if defined( RLIMIT_CORE ) p = getenv( "LSAPI_ALLOW_CORE_DUMP" ); if ( !p ) { struct rlimit limit = { 0, 0 }; setrlimit( RLIMIT_CORE, &limit ); } else s_enable_core_dump = 1; #endif p = getenv( "LSAPI_MAX_IDLE" ); if ( p ) { n = atoi( p ); LSAPI_Set_Max_Idle( n ); } if ( LSAPI_Is_Listen() ) { n = 0; p = getenv( "PHP_LSAPI_CHILDREN" ); if ( !p ) p = getenv( "LSAPI_CHILDREN" ); if ( p ) n = atoi( p ); if ( n > 1 ) { LSAPI_Init_Prefork_Server( n, fp, avoidFork != 0 ); LSAPI_Set_Server_fd( g_req.m_fdListen ); } p = getenv( "LSAPI_EXTRA_CHILDREN" ); if ( p ) LSAPI_Set_Extra_Children( atoi( p ) ); p = getenv( "LSAPI_MAX_IDLE_CHILDREN" ); if ( p ) LSAPI_Set_Max_Idle_Children( atoi( p ) ); p = getenv( "LSAPI_PGRP_MAX_IDLE" ); if ( p ) { LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) ); } p = getenv( "LSAPI_MAX_PROCESS_TIME" ); if ( p ) LSAPI_Set_Max_Process_Time( atoi( p ) ); if ( getenv( "LSAPI_PPID_NO_CHECK" ) ) { LSAPI_No_Check_ppid(); } p = getenv("LSAPI_MAX_BUSY_WORKER"); if (p) { n = atoi(p); s_max_busy_workers = n; if (n >= 0) LSAPI_No_Check_ppid(); } p = getenv( "LSAPI_DUMP_DEBUG_INFO" ); if ( p ) s_dump_debug_info = atoi( p ); if ( lsapi_initSuEXEC() == -1 ) return -1; #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) lsapi_initLVE(); #endif } unset_lsapi_envs(); return 0; } int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders, const char * pBody, int bodyLen ) { LSAPI_SetRespStatus_r( pReq, code ); if ( pRespHeaders ) { while( *pRespHeaders ) { LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) ); ++pRespHeaders; } } if ( pBody &&( bodyLen > 0 )) { LSAPI_Write_r( pReq, pBody, bodyLen ); } LSAPI_Finish_r( pReq ); return 0; } static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]); /* * Note: this code is harmless on little-endian machines. */ static void byteReverse(unsigned char *buf, unsigned longs) { uint32 t; do { t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); *(uint32 *) buf = t; buf += 4; } while (--longs); } /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ void lsapi_MD5Init(struct lsapi_MD5Context *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bits[0] = 0; ctx->bits[1] = 0; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len) { register uint32 t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if (t) { unsigned char *p = (unsigned char *) ctx->in + t; t = 64 - t; if (len < t) { memmove(p, buf, len); return; } memmove(p, buf, t); byteReverse(ctx->in, 16); lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { memmove(ctx->in, buf, 64); byteReverse(ctx->in, 16); lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ memmove(ctx->in, buf, len); } /* * Final wrap-up - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx) { unsigned int count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in, 16); lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); } else { /* Pad block to 56 bytes */ memset(p, 0, count - 8); } byteReverse(ctx->in, 14); /* Append length in bits and transform */ ((uint32 *) ctx->in)[14] = ctx->bits[0]; ((uint32 *) ctx->in)[15] = ctx->bits[1]; lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memmove(digest, ctx->buf, 16); memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ } /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]) { register uint32 a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } int LSAPI_Set_Restored_Parent_Pid(int pid) { int old_ppid = s_ppid; s_restored_ppid = pid; return old_ppid; } int LSAPI_Inc_Req_Processed(int cnt) { return __atomic_add_fetch(s_global_counter, cnt, __ATOMIC_SEQ_CST); } PK% ]Dk--&gems/ruby-lsapi-5.5/ext/lsapi/lsapi.sonuȯELF>U@&@8 @ !!0 !!888$$hhh Stdhhh PtdPPPQtdRtd!!P P GNU5<-s흏2bC H‚3@(L`qCSlP*fRn}'3qѮl>&Sɶ ܮʼnSO`[is|&߱RD/y7řkՊ eY&09=By:%/=ejOzJ6'l#mNULCB1{!\$O#W23S=apbU06aD7jp#7ĴDIΊ=\4yݾCEкQuo rSѮIo|q%h6 󝵛 ' =qX[ u  f   d ysOq    T [M f A k &K ! , 2TRT" s G +L  } >W  9 - kH  .E   $7x9 vo | Z A 9J 4, 2> F"`| E]   r G p `}F 0rD @I  `K 5 0vi~  z@! b П. P! ] Z\ g o  v 1 r Y ` Pq@  @ sl zj V } - Ps]   `o @rY po  5 o x$ Pl! u U U E v rS o7 @oT (   0  }F rJ @pT ! P~I   Е  P!b g  @g "! l p6 o p [ !__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizecompareValueLocationset_skip_writesigactionsigemptyset__stack_chk_failreallocfcntlacceptsetsockoptmmapmemsetsetsidread__errno_locationclosewritevkillgetppid__ctype_b_locstrncpystrchrstrcasecmpstrtolgetaddrinfomemcpyfreeaddrinfoinet_addrLSAPI_Log__vfprintf_chk__snprintf_chkgetuid__fprintf_chkgettimeofdaylocaltime_rwaitpidforksystemexitlsapi_perrorstrerrorLSAPI_is_suEXEC_DaemonLSAPI_StopLSAPI_IsRunningLSAPI_Register_Pgrp_Timer_CallbackLSAPI_InitRequestmallocgetpeernamedup2LSAPI_Initgeteuidsignalg_reqdlopendlsymLSAPI_Is_Listen_rLSAPI_Is_ListenLSAPI_Reset_rLSAPI_Release_rfreeLSAPI_GetHeader_rLSAPI_ReqBodyGetChar_rLSAPI_ReqBodyGetLine_rmemchrmemmoveLSAPI_ReadReqBody_rFlush_RespBuf_rLSAPI_GetEnv_rstrcmp__ctype_toupper_locLSAPI_ForeachOrgHeader_rqsortLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rLSAPI_ForeachSpecialEnv_rLSAPI_FinalizeRespHeaders_rLSAPI_Flush_rLSAPI_Write_Stderr_rgetpidgetcwdmemccpy__realpath_chkLSAPI_Finish_rLSAPI_End_Response_rLSAPI_Write_rLSAPI_sendfile_rsendfileLSAPI_AppendRespHeader2_rstrlenLSAPI_AppendRespHeader_rLSAPI_CreateListenSock2socketbindlistenunlinkLSAPI_ParseSockAddrLSAPI_CreateListenSockLSAPI_Init_Prefork_ServercallocsetpgidsysconfLSAPI_Set_Server_fdLSAPI_reset_server_stateis_enough_free_memLSAPI_Postfork_ChildLSAPI_Postfork_ParenttimeLSAPI_Accept_Before_Fork__fdelt_chkusleepsched_yieldLSAPI_Set_Max_ReqsLSAPI_Set_Max_IdleLSAPI_Set_Max_ChildrenLSAPI_Set_Extra_ChildrenLSAPI_Set_Max_Process_TimeLSAPI_Set_Max_Idle_ChildrenLSAPI_Set_Server_Max_Idle_SecsLSAPI_Set_Slow_Req_MsecsLSAPI_Get_Slow_Req_MsecsLSAPI_No_Check_ppidLSAPI_Get_ppidLSAPI_Init_Env_Parametersgetenvgetpwnamdlerrorsetrlimit__fxstatsetreuidLSAPI_ErrResponse_rlsapi_MD5Initlsapi_MD5Updatelsapi_MD5FinalgetpwuidsetgidsetgroupssetuidstrtollprctlinitgroupsLSAPI_Accept_rLSAPI_Prefork_Accept_rsigaddsetsigprocmaskLSAPI_Set_Restored_Parent_PidLSAPI_Inc_Req_Processedselectrb_tainted_str_newrb_hash_asetrb_funcallvrb_intern2rb_gc_markmunmaprb_check_typerb_obj_as_stringrb_f_sprintfs_fn_add_envrb_safe_levelrb_string_value_ptrrb_eval_string_wraprb_string_valuerb_check_safe_objrb_ruby_verbose_ptrrb_define_global_construby_strdupmkstempftruncaterb_str_buf_newrb_str_catrb_num2intrb_fix2intrb_eSecurityErrorrb_raisememmemrb_yieldrb_gc_writebarrier_unprotectrb_io_putsrb_ary_detransientrb_str_new_staticrb_exec_recursiverb_default_rsrb_output_fsrb_output_rsrb_lastline_getInit_lsapichdirrb_stderrrb_cObjectrb_const_getrb_global_variablerb_define_global_functionrb_define_classrb_define_singleton_methodrb_define_methodrb_data_object_zallocrb_stdoutrb_stdinrb_hash_new__memcpy_chklibruby.so.2.6libm.so.6libc.so.6__environ_edata__bss_start_endGLIBC_2.14GLIBC_2.15GLIBC_2.4GLIBC_2.3.4GLIBC_2.2.5GLIBC_2.3/opt/alt/ruby26/lib64@ l w ii  ti  ui  ii  !U!pU!!!!!!!!!! !(!0! 8!@!*H!8P!CX!P`!_h!fp!nx!s!z!!!!!!!!!!!!!!!2!G !\(!o0!8!@!H!P!X!`!h!p!x!!!!2!@!Y!i!t!!!!!!!X!!!!H!P!X!`!h!p!x!!!$!5!!?!K!M!U!Y!Y!Z!!!q!!! ! ! ! ! ! ! !( !0 !8 !@ !H ! P ! X ! ` ! h ! p !x ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !( ! 0 !8 !"@ !#H !%P !&X !` !'h !(p !)x ! !* !+ ! !, ! ! ! !- !. !/ !0 ! ! ! ! !1 !2 !3 ! !4 !( !0 !68 !7@ !8H !9P !:X !;` !<h !>p !@x !A !B !C ! !D !E !F !G !H !I ! !J ! !L !N !O !P !Q !R ! !S !T( !0 !V8 !@ !WH !XP ![X !\` !]h !^p !_x !` !a ! !b !c ! !d !e !f !g !h !i !j !k !l !m !!n!o!p! !(!r0!s8!t@!uH!vP!X!w`!xh!yp!{x!|!}!~!!!!!!!!!!!!!!!!!! !(!0!8!@!HH! HtH5J %K hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhA% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݾ D%վ D%; D%ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݽ D%ս D%ͽ D%Ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݼ D%ռ D%ͼ D%ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݻ D%ջ D%ͻ D%Ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݺ D%պ D%ͺ D%ź D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E DH= H H9tH6 Ht H= H5 H)HHH?HHtH HtfD=e u+UH=b Ht H=. d= ]wff. ÐHGH+FHcAVIH@AUATL$USHtQHHtIHIL9r 0HI9v'KHSMsH;Յ[]A\A]A^[D]A\A]A^øff.f= D2 ÐO AWDD_AVAUATUSD6^nAxj׋G3G D!3G V\$ЋW^$DD1\$!3WAʋN Fp $E‰L$A1A1DD^ !D1G;νD\$DEDVDT$A!A1EE|A 1AD!E1DD*ƇGD1D!A1A1DDN DL$E F0D!DnA1D1DGFEDf Dd$D^(A!A1EEؘiA 1AD!1DDDʋ^0D1D!A1DE [D 1!D1DDN,A1DL$G\EA!Df8A1ED"kA 1AD!1DDN4EqDD1!1DE CyD 1!D1DDV<1G!I!1DDD$ Eb%1!1DDD$E@@1!1DDD$ EQZ^&1!1DE6Ƕ1!1DD]/։ 1!1DESD1!1DE ؉ 1!1DDD$E01!1DDD$ E!1!1DE7É1!1DDD$ E 1!1DDD$A0ZEAA1A!A1AA㩉A AD1!1t$DD1!A ogD1 1D!FL*1DD$Ή1AA!B9A1DD$A AD1D$qDD11‹D$ 0"amD1G 81Ɖ11DDD$ ED꾤11DDD$AKAA1A5`KA1AЉApA 1AD1D1D1A ~(D 1G'111DDD$ A0AA1A1AЋT$A2A1D1֋T$ 9ىDD11D11C|A A1A1AD$A0eVĉA1D1AD")Dt$ D D1A *CDG# 1  1DD9Ή 1DDY[e\$  1DE Dt$ щ1DE3}D\$  1DDD$E] 1DEO~oA AD 1DE ,DT$ A1ADE6CDt$ AN 1A~SADEAA A1A5:ADA AD 1Љ3*\$D D1DFӆ[ ]A\A]A^ 1։ 1DƉA4A_ OW GOW ATI1USHdH%(H$1HHH<$t)H$dH3%(uL{8IHC0L)H9>Lt$L+{(LA@LLfIM)MK H@σLSLCpNIHDI0HI@HKpM~HC(MxIH E1I@HC8HL1HMLIHHKpH9eHMthILM)MUI9t H)tDL+t$HL[]A\A]A^A_DM@@M)(+IHt$HLHk8f.HAVLAUIATIUSHu\H߉[AD${LǃLSHu0{L[L]A\A]A^K[H]A\A]A^Hff.AWAVAUATUSHHHHD$ 0xIHIHLc\CHcT t u(HDLcLH t tLÅ~6HcAT t u#H@Å~ALH t tE<AG=I|$PHHTI9T$Hs7HI+t$@L2%))I|$PLHHcAMt$PHLIFID$PA:I|$P}MD$PII@ID$PAIc$0fET8HЃA$0D$ H[]A\A]A^A_D$ ff.H HB=0AUATUSHcHfDA< t< uH؅uH[]A\A]IHPHHDI9D$Hs3HI+t$@L2%))tQI|$PHHAPI\$PHCID$PIc$0fET8HЃA$0H1[]A\A]øSDAUATAUHSH?dH%(HD$1D$ff t1fHL$dH3 %(H[]A\A]ÐA1ҾÃtʼnǺ1HL$Aߺ踿u#DH'uDo̾߻D HJDeOAkDH}An衾}NSHtff.USHdH%(H$1HHu/HH$dH3%(uHĘ[]Ŀ@1H= tAUATA'USH݋ 'DNuD H@AHH^ HHtH- t YƉlj JUDk HM DcEuSH8dH%(H$(1=HtH H=H H=_>HE1 H讹H=Y>Ht 1H膹 H=E>ijHHt 1H]IAąWE1H=">萳Ht 1H, H=>jHtHǺ 1_H==CH H==$HtHǺ 1IԶH==H1 H舸OH==òHtHǺ 1_H==蜲HtHǺ 18!H==uHtHǺ 1H==NHtHǺ 1蓲H=r='HtMH=p=Ht 1H護ۀ _H=X=Ht 1H D   EH=$=H=r u Pe 5[ H=&=cH 1H% …t% HQv HHHHD L*=L =L#=C HLt@HֹL€D t%HtAHHt9HLuHfDHJHHJHuHHu1ۉH$(dH3%(H8[]A\A]fD& H覲D9舭HHiHǺ11˵ÃHT$ƿD$(?H5/ رHgH Htxc@dx@D  E9D E)ZfH=}8贬 HK]  u t 'j X '> )fՅtbH H-DHH5?1 cAHc螲L%~ HH~ a蓮Åt=~ 0~ u ~ 5~ `HH5@?uHH5>1u HH5>Fff.AVIAUEATIUHSHt4Hu!(fDHH蔭HLgH]HuMtEL [1]A\A]A^ÐIcLLH#EgHGHHܺvT2HGAWAVAAUIATUHoSH1HGO@ƉWDW?t;AĉDHH|@D)A9rhAGt4LLDHL9A?vWEfAIIIH޺@HH@ HLL9uA?DLHH[]A\A]A^A_ܱIATLfUHSFH?LHz?)ƒw=t19rLHfCAD$AD$ ID$071)"HCHLHCP?o H{1HMHHCPH)KXH[]A\ff.fAWAVAUATUSHdH%(H$1Ht^ IAfMcg IoA_@LH3HuM88u =Yw uٽH$dH3 %( HĨ[]A\A]A^A_f~AAuIALJf8LS|xr@tPHf@HPXN MgA;G ZA9~uEo)HHcIHLD"Hu$'85Dv uAMgA9ID$,HD$HcIIDhAh(A9}A /HcIH4@HUHAIIh$A9}A HcIH4@HHAIIHl$p(ILHIILp$hMIc@o9gIcP[9SIcpG9?IcH39+IHHHHIHT$IIc@ H)IHHIHHHIHIIcHIHHHD$I9E1DL4t9dfH H IGAG IPH f@ f@ HHP P H HPPHHPPHHPPHHPPf@f@f@HH#PP H H'P#P$H$H+P'P(f@f@!f@%H(P+f@)I1 fDIHcȋL4t#fBIHT4 rfB@2JHHuMIcP IHHH9pH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@pHH9wMApIbIc@ IH0zu ALJt`!u u Au 1LHc迩IHIGAo IuID%t D-t B(AA1IcH4IILI 9HqH=W. IJDB(9xHqH=2. XIJB($AD$IKAzHL$;MbfoOt Lt$ LAoL$AT$Ml$)$踪 LL(HL$LHLLH$ID$H$I3L$H1H D$$Dl$EDDl$H=s IHIDEs MH=$s t"LDLŃP|$臨Et$A9uHt$莤D=Ń5r $A?D5r t 0AH5*L*HtHHr f)r #AH5:e 1;H@H5+1YLH 1HIH531H531D%q q DD$$H=q IHtZEW7E1111H=3H5*1耨E|$迦M2;|$藦E1H5*LuI}觧Ń1H5*LKfD=p -p p ED$AIFH5*1覧HH)H51H1聧1H5!*L 1H5C2LA#LH 3H H=NQ HL~H-> H 4> H=H HP HzH HJH*HQ H]> HH> HH=P LH5}H = H="H HP HH HJH*H踀yH(yHHP 1aH5P H=}H3H=r}yH(H[]A\A]@HPHH=L }HwHL H.XXXXXXH(Ht+H=uH=O 1HxH5,H=O 1HJfDmHzHfKHzHt -GF OkHyHu-*F 2HHAnonymous mmap() failedlocalhost%02d:%02d:%02d [%s] [UID:%d][%d] %.*syesnosystem()%s, errno: %d (%s) /dev/nulllibpthread.sopthread_atforkHTTP_[UID:%d][%d] %s:%s: %s LSAPI: jail() failure./etc/Can't set signalsaccept() failedLSAPI_STDERR_LOGPHP_LSAPI_MAX_REQUESTSLSAPI_MAX_REQSLSAPI_KEEP_LISTENLSAPI_AVOID_FORKLSAPI_ACCEPT_NOTIFYLSAPI_SLOW_REQ_MSECSLSAPI_ALLOW_CORE_DUMPLSAPI_MAX_IDLEPHP_LSAPI_CHILDRENLSAPI_EXTRA_CHILDRENLSAPI_MAX_IDLE_CHILDRENLSAPI_PGRP_MAX_IDLELSAPI_MAX_PROCESS_TIMELSAPI_PPID_NO_CHECKLSAPI_MAX_BUSY_WORKERLSAPI_DUMP_DEBUG_INFOnobodyLSAPI_DEFAULT_UIDLSAPI_DEFAULT_GIDLSAPI_SECRETLSAPI_LVE_ENABLEliblve.so.0lve_is_availablelve_instance_initlve_destroylve_enterlve_leavejailPHP_LSAPI_PHPRC=packetLen < 0 packetLen > %d Bad request header - ERROR#1 ParseRequest error SUEXEC_AUTHSUEXEC_UGIDLSAPI: setgid()LSAPI: initgroups()LSAPI: setgroups()LSAPI: setuid()Bad request header - ERROR#2 lsapi_accept() errorPragma: no-cacheRetry-After: 60Content-Type: text/htmlDEBUGNOTICEWARNERRORCRITFATALAcceptAccept-CharsetAccept-EncodingAccept-LanguageAuthorizationConnectionContent-TypeContent-LengthCookieCookie2HostPragmaRefererUser-AgentCache-ControlIf-Modified-SinceIf-MatchIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveX-Forwarded-ForViaTransfer-EncodingHTTP_ACCEPTHTTP_ACCEPT_CHARSETHTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_AUTHORIZATIONHTTP_CONNECTIONCONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_COOKIE2HTTP_HOSTHTTP_PRAGMAHTTP_REFERERHTTP_USER_AGENTHTTP_CACHE_CONTROLHTTP_IF_MODIFIED_SINCEHTTP_IF_MATCHHTTP_IF_NONE_MATCHHTTP_IF_RANGEHTTP_IF_UNMODIFIED_SINCEHTTP_KEEP_ALIVEHTTP_RANGEHTTP_X_FORWARDED_FORHTTP_VIAHTTP_TRANSFER_ENCODING%04d-%02d-%02d %02d:%02d:%02d.%06d Child process with pid: %d was killed by signal: %d, core dumped: %s Possible runaway process, UID: %d, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld gdb --batch -ex "attach %d" -ex "set height 0" -ex "bt" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2Force killing runaway process PID: %d with SIGKILL Killing runaway process PID: %d with SIGTERM Children tracking is wrong: Cur Children: %d, count: %d, idle: %d, dying: %d LSAPI: LVE jail(%d) result: %d, error: %s ! Invalid custom stderr log pathFailed to open custom stderr logCan't set signal handler for SIGCHILDReached max children process limit: %d, extra: %d, current: %d, busy: %d, please increase LSAPI_CHILDREN. LSAPI: failed to open secret file: %s! LSAPI: failed to check state of file: %s! LSAPI: file permission check failure: %s LSAPI: failed to read secret from secret file: %s LSAPI: Unable to initialize LVERequest header does match total size, total: %d, real: %ld LSAPI: missing SUEXEC_UGID env, use default user! LSAPI: SUEXEC_AUTH authentication failed, use default user! LSAPI: lve_enter() failure, reached resource limit.prctl: Failed to set dumpable, core dump may not be available!sigprocmask(SIG_BLOCK) to block SIGCHLDsigprocmask( SIG_SETMASK ) to restore SIGMASK in childfork() failed, please increase process limitsigprocmask( SIG_SETMASK ) to restore SIGMASKCache-Control: private, no-cache, no-store, must-revalidate, max-age=0PID 508 Resource Limit Is Reached

Resource Limit Is Reached

The website is temporarily unable to service your request as it exceeded resource limit. Please try again later.
          replacesrandQUERY_STRINGREQUEST_URIPATH_INFOREQUEST_PATHSCRIPT_NAMESTDERRreopenftruncate() failed. File mapping failed. Memory calloc error[...]nilLSAPI_MAX_BODYBUF_LENGTHLSAPI_TEMPFILEXXXXXXRACK_ROOTchdir()to_hashCGI/1.2eval_string_wrapLSAPIacceptaccept_new_connectionpostfork_childpostfork_parentprocessputcwriteprintprintfputs<<flushgetcgetsreadrewindeacheofeof?closebinmodeisattytty?syncsync=RACK_ENVInsecure: operation on untainted IOGATEWAY_Irewindable_input.rbNTERFACE/tmp/lsapi.XXXXX;z@Ze pp8pLp`pt q0q@qx00ydyxyPzz|$|t}~<Pd$@ppH p  0 @ Ќ 0 D PX t ` Џ 8 PL p P d `x p ph ` (pt@ @pp0<PPdx`Я,@T h@|`й4Ptp@ L $@8pL`tp00\Pxp@,`x`@ pHzRx $@V FJ w?:*3$"D` \0lp,l(l L$lsEIB E(A0z (A BBBI A (D BBBA Tl Pl@LlYGJB B(A0A80F(B DBb0ThsBFC G  AABK sk( tGADJ n AAA 4DtUAGK R CAG L JCG ltAG] AJ $tt C KFLHuBBE A(H0H (D BBBD  (D BBBA PtvvFB A(D0D (A BBBB L(A BBBA$vaAAD XAAHwBBB B(A0A8D@N 8C0A(B BBBH $`wOAf Q C E H@wYBBB A(D0J 0A(A BBBF xzFEA C(G   (A ABBD M I c A  E M A k E E E E H V HHT|FBB B(A0A8D`` 8A0A(B BBBD l}+BBB B(A0D8JYHPC Mi 8A0A(B BBBE LTMDd~6BBB B(A0A8DP 8A0A(B BBBG  8J0H(G DBBK $l`7EFF IIOx | 4xFAA G>  AABG EO D  A @ ThY|JED$S p]Ph H XAHlFBB B(A0A8LP 8A0A(B BBBH <Є FBB A(A0 (D BBBI \i`pFBB B(A0A8DP~ 8A0A(B BBBA k 8A0A(B BBBH L$FBB A(A0H Q D 0A(A BBBH L$FBB B(A0A8G 8A0A(B BBBF thFF$lnCXJLDlFBB B(A0A8DA 8A0A(B BBBA `( dBBB B(A0A8G I K I L N N w 8A0A(B BBBI 0 BMD GL  AABA < |=BAA G L@I@U  AABG $ |TWEHG ( ag H SHL pFBB B(A0A8DPS 8D0A(B BBBF T bIE D(C0P (F BBBM Q(H BBBAH lFBB B(A0A8DP 8A0A(B BBBA T< CBA A(G0` (A ABBD  (C ABBA J8 Ȗ-FBD D(D@T (A ABBB  ( ȗlECGF AAI L !cBG A(D0 (A ABBE XD0` t Z D10 ppFAA G@7  AABF  @LsL КFBB B(A0A8G 8A0A(B BBBG < P d x    Ȟ Ԟ  О  ̞Ȟ <Ğ FBA K(G (A ABBG <XFEE D(D0M (C BBBB ԧ(HFBH E(A0E8I@ 8A0A(B BBBE (FED ABH$8 BBB B(A0A8G 8A0A(B BBBJ Dp̴FBB A(A0G 0A(A BBBF L4 FBB B(A0A8G  8A0A(B BBBA 4 H\+p(BFGA kFB4zD O E  HU gHQ G <ayd(THEDL ] CAJ ELEY HW HW-Hd(EAD  DAJ ,aED y AE HP FBB E(D0C8GPm 8F0A(B BBBG ,ZAD J ABL 4PoAD  AAK pP \FBD C(G0 (D ABBE j (D ABBE | (G DBBA HdhFBB B(A0A8G@ 8D0A(B BBBD 7^UVvd1",a^E7Y:LP*%p 'P-Eҁ<whoIs2@:ra0l h|w/OR8 #iXtIsBe1q~]|IP9t¨Cv؈s+@r|HS6aRawoto %1ɯ`1/bcRۆP;[0jdZE7TB^:kW/#Iƒ~fpBDURnew·]9 x4M xovyC arD^U;t6#&YCçFZ#`ٔSÕ/7Elqb#SIS,Ko>_]Vp1}=50CoFլ8XgEe+6%(4oOc/$md٤Ũ;xuXx+5E^uCĵ,I)PZ5#ǯ>v>} /`sw[m^"a"Iz09بa~d5*_Mt++!T´TN;GO>jiVnƈw%ZsyX:70ER54$nEWraR{ D'c#DqDMX/3%oRQZWb^· O |a=LQuU)JUsjC q2εxR.8mHP Hq1b A $z")nT\?Iށ-#f ]p2:U]d,D.I@@98 ,.+/*0)1fDHff.HHH+HHODH1f1fATIHUSHcHcLHH=HH[]A\ff.HH5dH%(HD$1HH$Ht-H=HHD$dH3%(u&H@H=HHfDHHH=HfHH=Hc5;5H=|6HHHfDf?IH=HH+9M1~+HHcHc5H5~Hfff.@UHSH HHm t]uaHHHtT؃tJ tEHH؉уu5HM u@HHpH}HH[]HD@HuHHMH tHPHpfSHCH[ff.SHHH[ÐHH=HHHH=HHHH=tHHHUSHH=H=HtHH9t H5Ht[11ҿ1HH-H;HHuHuH;HHHH[]fH=HHSHHt$~0H|$H\$H1HH[@H\$HH|$ff.@AWAVAUAATIUSHHJfDmHHfKHHt -OkHHu-2 GA$3p1067GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA$3p1067GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1067GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1067GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1067GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: gcc-annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realignreplacesrand/QUERY_STRINGREQUEST_URIPATH_INFOREQUEST_PATHSCRIPT_NAMESTDERRreopen%s: %s ftruncate() failed. File mapping failed. Memory calloc error [...]nilLSAPI_MAX_BODYBUF_LENGTHLSAPI_TEMPFILEXXXXXXLSAPI_CHILDRENRACK_ROOTchdir()ENVto_hashCGI/1.2eval_string_wrapLSAPIacceptaccept_new_connectionpostfork_childpostfork_parentprocessputcwriteprintprintfputs<<flushgetcgetsreadrewindeacheofeof?closebinmodeisattytty?syncsync=RACK_ENVInsecure: operation on untainted IOGATEWAY_Irewindable_input.rbNTERFACE/tmp/lsapi.XXXXXG K9%I'P(int)@ 9 1 3 6  7  8  9 : ( ; 0 < 8 = @ @ H A P B X D` Fh Hp It J x MP NW O Q Y [ \ ] ^ G _ - ` b  +  9  9 ? M     UJ U   U a}^q!$2 7 ;  e9:IDf9@4 @\     Hr  @`  @ @ @x@t#u :vF@  :@   3 :hlen ptr aux3ary  9(rash@  0 :elen aux ptreF0ary F 9(rask(g hri % j % k G % !G "% ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::(:+:,:-:.:/:: 9 7  8 9 : ;< = > #@,     $q %s%t kX m n  o  p  u ,                  $  (    4   9 0 9 r               "  "r 4 6 7  /7 1 2  3  4 & :R < = ? @ B C E( F0 G8 I@ JH KP L!WX O` Ph Qp Rx T' V' W' X' Y' Z' \' ]' _ ` a b c d e f g h i'k''m'('n'8'oG R   G  -] X0  9 j(9q7s) !!!!!G-.P W #  \/ l 9 /lww   #   X*r# wW| !, 7rBMXcny  !{$% % %   9  9   9 ;   ;; Ih 9 x 9@hxx+":+#:,$: ,(: ,*: ,,: ,.  2R-req4R-env5: 6q)q!R!!-X7,9: ,;: ,< w,>: +?,@~  BE D E F GH,JE  x(9,K g .  /-K%%0/ :1p0 01 2M3S*K 4HD5U 5T320T6T5%0T23TK 4HD5U 5T74UD5Q05R02,0 :4bD5TH5Q 5R|2q0:4bD5TH5Q 5R|7A%38e%59:s%:~%86: ;H:4oD5Us5T05Q:<{D%5U <DC5Us5TM<Da5Us5Tm<D5Us5TK4D5Us5Tk8K%69:Y%8 :!*;):;:4D5U 5Ts5Qv5R =9# k;9;9<{D5U 4D5Us86:9;H:4oD5T05Q:>D<{D 5U >D>D<{DE5U >D>E< E~5U <E5U 5T7<E5U 5TA<'E5Q}<4E5U 5T 5Q1<AE.5U <NE_5T 5Q 5R0<ZE5T 5Q 5R0<ZE5T 5Q 5R1<ZE5T 5Q 5R1<ZE$ 5T 5Q 5R <ZEV 5T 5Q 5R <ZE 5T 5Q 5R <ZE 5T 5Q 5R1<ZE 5T 5Q 5R0<ZE!5T 5Q 5R0<ZEL!5T 5Q 5R0<ZE~!5T 5Q 5R <ZE!5T 5Q 5R0<ZE!5T 5Q 5R0<ZE"5T 5Q 5R0<ZEB"5T 5Q 5R0<ZEs"5T 5Q 5R0<ZE"5T 5Q 5R0<ZE"5T 5Q 5R0<ZE#5T 5Q 5R0<ZE7#5T 5Q 5R0<ZEh#5T 5Q 5R1<ZE#5T 5Q 5R < E#5U < E#5U >gE>gE>tE>i4<E+$5U <EJ$5U >gE<NE$5T 5Q 5R0<NE$5T 5Q 5R0<NE$5T 5Q 5R0<E %5U 4{D5U  F5%?:%%%@& A e%BpA %Bn  Bp C:%D D-D9:6 :E3*K F:gl&G :Hz+ >E>E>EF:&I":UI-:TJ:&D:C:&D!:F: 'I":UF:+{'I:UK8 L8F:C8(G:1str :=8( ';J(7+ <**(5Us>EC:X(D!:Fr:*GrGr*Gr6:1strt :1nu 0v 0w 89 N);9>E>E>E>/+<E)5Us $ &<R*)5U}<F)5U|5Qs $ &<F)5U|5Q} $ &4F5T CC:R*DC :BstrE :6FBnG BpH F. a+G."M0 01 02 03 64 884+L8>FN)N$O N+Bfd Oz+Bfd Bsfn NC:+D :Bch F:+G!:>EF:c,Pout!:Pstr,:4.5Us5TTC:,DD*Qout6:Bi 6 :Ce:-Qarye#:Qoute.:De7Btmpg :Bih F\:-G\G\,Pout\8:<'F-5UU5TT4.5UsF8:O.G8G8,Pout88:1i: 3; :@8.9JK.;@9<4Fh.5U~5T3<..5Uv<..5Uv<..5Uv<..5Uv>AF>NFR,:/G,!:Pstr,-:0.1len/ 890/;94WF5Uv5T<8.92 /;@94dF5UsF : 1G :Pc +:Sch" W0#8N9"0;`9T9W;9<E05Us>E89$0;94WF5Uv5T<U15TW5Q1>NFF: S1I#:UV:a2W+:Xstr7:>E<WF15T5<qF15Us<~F15T0<F25Us>FV: Z2W,:>FV: 2W+:>FV:-2W,:>FV:O4W$:Ypid 23Z + 5%Z 23, K 4HD5U 5T54UD5U85Q05R0[O4 '4;\4>i4<F45Qs4F5Qs>F>E>D\ i4])^ z!525_,15`_24,K 4HD5U 5T74UD5Q15Rw>NF F15 9!5V B6W)W3WHWTXarg#G<E55UQ5T R $ &<E65U|5Ts $ &4'E5QvVd I8Wd(Wd2WdGWdSXarge"GYpg `lenh <E65U|5T~<E75Us5Tv $ &<'E75Q|<F875U|5T?<EX75U|5T<E|75U 5T9<'E75Qw<E75U|5T<E75U 5T<<'E75Qw<E85U5T}<E485U 5T<4'E5Q}aZ 8WZ&bFc8]?Rc8]gE>gE<E;5U >gElUD5QU5RTh/+>mA+=8=<L8Hz+8/+ >9:A+8N+=9:`+:l+8V: =;s:;g:4 G5T15Q 5Rs<G>=5U <"GV=5Us</Gn=5Us<E=5Us>HG4E5Us<UG=5Uv5Ts<bG>5U05Ts5Q35R15Xv5Y0<nG>5Uv<E=>5U <nGU>5Uv<Et>5U 4nG5Uv<{G>5T14E5U h*h@;*j!*n.*j;*oF*p*C?L*9:!*j.*:;*:F*H!+X <R*~?5U <G?5U|"5Tv5Q 5R1<E?5Uv4F5U|5Qv>E>/+4F5T h+o@;+:+=+@;+qj+4F5T >E>Gh,B;,;,;,r,@:,89pPA;"9=l9rA;9;9;~94G5Us88rB;8988s B;94G5Us=,'eB;,;,;,q'r,@j,<4FB5U 5T54G5U15Tw5Qv<GB5U15Tw5Qv>NFhc,PHD;u,;,;,j,j,pc,3DL,L,Lu,9:,:,8.9C;@9<GC5U 5Qs>dF<.D5Us5T~<.D5Us44F5U|5T34.5UsssNstswuv/tmp/lsapi.XXXXXXuv .XXXXXXst{snsts sssssstssdsss  ttL s3 sssswss snt ssswsOssTsLsSs[sss}tts^tstZ t Ds s9 t% ss t9sa ssqtv lsruby.csss=s% : ; 9 I$ >  $ > &I I7I I !I/  : ; 9  : ; 9 I8 : ; 9 <4: ; 9 I?<!4: ;9 I?<: ; 9 I> I: ;9 ( (((   : ;9  : ;9 I8  : ;9  : ;9 I : ;9  : ;9 I8  : ;9 I : ;9 I 8 '!I": ;9 I#> I: ; 9 $ : ; 9 % : ; 9 I& : ; 9 ' : ; 9 I8(!I/)'I* : ;9 +4: ; 9 I,4: ; 9 I- : ; 9 I8 .4: ; 9 I?/.?: ;9 @B04: ;9 IB14: ;9 IB2 U34: ;9 I415B64: ;9 I71RB UX YW 81RB UX YW 9 U:41B;1B<1=1RB X YW >1?!I/ @.: ;9 A.: ;9 B4: ;9 IC.: ;9 'I D: ;9 IE F.: ;9 'I@BG: ;9 IBH1RB X YW I: ;9 IJ.: ;9 'IK1RB X YW L1M4: ;9 IN.: ;9 I O.: ;9 I P: ;9 IBQ: ;9 IR.: ;9 'I@BS4: ;9 IT1RB UX YW UV.: ; 9 'I@BW: ; 9 IBX: ; 9 IBY4: ; 9 IBZ4: ; 9 IB[1RB UX Y W \.: ; 9 ' ]: ; 9 I^.: ; 9 @B_4: ; 9 I `4: ; 9 I a.: ; 9 '@BbB1c.: ; 9 'I d.?: ;9 '<e.?: ; 9 'I 4f.?: ;9 'I gh.1@Bi1j41k 1UlB1m41 n41o41 p1UX YW q r41s.?<n: ;9 t.?<n: ; 9 u.?<n: ; v6w.?<n`VpP!PP0V0VK0{00{00P0WPZjP@VPV}SKSRVPVZSPSSSS   PUU U  S  P P U  S  P U V U V U V  U / V/ 4 U4 L V T  \ T \  T * \* 4 T4 L \ Q S Q S Q S  Q + S+ 4 Q4 L S  P i \i l Pl \ P  \ N Sl s S P ]  S v} ? v} $0 $+(  v} $0 $+(V ^ P P U U U u@aUN $ &"^a $ &"O^PNQ^aQpUU ,U,1S12P ,T,2T@LUL_U@LTL_T@LQL^S^_QUU1T]TTWQVQQV0IoSS0' s $ &3$}"o s $ &3$}"pUVUpTSSVVPxUVSSUGVGHUH\VTFSFHTH\S!PTSHWSSHWS  U VU!UT`oUoUUUUUUU+EPP@S00@S00\SU\UTSTQQRRXX0rUrwSS S S0uTuVTTVTVTOV0Q\#Q#\:Q:O\0kRk]R]R7]7^RJ]JO^0XX#X#X:X:OX'@P@_:DPDO_`hUhmUPuUuSQUSPuTuVRTVPuQuQquQuQqVRTVqSQUSy\\bV VW a  a ~ V0I IYPYV V $ P$ ~ VBFPFiS a S> a E J pJ N UP i Ui S U S" 1 P1 s \ \ s S S P  P  U V SV \ U\ f Sf g Ug  SN [ P\ e Pg  S U S ,U,MSM\U\|U T 'V',T,MVMUTU|V Q MQM`Q`|Q ] } ],M] S S ,M  r,M r S S,MS S,6SM\U\wUM`Q`wQMUTUwV`UUUU`TTTT`QTSTaQaSQSQw0 UPS^}P^UU,K8U 8U/xx|3:@S3:@ESU\q0 ~ 0b W , ; > O s  0P 0@PWPW wSh,o;;}KERRZ}CJT]mt{xmt{x0>BUb /opt/alt/ruby26/include/ruby-2.6.0/ruby/usr/include/bits/usr/include/usr/lib/gcc/x86_64-redhat-linux/8/include/usr/include/bits/types/usr/include/sys/usr/include/netinetlsruby.clsapilib.hruby.hstdio2.hstdlib.hstring_fortified.hstddef.htypes.hstruct_FILE.hFILE.hstdio.hsys_errlist.htypes.hstdint-intn.hstdint-uintn.hunistd.hgetopt_core.hmath.hintern.hversion.hlsapidef.htime.hstruct_iovec.herrno.hsockaddr.hsocket.hin.hsignal.hstring.hmman.hutil.h  JK?K| #t>iK>KK{KY;./*X **}( // RX} t     0Yf q\:>X. t" u t/u* uZ ^  %gfu Z3 X }t }< tXX uKy 'XX" t  f. f *8u J<t  X    ot@5< t-< ti J [t ,JiX P  L( ff,X< o9= t; K1 tlQJ/f J LXHKy XX" t L 2  =t<UMtUX&<< ` 0z X .    =Yl  rX[wt Z " h   m grtX  h fY:g< KXfKY sbXtv  SY|X |X<   L/$ eX< z < zt yt5Y|X |.X z  Z rh Y   *xp*suqwZ7v -uY "u{ wt JvI ;tZvpJuI==[X=XvXuv0X>f~z t gz t p((* uv #G< Y(%[$ rb_mWaitWritable_sys_errlistm_pScriptFileRUBY_Qnilrb_eNoMemError_unused2_filenorb_cMethodrb_obj_wb_unprotectrb_eSyntaxErrorm_cntUnknownHeadersH_AUTHORIZATIONsockaddr_isoblockSizem_pIovecEndstrcpym_pRespBufPosRUBY_FL_EXIVAR__uint8_tdmarkRUBY_DATA_FUNCm_pktHeaderrb_eIOErrorm_bytesm_pHeaderrb_data_object_get_shortbufsockaddr_inrb_cFilerb_eSignalunlinklsapi_dataRUBY_T_ARRAYrb_eKeyErroradd_env_rails__environlsapi_addstrsa_datauint16_tm_totalLensin_zeroRUBY_FL_UNTRUSTEDrb_eZeroDivErrorin_port_t_flagslsapi_getscallocm_respPktHeader__off_tcreateTempFiledfreeRUBY_T_IMEMOrb_global_variable_lockROBJECT_EMBED_LEN_MAXRUBY_T_UNDEFrb_cStringrb_eEOFErroratoim_pHttpHeaderLSAPI_GetReqBodyRemain_rm_pScriptNamerb_mKernelm_pEnvListrb_output_fsint32_t__fmtsa_familym_specialEnvListSizerb_cModulesockaddr_ns__u6_addr8RUBY_T_FALSEruby_robject_flagsrb_cIntegerRUBY_T_FILE_IO_write_endm_iLensockaddrrb_cTrueClasss_addrRUBY_FL_USER0RUBY_FL_USER1RUBY_FL_USER2RUBY_FL_USER3RUBY_FL_USER4RUBY_FL_USER5RUBY_FL_USER6RUBY_FL_USER7RUBY_FL_USER8RUBY_FL_USER9nameLenLSAPI_Postfork_Childfreerb_fsm_requestMethodOffRUBY_T_COMPLEXdata_struct_objrb_eEncCompatErrorruby_special_constsvalLenRSTRING_EMBED_LEN_SHIFT__stack_chk_failruby_rarray_flagsruby_descriptionsin_familyRStringm_fdListenMAX_BODYBUF_LENGTHlsapi_bodym_statusm_reqBodyLenrb_eNameErroroptargneedReadrb_eRegexpErrorrb_cBasicObjectRUBY_T_STRUCTrb_cRationalrb_cFloatrb_cClassrb_cStatsys_errlistin_addr_tbasicRUBY_QtrueLSAPI_ReqBodyGetChar_rpKey__uint16_tsin_portRUBY_T_STRINGrb_cContrb_cFalseClassm_flagRARRAY_EMBED_LEN_SHIFTreadMaxBodyBufLengthm_pQueryString_chainRUBY_T_MODULErb_eArgErrorrb_eInterruptrecurrb_funcallvRUBY_FL_SINGLETONsockaddr_ununsigned charcapanReadm_cntSpecialEnv_IO_lock_tRUBY_T_ZOMBIEfloatLSAPI_key_value_pairLSAPI_ForeachHeader_rrb_stderrlsapi_eachm_cntHeadersrb_str_catbodyBufRARRAY_EMBED_LEN_MAXRUBY_T_FIXNUMrb_eSecurityErrorisEofBodyBuflsapi_processlsapi_flushRARRAY_EMBED_FLAGROBJECT_EMBEDoff_tchild_statusRUBY_SYMBOL_FLAGrb_mComparableH_X_FORWARDED_FOR__fprintf_chkm_queryStringOffrb_define_global_functionRUBY_FLONUM_FLAGrb_stdoutruby_rstring_flagsH_CONTENT_LENGTHruby_engine_IO_write_ptrrb_output_rsROBJECT_ENUM_ENDlsapi_packet_headerLSAPI_ReadReqBody_rrb_eFatallsapi_http_header_indexrb_funcall_argcsTempFilerb_funcall_argsclosesharedlsapi_printfRUBY_T_OBJECTFILEH_COOKIEs_fn_add_envmunmapRSTRING_EMBED_LEN_MAXbodyCurrentLenLSAPI_Accept_Before_Forkrb_cNumerics_req_stderrrb_cHashsize_trb_array_const_ptrH_CONNECTIONrb_rsuint8_tH_CONTENT_TYPERArraylsapi_markm_headerLenRUBY_ELTS_SHAREDperrorlsapi_envruby_release_daterb_cDirsetup_cgi_env_IO_save_baseioveclsapi_eofrb_array_const_ptr_transientenvironlsapi_child_statusreadTempFileTemplatesockaddr_x25rb_eLoadErrorsin6_flowinfom_pIovecToWriteorig_stderrm_respHeaderLen_wide_dataH_IF_MATCHRUBY_FL_PROMOTED0RUBY_FL_PROMOTED1__in6_uGNU C17 8.5.0 20210514 (Red Hat 8.5.0-18) -mtune=generic -m64 -march=x86-64 -g -O2 -fPIC -fexceptions -fstack-protector-strong -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection=full -fplugin=gcc-annobinH_ACC_CHARSETruby_versionorig_stdout__streamsigngamruby_copyrightm_reqBufSizerb_eExceptionrb_yieldadd_env_no_fixRUBY_T_FLOATRUBY_T_CLASSrb_cDataftruncateruby_fl_typelsapi_requestrb_cComplexfprintfrb_check_typeRUBY_T_HASHsyncRUBY_T_NODEchdir__ssize_t__srcrb_mErrnolsapi_closeH_IF_RANGEnameOffruby_api_versionstrerrorsa_family_tm_packetLenreadMoreRUBY_FL_WB_PROTECTEDin6_addrisBodyWriteToFilelinesin6_addrrb_mWaitReadablelsapi_setsyncm_respPktHeaderEndRUBY_FL_TAINTLSAPI_Postfork_Parentrb_check_safe_objfn_add_envlsapi_printrb_eSystemCallErrorrb_intern2stderrm_pHeaderIndexprogram_invocation_short_namerb_safe_levelrb_cUnboundMethodrb_f_sprintf_IO_save_endrb_const_get__nptrLSAPI_InitLSAPI_Requestrb_eScriptErrorrb_tainted_str_newfn_writelsapi_syncm_bufProcessedstdoutreadBodyBufoptoptlsapi_reopenrb_mGCrb_eIndexErrorm_httpHeaderLencurPosH_IF_NO_MATCHlsapi_s_acceptpreforkRUBY_T_DATAbuffssizetypekeyLenRUBY_FL_DUPPED__builtin_strchrLSAPI_Flush_rshort unsigned intsigned charrb_array_lentz_dsttimefilenamelsruby.clsapi_header_offset__off64_tsockaddr_eon_IO_read_base_offsetm_pIovecrb_string_value_ptrrb_eFloatDomainError_IO_buf_endm_respInfoopterrrb_define_singleton_methodlsapi_puts_ary_modeblkSize_IO_write_basevalueLenInit_lsapirb_eStandardErrorrb_cSymbolrb_argv0H_CACHE_CTRLH_COOKIE2__destrb_cMatchrb_cEncodinglsapi_isattyH_USERAGENTRARRAY_EMBED_LEN_MASKLSAPI_ForeachEnv_rlong intRUBY_T_NONErb_mProcessrb_mFileTestremain_IO_markerrb_cEnumeratorm_pRespBufEnd__builtin___memcpy_chkrb_io_putslsapi_s_postfork_childrb_define_global_constrb_obj_as_stringm_bufReadin_addruint32_tsockaddr_in6__pid_t_IO_codecvtrb_funcall_nargsH_RANGERDatastrtolg_reqlong doublerb_cRangeiov_lenlsapi_resp_inforb_cObjectlong unsigned intlsapi_req_headerrb_gc_markinitBodyBufruby_strdupm_headerOffrb_eNotImpError__errno_location/builddir/build/BUILD/opt/alt/ruby26/lib64/ruby/gems/2.6.0/gems/ruby-lsapi-5.5/ext/lsapilsapi_s_postfork_parentcharsockaddr_inarpm_pSpecialEnvListsin6_scope_idrb_cIORSTRING_ENUM_ENDstdinsin_addrRUBY_T_BIGNUM_IO_buf_baseRSTRING_NOEMBEDRUBY_T_RATIONALRUBY_FL_PROMOTEDs_bodyrb_eTypeErrorRBasicrb_eNoMethodError_IO_read_endRUBY_T_ICLASSrb_num2intcLSAPIRUBY_SPECIAL_SHIFT_IO_FILEH_IF_UNMOD_SINCEm_fdRUBY_T_SYMBOLH_HOSTrb_num2char_inline_IO_wide_datastrlen__u6_addr16s_pidselfrb_eSystemExitisAllBodyReadm_respHeaderrb_cThreadm_envListSizem_pAppDataruby_platformsockaddr_ax25RSTRING_FSTRrb_eThreadError__pad5rb_str_new_static__u6_addr32rb_cNilClassm_type_markersrb_stdinrb_eStopIterationm_scriptFileOffRUBY_FL_USHIFTklassrb_define_classH_VIA_codecvtm_pRespHeaderBufEndH_PRAGMARUBY_FL_FINALIZErb_cRandomdoublemkstemplsapi_putcargcssize_tstrcatlsapi_writelsapi_putsorig_stdinRUBY_FIXNUM_FLAGargvRARRAY_ENUM_ENDrb_eRuntimeErrorm_pRespHeaderBuf__int32_trb_cProc__uint32_tRUBY_IMMEDIATE_MASKrb_hash_asetdataH_REFERERrb_cStructLSAPI_Prefork_Accept_rheap_sys_siglistRARRAY_TRANSIENT_FLAGm_pUnknownHeaderrb_typem_reqStateRUBY_T_NILrb_cTimerb_eSysStackErrorm_pRespBufrb_num2int_inlineprogram_invocation_namerb_cArrayrb_eEncodingErrorrb_ruby_verbose_ptrrb_cBindingrb_intern_id_cacheH_TRANSFER_ENCODINGH_IF_MODIFIED_SINCErb_ary_detransientRUBY_FL_USER10RUBY_FL_USER11RUBY_FL_USER12RUBY_FL_USER13RUBY_FL_USER14RUBY_FL_USER15RUBY_FL_USER16RUBY_FL_USER17RUBY_FL_USER18RUBY_FL_USER19_freeres_bufRUBY_T_MATCHlong long unsigned intpid_t_cur_columnlsapi_rewinds_reqrb_eRangeErrorm_pRespHeaderBufPoss_stderr_datarb_eval_string_wrapgetpidm_cntEnvRUBY_T_MASKrb_lastline_get_IO_backup_baseH_KEEP_ALIVE__memcpy_chk_IO_read_ptrrb_eMathDomainErrorrb_fix2intLSAPI_GetReqBodyLen_rrb_gc_writebarrier_unprotectrb_exec_recursivegetenv_freeres_listrb_eLocalJumpErrorrb_raise_sys_nerrlsapi_readtimezonepReqlsapi_getcrb_hash_newclear_envrb_cRegexplsapi_binmode_old_offsetstrchrm_pReqBufrb_cNameErrorMesgvalueOffoptindH_ACC_LANGlong long intin6addr_loopback_flags2VALUErb_mMathRUBY_T_TRUEmemmemsin6_familysockaddr_atruby_value_typem_scriptNameOffH_ACCEPTm_lLastActivelsapi_resp_headersys_nerrin6addr_anym_pRequestMethods_req_dataiov_basem_lReqBegincreateBodyBufm_versionB0m_versionB1rb_str_buf_newrb_define_methodRUBY_FLONUM_MASKruby_patchlevelRUBY_T_REGEXPm_pIovecCurLSAPI_Init_Env_Parametersorig_envm_reqBodyReadRUBY_Qundeflsapi_s_accept_new_connrb_eFrozenErrorsockaddr_dlRSTRING_EMBED_LEN_MASKRUBY_FL_FREEZEunsigned intbodyLensockaddr_ipxrb_default_rsshort intrb_string_value_vtable_offsetpValueenv_copymmaporig_verboserb_data_object_zallocrb_mEnumerableRUBY_Qfalseflagstz_minuteswestsys_siglistH_ACC_ENCODINGsin6_portlsapi_eval_string_wrapGCC: (GNU) 8.5.0 20210514 (Red Hat 8.5.0-18)GNUzRx  0D+Xl(BFGA kFBzD O E  HUgHQ G $ayd(<EDL ] CAJ hELEY HW HW-Hd(EAD  DAJ aED y AE H8FBB E(D0C8GPm 8F0A(B BBBG ,ZAD J ABL 4oAD  AAK pP \FBD C(G0 (D ABBE j (D ABBE | (G DBBA HLhFBB B(A0A8G@ 8D0A(B BBBD CKw oEA J F A 8FBA D(D@ (A ABBE ((EDG0 AAI HTPFBB A(A0 (F BBBH {(F BBB@OFBB A(D0D@  0A(A BBBJ <KFBA A(D0 (A ABBE   - )  ?.Yt/01 5 C _"y @"[0+[h` h)wCpPwmB pZz# < xEZ_mw` mpg0aIaUapp2 2_@_Bg`   2-Jh X  `!a!;OV0dOP  ~  @)~ CL [ fL  P h   C    o  ; |W  f |    \  \  `P 8 Q O] w K        h "$%'./0123-4   @ )  3   L S  b Z x ! ' - 3 9 ? E K Q  W (] c $i *o fu n{ s y                    1 G V    ) 9 N b ()*+,s              / < R g          ,3G^jry 0MXk}K#.;Nhx.annobin_lsruby.c.annobin_lsruby.c_end.annobin_lsruby.c.hot.annobin_lsruby.c_end.hot.annobin_lsruby.c.unlikely.annobin_lsruby.c_end.unlikely.annobin_lsruby.c.startup.annobin_lsruby.c_end.startup.annobin_lsruby.c.exit.annobin_lsruby.c_end.exit.annobin_lsapi_process.start.annobin_lsapi_process.endlsapi_process.annobin_lsapi_rewind.start.annobin_lsapi_rewind.endlsapi_rewinds_body.annobin_lsapi_eof.start.annobin_lsapi_eof.endlsapi_eof.annobin_lsapi_binmode.start.annobin_lsapi_binmode.endlsapi_binmode.annobin_lsapi_isatty.start.annobin_lsapi_isatty.endlsapi_isatty.annobin_lsapi_setsync.start.annobin_lsapi_setsync.endlsapi_setsync.annobin_add_env_no_fix.start.annobin_add_env_no_fix.endadd_env_no_fixlsapi_env.annobin_clear_env.start.annobin_clear_env.endclear_envrb_intern_id_cache.13602env_copy.annobin_lsapi_mark.start.annobin_lsapi_mark.endlsapi_mark.annobin_lsapi_flush.start.annobin_lsapi_flush.endlsapi_flush.annobin_lsapi_close.start.annobin_lsapi_close.endlsapi_closeMAX_BODYBUF_LENGTH.annobin_readBodyBuf.start.annobin_readBodyBuf.endreadBodyBuf.annobin_lsapi_write.start.annobin_lsapi_write.endlsapi_write.annobin_lsapi_addstr.start.annobin_lsapi_addstr.endlsapi_addstr.annobin_lsapi_printf.start.annobin_lsapi_printf.endlsapi_printf.annobin_lsapi_s_postfork_parent.start.annobin_lsapi_s_postfork_parent.endlsapi_s_postfork_parents_req.annobin_lsapi_s_postfork_child.start.annobin_lsapi_s_postfork_child.endlsapi_s_postfork_child.annobin_lsapi_s_accept_new_conn.start.annobin_lsapi_s_accept_new_conn.endlsapi_s_accept_new_conn.annobin_lsapi_s_accept.start.annobin_lsapi_s_accept.endlsapi_s_accepts_pidrb_intern_id_cache.13615s_req_data.annobin_lsapi_eval_string_wrap.start.annobin_lsapi_eval_string_wrap.endlsapi_eval_string_wrap.annobin_add_env_rails.start.annobin_add_env_rails.endadd_env_rails.annobin_lsapi_reopen.start.annobin_lsapi_reopen.endlsapi_reopens_req_stderrorig_stderrrb_intern_id_cache.13779.annobin_createBodyBuf.start.annobin_createBodyBuf.endcreateBodyBufsTempFile.annobin_lsapi_read.start.annobin_lsapi_read.endlsapi_read.annobin_lsapi_gets.start.annobin_lsapi_gets.endlsapi_gets.annobin_lsapi_each.start.annobin_lsapi_each.endlsapi_each.annobin_lsapi_getc.start.annobin_lsapi_getc.endlsapi_getc.annobin_lsapi_puts_ary.start.annobin_lsapi_puts_ary.endlsapi_puts_ary.annobin_lsapi_sync.start.annobin_lsapi_sync.endlsapi_sync.annobin_lsapi_putc.start.annobin_lsapi_putc.endlsapi_putc.annobin_lsapi_puts.start.annobin_lsapi_puts.endlsapi_puts.annobin_lsapi_print.start.annobin_lsapi_print.endlsapi_print.annobin_Init_lsapi.start.annobin_Init_lsapi.endrb_intern_id_cache.13795rb_intern_id_cache.13800orig_envcLSAPI.LC0.LC1.LC7.LC5.LC4.LC6.LC3.LC2.LC8.LC9.LC13.LC11.LC10.LC12.LC14.LC15.LC16.LC17.LC18.LC19.LC56.LC21.LC22.LC26.LC27.LC28.LC29.LC30.LC34.LC35.LC36.LC37.LC38.LC39.LC40.LC41.LC42.LC43.LC44.LC45.LC46.LC47.LC48.LC49.LC50.LC51.LC52.LC53.LC54.LC24.LC20.LC31.LC32.LC33.LC25.LC23.LC55.text.group.text.hot.group.text.unlikely.group.text.startup.group.text.exit.group_GLOBAL_OFFSET_TABLE_g_reqrb_tainted_str_newrb_hash_asetrb_funcallvrb_intern2__stack_chk_failrb_gc_markLSAPI_Flush_rmunmapfreeLSAPI_ReadReqBody_rrb_check_typerb_obj_as_stringrb_f_sprintfLSAPI_Postfork_ParentLSAPI_Postfork_ChildLSAPI_Accept_Before_ForkLSAPI_Prefork_Accept_rgetpids_fn_add_envLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rrb_safe_levelrb_string_value_ptrrb_eval_string_wraprb_string_valuerb_check_safe_objstrchrrb_ruby_verbose_ptrrb_define_global_construby_strdupmkstempunlinkftruncatemmapcallocperror__errno_locationstrerror__fprintf_chkrb_str_buf_newrb_str_catrb_num2intrb_fix2intrb_eSecurityErrorrb_raisememmemrb_yieldLSAPI_ReqBodyGetChar_rrb_gc_writebarrier_unprotectrb_io_putsrb_ary_detransientrb_str_new_staticrb_exec_recursiverb_default_rsrb_output_fsrb_output_rsrb_lastline_getInit_lsapiLSAPI_InitgetenvstrtolstrlenselectLSAPI_Init_Env_Parameterschdirrb_stderrrb_cObjectrb_const_getrb_global_variablerb_define_global_functionrb_define_classrb_define_singleton_methodrb_define_methodrb_data_object_zallocLSAPI_Write_rrb_stdoutrb_stdinLSAPI_Write_Stderr_rrb_hash_new__memcpy_chkH7*ltl@EOV{**D <8DH*?HF<KUHIk*pw***<8DH'-T6<TOX\d*snl LXalltll1Wrz  C*D& 3<8CV^eDo <  < @     !  ( 7 A *K S d i  p    D L H v L <  L  L D  L <  L7 *> H f  < D H  L  W La <i o L *   D H  D L E *J j *q {   DX]qx QX ;*v*:Q* *!"$"8-D3H<%S&gy %'L<%&*()T %*.*?*+FP`*,i-pw|tt.t/0d1,d<A2Hd[`2gdz2d2d2d2d2d2d.32:dJO2Vdin2ud2d2d2d2d2d2d-229dIN2Udej2qd2d2*d3**4\*5 *6.d,33*7:ET.Yam8tll<9<d+017dGL1Sdch1| %% 7B i  $, P X" ""["[[hD[Lhphxwhwww 08dlZZZm$Z,mPmXmaDLapaxa2 2028_d2l___$,PX  !D L !p !x O ! O O  O 0 8 ~ d l ~ ~ L ~ L L  $ L ,  P  X           |D  L |p |x  |   \  \0 \8 d \l       K$,K       $ ) . U < C L S Z _ m #r B~ z   B A      ' 4 XA N [ h bu    x  A  N    = L  f+ 8 E R _ l y E  G   U B  E' 3 :? [ g Ds           <     ." `) .  ; W j p v ,|   2 !  U  L   i   \  V B    T      6  !& l, -2 8 > _D J P RV \] p ]v |        u       + 9 G U   * 9 H& W/ f8 uA J S ] d k s    y  4 &   o     4 ,& s  B    "    H ,# v       Y , 9 F fS ` m z B         d v  # g0 = mJ bW d q L ~ -  ] V J  - 3     ' 4 A N +[ h Au  | 6    k _   I S  + 8 XE R _ l y   g 6   ( J     " u/ y < I JV c p }  |   6 "   2 &+  7 Q lW ] c i o o u {   L ;    ?   o     u    '  7  $ 1 :> |K HY 'f s X | e \    S 7 i   [1 -> K cX e s   s    Y   f = L * 8 F JS (` um z  )  \   i   H n  P # 0 /= J W d 5q A~        + |    t 2( 6 D S D ^  k x     y P$ <0 = +J x @   K V 7 M K  , 4: H V d     U  l   ~   a j !! r. A M ~   '   v Sx p U }E x } h  ` ?  * vX h  + 8 hF hR _@y @    a   A ;    ` $ ->1N W c g l y  F B  1    ~`- `6 B F K0a`v ; P P    R  @ <W@1&kDb;}    v    7 3 @/8U Y b f l1 0  1 '<1F"Sm`ux1 m(1%1$/!D1*Q`Eu1fd1n1sp 1y % : 1G @W l 1y `  1    1 p 7!1 ! !S1!1>!P M!rb!1o! !!1!!!1! !!1"0"'"14"0C"X"1e"t""1"`"6"1"p"R"1"p#n#1)#8#M#1Z#i#~#1S#P###X##]#e#q$ $"$1,$A$1LK$X$4m$11z$$P$1G$$l$1V$`$%1 %%1=% B% CL% W f% % 5% % C% |% a% %% %& |& & '&0&E&R&_&m& y&& |& & & |& t& |& &`' |!'  -'0D' |W'4`'4|' ' ' |' ?' 9' ' ' ' ' ' ( ( @( +( 9( K( |Y( Ne( |( ( ( ( C( ( ( |( ( ( ( ( 1( '( ( ( ( 1) " )  ) ) +) \ /) X 4) A) O) \) i) )V ) ) )L )m* * |/* S* "_*v* * * * * * * * 1* [ * Y * T* * ~ * ** +O+ "+ 0+ O+ J{+ {+ g+ |+ +p+ |+ + ++ , *, ., ?, H C, D H,-d, v, , C, , , - -@+- 7- ;- @- CL- P- a-  e- j-M-X- -- - S - M - C- - - # -  . . . (.o1. B. F. L.>i.I.f..... .p/ |/ S/ M(/ ,/ 1/ =/ A/ R/ *V/ (_/xh/ y/ Q}/ M/// / / // // |0  0 0 00 (30 ?0 C0 L0U0 f0 j0 s0|0 00 0 00U0 0 `0 A0 =00"1\!1 -1D1 |T1 _1v1 |1 {1 w1 1 11111 22 "2`92 |D2 H2 M2t[2 5f2}2 |2 2 22 22 |2 W2 S22 }23 |3 3 $3 (3 -3 063 A3 E3 J3 V3 a3 Ge3 Cj3 ps3 33313S3\3 3 3 3a3w4(454B4+P4 ]4 j4 ~q44 4 4 4 4 @4 44I4145Z75 M B5Y5 =d5 h5 m5 x5 |5 5 L5 L5 H5 5 5 5 5 5566 '60>6 =I6 M6 R6 ]6 a6 xf6 Lq6 Tu6 Hz6 6 6 6 6 6 W6 O6677$97PY7en71)}7x77713778&8158J8 Q8`h8 s8 w8 |8m8 8 b8 8 b8 \ 8 8  9 /9 #O9 Bm9 a9 9 9 99 g9 9 V: : : V*: 7: I: W: h: t: %::p:P: : : v: l; ; ;q; ); )-; %6; j:; bC; G; L; U; 4Y; 0b; k;|;1S;v;~;;1L;;;<<B<K<d<0m< Pz< P< r< j<0< < < < < f< `<> < < < < < <O =1Z =<5=@?=GW=Zo=b=% =, =W =s=>> 4>1b>> V>m k>1xu>t >>>1>P > > ? ? ?  ? .? 2? ;? ?? H? Q? f? ? ?1? ?m ?j ? @ @m @ ;@ N?@ BH@ L@ U@g ^@g {@ @ @g @ @m@ @N @ @ A@ 5@ A  A b A Z A $A -A 6A pGA .!KA *!UA ^A {A h!A d!A !A !A !A !A A A A "A "A A A A K"B G"BH!BP*BPGB "KB "TB "XB "aB "eB "jBPBaB1BuB B|C`C =#!C 5#*C #.C #7C $;C $NC jC sC $wC $C $C $CC C U%C Q%CC C CDNDz4DID /MD /VD ZD cD ngD npD tD |D D D D D D D cD cD D D \D \D LD LD D E E E lE lE E (E ,E 5E 9E BE FE OE SE [E _E hE lE uE ryE rE LE LE E E E E E E E E D E D E E E E E nE nE E F F F ;F ;F K F K (F ,F 5F 9F BF hFF hOF SF XF \F eF ciF crF wvF wF 8F 8F -F -F F F F F kF kF  F  F {F {F F F F F F F 8G 8 G G G OG O#G 'G 0G v4G v=G wAG wIG 3MG 3VG  ZG  cG \gG \oG sG |G +G +G -G -G &G &G G G G G *G *G G  D  DJ@f@ D@ L @- L> @1Z{! G! G q 4H0\`pp`p (@pl @`<0P PP    ,X`.symtab.strtab.shstrtab.rela.text.data.bss.rela.gnu.build.attributes.text.hot.rela.gnu.build.attributes.hot.text.unlikely.rela.gnu.build.attributes.unlikely.text.startup.rela.gnu.build.attributes.startup.text.exit.rela.gnu.build.attributes.exit.rodata.str1.1.rodata.str1.8.rela.data.rel.local.rodata.cst16.rela.debug_info.debug_abbrev.rela.debug_loc.rela.debug_aranges.debug_ranges.rela.debug_line.debug_str.comment.text.hot.zzz.text.unlikely.zzz.text.startup.zzz.text.exit.zzz.note.GNU-stack.note.gnu.property.rela.eh_frame.group/@6/T6/l6/6/6 K@#6&,@ 6@41@H9 6 Lt([t(V@E06 uH*H*@F06,,@8F06--@hF062/21M'2"@F672J 2GE@F6Vz#i&%d@H86 y0t@06"qY@6%00.uL   %  @64(p7  6PK% ]lΉ!gems/ruby-lsapi-5.5/lsapi.gemspecnu[Gem::Specification.new do |s| s.name = %q{ruby-lsapi} s.version = "5.5" s.date = %q{2023-06-08} s.description = "This is a ruby extension for fast communication with LiteSpeed Web Server." s.summary = %q{A ruby extension for fast communication with LiteSpeed Web Server.} s.has_rdoc = false s.authors = ["LiteSpeed Technologies Inc."] s.email = "info@litespeedtech.com" s.homepage = "http://www.litespeedtech.com/" s.rubyforge_project = "ruby-lsapi" s.files = ["lsapi.gemspec", "README", "examples", "examples/testlsapi.rb", "examples/lsapi_with_cgi.rb", "ext", "ext/lsapi", "ext/lsapi/extconf.rb", "ext/lsapi/lsapidef.h", "ext/lsapi/lsapilib.c", "ext/lsapi/lsapilib.h", "ext/lsapi/lsruby.c", "rails", "rails/dispatch.lsapi", "scripts", "scripts/lsruby_runner.rb", "setup.rb"] s.extra_rdoc_files = ["README"] s.extensions << "ext/lsapi/extconf.rb" s.require_paths << "lib" end PK% ]^wͱgems/ruby-lsapi-5.5/READMEnu[ lsapi - LSAPI extension for Ruby ================================ INSTALL ------- $ ruby setup.rb config $ ruby setup.rb setup # ruby setup.rb install USAGE ----- General CGI scripts ^^^^^^^^^^^^^^^^^^^ The most efficient way to use LSAPI interface is to modify your CGI scripts. You need to add the following code to your CGI scripts: require 'lsapi' while LSAPI.accept != nil ... end There is no need to change the way that how CGI environment variables are being accessed in your scripts. You can find some examples under examples/ folder. Ruby Script Runner ^^^^^^^^^^^^^^^^^^ If you don't want to change your existing Ruby CGI code, you can use our Ruby script runner under scripts/ folder. You need to configure lsruby_runner.rb as a LSAPI application, then add a script handler for "rb" suffix. Rails dispatcher ^^^^^^^^^^^^^^^^ With Ruby LSAPI, we proudly provide a optimum platform for Rails application deployment. Ruby LSAPI has the following advantages over other solutions. * Easy configuration, deploy a Rails application only take a few clicks with our Rails easy configuration * Fast startup, the expensive Rails framework initialization only takes place once when multiple processes need to be started * Resource efficience, ruby processes can be started on demand, idle process will be stop. To use LSAPI with Ruby on Rails, please check out our toturial http://www.litespeedtech.com/support/wiki/doku.php There are a few environment variables that can be tweaked to tune ruby LSAPI process. * LSAPI_CHILDREN (default: 0) LSAPI_CHILDREN controls the maximum number of children processes can be started by the first ruby process started by web server. When set to <=1, the first ruby process will handle request by itself, without starting any child process. When LSAPI_CHILDREN is >1, the LSAPI application is stared in "Self Managed Mode", which will start children processes based on demand. With Rails easy configuration, LSAPI_CHILDREN is set to the value of "Max Connections" by web server, no need to set it explicitly. Usually, there is no need to set value of LSAPI_CHILDREN over 100 in most server environment. * LSAPI_AVOID_FORK (default: 0) LSAPI_AVOID_FORK specifies the policy of the internal process manager in "Self Managed Mode". When set to 0, the internal process manager will stop and start children process on demand to save system resource. This is preferred in a shared hosting environment. When set to 1, the internal process manager will try to avoid freqently stopping and starting children process. This might be preferred in a dedicate hosting environment. * LSAPI_EXTRA_CHILDREN (default: 1/3 of LSAPI_CHILDREN or 0) LSAPI_EXTRA_CHILDREN controls the maximum number of extra children processes can be started when some or all existing children processes are in malfunctioning state. Total number of children processes will be reduced to LSAPI_CHILDREN level as soon as service is back to normal. When LSAPI_AVOID_FORK is set to 0, the default value is 1/3 of LSAPI_CHIDLREN, When LSAPI_AVOID_FORK is set to 1, the default value is 0. * LSAPI_MAX_REQS (default value: 10000) LSAPI_MAX_REQS specifies the maximum number of requests each child process will handle before it exits automatically. This parameter can help reducing memory usage when there are memory leaks in the application. * LSAPI_MAX_IDLE (default value: 300 seconds) In Self Managed Mode, LSAPI_MAX_IDLE controls how long a idle child process will wait for a new request before exit. This option help releasing system resources taken by idle processes. * LSAPI_MAX_IDLE_CHILDREN (default value: 1/3 of LSAPI_CHILDREN or LSAPI_CHILDREN) In Self Managed Mode, LSAI_MAX_IDLE_CHILDREN controls how many idle children processes are allowed. Excessive idle children processes will be killed by the parent process. When LSAPI_AVOID_FORK is set to 0, the default value is 1/3 of LSAPI_CHIDLREN, When LSAPI_AVOID_FORK is set to 1, the default value is LSAPI_CHILDREN. * LSAPI_MAX_PROCESS_TIME (default value: 300 seconds) In Self Managed Mode, LSAPI_MAX_PROCESS_TIME controls the maximum processing time allowed when processing a request. If a child process can not finish processing of a request in the given time period, it will be killed by the parent process. This option can help getting rid of dead or runaway child process. * LSAPI_PGRP_MAX_IDLE (default value: FOREVER ) In Self Managed Mode, LSAPI_PGRP_MAX_IDLE controls how long the parent process will wait before exiting when there is no child process. This option help releasing system resources taken by an idle parent process. * LSAPI_PPID_NO_CHECK By default a LSAPI application check the existence of its parent process and exits automatically if the parent process died. This is to reduce orphan process when web server is restarted. However, it is desireable to disable this feature, such as when a LSAPI process was started manually from command line. LSAPI_PPID_NO_CHECK should be set when you want to disable the checking of existence of parent process. License ------- LSAPI library code is under BSD license LSAPI ruby extension code is under Ruby license * (()) (Japanese) * (()) (English) Copyright --------- Copyright (C) 2006 Lite Speed Technologies Inc. PK% ]GF(gems/ruby-lsapi-5.5/rails/dispatch.lsapinuȯ#!/opt/alt/ruby26/bin/ruby if GC.respond_to?(:copy_on_write_friendly=) GC.copy_on_write_friendly = true end require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) # If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like: # "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired require "dispatcher" require "lsapi" while LSAPI.accept != nil Dispatcher.dispatch end PK% ]H@MM,gems/ruby-lsapi-5.5/scripts/lsruby_runner.rbnuȯ#!/opt/alt/ruby26/bin/ruby require 'lsapi' class CodeCache def [](filename) mtime = File.mtime( filename ) entry = @cache[filename]; if entry != nil return entry end code = compile(filename) #entry = CodeEntry.new( filename, mtime, code ) @cache[filename] = code return code end private def initialize @cache = {} end def compile(filename) open(filename) do |f| s = f.read s.untaint binding = eval_string_wrap("binding") return eval(format("Proc.new {\n%s\n}", s), binding, filename, 0) end end end $count = 0; $cache = CodeCache.new while true $req = LSAPI.accept break if $req == nil filename = ENV['SCRIPT_FILENAME'] filename.untaint filename =~ %r{^(\/.*?)\/*([^\/]+)$} path = $1 Dir.chdir( path ) #load( filename, true ) code = $cache[filename] code.call end class CodeEntry public :path, :name, :mtime, :opcode def initizlize( filename, mtime, opcode ) filename =~ %r{^(\/.*?)\/*([^\/]+)$} @path = $1 @name = $2 @mtime = mtime @opcode = opcode end end PK% ]##BBgems/ruby-lsapi-5.5/setup.rbnu[# # setup.rb # # Copyright (c) 2000-2005 Minero Aoki # # This program is free software. # You can distribute/modify this program under the terms of # the GNU LGPL, Lesser General Public License version 2.1. # unless Enumerable.method_defined?(:map) # Ruby 1.4.6 module Enumerable alias map collect end end unless File.respond_to?(:read) # Ruby 1.6 def File.read(fname) open(fname) {|f| return f.read } end end unless Errno.const_defined?(:ENOTEMPTY) # Windows? module Errno class ENOTEMPTY # We do not raise this exception, implementation is not needed. end end end def File.binread(fname) open(fname, 'rb') {|f| return f.read } end # for corrupted Windows' stat(2) def File.dir?(path) File.directory?((path[-1,1] == '/') ? path : path + '/') end class ConfigTable include Enumerable def initialize(rbconfig) @rbconfig = rbconfig @items = [] @table = {} # options @install_prefix = nil @config_opt = nil @verbose = true @no_harm = false end attr_accessor :install_prefix attr_accessor :config_opt attr_writer :verbose def verbose? @verbose end attr_writer :no_harm def no_harm? @no_harm end def [](key) lookup(key).resolve(self) end def []=(key, val) lookup(key).set val end def names @items.map {|i| i.name } end def each(&block) @items.each(&block) end def key?(name) @table.key?(name) end def lookup(name) @table[name] or setup_rb_error "no such config item: #{name}" end def add(item) @items.push item @table[item.name] = item end def remove(name) item = lookup(name) @items.delete_if {|i| i.name == name } @table.delete_if {|name, i| i.name == name } item end def load_script(path, inst = nil) if File.file?(path) MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path end end def savefile '.config' end def load_savefile begin File.foreach(savefile()) do |line| k, v = *line.split(/=/, 2) self[k] = v.strip end rescue Errno::ENOENT setup_rb_error $!.message + "\n#{File.basename($0)} config first" end end def save @items.each {|i| i.value } File.open(savefile(), 'w') {|f| @items.each do |i| f.printf "%s=%s\n", i.name, i.value if i.value? and i.value end } end def load_standard_entries standard_entries(@rbconfig).each do |ent| add ent end end def standard_entries(rbconfig) c = rbconfig rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT']) major = c['MAJOR'].to_i minor = c['MINOR'].to_i teeny = c['TEENY'].to_i version = "#{major}.#{minor}" # ruby ver. >= 1.4.4? newpath_p = ((major >= 2) or ((major == 1) and ((minor >= 5) or ((minor == 4) and (teeny >= 4))))) if c['rubylibdir'] # V > 1.6.3 libruby = "#{c['prefix']}/lib/ruby" librubyver = c['rubylibdir'] librubyverarch = c['archdir'] siteruby = c['sitedir'] siterubyver = c['sitelibdir'] siterubyverarch = c['sitearchdir'] elsif newpath_p # 1.4.4 <= V <= 1.6.3 libruby = "#{c['prefix']}/lib/ruby" librubyver = "#{c['prefix']}/lib/ruby/#{version}" librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" siteruby = c['sitedir'] siterubyver = "$siteruby/#{version}" siterubyverarch = "$siterubyver/#{c['arch']}" else # V < 1.4.4 libruby = "#{c['prefix']}/lib/ruby" librubyver = "#{c['prefix']}/lib/ruby/#{version}" librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby" siterubyver = siteruby siterubyverarch = "$siterubyver/#{c['arch']}" end parameterize = lambda {|path| path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix') } if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } makeprog = arg.sub(/'/, '').split(/=/, 2)[1] else makeprog = 'make' end [ ExecItem.new('installdirs', 'std/site/home', 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\ {|val, table| case val when 'std' table['rbdir'] = '$librubyver' table['sodir'] = '$librubyverarch' when 'site' table['rbdir'] = '$siterubyver' table['sodir'] = '$siterubyverarch' when 'home' setup_rb_error '$HOME was not set' unless ENV['HOME'] table['prefix'] = ENV['HOME'] table['rbdir'] = '$libdir/ruby' table['sodir'] = '$libdir/ruby' end }, PathItem.new('prefix', 'path', c['prefix'], 'path prefix of target environment'), PathItem.new('bindir', 'path', parameterize.call(c['bindir']), 'the directory for commands'), PathItem.new('libdir', 'path', parameterize.call(c['libdir']), 'the directory for libraries'), PathItem.new('datadir', 'path', parameterize.call(c['datadir']), 'the directory for shared data'), PathItem.new('mandir', 'path', parameterize.call(c['mandir']), 'the directory for man pages'), PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), 'the directory for system configuration files'), PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']), 'the directory for local state data'), PathItem.new('libruby', 'path', libruby, 'the directory for ruby libraries'), PathItem.new('librubyver', 'path', librubyver, 'the directory for standard ruby libraries'), PathItem.new('librubyverarch', 'path', librubyverarch, 'the directory for standard ruby extensions'), PathItem.new('siteruby', 'path', siteruby, 'the directory for version-independent aux ruby libraries'), PathItem.new('siterubyver', 'path', siterubyver, 'the directory for aux ruby libraries'), PathItem.new('siterubyverarch', 'path', siterubyverarch, 'the directory for aux ruby binaries'), PathItem.new('rbdir', 'path', '$siterubyver', 'the directory for ruby scripts'), PathItem.new('sodir', 'path', '$siterubyverarch', 'the directory for ruby extentions'), PathItem.new('rubypath', 'path', rubypath, 'the path to set to #! line'), ProgramItem.new('rubyprog', 'name', rubypath, 'the ruby program using for installation'), ProgramItem.new('makeprog', 'name', makeprog, 'the make program to compile ruby extentions'), SelectItem.new('shebang', 'all/ruby/never', 'ruby', 'shebang line (#!) editing mode'), BoolItem.new('without-ext', 'yes/no', 'no', 'does not compile/install ruby extentions') ] end private :standard_entries def load_multipackage_entries multipackage_entries().each do |ent| add ent end end def multipackage_entries [ PackageSelectionItem.new('with', 'name,name...', '', 'ALL', 'package names that you want to install'), PackageSelectionItem.new('without', 'name,name...', '', 'NONE', 'package names that you do not want to install') ] end private :multipackage_entries ALIASES = { 'std-ruby' => 'librubyver', 'stdruby' => 'librubyver', 'rubylibdir' => 'librubyver', 'archdir' => 'librubyverarch', 'site-ruby-common' => 'siteruby', # For backward compatibility 'site-ruby' => 'siterubyver', # For backward compatibility 'bin-dir' => 'bindir', 'bin-dir' => 'bindir', 'rb-dir' => 'rbdir', 'so-dir' => 'sodir', 'data-dir' => 'datadir', 'ruby-path' => 'rubypath', 'ruby-prog' => 'rubyprog', 'ruby' => 'rubyprog', 'make-prog' => 'makeprog', 'make' => 'makeprog' } def fixup ALIASES.each do |ali, name| @table[ali] = @table[name] end @items.freeze @table.freeze @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/ end def parse_opt(opt) m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}" m.to_a[1,2] end def dllext @rbconfig['DLEXT'] end def value_config?(name) lookup(name).value? end class Item def initialize(name, template, default, desc) @name = name.freeze @template = template @value = default @default = default @description = desc end attr_reader :name attr_reader :description attr_accessor :default alias help_default default def help_opt "--#{@name}=#{@template}" end def value? true end def value @value end def resolve(table) @value.gsub(%r<\$([^/]+)>) { table[$1] } end def set(val) @value = check(val) end private def check(val) setup_rb_error "config: --#{name} requires argument" unless val val end end class BoolItem < Item def config_type 'bool' end def help_opt "--#{@name}" end private def check(val) return 'yes' unless val case val when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes' when /\An(o)?\z/i, /\Af(alse)\z/i then 'no' else setup_rb_error "config: --#{@name} accepts only yes/no for argument" end end end class PathItem < Item def config_type 'path' end private def check(path) setup_rb_error "config: --#{@name} requires argument" unless path path[0,1] == '$' ? path : File.expand_path(path) end end class ProgramItem < Item def config_type 'program' end end class SelectItem < Item def initialize(name, selection, default, desc) super @ok = selection.split('/') end def config_type 'select' end private def check(val) unless @ok.include?(val.strip) setup_rb_error "config: use --#{@name}=#{@template} (#{val})" end val.strip end end class ExecItem < Item def initialize(name, selection, desc, &block) super name, selection, nil, desc @ok = selection.split('/') @action = block end def config_type 'exec' end def value? false end def resolve(table) setup_rb_error "$#{name()} wrongly used as option value" end undef set def evaluate(val, table) v = val.strip.downcase unless @ok.include?(v) setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})" end @action.call v, table end end class PackageSelectionItem < Item def initialize(name, template, default, help_default, desc) super name, template, default, desc @help_default = help_default end attr_reader :help_default def config_type 'package' end private def check(val) unless File.dir?("packages/#{val}") setup_rb_error "config: no such package: #{val}" end val end end class MetaConfigEnvironment def initialize(config, installer) @config = config @installer = installer end def config_names @config.names end def config?(name) @config.key?(name) end def bool_config?(name) @config.lookup(name).config_type == 'bool' end def path_config?(name) @config.lookup(name).config_type == 'path' end def value_config?(name) @config.lookup(name).config_type != 'exec' end def add_config(item) @config.add item end def add_bool_config(name, default, desc) @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) end def add_path_config(name, default, desc) @config.add PathItem.new(name, 'path', default, desc) end def set_config_default(name, default) @config.lookup(name).default = default end def remove_config(name) @config.remove(name) end # For only multipackage def packages raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer @installer.packages end # For only multipackage def declare_packages(list) raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer @installer.packages = list end end end # class ConfigTable # This module requires: #verbose?, #no_harm? module FileOperations def mkdir_p(dirname, prefix = nil) dirname = prefix + File.expand_path(dirname) if prefix $stderr.puts "mkdir -p #{dirname}" if verbose? return if no_harm? # Does not check '/', it's too abnormal. dirs = File.expand_path(dirname).split(%r<(?=/)>) if /\A[a-z]:\z/i =~ dirs[0] disk = dirs.shift dirs[0] = disk + dirs[0] end dirs.each_index do |idx| path = dirs[0..idx].join('') Dir.mkdir path unless File.dir?(path) end end def rm_f(path) $stderr.puts "rm -f #{path}" if verbose? return if no_harm? force_remove_file path end def rm_rf(path) $stderr.puts "rm -rf #{path}" if verbose? return if no_harm? remove_tree path end def remove_tree(path) if File.symlink?(path) remove_file path elsif File.dir?(path) remove_tree0 path else force_remove_file path end end def remove_tree0(path) Dir.foreach(path) do |ent| next if ent == '.' next if ent == '..' entpath = "#{path}/#{ent}" if File.symlink?(entpath) remove_file entpath elsif File.dir?(entpath) remove_tree0 entpath else force_remove_file entpath end end begin Dir.rmdir path rescue Errno::ENOTEMPTY # directory may not be empty end end def move_file(src, dest) force_remove_file dest begin File.rename src, dest rescue File.open(dest, 'wb') {|f| f.write File.binread(src) } File.chmod File.stat(src).mode, dest File.unlink src end end def force_remove_file(path) begin remove_file path rescue end end def remove_file(path) File.chmod 0777, path File.unlink path end def install(from, dest, mode, prefix = nil) $stderr.puts "install #{from} #{dest}" if verbose? return if no_harm? realdest = prefix ? prefix + File.expand_path(dest) : dest realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) str = File.binread(from) if diff?(str, realdest) verbose_off { rm_f realdest if File.exist?(realdest) } File.open(realdest, 'wb') {|f| f.write str } File.chmod mode, realdest File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| if prefix f.puts realdest.sub(prefix, '') else f.puts realdest end } end end def diff?(new_content, path) return true unless File.exist?(path) new_content != File.binread(path) end def command(*args) $stderr.puts args.join(' ') if verbose? system(*args) or raise RuntimeError, "system(#{args.map{|a| a.inspect }.join(' ')}) failed" end def ruby(*args) command config('rubyprog'), *args end def make(task = nil) command(*[config('makeprog'), task].compact) end def extdir?(dir) File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb") end def files_of(dir) Dir.open(dir) {|d| return d.select {|ent| File.file?("#{dir}/#{ent}") } } end DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn ) def directories_of(dir) Dir.open(dir) {|d| return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT } end end # This module requires: #srcdir_root, #objdir_root, #relpath module HookScriptAPI def get_config(key) @config[key] end alias config get_config # obsolete: use metaconfig to change configuration def set_config(key, val) @config[key] = val end # # srcdir/objdir (works only in the package directory) # def curr_srcdir "#{srcdir_root()}/#{relpath()}" end def curr_objdir "#{objdir_root()}/#{relpath()}" end def srcfile(path) "#{curr_srcdir()}/#{path}" end def srcexist?(path) File.exist?(srcfile(path)) end def srcdirectory?(path) File.dir?(srcfile(path)) end def srcfile?(path) File.file?(srcfile(path)) end def srcentries(path = '.') Dir.open("#{curr_srcdir()}/#{path}") {|d| return d.to_a - %w(. ..) } end def srcfiles(path = '.') srcentries(path).select {|fname| File.file?(File.join(curr_srcdir(), path, fname)) } end def srcdirectories(path = '.') srcentries(path).select {|fname| File.dir?(File.join(curr_srcdir(), path, fname)) } end end class ToplevelInstaller Version = '3.4.1' Copyright = 'Copyright (c) 2000-2005 Minero Aoki' TASKS = [ [ 'all', 'do config, setup, then install' ], [ 'config', 'saves your configurations' ], [ 'show', 'shows current configuration' ], [ 'setup', 'compiles ruby extentions and others' ], [ 'install', 'installs files' ], [ 'test', 'run all tests in test/' ], [ 'clean', "does `make clean' for each extention" ], [ 'distclean',"does `make distclean' for each extention" ] ] def ToplevelInstaller.invoke config = ConfigTable.new(load_rbconfig()) config.load_standard_entries config.load_multipackage_entries if multipackage? config.fixup klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller) klass.new(File.dirname($0), config).invoke end def ToplevelInstaller.multipackage? File.dir?(File.dirname($0) + '/packages') end def ToplevelInstaller.load_rbconfig if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } ARGV.delete(arg) load File.expand_path(arg.split(/=/, 2)[1]) $".push 'rbconfig.rb' else require 'rbconfig' end ::Config::CONFIG end def initialize(ardir_root, config) @ardir = File.expand_path(ardir_root) @config = config # cache @valid_task_re = nil end def config(key) @config[key] end def inspect "#<#{self.class} #{__id__()}>" end def invoke run_metaconfigs case task = parsearg_global() when nil, 'all' parsearg_config init_installers exec_config exec_setup exec_install else case task when 'config', 'test' ; when 'clean', 'distclean' @config.load_savefile if File.exist?(@config.savefile) else @config.load_savefile end __send__ "parsearg_#{task}" init_installers __send__ "exec_#{task}" end end def run_metaconfigs @config.load_script "#{@ardir}/metaconfig" end def init_installers @installer = Installer.new(@config, @ardir, File.expand_path('.')) end # # Hook Script API bases # def srcdir_root @ardir end def objdir_root '.' end def relpath '.' end # # Option Parsing # def parsearg_global while arg = ARGV.shift case arg when /\A\w+\z/ setup_rb_error "invalid task: #{arg}" unless valid_task?(arg) return arg when '-q', '--quiet' @config.verbose = false when '--verbose' @config.verbose = true when '--help' print_usage $stdout exit 0 when '--version' puts "#{File.basename($0)} version #{Version}" exit 0 when '--copyright' puts Copyright exit 0 else setup_rb_error "unknown global option '#{arg}'" end end nil end def valid_task?(t) valid_task_re() =~ t end def valid_task_re @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/ end def parsearg_no_options unless ARGV.empty? task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1) setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}" end end alias parsearg_show parsearg_no_options alias parsearg_setup parsearg_no_options alias parsearg_test parsearg_no_options alias parsearg_clean parsearg_no_options alias parsearg_distclean parsearg_no_options def parsearg_config evalopt = [] set = [] @config.config_opt = [] while i = ARGV.shift if /\A--?\z/ =~ i @config.config_opt = ARGV.dup break end name, value = *@config.parse_opt(i) if @config.value_config?(name) @config[name] = value else evalopt.push [name, value] end set.push name end evalopt.each do |name, value| @config.lookup(name).evaluate value, @config end # Check if configuration is valid set.each do |n| @config[n] if @config.value_config?(n) end end def parsearg_install @config.no_harm = false @config.install_prefix = '' while a = ARGV.shift case a when '--no-harm' @config.no_harm = true when /\A--prefix=/ path = a.split(/=/, 2)[1] path = File.expand_path(path) unless path[0,1] == '/' @config.install_prefix = path else setup_rb_error "install: unknown option #{a}" end end end def print_usage(out) out.puts 'Typical Installation Procedure:' out.puts " $ ruby #{File.basename $0} config" out.puts " $ ruby #{File.basename $0} setup" out.puts " # ruby #{File.basename $0} install (may require root privilege)" out.puts out.puts 'Detailed Usage:' out.puts " ruby #{File.basename $0} " out.puts " ruby #{File.basename $0} [] []" fmt = " %-24s %s\n" out.puts out.puts 'Global options:' out.printf fmt, '-q,--quiet', 'suppress message outputs' out.printf fmt, ' --verbose', 'output messages verbosely' out.printf fmt, ' --help', 'print this message' out.printf fmt, ' --version', 'print version and quit' out.printf fmt, ' --copyright', 'print copyright and quit' out.puts out.puts 'Tasks:' TASKS.each do |name, desc| out.printf fmt, name, desc end fmt = " %-24s %s [%s]\n" out.puts out.puts 'Options for CONFIG or ALL:' @config.each do |item| out.printf fmt, item.help_opt, item.description, item.help_default end out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" out.puts out.puts 'Options for INSTALL:' out.printf fmt, '--no-harm', 'only display what to do if given', 'off' out.printf fmt, '--prefix=path', 'install path prefix', '' out.puts end # # Task Handlers # def exec_config @installer.exec_config @config.save # must be final end def exec_setup @installer.exec_setup end def exec_install @installer.exec_install end def exec_test @installer.exec_test end def exec_show @config.each do |i| printf "%-20s %s\n", i.name, i.value if i.value? end end def exec_clean @installer.exec_clean end def exec_distclean @installer.exec_distclean end end # class ToplevelInstaller class ToplevelInstallerMulti < ToplevelInstaller include FileOperations def initialize(ardir_root, config) super @packages = directories_of("#{@ardir}/packages") raise 'no package exists' if @packages.empty? @root_installer = Installer.new(@config, @ardir, File.expand_path('.')) end def run_metaconfigs @config.load_script "#{@ardir}/metaconfig", self @packages.each do |name| @config.load_script "#{@ardir}/packages/#{name}/metaconfig" end end attr_reader :packages def packages=(list) raise 'package list is empty' if list.empty? list.each do |name| raise "directory packages/#{name} does not exist"\ unless File.dir?("#{@ardir}/packages/#{name}") end @packages = list end def init_installers @installers = {} @packages.each do |pack| @installers[pack] = Installer.new(@config, "#{@ardir}/packages/#{pack}", "packages/#{pack}") end with = extract_selection(config('with')) without = extract_selection(config('without')) @selected = @installers.keys.select {|name| (with.empty? or with.include?(name)) \ and not without.include?(name) } end def extract_selection(list) a = list.split(/,/) a.each do |name| setup_rb_error "no such package: #{name}" unless @installers.key?(name) end a end def print_usage(f) super f.puts 'Inluded packages:' f.puts ' ' + @packages.sort.join(' ') f.puts end # # Task Handlers # def exec_config run_hook 'pre-config' each_selected_installers {|inst| inst.exec_config } run_hook 'post-config' @config.save # must be final end def exec_setup run_hook 'pre-setup' each_selected_installers {|inst| inst.exec_setup } run_hook 'post-setup' end def exec_install run_hook 'pre-install' each_selected_installers {|inst| inst.exec_install } run_hook 'post-install' end def exec_test run_hook 'pre-test' each_selected_installers {|inst| inst.exec_test } run_hook 'post-test' end def exec_clean rm_f @config.savefile run_hook 'pre-clean' each_selected_installers {|inst| inst.exec_clean } run_hook 'post-clean' end def exec_distclean rm_f @config.savefile run_hook 'pre-distclean' each_selected_installers {|inst| inst.exec_distclean } run_hook 'post-distclean' end # # lib # def each_selected_installers Dir.mkdir 'packages' unless File.dir?('packages') @selected.each do |pack| $stderr.puts "Processing the package `#{pack}' ..." if verbose? Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") Dir.chdir "packages/#{pack}" yield @installers[pack] Dir.chdir '../..' end end def run_hook(id) @root_installer.run_hook id end # module FileOperations requires this def verbose? @config.verbose? end # module FileOperations requires this def no_harm? @config.no_harm? end end # class ToplevelInstallerMulti class Installer FILETYPES = %w( bin lib ext data conf man ) include FileOperations include HookScriptAPI def initialize(config, srcroot, objroot) @config = config @srcdir = File.expand_path(srcroot) @objdir = File.expand_path(objroot) @currdir = '.' end def inspect "#<#{self.class} #{File.basename(@srcdir)}>" end def noop(rel) end # # Hook Script API base methods # def srcdir_root @srcdir end def objdir_root @objdir end def relpath @currdir end # # Config Access # # module FileOperations requires this def verbose? @config.verbose? end # module FileOperations requires this def no_harm? @config.no_harm? end def verbose_off begin save, @config.verbose = @config.verbose?, false yield ensure @config.verbose = save end end # # TASK config # def exec_config exec_task_traverse 'config' end alias config_dir_bin noop alias config_dir_lib noop def config_dir_ext(rel) extconf if extdir?(curr_srcdir()) end alias config_dir_data noop alias config_dir_conf noop alias config_dir_man noop def extconf ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt end # # TASK setup # def exec_setup exec_task_traverse 'setup' end def setup_dir_bin(rel) files_of(curr_srcdir()).each do |fname| update_shebang_line "#{curr_srcdir()}/#{fname}" end end alias setup_dir_lib noop def setup_dir_ext(rel) make if extdir?(curr_srcdir()) end alias setup_dir_data noop alias setup_dir_conf noop alias setup_dir_man noop def update_shebang_line(path) return if no_harm? return if config('shebang') == 'never' old = Shebang.load(path) if old $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1 new = new_shebang(old) return if new.to_s == old.to_s else return unless config('shebang') == 'all' new = Shebang.new(config('rubypath')) end $stderr.puts "updating shebang: #{File.basename(path)}" if verbose? open_atomic_writer(path) {|output| File.open(path, 'rb') {|f| f.gets if old # discard output.puts new.to_s output.print f.read } } end def new_shebang(old) if /\Aruby/ =~ File.basename(old.cmd) Shebang.new(config('rubypath'), old.args) elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby' Shebang.new(config('rubypath'), old.args[1..-1]) else return old unless config('shebang') == 'all' Shebang.new(config('rubypath')) end end def open_atomic_writer(path, &block) tmpfile = File.basename(path) + '.tmp' begin File.open(tmpfile, 'wb', &block) File.rename tmpfile, File.basename(path) ensure File.unlink tmpfile if File.exist?(tmpfile) end end class Shebang def Shebang.load(path) line = nil File.open(path) {|f| line = f.gets } return nil unless /\A#!/ =~ line parse(line) end def Shebang.parse(line) cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ') new(cmd, args) end def initialize(cmd, args = []) @cmd = cmd @args = args end attr_reader :cmd attr_reader :args def to_s "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}") end end # # TASK install # def exec_install rm_f 'InstalledFiles' exec_task_traverse 'install' end def install_dir_bin(rel) install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755 end def install_dir_lib(rel) install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644 end def install_dir_ext(rel) return unless extdir?(curr_srcdir()) install_files rubyextentions('.'), "#{config('sodir')}/#{File.dirname(rel)}", 0555 end def install_dir_data(rel) install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644 end def install_dir_conf(rel) # FIXME: should not remove current config files # (rename previous file to .old/.org) install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644 end def install_dir_man(rel) install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644 end def install_files(list, dest, mode) mkdir_p dest, @config.install_prefix list.each do |fname| install fname, dest, mode, @config.install_prefix end end def libfiles glob_reject(%w(*.y *.output), targetfiles()) end def rubyextentions(dir) ents = glob_select("*.#{@config.dllext}", targetfiles()) if ents.empty? setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" end ents end def targetfiles mapdir(existfiles() - hookfiles()) end def mapdir(ents) ents.map {|ent| if File.exist?(ent) then ent # objdir else "#{curr_srcdir()}/#{ent}" # srcdir end } end # picked up many entries from cvs-1.11.1/src/ignore.c JUNK_FILES = %w( core RCSLOG tags TAGS .make.state .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb *~ *.old *.bak *.BAK *.orig *.rej _$* *$ *.org *.in .* ) def existfiles glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.'))) end def hookfiles %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| %w( config setup install clean ).map {|t| sprintf(fmt, t) } }.flatten end def glob_select(pat, ents) re = globs2re([pat]) ents.select {|ent| re =~ ent } end def glob_reject(pats, ents) re = globs2re(pats) ents.reject {|ent| re =~ ent } end GLOB2REGEX = { '.' => '\.', '$' => '\$', '#' => '\#', '*' => '.*' } def globs2re(pats) /\A(?:#{ pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|') })\z/ end # # TASK test # TESTDIR = 'test' def exec_test unless File.directory?('test') $stderr.puts 'no test in this package' if verbose? return end $stderr.puts 'Running tests...' if verbose? begin require 'test/unit' rescue LoadError setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.' end runner = Test::Unit::AutoRunner.new(true) runner.to_run << TESTDIR runner.run end # # TASK clean # def exec_clean exec_task_traverse 'clean' rm_f @config.savefile rm_f 'InstalledFiles' end alias clean_dir_bin noop alias clean_dir_lib noop alias clean_dir_data noop alias clean_dir_conf noop alias clean_dir_man noop def clean_dir_ext(rel) return unless extdir?(curr_srcdir()) make 'clean' if File.file?('Makefile') end # # TASK distclean # def exec_distclean exec_task_traverse 'distclean' rm_f @config.savefile rm_f 'InstalledFiles' end alias distclean_dir_bin noop alias distclean_dir_lib noop def distclean_dir_ext(rel) return unless extdir?(curr_srcdir()) make 'distclean' if File.file?('Makefile') end alias distclean_dir_data noop alias distclean_dir_conf noop alias distclean_dir_man noop # # Traversing # def exec_task_traverse(task) run_hook "pre-#{task}" FILETYPES.each do |type| if type == 'ext' and config('without-ext') == 'yes' $stderr.puts 'skipping ext/* by user option' if verbose? next end traverse task, type, "#{task}_dir_#{type}" end run_hook "post-#{task}" end def traverse(task, rel, mid) dive_into(rel) { run_hook "pre-#{task}" __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') directories_of(curr_srcdir()).each do |d| traverse task, "#{rel}/#{d}", mid end run_hook "post-#{task}" } end def dive_into(rel) return unless File.dir?("#{@srcdir}/#{rel}") dir = File.basename(rel) Dir.mkdir dir unless File.dir?(dir) prevdir = Dir.pwd Dir.chdir dir $stderr.puts '---> ' + rel if verbose? @currdir = rel yield Dir.chdir prevdir $stderr.puts '<--- ' + rel if verbose? @currdir = File.dirname(rel) end def run_hook(id) path = [ "#{curr_srcdir()}/#{id}", "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) } return unless path begin instance_eval File.read(path), path, 1 rescue raise if $DEBUG setup_rb_error "hook #{path} failed:\n" + $!.message end end end # class Installer class SetupError < StandardError; end def setup_rb_error(msg) raise SetupError, msg end if $0 == __FILE__ begin ToplevelInstaller.invoke rescue SetupError raise if $DEBUG $stderr.puts $!.message $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." exit 1 end end PK% ]&E  )gems/ruby-lsapi-5.5/examples/testlsapi.rbnuȯ#!/opt/alt/ruby26/bin/ruby require 'lsapi' $count = 0; while LSAPI.accept != nil print "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\nHello World! \##{$count}
\r\n" ENV.each_pair {|key, value| print "#{key} is #{value}
\r\n" } $count = $count + 1 end PK% ]+.gems/ruby-lsapi-5.5/examples/lsapi_with_cgi.rbnuȯ#!/opt/alt/ruby26/bin/ruby require 'lsapi' require 'cgi' while LSAPI.accept != nil cgi = CGI.new name = cgi['name'] puts cgi.header puts "Hello #{name}!
" if name puts "You are from #{cgi.remote_addr}
" end PK% ]&\-- gems/ruby-lsapi-5.5/lib/lsapi.sonuȯELF>U@&@8 @ !!0 !!888$$hhh Stdhhh PtdPPPQtdRtd!!P P GNU5<-s흏2bC H‚3@(L`qCSlP*fRn}'3qѮl>&Sɶ ܮʼnSO`[is|&߱RD/y7řkՊ eY&09=By:%/=ejOzJ6'l#mNULCB1{!\$O#W23S=apbU06aD7jp#7ĴDIΊ=\4yݾCEкQuo rSѮIo|q%h6 󝵛 ' =qX[ u  f   d ysOq    T [M f A k &K ! , 2TRT" s G +L  } >W  9 - kH  .E   $7x9 vo | Z A 9J 4, 2> F"`| E]   r G p `}F 0rD @I  `K 5 0vi~  z@! b П. P! ] Z\ g o  v 1 r Y ` Pq@  @ sl zj V } - Ps]   `o @rY po  5 o x$ Pl! u U U E v rS o7 @oT (   0  }F rJ @pT ! P~I   Е  P!b g  @g "! l p6 o p [ !__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizecompareValueLocationset_skip_writesigactionsigemptyset__stack_chk_failreallocfcntlacceptsetsockoptmmapmemsetsetsidread__errno_locationclosewritevkillgetppid__ctype_b_locstrncpystrchrstrcasecmpstrtolgetaddrinfomemcpyfreeaddrinfoinet_addrLSAPI_Log__vfprintf_chk__snprintf_chkgetuid__fprintf_chkgettimeofdaylocaltime_rwaitpidforksystemexitlsapi_perrorstrerrorLSAPI_is_suEXEC_DaemonLSAPI_StopLSAPI_IsRunningLSAPI_Register_Pgrp_Timer_CallbackLSAPI_InitRequestmallocgetpeernamedup2LSAPI_Initgeteuidsignalg_reqdlopendlsymLSAPI_Is_Listen_rLSAPI_Is_ListenLSAPI_Reset_rLSAPI_Release_rfreeLSAPI_GetHeader_rLSAPI_ReqBodyGetChar_rLSAPI_ReqBodyGetLine_rmemchrmemmoveLSAPI_ReadReqBody_rFlush_RespBuf_rLSAPI_GetEnv_rstrcmp__ctype_toupper_locLSAPI_ForeachOrgHeader_rqsortLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rLSAPI_ForeachSpecialEnv_rLSAPI_FinalizeRespHeaders_rLSAPI_Flush_rLSAPI_Write_Stderr_rgetpidgetcwdmemccpy__realpath_chkLSAPI_Finish_rLSAPI_End_Response_rLSAPI_Write_rLSAPI_sendfile_rsendfileLSAPI_AppendRespHeader2_rstrlenLSAPI_AppendRespHeader_rLSAPI_CreateListenSock2socketbindlistenunlinkLSAPI_ParseSockAddrLSAPI_CreateListenSockLSAPI_Init_Prefork_ServercallocsetpgidsysconfLSAPI_Set_Server_fdLSAPI_reset_server_stateis_enough_free_memLSAPI_Postfork_ChildLSAPI_Postfork_ParenttimeLSAPI_Accept_Before_Fork__fdelt_chkusleepsched_yieldLSAPI_Set_Max_ReqsLSAPI_Set_Max_IdleLSAPI_Set_Max_ChildrenLSAPI_Set_Extra_ChildrenLSAPI_Set_Max_Process_TimeLSAPI_Set_Max_Idle_ChildrenLSAPI_Set_Server_Max_Idle_SecsLSAPI_Set_Slow_Req_MsecsLSAPI_Get_Slow_Req_MsecsLSAPI_No_Check_ppidLSAPI_Get_ppidLSAPI_Init_Env_Parametersgetenvgetpwnamdlerrorsetrlimit__fxstatsetreuidLSAPI_ErrResponse_rlsapi_MD5Initlsapi_MD5Updatelsapi_MD5FinalgetpwuidsetgidsetgroupssetuidstrtollprctlinitgroupsLSAPI_Accept_rLSAPI_Prefork_Accept_rsigaddsetsigprocmaskLSAPI_Set_Restored_Parent_PidLSAPI_Inc_Req_Processedselectrb_tainted_str_newrb_hash_asetrb_funcallvrb_intern2rb_gc_markmunmaprb_check_typerb_obj_as_stringrb_f_sprintfs_fn_add_envrb_safe_levelrb_string_value_ptrrb_eval_string_wraprb_string_valuerb_check_safe_objrb_ruby_verbose_ptrrb_define_global_construby_strdupmkstempftruncaterb_str_buf_newrb_str_catrb_num2intrb_fix2intrb_eSecurityErrorrb_raisememmemrb_yieldrb_gc_writebarrier_unprotectrb_io_putsrb_ary_detransientrb_str_new_staticrb_exec_recursiverb_default_rsrb_output_fsrb_output_rsrb_lastline_getInit_lsapichdirrb_stderrrb_cObjectrb_const_getrb_global_variablerb_define_global_functionrb_define_classrb_define_singleton_methodrb_define_methodrb_data_object_zallocrb_stdoutrb_stdinrb_hash_new__memcpy_chklibruby.so.2.6libm.so.6libc.so.6__environ_edata__bss_start_endGLIBC_2.14GLIBC_2.15GLIBC_2.4GLIBC_2.3.4GLIBC_2.2.5GLIBC_2.3/opt/alt/ruby26/lib64@ l w ii  ti  ui  ii  !U!pU!!!!!!!!!! !(!0! 8!@!*H!8P!CX!P`!_h!fp!nx!s!z!!!!!!!!!!!!!!!2!G !\(!o0!8!@!H!P!X!`!h!p!x!!!!2!@!Y!i!t!!!!!!!X!!!!H!P!X!`!h!p!x!!!$!5!!?!K!M!U!Y!Y!Z!!!q!!! ! ! ! ! ! ! !( !0 !8 !@ !H ! P ! X ! ` ! h ! p !x ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !( ! 0 !8 !"@ !#H !%P !&X !` !'h !(p !)x ! !* !+ ! !, ! ! ! !- !. !/ !0 ! ! ! ! !1 !2 !3 ! !4 !( !0 !68 !7@ !8H !9P !:X !;` !<h !>p !@x !A !B !C ! !D !E !F !G !H !I ! !J ! !L !N !O !P !Q !R ! !S !T( !0 !V8 !@ !WH !XP ![X !\` !]h !^p !_x !` !a ! !b !c ! !d !e !f !g !h !i !j !k !l !m !!n!o!p! !(!r0!s8!t@!uH!vP!X!w`!xh!yp!{x!|!}!~!!!!!!!!!!!!!!!!!! !(!0!8!@!HH! HtH5J %K hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhA% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݾ D%վ D%; D%ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݽ D%ս D%ͽ D%Ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݼ D%ռ D%ͼ D%ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݻ D%ջ D%ͻ D%Ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݺ D%պ D%ͺ D%ź D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E DH= H H9tH6 Ht H= H5 H)HHH?HHtH HtfD=e u+UH=b Ht H=. d= ]wff. ÐHGH+FHcAVIH@AUATL$USHtQHHtIHIL9r 0HI9v'KHSMsH;Յ[]A\A]A^[D]A\A]A^øff.f= D2 ÐO AWDD_AVAUATUSD6^nAxj׋G3G D!3G V\$ЋW^$DD1\$!3WAʋN Fp $E‰L$A1A1DD^ !D1G;νD\$DEDVDT$A!A1EE|A 1AD!E1DD*ƇGD1D!A1A1DDN DL$E F0D!DnA1D1DGFEDf Dd$D^(A!A1EEؘiA 1AD!1DDDʋ^0D1D!A1DE [D 1!D1DDN,A1DL$G\EA!Df8A1ED"kA 1AD!1DDN4EqDD1!1DE CyD 1!D1DDV<1G!I!1DDD$ Eb%1!1DDD$E@@1!1DDD$ EQZ^&1!1DE6Ƕ1!1DD]/։ 1!1DESD1!1DE ؉ 1!1DDD$E01!1DDD$ E!1!1DE7É1!1DDD$ E 1!1DDD$A0ZEAA1A!A1AA㩉A AD1!1t$DD1!A ogD1 1D!FL*1DD$Ή1AA!B9A1DD$A AD1D$qDD11‹D$ 0"amD1G 81Ɖ11DDD$ ED꾤11DDD$AKAA1A5`KA1AЉApA 1AD1D1D1A ~(D 1G'111DDD$ A0AA1A1AЋT$A2A1D1֋T$ 9ىDD11D11C|A A1A1AD$A0eVĉA1D1AD")Dt$ D D1A *CDG# 1  1DD9Ή 1DDY[e\$  1DE Dt$ щ1DE3}D\$  1DDD$E] 1DEO~oA AD 1DE ,DT$ A1ADE6CDt$ AN 1A~SADEAA A1A5:ADA AD 1Љ3*\$D D1DFӆ[ ]A\A]A^ 1։ 1DƉA4A_ OW GOW ATI1USHdH%(H$1HHH<$t)H$dH3%(uL{8IHC0L)H9>Lt$L+{(LA@LLfIM)MK H@σLSLCpNIHDI0HI@HKpM~HC(MxIH E1I@HC8HL1HMLIHHKpH9eHMthILM)MUI9t H)tDL+t$HL[]A\A]A^A_DM@@M)(+IHt$HLHk8f.HAVLAUIATIUSHu\H߉[AD${LǃLSHu0{L[L]A\A]A^K[H]A\A]A^Hff.AWAVAUATUSHHHHD$ 0xIHIHLc\CHcT t u(HDLcLH t tLÅ~6HcAT t u#H@Å~ALH t tE<AG=I|$PHHTI9T$Hs7HI+t$@L2%))I|$PLHHcAMt$PHLIFID$PA:I|$P}MD$PII@ID$PAIc$0fET8HЃA$0D$ H[]A\A]A^A_D$ ff.H HB=0AUATUSHcHfDA< t< uH؅uH[]A\A]IHPHHDI9D$Hs3HI+t$@L2%))tQI|$PHHAPI\$PHCID$PIc$0fET8HЃA$0H1[]A\A]øSDAUATAUHSH?dH%(HD$1D$ff t1fHL$dH3 %(H[]A\A]ÐA1ҾÃtʼnǺ1HL$Aߺ踿u#DH'uDo̾߻D HJDeOAkDH}An衾}NSHtff.USHdH%(H$1HHu/HH$dH3%(uHĘ[]Ŀ@1H= tAUATA'USH݋ 'DNuD H@AHH^ HHtH- t YƉlj JUDk HM DcEuSH8dH%(H$(1=HtH H=H H=_>HE1 H讹H=Y>Ht 1H膹 H=E>ijHHt 1H]IAąWE1H=">萳Ht 1H, H=>jHtHǺ 1_H==CH H==$HtHǺ 1IԶH==H1 H舸OH==òHtHǺ 1_H==蜲HtHǺ 18!H==uHtHǺ 1H==NHtHǺ 1蓲H=r='HtMH=p=Ht 1H護ۀ _H=X=Ht 1H D   EH=$=H=r u Pe 5[ H=&=cH 1H% …t% HQv HHHHD L*=L =L#=C HLt@HֹL€D t%HtAHHt9HLuHfDHJHHJHuHHu1ۉH$(dH3%(H8[]A\A]fD& H覲D9舭HHiHǺ11˵ÃHT$ƿD$(?H5/ رHgH Htxc@dx@D  E9D E)ZfH=}8贬 HK]  u t 'j X '> )fՅtbH H-DHH5?1 cAHc螲L%~ HH~ a蓮Åt=~ 0~ u ~ 5~ `HH5@?uHH5>1u HH5>Fff.AVIAUEATIUHSHt4Hu!(fDHH蔭HLgH]HuMtEL [1]A\A]A^ÐIcLLH#EgHGHHܺvT2HGAWAVAAUIATUHoSH1HGO@ƉWDW?t;AĉDHH|@D)A9rhAGt4LLDHL9A?vWEfAIIIH޺@HH@ HLL9uA?DLHH[]A\A]A^A_ܱIATLfUHSFH?LHz?)ƒw=t19rLHfCAD$AD$ ID$071)"HCHLHCP?o H{1HMHHCPH)KXH[]A\ff.fAWAVAUATUSHdH%(H$1Ht^ IAfMcg IoA_@LH3HuM88u =Yw uٽH$dH3 %( HĨ[]A\A]A^A_f~AAuIALJf8LS|xr@tPHf@HPXN MgA;G ZA9~uEo)HHcIHLD"Hu$'85Dv uAMgA9ID$,HD$HcIIDhAh(A9}A /HcIH4@HUHAIIh$A9}A HcIH4@HHAIIHl$p(ILHIILp$hMIc@o9gIcP[9SIcpG9?IcH39+IHHHHIHT$IIc@ H)IHHIHHHIHIIcHIHHHD$I9E1DL4t9dfH H IGAG IPH f@ f@ HHP P H HPPHHPPHHPPHHPPf@f@f@HH#PP H H'P#P$H$H+P'P(f@f@!f@%H(P+f@)I1 fDIHcȋL4t#fBIHT4 rfB@2JHHuMIcP IHHH9pH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@pHH9wMApIbIc@ IH0zu ALJt`!u u Au 1LHc迩IHIGAo IuID%t D-t B(AA1IcH4IILI 9HqH=W. IJDB(9xHqH=2. XIJB($AD$IKAzHL$;MbfoOt Lt$ LAoL$AT$Ml$)$踪 LL(HL$LHLLH$ID$H$I3L$H1H D$$Dl$EDDl$H=s IHIDEs MH=$s t"LDLŃP|$臨Et$A9uHt$莤D=Ń5r $A?D5r t 0AH5*L*HtHHr f)r #AH5:e 1;H@H5+1YLH 1HIH531H531D%q q DD$$H=q IHtZEW7E1111H=3H5*1耨E|$迦M2;|$藦E1H5*LuI}觧Ń1H5*LKfD=p -p p ED$AIFH5*1覧HH)H51H1聧1H5!*L 1H5C2LA#LH 3H H=NQ HL~H-> H 4> H=H HP HzH HJH*HQ H]> HH> HH=P LH5}H = H="H HP HH HJH*H踀yH(yHHP 1aH5P H=}H3H=r}yH(H[]A\A]@HPHH=L }HwHL H.XXXXXXH(Ht+H=uH=O 1HxH5,H=O 1HJfDmHzHfKHzHt -GF OkHyHu-*F 2HHAnonymous mmap() failedlocalhost%02d:%02d:%02d [%s] [UID:%d][%d] %.*syesnosystem()%s, errno: %d (%s) /dev/nulllibpthread.sopthread_atforkHTTP_[UID:%d][%d] %s:%s: %s LSAPI: jail() failure./etc/Can't set signalsaccept() failedLSAPI_STDERR_LOGPHP_LSAPI_MAX_REQUESTSLSAPI_MAX_REQSLSAPI_KEEP_LISTENLSAPI_AVOID_FORKLSAPI_ACCEPT_NOTIFYLSAPI_SLOW_REQ_MSECSLSAPI_ALLOW_CORE_DUMPLSAPI_MAX_IDLEPHP_LSAPI_CHILDRENLSAPI_EXTRA_CHILDRENLSAPI_MAX_IDLE_CHILDRENLSAPI_PGRP_MAX_IDLELSAPI_MAX_PROCESS_TIMELSAPI_PPID_NO_CHECKLSAPI_MAX_BUSY_WORKERLSAPI_DUMP_DEBUG_INFOnobodyLSAPI_DEFAULT_UIDLSAPI_DEFAULT_GIDLSAPI_SECRETLSAPI_LVE_ENABLEliblve.so.0lve_is_availablelve_instance_initlve_destroylve_enterlve_leavejailPHP_LSAPI_PHPRC=packetLen < 0 packetLen > %d Bad request header - ERROR#1 ParseRequest error SUEXEC_AUTHSUEXEC_UGIDLSAPI: setgid()LSAPI: initgroups()LSAPI: setgroups()LSAPI: setuid()Bad request header - ERROR#2 lsapi_accept() errorPragma: no-cacheRetry-After: 60Content-Type: text/htmlDEBUGNOTICEWARNERRORCRITFATALAcceptAccept-CharsetAccept-EncodingAccept-LanguageAuthorizationConnectionContent-TypeContent-LengthCookieCookie2HostPragmaRefererUser-AgentCache-ControlIf-Modified-SinceIf-MatchIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveX-Forwarded-ForViaTransfer-EncodingHTTP_ACCEPTHTTP_ACCEPT_CHARSETHTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_AUTHORIZATIONHTTP_CONNECTIONCONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_COOKIE2HTTP_HOSTHTTP_PRAGMAHTTP_REFERERHTTP_USER_AGENTHTTP_CACHE_CONTROLHTTP_IF_MODIFIED_SINCEHTTP_IF_MATCHHTTP_IF_NONE_MATCHHTTP_IF_RANGEHTTP_IF_UNMODIFIED_SINCEHTTP_KEEP_ALIVEHTTP_RANGEHTTP_X_FORWARDED_FORHTTP_VIAHTTP_TRANSFER_ENCODING%04d-%02d-%02d %02d:%02d:%02d.%06d Child process with pid: %d was killed by signal: %d, core dumped: %s Possible runaway process, UID: %d, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld gdb --batch -ex "attach %d" -ex "set height 0" -ex "bt" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2Force killing runaway process PID: %d with SIGKILL Killing runaway process PID: %d with SIGTERM Children tracking is wrong: Cur Children: %d, count: %d, idle: %d, dying: %d LSAPI: LVE jail(%d) result: %d, error: %s ! Invalid custom stderr log pathFailed to open custom stderr logCan't set signal handler for SIGCHILDReached max children process limit: %d, extra: %d, current: %d, busy: %d, please increase LSAPI_CHILDREN. LSAPI: failed to open secret file: %s! LSAPI: failed to check state of file: %s! LSAPI: file permission check failure: %s LSAPI: failed to read secret from secret file: %s LSAPI: Unable to initialize LVERequest header does match total size, total: %d, real: %ld LSAPI: missing SUEXEC_UGID env, use default user! LSAPI: SUEXEC_AUTH authentication failed, use default user! LSAPI: lve_enter() failure, reached resource limit.prctl: Failed to set dumpable, core dump may not be available!sigprocmask(SIG_BLOCK) to block SIGCHLDsigprocmask( SIG_SETMASK ) to restore SIGMASK in childfork() failed, please increase process limitsigprocmask( SIG_SETMASK ) to restore SIGMASKCache-Control: private, no-cache, no-store, must-revalidate, max-age=0PID 508 Resource Limit Is Reached

Resource Limit Is Reached

The website is temporarily unable to service your request as it exceeded resource limit. Please try again later.
          replacesrandQUERY_STRINGREQUEST_URIPATH_INFOREQUEST_PATHSCRIPT_NAMESTDERRreopenftruncate() failed. File mapping failed. Memory calloc error[...]nilLSAPI_MAX_BODYBUF_LENGTHLSAPI_TEMPFILEXXXXXXRACK_ROOTchdir()to_hashCGI/1.2eval_string_wrapLSAPIacceptaccept_new_connectionpostfork_childpostfork_parentprocessputcwriteprintprintfputs<<flushgetcgetsreadrewindeacheofeof?closebinmodeisattytty?syncsync=RACK_ENVInsecure: operation on untainted IOGATEWAY_Irewindable_input.rbNTERFACE/tmp/lsapi.XXXXX;z@Ze pp8pLp`pt q0q@qx00ydyxyPzz|$|t}~<Pd$@ppH p  0 @ Ќ 0 D PX t ` Џ 8 PL p P d `x p ph ` (pt@ @pp0<PPdx`Я,@T h@|`й4Ptp@ L $@8pL`tp00\Pxp@,`x`@ pHzRx $@V FJ w?:*3$"D` \0lp,l(l L$lsEIB E(A0z (A BBBI A (D BBBA Tl Pl@LlYGJB B(A0A80F(B DBb0ThsBFC G  AABK sk( tGADJ n AAA 4DtUAGK R CAG L JCG ltAG] AJ $tt C KFLHuBBE A(H0H (D BBBD  (D BBBA PtvvFB A(D0D (A BBBB L(A BBBA$vaAAD XAAHwBBB B(A0A8D@N 8C0A(B BBBH $`wOAf Q C E H@wYBBB A(D0J 0A(A BBBF xzFEA C(G   (A ABBD M I c A  E M A k E E E E H V HHT|FBB B(A0A8D`` 8A0A(B BBBD l}+BBB B(A0D8JYHPC Mi 8A0A(B BBBE LTMDd~6BBB B(A0A8DP 8A0A(B BBBG  8J0H(G DBBK $l`7EFF IIOx | 4xFAA G>  AABG EO D  A @ ThY|JED$S p]Ph H XAHlFBB B(A0A8LP 8A0A(B BBBH <Є FBB A(A0 (D BBBI \i`pFBB B(A0A8DP~ 8A0A(B BBBA k 8A0A(B BBBH L$FBB A(A0H Q D 0A(A BBBH L$FBB B(A0A8G 8A0A(B BBBF thFF$lnCXJLDlFBB B(A0A8DA 8A0A(B BBBA `( dBBB B(A0A8G I K I L N N w 8A0A(B BBBI 0 BMD GL  AABA < |=BAA G L@I@U  AABG $ |TWEHG ( ag H SHL pFBB B(A0A8DPS 8D0A(B BBBF T bIE D(C0P (F BBBM Q(H BBBAH lFBB B(A0A8DP 8A0A(B BBBA T< CBA A(G0` (A ABBD  (C ABBA J8 Ȗ-FBD D(D@T (A ABBB  ( ȗlECGF AAI L !cBG A(D0 (A ABBE XD0` t Z D10 ppFAA G@7  AABF  @LsL КFBB B(A0A8G 8A0A(B BBBG < P d x    Ȟ Ԟ  О  ̞Ȟ <Ğ FBA K(G (A ABBG <XFEE D(D0M (C BBBB ԧ(HFBH E(A0E8I@ 8A0A(B BBBE (FED ABH$8 BBB B(A0A8G 8A0A(B BBBJ Dp̴FBB A(A0G 0A(A BBBF L4 FBB B(A0A8G  8A0A(B BBBA 4 H\+p(BFGA kFB4zD O E  HU gHQ G <ayd(THEDL ] CAJ ELEY HW HW-Hd(EAD  DAJ ,aED y AE HP FBB E(D0C8GPm 8F0A(B BBBG ,ZAD J ABL 4PoAD  AAK pP \FBD C(G0 (D ABBE j (D ABBE | (G DBBA HdhFBB B(A0A8G@ 8D0A(B BBBD 7^UVvd1",a^E7Y:LP*%p 'P-Eҁ<whoIs2@:ra0l h|w/OR8 #iXtIsBe1q~]|IP9t¨Cv؈s+@r|HS6aRawoto %1ɯ`1/bcRۆP;[0jdZE7TB^:kW/#Iƒ~fpBDURnew·]9 x4M xovyC arD^U;t6#&YCçFZ#`ٔSÕ/7Elqb#SIS,Ko>_]Vp1}=50CoFլ8XgEe+6%(4oOc/$md٤Ũ;xuXx+5E^uCĵ,I)PZ5#ǯ>v>} /`sw[m^"a"Iz09بa~d5*_Mt++!T´TN;GO>jiVnƈw%ZsyX:70ER54$nEWraR{ D'c#DqDMX/3%oRQZWb^· O |a=LQuU)JUsjC q2εxR.8mHP Hq1b A $z")nT\?Iށ-#f ]p2:U]d,D.I 5.0". # # Further, minitest 6 will be dropping the following: # # + MiniTest (it's been Minitest for *years*) # + MiniTest::Unit # + MiniTest::Unit::TestCase # + assert_send (unless you argue for it well) # EOM end desc "Find missing expectations" task :specs do $:.unshift "lib" require "minitest/test" require "minitest/spec" pos_prefix, neg_prefix = "must", "wont" skip_re = /^(must|wont)$|wont_(throw)|must_(block|not?_|nothing|raise$)/x dont_flip_re = /(must|wont)_(include|respond_to)/ map = { /(must_throw)s/ => '\1', /(?!not)_same/ => "_be_same_as", /_in_/ => "_be_within_", /_operator/ => "_be", /_includes/ => "_include", /(must|wont)_(.*_of|nil|silent|empty)/ => '\1_be_\2', /must_raises/ => "must_raise", } expectations = Minitest::Expectations.public_instance_methods.map(&:to_s) assertions = Minitest::Assertions.public_instance_methods.map(&:to_s) assertions.sort.each do |assertion| expectation = case assertion when /^assert/ then assertion.sub(/^assert/, pos_prefix.to_s) when /^refute/ then assertion.sub(/^refute/, neg_prefix.to_s) end next unless expectation next if expectation =~ skip_re regexp, replacement = map.find { |re, _| expectation =~ re } expectation.sub! regexp, replacement if replacement next if expectations.include? expectation args = [assertion, expectation].map(&:to_sym).map(&:inspect) args << :reverse if expectation =~ dont_flip_re puts puts "##" puts "# :method: #{expectation}" puts "# See Minitest::Assertions##{assertion}" puts puts "infect_an_assertion #{args.join ", "}" end end task :bugs do sh "for f in bug*.rb ; do echo $f; echo; #{Gem.ruby} -Ilib $f && rm $f ; done" end # vim: syntax=Ruby PK% ]9(  =gems/minitest-5.11.3/test/minitest/test_minitest_benchmark.rbnu[require "minitest/autorun" require "minitest/benchmark" ## # Used to verify data: # http://www.wolframalpha.com/examples/RegressionAnalysis.html class TestMinitestBenchmark < Minitest::Test def test_cls_bench_exp assert_equal [2, 4, 8, 16, 32], Minitest::Benchmark.bench_exp(2, 32, 2) end def test_cls_bench_linear assert_equal [2, 4, 6, 8, 10], Minitest::Benchmark.bench_linear(2, 10, 2) end def test_cls_runnable_methods assert_equal [], Minitest::Benchmark.runnable_methods c = Class.new(Minitest::Benchmark) do def bench_blah end end assert_equal ["bench_blah"], c.runnable_methods end def test_cls_bench_range assert_equal [1, 10, 100, 1_000, 10_000], Minitest::Benchmark.bench_range end def test_fit_exponential_clean x = [1.0, 2.0, 3.0, 4.0, 5.0] y = x.map { |n| 1.1 * Math.exp(2.1 * n) } assert_fit :exponential, x, y, 1.0, 1.1, 2.1 end def test_fit_exponential_noisy x = [1.0, 1.9, 2.6, 3.4, 5.0] y = [12, 10, 8.2, 6.9, 5.9] # verified with Numbers and R assert_fit :exponential, x, y, 0.95, 13.81148, -0.1820 end def test_fit_logarithmic_clean x = [1.0, 2.0, 3.0, 4.0, 5.0] y = x.map { |n| 1.1 + 2.1 * Math.log(n) } assert_fit :logarithmic, x, y, 1.0, 1.1, 2.1 end def test_fit_logarithmic_noisy x = [1.0, 2.0, 3.0, 4.0, 5.0] # Generated with # y = x.map { |n| jitter = 0.999 + 0.002 * rand; (Math.log(n) ) * jitter } y = [0.0, 0.6935, 1.0995, 1.3873, 1.6097] assert_fit :logarithmic, x, y, 0.95, 0, 1 end def test_fit_constant_clean x = (1..5).to_a y = [5.0, 5.0, 5.0, 5.0, 5.0] assert_fit :linear, x, y, nil, 5.0, 0 end def test_fit_constant_noisy x = (1..5).to_a y = [1.0, 1.2, 1.0, 0.8, 1.0] # verified in numbers and R assert_fit :linear, x, y, nil, 1.12, -0.04 end def test_fit_linear_clean # y = m * x + b where m = 2.2, b = 3.1 x = (1..5).to_a y = x.map { |n| 2.2 * n + 3.1 } assert_fit :linear, x, y, 1.0, 3.1, 2.2 end def test_fit_linear_noisy x = [ 60, 61, 62, 63, 65] y = [3.1, 3.6, 3.8, 4.0, 4.1] # verified in numbers and R assert_fit :linear, x, y, 0.8315, -7.9635, 0.1878 end def test_fit_power_clean # y = A x ** B, where B = b and A = e ** a # if, A = 1, B = 2, then x = [1.0, 2.0, 3.0, 4.0, 5.0] y = [1.0, 4.0, 9.0, 16.0, 25.0] assert_fit :power, x, y, 1.0, 1.0, 2.0 end def test_fit_power_noisy # from www.engr.uidaho.edu/thompson/courses/ME330/lecture/least_squares.html x = [10, 12, 15, 17, 20, 22, 25, 27, 30, 32, 35] y = [95, 105, 125, 141, 173, 200, 253, 298, 385, 459, 602] # verified in numbers assert_fit :power, x, y, 0.90, 2.6217, 1.4556 # income to % of households below income amount # http://library.wolfram.com/infocenter/Conferences/6461/PowerLaws.nb x = [15_000, 25_000, 35_000, 50_000, 75_000, 100_000] y = [0.154, 0.283, 0.402, 0.55, 0.733, 0.843] # verified in numbers assert_fit :power, x, y, 0.96, 3.119e-5, 0.8959 end def assert_fit msg, x, y, fit, exp_a, exp_b bench = Minitest::Benchmark.new :blah a, b, rr = bench.send "fit_#{msg}", x, y assert_operator rr, :>=, fit if fit assert_in_delta exp_a, a assert_in_delta exp_b, b end end describe "my class Bench" do klass = self it "should provide bench methods" do klass.must_respond_to :bench end end PK% ]`#*ii<gems/minitest-5.11.3/test/minitest/test_minitest_reporter.rbnu[require "minitest/autorun" require "minitest/metametameta" class Runnable def woot assert true end end class TestMinitestReporter < MetaMetaMetaTestCase attr_accessor :r, :io def new_composite_reporter reporter = Minitest::CompositeReporter.new reporter << Minitest::SummaryReporter.new(self.io) reporter << Minitest::ProgressReporter.new(self.io) def reporter.first reporters.first end def reporter.results first.results end def reporter.count first.count end def reporter.assertions first.assertions end reporter end def setup self.io = StringIO.new("") self.r = new_composite_reporter end def error_test unless defined? @et then @et = Minitest::Test.new(:woot) @et.failures << Minitest::UnexpectedError.new(begin raise "no" rescue => e e end) @et = Minitest::Result.from @et end @et end def fail_test unless defined? @ft then @ft = Minitest::Test.new(:woot) @ft.failures << begin raise Minitest::Assertion, "boo" rescue Minitest::Assertion => e e end @ft = Minitest::Result.from @ft end @ft end def passing_test @pt ||= Minitest::Result.from Minitest::Test.new(:woot) end def skip_test unless defined? @st then @st = Minitest::Test.new(:woot) @st.failures << begin raise Minitest::Skip rescue Minitest::Assertion => e e end @st = Minitest::Result.from @st end @st end def test_to_s r.record passing_test r.record fail_test assert_match "woot", r.first.to_s end def test_passed_eh_empty assert_predicate r, :passed? end def test_passed_eh_failure r.results << fail_test refute_predicate r, :passed? end SKIP_MSG = "\n\nYou have skipped tests. Run with --verbose for details." def test_passed_eh_error r.start r.results << error_test refute_predicate r, :passed? r.report refute_match SKIP_MSG, io.string end def test_passed_eh_skipped r.start r.results << skip_test assert r.passed? restore_env do r.report end assert_match SKIP_MSG, io.string end def test_passed_eh_skipped_verbose r.first.options[:verbose] = true r.start r.results << skip_test assert r.passed? r.report refute_match SKIP_MSG, io.string end def test_start r.start exp = "Run options: \n\n# Running:\n\n" assert_equal exp, io.string end def test_record_pass r.record passing_test assert_equal ".", io.string assert_empty r.results assert_equal 1, r.count assert_equal 0, r.assertions end def test_record_fail fail_test = self.fail_test r.record fail_test assert_equal "F", io.string assert_equal [fail_test], r.results assert_equal 1, r.count assert_equal 0, r.assertions end def test_record_error error_test = self.error_test r.record error_test assert_equal "E", io.string assert_equal [error_test], r.results assert_equal 1, r.count assert_equal 0, r.assertions end def test_record_skip skip_test = self.skip_test r.record skip_test assert_equal "S", io.string assert_equal [skip_test], r.results assert_equal 1, r.count assert_equal 0, r.assertions end def test_report_empty r.start r.report exp = clean <<-EOM Run options: # Running: Finished in 0.00 0 runs, 0 assertions, 0 failures, 0 errors, 0 skips EOM assert_equal exp, normalize_output(io.string) end def test_report_passing r.start r.record passing_test r.report exp = clean <<-EOM Run options: # Running: . Finished in 0.00 1 runs, 0 assertions, 0 failures, 0 errors, 0 skips EOM assert_equal exp, normalize_output(io.string) end def test_report_failure r.start r.record fail_test r.report exp = clean <<-EOM Run options: # Running: F Finished in 0.00 1) Failure: Minitest::Test#woot [FILE:LINE]: boo 1 runs, 0 assertions, 1 failures, 0 errors, 0 skips EOM assert_equal exp, normalize_output(io.string) end def test_report_error r.start r.record error_test r.report exp = clean <<-EOM Run options: # Running: E Finished in 0.00 1) Error: Minitest::Test#woot: RuntimeError: no FILE:LINE:in `error_test' FILE:LINE:in `test_report_error' 1 runs, 0 assertions, 0 failures, 1 errors, 0 skips EOM assert_equal exp, normalize_output(io.string) end def test_report_skipped r.start r.record skip_test restore_env do r.report end exp = clean <<-EOM Run options: # Running: S Finished in 0.00 1 runs, 0 assertions, 0 failures, 0 errors, 1 skips You have skipped tests. Run with --verbose for details. EOM assert_equal exp, normalize_output(io.string) end end PK% ]HB"ee8gems/minitest-5.11.3/test/minitest/test_minitest_test.rbnu[# encoding: UTF-8 require "pathname" require "minitest/metametameta" if defined? Encoding then e = Encoding.default_external if e != Encoding::UTF_8 then warn "" warn "" warn "NOTE: External encoding #{e} is not UTF-8. Tests WILL fail." warn " Run tests with `RUBYOPT=-Eutf-8 rake` to avoid errors." warn "" warn "" end end module MyModule; end class AnError < StandardError; include MyModule; end class ImmutableString < String; def inspect; super.freeze; end; end SomeError = Class.new Exception class Minitest::Runnable def whatever # faked for testing assert true end end class TestMinitestUnit < MetaMetaMetaTestCase parallelize_me! pwd = Pathname.new File.expand_path Dir.pwd basedir = Pathname.new(File.expand_path "lib/minitest") + "mini" basedir = basedir.relative_path_from(pwd).to_s MINITEST_BASE_DIR = basedir[/\A\./] ? basedir : "./#{basedir}" BT_MIDDLE = ["#{MINITEST_BASE_DIR}/test.rb:161:in `each'", "#{MINITEST_BASE_DIR}/test.rb:158:in `each'", "#{MINITEST_BASE_DIR}/test.rb:139:in `run'", "#{MINITEST_BASE_DIR}/test.rb:106:in `run'"] def test_filter_backtrace # this is a semi-lame mix of relative paths. # I cheated by making the autotest parts not have ./ bt = (["lib/autotest.rb:571:in `add_exception'", "test/test_autotest.rb:62:in `test_add_exception'", "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + BT_MIDDLE + ["#{MINITEST_BASE_DIR}/test.rb:29", "test/test_autotest.rb:422"]) bt = util_expand_bt bt ex = ["lib/autotest.rb:571:in `add_exception'", "test/test_autotest.rb:62:in `test_add_exception'"] ex = util_expand_bt ex fu = Minitest.filter_backtrace(bt) assert_equal ex, fu end def test_filter_backtrace_all_unit bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + BT_MIDDLE + ["#{MINITEST_BASE_DIR}/test.rb:29"]) ex = bt.clone fu = Minitest.filter_backtrace(bt) assert_equal ex, fu end def test_filter_backtrace_unit_starts bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] + BT_MIDDLE + ["#{MINITEST_BASE_DIR}/mini/test.rb:29", "-e:1"]) bt = util_expand_bt bt ex = ["-e:1"] fu = Minitest.filter_backtrace bt assert_equal ex, fu end # def test_default_runner_is_minitest_unit # assert_instance_of Minitest::Unit, Minitest::Unit.runner # end def test_infectious_binary_encoding @tu = Class.new FakeNamedTest do def test_this_is_not_ascii_assertion assert_equal "ЁЁЁ", "ёёё" end def test_this_is_non_ascii_failure_message fail 'ЁЁЁ'.force_encoding('ASCII-8BIT') end end expected = clean <<-EOM EF Finished in 0.00 1) Error: FakeNamedTestXX#test_this_is_non_ascii_failure_message: RuntimeError: ЁЁЁ FILE:LINE:in `test_this_is_non_ascii_failure_message' 2) Failure: FakeNamedTestXX#test_this_is_not_ascii_assertion [FILE:LINE]: Expected: \"ЁЁЁ\" Actual: \"ёёё\" 2 runs, 1 assertions, 1 failures, 1 errors, 0 skips EOM assert_report expected end def test_passed_eh_teardown_good test_class = Class.new FakeNamedTest do def teardown; assert true; end def test_omg; assert true; end end test = test_class.new :test_omg test.run refute_predicate test, :error? assert_predicate test, :passed? refute_predicate test, :skipped? end def test_passed_eh_teardown_skipped test_class = Class.new FakeNamedTest do def teardown; assert true; end def test_omg; skip "bork"; end end test = test_class.new :test_omg test.run refute_predicate test, :error? refute_predicate test, :passed? assert_predicate test, :skipped? end def test_passed_eh_teardown_flunked test_class = Class.new FakeNamedTest do def teardown; flunk; end def test_omg; assert true; end end test = test_class.new :test_omg test.run refute_predicate test, :error? refute_predicate test, :passed? refute_predicate test, :skipped? end def util_expand_bt bt if RUBY_VERSION >= "1.9.0" then bt.map { |f| (f =~ /^\./) ? File.expand_path(f) : f } else bt end end end class TestMinitestUnitInherited < MetaMetaMetaTestCase def with_overridden_include Class.class_eval do def inherited_with_hacks _klass throw :inherited_hook end alias inherited_without_hacks inherited alias inherited inherited_with_hacks alias IGNORE_ME! inherited # 1.8 bug. god I love venture bros end yield ensure Class.class_eval do alias inherited inherited_without_hacks undef_method :inherited_with_hacks undef_method :inherited_without_hacks end refute_respond_to Class, :inherited_with_hacks refute_respond_to Class, :inherited_without_hacks end def test_inherited_hook_plays_nice_with_others with_overridden_include do assert_throws :inherited_hook do Class.new FakeNamedTest end end end end class TestMinitestRunner < MetaMetaMetaTestCase # do not parallelize this suite... it just can't handle it. def test_class_runnables @assertion_count = 0 tc = Class.new(Minitest::Test) assert_equal 1, Minitest::Test.runnables.size assert_equal [tc], Minitest::Test.runnables end def test_run_test @tu = Class.new FakeNamedTest do attr_reader :foo def run @foo = "hi mom!" r = super @foo = "okay" r end def test_something assert_equal "hi mom!", foo end end expected = clean <<-EOM . Finished in 0.00 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips EOM assert_report expected end def test_run_error @tu = Class.new FakeNamedTest do def test_something assert true end def test_error raise "unhandled exception" end end expected = clean <<-EOM E. Finished in 0.00 1) Error: FakeNamedTestXX#test_error: RuntimeError: unhandled exception FILE:LINE:in \`test_error\' 2 runs, 1 assertions, 0 failures, 1 errors, 0 skips EOM assert_report expected end def test_run_error_teardown @tu = Class.new FakeNamedTest do def test_something assert true end def teardown raise "unhandled exception" end end expected = clean <<-EOM E Finished in 0.00 1) Error: FakeNamedTestXX#test_something: RuntimeError: unhandled exception FILE:LINE:in \`teardown\' 1 runs, 1 assertions, 0 failures, 1 errors, 0 skips EOM assert_report expected end def test_run_failing setup_basic_tu expected = clean <<-EOM F. Finished in 0.00 1) Failure: FakeNamedTestXX#test_failure [FILE:LINE]: Expected false to be truthy. 2 runs, 2 assertions, 1 failures, 0 errors, 0 skips EOM assert_report expected end def setup_basic_tu @tu = Class.new FakeNamedTest do def test_something assert true end def test_failure assert false end end end def test_run_failing_filtered setup_basic_tu expected = clean <<-EOM . Finished in 0.00 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips EOM assert_report expected, %w[--name /some|thing/ --seed 42] end def assert_filtering filter, name, expected, a = false args = %W[--#{filter} #{name} --seed 42] alpha = Class.new FakeNamedTest do define_method :test_something do assert a end end Object.const_set(:Alpha, alpha) beta = Class.new FakeNamedTest do define_method :test_something do assert true end end Object.const_set(:Beta, beta) @tus = [alpha, beta] assert_report expected, args ensure Object.send :remove_const, :Alpha Object.send :remove_const, :Beta end def test_run_filtered_including_suite_name expected = clean <<-EOM . Finished in 0.00 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips EOM assert_filtering "name", "/Beta#test_something/", expected end def test_run_filtered_including_suite_name_string expected = clean <<-EOM . Finished in 0.00 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips EOM assert_filtering "name", "Beta#test_something", expected end def test_run_filtered_string_method_only expected = clean <<-EOM .. Finished in 0.00 2 runs, 2 assertions, 0 failures, 0 errors, 0 skips EOM assert_filtering "name", "test_something", expected, :pass end def test_run_failing_excluded setup_basic_tu expected = clean <<-EOM . Finished in 0.00 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips EOM assert_report expected, %w[--exclude /failure/ --seed 42] end def test_run_filtered_excluding_suite_name expected = clean <<-EOM . Finished in 0.00 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips EOM assert_filtering "exclude", "/Alpha#test_something/", expected end def test_run_filtered_excluding_suite_name_string expected = clean <<-EOM . Finished in 0.00 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips EOM assert_filtering "exclude", "Alpha#test_something", expected end def test_run_filtered_excluding_string_method_only expected = clean <<-EOM Finished in 0.00 0 runs, 0 assertions, 0 failures, 0 errors, 0 skips EOM assert_filtering "exclude", "test_something", expected, :pass end def test_run_passing @tu = Class.new FakeNamedTest do def test_something assert true end end expected = clean <<-EOM . Finished in 0.00 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips EOM assert_report expected end def test_run_skip @tu = Class.new FakeNamedTest do def test_something assert true end def test_skip skip "not yet" end end expected = clean <<-EOM S. Finished in 0.00 2 runs, 1 assertions, 0 failures, 0 errors, 1 skips You have skipped tests. Run with --verbose for details. EOM restore_env do assert_report expected end end def test_run_skip_verbose @tu = Class.new FakeNamedTest do def test_something assert true end def test_skip skip "not yet" end end expected = clean <<-EOM FakeNamedTestXX#test_skip = 0.00 s = S FakeNamedTestXX#test_something = 0.00 s = . Finished in 0.00 1) Skipped: FakeNamedTestXX#test_skip [FILE:LINE]: not yet 2 runs, 1 assertions, 0 failures, 0 errors, 1 skips EOM assert_report expected, %w[--seed 42 --verbose] end def test_run_with_other_runner @tu = Class.new FakeNamedTest do def self.run reporter, options = {} @reporter = reporter before_my_suite super end def self.name; "wacky!" end def self.before_my_suite @reporter.io.puts "Running #{self.name} tests" @@foo = 1 end def test_something assert_equal 1, @@foo end def test_something_else assert_equal 1, @@foo end end expected = clean <<-EOM Running wacky! tests .. Finished in 0.00 2 runs, 2 assertions, 0 failures, 0 errors, 0 skips EOM assert_report expected end require "monitor" class Latch def initialize count = 1 @count = count @lock = Monitor.new @cv = @lock.new_cond end def release @lock.synchronize do @count -= 1 if @count > 0 @cv.broadcast if @count == 0 end end def await @lock.synchronize { @cv.wait_while { @count > 0 } } end end def test_run_parallel skip "I don't have ParallelEach debugged yet" if maglev? test_count = 2 test_latch = Latch.new test_count wait_latch = Latch.new test_count main_latch = Latch.new thread = Thread.new { Thread.current.abort_on_exception = true # This latch waits until both test latches have been released. Both # latches can't be released unless done in separate threads because # `main_latch` keeps the test method from finishing. test_latch.await main_latch.release } @tu = Class.new FakeNamedTest do parallelize_me! test_count.times do |i| define_method :"test_wait_on_main_thread_#{i}" do test_latch.release # This latch blocks until the "main thread" releases it. The main # thread can't release this latch until both test latches have # been released. This forces the latches to be released in separate # threads. main_latch.await assert true end end end expected = clean <<-EOM .. Finished in 0.00 2 runs, 2 assertions, 0 failures, 0 errors, 0 skips EOM assert_report(expected) do |reporter| reporter.extend(Module.new { define_method("record") do |result| super(result) wait_latch.release end define_method("report") do wait_latch.await super() end }) end assert thread.join end end class TestMinitestUnitOrder < MetaMetaMetaTestCase # do not parallelize this suite... it just can't handle it. def test_before_setup call_order = [] @tu = Class.new FakeNamedTest do define_method :setup do super() call_order << :setup end define_method :before_setup do call_order << :before_setup end def test_omg; assert true; end end run_tu_with_fresh_reporter expected = [:before_setup, :setup] assert_equal expected, call_order end def test_after_teardown call_order = [] @tu = Class.new FakeNamedTest do define_method :teardown do super() call_order << :teardown end define_method :after_teardown do call_order << :after_teardown end def test_omg; assert true; end end run_tu_with_fresh_reporter expected = [:teardown, :after_teardown] assert_equal expected, call_order end def test_all_teardowns_are_guaranteed_to_run call_order = [] @tu = Class.new FakeNamedTest do define_method :after_teardown do super() call_order << :after_teardown raise end define_method :teardown do super() call_order << :teardown raise end define_method :before_teardown do super() call_order << :before_teardown raise end def test_omg; assert true; end end run_tu_with_fresh_reporter expected = [:before_teardown, :teardown, :after_teardown] assert_equal expected, call_order end def test_setup_and_teardown_survive_inheritance call_order = [] @tu = Class.new FakeNamedTest do define_method :setup do call_order << :setup_method end define_method :teardown do call_order << :teardown_method end define_method :test_something do call_order << :test end end run_tu_with_fresh_reporter @tu = Class.new @tu run_tu_with_fresh_reporter # Once for the parent class, once for the child expected = [:setup_method, :test, :teardown_method] * 2 assert_equal expected, call_order end end class TestMinitestRunnable < Minitest::Test def setup_marshal klass tc = klass.new "whatever" tc.assertions = 42 tc.failures << "a failure" yield tc if block_given? def tc.setup @blah = "blah" end tc.setup @tc = Minitest::Result.from tc end def assert_marshal expected_ivars new_tc = Marshal.load Marshal.dump @tc ivars = new_tc.instance_variables.map(&:to_s).sort assert_equal expected_ivars, ivars assert_equal "whatever", new_tc.name assert_equal 42, new_tc.assertions assert_equal ["a failure"], new_tc.failures yield new_tc if block_given? end def test_marshal setup_marshal Minitest::Runnable assert_marshal %w[@NAME @assertions @failures @klass @source_location @time] end def test_spec_marshal klass = describe("whatever") { it("passes") { assert true } } rm = klass.runnable_methods.first # Run the test @tc = klass.new(rm).run assert_kind_of Minitest::Result, @tc # Pass it over the wire over_the_wire = Marshal.load Marshal.dump @tc assert_equal @tc.time, over_the_wire.time assert_equal @tc.name, over_the_wire.name assert_equal @tc.assertions, over_the_wire.assertions assert_equal @tc.failures, over_the_wire.failures assert_equal @tc.klass, over_the_wire.klass end end class TestMinitestTest < TestMinitestRunnable def test_dup setup_marshal Minitest::Test do |tc| tc.time = 3.14 end assert_marshal %w[@NAME @assertions @failures @klass @source_location @time] do |new_tc| assert_in_epsilon 3.14, new_tc.time end end end class TestMinitestUnitTestCase < Minitest::Test # do not call parallelize_me! - teardown accesses @tc._assertions # which is not threadsafe. Nearly every method in here is an # assertion test so it isn't worth splitting it out further. RUBY18 = !defined? Encoding def setup super Minitest::Test.reset @tc = Minitest::Test.new "fake tc" @zomg = "zomg ponies!" @assertion_count = 1 end def teardown assert_equal(@assertion_count, @tc.assertions, "expected #{@assertion_count} assertions to be fired during the test, not #{@tc.assertions}") if @tc.passed? end def non_verbose orig_verbose = $VERBOSE $VERBOSE = false yield ensure $VERBOSE = orig_verbose end def test_assert @assertion_count = 2 @tc.assert_equal true, @tc.assert(true), "returns true on success" end def test_assert__triggered assert_triggered "Expected false to be truthy." do @tc.assert false end end def test_assert__triggered_message assert_triggered @zomg do @tc.assert false, @zomg end end def test_assert_empty @assertion_count = 2 @tc.assert_empty [] end def test_assert_empty_triggered @assertion_count = 2 assert_triggered "Expected [1] to be empty." do @tc.assert_empty [1] end end def test_assert_equal @tc.assert_equal 1, 1 end def test_assert_equal_different_collection_array_hex_invisible object1 = Object.new object2 = Object.new msg = "No visible difference in the Array#inspect output. You should look at the implementation of #== on Array or its members. [#]".gsub(/^ +/, "") assert_triggered msg do @tc.assert_equal [object1], [object2] end end def test_assert_equal_different_collection_hash_hex_invisible h1, h2 = {}, {} h1[1] = Object.new h2[1] = Object.new msg = "No visible difference in the Hash#inspect output. You should look at the implementation of #== on Hash or its members. {1=>#}".gsub(/^ +/, "") assert_triggered msg do @tc.assert_equal h1, h2 end end def test_assert_equal_string_encodings msg = <<-EOM.gsub(/^ {10}/, "") --- expected +++ actual @@ -1 +1,2 @@ +# encoding: ASCII-8BIT "bad-utf8-\\xF1.txt" EOM assert_triggered msg do x = "bad-utf8-\xF1.txt" y = x.dup.force_encoding "binary" # TODO: switch to .b when 1.9 dropped @tc.assert_equal x, y end end unless RUBY18 def test_assert_equal_string_encodings_both_different msg = <<-EOM.gsub(/^ {10}/, "") --- expected +++ actual @@ -1,2 +1,2 @@ -# encoding: US-ASCII +# encoding: ASCII-8BIT "bad-utf8-\\xF1.txt" EOM assert_triggered msg do x = "bad-utf8-\xF1.txt".force_encoding "ASCII" y = x.dup.force_encoding "binary" # TODO: switch to .b when 1.9 dropped @tc.assert_equal x, y end end unless RUBY18 def test_assert_equal_different_diff_deactivated skip "https://github.com/MagLev/maglev/issues/209" if maglev? without_diff do assert_triggered util_msg("haha" * 10, "blah" * 10) do o1 = "haha" * 10 o2 = "blah" * 10 @tc.assert_equal o1, o2 end end end def test_assert_equal_different_hex c = Class.new do def initialize s; @name = s; end end o1 = c.new "a" o2 = c.new "b" msg = "--- expected +++ actual @@ -1 +1 @@ -#<#:0xXXXXXX @name=\"a\"> +#<#:0xXXXXXX @name=\"b\"> ".gsub(/^ +/, "") assert_triggered msg do @tc.assert_equal o1, o2 end end def test_assert_equal_different_hex_invisible o1 = Object.new o2 = Object.new msg = "No visible difference in the Object#inspect output. You should look at the implementation of #== on Object or its members. #".gsub(/^ +/, "") assert_triggered msg do @tc.assert_equal o1, o2 end end def test_assert_equal_different_long msg = "--- expected +++ actual @@ -1 +1 @@ -\"hahahahahahahahahahahahahahahahahahahaha\" +\"blahblahblahblahblahblahblahblahblahblah\" ".gsub(/^ +/, "") assert_triggered msg do o1 = "haha" * 10 o2 = "blah" * 10 @tc.assert_equal o1, o2 end end def test_assert_equal_different_long_invisible msg = "No visible difference in the String#inspect output. You should look at the implementation of #== on String or its members. \"blahblahblahblahblahblahblahblahblahblah\"".gsub(/^ +/, "") assert_triggered msg do o1 = "blah" * 10 o2 = "blah" * 10 def o1.== _ false end @tc.assert_equal o1, o2 end end def test_assert_equal_different_long_msg msg = "message. --- expected +++ actual @@ -1 +1 @@ -\"hahahahahahahahahahahahahahahahahahahaha\" +\"blahblahblahblahblahblahblahblahblahblah\" ".gsub(/^ +/, "") assert_triggered msg do o1 = "haha" * 10 o2 = "blah" * 10 @tc.assert_equal o1, o2, "message" end end def test_assert_equal_different_short assert_triggered util_msg(1, 2) do @tc.assert_equal 1, 2 end end def test_assert_equal_different_short_msg assert_triggered util_msg(1, 2, "message") do @tc.assert_equal 1, 2, "message" end end def test_assert_equal_different_short_multiline msg = "--- expected\n+++ actual\n@@ -1,2 +1,2 @@\n \"a\n-b\"\n+c\"\n" assert_triggered msg do @tc.assert_equal "a\nb", "a\nc" end end def test_assert_equal_does_not_allow_lhs_nil if Minitest::VERSION =~ /^6/ then warn "Time to strip the MT5 test" @assertion_count += 1 assert_triggered(/Use assert_nil if expecting nil/) do @tc.assert_equal nil, nil end else err_re = /Use assert_nil if expecting nil from .*test_minitest_test.rb/ err_re = "" if $-w.nil? assert_output "", err_re do @tc.assert_equal nil, nil end end end def test_assert_equal_does_not_allow_lhs_nil_triggered assert_triggered "Expected: nil\n Actual: false" do @tc.assert_equal nil, false end end def test_assert_in_delta @tc.assert_in_delta 0.0, 1.0 / 1000, 0.1 end def test_delta_consistency @assertion_count = 2 @tc.assert_in_delta 0, 1, 1 assert_triggered "Expected |0 - 1| (1) to not be <= 1." do @tc.refute_in_delta 0, 1, 1 end end def test_assert_in_delta_triggered x = maglev? ? "9.999999xxxe-07" : "1.0e-06" assert_triggered "Expected |0.0 - 0.001| (0.001) to be <= #{x}." do @tc.assert_in_delta 0.0, 1.0 / 1000, 0.000001 end end def test_assert_in_epsilon @assertion_count = 10 @tc.assert_in_epsilon 10_000, 9991 @tc.assert_in_epsilon 9991, 10_000 @tc.assert_in_epsilon 1.0, 1.001 @tc.assert_in_epsilon 1.001, 1.0 @tc.assert_in_epsilon 10_000, 9999.1, 0.0001 @tc.assert_in_epsilon 9999.1, 10_000, 0.0001 @tc.assert_in_epsilon 1.0, 1.0001, 0.0001 @tc.assert_in_epsilon 1.0001, 1.0, 0.0001 @tc.assert_in_epsilon(-1, -1) @tc.assert_in_epsilon(-10_000, -9991) end def test_epsilon_consistency @assertion_count = 2 @tc.assert_in_epsilon 1.0, 1.001 msg = "Expected |1.0 - 1.001| (0.000999xxx) to not be <= 0.001." assert_triggered msg do @tc.refute_in_epsilon 1.0, 1.001 end end def test_assert_in_epsilon_triggered assert_triggered "Expected |10000 - 9990| (10) to be <= 9.99." do @tc.assert_in_epsilon 10_000, 9990 end end def test_assert_in_epsilon_triggered_negative_case x = (RUBY18 and not maglev?) ? "0.1" : "0.100000xxx" y = maglev? ? "0.100000xxx" : "0.1" assert_triggered "Expected |-1.1 - -1| (#{x}) to be <= #{y}." do @tc.assert_in_epsilon(-1.1, -1, 0.1) end end def test_assert_includes @assertion_count = 2 @tc.assert_includes [true], true end def test_assert_includes_triggered @assertion_count = 3 e = @tc.assert_raises Minitest::Assertion do @tc.assert_includes [true], false end expected = "Expected [true] to include false." assert_equal expected, e.message end def test_assert_instance_of @tc.assert_instance_of String, "blah" end def test_assert_instance_of_triggered assert_triggered 'Expected "blah" to be an instance of Array, not String.' do @tc.assert_instance_of Array, "blah" end end def test_assert_kind_of @tc.assert_kind_of String, "blah" end def test_assert_kind_of_triggered assert_triggered 'Expected "blah" to be a kind of Array, not String.' do @tc.assert_kind_of Array, "blah" end end def test_assert_match @assertion_count = 2 @tc.assert_match(/\w+/, "blah blah blah") end def test_assert_match_matcher_object @assertion_count = 2 pattern = Object.new def pattern.=~ _; true end @tc.assert_match pattern, 5 end def test_assert_match_matchee_to_str @assertion_count = 2 obj = Object.new def obj.to_str; "blah" end @tc.assert_match "blah", obj end def test_assert_match_object_triggered @assertion_count = 2 pattern = Object.new def pattern.=~ _; false end def pattern.inspect; "[Object]" end assert_triggered "Expected [Object] to match 5." do @tc.assert_match pattern, 5 end end def test_assert_match_triggered @assertion_count = 2 assert_triggered 'Expected /\d+/ to match "blah blah blah".' do @tc.assert_match(/\d+/, "blah blah blah") end end def test_assert_nil @tc.assert_nil nil end def test_assert_nil_triggered assert_triggered "Expected 42 to be nil." do @tc.assert_nil 42 end end def test_assert_operator @tc.assert_operator 2, :>, 1 end def test_assert_operator_bad_object bad = Object.new def bad.== _; true end @tc.assert_operator bad, :equal?, bad end def test_assert_operator_triggered assert_triggered "Expected 2 to be < 1." do @tc.assert_operator 2, :<, 1 end end def test_assert_output_both @assertion_count = 2 @tc.assert_output "yay", "blah" do print "yay" $stderr.print "blah" end end def test_assert_output_both_regexps @assertion_count = 4 @tc.assert_output(/y.y/, /bl.h/) do print "yay" $stderr.print "blah" end end def test_assert_output_err @tc.assert_output nil, "blah" do $stderr.print "blah" end end def test_assert_output_neither @assertion_count = 0 @tc.assert_output do # do nothing end end def test_assert_output_out @tc.assert_output "blah" do print "blah" end end def test_assert_output_triggered_both assert_triggered util_msg("blah", "blah blah", "In stderr") do @tc.assert_output "yay", "blah" do print "boo" $stderr.print "blah blah" end end end def test_assert_output_triggered_err assert_triggered util_msg("blah", "blah blah", "In stderr") do @tc.assert_output nil, "blah" do $stderr.print "blah blah" end end end def test_assert_output_triggered_out assert_triggered util_msg("blah", "blah blah", "In stdout") do @tc.assert_output "blah" do print "blah blah" end end end def test_assert_predicate @tc.assert_predicate "", :empty? end def test_assert_predicate_triggered assert_triggered 'Expected "blah" to be empty?.' do @tc.assert_predicate "blah", :empty? end end def test_assert_raises @tc.assert_raises RuntimeError do raise "blah" end end def test_assert_raises_default @tc.assert_raises do raise StandardError, "blah" end end def test_assert_raises_default_triggered e = assert_raises Minitest::Assertion do @tc.assert_raises do raise SomeError, "blah" end end expected = clean <<-EOM.chomp [StandardError] exception expected, not Class: Message: <\"blah\"> ---Backtrace--- FILE:LINE:in \`test_assert_raises_default_triggered\' --------------- EOM actual = e.message.gsub(/^.+:\d+/, "FILE:LINE") actual.gsub!(/block \(\d+ levels\) in /, "") if RUBY_VERSION >= "1.9.0" assert_equal expected, actual end def test_assert_raises_module @tc.assert_raises MyModule do raise AnError end end ## # *sigh* This is quite an odd scenario, but it is from real (albeit # ugly) test code in ruby-core: # # http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=29259 def test_assert_raises_skip @assertion_count = 0 assert_triggered "skipped", Minitest::Skip do @tc.assert_raises ArgumentError do begin raise "blah" rescue skip "skipped" end end end end def test_assert_raises_triggered_different e = assert_raises Minitest::Assertion do @tc.assert_raises RuntimeError do raise SyntaxError, "icky" end end expected = clean <<-EOM.chomp [RuntimeError] exception expected, not Class: Message: <\"icky\"> ---Backtrace--- FILE:LINE:in \`test_assert_raises_triggered_different\' --------------- EOM actual = e.message.gsub(/^.+:\d+/, "FILE:LINE") actual.gsub!(/block \(\d+ levels\) in /, "") if RUBY_VERSION >= "1.9.0" assert_equal expected, actual end def test_assert_raises_triggered_different_msg e = assert_raises Minitest::Assertion do @tc.assert_raises RuntimeError, "XXX" do raise SyntaxError, "icky" end end expected = clean <<-EOM XXX. [RuntimeError] exception expected, not Class: Message: <\"icky\"> ---Backtrace--- FILE:LINE:in \`test_assert_raises_triggered_different_msg\' --------------- EOM actual = e.message.gsub(/^.+:\d+/, "FILE:LINE") actual.gsub!(/block \(\d+ levels\) in /, "") if RUBY_VERSION >= "1.9.0" assert_equal expected.chomp, actual end def test_assert_raises_triggered_none e = assert_raises Minitest::Assertion do @tc.assert_raises Minitest::Assertion do # do nothing end end expected = "Minitest::Assertion expected but nothing was raised." assert_equal expected, e.message end def test_assert_raises_triggered_none_msg e = assert_raises Minitest::Assertion do @tc.assert_raises Minitest::Assertion, "XXX" do # do nothing end end expected = "XXX.\nMinitest::Assertion expected but nothing was raised." assert_equal expected, e.message end def test_assert_raises_subclass @tc.assert_raises StandardError do raise AnError end end def test_assert_raises_subclass_triggered e = assert_raises Minitest::Assertion do @tc.assert_raises SomeError do raise AnError, "some message" end end expected = clean <<-EOM [SomeError] exception expected, not Class: Message: <\"some message\"> ---Backtrace--- FILE:LINE:in \`test_assert_raises_subclass_triggered\' --------------- EOM actual = e.message.gsub(/^.+:\d+/, "FILE:LINE") actual.gsub!(/block \(\d+ levels\) in /, "") if RUBY_VERSION >= "1.9.0" assert_equal expected.chomp, actual end def test_assert_raises_exit @tc.assert_raises SystemExit do exit 1 end end def test_assert_raises_signals @tc.assert_raises SignalException do raise SignalException, :INT end end def test_assert_respond_to @tc.assert_respond_to "blah", :empty? end def test_assert_respond_to_triggered assert_triggered 'Expected "blah" (String) to respond to #rawr!.' do @tc.assert_respond_to "blah", :rawr! end end def test_assert_same @assertion_count = 3 o = "blah" @tc.assert_same 1, 1 @tc.assert_same :blah, :blah @tc.assert_same o, o end def test_assert_same_triggered @assertion_count = 2 assert_triggered "Expected 2 (oid=N) to be the same as 1 (oid=N)." do @tc.assert_same 1, 2 end s1 = "blah" s2 = "blah" assert_triggered 'Expected "blah" (oid=N) to be the same as "blah" (oid=N).' do @tc.assert_same s1, s2 end end def assert_deprecated name dep = /DEPRECATED: #{name}. From #{__FILE__}:\d+(?::.*)?/ dep = "" if $-w.nil? assert_output nil, dep do yield end end def test_assert_send assert_deprecated :assert_send do @tc.assert_send [1, :<, 2] end end def test_assert_send_bad assert_deprecated :assert_send do assert_triggered "Expected 1.>(*[2]) to return true." do @tc.assert_send [1, :>, 2] end end end def test_assert_silent @assertion_count = 2 @tc.assert_silent do # do nothing end end def test_assert_silent_triggered_err assert_triggered util_msg("", "blah blah", "In stderr") do @tc.assert_silent do $stderr.print "blah blah" end end end def test_assert_silent_triggered_out @assertion_count = 2 assert_triggered util_msg("", "blah blah", "In stdout") do @tc.assert_silent do print "blah blah" end end end def test_assert_throws @tc.assert_throws :blah do throw :blah end end def test_assert_throws_name_error @tc.assert_raises NameError do @tc.assert_throws :blah do raise NameError end end end def test_assert_throws_argument_exception @tc.assert_raises ArgumentError do @tc.assert_throws :blah do raise ArgumentError end end end def test_assert_throws_different assert_triggered "Expected :blah to have been thrown, not :not_blah." do @tc.assert_throws :blah do throw :not_blah end end end def test_assert_throws_unthrown assert_triggered "Expected :blah to have been thrown." do @tc.assert_throws :blah do # do nothing end end end def test_capture_io @assertion_count = 0 non_verbose do out, err = capture_io do puts "hi" $stderr.puts "bye!" end assert_equal "hi\n", out assert_equal "bye!\n", err end end def test_capture_subprocess_io @assertion_count = 0 non_verbose do out, err = capture_subprocess_io do system("echo hi") system("echo bye! 1>&2") end assert_equal "hi\n", out assert_equal "bye!", err.strip end end def test_class_asserts_match_refutes @assertion_count = 0 methods = Minitest::Assertions.public_instance_methods methods.map!(&:to_s) if Symbol === methods.first # These don't have corresponding refutes _on purpose_. They're # useless and will never be added, so don't bother. ignores = %w[assert_output assert_raises assert_send assert_silent assert_throws assert_mock] # These are test/unit methods. I'm not actually sure why they're still here ignores += %w[assert_no_match assert_not_equal assert_not_nil assert_not_same assert_nothing_raised assert_nothing_thrown assert_raise] asserts = methods.grep(/^assert/).sort - ignores refutes = methods.grep(/^refute/).sort - ignores assert_empty refutes.map { |n| n.sub(/^refute/, "assert") } - asserts assert_empty asserts.map { |n| n.sub(/^assert/, "refute") } - refutes end def test_flunk assert_triggered "Epic Fail!" do @tc.flunk end end def test_flunk_message assert_triggered @zomg do @tc.flunk @zomg end end def test_message @assertion_count = 0 assert_equal "blah2.", @tc.message { "blah2" }.call assert_equal "blah2.", @tc.message("") { "blah2" }.call assert_equal "blah1.\nblah2.", @tc.message(:blah1) { "blah2" }.call assert_equal "blah1.\nblah2.", @tc.message("blah1") { "blah2" }.call message = proc { "blah1" } assert_equal "blah1.\nblah2.", @tc.message(message) { "blah2" }.call message = @tc.message { "blah1" } assert_equal "blah1.\nblah2.", @tc.message(message) { "blah2" }.call end def test_message_message assert_triggered "whoops.\nExpected: 1\n Actual: 2" do @tc.assert_equal 1, 2, message { "whoops" } end end def test_message_lambda assert_triggered "whoops.\nExpected: 1\n Actual: 2" do @tc.assert_equal 1, 2, lambda { "whoops" } end end def test_message_deferred @assertion_count, var = 0, nil msg = message { var = "blah" } assert_nil var msg.call assert_equal "blah", var end def test_pass @tc.pass end def test_prints printer = Class.new { extend Minitest::Assertions } @tc.assert_equal '"test"', printer.mu_pp(ImmutableString.new "test") end def test_refute @assertion_count = 2 @tc.assert_equal false, @tc.refute(false), "returns false on success" end def test_refute_empty @assertion_count = 2 @tc.refute_empty [1] end def test_refute_empty_triggered @assertion_count = 2 assert_triggered "Expected [] to not be empty." do @tc.refute_empty [] end end def test_refute_equal @tc.refute_equal "blah", "yay" end def test_refute_equal_triggered assert_triggered 'Expected "blah" to not be equal to "blah".' do @tc.refute_equal "blah", "blah" end end def test_refute_in_delta @tc.refute_in_delta 0.0, 1.0 / 1000, 0.000001 end def test_refute_in_delta_triggered x = maglev? ? "0.100000xxx" : "0.1" assert_triggered "Expected |0.0 - 0.001| (0.001) to not be <= #{x}." do @tc.refute_in_delta 0.0, 1.0 / 1000, 0.1 end end def test_refute_in_epsilon @tc.refute_in_epsilon 10_000, 9990-1 end def test_refute_in_epsilon_triggered assert_triggered "Expected |10000 - 9990| (10) to not be <= 10.0." do @tc.refute_in_epsilon 10_000, 9990 flunk end end def test_refute_includes @assertion_count = 2 @tc.refute_includes [true], false end def test_refute_includes_triggered @assertion_count = 3 e = @tc.assert_raises Minitest::Assertion do @tc.refute_includes [true], true end expected = "Expected [true] to not include true." assert_equal expected, e.message end def test_refute_instance_of @tc.refute_instance_of Array, "blah" end def test_refute_instance_of_triggered assert_triggered 'Expected "blah" to not be an instance of String.' do @tc.refute_instance_of String, "blah" end end def test_refute_kind_of @tc.refute_kind_of Array, "blah" end def test_refute_kind_of_triggered assert_triggered 'Expected "blah" to not be a kind of String.' do @tc.refute_kind_of String, "blah" end end def test_refute_match @assertion_count = 2 @tc.refute_match(/\d+/, "blah blah blah") end def test_refute_match_matcher_object @assertion_count = 2 @tc.refute_match Object.new, 5 # default #=~ returns false end def test_refute_match_object_triggered @assertion_count = 2 pattern = Object.new def pattern.=~ _; true end def pattern.inspect; "[Object]" end assert_triggered "Expected [Object] to not match 5." do @tc.refute_match pattern, 5 end end def test_refute_match_triggered @assertion_count = 2 assert_triggered 'Expected /\w+/ to not match "blah blah blah".' do @tc.refute_match(/\w+/, "blah blah blah") end end def test_refute_nil @tc.refute_nil 42 end def test_refute_nil_triggered assert_triggered "Expected nil to not be nil." do @tc.refute_nil nil end end def test_refute_predicate @tc.refute_predicate "42", :empty? end def test_refute_predicate_triggered assert_triggered 'Expected "" to not be empty?.' do @tc.refute_predicate "", :empty? end end def test_refute_operator @tc.refute_operator 2, :<, 1 end def test_refute_operator_bad_object bad = Object.new def bad.== _; true end @tc.refute_operator true, :equal?, bad end def test_refute_operator_triggered assert_triggered "Expected 2 to not be > 1." do @tc.refute_operator 2, :>, 1 end end def test_refute_respond_to @tc.refute_respond_to "blah", :rawr! end def test_refute_respond_to_triggered assert_triggered 'Expected "blah" to not respond to empty?.' do @tc.refute_respond_to "blah", :empty? end end def test_refute_same @tc.refute_same 1, 2 end def test_refute_same_triggered assert_triggered "Expected 1 (oid=N) to not be the same as 1 (oid=N)." do @tc.refute_same 1, 1 end end def test_skip @assertion_count = 0 assert_triggered "haha!", Minitest::Skip do @tc.skip "haha!" end end def test_runnable_methods_random @assertion_count = 0 sample_test_case = Class.new FakeNamedTest do def self.test_order; :random; end def test_test1; assert "does not matter" end def test_test2; assert "does not matter" end def test_test3; assert "does not matter" end end srand 42 expected = case when maglev? then %w[test_test2 test_test3 test_test1] else %w[test_test2 test_test1 test_test3] end assert_equal expected, sample_test_case.runnable_methods end def test_runnable_methods_sorted @assertion_count = 0 sample_test_case = Class.new FakeNamedTest do def self.test_order; :sorted end def test_test3; assert "does not matter" end def test_test2; assert "does not matter" end def test_test1; assert "does not matter" end end expected = %w[test_test1 test_test2 test_test3] assert_equal expected, sample_test_case.runnable_methods end def test_i_suck_and_my_tests_are_order_dependent_bang_sets_test_order_alpha @assertion_count = 0 shitty_test_case = Class.new FakeNamedTest shitty_test_case.i_suck_and_my_tests_are_order_dependent! assert_equal :alpha, shitty_test_case.test_order end def test_i_suck_and_my_tests_are_order_dependent_bang_does_not_warn @assertion_count = 0 shitty_test_case = Class.new FakeNamedTest def shitty_test_case.test_order; :lol end assert_silent do shitty_test_case.i_suck_and_my_tests_are_order_dependent! end end def assert_triggered expected, klass = Minitest::Assertion e = assert_raises klass do yield end msg = e.message.sub(/(---Backtrace---).*/m, '\1') msg.gsub!(/\(oid=[-0-9]+\)/, "(oid=N)") msg.gsub!(/(\d\.\d{6})\d+/, '\1xxx') # normalize: ruby version, impl, platform assert_msg = Regexp === expected ? :assert_match : :assert_equal self.send assert_msg, expected, msg end def util_msg exp, act, msg = nil s = "Expected: #{exp.inspect}\n Actual: #{act.inspect}" s = "#{msg}.\n#{s}" if msg s end def without_diff old_diff = Minitest::Assertions.diff Minitest::Assertions.diff = nil yield ensure Minitest::Assertions.diff = old_diff end end class TestMinitestGuard < Minitest::Test parallelize_me! def test_mri_eh assert self.class.mri? "ruby blah" assert self.mri? "ruby blah" end def test_jruby_eh assert self.class.jruby? "java" assert self.jruby? "java" end def test_rubinius_eh assert self.class.rubinius? "rbx" assert self.rubinius? "rbx" end def test_windows_eh assert self.class.windows? "mswin" assert self.windows? "mswin" end end class TestMinitestUnitRecording < MetaMetaMetaTestCase # do not parallelize this suite... it just can't handle it. def assert_run_record *expected, &block @tu = Class.new FakeNamedTest, &block run_tu_with_fresh_reporter recorded = first_reporter.results.map(&:failures).flatten.map { |f| f.error.class } assert_equal expected, recorded end def test_run_with_bogus_reporter # https://github.com/seattlerb/minitest/issues/659 # TODO: remove test for minitest 6 @tu = Class.new FakeNamedTest do def test_method assert true end end bogus_reporter = Class.new do # doesn't subclass AbstractReporter def start; @success = false; end # def prerecord klass, name; end # doesn't define full API def record result; @success = true; end def report; end def passed?; end def results; end def success?; @success; end end.new self.reporter = Minitest::CompositeReporter.new reporter << bogus_reporter Minitest::Runnable.runnables.delete @tu @tu.run reporter, {} assert_predicate bogus_reporter, :success? end def test_record_passing assert_run_record do def test_method assert true end end end def test_record_failing assert_run_record Minitest::Assertion do def test_method assert false end end end def test_record_error assert_run_record RuntimeError do def test_method raise "unhandled exception" end end end def test_record_error_teardown assert_run_record RuntimeError do def test_method assert true end def teardown raise "unhandled exception" end end end def test_record_error_in_test_and_teardown assert_run_record AnError, RuntimeError do def test_method raise AnError end def teardown raise "unhandled exception" end end end def test_to_s_error_in_test_and_teardown @tu = Class.new FakeNamedTest do def test_method raise AnError end def teardown raise "unhandled exception" end end run_tu_with_fresh_reporter exp = clean " Error: FakeNamedTestXX#test_method: AnError: AnError FILE:LINE:in `test_method' Error: FakeNamedTestXX#test_method: RuntimeError: unhandled exception FILE:LINE:in `teardown' " assert_equal exp.strip, normalize_output(first_reporter.results.first.to_s).strip end def test_record_skip assert_run_record Minitest::Skip do def test_method skip "not yet" end end end end PK% ]B1YJYJ8gems/minitest-5.11.3/test/minitest/test_minitest_mock.rbnu[require "minitest/autorun" class TestMinitestMock < Minitest::Test parallelize_me! def setup @mock = Minitest::Mock.new.expect(:foo, nil) @mock.expect(:meaning_of_life, 42) end def test_create_stub_method assert_nil @mock.foo end def test_allow_return_value_specification assert_equal 42, @mock.meaning_of_life end def test_blow_up_if_not_called @mock.foo util_verify_bad "expected meaning_of_life() => 42" end def test_not_blow_up_if_everything_called @mock.foo @mock.meaning_of_life assert_mock @mock end def test_allow_expectations_to_be_added_after_creation @mock.expect(:bar, true) assert @mock.bar end def test_not_verify_if_new_expected_method_is_not_called @mock.foo @mock.meaning_of_life @mock.expect(:bar, true) util_verify_bad "expected bar() => true" end def test_blow_up_on_wrong_number_of_arguments @mock.foo @mock.meaning_of_life @mock.expect(:sum, 3, [1, 2]) e = assert_raises ArgumentError do @mock.sum end assert_equal "mocked method :sum expects 2 arguments, got 0", e.message end def test_return_mock_does_not_raise retval = Minitest::Mock.new mock = Minitest::Mock.new mock.expect(:foo, retval) mock.foo assert_mock mock end def test_mock_args_does_not_raise skip "non-opaque use of ==" if maglev? arg = Minitest::Mock.new mock = Minitest::Mock.new mock.expect(:foo, nil, [arg]) mock.foo(arg) assert_mock mock end def test_set_expectation_on_special_methods mock = Minitest::Mock.new mock.expect :object_id, "received object_id" assert_equal "received object_id", mock.object_id mock.expect :respond_to_missing?, "received respond_to_missing?" assert_equal "received respond_to_missing?", mock.respond_to_missing? mock.expect :===, "received ===" assert_equal "received ===", mock.=== mock.expect :inspect, "received inspect" assert_equal "received inspect", mock.inspect mock.expect :to_s, "received to_s" assert_equal "received to_s", mock.to_s mock.expect :public_send, "received public_send" assert_equal "received public_send", mock.public_send mock.expect :send, "received send" assert_equal "received send", mock.send assert_mock mock end def test_expectations_can_be_satisfied_via_send @mock.send :foo @mock.send :meaning_of_life assert_mock @mock end def test_expectations_can_be_satisfied_via_public_send skip "Doesn't run on 1.8" if RUBY_VERSION < "1.9" @mock.public_send :foo @mock.public_send :meaning_of_life assert_mock @mock end def test_blow_up_on_wrong_arguments @mock.foo @mock.meaning_of_life @mock.expect(:sum, 3, [1, 2]) e = assert_raises MockExpectationError do @mock.sum(2, 4) end exp = "mocked method :sum called with unexpected arguments [2, 4]" assert_equal exp, e.message end def test_expect_with_non_array_args e = assert_raises ArgumentError do @mock.expect :blah, 3, false end assert_equal "args must be an array", e.message end def test_respond_appropriately assert @mock.respond_to?(:foo) assert @mock.respond_to?(:foo, true) assert @mock.respond_to?("foo") assert !@mock.respond_to?(:bar) end def test_no_method_error_on_unexpected_methods e = assert_raises NoMethodError do @mock.bar end expected = "unmocked method :bar, expected one of [:foo, :meaning_of_life]" assert_equal expected, e.message end def test_assign_per_mock_return_values a = Minitest::Mock.new b = Minitest::Mock.new a.expect(:foo, :a) b.expect(:foo, :b) assert_equal :a, a.foo assert_equal :b, b.foo end def test_do_not_create_stub_method_on_new_mocks a = Minitest::Mock.new a.expect(:foo, :a) assert !Minitest::Mock.new.respond_to?(:foo) end def test_mock_is_a_blank_slate @mock.expect :kind_of?, true, [String] @mock.expect :==, true, [1] assert @mock.kind_of?(String), "didn't mock :kind_of\?" assert @mock == 1, "didn't mock :==" end def test_verify_allows_called_args_to_be_loosely_specified mock = Minitest::Mock.new mock.expect :loose_expectation, true, [Integer] mock.loose_expectation 1 assert_mock mock end def test_verify_raises_with_strict_args mock = Minitest::Mock.new mock.expect :strict_expectation, true, [2] e = assert_raises MockExpectationError do mock.strict_expectation 1 end exp = "mocked method :strict_expectation called with unexpected arguments [1]" assert_equal exp, e.message end def test_method_missing_empty mock = Minitest::Mock.new mock.expect :a, nil mock.a e = assert_raises MockExpectationError do mock.a end assert_equal "No more expects available for :a: []", e.message end def test_same_method_expects_are_verified_when_all_called mock = Minitest::Mock.new mock.expect :foo, nil, [:bar] mock.expect :foo, nil, [:baz] mock.foo :bar mock.foo :baz assert_mock mock end def test_same_method_expects_blow_up_when_not_all_called mock = Minitest::Mock.new mock.expect :foo, nil, [:bar] mock.expect :foo, nil, [:baz] mock.foo :bar e = assert_raises(MockExpectationError) { mock.verify } exp = "expected foo(:baz) => nil, got [foo(:bar) => nil]" assert_equal exp, e.message end def test_same_method_expects_with_same_args_blow_up_when_not_all_called mock = Minitest::Mock.new mock.expect :foo, nil, [:bar] mock.expect :foo, nil, [:bar] mock.foo :bar e = assert_raises(MockExpectationError) { mock.verify } exp = "expected foo(:bar) => nil, got [foo(:bar) => nil]" assert_equal exp, e.message end def test_verify_passes_when_mock_block_returns_true mock = Minitest::Mock.new mock.expect :foo, nil do true end mock.foo assert_mock mock end def test_mock_block_is_passed_function_params arg1, arg2, arg3 = :bar, [1, 2, 3], { :a => "a" } mock = Minitest::Mock.new mock.expect :foo, nil do |a1, a2, a3| a1 == arg1 && a2 == arg2 && a3 == arg3 end mock.foo arg1, arg2, arg3 assert_mock mock end def test_mock_block_is_passed_function_block mock = Minitest::Mock.new block = proc { "bar" } mock.expect :foo, nil do |arg, &blk| arg == "foo" && blk == block end mock.foo "foo", &block assert_mock mock end def test_verify_fails_when_mock_block_returns_false mock = Minitest::Mock.new mock.expect :foo, nil do false end e = assert_raises(MockExpectationError) { mock.foo } exp = "mocked method :foo failed block w/ []" assert_equal exp, e.message end def test_mock_block_throws_if_args_passed mock = Minitest::Mock.new e = assert_raises(ArgumentError) do mock.expect :foo, nil, [:a, :b, :c] do true end end exp = "args ignored when block given" assert_equal exp, e.message end def test_mock_returns_retval_when_called_with_block mock = Minitest::Mock.new mock.expect(:foo, 32) do true end rs = mock.foo assert_equal rs, 32 end def util_verify_bad exp e = assert_raises MockExpectationError do @mock.verify end assert_equal exp, e.message end def test_mock_called_via_send mock = Minitest::Mock.new mock.expect(:foo, true) mock.send :foo assert_mock mock end def test_mock_called_via___send__ mock = Minitest::Mock.new mock.expect(:foo, true) mock.__send__ :foo assert_mock mock end def test_mock_called_via_send_with_args mock = Minitest::Mock.new mock.expect(:foo, true, [1, 2, 3]) mock.send(:foo, 1, 2, 3) assert_mock mock end end require "minitest/metametameta" class TestMinitestStub < Minitest::Test parallelize_me! def setup super Minitest::Test.reset @tc = Minitest::Test.new "fake tc" @assertion_count = 1 end def teardown super assert_equal @assertion_count, @tc.assertions end class Time def self.now 24 end end def assert_stub val_or_callable @assertion_count += 1 t = Time.now.to_i Time.stub :now, val_or_callable do @tc.assert_equal 42, Time.now end @tc.assert_operator Time.now.to_i, :>=, t end def test_stub_private_module_method @assertion_count += 1 t0 = Time.now self.stub :sleep, nil do @tc.assert_nil sleep(10) end @tc.assert_operator Time.now - t0, :<=, 1 end def test_stub_private_module_method_indirect @assertion_count += 1 fail_clapper = Class.new do def fail_clap raise :clap end end.new fail_clapper.stub :raise, nil do |safe_clapper| @tc.assert_equal :clap, safe_clapper.fail_clap # either form works @tc.assert_equal :clap, fail_clapper.fail_clap # yay closures end end def test_stub_public_module_method Math.stub :log10, :stubbed do @tc.assert_equal :stubbed, Math.log10(1000) end end def test_stub_value assert_stub 42 end def test_stub_block assert_stub lambda { 42 } end def test_stub_block_args @assertion_count += 1 t = Time.now.to_i Time.stub :now, lambda { |n| n * 2 } do @tc.assert_equal 42, Time.now(21) end @tc.assert_operator Time.now.to_i, :>=, t end def test_stub_callable obj = Object.new def obj.call 42 end assert_stub obj end def test_stub_yield_self obj = "foo" val = obj.stub :to_s, "bar" do |s| s.to_s end @tc.assert_equal "bar", val end def test_dynamic_method @assertion_count = 2 dynamic = Class.new do def self.respond_to? meth meth == :found end def self.method_missing meth, *args, &block if meth == :found false else super end end end val = dynamic.stub(:found, true) do |s| s.found end @tc.assert_equal true, val @tc.assert_equal false, dynamic.found end def test_stub_NameError e = @tc.assert_raises NameError do Time.stub :nope_nope_nope, 42 do # do nothing end end exp = /undefined method `nope_nope_nope' for( class)? `#{self.class}::Time'/ assert_match exp, e.message end def test_mock_with_yield mock = Minitest::Mock.new mock.expect(:write, true) do true end rs = nil File.stub :open, true, mock do File.open "foo.txt", "r" do |f| rs = f.write end end @tc.assert_equal true, rs end alias test_stub_value__old test_stub_value # TODO: remove/rename ## Permutation Sets: # [:value, :lambda] # [:*, :block, :block_call] # [:**, :block_args] # # Where: # # :value = a normal value # :lambda = callable or lambda # :* = no block # :block = normal block # :block_call = :lambda invokes the block (N/A for :value) # :** = no args # :args = args passed to stub ## Permutations # [:call, :*, :**] =>5 callable+block FIX: CALL BOTH (bug) # [:call, :*, :**] =>6 callable # [:lambda, :*, :**] => lambda result # [:lambda, :*, :args] => lambda result NO ARGS # [:lambda, :block, :**] =>5 lambda result FIX: CALL BOTH (bug) # [:lambda, :block, :**] =>6 lambda result # [:lambda, :block, :args] =>5 lambda result FIX: CALL BOTH (bug) # [:lambda, :block, :args] =>6 lambda result # [:lambda, :block, :args] =>7 raise ArgumentError # [:lambda, :block_call, :**] =>5 lambda FIX: BUG!-not passed block to lambda # [:lambda, :block_call, :**] =>6 lambda+block result # [:lambda, :block_call, :args] =>5 lambda FIX: BUG!-not passed block to lambda # [:lambda, :block_call, :args] =>6 lambda+block result # [:value, :*, :**] => value # [:value, :*, :args] => value, ignore args # [:value, :block, :**] =>5 value, call block # [:value, :block, :**] =>6 value # [:value, :block, :args] =>5 value, call block w/ args # [:value, :block, :args] =>6 value, call block w/ args, deprecated # [:value, :block, :args] =>7 raise ArgumentError # [:value, :block_call, :**] => N/A # [:value, :block_call, :args] => N/A class Bar def call puts "hi" end end class Foo def self.blocking yield end end class Thingy def self.identity arg arg end end def test_stub_callable_block_5 # from tenderlove @assertion_count += 1 Foo.stub5 :blocking, Bar.new do @tc.assert_output "hi\n", "" do Foo.blocking do @tc.flunk "shouldn't ever hit this" end end end end def test_stub_callable_block_6 # from tenderlove skip_stub6 @assertion_count += 1 Foo.stub6 :blocking, Bar.new do @tc.assert_output "hi\n", "" do Foo.blocking do @tc.flunk "shouldn't ever hit this" end end end end def test_stub_lambda Thread.stub :new, lambda { 21+21 } do @tc.assert_equal 42, Thread.new end end def test_stub_lambda_args Thread.stub :new, lambda { 21+21 }, :wtf do @tc.assert_equal 42, Thread.new end end def test_stub_lambda_block_5 Thread.stub5 :new, lambda { 21+21 } do result = Thread.new do @tc.flunk "shouldn't ever hit this" end @tc.assert_equal 42, result end end def test_stub_lambda_block_6 skip_stub6 Thread.stub6 :new, lambda { 21+21 } do result = Thread.new do @tc.flunk "shouldn't ever hit this" end @tc.assert_equal 42, result end end def test_stub_lambda_block_args_5 @assertion_count += 1 Thingy.stub5 :identity, lambda { |y| @tc.assert_equal :nope, y; 21+21 }, :WTF? do result = Thingy.identity :nope do |x| @tc.flunk "shouldn't reach this" end @tc.assert_equal 42, result end end def test_stub_lambda_block_args_6 skip_stub6 @assertion_count += 1 Thingy.stub6 :identity, lambda { |y| @tc.assert_equal :nope, y; 21+21 }, :WTF? do result = Thingy.identity :nope do |x| @tc.flunk "shouldn't reach this" end @tc.assert_equal 42, result end end def test_stub_lambda_block_args_6_2 skip_stub6 @tc.assert_raises ArgumentError do Thingy.stub6_2 :identity, lambda { |y| :__not_run__ }, :WTF? do # doesn't matter end end end def test_stub_lambda_block_call_5 @assertion_count += 1 rs = nil io = StringIO.new "", "w" File.stub5 :open, lambda { |p, m, &blk| blk and blk.call io } do File.open "foo.txt", "r" do |f| rs = f && f.write("woot") end end @tc.assert_equal 4, rs @tc.assert_equal "woot", io.string end def test_stub_lambda_block_call_6 skip_stub6 @assertion_count += 1 rs = nil io = StringIO.new "", "w" File.stub6 :open, lambda { |p, m, &blk| blk.call io } do File.open "foo.txt", "r" do |f| rs = f.write("woot") end end @tc.assert_equal 4, rs @tc.assert_equal "woot", io.string end def test_stub_lambda_block_call_args_5 @assertion_count += 1 rs = nil io = StringIO.new "", "w" File.stub5(:open, lambda { |p, m, &blk| blk and blk.call io }, :WTF?) do File.open "foo.txt", "r" do |f| rs = f.write("woot") end end @tc.assert_equal 4, rs @tc.assert_equal "woot", io.string end def test_stub_lambda_block_call_args_6 skip_stub6 @assertion_count += 1 rs = nil io = StringIO.new "", "w" File.stub6(:open, lambda { |p, m, &blk| blk.call io }, :WTF?) do File.open "foo.txt", "r" do |f| rs = f.write("woot") end end @tc.assert_equal 4, rs @tc.assert_equal "woot", io.string end def test_stub_lambda_block_call_args_6_2 skip_stub6 @assertion_count += 2 rs = nil io = StringIO.new "", "w" @tc.assert_raises ArgumentError do File.stub6_2(:open, lambda { |p, m, &blk| blk.call io }, :WTF?) do File.open "foo.txt", "r" do |f| rs = f.write("woot") end end end @tc.assert_nil rs @tc.assert_equal "", io.string end def test_stub_value Thread.stub :new, 42 do result = Thread.new @tc.assert_equal 42, result end end def test_stub_value_args Thread.stub :new, 42, :WTF? do result = Thread.new @tc.assert_equal 42, result end end def test_stub_value_block_5 @assertion_count += 1 Thread.stub5 :new, 42 do result = Thread.new do @tc.assert true end @tc.assert_equal 42, result end end def test_stub_value_block_6 skip_stub6 Thread.stub6 :new, 42 do result = Thread.new do @tc.flunk "shouldn't hit this" end @tc.assert_equal 42, result end end def test_stub_value_block_args_5 @assertion_count += 2 rs = nil io = StringIO.new "", "w" File.stub5 :open, :value, io do result = File.open "foo.txt", "r" do |f| rs = f.write("woot") end @tc.assert_equal :value, result end @tc.assert_equal 4, rs @tc.assert_equal "woot", io.string end def test_stub_value_block_args_5__break_if_not_passed e = @tc.assert_raises NoMethodError do File.stub5 :open, :return_value do # intentionally bad setup w/ no args File.open "foo.txt", "r" do |f| f.write "woot" end end end exp = "undefined method `write' for nil:NilClass" assert_equal exp, e.message end def test_stub_value_block_args_6 skip_stub6 @assertion_count += 2 rs = nil io = StringIO.new "", "w" assert_deprecated do File.stub6 :open, :value, io do result = File.open "foo.txt", "r" do |f| rs = f.write("woot") end @tc.assert_equal :value, result end end @tc.assert_equal 4, rs @tc.assert_equal "woot", io.string end def test_stub_value_block_args_6_2 skip_stub6 @assertion_count += 2 rs = nil io = StringIO.new "", "w" @tc.assert_raises ArgumentError do File.stub6_2 :open, :value, io do result = File.open "foo.txt", "r" do |f| @tc.flunk "shouldn't hit this" end @tc.assert_equal :value, result end end @tc.assert_nil rs @tc.assert_equal "", io.string end def assert_deprecated re = /deprecated/ assert_output "", re do yield end end def skip_stub6 skip "not yet" unless STUB6 end end STUB6 = ENV["STUB6"] if STUB6 then require "minitest/mock6" if STUB6 else class Object alias stub5 stub alias stub6 stub end end PK% ]xc2gems/minitest-5.11.3/test/minitest/metametameta.rbnu[require "tempfile" require "stringio" require "minitest/autorun" class Minitest::Test def clean s s.gsub(/^ {6}/, "") end end class FakeNamedTest < Minitest::Test @@count = 0 def self.name @fake_name ||= begin @@count += 1 "FakeNamedTest%02d" % @@count end end end class MetaMetaMetaTestCase < Minitest::Test attr_accessor :reporter, :output, :tu def run_tu_with_fresh_reporter flags = %w[--seed 42] options = Minitest.process_args flags @output = StringIO.new("".encode('UTF-8')) self.reporter = Minitest::CompositeReporter.new reporter << Minitest::SummaryReporter.new(@output, options) reporter << Minitest::ProgressReporter.new(@output, options) reporter.start yield(reporter) if block_given? @tus ||= [@tu] @tus.each do |tu| Minitest::Runnable.runnables.delete tu tu.run reporter, options end reporter.report end def first_reporter reporter.reporters.first end def assert_report expected, flags = %w[--seed 42], &block header = clean <<-EOM Run options: #{flags.map { |s| s =~ /\|/ ? s.inspect : s }.join " "} # Running: EOM run_tu_with_fresh_reporter flags, &block output = normalize_output @output.string.dup assert_equal header + expected, output end def normalize_output output output.sub!(/Finished in .*/, "Finished in 0.00") output.sub!(/Loaded suite .*/, "Loaded suite blah") output.gsub!(/FakeNamedTest\d+/, "FakeNamedTestXX") output.gsub!(/ = \d+.\d\d s = /, " = 0.00 s = ") output.gsub!(/0x[A-Fa-f0-9]+/, "0xXXX") output.gsub!(/ +$/, "") if windows? then output.gsub!(/\[(?:[A-Za-z]:)?[^\]:]+:\d+\]/, "[FILE:LINE]") output.gsub!(/^(\s+)(?:[A-Za-z]:)?[^:]+:\d+:in/, '\1FILE:LINE:in') else output.gsub!(/\[[^\]:]+:\d+\]/, "[FILE:LINE]") output.gsub!(/^(\s+)[^:]+:\d+:in/, '\1FILE:LINE:in') end output end def restore_env old_value = ENV["MT_NO_SKIP_MSG"] ENV.delete "MT_NO_SKIP_MSG" yield ensure ENV["MT_NO_SKIP_MSG"] = old_value end def setup super srand 42 Minitest::Test.reset @tu = nil end end PK% ] dd8gems/minitest-5.11.3/test/minitest/test_minitest_spec.rbnu[# encoding: utf-8 require "minitest/autorun" require "stringio" class MiniSpecA < Minitest::Spec; end class MiniSpecB < Minitest::Test; extend Minitest::Spec::DSL; end class MiniSpecC < MiniSpecB; end class NamedExampleA < MiniSpecA; end class NamedExampleB < MiniSpecB; end class NamedExampleC < MiniSpecC; end class ExampleA; end class ExampleB < ExampleA; end describe Minitest::Spec do # helps to deal with 2.4 deprecation of Fixnum for Integer Int = 1.class # do not parallelize this suite... it just can"t handle it. def assert_triggered expected = "blah", klass = Minitest::Assertion @assertion_count += 1 e = assert_raises(klass) do yield end msg = e.message.sub(/(---Backtrace---).*/m, '\1') msg.gsub!(/\(oid=[-0-9]+\)/, "(oid=N)") msg.gsub!(/@.+>/, "@PATH>") msg.gsub!(/(\d\.\d{6})\d+/, '\1xxx') # normalize: ruby version, impl, platform msg.gsub!(/:0x[a-fA-F0-9]{4,}/m, ":0xXXXXXX") if expected @assertion_count += 1 case expected when String then assert_equal expected, msg when Regexp then @assertion_count += 1 assert_match expected, msg else flunk "Unknown: #{expected.inspect}" end end end before do @assertion_count = 4 end after do _(self.assertions).must_equal @assertion_count if passed? and not skipped? end it "needs to be able to catch a Minitest::Assertion exception" do @assertion_count = 1 assert_triggered "Expected 1 to not be equal to 1." do 1.wont_equal 1 end end it "needs to be sensible about must_include order" do @assertion_count += 3 # must_include is 2 assertions [1, 2, 3].must_include(2).must_equal true assert_triggered "Expected [1, 2, 3] to include 5." do [1, 2, 3].must_include 5 end assert_triggered "msg.\nExpected [1, 2, 3] to include 5." do [1, 2, 3].must_include 5, "msg" end end it "needs to be sensible about wont_include order" do @assertion_count += 3 # wont_include is 2 assertions [1, 2, 3].wont_include(5).must_equal false assert_triggered "Expected [1, 2, 3] to not include 2." do [1, 2, 3].wont_include 2 end assert_triggered "msg.\nExpected [1, 2, 3] to not include 2." do [1, 2, 3].wont_include 2, "msg" end end it "needs to catch an expected exception" do @assertion_count = 2 proc { raise "blah" }.must_raise RuntimeError proc { raise Minitest::Assertion }.must_raise Minitest::Assertion end it "needs to catch an unexpected exception" do @assertion_count -= 2 # no positive msg = <<-EOM.gsub(/^ {6}/, "").chomp [RuntimeError] exception expected, not Class: Message: <"woot"> ---Backtrace--- EOM assert_triggered msg do proc { raise StandardError, "woot" }.must_raise RuntimeError end assert_triggered "msg.\n#{msg}" do proc { raise StandardError, "woot" }.must_raise RuntimeError, "msg" end end it "needs to ensure silence" do @assertion_count -= 1 # no msg @assertion_count += 2 # assert_output is 2 assertions proc {}.must_be_silent.must_equal true assert_triggered "In stdout.\nExpected: \"\"\n Actual: \"xxx\"" do proc { print "xxx" }.must_be_silent end end it "needs to have all methods named well" do @assertion_count = 2 methods = Object.public_instance_methods.find_all { |n| n =~ /^must|^wont/ } methods.map!(&:to_s) if Symbol === methods.first musts, wonts = methods.sort.partition { |m| m =~ /^must/ } expected_musts = %w[must_be must_be_close_to must_be_empty must_be_instance_of must_be_kind_of must_be_nil must_be_same_as must_be_silent must_be_within_delta must_be_within_epsilon must_equal must_include must_match must_output must_raise must_respond_to must_throw] bad = %w[not raise throw send output be_silent] expected_wonts = expected_musts.map { |m| m.sub(/^must/, "wont") } expected_wonts.reject! { |m| m =~ /wont_#{Regexp.union(*bad)}/ } musts.must_equal expected_musts wonts.must_equal expected_wonts end it "needs to raise if an expected exception is not raised" do @assertion_count -= 2 # no positive test assert_triggered "RuntimeError expected but nothing was raised." do proc { 42 }.must_raise RuntimeError end assert_triggered "msg.\nRuntimeError expected but nothing was raised." do proc { 42 }.must_raise RuntimeError, "msg" end end it "needs to verify binary messages" do 42.wont_be(:<, 24).must_equal false assert_triggered "Expected 24 to not be < 42." do 24.wont_be :<, 42 end assert_triggered "msg.\nExpected 24 to not be < 42." do 24.wont_be :<, 42, "msg" end end it "needs to verify emptyness" do @assertion_count += 3 # empty is 2 assertions [].must_be_empty.must_equal true assert_triggered "Expected [42] to be empty." do [42].must_be_empty end assert_triggered "msg.\nExpected [42] to be empty." do [42].must_be_empty "msg" end end it "needs to verify equality" do @assertion_count += 1 (6 * 7).must_equal(42).must_equal true assert_triggered "Expected: 42\n Actual: 54" do (6 * 9).must_equal 42 end assert_triggered "msg.\nExpected: 42\n Actual: 54" do (6 * 9).must_equal 42, "msg" end assert_triggered(/^-42\n\+#\n/) do proc { 42 }.must_equal 42 # proc isn't called, so expectation fails end end it "needs to warn on equality with nil" do @assertion_count += 1 # extra test out, err = capture_io do nil.must_equal(nil).must_equal true end exp = "DEPRECATED: Use assert_nil if expecting nil from #{__FILE__}:#{__LINE__-3}. " \ "This will fail in Minitest 6.\n" exp = "" if $-w.nil? assert_empty out assert_equal exp, err end it "needs to verify floats outside a delta" do @assertion_count += 1 # extra test 24.wont_be_close_to(42).must_equal false assert_triggered "Expected |42 - 42.0| (0.0) to not be <= 0.001." do (6 * 7.0).wont_be_close_to 42 end x = maglev? ? "1.0000000000000001e-05" : "1.0e-05" assert_triggered "Expected |42 - 42.0| (0.0) to not be <= #{x}." do (6 * 7.0).wont_be_close_to 42, 0.00001 end assert_triggered "msg.\nExpected |42 - 42.0| (0.0) to not be <= #{x}." do (6 * 7.0).wont_be_close_to 42, 0.00001, "msg" end end it "needs to verify floats outside an epsilon" do @assertion_count += 1 # extra test 24.wont_be_within_epsilon(42).must_equal false x = maglev? ? "0.042000000000000003" : "0.042" assert_triggered "Expected |42 - 42.0| (0.0) to not be <= #{x}." do (6 * 7.0).wont_be_within_epsilon 42 end x = maglev? ? "0.00042000000000000002" : "0.00042" assert_triggered "Expected |42 - 42.0| (0.0) to not be <= #{x}." do (6 * 7.0).wont_be_within_epsilon 42, 0.00001 end assert_triggered "msg.\nExpected |42 - 42.0| (0.0) to not be <= #{x}." do (6 * 7.0).wont_be_within_epsilon 42, 0.00001, "msg" end end it "needs to verify floats within a delta" do @assertion_count += 1 # extra test (6.0 * 7).must_be_close_to(42.0).must_equal true assert_triggered "Expected |0.0 - 0.01| (0.01) to be <= 0.001." do (1.0 / 100).must_be_close_to 0.0 end x = maglev? ? "9.9999999999999995e-07" : "1.0e-06" assert_triggered "Expected |0.0 - 0.001| (0.001) to be <= #{x}." do (1.0 / 1000).must_be_close_to 0.0, 0.000001 end assert_triggered "msg.\nExpected |0.0 - 0.001| (0.001) to be <= #{x}." do (1.0 / 1000).must_be_close_to 0.0, 0.000001, "msg" end end it "needs to verify floats within an epsilon" do @assertion_count += 1 # extra test (6.0 * 7).must_be_within_epsilon(42.0).must_equal true assert_triggered "Expected |0.0 - 0.01| (0.01) to be <= 0.0." do (1.0 / 100).must_be_within_epsilon 0.0 end assert_triggered "Expected |0.0 - 0.001| (0.001) to be <= 0.0." do (1.0 / 1000).must_be_within_epsilon 0.0, 0.000001 end assert_triggered "msg.\nExpected |0.0 - 0.001| (0.001) to be <= 0.0." do (1.0 / 1000).must_be_within_epsilon 0.0, 0.000001, "msg" end end it "needs to verify identity" do 1.must_be_same_as(1).must_equal true assert_triggered "Expected 1 (oid=N) to be the same as 2 (oid=N)." do 1.must_be_same_as 2 end assert_triggered "msg.\nExpected 1 (oid=N) to be the same as 2 (oid=N)." do 1.must_be_same_as 2, "msg" end end it "needs to verify inequality" do @assertion_count += 2 42.wont_equal(6 * 9).must_equal false proc {}.wont_equal(42).must_equal false assert_triggered "Expected 1 to not be equal to 1." do 1.wont_equal 1 end assert_triggered "msg.\nExpected 1 to not be equal to 1." do 1.wont_equal 1, "msg" end end it "needs to verify instances of a class" do 42.wont_be_instance_of(String).must_equal false assert_triggered "Expected 42 to not be a kind of #{Int.name}." do 42.wont_be_kind_of Int end assert_triggered "msg.\nExpected 42 to not be an instance of #{Int.name}." do 42.wont_be_instance_of Int, "msg" end end it "needs to verify kinds of a class" do @assertion_count += 2 42.wont_be_kind_of(String).must_equal false proc {}.wont_be_kind_of(String).must_equal false assert_triggered "Expected 42 to not be a kind of #{Int.name}." do 42.wont_be_kind_of Int end assert_triggered "msg.\nExpected 42 to not be a kind of #{Int.name}." do 42.wont_be_kind_of Int, "msg" end end it "needs to verify kinds of objects" do @assertion_count += 3 # extra test (6 * 7).must_be_kind_of(Int).must_equal true (6 * 7).must_be_kind_of(Numeric).must_equal true assert_triggered "Expected 42 to be a kind of String, not #{Int.name}." do (6 * 7).must_be_kind_of String end assert_triggered "msg.\nExpected 42 to be a kind of String, not #{Int.name}." do (6 * 7).must_be_kind_of String, "msg" end exp = "Expected # to be a kind of String, not Proc." assert_triggered exp do proc {}.must_be_kind_of String end end it "needs to verify mismatch" do @assertion_count += 3 # match is 2 "blah".wont_match(/\d+/).must_equal false assert_triggered "Expected /\\w+/ to not match \"blah\"." do "blah".wont_match(/\w+/) end assert_triggered "msg.\nExpected /\\w+/ to not match \"blah\"." do "blah".wont_match(/\w+/, "msg") end end it "needs to verify nil" do nil.must_be_nil.must_equal true assert_triggered "Expected 42 to be nil." do 42.must_be_nil end assert_triggered "msg.\nExpected 42 to be nil." do 42.must_be_nil "msg" end end it "needs to verify non-emptyness" do @assertion_count += 3 # empty is 2 assertions ["some item"].wont_be_empty.must_equal false assert_triggered "Expected [] to not be empty." do [].wont_be_empty end assert_triggered "msg.\nExpected [] to not be empty." do [].wont_be_empty "msg" end end it "needs to verify non-identity" do 1.wont_be_same_as(2).must_equal false assert_triggered "Expected 1 (oid=N) to not be the same as 1 (oid=N)." do 1.wont_be_same_as 1 end assert_triggered "msg.\nExpected 1 (oid=N) to not be the same as 1 (oid=N)." do 1.wont_be_same_as 1, "msg" end end it "needs to verify non-nil" do 42.wont_be_nil.must_equal false assert_triggered "Expected nil to not be nil." do nil.wont_be_nil end assert_triggered "msg.\nExpected nil to not be nil." do nil.wont_be_nil "msg" end end it "needs to verify objects not responding to a message" do "".wont_respond_to(:woot!).must_equal false assert_triggered "Expected \"\" to not respond to to_s." do "".wont_respond_to :to_s end assert_triggered "msg.\nExpected \"\" to not respond to to_s." do "".wont_respond_to :to_s, "msg" end end it "needs to verify output in stderr" do @assertion_count -= 1 # no msg proc { $stderr.print "blah" }.must_output(nil, "blah").must_equal true assert_triggered "In stderr.\nExpected: \"blah\"\n Actual: \"xxx\"" do proc { $stderr.print "xxx" }.must_output(nil, "blah") end end it "needs to verify output in stdout" do @assertion_count -= 1 # no msg proc { print "blah" }.must_output("blah").must_equal true assert_triggered "In stdout.\nExpected: \"blah\"\n Actual: \"xxx\"" do proc { print "xxx" }.must_output("blah") end end it "needs to verify regexp matches" do @assertion_count += 3 # must_match is 2 assertions "blah".must_match(/\w+/).must_equal true assert_triggered "Expected /\\d+/ to match \"blah\"." do "blah".must_match(/\d+/) end assert_triggered "msg.\nExpected /\\d+/ to match \"blah\"." do "blah".must_match(/\d+/, "msg") end end describe "expect" do before do @assertion_count -= 3 end it "can use expect" do _(1 + 1).must_equal 2 end it "can use expect with a lambda" do _ { raise "blah" }.must_raise RuntimeError end it "can use expect in a thread" do Thread.new { _(1 + 1).must_equal 2 }.join end it "can NOT use must_equal in a thread. It must use expect in a thread" do assert_raises NoMethodError do capture_io do Thread.new { (1 + 1).must_equal 2 }.join end end end end it "needs to verify throw" do @assertion_count += 2 # 2 extra tests proc { throw :blah }.must_throw(:blah).must_equal true assert_triggered "Expected :blah to have been thrown." do proc {}.must_throw :blah end assert_triggered "Expected :blah to have been thrown, not :xxx." do proc { throw :xxx }.must_throw :blah end assert_triggered "msg.\nExpected :blah to have been thrown." do proc {}.must_throw :blah, "msg" end assert_triggered "msg.\nExpected :blah to have been thrown, not :xxx." do proc { throw :xxx }.must_throw :blah, "msg" end end it "needs to verify types of objects" do (6 * 7).must_be_instance_of(Int).must_equal true exp = "Expected 42 to be an instance of String, not #{Int.name}." assert_triggered exp do (6 * 7).must_be_instance_of String end assert_triggered "msg.\n#{exp}" do (6 * 7).must_be_instance_of String, "msg" end end it "needs to verify using any (negative) predicate" do @assertion_count -= 1 # doesn"t take a message "blah".wont_be(:empty?).must_equal false assert_triggered "Expected \"\" to not be empty?." do "".wont_be :empty? end end it "needs to verify using any binary operator" do @assertion_count -= 1 # no msg 41.must_be(:<, 42).must_equal true assert_triggered "Expected 42 to be < 41." do 42.must_be(:<, 41) end end it "needs to verify using any predicate" do @assertion_count -= 1 # no msg "".must_be(:empty?).must_equal true assert_triggered "Expected \"blah\" to be empty?." do "blah".must_be :empty? end end it "needs to verify using respond_to" do 42.must_respond_to(:+).must_equal true assert_triggered "Expected 42 (#{Int.name}) to respond to #clear." do 42.must_respond_to :clear end assert_triggered "msg.\nExpected 42 (#{Int.name}) to respond to #clear." do 42.must_respond_to :clear, "msg" end end end describe Minitest::Spec, :let do i_suck_and_my_tests_are_order_dependent! def _count $let_count ||= 0 end let :count do $let_count += 1 $let_count end it "is evaluated once per example" do _count.must_equal 0 count.must_equal 1 count.must_equal 1 _count.must_equal 1 end it "is REALLY evaluated once per example" do _count.must_equal 1 count.must_equal 2 count.must_equal 2 _count.must_equal 2 end it 'raises an error if the name begins with "test"' do proc { self.class.let(:test_value) { true } }.must_raise ArgumentError end it "raises an error if the name shadows a normal instance method" do proc { self.class.let(:message) { true } }.must_raise ArgumentError end it "doesn't raise an error if it is just another let" do proc do describe :outer do let(:bar) describe :inner do let(:bar) end end :good end.call.must_equal :good end it "procs come after dont_flip" do p = proc {} assert_respond_to p, :call p.must_respond_to :call end end describe Minitest::Spec, :subject do attr_reader :subject_evaluation_count subject do @subject_evaluation_count ||= 0 @subject_evaluation_count += 1 @subject_evaluation_count end it "is evaluated once per example" do subject.must_equal 1 subject.must_equal 1 subject_evaluation_count.must_equal 1 end end class TestMetaStatic < Minitest::Test def test_children Minitest::Spec.children.clear # prevents parallel run y = z = nil x = describe "top-level thingy" do y = describe "first thingy" do end it "top-level-it" do end z = describe "second thingy" do end end assert_equal [x], Minitest::Spec.children assert_equal [y, z], x.children assert_equal [], y.children assert_equal [], z.children end def test_it_wont_remove_existing_child_test_methods Minitest::Spec.children.clear # prevents parallel run inner = nil outer = describe "outer" do inner = describe "inner" do it do assert true end end it do assert true end end assert_equal 1, outer.public_instance_methods.grep(/^test_/).count assert_equal 1, inner.public_instance_methods.grep(/^test_/).count end def test_it_wont_add_test_methods_to_children Minitest::Spec.children.clear # prevents parallel run inner = nil outer = describe "outer" do inner = describe "inner" do end it do assert true end end assert_equal 1, outer.public_instance_methods.grep(/^test_/).count assert_equal 0, inner.public_instance_methods.grep(/^test_/).count end end require "minitest/metametameta" class TestMeta < MetaMetaMetaTestCase parallelize_me! def util_structure y = z = nil before_list = [] after_list = [] x = describe "top-level thingy" do before { before_list << 1 } after { after_list << 1 } it "top-level-it" do end y = describe "inner thingy" do before { before_list << 2 } after { after_list << 2 } it "inner-it" do end z = describe "very inner thingy" do before { before_list << 3 } after { after_list << 3 } it "inner-it" do end it { } # ignore me specify { } # anonymous it end end end return x, y, z, before_list, after_list end def test_register_spec_type original_types = Minitest::Spec::TYPES.dup assert_includes Minitest::Spec::TYPES, [//, Minitest::Spec] Minitest::Spec.register_spec_type(/woot/, TestMeta) p = lambda do |_| true end Minitest::Spec.register_spec_type TestMeta, &p keys = Minitest::Spec::TYPES.map(&:first) assert_includes keys, /woot/ assert_includes keys, p ensure Minitest::Spec::TYPES.replace original_types end def test_spec_type original_types = Minitest::Spec::TYPES.dup Minitest::Spec.register_spec_type(/A$/, MiniSpecA) Minitest::Spec.register_spec_type MiniSpecB do |desc| desc.superclass == ExampleA end Minitest::Spec.register_spec_type MiniSpecC do |_desc, *addl| addl.include? :woot end assert_equal MiniSpecA, Minitest::Spec.spec_type(ExampleA) assert_equal MiniSpecB, Minitest::Spec.spec_type(ExampleB) assert_equal MiniSpecC, Minitest::Spec.spec_type(ExampleB, :woot) ensure Minitest::Spec::TYPES.replace original_types end def test_bug_dsl_expectations spec_class = Class.new MiniSpecB do it "should work" do 0.must_equal 0 end end test_name = spec_class.instance_methods.sort.grep(/test/).first spec = spec_class.new test_name result = spec.run assert spec.passed? assert result.passed? assert_equal 1, result.assertions end def test_name spec_a = describe ExampleA do; end spec_b = describe ExampleB, :random_method do; end spec_c = describe ExampleB, :random_method, :addl_context do; end assert_equal "ExampleA", spec_a.name assert_equal "ExampleB::random_method", spec_b.name assert_equal "ExampleB::random_method::addl_context", spec_c.name end def test_name2 assert_equal "NamedExampleA", NamedExampleA.name assert_equal "NamedExampleB", NamedExampleB.name assert_equal "NamedExampleC", NamedExampleC.name spec_a = describe ExampleA do; end spec_b = describe ExampleB, :random_method do; end assert_equal "ExampleA", spec_a.name assert_equal "ExampleB::random_method", spec_b.name end def test_structure x, y, z, * = util_structure assert_equal "top-level thingy", x.to_s assert_equal "top-level thingy::inner thingy", y.to_s assert_equal "top-level thingy::inner thingy::very inner thingy", z.to_s assert_equal "top-level thingy", x.desc assert_equal "inner thingy", y.desc assert_equal "very inner thingy", z.desc top_methods = %w[setup teardown test_0001_top-level-it] inner_methods1 = %w[setup teardown test_0001_inner-it] inner_methods2 = inner_methods1 + %w[test_0002_anonymous test_0003_anonymous] assert_equal top_methods, x.instance_methods(false).sort.map(&:to_s) assert_equal inner_methods1, y.instance_methods(false).sort.map(&:to_s) assert_equal inner_methods2, z.instance_methods(false).sort.map(&:to_s) end def test_structure_postfix_it z = nil y = describe "outer" do # NOT here, below the inner-describe! # it "inner-it" do end z = describe "inner" do it "inner-it" do end end # defined AFTER inner describe means we'll try to wipe out the inner-it it "inner-it" do end end assert_equal %w[test_0001_inner-it], y.instance_methods(false).map(&:to_s) assert_equal %w[test_0001_inner-it], z.instance_methods(false).map(&:to_s) end def test_setup_teardown_behavior _, _, z, before_list, after_list = util_structure @tu = z run_tu_with_fresh_reporter size = z.runnable_methods.size assert_equal [1, 2, 3] * size, before_list assert_equal [3, 2, 1] * size, after_list end def test_describe_first_structure x1 = x2 = y = z = nil x = describe "top-level thingy" do y = describe "first thingy" do end x1 = it "top level it" do end x2 = it "не латинские &いった α, β, γ, δ, ε hello!!! world" do end z = describe "second thingy" do end end test_methods = ["test_0001_top level it", "test_0002_не латинские &いった α, β, γ, δ, ε hello!!! world", ].sort assert_equal test_methods, [x1, x2] assert_equal test_methods, x.instance_methods.grep(/^test/).map(&:to_s).sort assert_equal [], y.instance_methods.grep(/^test/) assert_equal [], z.instance_methods.grep(/^test/) end def test_structure_subclasses z = nil x = Class.new Minitest::Spec do def xyz; end end y = Class.new x do z = describe("inner") { } end assert_respond_to x.new(nil), "xyz" assert_respond_to y.new(nil), "xyz" assert_respond_to z.new(nil), "xyz" end end class TestSpecInTestCase < MetaMetaMetaTestCase def setup super Thread.current[:current_spec] = self @tc = self @assertion_count = 2 end def assert_triggered expected, klass = Minitest::Assertion @assertion_count += 1 e = assert_raises klass do yield end msg = e.message.sub(/(---Backtrace---).*/m, "\1") msg.gsub!(/\(oid=[-0-9]+\)/, "(oid=N)") assert_equal expected, msg end def teardown msg = "expected #{@assertion_count} assertions, not #{@tc.assertions}" assert_equal @assertion_count, @tc.assertions, msg end def test_expectation @tc.assert_equal true, 1.must_equal(1) end def test_expectation_triggered assert_triggered "Expected: 2\n Actual: 1" do 1.must_equal 2 end end def test_expectation_with_a_message assert_triggered "woot.\nExpected: 2\n Actual: 1" do 1.must_equal 2, "woot" end end end class ValueMonadTest < Minitest::Test attr_accessor :struct def setup @struct = { :_ => "a", :value => "b", :expect => "c" } def @struct.method_missing k # think openstruct self[k] end end def test_value_monad_method assert_equal "a", struct._ end def test_value_monad_value_alias assert_equal "b", struct.value end def test_value_monad_expect_alias assert_equal "c", struct.expect end end PK% ]smm gems/minitest-5.11.3/README.rdocnu[= minitest/{test,spec,mock,benchmark} home :: https://github.com/seattlerb/minitest bugs :: https://github.com/seattlerb/minitest/issues rdoc :: http://docs.seattlerb.org/minitest vim :: https://github.com/sunaku/vim-ruby-minitest emacs:: https://github.com/arthurnn/minitest-emacs == DESCRIPTION: minitest provides a complete suite of testing facilities supporting TDD, BDD, mocking, and benchmarking. "I had a class with Jim Weirich on testing last week and we were allowed to choose our testing frameworks. Kirk Haines and I were paired up and we cracked open the code for a few test frameworks... I MUST say that minitest is *very* readable / understandable compared to the 'other two' options we looked at. Nicely done and thank you for helping us keep our mental sanity." -- Wayne E. Seguin minitest/test is a small and incredibly fast unit testing framework. It provides a rich set of assertions to make your tests clean and readable. minitest/spec is a functionally complete spec engine. It hooks onto minitest/test and seamlessly bridges test assertions over to spec expectations. minitest/benchmark is an awesome way to assert the performance of your algorithms in a repeatable manner. Now you can assert that your newb co-worker doesn't replace your linear algorithm with an exponential one! minitest/mock by Steven Baker, is a beautifully tiny mock (and stub) object framework. minitest/pride shows pride in testing and adds coloring to your test output. I guess it is an example of how to write IO pipes too. :P minitest/test is meant to have a clean implementation for language implementors that need a minimal set of methods to bootstrap a working test suite. For example, there is no magic involved for test-case discovery. "Again, I can't praise enough the idea of a testing/specing framework that I can actually read in full in one sitting!" -- Piotr Szotkowski Comparing to rspec: rspec is a testing DSL. minitest is ruby. -- Adam Hawkins, "Bow Before MiniTest" minitest doesn't reinvent anything that ruby already provides, like: classes, modules, inheritance, methods. This means you only have to learn ruby to use minitest and all of your regular OO practices like extract-method refactorings still apply. == FEATURES/PROBLEMS: * minitest/autorun - the easy and explicit way to run all your tests. * minitest/test - a very fast, simple, and clean test system. * minitest/spec - a very fast, simple, and clean spec system. * minitest/mock - a simple and clean mock/stub system. * minitest/benchmark - an awesome way to assert your algorithm's performance. * minitest/pride - show your pride in testing! * Incredibly small and fast runner, but no bells and whistles. * Written by squishy human beings. Software can never be perfect. We will all eventually die. == RATIONALE: See design_rationale.rb to see how specs and tests work in minitest. == SYNOPSIS: Given that you'd like to test the following class: class Meme def i_can_has_cheezburger? "OHAI!" end def will_it_blend? "YES!" end end === Unit tests Define your tests as methods beginning with +test_+. require "minitest/autorun" class TestMeme < Minitest::Test def setup @meme = Meme.new end def test_that_kitty_can_eat assert_equal "OHAI!", @meme.i_can_has_cheezburger? end def test_that_it_will_not_blend refute_match /^no/i, @meme.will_it_blend? end def test_that_will_be_skipped skip "test this later" end end === Specs require "minitest/autorun" describe Meme do before do @meme = Meme.new end describe "when asked about cheeseburgers" do it "must respond positively" do @meme.i_can_has_cheezburger?.must_equal "OHAI!" end end describe "when asked about blending possibilities" do it "won't say no" do @meme.will_it_blend?.wont_match /^no/i end end end For matchers support check out: * https://github.com/wojtekmach/minitest-matchers * https://github.com/rmm5t/minitest-matchers_vaccine === Benchmarks Add benchmarks to your tests. # optionally run benchmarks, good for CI-only work! require "minitest/benchmark" if ENV["BENCH"] class TestMeme < Minitest::Benchmark # Override self.bench_range or default range is [1, 10, 100, 1_000, 10_000] def bench_my_algorithm assert_performance_linear 0.9999 do |n| # n is a range value @obj.my_algorithm(n) end end end Or add them to your specs. If you make benchmarks optional, you'll need to wrap your benchmarks in a conditional since the methods won't be defined. In minitest 5, the describe name needs to match /Bench(mark)?$/. describe "Meme Benchmark" do if ENV["BENCH"] then bench_performance_linear "my_algorithm", 0.9999 do |n| 100.times do @obj.my_algorithm(n) end end end end outputs something like: # Running benchmarks: TestBlah 100 1000 10000 bench_my_algorithm 0.006167 0.079279 0.786993 bench_other_algorithm 0.061679 0.792797 7.869932 Output is tab-delimited to make it easy to paste into a spreadsheet. === Mocks Mocks and stubs defined using terminology by Fowler & Meszaros at http://www.martinfowler.com/bliki/TestDouble.html: "Mocks are pre-programmed with expectations which form a specification of the calls they are expected to receive. They can throw an exception if they receive a call they don't expect and are checked during verification to ensure they got all the calls they were expecting." class MemeAsker def initialize(meme) @meme = meme end def ask(question) method = question.tr(" ", "_") + "?" @meme.__send__(method) end end require "minitest/autorun" describe MemeAsker, :ask do describe "when passed an unpunctuated question" do it "should invoke the appropriate predicate method on the meme" do @meme = Minitest::Mock.new @meme_asker = MemeAsker.new @meme @meme.expect :will_it_blend?, :return_value @meme_asker.ask "will it blend" @meme.verify end end end **Multi-threading and Mocks** Minitest mocks do not support multi-threading if it works, fine, if it doesn't you can use regular ruby patterns and facilities like local variables. Here's an example of asserting that code inside a thread is run: def test_called_inside_thread called = false pr = Proc.new { called = true } thread = Thread.new(&pr) thread.join assert called, "proc not called" end === Stubs Mocks and stubs are defined using terminology by Fowler & Meszaros at http://www.martinfowler.com/bliki/TestDouble.html: "Stubs provide canned answers to calls made during the test". Minitest's stub method overrides a single method for the duration of the block. def test_stale_eh obj_under_test = Something.new refute obj_under_test.stale? Time.stub :now, Time.at(0) do # stub goes away once the block is done assert obj_under_test.stale? end end A note on stubbing: In order to stub a method, the method must actually exist prior to stubbing. Use a singleton method to create a new non-existing method: def obj_under_test.fake_method ... end === Running Your Tests Ideally, you'll use a rake task to run your tests, either piecemeal or all at once. Both rake and rails ship with rake tasks for running your tests. BUT! You don't have to: % ruby -Ilib:test test/minitest/test_minitest_test.rb Run options: --seed 37685 # Running: ...................................................................... (etc) Finished in 0.107130s, 1446.8403 runs/s, 2959.0217 assertions/s. 155 runs, 317 assertions, 0 failures, 0 errors, 0 skips There are runtime options available, both from minitest itself, and also provided via plugins. To see them, simply run with +--help+: % ruby -Ilib:test test/minitest/test_minitest_test.rb --help minitest options: -h, --help Display this help. -s, --seed SEED Sets random seed. Also via env. Eg: SEED=n rake -v, --verbose Verbose. Show progress processing files. -n, --name PATTERN Filter run on /regexp/ or string. -e, --exclude PATTERN Exclude /regexp/ or string from run. Known extensions: pride, autotest -p, --pride Pride. Show your testing pride! -a, --autotest Connect to autotest server. == Writing Extensions To define a plugin, add a file named minitest/XXX_plugin.rb to your project/gem. That file must be discoverable via ruby's LOAD_PATH (via rubygems or otherwise). Minitest will find and require that file using Gem.find_files. It will then try to call +plugin_XXX_init+ during startup. The option processor will also try to call +plugin_XXX_options+ passing the OptionParser instance and the current options hash. This lets you register your own command-line options. Here's a totally bogus example: # minitest/bogus_plugin.rb: module Minitest def self.plugin_bogus_options(opts, options) opts.on "--myci", "Report results to my CI" do options[:myci] = true options[:myci_addr] = get_myci_addr options[:myci_port] = get_myci_port end end def self.plugin_bogus_init(options) self.reporter << MyCI.new(options) if options[:myci] end end === Adding custom reporters Minitest uses composite reporter to output test results using multiple reporter instances. You can add new reporters to the composite during the init_plugins phase. As we saw in +plugin_bogus_init+ above, you simply add your reporter instance to the composite via <<. +AbstractReporter+ defines the API for reporters. You may subclass it and override any method you want to achieve your desired behavior. start :: Called when the run has started. record :: Called for each result, passed or otherwise. report :: Called at the end of the run. passed? :: Called to see if you detected any problems. Using our example above, here is how we might implement MyCI: # minitest/bogus_plugin.rb module Minitest class MyCI < AbstractReporter attr_accessor :results, :addr, :port def initialize options self.results = [] self.addr = options[:myci_addr] self.port = options[:myci_port] end def record result self.results << result end def report CI.connect(addr, port).send_results self.results end end # code from above... end == FAQ === How to test SimpleDelegates? The following implementation and test: class Worker < SimpleDelegator def work end end describe Worker do before do @worker = Worker.new(Object.new) end it "must respond to work" do @worker.must_respond_to :work end end outputs a failure: 1) Failure: Worker#test_0001_must respond to work [bug11.rb:16]: Expected # (Object) to respond to #work. Worker is a SimpleDelegate which in 1.9+ is a subclass of BasicObject. Expectations are put on Object (one level down) so the Worker (SimpleDelegate) hits +method_missing+ and delegates down to the +Object.new+ instance. That object doesn't respond to work so the test fails. You can bypass SimpleDelegate#method_missing by extending the worker with Minitest::Expectations. You can either do that in your setup at the instance level, like: before do @worker = Worker.new(Object.new) @worker.extend Minitest::Expectations end or you can extend the Worker class (within the test file!), like: class Worker include ::Minitest::Expectations end === How to share code across test classes? Use a module. That's exactly what they're for: module UsefulStuff def useful_method # ... end end describe Blah do include UsefulStuff def test_whatever # useful_method available here end end Remember, +describe+ simply creates test classes. It's just ruby at the end of the day and all your normal Good Ruby Rules (tm) apply. If you want to extend your test using setup/teardown via a module, just make sure you ALWAYS call super. before/after automatically call super for you, so make sure you don't do it twice. === How to run code before a group of tests? Use a constant with begin...end like this: describe Blah do SETUP = begin # ... this runs once when describe Blah starts end # ... end This can be useful for expensive initializations or sharing state. Remember, this is just ruby code, so you need to make sure this technique and sharing state doesn't interfere with your tests. === Why am I seeing uninitialized constant MiniTest::Test (NameError)? Are you running the test with Bundler (e.g. via bundle exec )? If so, in order to require minitest, you must first add the gem 'minitest' to your Gemfile and run +bundle+. Once it's installed, you should be able to require minitest and run your tests. == Prominent Projects using Minitest: * arel * journey * mime-types * nokogiri * rails (active_support et al) * rake * rdoc * ...and of course, everything from seattle.rb... == Developing Minitest: === Minitest's own tests require UTF-8 external encoding. This is a common problem in Windows, where the default external Encoding is often CP850, but can affect any platform. Minitest can run test suites using any Encoding, but to run Minitest's own tests you must have a default external Encoding of UTF-8. If your encoding is wrong, you'll see errors like: --- expected +++ actual @@ -1,2 +1,3 @@ # encoding: UTF-8 -"Expected /\\w+/ to not match \"blah blah blah\"." +"Expected /\\w+/ to not match # encoding: UTF-8 +\"blah blah blah\"." To check your current encoding, run: ruby -e 'puts Encoding.default_external' If your output is something other than UTF-8, you can set the RUBYOPTS env variable to a value of '-Eutf-8'. Something like: RUBYOPT='-Eutf-8' ruby -e 'puts Encoding.default_external' Check your OS/shell documentation for the precise syntax (the above will not work on a basic Windows CMD prompt, look for the SET command). Once you've got it successfully outputing UTF-8, use the same setting when running rake in Minitest. === Minitest's own tests require GNU (or similar) diff. This is also a problem primarily affecting Windows developers. PowerShell has a command called diff, but it is not suitable for use with Minitest. If you see failures like either of these, you are probably missing diff tool: 4) Failure: TestMinitestUnitTestCase#test_assert_equal_different_long [D:/ruby/seattlerb/minitest/test/minitest/test_minitest_test.rb:936]: Expected: "--- expected\n+++ actual\n@@ -1 +1 @@\n-\"hahahahahahahahahahahahahahahahahahahaha\"\n+\"blahblahblahblahblahblahblahblahblahblah\"\n" Actual: "Expected: \"hahahahahahahahahahahahahahahahahahahaha\"\n Actual: \"blahblahblahblahblahblahblahblahblahblah\"" 5) Failure: TestMinitestUnitTestCase#test_assert_equal_different_collection_hash_hex_invisible [D:/ruby/seattlerb/minitest/test/minitest/test_minitest_test.rb:845]: Expected: "No visible difference in the Hash#inspect output.\nYou should look at the implementation of #== on Hash or its members.\n {1=>#}" Actual: "Expected: {1=>#}\n Actual: {1=>#}" If you use Cygwin or MSYS2 or similar there are packages that include a GNU diff for Windows. If you don't, you can download GNU diffutils from http://gnuwin32.sourceforge.net/packages/diffutils.htm (make sure to add it to your PATH). You can make sure it's installed and path is configured properly with: diff.exe -v There are multiple lines of output, the first should be something like: diff (GNU diffutils) 2.8.1 If you are using PowerShell make sure you run diff.exe, not just diff, which will invoke the PowerShell built in function. == Known Extensions: capybara_minitest_spec :: Bridge between Capybara RSpec matchers and Minitest::Spec expectations (e.g. page.must_have_content("Title")). color_pound_spec_reporter :: Test names print Ruby Object types in color with your Minitest Spec style tests. minispec-metadata :: Metadata for describe/it blocks & CLI tag filter. E.g. it "requires JS driver", js: true do & ruby test.rb --tag js runs tests tagged :js. minispec-rails :: Minimal support to use Spec style in Rails 5+. minitest-around :: Around block for minitest. An alternative to setup/teardown dance. minitest-assert_errors :: Adds Minitest assertions to test for errors raised or not raised by Minitest itself. minitest-autotest :: autotest is a continuous testing facility meant to be used during development. minitest-bacon :: minitest-bacon extends minitest with bacon-like functionality. minitest-bang :: Adds support for RSpec-style let! to immediately invoke let statements before each test. minitest-bisect :: Helps you isolate and debug random test failures. minitest-blink1_reporter :: Display test results with a Blink1. minitest-capistrano :: Assertions and expectations for testing Capistrano recipes. minitest-capybara :: Capybara matchers support for minitest unit and spec. minitest-chef-handler :: Run Minitest suites as Chef report handlers minitest-ci :: CI reporter plugin for Minitest. minitest-context :: Defines contexts for code reuse in Minitest specs that share common expectations. minitest-debugger :: Wraps assert so failed assertions drop into the ruby debugger. minitest-display :: Patches Minitest to allow for an easily configurable output. minitest-documentation :: Minimal documentation format inspired by rspec's. minitest-doc_reporter :: Detailed output inspired by rspec's documentation format. minitest-emoji :: Print out emoji for your test passes, fails, and skips. minitest-english :: Semantically symmetric aliases for assertions and expectations. minitest-excludes :: Clean API for excluding certain tests you don't want to run under certain conditions. minitest-fail-fast :: Reimplements RSpec's "fail fast" feature minitest-filecontent :: Support unit tests with expectation results in files. Differing results will be stored again in files. minitest-filesystem :: Adds assertion and expectation to help testing filesystem contents. minitest-firemock :: Makes your Minitest mocks more resilient. minitest-focus :: Focus on one test at a time. minitest-gcstats :: A minitest plugin that adds a report of the top tests by number of objects allocated. minitest-great_expectations :: Generally useful additions to minitest's assertions and expectations. minitest-growl :: Test notifier for minitest via growl. minitest-happy :: GLOBALLY ACTIVATE MINITEST PRIDE! RAWR! minitest-have_tag :: Adds Minitest assertions to test for the existence of HTML tags, including contents, within a provided string. minitest-hooks :: Around and before_all/after_all/around_all hooks minitest-hyper :: Pretty, single-page HTML reports for your Minitest runs minitest-implicit-subject :: Implicit declaration of the test subject. minitest-instrument :: Instrument ActiveSupport::Notifications when test method is executed. minitest-instrument-db :: Store information about speed of test execution provided by minitest-instrument in database. minitest-junit :: JUnit-style XML reporter for minitest. minitest-keyword :: Use Minitest assertions with keyword arguments. minitest-libnotify :: Test notifier for minitest via libnotify. minitest-line :: Run test at line number. minitest-logger :: Define assert_log and enable minitest to test log messages. Supports Logger and Log4r::Logger. minitest-macruby :: Provides extensions to minitest for macruby UI testing. minitest-matchers :: Adds support for RSpec-style matchers to minitest. minitest-matchers_vaccine :: Adds assertions that adhere to the matcher spec, but without any expectation infections. minitest-metadata :: Annotate tests with metadata (key-value). minitest-mongoid :: Mongoid assertion matchers for Minitest. minitest-must_not :: Provides must_not as an alias for wont in Minitest. minitest-optional_retry :: Automatically retry failed test to help with flakiness. minitest-osx :: Reporter for the Mac OS X notification center. minitest-parallel_fork :: Fork-based parallelization minitest-parallel-db :: Run tests in parallel with a single database. minitest-power_assert :: PowerAssert for Minitest. minitest-predicates :: Adds support for .predicate? methods. minitest-profile :: List the 10 slowest tests in your suite. minitest-rails :: Minitest integration for Rails 3.x. minitest-rails-capybara :: Capybara integration for Minitest::Rails. minitest-reporters :: Create customizable Minitest output formats. minitest-rg :: Colored red/green output for Minitest. minitest-rspec_mocks :: Use RSpec Mocks with Minitest. minitest-server :: minitest-server provides a client/server setup with your minitest process, allowing your test run to send its results directly to a handler. minitest-sequel :: Minitest assertions to speed-up development and testing of Ruby Sequel database setups. minitest-shared_description :: Support for shared specs and shared spec subclasses minitest-should_syntax :: RSpec-style x.should == y assertions for Minitest. minitest-shouldify :: Adding all manner of shoulds to Minitest (bad idea) minitest-snail :: Print a list of tests that take too long minitest-spec-context :: Provides rspec-ish context method to Minitest::Spec. minitest-spec-expect :: Expect syntax for Minitest::Spec (e.g. expect(sequences).to_include :celery_man). minitest-spec-magic :: Minitest::Spec extensions for Rails and beyond. minitest-spec-rails :: Drop in Minitest::Spec superclass for ActiveSupport::TestCase. minitest-sprint :: Runs (Get it? It's fast!) your tests and makes it easier to rerun individual failures. minitest-stately :: Find leaking state between tests minitest-stub_any_instance :: Stub any instance of a method on the given class for the duration of a block. minitest-stub-const :: Stub constants for the duration of a block. minitest-tags :: Add tags for minitest. minitest-unordered :: Adds a new assertion to minitest for checking the contents of a collection, ignoring element order. minitest-vcr :: Automatic cassette managment with Minitest::Spec and VCR. minitest_owrapper :: Get tests results as a TestResult object. minitest_should :: Shoulda style syntax for minitest test::unit. minitest_tu_shim :: Bridges between test/unit and minitest. mongoid-minitest :: Minitest matchers for Mongoid. pry-rescue :: A pry plugin w/ minitest support. See pry-rescue/minitest.rb. rspec2minitest :: Easily translate any RSpec matchers to Minitest assertions and expectations. == Unknown Extensions: Authors... Please send me a pull request with a description of your minitest extension. * assay-minitest * detroit-minitest * em-minitest-spec * flexmock-minitest * guard-minitest * guard-minitest-decisiv * minitest-activemodel * minitest-ar-assertions * minitest-capybara-unit * minitest-colorer * minitest-deluxe * minitest-extra-assertions * minitest-rails-shoulda * minitest-spec * minitest-spec-should * minitest-sugar * spork-minitest == Minitest related goods * minitest/pride fabric: http://www.spoonflower.com/fabric/3928730-again-by-katie_allen == REQUIREMENTS: * Ruby 1.8.7+. No magic is involved. I hope. * NOTE: 1.8 and 1.9 will be dropped in minitest 6+. == INSTALL: sudo gem install minitest On 1.9, you already have it. To get newer candy you can still install the gem, and then requiring "minitest/autorun" should automatically pull it in. If not, you'll need to do it yourself: gem "minitest" # ensures you"re using the gem, and not the built-in MT require "minitest/autorun" # ... usual testing stuffs ... DO NOTE: There is a serious problem with the way that ruby 1.9/2.0 packages their own gems. They install a gem specification file, but don't install the gem contents in the gem path. This messes up Gem.find_files and many other things (gem which, gem contents, etc). Just install minitest as a gem for real and you'll be happier. == LICENSE: (The MIT License) Copyright (c) Ryan Davis, seattle.rb 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. PK% ]R`4Y4Y$gems/minitest-5.11.3/lib/minitest.rbnu[require "optparse" require "thread" require "mutex_m" require "minitest/parallel" require "stringio" ## # :include: README.rdoc module Minitest VERSION = "5.11.3" # :nodoc: ENCS = "".respond_to? :encoding # :nodoc: @@installed_at_exit ||= false @@after_run = [] @extensions = [] mc = (class << self; self; end) ## # Parallel test executor mc.send :attr_accessor, :parallel_executor self.parallel_executor = Parallel::Executor.new((ENV["N"] || 2).to_i) ## # Filter object for backtraces. mc.send :attr_accessor, :backtrace_filter ## # Reporter object to be used for all runs. # # NOTE: This accessor is only available during setup, not during runs. mc.send :attr_accessor, :reporter ## # Names of known extension plugins. mc.send :attr_accessor, :extensions ## # The signal to use for dumping information to STDERR. Defaults to "INFO". mc.send :attr_accessor, :info_signal self.info_signal = "INFO" ## # Registers Minitest to run at process exit def self.autorun at_exit { next if $! and not ($!.kind_of? SystemExit and $!.success?) exit_code = nil at_exit { @@after_run.reverse_each(&:call) exit exit_code || false } exit_code = Minitest.run ARGV } unless @@installed_at_exit @@installed_at_exit = true end ## # A simple hook allowing you to run a block of code after everything # is done running. Eg: # # Minitest.after_run { p $debugging_info } def self.after_run &block @@after_run << block end def self.init_plugins options # :nodoc: self.extensions.each do |name| msg = "plugin_#{name}_init" send msg, options if self.respond_to? msg end end def self.load_plugins # :nodoc: return unless self.extensions.empty? seen = {} require "rubygems" unless defined? Gem Gem.find_files("minitest/*_plugin.rb").each do |plugin_path| name = File.basename plugin_path, "_plugin.rb" next if seen[name] seen[name] = true require plugin_path self.extensions << name end end ## # This is the top-level run method. Everything starts from here. It # tells each Runnable sub-class to run, and each of those are # responsible for doing whatever they do. # # The overall structure of a run looks like this: # # Minitest.autorun # Minitest.run(args) # Minitest.__run(reporter, options) # Runnable.runnables.each # runnable.run(reporter, options) # self.runnable_methods.each # self.run_one_method(self, runnable_method, reporter) # Minitest.run_one_method(klass, runnable_method) # klass.new(runnable_method).run def self.run args = [] self.load_plugins unless args.delete("--no-plugins") || ENV["MT_NO_PLUGINS"] options = process_args args reporter = CompositeReporter.new reporter << SummaryReporter.new(options[:io], options) reporter << ProgressReporter.new(options[:io], options) self.reporter = reporter # this makes it available to plugins self.init_plugins options self.reporter = nil # runnables shouldn't depend on the reporter, ever self.parallel_executor.start if parallel_executor.respond_to?(:start) reporter.start begin __run reporter, options rescue Interrupt warn "Interrupted. Exiting..." end self.parallel_executor.shutdown reporter.report reporter.passed? end ## # Internal run method. Responsible for telling all Runnable # sub-classes to run. def self.__run reporter, options suites = Runnable.runnables.reject { |s| s.runnable_methods.empty? }.shuffle parallel, serial = suites.partition { |s| s.test_order == :parallel } # If we run the parallel tests before the serial tests, the parallel tests # could run in parallel with the serial tests. This would be bad because # the serial tests won't lock around Reporter#record. Run the serial tests # first, so that after they complete, the parallel tests will lock when # recording results. serial.map { |suite| suite.run reporter, options } + parallel.map { |suite| suite.run reporter, options } end def self.process_args args = [] # :nodoc: options = { :io => $stdout, } orig_args = args.dup OptionParser.new do |opts| opts.banner = "minitest options:" opts.version = Minitest::VERSION opts.on "-h", "--help", "Display this help." do puts opts exit end opts.on "--no-plugins", "Bypass minitest plugin auto-loading (or set $MT_NO_PLUGINS)." desc = "Sets random seed. Also via env. Eg: SEED=n rake" opts.on "-s", "--seed SEED", Integer, desc do |m| options[:seed] = m.to_i end opts.on "-v", "--verbose", "Verbose. Show progress processing files." do options[:verbose] = true end opts.on "-n", "--name PATTERN", "Filter run on /regexp/ or string." do |a| options[:filter] = a end opts.on "-e", "--exclude PATTERN", "Exclude /regexp/ or string from run." do |a| options[:exclude] = a end unless extensions.empty? opts.separator "" opts.separator "Known extensions: #{extensions.join(", ")}" extensions.each do |meth| msg = "plugin_#{meth}_options" send msg, opts, options if self.respond_to?(msg) end end begin opts.parse! args rescue OptionParser::InvalidOption => e puts puts e puts puts opts exit 1 end orig_args -= args end unless options[:seed] then srand options[:seed] = (ENV["SEED"] || srand).to_i % 0xFFFF orig_args << "--seed" << options[:seed].to_s end srand options[:seed] options[:args] = orig_args.map { |s| s =~ /[\s|&<>$()]/ ? s.inspect : s }.join " " options end def self.filter_backtrace bt # :nodoc: backtrace_filter.filter bt end ## # Represents anything "runnable", like Test, Spec, Benchmark, or # whatever you can dream up. # # Subclasses of this are automatically registered and available in # Runnable.runnables. class Runnable ## # Number of assertions executed in this run. attr_accessor :assertions ## # An assertion raised during the run, if any. attr_accessor :failures ## # The time it took to run. attr_accessor :time def time_it # :nodoc: t0 = Minitest.clock_time yield ensure self.time = Minitest.clock_time - t0 end ## # Name of the run. def name @NAME end ## # Set the name of the run. def name= o @NAME = o end ## # Returns all instance methods matching the pattern +re+. def self.methods_matching re public_instance_methods(true).grep(re).map(&:to_s) end def self.reset # :nodoc: @@runnables = [] end reset ## # Responsible for running all runnable methods in a given class, # each in its own instance. Each instance is passed to the # reporter to record. def self.run reporter, options = {} filter = options[:filter] || "/./" filter = Regexp.new $1 if filter =~ %r%/(.*)/% filtered_methods = self.runnable_methods.find_all { |m| filter === m || filter === "#{self}##{m}" } exclude = options[:exclude] exclude = Regexp.new $1 if exclude =~ %r%/(.*)/% filtered_methods.delete_if { |m| exclude === m || exclude === "#{self}##{m}" } return if filtered_methods.empty? with_info_handler reporter do filtered_methods.each do |method_name| run_one_method self, method_name, reporter end end end ## # Runs a single method and has the reporter record the result. # This was considered internal API but is factored out of run so # that subclasses can specialize the running of an individual # test. See Minitest::ParallelTest::ClassMethods for an example. def self.run_one_method klass, method_name, reporter reporter.prerecord klass, method_name reporter.record Minitest.run_one_method(klass, method_name) end def self.with_info_handler reporter, &block # :nodoc: handler = lambda do unless reporter.passed? then warn "Current results:" warn "" warn reporter.reporters.first warn "" end end on_signal ::Minitest.info_signal, handler, &block end SIGNALS = Signal.list # :nodoc: def self.on_signal name, action # :nodoc: supported = SIGNALS[name] old_trap = trap name do old_trap.call if old_trap.respond_to? :call action.call end if supported yield ensure trap name, old_trap if supported end ## # Each subclass of Runnable is responsible for overriding this # method to return all runnable methods. See #methods_matching. def self.runnable_methods raise NotImplementedError, "subclass responsibility" end ## # Returns all subclasses of Runnable. def self.runnables @@runnables end @@marshal_dump_warned = false def marshal_dump # :nodoc: unless @@marshal_dump_warned then warn ["Minitest::Runnable#marshal_dump is deprecated.", "You might be violating internals. From", caller.first].join " " @@marshal_dump_warned = true end [self.name, self.failures, self.assertions, self.time] end def marshal_load ary # :nodoc: self.name, self.failures, self.assertions, self.time = ary end def failure # :nodoc: self.failures.first end def initialize name # :nodoc: self.name = name self.failures = [] self.assertions = 0 end ## # Runs a single method. Needs to return self. def run raise NotImplementedError, "subclass responsibility" end ## # Did this run pass? # # Note: skipped runs are not considered passing, but they don't # cause the process to exit non-zero. def passed? raise NotImplementedError, "subclass responsibility" end ## # Returns a single character string to print based on the result # of the run. Eg ".", "F", or "E". def result_code raise NotImplementedError, "subclass responsibility" end ## # Was this run skipped? See #passed? for more information. def skipped? raise NotImplementedError, "subclass responsibility" end end ## # Shared code for anything that can get passed to a Reporter. See # Minitest::Test & Minitest::Result. module Reportable ## # Did this run pass? # # Note: skipped runs are not considered passing, but they don't # cause the process to exit non-zero. def passed? not self.failure end ## # The location identifier of this test. Depends on a method # existing called class_name. def location loc = " [#{self.failure.location}]" unless passed? or error? "#{self.class_name}##{self.name}#{loc}" end def class_name # :nodoc: raise NotImplementedError, "subclass responsibility" end ## # Returns ".", "F", or "E" based on the result of the run. def result_code self.failure and self.failure.result_code or "." end ## # Was this run skipped? def skipped? self.failure and Skip === self.failure end ## # Did this run error? def error? self.failures.any? { |f| UnexpectedError === f } end end ## # This represents a test result in a clean way that can be # marshalled over a wire. Tests can do anything they want to the # test instance and can create conditions that cause Marshal.dump to # blow up. By using Result.from(a_test) you can be reasonably sure # that the test result can be marshalled. class Result < Runnable include Minitest::Reportable undef_method :marshal_dump undef_method :marshal_load ## # The class name of the test result. attr_accessor :klass ## # The location of the test method. attr_accessor :source_location ## # Create a new test result from a Runnable instance. def self.from runnable o = runnable r = self.new o.name r.klass = o.class.name r.assertions = o.assertions r.failures = o.failures.dup r.time = o.time r.source_location = o.method(o.name).source_location rescue ["unknown", -1] r end def class_name # :nodoc: self.klass # for Minitest::Reportable end def to_s # :nodoc: return location if passed? and not skipped? failures.map { |failure| "#{failure.result_label}:\n#{self.location}:\n#{failure.message}\n" }.join "\n" end end ## # Defines the API for Reporters. Subclass this and override whatever # you want. Go nuts. class AbstractReporter include Mutex_m ## # Starts reporting on the run. def start end ## # About to start running a test. This allows a reporter to show # that it is starting or that we are in the middle of a test run. def prerecord klass, name end ## # Record a result and output the Runnable#result_code. Stores the # result of the run if the run did not pass. def record result end ## # Outputs the summary of the run. def report end ## # Did this run pass? def passed? true end end class Reporter < AbstractReporter # :nodoc: ## # The IO used to report. attr_accessor :io ## # Command-line options for this run. attr_accessor :options def initialize io = $stdout, options = {} # :nodoc: super() self.io = io self.options = options end end ## # A very simple reporter that prints the "dots" during the run. # # This is added to the top-level CompositeReporter at the start of # the run. If you want to change the output of minitest via a # plugin, pull this out of the composite and replace it with your # own. class ProgressReporter < Reporter def prerecord klass, name #:nodoc: if options[:verbose] then io.print "%s#%s = " % [klass.name, name] io.flush end end def record result # :nodoc: io.print "%.2f s = " % [result.time] if options[:verbose] io.print result.result_code io.puts if options[:verbose] end end ## # A reporter that gathers statistics about a test run. Does not do # any IO because meant to be used as a parent class for a reporter # that does. # # If you want to create an entirely different type of output (eg, # CI, HTML, etc), this is the place to start. class StatisticsReporter < Reporter # :stopdoc: attr_accessor :assertions attr_accessor :count attr_accessor :results attr_accessor :start_time attr_accessor :total_time attr_accessor :failures attr_accessor :errors attr_accessor :skips # :startdoc: def initialize io = $stdout, options = {} # :nodoc: super self.assertions = 0 self.count = 0 self.results = [] self.start_time = nil self.total_time = nil self.failures = nil self.errors = nil self.skips = nil end def passed? # :nodoc: results.all?(&:skipped?) end def start # :nodoc: self.start_time = Minitest.clock_time end def record result # :nodoc: self.count += 1 self.assertions += result.assertions results << result if not result.passed? or result.skipped? end def report # :nodoc: aggregate = results.group_by { |r| r.failure.class } aggregate.default = [] # dumb. group_by should provide this self.total_time = Minitest.clock_time - start_time self.failures = aggregate[Assertion].size self.errors = aggregate[UnexpectedError].size self.skips = aggregate[Skip].size end end ## # A reporter that prints the header, summary, and failure details at # the end of the run. # # This is added to the top-level CompositeReporter at the start of # the run. If you want to change the output of minitest via a # plugin, pull this out of the composite and replace it with your # own. class SummaryReporter < StatisticsReporter # :stopdoc: attr_accessor :sync attr_accessor :old_sync # :startdoc: def start # :nodoc: super io.puts "Run options: #{options[:args]}" io.puts io.puts "# Running:" io.puts self.sync = io.respond_to? :"sync=" # stupid emacs self.old_sync, io.sync = io.sync, true if self.sync end def report # :nodoc: super io.sync = self.old_sync io.puts unless options[:verbose] # finish the dots io.puts io.puts statistics aggregated_results io io.puts summary end def statistics # :nodoc: "Finished in %.6fs, %.4f runs/s, %.4f assertions/s." % [total_time, count / total_time, assertions / total_time] end def aggregated_results io # :nodoc: filtered_results = results.dup filtered_results.reject!(&:skipped?) unless options[:verbose] filtered_results.each_with_index { |result, i| io.puts "\n%3d) %s" % [i+1, result] } io.puts io end def to_s # :nodoc: aggregated_results(StringIO.new(binary_string)).string end def summary # :nodoc: extra = "" extra = "\n\nYou have skipped tests. Run with --verbose for details." if results.any?(&:skipped?) unless options[:verbose] or ENV["MT_NO_SKIP_MSG"] "%d runs, %d assertions, %d failures, %d errors, %d skips%s" % [count, assertions, failures, errors, skips, extra] end private if '<3'.respond_to? :b def binary_string; ''.b; end else def binary_string; ''.force_encoding(Encoding::ASCII_8BIT); end end end ## # Dispatch to multiple reporters as one. class CompositeReporter < AbstractReporter ## # The list of reporters to dispatch to. attr_accessor :reporters def initialize *reporters # :nodoc: super() self.reporters = reporters end def io # :nodoc: reporters.first.io end ## # Add another reporter to the mix. def << reporter self.reporters << reporter end def passed? # :nodoc: self.reporters.all?(&:passed?) end def start # :nodoc: self.reporters.each(&:start) end def prerecord klass, name # :nodoc: self.reporters.each do |reporter| # TODO: remove conditional for minitest 6 reporter.prerecord klass, name if reporter.respond_to? :prerecord end end def record result # :nodoc: self.reporters.each do |reporter| reporter.record result end end def report # :nodoc: self.reporters.each(&:report) end end ## # Represents run failures. class Assertion < Exception def error # :nodoc: self end ## # Where was this run before an assertion was raised? def location last_before_assertion = "" self.backtrace.reverse_each do |s| break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/ last_before_assertion = s end last_before_assertion.sub(/:in .*$/, "") end def result_code # :nodoc: result_label[0, 1] end def result_label # :nodoc: "Failure" end end ## # Assertion raised when skipping a run. class Skip < Assertion def result_label # :nodoc: "Skipped" end end ## # Assertion wrapping an unexpected error that was raised during a run. class UnexpectedError < Assertion attr_accessor :exception # :nodoc: def initialize exception # :nodoc: super "Unexpected exception" self.exception = exception end def backtrace # :nodoc: self.exception.backtrace end def error # :nodoc: self.exception end def message # :nodoc: bt = Minitest.filter_backtrace(self.backtrace).join "\n " "#{self.exception.class}: #{self.exception.message}\n #{bt}" end def result_label # :nodoc: "Error" end end ## # Provides a simple set of guards that you can use in your tests # to skip execution if it is not applicable. These methods are # mixed into Test as both instance and class methods so you # can use them inside or outside of the test methods. # # def test_something_for_mri # skip "bug 1234" if jruby? # # ... # end # # if windows? then # # ... lots of test methods ... # end module Guard ## # Is this running on jruby? def jruby? platform = RUBY_PLATFORM "java" == platform end ## # Is this running on maglev? def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE "maglev" == platform end ## # Is this running on mri? def mri? platform = RUBY_DESCRIPTION /^ruby/ =~ platform end ## # Is this running on rubinius? def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE "rbx" == platform end ## # Is this running on windows? def windows? platform = RUBY_PLATFORM /mswin|mingw/ =~ platform end end ## # The standard backtrace filter for minitest. # # See Minitest.backtrace_filter=. class BacktraceFilter MT_RE = %r%lib/minitest% #:nodoc: ## # Filter +bt+ to something useful. Returns the whole thing if $DEBUG. def filter bt return ["No backtrace"] unless bt return bt.dup if $DEBUG new_bt = bt.take_while { |line| line !~ MT_RE } new_bt = bt.select { |line| line !~ MT_RE } if new_bt.empty? new_bt = bt.dup if new_bt.empty? new_bt end end self.backtrace_filter = BacktraceFilter.new def self.run_one_method klass, method_name # :nodoc: result = klass.new(method_name).run raise "#{klass}#run _must_ return a Result" unless Result === result result end # :stopdoc: if defined? Process::CLOCK_MONOTONIC # :nodoc: def self.clock_time Process.clock_gettime Process::CLOCK_MONOTONIC end else def self.clock_time Time.now end end class Runnable # re-open def self.inherited klass # :nodoc: self.runnables << klass super end end # :startdoc: end require "minitest/test" PK% ]lrR^CC*gems/minitest-5.11.3/lib/minitest/pride.rbnu[require "minitest" Minitest.load_plugins Minitest::PrideIO.pride! PK% ]<II/gems/minitest-5.11.3/lib/minitest/assertions.rbnu[# encoding: UTF-8 require "rbconfig" require "tempfile" require "stringio" module Minitest ## # Minitest Assertions. All assertion methods accept a +msg+ which is # printed if the assertion fails. # # Protocol: Nearly everything here boils up to +assert+, which # expects to be able to increment an instance accessor named # +assertions+. This is not provided by Assertions and must be # provided by the thing including Assertions. See Minitest::Runnable # for an example. module Assertions UNDEFINED = Object.new # :nodoc: def UNDEFINED.inspect # :nodoc: "UNDEFINED" # again with the rdoc bugs... :( end ## # Returns the diff command to use in #diff. Tries to intelligently # figure out what diff to use. def self.diff @diff = if (RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ && system("diff.exe", __FILE__, __FILE__)) then "diff.exe -u" elsif Minitest::Test.maglev? then "diff -u" elsif system("gdiff", __FILE__, __FILE__) "gdiff -u" # solaris and kin suck elsif system("diff", __FILE__, __FILE__) "diff -u" else nil end unless defined? @diff @diff end ## # Set the diff command to use in #diff. def self.diff= o @diff = o end ## # Returns a diff between +exp+ and +act+. If there is no known # diff command or if it doesn't make sense to diff the output # (single line, short output), then it simply returns a basic # comparison between the two. def diff exp, act expect = mu_pp_for_diff exp butwas = mu_pp_for_diff act result = nil need_to_diff = (expect.include?("\n") || butwas.include?("\n") || expect.size > 30 || butwas.size > 30 || expect == butwas) && Minitest::Assertions.diff return "Expected: #{mu_pp exp}\n Actual: #{mu_pp act}" unless need_to_diff Tempfile.open("expect") do |a| a.puts expect a.flush Tempfile.open("butwas") do |b| b.puts butwas b.flush result = `#{Minitest::Assertions.diff} #{a.path} #{b.path}` result.sub!(/^\-\-\- .+/, "--- expected") result.sub!(/^\+\+\+ .+/, "+++ actual") if result.empty? then klass = exp.class result = [ "No visible difference in the #{klass}#inspect output.\n", "You should look at the implementation of #== on ", "#{klass} or its members.\n", expect, ].join end end end result end ## # This returns a human-readable version of +obj+. By default # #inspect is called. You can override this to use #pretty_print # if you want. def mu_pp obj s = obj.inspect if defined? Encoding then s = s.encode Encoding.default_external if String === obj && obj.encoding != Encoding.default_external then s = "# encoding: #{obj.encoding}\n#{s}" end end s end ## # This returns a diff-able human-readable version of +obj+. This # differs from the regular mu_pp because it expands escaped # newlines and makes hex-values generic (like object_ids). This # uses mu_pp to do the first pass and then cleans it up. def mu_pp_for_diff obj mu_pp(obj).gsub(/\\n/, "\n").gsub(/:0x[a-fA-F0-9]{4,}/m, ":0xXXXXXX") end ## # Fails unless +test+ is truthy. def assert test, msg = nil self.assertions += 1 unless test then msg ||= "Expected #{mu_pp test} to be truthy." msg = msg.call if Proc === msg raise Minitest::Assertion, msg end true end def _synchronize # :nodoc: yield end ## # Fails unless +obj+ is empty. def assert_empty obj, msg = nil msg = message(msg) { "Expected #{mu_pp(obj)} to be empty" } assert_respond_to obj, :empty? assert obj.empty?, msg end E = "" # :nodoc: ## # Fails unless exp == act printing the difference between # the two, if possible. # # If there is no visible difference but the assertion fails, you # should suspect that your #== is buggy, or your inspect output is # missing crucial details. For nicer structural diffing, set # Minitest::Test.make_my_diffs_pretty! # # For floats use assert_in_delta. # # See also: Minitest::Assertions.diff def assert_equal exp, act, msg = nil msg = message(msg, E) { diff exp, act } result = assert exp == act, msg if nil == exp then if Minitest::VERSION =~ /^6/ then refute_nil exp, "Use assert_nil if expecting nil." else where = Minitest.filter_backtrace(caller).first where = where.split(/:in /, 2).first # clean up noise warn "DEPRECATED: Use assert_nil if expecting nil from #{where}. This will fail in Minitest 6." end end result end ## # For comparing Floats. Fails unless +exp+ and +act+ are within +delta+ # of each other. # # assert_in_delta Math::PI, (22.0 / 7.0), 0.01 def assert_in_delta exp, act, delta = 0.001, msg = nil n = (exp - act).abs msg = message(msg) { "Expected |#{exp} - #{act}| (#{n}) to be <= #{delta}" } assert delta >= n, msg end ## # For comparing Floats. Fails unless +exp+ and +act+ have a relative # error less than +epsilon+. def assert_in_epsilon exp, act, epsilon = 0.001, msg = nil assert_in_delta exp, act, [exp.abs, act.abs].min * epsilon, msg end ## # Fails unless +collection+ includes +obj+. def assert_includes collection, obj, msg = nil msg = message(msg) { "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}" } assert_respond_to collection, :include? assert collection.include?(obj), msg end ## # Fails unless +obj+ is an instance of +cls+. def assert_instance_of cls, obj, msg = nil msg = message(msg) { "Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}" } assert obj.instance_of?(cls), msg end ## # Fails unless +obj+ is a kind of +cls+. def assert_kind_of cls, obj, msg = nil msg = message(msg) { "Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" } assert obj.kind_of?(cls), msg end ## # Fails unless +matcher+ =~ +obj+. def assert_match matcher, obj, msg = nil msg = message(msg) { "Expected #{mu_pp matcher} to match #{mu_pp obj}" } assert_respond_to matcher, :"=~" matcher = Regexp.new Regexp.escape matcher if String === matcher assert matcher =~ obj, msg end ## # Fails unless +obj+ is nil def assert_nil obj, msg = nil msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" } assert obj.nil?, msg end ## # For testing with binary operators. Eg: # # assert_operator 5, :<=, 4 def assert_operator o1, op, o2 = UNDEFINED, msg = nil return assert_predicate o1, op, msg if UNDEFINED == o2 msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" } assert o1.__send__(op, o2), msg end ## # Fails if stdout or stderr do not output the expected results. # Pass in nil if you don't care about that streams output. Pass in # "" if you require it to be silent. Pass in a regexp if you want # to pattern match. # # assert_output(/hey/) { method_with_output } # # NOTE: this uses #capture_io, not #capture_subprocess_io. # # See also: #assert_silent def assert_output stdout = nil, stderr = nil out, err = capture_io do yield end err_msg = Regexp === stderr ? :assert_match : :assert_equal if stderr out_msg = Regexp === stdout ? :assert_match : :assert_equal if stdout y = send err_msg, stderr, err, "In stderr" if err_msg x = send out_msg, stdout, out, "In stdout" if out_msg (!stdout || x) && (!stderr || y) end ## # For testing with predicates. Eg: # # assert_predicate str, :empty? # # This is really meant for specs and is front-ended by assert_operator: # # str.must_be :empty? def assert_predicate o1, op, msg = nil msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op}" } assert o1.__send__(op), msg end ## # Fails unless the block raises one of +exp+. Returns the # exception matched so you can check the message, attributes, etc. # # +exp+ takes an optional message on the end to help explain # failures and defaults to StandardError if no exception class is # passed. def assert_raises *exp msg = "#{exp.pop}.\n" if String === exp.last exp << StandardError if exp.empty? begin yield rescue *exp => e pass # count assertion return e rescue Minitest::Skip, Minitest::Assertion # don't count assertion raise rescue SignalException, SystemExit raise rescue Exception => e flunk proc { exception_details(e, "#{msg}#{mu_pp(exp)} exception expected, not") } end exp = exp.first if exp.size == 1 flunk "#{msg}#{mu_pp(exp)} expected but nothing was raised." end ## # Fails unless +obj+ responds to +meth+. def assert_respond_to obj, meth, msg = nil msg = message(msg) { "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}" } assert obj.respond_to?(meth), msg end ## # Fails unless +exp+ and +act+ are #equal? def assert_same exp, act, msg = nil msg = message(msg) { data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id] "Expected %s (oid=%d) to be the same as %s (oid=%d)" % data } assert exp.equal?(act), msg end ## # +send_ary+ is a receiver, message and arguments. # # Fails unless the call returns a true value def assert_send send_ary, m = nil where = Minitest.filter_backtrace(caller).first where = where.split(/:in /, 2).first # clean up noise warn "DEPRECATED: assert_send. From #{where}" recv, msg, *args = send_ary m = message(m) { "Expected #{mu_pp(recv)}.#{msg}(*#{mu_pp(args)}) to return true" } assert recv.__send__(msg, *args), m end ## # Fails if the block outputs anything to stderr or stdout. # # See also: #assert_output def assert_silent assert_output "", "" do yield end end ## # Fails unless the block throws +sym+ def assert_throws sym, msg = nil default = "Expected #{mu_pp(sym)} to have been thrown" caught = true catch(sym) do begin yield rescue ThreadError => e # wtf?!? 1.8 + threads == suck default += ", not \:#{e.message[/uncaught throw \`(\w+?)\'/, 1]}" rescue ArgumentError => e # 1.9 exception raise e unless e.message.include?("uncaught throw") default += ", not #{e.message.split(/ /).last}" rescue NameError => e # 1.8 exception raise e unless e.name == sym default += ", not #{e.name.inspect}" end caught = false end assert caught, message(msg) { default } end ## # Captures $stdout and $stderr into strings: # # out, err = capture_io do # puts "Some info" # warn "You did a bad thing" # end # # assert_match %r%info%, out # assert_match %r%bad%, err # # NOTE: For efficiency, this method uses StringIO and does not # capture IO for subprocesses. Use #capture_subprocess_io for # that. def capture_io _synchronize do begin captured_stdout, captured_stderr = StringIO.new, StringIO.new orig_stdout, orig_stderr = $stdout, $stderr $stdout, $stderr = captured_stdout, captured_stderr yield return captured_stdout.string, captured_stderr.string ensure $stdout = orig_stdout $stderr = orig_stderr end end end ## # Captures $stdout and $stderr into strings, using Tempfile to # ensure that subprocess IO is captured as well. # # out, err = capture_subprocess_io do # system "echo Some info" # system "echo You did a bad thing 1>&2" # end # # assert_match %r%info%, out # assert_match %r%bad%, err # # NOTE: This method is approximately 10x slower than #capture_io so # only use it when you need to test the output of a subprocess. def capture_subprocess_io _synchronize do begin require "tempfile" captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err") orig_stdout, orig_stderr = $stdout.dup, $stderr.dup $stdout.reopen captured_stdout $stderr.reopen captured_stderr yield $stdout.rewind $stderr.rewind return captured_stdout.read, captured_stderr.read ensure captured_stdout.unlink captured_stderr.unlink $stdout.reopen orig_stdout $stderr.reopen orig_stderr end end end ## # Returns details for exception +e+ def exception_details e, msg [ "#{msg}", "Class: <#{e.class}>", "Message: <#{e.message.inspect}>", "---Backtrace---", "#{Minitest.filter_backtrace(e.backtrace).join("\n")}", "---------------", ].join "\n" end ## # Fails with +msg+ def flunk msg = nil msg ||= "Epic Fail!" assert false, msg end ## # Returns a proc that will output +msg+ along with the default message. def message msg = nil, ending = nil, &default proc { msg = msg.call.chomp(".") if Proc === msg custom_message = "#{msg}.\n" unless msg.nil? or msg.to_s.empty? "#{custom_message}#{default.call}#{ending || "."}" } end ## # used for counting assertions def pass _msg = nil assert true end ## # Fails if +test+ is truthy. def refute test, msg = nil msg ||= message { "Expected #{mu_pp(test)} to not be truthy" } not assert !test, msg end ## # Fails if +obj+ is empty. def refute_empty obj, msg = nil msg = message(msg) { "Expected #{mu_pp(obj)} to not be empty" } assert_respond_to obj, :empty? refute obj.empty?, msg end ## # Fails if exp == act. # # For floats use refute_in_delta. def refute_equal exp, act, msg = nil msg = message(msg) { "Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}" } refute exp == act, msg end ## # For comparing Floats. Fails if +exp+ is within +delta+ of +act+. # # refute_in_delta Math::PI, (22.0 / 7.0) def refute_in_delta exp, act, delta = 0.001, msg = nil n = (exp - act).abs msg = message(msg) { "Expected |#{exp} - #{act}| (#{n}) to not be <= #{delta}" } refute delta >= n, msg end ## # For comparing Floats. Fails if +exp+ and +act+ have a relative error # less than +epsilon+. def refute_in_epsilon a, b, epsilon = 0.001, msg = nil refute_in_delta a, b, a * epsilon, msg end ## # Fails if +collection+ includes +obj+. def refute_includes collection, obj, msg = nil msg = message(msg) { "Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}" } assert_respond_to collection, :include? refute collection.include?(obj), msg end ## # Fails if +obj+ is an instance of +cls+. def refute_instance_of cls, obj, msg = nil msg = message(msg) { "Expected #{mu_pp(obj)} to not be an instance of #{cls}" } refute obj.instance_of?(cls), msg end ## # Fails if +obj+ is a kind of +cls+. def refute_kind_of cls, obj, msg = nil msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" } refute obj.kind_of?(cls), msg end ## # Fails if +matcher+ =~ +obj+. def refute_match matcher, obj, msg = nil msg = message(msg) { "Expected #{mu_pp matcher} to not match #{mu_pp obj}" } assert_respond_to matcher, :"=~" matcher = Regexp.new Regexp.escape matcher if String === matcher refute matcher =~ obj, msg end ## # Fails if +obj+ is nil. def refute_nil obj, msg = nil msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" } refute obj.nil?, msg end ## # Fails if +o1+ is not +op+ +o2+. Eg: # # refute_operator 1, :>, 2 #=> pass # refute_operator 1, :<, 2 #=> fail def refute_operator o1, op, o2 = UNDEFINED, msg = nil return refute_predicate o1, op, msg if UNDEFINED == o2 msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}" } refute o1.__send__(op, o2), msg end ## # For testing with predicates. # # refute_predicate str, :empty? # # This is really meant for specs and is front-ended by refute_operator: # # str.wont_be :empty? def refute_predicate o1, op, msg = nil msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op}" } refute o1.__send__(op), msg end ## # Fails if +obj+ responds to the message +meth+. def refute_respond_to obj, meth, msg = nil msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" } refute obj.respond_to?(meth), msg end ## # Fails if +exp+ is the same (by object identity) as +act+. def refute_same exp, act, msg = nil msg = message(msg) { data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id] "Expected %s (oid=%d) to not be the same as %s (oid=%d)" % data } refute exp.equal?(act), msg end ## # Skips the current run. If run in verbose-mode, the skipped run # gets listed at the end of the run but doesn't cause a failure # exit code. def skip msg = nil, bt = caller msg ||= "Skipped, no message given" @skip = true raise Minitest::Skip, msg, bt end ## # Was this testcase skipped? Meant for #teardown. def skipped? defined?(@skip) and @skip end end end PK% ]+**)gems/minitest-5.11.3/lib/minitest/test.rbnu[require "minitest" unless defined? Minitest::Runnable module Minitest ## # Subclass Test to create your own tests. Typically you'll want a # Test subclass per implementation class. # # See Minitest::Assertions class Test < Runnable require "minitest/assertions" include Minitest::Assertions include Minitest::Reportable def class_name # :nodoc: self.class.name # for Minitest::Reportable end PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, SystemExit] # :nodoc: # :stopdoc: class << self; attr_accessor :io_lock; end self.io_lock = Mutex.new # :startdoc: ## # Call this at the top of your tests when you absolutely # positively need to have ordered tests. In doing so, you're # admitting that you suck and your tests are weak. def self.i_suck_and_my_tests_are_order_dependent! class << self undef_method :test_order if method_defined? :test_order define_method :test_order do :alpha end end end ## # Make diffs for this Test use #pretty_inspect so that diff # in assert_equal can have more details. NOTE: this is much slower # than the regular inspect but much more usable for complex # objects. def self.make_my_diffs_pretty! require "pp" define_method :mu_pp, &:pretty_inspect end ## # Call this at the top of your tests when you want to run your # tests in parallel. In doing so, you're admitting that you rule # and your tests are awesome. def self.parallelize_me! include Minitest::Parallel::Test extend Minitest::Parallel::Test::ClassMethods end ## # Returns all instance methods starting with "test_". Based on # #test_order, the methods are either sorted, randomized # (default), or run in parallel. def self.runnable_methods methods = methods_matching(/^test_/) case self.test_order when :random, :parallel then max = methods.size methods.sort.sort_by { rand max } when :alpha, :sorted then methods.sort else raise "Unknown test_order: #{self.test_order.inspect}" end end ## # Defines the order to run tests (:random by default). Override # this or use a convenience method to change it for your tests. def self.test_order :random end TEARDOWN_METHODS = %w[ before_teardown teardown after_teardown ] # :nodoc: ## # Runs a single test with setup/teardown hooks. def run with_info_handler do time_it do capture_exceptions do before_setup; setup; after_setup self.send self.name end TEARDOWN_METHODS.each do |hook| capture_exceptions do self.send hook end end end end Result.from self # per contract end ## # Provides before/after hooks for setup and teardown. These are # meant for library writers, NOT for regular test authors. See # #before_setup for an example. module LifecycleHooks ## # Runs before every test, before setup. This hook is meant for # libraries to extend minitest. It is not meant to be used by # test developers. # # As a simplistic example: # # module MyMinitestPlugin # def before_setup # super # # ... stuff to do before setup is run # end # # def after_setup # # ... stuff to do after setup is run # super # end # # def before_teardown # super # # ... stuff to do before teardown is run # end # # def after_teardown # # ... stuff to do after teardown is run # super # end # end # # class MiniTest::Test # include MyMinitestPlugin # end def before_setup; end ## # Runs before every test. Use this to set up before each test # run. def setup; end ## # Runs before every test, after setup. This hook is meant for # libraries to extend minitest. It is not meant to be used by # test developers. # # See #before_setup for an example. def after_setup; end ## # Runs after every test, before teardown. This hook is meant for # libraries to extend minitest. It is not meant to be used by # test developers. # # See #before_setup for an example. def before_teardown; end ## # Runs after every test. Use this to clean up after each test # run. def teardown; end ## # Runs after every test, after teardown. This hook is meant for # libraries to extend minitest. It is not meant to be used by # test developers. # # See #before_setup for an example. def after_teardown; end end # LifecycleHooks def capture_exceptions # :nodoc: yield rescue *PASSTHROUGH_EXCEPTIONS raise rescue Assertion => e self.failures << e rescue Exception => e self.failures << UnexpectedError.new(e) end def with_info_handler &block # :nodoc: t0 = Minitest.clock_time handler = lambda do warn "\nCurrent: %s#%s %.2fs" % [self.class, self.name, Minitest.clock_time - t0] end self.class.on_signal ::Minitest.info_signal, handler, &block end include LifecycleHooks include Guard extend Guard end # Test end require "minitest/unit" unless defined?(MiniTest) # compatibility layer only PK% ]Us//.gems/minitest-5.11.3/lib/minitest/benchmark.rbnu[require "minitest/test" require "minitest/spec" module Minitest ## # Subclass Benchmark to create your own benchmark runs. Methods # starting with "bench_" get executed on a per-class. # # See Minitest::Assertions class Benchmark < Test def self.io # :nodoc: @io end def io # :nodoc: self.class.io end def self.run reporter, options = {} # :nodoc: @io = reporter.io super end def self.runnable_methods # :nodoc: methods_matching(/^bench_/) end ## # Returns a set of ranges stepped exponentially from +min+ to # +max+ by powers of +base+. Eg: # # bench_exp(2, 16, 2) # => [2, 4, 8, 16] def self.bench_exp min, max, base = 10 min = (Math.log10(min) / Math.log10(base)).to_i max = (Math.log10(max) / Math.log10(base)).to_i (min..max).map { |m| base ** m }.to_a end ## # Returns a set of ranges stepped linearly from +min+ to +max+ by # +step+. Eg: # # bench_linear(20, 40, 10) # => [20, 30, 40] def self.bench_linear min, max, step = 10 (min..max).step(step).to_a rescue LocalJumpError # 1.8.6 r = []; (min..max).step(step) { |n| r << n }; r end ## # Specifies the ranges used for benchmarking for that class. # Defaults to exponential growth from 1 to 10k by powers of 10. # Override if you need different ranges for your benchmarks. # # See also: ::bench_exp and ::bench_linear. def self.bench_range bench_exp 1, 10_000 end ## # Runs the given +work+, gathering the times of each run. Range # and times are then passed to a given +validation+ proc. Outputs # the benchmark name and times in tab-separated format, making it # easy to paste into a spreadsheet for graphing or further # analysis. # # Ranges are specified by ::bench_range. # # Eg: # # def bench_algorithm # validation = proc { |x, y| ... } # assert_performance validation do |n| # @obj.algorithm(n) # end # end def assert_performance validation, &work range = self.class.bench_range io.print "#{self.name}" times = [] range.each do |x| GC.start t0 = Minitest.clock_time instance_exec(x, &work) t = Minitest.clock_time - t0 io.print "\t%9.6f" % t times << t end io.puts validation[range, times] end ## # Runs the given +work+ and asserts that the times gathered fit to # match a constant rate (eg, linear slope == 0) within a given # +threshold+. Note: because we're testing for a slope of 0, R^2 # is not a good determining factor for the fit, so the threshold # is applied against the slope itself. As such, you probably want # to tighten it from the default. # # See http://www.graphpad.com/curvefit/goodness_of_fit.htm for # more details. # # Fit is calculated by #fit_linear. # # Ranges are specified by ::bench_range. # # Eg: # # def bench_algorithm # assert_performance_constant 0.9999 do |n| # @obj.algorithm(n) # end # end def assert_performance_constant threshold = 0.99, &work validation = proc do |range, times| a, b, rr = fit_linear range, times assert_in_delta 0, b, 1 - threshold [a, b, rr] end assert_performance validation, &work end ## # Runs the given +work+ and asserts that the times gathered fit to # match a exponential curve within a given error +threshold+. # # Fit is calculated by #fit_exponential. # # Ranges are specified by ::bench_range. # # Eg: # # def bench_algorithm # assert_performance_exponential 0.9999 do |n| # @obj.algorithm(n) # end # end def assert_performance_exponential threshold = 0.99, &work assert_performance validation_for_fit(:exponential, threshold), &work end ## # Runs the given +work+ and asserts that the times gathered fit to # match a logarithmic curve within a given error +threshold+. # # Fit is calculated by #fit_logarithmic. # # Ranges are specified by ::bench_range. # # Eg: # # def bench_algorithm # assert_performance_logarithmic 0.9999 do |n| # @obj.algorithm(n) # end # end def assert_performance_logarithmic threshold = 0.99, &work assert_performance validation_for_fit(:logarithmic, threshold), &work end ## # Runs the given +work+ and asserts that the times gathered fit to # match a straight line within a given error +threshold+. # # Fit is calculated by #fit_linear. # # Ranges are specified by ::bench_range. # # Eg: # # def bench_algorithm # assert_performance_linear 0.9999 do |n| # @obj.algorithm(n) # end # end def assert_performance_linear threshold = 0.99, &work assert_performance validation_for_fit(:linear, threshold), &work end ## # Runs the given +work+ and asserts that the times gathered curve # fit to match a power curve within a given error +threshold+. # # Fit is calculated by #fit_power. # # Ranges are specified by ::bench_range. # # Eg: # # def bench_algorithm # assert_performance_power 0.9999 do |x| # @obj.algorithm # end # end def assert_performance_power threshold = 0.99, &work assert_performance validation_for_fit(:power, threshold), &work end ## # Takes an array of x/y pairs and calculates the general R^2 value. # # See: http://en.wikipedia.org/wiki/Coefficient_of_determination def fit_error xys y_bar = sigma(xys) { |_, y| y } / xys.size.to_f ss_tot = sigma(xys) { |_, y| (y - y_bar) ** 2 } ss_err = sigma(xys) { |x, y| (yield(x) - y) ** 2 } 1 - (ss_err / ss_tot) end ## # To fit a functional form: y = ae^(bx). # # Takes x and y values and returns [a, b, r^2]. # # See: http://mathworld.wolfram.com/LeastSquaresFittingExponential.html def fit_exponential xs, ys n = xs.size xys = xs.zip(ys) sxlny = sigma(xys) { |x, y| x * Math.log(y) } slny = sigma(xys) { |_, y| Math.log(y) } sx2 = sigma(xys) { |x, _| x * x } sx = sigma xs c = n * sx2 - sx ** 2 a = (slny * sx2 - sx * sxlny) / c b = ( n * sxlny - sx * slny ) / c return Math.exp(a), b, fit_error(xys) { |x| Math.exp(a + b * x) } end ## # To fit a functional form: y = a + b*ln(x). # # Takes x and y values and returns [a, b, r^2]. # # See: http://mathworld.wolfram.com/LeastSquaresFittingLogarithmic.html def fit_logarithmic xs, ys n = xs.size xys = xs.zip(ys) slnx2 = sigma(xys) { |x, _| Math.log(x) ** 2 } slnx = sigma(xys) { |x, _| Math.log(x) } sylnx = sigma(xys) { |x, y| y * Math.log(x) } sy = sigma(xys) { |_, y| y } c = n * slnx2 - slnx ** 2 b = ( n * sylnx - sy * slnx ) / c a = (sy - b * slnx) / n return a, b, fit_error(xys) { |x| a + b * Math.log(x) } end ## # Fits the functional form: a + bx. # # Takes x and y values and returns [a, b, r^2]. # # See: http://mathworld.wolfram.com/LeastSquaresFitting.html def fit_linear xs, ys n = xs.size xys = xs.zip(ys) sx = sigma xs sy = sigma ys sx2 = sigma(xs) { |x| x ** 2 } sxy = sigma(xys) { |x, y| x * y } c = n * sx2 - sx**2 a = (sy * sx2 - sx * sxy) / c b = ( n * sxy - sx * sy ) / c return a, b, fit_error(xys) { |x| a + b * x } end ## # To fit a functional form: y = ax^b. # # Takes x and y values and returns [a, b, r^2]. # # See: http://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html def fit_power xs, ys n = xs.size xys = xs.zip(ys) slnxlny = sigma(xys) { |x, y| Math.log(x) * Math.log(y) } slnx = sigma(xs) { |x | Math.log(x) } slny = sigma(ys) { | y| Math.log(y) } slnx2 = sigma(xs) { |x | Math.log(x) ** 2 } b = (n * slnxlny - slnx * slny) / (n * slnx2 - slnx ** 2) a = (slny - b * slnx) / n return Math.exp(a), b, fit_error(xys) { |x| (Math.exp(a) * (x ** b)) } end ## # Enumerates over +enum+ mapping +block+ if given, returning the # sum of the result. Eg: # # sigma([1, 2, 3]) # => 1 + 2 + 3 => 6 # sigma([1, 2, 3]) { |n| n ** 2 } # => 1 + 4 + 9 => 14 def sigma enum, &block enum = enum.map(&block) if block enum.inject { |sum, n| sum + n } end ## # Returns a proc that calls the specified fit method and asserts # that the error is within a tolerable threshold. def validation_for_fit msg, threshold proc do |range, times| a, b, rr = send "fit_#{msg}", range, times assert_operator rr, :>=, threshold [a, b, rr] end end end end module Minitest ## # The spec version of Minitest::Benchmark. class BenchSpec < Benchmark extend Minitest::Spec::DSL ## # This is used to define a new benchmark method. You usually don't # use this directly and is intended for those needing to write new # performance curve fits (eg: you need a specific polynomial fit). # # See ::bench_performance_linear for an example of how to use this. def self.bench name, &block define_method "bench_#{name.gsub(/\W+/, "_")}", &block end ## # Specifies the ranges used for benchmarking for that class. # # bench_range do # bench_exp(2, 16, 2) # end # # See Minitest::Benchmark#bench_range for more details. def self.bench_range &block return super unless block meta = (class << self; self; end) meta.send :define_method, "bench_range", &block end ## # Create a benchmark that verifies that the performance is linear. # # describe "my class Bench" do # bench_performance_linear "fast_algorithm", 0.9999 do |n| # @obj.fast_algorithm(n) # end # end def self.bench_performance_linear name, threshold = 0.99, &work bench name do assert_performance_linear threshold, &work end end ## # Create a benchmark that verifies that the performance is constant. # # describe "my class Bench" do # bench_performance_constant "zoom_algorithm!" do |n| # @obj.zoom_algorithm!(n) # end # end def self.bench_performance_constant name, threshold = 0.99, &work bench name do assert_performance_constant threshold, &work end end ## # Create a benchmark that verifies that the performance is exponential. # # describe "my class Bench" do # bench_performance_exponential "algorithm" do |n| # @obj.algorithm(n) # end # end def self.bench_performance_exponential name, threshold = 0.99, &work bench name do assert_performance_exponential threshold, &work end end ## # Create a benchmark that verifies that the performance is logarithmic. # # describe "my class Bench" do # bench_performance_logarithmic "algorithm" do |n| # @obj.algorithm(n) # end # end def self.bench_performance_logarithmic name, threshold = 0.99, &work bench name do assert_performance_logarithmic threshold, &work end end ## # Create a benchmark that verifies that the performance is power. # # describe "my class Bench" do # bench_performance_power "algorithm" do |n| # @obj.algorithm(n) # end # end def self.bench_performance_power name, threshold = 0.99, &work bench name do assert_performance_power threshold, &work end end end Minitest::Spec.register_spec_type(/Bench(mark)?$/, Minitest::BenchSpec) end PK% ]y)gems/minitest-5.11.3/lib/minitest/unit.rbnu[# :stopdoc: unless defined?(Minitest) then # all of this crap is just to avoid circular requires and is only # needed if a user requires "minitest/unit" directly instead of # "minitest/autorun", so we also warn from = caller.reject { |s| s =~ /rubygems/ }.join("\n ") warn "Warning: you should require 'minitest/autorun' instead." warn %(Warning: or add 'gem "minitest"' before 'require "minitest/autorun"') warn "From:\n #{from}" module Minitest; end MiniTest = Minitest # prevents minitest.rb from requiring back to us require "minitest" end MiniTest = Minitest unless defined?(MiniTest) module Minitest class Unit VERSION = Minitest::VERSION class TestCase < Minitest::Test def self.inherited klass # :nodoc: from = caller.first warn "MiniTest::Unit::TestCase is now Minitest::Test. From #{from}" super end end def self.autorun # :nodoc: from = caller.first warn "MiniTest::Unit.autorun is now Minitest.autorun. From #{from}" Minitest.autorun end def self.after_tests &b # :nodoc: from = caller.first warn "MiniTest::Unit.after_tests is now Minitest.after_run. From #{from}" Minitest.after_run(&b) end end end # :startdoc: PK% ]/w[NN)gems/minitest-5.11.3/lib/minitest/mock.rbnu[class MockExpectationError < StandardError; end # :nodoc: module Minitest # :nodoc: ## # A simple and clean mock object framework. # # All mock objects are an instance of Mock class Mock alias :__respond_to? :respond_to? overridden_methods = %w[ === class inspect instance_eval instance_variables object_id public_send respond_to_missing? send to_s ] instance_methods.each do |m| undef_method m unless overridden_methods.include?(m.to_s) || m =~ /^__/ end overridden_methods.map(&:to_sym).each do |method_id| define_method method_id do |*args, &b| if @expected_calls.key? method_id then method_missing(method_id, *args, &b) else super(*args, &b) end end end def initialize delegator = nil # :nodoc: @delegator = delegator @expected_calls = Hash.new { |calls, name| calls[name] = [] } @actual_calls = Hash.new { |calls, name| calls[name] = [] } end ## # Expect that method +name+ is called, optionally with +args+ or a # +blk+, and returns +retval+. # # @mock.expect(:meaning_of_life, 42) # @mock.meaning_of_life # => 42 # # @mock.expect(:do_something_with, true, [some_obj, true]) # @mock.do_something_with(some_obj, true) # => true # # @mock.expect(:do_something_else, true) do |a1, a2| # a1 == "buggs" && a2 == :bunny # end # # +args+ is compared to the expected args using case equality (ie, the # '===' operator), allowing for less specific expectations. # # @mock.expect(:uses_any_string, true, [String]) # @mock.uses_any_string("foo") # => true # @mock.verify # => true # # @mock.expect(:uses_one_string, true, ["foo"]) # @mock.uses_one_string("bar") # => raises MockExpectationError # # If a method will be called multiple times, specify a new expect for each one. # They will be used in the order you define them. # # @mock.expect(:ordinal_increment, 'first') # @mock.expect(:ordinal_increment, 'second') # # @mock.ordinal_increment # => 'first' # @mock.ordinal_increment # => 'second' # @mock.ordinal_increment # => raises MockExpectationError "No more expects available for :ordinal_increment" # def expect name, retval, args = [], &blk name = name.to_sym if block_given? raise ArgumentError, "args ignored when block given" unless args.empty? @expected_calls[name] << { :retval => retval, :block => blk } else raise ArgumentError, "args must be an array" unless Array === args @expected_calls[name] << { :retval => retval, :args => args } end self end def __call name, data # :nodoc: case data when Hash then "#{name}(#{data[:args].inspect[1..-2]}) => #{data[:retval].inspect}" else data.map { |d| __call name, d }.join ", " end end ## # Verify that all methods were called as expected. Raises # +MockExpectationError+ if the mock object was not called as # expected. def verify @expected_calls.each do |name, expected| actual = @actual_calls.fetch(name, nil) raise MockExpectationError, "expected #{__call name, expected[0]}" unless actual raise MockExpectationError, "expected #{__call name, expected[actual.size]}, got [#{__call name, actual}]" if actual.size < expected.size end true end def method_missing sym, *args, &block # :nodoc: unless @expected_calls.key?(sym) then if @delegator && @delegator.respond_to?(sym) return @delegator.public_send(sym, *args, &block) else raise NoMethodError, "unmocked method %p, expected one of %p" % [sym, @expected_calls.keys.sort_by(&:to_s)] end end index = @actual_calls[sym].length expected_call = @expected_calls[sym][index] unless expected_call then raise MockExpectationError, "No more expects available for %p: %p" % [sym, args] end expected_args, retval, val_block = expected_call.values_at(:args, :retval, :block) if val_block then # keep "verify" happy @actual_calls[sym] << expected_call raise MockExpectationError, "mocked method %p failed block w/ %p" % [sym, args] unless val_block.call(*args, &block) return retval end if expected_args.size != args.size then raise ArgumentError, "mocked method %p expects %d arguments, got %d" % [sym, expected_args.size, args.size] end zipped_args = expected_args.zip(args) fully_matched = zipped_args.all? { |mod, a| mod === a or mod == a } unless fully_matched then raise MockExpectationError, "mocked method %p called with unexpected arguments %p" % [sym, args] end @actual_calls[sym] << { :retval => retval, :args => zipped_args.map! { |mod, a| mod === a ? mod : a }, } retval end def respond_to? sym, include_private = false # :nodoc: return true if @expected_calls.key? sym.to_sym return true if @delegator && @delegator.respond_to?(sym, include_private) __respond_to?(sym, include_private) end end end module Minitest::Assertions ## # Assert that the mock verifies correctly. def assert_mock mock assert mock.verify end end ## # Object extensions for Minitest::Mock. class Object ## # Add a temporary stubbed method replacing +name+ for the duration # of the +block+. If +val_or_callable+ responds to #call, then it # returns the result of calling it, otherwise returns the value # as-is. If stubbed method yields a block, +block_args+ will be # passed along. Cleans up the stub at the end of the +block+. The # method +name+ must exist before stubbing. # # def test_stale_eh # obj_under_test = Something.new # refute obj_under_test.stale? # # Time.stub :now, Time.at(0) do # assert obj_under_test.stale? # end # end # def stub name, val_or_callable, *block_args new_name = "__minitest_stub__#{name}" metaclass = class << self; self; end if respond_to? name and not methods.map(&:to_s).include? name.to_s then metaclass.send :define_method, name do |*args| super(*args) end end metaclass.send :alias_method, new_name, name metaclass.send :define_method, name do |*args, &blk| if val_or_callable.respond_to? :call then val_or_callable.call(*args, &blk) else blk.call(*block_args) if blk val_or_callable end end yield self ensure metaclass.send :undef_method, name metaclass.send :alias_method, name, new_name metaclass.send :undef_method, new_name end end PK% ]_cGG-gems/minitest-5.11.3/lib/minitest/parallel.rbnu[module Minitest module Parallel #:nodoc: ## # The engine used to run multiple tests in parallel. class Executor ## # The size of the pool of workers. attr_reader :size ## # Create a parallel test executor of with +size+ workers. def initialize size @size = size @queue = Queue.new @pool = nil end ## # Start the executor def start @pool = size.times.map { Thread.new(@queue) do |queue| Thread.current.abort_on_exception = true while (job = queue.pop) klass, method, reporter = job reporter.synchronize { reporter.prerecord klass, method } result = Minitest.run_one_method klass, method reporter.synchronize { reporter.record result } end end } end ## # Add a job to the queue def << work; @queue << work; end ## # Shuts down the pool of workers by signalling them to quit and # waiting for them all to finish what they're currently working # on. def shutdown size.times { @queue << nil } @pool.each(&:join) end end module Test # :nodoc: def _synchronize; Minitest::Test.io_lock.synchronize { yield }; end # :nodoc: module ClassMethods # :nodoc: def run_one_method klass, method_name, reporter Minitest.parallel_executor << [klass, method_name, reporter] end def test_order :parallel end end end end end PK% ]oz)gems/minitest-5.11.3/lib/minitest/hell.rbnu[require "minitest/parallel" class Minitest::Test parallelize_me! end begin require "minitest/proveit" rescue LoadError warn "NOTE: `gem install minitest-proveit` for even more hellish tests" end PK% ]9M M 1gems/minitest-5.11.3/lib/minitest/pride_plugin.rbnu[require "minitest" module Minitest def self.plugin_pride_options opts, _options # :nodoc: opts.on "-p", "--pride", "Pride. Show your testing pride!" do PrideIO.pride! end end def self.plugin_pride_init options # :nodoc: if PrideIO.pride? then klass = ENV["TERM"] =~ /^xterm|-256color$/ ? PrideLOL : PrideIO io = klass.new options[:io] self.reporter.reporters.grep(Minitest::Reporter).each do |rep| rep.io = io if rep.io.tty? end end end ## # Show your testing pride! class PrideIO ## # Activate the pride plugin. Called from both -p option and minitest/pride def self.pride! @pride = true end ## # Are we showing our testing pride? def self.pride? @pride ||= false end # Start an escape sequence ESC = "\e[" # End the escape sequence NND = "#{ESC}0m" # The IO we're going to pipe through. attr_reader :io def initialize io # :nodoc: @io = io # stolen from /System/Library/Perl/5.10.0/Term/ANSIColor.pm # also reference http://en.wikipedia.org/wiki/ANSI_escape_code @colors ||= (31..36).to_a @size = @colors.size @index = 0 end ## # Wrap print to colorize the output. def print o case o when "." then io.print pride o when "E", "F" then io.print "#{ESC}41m#{ESC}37m#{o}#{NND}" when "S" then io.print pride o else io.print o end end def puts *o # :nodoc: o.map! { |s| s.to_s.sub(/Finished/) { @index = 0 "Fabulous run".split(//).map { |c| pride(c) }.join } } io.puts(*o) end ## # Color a string. def pride string string = "*" if string == "." c = @colors[@index % @size] @index += 1 "#{ESC}#{c}m#{string}#{NND}" end def method_missing msg, *args # :nodoc: io.send(msg, *args) end end ## # If you thought the PrideIO was colorful... # # (Inspired by lolcat, but with clean math) class PrideLOL < PrideIO PI_3 = Math::PI / 3 # :nodoc: def initialize io # :nodoc: # walk red, green, and blue around a circle separated by equal thirds. # # To visualize, type this into wolfram-alpha: # # plot (3*sin(x)+3), (3*sin(x+2*pi/3)+3), (3*sin(x+4*pi/3)+3) # 6 has wide pretty gradients. 3 == lolcat, about half the width @colors = (0...(6 * 7)).map { |n| n *= 1.0 / 6 r = (3 * Math.sin(n ) + 3).to_i g = (3 * Math.sin(n + 2 * PI_3) + 3).to_i b = (3 * Math.sin(n + 4 * PI_3) + 3).to_i # Then we take rgb and encode them in a single number using base 6. # For some mysterious reason, we add 16... to clear the bottom 4 bits? # Yes... they're ugly. 36 * r + 6 * g + b + 16 } super end ## # Make the string even more colorful. Damnit. def pride string c = @colors[@index % @size] @index += 1 "#{ESC}38;5;#{c}m#{string}#{NND}" end end end PK% ]1gems/minitest-5.11.3/lib/minitest/expectations.rbnu[## # It's where you hide your "assertions". # # Please note, because of the way that expectations are implemented, # all expectations (eg must_equal) are dependent upon a thread local # variable +:current_spec+. If your specs rely on mixing threads into # the specs themselves, you're better off using assertions or the new # _(value) wrapper. For example: # # it "should still work in threads" do # my_threaded_thingy do # (1+1).must_equal 2 # bad # assert_equal 2, 1+1 # good # _(1 + 1).must_equal 2 # good # value(1 + 1).must_equal 2 # good, also #expect # end # end module Minitest::Expectations ## # See Minitest::Assertions#assert_empty. # # collection.must_be_empty # # :method: must_be_empty infect_an_assertion :assert_empty, :must_be_empty, :unary ## # See Minitest::Assertions#assert_equal # # a.must_equal b # # :method: must_equal infect_an_assertion :assert_equal, :must_equal ## # See Minitest::Assertions#assert_in_delta # # n.must_be_close_to m [, delta] # # :method: must_be_close_to infect_an_assertion :assert_in_delta, :must_be_close_to alias :must_be_within_delta :must_be_close_to # :nodoc: ## # See Minitest::Assertions#assert_in_epsilon # # n.must_be_within_epsilon m [, epsilon] # # :method: must_be_within_epsilon infect_an_assertion :assert_in_epsilon, :must_be_within_epsilon ## # See Minitest::Assertions#assert_includes # # collection.must_include obj # # :method: must_include infect_an_assertion :assert_includes, :must_include, :reverse ## # See Minitest::Assertions#assert_instance_of # # obj.must_be_instance_of klass # # :method: must_be_instance_of infect_an_assertion :assert_instance_of, :must_be_instance_of ## # See Minitest::Assertions#assert_kind_of # # obj.must_be_kind_of mod # # :method: must_be_kind_of infect_an_assertion :assert_kind_of, :must_be_kind_of ## # See Minitest::Assertions#assert_match # # a.must_match b # # :method: must_match infect_an_assertion :assert_match, :must_match ## # See Minitest::Assertions#assert_nil # # obj.must_be_nil # # :method: must_be_nil infect_an_assertion :assert_nil, :must_be_nil, :unary ## # See Minitest::Assertions#assert_operator # # n.must_be :<=, 42 # # This can also do predicates: # # str.must_be :empty? # # :method: must_be infect_an_assertion :assert_operator, :must_be, :reverse ## # See Minitest::Assertions#assert_output # # proc { ... }.must_output out_or_nil [, err] # # :method: must_output infect_an_assertion :assert_output, :must_output, :block ## # See Minitest::Assertions#assert_raises # # proc { ... }.must_raise exception # # :method: must_raise infect_an_assertion :assert_raises, :must_raise, :block ## # See Minitest::Assertions#assert_respond_to # # obj.must_respond_to msg # # :method: must_respond_to infect_an_assertion :assert_respond_to, :must_respond_to, :reverse ## # See Minitest::Assertions#assert_same # # a.must_be_same_as b # # :method: must_be_same_as infect_an_assertion :assert_same, :must_be_same_as ## # See Minitest::Assertions#assert_silent # # proc { ... }.must_be_silent # # :method: must_be_silent infect_an_assertion :assert_silent, :must_be_silent, :block ## # See Minitest::Assertions#assert_throws # # proc { ... }.must_throw sym # # :method: must_throw infect_an_assertion :assert_throws, :must_throw, :block ## # See Minitest::Assertions#refute_empty # # collection.wont_be_empty # # :method: wont_be_empty infect_an_assertion :refute_empty, :wont_be_empty, :unary ## # See Minitest::Assertions#refute_equal # # a.wont_equal b # # :method: wont_equal infect_an_assertion :refute_equal, :wont_equal ## # See Minitest::Assertions#refute_in_delta # # n.wont_be_close_to m [, delta] # # :method: wont_be_close_to infect_an_assertion :refute_in_delta, :wont_be_close_to alias :wont_be_within_delta :wont_be_close_to # :nodoc: ## # See Minitest::Assertions#refute_in_epsilon # # n.wont_be_within_epsilon m [, epsilon] # # :method: wont_be_within_epsilon infect_an_assertion :refute_in_epsilon, :wont_be_within_epsilon ## # See Minitest::Assertions#refute_includes # # collection.wont_include obj # # :method: wont_include infect_an_assertion :refute_includes, :wont_include, :reverse ## # See Minitest::Assertions#refute_instance_of # # obj.wont_be_instance_of klass # # :method: wont_be_instance_of infect_an_assertion :refute_instance_of, :wont_be_instance_of ## # See Minitest::Assertions#refute_kind_of # # obj.wont_be_kind_of mod # # :method: wont_be_kind_of infect_an_assertion :refute_kind_of, :wont_be_kind_of ## # See Minitest::Assertions#refute_match # # a.wont_match b # # :method: wont_match infect_an_assertion :refute_match, :wont_match ## # See Minitest::Assertions#refute_nil # # obj.wont_be_nil # # :method: wont_be_nil infect_an_assertion :refute_nil, :wont_be_nil, :unary ## # See Minitest::Assertions#refute_operator # # n.wont_be :<=, 42 # # This can also do predicates: # # str.wont_be :empty? # # :method: wont_be infect_an_assertion :refute_operator, :wont_be, :reverse ## # See Minitest::Assertions#refute_respond_to # # obj.wont_respond_to msg # # :method: wont_respond_to infect_an_assertion :refute_respond_to, :wont_respond_to, :reverse ## # See Minitest::Assertions#refute_same # # a.wont_be_same_as b # # :method: wont_be_same_as infect_an_assertion :refute_same, :wont_be_same_as end PK% ]I,gems/minitest-5.11.3/lib/minitest/autorun.rbnu[begin require "rubygems" gem "minitest" rescue Gem::LoadError # do nothing end require "minitest" require "minitest/spec" require "minitest/mock" require "minitest/hell" if ENV["MT_HELL"] Minitest.autorun PK% ]>!!)gems/minitest-5.11.3/lib/minitest/spec.rbnu[require "minitest/test" class Module # :nodoc: def infect_an_assertion meth, new_name, dont_flip = false # :nodoc: block = dont_flip == :block dont_flip = false if block # warn "%-22p -> %p %p" % [meth, new_name, dont_flip] self.class_eval <<-EOM, __FILE__, __LINE__ + 1 def #{new_name} *args Minitest::Expectation.new(self, Minitest::Spec.current).#{new_name}(*args) end EOM Minitest::Expectation.class_eval <<-EOM, __FILE__, __LINE__ + 1 def #{new_name} *args case when #{!!dont_flip} then ctx.#{meth}(target, *args) when #{block} && Proc === target then ctx.#{meth}(*args, &target) else ctx.#{meth}(args.first, target, *args[1..-1]) end end EOM end end Minitest::Expectation = Struct.new :target, :ctx # :nodoc: ## # Kernel extensions for minitest module Kernel ## # Describe a series of expectations for a given target +desc+. # # Defines a test class subclassing from either Minitest::Spec or # from the surrounding describe's class. The surrounding class may # subclass Minitest::Spec manually in order to easily share code: # # class MySpec < Minitest::Spec # # ... shared code ... # end # # class TestStuff < MySpec # it "does stuff" do # # shared code available here # end # describe "inner stuff" do # it "still does stuff" do # # ...and here # end # end # end # # For more information on getting started with writing specs, see: # # http://www.rubyinside.com/a-minitestspec-tutorial-elegant-spec-style-testing-that-comes-with-ruby-5354.html # # For some suggestions on how to improve your specs, try: # # http://betterspecs.org # # but do note that several items there are debatable or specific to # rspec. # # For more information about expectations, see Minitest::Expectations. def describe desc, *additional_desc, &block # :doc: stack = Minitest::Spec.describe_stack name = [stack.last, desc, *additional_desc].compact.join("::") sclas = stack.last || if Class === self && kind_of?(Minitest::Spec::DSL) then self else Minitest::Spec.spec_type desc, *additional_desc end cls = sclas.create name, desc stack.push cls cls.class_eval(&block) stack.pop cls end private :describe end ## # Minitest::Spec -- The faster, better, less-magical spec framework! # # For a list of expectations, see Minitest::Expectations. class Minitest::Spec < Minitest::Test def self.current # :nodoc: Thread.current[:current_spec] end def initialize name # :nodoc: super Thread.current[:current_spec] = self end ## # Oh look! A Minitest::Spec::DSL module! Eat your heart out DHH. module DSL ## # Contains pairs of matchers and Spec classes to be used to # calculate the superclass of a top-level describe. This allows for # automatically customizable spec types. # # See: register_spec_type and spec_type TYPES = [[//, Minitest::Spec]] ## # Register a new type of spec that matches the spec's description. # This method can take either a Regexp and a spec class or a spec # class and a block that takes the description and returns true if # it matches. # # Eg: # # register_spec_type(/Controller$/, Minitest::Spec::Rails) # # or: # # register_spec_type(Minitest::Spec::RailsModel) do |desc| # desc.superclass == ActiveRecord::Base # end def register_spec_type *args, &block if block then matcher, klass = block, args.first else matcher, klass = *args end TYPES.unshift [matcher, klass] end ## # Figure out the spec class to use based on a spec's description. Eg: # # spec_type("BlahController") # => Minitest::Spec::Rails def spec_type desc, *additional TYPES.find { |matcher, _klass| if matcher.respond_to? :call then matcher.call desc, *additional else matcher === desc.to_s end }.last end def describe_stack # :nodoc: Thread.current[:describe_stack] ||= [] end def children # :nodoc: @children ||= [] end def nuke_test_methods! # :nodoc: self.public_instance_methods.grep(/^test_/).each do |name| self.send :undef_method, name end end ## # Define a 'before' action. Inherits the way normal methods should. # # NOTE: +type+ is ignored and is only there to make porting easier. # # Equivalent to Minitest::Test#setup. def before _type = nil, &block define_method :setup do super() self.instance_eval(&block) end end ## # Define an 'after' action. Inherits the way normal methods should. # # NOTE: +type+ is ignored and is only there to make porting easier. # # Equivalent to Minitest::Test#teardown. def after _type = nil, &block define_method :teardown do self.instance_eval(&block) super() end end ## # Define an expectation with name +desc+. Name gets morphed to a # proper test method name. For some freakish reason, people who # write specs don't like class inheritance, so this goes way out of # its way to make sure that expectations aren't inherited. # # This is also aliased to #specify and doesn't require a +desc+ arg. # # Hint: If you _do_ want inheritance, use minitest/test. You can mix # and match between assertions and expectations as much as you want. def it desc = "anonymous", &block block ||= proc { skip "(no tests defined)" } @specs ||= 0 @specs += 1 name = "test_%04d_%s" % [ @specs, desc ] undef_klasses = self.children.reject { |c| c.public_method_defined? name } define_method name, &block undef_klasses.each do |undef_klass| undef_klass.send :undef_method, name end name end ## # Essentially, define an accessor for +name+ with +block+. # # Why use let instead of def? I honestly don't know. def let name, &block name = name.to_s pre, post = "let '#{name}' cannot ", ". Please use another name." methods = Minitest::Spec.instance_methods.map(&:to_s) - %w[subject] raise ArgumentError, "#{pre}begin with 'test'#{post}" if name =~ /\Atest/ raise ArgumentError, "#{pre}override a method in Minitest::Spec#{post}" if methods.include? name define_method name do @_memoized ||= {} @_memoized.fetch(name) { |k| @_memoized[k] = instance_eval(&block) } end end ## # Another lazy man's accessor generator. Made even more lazy by # setting the name for you to +subject+. def subject &block let :subject, &block end def create name, desc # :nodoc: cls = Class.new(self) do @name = name @desc = desc nuke_test_methods! end children << cls cls end def name # :nodoc: defined?(@name) ? @name : super end def to_s # :nodoc: name # Can't alias due to 1.8.7, not sure why end attr_reader :desc # :nodoc: alias :specify :it ## # Rdoc... why are you so dumb? module InstanceMethods ## # Returns a value monad that has all of Expectations methods # available to it. # # Also aliased to #value and #expect for your aesthetic pleasure: # # _(1 + 1).must_equal 2 # value(1 + 1).must_equal 2 # expect(1 + 1).must_equal 2 # # This method of expectation-based testing is preferable to # straight-expectation methods (on Object) because it stores its # test context, bypassing our hacky use of thread-local variables. # # At some point, the methods on Object will be deprecated and then # removed. def _ value = nil, &block Minitest::Expectation.new block || value, self end alias value _ alias expect _ def before_setup # :nodoc: super Thread.current[:current_spec] = self end end def self.extended obj # :nodoc: obj.send :include, InstanceMethods end end extend DSL TYPES = DSL::TYPES # :nodoc: end require "minitest/expectations" class Object # :nodoc: include Minitest::Expectations unless ENV["MT_NO_EXPECTATIONS"] end PK% ]Lj)p(gems/minitest-5.11.3/lib/hoe/minitest.rbnu[# :stopdoc: class Hoe end module Hoe::Minitest def minitest? self.name == "minitest" end def initialize_minitest unless minitest? then dir = "../../minitest/dev/lib" Hoe.add_include_dirs dir if File.directory? dir end gem "minitest" require "minitest" version = Minitest::VERSION.split(/\./).first(2).join(".") dependency "minitest", "~> #{version}", :development unless minitest? or ENV["MT_NO_ISOLATE"] end def define_minitest_tasks self.testlib = :minitest # make sure we use the gemmed minitest on 1.9 self.test_prelude = 'gem "minitest"' unless minitest? or ENV["MT_NO_ISOLATE"] end end PK% ]koOO!gems/minitest-5.11.3/History.rdocnu[=== 5.11.3 / 2018-01-26 * 1 bug fix: * Pushed #error? up to Reportable module. (composerinteralia) === 5.11.2 / 2018-01-25 * 1 minor enhancement: * Reversed Test < Result. Back to < Runnable and using Reportable for shared code. * 2 bug fixes: * Fixed Result#location for instances of Test. (alexisbernard) * Fixed deprecation message for Runnable#marshal_dump. (y-yagi) === 5.11.1 / 2018-01-02 * 1 bug fix: * Fixed Result (a superclass of Test) overriding Runnable's name accessors. (y-yagi, MSP-Greg) === 5.11.0 / 2018-01-01 * 2 major enhancements: * Added Minitest::Result and Minitest::Result.from(runnable). * Changed Minitest::Test to subclass Result and refactored methods up. * 7 minor enhancements: * Added --no-plugins and MT_NO_PLUGINS to bypass MT plugin autoloading. Helps with bad actors installed globally. * Added bench_performance_{logarithmic,power} for spec-style benchmarks. (rickhull) * Added deprecation warning for Runnable#marshal_dump. * Minitest.run_one_method now checks for instance of Result, not exact same class. * Minitest::Test.run returns a Result version of self, not self. * ProgressReporter#prerecord now explicitly prints klass.name. Allows for fakers. * 4 bug fixes: * Object.stub no longer calls the passed block if stubbed with a callable. * Object.stub now passes blocks down to the callable result. * Pushed Minitest::Test#time & #time_it up to Runnable. * Test nil equality directly in assert_equal. Fixes #679. (voxik) === 5.11.0b1 / 2017-12-20 * 2 major enhancements: * Added Minitest::Result and Minitest::Result.from(runnable). * Changed Minitest::Test to subclass Result and refactored methods up. * 6 minor enhancements: * Added --no-plugins and MT_NO_PLUGINS to bypass MT plugin autoloading. Helps with bad actors installed globally. * Added bench_performance_{logarithmic,power} for spec-style benchmarks. (rickhull) * Minitest.run_one_method now checks for instance of Result, not exact same class. * Minitest::Test.run returns a Result version of self, not self. * ProgressReporter#prerecord now explicitly prints klass.name. Allows for fakers. * Removed Runnable.marshal_dump/load. * 4 bug fixes: * Object.stub no longer calls the passed block if stubbed with a callable. * Object.stub now passes blocks down to the callable result. * Pushed Minitest::Test#time & #time_it up to Runnable. * Test nil equality directly in assert_equal. Fixes #679. (voxik) === 5.10.3 / 2017-07-21 * 1 minor enhancement: * Extended documentation for Mock#expect for multiple calls to mock object. (insti) * 2 bug fixes: * Finished off missing doco. * Fixed verbose output on parallelize_me! classes. (chanks) === 5.10.2 / 2017-05-09 * 1 minor enhancement: * Added suggestion in minitest/hell to install minitest/proveit. * 7 bug fixes: * Expand MT6 to Minitest 6. (xaviershay) * Fixed location of assert_send deprecation. (rab) * Fixed location of nil assert_equal deprecation to work with expectations. (jeremyevans) * Fixed minitest/hell to use parallelize_me! (azul) * Made deprecation use warn so -W0 will silence it. * Workaround for rdoc nodoc generation bug that totally f'd up minitest doco. (Paxa) * Write aggregated_results directly to the IO object to avoid mixed encoding errors. (tenderlove) === 5.10.1 / 2016-12-01 * 1 bug fix: * Added a hack/kludge to deal with missing #prerecord on reporters that aren't properly subclassing AbstractReporter (I'm looking at you minitest-reporters) === 5.10.0 / 2016-11-30 * 1 major enhancement: * Deprecated ruby 1.8, 1.9, possibly 2.0, assert_send, & old MiniTest namespace. * 3 minor enhancements: * Warn if assert_equal expects a nil. This will fail in minitest 6+. (tenderlove) * Added AbstractReporter#prerecord and extended ProgressReporter and CompositeReporter to use it. * Minor optimization: remove runnables with no runnable methods before run. * 3 bug fixes: * Fix assert_throw rescuing any NameError and ArgumentError. (waldyr) * Clean up (most of the) last remaining vestiges of minitest/unit. * 2.4: removed deprecation warnings when referring to Fixnum. === 5.9.1 / 2016-09-25 * 2 bug fixes: * Re-release to refresh gem certificate signing. ugh. * Fixed hoe/minitest to not augment load path if we're actually testing minitest. === 5.9.0 / 2016-05-16 * 8 minor enhancements: * Added Minitest.info_signal accessors to customize signal for test run info. (nate) * Added assert_mock to make it more clear that you're testing w/ them. * Added negative filter by test name. (utilum) * Added warning to README that 1.8 and 1.9 support will be dropped in minitest 6. * Automatically activate minitest/hell if $MT_HELL is defined. * Improved default error messages for assert and refute. (bhenderson) * minitest/hell now tries to require minitest/proveit * mu_pp for strings prints out non-standard encodings to improve assert_equal diffs. * 1 bug fix: * Removed Interrupt from PASSTHROUGH_EXCEPTIONS (already handled). (waldyr) === 5.8.5 / 2016-09-25 * 2 bug fixes: * Re-release to refresh gem certificate signing. ugh. * Fixed hoe/minitest to not augment load path if we're actually testing minitest. === 5.8.4 / 2016-01-21 * 1 bug fix: * Allow Minitest::Assertion to pass through assert_raises so inner failures are dealt with first. === 5.8.3 / 2015-11-17 * 1 minor enhancement: * Added extra note about mocks and threads to readme. (zamith) * 1 bug fix: * Fixed bug in Mock#verify. (pithub/zamith) === 5.8.2 / 2015-10-26 * 1 bug fix: * Fixed using parallelize_me! and capture_io (or any locking io). (arlt/tenderlove) === 5.8.1 / 2015-09-23 * 1 minor enhancement: * Refactor assert_raises to be cleaner and to pass SystemExit and SignalException. (bhenderson) === 5.8.0 / 2015-08-06 * 2 minor enhancements: * Add optional delegation mechanism to extend object with a mock. (zamith) * Return early if there are no filtered methods. (jeremyevans) * 1 bug fix: * Don't extend io with pride if io is not a tty. (toy) === 5.7.0 / 2015-05-27 * 1 major enhancement: * assert_raises now matches subclasses of the expected exception types. (jeremyevans) * 3 minor enhancements: * Added :block type for minitest/spec's #infect_an_assertion. (jeremyevans) * Inline verification error messages in minitest/mock for GC performance. (zamith) * assert_raises defaults to RuntimeError if not specified. (jeremyevans) * 4 bug fixes: * Added 'class' to minitest/mock's overridden_methods list. (zamith) * Added file/line to infect_an_assertion's class_eval call. (jeremyevans) * Cleared UnexpectedError's mesg w/ generic string. * Fixed non-proc-oriented expectations when used on proc target. (jeremyevans) === 5.6.1 / 2015-04-27 * 2 bug fixes: * Added Minitest.clock_time and switched all Time.now to it. (tenderlove) * Moved Minitest::Expectations#_ into Minitest::Spec::DSL. === 5.6.0 / 2015-04-13 * 4 major enhancements: * Added Minitest::Expectation value monad. * Added Minitest::Expectations#_ that returns an Expectation. Aliased to value. * All expectations are added to Minitest::Expectation. * At some point, the methods on Object will be deprecated and then removed. * 4 minor enhancements: * Added a note about bundle exec pitfall in ruby 2.2+. (searls) * Lazily start the parallel executor. (tenderlove) * Make mocks more debugger-friendly (edward) * Print out the current test run on interrupt. (riffraff) * 3 bug fixes: * Fix failing test under Windows. (kimhmadsen) * Record mocked calls before they happen so mocks can raise exceptions easier (tho I'm not a fan). (corecode) * Tried to clarify mocks vs stubs terminology better. (kkirsche) === 5.5.1 / 2015-01-09 * 1 bug fix: * Fixed doco problems. (zzak) === 5.5.0 / 2014-12-12 // mri 2.2.0 (as a real gem) * 1 minor enhancement: * Allow seed to be given via ENV for rake test loader sadness: eg rake SEED=42. === 5.4.3 / 2014-11-11 * 2 bug fixes: * Clarified requirements for ruby are now 1.8.7 or better. * Force encode error output in case mal-encoded exception is raised. (jasonrclark) === 5.4.2 / 2014-09-26 * 2 minor enhancements: * Extract teardown method list. * Thanks to minitest-gcstats got a 5-10% speedup via reduced GC! === 5.4.1 / 2014-08-28 * 1 bug fix: * Fixed specs hidden by nesting/ordering bug (blowmage/apotonick) === 5.4.0 / 2014-07-07 * 2 minor enhancements: * Kernel#describe extended to splat additional_desc. * Spec#spec_type extended to take a splat of additional items, passed to matcher procs. * 1 bug fix: * minitest/spec should require minitest/test, not minitest/unit. (doudou) === 5.3.5 / 2014-06-17 * 1 minor enhancement: * Spit and polish (mostly spit). === 5.3.4 / 2014-05-15 * 1 minor enhancement: * Test classes are randomized before running. (judofyr) === 5.3.3 / 2014-04-14 * 1 bug fix: * Fixed using expectations w/ DSL in Test class w/o describe. (blowmage+others) === 5.3.2 / 2014-04-02 * 1 bug fix: * Fixed doco on Assertions.assertions. (xaviershay) === 5.3.1 / 2014-03-14 * 1 minor enhancement: * Modified verbage on bad 'let' names to be more helpful. (Archytaus) * 1 bug fix: * Fixed 2 cases still using MiniTest. (mikesea) === 5.3.0 / 2014-02-25 * 1 minor enhancement: * Mocked methods can take a block to verify state. Seattle.rb 12 bday present from ernie! Thanks!! === 5.2.3 / 2014-02-10 * 1 bug fix: * Fixed Spec#let check to allow overriding of other lets. (mvz) === 5.2.2 / 2014-01-22 * 1 minor enhancement: * Spec#let raises ArgumentError if you override _any_ instance method (except subject). (rynr) * 1 bug fix: * Fixed up benchmark spec doco and added a test to demonstrate. (bhenderson) === 5.2.1 / 2014-01-07 * 1 bug fix: * Properly deal with horrible mix of runtime load errors + other at_exit handlers. (dougo/chqr) === 5.2.0 / 2013-12-13 * 1 minor enhancement: * Change expectations to allow calling most on procs (but not calling the proc). (bhenderson+others) === 5.1.0 / 2013-12-05 * 1 minor enhancement: * Use a Queue for scheduling parallel tests. (tenderlove) * 1 bug fix: * Fixed misspelling in doco. (amatsuda) === 5.0.8 / 2013-09-20 * 1 bug fix: * Fixed siginfo handler by rearranging reporters and fixing to_s. (tenderlove) === 5.0.7 / 2013-09-05 * 2 minor enhancements: * Added clarification about the use of thread local variables in expectations. (jemc) * Added extra message about skipped tests, if any. Disable globally with $MT_NO_SKIP_MSG. * 2 bug fixes: * Only require minitest, not minitest/autorun in pride_plugin. (judofyr) * Require rubygems in load_plugins in case you're not using minitest/autorun. === 5.0.6 / 2013-06-28 * 3 minor enhancements: * Allow stub to pass args to blocks. (swindsor) * Improved warning message about minitest/autorun to address 1.9's minitest/autorun. * Made minitest/test require minitest as needed. For lib writers. (erikh) * 1 bug fix: * Fixed missing require in minitest/test. (erikh) === 4.7.5 / 2013-06-21 // mri 2.1.1 * 2 bug fixes: * Fix Spec#describe_stack to be thread local. * Fix multithreaded test failures by defining Time local to mock test namespace === 5.0.5 / 2013-06-20 * 6 bug fixes: * DOH! Fixed the rest of the new casing on Minitest. (splattael) * Fixed typo on minitest/mock rdoc. (mrgilman/guiceolin) * Make Spec::DSL.describe_stack thread local to avoid failing on my own tests. * Make a fake Time.now local to the tests so they won't interfere with real reporter timings. * Make everything mockable by wrapping all 'special' methods in a smarter wrapper. (bestie) * Raise ArgumentError if let name starts with 'test'. (johnmaxwell) === 5.0.4 / 2013-06-07 * 5 minor enhancements: * Added AbstractReporter, defining required Reporter API to quack properly. * Added doco for writing reporters. * Refactored Reporter into ProgressReporter and SummaryReporter. (idea: phiggins, code:me+scotch) * Refactored SummaryReporter pushing up to StatisticsReporter. (phiggins) * Removed Reporter#run_and_report... cleaner, but doesn't "fit" in the API. === 5.0.3 / 2013-05-29 * 4 minor enhancements: * Added Runnable.with_info_handler and Runnable.on_signal. * Moved io.sync restore to Reporter#run_and_report. * Refactored inner loop of Reporter#report to #to_s. Callable for status updates. * Restored MT4's mid-run report (^t). (tenderlove). === 5.0.2 / 2013-05-20 * 3 bug fixes: * Gem.find_files is smarter than I remember... cause I wrote it that way. *sigh* I'm getting old. * Pride wasn't doing puts through its #io. (tmiller/tenderlove) * Replaced Runnable#dup and Test#dup with marshal_dump/load. Too many problems cropping up on untested rails code. (tenderlove/rubys) === 5.0.1 / 2013-05-14 * 2 bug fixes: * Documented Assertions' need for @assertions to be defined by the includer. * Only load one plugin version per name. Tries for latest. === 5.0.0 / 2013-05-10 Oh god... here we go... Minitest 5: * 4 deaths in the family: * MiniTest.runner is dead. No more manager objects. * MiniTest::Unit#record is dead. Use a Reporter instance instead. * MiniTest::Unit._run_* is dead. Runnable things are responsible for their own runs. * MiniTest::Unit.output is dead. No more centralized IO. * 12 major (oft incompatible) changes: * Renamed MiniTest to Minitest. Your pinkies will thank me. (aliased to MiniTest) * Removed MiniTest::Unit entirely. No more manager objects. * Added Minitest::Runnable. Everything minitest can run subclasses this. * Renamed MiniTest::Unit::TestCase to Minitest::Test (subclassing Runnable). * Added Minitest::Benchmark. * Your benchmarks need to move to their own subclass. * Benchmarks using the spec DSL have to have "Bench" somewhere in their describe. * MiniTest::Unit.after_tests moved to Minitest.after_tests * MiniTest::Unit.autorun is now Minitest.autorun. Just require minitest/autorun pls. * Removed ParallelEach#grep since it isn't used anywhere. * Renamed Runnable#__name__ to Runnable#name (but uses @NAME internally). * Runnable#run needs to return self. Allows for swapping of results as needed. * 8 minor moves: * Moved Assertions module to minitest/assertions.rb * Moved Expectations module to minitest/expectations.rb * Moved Test to minitest/test.rb * Moved everything else in minitest/unit.rb to minitest.rb * minitest/unit.rb is now just a small (user-test only) compatibility layer. * Moved most of minitest/pride into minitest/pride_plugin. * minitest/pride now just activates pride. * Moved ParallelEach under Minitest. * 9 additions: * Added a plugin system that can extend command-line options. * Added Minitest.extensions. * Added Minitest.reporter (only available during startup). * Added Minitest.run(args). This is the very top of any Minitest run. * Added Minitest::Reporter. Everything minitest can report goes through here. * Minitest.reporter is a composite so you can add your own. * Added Minitest::CompositeReporter. Much easier to extend with your own reporters. * Added UnexpectedError, an Assertion subclass, to wrap up errors. * Minitest::Test#run is now freakin' beautiful. 47 -> 17 loc * 11 other: * Removed Object.infect_with_assertions (it was already dead code). * Runnables are responsible for knowing their result_code (eg "." or "F"). * Minitest.autorun now returns boolean, not exit code. * Added FAQ entry for extending via modules. (phiggins) * Implement Runnable#dup to cleanse state back to test results. Helps with serialization. pair:tenderlove * Moved ParallelEach under Minitest. * Runnable#run needs to return self. Allows for swapping of results as needed. * Minitest.init_plugins passes down options. * Minitest.load_plugins only loads once. * Fixed minitest/pride to work with rake test loader again. (tmiller) * Added count/size to ParallelEach to fix use w/in stdlib's test/unit. :( (btaitelb) * 5 voodoo: * Removed mutex from minitest.rb (phiggins) * Removed mutex from test.rb (phiggins) * Removed Minitest::Reporter.synchronize (phiggins) * Removed Minitest::Test.synchronize (phiggins) * Upon loading minitest/parallel_each, record, capture_io and capture_subprocess_io are doped with synchronization code. (phiggins) === 4.7.4 / 2013-05-01 This is probably the last release of the 4.x series. It will be merged to ruby and will be put into maintenance mode there. I'm not set in stone on this, but at this point further development of minitest (5+) will be gem-only. It is just too hard to work w/in ruby-core w/ test-unit compatibility holding minitest development back. * 2 minor enhancements: * Added count/size to ParallelEach to fix use w/in stdlib's test/unit. :( (btaitelb) * Allow disabling of info_signal handler in runner. (erikh) === 4.7.3 / 2013-04-20 * 1 bug fix: * Reverted stubbing of module methods change. Stub the user, not the impl. (ab9/tyabe) === 4.7.2 / 2013-04-18 * 2 bug fixes: * Fixed inconsistency in refute_in_delta/epsilon. I double negatived my logic. (nettsundere) * Fixed stubbing of module methods (eg Kernel#sleep). (steveklabnik) === 4.7.1 / 2013-04-09 * 1 minor enhancement: * Added FAQ section to README * 1 bug fix: * Fixed bug where guard runs tests bypassing minitest/autorun and an ivar isn't set right. (darrencauthon) === 4.7.0 / 2013-03-18 * 1 major enhancement: * Refactored MiniTest::Spec into MiniTest::Spec::DSL. * 1 bug fix: * Removed $DEBUG handler that detected when test/unit and minitest were both loaded. (tenderlove) === 4.6.2 / 2013-02-27 * 1 minor enhancement: * Change error output to match Class#method, making it easier to use -n filter. === 4.6.1 / 2013-02-14 * 1 bug fix: * Fixed an option processing bug caused by test/unit's irresponsibly convoluted code. (floehopper) === 4.6.0 / 2013-02-07 * 3 major enhancements: * Removed ::reset_setup_teardown_hooks * Removed the long deprecated assert_block * Removed the long deprecated lifecycle hooks: add_(setup|teardown)_hook * 1 minor enhancement: * Allow filtering tests by suite name as well as test name. (lazyatom) * 2 bug fixes: * Made hex handling (eg object_ids) in mu_pp_for_diff more specific. (maxim) * nodoc top-level module. (zzak) === 4.5.0 / 2013-01-22 * 1 major enhancement: * Rearranged minitest/unit.rb so NO parallelization code is loaded/used until you opt-in. * 4 minor enhancements: * Added TestCase#skipped? for teardown guards * Added maglev? guard * Document that record can be sent twice if teardown fails or errors (randycoulman) * Errors in teardown are now recorded. (randycoulman) * 3 bug fixes: * Added hacks and skips to get clean test runs on maglev * Modified float tests for maglev float output differences. Not sure this is right. Not sure I care. * Test for existance of diff.exe instead of assuming they have devkit. (blowmage/Cumbayah) === 4.4.0 / 2013-01-07 * 3 minor enhancements: * Added fit_logarithic and assert_performance_logarithmic. (ktheory) * Merge processed options so others can mess with defaults. (tenderlove) * TestCase#message can now take another proc to defer custom message cost. (ordinaryzelig/bhenderson) * 1 bug fix: * TestCase#passed? now true if test is skipped. (qanhd) === 4.3.3 / 2012-12-06 * 1 bug fix: * Updated information about stubbing. (daviddavis) === 4.3.2 / 2012-11-27 // mri 2.0.0 * 1 minor enhancement: * Improved assert_equals error message to point you at #== of member objects. (kcurtin) === 4.3.1 / 2012-11-23 * 1 bug fix: * Moved test_children to serial testcase to prevent random failures. === 4.3.0 / 2012-11-17 * 4 minor enhancements: * Allow #autorun to run even if loaded with other test libs that call exit. (sunaku) * Do not include Expectations in Object if $MT_NO_EXPECTATIONS is set (experimental?) * Gave some much needed love to assert_raises. * Mock#expect can take a block to custom-validate args. (gmoothart) === 4.2.0 / 2012-11-02 * 4 major enhancements: * Added minitest/hell - run all your tests through the ringer! * Added support for :parallel test_order to run test cases in parallel. * Removed last_error and refactored runner code to be threadsafe. * _run_suites now runs suites in parallel if they opt-in. * 4 minor enhancements: * Added TestCase#synchronize * Added TestCase.make_my_diffs_pretty! * Added TestCase.parallelize_me! * Lock on capture_io for thread safety (tenderlove) === 4.1.0 / 2012-10-05 * 2 minor enhancements: * Added skip example to readme. (dissolved) * Extracted backtrace filter to object. (tenderlove) * 1 bug fix: * OMG I'm so dumb. Fixed access to deprecated hook class methods. I hate ruby modules. (route) === 4.0.0 / 2012-09-28 * 1 major enhancement: * The names of a privately-used undocumented constants are Super Important™. * 1 minor enhancement: * Support stubbing methods that would be handled via method_missing. (jhsu) * 3 bug fixes: * Add include_private param to MiniTest::Mock#respond_to? (rf-) * Fixed use of minitest/pride with --help. (zw963) * Made 'No visible difference.' message more clear. (ckrailo) === 3.5.0 / 2012-09-21 * 1 minor enhancement: * Added #capture_subprocess_io. (route) === 3.4.0 / 2012-09-05 * 2 minor enhancements: * assert_output can now take regexps for expected values. (suggested by stomar) * Clarified that ruby 1.9/2.0's phony gems cause serious confusion for rubygems. === 3.3.0 / 2012-07-26 * 1 major enhancement: * Deprecated add_(setup|teardown)_hook in favor of (before|after)_(setup|teardown) [2013-01-01] * 4 minor enhancements: * Refactored deprecated hook system into a module. * Refactored lifecycle hooks into a module. * Removed after_setup/before_teardown + run_X_hooks from Spec. * Spec#before/after now do a simple define_method and call super. DUR. * 2 bug fixes: * Fixed #passed? when used against a test that called flunk. (floehopper) * Fixed rdoc bug preventing doco for some expectations. (stomar). === 3.2.0 / 2012-06-26 * 1 minor enhancement: * Stubs now yield self. (peterhellberg) * 1 bug fix: * Fixed verbose test that only fails when run in verbose mode. mmmm irony. === 3.1.0 / 2012-06-13 * 2 minor enhancements: * Removed LONG deprecated Unit.out accessor * Removed generated method name munging from minitest/spec. (ordinaryzelig/tenderlove) === 3.0.1 / 2012-05-24 * 1 bug fix: * I'm a dumbass and refactored into Mock#call. Renamed to #__call so you can mock #call. (mschuerig) === 3.0.0 / 2012-05-08 * 3 major enhancements: * Added Object#stub (in minitest/mock.rb). * Mock#expect mocks are used in the order they're given. * Mock#verify now strictly compares against expect calls. * 3 minor enhancements: * Added caller to deprecation message. * Mock error messages are much prettier. * Removed String check for RHS of assert/refute_match. This lets #to_str work properly. * 1 bug fix: * Support drive letter on Windows. Patch provided from MRI by Usaku NAKAMURA. (ayumin) === 2.12.1 / 2012-04-10 * 1 minor enhancement: * Added ruby releases to History.txt to make it easier to see what you're missing * 1 bug fix: * Rolled my own deprecate msg to allow MT to work with rubygems < 1.7 === 2.12.0 / 2012-04-03 * 4 minor enhancements: * ::it returns test method name (wojtekmach) * Added #record method to runner so runner subclasses can cleanly gather data. * Added Minitest alias for MiniTest because even I forget. * Deprecated assert_block!! Yay!!! * 1 bug fix: * Fixed warning in i_suck_and_my_tests_are_order_dependent! (phiggins) === 2.11.4 / 2012-03-20 * 2 minor enhancements: * Updated known extensions * You got your unicode in my tests! You got your tests in my unicode! (fl00r) * 1 bug fix: * Fixed MiniTest::Mock example in the readme. (conradwt) === 2.11.3 / 2012-02-29 * 2 bug fixes: * Clarified that assert_raises returns the exception for further testing * Fixed assert_in_epsilon when both args are negative. (tamc) === 2.11.2 / 2012-02-14 * 1 minor enhancement: * Display failures/errors on SIGINFO. (tenderlove) * 1 bug fix: * Fixed MiniTest::Unit.after_tests for Ruby 1.9.3. (ysbaddaden) === 2.11.1 / 2012-02-01 * 3 bug fixes: * Improved description for --name argument. (drd) * Ensure Mock#expect's expected args is an Array. (mperham) * Ensure Mock#verify verifies multiple expects of the same method. (chastell) === 2.11.0 / 2012-01-25 * 2 minor enhancements: * Added before / after hooks for setup and teardown. (tenderlove) * Pushed run_setup_hooks down to Spec. (tenderlove) === 2.10.1 / 2012-01-17 * 1 bug fix: * Fixed stupid 1.9 path handling grumble grumble. (graaff) === 2.10.0 / 2011-12-20 * 3 minor enhancements: * Added specs for must/wont be_empty/respond_to/be_kind_of and others. * Added tests for assert/refute predicate. * Split minitest/excludes.rb out to its own gem. * 1 bug fix: * Fixed must_be_empty and wont_be_empty argument handling. (mrsimo) === 2.9.1 / 2011-12-13 * 4 minor enhancements: * Added a ton of tests on spec error message output. * Cleaned up consistency of msg handling on unary expectations. * Improved error messages on assert/refute_in_delta. * infect_an_assertion no longer checks arity and better handles args. * 1 bug fix: * Fixed error message on specs when 2+ args and custom message provided. (chastell) === 2.9.0 / 2011-12-07 * 4 minor enhancements: * Added TestCase.exclude and load_excludes for programmatic filtering of tests. * Added guard methods so you can cleanly skip based on platform/impl * Holy crap! 100% doco! `rdoc -C` ftw * Switch assert_output to test stderr before stdout to possibly improve debugging === 2.8.1 / 2011-11-17 * 1 bug fix: * Ugh. 1.9's test/unit violates my internals. Added const_missing. === 2.8.0 / 2011-11-08 * 2 minor enhancements: * Add a method so that code can be run around a particular test case (tenderlove) * Turn off backtrace filtering if we're running inside a ruby checkout. (drbrain) * 2 bug fixes: * Fixed 2 typos and 2 doc glitches. (splattael) * Remove unused block arguments to avoid creating Proc objects. (k-tsj) === 2.7.0 / 2011-10-25 * 2 minor enhancements: * Include failed values in the expected arg output in MockExpectationError. (nono) * Make minitest/pride work with other 256 color capable terms. (sunaku) * 2 bug fixes: * Clarified the documentation of minitest/benchmark (eregon) * Fixed using expectations in regular unit tests. (sunaku) === 2.6.2 / 2011-10-19 * 1 minor enhancement: * Added link to vim bundle. (sunaku) * 2 bug fixes: * Force gem activation in hoe minitest plugin * Support RUBY_VERSION='2.0.0' (nagachika) === 2.6.1 / 2011-09-27 * 2 bug fixes: * Alias Spec.name from Spec.to_s so it works when @name is nil (nathany) * Fixed assert and refute_operator where second object has a bad == method. === 2.6.0 / 2011-09-13 * 2 minor enhancements: * Added specify alias for it and made desc optional. * Spec#must_be and #wont_be can be used with predicates (metaskills) * 1 bug fix: * Fixed Mock.respond_to?(var) to work with strings. (holli) === 2.5.1 / 2011-08-27 // ruby 1.9.3: p0, p125, p34579 * 2 minor enhancements: * Added gem activation for minitest in minitest/autoload to help out 1.9 users * Extended Spec.register_spec_type to allow for procs instead of just regexps. === 2.5.0 / 2011-08-18 * 4 minor enhancements: * Added 2 more arguments against rspec: let & subject in 9 loc! (emmanuel/luis) * Added TestCase.i_suck_and_my_tests_are_order_dependent! * Extended describe to take an optional method name (2 line change!). (emmanuel) * Refactored and extended minitest/pride to do full 256 color support. (lolcat) * 1 bug fix: * Doc fixes. (chastell) === 2.4.0 / 2011-08-09 * 4 minor enhancements: * Added simple examples for all expectations. * Improved Mock error output when args mismatch. * Moved all expectations from Object to MiniTest::Expectations. * infect_with_assertions has been removed due to excessive clever * 4 bug fixes: * Fix Assertions#mu_pp to deal with immutable encoded strings. (ferrous26) * Fix minitest/pride for MacRuby (ferrous26) * Made error output less fancy so it is more readable * Mock shouldn't undef === and inspect. (dgraham) === 2.3.1 / 2011-06-22 * 1 bug fix: * Fixed minitest hoe plugin to be a spermy dep and not depend on itself. === 2.3.0 / 2011-06-15 * 5 minor enhancements: * Add setup and teardown hooks to MiniTest::TestCase. (phiggins) * Added nicer error messages for MiniTest::Mock. (phiggins) * Allow for less specific expected arguments in Mock. (bhenderson/phiggins) * Made MiniTest::Mock a blank slate. (phiggins) * Refactored minitest/spec to use the hooks instead of define_inheritable_method. (phiggins) * 2 bug fixes: * Fixed TestCase's inherited hook. (dchelimsky/phiggins/jamis, the 'good' neighbor) * MiniTest::Assertions#refute_empty should use mu_pp in the default message. (whatthejeff) === 2.2.2 / 2011-06-01 * 2 bug fixes: * Got rid of the trailing period in message for assert_equal. (tenderlove) * Windows needs more flushing. (Akio Tajima) === 2.2.1 / 2011-05-31 * 1 bug fix: * My _ONE_ non-rubygems-using minitest user goes to Seattle.rb! === 2.2.0 / 2011-05-29 * 6 minor enhancements: * assert_equal (and must_equal) now tries to diff output where it makes sense. * Added Assertions#diff(exp, act) to be used by assert_equal. * Added Assertions#mu_pp_for_diff * Added Assertions.diff and diff= * Moved minitest hoe-plugin from hoe-seattlerb. (erikh) * Skipped tests only output details in verbose mode. (tenderlove+zenspider=xoxo) === 2.1.0 / 2011-04-11 * 5 minor enhancements: * Added MiniTest::Spec.register_spec_type(matcher, klass) and spec_type(desc) * Added ability for specs to share code via subclassing of Spec. (metaskills) * Clarified (or tried to) bench_performance_linear's use of threshold. * MiniTest::Unit.runner=(runner) provides an easy way of creating custom test runners for specialized needs. (justinweiss) * Reverse order of inheritance in teardowns of specs. (deepfryed) * 3 bug fixes: * FINALLY fixed problems of inheriting specs in describe/it/describe scenario. (MGPalmer) * Fixed a new warning in 1.9.3. * Fixed assert_block's message handling. (nobu) === 2.0.2 / 2010-12-24 * 1 minor enhancement: * Completed doco on minitest/benchmark for specs. * 1 bug fix: * Benchmarks in specs that didn't call bench_range would die. (zzak). === 2.0.1 / 2010-12-15 * 4 minor enhancements: * Do not filter backtrace if $DEBUG * Exit autorun via nested at_exit handler, in case other libs call exit * Make options accesor lazy. * Split printing of test name and its time. (nurse) * 1 bug fix: * Fix bug when ^T is hit before runner start === 2.0.0 / 2010-11-11 * 3 major enhancements: * Added minitest/benchmark! Assert your performance! YAY! * Refactored runner to allow for more extensibility. See minitest/benchmark. * This makes the runner backwards incompatible in some ways! * 9 minor enhancements: * Added MiniTest::Unit.after_tests { ... } * Improved output by adding test rates and a more sortable verbose format * Improved readme based on feedback from others * Added io method to TestCase. If used, it'll supplant '.EF' output. * Refactored IO in MiniTest::Unit. * Refactored _run_anything to _run_suite to make it easier to wrap (ngauthier) * Spec class names are now the unmunged descriptions (btakita) * YAY for not having redundant rdoc/readmes! * Help output is now generated from the flags you passed straight up. * 4 bug fixes: * Fixed scoping issue on minitest/mock (srbaker/prosperity) * Fixed some of the assertion default messages * Fixes autorun when on windows with ruby install on different drive (larsch) * Fixed rdoc output bug in spec.rb === 1.7.2 / 2010-09-23 * 3 bug fixes: * Fixed doco for expectations and Spec. * Fixed test_capture_io on 1.9.3+ (sora_h) * assert_raises now lets MiniTest::Skip through. (shyouhei) === 1.7.1 / 2010-09-01 * 1 bug fix: * 1.9.2 fixes for spec tests === 1.7.0 / 2010-07-15 * 5 minor enhancements: * Added assert_output (mapped to must_output). * Added assert_silent (mapped to must_be_silent). * Added examples to readme (Mike Dalessio) * Added options output at the top of the run, for fatal run debugging (tenderlove) * Spec's describe method returns created class === 1.6.0 / 2010-03-27 // ruby 1.9.2-p290 * 10 minor enhancements: * Added --seed argument so you can reproduce a random order for debugging. * Added documentation for assertions * Added more rdoc and tons of :nodoc: * Added output to give you all the options you need to reproduce that run. * Added proper argument parsing to minitest. * Added unique serial # to spec names so order can be preserved (needs tests). (phrogz) * Empty 'it' fails with default msg. (phrogz) * Remove previous method on expect to remove 1.9 warnings * Spec#it is now order-proof wrt subclasses/nested describes. * assert_same error message now reports in decimal, eg: oid=123. (mattkent) * 2 bug fixes: * Fixed message on refute_same to be consistent with assert_same. * Fixed method randomization to be stable for testing. === 1.5.0 / 2010-01-06 * 4 minor enhancements: * Added ability to specify what assertions should have their args flipped. * Don't flip arguments on *include and *respond_to assertions. * Refactored Module.infect_an_assertion from Module.infect_with_assertions. * before/after :all now bitches and acts like :each * 3 bug fixes: * Nested describes now map to nested test classes to avoid namespace collision. * Using undef_method instead of remove_method to clean out inherited specs. * assert_raises was ignoring passed in message. === 1.4.2 / 2009-06-25 * 1 bug fix: * Fixed info handler for systems that don't have siginfo. === 1.4.1 / 2009-06-23 * 1 major enhancement: * Handle ^C and other fatal exceptions by failing * 1 minor enhancement: * Added something to catch mixed use of test/unit and minitest if $DEBUG * 1 bug fix: * Added SIGINFO handler for finding slow tests without verbose === 1.4.0 / 2009-06-18 * 5 minor enhancement: * Added clarification doco. * Added specs and mocks to autorun. * Changed spec test class creation to be non-destructive. * Updated rakefile for new hoe capabilities. * describes are nestable (via subclass). before/after/def inherits, specs don't. * 3 bug fixes: * Fixed location on must/wont. * Switched to __name__ to avoid common ivar name. * Fixed indentation in test file (1.9). === 1.3.1 / 2009-01-20 // ruby 1.9.1-p431 * 1 minor enhancement: * Added miniunit/autorun.rb as replacement for test/unit.rb's autorun. * 16 bug fixes: * 1.9 test fixes. * Bug fixes from nobu and akira for really odd scenarios. They run ruby funny. * Fixed (assert|refute)_match's argument order. * Fixed LocalJumpError in autorun if exception thrown before at_exit. * Fixed assert_in_delta (should be >=, not >). * Fixed assert_raises to match Modules. * Fixed capture_io to not dup IOs. * Fixed indentation of capture_io for ruby 1.9 warning. * Fixed location to deal better with custom assertions and load paths. (Yuki) * Fixed order of (must|wont)_include in MiniTest::Spec. * Fixed skip's backtrace. * Got arg order wrong in *_match in tests, message wrong as a result. * Made describe private. For some reason I thought that an attribute of Kernel. * Removed disable_autorun method, added autorun.rb instead. * assert_match escapes if passed string for pattern. * instance_of? is different from ===, use instance_of. === 1.3.0 / 2008-10-09 * 2 major enhancements: * renamed to minitest and pulled out test/unit compatibility. * mini/test.rb is now minitest/unit.rb, everything else maps directly. * 12 minor enhancements: * assert_match now checks that act can call =~ and converts exp to a regexp only if needed. * Added assert_send... seems useless to me tho. * message now forces to string... ruby-core likes to pass classes and arrays :( * Added -v handling and switched to @verbose from $DEBUG. * Verbose output now includes test class name and adds a sortable running time! * Switched message generation into procs for message deferment. * Added skip and renamed fail to flunk. * Improved output failure messages for assert_instance_of, assert_kind_of * Improved output for assert_respond_to, assert_same. * at_exit now exits false instead of errors+failures. * Made the tests happier and more readable imhfo. * Switched index(s) == 0 to rindex(s, 0) on nobu's suggestion. Faster. * 5 bug fixes: * 1.9: Added encoding normalization in mu_pp. * 1.9: Fixed backtrace filtering (BTs are expanded now) * Added back exception_details to assert_raises. DOH. * Fixed shadowed variable in mock.rb * Fixed stupid muscle memory message bug in assert_send. === 1.2.1 / 2008-06-10 * 7 minor enhancements: * Added deprecations everywhere in test/unit. * Added test_order to TestCase. :random on mini, :sorted on test/unit (for now). * Big cleanup in test/unit for rails. Thanks Jeremy Kemper! * Minor readability cleanup. * Pushed setup/run/teardown down to testcase allowing specialized testcases. * Removed pp. Tests run 2x faster. :/ * Renamed deprecation methods and moved to test/unit/deprecate.rb. === 1.2.0 / 2008-06-09 * 2 major enhancements: * Added Mini::Spec. * Added Mini::Mock. Thanks Steven Baker!! * 23 minor enhancements: * Added bin/use_miniunit to make it easy to test out miniunit. * Added -n filtering, thanks to Phil Hagelberg! * Added args argument to #run, takes ARGV from at_exit. * Added test name output if $DEBUG. * Added a refute (was deny) for every assert. * Added capture_io and a bunch of nice assertions from zentest. * Added deprecation mechanism for assert_no/not methods to test/unit/assertions. * Added pp output when available. * Added tests for all assertions. Pretty much maxed out coverage. * Added tests to verify consistency and good naming. * Aliased and deprecated all ugly assertions. * Cleaned out test/unit. Moved autorun there. * Code cleanup to make extensions easier. Thanks Chad! * Got spec args reversed in all but a couple assertions. Much more readable. * Improved error messages across the board. Adds your message to the default. * Moved into Mini namespace, renamed to Mini::Test and Mini::Spec. * Pulled the assertions into their own module... * Removed as much code as I could while still maintaining full functionality. * Moved filter_backtrace into MiniTest. * Removed MiniTest::Unit::run. Unnecessary. * Removed location_of_failure. Unnecessary. * Rewrote test/unit's filter_backtrace. Flog from 37.0 to 18.1 * Removed assert_send. Google says it is never used. * Renamed MiniTest::Unit.autotest to #run. * Renamed deny to refute. * Rewrote some ugly/confusing default assertion messages. * assert_in_delta now defaults to 0.001 precision. Makes specs prettier. * 9 bug fixes: * Fixed assert_raises to raise outside of the inner-begin/rescue. * Fixed for ruby 1.9 and rubinius. * No longer exits 0 if exception in code PRE-test run causes early exit. * Removed implementors method list from mini/test.rb - too stale. * assert_nothing_raised takes a class as an arg. wtf? STUPID * ".EF" output is now unbuffered. * Bunch of changes to get working with rails... UGH. * Added stupid hacks to deal with rails not requiring their dependencies. * Now bitch loudly if someone defines one of my classes instead of requiring. * Fixed infect method to work better on 1.9. * Fixed all shadowed variable warnings in 1.9. === 1.1.0 / 2007-11-08 * 4 major enhancements: * Finished writing all missing assertions. * Output matches original test/unit. * Documented every method needed by language implementor. * Fully switched over to self-testing setup. * 2 minor enhancements: * Added deny (assert ! test), our favorite extension to test/unit. * Added .autotest and fairly complete unit tests. (thanks Chad for help here) === 1.0.0 / 2006-10-30 * 1 major enhancement * Birthday! PK% ]5~~(gems/minitest-5.11.3/design_rationale.rbnu[# Specs: # Equivalent Unit Tests: ############################################################################### describe Thingy do # class TestThingy < Minitest::Test before do # def setup do_some_setup # super end # do_some_setup # end it "should do the first thing" do # 1.must_equal 1 # def test_first_thing end # assert_equal 1, 1 # end describe SubThingy do # end before do # do_more_setup # class TestSubThingy < TestThingy end # def setup # super it "should do the second thing" do # do_more_setup 2.must_equal 2 # end end # end # def test_second_thing end # assert_equal 2, 2 # end # end ############################################################################### # runs 2 specs # runs 3 tests ############################################################################### # The specs generate: class ThingySpec < Minitest::Spec def setup super do_some_setup end def test_should_do_the_first_thing assert_equal 1, 1 end end class SubThingySpec < ThingySpec def setup super do_more_setup end # because only setup/teardown is inherited, not specs remove_method :test_should_do_the_first_thing def test_should_do_the_second_thing assert_equal 2, 2 end end PK% ]Wgems/rake-12.3.3/MIT-LICENSEnu[Copyright (c) Jim Weirich 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. PK% ]''gems/rake-12.3.3/Gemfilenu[source "https://rubygems.org" gemspec PK% ]Igems/rake-12.3.3/exe/rakenuȯ#!/usr/bin/ruby #-- # Copyright (c) 2003, 2004, 2005, 2006, 2007 Jim Weirich # # 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. #++ require "rake" Rake.application.run PK% ]VQOgems/rake-12.3.3/Rakefilenu[# Rakefile for rake -*- ruby -*- # Copyright 2003, 2004, 2005 by Jim Weirich (jim@weirichhouse.org) # All rights reserved. # This file may be distributed under an MIT style license. See # MIT-LICENSE for details. lib = File.expand_path("../lib", __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) begin require "bundler/gem_tasks" rescue LoadError end require "rake/testtask" Rake::TestTask.new(:test) do |t| t.libs << "test" t.verbose = true t.test_files = FileList["test/**/test_*.rb"] end require "rdoc/task" RDoc::Task.new do |doc| doc.main = "README.rdoc" doc.title = "Rake -- Ruby Make" doc.rdoc_files = FileList.new %w[lib MIT-LICENSE doc/**/*.rdoc *.rdoc] doc.rdoc_dir = "html" end task ghpages: :rdoc do %x[git checkout gh-pages] require "fileutils" FileUtils.rm_rf "/tmp/html" FileUtils.mv "html", "/tmp" FileUtils.rm_rf "*" FileUtils.cp_r Dir.glob("/tmp/html/*"), "." end task default: :test PK% ]n\?$gems/rake-12.3.3/azure-pipelines.ymlnu[jobs: - job: macOS pool: vmImage: 'macos-10.13' steps: - script: | gem install bundler bundle install --retry=3 --jobs=4 displayName: 'bundle install' - script: ruby -Ilib exe/rake displayName: 'ruby -Ilib exe/rake' PK% ]gems/rake-12.3.3/README.rdocnu[= RAKE -- Ruby Make home :: https://github.com/ruby/rake bugs :: https://github.com/ruby/rake/issues docs :: https://ruby.github.io/rake build status :: {travis-ci}[https://travis-ci.org/ruby/rake] {appveyor}[https://ci.appveyor.com/project/ruby/rake] == Description Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax. Rake has the following features: * Rakefiles (rake's version of Makefiles) are completely defined in standard Ruby syntax. No XML files to edit. No quirky Makefile syntax to worry about (is that a tab or a space?) * Users can specify tasks with prerequisites. * Rake supports rule patterns to synthesize implicit tasks. * Flexible FileLists that act like arrays but know about manipulating file names and paths. * A library of prepackaged tasks to make building rakefiles easier. For example, tasks for building tarballs. (Formerly tasks for building RDoc, Gems, and publishing to FTP were included in rake but they're now available in RDoc, RubyGems, and rake-contrib respectively.) * Supports parallel execution of tasks. == Installation === Gem Installation Download and install rake with the following. gem install rake == Usage === Simple Example First, you must write a "Rakefile" file which contains the build rules. Here's a simple example: task default: %w[test] task :test do ruby "test/unittest.rb" end This Rakefile has two tasks: * A task named "test", which -- upon invocation -- will run a unit test file in Ruby. * A task named "default". This task does nothing by itself, but it has exactly one dependency, namely the "test" task. Invoking the "default" task will cause Rake to invoke the "test" task as well. Running the "rake" command without any options will cause it to run the "default" task in the Rakefile: % ls Rakefile test/ % rake (in /home/some_user/Projects/rake) ruby test/unittest.rb ....unit test output here... Type "rake --help" for all available options. == Resources === Rake Information * {Rake command-line}[link:doc/command_line_usage.rdoc] * {Writing Rakefiles}[link:doc/rakefile.rdoc] * The original {Rake announcement}[link:doc/rational.rdoc] * Rake {glossary}[link:doc/glossary.rdoc] === Presentations and Articles about Rake * Avdi Grimm's rake series: 1. {Rake Basics}[http://devblog.avdi.org/2014/04/21/rake-part-1-basics/] 2. {Rake File Lists}[http://devblog.avdi.org/2014/04/22/rake-part-2-file-lists/] 3. {Rake Rules}[http://devblog.avdi.org/2014/04/23/rake-part-3-rules/] 4. {Rake Pathmap}[http://devblog.avdi.org/2014/04/24/rake-part-4-pathmap/] 5. {File Operations}[http://devblog.avdi.org/2014/04/25/rake-part-5-file-operations/] 6. {Clean and Clobber}[http://devblog.avdi.org/2014/04/28/rake-part-6-clean-and-clobber/] 7. {MultiTask}[http://devblog.avdi.org/2014/04/29/rake-part-7-multitask/] * {Jim Weirich's 2003 RubyConf presentation}[http://web.archive.org/web/20140221123354/http://onestepback.org/articles/buildingwithrake/] * Martin Fowler's article on Rake: http://martinfowler.com/articles/rake.html == Other Make Re-envisionings ... Rake is a late entry in the make replacement field. Here are links to other projects with similar (and not so similar) goals. * http://directory.fsf.org/wiki/Bras -- Bras, one of earliest implementations of "make in a scripting language". * http://www.a-a-p.org -- Make in Python * http://ant.apache.org -- The Ant project * http://search.cpan.org/search?query=PerlBuildSystem -- The Perl Build System * http://www.rubydoc.info/gems/rant/0.5.7/frames -- Rant, another Ruby make tool. == Credits [Jim Weirich] Who originally created Rake. [Ryan Dlugosz] For the initial conversation that sparked Rake. [Nobuyoshi Nakada ] For the initial patch for rule support. [Tilman Sauerbeck ] For the recursive rule patch. [Eric Hodel] For aid in maintaining rake. [Hiroshi SHIBATA] Maintainer of Rake 10.X and Rake 11.X == License Rake is available under an MIT-style license. :include: MIT-LICENSE --- = Other stuff Author:: Jim Weirich Requires:: Ruby 2.0.0 or later License:: Copyright Jim Weirich. Released under an MIT-style license. See the MIT-LICENSE file included in the distribution. == Warranty This software is provided "as is" and without any express or implied warranties, including, without limitation, the implied warranties of merchantability and fitness for a particular purpose. == Historical Rake was originally created by Jim Weirich, who unfortunately passed away in February 2014. This repository was originally hosted at {github.com/jimweirich/rake}[https://github.com/jimweirich/rake/], however with his passing, has been moved to {ruby/rake}[https://github.com/ruby/rake]. You can view Jim's last commit here: https://github.com/jimweirich/rake/tree/336559f28f55bce418e2ebcc0a57548dcbac4025 You can {read more about Jim}[https://en.wikipedia.org/wiki/Jim_Weirich] at Wikipedia. Thank you for this great tool, Jim. We'll remember you. PK% ]tocgems/rake-12.3.3/rake.gemspecnu[# -*- encoding: utf-8 -*- # stub: rake 12.3.3 ruby lib Gem::Specification.new do |s| s.name = "rake".freeze s.version = "12.3.3" s.required_rubygems_version = Gem::Requirement.new(">= 1.3.2".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Hiroshi SHIBATA".freeze, "Eric Hodel".freeze, "Jim Weirich".freeze] s.bindir = "exe".freeze s.date = "2019-07-22" s.description = "Rake is a Make-like program implemented in Ruby. Tasks and dependencies are\nspecified in standard Ruby syntax.\nRake has the following features:\n * Rakefiles (rake's version of Makefiles) are completely defined in standard Ruby syntax.\n No XML files to edit. No quirky Makefile syntax to worry about (is that a tab or a space?)\n * Users can specify tasks with prerequisites.\n * Rake supports rule patterns to synthesize implicit tasks.\n * Flexible FileLists that act like arrays but know about manipulating file names and paths.\n * Supports parallel execution of tasks.\n".freeze s.email = ["hsbt@ruby-lang.org".freeze, "drbrain@segment7.net".freeze, "".freeze] s.executables = ["rake".freeze] s.files = ["CONTRIBUTING.rdoc".freeze, "Gemfile".freeze, "History.rdoc".freeze, "MIT-LICENSE".freeze, "README.rdoc".freeze, "Rakefile".freeze, "azure-pipelines.yml".freeze, "bin/bundle".freeze, "bin/console".freeze, "bin/rake".freeze, "bin/rdoc".freeze, "bin/rubocop".freeze, "bin/setup".freeze, "doc/command_line_usage.rdoc".freeze, "doc/example/Rakefile1".freeze, "doc/example/Rakefile2".freeze, "doc/example/a.c".freeze, "doc/example/b.c".freeze, "doc/example/main.c".freeze, "doc/glossary.rdoc".freeze, "doc/jamis.rb".freeze, "doc/proto_rake.rdoc".freeze, "doc/rake.1".freeze, "doc/rakefile.rdoc".freeze, "doc/rational.rdoc".freeze, "exe/rake".freeze, "lib/rake.rb".freeze, "lib/rake/application.rb".freeze, "lib/rake/backtrace.rb".freeze, "lib/rake/clean.rb".freeze, "lib/rake/cloneable.rb".freeze, "lib/rake/cpu_counter.rb".freeze, "lib/rake/default_loader.rb".freeze, "lib/rake/dsl_definition.rb".freeze, "lib/rake/early_time.rb".freeze, "lib/rake/ext/core.rb".freeze, "lib/rake/ext/string.rb".freeze, "lib/rake/file_creation_task.rb".freeze, "lib/rake/file_list.rb".freeze, "lib/rake/file_task.rb".freeze, "lib/rake/file_utils.rb".freeze, "lib/rake/file_utils_ext.rb".freeze, "lib/rake/invocation_chain.rb".freeze, "lib/rake/invocation_exception_mixin.rb".freeze, "lib/rake/late_time.rb".freeze, "lib/rake/linked_list.rb".freeze, "lib/rake/loaders/makefile.rb".freeze, "lib/rake/multi_task.rb".freeze, "lib/rake/name_space.rb".freeze, "lib/rake/packagetask.rb".freeze, "lib/rake/phony.rb".freeze, "lib/rake/private_reader.rb".freeze, "lib/rake/promise.rb".freeze, "lib/rake/pseudo_status.rb".freeze, "lib/rake/rake_module.rb".freeze, "lib/rake/rake_test_loader.rb".freeze, "lib/rake/rule_recursion_overflow_error.rb".freeze, "lib/rake/scope.rb".freeze, "lib/rake/task.rb".freeze, "lib/rake/task_argument_error.rb".freeze, "lib/rake/task_arguments.rb".freeze, "lib/rake/task_manager.rb".freeze, "lib/rake/tasklib.rb".freeze, "lib/rake/testtask.rb".freeze, "lib/rake/thread_history_display.rb".freeze, "lib/rake/thread_pool.rb".freeze, "lib/rake/trace_output.rb".freeze, "lib/rake/version.rb".freeze, "lib/rake/win32.rb".freeze, "rake.gemspec".freeze] s.homepage = "https://github.com/ruby/rake".freeze s.licenses = ["MIT".freeze] s.rdoc_options = ["--main".freeze, "README.rdoc".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.0.0".freeze) s.rubygems_version = "3.1.2".freeze s.summary = "Rake is a Make-like program implemented in Ruby".freeze if s.respond_to? :specification_version then s.specification_version = 4 end if s.respond_to? :add_runtime_dependency then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]?qFF,gems/rake-12.3.3/doc/command_line_usage.rdocnu[= Rake Command Line Usage Rake is invoked from the command line using: % rake [options ...] [VAR=VALUE ...] [targets ...] Options are: [name=value] Set the environment variable name to value during the execution of the rake command. You can access the value by using ENV['name']. [--all (-A)] Used in combination with the -T and -D options, will force those options to show all the tasks, even the ones without comments. [--backtrace{=_output_} (-n)] Enable a full backtrace (i.e. like --trace, but without the task tracing details). The _output_ parameter is optional, but if specified it controls where the backtrace output is sent. If _output_ is stdout, then backtrace output is directed to standard output. If _output_ is stderr, or if it is missing, then the backtrace output is sent to standard error. [--comments] Used in combination with the -W options to force the output to contain commented options only. This is the reverse of --all. [--describe _pattern_ (-D)] Describe the tasks (matching optional PATTERN), then exit. [--dry-run (-n)] Do a dry run. Print the tasks invoked and executed, but do not actually execute any of the actions. [--execute _code_ (-e)] Execute some Ruby code and exit. [--execute-print _code_ (-p)] Execute some Ruby code, print the result, and exit. [--execute-continue _code_ (-E)] Execute some Ruby code, then continue with normal task processing. [--help (-H)] Display some help text and exit. [--jobs _number_ (-j)] Specifies the maximum number of concurrent threads allowed. Rake will allocate threads as needed up to this maximum number. If omitted, Rake will attempt to estimate the number of CPUs on the system and add 4 to that number. The concurrent threads are used to execute the multitask prerequisites. Also see the -m option which turns all tasks into multitasks. Sample values: (no -j) : Allow up to (# of CPUs + 4) number of threads --jobs : Allow unlimited number of threads --jobs=1 : Allow only one thread (the main thread) --jobs=16 : Allow up to 16 concurrent threads [--job-stats _level_] Display job statistics at the completion of the run. By default, this will display the requested number of active threads (from the -j options) and the maximum number of threads in play at any given time. If the optional _level_ is history, then a complete trace of task history will be displayed on standard output. [--libdir _directory_ (-I)] Add _directory_ to the list of directories searched for require. [--multitask (-m)] Treat all tasks as multitasks. ('make/drake' semantics) [--nosearch (-N)] Do not search for a Rakefile in parent directories. [--prereqs (-P)] Display a list of all tasks and their immediate prerequisites. [--quiet (-q)] Do not echo commands from FileUtils. [--rakefile _filename_ (-f)] Use _filename_ as the name of the rakefile. The default rakefile names are +rakefile+ and +Rakefile+ (with +rakefile+ taking precedence). If the rakefile is not found in the current directory, +rake+ will search parent directories for a match. The directory where the Rakefile is found will become the current directory for the actions executed in the Rakefile. [--rakelibdir _rakelibdir_ (-R)] Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib') [--require _name_ (-r)] Require _name_ before executing the Rakefile. [--rules] Trace the rules resolution. [--silent (-s)] Like --quiet, but also suppresses the 'in directory' announcement. [--suppress-backtrace _pattern_ ] Line matching the regular expression _pattern_ will be removed from the backtrace output. Note that the --backtrace option is the full backtrace without these lines suppressed. [--system (-g)] Use the system wide (global) rakefiles. The project Rakefile is ignored. By default, the system wide rakefiles are used only if no project Rakefile is found. On Unix-like system, the system wide rake files are located in $HOME/.rake. On a windows system they are stored in $APPDATA/Rake. [--no-system (-G)] Use the project level Rakefile, ignoring the system-wide (global) rakefiles. [--tasks pattern (-T)] Display a list of the major tasks and their comments. Comments are defined using the "desc" command. If a pattern is given, then only tasks matching the pattern are displayed. [--trace{=_output_} (-t)] Turn on invoke/execute tracing. Also enable full backtrace on errors. The _output_ parameter is optional, but if specified it controls where the trace output is sent. If _output_ is stdout, then trace output is directed to standard output. If _output_ is stderr, or if it is missing, then trace output is sent to standard error. [--verbose (-v)] Echo the Sys commands to standard output. [--version (-V)] Display the program version and exit. [--where pattern (-W)] Display tasks that match pattern and the file and line number where the task is defined. By default this option will display all tasks, not just the tasks that have descriptions. [--no-deprecation-warnings (-X)] Do not display the deprecation warnings. In addition, any command line option of the form VAR=VALUE will be added to the environment hash ENV and may be tested in the Rakefile. PK% ]@u,u,gems/rake-12.3.3/doc/jamis.rbnu[# frozen_string_literal: true module RDoc module Page FONTS = "\"Bitstream Vera Sans\", Verdana, Arial, Helvetica, sans-serif" STYLE = < pre { padding: 0.5em; border: 1px dotted black; background: #FFE; } CSS XHTML_PREAMBLE = %{ } HEADER = XHTML_PREAMBLE + < %title% ENDHEADER FILE_PAGE = <
File
%short_name%
Path: %full_path% IF:cvsurl  (CVS) ENDIF:cvsurl
Modified: %dtm_modified%

HTML ################################################################### CLASS_PAGE = < %classmod%
%full_name% IF:parent ENDIF:parent
In: START:infiles HREF:full_path_url:full_path: IF:cvsurl  (CVS) ENDIF:cvsurl END:infiles
Parent: IF:par_url ENDIF:par_url %parent% IF:par_url ENDIF:par_url
HTML ################################################################### METHOD_LIST = < IF:diagram
%diagram%
ENDIF:diagram IF:description
%description%
ENDIF:description IF:requires
Required Files
    START:requires
  • HREF:aref:name:
  • END:requires
ENDIF:requires IF:toc
Contents
ENDIF:toc IF:methods
Methods
    START:methods
  • HREF:aref:name:
  • END:methods
ENDIF:methods IF:includes
Included Modules
    START:includes
  • HREF:aref:name:
  • END:includes
ENDIF:includes START:sections IF:sectitle IF:seccomment
%seccomment%
ENDIF:seccomment ENDIF:sectitle IF:classlist
Classes and Modules
%classlist% ENDIF:classlist IF:constants
Constants
START:constants IF:desc ENDIF:desc END:constants
%name% = %value%
  %desc%
ENDIF:constants IF:attributes
Attributes
START:attributes END:attributes
IF:rw [%rw%] ENDIF:rw %name% %a_desc%
ENDIF:attributes IF:method_list START:method_list IF:methods
%type% %category% methods
START:methods
IF:callseq %callseq% ENDIF:callseq IFNOT:callseq %name%%params% ENDIF:callseq IF:codeurl [ source ] ENDIF:codeurl
IF:m_desc
%m_desc%
ENDIF:m_desc IF:aka
This method is also aliased as START:aka %name% END:aka
ENDIF:aka IF:sourcecode
%sourcecode%
ENDIF:sourcecode
END:methods ENDIF:methods END:method_list ENDIF:method_list END:sections HTML FOOTER = < ENDFOOTER BODY = HEADER + <
#{METHOD_LIST}
#{FOOTER} ENDBODY ########################## Source code ########################## SRC_PAGE = XHTML_PREAMBLE + < %title%
%code%
HTML ########################## Index ################################ FR_INDEX_BODY = <
START:entries %name%
END:entries
HTML CLASS_INDEX = FILE_INDEX METHOD_INDEX = FILE_INDEX INDEX = XHTML_PREAMBLE + < %title% IF:inline_source ENDIF:inline_source IFNOT:inline_source ENDIF:inline_source <body bgcolor="white"> Click <a href="html/index.html">here</a> for a non-frames version of this page. </body> HTML end end PK% ]Oq AA gems/rake-12.3.3/doc/example/a.cnu[#include void a() { printf ("In function a\n"); } PK% ]۸ &gems/rake-12.3.3/doc/example/Rakefile1nu[# Example Rakefile -*- ruby -*- task :default => [:main] file "a.o" => ["a.c"] do |t| src = t.name.sub(/\.o$/, '.c') sh "gcc #{src} -c -o #{t.name}" end file "b.o" => ["b.c"] do |t| src = t.name.sub(/\.o$/, '.c') sh "gcc #{src} -c -o #{t.name}" end file "main.o" => ["main.c"] do |t| src = t.name.sub(/\.o$/, '.c') sh "gcc #{src} -c -o #{t.name}" end OBJFILES = ["a.o", "b.o", "main.o"] task :obj => OBJFILES file "main" => OBJFILES do |t| sh "gcc -o #{t.name} main.o a.o b.o" end task :clean do rm_f FileList['*.o'] Dir['*~'].each { |fn| rm_f fn } end task :clobber => [:clean] do rm_f "main" end task :run => ["main"] do sh "./main" end PK% ]AA gems/rake-12.3.3/doc/example/b.cnu[#include void b() { printf ("In function b\n"); } PK% ]";WW&gems/rake-12.3.3/doc/example/Rakefile2nu[# Example Rakefile -*- ruby -*- # Using the power of Ruby task :default => [:main] def ext(fn, newext) fn.sub(/\.[^.]+$/, newext) end SRCFILES = Dir['*.c'] OBJFILES = SRCFILES.collect { |fn| ext(fn,".o") } OBJFILES.each do |objfile| srcfile = ext(objfile, ".c") file objfile => [srcfile] do |t| sh "gcc #{srcfile} -c -o #{t.name}" end end file "main" => OBJFILES do |t| sh "gcc -o #{t.name} main.o a.o b.o" end task :clean do rm_f FileList['*.o'] Dir['*~'].each { |fn| rm_f fn } end task :clobber => [:clean] do rm_f "main" end task :run => ["main"] do sh "./main" end PK% ]_bgg#gems/rake-12.3.3/doc/example/main.cnu[#include extern void a(); extern void b(); int main () { a(); b(); return 0; } PK% ]PP"gems/rake-12.3.3/doc/rakefile.rdocnu[= Rakefile Format First of all, there is no special format for a Rakefile. A Rakefile contains executable Ruby code. Anything legal in a ruby script is allowed in a Rakefile. Now that we understand there is no special syntax in a Rakefile, there are some conventions that are used in a Rakefile that are a little unusual in a typical Ruby program. Since a Rakefile is tailored to specifying tasks and actions, the idioms used in a Rakefile are designed to support that. So, what goes into a Rakefile? == Tasks Tasks are the main unit of work in a Rakefile. Tasks have a name (usually given as a symbol or a string), a list of prerequisites (more symbols or strings) and a list of actions (given as a block). === Simple Tasks A task is declared by using the +task+ method. +task+ takes a single parameter that is the name of the task. task :name === Tasks with Prerequisites Any prerequisites are given as a list (enclosed in square brackets) following the name and an arrow (=>). task name: [:prereq1, :prereq2] *NOTE:* Although this syntax looks a little funky, it is legal Ruby. We are constructing a hash where the key is :name and the value for that key is the list of prerequisites. It is equivalent to the following ... hash = Hash.new hash[:name] = [:prereq1, :prereq2] task(hash) You can also use strings for task names and prerequisites, rake doesn't care. This is the same task definition: task 'name' => %w[prereq1 prereq2] As is this: task name: %w[prereq1 prereq2] We'll prefer this style for regular tasks with prerequisites throughout the rest of the document. Using an array of strings for the prerequisites means you will need to make fewer changes if you need to move tasks into namespaces or perform other refactorings. === Tasks with Actions Actions are defined by passing a block to the +task+ method. Any Ruby code can be placed in the block. The block may reference the task object via the block parameter. task name: [:prereq1, :prereq2] do |t| # actions (may reference t) end === Multiple Definitions A task may be specified more than once. Each specification adds its prerequisites and actions to the existing definition. This allows one part of a rakefile to specify the actions and a different rakefile (perhaps separately generated) to specify the dependencies. For example, the following is equivalent to the single task specification given above. task :name task name: :prereq1 task name: %w[prereq2] task :name do |t| # actions end == File Tasks Some tasks are designed to create a file from one or more other files. Tasks that generate these files may be skipped if the file already exists. File tasks are used to specify file creation tasks. File tasks are declared using the +file+ method (instead of the +task+ method). In addition, file tasks are usually named with a string rather than a symbol. The following file task creates a executable program (named +prog+) given two object files named +a.o+ and +b.o+. The tasks for creating +a.o+ and +b.o+ are not shown. file "prog" => ["a.o", "b.o"] do |t| sh "cc -o #{t.name} #{t.prerequisites.join(' ')}" end == Directory Tasks It is common to need to create directories upon demand. The +directory+ convenience method is a short-hand for creating a FileTask that creates the directory. For example, the following declaration ... directory "testdata/examples/doc" is equivalent to ... file "testdata" do |t| mkdir t.name end file "testdata/examples" => ["testdata"] do |t| mkdir t.name end file "testdata/examples/doc" => ["testdata/examples"] do |t| mkdir t.name end The +directory+ method does not accept prerequisites or actions, but both prerequisites and actions can be added later. For example ... directory "testdata" file "testdata" => ["otherdata"] file "testdata" do cp Dir["standard_data/*.data"], "testdata" end == Tasks with Parallel Prerequisites Rake allows parallel execution of prerequisites using the following syntax: multitask copy_files: %w[copy_src copy_doc copy_bin] do puts "All Copies Complete" end In this example, +copy_files+ is a normal rake task. Its actions are executed whenever all of its prerequisites are done. The big difference is that the prerequisites (+copy_src+, +copy_bin+ and +copy_doc+) are executed in parallel. Each of the prerequisites are run in their own Ruby thread, possibly allowing faster overall runtime. === Secondary Prerequisites If any of the primary prerequisites of a multitask have common secondary prerequisites, all of the primary/parallel prerequisites will wait until the common prerequisites have been run. For example, if the copy_xxx tasks have the following prerequisites: task copy_src: :prep_for_copy task copy_bin: :prep_for_copy task copy_doc: :prep_for_copy Then the +prep_for_copy+ task is run before starting all the copies in parallel. Once +prep_for_copy+ is complete, +copy_src+, +copy_bin+, and +copy_doc+ are all run in parallel. Note that +prep_for_copy+ is run only once, even though it is referenced in multiple threads. === Thread Safety The Rake internal data structures are thread-safe with respect to the multitask parallel execution, so there is no need for the user to do extra synchronization for Rake's benefit. However, if there are user data structures shared between the parallel prerequisites, the user must do whatever is necessary to prevent race conditions. == Tasks with Arguments Prior to version 0.8.0, rake was only able to handle command line arguments of the form NAME=VALUE that were passed into Rake via the ENV hash. Many folks had asked for some kind of simple command line arguments, perhaps using "--" to separate regular task names from argument values on the command line. The problem is that there was no easy way to associate positional arguments on the command line with different tasks. Suppose both tasks :a and :b expect a command line argument: does the first value go with :a? What if :b is run first? Should it then get the first command line argument. Rake 0.8.0 solves this problem by explicitly passing values directly to the tasks that need them. For example, if I had a release task that required a version number, I could say: rake release[0.8.2] And the string "0.8.2" will be passed to the :release task. Multiple arguments can be passed by separating them with a comma, for example: rake name[john,doe] Just a few words of caution. The rake task name and its arguments need to be a single command line argument to rake. This generally means no spaces. If spaces are needed, then the entire name + argument string should be quoted. Something like this: rake "name[billy bob, smith]" (Quoting rules vary between operating systems and shells, so make sure you consult the proper docs for your OS/shell). === Tasks that Expect Parameters Parameters are only given to tasks that are setup to expect them. In order to handle named parameters, the task declaration syntax for tasks has been extended slightly. For example, a task that needs a first name and last name might be declared as: task :name, [:first_name, :last_name] The first argument is still the name of the task (:name in this case). The next two arguments are the names of the parameters expected by :name in an array (:first_name and :last_name in the example). To access the values of the parameters, the block defining the task behaviour can now accept a second parameter: task :name, [:first_name, :last_name] do |t, args| puts "First name is #{args.first_name}" puts "Last name is #{args.last_name}" end The first argument of the block "t" is always bound to the current task object. The second argument "args" is an open-struct like object that allows access to the task arguments. Extra command line arguments to a task are ignored. If you wish to specify default values for the arguments, you can use the with_defaults method in the task body. Here is the above example where we specify default values for the first and last names: task :name, [:first_name, :last_name] do |t, args| args.with_defaults(:first_name => "John", :last_name => "Dough") puts "First name is #{args.first_name}" puts "Last name is #{args.last_name}" end === Tasks that Expect Parameters and Have Prerequisites Tasks that use parameters have a slightly different format for prerequisites. Use the arrow notation to indicate the prerequisites for tasks with arguments. For example: task :name, [:first_name, :last_name] => [:pre_name] do |t, args| args.with_defaults(:first_name => "John", :last_name => "Dough") puts "First name is #{args.first_name}" puts "Last name is #{args.last_name}" end === Tasks that take Variable-length Parameters Tasks that need to handle a list of values as a parameter can use the extras method of the args variable. This allows for tasks that can loop over a variable number of values, and its compatible with named parameters as well: task :email, [:message] do |t, args| mail = Mail.new(args.message) recipients = args.extras recipients.each do |target| mail.send_to(target) end end There is also the convenience method to_a that returns all parameters in the sequential order they were given, including those associated with named parameters. === Deprecated Task Parameters Format There is an older format for declaring task parameters that omitted the task argument array and used the :needs keyword to introduce the dependencies. That format is still supported for compatibility, but is not recommended for use. The older format may be dropped in future versions of rake. == Accessing Task Programmatically Sometimes it is useful to manipulate tasks programmatically in a Rakefile. To find a task object use Rake::Task.[]. === Programmatic Task Example For example, the following Rakefile defines two tasks. The :doit task simply prints a simple "DONE" message. The :dont class will lookup the doit class and remove (clear) all of its prerequisites and actions. task :doit do puts "DONE" end task :dont do Rake::Task[:doit].clear end Running this example: $ rake doit (in /Users/jim/working/git/rake/x) DONE $ rake dont doit (in /Users/jim/working/git/rake/x) $ The ability to programmatically manipulate tasks gives rake very powerful meta-programming capabilities w.r.t. task execution, but should be used with caution. == Rules When a file is named as a prerequisite, but does not have a file task defined for it, Rake will attempt to synthesize a task by looking at a list of rules supplied in the Rakefile. Suppose we were trying to invoke task "mycode.o", but no task is defined for it. But the rakefile has a rule that look like this ... rule '.o' => ['.c'] do |t| sh "cc #{t.source} -c -o #{t.name}" end This rule will synthesize any task that ends in ".o". It has a prerequisite a source file with an extension of ".c" must exist. If Rake is able to find a file named "mycode.c", it will automatically create a task that builds "mycode.o" from "mycode.c". If the file "mycode.c" does not exist, rake will attempt to recursively synthesize a rule for it. When a task is synthesized from a rule, the +source+ attribute of the task is set to the matching source file. This allows us to write rules with actions that reference the source file. === Advanced Rules Any regular expression may be used as the rule pattern. Additionally, a proc may be used to calculate the name of the source file. This allows for complex patterns and sources. The following rule is equivalent to the example above. rule( /\.o$/ => [ proc {|task_name| task_name.sub(/\.[^.]+$/, '.c') } ]) do |t| sh "cc #{t.source} -c -o #{t.name}" end *NOTE:* Because of a _quirk_ in Ruby syntax, parenthesis are required on *rule* when the first argument is a regular expression. The following rule might be used for Java files ... rule '.class' => [ proc { |tn| tn.sub(/\.class$/, '.java').sub(/^classes\//, 'src/') } ] do |t| java_compile(t.source, t.name) end *NOTE:* +java_compile+ is a hypothetical method that invokes the java compiler. == Importing Dependencies Any ruby file (including other rakefiles) can be included with a standard Ruby +require+ command. The rules and declarations in the required file are just added to the definitions already accumulated. Because the files are loaded _before_ the rake targets are evaluated, the loaded files must be "ready to go" when the rake command is invoked. This makes generated dependency files difficult to use. By the time rake gets around to updating the dependencies file, it is too late to load it. The +import+ command addresses this by specifying a file to be loaded _after_ the main rakefile is loaded, but _before_ any targets on the command line are invoked. In addition, if the file name matches an explicit task, that task is invoked before loading the file. This allows dependency files to be generated and used in a single rake command invocation. Example: require 'rake/loaders/makefile' file ".depends.mf" => [SRC_LIST] do |t| sh "makedepend -f- -- #{CFLAGS} -- #{t.prerequisites} > #{t.name}" end import ".depends.mf" If ".depends" does not exist, or is out of date w.r.t. the source files, a new ".depends" file is generated using +makedepend+ before loading. == Comments Standard Ruby comments (beginning with "#") can be used anywhere it is legal in Ruby source code, including comments for tasks and rules. However, if you wish a task to be described using the "-T" switch, then you need to use the +desc+ command to describe the task. Example: desc "Create a distribution package" task package: %w[ ... ] do ... end The "-T" switch (or "--tasks" if you like to spell things out) will display a list of tasks that have a description. If you use +desc+ to describe your major tasks, you have a semi-automatic way of generating a summary of your Rake file. $ rake -T (in /home/.../rake) rake clean # Remove any temporary products. rake clobber # Remove any generated file. rake clobber_rdoc # Remove rdoc products rake contrib_test # Run tests for contrib_test rake default # Default Task rake install # Install the application rake lines # Count lines in the main rake file rake rdoc # Build the rdoc HTML Files rake rerdoc # Force a rebuild of the RDOC files rake test # Run tests rake testall # Run all test targets Only tasks with descriptions will be displayed with the "-T" switch. Use "-P" (or "--prereqs") to get a list of all tasks and their prerequisites. == Namespaces As projects grow (and along with it, the number of tasks), it is common for task names to begin to clash. For example, if you might have a main program and a set of sample programs built by a single Rakefile. By placing the tasks related to the main program in one namespace, and the tasks for building the sample programs in a different namespace, the task names will not interfere with each other. For example: namespace "main" do task :build do # Build the main program end end namespace "samples" do task :build do # Build the sample programs end end task build: %w[main:build samples:build] Referencing a task in a separate namespace can be achieved by prefixing the task name with the namespace and a colon (e.g. "main:build" refers to the :build task in the +main+ namespace). Nested namespaces are supported. Note that the name given in the +task+ command is always the unadorned task name without any namespace prefixes. The +task+ command always defines a task in the current namespace. === FileTasks File task names are not scoped by the namespace command. Since the name of a file task is the name of an actual file in the file system, it makes little sense to include file task names in name space. Directory tasks (created by the +directory+ command) are a type of file task and are also not affected by namespaces. === Name Resolution When looking up a task name, rake will start with the current namespace and attempt to find the name there. If it fails to find a name in the current namespace, it will search the parent namespaces until a match is found (or an error occurs if there is no match). The "rake" namespace is a special implicit namespace that refers to the toplevel names. If a task name begins with a "^" character, the name resolution will start in the parent namespace. Multiple "^" characters are allowed. Here is an example file with multiple :run tasks and how various names resolve in different locations. task :run namespace "one" do task :run namespace "two" do task :run # :run => "one:two:run" # "two:run" => "one:two:run" # "one:two:run" => "one:two:run" # "one:run" => "one:run" # "^run" => "one:run" # "^^run" => "rake:run" (the top level task) # "rake:run" => "rake:run" (the top level task) end # :run => "one:run" # "two:run" => "one:two:run" # "^run" => "rake:run" end # :run => "rake:run" # "one:run" => "one:run" # "one:two:run" => "one:two:run" == FileLists FileLists are the way Rake manages lists of files. You can treat a FileList as an array of strings for the most part, but FileLists support some additional operations. === Creating a FileList Creating a file list is easy. Just give it the list of file names: fl = FileList['file1.rb', file2.rb'] Or give it a glob pattern: fl = FileList['*.rb'] == Odds and Ends === do/end versus { } Blocks may be specified with either a +do+/+end+ pair, or with curly braces in Ruby. We _strongly_ recommend using +do+/+end+ to specify the actions for tasks and rules. Because the rakefile idiom tends to leave off parentheses on the task/file/rule methods, unusual ambiguities can arise when using curly braces. For example, suppose that the method +object_files+ returns a list of object files in a project. Now we use +object_files+ as the prerequisites in a rule specified with actions in curly braces. # DON'T DO THIS! file "prog" => object_files { # Actions are expected here (but it doesn't work)! } Because curly braces have a higher precedence than +do+/+end+, the block is associated with the +object_files+ method rather than the +file+ method. This is the proper way to specify the task ... # THIS IS FINE file "prog" => object_files do # Actions go here end == Rakefile Path When issuing the +rake+ command in a terminal, Rake will look for a Rakefile in the current directory. If a Rakefile is not found, it will search parent directories until one is found. For example, if a Rakefile resides in the +project/+ directory, moving deeper into the project's directory tree will not have an adverse effect on rake tasks: $ pwd /home/user/project $ cd lib/foo/bar $ pwd /home/user/project/lib/foo/bar $ rake run_pwd /home/user/project As far as rake is concerned, all tasks are run from the directory in which the Rakefile resides. === Multiple Rake Files Not all tasks need to be included in a single Rakefile. Additional rake files (with the file extension "+.rake+") may be placed in +rakelib+ directory located at the top level of a project (i.e. the same directory that contains the main +Rakefile+). Also, rails projects may include additional rake files in the +lib/tasks+ directory. === Clean and Clobber Tasks Through require 'rake/clean' Rake provides +clean+ and +clobber+ tasks: +clean+ :: Clean up the project by deleting scratch files and backup files. Add files to the +CLEAN+ FileList to have the +clean+ target handle them. +clobber+ :: Clobber all generated and non-source files in a project. The task depends on +clean+, so all the +CLEAN+ files will be deleted as well as files in the +CLOBBER+ FileList. The intent of this task is to return a project to its pristine, just unpacked state. You can add file names or glob patterns to both the +CLEAN+ and +CLOBBER+ lists. === Phony Task The phony task can be used as a dependency to allow file-based tasks to use non-file-based-tasks as prerequisites without forcing them to rebuild. You can require 'rake/phony' to add the +phony+ task. ---- == See * README.rdoc -- Main documentation for Rake. PK% ]) $gems/rake-12.3.3/doc/proto_rake.rdocnu[= Original Prototype Rake This is the original 100 line prototype rake program. --- #!/usr/bin/env ruby require 'ftools' class Task TASKS = Hash.new attr_reader :prerequisites def initialize(task_name) @name = task_name @prerequisites = [] @actions = [] end def enhance(deps=nil, &block) @prerequisites |= deps if deps @actions << block if block_given? self end def name @name.to_s end def invoke @prerequisites.each { |n| Task[n].invoke } execute if needed? end def execute return if @triggered @triggered = true @actions.collect { |act| result = act.call(self) }.last end def needed? true end def timestamp Time.now end class << self def [](task_name) TASKS[intern(task_name)] or fail "Don't know how to rake #{task_name}" end def define_task(args, &block) case args when Hash fail "Too Many Target Names: #{args.keys.join(' ')}" if args.size > 1 fail "No Task Name Given" if args.size < 1 task_name = args.keys[0] deps = args[task_name] else task_name = args deps = [] end deps = deps.collect {|d| intern(d) } get(task_name).enhance(deps, &block) end def get(task_name) name = intern(task_name) TASKS[name] ||= self.new(name) end def intern(task_name) (Symbol === task_name) ? task_name : task_name.intern end end end class FileTask < Task def needed? return true unless File.exist?(name) latest_prereq = @prerequisites.collect{|n| Task[n].timestamp}.max return false if latest_prereq.nil? timestamp < latest_prereq end def timestamp File.new(name.to_s).mtime end end def task(args, &block) Task.define_task(args, &block) end def file(args, &block) FileTask.define_task(args, &block) end def sys(cmd) puts cmd system(cmd) or fail "Command Failed: [#{cmd}]" end def rake begin here = Dir.pwd while ! File.exist?("Rakefile") Dir.chdir("..") fail "No Rakefile found" if Dir.pwd == here here = Dir.pwd end puts "(in #{Dir.pwd})" load "./Rakefile" ARGV.push("default") if ARGV.size == 0 ARGV.each { |task_name| Task[task_name].invoke } rescue Exception => ex puts "rake aborted ... #{ex.message}" puts ex.backtrace.find {|str| str =~ /Rakefile/ } || "" end end if __FILE__ == $0 then rake end PK% ]gems/rake-12.3.3/doc/rake.1nu[.Dd June 12, 2016 .Dt RAKE 1 .Os rake 11.2.2 .Sh NAME .Nm rake .Nd make-like build utility for Ruby .Sh SYNOPSIS .Nm .Op Fl f Ar rakefile .Op Ar options .Ar targets ... .Sh DESCRIPTION .Nm is a .Xr make 1 Ns -like build utility for Ruby. Tasks and dependencies are specified in standard Ruby syntax. .Sh OPTIONS .Bl -tag -width Ds .It Fl m , Fl -multitask Treat all tasks as multitasks. .It Fl B , Fl -build-all Build all prerequisites, including those which are up\-to\-date. .It Fl j , Fl -jobs Ar num_jobs Specifies the maximum number of tasks to execute in parallel (default is number of CPU cores + 4). .El .Ss Modules .Bl -tag -width Ds .It Fl I , Fl -libdir Ar libdir Include .Ar libdir in the search path for required modules. .It Fl r , Fl -require Ar module Require .Ar module before executing .Pa rakefile . .El .Ss Rakefile location .Bl -tag -width Ds .It Fl f , Fl -rakefile Ar filename Use .Ar filename as the rakefile to search for. .It Fl N , Fl -no-search , Fl -nosearch Do not search parent directories for the Rakefile. .It Fl G , Fl -no-system , Fl -nosystem Use standard project Rakefile search paths, ignore system wide rakefiles. .It Fl R , Fl -rakelib Ar rakelibdir , Fl -rakelibdir Ar rakelibdir Auto-import any .rake files in .Ar rakelibdir (default is .Sq rakelib ) .It Fl g , Fl -system Use system-wide (global) rakefiles (usually .Pa ~/.rake/*.rake ) . .El .Ss Debugging .Bl -tag -width Ds .It Fl -backtrace Ns = Ns Ar out Enable full backtrace. .Ar out can be .Dv stderr (default) or .Dv stdout . .It Fl t , Fl -trace Ns = Ns Ar out Turn on invoke/execute tracing, enable full backtrace. .Ar out can be .Dv stderr (default) or .Dv stdout . .It Fl -suppress-backtrace Ar pattern Suppress backtrace lines matching regexp .Ar pattern . Ignored if .Fl -trace is on. .It Fl -rules Trace the rules resolution. .It Fl n , Fl -dry-run Do a dry run without executing actions. .It Fl T , Fl -tasks Op Ar pattern Display the tasks (matching optional .Ar pattern ) with descriptions, then exit. .It Fl D , Fl -describe Op Ar pattern Describe the tasks (matching optional .Ar pattern ) , then exit. .It Fl W , Fl -where Op Ar pattern Describe the tasks (matching optional .Ar pattern ) , then exit. .It Fl P , Fl -prereqs Display the tasks and dependencies, then exit. .It Fl e , Fl -execute Ar code Execute some Ruby code and exit. .It Fl p , Fl -execute-print Ar code Execute some Ruby code, print the result, then exit. .It Fl E , Fl -execute-continue Ar code Execute some Ruby code, then continue with normal task processing. .El .Ss Information .Bl -tag -width Ds .It Fl v , Fl -verbose Log message to standard output. .It Fl q , Fl -quiet Do not log messages to standard output. .It Fl s , Fl -silent Like .Fl -quiet , but also suppresses the .Sq in directory announcement. .It Fl X , Fl -no-deprecation-warnings Disable the deprecation warnings. .It Fl -comments Show commented tasks only .It Fl A , Fl -all Show all tasks, even uncommented ones (in combination with .Fl T or .Fl D ) .It Fl -job-stats Op Ar level Display job statistics. If .Ar level is .Sq history , displays a complete job list. .It Fl V , Fl -version Display the program version. .It Fl h , Fl H , Fl -help Display a help message. .El .Sh SEE ALSO The complete documentation for .Nm rake has been installed at .Pa /usr/share/doc/rake-doc/html/index.html . It is also available online at .Lk https://ruby.github.io/rake . .Sh AUTHORS .An -nosplit .Nm was written by .An Jim Weirich Aq Mt jim@weirichhouse.org . .Pp This manual was created by .An Caitlin Matos Aq Mt caitlin.matos@zoho.com for the Debian project (but may be used by others). It was inspired by the manual by .An Jani Monoses Aq Mt jani@iv.ro for the Ubuntu project. PK% ]v3HH"gems/rake-12.3.3/doc/rational.rdocnu[= Why rake? Ok, let me state from the beginning that I never intended to write this code. I'm not convinced it is useful, and I'm not convinced anyone would even be interested in it. All I can say is that Why's onion truck must by been passing through the Ohio valley. What am I talking about? ... A Ruby version of Make. See, I can sense you cringing already, and I agree. The world certainly doesn't need yet another reworking of the "make" program. I mean, we already have "ant". Isn't that enough? It started yesterday. I was helping a coworker fix a problem in one of the Makefiles we use in our project. Not a particularly tough problem, but during the course of the conversation I began lamenting some of the shortcomings of make. In particular, in one of my makefiles I wanted to determine the name of a file dynamically and had to resort to some simple scripting (in Ruby) to make it work. "Wouldn't it be nice if you could just use Ruby inside a Makefile" I said. My coworker (a recent convert to Ruby) agreed, but wondered what it would look like. So I sketched the following on the whiteboard... "What if you could specify the make tasks in Ruby, like this ..." task "build" do java_compile(...args, etc ...) end "The task function would register "build" as a target to be made, and the block would be the action executed whenever the build system determined that it was time to do the build target." We agreed that would be cool, but writing make from scratch would be WAY too much work. And that was the end of that! ... Except I couldn't get the thought out of my head. What exactly would be needed to make the about syntax work as a make file? Hmmm, you would need to register the tasks, you need some way of specifying dependencies between tasks, and some way of kicking off the process. Hey! What if we did ... and fifteen minutes later I had a working prototype of Ruby make, complete with dependencies and actions. I showed the code to my coworker and we had a good laugh. It was just about a page worth of code that reproduced an amazing amount of the functionality of make. We were both truly stunned with the power of Ruby. But it didn't do everything make did. In particular, it didn't have timestamp based file dependencies (where a file is rebuilt if any of its prerequisite files have a later timestamp). Obviously THAT would be a pain to add and so Ruby Make would remain an interesting experiment. ... Except as I walked back to my desk, I started thinking about what file based dependencies would really need. Rats! I was hooked again, and by adding a new class and two new methods, file/timestamp dependencies were implemented. Ok, now I was really hooked. Last night (during CSI!) I massaged the code and cleaned it up a bit. The result is a bare-bones replacement for make in exactly 100 lines of code. For the curious, you can see it at ... * doc/proto_rake.rdoc Oh, about the name. When I wrote the example Ruby Make task on my whiteboard, my coworker exclaimed "Oh! I have the perfect name: Rake ... Get it? Ruby-Make. Rake!" He said he envisioned the tasks as leaves and Rake would clean them up ... or something like that. Anyways, the name stuck. Some quick examples ... A simple task to delete backup files ... task :clean do Dir['*~'].each {|fn| rm fn rescue nil} end Note that task names are symbols (they are slightly easier to type than quoted strings ... but you may use quoted string if you would rather). Rake makes the methods of the FileUtils module directly available, so we take advantage of the rm command. Also note the use of "rescue nil" to trap and ignore errors in the rm command. To run it, just type "rake clean". Rake will automatically find a Rakefile in the current directory (or above!) and will invoke the targets named on the command line. If there are no targets explicitly named, rake will invoke the task "default". Here's another task with dependencies ... task :clobber => [:clean] do rm_r "tempdir" end Task :clobber depends upon task :clean, so :clean will be run before :clobber is executed. Files are specified by using the "file" command. It is similar to the task command, except that the task name represents a file, and the task will be run only if the file doesn't exist, or if its modification time is earlier than any of its prerequisites. Here is a file based dependency that will compile "hello.cc" to "hello.o". file "hello.cc" file "hello.o" => ["hello.cc"] do |t| srcfile = t.name.sub(/\.o$/, ".cc") sh %{g++ #{srcfile} -c -o #{t.name}} end I normally specify file tasks with string (rather than symbols). Some file names can't be represented by symbols. Plus it makes the distinction between them more clear to the casual reader. Currently writing a task for each and every file in the project would be tedious at best. I envision a set of libraries to make this job easier. For instance, perhaps something like this ... require 'rake/ctools' Dir['*.c'].each do |fn| c_source_file(fn) end where "c_source_file" will create all the tasks need to compile all the C source files in a directory. Any number of useful libraries could be created for rake. That's it. There's no documentation (other than whats in this message). Does this sound interesting to anyone? If so, I'll continue to clean it up and write it up and publish it on RAA. Otherwise, I'll leave it as an interesting exercise and a tribute to the power of Ruby. Why /might/ rake be interesting to Ruby programmers. I don't know, perhaps ... * No weird make syntax (only weird Ruby syntax :-) * No need to edit or read XML (a la ant) * Platform independent build scripts. * Will run anywhere Ruby exists, so no need to have "make" installed. If you stay away from the "sys" command and use things like 'ftools', you can have a perfectly platform independent build script. Also rake is only 100 lines of code, so it can easily be packaged along with the rest of your code. So ... Sorry for the long rambling message. Like I said, I never intended to write this code at all. PK% ]'S{"gems/rake-12.3.3/doc/glossary.rdocnu[= Glossary action :: Code to be executed in order to perform a task. Actions in a Rakefile are specified in a code block. (Usually delimited by +do+/+end+ pairs.) execute :: When a task is executed, all of its actions are performed in the order they were defined. Note that, unlike invoke, execute always executes the actions (without invoking or executing the prerequisites). file task (Rake::FileTask) :: A file task is a task whose purpose is to create a file (which has the same name as the task). When invoked, a file task will only execute if one or more of the following conditions are true. 1. The associated file does not exist. 2. A prerequisite has a later time stamp than the existing file. Because normal Tasks always have the current time as timestamp, a FileTask that has a normal Task prerequisite will always execute. invoke :: When a task is invoked, first we check to see if it has been invoked before. If it has been, then nothing else is done. If this is the first time it has been invoked, then we invoke each of its prerequisites. Finally, we check to see if we need to execute the actions of this task by calling Rake::Task#needed?. If the task is needed, we execute its actions. NOTE: Prerequisites are still invoked even if the task is not needed. prerequisites :: Every task has a (possibly empty) set of prerequisites. A prerequisite P to Task T is itself a task that must be invoked before Task T. rule :: A rule is a recipe for synthesizing a task when no task is explicitly defined. Rules generally synthesize file tasks. task (Rake::Task) :: The basic unit of work in a Rakefile. A task has a name, a set of prerequisites, and a list of actions to be performed. PK% ]Xgems/rake-12.3.3/bin/rdocnu[#!/usr/bin/env ruby # frozen_string_literal: true # # This file was generated by Bundler. # # The application 'rdoc' is installed as part of a gem, and # this file is here to facilitate running it. # require "pathname" ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath) bundle_binstub = File.expand_path("../bundle", __FILE__) if File.file?(bundle_binstub) if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ load(bundle_binstub) else abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") end end require "rubygems" require "bundler/setup" load Gem.bin_path("rdoc", "rdoc") PK% ]Ygems/rake-12.3.3/bin/rakenu[#!/usr/bin/env ruby # frozen_string_literal: true # # This file was generated by Bundler. # # The application 'rake' is installed as part of a gem, and # this file is here to facilitate running it. # require "pathname" ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath) bundle_binstub = File.expand_path("../bundle", __FILE__) if File.file?(bundle_binstub) if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ load(bundle_binstub) else abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") end end require "rubygems" require "bundler/setup" load Gem.bin_path("rake", "rake") PK% ]|u%gems/rake-12.3.3/bin/rubocopnu[#!/usr/bin/env ruby # frozen_string_literal: true # # This file was generated by Bundler. # # The application 'rubocop' is installed as part of a gem, and # this file is here to facilitate running it. # require "pathname" ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath) bundle_binstub = File.expand_path("../bundle", __FILE__) if File.file?(bundle_binstub) if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ load(bundle_binstub) else abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") end end require "rubygems" require "bundler/setup" load Gem.bin_path("rubocop", "rubocop") PK% ]t/;JJgems/rake-12.3.3/bin/setupnu[#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' set -vx bundle install PK% ]r WUUgems/rake-12.3.3/bin/consolenu[#!/usr/bin/env ruby require "bundler/setup" require "rake" require "irb" IRB.start PK% ]>h  gems/rake-12.3.3/bin/bundlenu[#!/usr/bin/env ruby # frozen_string_literal: true # # This file was generated by Bundler. # # The application 'bundle' is installed as part of a gem, and # this file is here to facilitate running it. # require "rubygems" m = Module.new do module_function def invoked_as_script? File.expand_path($0) == File.expand_path(__FILE__) end def env_var_version ENV["BUNDLER_VERSION"] end def cli_arg_version return unless invoked_as_script? # don't want to hijack other binstubs return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` bundler_version = nil update_index = nil ARGV.each_with_index do |a, i| if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN bundler_version = a end next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ bundler_version = $1 || ">= 0.a" update_index = i end bundler_version end def gemfile gemfile = ENV["BUNDLE_GEMFILE"] return gemfile if gemfile && !gemfile.empty? File.expand_path("../../Gemfile", __FILE__) end def lockfile lockfile = case File.basename(gemfile) when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) else "#{gemfile}.lock" end File.expand_path(lockfile) end def lockfile_version return unless File.file?(lockfile) lockfile_contents = File.read(lockfile) return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ Regexp.last_match(1) end def bundler_version @bundler_version ||= begin env_var_version || cli_arg_version || lockfile_version || "#{Gem::Requirement.default}.a" end end def load_bundler! ENV["BUNDLE_GEMFILE"] ||= gemfile # must dup string for RG < 1.8 compatibility activate_bundler(bundler_version.dup) end def activate_bundler(bundler_version) if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0") bundler_version = "< 2" end gem_error = activation_error_handling do gem "bundler", bundler_version end return if gem_error.nil? require_error = activation_error_handling do require "bundler/version" end return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION)) warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`" exit 42 end def activation_error_handling yield nil rescue StandardError, LoadError => e e end end m.load_bundler! if m.invoked_as_script? load Gem.bin_path("bundler", "bundle") end PK% ]R  (gems/rake-12.3.3/lib/rake/linked_list.rbnu[# frozen_string_literal: true module Rake # Polylithic linked list structure used to implement several data # structures in Rake. class LinkedList include Enumerable attr_reader :head, :tail # Polymorphically add a new element to the head of a list. The # type of head node will be the same list type as the tail. def conj(item) self.class.cons(item, self) end # Is the list empty? # .make guards against a list being empty making any instantiated LinkedList # object not empty by default # You should consider overriding this method if you implement your own .make method def empty? false end # Lists are structurally equivalent. def ==(other) current = self while !current.empty? && !other.empty? return false if current.head != other.head current = current.tail other = other.tail end current.empty? && other.empty? end # Convert to string: LL(item, item...) def to_s items = map(&:to_s).join(", ") "LL(#{items})" end # Same as +to_s+, but with inspected items. def inspect items = map(&:inspect).join(", ") "LL(#{items})" end # For each item in the list. def each current = self while !current.empty? yield(current.head) current = current.tail end self end # Make a list out of the given arguments. This method is # polymorphic def self.make(*args) # return an EmptyLinkedList if there are no arguments return empty if !args || args.empty? # build a LinkedList by starting at the tail and iterating # through each argument # inject takes an EmptyLinkedList to start args.reverse.inject(empty) do |list, item| list = cons(item, list) list # return the newly created list for each item in the block end end # Cons a new head onto the tail list. def self.cons(head, tail) new(head, tail) end # The standard empty list class for the given LinkedList class. def self.empty self::EMPTY end protected def initialize(head, tail=EMPTY) @head = head @tail = tail end # Represent an empty list, using the Null Object Pattern. # # When inheriting from the LinkedList class, you should implement # a type specific Empty class as well. Make sure you set the class # instance variable @parent to the associated list class (this # allows conj, cons and make to work polymorphically). class EmptyLinkedList < LinkedList @parent = LinkedList def initialize end def empty? true end def self.cons(head, tail) @parent.cons(head, tail) end end EMPTY = EmptyLinkedList.new end end PK% ]2bb-gems/rake-12.3.3/lib/rake/loaders/makefile.rbnu[# frozen_string_literal: true module Rake # Makefile loader to be used with the import file loader. Use this to # import dependencies from make dependency tools: # # require 'rake/loaders/makefile' # # file ".depends.mf" => [SRC_LIST] do |t| # sh "makedepend -f- -- #{CFLAGS} -- #{t.prerequisites} > #{t.name}" # end # # import ".depends.mf" # # See {Importing Dependencies}[link:doc/rakefile_rdoc.html#label-Importing+Dependencies] # for further details. class MakefileLoader include Rake::DSL SPACE_MARK = "\0" # :nodoc: # Load the makefile dependencies in +fn+. def load(fn) # :nodoc: lines = File.read fn lines.gsub!(/\\ /, SPACE_MARK) lines.gsub!(/#[^\n]*\n/m, "") lines.gsub!(/\\\n/, " ") lines.each_line do |line| process_line(line) end end private # Process one logical line of makefile data. def process_line(line) # :nodoc: file_tasks, args = line.split(":", 2) return if args.nil? dependents = args.split.map { |d| respace(d) } file_tasks.scan(/\S+/) do |file_task| file_task = respace(file_task) file file_task => dependents end end def respace(str) # :nodoc: str.tr SPACE_MARK, " " end end # Install the handler Rake.application.add_loader("mf", MakefileLoader.new) end PK% ]u%gems/rake-12.3.3/lib/rake/ext/core.rbnu[# frozen_string_literal: true class Module # Check for an existing method in the current class before extending. If # the method already exists, then a warning is printed and the extension is # not added. Otherwise the block is yielded and any definitions in the # block will take effect. # # Usage: # # class String # rake_extension("xyz") do # def xyz # ... # end # end # end # def rake_extension(method) # :nodoc: if method_defined?(method) $stderr.puts "WARNING: Possible conflict with Rake extension: " + "#{self}##{method} already exists" else yield end end end PK% ]yOurr'gems/rake-12.3.3/lib/rake/ext/string.rbnu[# frozen_string_literal: true require "rake/ext/core" class String rake_extension("ext") do # Replace the file extension with +newext+. If there is no extension on # the string, append the new extension to the end. If the new extension # is not given, or is the empty string, remove any existing extension. # # +ext+ is a user added method for the String class. # # This String extension comes from Rake def ext(newext="") return self.dup if [".", ".."].include? self if newext != "" newext = "." + newext unless newext =~ /^\./ end self.chomp(File.extname(self)) << newext end end rake_extension("pathmap") do # Explode a path into individual components. Used by +pathmap+. # # This String extension comes from Rake def pathmap_explode head, tail = File.split(self) return [self] if head == self return [tail] if head == "." || tail == "/" return [head, tail] if head == "/" return head.pathmap_explode + [tail] end protected :pathmap_explode # Extract a partial path from the path. Include +n+ directories from the # front end (left hand side) if +n+ is positive. Include |+n+| # directories from the back end (right hand side) if +n+ is negative. # # This String extension comes from Rake def pathmap_partial(n) dirs = File.dirname(self).pathmap_explode partial_dirs = if n > 0 dirs[0...n] elsif n < 0 dirs.reverse[0...-n].reverse else "." end File.join(partial_dirs) end protected :pathmap_partial # Perform the pathmap replacement operations on the given path. The # patterns take the form 'pat1,rep1;pat2,rep2...'. # # This String extension comes from Rake def pathmap_replace(patterns, &block) result = self patterns.split(";").each do |pair| pattern, replacement = pair.split(",") pattern = Regexp.new(pattern) if replacement == "*" && block_given? result = result.sub(pattern, &block) elsif replacement result = result.sub(pattern, replacement) else result = result.sub(pattern, "") end end result end protected :pathmap_replace # Map the path according to the given specification. The specification # controls the details of the mapping. The following special patterns are # recognized: # # %p :: The complete path. # %f :: The base file name of the path, with its file extension, # but without any directories. # %n :: The file name of the path without its file extension. # %d :: The directory list of the path. # %x :: The file extension of the path. An empty string if there # is no extension. # %X :: Everything *but* the file extension. # %s :: The alternate file separator if defined, otherwise use # # the standard file separator. # %% :: A percent sign. # # The %d specifier can also have a numeric prefix (e.g. '%2d'). # If the number is positive, only return (up to) +n+ directories in the # path, starting from the left hand side. If +n+ is negative, return (up # to) +n+ directories from the right hand side of the path. # # Examples: # # 'a/b/c/d/file.txt'.pathmap("%2d") => 'a/b' # 'a/b/c/d/file.txt'.pathmap("%-2d") => 'c/d' # # Also the %d, %p, %f, %n, # %x, and %X operators can take a pattern/replacement # argument to perform simple string substitutions on a particular part of # the path. The pattern and replacement are separated by a comma and are # enclosed by curly braces. The replacement spec comes after the % # character but before the operator letter. (e.g. "%{old,new}d"). # Multiple replacement specs should be separated by semi-colons (e.g. # "%{old,new;src,bin}d"). # # Regular expressions may be used for the pattern, and back refs may be # used in the replacement text. Curly braces, commas and semi-colons are # excluded from both the pattern and replacement text (let's keep parsing # reasonable). # # For example: # # "src/org/onestepback/proj/A.java".pathmap("%{^src,class}X.class") # # returns: # # "class/org/onestepback/proj/A.class" # # If the replacement text is '*', then a block may be provided to perform # some arbitrary calculation for the replacement. # # For example: # # "/path/to/file.TXT".pathmap("%X%{.*,*}x") { |ext| # ext.downcase # } # # Returns: # # "/path/to/file.txt" # # This String extension comes from Rake def pathmap(spec=nil, &block) return self if spec.nil? result = "".dup spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag| case frag when "%f" result << File.basename(self) when "%n" result << File.basename(self).ext when "%d" result << File.dirname(self) when "%x" result << File.extname(self) when "%X" result << self.ext when "%p" result << self when "%s" result << (File::ALT_SEPARATOR || File::SEPARATOR) when "%-" # do nothing when "%%" result << "%" when /%(-?\d+)d/ result << pathmap_partial($1.to_i) when /^%\{([^}]*)\}(\d*[dpfnxX])/ patterns, operator = $1, $2 result << pathmap("%" + operator).pathmap_replace(patterns, &block) when /^%/ fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'" else result << frag end end result end end end PK% ].*C}}"gems/rake-12.3.3/lib/rake/phony.rbnu[# frozen_string_literal: true # Defines a :phony task that you can use as a dependency. This allows # file-based tasks to use non-file-based tasks as prerequisites # without forcing them to rebuild. # # See FileTask#out_of_date? and Task#timestamp for more info. require "rake" task :phony Rake::Task[:phony].tap do |task| def task.timestamp # :nodoc: Time.at 0 end end PK% ]?{Hrr'gems/rake-12.3.3/lib/rake/early_time.rbnu[# frozen_string_literal: true module Rake # EarlyTime is a fake timestamp that occurs _before_ any other time value. class EarlyTime include Comparable include Singleton ## # The EarlyTime always comes before +other+! def <=>(other) -1 end def to_s # :nodoc: "" end end EARLY = EarlyTime.instance end PK% ]n#0gems/rake-12.3.3/lib/rake/task_argument_error.rbnu[# frozen_string_literal: true module Rake # Error indicating an ill-formed task declaration. class TaskArgumentError < ArgumentError end end PK% ]ݢ"gems/rake-12.3.3/lib/rake/clean.rbnu[# frozen_string_literal: true # The 'rake/clean' file defines two file lists (CLEAN and CLOBBER) and # two rake tasks (:clean and :clobber). # # [:clean] Clean up the project by deleting scratch files and backup # files. Add files to the CLEAN file list to have the :clean # target handle them. # # [:clobber] Clobber all generated and non-source files in a project. # The task depends on :clean, so all the clean files will # be deleted as well as files in the CLOBBER file list. # The intent of this task is to return a project to its # pristine, just unpacked state. require "rake" # :stopdoc: module Rake module Cleaner extend FileUtils module_function def cleanup_files(file_names) file_names.each do |file_name| cleanup(file_name) end end def cleanup(file_name, opts={}) begin opts = { verbose: Rake.application.options.trace }.merge(opts) rm_r file_name, opts rescue StandardError => ex puts "Failed to remove #{file_name}: #{ex}" unless file_already_gone?(file_name) end end def file_already_gone?(file_name) return false if File.exist?(file_name) path = file_name prev = nil while path = File.dirname(path) return false if cant_be_deleted?(path) break if [prev, "."].include?(path) prev = path end true end private_class_method :file_already_gone? def cant_be_deleted?(path_name) File.exist?(path_name) && (!File.readable?(path_name) || !File.executable?(path_name)) end private_class_method :cant_be_deleted? end end CLEAN = ::Rake::FileList["**/*~", "**/*.bak", "**/core"] CLEAN.clear_exclude.exclude { |fn| fn.pathmap("%f").downcase == "core" && File.directory?(fn) } desc "Remove any temporary products." task :clean do Rake::Cleaner.cleanup_files(CLEAN) end CLOBBER = ::Rake::FileList.new desc "Remove any generated files." task clobber: [:clean] do Rake::Cleaner.cleanup_files(CLOBBER) end PK% ]d11&gems/rake-12.3.3/lib/rake/file_list.rbnu[# frozen_string_literal: true require "rake/cloneable" require "rake/file_utils_ext" require "rake/ext/string" module Rake ## # A FileList is essentially an array with a few helper methods defined to # make file manipulation a bit easier. # # FileLists are lazy. When given a list of glob patterns for possible files # to be included in the file list, instead of searching the file structures # to find the files, a FileList holds the pattern for latter use. # # This allows us to define a number of FileList to match any number of # files, but only search out the actual files when then FileList itself is # actually used. The key is that the first time an element of the # FileList/Array is requested, the pending patterns are resolved into a real # list of file names. # class FileList include Cloneable # == Method Delegation # # The lazy evaluation magic of FileLists happens by implementing all the # array specific methods to call +resolve+ before delegating the heavy # lifting to an embedded array object (@items). # # In addition, there are two kinds of delegation calls. The regular kind # delegates to the @items array and returns the result directly. Well, # almost directly. It checks if the returned value is the @items object # itself, and if so will return the FileList object instead. # # The second kind of delegation call is used in methods that normally # return a new Array object. We want to capture the return value of these # methods and wrap them in a new FileList object. We enumerate these # methods in the +SPECIAL_RETURN+ list below. # List of array methods (that are not in +Object+) that need to be # delegated. ARRAY_METHODS = (Array.instance_methods - Object.instance_methods).map(&:to_s) # List of additional methods that must be delegated. MUST_DEFINE = %w[inspect <=>] # List of methods that should not be delegated here (we define special # versions of them explicitly below). MUST_NOT_DEFINE = %w[to_a to_ary partition * <<] # List of delegated methods that return new array values which need # wrapping. SPECIAL_RETURN = %w[ map collect sort sort_by select find_all reject grep compact flatten uniq values_at + - & | ] DELEGATING_METHODS = (ARRAY_METHODS + MUST_DEFINE - MUST_NOT_DEFINE).map(&:to_s).sort.uniq # Now do the delegation. DELEGATING_METHODS.each do |sym| if SPECIAL_RETURN.include?(sym) ln = __LINE__ + 1 class_eval %{ def #{sym}(*args, &block) resolve result = @items.send(:#{sym}, *args, &block) self.class.new.import(result) end }, __FILE__, ln else ln = __LINE__ + 1 class_eval %{ def #{sym}(*args, &block) resolve result = @items.send(:#{sym}, *args, &block) result.object_id == @items.object_id ? self : result end }, __FILE__, ln end end GLOB_PATTERN = %r{[*?\[\{]} # Create a file list from the globbable patterns given. If you wish to # perform multiple includes or excludes at object build time, use the # "yield self" pattern. # # Example: # file_list = FileList.new('lib/**/*.rb', 'test/test*.rb') # # pkg_files = FileList.new('lib/**/*') do |fl| # fl.exclude(/\bCVS\b/) # end # def initialize(*patterns) @pending_add = [] @pending = false @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup @exclude_procs = DEFAULT_IGNORE_PROCS.dup @items = [] patterns.each { |pattern| include(pattern) } yield self if block_given? end # Add file names defined by glob patterns to the file list. If an array # is given, add each element of the array. # # Example: # file_list.include("*.java", "*.cfg") # file_list.include %w( math.c lib.h *.o ) # def include(*filenames) # TODO: check for pending filenames.each do |fn| if fn.respond_to? :to_ary include(*fn.to_ary) else @pending_add << Rake.from_pathname(fn) end end @pending = true self end alias :add :include # Register a list of file name patterns that should be excluded from the # list. Patterns may be regular expressions, glob patterns or regular # strings. In addition, a block given to exclude will remove entries that # return true when given to the block. # # Note that glob patterns are expanded against the file system. If a file # is explicitly added to a file list, but does not exist in the file # system, then an glob pattern in the exclude list will not exclude the # file. # # Examples: # FileList['a.c', 'b.c'].exclude("a.c") => ['b.c'] # FileList['a.c', 'b.c'].exclude(/^a/) => ['b.c'] # # If "a.c" is a file, then ... # FileList['a.c', 'b.c'].exclude("a.*") => ['b.c'] # # If "a.c" is not a file, then ... # FileList['a.c', 'b.c'].exclude("a.*") => ['a.c', 'b.c'] # def exclude(*patterns, &block) patterns.each do |pat| if pat.respond_to? :to_ary exclude(*pat.to_ary) else @exclude_patterns << Rake.from_pathname(pat) end end @exclude_procs << block if block_given? resolve_exclude unless @pending self end # Clear all the exclude patterns so that we exclude nothing. def clear_exclude @exclude_patterns = [] @exclude_procs = [] self end # A FileList is equal through array equality. def ==(array) to_ary == array end # Return the internal array object. def to_a resolve @items end # Return the internal array object. def to_ary to_a end # Lie about our class. def is_a?(klass) klass == Array || super(klass) end alias kind_of? is_a? # Redefine * to return either a string or a new file list. def *(other) result = @items * other case result when Array self.class.new.import(result) else result end end def <<(obj) resolve @items << Rake.from_pathname(obj) self end # Resolve all the pending adds now. def resolve if @pending @pending = false @pending_add.each do |fn| resolve_add(fn) end @pending_add = [] resolve_exclude end self end def resolve_add(fn) # :nodoc: case fn when GLOB_PATTERN add_matching(fn) else self << fn end end private :resolve_add def resolve_exclude # :nodoc: reject! { |fn| excluded_from_list?(fn) } self end private :resolve_exclude # Return a new FileList with the results of running +sub+ against each # element of the original list. # # Example: # FileList['a.c', 'b.c'].sub(/\.c$/, '.o') => ['a.o', 'b.o'] # def sub(pat, rep) inject(self.class.new) { |res, fn| res << fn.sub(pat, rep) } end # Return a new FileList with the results of running +gsub+ against each # element of the original list. # # Example: # FileList['lib/test/file', 'x/y'].gsub(/\//, "\\") # => ['lib\\test\\file', 'x\\y'] # def gsub(pat, rep) inject(self.class.new) { |res, fn| res << fn.gsub(pat, rep) } end # Same as +sub+ except that the original file list is modified. def sub!(pat, rep) each_with_index { |fn, i| self[i] = fn.sub(pat, rep) } self end # Same as +gsub+ except that the original file list is modified. def gsub!(pat, rep) each_with_index { |fn, i| self[i] = fn.gsub(pat, rep) } self end # Apply the pathmap spec to each of the included file names, returning a # new file list with the modified paths. (See String#pathmap for # details.) def pathmap(spec=nil, &block) collect { |fn| fn.pathmap(spec, &block) } end # Return a new FileList with String#ext method applied to # each member of the array. # # This method is a shortcut for: # # array.collect { |item| item.ext(newext) } # # +ext+ is a user added method for the Array class. def ext(newext="") collect { |fn| fn.ext(newext) } end # Grep each of the files in the filelist using the given pattern. If a # block is given, call the block on each matching line, passing the file # name, line number, and the matching line of text. If no block is given, # a standard emacs style file:linenumber:line message will be printed to # standard out. Returns the number of matched items. def egrep(pattern, *options) matched = 0 each do |fn| begin File.open(fn, "r", *options) do |inf| count = 0 inf.each do |line| count += 1 if pattern.match(line) matched += 1 if block_given? yield fn, count, line else puts "#{fn}:#{count}:#{line}" end end end end rescue StandardError => ex $stderr.puts "Error while processing '#{fn}': #{ex}" end end matched end # Return a new file list that only contains file names from the current # file list that exist on the file system. def existing select { |fn| File.exist?(fn) }.uniq end # Modify the current file list so that it contains only file name that # exist on the file system. def existing! resolve @items = @items.select { |fn| File.exist?(fn) }.uniq self end # FileList version of partition. Needed because the nested arrays should # be FileLists in this version. def partition(&block) # :nodoc: resolve result = @items.partition(&block) [ self.class.new.import(result[0]), self.class.new.import(result[1]), ] end # Convert a FileList to a string by joining all elements with a space. def to_s resolve self.join(" ") end # Add matching glob patterns. def add_matching(pattern) self.class.glob(pattern).each do |fn| self << fn unless excluded_from_list?(fn) end end private :add_matching # Should the given file name be excluded from the list? # # NOTE: This method was formerly named "exclude?", but Rails # introduced an exclude? method as an array method and setup a # conflict with file list. We renamed the method to avoid # confusion. If you were using "FileList#exclude?" in your user # code, you will need to update. def excluded_from_list?(fn) return true if @exclude_patterns.any? do |pat| case pat when Regexp fn =~ pat when GLOB_PATTERN flags = File::FNM_PATHNAME # Ruby <= 1.9.3 does not support File::FNM_EXTGLOB flags |= File::FNM_EXTGLOB if defined? File::FNM_EXTGLOB File.fnmatch?(pat, fn, flags) else fn == pat end end @exclude_procs.any? { |p| p.call(fn) } end DEFAULT_IGNORE_PATTERNS = [ /(^|[\/\\])CVS([\/\\]|$)/, /(^|[\/\\])\.svn([\/\\]|$)/, /\.bak$/, /~$/ ] DEFAULT_IGNORE_PROCS = [ proc { |fn| fn =~ /(^|[\/\\])core$/ && !File.directory?(fn) } ] def import(array) # :nodoc: @items = array self end class << self # Create a new file list including the files listed. Similar to: # # FileList.new(*args) def [](*args) new(*args) end # Get a sorted list of files matching the pattern. This method # should be preferred to Dir[pattern] and Dir.glob(pattern) because # the files returned are guaranteed to be sorted. def glob(pattern, *args) Dir.glob(pattern, *args).sort end end end end module Rake class << self # Yield each file or directory component. def each_dir_parent(dir) # :nodoc: old_length = nil while dir != "." && dir.length != old_length yield(dir) old_length = dir.length dir = File.dirname(dir) end end # Convert Pathname and Pathname-like objects to strings; # leave everything else alone def from_pathname(path) # :nodoc: path = path.to_path if path.respond_to?(:to_path) path = path.to_str if path.respond_to?(:to_str) path end end end # module Rake PK% ]F- +gems/rake-12.3.3/lib/rake/dsl_definition.rbnu[# frozen_string_literal: true # Rake DSL functions. require "rake/file_utils_ext" module Rake ## # DSL is a module that provides #task, #desc, #namespace, etc. Use this # when you'd like to use rake outside the top level scope. # # For a Rakefile you run from the command line this module is automatically # included. module DSL #-- # Include the FileUtils file manipulation functions in the top # level module, but mark them private so that they don't # unintentionally define methods on other objects. #++ include FileUtilsExt private(*FileUtils.instance_methods(false)) private(*FileUtilsExt.instance_methods(false)) private # :call-seq: # task(task_name) # task(task_name: dependencies) # task(task_name, arguments => dependencies) # # Declare a basic task. The +task_name+ is always the first argument. If # the task name contains a ":" it is defined in that namespace. # # The +dependencies+ may be a single task name or an Array of task names. # The +argument+ (a single name) or +arguments+ (an Array of names) define # the arguments provided to the task. # # The task, argument and dependency names may be either symbols or # strings. # # A task with a single dependency: # # task clobber: %w[clean] do # rm_rf "html" # end # # A task with an argument and a dependency: # # task :package, [:version] => :test do |t, args| # # ... # end # # To invoke this task from the command line: # # $ rake package[1.2.3] # def task(*args, &block) # :doc: Rake::Task.define_task(*args, &block) end # Declare a file task. # # Example: # file "config.cfg" => ["config.template"] do # open("config.cfg", "w") do |outfile| # open("config.template") do |infile| # while line = infile.gets # outfile.puts line # end # end # end # end # def file(*args, &block) # :doc: Rake::FileTask.define_task(*args, &block) end # Declare a file creation task. # (Mainly used for the directory command). def file_create(*args, &block) Rake::FileCreationTask.define_task(*args, &block) end # Declare a set of files tasks to create the given directories on # demand. # # Example: # directory "testdata/doc" # def directory(*args, &block) # :doc: result = file_create(*args, &block) dir, _ = *Rake.application.resolve_args(args) dir = Rake.from_pathname(dir) Rake.each_dir_parent(dir) do |d| file_create d do |t| mkdir_p t.name unless File.exist?(t.name) end end result end # Declare a task that performs its prerequisites in # parallel. Multitasks does *not* guarantee that its prerequisites # will execute in any given order (which is obvious when you think # about it) # # Example: # multitask deploy: %w[deploy_gem deploy_rdoc] # def multitask(*args, &block) # :doc: Rake::MultiTask.define_task(*args, &block) end # Create a new rake namespace and use it for evaluating the given # block. Returns a NameSpace object that can be used to lookup # tasks defined in the namespace. # # Example: # # ns = namespace "nested" do # # the "nested:run" task # task :run # end # task_run = ns[:run] # find :run in the given namespace. # # Tasks can also be defined in a namespace by using a ":" in the task # name: # # task "nested:test" do # # ... # end # def namespace(name=nil, &block) # :doc: name = name.to_s if name.kind_of?(Symbol) name = name.to_str if name.respond_to?(:to_str) unless name.kind_of?(String) || name.nil? raise ArgumentError, "Expected a String or Symbol for a namespace name" end Rake.application.in_namespace(name, &block) end # Declare a rule for auto-tasks. # # Example: # rule '.o' => '.c' do |t| # sh 'cc', '-o', t.name, t.source # end # def rule(*args, &block) # :doc: Rake::Task.create_rule(*args, &block) end # Describes the next rake task. Duplicate descriptions are discarded. # Descriptions are shown with rake -T (up to the first # sentence) and rake -D (the entire description). # # Example: # desc "Run the Unit Tests" # task test: [:build] # # ... run tests # end # def desc(description) # :doc: Rake.application.last_description = description end # Import the partial Rakefiles +fn+. Imported files are loaded # _after_ the current file is completely loaded. This allows the # import statement to appear anywhere in the importing file, and yet # allowing the imported files to depend on objects defined in the # importing file. # # A common use of the import statement is to include files # containing dependency declarations. # # See also the --rakelibdir command line option. # # Example: # import ".depend", "my_rules" # def import(*fns) # :doc: fns.each do |fn| Rake.application.add_import(fn) end end end extend FileUtilsExt end # Extend the main object with the DSL commands. This allows top-level # calls to task, etc. to work from a Rakefile without polluting the # object inheritance tree. self.extend Rake::DSL PK% ]&gems/rake-12.3.3/lib/rake/cloneable.rbnu[# frozen_string_literal: true module Rake ## # Mixin for creating easily cloned objects. module Cloneable # :nodoc: # The hook that is invoked by 'clone' and 'dup' methods. def initialize_copy(source) super source.instance_variables.each do |var| src_value = source.instance_variable_get(var) value = src_value.clone rescue src_value instance_variable_set(var, value) end end end end PK% ]; rm # -rf /. # # If a block is given, upon command completion the block is called with an # OK flag (true on a zero exit status) and a Process::Status object. # Without a block a RuntimeError is raised when the command exits non-zero. # # Examples: # # sh 'ls -ltr' # # sh 'ls', 'file with spaces' # # # check exit status after command runs # sh %{grep pattern file} do |ok, res| # if !ok # puts "pattern not found (status = #{res.exitstatus})" # end # end # def sh(*cmd, &block) options = (Hash === cmd.last) ? cmd.pop : {} shell_runner = block_given? ? block : create_shell_runner(cmd) set_verbose_option(options) verbose = options.delete :verbose noop = options.delete(:noop) || Rake::FileUtilsExt.nowrite_flag Rake.rake_output_message sh_show_command cmd if verbose unless noop res = (Hash === cmd.last) ? system(*cmd) : system(*cmd, options) status = $? status = Rake::PseudoStatus.new(1) if !res && status.nil? shell_runner.call(res, status) end end def create_shell_runner(cmd) # :nodoc: show_command = sh_show_command cmd show_command = show_command[0, 42] + "..." unless $trace lambda do |ok, status| ok or fail "Command failed with status (#{status.exitstatus}): " + "[#{show_command}]" end end private :create_shell_runner def sh_show_command(cmd) # :nodoc: cmd = cmd.dup if Hash === cmd.first env = cmd.first env = env.map { |name, value| "#{name}=#{value}" }.join " " cmd[0] = env end cmd.join " " end private :sh_show_command def set_verbose_option(options) # :nodoc: unless options.key? :verbose options[:verbose] = (Rake::FileUtilsExt.verbose_flag == Rake::FileUtilsExt::DEFAULT) || Rake::FileUtilsExt.verbose_flag end end private :set_verbose_option # Run a Ruby interpreter with the given arguments. # # Example: # ruby %{-pe '$_.upcase!' 1 sh(*([RUBY] + args + [options]), &block) else sh("#{RUBY} #{args.first}", options, &block) end end LN_SUPPORTED = [true] # Attempt to do a normal file link, but fall back to a copy if the link # fails. def safe_ln(*args) if !LN_SUPPORTED[0] cp(*args) else begin ln(*args) rescue StandardError, NotImplementedError LN_SUPPORTED[0] = false cp(*args) end end end # Split a file path into individual directory names. # # Example: # split_all("a/b/c") => ['a', 'b', 'c'] # def split_all(path) head, tail = File.split(path) return [tail] if head == "." || tail == "/" return [head, tail] if head == "/" return split_all(head) + [tail] end end PK% ]"gems/rake-12.3.3/lib/rake/scope.rbnu[# frozen_string_literal: true module Rake class Scope < LinkedList # :nodoc: all # Path for the scope. def path map(&:to_s).reverse.join(":") end # Path for the scope + the named path. def path_with_task_name(task_name) "#{path}:#{task_name}" end # Trim +n+ innermost scope levels from the scope. In no case will # this trim beyond the toplevel scope. def trim(n) result = self while n > 0 && !result.empty? result = result.tail n -= 1 end result end # Scope lists always end with an EmptyScope object. See Null # Object Pattern) class EmptyScope < EmptyLinkedList @parent = Scope def path "" end def path_with_task_name(task_name) task_name end end # Singleton null object for an empty scope. EMPTY = EmptyScope.new end end PK% ]zSS+gems/rake-12.3.3/lib/rake/file_utils_ext.rbnu[# frozen_string_literal: true require "rake/file_utils" module Rake # # FileUtilsExt provides a custom version of the FileUtils methods # that respond to the verbose and nowrite # commands. # module FileUtilsExt include FileUtils class << self attr_accessor :verbose_flag, :nowrite_flag end DEFAULT = Object.new FileUtilsExt.verbose_flag = DEFAULT FileUtilsExt.nowrite_flag = false FileUtils.commands.each do |name| opts = FileUtils.options_of name default_options = [] if opts.include?("verbose") default_options << ":verbose => FileUtilsExt.verbose_flag" end if opts.include?("noop") default_options << ":noop => FileUtilsExt.nowrite_flag" end next if default_options.empty? module_eval(<<-EOS, __FILE__, __LINE__ + 1) def #{name}( *args, &block ) super( *rake_merge_option(args, #{default_options.join(', ')} ), &block) end EOS end # Get/set the verbose flag controlling output from the FileUtils # utilities. If verbose is true, then the utility method is # echoed to standard output. # # Examples: # verbose # return the current value of the # # verbose flag # verbose(v) # set the verbose flag to _v_. # verbose(v) { code } # Execute code with the verbose flag set # # temporarily to _v_. Return to the # # original value when code is done. def verbose(value=nil) oldvalue = FileUtilsExt.verbose_flag FileUtilsExt.verbose_flag = value unless value.nil? if block_given? begin yield ensure FileUtilsExt.verbose_flag = oldvalue end end FileUtilsExt.verbose_flag end # Get/set the nowrite flag controlling output from the FileUtils # utilities. If verbose is true, then the utility method is # echoed to standard output. # # Examples: # nowrite # return the current value of the # # nowrite flag # nowrite(v) # set the nowrite flag to _v_. # nowrite(v) { code } # Execute code with the nowrite flag set # # temporarily to _v_. Return to the # # original value when code is done. def nowrite(value=nil) oldvalue = FileUtilsExt.nowrite_flag FileUtilsExt.nowrite_flag = value unless value.nil? if block_given? begin yield ensure FileUtilsExt.nowrite_flag = oldvalue end end oldvalue end # Use this function to prevent potentially destructive ruby code # from running when the :nowrite flag is set. # # Example: # # when_writing("Building Project") do # project.build # end # # The following code will build the project under normal # conditions. If the nowrite(true) flag is set, then the example # will print: # # DRYRUN: Building Project # # instead of actually building the project. # def when_writing(msg=nil) if FileUtilsExt.nowrite_flag $stderr.puts "DRYRUN: #{msg}" if msg else yield end end # Merge the given options with the default values. def rake_merge_option(args, defaults) if Hash === args.last defaults.update(args.last) args.pop end args.push defaults args end # Send the message to the default rake output (which is $stderr). def rake_output_message(message) $stderr.puts(message) end # Check that the options do not contain options not listed in # +optdecl+. An ArgumentError exception is thrown if non-declared # options are found. def rake_check_options(options, *optdecl) h = options.dup optdecl.each do |name| h.delete name end raise ArgumentError, "no such option: #{h.keys.join(' ')}" unless h.empty? end extend self end end PK% ]D8B(gems/rake-12.3.3/lib/rake/packagetask.rbnu[# frozen_string_literal: true # Define a package task library to aid in the definition of # redistributable package files. require "rake" require "rake/tasklib" module Rake # Create a packaging task that will package the project into # distributable files (e.g zip archive or tar files). # # The PackageTask will create the following targets: # # +:package+ :: # Create all the requested package files. # # +:clobber_package+ :: # Delete all the package files. This target is automatically # added to the main clobber target. # # +:repackage+ :: # Rebuild the package files from scratch, even if they are not out # of date. # # "package_dir/name-version.tgz" :: # Create a gzipped tar package (if need_tar is true). # # "package_dir/name-version.tar.gz" :: # Create a gzipped tar package (if need_tar_gz is true). # # "package_dir/name-version.tar.bz2" :: # Create a bzip2'd tar package (if need_tar_bz2 is true). # # "package_dir/name-version.zip" :: # Create a zip package archive (if need_zip is true). # # Example: # # Rake::PackageTask.new("rake", "1.2.3") do |p| # p.need_tar = true # p.package_files.include("lib/**/*.rb") # end # class PackageTask < TaskLib # Name of the package (from the GEM Spec). attr_accessor :name # Version of the package (e.g. '1.3.2'). attr_accessor :version # Directory used to store the package files (default is 'pkg'). attr_accessor :package_dir # True if a gzipped tar file (tgz) should be produced (default is # false). attr_accessor :need_tar # True if a gzipped tar file (tar.gz) should be produced (default # is false). attr_accessor :need_tar_gz # True if a bzip2'd tar file (tar.bz2) should be produced (default # is false). attr_accessor :need_tar_bz2 # True if a xz'd tar file (tar.xz) should be produced (default is false) attr_accessor :need_tar_xz # True if a zip file should be produced (default is false) attr_accessor :need_zip # List of files to be included in the package. attr_accessor :package_files # Tar command for gzipped or bzip2ed archives. The default is 'tar'. attr_accessor :tar_command # Zip command for zipped archives. The default is 'zip'. attr_accessor :zip_command # Create a Package Task with the given name and version. Use +:noversion+ # as the version to build a package without a version or to provide a # fully-versioned package name. def initialize(name=nil, version=nil) init(name, version) yield self if block_given? define unless name.nil? end # Initialization that bypasses the "yield self" and "define" step. def init(name, version) @name = name @version = version @package_files = Rake::FileList.new @package_dir = "pkg" @need_tar = false @need_tar_gz = false @need_tar_bz2 = false @need_tar_xz = false @need_zip = false @tar_command = "tar" @zip_command = "zip" end # Create the tasks defined by this task library. def define fail "Version required (or :noversion)" if @version.nil? @version = nil if :noversion == @version desc "Build all the packages" task :package desc "Force a rebuild of the package files" task repackage: [:clobber_package, :package] desc "Remove package products" task :clobber_package do rm_r package_dir rescue nil end task clobber: [:clobber_package] [ [need_tar, tgz_file, "z"], [need_tar_gz, tar_gz_file, "z"], [need_tar_bz2, tar_bz2_file, "j"], [need_tar_xz, tar_xz_file, "J"] ].each do |need, file, flag| if need task package: ["#{package_dir}/#{file}"] file "#{package_dir}/#{file}" => [package_dir_path] + package_files do chdir(package_dir) { sh @tar_command, "#{flag}cvf", file, package_name } end end end if need_zip task package: ["#{package_dir}/#{zip_file}"] file "#{package_dir}/#{zip_file}" => [package_dir_path] + package_files do chdir(package_dir) { sh @zip_command, "-r", zip_file, package_name } end end directory package_dir_path => @package_files do @package_files.each do |fn| f = File.join(package_dir_path, fn) fdir = File.dirname(f) mkdir_p(fdir) unless File.exist?(fdir) if File.directory?(fn) mkdir_p(f) else rm_f f safe_ln(fn, f) end end end self end # The name of this package def package_name @version ? "#{@name}-#{@version}" : @name end # The directory this package will be built in def package_dir_path "#{package_dir}/#{package_name}" end # The package name with .tgz added def tgz_file "#{package_name}.tgz" end # The package name with .tar.gz added def tar_gz_file "#{package_name}.tar.gz" end # The package name with .tar.bz2 added def tar_bz2_file "#{package_name}.tar.bz2" end # The package name with .tar.xz added def tar_xz_file "#{package_name}.tar.xz" end # The package name with .zip added def zip_file "#{package_name}.zip" end end end PK% ]4Tc(gems/rake-12.3.3/lib/rake/thread_pool.rbnu[# frozen_string_literal: true require "set" require "rake/promise" module Rake class ThreadPool # :nodoc: all # Creates a ThreadPool object. The +thread_count+ parameter is the size # of the pool. def initialize(thread_count) @max_active_threads = [thread_count, 0].max @threads = Set.new @threads_mon = Monitor.new @queue = Queue.new @join_cond = @threads_mon.new_cond @history_start_time = nil @history = [] @history_mon = Monitor.new @total_threads_in_play = 0 end # Creates a future executed by the +ThreadPool+. # # The args are passed to the block when executing (similarly to # Thread#new) The return value is an object representing # a future which has been created and added to the queue in the # pool. Sending #value to the object will sleep the # current thread until the future is finished and will return the # result (or raise an exception thrown from the future) def future(*args, &block) promise = Promise.new(args, &block) promise.recorder = lambda { |*stats| stat(*stats) } @queue.enq promise stat :queued, item_id: promise.object_id start_thread promise end # Waits until the queue of futures is empty and all threads have exited. def join @threads_mon.synchronize do begin stat :joining @join_cond.wait unless @threads.empty? stat :joined rescue Exception => e stat :joined $stderr.puts e $stderr.print "Queue contains #{@queue.size} items. " + "Thread pool contains #{@threads.count} threads\n" $stderr.print "Current Thread #{Thread.current} status = " + "#{Thread.current.status}\n" $stderr.puts e.backtrace.join("\n") @threads.each do |t| $stderr.print "Thread #{t} status = #{t.status}\n" $stderr.puts t.backtrace.join("\n") end raise e end end end # Enable the gathering of history events. def gather_history #:nodoc: @history_start_time = Time.now if @history_start_time.nil? end # Return a array of history events for the thread pool. # # History gathering must be enabled to be able to see the events # (see #gather_history). Best to call this when the job is # complete (i.e. after ThreadPool#join is called). def history # :nodoc: @history_mon.synchronize { @history.dup }. sort_by { |i| i[:time] }. each { |i| i[:time] -= @history_start_time } end # Return a hash of always collected statistics for the thread pool. def statistics # :nodoc: { total_threads_in_play: @total_threads_in_play, max_active_threads: @max_active_threads, } end private # processes one item on the queue. Returns true if there was an # item to process, false if there was no item def process_queue_item #:nodoc: return false if @queue.empty? # Even though we just asked if the queue was empty, it # still could have had an item which by this statement # is now gone. For this reason we pass true to Queue#deq # because we will sleep indefinitely if it is empty. promise = @queue.deq(true) stat :dequeued, item_id: promise.object_id promise.work return true rescue ThreadError # this means the queue is empty false end def safe_thread_count @threads_mon.synchronize do @threads.count end end def start_thread # :nodoc: @threads_mon.synchronize do next unless @threads.count < @max_active_threads t = Thread.new do begin while safe_thread_count <= @max_active_threads break unless process_queue_item end ensure @threads_mon.synchronize do @threads.delete Thread.current stat :ended, thread_count: @threads.count @join_cond.broadcast if @threads.empty? end end end @threads << t stat( :spawned, new_thread: t.object_id, thread_count: @threads.count) @total_threads_in_play = @threads.count if @threads.count > @total_threads_in_play end end def stat(event, data=nil) # :nodoc: return if @history_start_time.nil? info = { event: event, data: data, time: Time.now, thread: Thread.current.object_id, } @history_mon.synchronize { @history << info } end # for testing only def __queue__ # :nodoc: @queue end end end PK% ] e @error = e end stat :did_execute, item_id: object_id discard end # Do we have a result for the promise def result? !@result.equal?(NOT_SET) end # Did the promise throw an error def error? !@error.equal?(NOT_SET) end # Are we done with the promise def complete? result? || error? end # free up these items for the GC def discard @args = nil @block = nil end # Record execution statistics if there is a recorder def stat(*args) @recorder.call(*args) if @recorder end end end PK% ]YY'gems/rake-12.3.3/lib/rake/multi_task.rbnu[# frozen_string_literal: true module Rake # Same as a regular task, but the immediate prerequisites are done in # parallel using Ruby threads. # class MultiTask < Task private def invoke_prerequisites(task_args, invocation_chain) # :nodoc: invoke_prerequisites_concurrently(task_args, invocation_chain) end end end PK% ]j"gems/rake-12.3.3/lib/rake/win32.rbnu[# frozen_string_literal: true require "rbconfig" module Rake # Win 32 interface methods for Rake. Windows specific functionality # will be placed here to collect that knowledge in one spot. module Win32 # :nodoc: all # Error indicating a problem in locating the home directory on a # Win32 system. class Win32HomeError < RuntimeError end class << self # True if running on a windows system. def windows? RbConfig::CONFIG["host_os"] =~ %r!(msdos|mswin|djgpp|mingw|[Ww]indows)! end # The standard directory containing system wide rake files on # Win 32 systems. Try the following environment variables (in # order): # # * HOME # * HOMEDRIVE + HOMEPATH # * APPDATA # * USERPROFILE # # If the above are not defined, the return nil. def win32_system_dir #:nodoc: win32_shared_path = ENV["HOME"] if win32_shared_path.nil? && ENV["HOMEDRIVE"] && ENV["HOMEPATH"] win32_shared_path = ENV["HOMEDRIVE"] + ENV["HOMEPATH"] end win32_shared_path ||= ENV["APPDATA"] win32_shared_path ||= ENV["USERPROFILE"] raise Win32HomeError, "Unable to determine home path environment variable." if win32_shared_path.nil? or win32_shared_path.empty? normalize(File.join(win32_shared_path, "Rake")) end # Normalize a win32 path so that the slashes are all forward slashes. def normalize(path) path.gsub(/\\/, "/") end end end end PK% ]Ӭs~~:gems/rake-12.3.3/lib/rake/rule_recursion_overflow_error.rbnu[# frozen_string_literal: true module Rake # Error indicating a recursion overflow error in task selection. class RuleRecursionOverflowError < StandardError def initialize(*args) super @targets = [] end def add_target(target) @targets << target end def message super + ": [" + @targets.reverse.join(" => ") + "]" end end end PK% ]0ZR+gems/rake-12.3.3/lib/rake/private_reader.rbnu[# frozen_string_literal: true module Rake # Include PrivateReader to use +private_reader+. module PrivateReader # :nodoc: all def self.included(base) base.extend(ClassMethods) end module ClassMethods # Declare a list of private accessors def private_reader(*names) attr_reader(*names) private(*names) end end end end PK% ]7gems/rake-12.3.3/lib/rake/invocation_exception_mixin.rbnu[# frozen_string_literal: true module Rake module InvocationExceptionMixin # Return the invocation chain (list of Rake tasks) that were in # effect when this exception was detected by rake. May be null if # no tasks were active. def chain @rake_invocation_chain ||= nil end # Set the invocation chain in effect when this exception was # detected. def chain=(value) @rake_invocation_chain = value end end end PK% ]&&U0U0!gems/rake-12.3.3/lib/rake/task.rbnu[# frozen_string_literal: true require "rake/invocation_exception_mixin" module Rake ## # A Task is the basic unit of work in a Rakefile. Tasks have associated # actions (possibly more than one) and a list of prerequisites. When # invoked, a task will first ensure that all of its prerequisites have an # opportunity to run and then it will execute its own actions. # # Tasks are not usually created directly using the new method, but rather # use the +file+ and +task+ convenience methods. # class Task # List of prerequisites for a task. attr_reader :prerequisites alias prereqs prerequisites # List of actions attached to a task. attr_reader :actions # Application owning this task. attr_accessor :application # Array of nested namespaces names used for task lookup by this task. attr_reader :scope # File/Line locations of each of the task definitions for this # task (only valid if the task was defined with the detect # location option set). attr_reader :locations # Has this task already been invoked? Already invoked tasks # will be skipped unless you reenable them. attr_reader :already_invoked # Return task name def to_s name end def inspect # :nodoc: "<#{self.class} #{name} => [#{prerequisites.join(', ')}]>" end # List of sources for task. attr_writer :sources def sources if defined?(@sources) @sources else prerequisites end end # List of prerequisite tasks def prerequisite_tasks prerequisites.map { |pre| lookup_prerequisite(pre) } end def lookup_prerequisite(prerequisite_name) # :nodoc: scoped_prerequisite_task = application[prerequisite_name, @scope] if scoped_prerequisite_task == self unscoped_prerequisite_task = application[prerequisite_name] end unscoped_prerequisite_task || scoped_prerequisite_task end private :lookup_prerequisite # List of all unique prerequisite tasks including prerequisite tasks' # prerequisites. # Includes self when cyclic dependencies are found. def all_prerequisite_tasks seen = {} collect_prerequisites(seen) seen.values end def collect_prerequisites(seen) # :nodoc: prerequisite_tasks.each do |pre| next if seen[pre.name] seen[pre.name] = pre pre.collect_prerequisites(seen) end end protected :collect_prerequisites # First source from a rule (nil if no sources) def source sources.first end # Create a task named +task_name+ with no actions or prerequisites. Use # +enhance+ to add actions and prerequisites. def initialize(task_name, app) @name = task_name.to_s @prerequisites = [] @actions = [] @already_invoked = false @comments = [] @lock = Monitor.new @application = app @scope = app.current_scope @arg_names = nil @locations = [] @invocation_exception = nil end # Enhance a task with prerequisites or actions. Returns self. def enhance(deps=nil, &block) @prerequisites |= deps if deps @actions << block if block_given? self end # Name of the task, including any namespace qualifiers. def name @name.to_s end # Name of task with argument list description. def name_with_args # :nodoc: if arg_description "#{name}#{arg_description}" else name end end # Argument description (nil if none). def arg_description # :nodoc: @arg_names ? "[#{arg_names.join(',')}]" : nil end # Name of arguments for this task. def arg_names @arg_names || [] end # Reenable the task, allowing its tasks to be executed if the task # is invoked again. def reenable @already_invoked = false end # Clear the existing prerequisites, actions, comments, and arguments of a rake task. def clear clear_prerequisites clear_actions clear_comments clear_args self end # Clear the existing prerequisites of a rake task. def clear_prerequisites prerequisites.clear self end # Clear the existing actions on a rake task. def clear_actions actions.clear self end # Clear the existing comments on a rake task. def clear_comments @comments = [] self end # Clear the existing arguments on a rake task. def clear_args @arg_names = nil self end # Invoke the task if it is needed. Prerequisites are invoked first. def invoke(*args) task_args = TaskArguments.new(arg_names, args) invoke_with_call_chain(task_args, InvocationChain::EMPTY) end # Same as invoke, but explicitly pass a call chain to detect # circular dependencies. # # If multiple tasks depend on this # one in parallel, they will all fail if the first execution of # this task fails. def invoke_with_call_chain(task_args, invocation_chain) new_chain = Rake::InvocationChain.append(self, invocation_chain) @lock.synchronize do begin if application.options.trace application.trace "** Invoke #{name} #{format_trace_flags}" end if @already_invoked if @invocation_exception if application.options.trace application.trace "** Previous invocation of #{name} failed #{format_trace_flags}" end raise @invocation_exception else return end end @already_invoked = true invoke_prerequisites(task_args, new_chain) execute(task_args) if needed? rescue Exception => ex add_chain_to(ex, new_chain) @invocation_exception = ex raise ex end end end protected :invoke_with_call_chain def add_chain_to(exception, new_chain) # :nodoc: exception.extend(InvocationExceptionMixin) unless exception.respond_to?(:chain) exception.chain = new_chain if exception.chain.nil? end private :add_chain_to # Invoke all the prerequisites of a task. def invoke_prerequisites(task_args, invocation_chain) # :nodoc: if application.options.always_multitask invoke_prerequisites_concurrently(task_args, invocation_chain) else prerequisite_tasks.each { |p| prereq_args = task_args.new_scope(p.arg_names) p.invoke_with_call_chain(prereq_args, invocation_chain) } end end # Invoke all the prerequisites of a task in parallel. def invoke_prerequisites_concurrently(task_args, invocation_chain)# :nodoc: futures = prerequisite_tasks.map do |p| prereq_args = task_args.new_scope(p.arg_names) application.thread_pool.future(p) do |r| r.invoke_with_call_chain(prereq_args, invocation_chain) end end # Iterate in reverse to improve performance related to thread waiting and switching futures.reverse_each(&:value) end # Format the trace flags for display. def format_trace_flags flags = [] flags << "first_time" unless @already_invoked flags << "not_needed" unless needed? flags.empty? ? "" : "(" + flags.join(", ") + ")" end private :format_trace_flags # Execute the actions associated with this task. def execute(args=nil) args ||= EMPTY_TASK_ARGS if application.options.dryrun application.trace "** Execute (dry run) #{name}" return end application.trace "** Execute #{name}" if application.options.trace application.enhance_with_matching_rule(name) if @actions.empty? @actions.each { |act| act.call(self, args) } end # Is this task needed? def needed? true end # Timestamp for this task. Basic tasks return the current time for their # time stamp. Other tasks can be more sophisticated. def timestamp Time.now end # Add a description to the task. The description can consist of an option # argument list (enclosed brackets) and an optional comment. def add_description(description) return unless description comment = description.strip add_comment(comment) if comment && !comment.empty? end def comment=(comment) # :nodoc: add_comment(comment) end def add_comment(comment) # :nodoc: return if comment.nil? @comments << comment unless @comments.include?(comment) end private :add_comment # Full collection of comments. Multiple comments are separated by # newlines. def full_comment transform_comments("\n") end # First line (or sentence) of all comments. Multiple comments are # separated by a "/". def comment transform_comments(" / ") { |c| first_sentence(c) } end # Transform the list of comments as specified by the block and # join with the separator. def transform_comments(separator, &block) if @comments.empty? nil else block ||= lambda { |c| c } @comments.map(&block).join(separator) end end private :transform_comments # Get the first sentence in a string. The sentence is terminated # by the first period, exclamation mark, or the end of the line. # Decimal points do not count as periods. def first_sentence(string) string.split(/(?<=\w)(\.|!)[ \t]|(\.$|!)|\n/).first end private :first_sentence # Set the names of the arguments for this task. +args+ should be # an array of symbols, one for each argument name. def set_arg_names(args) @arg_names = args.map(&:to_sym) end # Return a string describing the internal state of a task. Useful for # debugging. def investigation result = "------------------------------\n".dup result << "Investigating #{name}\n" result << "class: #{self.class}\n" result << "task needed: #{needed?}\n" result << "timestamp: #{timestamp}\n" result << "pre-requisites: \n" prereqs = prerequisite_tasks prereqs.sort! { |a, b| a.timestamp <=> b.timestamp } prereqs.each do |p| result << "--#{p.name} (#{p.timestamp})\n" end latest_prereq = prerequisite_tasks.map(&:timestamp).max result << "latest-prerequisite time: #{latest_prereq}\n" result << "................................\n\n" return result end # ---------------------------------------------------------------- # Rake Module Methods # class << self # Clear the task list. This cause rake to immediately forget all the # tasks that have been assigned. (Normally used in the unit tests.) def clear Rake.application.clear end # List of all defined tasks. def tasks Rake.application.tasks end # Return a task with the given name. If the task is not currently # known, try to synthesize one from the defined rules. If no rules are # found, but an existing file matches the task name, assume it is a file # task with no dependencies or actions. def [](task_name) Rake.application[task_name] end # TRUE if the task name is already defined. def task_defined?(task_name) Rake.application.lookup(task_name) != nil end # Define a task given +args+ and an option block. If a rule with the # given name already exists, the prerequisites and actions are added to # the existing task. Returns the defined task. def define_task(*args, &block) Rake.application.define_task(self, *args, &block) end # Define a rule for synthesizing tasks. def create_rule(*args, &block) Rake.application.create_rule(*args, &block) end # Apply the scope to the task name according to the rules for # this kind of task. Generic tasks will accept the scope as # part of the name. def scope_name(scope, task_name) scope.path_with_task_name(task_name) end end # class << Rake::Task end # class Rake::Task end PK% ]i  +gems/rake-12.3.3/lib/rake/default_loader.rbnu[# frozen_string_literal: true module Rake # Default Rakefile loader used by +import+. class DefaultLoader ## # Loads a rakefile into the current application from +fn+ def load(fn) Rake.load_rakefile(File.expand_path(fn)) end end end PK% ]l??)gems/rake-12.3.3/lib/rake/trace_output.rbnu[# frozen_string_literal: true module Rake module TraceOutput # :nodoc: all # Write trace output to output stream +out+. # # The write is done as a single IO call (to print) to lessen the # chance that the trace output is interrupted by other tasks also # producing output. def trace_on(out, *strings) sep = $\ || "\n" if strings.empty? output = sep else output = strings.map { |s| next if s.nil? s.end_with?(sep) ? s : s + sep }.join end out.print(output) end end end PK% ]I&gems/rake-12.3.3/lib/rake/file_task.rbnu[# frozen_string_literal: true require "rake/task" require "rake/early_time" module Rake # A FileTask is a task that includes time based dependencies. If any of a # FileTask's prerequisites have a timestamp that is later than the file # represented by this task, then the file must be rebuilt (using the # supplied actions). # class FileTask < Task # Is this file task needed? Yes if it doesn't exist, or if its time stamp # is out of date. def needed? !File.exist?(name) || out_of_date?(timestamp) || @application.options.build_all end # Time stamp for file task. def timestamp if File.exist?(name) File.mtime(name.to_s) else Rake::LATE end end private # Are there any prerequisites with a later time than the given time stamp? def out_of_date?(stamp) all_prerequisite_tasks.any? { |prereq| prereq_task = application[prereq, @scope] if prereq_task.instance_of?(Rake::FileTask) prereq_task.timestamp > stamp || @application.options.build_all else prereq_task.timestamp > stamp end } end # ---------------------------------------------------------------- # Task class methods. # class << self # Apply the scope to the task name according to the rules for this kind # of task. File based tasks ignore the scope when creating the name. def scope_name(scope, task_name) Rake.from_pathname(task_name) end end end end PK% ]p,۞%gems/rake-12.3.3/lib/rake/testtask.rbnu[# frozen_string_literal: true require "rake" require "rake/tasklib" module Rake # Create a task that runs a set of tests. # # Example: # require "rake/testtask" # # Rake::TestTask.new do |t| # t.libs << "test" # t.test_files = FileList['test/test*.rb'] # t.verbose = true # end # # If rake is invoked with a "TEST=filename" command line option, # then the list of test files will be overridden to include only the # filename specified on the command line. This provides an easy way # to run just one test. # # If rake is invoked with a "TESTOPTS=options" command line option, # then the given options are passed to the test process after a # '--'. This allows Test::Unit options to be passed to the test # suite. # # Examples: # # rake test # run tests normally # rake test TEST=just_one_file.rb # run just one test file. # rake test TESTOPTS="-v" # run in verbose mode # rake test TESTOPTS="--runner=fox" # use the fox test runner # class TestTask < TaskLib # Name of test task. (default is :test) attr_accessor :name # List of directories added to $LOAD_PATH before running the # tests. (default is 'lib') attr_accessor :libs # True if verbose test output desired. (default is false) attr_accessor :verbose # Test options passed to the test suite. An explicit # TESTOPTS=opts on the command line will override this. (default # is NONE) attr_accessor :options # Request that the tests be run with the warning flag set. # E.g. warning=true implies "ruby -w" used to run the tests. # (default is true) attr_accessor :warning # Glob pattern to match test files. (default is 'test/test*.rb') attr_accessor :pattern # Style of test loader to use. Options are: # # * :rake -- Rake provided test loading script (default). # * :testrb -- Ruby provided test loading script. # * :direct -- Load tests using command line loader. # attr_accessor :loader # Array of command line options to pass to ruby when running test loader. attr_accessor :ruby_opts # Description of the test task. (default is 'Run tests') attr_accessor :description # Task prerequisites. attr_accessor :deps # Explicitly define the list of test files to be included in a # test. +list+ is expected to be an array of file names (a # FileList is acceptable). If both +pattern+ and +test_files+ are # used, then the list of test files is the union of the two. def test_files=(list) @test_files = list end # Create a testing task. def initialize(name=:test) @name = name @libs = ["lib"] @pattern = nil @options = nil @test_files = nil @verbose = false @warning = true @loader = :rake @ruby_opts = [] @description = "Run tests" + (@name == :test ? "" : " for #{@name}") @deps = [] if @name.is_a?(Hash) @deps = @name.values.first @name = @name.keys.first end yield self if block_given? @pattern = "test/test*.rb" if @pattern.nil? && @test_files.nil? define end # Create the tasks defined by this task lib. def define desc @description task @name => Array(deps) do FileUtilsExt.verbose(@verbose) do puts "Use TESTOPTS=\"--verbose\" to pass --verbose" \ ", etc. to runners." if ARGV.include? "--verbose" args = "#{ruby_opts_string} #{run_code} " + "#{file_list_string} #{option_list}" ruby args do |ok, status| if !ok && status.respond_to?(:signaled?) && status.signaled? raise SignalException.new(status.termsig) elsif !ok status = "Command failed with status (#{status.exitstatus})" details = ": [ruby #{args}]" message = if Rake.application.options.trace or @verbose status + details else status end fail message end end end end self end def option_list # :nodoc: (ENV["TESTOPTS"] || ENV["TESTOPT"] || ENV["TEST_OPTS"] || ENV["TEST_OPT"] || @options || "") end def ruby_opts_string # :nodoc: opts = @ruby_opts.dup opts.unshift("-I\"#{lib_path}\"") unless @libs.empty? opts.unshift("-w") if @warning opts.join(" ") end def lib_path # :nodoc: @libs.join(File::PATH_SEPARATOR) end def file_list_string # :nodoc: file_list.map { |fn| "\"#{fn}\"" }.join(" ") end def file_list # :nodoc: if ENV["TEST"] FileList[ENV["TEST"]] else result = [] result += @test_files.to_a if @test_files result += FileList[@pattern].to_a if @pattern result end end def ruby_version # :nodoc: RUBY_VERSION end def run_code # :nodoc: case @loader when :direct "-e \"ARGV.each{|f| require f}\"" when :testrb "-S testrb" when :rake "#{rake_include_arg} \"#{rake_loader}\"" end end def rake_loader # :nodoc: find_file("rake/rake_test_loader") or fail "unable to find rake test loader" end def find_file(fn) # :nodoc: $LOAD_PATH.each do |path| file_path = File.join(path, "#{fn}.rb") return file_path if File.exist? file_path end nil end def rake_include_arg # :nodoc: spec = Gem.loaded_specs["rake"] if spec.respond_to?(:default_gem?) && spec.default_gem? "" else "-I\"#{rake_lib_dir}\"" end end def rake_lib_dir # :nodoc: find_dir("rake") or fail "unable to find rake lib" end def find_dir(fn) # :nodoc: $LOAD_PATH.each do |path| file_path = File.join(path, "#{fn}.rb") return path if File.exist? file_path end nil end end end PK% ]lD'gems/rake-12.3.3/lib/rake/name_space.rbnu[# frozen_string_literal: true ## # The NameSpace class will lookup task names in the scope defined by a # +namespace+ command. class Rake::NameSpace ## # Create a namespace lookup object using the given task manager # and the list of scopes. def initialize(task_manager, scope_list) @task_manager = task_manager @scope = scope_list.dup end ## # Lookup a task named +name+ in the namespace. def [](name) @task_manager.lookup(name, @scope) end ## # The scope of the namespace (a LinkedList) def scope @scope.dup end ## # Return the list of tasks defined in this and nested namespaces. def tasks @task_manager.tasks_in_scope(@scope) end end PK% ]m3gems/rake-12.3.3/lib/rake/thread_history_display.rbnu[# frozen_string_literal: true require "rake/private_reader" module Rake class ThreadHistoryDisplay # :nodoc: all include Rake::PrivateReader private_reader :stats, :items, :threads def initialize(stats) @stats = stats @items = { _seq_: 1 } @threads = { _seq_: "A" } end def show puts "Job History:" stats.each do |stat| stat[:data] ||= {} rename(stat, :thread, threads) rename(stat[:data], :item_id, items) rename(stat[:data], :new_thread, threads) rename(stat[:data], :deleted_thread, threads) printf("%8d %2s %-20s %s\n", (stat[:time] * 1_000_000).round, stat[:thread], stat[:event], stat[:data].map do |k, v| "#{k}:#{v}" end.join(" ")) end end private def rename(hash, key, renames) if hash && hash[key] original = hash[key] value = renames[original] unless value value = renames[:_seq_] renames[:_seq_] = renames[:_seq_].succ renames[original] = value end hash[key] = value end end end end PK% ]Jሀ&gems/rake-12.3.3/lib/rake/backtrace.rbnu[# frozen_string_literal: true module Rake module Backtrace # :nodoc: all SYS_KEYS = RbConfig::CONFIG.keys.grep(/(?:[a-z]prefix|libdir)\z/) SYS_PATHS = RbConfig::CONFIG.values_at(*SYS_KEYS).uniq + [ File.join(File.dirname(__FILE__), "..") ] SUPPRESSED_PATHS = SYS_PATHS. map { |s| s.tr("\\", "/") }. map { |f| File.expand_path(f) }. reject { |s| s.nil? || s =~ /^ *$/ } SUPPRESSED_PATHS_RE = SUPPRESSED_PATHS.map { |f| Regexp.quote(f) }.join("|") SUPPRESSED_PATHS_RE << "|^org\\/jruby\\/\\w+\\.java" if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == "jruby" SUPPRESS_PATTERN = %r!(\A(#{SUPPRESSED_PATHS_RE})|bin/rake:\d+)!i def self.collapse(backtrace) pattern = Rake.application.options.suppress_backtrace_pattern || SUPPRESS_PATTERN backtrace.reject { |elem| elem =~ pattern } end end end PK% ]H bb(gems/rake-12.3.3/lib/rake/application.rbnu[# frozen_string_literal: true require "optparse" require "rake/task_manager" require "rake/file_list" require "rake/thread_pool" require "rake/thread_history_display" require "rake/trace_output" require "rake/win32" module Rake CommandLineOptionError = Class.new(StandardError) ## # Rake main application object. When invoking +rake+ from the # command line, a Rake::Application object is created and run. class Application include TaskManager include TraceOutput # The name of the application (typically 'rake') attr_reader :name # The original directory where rake was invoked. attr_reader :original_dir # Name of the actual rakefile used. attr_reader :rakefile # Number of columns on the terminal attr_accessor :terminal_columns # List of the top level task names (task names from the command line). attr_reader :top_level_tasks # Override the detected TTY output state (mostly for testing) attr_writer :tty_output DEFAULT_RAKEFILES = [ "rakefile", "Rakefile", "rakefile.rb", "Rakefile.rb" ].freeze # Initialize a Rake::Application object. def initialize super @name = "rake" @rakefiles = DEFAULT_RAKEFILES.dup @rakefile = nil @pending_imports = [] @imported = [] @loaders = {} @default_loader = Rake::DefaultLoader.new @original_dir = Dir.pwd @top_level_tasks = [] add_loader("rb", DefaultLoader.new) add_loader("rf", DefaultLoader.new) add_loader("rake", DefaultLoader.new) @tty_output = STDOUT.tty? @terminal_columns = ENV["RAKE_COLUMNS"].to_i set_default_options end # Run the Rake application. The run method performs the following # three steps: # # * Initialize the command line options (+init+). # * Define the tasks (+load_rakefile+). # * Run the top level tasks (+top_level+). # # If you wish to build a custom rake command, you should call # +init+ on your application. Then define any tasks. Finally, # call +top_level+ to run your top level tasks. def run(argv = ARGV) standard_exception_handling do init "rake", argv load_rakefile top_level end end # Initialize the command line parameters and app name. def init(app_name="rake", argv = ARGV) standard_exception_handling do @name = app_name begin args = handle_options argv rescue ArgumentError # Backward compatibility for capistrano args = handle_options end collect_command_line_tasks(args) end end # Find the rakefile and then load it and any pending imports. def load_rakefile standard_exception_handling do raw_load_rakefile end end # Run the top level tasks of a Rake application. def top_level run_with_threads do if options.show_tasks display_tasks_and_comments elsif options.show_prereqs display_prerequisites else top_level_tasks.each { |task_name| invoke_task(task_name) } end end end # Run the given block with the thread startup and shutdown. def run_with_threads thread_pool.gather_history if options.job_stats == :history yield thread_pool.join if options.job_stats stats = thread_pool.statistics puts "Maximum active threads: #{stats[:max_active_threads]} + main" puts "Total threads in play: #{stats[:total_threads_in_play]} + main" end ThreadHistoryDisplay.new(thread_pool.history).show if options.job_stats == :history end # Add a loader to handle imported files ending in the extension # +ext+. def add_loader(ext, loader) ext = ".#{ext}" unless ext =~ /^\./ @loaders[ext] = loader end # Application options from the command line def options @options ||= OpenStruct.new end # Return the thread pool used for multithreaded processing. def thread_pool # :nodoc: @thread_pool ||= ThreadPool.new(options.thread_pool_size || Rake.suggested_thread_count-1) end # internal ---------------------------------------------------------------- # Invokes a task with arguments that are extracted from +task_string+ def invoke_task(task_string) # :nodoc: name, args = parse_task_string(task_string) t = self[name] t.invoke(*args) end def parse_task_string(string) # :nodoc: /^([^\[]+)(?:\[(.*)\])$/ =~ string.to_s name = $1 remaining_args = $2 return string, [] unless name return name, [] if remaining_args.empty? args = [] begin /\s*((?:[^\\,]|\\.)*?)\s*(?:,\s*(.*))?$/ =~ remaining_args remaining_args = $2 args << $1.gsub(/\\(.)/, '\1') end while remaining_args return name, args end # Provide standard exception handling for the given block. def standard_exception_handling # :nodoc: yield rescue SystemExit # Exit silently with current status raise rescue OptionParser::InvalidOption => ex $stderr.puts ex.message exit(false) rescue Exception => ex # Exit with error message display_error_message(ex) exit_because_of_exception(ex) end # Exit the program because of an unhandled exception. # (may be overridden by subclasses) def exit_because_of_exception(ex) # :nodoc: exit(false) end # Display the error message that caused the exception. def display_error_message(ex) # :nodoc: trace "#{name} aborted!" display_exception_details(ex) trace "Tasks: #{ex.chain}" if has_chain?(ex) trace "(See full trace by running task with --trace)" unless options.backtrace end def display_exception_details(ex) # :nodoc: display_exception_details_seen << ex display_exception_message_details(ex) display_exception_backtrace(ex) display_cause_details(ex.cause) if has_cause?(ex) end def display_cause_details(ex) # :nodoc: return if display_exception_details_seen.include? ex trace "\nCaused by:" display_exception_details(ex) end def display_exception_details_seen # :nodoc: Thread.current[:rake_display_exception_details_seen] ||= [] end def has_cause?(ex) # :nodoc: ex.respond_to?(:cause) && ex.cause end def display_exception_message_details(ex) # :nodoc: if ex.instance_of?(RuntimeError) trace ex.message else trace "#{ex.class.name}: #{ex.message}" end end def display_exception_backtrace(ex) # :nodoc: if options.backtrace trace ex.backtrace.join("\n") else trace Backtrace.collapse(ex.backtrace).join("\n") end end # Warn about deprecated usage. # # Example: # Rake.application.deprecate("import", "Rake.import", caller.first) # def deprecate(old_usage, new_usage, call_site) # :nodoc: unless options.ignore_deprecate $stderr.puts "WARNING: '#{old_usage}' is deprecated. " + "Please use '#{new_usage}' instead.\n" + " at #{call_site}" end end # Does the exception have a task invocation chain? def has_chain?(exception) # :nodoc: exception.respond_to?(:chain) && exception.chain end private :has_chain? # True if one of the files in RAKEFILES is in the current directory. # If a match is found, it is copied into @rakefile. def have_rakefile # :nodoc: @rakefiles.each do |fn| if File.exist?(fn) others = FileList.glob(fn, File::FNM_CASEFOLD) return others.size == 1 ? others.first : fn elsif fn == "" return fn end end return nil end # True if we are outputting to TTY, false otherwise def tty_output? # :nodoc: @tty_output end # We will truncate output if we are outputting to a TTY or if we've been # given an explicit column width to honor def truncate_output? # :nodoc: tty_output? || @terminal_columns.nonzero? end # Display the tasks and comments. def display_tasks_and_comments # :nodoc: displayable_tasks = tasks.select { |t| (options.show_all_tasks || t.comment) && t.name =~ options.show_task_pattern } case options.show_tasks when :tasks width = displayable_tasks.map { |t| t.name_with_args.length }.max || 10 if truncate_output? max_column = terminal_width - name.size - width - 7 else max_column = nil end displayable_tasks.each do |t| printf("#{name} %-#{width}s # %s\n", t.name_with_args, max_column ? truncate(t.comment, max_column) : t.comment) end when :describe displayable_tasks.each do |t| puts "#{name} #{t.name_with_args}" comment = t.full_comment || "" comment.split("\n").each do |line| puts " #{line}" end puts end when :lines displayable_tasks.each do |t| t.locations.each do |loc| printf "#{name} %-30s %s\n", t.name_with_args, loc end end else fail "Unknown show task mode: '#{options.show_tasks}'" end end def terminal_width # :nodoc: if @terminal_columns.nonzero? result = @terminal_columns else result = unix? ? dynamic_width : 80 end (result < 10) ? 80 : result rescue 80 end # Calculate the dynamic width of the def dynamic_width # :nodoc: @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput) end def dynamic_width_stty # :nodoc: %x{stty size 2>/dev/null}.split[1].to_i end def dynamic_width_tput # :nodoc: %x{tput cols 2>/dev/null}.to_i end def unix? # :nodoc: RbConfig::CONFIG["host_os"] =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i end def windows? # :nodoc: Win32.windows? end def truncate(string, width) # :nodoc: if string.nil? "" elsif string.length <= width string else (string[0, width - 3] || "") + "..." end end # Display the tasks and prerequisites def display_prerequisites # :nodoc: tasks.each do |t| puts "#{name} #{t.name}" t.prerequisites.each { |pre| puts " #{pre}" } end end def trace(*strings) # :nodoc: options.trace_output ||= $stderr trace_on(options.trace_output, *strings) end def sort_options(options) # :nodoc: options.sort_by { |opt| opt.select { |o| o.is_a?(String) && o =~ /^-/ }.map(&:downcase).sort.reverse } end private :sort_options # A list of all the standard options used in rake, suitable for # passing to OptionParser. def standard_rake_options # :nodoc: sort_options( [ ["--all", "-A", "Show all tasks, even uncommented ones (in combination with -T or -D)", lambda { |value| options.show_all_tasks = value } ], ["--backtrace=[OUT]", "Enable full backtrace. OUT can be stderr (default) or stdout.", lambda { |value| options.backtrace = true select_trace_output(options, "backtrace", value) } ], ["--build-all", "-B", "Build all prerequisites, including those which are up-to-date.", lambda { |value| options.build_all = true } ], ["--comments", "Show commented tasks only", lambda { |value| options.show_all_tasks = !value } ], ["--describe", "-D [PATTERN]", "Describe the tasks (matching optional PATTERN), then exit.", lambda { |value| select_tasks_to_show(options, :describe, value) } ], ["--dry-run", "-n", "Do a dry run without executing actions.", lambda { |value| Rake.verbose(true) Rake.nowrite(true) options.dryrun = true options.trace = true } ], ["--execute", "-e CODE", "Execute some Ruby code and exit.", lambda { |value| eval(value) exit } ], ["--execute-print", "-p CODE", "Execute some Ruby code, print the result, then exit.", lambda { |value| puts eval(value) exit } ], ["--execute-continue", "-E CODE", "Execute some Ruby code, " + "then continue with normal task processing.", lambda { |value| eval(value) } ], ["--jobs", "-j [NUMBER]", "Specifies the maximum number of tasks to execute in parallel. " + "(default is number of CPU cores + 4)", lambda { |value| if value.nil? || value == "" value = Float::INFINITY elsif value =~ /^\d+$/ value = value.to_i else value = Rake.suggested_thread_count end value = 1 if value < 1 options.thread_pool_size = value - 1 } ], ["--job-stats [LEVEL]", "Display job statistics. " + "LEVEL=history displays a complete job list", lambda { |value| if value =~ /^history/i options.job_stats = :history else options.job_stats = true end } ], ["--libdir", "-I LIBDIR", "Include LIBDIR in the search path for required modules.", lambda { |value| $:.push(value) } ], ["--multitask", "-m", "Treat all tasks as multitasks.", lambda { |value| options.always_multitask = true } ], ["--no-search", "--nosearch", "-N", "Do not search parent directories for the Rakefile.", lambda { |value| options.nosearch = true } ], ["--prereqs", "-P", "Display the tasks and dependencies, then exit.", lambda { |value| options.show_prereqs = true } ], ["--quiet", "-q", "Do not log messages to standard output.", lambda { |value| Rake.verbose(false) } ], ["--rakefile", "-f [FILENAME]", "Use FILENAME as the rakefile to search for.", lambda { |value| value ||= "" @rakefiles.clear @rakefiles << value } ], ["--rakelibdir", "--rakelib", "-R RAKELIBDIR", "Auto-import any .rake files in RAKELIBDIR. " + "(default is 'rakelib')", lambda { |value| options.rakelib = value.split(File::PATH_SEPARATOR) } ], ["--require", "-r MODULE", "Require MODULE before executing rakefile.", lambda { |value| begin require value rescue LoadError => ex begin rake_require value rescue LoadError raise ex end end } ], ["--rules", "Trace the rules resolution.", lambda { |value| options.trace_rules = true } ], ["--silent", "-s", "Like --quiet, but also suppresses the " + "'in directory' announcement.", lambda { |value| Rake.verbose(false) options.silent = true } ], ["--suppress-backtrace PATTERN", "Suppress backtrace lines matching regexp PATTERN. " + "Ignored if --trace is on.", lambda { |value| options.suppress_backtrace_pattern = Regexp.new(value) } ], ["--system", "-g", "Using system wide (global) rakefiles " + "(usually '~/.rake/*.rake').", lambda { |value| options.load_system = true } ], ["--no-system", "--nosystem", "-G", "Use standard project Rakefile search paths, " + "ignore system wide rakefiles.", lambda { |value| options.ignore_system = true } ], ["--tasks", "-T [PATTERN]", "Display the tasks (matching optional PATTERN) " + "with descriptions, then exit. " + "-AT combination displays all of tasks contained no description.", lambda { |value| select_tasks_to_show(options, :tasks, value) } ], ["--trace=[OUT]", "-t", "Turn on invoke/execute tracing, enable full backtrace. " + "OUT can be stderr (default) or stdout.", lambda { |value| options.trace = true options.backtrace = true select_trace_output(options, "trace", value) Rake.verbose(true) } ], ["--verbose", "-v", "Log message to standard output.", lambda { |value| Rake.verbose(true) } ], ["--version", "-V", "Display the program version.", lambda { |value| puts "rake, version #{Rake::VERSION}" exit } ], ["--where", "-W [PATTERN]", "Describe the tasks (matching optional PATTERN), then exit.", lambda { |value| select_tasks_to_show(options, :lines, value) options.show_all_tasks = true } ], ["--no-deprecation-warnings", "-X", "Disable the deprecation warnings.", lambda { |value| options.ignore_deprecate = true } ], ]) end def select_tasks_to_show(options, show_tasks, value) # :nodoc: options.show_tasks = show_tasks options.show_task_pattern = Regexp.new(value || "") Rake::TaskManager.record_task_metadata = true end private :select_tasks_to_show def select_trace_output(options, trace_option, value) # :nodoc: value = value.strip unless value.nil? case value when "stdout" options.trace_output = $stdout when "stderr", nil options.trace_output = $stderr else fail CommandLineOptionError, "Unrecognized --#{trace_option} option '#{value}'" end end private :select_trace_output # Read and handle the command line options. Returns the command line # arguments that we didn't understand, which should (in theory) be just # task names and env vars. def handle_options(argv) # :nodoc: set_default_options OptionParser.new do |opts| opts.banner = "#{Rake.application.name} [-f rakefile] {options} targets..." opts.separator "" opts.separator "Options are ..." opts.on_tail("-h", "--help", "-H", "Display this help message.") do puts opts exit end standard_rake_options.each { |args| opts.on(*args) } opts.environment("RAKEOPT") end.parse(argv) end # Similar to the regular Ruby +require+ command, but will check # for *.rake files in addition to *.rb files. def rake_require(file_name, paths=$LOAD_PATH, loaded=$") # :nodoc: fn = file_name + ".rake" return false if loaded.include?(fn) paths.each do |path| full_path = File.join(path, fn) if File.exist?(full_path) Rake.load_rakefile(full_path) loaded << fn return true end end fail LoadError, "Can't find #{file_name}" end def find_rakefile_location # :nodoc: here = Dir.pwd until (fn = have_rakefile) Dir.chdir("..") return nil if Dir.pwd == here || options.nosearch here = Dir.pwd end [fn, here] ensure Dir.chdir(Rake.original_dir) end def print_rakefile_directory(location) # :nodoc: $stderr.puts "(in #{Dir.pwd})" unless options.silent or original_dir == location end def raw_load_rakefile # :nodoc: rakefile, location = find_rakefile_location if (!options.ignore_system) && (options.load_system || rakefile.nil?) && system_dir && File.directory?(system_dir) print_rakefile_directory(location) glob("#{system_dir}/*.rake") do |name| add_import name end else fail "No Rakefile found (looking for: #{@rakefiles.join(', ')})" if rakefile.nil? @rakefile = rakefile Dir.chdir(location) print_rakefile_directory(location) Rake.load_rakefile(File.expand_path(@rakefile)) if @rakefile && @rakefile != "" options.rakelib.each do |rlib| glob("#{rlib}/*.rake") do |name| add_import name end end end load_imports end def glob(path, &block) # :nodoc: FileList.glob(path.tr("\\", "/")).each(&block) end private :glob # The directory path containing the system wide rakefiles. def system_dir # :nodoc: @system_dir ||= begin if ENV["RAKE_SYSTEM"] ENV["RAKE_SYSTEM"] else standard_system_dir end end end # The standard directory containing system wide rake files. if Win32.windows? def standard_system_dir #:nodoc: Win32.win32_system_dir end else def standard_system_dir #:nodoc: File.join(File.expand_path("~"), ".rake") end end private :standard_system_dir # Collect the list of tasks on the command line. If no tasks are # given, return a list containing only the default task. # Environmental assignments are processed at this time as well. # # `args` is the list of arguments to peruse to get the list of tasks. # It should be the command line that was given to rake, less any # recognised command-line options, which OptionParser.parse will # have taken care of already. def collect_command_line_tasks(args) # :nodoc: @top_level_tasks = [] args.each do |arg| if arg =~ /^(\w+)=(.*)$/m ENV[$1] = $2 else @top_level_tasks << arg unless arg =~ /^-/ end end @top_level_tasks.push(default_task_name) if @top_level_tasks.empty? end # Default task name ("default"). # (May be overridden by subclasses) def default_task_name # :nodoc: "default" end # Add a file to the list of files to be imported. def add_import(fn) # :nodoc: @pending_imports << fn end # Load the pending list of imported files. def load_imports # :nodoc: while fn = @pending_imports.shift next if @imported.member?(fn) fn_task = lookup(fn) and fn_task.invoke ext = File.extname(fn) loader = @loaders[ext] || @default_loader loader.load(fn) if fn_task = lookup(fn) and fn_task.needed? fn_task.reenable fn_task.invoke loader.load(fn) end @imported << fn end end def rakefile_location(backtrace=caller) # :nodoc: backtrace.map { |t| t[/([^:]+):/, 1] } re = /^#{@rakefile}$/ re = /#{re.source}/i if windows? backtrace.find { |str| str =~ re } || "" end def set_default_options # :nodoc: options.always_multitask = false options.backtrace = false options.build_all = false options.dryrun = false options.ignore_deprecate = false options.ignore_system = false options.job_stats = false options.load_system = false options.nosearch = false options.rakelib = %w[rakelib] options.show_all_tasks = false options.show_prereqs = false options.show_task_pattern = nil options.show_tasks = nil options.silent = false options.suppress_backtrace_pattern = nil options.thread_pool_size = Rake.suggested_thread_count options.trace = false options.trace_output = $stderr options.trace_rules = false end end end PK% ]Q(gems/rake-12.3.3/lib/rake/rake_module.rbnu[# frozen_string_literal: true require "rake/application" module Rake class << self # Current Rake Application def application @application ||= Rake::Application.new end # Set the current Rake application object. def application=(app) @application = app end def suggested_thread_count # :nodoc: @cpu_count ||= Rake::CpuCounter.count @cpu_count + 4 end # Return the original directory where the Rake application was started. def original_dir application.original_dir end # Load a rakefile. def load_rakefile(path) load(path) end # Add files to the rakelib list def add_rakelib(*files) application.options.rakelib ||= [] application.options.rakelib.concat(files) end # Make +block_application+ the default rake application inside a block so # you can load rakefiles into a different application. # # This is useful when you want to run rake tasks inside a library without # running rake in a sub-shell. # # Example: # # Dir.chdir 'other/directory' # # other_rake = Rake.with_application do |rake| # rake.load_rakefile # end # # puts other_rake.tasks def with_application(block_application = Rake::Application.new) orig_application = Rake.application Rake.application = block_application yield block_application block_application ensure Rake.application = orig_application end end end PK% ]eR&&)gems/rake-12.3.3/lib/rake/task_manager.rbnu[# frozen_string_literal: true module Rake # The TaskManager module is a mixin for managing tasks. module TaskManager # Track the last comment made in the Rakefile. attr_accessor :last_description def initialize # :nodoc: super @tasks = Hash.new @rules = Array.new @scope = Scope.make @last_description = nil end def create_rule(*args, &block) # :nodoc: pattern, args, deps = resolve_args(args) pattern = Regexp.new(Regexp.quote(pattern) + "$") if String === pattern @rules << [pattern, args, deps, block] end def define_task(task_class, *args, &block) # :nodoc: task_name, arg_names, deps = resolve_args(args) original_scope = @scope if String === task_name and not task_class.ancestors.include? Rake::FileTask task_name, *definition_scope = *(task_name.split(":").reverse) @scope = Scope.make(*(definition_scope + @scope.to_a)) end task_name = task_class.scope_name(@scope, task_name) deps = [deps] unless deps.respond_to?(:to_ary) deps = deps.map { |d| Rake.from_pathname(d).to_s } task = intern(task_class, task_name) task.set_arg_names(arg_names) unless arg_names.empty? if Rake::TaskManager.record_task_metadata add_location(task) task.add_description(get_description(task)) end task.enhance(deps, &block) ensure @scope = original_scope end # Lookup a task. Return an existing task if found, otherwise # create a task of the current type. def intern(task_class, task_name) @tasks[task_name.to_s] ||= task_class.new(task_name, self) end # Find a matching task for +task_name+. def [](task_name, scopes=nil) task_name = task_name.to_s self.lookup(task_name, scopes) or enhance_with_matching_rule(task_name) or synthesize_file_task(task_name) or fail generate_message_for_undefined_task(task_name) end def generate_message_for_undefined_task(task_name) message = "Don't know how to build task '#{task_name}' "\ "(See the list of available tasks with `#{Rake.application.name} --tasks`)" message + generate_did_you_mean_suggestions(task_name) end def generate_did_you_mean_suggestions(task_name) return "" unless defined?(::DidYouMean::SpellChecker) suggestions = ::DidYouMean::SpellChecker.new(dictionary: @tasks.keys).correct(task_name.to_s) if ::DidYouMean.respond_to?(:formatter)# did_you_mean v1.2.0 or later ::DidYouMean.formatter.message_for(suggestions) elsif defined?(::DidYouMean::Formatter) # before did_you_mean v1.2.0 ::DidYouMean::Formatter.new(suggestions).to_s else "" end end def synthesize_file_task(task_name) # :nodoc: return nil unless File.exist?(task_name) define_task(Rake::FileTask, task_name) end # Resolve the arguments for a task/rule. Returns a triplet of # [task_name, arg_name_list, prerequisites]. def resolve_args(args) if args.last.is_a?(Hash) deps = args.pop resolve_args_with_dependencies(args, deps) else resolve_args_without_dependencies(args) end end # Resolve task arguments for a task or rule when there are no # dependencies declared. # # The patterns recognized by this argument resolving function are: # # task :t # task :t, [:a] # def resolve_args_without_dependencies(args) task_name = args.shift if args.size == 1 && args.first.respond_to?(:to_ary) arg_names = args.first.to_ary else arg_names = args end [task_name, arg_names, []] end private :resolve_args_without_dependencies # Resolve task arguments for a task or rule when there are # dependencies declared. # # The patterns recognized by this argument resolving function are: # # task :t => [:d] # task :t, [a] => [:d] # def resolve_args_with_dependencies(args, hash) # :nodoc: fail "Task Argument Error" if hash.size != 1 key, value = hash.map { |k, v| [k, v] }.first if args.empty? task_name = key arg_names = [] deps = value || [] else task_name = args.shift arg_names = key deps = value end deps = [deps] unless deps.respond_to?(:to_ary) [task_name, arg_names, deps] end private :resolve_args_with_dependencies # If a rule can be found that matches the task name, enhance the # task with the prerequisites and actions from the rule. Set the # source attribute of the task appropriately for the rule. Return # the enhanced task or nil of no rule was found. def enhance_with_matching_rule(task_name, level=0) fail Rake::RuleRecursionOverflowError, "Rule Recursion Too Deep" if level >= 16 @rules.each do |pattern, args, extensions, block| if pattern && pattern.match(task_name) task = attempt_rule(task_name, pattern, args, extensions, block, level) return task if task end end nil rescue Rake::RuleRecursionOverflowError => ex ex.add_target(task_name) fail ex end # List of all defined tasks in this application. def tasks @tasks.values.sort_by { |t| t.name } end # List of all the tasks defined in the given scope (and its # sub-scopes). def tasks_in_scope(scope) prefix = scope.path tasks.select { |t| /^#{prefix}:/ =~ t.name } end # Clear all tasks in this application. def clear @tasks.clear @rules.clear end # Lookup a task, using scope and the scope hints in the task name. # This method performs straight lookups without trying to # synthesize file tasks or rules. Special scope names (e.g. '^') # are recognized. If no scope argument is supplied, use the # current scope. Return nil if the task cannot be found. def lookup(task_name, initial_scope=nil) initial_scope ||= @scope task_name = task_name.to_s if task_name =~ /^rake:/ scopes = Scope.make task_name = task_name.sub(/^rake:/, "") elsif task_name =~ /^(\^+)/ scopes = initial_scope.trim($1.size) task_name = task_name.sub(/^(\^+)/, "") else scopes = initial_scope end lookup_in_scope(task_name, scopes) end # Lookup the task name def lookup_in_scope(name, scope) loop do tn = scope.path_with_task_name(name) task = @tasks[tn] return task if task break if scope.empty? scope = scope.tail end nil end private :lookup_in_scope # Return the list of scope names currently active in the task # manager. def current_scope @scope end # Evaluate the block in a nested namespace named +name+. Create # an anonymous namespace if +name+ is nil. def in_namespace(name) name ||= generate_name @scope = Scope.new(name, @scope) ns = NameSpace.new(self, @scope) yield(ns) ns ensure @scope = @scope.tail end private # Add a location to the locations field of the given task. def add_location(task) loc = find_location task.locations << loc if loc task end # Find the location that called into the dsl layer. def find_location locations = caller i = 0 while locations[i] return locations[i + 1] if locations[i] =~ /rake\/dsl_definition.rb/ i += 1 end nil end # Generate an anonymous namespace name. def generate_name @seed ||= 0 @seed += 1 "_anon_#{@seed}" end def trace_rule(level, message) # :nodoc: options.trace_output.puts "#{" " * level}#{message}" if Rake.application.options.trace_rules end # Attempt to create a rule given the list of prerequisites. def attempt_rule(task_name, task_pattern, args, extensions, block, level) sources = make_sources(task_name, task_pattern, extensions) prereqs = sources.map { |source| trace_rule level, "Attempting Rule #{task_name} => #{source}" if File.exist?(source) || Rake::Task.task_defined?(source) trace_rule level, "(#{task_name} => #{source} ... EXIST)" source elsif parent = enhance_with_matching_rule(source, level + 1) trace_rule level, "(#{task_name} => #{source} ... ENHANCE)" parent.name else trace_rule level, "(#{task_name} => #{source} ... FAIL)" return nil end } task = FileTask.define_task(task_name, { args => prereqs }, &block) task.sources = prereqs task end # Make a list of sources from the list of file name extensions / # translation procs. def make_sources(task_name, task_pattern, extensions) result = extensions.map { |ext| case ext when /%/ task_name.pathmap(ext) when %r{/} ext when /^\./ source = task_name.sub(task_pattern, ext) source == ext ? task_name.ext(ext) : source when String ext when Proc, Method if ext.arity == 1 ext.call(task_name) else ext.call end else fail "Don't know how to handle rule dependent: #{ext.inspect}" end } result.flatten end # Return the current description, clearing it in the process. def get_description(task) desc = @last_description @last_description = nil desc end class << self attr_accessor :record_task_metadata # :nodoc: TaskManager.record_task_metadata = false end end end PK% ]~y +gems/rake-12.3.3/lib/rake/task_arguments.rbnu[# frozen_string_literal: true module Rake ## # TaskArguments manage the arguments passed to a task. # class TaskArguments include Enumerable # Argument names attr_reader :names # Create a TaskArgument object with a list of argument +names+ and a set # of associated +values+. +parent+ is the parent argument object. def initialize(names, values, parent=nil) @names = names @parent = parent @hash = {} @values = values names.each_with_index { |name, i| next if values[i].nil? || values[i] == "" @hash[name.to_sym] = values[i] } end # Retrieve the complete array of sequential values def to_a @values.dup end # Retrieve the list of values not associated with named arguments def extras @values[@names.length..-1] || [] end # Create a new argument scope using the prerequisite argument # names. def new_scope(names) values = names.map { |n| self[n] } self.class.new(names, values + extras, self) end # Find an argument value by name or index. def [](index) lookup(index.to_sym) end # Specify a hash of default values for task arguments. Use the # defaults only if there is no specific value for the given # argument. def with_defaults(defaults) @hash = defaults.merge(@hash) end # Enumerates the arguments and their values def each(&block) @hash.each(&block) end # Extracts the argument values at +keys+ def values_at(*keys) keys.map { |k| lookup(k) } end # Returns the value of the given argument via method_missing def method_missing(sym, *args) lookup(sym.to_sym) end # Returns a Hash of arguments and their values def to_hash @hash.dup end def to_s # :nodoc: inspect end def inspect # :nodoc: inspection = @hash.map do |k,v| "#{k.to_s}: #{v.to_s}" end.join(", ") "#<#{self.class} #{inspection}>" end # Returns true if +key+ is one of the arguments def has_key?(key) @hash.has_key?(key) end alias key? has_key? def fetch(*args, &block) @hash.fetch(*args, &block) end protected def lookup(name) # :nodoc: if @hash.has_key?(name) @hash[name] elsif @parent @parent.lookup(name) end end end EMPTY_TASK_ARGS = TaskArguments.new([], []) # :nodoc: end PK% ]K*gems/rake-12.3.3/lib/rake/pseudo_status.rbnu[# frozen_string_literal: true module Rake ## # Exit status class for times the system just gives us a nil. class PseudoStatus # :nodoc: all attr_reader :exitstatus def initialize(code=0) @exitstatus = code end def to_i @exitstatus << 8 end def >>(n) to_i >> n end def stopped? false end def exited? true end end end PK% ]M M (gems/rake-12.3.3/lib/rake/cpu_counter.rbnu[# frozen_string_literal: true module Rake # Based on a script at: # http://stackoverflow.com/questions/891537/ruby-detect-number-of-cpus-installed class CpuCounter # :nodoc: all def self.count new.count_with_default end def count_with_default(default=4) count || default rescue StandardError default end begin require "etc" rescue LoadError else if Etc.respond_to?(:nprocessors) def count return Etc.nprocessors end end end end end unless Rake::CpuCounter.method_defined?(:count) Rake::CpuCounter.class_eval <<-'end;', __FILE__, __LINE__+1 require 'rbconfig' def count if RUBY_PLATFORM == 'java' count_via_java_runtime else case RbConfig::CONFIG['host_os'] when /linux/ count_via_cpuinfo when /darwin|bsd/ count_via_sysctl when /mswin|mingw/ count_via_win32 else # Try everything count_via_win32 || count_via_sysctl || count_via_cpuinfo end end end def count_via_java_runtime Java::Java.lang.Runtime.getRuntime.availableProcessors rescue StandardError nil end def count_via_win32 require 'win32ole' wmi = WIN32OLE.connect("winmgmts://") cpu = wmi.ExecQuery("select NumberOfCores from Win32_Processor") # TODO count hyper-threaded in this cpu.to_enum.first.NumberOfCores rescue StandardError, LoadError nil end def count_via_cpuinfo open('/proc/cpuinfo') { |f| f.readlines }.grep(/processor/).size rescue StandardError nil end def count_via_sysctl run 'sysctl', '-n', 'hw.ncpu' end def run(command, *args) cmd = resolve_command(command) if cmd IO.popen [cmd, *args] do |io| io.read.to_i end else nil end end def resolve_command(command) look_for_command("/usr/sbin", command) || look_for_command("/sbin", command) || in_path_command(command) end def look_for_command(dir, command) path = File.join(dir, command) File.exist?(path) ? path : nil end def in_path_command(command) IO.popen ['which', command] do |io| io.eof? ? nil : command end end end; end PK% ]''&gems/rake-12.3.3/lib/rake/late_time.rbnu[# frozen_string_literal: true module Rake # LateTime is a fake timestamp that occurs _after_ any other time value. class LateTime include Comparable include Singleton def <=>(other) 1 end def to_s "" end end LATE = LateTime.instance end PK% ]-gems/rake-12.3.3/lib/rake/rake_test_loader.rbnu[# frozen_string_literal: true require "rake" # Load the test files from the command line. argv = ARGV.select do |argument| begin case argument when /^-/ then argument when /\*/ then FileList[argument].to_a.each do |file| require File.expand_path file end false else require File.expand_path argument false end rescue LoadError => e raise unless e.path abort "\nFile does not exist: #{e.path}\n\n" end end ARGV.replace argv PK% ]K\-gems/rake-12.3.3/lib/rake/invocation_chain.rbnu[# frozen_string_literal: true module Rake # InvocationChain tracks the chain of task invocations to detect # circular dependencies. class InvocationChain < LinkedList # Is the invocation already in the chain? def member?(invocation) head == invocation || tail.member?(invocation) end # Append an invocation to the chain of invocations. It is an error # if the invocation already listed. def append(invocation) if member?(invocation) fail RuntimeError, "Circular dependency detected: #{to_s} => #{invocation}" end conj(invocation) end # Convert to string, ie: TOP => invocation => invocation def to_s "#{prefix}#{head}" end # Class level append. def self.append(invocation, chain) chain.append(invocation) end private def prefix "#{tail} => " end # Null object for an empty chain. class EmptyInvocationChain < LinkedList::EmptyLinkedList @parent = InvocationChain def member?(obj) false end def append(invocation) conj(invocation) end def to_s "TOP" end end EMPTY = EmptyInvocationChain.new end end PK% ]E.$gems/rake-12.3.3/lib/rake/tasklib.rbnu[# frozen_string_literal: true require "rake" module Rake # Base class for Task Libraries. class TaskLib include Cloneable include Rake::DSL end end PK% ]l/gems/rake-12.3.3/lib/rake/file_creation_task.rbnu[# frozen_string_literal: true require "rake/file_task" require "rake/early_time" module Rake # A FileCreationTask is a file task that when used as a dependency will be # needed if and only if the file has not been created. Once created, it is # not re-triggered if any of its dependencies are newer, nor does trigger # any rebuilds of tasks that depend on it whenever it is updated. # class FileCreationTask < FileTask # Is this file task needed? Yes if it doesn't exist. def needed? !File.exist?(name) end # Time stamp for file creation task. This time stamp is earlier # than any other time stamp. def timestamp Rake::EARLY end end end PK% ]Q=rrgems/rake-12.3.3/lib/rake.rbnu[# frozen_string_literal: true #-- # Copyright 2003-2010 by Jim Weirich (jim.weirich@gmail.com) # # 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. #++ module Rake; end require "rake/version" require "rbconfig" require "fileutils" require "singleton" require "monitor" require "optparse" require "ostruct" require "rake/ext/string" require "rake/win32" require "rake/linked_list" require "rake/cpu_counter" require "rake/scope" require "rake/task_argument_error" require "rake/rule_recursion_overflow_error" require "rake/rake_module" require "rake/trace_output" require "rake/pseudo_status" require "rake/task_arguments" require "rake/invocation_chain" require "rake/task" require "rake/file_task" require "rake/file_creation_task" require "rake/multi_task" require "rake/dsl_definition" require "rake/file_utils_ext" require "rake/file_list" require "rake/default_loader" require "rake/early_time" require "rake/late_time" require "rake/name_space" require "rake/task_manager" require "rake/application" require "rake/backtrace" $trace = false # :stopdoc: # # Some top level Constants. FileList = Rake::FileList RakeFileUtils = Rake::FileUtilsExt PK% ]wgggems/rake-12.3.3/History.rdocnu[=== 12.3.3 ==== Bug fixes * Use the application's name in error message if a task is not found. Pull Request #303 by tmatilai ==== Enhancements: * Use File.open explicitly. === 12.3.2 ==== Bug fixes * Fixed test fails caused by 2.6 warnings. Pull Request #297 by hsbt ==== Enhancements: * Rdoc improvements. Pull Request #293 by colby-swandale * Improve multitask performance. Pull Request #273 by jsm * Add alias `prereqs`. Pull Request #268 by take-cheeze === 12.3.1 ==== Bug fixes * Support did_you_mean >= v1.2.0 which has a breaking change on formatters. Pull request #262 by FUJI Goro. ==== Enhancements: * Don't run task if it depends on already invoked but failed task. Pull request #252 by Gonzalo Rodriguez. * Make space trimming consistent for all task arguments. Pull request #259 by Gonzalo Rodriguez. * Removes duplicated inclusion of Rake::DSL in tests. Pull request #254 by Gonzalo Rodriguez. * Re-raise a LoadError that didn't come from require in the test loader. Pull request #250 by Dylan Thacker-Smith. === 12.3.0 ==== Compatibility Changes * Bump `required_ruby_version` to Ruby 2.0.0. Rake has already removed support for Ruby 1.9.x. ==== Enhancements: * Support `test-bundled-gems` task on ruby core. === 12.2.1 ==== Bug fixes * Fixed to break Capistrano::Application on capistrano3. === 12.2.0 ==== Enhancements: * Make rake easier to use as a library Pull request #211 by @drbrain * Fix quadratic performance in FileTask#out_of_date? Pull request #224 by @doudou * Clarify output when printing nested exception traces Pull request #232 by @urbanautomaton ==== Bug fixes * Account for a file that match 2 or more patterns. Pull request #231 by @styd === 12.1.0 ==== Enhancements: * Added did_you_mean feature for invalid rake task. Pull request #221 by @xtina-starr * Enabled to dependency chained by extensions. Pull request #39 by Petr Skocik. * Make all of string literals to frozen objects on Ruby 2.4 or later. ==== Bug fixes * Typo fixes in rakefile.rdoc. Pull request #180 by Yuta Kurotaki. * Fix unexpected behavior of file task with dryrun option. Pull request #183 by @aycabta. * Make LoadError from running tests more obvious. Pull request #195 by Eric Hodel. * Fix unexpected TypeError with hash style option. Pull request #202 by Kuniaki IGARASHI. === 12.0.0 ==== Compatibility Changes * Removed arguments on clear #157 by Jesse Bowes * Removed `rake/contrib` packages. These are extracted to `rake-contrib` gem. * Removed deprecated method named `last\_comment`. ==== Enhancements: * Re-use trace option on `cleanup` task. #164 by Brian Henderson * Actions adore keyword arguments #174 by Josh Cheek * Rake::TaskArguments#key? alias of #has_key? #175 by Paul Annesley === 11.3.0 / 2016-09-20 ==== Enhancements: * Remove to reference `Fixnum` constant. Pull request #160 by nobu === 11.2.2 / 2016-06-12 ==== Bug fixes * Fix unexpected behavior with multiple dependencies on Rake::TestTask === 11.2.1 / 2016-06-12 ==== Bug fixes * Fix regression of dependencies handling on Rake::TestTask. Report #139 === 11.2.0 / 2016-06-11 ==== Bug fixes * Fix unexpected cut-out behavior on task description using triple dots and exclamation. Report #106 from Stephan Kämper and Pull request #134 by Lee * Fix empty argument assignment with `with_defaults` option. Pull request #135 by bakunyo * Ignore to use `hwprefs` on Darwin platform. Use sysctl now. Report #128 ==== Enhancements * Spawn options for sh Pull equest #138 by Eric Hodel. * Allow to specify dependencies(prerequisites) for Rake::TestTask Pull request #117 by Tim Maslyuchenko * Use Bundler task instead of hoe for gem release. * Remove explicitly load to rubygems for Ruby 1.8. * Unify to declare `Rake::VERSION`. * Support xz format for PackageTask. === 11.1.2 / 2016-03-28 ==== Bug fixes * Remove `-W` option when Rake::TestTask#verbose enabled. It's misunderstanding specification change with Rake 11. Partly revert #67 === 11.1.1 / 2016-03-14 ==== Bug fixes * Use `-W` instead of `--verbose` when Rake::TestTask#verbose enabled. JRuby doesn't have `--verbose` option. === 11.1.0 / 2016-03-11 ==== Compatibility Changes * Revert to remove `last\_comment`. It will remove Rake 12. === 11.0.1 / 2016-03-09 ==== Bug fixes * Fixed packaging manifest. === 11.0.0 / 2016-03-09 ==== Bug fixes * Correctly handle bad encoding in exception messages. Pull request #113 by Tomer Brisker * Fix verbose option at TestTask. Pull request #67 by Mike Blumtritt ==== Enhancements * Make FileList#exclude more analogous to FileList#include. * Use IO.open instead of Open3.popen3 for CPU counter. * Make Rake::Task#already_invoked publicly accessible. Pull request #93 by Joe Rafaniello * Lookup prerequisites with same name outside of scope instead of matching self. Pull request #96 by Sandy Vanderbleek * Make FileList#pathmap behave like String#pathmap. Pull request #61 by Daniel Tamai * Add fetch method to task arguments. Pull request #12 by Chris Keathley * Use ruby warnings by default. Pull request #97 by Harold Giménez ==== Compatibility Changes * Removed to support Ruby 1.8.x * Removed constant named `RAKEVERSION` * Removed Rake::AltSystem * Removed Rake::RubyForgePublisher * Removed Rake::TaskManager#last\_comment. Use last\_description. * Removed Rake::TaskLib#paste * Removed Top-level SshDirPublisher, SshFreshDirPublisher, SshFilePublisher and CompositePublisher from lib/rake/contrib/publisher.rb * Removed "rake/runtest.rb" === 10.5.0 / 2016-01-13 ==== Enhancements * Removed monkey patching for Ruby 1.8. Pull request #46 by Pablo Herrero. * Inheritance class of Rake::FileList returns always self class. Pull request #74 by Thomas Scholz === 10.4.2 / 2014-12-02 ==== Bug fixes * Rake no longer edits ARGV. This allows you to re-exec rake from a rake task. Pull requset #9 by Matt Palmer. * Documented how Rake::DSL#desc handles sentences in task descriptions. Issue #7 by Raza Sayed. * Fixed test error on 1.9.3 with legacy RubyGems. Issue #8 by Matt Palmer. * Deleted duplicated History entry. Pull request #10 by Yuji Yamamoto. === 10.4.1 / 2014-12-01 ==== Bug fixes * Reverted fix for #277 as it caused numerous issues for rake users. rails/spring issue #366 by Gustavo Dutra. === 10.4.0 / 2014-11-22 ==== Enhancements * Upgraded to minitest 5. Pull request #292 by Teo Ljungberg. * Added support for Pathname in rake tasks. Pull request #271 by Randy Coulman. * Rake now ignores falsy dependencies which allows for easier programmatic creation of tasks. Pull request #273 by Manav. * Rake no longer edits ARGV. This allows you to re-exec rake from a rake task. Issue #277 by Matt Palmer. * Etc.nprocessors is used for counting the number of CPUs. ==== Bug fixes * Updated rake manpage. Issue #283 by Nathan Long, pull request #291 by skittleys. * Add Rake::LATE to allow rebuilding of files that depend on deleted files. Bug #286, pull request #287 by David Grayson. * Fix relinking of files when repackaging. Bug #276 by Muenze. * Fixed some typos. Pull request #280 by Jed Northridge. * Try counting CPUs via cpuinfo if host_os was not matched. Pull request #282 by Edouard B. === 10.3.2 / 2014-05-15 ==== Bug fixes * Rake no longer infinitely loops when showing exception causes that refer to each other. Bug #272 by Chris Bandy. * Fixed documentation typos. Bug #275 by Jake Worth. === 10.3.1 / 2014-04-17 ==== Bug fixes * Really stop reporting an error when cleaning already-deleted files. Pull request #269 by Randy Coulman * Fixed infinite loop when cleaning already-deleted files on windows. === 10.3 / 2014-04-15 ==== Enhancements * Added --build-all option to rake which treats all file prerequisites as out-of-date. Pull request #254 by Andrew Gilbert. * Added Rake::NameSpace#scope. Issue #263 by Jon San Miguel. ==== Bug fixes * Suppress org.jruby package files in rake error messages for JRuby users. Issue #213 by Charles Nutter. * Fixed typo, removed extra "h". Pull request #267 by Hsing-Hui Hsu. * Rake no longer reports an error when cleaning already-deleted files. Pull request #266 by Randy Coulman. * Consume stderr while determining CPU count to avoid hang. Issue #268 by Albert Sun. === 10.2.2 / 2014-03-27 ==== Bug fixes * Restored Ruby 1.8.7 compatibility === 10.2.1 / 2014-03-25 ==== Bug fixes * File tasks including a ':' are now top-level tasks again. Issue #262 by Josh Holtrop. * Use sysctl for CPU count for all BSDs. Pull request #261 by Joshua Stein. * Fixed CPU detection for unknown platforms. === 10.2.0 / 2014-03-24 ==== Enhancements * Rake now requires Ruby 1.9 or newer. For me, this is a breaking change, but it seems that Jim planned to release it with Rake 10.2. See also pull request #247 by Philip Arndt. * Rake now allows you to declare tasks under a namespace like: task 'a:b' do ... end Pull request #232 by Judson Lester. * Task#source defaults to the first prerequisite in non-rule tasks. Pull request #215 by Avdi Grimm. * Rake now automatically rebuilds and reloads imported files. Pull request #209 by Randy Coulman. * The rake task arguments can contain escaped commas. Pull request #214 by Filip Hrbek. * Rake now prints the exception class on errors. Patch #251 by David Cornu. ==== Bug fixes * Fixed typos. Pull request #256 by Valera Rozuvan, #250 via Jake Worth, #260 by Zachary Scott. * Fixed documentation for calling tasks with arguments. Pull request #235 by John Varghese. * Clarified `rake -f` usage message. Pull request #252 by Marco Pfatschbacher. * Fixed a test failure on windows. Pull request #231 by Hiroshi Shirosaki. * Fixed corrupted rake.1.gz. Pull request #225 by Michel Boaventura. * Fixed bug in can\_detect\_signals? in test. Patch from #243 by Alexey Borzenkov. === 10.1.1 * Use http://github.com/jimweirich/rake instead of http://rake.rubyforge.org for canonical project url. === 10.1.0 ==== Changes ===== New Features * Add support for variable length task argument lists. If more actual arguments are supplied than named arguments, then the extra arguments values will be in args.extras. * Application name is not displayed in the help banner. (Previously "rake" was hardcoded, now rake-based applications can display their own names). ===== Bug Fixes Bug fixes include: * Fix backtrace suppression issues. * Rules now explicit get task arguments passed to them. * Rename FileList#exclude? to FileList#exclude\_from\_list? to avoid conflict with new Rails method. * Clean / Clobber tasks now report failure to remove files. * Plus heaps of internal code cleanup. ==== Thanks As usual, it was input from users that drove a lot of these changes. The following people contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Michael Nikitochkin (general code cleanup) * Vipul A M (general code cleanup) * Dennis Bell (variable length task argument lists) * Jacob Swanner (rules arguments) * Rafael Rosa Fu (documentation typo) * Stuart Nelson (install.rb fixes) * Lee Hambley (application name in help banner) -- Jim Weirich === 10.0.3 "Jim, when will Rake reach version 1.0?" Over the past several years I've been asked that question at conferences, panels and over twitter. Due to historical reasons (or maybe just plain laziness) Rake has (incorrectly) been treating the second digit of the version as the major release number. So in my head Rake was already at version 9. Well, it's time to fix things. This next version of Rake drops old, crufty, backwards compatibility hacks such as top level constants, DSL methods defined in Object and numerous other features that are just no longer desired. It's also time to drop the leading zero from the version number as well and call this new version of rake what it really is: Version 10. So, welcome to Rake 10.0! Rake 10 is actually feature identical to the latest version of Rake 9 (that would be the version spelled 0.9.3), *except* that Rake 10 drops all the sundry deprecated features that have accumulated over the years. If your Rakefile is up to date and current with all the new features of Rake 10, you are ready to go. If your Rakefile still uses a few deprecated feeatures, feel free to use Rake 9 (0.9.3) with the same feature set. Just be aware that future features will be in Rake 10 family line. ==== Changes As mentioned above, there are no new features in Rake 10. However, there are a number of features missing: * Classic namespaces are now gone. Rake is no longer able to reflect the options settings in the global variables ($rakefile, $show\_tasks, $show\_prereqs, $trace, $dryrun and $silent). The --classic-namespace option is no longer supported. * Global constants are no longer supported. This includes Task, FileTask, FileCreationTask and RakeApp). The constant missing hook to warn about using global rake constants has been removed. * The Rake DSL methods (task, file, directory, etc) are in their own module (Rake::DSL). The stub versions of these methods (that printed warnings) in Object have been removed. However, the DSL methods are added to the top-level main object. Since main is not in the inheritance tree, the presence of the DSL methods in main should be low impact on other libraries. If you want to use the Rake DSL commands from your own code, just include Rake::DSL into your own classes and modules. * The deprecated syntax for task arguments (the one using :needs) has been removed. * The --reduce-compat flag has been removed (it's not needed anymore). * The deprecated rake/sys.rb library has been removed. * The deprecated rake/rdoctask.rb library has been removed. RDoc supplies its own rake task now. * The deprecated rake/gempackagetask.rb library has been removed. Gem supplies its own package task now. There is one small behavioral change: * Non-file tasks now always report the current time as their time stamp. This is different from the previous behavior where non-file tasks reported current time only if there were no prerequisites, and the max prerequisite timestamp otherwise. This lead to inconsistent and surprising behavior when adding prerequisites to tasks that in turn were prequisites to file tasks. The new behavior is more consistent and predictable. ==== Changes (from 0.9.3, 0.9.4, 0.9.5) Since Rake 10 includes the changes from the last version of Rake 9, we'll repeat the changes for versions 0.9.3 through 0.9.5 here. ===== New Features (in 0.9.3) * Multitask tasks now use a thread pool. Use -j to limit the number of available threads. * Use -m to turn regular tasks into multitasks (use at your own risk). * You can now do "Rake.add_rakelib 'dir'" in your Rakefile to programatically add rake task libraries. * You can specific backtrace suppression patterns (see --suppress-backtrace) * Directory tasks can now take prerequisites and actions * Use --backtrace to request a full backtrace without the task trace. * You can say "--backtrace=stdout" and "--trace=stdout" to route trace output to standard output rather than standard error. * Optional 'phony' target (enable with 'require 'rake/phony'") for special purpose builds. * Task#clear now clears task comments as well as actions and prerequisites. Task#clear_comment will specifically target comments. * The --all option will force -T and -D to consider all the tasks, with and without descriptions. ===== Bug Fixes (in 0.9.3) * Semi-colons in windows rakefile paths now work. * Improved Control-C support when invoking multiple test suites. * egrep method now reads files in text mode (better support for Windows) * Better deprecation line number reporting. * The -W option now works with all tasks, whether they have a description or not. * File globs in rake should not be sorted alphabetically, independent of file system and platform. * Numerous internal improvements. * Documentation typos and fixes. ===== Bug Fixes (in 0.9.4) * Exit status with failing tests is not correctly set to non-zero. * Simplified syntax for phony task (for older versions of RDoc). * Stand alone FileList usage gets glob function (without loading in extra dependencies) ===== Bug Fixes (in 0.9.5) * --trace and --backtrace no longer swallow following task names. ==== Thanks As usual, it was input from users that drove a lot of these changes. The following people contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Aaron Patterson * Dylan Smith * Jo Liss * Jonas Pfenniger * Kazuki Tsujimoto * Michael Bishop * Michael Elufimov * NAKAMURA Usaku * Ryan Davis * Sam Grönblom * Sam Phippen * Sergio Wong * Tay Ray Chuan * grosser * quix Also, many thanks to Eric Hodel for assisting with getting this release out the door. -- Jim Weirich === 10.0.2 ==== Changes ===== Bug Fixes * --trace and --backtrace no longer swallow following task names. ==== Thanks As usual, it was input from users that drove a lot of these changes. The following people contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Aaron Patterson * Dylan Smith * Jo Liss * Jonas Pfenniger * Kazuki Tsujimoto * Michael Bishop * Michael Elufimov * NAKAMURA Usaku * Ryan Davis * Sam Grönblom * Sam Phippen * Sergio Wong * Tay Ray Chuan * grosser * quix Also, many thanks to Eric Hodel for assisting with getting this release out the door. -- Jim Weirich === 10.0.1 ==== Changes ===== Bug Fixes * Exit status with failing tests is not correctly set to non-zero. * Simplified syntax for phony task (for older versions of RDoc). * Stand alone FileList usage gets glob function (without loading in extra dependencies) ==== Thanks As usual, it was input from users that drove a lot of these changes. The following people contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Aaron Patterson * Dylan Smith * Jo Liss * Jonas Pfenniger * Kazuki Tsujimoto * Michael Bishop * Michael Elufimov * NAKAMURA Usaku * Ryan Davis * Sam Grönblom * Sam Phippen * Sergio Wong * Tay Ray Chuan * grosser * quix Also, many thanks to Eric Hodel for assisting with getting this release out the door. -- Jim Weirich === 10.0.0 "Jim, when will Rake reach version 1.0?" Over the past several years I've been asked that question at conferences, panels and over twitter. Due to historical reasons (or maybe just plain laziness) Rake has (incorrectly) been treating the second digit of the version as the major release number. So in my head Rake was already at version 9. Well, it's time to fix things. This next version of Rake drops old, crufty, backwards compatibility hacks such as top level constants, DSL methods defined in Object and numerous other features that are just no longer desired. It's also time to drop the leading zero from the version number as well and call this new version of rake what it really is: Version 10. So, welcome to Rake 10.0! Rake 10 is actually feature identical to the latest version of Rake 9 (that would be the version spelled 0.9.3), *except* that Rake 10 drops all the sundry deprecated features that have accumulated over the years. If your Rakefile is up to date and current with all the new features of Rake 10, you are ready to go. If your Rakefile still uses a few deprecated feeatures, feel free to use Rake 9 (0.9.3) with the same feature set. Just be aware that future features will be in Rake 10 family line. ==== Changes in 10.0 As mentioned above, there are no new features in Rake 10. However, there are a number of features missing: * Classic namespaces are now gone. Rake is no longer able to reflect the options settings in the global variables ($rakefile, $show\_tasks, $show\_prereqs, $trace, $dryrun and $silent). The --classic-namespace option is no longer supported. * Global constants are no longer supported. This includes Task, FileTask, FileCreationTask and RakeApp). The constant missing hook to warn about using global rake constants has been removed. * The Rake DSL methods (task, file, directory, etc) are in their own module (Rake::DSL). The stub versions of these methods (that printed warnings) in Object have been removed. However, the DSL methods are added to the top-level main object. Since main is not in the inheritance tree, the presence of the DSL methods in main should be low impact on other libraries. If you want to use the Rake DSL commands from your own code, just include Rake::DSL into your own classes and modules. * The deprecated syntax for task arguments (the one using :needs) has been removed. * The --reduce-compat flag has been removed (it's not needed anymore). * The deprecated rake/sys.rb library has been removed. * The deprecated rake/rdoctask.rb library has been removed. RDoc supplies its own rake task now. * The deprecated rake/gempackagetask.rb library has been removed. Gem supplies its own package task now. There is one small behavioral change: * Non-file tasks now always report the current time as their time stamp. This is different from the previous behavior where non-file tasks reported current time only if there were no prerequisites, and the max prerequisite timestamp otherwise. This lead to inconsistent and surprising behavior when adding prerequisites to tasks that in turn were prequisites to file tasks. The new behavior is more consistent and predictable. ==== Changes (from 0.9.3) Since Rake 10 includes the changes from the last version of Rake 9, we'll repeat the changes for version 0.9.3 here. ===== New Features * Multitask tasks now use a thread pool. Use -j to limit the number of available threads. * Use -m to turn regular tasks into multitasks (use at your own risk). * You can now do "Rake.add_rakelib 'dir'" in your Rakefile to programatically add rake task libraries. * You can specific backtrace suppression patterns (see --suppress-backtrace) * Directory tasks can now take prerequisites and actions * Use --backtrace to request a full backtrace without the task trace. * You can say "--backtrace=stdout" and "--trace=stdout" to route trace output to standard output rather than standard error. * Optional 'phony' target (enable with 'require 'rake/phony'") for special purpose builds. * Task#clear now clears task comments as well as actions and prerequisites. Task#clear_comment will specifically target comments. * The --all option will force -T and -D to consider all the tasks, with and without descriptions. ===== Bug Fixes * Semi-colons in windows rakefile paths now work. * Improved Control-C support when invoking multiple test suites. * egrep method now reads files in text mode (better support for Windows) * Better deprecation line number reporting. * The -W option now works with all tasks, whether they have a description or not. * File globs in rake should not be sorted alphabetically, independent of file system and platform. * Numerous internal improvements. * Documentation typos and fixes. ==== Thanks As usual, it was input from users that drove a lot of these changes. The following people contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Aaron Patterson * Dylan Smith * Jo Liss * Jonas Pfenniger * Kazuki Tsujimoto * Michael Bishop * Michael Elufimov * NAKAMURA Usaku * Ryan Davis * Sam Grönblom * Sam Phippen * Sergio Wong * Tay Ray Chuan * grosser * quix Also, many thanks to Eric Hodel for assisting with getting this release out the door. -- Jim Weirich === 0.9.6 Rake version 0.9.6 contains a number of fixes mainly for merging Rake into the Ruby source tree and fixing tests. ==== Changes ===== Bug Fixes (0.9.6) * Better trace output when using a multi-threaded Rakefile. * Arg parsing is now consistent for tasks and multitasks. * Skip exit code test in versions of Ruby that don't support it well. Changes for better integration with the Ruby source tree: * Fix version literal for Ruby source tree build. * Better loading of libraries for testing in Ruby build. * Use the ruby version provided by Ruby's tests. ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Aaron Patterson * Dylan Smith * Jo Liss * Jonas Pfenniger * Kazuki Tsujimoto * Michael Bishop * Michael Elufimov * NAKAMURA Usaku * Ryan Davis * Sam Grönblom * Sam Phippen * Sergio Wong * Tay Ray Chuan * grosser * quix Also, many thanks to Eric Hodel for assisting with getting this release out the door. -- Jim Weirich === 0.9.5 Rake version 0.9.5 contains a number of bug fixes. ==== Changes ===== Bug Fixes (0.9.5) * --trace and --backtrace no longer swallow following task names. ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Aaron Patterson * Dylan Smith * Jo Liss * Jonas Pfenniger * Kazuki Tsujimoto * Michael Bishop * Michael Elufimov * NAKAMURA Usaku * Ryan Davis * Sam Grönblom * Sam Phippen * Sergio Wong * Tay Ray Chuan * grosser * quix Also, many thanks to Eric Hodel for assisting with getting this release out the door. -- Jim Weirich === 0.9.4 Rake version 0.9.4 contains a number of bug fixes. ==== Changes ===== Bug Fixes (0.9.4) * Exit status with failing tests is not correctly set to non-zero. * Simplified syntax for phony task (for older versions of RDoc). * Stand alone FileList usage gets glob function (without loading in extra dependencies) ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Aaron Patterson * Dylan Smith * Jo Liss * Jonas Pfenniger * Kazuki Tsujimoto * Michael Bishop * Michael Elufimov * NAKAMURA Usaku * Ryan Davis * Sam Grönblom * Sam Phippen * Sergio Wong * Tay Ray Chuan * grosser * quix Also, many thanks to Eric Hodel for assisting with getting this release out the door. -- Jim Weirich === 0.9.3 Rake version 0.9.3 contains some new, backwards compatible features and a number of bug fixes. ==== Changes ===== New Features * Multitask tasks now use a thread pool. Use -j to limit the number of available threads. * Use -m to turn regular tasks into multitasks (use at your own risk). * You can now do "Rake.add_rakelib 'dir'" in your Rakefile to programatically add rake task libraries. * You can specific backtrace suppression patterns (see --suppress-backtrace) * Directory tasks can now take prerequisites and actions * Use --backtrace to request a full backtrace without the task trace. * You can say "--backtrace=stdout" and "--trace=stdout" to route trace output to standard output rather than standard error. * Optional 'phony' target (enable with 'require 'rake/phony'") for special purpose builds. * Task#clear now clears task comments as well as actions and prerequisites. Task#clear_comment will specifically target comments. * The --all option will force -T and -D to consider all the tasks, with and without descriptions. ===== Bug Fixes * Semi-colons in windows rakefile paths now work. * Improved Control-C support when invoking multiple test suites. * egrep method now reads files in text mode (better support for Windows) * Better deprecation line number reporting. * The -W option now works with all tasks, whether they have a description or not. * File globs in rake should not be sorted alphabetically, independent of file system and platform. * Numerous internal improvements. * Documentation typos and fixes. ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Aaron Patterson * Dylan Smith * Jo Liss * Jonas Pfenniger * Kazuki Tsujimoto * Michael Bishop * Michael Elufimov * NAKAMURA Usaku * Ryan Davis * Sam Grönblom * Sam Phippen * Sergio Wong * Tay Ray Chuan * grosser * quix Also, many thanks to Eric Hodel for assisting with getting this release out the door. -- Jim Weirich === Rake 0.9.2.2 Rake version 0.9.2.2 is mainly bug fixes. ==== Changes * The rake test loader now removes arguments it has processed. Issue #51 * Rake::TaskArguments now responds to #values\_at * RakeFileUtils.verbose_flag = nil silences output the same as 0.8.7 * Rake tests are now directory-independent * Rake tests are no longer require flexmock * Commands constant is no longer polluting top level namespace. * Show only the interesting portion of the backtrace by default (James M. Lawrence). * Added --reduce-compat option to remove backward compatible DSL hacks (James M. Lawrence). ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * James M. Lawrence (quix) * Roger Pack * Cezary Baginski * Sean Scot August Moon * R.T. Lechow * Alex Chaffee * James Tucker * Matthias Lüdtke * Santiago Pastorino Also, bit thanks to Eric Hodel for assisting with getting this release out the door (where "assisting" includes, but is not by any means limited to, "pushing" me to get it done). -- Jim Weirich === 0.9.2 Rake version 0.9.2 has a few small fixes. See below for details. ==== Changes * Support for Ruby 1.8.6 was fixed. * Global DSL warnings now honor --no-deprecate ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * James M. Lawrence (quix) * Roger Pack * Cezary Baginski * Sean Scot August Moon * R.T. Lechow * Alex Chaffee * James Tucker * Matthias Lüdtke * Santiago Pastorino Also, bit thanks to Eric Hodel for assisting with getting this release out the door (where "assisting" includes, but is not by any means limited to, "pushing" me to get it done). -- Jim Weirich === 0.9.1 Rake version 0.9.1 has a number of bug fixes and enhancments (see below for more details). Additionally, the internals have be slightly restructured and improved. ==== Changes Rake 0.9.1 adds back the global DSL methods, but with deprecation messages. This allows Rake 0.9.1 to be used with older rakefiles with warning messages. ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * James M. Lawrence (quix) * Roger Pack * Cezary Baginski * Sean Scot August Moon * R.T. Lechow * Alex Chaffee * James Tucker * Matthias Lüdtke * Santiago Pastorino Also, bit thanks to Eric Hodel for assisting with getting this release out the door (where "assisting" includes, but is not by any means limited to, "pushing" me to get it done). -- Jim Weirich === 0.9.0 Rake version 0.9.0 has a number of bug fixes and enhancments (see below for more details). Additionally, the internals have be slightly restructured and improved. ==== Changes ===== New Features / Enhancements / Bug Fixes in Version 0.9.0 * Rake now warns when the deprecated :needs syntax used (and suggests the proper syntax in the warning). * Moved Rake DSL commands to top level ruby object 'main'. Rake DSL commands are no longer private methods in Object. (Suggested by James M. Lawrence/quix) * Rake now uses case-insensitive comparisons to find the Rakefile on Windows. Based on patch by Roger Pack. * Rake now requires (instead of loads) files in the test task. Patch by Cezary Baginski. * Fixed typos. Patches by Sean Scot August Moon and R.T. Lechow. * Rake now prints the Rakefile directory only when it's different from the current directory. Patch by Alex Chaffee. * Improved rakefile_location discovery on Windows. Patch by James Tucker. * Rake now recognizes "Windows Server" as a windows system. Patch by Matthias Lüdtke * Rake::RDocTask is deprecated. Use RDoc::Task from RDoc 2.4.2+ (require 'rdoc/task') * Rake::GemPackageTask is deprecated. Use Gem::PackageTask (require 'rubygems/package\_task') * Rake now outputs various messages to $stderr instead of $stdout. * Rake no longer emits warnings for Config. Patch by Santiago Pastorino. * Removed Rake's DSL methods from the top level scope. If you need to call 'task :xzy' in your code, include Rake::DSL into your class, or put the code in a Rake::DSL.environment do ... end block. * Split rake.rb into individual files. * Support for the --where (-W) flag for showing where a task is defined. * Fixed quoting in test task. (http://onestepback.org/redmine/issues/show/44, http://www.pivotaltracker.com/story/show/1223138) * Fixed the silent option parsing problem. (http://onestepback.org/redmine/issues/show/47) * Fixed :verbose=>false flag on sh and ruby commands. * Rake command line options may be given by default in a RAKEOPT environment variable. * Errors in Rake will now display the task invocation chain in effect at the time of the error. * Accepted change by warnickr to not expand test patterns in shell (allowing more files in the test suite). * Fixed that file tasks did not perform prereq lookups in scope (Redmine #57). ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * James M. Lawrence (quix) * Roger Pack * Cezary Baginski * Sean Scot August Moon * R.T. Lechow * Alex Chaffee * James Tucker * Matthias Lüdtke * Santiago Pastorino Also, bit thanks to Eric Hodel for assisting with getting this release out the door (where "assisting" includes, but is not by any means limited to, "pushing" me to get it done). -- Jim Weirich === 0.8.7 Rake version 0.8.5 introduced greatly improved support for executing commands on Windows. The "sh" command now has the same semantics on Windows that it has on Unix based platforms. Rake version 0.8.6 includes minor fixes the the RDoc generation. Rake version 0.8.7 includes a minor fix for JRuby running on windows. ==== Changes ===== New Features / Enhancements in Version 0.8.5 * Improved implementation of the Rake system command for Windows. (patch from James M. Lawrence/quix) * Support for Ruby 1.9's improved system command. (patch from James M. Lawrence/quix) * Rake now includes the configured extension when invoking an executable (Config::CONFIG['EXEEXT]) ===== Bug Fixes in Version 0.8.5 * Environment variable keys are now correctly cased (it matters in some implementations). ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Charles Nutter -- Jim Weirich === 0.8.6 Rake version 0.8.5 introduced greatly improved support for executing commands on Windows. The "sh" command now has the same semantics on Windows that it has on Unix based platforms. Rake version 0.8.5 includes minor fixes the the RDoc generation. ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * James M. Lawrence/quix * Luis Lavena -- Jim Weirich === 0.8.5 Rake version 0.8.5 is a new release of Rake with greatly improved support for executing commands on Windows. The "sh" command now has the same semantics on Windows that it has on Unix based platforms. ==== Changes ===== New Features / Enhancements in Version 0.8.5 * Improved implementation of the Rake system command for Windows. (patch from James M. Lawrence/quix) * Support for Ruby 1.9's improved system command. (patch from James M. Lawrence/quix) * Rake now includes the configured extension when invoking an executable (Config::CONFIG['EXEEXT]) ===== Bug Fixes in Version 0.8.5 * Environment variable keys are now correctly cased (it matters in some implementations). ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * James M. Lawrence/quix * Luis Lavena -- Jim Weirich === 0.8.4 Rake version 0.8.4 is a bug-fix release of rake. NOTE: The version of Rake that comes with Ruby 1.9 has diverged slightly from the core Rake code base. Rake 0.8.4 will work with Ruby 1.9, but is not a strict upgrade for the Rake that comes with Ruby 1.9. A (near) future release of Rake will unify those two codebases. ==== Letter Writing Campaign Thanks to Aaron Patterson (@tenderlove) and Eric Hodel (@drbrain) for their encouraging support in organizing a letter writing campaign to lobby for the "Warning Free" release of rake 0.8.4. A special callout goes to Jonathan D. Lord, Sr (Dr. Wingnut) whose postcard was the first to actually reach me. (see http://tenderlovemaking.com/2009/02/26/we-need-a-new-version-of-rake/ for details) ==== Changes ===== New Features / Enhancements in Version 0.8.4 * Case is preserved on rakefile names. (patch from James M. Lawrence/quix) * Improved Rakefile case insensitivity testing (patch from Luis Lavena). * Windows system dir search order is now: HOME, HOMEDRIVE + HOMEPATH, APPDATA, USERPROFILE (patch from Luis Lavena) * MingGW is now recognized as a windows platform. (patch from Luis Lavena) ===== Bug Fixes in Version 0.8.4 * Removed reference to manage_gem to fix the warning produced by the gem package task. * Fixed stray ARGV option problem that was interfering with Test::Unit::Runner. (patch from Pivotal Labs) ===== Infrastructure Improvements in Version 0.8.4 * Numerous fixes to the windows test suite (patch from Luis Lavena). * Improved Rakefile case insensitivity testing (patch from Luis Lavena). * Better support for windows paths in the test task (patch from Simon Chiang/bahuvrihi) ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * James M. Lawrence/quix * Luis Lavena * Pivotal Labs * Simon Chiang/bahuvrihi -- Jim Weirich === 0.8.3 Rake version 0.8.3 is a bug-fix release of rake. ==== Changes ===== Bug Fixes in Version 0.8.3 * Enhanced the system directory detection in windows. We now check HOMEDRIVE/HOMEPATH and USERPROFILE if APPDATA isn't found. (Patch supplied by James Tucker). Rake no long aborts if it can't find the directory. * Added fix to handle ruby installations in directories with spaces in their name. ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Edwin Pratomo * Gavin Stark * Adam Q. Salter * Adam Majer * Emanuel Indermühle * Ittay Dror * Bheeshmar Redheendran (for spending an afternoon with me debugging windows issues) -- Jim Weirich === 0.8.2 Rake version 0.8.2 is a new release of rake that includes a number of new features and numerous bug fixes. ==== Changes ===== New Features in Version 0.8.2 * Switched from getoptlong to optparse (patches supplied by Edwin Pratomo). * The -T option will now attempt to dynamically sense the size of the terminal. The -T output will only self-truncate if the output is a tty. However, if RAKE_COLUMNS is explicitly set, it will be honored in any case. (Patch provided by Gavin Stark). * The following public methods have been added to rake task objects: * task.clear -- Clear both the prerequisites and actions of the target rake task. * task.clear_prerequisites -- Clear all the existing prerequisites from the target rake task. * task.clear_actions -- Clear all the existing actions from the target rake task. * task.reenable -- Re-enable a task, allowing its actions to be executed again if the task is invoked. * Changed RDoc test task to have no default template. This makes it easier for the tempate to pick up the template from the environment. * Default values for task arguments can easily be specified with the :with_defaults method. (Idea for default argument merging supplied by (Adam Q. Salter) ===== Bug Fixes in Version 0.8.2 * Fixed bug in package task so that it will include the subdir directory in the package for testing. (Bug found by Adam Majer) * Fixed filename dependency order bug in test\_inspect\_pending and test\_to\_s\_pending. (Bug found by Adam Majer) * Fixed check for file utils options to make them immune to the symbol/string differences. (Patch supplied by Edwin Pratomo) * Fixed bug with rules involving multiple source, where only the first dependency of a rule has any effect (Patch supplied by Emanuel Indermühle) * FileList#clone and FileList#dup have better sematics w.r.t. taint and freeze. * Changed from using Mutex to Monitor. Evidently Mutex causes thread join errors when Ruby is compiled with -disable-pthreads. (Patch supplied by Ittay Dror) * Fixed bug in makefile parser that had problems with extra spaces in file task names. (Patch supplied by Ittay Dror) ==== Other changes in Version 0.8.2 * Added ENV var to rake's own Rakefile to prevent OS X from including extended attribute junk in the rake package tar file. (Bug found by Adam Majer) * Added a performance patch for reading large makefile dependency files. (Patch supplied by Ittay Dror) ==== Task Argument Examples Prior to version 0.8.0, rake was only able to handle command line arguments of the form NAME=VALUE that were passed into Rake via the ENV hash. Many folks had asked for some kind of simple command line arguments, perhaps using "--" to separate regular task names from argument values on the command line. The problem is that there was no easy way to associate positional arguments on the command line with different tasks. Suppose both tasks :a and :b expect a command line argument: does the first value go with :a? What if :b is run first? Should it then get the first command line argument. Rake 0.8.0 solves this problem by explicitly passing values directly to the tasks that need them. For example, if I had a release task that required a version number, I could say: rake release[0.8.2] And the string "0.8.2" will be passed to the :release task. Multiple arguments can be passed by separating them with a comma, for example: rake name[john,doe] Just a few words of caution. The rake task name and its arguments need to be a single command line argument to rake. This generally means no spaces. If spaces are needed, then the entire rake + argument string should be quoted. Something like this: rake "name[billy bob, smith]" (Quoting rules vary between operating systems and shells, so make sure you consult the proper docs for your OS/shell). ===== Tasks that Expect Parameters Parameters are only given to tasks that are setup to expect them. In order to handle named parameters, the task declaration syntax for tasks has been extended slightly. For example, a task that needs a first name and last name might be declared as: task :name, :first_name, :last_name The first argument is still the name of the task (:name in this case). The next to argumements are the names of the parameters expected by :name (:first_name and :last_name in the example). To access the values of the parameters, the block defining the task behaviour can now accept a second parameter: task :name, :first_name, :last_name do |t, args| puts "First name is #{args.first_name}" puts "Last name is #{args.last_name}" end The first argument of the block "t" is always bound to the current task object. The second argument "args" is an open-struct like object that allows access to the task arguments. Extra command line arguments to a task are ignored. Missing command line arguments are given the nil value. ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Edwin Pratomo * Gavin Stark * Adam Q. Salter * Adam Majer * Emanuel Indermühle * Ittay Dror * Bheeshmar Redheendran (for spending an afternoon with me debugging windows issues) -- Jim Weirich === 0.8.0/0.8.1 Rake version 0.8.0 is a new release of rake that includes serveral new features. ==== Changes ===== New Features in Version 0.8.0 * Tasks can now receive command line parameters. See the examples below for more details. * Comments are limited to 80 columns on output, but full comments can be seen by using the -D parameter. (feature suggested by Jamis Buck). * Explicit exit(n) calls will now set the exit status to n. (patch provided by Stephen Touset). * Rake is now compatible with Ruby 1.9. Version 0.8.1 is a minor update that includes additional Ruby 1.9 compatibility fixes. ==== Task Argument Examples Prior to version 0.8.0, rake was only able to handle command line arguments of the form NAME=VALUE that were passed into Rake via the ENV hash. Many folks had asked for some kind of simple command line arguments, perhaps using "--" to separate regular task names from argument values on the command line. The problem is that there was no easy way to associate positional arguments on the command line with different tasks. Suppose both tasks :a and :b expect a command line argument: does the first value go with :a? What if :b is run first? Should it then get the first command line argument. Rake 0.8.0 solves this problem by explicitly passing values directly to the tasks that need them. For example, if I had a release task that required a version number, I could say: rake release[0.8.0] And the string "0.8.0" will be passed to the :release task. Multiple arguments can be passed by separating them with a comma, for example: rake name[john,doe] Just a few words of caution. The rake task name and its arguments need to be a single command line argument to rake. This generally means no spaces. If spaces are needed, then the entire rake + argument string should be quoted. Something like this: rake "name[billy bob, smith]" (Quoting rules vary between operating systems and shells, so make sure you consult the proper docs for your OS/shell). ===== Tasks that Expect Parameters Parameters are only given to tasks that are setup to expect them. In order to handle named parameters, the task declaration syntax for tasks has been extended slightly. For example, a task that needs a first name and last name might be declared as: task :name, :first_name, :last_name The first argument is still the name of the task (:name in this case). The next to argumements are the names of the parameters expected by :name (:first_name and :last_name in the example). To access the values of the parameters, the block defining the task behaviour can now accept a second parameter: task :name, :first_name, :last_name do |t, args| puts "First name is #{args.first_name}" puts "Last name is #{args.last_name}" end The first argument of the block "t" is always bound to the current task object. The second argument "args" is an open-struct like object that allows access to the task arguments. Extra command line arguments to a task are ignored. Missing command line arguments are given the nil value. ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Jamis Buck (for comment formatting suggestions) * Stephen Touset (for exit status patch). -- Jim Weirich === 0.7.3 Rake version 0.7.3 is a minor release that includes some refactoring to better support custom Rake applications. ==== Changes ===== New Features in Version 0.7.3 * Added the +init+ and +top_level+ methods to make the creation of custom Rake applications a bit easier. E.g. gem 'rake', ">= 0.7.3" require 'rake' Rake.application.init('myrake') task :default do something_interesting end Rake.application.top_level ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... -- Jim Weirich === 0.7.2 Version 0.7.2 supplies a bug fix and a few minor enhancements. In particular, the new version fixes an incompatibility with the soon to be released Ruby 1.8.6. We strongly recommend upgrading to Rake 0.7.2 in order to be compatible with the new version of Ruby. ==== Changes ===== Bug Fixes in 0.7.2 There are quite a number of bug fixes in the new 0.7.2 version of Rake: * Removed dependency on internal fu_xxx functions from FileUtils. * Error messages are now send to stderr rather than stdout (from Payton Quackenbush). * Better error handling on invalid command line arguments (from Payton Quackenbush). * Fixed some bugs where the application object was going to the global appliation instead of using its own data. * Fixed the method name leak from FileUtils (bug found by Glenn Vanderburg). * Added test for noop, bad_option and verbose flags to sh command. * Added a description to the gem task in GemPackageTask. * Fixed a bug when rules have multiple prerequisites (patch by Joel VanderWerf) * Added the handful of RakeFileUtils to the private method as well. ===== New Features in 0.7.2 The following new features are available in Rake version 0.7.2: * Added square and curly bracket patterns to FileList#include (Tilman Sauerbeck). * FileLists can now pass a block to FileList#exclude to exclude files based on calculated values. * Added plain filename support to rule dependents (suggested by Nobu Nakada). * Added pathmap support to rule dependents. In other words, if a pathmap format (beginning with a '%') is given as a Rake rule dependent, then the name of the depend will be the name of the target with the pathmap format applied. * Added a 'tasks' method to a namespace to get a list of tasks associated with the namespace. * Added tar_command and zip_command options to the Package task. * The clean task will no longer delete 'core' if it is a directory. ===== Internal Rake Improvements The following changes will are mainly internal improvements and refactorings and have little effect on the end user. But they may be of interest to the general public. * Added rcov task and updated unit testing for better code coverage. * Added a 'shame' task to the Rakefile. * Added rake_extension to handle detection of extension collisions. * Added a protected 'require "rubygems"' to test/test_application to unbreak cruisecontrol.rb. * Removed rake\_dup. Now we just simply rescue a bad dup. * Refactored the FileList reject logic to remove duplication. * Removed if \_\_FILE\_\_ at the end of the rake.rb file. ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Payton Quackenbush -- For several error handling improvements. * Glenn Vanderburg -- For finding and fixing the method name leak from FileUtils. * Joel VanderWerf -- for finding and fixing a bug in the handling of multiple prerequisites. * Tilman Sauerbeck -- For some enhancing FileList to support more advanced file globbing. * Nobu Nakada -- For suggesting plain file name support to rule dependents. -- Jim Weirich === 0.7.1 Version 0.7.1 supplies a bug fix and a few minor enhancements. ==== Changes ===== Bug Fixes in 0.7.1 * Changes in the exception reported for the FileUtils.ln caused safe_ln to fail with a NotImplementedError. Rake 0.7.1 will now catch that error or any StandardError and properly fall back to using +cp+. ===== New Features in 0.7.1 * You can filter the results of the --task option by supplying an optional regular expression. This allows the user to easily find a particular task name in a long list of possible names. * Transforming procs in a rule may now return a list of prerequisites. This allows more flexible rule formation. * FileList and String now support a +pathmap+ melthod that makes the transforming paths a bit easier. See the API docs for +pathmap+ for details. * The -f option without a value will disable the search for a Rakefile. This allows the Rakefile to be defined entirely in a library (and loaded with the -r option). The current working directory is not changed when this is done. ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * James Britt and Assaph Mehr for reporting and helping to debug the safe_ln issue. -- Jim Weirich === 0.7.0 These changes for Rake have been brewing for a long time. Here they are, I hope you enjoy them. ==== Changes ===== New Features * Name space support for task names (see below). * Prerequisites can be executed in parallel (see below). * Added safe_ln support for openAFS (via Ludvig Omholt). * RDoc defaults to internal (in-process) invocation. The old behavior is still available by setting the +external+ flag to true. * Rakefiles are now loaded with the expanded path to prevent accidental pollution from the Ruby load path. * Task objects my now be used in prerequisite lists directly. * Task objects (in addition to task names) may now be included in the prerequisite list of a task. * Internals cleanup and refactoring. ===== Bug Fixes * Compatibility fixes for Ruby 1.8.4 FileUtils changes. ===== Namespaces Tasks can now be nested inside their own namespaces. Tasks within one namespace will not accidentally interfer with tasks named in a different namespace. For example: namespace "main" do task :build do # Build the main program end end namespace "samples" do task :build do # Build the sample programs end end task :build_all => ["main:build", "samples:build"] Even though both tasks are named :build, they are separate tasks in their own namespaces. The :build_all task (defined in the toplevel namespace) references both build tasks in its prerequisites. You may invoke each of the individual build tasks with the following commands: rake main:build rake samples:build Or invoke both via the :build_all command: rake build_all Namespaces may be nested arbitrarily. Since the name of file tasks correspond to the name of a file in the external file system, FileTasks are not affected by the namespaces. See the Rakefile format documentation (in the Rake API documents) for more information. ===== Parallel Tasks Sometimes you have several tasks that can be executed in parallel. By specifying these tasks as prerequisites to a +multitask+ task. In the following example the tasks copy\_src, copy\_doc and copy\_bin will all execute in parallel in their own thread. multitask :copy_files => [:copy_src, :copy_doc, :copy_bin] do puts "All Copies Complete" end ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Doug Young (inspiration for the parallel task) * David Heinemeier Hansson (for --trace message enhancement and for pushing for namespace support). * Ludvig Omholt (for the openAFS fix) -- Jim Weirich === 0.6.1 * Rebuilt 0.6.0 gem without signing. === 0.6.0 Its time for some long requested enhancements and lots of bug fixes ... And a whole new web page. ==== New Web Page The primary documentation for rake has moved from the RubyForge based wiki to its own Hieraki based web site. Constant spam on the wiki made it a difficult to keep clean. The new site will be easier to update and organize. Check out the new documentation at: http://docs.rubyrake.org We will be adding new documentation to the site as time goes on. In addition to the new docs page, make sure you check out Martin Fowlers article on rake at http://martinfowler.com/articles/rake.html ==== Changes ===== New Features * Multiple prerequisites on Rake rules now allowed. However, keep the following in mind: 1. All the prerequisites of a rule must be available before a rule is triggered, where "enabled" means (a) an existing file, (b) a defined rule, or (c) another rule which also must be trigger-able. 2. Rules are checked in order of definition, so it is important to order your rules properly. If a file can be created by two different rules, put the more specific rule first (otherwise the more general rule will trigger first and the specific one will never be triggered). 3. The source method now returns the name of the first prerequisite listed in the rule. sources returns the names of all the rule prerequisites, ordered as they are defined in the rule. If the task has other prerequisites not defined in the rule (but defined in an explicit task definition), then they will _not_ be included in the sources list. * FileLists may now use the egrep command. This popular enhancement is now a core part of the FileList object. If you want to get a list of all your to-dos, fixmes and TBD comments, add the following to your Rakefile. desc "Look for TODO and FIXME tags in the code" task :todo do FileList['**/*.rb'].egrep /#.*(FIXME|TODO|TBD)/ end * The investigation method was added to task object to dump out some important values. This makes it a bit easier to debug Rake tasks. For example, if you are having problems with a particular task, just print it out: task :huh do puts Rake::Task['huh'].investigation end * The Rake::TestTask class now supports a "ruby\_opts" option to pass arbitrary ruby options to a test subprocess. ===== Some Incompatibilities * When using the ruby command to start a Ruby subprocess, the Ruby interpreter that is currently running rake is used by default. This makes it easier to use rake in an environment with multiple ruby installation. (Previously, the first ruby command found in the PATH was used). If you wish to chose a different Ruby interpreter, you can explicitly choose the interpreter via the sh command. * The major rake classes (Task, FileTask, FileCreationTask, RakeApp) have been moved out of the toplevel scope and are now accessible as Rake::Task, Rake::FileTask, Rake::FileCreationTask and Rake::Application. If your Rakefile directly references any one of these tasks, you may: 1. Update your Rakefile to use the new classnames 2. Use the --classic-namespace option on the rake command to get the old behavior, 3. Add require 'rake/classic_namespace' to the Rakefile to get the old behavior. rake will print a rather annoying warning whenever a deprecated class name is referenced without enabling classic namespace. ===== Bug Fixes * Several unit tests and functional tests were fixed to run better under windows. * Directory tasks are now a specialized version of a File task. A directory task will only be triggered if it doesn't exist. It will not be triggered if it is out of date w.r.t. any of its prerequisites. * Fixed a bug in the Rake::GemPackageTask class so that the gem now properly contains the platform name. * Fixed a bug where a prerequisite on a file task would cause an exception if the prerequisite did not exist. ==== Thanks As usual, it was input from users that drove a alot of these changes. The following people either contributed patches, made suggestions or made otherwise helpful comments. Thanks to ... * Greg Fast (better ruby_opt test options) * Kelly Felkins (requested by better namespace support) * Martin Fowler (suggested Task.investigation) * Stuart Jansen (send initial patch for multiple prerequisites). * Masao Mutch (better support for non-ruby Gem platforms) * Philipp Neubeck (patch for file task exception fix) -- Jim Weirich === 0.5.4 Time for some minor bug fixes and small enhancements ==== Changes Here are the changes for version 0.5.4 ... * Added double quotes to the test runner. This allows the location of the tests (and runner) to be in a directory path that contains spaces (e.g. "C:/Program Files/ruby/bin"). * Added .svn to default ignore list. Now subversion project metadata is automatically ignored by Rake's FileList. * Updated FileList#include to support nested arrays and filelists. FileLists are flat lists of file names. Using a FileList in an include will flatten out the nested file names. == Thanks As usual, it was input from users that drove a alot of these changes. Thanks to ... * Tilman Sauerbeck for the nested FileList suggestion. * Josh Knowles for pointing out the spaces in directory name problem. -- Jim Weirich === 0.5.3 Although it has only been two weeks since the last release, we have enough updates to the Rake program to make it time for another release. ==== Changes Here are the changes for version 0.5.3 ... * FileLists have been extensively changed so that they mimic the behavior of real arrays even more closely. In particular, operations on FileLists that return a new collection (e.g. collect, reject) will now return a FileList rather than an array. In addition, several places where FileLists were not properly expanded before use have been fixed. * A method (+ext+) to simplify the handling of file extensions was added to String and to Array. * The 'testrb' script in test/unit tends to silently swallow syntax errors in test suites. Because of that, the default test loader is now a rake-provided script. You can still use 'testrb' by setting the loader flag in the test task to :testrb. (See the API documents for TestTask for all the loader flag values). * FileUtil methods (e.g. cp, mv, install) are now declared to be private. This will cut down on the interference with user defined methods of the same name. * Fixed the verbose flag in the TestTask so that the test code is controlled by the flag. Also shortened up some failure messages. (Thanks to Tobias Luetke for the suggestion). * Rules will now properly detect a task that can generate a source file. Previously rules would only consider source files that were already present. * Added an +import+ command that allows Rake to dynamically import dependendencies into a running Rake session. The +import+ command can run tasks to update the dependency file before loading them. Dependency files can be in rake or make format, allowing rake to work with tools designed to generate dependencies for make. ==== Thanks As usual, it was input from users that drove a alot of these changes. Thanks to ... * Brian Gernhardt for the rules fix (especially for the patience to explain the problem to me until I got what he was talking about). * Stefan Lang for pointing out problems in the dark corners of the FileList implementation. * Alexey Verkhovsky pointing out the silently swallows syntax errors in tests. * Tobias Luetke for beautifying the test task output. * Sam Roberts for some of the ideas behind dependency loading. -- Jim Weirich === 0.5.0 It has been a long time in coming, but we finally have a new version of Rake available. ==== Changes * Fixed documentation that was lacking the Rake module name (Tilman Sauerbeck). * Added tar.gz and tar.bz2 support to package task (Tilman Sauerbeck). * Recursive rules are now supported (Tilman Sauerbeck). * Added warning option for the Test Task (requested by Eric Hodel). * The jamis rdoc template is only used if it exists. * Added fix for Ruby 1.8.2 test/unit and rails problem. * Added contributed rake man file (Jani Monoses). * Added Brian Candler's fix for problems in --trace and --dry-run mode. ==== Thanks Lots of people provided input to this release. Thanks to Tilman Sauerbeck for numerous patches, documentation fixes and suggestions. And for also pushing me to get this release out. Also, thanks to Brian Candler for the finding and fixing --trace/dry-run fix. That was an obscure bug. Also to Eric Hodel for some good suggestions. -- Jim Weirich === 0.4.15 ==== Changes Version 0.4.15 is a bug fix update for the Ruby 1.8.2 compatibility changes. This release includes: * Fixed a bug that prevented the TESTOPTS flag from working with the revised for 1.8.2 test task. * Updated the docs on --trace to indicate that it also enables a full backtrace on errors. * Several fixes for new warnings generated. ==== Mini-Roadmap I will continue to issue Rake updates in the 0.4.xx series as new Ruby-1.8.2 issues become manifest. Once the codebase stabilizes, I will release a 0.5.0 version incorporating all the changes. If you are not using Ruby-1.8.2 and wish to avoid version churn, I recommend staying with a release prior to Rake-0.4.14. === 0.4.14 Version 0.4.14 is a compatibility fix to allow Rake's test task to work under Ruby 1.8.2. A change in the Test::Unit autorun feature prevented Rake from running any tests. This release fixes the problem. Rake 0.4.14 is the recommended release for anyone using Ruby 1.8.2. === 0.4.13 * Fixed the dry-run flag so it is operating again. * Multiple arguments to sh and ruby commands will not be interpreted by the shell (patch provided by Jonathan Paisley). === 0.4.12 * Added --silent (-s) to suppress the (in directory) rake message. === 0.4.11 * Changed the "don't know how to rake" message (finally) * Changes references to a literal "Rakefile" to reference the global variable $rakefile (which contains the actual name of the rakefile). === 0.4.10 * Added block support to the "sh" command, allowing users to take special actions on the result of the system call. E.g. sh "shell_command" do |ok, res| puts "Program returned #{res.exitstatus}" if ! ok end === 0.4.9 * Switched to Jamis Buck's RDoc template. * Removed autorequire from Rake's gem spec. This prevents the Rake libraries from loading while using rails. === 0.4.8 * Added support for .rb versions of Rakefile. * Removed \\\n's from test task. * Fixed Ruby 1.9 compatibility issue with FileList. === 0.4.7 * Fixed problem in FileList that caused Ruby 1.9 to go into infinite recursion. Since to_a was removed from Object, it does not need to added back into the list of methods to rewrite in FileList. (Thanks to Kent Sibilev for pointing this out). === 0.4.6 * Removed test version of ln in FileUtils that prevented safe_ln from using ln. === 0.4.5 * Upgraded comments in TestTask. * FileList to_s and inspect now automatically resolve pending changes. * FileList#exclude properly returns the FileList. === 0.4.4 * Fixed initialization problem with @comment. * Now using multi -r technique in TestTask. Switch Rakefile back to using the built-in test task macros because the rake runtime is no longer needed. * Added 'TEST=filename' and 'TESTOPTS=options' to the Test Task macros. * Allow a +test_files+ attribute in test tasks. This allows more flexibility in specifying test files. === 0.4.3 * Fixed Comment leakage. === 0.4.2 * Added safe_ln that falls back to a copy if a file link is not supported. * Package builder now uses safe\_ln. === 0.4.1 * Task comments are now additive, combined with "/". * Works with (soon to be released) rubygems 0.6.2 (or 0.7.0) === 0.4.0 * FileList now uses deferred loading. The file system is not searched until the first call that needs the file names. * VAR=VALUE options are now accepted on the command line and are treated like environment variables. The values may be tested in a Rakefile by referencing ENV['VAR']. * File.mtime is now used (instead of File.new().mtime). === 0.3.2.x * Removed some hidden dependencies on rubygems. Tests now will test gems only if they are installed. * Removed Sys from some example files. I believe that is that last reference to Sys outside of the contrib area. * Updated all copyright notices to include 2004. === 0.3.2 * GEM Installation now works with the application stub. === 0.3.1 * FileLists now automatically ignore CVS, .bak, ! * GEM Installation now works. === 0.3.0 Promoted 0.2.10. === 0.2.10 General * Added title to Rake's rdocs * Contrib packages are no longer included in the documentation. RDoc Issues * Removed default for the '--main' option * Fixed rendering of the rdoc options * Fixed clean/clobber confusion with rerdoc * 'title' attribute added Package Task Library Issues * Version (or explicit :noversion) is required. * +package_file+ attribute is now writable FileList Issues * Dropped bang version of exclude. Now using ant-like include/exclude semantics. * Enabled the "yield self" idiom in FileList#initialize. === 0.2.9 This version contains numerous changes as the RubyConf.new(2003) presentation was being prepared. The changes include: * The monolithic rubyapp task library is in the process of being dropped in favor of lighter weight task libraries. === 0.2.7 * Added "desc" for task descriptions. * -T will now display tasks with descriptions. * -P will display tasks and prerequisites. * Dropped the Sys module in favor of the 1.8.x FileUtils module. Sys is still supported in the contrib area. === 0.2.6 * Moved to RubyForge === 0.2.5 * Switched to standard ruby app builder. * Added no_match option to file matcher. === 0.2.4 * Fixed indir, which neglected to actually change directories. === 0.2.3 * Added rake module for a help target * Added 'for\_files' to Sys * Added a $rakefile constant * Added test for selecting proper rule with multiple targets. PK% ]U&"gems/rake-12.3.3/CONTRIBUTING.rdocnu[= Source Repository Rake is currently hosted at github. The github web page is https://github.com/ruby/rake . The public git clone URL is https://github.com/ruby/rake.git = Running the Rake Test Suite If you wish to run the unit and functional tests that come with Rake: * +cd+ into the top project directory of rake. * Install gem dependency using bundler: $ bundle install # Install bundler, minitest and rdoc * Run the test suite $ rake = Rubocop Rake uses Rubocop to enforce a consistent style on new changes being proposed. You can check your code with Rubocop using: $ ./bin/rubocop = Issues and Bug Reports Feel free to submit commits or feature requests. If you send a patch, remember to update the corresponding unit tests. In fact, I prefer new feature to be submitted in the form of new unit tests. For other information, feel free to ask on the ruby-talk mailing list. If you have found a bug in rake please try with the latest version of rake before filing an issue. Also check History.rdoc for bug fixes that may have addressed your issue. When submitting pull requests please check the rake Travis-CI page for test failures: https://travis-ci.org/ruby/rake PK% ]xgems/irb-1.0.0/exe/irbnuȯ#!/usr/bin/ruby # # irb.rb - interactive ruby # $Release Version: 0.9.6 $ # $Revision: 65963 $ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # require "irb" IRB.start(__FILE__) PK% ] gems/xmlrpc-0.3.0/LICENSE.txtnu[Ruby is copyrighted free software by Yukihiro Matsumoto . You can redistribute it and/or modify it under either the terms of the 2-clause BSDL (see the file BSDL), or the conditions below: 1. You may make and give away verbatim copies of the source form of the software without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may modify your copy of the software in any way, provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or by allowing the author to include your modifications in the software. b) use the modified software only within your corporation or organization. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 3. You may distribute the software in object code or binary form, provided that you do at least ONE of the following: a) distribute the binaries and library files of the software, together with instructions (in the manual page or equivalent) on where to get the original distribution. b) accompany the distribution with the machine-readable source of the software. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 4. You may modify and include the part of the software into any other software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under these terms. For the list of those files and their copying conditions, see the file LEGAL. 5. The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the copyright of the software, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this software. 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. PK% ]K''gems/xmlrpc-0.3.0/Gemfilenu[source 'https://rubygems.org' gemspec PK% ]n, gems/xmlrpc-0.3.0/xmlrpc.gemspecnu[# -*- encoding: utf-8 -*- # stub: xmlrpc 0.3.0 ruby lib Gem::Specification.new do |s| s.name = "xmlrpc".freeze s.version = "0.3.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["SHIBATA Hiroshi".freeze] s.bindir = "exe".freeze s.date = "2017-02-16" s.description = "XMLRPC is a lightweight protocol that enables remote procedure calls over HTTP.".freeze s.email = ["hsbt@ruby-lang.org".freeze] s.files = [".gitignore".freeze, ".travis.yml".freeze, "Gemfile".freeze, "LICENSE.txt".freeze, "README.md".freeze, "Rakefile".freeze, "bin/console".freeze, "bin/setup".freeze, "lib/xmlrpc.rb".freeze, "lib/xmlrpc/base64.rb".freeze, "lib/xmlrpc/client.rb".freeze, "lib/xmlrpc/config.rb".freeze, "lib/xmlrpc/create.rb".freeze, "lib/xmlrpc/datetime.rb".freeze, "lib/xmlrpc/marshal.rb".freeze, "lib/xmlrpc/parser.rb".freeze, "lib/xmlrpc/server.rb".freeze, "lib/xmlrpc/utils.rb".freeze, "xmlrpc.gemspec".freeze] s.homepage = "https://github.com/ruby/xmlrpc".freeze s.licenses = ["Ruby".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3".freeze) s.rubygems_version = "3.1.2".freeze s.summary = "XMLRPC is a lightweight protocol that enables remote procedure calls over HTTP.".freeze if s.respond_to? :specification_version then s.specification_version = 4 end if s.respond_to? :add_runtime_dependency then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]\Wgems/xmlrpc-0.3.0/Rakefilenu[require "bundler/gem_tasks" require "rake/testtask" Rake::TestTask.new(:test) do |t| t.libs << "test" t.libs << "lib" t.test_files = FileList['test/**/test_*.rb'] end task :default => :test PK% ]igems/xmlrpc-0.3.0/README.mdnu[# XMLRPC [![Build Status](https://travis-ci.org/ruby/xmlrpc.svg?branch=master)](https://travis-ci.org/ruby/xmlrpc) ## Overview XMLRPC is a lightweight protocol that enables remote procedure calls over HTTP. It is defined at http://www.xmlrpc.com. XMLRPC allows you to create simple distributed computing solutions that span computer languages. Its distinctive feature is its simplicity compared to other approaches like SOAP and CORBA. The Ruby standard library package 'xmlrpc' enables you to create a server that implements remote procedures and a client that calls them. Very little code is required to achieve either of these. ## Installation Add this line to your application's Gemfile: ```ruby gem 'xmlrpc' ``` And then execute: $ bundle Or install it yourself as: $ gem install xmlrpc ## Example Try the following code. It calls a standard demonstration remote procedure. ```ruby require 'xmlrpc/client' require 'pp' server = XMLRPC::Client.new2("http://xmlrpc-c.sourceforge.net/api/sample.php") result = server.call("sample.sumAndDifference", 5, 3) pp result ``` ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). ## Contributing Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/xmlrpc. ## License Released under the same term of license as Ruby. PK% ]gems/xmlrpc-0.3.0/bin/setupnu[#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' set -vx bundle install # Do any other automated setup that you need to do here PK% ]N=KKgems/xmlrpc-0.3.0/bin/consolenu[#!/usr/bin/env ruby require "bundler/setup" require "xmlrpc" # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. # (If you use this, don't forget to add pry to your Gemfile!) # require "pry" # Pry.start require "irb" IRB.start PK% ]Xgems/xmlrpc-0.3.0/lib/xmlrpc.rbnu[# frozen_string_literal: false # == Author and Copyright # # Copyright (C) 2001-2004 by Michael Neumann (mailto:mneumann@ntecs.de) # # Released under the same term of license as Ruby. # # == Overview # # XMLRPC is a lightweight protocol that enables remote procedure calls over # HTTP. It is defined at http://www.xmlrpc.com. # # XMLRPC allows you to create simple distributed computing solutions that span # computer languages. Its distinctive feature is its simplicity compared to # other approaches like SOAP and CORBA. # # The Ruby standard library package 'xmlrpc' enables you to create a server that # implements remote procedures and a client that calls them. Very little code # is required to achieve either of these. # # == Example # # Try the following code. It calls a standard demonstration remote procedure. # # require 'xmlrpc/client' # require 'pp' # # server = XMLRPC::Client.new2("http://xmlrpc-c.sourceforge.net/api/sample.php") # result = server.call("sample.sumAndDifference", 5, 3) # pp result # # == Documentation # # See http://www.ntecs.de/ruby/xmlrpc4r/. There is plenty of detail there to # use the client and implement a server. # # == Features of XMLRPC for Ruby # # * Extensions # * Introspection # * multiCall # * optionally nil values and integers larger than 32 Bit # # * Server # * Standalone XML-RPC server # * CGI-based (works with FastCGI) # * Apache mod_ruby server # * WEBrick servlet # # * Client # * synchronous/asynchronous calls # * Basic HTTP-401 Authentication # * HTTPS protocol (SSL) # # * Parsers # * REXML (XMLParser::REXMLStreamParser) # * Not compiled (pure ruby) # * See ruby standard library # * libxml (LibXMLStreamParser) # * Compiled # * See https://rubygems.org/gems/libxml-ruby/ # # * General # * possible to choose between XMLParser module (Expat wrapper) and REXML (pure Ruby) parsers # * Marshalling Ruby objects to Hashes and reconstruct them later from a Hash # * SandStorm component architecture XMLRPC::Client interface # # == Howto # # === Client # # require "xmlrpc/client" # # # Make an object to represent the XML-RPC server. # server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") # # # Call the remote server and get our result # result = server.call("sample.sumAndDifference", 5, 3) # # sum = result["sum"] # difference = result["difference"] # # puts "Sum: #{sum}, Difference: #{difference}" # # === XMLRPC::Client with XML-RPC fault-structure handling # # There are two possible ways, of handling a fault-structure: # # ==== by catching a XMLRPC::FaultException exception # # require "xmlrpc/client" # # # Make an object to represent the XML-RPC server. # server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") # # begin # # Call the remote server and get our result # result = server.call("sample.sumAndDifference", 5, 3) # # sum = result["sum"] # difference = result["difference"] # # puts "Sum: #{sum}, Difference: #{difference}" # # rescue XMLRPC::FaultException => e # puts "Error: " # puts e.faultCode # puts e.faultString # end # # ==== by calling "call2" which returns a boolean # # require "xmlrpc/client" # # # Make an object to represent the XML-RPC server. # server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") # # # Call the remote server and get our result # ok, result = server.call2("sample.sumAndDifference", 5, 3) # # if ok # sum = result["sum"] # difference = result["difference"] # # puts "Sum: #{sum}, Difference: #{difference}" # else # puts "Error: " # puts result.faultCode # puts result.faultString # end # # === Using XMLRPC::Client::Proxy # # You can create a Proxy object onto which you can call methods. This way it # looks nicer. Both forms, _call_ and _call2_ are supported through _proxy_ and # _proxy2_. You can additionally give arguments to the Proxy, which will be # given to each XML-RPC call using that Proxy. # # require "xmlrpc/client" # # # Make an object to represent the XML-RPC server. # server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") # # # Create a Proxy object # sample = server.proxy("sample") # # # Call the remote server and get our result # result = sample.sumAndDifference(5,3) # # sum = result["sum"] # difference = result["difference"] # # puts "Sum: #{sum}, Difference: #{difference}" # # === CGI-based server using XMLRPC::CGIServer # # There are also two ways to define handler, the first is # like C/PHP, the second like Java, of course both ways # can be mixed: # # ==== C/PHP-like (handler functions) # # require "xmlrpc/server" # # s = XMLRPC::CGIServer.new # # s.add_handler("sample.sumAndDifference") do |a,b| # { "sum" => a + b, "difference" => a - b } # end # # s.serve # # ==== Java-like (handler classes) # # require "xmlrpc/server" # # s = XMLRPC::CGIServer.new # # class MyHandler # def sumAndDifference(a, b) # { "sum" => a + b, "difference" => a - b } # end # end # # # NOTE: Security Hole (read below)!!! # s.add_handler("sample", MyHandler.new) # s.serve # # # To return a fault-structure you have to raise an XMLRPC::FaultException e.g.: # # raise XMLRPC::FaultException.new(3, "division by Zero") # # ===== Security Note # # From Brian Candler: # # Above code sample has an extremely nasty security hole, in that you can now call # any method of 'MyHandler' remotely, including methods inherited from Object # and Kernel! For example, in the client code, you can use # # puts server.call("sample.send","`","ls") # # (backtick being the method name for running system processes). Needless to # say, 'ls' can be replaced with something else. # # The version which binds proc objects (or the version presented below in the next section) # doesn't have this problem, but people may be tempted to use the second version because it's # so nice and 'Rubyesque'. I think it needs a big red disclaimer. # # # From Michael: # # A solution is to undef insecure methods or to use # XMLRPC::Service::PublicInstanceMethodsInterface as shown below: # # class MyHandler # def sumAndDifference(a, b) # { "sum" => a + b, "difference" => a - b } # end # end # # # ... server initialization ... # # s.add_handler(XMLRPC::iPIMethods("sample"), MyHandler.new) # # # ... # # This adds only public instance methods explicitly declared in class MyHandler # (and not those inherited from any other class). # # ==== With interface declarations # # Code sample from the book Ruby Developer's Guide: # # require "xmlrpc/server" # # class Num # INTERFACE = XMLRPC::interface("num") { # meth 'int add(int, int)', 'Add two numbers', 'add' # meth 'int div(int, int)', 'Divide two numbers' # } # # def add(a, b) a + b end # def div(a, b) a / b end # end # # # s = XMLRPC::CGIServer.new # s.add_handler(Num::INTERFACE, Num.new) # s.serve # # === Standalone XMLRPC::Server # # Same as CGI-based server, the only difference being # # server = XMLRPC::CGIServer.new # # must be changed to # # server = XMLRPC::Server.new(8080) # # if you want a server listening on port 8080. # The rest is the same. # # === Choosing a different XMLParser or XMLWriter # # The examples above all use the default parser (which is now since 1.8 # XMLParser::REXMLStreamParser) and a default XMLRPC::XMLWriter. # If you want to use a different XMLParser, then you have to call the # ParserWriterChooseMixin#set_parser method of XMLRPC::Client instances # or instances of subclasses of XMLRPC::BasicServer or by editing # xmlrpc/config.rb. # # XMLRPC::Client Example: # # # ... # server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php") # server.set_parser(XMLRPC::XMLParser::XMLParser.new) # # ... # # XMLRPC::Server Example: # # # ... # s = XMLRPC::CGIServer.new # s.set_parser(XMLRPC::XMLParser::XMLParser.new) # # ... # # # You can change the XML-writer by calling method ParserWriterChooseMixin#set_writer. module XMLRPC VERSION = "0.3.0" end PK% ]Gea a (gems/xmlrpc-0.3.0/lib/xmlrpc/datetime.rbnu[# frozen_string_literal: false # # xmlrpc/datetime.rb # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # Released under the same term of license as Ruby. # require "date" module XMLRPC # :nodoc: # This class is important to handle XMLRPC +dateTime.iso8601+ values, # correctly, because normal UNIX-dates, ie: Date, only handle dates # from year 1970 on, and ruby's native Time class handles dates without the # time component. # # XMLRPC::DateTime is able to store a XMLRPC +dateTime.iso8601+ value correctly. class DateTime # Return the value of the specified date/time component. attr_reader :year, :month, :day, :hour, :min, :sec # Set +value+ as the new date/time component. # # Raises ArgumentError if the given +value+ is out of range, or in the case # of XMLRPC::DateTime#year= if +value+ is not of type Integer. def year=(value) raise ArgumentError, "date/time out of range" unless value.is_a? Integer @year = value end # Set +value+ as the new date/time component. # # Raises an ArgumentError if the given +value+ isn't between 1 and 12. def month=(value) raise ArgumentError, "date/time out of range" unless (1..12).include? value @month = value end # Set +value+ as the new date/time component. # # Raises an ArgumentError if the given +value+ isn't between 1 and 31. def day=(value) raise ArgumentError, "date/time out of range" unless (1..31).include? value @day = value end # Set +value+ as the new date/time component. # # Raises an ArgumentError if the given +value+ isn't between 0 and 24. def hour=(value) raise ArgumentError, "date/time out of range" unless (0..24).include? value @hour = value end # Set +value+ as the new date/time component. # # Raises an ArgumentError if the given +value+ isn't between 0 and 59. def min=(value) raise ArgumentError, "date/time out of range" unless (0..59).include? value @min = value end # Set +value+ as the new date/time component. # # Raises an ArgumentError if the given +value+ isn't between 0 and 59. def sec=(value) raise ArgumentError, "date/time out of range" unless (0..59).include? value @sec = value end # Alias for XMLRPC::DateTime#month. alias mon month # Alias for XMLRPC::DateTime#month=. alias mon= month= # Creates a new XMLRPC::DateTime instance with the # parameters +year+, +month+, +day+ as date and # +hour+, +min+, +sec+ as time. # # Raises an ArgumentError if a parameter is out of range, # or if +year+ is not of the Integer type. def initialize(year, month, day, hour, min, sec) self.year, self.month, self.day = year, month, day self.hour, self.min, self.sec = hour, min, sec end # Return a Time object of the date/time which represents +self+. # # The timezone used is GMT. def to_time Time.gm(*to_a) end # Return a Date object of the date which represents +self+. # # The Date object do _not_ contain the time component (only date). def to_date Date.new(*to_a[0,3]) end # Returns all date/time components in an array. # # Returns +[year, month, day, hour, min, sec]+. def to_a [@year, @month, @day, @hour, @min, @sec] end # Returns whether or not all date/time components are an array. def ==(o) self.to_a == Array(o) rescue false end end end # module XMLRPC =begin = History $Id$ =end PK% ]-KKKK&gems/xmlrpc-0.3.0/lib/xmlrpc/client.rbnu[# frozen_string_literal: false # xmlrpc/client.rb # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # Released under the same term of license as Ruby. # # History # $Id$ # require "xmlrpc/parser" require "xmlrpc/create" require "xmlrpc/config" require "xmlrpc/utils" # ParserWriterChooseMixin require "net/http" require "uri" module XMLRPC # :nodoc: # Provides remote procedure calls to a XML-RPC server. # # After setting the connection-parameters with XMLRPC::Client.new which # creates a new XMLRPC::Client instance, you can execute a remote procedure # by sending the XMLRPC::Client#call or XMLRPC::Client#call2 # message to this new instance. # # The given parameters indicate which method to call on the remote-side and # of course the parameters for the remote procedure. # # require "xmlrpc/client" # # server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80) # begin # param = server.call("michael.add", 4, 5) # puts "4 + 5 = #{param}" # rescue XMLRPC::FaultException => e # puts "Error:" # puts e.faultCode # puts e.faultString # end # # or # # require "xmlrpc/client" # # server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80) # ok, param = server.call2("michael.add", 4, 5) # if ok then # puts "4 + 5 = #{param}" # else # puts "Error:" # puts param.faultCode # puts param.faultString # end class Client USER_AGENT = "XMLRPC::Client (Ruby #{RUBY_VERSION})" include ParserWriterChooseMixin include ParseContentType # Creates an object which represents the remote XML-RPC server on the # given +host+. If the server is CGI-based, +path+ is the # path to the CGI-script, which will be called, otherwise (in the # case of a standalone server) +path+ should be "/RPC2". # +port+ is the port on which the XML-RPC server listens. # # If +proxy_host+ is given, then a proxy server listening at # +proxy_host+ is used. +proxy_port+ is the port of the # proxy server. # # Default values for +host+, +path+ and +port+ are 'localhost', '/RPC2' and # '80' respectively using SSL '443'. # # If +user+ and +password+ are given, each time a request is sent, # an Authorization header is sent. Currently only Basic Authentication is # implemented, no Digest. # # If +use_ssl+ is set to +true+, communication over SSL is enabled. # # Parameter +timeout+ is the time to wait for a XML-RPC response, defaults to 30. def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil, user=nil, password=nil, use_ssl=nil, timeout=nil) @http_header_extra = nil @http_last_response = nil @cookie = nil @host = host || "localhost" @path = path || "/RPC2" @proxy_host = proxy_host @proxy_port = proxy_port @proxy_host ||= 'localhost' if @proxy_port != nil @proxy_port ||= 8080 if @proxy_host != nil @use_ssl = use_ssl || false @timeout = timeout || 30 if use_ssl require "net/https" @port = port || 443 else @port = port || 80 end @user, @password = user, password set_auth # convert ports to integers @port = @port.to_i if @port != nil @proxy_port = @proxy_port.to_i if @proxy_port != nil # HTTP object for synchronous calls @http = net_http(@host, @port, @proxy_host, @proxy_port) @http.use_ssl = @use_ssl if @use_ssl @http.read_timeout = @timeout @http.open_timeout = @timeout @parser = nil @create = nil end class << self # Creates an object which represents the remote XML-RPC server at the # given +uri+. The URI should have a host, port, path, user and password. # Example: https://user:password@host:port/path # # Raises an ArgumentError if the +uri+ is invalid, # or if the protocol isn't http or https. # # If a +proxy+ is given it should be in the form of "host:port". # # The optional +timeout+ defaults to 30 seconds. def new2(uri, proxy=nil, timeout=nil) begin url = URI(uri) rescue URI::InvalidURIError => e raise ArgumentError, e.message, e.backtrace end unless URI::HTTP === url raise ArgumentError, "Wrong protocol specified. Only http or https allowed!" end proto = url.scheme user = url.user passwd = url.password host = url.host port = url.port path = url.path.empty? ? nil : url.request_uri proxy_host, proxy_port = (proxy || "").split(":") proxy_port = proxy_port.to_i if proxy_port self.new(host, path, port, proxy_host, proxy_port, user, passwd, (proto == "https"), timeout) end alias new_from_uri new2 # Receives a Hash and calls XMLRPC::Client.new # with the corresponding values. # # The +hash+ parameter has following case-insensitive keys: # * host # * path # * port # * proxy_host # * proxy_port # * user # * password # * use_ssl # * timeout def new3(hash={}) # convert all keys into lowercase strings h = {} hash.each { |k,v| h[k.to_s.downcase] = v } self.new(h['host'], h['path'], h['port'], h['proxy_host'], h['proxy_port'], h['user'], h['password'], h['use_ssl'], h['timeout']) end alias new_from_hash new3 end # Returns the Net::HTTP object for the client. If you want to # change HTTP client options except header, cookie, timeout, # user and password, use Net::HTTP directly. # # Since 2.1.0. attr_reader :http # Add additional HTTP headers to the request attr_accessor :http_header_extra # Returns the Net::HTTPResponse object of the last RPC. attr_reader :http_last_response # Get and set the HTTP Cookie header. attr_accessor :cookie # Return the corresponding attributes. attr_reader :timeout, :user, :password # Sets the Net::HTTP#read_timeout and Net::HTTP#open_timeout to # +new_timeout+ def timeout=(new_timeout) @timeout = new_timeout @http.read_timeout = @timeout @http.open_timeout = @timeout end # Changes the user for the Basic Authentication header to +new_user+ def user=(new_user) @user = new_user set_auth end # Changes the password for the Basic Authentication header to # +new_password+ def password=(new_password) @password = new_password set_auth end # Invokes the method named +method+ with the parameters given by # +args+ on the XML-RPC server. # # The +method+ parameter is converted into a String and should # be a valid XML-RPC method-name. # # Each parameter of +args+ must be of one of the following types, # where Hash, Struct and Array can contain any of these listed _types_: # # * Integer # * TrueClass, FalseClass, +true+, +false+ # * String, Symbol # * Float # * Hash, Struct # * Array # * Date, Time, XMLRPC::DateTime # * XMLRPC::Base64 # * A Ruby object which class includes XMLRPC::Marshallable # (only if Config::ENABLE_MARSHALLING is +true+). # That object is converted into a hash, with one additional key/value # pair ___class___ which contains the class name # for restoring that object later. # # The method returns the return-value from the Remote Procedure Call. # # The type of the return-value is one of the types shown above. # # An Integer is only allowed when it fits in 32-bit. A XML-RPC # +dateTime.iso8601+ type is always returned as a XMLRPC::DateTime object. # Struct is never returned, only a Hash, the same for a Symbol, where as a # String is always returned. XMLRPC::Base64 is returned as a String from # xmlrpc4r version 1.6.1 on. # # If the remote procedure returned a fault-structure, then a # XMLRPC::FaultException exception is raised, which has two accessor-methods # +faultCode+ an Integer, and +faultString+ a String. def call(method, *args) ok, param = call2(method, *args) if ok param else raise param end end # The difference between this method and XMLRPC::Client#call is, that # this method will NOT raise a XMLRPC::FaultException exception. # # The method returns an array of two values. The first value indicates if # the second value is +true+ or an XMLRPC::FaultException. # # Both are explained in XMLRPC::Client#call. # # Simple to remember: The "2" in "call2" denotes the number of values it returns. def call2(method, *args) request = create().methodCall(method, *args) data = do_rpc(request, false) parser().parseMethodResponse(data) end # Similar to XMLRPC::Client#call, however can be called concurrently and # use a new connection for each request. In contrast to the corresponding # method without the +_async+ suffix, which use connect-alive (one # connection for all requests). # # Note, that you have to use Thread to call these methods concurrently. # The following example calls two methods concurrently: # # Thread.new { # p client.call_async("michael.add", 4, 5) # } # # Thread.new { # p client.call_async("michael.div", 7, 9) # } # def call_async(method, *args) ok, param = call2_async(method, *args) if ok param else raise param end end # Same as XMLRPC::Client#call2, but can be called concurrently. # # See also XMLRPC::Client#call_async def call2_async(method, *args) request = create().methodCall(method, *args) data = do_rpc(request, true) parser().parseMethodResponse(data) end # You can use this method to execute several methods on a XMLRPC server # which support the multi-call extension. # # s.multicall( # ['michael.add', 3, 4], # ['michael.sub', 4, 5] # ) # # => [7, -1] def multicall(*methods) ok, params = multicall2(*methods) if ok params else raise params end end # Same as XMLRPC::Client#multicall, but returns two parameters instead of # raising an XMLRPC::FaultException. # # See XMLRPC::Client#call2 def multicall2(*methods) gen_multicall(methods, false) end # Similar to XMLRPC::Client#multicall, however can be called concurrently and # use a new connection for each request. In contrast to the corresponding # method without the +_async+ suffix, which use connect-alive (one # connection for all requests). # # Note, that you have to use Thread to call these methods concurrently. # The following example calls two methods concurrently: # # Thread.new { # p client.multicall_async("michael.add", 4, 5) # } # # Thread.new { # p client.multicall_async("michael.div", 7, 9) # } # def multicall_async(*methods) ok, params = multicall2_async(*methods) if ok params else raise params end end # Same as XMLRPC::Client#multicall2, but can be called concurrently. # # See also XMLRPC::Client#multicall_async def multicall2_async(*methods) gen_multicall(methods, true) end # Returns an object of class XMLRPC::Client::Proxy, initialized with # +prefix+ and +args+. # # A proxy object returned by this method behaves like XMLRPC::Client#call, # i.e. a call on that object will raise a XMLRPC::FaultException when a # fault-structure is returned by that call. def proxy(prefix=nil, *args) Proxy.new(self, prefix, args, :call) end # Almost the same like XMLRPC::Client#proxy only that a call on the returned # XMLRPC::Client::Proxy object will return two parameters. # # See XMLRPC::Client#call2 def proxy2(prefix=nil, *args) Proxy.new(self, prefix, args, :call2) end # Similar to XMLRPC::Client#proxy, however can be called concurrently and # use a new connection for each request. In contrast to the corresponding # method without the +_async+ suffix, which use connect-alive (one # connection for all requests). # # Note, that you have to use Thread to call these methods concurrently. # The following example calls two methods concurrently: # # Thread.new { # p client.proxy_async("michael.add", 4, 5) # } # # Thread.new { # p client.proxy_async("michael.div", 7, 9) # } # def proxy_async(prefix=nil, *args) Proxy.new(self, prefix, args, :call_async) end # Same as XMLRPC::Client#proxy2, but can be called concurrently. # # See also XMLRPC::Client#proxy_async def proxy2_async(prefix=nil, *args) Proxy.new(self, prefix, args, :call2_async) end private def net_http(host, port, proxy_host, proxy_port) Net::HTTP.new host, port, proxy_host, proxy_port end def dup_net_http http = net_http(@http.address, @http.port, @http.proxy_address, @http.proxy_port) http.proxy_user = @http.proxy_user http.proxy_pass = @http.proxy_pass if @http.use_ssl? http.use_ssl = true Net::HTTP::SSL_ATTRIBUTES.each do |attribute| http.__send__("#{attribute}=", @http.__send__(attribute)) end end http.read_timeout = @http.read_timeout http.open_timeout = @http.open_timeout http end def set_auth if @user.nil? @auth = nil else a = "#@user" a << ":#@password" if @password != nil @auth = "Basic " + [a].pack("m0") end end def do_rpc(request, async=false) header = { "User-Agent" => USER_AGENT, "Content-Type" => "text/xml; charset=utf-8", "Content-Length" => request.bytesize.to_s, "Connection" => (async ? "close" : "keep-alive") } header["Cookie"] = @cookie if @cookie header.update(@http_header_extra) if @http_header_extra if @auth != nil # add authorization header header["Authorization"] = @auth end resp = nil @http_last_response = nil if async # use a new HTTP object for each call http = dup_net_http # post request http.start { resp = http.request_post(@path, request, header) } else # reuse the HTTP object for each call => connection alive is possible # we must start connection explicitly first time so that http.request # does not assume that we don't want keepalive @http.start if not @http.started? # post request resp = @http.request_post(@path, request, header) end @http_last_response = resp data = resp.body if resp.code == "401" # Authorization Required raise "Authorization failed.\nHTTP-Error: #{resp.code} #{resp.message}" elsif resp.code[0,1] != "2" raise "HTTP-Error: #{resp.code} #{resp.message}" end # assume text/xml on instances where Content-Type header is not set ct_expected = resp["Content-Type"] || 'text/xml' ct = parse_content_type(ct_expected).first if ct != "text/xml" if ct == "text/html" raise "Wrong content-type (received '#{ct}' but expected 'text/xml'): \n#{data}" else raise "Wrong content-type (received '#{ct}' but expected 'text/xml')" end end expected = resp["Content-Length"] || "" if data.nil? or data.bytesize == 0 raise "Wrong size. Was #{data.bytesize}, should be #{expected}" end parse_set_cookies(resp.get_fields("Set-Cookie")) return data end def parse_set_cookies(set_cookies) return if set_cookies.nil? return if set_cookies.empty? require 'webrick/cookie' pairs = {} set_cookies.each do |set_cookie| cookie = WEBrick::Cookie.parse_set_cookie(set_cookie) pairs.delete(cookie.name) pairs[cookie.name] = cookie.value end cookies = pairs.collect do |name, value| WEBrick::Cookie.new(name, value).to_s end @cookie = cookies.join("; ") end def gen_multicall(methods=[], async=false) meth = :call2 meth = :call2_async if async ok, params = self.send(meth, "system.multicall", methods.collect {|m| {'methodName' => m[0], 'params' => m[1..-1]} } ) if ok params = params.collect do |param| if param.is_a? Array param[0] elsif param.is_a? Hash XMLRPC::FaultException.new(param["faultCode"], param["faultString"]) else raise "Wrong multicall return value" end end end return ok, params end # XML-RPC calls look nicer! # # You can call any method onto objects of that class - the object handles # XMLRPC::Client::Proxy#method_missing and will forward the method call to # a XML-RPC server. # # Don't use this class directly, instead use the public instance method # XMLRPC::Client#proxy or XMLRPC::Client#proxy2. # # require "xmlrpc/client" # # server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80) # # michael = server.proxy("michael") # michael2 = server.proxy("michael", 4) # # # both calls should return the same value '9'. # p michael.add(4,5) # p michael2.add(5) class Proxy # Creates an object which provides XMLRPC::Client::Proxy#method_missing. # # The given +server+ must be an instance of XMLRPC::Client, which is the # XML-RPC server to be used for a XML-RPC call. # # +prefix+ and +delim+ will be prepended to the method name called onto this object. # # An optional parameter +meth+ is the method to use for a RPC. # It can be either, call, call2, call_async, call2_async # # +args+ are arguments which are automatically given to every XML-RPC # call before being provided through +method_missing+. def initialize(server, prefix, args=[], meth=:call, delim=".") @server = server @prefix = prefix ? prefix + delim : "" @args = args @meth = meth end # Every method call is forwarded to the XML-RPC server defined in # XMLRPC::Client::Proxy#new. # # Note: Inherited methods from class Object cannot be used as XML-RPC # names, because they get around +method_missing+. def method_missing(mid, *args) pre = @prefix + mid.to_s arg = @args + args @server.send(@meth, pre, *arg) end end # class Proxy end # class Client end # module XMLRPC PK% ]z[W(O(O&gems/xmlrpc-0.3.0/lib/xmlrpc/server.rbnu[# frozen_string_literal: false # xmlrpc/server.rb # Copyright (C) 2001, 2002, 2003, 2005 by Michael Neumann (mneumann@ntecs.de) # # Released under the same term of license as Ruby. require "xmlrpc/parser" require "xmlrpc/create" require "xmlrpc/config" require "xmlrpc/utils" # ParserWriterChooseMixin module XMLRPC # :nodoc: # This is the base class for all XML-RPC server-types (CGI, standalone). # You can add handler and set a default handler. # Do not use this server, as this is/should be an abstract class. # # === How the method to call is found # The arity (number of accepted arguments) of a handler (method or Proc # object) is compared to the given arguments submitted by the client for a # RPC, or Remote Procedure Call. # # A handler is only called if it accepts the number of arguments, otherwise # the search for another handler will go on. When at the end no handler was # found, the default_handler, XMLRPC::BasicServer#set_default_handler will be # called. # # With this technique it is possible to do overloading by number of parameters, but # only for Proc handler, because you cannot define two methods of the same name in # the same class. class BasicServer include ParserWriterChooseMixin include ParseContentType ERR_METHOD_MISSING = 1 ERR_UNCAUGHT_EXCEPTION = 2 ERR_MC_WRONG_PARAM = 3 ERR_MC_MISSING_PARAMS = 4 ERR_MC_MISSING_METHNAME = 5 ERR_MC_RECURSIVE_CALL = 6 ERR_MC_WRONG_PARAM_PARAMS = 7 ERR_MC_EXPECTED_STRUCT = 8 # Creates a new XMLRPC::BasicServer instance, which should not be # done, because XMLRPC::BasicServer is an abstract class. This # method should be called from a subclass indirectly by a +super+ call # in the initialize method. # # The parameter +class_delim+ is used by add_handler, see # XMLRPC::BasicServer#add_handler, when an object is added as a handler, to # delimit the object-prefix and the method-name. def initialize(class_delim=".") @handler = [] @default_handler = nil @service_hook = nil @class_delim = class_delim @create = nil @parser = nil add_multicall if Config::ENABLE_MULTICALL add_introspection if Config::ENABLE_INTROSPECTION end # Adds +aBlock+ to the list of handlers, with +name+ as the name of # the method. # # Parameters +signature+ and +help+ are used by the Introspection method if # specified, where +signature+ is either an Array containing strings each # representing a type of it's signature (the first is the return value) or # an Array of Arrays if the method has multiple signatures. # # Value type-names are "int, boolean, double, string, dateTime.iso8601, # base64, array, struct". # # Parameter +help+ is a String with information about how to call this method etc. # # When a method fails, it can tell the client by throwing an # XMLRPC::FaultException like in this example: # # s.add_handler("michael.div") do |a,b| # if b == 0 # raise XMLRPC::FaultException.new(1, "division by zero") # else # a / b # end # end # # In the case of b==0 the client gets an object back of type # XMLRPC::FaultException that has a +faultCode+ and +faultString+ field. # # This is the second form of (()). # To add an object write: # # server.add_handler("michael", MyHandlerClass.new) # # All public methods of MyHandlerClass are accessible to # the XML-RPC clients by michael."name of method". This is # where the +class_delim+ in XMLRPC::BasicServer.new plays it's role, a # XML-RPC method-name is defined by +prefix+ + +class_delim+ + "name # of method". # # The third form of +add_handler is to use XMLRPC::Service::Interface to # generate an object, which represents an interface (with signature and # help text) for a handler class. # # The +interface+ parameter must be an instance of XMLRPC::Service::Interface. # Adds all methods of +obj+ which are defined in the +interface+ to the server. # # This is the recommended way of adding services to a server! def add_handler(prefix, obj_or_signature=nil, help=nil, &block) if block_given? # proc-handler @handler << [prefix, block, obj_or_signature, help] else if prefix.kind_of? String # class-handler raise ArgumentError, "Expected non-nil value" if obj_or_signature.nil? @handler << [prefix + @class_delim, obj_or_signature] elsif prefix.kind_of? XMLRPC::Service::BasicInterface # class-handler with interface # add all methods @handler += prefix.get_methods(obj_or_signature, @class_delim) else raise ArgumentError, "Wrong type for parameter 'prefix'" end end self end # Returns the service-hook, which is called on each service request (RPC) # unless it's +nil+. def get_service_hook @service_hook end # A service-hook is called for each service request (RPC). # # You can use a service-hook for example to wrap existing methods and catch # exceptions of them or convert values to values recognized by XMLRPC. # # You can disable it by passing +nil+ as the +handler+ parameter. # # The service-hook is called with a Proc object along with any parameters. # # An example: # # server.set_service_hook {|obj, *args| # begin # ret = obj.call(*args) # call the original service-method # # could convert the return value # rescue # # rescue exceptions # end # } # def set_service_hook(&handler) @service_hook = handler self end # Returns the default-handler, which is called when no handler for # a method-name is found. # # It is either a Proc object or +nil+. def get_default_handler @default_handler end # Sets +handler+ as the default-handler, which is called when # no handler for a method-name is found. # # +handler+ is a code-block. # # The default-handler is called with the (XML-RPC) method-name as first # argument, and the other arguments are the parameters given by the # client-call. # # If no block is specified the default of XMLRPC::BasicServer is # used, which raises a XMLRPC::FaultException saying "method missing". def set_default_handler(&handler) @default_handler = handler self end # Adds the multi-call handler "system.multicall". def add_multicall add_handler("system.multicall", %w(array array), "Multicall Extension") do |arrStructs| unless arrStructs.is_a? Array raise XMLRPC::FaultException.new(ERR_MC_WRONG_PARAM, "system.multicall expects an array") end arrStructs.collect {|call| if call.is_a? Hash methodName = call["methodName"] params = call["params"] if params.nil? multicall_fault(ERR_MC_MISSING_PARAMS, "Missing params") elsif methodName.nil? multicall_fault(ERR_MC_MISSING_METHNAME, "Missing methodName") else if methodName == "system.multicall" multicall_fault(ERR_MC_RECURSIVE_CALL, "Recursive system.multicall forbidden") else unless params.is_a? Array multicall_fault(ERR_MC_WRONG_PARAM_PARAMS, "Parameter params have to be an Array") else ok, val = call_method(methodName, *params) if ok # correct return value [val] else # exception multicall_fault(val.faultCode, val.faultString) end end end end else multicall_fault(ERR_MC_EXPECTED_STRUCT, "system.multicall expected struct") end } end # end add_handler self end # Adds the introspection handlers "system.listMethods", # "system.methodSignature" and # "system.methodHelp", where only the first one works. def add_introspection add_handler("system.listMethods",%w(array), "List methods available on this XML-RPC server") do methods = [] @handler.each do |name, obj| if obj.kind_of? Proc methods << name else obj.class.public_instance_methods(false).each do |meth| methods << "#{name}#{meth}" end end end methods end add_handler("system.methodSignature", %w(array string), "Returns method signature") do |meth| sigs = [] @handler.each do |name, obj, sig| if obj.kind_of? Proc and sig != nil and name == meth if sig[0].kind_of? Array # sig contains multiple signatures, e.g. [["array"], ["array", "string"]] sig.each {|s| sigs << s} else # sig is a single signature, e.g. ["array"] sigs << sig end end end sigs.uniq! || sigs # remove eventually duplicated signatures end add_handler("system.methodHelp", %w(string string), "Returns help on using this method") do |meth| help = nil @handler.each do |name, obj, sig, hlp| if obj.kind_of? Proc and name == meth help = hlp break end end help || "" end self end def process(data) method, params = parser().parseMethodCall(data) handle(method, *params) end private def multicall_fault(nr, str) {"faultCode" => nr, "faultString" => str} end def dispatch(methodname, *args) for name, obj in @handler if obj.kind_of? Proc next unless methodname == name else next unless methodname =~ /^#{name}(.+)$/ next unless obj.respond_to? $1 obj = obj.method($1) end if check_arity(obj, args.size) if @service_hook.nil? return obj.call(*args) else return @service_hook.call(obj, *args) end end end if @default_handler.nil? raise XMLRPC::FaultException.new(ERR_METHOD_MISSING, "Method #{methodname} missing or wrong number of parameters!") else @default_handler.call(methodname, *args) end end # Returns +true+, if the arity of +obj+ matches +n_args+ def check_arity(obj, n_args) ary = obj.arity if ary >= 0 n_args == ary else n_args >= (ary+1).abs end end def call_method(methodname, *args) begin [true, dispatch(methodname, *args)] rescue XMLRPC::FaultException => e [false, e] rescue Exception => e [false, XMLRPC::FaultException.new(ERR_UNCAUGHT_EXCEPTION, "Uncaught exception #{e.message} in method #{methodname}")] end end def handle(methodname, *args) create().methodResponse(*call_method(methodname, *args)) end end # Implements a CGI-based XML-RPC server. # # require "xmlrpc/server" # # s = XMLRPC::CGIServer.new # # s.add_handler("michael.add") do |a,b| # a + b # end # # s.add_handler("michael.div") do |a,b| # if b == 0 # raise XMLRPC::FaultException.new(1, "division by zero") # else # a / b # end # end # # s.set_default_handler do |name, *args| # raise XMLRPC::FaultException.new(-99, "Method #{name} missing" + # " or wrong number of parameters!") # end # # s.serve # # # Note: Make sure that you don't write to standard-output in a # handler, or in any other part of your program, this would cause a CGI-based # server to fail! class CGIServer < BasicServer @@obj = nil # Creates a new XMLRPC::CGIServer instance. # # All parameters given are by-passed to XMLRPC::BasicServer.new. # # You can only create one XMLRPC::CGIServer instance, because more # than one makes no sense. def CGIServer.new(*a) @@obj = super(*a) if @@obj.nil? @@obj end def initialize(*a) super(*a) end # Call this after you have added all you handlers to the server. # # This method processes a XML-RPC method call and sends the answer # back to the client. def serve catch(:exit_serve) { length = ENV['CONTENT_LENGTH'].to_i http_error(405, "Method Not Allowed") unless ENV['REQUEST_METHOD'] == "POST" http_error(400, "Bad Request") unless parse_content_type(ENV['CONTENT_TYPE']).first == "text/xml" http_error(411, "Length Required") unless length > 0 # TODO: do we need a call to binmode? $stdin.binmode if $stdin.respond_to? :binmode data = $stdin.read(length) http_error(400, "Bad Request") if data.nil? or data.bytesize != length http_write(process(data), "Content-type" => "text/xml; charset=utf-8") } end private def http_error(status, message) err = "#{status} #{message}" msg = <<-"MSGEND" #{err}

#{err}

Unexpected error occurred while processing XML-RPC request!

MSGEND http_write(msg, "Status" => err, "Content-type" => "text/html") throw :exit_serve # exit from the #serve method end def http_write(body, header) h = {} header.each {|key, value| h[key.to_s.capitalize] = value} h['Status'] ||= "200 OK" h['Content-length'] ||= body.bytesize.to_s str = "" h.each {|key, value| str << "#{key}: #{value}\r\n"} str << "\r\n#{body}" print str end end # Implements a XML-RPC server, which works with Apache mod_ruby. # # Use it in the same way as XMLRPC::CGIServer! class ModRubyServer < BasicServer # Creates a new XMLRPC::ModRubyServer instance. # # All parameters given are by-passed to XMLRPC::BasicServer.new. def initialize(*a) @ap = Apache::request super(*a) end # Call this after you have added all you handlers to the server. # # This method processes a XML-RPC method call and sends the answer # back to the client. def serve catch(:exit_serve) { header = {} @ap.headers_in.each {|key, value| header[key.capitalize] = value} length = header['Content-length'].to_i http_error(405, "Method Not Allowed") unless @ap.request_method == "POST" http_error(400, "Bad Request") unless parse_content_type(header['Content-type']).first == "text/xml" http_error(411, "Length Required") unless length > 0 # TODO: do we need a call to binmode? @ap.binmode data = @ap.read(length) http_error(400, "Bad Request") if data.nil? or data.bytesize != length http_write(process(data), 200, "Content-type" => "text/xml; charset=utf-8") } end private def http_error(status, message) err = "#{status} #{message}" msg = <<-"MSGEND" #{err}

#{err}

Unexpected error occurred while processing XML-RPC request!

MSGEND http_write(msg, status, "Status" => err, "Content-type" => "text/html") throw :exit_serve # exit from the #serve method end def http_write(body, status, header) h = {} header.each {|key, value| h[key.to_s.capitalize] = value} h['Status'] ||= "200 OK" h['Content-length'] ||= body.bytesize.to_s h.each {|key, value| @ap.headers_out[key] = value } @ap.content_type = h["Content-type"] @ap.status = status.to_i @ap.send_http_header @ap.print body end end class WEBrickServlet < BasicServer; end # forward declaration # Implements a standalone XML-RPC server. The method XMLRPC::Server#serve is # left if a SIGHUP is sent to the program. # # require "xmlrpc/server" # # s = XMLRPC::Server.new(8080) # # s.add_handler("michael.add") do |a,b| # a + b # end # # s.add_handler("michael.div") do |a,b| # if b == 0 # raise XMLRPC::FaultException.new(1, "division by zero") # else # a / b # end # end # # s.set_default_handler do |name, *args| # raise XMLRPC::FaultException.new(-99, "Method #{name} missing" + # " or wrong number of parameters!") # end # # s.serve class Server < WEBrickServlet # Creates a new XMLRPC::Server instance, which is a XML-RPC server # listening on the given +port+ and accepts requests for the given +host+, # which is +localhost+ by default. # # The server is not started, to start it you have to call # XMLRPC::Server#serve. # # The optional +audit+ and +debug+ parameters are obsolete! # # All additionally provided parameters in *a are by-passed to # XMLRPC::BasicServer.new. def initialize(port=8080, host="127.0.0.1", maxConnections=4, stdlog=$stdout, audit=true, debug=true, *a) super(*a) require 'webrick' @server = WEBrick::HTTPServer.new(:Port => port, :BindAddress => host, :MaxClients => maxConnections, :Logger => WEBrick::Log.new(stdlog)) @server.mount("/", self) end # Call this after you have added all you handlers to the server. # This method starts the server to listen for XML-RPC requests and answer them. def serve signals = %w[INT TERM HUP] & Signal.list.keys signals.each { |signal| trap(signal) { @server.shutdown } } @server.start end # Stops and shuts the server down. def shutdown @server.shutdown end end # Implements a servlet for use with WEBrick, a pure Ruby (HTTP) server # framework. # # require "webrick" # require "xmlrpc/server" # # s = XMLRPC::WEBrickServlet.new # s.add_handler("michael.add") do |a,b| # a + b # end # # s.add_handler("michael.div") do |a,b| # if b == 0 # raise XMLRPC::FaultException.new(1, "division by zero") # else # a / b # end # end # # s.set_default_handler do |name, *args| # raise XMLRPC::FaultException.new(-99, "Method #{name} missing" + # " or wrong number of parameters!") # end # # httpserver = WEBrick::HTTPServer.new(:Port => 8080) # httpserver.mount("/RPC2", s) # trap("HUP") { httpserver.shutdown } # use 1 instead of "HUP" on Windows # httpserver.start class WEBrickServlet < BasicServer def initialize(*a) super require "webrick/httpstatus" @valid_ip = nil end # Deprecated from WEBrick/1.2.2, but does not break anything. def require_path_info? false end def get_instance(config, *options) # TODO: set config & options self end # Specifies the valid IP addresses that are allowed to connect to the server. # # Each IP is either a String or a Regexp. def set_valid_ip(*ip_addr) if ip_addr.size == 1 and ip_addr[0].nil? @valid_ip = nil else @valid_ip = ip_addr end end # Return the valid IP addresses that are allowed to connect to the server. # # See also, XMLRPC::Server#set_valid_ip def get_valid_ip @valid_ip end def service(request, response) if @valid_ip raise WEBrick::HTTPStatus::Forbidden unless @valid_ip.any? { |ip| request.peeraddr[3] =~ ip } end if request.request_method != "POST" raise WEBrick::HTTPStatus::MethodNotAllowed, "unsupported method `#{request.request_method}'." end if parse_content_type(request['Content-type']).first != "text/xml" raise WEBrick::HTTPStatus::BadRequest end length = (request['Content-length'] || 0).to_i raise WEBrick::HTTPStatus::LengthRequired unless length > 0 data = request.body if data.nil? or data.bytesize != length raise WEBrick::HTTPStatus::BadRequest end resp = process(data) if resp.nil? or resp.bytesize <= 0 raise WEBrick::HTTPStatus::InternalServerError end response.status = 200 response['Content-Length'] = resp.bytesize response['Content-Type'] = "text/xml; charset=utf-8" response.body = resp end end end # module XMLRPC =begin = History $Id$ =end PK% ] T==&gems/xmlrpc-0.3.0/lib/xmlrpc/parser.rbnu[# frozen_string_literal: false # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # $Id$ # require "date" require "xmlrpc/base64" require "xmlrpc/datetime" module XMLRPC # :nodoc: # Raised when the remote procedure returns a fault-structure, which has two # accessor-methods +faultCode+ an Integer, and +faultString+ a String. class FaultException < StandardError attr_reader :faultCode, :faultString # Creates a new XMLRPC::FaultException instance. # # +faultString+ is passed to StandardError as the +msg+ of the Exception. def initialize(faultCode, faultString) @faultCode = faultCode @faultString = faultString super(@faultString) end # The +faultCode+ and +faultString+ of the exception in a Hash. def to_h {"faultCode" => @faultCode, "faultString" => @faultString} end end # Helper class used to convert types. module Convert # Converts a String to an Integer # # See also String.to_i def self.int(str) str.to_i end # Converts a String to +true+ or +false+ # # Raises an exception if +str+ is not +0+ or +1+ def self.boolean(str) case str when "0" then false when "1" then true else raise "RPC-value of type boolean is wrong" end end # Converts a String to a Float # # See also String.to_f def self.double(str) str.to_f end # Converts a the given +str+ to a +dateTime.iso8601+ formatted date. # # Raises an exception if the String isn't in +dateTime.iso8601+ format. # # See also, XMLRPC::DateTime def self.dateTime(str) case str when /^(-?\d\d\d\d)-?(\d\d)-?(\d\d)T(\d\d):(\d\d):(\d\d)(?:Z|([+-])(\d\d):?(\d\d))?$/ a = [$1, $2, $3, $4, $5, $6].collect{|i| i.to_i} if $7 ofs = $8.to_i*3600 + $9.to_i*60 ofs = -ofs if $7=='+' utc = Time.utc(*a) + ofs a = [ utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec ] end XMLRPC::DateTime.new(*a) when /^(-?\d\d)-?(\d\d)-?(\d\d)T(\d\d):(\d\d):(\d\d)(Z|([+-]\d\d):(\d\d))?$/ a = [$1, $2, $3, $4, $5, $6].collect{|i| i.to_i} if a[0] < 70 a[0] += 2000 else a[0] += 1900 end if $7 ofs = $8.to_i*3600 + $9.to_i*60 ofs = -ofs if $7=='+' utc = Time.utc(*a) + ofs a = [ utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec ] end XMLRPC::DateTime.new(*a) else raise "wrong dateTime.iso8601 format " + str end end # Decodes the given +str+ using XMLRPC::Base64.decode def self.base64(str) XMLRPC::Base64.decode(str) end # Converts the given +hash+ to a marshalled object. # # Returns the given +hash+ if an exception occurs. def self.struct(hash) # convert to marshalled object klass = hash["___class___"] if klass.nil? or Config::ENABLE_MARSHALLING == false hash else begin mod = Module klass.split("::").each {|const| mod = mod.const_get(const.strip)} obj = mod.allocate hash.delete "___class___" hash.each {|key, value| obj.instance_variable_set("@#{ key }", value) if key =~ /^([a-zA-Z_]\w*)$/ } obj rescue hash end end end # Converts the given +hash+ to an XMLRPC::FaultException object by passing # the +faultCode+ and +faultString+ attributes of the Hash to # XMLRPC::FaultException.new # # Raises an Exception if the given +hash+ doesn't meet the requirements. # Those requirements being: # * 2 keys # * 'faultCode' key is an Integer # * 'faultString' key is a String def self.fault(hash) if hash.kind_of? Hash and hash.size == 2 and hash.has_key? "faultCode" and hash.has_key? "faultString" and hash["faultCode"].kind_of? Integer and hash["faultString"].kind_of? String XMLRPC::FaultException.new(hash["faultCode"], hash["faultString"]) else raise "wrong fault-structure: #{hash.inspect}" end end end # module Convert # Parser for XML-RPC call and response module XMLParser class AbstractTreeParser def parseMethodResponse(str) methodResponse_document(createCleanedTree(str)) end def parseMethodCall(str) methodCall_document(createCleanedTree(str)) end private # Removes all whitespaces but in the tags i4, i8, int, boolean.... # and all comments def removeWhitespacesAndComments(node) remove = [] childs = node.childNodes.to_a childs.each do |nd| case _nodeType(nd) when :TEXT # TODO: add nil? unless %w(i4 i8 int boolean string double dateTime.iso8601 base64).include? node.nodeName if node.nodeName == "value" if not node.childNodes.to_a.detect {|n| _nodeType(n) == :ELEMENT}.nil? remove << nd if nd.nodeValue.strip == "" end else remove << nd if nd.nodeValue.strip == "" end end when :COMMENT remove << nd else removeWhitespacesAndComments(nd) end end remove.each { |i| node.removeChild(i) } end def nodeMustBe(node, name) cmp = case name when Array name.include?(node.nodeName) when String name == node.nodeName else raise "error" end if not cmp then raise "wrong xml-rpc (name)" end node end # Returns, when successfully the only child-node def hasOnlyOneChild(node, name=nil) if node.childNodes.to_a.size != 1 raise "wrong xml-rpc (size)" end if name != nil then nodeMustBe(node.firstChild, name) end end def assert(b) if not b then raise "assert-fail" end end # The node `node` has empty string or string def text_zero_one(node) nodes = node.childNodes.to_a.size if nodes == 1 text(node.firstChild) elsif nodes == 0 "" else raise "wrong xml-rpc (size)" end end def integer(node) #TODO: check string for float because to_i returnsa # 0 when wrong string nodeMustBe(node, %w(i4 i8 int)) hasOnlyOneChild(node) Convert.int(text(node.firstChild)) end def boolean(node) nodeMustBe(node, "boolean") hasOnlyOneChild(node) Convert.boolean(text(node.firstChild)) end def v_nil(node) nodeMustBe(node, "nil") assert( node.childNodes.to_a.size == 0 ) nil end def string(node) nodeMustBe(node, "string") text_zero_one(node) end def double(node) #TODO: check string for float because to_f returnsa # 0.0 when wrong string nodeMustBe(node, "double") hasOnlyOneChild(node) Convert.double(text(node.firstChild)) end def dateTime(node) nodeMustBe(node, "dateTime.iso8601") hasOnlyOneChild(node) Convert.dateTime( text(node.firstChild) ) end def base64(node) nodeMustBe(node, "base64") #hasOnlyOneChild(node) Convert.base64(text_zero_one(node)) end def member(node) nodeMustBe(node, "member") assert( node.childNodes.to_a.size == 2 ) [ name(node[0]), value(node[1]) ] end def name(node) nodeMustBe(node, "name") #hasOnlyOneChild(node) text_zero_one(node) end def array(node) nodeMustBe(node, "array") hasOnlyOneChild(node, "data") data(node.firstChild) end def data(node) nodeMustBe(node, "data") node.childNodes.to_a.collect do |val| value(val) end end def param(node) nodeMustBe(node, "param") hasOnlyOneChild(node, "value") value(node.firstChild) end def methodResponse(node) nodeMustBe(node, "methodResponse") hasOnlyOneChild(node, %w(params fault)) child = node.firstChild case child.nodeName when "params" [ true, params(child,false) ] when "fault" [ false, fault(child) ] else raise "unexpected error" end end def methodName(node) nodeMustBe(node, "methodName") hasOnlyOneChild(node) text(node.firstChild) end def params(node, call=true) nodeMustBe(node, "params") if call node.childNodes.to_a.collect do |n| param(n) end else # response (only one param) hasOnlyOneChild(node) param(node.firstChild) end end def fault(node) nodeMustBe(node, "fault") hasOnlyOneChild(node, "value") f = value(node.firstChild) Convert.fault(f) end # _nodeType is defined in the subclass def text(node) assert( _nodeType(node) == :TEXT ) assert( node.hasChildNodes == false ) assert( node.nodeValue != nil ) node.nodeValue.to_s end def struct(node) nodeMustBe(node, "struct") hash = {} node.childNodes.to_a.each do |me| n, v = member(me) hash[n] = v end Convert.struct(hash) end def value(node) nodeMustBe(node, "value") nodes = node.childNodes.to_a.size if nodes == 0 return "" elsif nodes > 1 raise "wrong xml-rpc (size)" end child = node.firstChild case _nodeType(child) when :TEXT text_zero_one(node) when :ELEMENT case child.nodeName when "i4", "i8", "int" then integer(child) when "boolean" then boolean(child) when "string" then string(child) when "double" then double(child) when "dateTime.iso8601" then dateTime(child) when "base64" then base64(child) when "struct" then struct(child) when "array" then array(child) when "nil" if Config::ENABLE_NIL_PARSER v_nil(child) else raise "wrong/unknown XML-RPC type 'nil'" end else raise "wrong/unknown XML-RPC type" end else raise "wrong type of node" end end def methodCall(node) nodeMustBe(node, "methodCall") assert( (1..2).include?( node.childNodes.to_a.size ) ) name = methodName(node[0]) if node.childNodes.to_a.size == 2 then pa = params(node[1]) else # no parameters given pa = [] end [name, pa] end end # module TreeParserMixin class AbstractStreamParser def parseMethodResponse(str) parser = @parser_class.new parser.parse(str) raise "No valid method response!" if parser.method_name != nil if parser.fault != nil # is a fault structure [false, parser.fault] else # is a normal return value raise "Missing return value!" if parser.params.size == 0 raise "Too many return values. Only one allowed!" if parser.params.size > 1 [true, parser.params[0]] end end def parseMethodCall(str) parser = @parser_class.new parser.parse(str) raise "No valid method call - missing method name!" if parser.method_name.nil? [parser.method_name, parser.params] end end module StreamParserMixin attr_reader :params attr_reader :method_name attr_reader :fault def initialize(*a) super(*a) @params = [] @values = [] @val_stack = [] @names = [] @name = [] @structs = [] @struct = {} @method_name = nil @fault = nil @data = nil end def startElement(name, attrs=[]) @data = nil case name when "value" @value = nil when "nil" raise "wrong/unknown XML-RPC type 'nil'" unless Config::ENABLE_NIL_PARSER @value = :nil when "array" @val_stack << @values @values = [] when "struct" @names << @name @name = [] @structs << @struct @struct = {} end end def endElement(name) @data ||= "" case name when "string" @value = @data when "i4", "i8", "int" @value = Convert.int(@data) when "boolean" @value = Convert.boolean(@data) when "double" @value = Convert.double(@data) when "dateTime.iso8601" @value = Convert.dateTime(@data) when "base64" @value = Convert.base64(@data) when "value" @value = @data if @value.nil? @values << (@value == :nil ? nil : @value) when "array" @value = @values @values = @val_stack.pop when "struct" @value = Convert.struct(@struct) @name = @names.pop @struct = @structs.pop when "name" @name[0] = @data when "member" @struct[@name[0]] = @values.pop when "param" @params << @values[0] @values = [] when "fault" @fault = Convert.fault(@values[0]) when "methodName" @method_name = @data end @data = nil end def character(data) if @data @data << data else @data = data end end end # module StreamParserMixin class REXMLStreamParser < AbstractStreamParser def initialize require "rexml/document" @parser_class = StreamListener end class StreamListener include StreamParserMixin alias :tag_start :startElement alias :tag_end :endElement alias :text :character alias :cdata :character def method_missing(*a) # ignore end def parse(str) REXML::Document.parse_stream(str, self) end end end class LibXMLStreamParser < AbstractStreamParser def initialize require 'libxml' @parser_class = LibXMLStreamListener end class LibXMLStreamListener include StreamParserMixin def on_start_element_ns(name, attributes, prefix, uri, namespaces) startElement(name) end def on_end_element_ns(name, prefix, uri) endElement(name) end alias :on_characters :character alias :on_cdata_block :character def method_missing(*a) end def parse(str) parser = LibXML::XML::SaxParser.string(str) parser.callbacks = self parser.parse() end end end Classes = [REXMLStreamParser, LibXMLStreamParser] # yields an instance of each installed parser def self.each_installed_parser XMLRPC::XMLParser::Classes.each do |klass| begin yield klass.new rescue LoadError end end end end # module XMLParser end # module XMLRPC PK% ]HB%gems/xmlrpc-0.3.0/lib/xmlrpc/utils.rbnu[# frozen_string_literal: false # # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # $Id$ # module XMLRPC # :nodoc: # This module enables a user-class to be marshalled # by XML-RPC for Ruby into a Hash, with one additional # key/value pair ___class___ => ClassName # module Marshallable end # Defines ParserWriterChooseMixin, which makes it possible to choose a # different XMLWriter and/or XMLParser then the default one. # # The Mixin is used in client.rb (class XMLRPC::Client) # and server.rb (class XMLRPC::BasicServer) module ParserWriterChooseMixin # Sets the XMLWriter to use for generating XML output. # # Should be an instance of a class from module XMLRPC::XMLWriter. # # If this method is not called, then XMLRPC::Config::DEFAULT_WRITER is used. def set_writer(writer) @create = Create.new(writer) self end # Sets the XMLParser to use for parsing XML documents. # # Should be an instance of a class from module XMLRPC::XMLParser. # # If this method is not called, then XMLRPC::Config::DEFAULT_PARSER is used. def set_parser(parser) @parser = parser self end private def create # if set_writer was not already called then call it now if @create.nil? then set_writer(Config::DEFAULT_WRITER.new) end @create end def parser # if set_parser was not already called then call it now if @parser.nil? then set_parser(Config::DEFAULT_PARSER.new) end @parser end end # module ParserWriterChooseMixin module Service # Base class for XMLRPC::Service::Interface definitions, used # by XMLRPC::BasicServer#add_handler class BasicInterface attr_reader :prefix, :methods def initialize(prefix) @prefix = prefix @methods = [] end def add_method(sig, help=nil, meth_name=nil) mname = nil sig = [sig] if sig.kind_of? String sig = sig.collect do |s| name, si = parse_sig(s) raise "Wrong signatures!" if mname != nil and name != mname mname = name si end @methods << [mname, meth_name || mname, sig, help] end private def parse_sig(sig) # sig is a String if sig =~ /^\s*(\w+)\s+([^(]+)(\(([^)]*)\))?\s*$/ params = [$1] name = $2.strip $4.split(",").each {|i| params << i.strip} if $4 != nil return name, params else raise "Syntax error in signature" end end end # class BasicInterface # # Class which wraps a XMLRPC::Service::Interface definition, used # by XMLRPC::BasicServer#add_handler # class Interface < BasicInterface def initialize(prefix, &p) raise "No interface specified" if p.nil? super(prefix) instance_eval(&p) end def get_methods(obj, delim=".") prefix = @prefix + delim @methods.collect { |name, meth, sig, help| [prefix + name.to_s, obj.method(meth).to_proc, sig, help] } end private def meth(*a) add_method(*a) end end # class Interface class PublicInstanceMethodsInterface < BasicInterface def initialize(prefix) super(prefix) end def get_methods(obj, delim=".") prefix = @prefix + delim obj.class.public_instance_methods(false).collect { |name| [prefix + name.to_s, obj.method(name).to_proc, nil, nil] } end end end # module Service # # Short-form to create a XMLRPC::Service::Interface # def self.interface(prefix, &p) Service::Interface.new(prefix, &p) end # Short-cut for creating a XMLRPC::Service::PublicInstanceMethodsInterface def self.iPIMethods(prefix) Service::PublicInstanceMethodsInterface.new(prefix) end module ParseContentType def parse_content_type(str) a, *b = str.split(";") return a.strip.downcase, *b end end end # module XMLRPC PK% ]*#&gems/xmlrpc-0.3.0/lib/xmlrpc/create.rbnu[# frozen_string_literal: false # # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # $Id$ # require "date" require "xmlrpc/base64" module XMLRPC # :nodoc: module XMLWriter class Abstract def ele(name, *children) element(name, nil, *children) end def tag(name, txt) element(name, nil, text(txt)) end end class Simple < Abstract def document_to_str(doc) doc end def document(*params) params.join("") end def pi(name, *params) "" end def element(name, attrs, *children) raise "attributes not yet implemented" unless attrs.nil? if children.empty? "<#{name}/>" else "<#{name}>" + children.join("") + "" end end def text(txt) cleaned = txt.dup cleaned.gsub!(/&/, '&') cleaned.gsub!(//, '>') cleaned end end # class Simple class XMLParser < Abstract def initialize require "xmltreebuilder" end def document_to_str(doc) doc.to_s end def document(*params) XML::SimpleTree::Document.new(*params) end def pi(name, *params) XML::SimpleTree::ProcessingInstruction.new(name, *params) end def element(name, attrs, *children) XML::SimpleTree::Element.new(name, attrs, *children) end def text(txt) XML::SimpleTree::Text.new(txt) end end # class XMLParser Classes = [Simple, XMLParser] # yields an instance of each installed XML writer def self.each_installed_writer XMLRPC::XMLWriter::Classes.each do |klass| begin yield klass.new rescue LoadError end end end end # module XMLWriter # Creates XML-RPC call/response documents # class Create def initialize(xml_writer = nil) @writer = xml_writer || Config::DEFAULT_WRITER.new end def methodCall(name, *params) name = name.to_s if name !~ /[a-zA-Z0-9_.:\/]+/ raise ArgumentError, "Wrong XML-RPC method-name" end parameter = params.collect do |param| @writer.ele("param", conv2value(param)) end tree = @writer.document( @writer.pi("xml", 'version="1.0"'), @writer.ele("methodCall", @writer.tag("methodName", name), @writer.ele("params", *parameter) ) ) @writer.document_to_str(tree) + "\n" end # # Generates a XML-RPC methodResponse document # # When +is_ret+ is +false+ then the +params+ array must # contain only one element, which is a structure # of a fault return-value. # # When +is_ret+ is +true+ then a normal # return-value of all the given +params+ is created. # def methodResponse(is_ret, *params) if is_ret resp = params.collect do |param| @writer.ele("param", conv2value(param)) end resp = [@writer.ele("params", *resp)] else if params.size != 1 or params[0] === XMLRPC::FaultException raise ArgumentError, "no valid fault-structure given" end resp = @writer.ele("fault", conv2value(params[0].to_h)) end tree = @writer.document( @writer.pi("xml", 'version="1.0"'), @writer.ele("methodResponse", resp) ) @writer.document_to_str(tree) + "\n" end private # # Converts a Ruby object into a XML-RPC tag # def conv2value(param) # :doc: val = case param when Integer # XML-RPC's int is 32bit int if Config::ENABLE_BIGINT @writer.tag("i4", param.to_s) else if param >= -(2**31) and param <= (2**31-1) @writer.tag("i4", param.to_s) else raise "Integer is too big! Must be signed 32-bit integer!" end end when TrueClass, FalseClass @writer.tag("boolean", param ? "1" : "0") when Symbol @writer.tag("string", param.to_s) when String @writer.tag("string", param) when NilClass if Config::ENABLE_NIL_CREATE @writer.ele("nil") else raise "Wrong type NilClass. Not allowed!" end when Float raise "Wrong value #{param}. Not allowed!" unless param.finite? @writer.tag("double", param.to_s) when Struct h = param.members.collect do |key| value = param[key] @writer.ele("member", @writer.tag("name", key.to_s), conv2value(value) ) end @writer.ele("struct", *h) when Hash # TODO: can a Hash be empty? h = param.collect do |key, value| @writer.ele("member", @writer.tag("name", key.to_s), conv2value(value) ) end @writer.ele("struct", *h) when Array # TODO: can an Array be empty? a = param.collect {|v| conv2value(v) } @writer.ele("array", @writer.ele("data", *a) ) when Time, Date, ::DateTime @writer.tag("dateTime.iso8601", param.strftime("%Y%m%dT%H:%M:%S")) when XMLRPC::DateTime @writer.tag("dateTime.iso8601", format("%.4d%02d%02dT%02d:%02d:%02d", *param.to_a)) when XMLRPC::Base64 @writer.tag("base64", param.encoded) else if Config::ENABLE_MARSHALLING and param.class.included_modules.include? XMLRPC::Marshallable # convert Ruby object into Hash ret = {"___class___" => param.class.name} param.instance_variables.each {|v| name = v[1..-1] val = param.instance_variable_get(v) if val.nil? ret[name] = val if Config::ENABLE_NIL_CREATE else ret[name] = val end } return conv2value(ret) else ok, pa = wrong_type(param) if ok return conv2value(pa) else raise "Wrong type!" end end end @writer.ele("value", val) end def wrong_type(value) false end end # class Create end # module XMLRPC PK% ]N W'gems/xmlrpc-0.3.0/lib/xmlrpc/marshal.rbnu[# frozen_string_literal: false # # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # $Id$ # require "xmlrpc/parser" require "xmlrpc/create" require "xmlrpc/config" require "xmlrpc/utils" module XMLRPC # :nodoc: # Marshalling of XMLRPC::Create#methodCall and XMLRPC::Create#methodResponse class Marshal include ParserWriterChooseMixin class << self def dump_call( methodName, *params ) new.dump_call( methodName, *params ) end def dump_response( param ) new.dump_response( param ) end def load_call( stringOrReadable ) new.load_call( stringOrReadable ) end def load_response( stringOrReadable ) new.load_response( stringOrReadable ) end alias dump dump_response alias load load_response end # class self def initialize( parser = nil, writer = nil ) set_parser( parser ) set_writer( writer ) end def dump_call( methodName, *params ) create.methodCall( methodName, *params ) end def dump_response( param ) create.methodResponse( ! param.kind_of?( XMLRPC::FaultException ) , param ) end # Returns [ methodname, params ] def load_call( stringOrReadable ) parser.parseMethodCall( stringOrReadable ) end # Returns +paramOrFault+ def load_response( stringOrReadable ) parser.parseMethodResponse( stringOrReadable )[1] end end # class Marshal end PK% ]T&gems/xmlrpc-0.3.0/lib/xmlrpc/base64.rbnu[# frozen_string_literal: false # # xmlrpc/base64.rb # Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de) # # Released under the same term of license as Ruby. module XMLRPC # :nodoc: # This class is necessary for 'xmlrpc4r' to determine that a string should # be transmitted base64-encoded and not as a raw-string. # # You can use XMLRPC::Base64 on the client and server-side as a # parameter and/or return-value. class Base64 # Creates a new XMLRPC::Base64 instance with string +str+ as the # internal string. When +state+ is +:dec+ it assumes that the # string +str+ is not in base64 format (perhaps already decoded), # otherwise if +state+ is +:enc+ it decodes +str+ # and stores it as the internal string. def initialize(str, state = :dec) case state when :enc @str = Base64.decode(str) when :dec @str = str else raise ArgumentError, "wrong argument; either :enc or :dec" end end # Returns the decoded internal string. def decoded @str end # Returns the base64 encoded internal string. def encoded Base64.encode(@str) end # Decodes string +str+ with base64 and returns that value. def Base64.decode(str) str.gsub(/\s+/, "").unpack("m")[0] end # Encodes string +str+ with base64 and returns that value. def Base64.encode(str) [str].pack("m") end end end # module XMLRPC =begin = History $Id$ =end PK% ]799&gems/xmlrpc-0.3.0/lib/xmlrpc/config.rbnu[# frozen_string_literal: false # # $Id$ # Configuration file for XML-RPC for Ruby # module XMLRPC # :nodoc: module Config # or XMLWriter::XMLParser DEFAULT_WRITER = XMLWriter::Simple # === Available parsers # # * XMLParser::REXMLStreamParser # * XMLParser::LibXMLStreamParser DEFAULT_PARSER = XMLParser::REXMLStreamParser # enable tag ENABLE_NIL_CREATE = false ENABLE_NIL_PARSER = false # allows integers greater than 32-bit if +true+ ENABLE_BIGINT = false # enable marshalling Ruby objects which include XMLRPC::Marshallable ENABLE_MARSHALLING = true # enable multiCall extension by default ENABLE_MULTICALL = false # enable Introspection extension by default ENABLE_INTROSPECTION = false end end PK% ]/gems/ruby-lsapi-5.6/ext/lsapi/.sitearchdir.timenu[PK% ]Y//(gems/ruby-lsapi-5.6/ext/lsapi/lsapilib.hnu[/* Copyright (c) 2002-2018, Lite Speed Technologies Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Lite Speed Technologies Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _LSAPILIB_H_ #define _LSAPILIB_H_ #if defined (c_plusplus) || defined (__cplusplus) extern "C" { #endif #include "lsapidef.h" #include #include #include struct LSAPI_key_value_pair { char * pKey; char * pValue; int keyLen; int valLen; }; struct lsapi_child_status; #define LSAPI_MAX_RESP_HEADERS 1000 typedef struct lsapi_request { int m_fdListen; int m_fd; long m_lLastActive; long m_lReqBegin; char * m_pReqBuf; int m_reqBufSize; char * m_pRespBuf; char * m_pRespBufEnd; char * m_pRespBufPos; char * m_pRespHeaderBuf; char * m_pRespHeaderBufEnd; char * m_pRespHeaderBufPos; struct lsapi_child_status * child_status; struct iovec * m_pIovec; struct iovec * m_pIovecEnd; struct iovec * m_pIovecCur; struct iovec * m_pIovecToWrite; struct lsapi_packet_header * m_respPktHeaderEnd; struct lsapi_req_header * m_pHeader; struct LSAPI_key_value_pair * m_pEnvList; struct LSAPI_key_value_pair * m_pSpecialEnvList; int m_envListSize; int m_specialEnvListSize; struct lsapi_http_header_index * m_pHeaderIndex; struct lsapi_header_offset * m_pUnknownHeader; char * m_pScriptFile; char * m_pScriptName; char * m_pQueryString; char * m_pHttpHeader; char * m_pRequestMethod; int m_totalLen; int m_reqState; off_t m_reqBodyLen; off_t m_reqBodyRead; int m_bufProcessed; int m_bufRead; struct lsapi_packet_header m_respPktHeader[5]; struct lsapi_resp_header m_respHeader; short m_respHeaderLen[LSAPI_MAX_RESP_HEADERS]; void * m_pAppData; }LSAPI_Request; extern LSAPI_Request g_req; /* return: >0 continue, ==0 stop, -1 failed */ typedef int (*LSAPI_CB_EnvHandler )( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ); int LSAPI_Init(void); void LSAPI_Stop(void); int LSAPI_Is_Listen_r( LSAPI_Request * pReq); int LSAPI_InitRequest( LSAPI_Request * pReq, int fd ); int LSAPI_Accept_r( LSAPI_Request * pReq ); void LSAPI_Reset_r( LSAPI_Request * pReq ); int LSAPI_Finish_r( LSAPI_Request * pReq ); int LSAPI_Release_r( LSAPI_Request * pReq ); char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex ); int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); int LSAPI_ForeachEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name ); ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t len ); int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq ); int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF ); int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq ); ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ); ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size ); ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len ); int LSAPI_Flush_r( LSAPI_Request * pReq ); int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len ); int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, const char * pHeaderValue ); int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders, const char * pBody, int bodyLen ); static inline int LSAPI_SetRespStatus_r( LSAPI_Request * pReq, int code ) { if ( !pReq ) return -1; pReq->m_respHeader.m_respInfo.m_status = code; return 0; } static inline int LSAPI_SetAppData_r( LSAPI_Request * pReq, void * data ) { if ( !pReq ) return -1; pReq->m_pAppData = data; return 0; } static inline void * LSAPI_GetAppData_r( LSAPI_Request * pReq ) { if ( !pReq ) return NULL; return pReq->m_pAppData; } static inline char * LSAPI_GetQueryString_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_pQueryString; return NULL; } static inline char * LSAPI_GetScriptFileName_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_pScriptFile; return NULL; } static inline char * LSAPI_GetScriptName_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_pScriptName; return NULL; } static inline char * LSAPI_GetRequestMethod_r( LSAPI_Request * pReq) { if ( pReq ) return pReq->m_pRequestMethod; return NULL; } static inline off_t LSAPI_GetReqBodyLen_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_reqBodyLen; return -1; } static inline off_t LSAPI_GetReqBodyRemain_r( LSAPI_Request * pReq ) { if ( pReq ) return pReq->m_reqBodyLen - pReq->m_reqBodyRead; return -1; } int LSAPI_End_Response_r(LSAPI_Request * pReq); int LSAPI_Is_Listen(void); static inline int LSAPI_Accept( void ) { return LSAPI_Accept_r( &g_req ); } static inline int LSAPI_Finish(void) { return LSAPI_Finish_r( &g_req ); } static inline char * LSAPI_GetHeader( int headerIndex ) { return LSAPI_GetHeader_r( &g_req, headerIndex ); } static inline int LSAPI_ForeachHeader( LSAPI_CB_EnvHandler fn, void * arg ) { return LSAPI_ForeachHeader_r( &g_req, fn, arg ); } static inline int LSAPI_ForeachOrgHeader( LSAPI_CB_EnvHandler fn, void * arg ) { return LSAPI_ForeachOrgHeader_r( &g_req, fn, arg ); } static inline int LSAPI_ForeachEnv( LSAPI_CB_EnvHandler fn, void * arg ) { return LSAPI_ForeachEnv_r( &g_req, fn, arg ); } static inline int LSAPI_ForeachSpecialEnv( LSAPI_CB_EnvHandler fn, void * arg ) { return LSAPI_ForeachSpecialEnv_r( &g_req, fn, arg ); } static inline char * LSAPI_GetEnv( const char * name ) { return LSAPI_GetEnv_r( &g_req, name ); } static inline char * LSAPI_GetQueryString(void) { return LSAPI_GetQueryString_r( &g_req ); } static inline char * LSAPI_GetScriptFileName(void) { return LSAPI_GetScriptFileName_r( &g_req ); } static inline char * LSAPI_GetScriptName(void) { return LSAPI_GetScriptName_r( &g_req ); } static inline char * LSAPI_GetRequestMethod(void) { return LSAPI_GetRequestMethod_r( &g_req ); } static inline off_t LSAPI_GetReqBodyLen(void) { return LSAPI_GetReqBodyLen_r( &g_req ); } static inline off_t LSAPI_GetReqBodyRemain(void) { return LSAPI_GetReqBodyRemain_r( &g_req ); } static inline ssize_t LSAPI_ReadReqBody( char * pBuf, size_t len ) { return LSAPI_ReadReqBody_r( &g_req, pBuf, len ); } static inline int LSAPI_ReqBodyGetChar(void) { return LSAPI_ReqBodyGetChar_r( &g_req ); } static inline int LSAPI_ReqBodyGetLine( char * pBuf, int len, int *getLF ) { return LSAPI_ReqBodyGetLine_r( &g_req, pBuf, len, getLF ); } static inline int LSAPI_FinalizeRespHeaders(void) { return LSAPI_FinalizeRespHeaders_r( &g_req ); } static inline ssize_t LSAPI_Write( const char * pBuf, ssize_t len ) { return LSAPI_Write_r( &g_req, pBuf, len ); } static inline ssize_t LSAPI_sendfile( int fdIn, off_t* off, size_t size ) { return LSAPI_sendfile_r(&g_req, fdIn, off, size ); } static inline ssize_t LSAPI_Write_Stderr( const char * pBuf, ssize_t len ) { return LSAPI_Write_Stderr_r( &g_req, pBuf, len ); } static inline int LSAPI_Flush(void) { return LSAPI_Flush_r( &g_req ); } static inline int LSAPI_AppendRespHeader( char * pBuf, int len ) { return LSAPI_AppendRespHeader_r( &g_req, pBuf, len ); } static inline int LSAPI_SetRespStatus( int code ) { return LSAPI_SetRespStatus_r( &g_req, code ); } static inline int LSAPI_ErrResponse( int code, const char ** pRespHeaders, const char * pBody, int bodyLen ) { return LSAPI_ErrResponse_r( &g_req, code, pRespHeaders, pBody, bodyLen ); } static inline int LSAPI_End_Response(void) { return LSAPI_End_Response_r( &g_req ); } int LSAPI_IsRunning(void); int LSAPI_CreateListenSock( const char * pBind, int backlog ); typedef int (*fn_select_t)( int, fd_set *, fd_set *, fd_set *, struct timeval * ); int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ); void LSAPI_Set_Server_fd( int fd ); int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ); void LSAPI_No_Check_ppid(void); void LSAPI_Set_Max_Reqs( int reqs ); void LSAPI_Set_Max_Idle( int secs ); void LSAPI_Set_Max_Children( int maxChildren ); void LSAPI_Set_Max_Idle_Children( int maxIdleChld ); void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle ); void LSAPI_Set_Max_Process_Time( int secs ); int LSAPI_Init_Env_Parameters( fn_select_t fp ); void LSAPI_Set_Slow_Req_Msecs( int msecs ); int LSAPI_Get_Slow_Req_Msecs(void); int LSAPI_is_suEXEC_Daemon(void); int LSAPI_Set_Restored_Parent_Pid(int pid); typedef void (*LSAPI_On_Timer_pf)(int *forked_child_pid); void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf); int LSAPI_Inc_Req_Processed(int cnt); int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq); int LSAPI_Postfork_Child(LSAPI_Request * pReq); int LSAPI_Postfork_Parent(LSAPI_Request * pReq); #define LSAPI_LOG_LEVEL_BITS 0xff #define LSAPI_LOG_FLAG_NONE 0 #define LSAPI_LOG_FLAG_DEBUG 1 #define LSAPI_LOG_FLAG_INFO 2 #define LSAPI_LOG_FLAG_NOTICE 3 #define LSAPI_LOG_FLAG_WARN 4 #define LSAPI_LOG_FLAG_ERROR 5 #define LSAPI_LOG_FLAG_CRIT 6 #define LSAPI_LOG_FLAG_FATAL 7 #define LSAPI_LOG_TIMESTAMP_BITS (0xff00) #define LSAPI_LOG_TIMESTAMP_FULL (0x100) #define LSAPI_LOG_TIMESTAMP_HMS (0x200) #define LSAPI_LOG_TIMESTAMP_STDERR (0x400) #define LSAPI_LOG_PID (0x10000) void LSAPI_Log(int flag, const char * fmt, ...) #if __GNUC__ __attribute__((format(printf, 2, 3))) #endif ; #if defined (c_plusplus) || defined (__cplusplus) } #endif #endif PK% ]7Zw(gems/ruby-lsapi-5.6/ext/lsapi/extconf.rbnu[require 'mkmf' dir_config( 'lsapi' ) if ( have_library( "socket" )) have_library( "nsl" ) end if RUBY_VERSION =~ /1.9/ then $CPPFLAGS += " -DRUBY_19" end if RUBY_VERSION =~ /2/ then $CPPFLAGS += " -DRUBY_2" end create_makefile( "lsapi" ) PK% ]dCR[R[&gems/ruby-lsapi-5.6/ext/lsapi/lsruby.cnu[ #include "ruby.h" #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 #include "util.h" #else #include #include #endif #include "lsapilib.h" #include #include #include #include #include #include #include #include #include #ifndef RUBY_API_VERSION_CODE #define RUBY_API_VERSION_CODE (RUBY_API_VERSION_MAJOR*10000+RUBY_API_VERSION_MINOR*100+RUBY_API_VERSION_TEENY) #endif /* RUBY_EXTERN VALUE ruby_errinfo; */ RUBY_EXTERN VALUE rb_stdin; RUBY_EXTERN VALUE rb_stdout; #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 RUBY_EXTERN VALUE rb_defout; #endif static VALUE orig_stdin; static VALUE orig_stdout; static VALUE orig_stderr; #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 static VALUE orig_defout; #endif static VALUE orig_env; static VALUE env_copy; static VALUE lsapi_env; static int MAX_BODYBUF_LENGTH = (10 * 1024 * 1024); #if RUBY_API_VERSION_CODE >= 20700 # if defined rb_tainted_str_new # undef rb_tainted_str_new # endif # define rb_tainted_str_new(p,l) rb_str_new((p),(l)) #endif /* static VALUE lsapi_objrefs; */ typedef struct lsapi_data { LSAPI_Request * req; VALUE env; ssize_t (* fn_write)( LSAPI_Request *, const char * , size_t ); }lsapi_data; static VALUE cLSAPI; static VALUE s_req = Qnil; static lsapi_data * s_req_data; static VALUE s_req_stderr = Qnil; static lsapi_data * s_stderr_data; static pid_t s_pid = 0; typedef struct lsapi_body { char *bodyBuf; //we put small one into memory, otherwise, into a memory mapping file, and we still use the bodyBuf to access this mapping int bodyLen; //expected length got form content-length int bodyCurrentLen; //current length by read() readBodyToReqBuf int curPos; }lsapi_body; static lsapi_body s_body; static char sTempFile[1024] = {0}; /* * static void lsapi_ruby_setenv(const char *name, const char *value) * { * if (!name) return; * * if (value && *value) * ruby_setenv(name, value); * else * ruby_unsetenv(name); } * * */ static void lsapi_mark( lsapi_data * data ) { rb_gc_mark( data->env ); } /* * static void lsapi_free_data( lsapi_data * data ) * { * free( data ); } * * */ static int add_env_rails( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ) { char * p; int len; /* Fixup some environment variables for rails */ switch( *pKey ) { case 'Q': if ( strcmp( pKey, "QUERY_STRING" ) == 0 ) { if ( !*pValue ) return 1; } break; case 'R': if (( *(pKey+8) == 'U' )&&( strcmp( pKey, "REQUEST_URI" ) == 0 )) { p = strchr( pValue, '?' ); if ( p ) { len = valLen - ( p - pValue ) - 1; /* * valLen = p - pValue; *p++ = 0; */ } else { p = (char *)pValue + valLen; len = 0; } rb_hash_aset( lsapi_env,rb_tainted_str_new("PATH_INFO", 9), rb_tainted_str_new(pValue, p - pValue)); rb_hash_aset( lsapi_env,rb_tainted_str_new("REQUEST_PATH", 12), rb_tainted_str_new(pValue, p - pValue)); if ( *p == '?' ) ++p; rb_hash_aset( lsapi_env,rb_tainted_str_new("QUERY_STRING", 12), rb_tainted_str_new(p, len)); } break; case 'S': if ( strcmp( pKey, "SCRIPT_NAME" ) == 0 ) { pValue = "/"; valLen = 1; } break; case 'P': if ( strcmp( pKey, "PATH_INFO" ) == 0 ) return 1; default: break; } /* lsapi_ruby_setenv(pKey, pValue ); */ rb_hash_aset( lsapi_env,rb_tainted_str_new(pKey, keyLen), rb_tainted_str_new(pValue, valLen)); return 1; } static int add_env_no_fix( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ) { rb_hash_aset( lsapi_env,rb_tainted_str_new(pKey, keyLen), rb_tainted_str_new(pValue, valLen)); return 1; } typedef int (*fn_add_env)( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ); fn_add_env s_fn_add_env = add_env_no_fix; static void clear_env() { /* rb_funcall( lsapi_env, rb_intern( "clear" ), 0 ); */ rb_funcall( lsapi_env, rb_intern( "replace" ), 1, env_copy ); } static void setup_cgi_env( lsapi_data * data ) { clear_env(); LSAPI_ForeachHeader_r( data->req, s_fn_add_env, data ); LSAPI_ForeachEnv_r( data->req, s_fn_add_env, data ); } static VALUE lsapi_s_accept( VALUE self ) { int pid; if ( LSAPI_Prefork_Accept_r( &g_req ) == -1 ) return Qnil; else { if (s_body.bodyBuf != NULL) free (s_body.bodyBuf); s_body.bodyBuf = NULL; s_body.bodyLen = -1; s_body.bodyCurrentLen = 0; s_body.curPos = 0; pid = getpid(); if ( pid != s_pid ) { s_pid = pid; rb_funcall( Qnil, rb_intern( "srand" ), 0 ); } setup_cgi_env( s_req_data ); return s_req; } } static VALUE lsapi_s_accept_new_conn(VALUE self) { if (LSAPI_Accept_Before_Fork(&g_req) == -1 ) return Qnil; else return s_req; } static VALUE lsapi_s_postfork_child(VALUE self) { LSAPI_Postfork_Child(&g_req); return s_req; } static VALUE lsapi_s_postfork_parent(VALUE self) { LSAPI_Postfork_Parent(&g_req); return s_req; } /* * static int chdir_file( const char * pFile ) * { * char * p = strrchr( pFile, '/' ); * int ret; * if ( !p ) * return -1; *p = 0; ret = chdir( pFile ); *p = '/'; return ret; } */ static VALUE lsapi_eval_string_wrap(VALUE self, VALUE str) { #if RUBY_API_VERSION_CODE < 20700 if (rb_safe_level() >= 4) { Check_Type(str, T_STRING); } else #endif { SafeStringValue(str); } return rb_eval_string_wrap(StringValuePtr(str), NULL); } static VALUE lsapi_process( VALUE self ) { /* lsapi_data *data; const char * pScriptPath; Data_Get_Struct(self,lsapi_data, data); pScriptPath = LSAPI_GetScriptFileName_r( data->req ); */ /* * if ( chdir_file( pScriptPath ) == -1 ) * { * lsapi_send_error( 404 ); * } * rb_load_file( pScriptPath ); */ return Qnil; } static VALUE lsapi_putc(VALUE self, VALUE c) { char ch = NUM2CHR(c); lsapi_data *data; Data_Get_Struct(self,lsapi_data, data); if ( (*data->fn_write)( data->req, &ch, 1 ) == 1 ) return c; else return INT2NUM( EOF ); } static VALUE lsapi_write( VALUE self, VALUE str ) { lsapi_data *data; int len; Data_Get_Struct(self,lsapi_data, data); /* len = LSAPI_Write_r( data->req, RSTRING_PTR(str), RSTRING_LEN(str) ); */ if (TYPE(str) != T_STRING) str = rb_obj_as_string(str); len = (*data->fn_write)( data->req, RSTRING_PTR(str), RSTRING_LEN(str) ); return INT2NUM( len ); } static VALUE lsapi_print( int argc, VALUE *argv, VALUE out ) { int i; VALUE line; /* if no argument given, print `$_' */ if (argc == 0) { argc = 1; line = rb_lastline_get(); argv = &line; } for (i = 0; i0) { lsapi_write(out, rb_output_fs); } switch (TYPE(argv[i])) { case T_NIL: lsapi_write(out, rb_str_new2("nil")); break; default: lsapi_write(out, argv[i]); break; } } if (!NIL_P(rb_output_rs)) { lsapi_write(out, rb_output_rs); } return Qnil; } static VALUE lsapi_printf(int argc, VALUE *argv, VALUE out) { lsapi_write(out, rb_f_sprintf(argc, argv)); return Qnil; } static VALUE lsapi_puts _((int, VALUE*, VALUE)); #if RUBY_API_VERSION_CODE >= 10900 static VALUE lsapi_puts_ary(VALUE ary, VALUE out, int recur ) { VALUE tmp; long i; if (recur) { tmp = rb_str_new2("[...]"); rb_io_puts(1, &tmp, out); return Qnil; } for (i=0; i= 10900 rb_exec_recursive(lsapi_puts_ary, argv[i], out); #else rb_protect_inspect(lsapi_puts_ary, argv[i], out); #endif continue; default: line = argv[i]; break; } line = rb_obj_as_string(line); lsapi_write(out, line); if (*( RSTRING_PTR(line) + RSTRING_LEN(line) - 1 ) != '\n') { lsapi_write(out, rb_default_rs); } } return Qnil; } static VALUE lsapi_addstr(VALUE out, VALUE str) { lsapi_write(out, str); return out; } static VALUE lsapi_flush( VALUE self ) { /* * lsapi_data *data; * Data_Get_Struct(self,lsapi_data, data); */ LSAPI_Flush_r( &g_req ); return Qnil; } static VALUE lsapi_getc( VALUE self ) { int ch; /* * lsapi_data *data; * Data_Get_Struct(self,lsapi_data, data); */ #if RUBY_API_VERSION_CODE < 20700 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) { rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO"); } #endif ch = LSAPI_ReqBodyGetChar_r( &g_req ); if ( ch == EOF ) return Qnil; return INT2NUM( ch ); } static inline int isBodyWriteToFile() { return ((s_body.bodyLen >= MAX_BODYBUF_LENGTH)? (1): (0)); } //create a temp file and open it, if failed, fd = -1 static inline int createTempFile() { int fd = -1; char *sfn = strdup(sTempFile); if ((fd = mkstemp(sfn)) == -1) { fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); } else unlink(sfn); free(sfn); return fd; } //return 1 if error occured! //if already created, always OK (0) static int createBodyBuf() { int fd = -1; if (s_body.bodyLen == -1) { s_body.bodyLen = LSAPI_GetReqBodyLen_r(&g_req); //Error if get a zeor length, should not happen if (s_body.bodyLen < 0) { //Wrong bode length will be treated as 0 s_body.bodyLen = 0; } if (s_body.bodyLen > 0) { if (isBodyWriteToFile()) { //create file mapping fd = createTempFile(); if (fd == -1) { return 1; } if (ftruncate(fd, s_body.bodyLen) == 0) { perror("ftruncate() failed. \n"); close(fd); return 1; } s_body.bodyBuf = mmap(NULL, s_body.bodyLen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (s_body.bodyBuf == MAP_FAILED) { perror("File mapping failed. \n"); close(fd); return 1; } close(fd); //close since needn't it anymore } else { s_body.bodyBuf = (char *)calloc(s_body.bodyLen, sizeof(char)); if (s_body.bodyBuf == NULL) { perror("Memory calloc error"); return 1; } } } } return 0; } static inline int isAllBodyRead() { return (s_body.bodyCurrentLen < s_body.bodyLen)? 0 : 1; } static inline int isEofBodyBuf() { return (s_body.curPos < s_body.bodyLen) ? 0 : 1; } //try to read length as times pagesize (such as 8KB * N) static int readBodyBuf(const int needRead) { const int blockSize = 8192; char *buff = s_body.bodyBuf + s_body.bodyCurrentLen; int nRead; int readMore = (needRead + blockSize -1) / blockSize * blockSize; int remain = LSAPI_GetReqBodyRemain_r( &g_req ); //Only when not enough left, needReadChange will be changed!!! if (remain < readMore) readMore = remain; if ( readMore <= 0 ) return 0; nRead = LSAPI_ReadReqBody_r(&g_req, buff, readMore); if ( nRead > 0 ) s_body.bodyCurrentLen += nRead; return nRead; } static VALUE lsapi_gets( VALUE self ) { VALUE str; const int blkSize = 4096; int n; char *p = NULL; #if RUBY_API_VERSION_CODE < 20700 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) { rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO"); } #endif if (createBodyBuf() == 1) { return Qnil; } //comment: while((p = memmem(s_body.bodyBuf + s_body.curPos, s_body.bodyCurrentLen - s_body.curPos, "\n", 1)) == NULL) { if (isAllBodyRead() == 1) break; //read one page and check, then reply readBodyBuf(blkSize); } p = memmem(s_body.bodyBuf + s_body.curPos, s_body.bodyCurrentLen - s_body.curPos, "\n", 1); if (p != NULL) n = p - s_body.bodyBuf - s_body.curPos + 1; else n = s_body.bodyCurrentLen - s_body.curPos; str = rb_str_buf_new( n ); #if RUBY_API_VERSION_CODE < 20700 OBJ_TAINT(str); #endif if (n > 0) { rb_str_buf_cat( str, s_body.bodyBuf + s_body.curPos, n ); s_body.curPos += n; } return str; } static VALUE lsapi_read(int argc, VALUE *argv, VALUE self) { VALUE str; int n; int needRead; int nRead; #if RUBY_API_VERSION_CODE < 20700 if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) { rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO"); } #endif if (createBodyBuf() == 1) { return Qnil; } //we need to consider these 4 cases: //1, need all data since argc == 0, we may have all data 2, or not //3, need a length of data (argv >= 1), we may have enough data already read, 4, or not if (argc == 0) n = s_body.bodyLen - s_body.curPos; else { n = NUM2INT(argv[0]); //request that length from currentpos if (n < 0) return Qnil; if (n > s_body.bodyLen - s_body.curPos) n = s_body.bodyLen - s_body.curPos; } needRead = s_body.curPos + n - s_body.bodyCurrentLen; if (needRead < 0) needRead = 0; str = rb_str_buf_new( n ); #if RUBY_API_VERSION_CODE < 20700 OBJ_TAINT(str); #endif if (n == 0) return str; //copy already have part first if (n - needRead != 0) { rb_str_buf_cat( str, s_body.bodyBuf + s_body.curPos, n - needRead); s_body.curPos += (n - needRead); } if (needRead > 0) { //try to read needRead, but may be less (changed) when read the end of the data nRead = readBodyBuf(needRead); if (nRead > 0) { n = ((nRead < needRead) ? nRead : needRead); rb_str_buf_cat( str, s_body.bodyBuf + s_body.curPos, n ); s_body.curPos += n; } } return str; } static VALUE lsapi_rewind(VALUE self) { s_body.curPos = 0; return self; } static VALUE lsapi_each(VALUE self) { VALUE str; lsapi_rewind(self); while(isEofBodyBuf() != 1) { str = lsapi_gets(self); rb_yield(str); } return self; } static VALUE lsapi_eof(VALUE self) { return (LSAPI_GetReqBodyRemain_r( &g_req ) <= 0) ? Qtrue : Qfalse; } static VALUE lsapi_binmode(VALUE self) { return self; } static VALUE lsapi_isatty(VALUE self) { return Qfalse; } static VALUE lsapi_sync(VALUE self) { return Qfalse; } static VALUE lsapi_setsync(VALUE self,VALUE sync) { return Qfalse; } static VALUE lsapi_close(VALUE self) { LSAPI_Flush_r( &g_req ); if (isBodyWriteToFile()) { //msync(s_body.bodyBuf, s_body.bodyLen, MS_SYNC); //sleep(5); munmap(s_body.bodyBuf, s_body.bodyLen); } else free(s_body.bodyBuf); s_body.bodyBuf = NULL; s_body.bodyLen = -1; s_body.bodyCurrentLen = 0; s_body.curPos = 0; //Should the temp be deleted here?! return Qnil; } static VALUE lsapi_reopen( int argc, VALUE *argv, VALUE self) { VALUE orig_verbose; if ( self == s_req_stderr ) { /* constant silence hack */ orig_verbose = (VALUE)ruby_verbose; ruby_verbose = Qnil; rb_define_global_const("STDERR", orig_stderr); ruby_verbose = (VALUE)orig_verbose; return rb_funcall2( orig_stderr, rb_intern( "reopen" ), argc, argv ); } return self; } static void readMaxBodyBufLength() { int n; const char *p = getenv( "LSAPI_MAX_BODYBUF_LENGTH" ); if ( p ) { n = atoi( p ); if (n > 0) { if (strstr(p, "M") || strstr(p, "m")) MAX_BODYBUF_LENGTH = n * 1024 * 1024; else if (strstr(p, "K") || strstr(p, "k")) MAX_BODYBUF_LENGTH = n * 1024; else MAX_BODYBUF_LENGTH = n; } } } static void readTempFileTemplate() { const char *p = getenv( "LSAPI_TEMPFILE" ); if (p == NULL || strlen(p) > 1024 - 7) p = "/tmp/lsapi.XXXXXX"; strcpy(sTempFile, p); if (strlen(p) <= 6 || strcmp(p + (strlen(p) - 6), "XXXXXX") != 0) strcat(sTempFile, ".XXXXXX"); } static void initBodyBuf() { s_body.bodyBuf = NULL; s_body.bodyLen = -1; s_body.bodyCurrentLen = 0; s_body.curPos = 0; } void Init_lsapi() { VALUE orig_verbose; char * p; int prefork = 0; LSAPI_Init(); initBodyBuf(); readMaxBodyBufLength(); readTempFileTemplate(); p = getenv("LSAPI_CHILDREN"); if (p && atoi(p) > 1) prefork = 1; #ifdef rb_thread_select LSAPI_Init_Env_Parameters( rb_thread_select ); #else LSAPI_Init_Env_Parameters( select ); #endif s_pid = getpid(); p = getenv( "RACK_ROOT" ); if ( p ) { if ( chdir( p ) == -1 ) perror( "chdir()" ); } if ( p || getenv( "RACK_ENV" ) ) s_fn_add_env = add_env_rails; orig_stdin = rb_stdin; orig_stdout = rb_stdout; orig_stderr = rb_stderr; #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 orig_defout = rb_defout; #endif orig_env = rb_const_get( rb_cObject, rb_intern("ENV") ); env_copy = rb_funcall( orig_env, rb_intern( "to_hash" ), 0 ); /* tell the garbage collector it is a global variable, do not recycle it. */ rb_global_variable(&env_copy); rb_hash_aset( env_copy,rb_tainted_str_new("GATEWAY_Irewindable_input.rbNTERFACE", 17), rb_tainted_str_new("CGI/1.2", 7)); rb_define_global_function("eval_string_wrap", lsapi_eval_string_wrap, 1); cLSAPI = rb_define_class("LSAPI", rb_cObject); rb_define_singleton_method(cLSAPI, "accept", lsapi_s_accept, 0); if (prefork) { rb_define_singleton_method(cLSAPI, "accept_new_connection", lsapi_s_accept_new_conn, 0); rb_define_singleton_method(cLSAPI, "postfork_child", lsapi_s_postfork_child, 0); rb_define_singleton_method(cLSAPI, "postfork_parent", lsapi_s_postfork_parent, 0); } rb_define_method(cLSAPI, "process", lsapi_process, 0 ); /* rb_define_method(cLSAPI, "initialize", lsapi_initialize, 0); */ rb_define_method(cLSAPI, "putc", lsapi_putc, 1); rb_define_method(cLSAPI, "write", lsapi_write, 1); rb_define_method(cLSAPI, "print", lsapi_print, -1); rb_define_method(cLSAPI, "printf", lsapi_printf, -1); rb_define_method(cLSAPI, "puts", lsapi_puts, -1); rb_define_method(cLSAPI, "<<", lsapi_addstr, 1); rb_define_method(cLSAPI, "flush", lsapi_flush, 0); rb_define_method(cLSAPI, "getc", lsapi_getc, 0); /* rb_define_method(cLSAPI, "ungetc", lsapi_ungetc, 1); */ rb_define_method(cLSAPI, "gets", lsapi_gets, 0); //TEST: adding readline function to make irb happy? /*rb_define_method(cLSAPI, "readline", lsapi_gets, 0); */ rb_define_method(cLSAPI, "read", lsapi_read, -1); rb_define_method(cLSAPI, "rewind", lsapi_rewind, 0); rb_define_method(cLSAPI, "each", lsapi_each, 0); rb_define_method(cLSAPI, "eof", lsapi_eof, 0); rb_define_method(cLSAPI, "eof?", lsapi_eof, 0); rb_define_method(cLSAPI, "close", lsapi_close, 0); /* rb_define_method(cLSAPI, "closed?", lsapi_closed, 0); */ rb_define_method(cLSAPI, "binmode", lsapi_binmode, 0); rb_define_method(cLSAPI, "isatty", lsapi_isatty, 0); rb_define_method(cLSAPI, "tty?", lsapi_isatty, 0); rb_define_method(cLSAPI, "sync", lsapi_sync, 0); rb_define_method(cLSAPI, "sync=", lsapi_setsync, 1); rb_define_method(cLSAPI, "reopen", lsapi_reopen, -1 ); s_req = Data_Make_Struct( cLSAPI, lsapi_data, lsapi_mark, free, s_req_data ); s_req_data->req = &g_req; s_req_data->fn_write = LSAPI_Write_r; rb_stdin = rb_stdout = s_req; #if defined( RUBY_VERSION_CODE ) && RUBY_VERSION_CODE < 180 rb_defout = s_req; #endif rb_global_variable(&s_req ); s_req_stderr = Data_Make_Struct( cLSAPI, lsapi_data, lsapi_mark, free, s_stderr_data ); s_stderr_data->req = &g_req; s_stderr_data->fn_write = LSAPI_Write_Stderr_r; rb_stderr = s_req_stderr; rb_global_variable(&s_req_stderr ); /* constant silence hack */ orig_verbose = (VALUE)ruby_verbose; ruby_verbose = Qnil; lsapi_env = rb_hash_new(); clear_env(); /* redefine ENV using a hash table, should be faster than char **environment */ rb_define_global_const("ENV", lsapi_env); rb_define_global_const("STDERR", rb_stderr); ruby_verbose = (VALUE)orig_verbose; return; } PK% ]W q,,(gems/ruby-lsapi-5.6/ext/lsapi/lsapidef.hnu[/* Copyright (c) 2002-2018, Lite Speed Technologies Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Lite Speed Technologies Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _LSAPIDEF_H_ #define _LSAPIDEF_H_ #include #if defined (c_plusplus) || defined (__cplusplus) extern "C" { #endif enum { H_ACCEPT = 0, H_ACC_CHARSET, H_ACC_ENCODING, H_ACC_LANG, H_AUTHORIZATION, H_CONNECTION, H_CONTENT_TYPE, H_CONTENT_LENGTH, H_COOKIE, H_COOKIE2, H_HOST, H_PRAGMA, H_REFERER, H_USERAGENT, H_CACHE_CTRL, H_IF_MODIFIED_SINCE, H_IF_MATCH, H_IF_NO_MATCH, H_IF_RANGE, H_IF_UNMOD_SINCE, H_KEEP_ALIVE, H_RANGE, H_X_FORWARDED_FOR, H_VIA, H_TRANSFER_ENCODING }; #define LSAPI_SOCK_FILENO 0 #define LSAPI_VERSION_B0 'L' #define LSAPI_VERSION_B1 'S' /* Values for m_flag in lsapi_packet_header */ #define LSAPI_ENDIAN_LITTLE 0 #define LSAPI_ENDIAN_BIG 1 #define LSAPI_ENDIAN_BIT 1 #if defined(__i386__)||defined( __x86_64 )||defined( __x86_64__ ) #define LSAPI_ENDIAN LSAPI_ENDIAN_LITTLE #else #define LSAPI_ENDIAN LSAPI_ENDIAN_BIG #endif /* Values for m_type in lsapi_packet_header */ #define LSAPI_BEGIN_REQUEST 1 #define LSAPI_ABORT_REQUEST 2 #define LSAPI_RESP_HEADER 3 #define LSAPI_RESP_STREAM 4 #define LSAPI_RESP_END 5 #define LSAPI_STDERR_STREAM 6 #define LSAPI_REQ_RECEIVED 7 #define LSAPI_CONN_CLOSE 8 #define LSAPI_INTERNAL_ERROR 9 #define LSAPI_MAX_HEADER_LEN 65535 #define LSAPI_MAX_DATA_PACKET_LEN 16384 #define LSAPI_RESP_HTTP_HEADER_MAX 32768 #define LSAPI_PACKET_HEADER_LEN 8 struct lsapi_packet_header { char m_versionB0; /* LSAPI protocol version */ char m_versionB1; char m_type; char m_flag; union { int32_t m_iLen; /* include this header */ char m_bytes[4]; }m_packetLen; }; /* LSAPI request header packet 1. struct lsapi_req_header 2. struct lsapi_http_header_index 3. lsapi_header_offset * unknownHeaders 4. org http request header 5. request body if available */ struct lsapi_req_header { struct lsapi_packet_header m_pktHeader; int32_t m_httpHeaderLen; int32_t m_reqBodyLen; int32_t m_scriptFileOff; /* path to the script file. */ int32_t m_scriptNameOff; /* decrypted URI, without pathinfo, */ int32_t m_queryStringOff; /* Query string inside env */ int32_t m_requestMethodOff; int32_t m_cntUnknownHeaders; int32_t m_cntEnv; int32_t m_cntSpecialEnv; } ; struct lsapi_http_header_index { uint16_t m_headerLen[H_TRANSFER_ENCODING+1]; int32_t m_headerOff[H_TRANSFER_ENCODING+1]; } ; struct lsapi_header_offset { int32_t nameOff; int32_t nameLen; int32_t valueOff; int32_t valueLen; } ; struct lsapi_resp_info { int32_t m_cntHeaders; int32_t m_status; }; struct lsapi_resp_header { struct lsapi_packet_header m_pktHeader; struct lsapi_resp_info m_respInfo; }; #if defined (c_plusplus) || defined (__cplusplus) } #endif #endif PK% ](((gems/ruby-lsapi-5.6/ext/lsapi/lsapilib.onu[ELF>@@=< 02/3.4-5ff.ÐHGH+FHcAVIH@AUATL$USHtQHHtIHIL9r 0HI9v'KHSMsH;Յ[]A\A]A^[D]A\A]A^øff.f=DÐO AWDD_AVAUATUSD6^nAxj׋G3G D!3G V\$ЋW^$DD1\$!3WAʋN Fp $E‰L$A1A1DD^ !D1G;νD\$DEDVDT$A!A1EE|A 1AD!E1DD*ƇGD1D!A1A1DDN DL$E F0D!DnA1D1DGFEDf Dd$D^(A!A1EEؘiA 1AD!1DDDʋ^0D1D!A1DE [D 1!D1DDN,A1DL$G\EA!Df8A1ED"kA 1AD!1DDN4EqDD1!1DE CyD 1!D1DDV<1G!I!1DDD$ Eb%1!1DDD$E@@1!1DDD$ EQZ^&1!1DE6Ƕ1!1DD]/։ 1!1DESD1!1DE ؉ 1!1DDD$E01!1DDD$ E!1!1DE7É1!1DDD$ E 1!1DDD$A0ZEAA1A!A1AA㩉A AD1!1t$DD1!A ogD1 1D!FL*1DD$Ή1AA!B9A1DD$A AD1D$qDD11‹D$ 0"amD1G 81Ɖ11DDD$ ED꾤11DDD$AKAA1A5`KA1AЉApA 1AD1D1D1A ~(D 1G'111DDD$ A0AA1A1AЋT$A2A1D1֋T$ 9ىDD11D11C|A A1A1AD$A0eVĉA1D1AD")Dt$ D D1A *CDG# 1  1DD9Ή 1DDY[e\$  1DE Dt$ щ1DE3}D\$  1DDD$E] 1DEO~oA AD 1DE ,DT$ A1ADE6CDt$ AN 1A~SADEAA A1A5:ADA AD 1Љ3*\$D D1DFӆ[ ]A\A]A^ 1։ 1DƉA4A_ OW GOW ATI1USHdH%(H$1HHH<$t)H$dH3%(u TH=1tIH=HcH5HH[ÉD1?H=HW(Hw`HLJHHLJ0HHWHVHWHWHWHWH)81HSHHHtHHtHHtH{@Ht1[fDHtGwBLHcAT4t/HcApHHH€:t HH1ff.fHtPtJSHcH;}HSHH[~ Hcи[ÃAWAVAUATUSHZHHHD$H:GH%HIHIIILfDA)HcHL9HcIOIvI HLHtML)HLHXHHAIA$D)EH[]A\A]A^A_LHHHAL|$II)AM?DLLHcH~A-H1|v@AVAUATUSHIHHHHHH+E1HH9HcHO؋)HH~)H9HwHHNHHIELL)Ht6Eu@HHDHu48u uMt-M[L]A\A]A^H~IHH)uIDHO(HW8HLJLSH)ʍBHGpH0HpH@Hwp~HcHHH HPHO8HGpAWAVAUATUSHHHT$HHH<$IH=HcB$HH@H,H9rZf.HH9vGH3LuHCH[]A\A]A^A_HD$L9IM9f.1H[]A\A]A^A_H$1L=L@Al4tI4LHHuHD$HcP 1~H $HLMtM9sHH$ID$HD$@IcMIcmH,$L| L9)A\$)H8HD$'-t _HHI9tHU:t8IcU IcEH$H€:H $HcHcAVHH€:@AVAUATUSL$HH $L9uHdH%(H$@1HHHHHHE1L LfHHcHcT4t7 qHM HIcAHL EHT DT t HHuHHcP HHL L9IcIHLfHH I9HcHHc0AHLcP IHcHHBDBHJH H2JAuH L$DIH Ic LEtaE1@AI E9~CAMIUIAuI}ӅH$@dH3%(u6H@[]A\A]A^D1@IcUff.AWAVAUATUSHXHt$ HT$dH%(H$H1HIH1E1L-HL%HHHcHcT4t/HHAAtIL{8IHC0L)H9>Lt$L+{(LA@LLfIM)MK H@σLSLCpNIHDI0HI@HKpM~HC(MxIH E1I@HC8HL1HMLIHHKpH9eHthILM)MUI9t HtDL+t$HL[]A\A]A^A_DM@@M)(IHt$HLHk8f.HAVLAUIATIUSHu\H߉AD${LǃLSHu0{L[L]A\A]A^[H]A\A]A^Hff.AWAVAUATUSHHHHD$ 0xIHIHLc\CHcT t u(HDLcLH t tLÅ~6HcAT t u#H@Å~ALH t tE<AG=I|$PHHTI9T$Hs7HI+t$@L2%))I|$PLHHcAMt$PHLIFID$PA:I|$PMD$PII@ID$PAIc$0fET8HЃA$0D$ H[]A\A]A^A_D$ ff.H HB=0AUATUSHcHfDA< t< uH؅uH[]A\A]IHPHHDI9D$Hs3HI+t$@L2%))tQI|$PHHAI\$PHCID$PIc$0fET8HЃA$0H1[]A\A]øSDAUATAUHSH?dH%(HD$1D$ff t1fHL$dH3 %(H[]A\A]ÐA1ҾÃtʼnǺ1HL$Aߺu#DHuDo߻D HDeOAkDH}An}NHtff.USHdH%(H$1HHu/HH$dH3%(uHĘ[]@1H=tAUATA'USH'DNuDH@AHHHHtH-ƉljUDk HDcEufH H IGAG IPH f@ f@ HHP P H HPPHHPPHHPPHHPPf@f@f@HH#PP H H'P#P$H$H+P'P(f@f@!f@%H(P+f@)I1 fDIHcȋL4t#fBIHT4 rfB@2JHHuMIcP IHHH9pH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@pHH9wMApIbIc@ IH0ALJt` A1LHcIHIGAo IuID%D-B(AA1IcH4IILI 9HqH= IJDB(9xHqH= XIJB($AD$IKAzHL$;MbfoLt$ LAoL$AT$Ml$)$ LLHL$LHLLH$ID$H$I3L$H1H D$$Dl$EDDl$H=IHIDMH=t"LDLŃP|$Et$A9uHt$DŃ5$A?D5t AH5LHtHHf)#AH51H@H51LH 1HIH51H51D%DD$H=IHtZEW7E1111H=H51E|$M2;|$E1H5LuI}Ń1H5LKfD=-ED$AIFH51HH)H5H11H5L 1H5LA#LH H1H5Laff.AVAUATUSHdH%(H$1D$ HH ;1Ll$Ld$Lt$ Hkl{ul;LLD$CHHt@HHt{1f|$=u|H4tH舴Hd1H$dH3 %(u}HĠ[]A\A]A^D {H5Hfы{LA;ff.AWAVAUATUSHD=dH%(H$1ExHH-H};DH-Ht 1HEDEH$L|$PDcA:E1AfD EDEtHHt @fLH1HIcDHD$PHD$XA ?)ѺHH D9#11A|$MHD9#HHt @D9#AD91葳fH$dH34%(' H[]A\A]A^A_KL$HDŽ$hMl$H$LH$LHHD$@AHLDŽ$hH$H$LHHD$0PH$LHHD$8+H$`L HHD$(H$ LHHD$HADžHD$PE1Ll$`HD$H$HD$H$`HD$fD%EHHt H=1IL9t<1ձL5EDu EME1VHLH1HHc}}LD$LHD$PHD$X ?)ѺH1H T`1 8Ht$(1ҿ x=_5tHHt @f,D9# DCHHt@HHtDc1DN ={H5HHHt*HHB(@HHt@HH@8B-DAD9M==H HtDHHt A9HHtD҉T$$DE ~:E~5T$$AAAuDE UM D9vHAHtDH51D$0 H=T$fD}蠩C1mH|$IH|$HT$Ht$161E Mt AMgMg{E1CHt$1ҿH=f;>fDD$$0d T$$WH=T$T$fDD#AfDRDEBHH29{H5H{wH=H=0MAH… H{HH=Ht$1ҿHL=HHHtH11L=AGHHt{1蝦D-EuHHt!E9~;t Ht$@1ҿL$Ht$01ҿHt$H1ҿHt$81ҿHt$(1ҿ kHLSH$$L$H=%,H=QHHt*fC1CD$CCT$HC(HC fD=ff.@H,LSLSLSLS GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realignAnonymous mmap() failedlocalhost%02d:%02d:%02d [%s] [UID:%d][%d] %.*syesnosystem()%s, errno: %d (%s) /dev/nulllibpthread.sopthread_atforkHTTP_[UID:%d][%d] %s:%s: %s LSAPI: jail() failure./etc/Can't set signalsaccept() failedLSAPI_STDERR_LOGPHP_LSAPI_MAX_REQUESTSLSAPI_MAX_REQSLSAPI_KEEP_LISTENLSAPI_AVOID_FORKLSAPI_ACCEPT_NOTIFYLSAPI_SLOW_REQ_MSECSLSAPI_ALLOW_CORE_DUMPLSAPI_MAX_IDLEPHP_LSAPI_CHILDRENLSAPI_CHILDRENLSAPI_EXTRA_CHILDRENLSAPI_MAX_IDLE_CHILDRENLSAPI_PGRP_MAX_IDLELSAPI_MAX_PROCESS_TIMELSAPI_PPID_NO_CHECKLSAPI_MAX_BUSY_WORKERLSAPI_DUMP_DEBUG_INFOnobodyLSAPI_DEFAULT_UIDLSAPI_DEFAULT_GIDLSAPI_SECRETLSAPI_LVE_ENABLELVE_ENABLEliblve.so.0lve_is_availablelve_instance_initlve_destroylve_enterlve_leavejailLSAPI_PHP_LSAPI_PHPRC=packetLen < 0 packetLen > %d Bad request header - ERROR#1 ParseRequest error SUEXEC_AUTHSUEXEC_UGIDLSAPI: setgid()LSAPI: initgroups()LSAPI: setgroups()LSAPI: setuid()Bad request header - ERROR#2 lsapi_accept() errorPragma: no-cacheRetry-After: 60Content-Type: text/htmlDEBUGINFONOTICEWARNERRORCRITFATALAcceptAccept-CharsetAccept-EncodingAccept-LanguageAuthorizationConnectionContent-TypeContent-LengthCookieCookie2HostPragmaRefererUser-AgentCache-ControlIf-Modified-SinceIf-MatchIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveRangeX-Forwarded-ForViaTransfer-EncodingHTTP_ACCEPTHTTP_ACCEPT_CHARSETHTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_AUTHORIZATIONHTTP_CONNECTIONCONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_COOKIE2HTTP_HOSTHTTP_PRAGMAHTTP_REFERERHTTP_USER_AGENTHTTP_CACHE_CONTROLHTTP_IF_MODIFIED_SINCEHTTP_IF_MATCHHTTP_IF_NONE_MATCHHTTP_IF_RANGEHTTP_IF_UNMODIFIED_SINCEHTTP_KEEP_ALIVEHTTP_RANGEHTTP_X_FORWARDED_FORHTTP_VIAHTTP_TRANSFER_ENCODING%04d-%02d-%02d %02d:%02d:%02d.%06d Child process with pid: %d was killed by signal: %d, core dumped: %s Possible runaway process, UID: %d, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld gdb --batch -ex "attach %d" -ex "set height 0" -ex "bt" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2Force killing runaway process PID: %d with SIGKILL Killing runaway process PID: %d with SIGTERM Children tracking is wrong: Cur Children: %d, count: %d, idle: %d, dying: %d LSAPI: LVE jail(%d) result: %d, error: %s ! Invalid custom stderr log pathFailed to open custom stderr logCan't set signal handler for SIGCHILDReached max children process limit: %d, extra: %d, current: %d, busy: %d, please increase LSAPI_CHILDREN. LSAPI: failed to open secret file: %s! LSAPI: failed to check state of file: %s! LSAPI: file permission check failure: %s LSAPI: failed to read secret from secret file: %s LSAPI: Unable to initialize LVERequest header does match total size, total: %d, real: %ld LSAPI: missing SUEXEC_UGID env, use default user! LSAPI: SUEXEC_AUTH authentication failed, use default user! LSAPI: lve_enter() failure, reached resource limit.prctl: Failed to set dumpable, core dump may not be available!sigprocmask(SIG_BLOCK) to block SIGCHLDsigprocmask( SIG_SETMASK ) to restore SIGMASK in childfork() failed, please increase process limitsigprocmask( SIG_SETMASK ) to restore SIGMASKCache-Control: private, no-cache, no-store, must-revalidate, max-age=0PID 508 Resource Limit Is Reached

Resource Limit Is Reached

The website is temporarily unable to service your request as it exceeded resource limit. Please try again later.
          ^ d/4-//// %-/Ga '9 (_intG )@/G G @ @ G @ G     G  `@ A C $E (J 0NL8PX@[+H\+X]+hj$xp4G- - N1 ooGGXa&& E18: ;1?A B C1GOI JK1 OQ RS TU1ac Ed EC^&e&g1 Y[ E]ah 1l5no 1tfv Ew x@ Cp3&5&<&Db_rtL&VO&i&p&y5G1$ +& ( * 0 { f|HCIRT Cv&"7&$ R  E+v"&T.1 4 c G@4HH//-Gldy"m - 911; CmGFy<d(eGfI@I@IEIE"1 36 |7 |8 |9 | : |(; |0< |8= |@@ |HA |PB |XD `F hHpItJ xM9NNO Q Y [ \ ] ^ E_ `b g+J  G J J  G4'  < ' ' '   T h4I ' T X@!      !!"! ! ! ""F " E" #!X@$  i0%9"# # # 4  G  "&4 &6 &7  < |"0'1 '3 |'4 |'6 '7 '8 |'9 | ': |(jtm8(, ( ( ( (  ( (((( ( ((0|< G'), ') ')'), ') ')H*! B@,H      !"#$%&'()*+,-./0123456789:;<<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'-$|'-2 '-7 '-; .U.m.4/"/*/!B@/) !)./23\^bgl00/{C/&/ &/ -&/ =-G=GMG"/h/ 4M'/h'/h"// ///-GK/,/ ///M/K0050708090: 0; F 0<0= | 0>( ,"n11 1 GkB@2,     C2q&2s9&2t"2k2m 2n 2o 2p 2u",22 2 92 9 2 92 92 92 92 9 2 9$2 9("222 4G9G"22 92 92 92 9 "2G2 92 9"2o2"2"/" / 1 | 2 | 3  4 k : < = ? @ B| C  E|( F|0 G|8 I|@ J|H K|P L!VX O ` P h Q p R x T'\ V'b W'h X'h Y' Z' \'n ]'t _| `| a| b| c| d e f g h iL k'zL m'G(L n'8L oE "0pVr s uhvwxz{ |(vGa=G q' s w9   EM X9    $EM x7=RH H"XOYbufP =Q YinRG-G?]!NB@j~            9     H  H  H  |      l "G * ^GN G t N  t G M>CQ L L @  J l E m  9    9#!  9 9 #! @! !9Z! #!  g!F!9! ! |'  ! m!        # # *"G&%" K "  K@ V#          ( 0 8M " z# V# @      #  -     H! x$2cnt!U$2pid'U  : YO%2buf'#!U#in>74r"4TsUs]4U T 4UsT  [5m4UsT 5UsT ,5UsT Q5UsT v5UsT 5U ʳY5U YU ;W6%;O";#;Y2x6k%2w~}׳6U2T~QwY7U 9Y,7U YK7U Yj7U Y7U Y7U ;Y7U Y7U <ytY,8U YK8U G<Yw8U ;Y8U ;Y8U <Y8U Q;Y'9U YF9U ^9Us<Y9U Y9U Q;{X9TvQ | $0.MX] ":!p], _ ":3:=GE `: E- G % :!p%) %2| %= ' :len( end) |:=G ;i pw!)p7 2;env ! )del! D TD ( ;*$U(;**U(<*'U(G<*&U(v<*$U(<*"U( <*U( =   H  -5+fd ret    ~ Et;=   5 >__d U| $ &585> 8! O EOOOOw PyPz%P{2P|?P~LPYPfPsPPPPtPtPuPvNPP p?P>QT?Q?U  y @y!y 9C@7@Ä*UvT|Q@T7@U}C AUAT|Qt7"AU}CGAU?T|QtClAU2T|QtCAU:T|QtCAU3T|Qt3AU OAU0KQ BU|[%BUV3KBT}Q0R0XtC|BU:TtQ0BU T BU [WVBUu7BUthCUtTAtDCU0TtQtLtCU2TtQCU  CU CU  DU 8DU tiDU2TtQ03DU0T0Q DT0LCDUATtQ0CEU?TtQ0C8EU3TtQ0C\EU2TtQ0CEU:TtQ0EU QU  ?yj"FQy-?y+Qy+y #/ y+y #  yy*T Q8ly 9G~y+y yy*T Q8zqQGUsOhGU03GU|TvQ0R0X[WGU|GU|T0Q HU LGHUs?Ãsx_HUsHUs?ÃsqpHUsOHU0M M M .5+ O 4 P 4Q }R E} S retT  V z#EactX ~;I   5I__d ;1J  #JU T7VJU|CJUATvQ 7JU|CJU?TvQ CJU2TvQ CKU:TvQ C@KU3TvQ 3[KU OrKU0KQKU}[KUV3KT|Q0R0XC LUAT Q0C2LU?T Q0C[LU3T Q0CLU2T Q0CLU:T Q0LU T LU [W )MU HMU gMU VMUu> @N > +5+5N C 4OU0L pO  *5+  y6 GOy!y@ 7NÄ 9O*UsTwQ@3OU0T0Q OT0LQ: Q : @z# ; 95+act=  =  = % = / >  >  ?  @ retA pidB  C 4 D 4 E  F E H  I FP   FQ__d )  D/ 1T+ : 6R  ,        %RU T   F lY  *  5 =X~ret pfd YSYUUTsZqYUsTv88 Z 8 ' 8 @ : Zp; | < |res=  = , > ? ZG -[  6[  Gret fd  D  ZT1Q0ZUsT2Q1[UsT1Q2RDX4?[UsTvQ} ][UsT|L,[Uv 8 [  /5+  B!len LF[ch )   ^  05+  C  ,   len ;\ch ;\ch 57]  U|  x]TTQ~  ]T}Qv]UvU} t^* 25+U- Ä F^  05+#fn !#arg ,E@p_QTRQt Fp_ t )5+#fnu !#argu ,E@p_QTRQ6a s` a 6h#nb #fnb (#argb 3E d #hrete qX} b  ,5+#fn !#arg ,Ei len! " |ret# $ ;Zb7 Z}p8 | 9 | : | ;  < &t < -t5(achK % O Fa__cO 9 ̋F 1b݋r}U~T}#X|3bUv3$|"T v2$}"X|$_d /5+#fn!#arg,Ei len  |ret  _d~5c |  &t -tEdUwQ R E=dUwT| $ &Q R 3QdXvA"pd=G d2v1'U2v27T|'f (5+ ; #h #h['ff$Ff$9fSf^fNkfelfwfffffUffUff9RU|Ts3$"RU|q|f q-5+ q@is t |)p | |  &t -t)ch) )__c8< -g </5+ <B!len<O >  ?p@ A - B -retC iovDg E  gGh $5+ret n .ph6$)CP]qTshhUshUs?Ãs^(iNi*'5+U "\  -Ä -j +5+ 5#offBj N "\ jÄg5jUs*RjT~Q8Z^yjTTQQRR^8 - k (5+ ;!lenH "\  p! " - # - $ - %  - l .5+ ;| Hlen -    l$UvQ|-o ʊlۊ@U~TvQsln -5+ :| G THlen -  -  |  |  |p |  >n#nTQsTQsmo no% ooU~jUT:Qs]mo -5++moo%ooUs o .5+  len -|Sp*+5+U 5off yJqp y&5+(nYp n%5+-`t}$qKzq K*5+h-qUsgEqUseqUs?Ãs^Us-r -%5+hqUsgqUsqpqUs^Ft %5+=X~ElenF ~~ ?yPsQy-?y+Qy+y / y+y   yy*T Q8zqhsUssT0sT|Q}sT0xsUssUv?ÃsqptUs8tT6Q1R~X4 yt*(5+Ut@FtU %w (5+#fd2  `Tu}$q  uvT Y' >vk%'w~~׳/vUvT~Q~ HveY'U T2ʳvU vUsT vUvT1wU0wT0( Sw2cb;*UD Tx EۄwU=T ۄxU:T ;xUIT1WxU2T1t{xU T0xU T1T A y A%5+lenC D 4/y!fd4) 6 /y?yG+^y!fd+,s y!fd5 y!fd 7y!fd.!pktN\ *z *5+ 4   |  | Wz 65+ D z D.5+uidF gidG H I J#h K#hiL 1 >{ 1.5+ 2|!len2 2+| 26 4 5>{-N{G { '5+!uid3L!gid>@ Prv pw! { 6 | +5+#uid7L#pwL!ret  Tw3o|UQTs|U T Q|Xs}|UvT Q0 $} ,5+!uid8L) ret  r} -5+r} } }G}=G#4}6{  {,5+ {? {R} ":_n~ i~ ~$zUvT Q1R X rf~U|Tv*~U2DrJ [ J%stLSfdM ) zrc+   )uid  -5+  i ) &t -t7 O 35+i F2bp|) &t -t7v /5+pb7 )Hp |b6t Y t4h tB*u! Q u#| w#h x xh!fdh j=XlenkF R ف R<ف SH S+ U#hh> >>\ >L)bF62 G 235+ 2=p4 |vTv$ Ă $+5+!n$5p&  05+ :  | i!fd 2i < Gret  n  -!fd' 2E!len?ret -7 у 35+ !fdret 6 U#fd# +val UsT3Q0@UUT47wф wJ\ x&!lenx0tR :A  A A2EsaC~CWUvT0Qs7oUsCUvTsQ0:8 υ2sig8!U:3 2sig3 Uu (7   .mUs@U T QURTvvwxfmt'PVbuf Tvyp |z Eap  u5VtvEuVtm u{iևzU|T Q1R X \i/XzU|T Q1R X õuUsT0ϵUsTu +۵T1Q}Ru\i-zUsTdQ1R X Yv3$" izUsTdQ1R X  > [[OT1Q X|rW  :5+ D.|ʊ|."-" "E"%.k|6kkk.\|`\\.>E>E>>.'E̋'E''.EG.8 18.did d<P.A]__sA]__nAAP.%|Ռ%%|sz' 8n n8i i8 B  BS.)s))PW11W"m"m,moooo-o ʊۊ@U~TvQ|,aq$ÃSу G$% L8Us+ $Ã, )6CP]UvQ|,Ot  OfT0,YYYYY}YYY}Y}YYG g)U|TsQ N ʑ)UvT|Ql  UsT0Q: ` T}q ̋ ݋ Uv 6\ SG) U|T:51U|T )OU}T]AzU}T0Q}R}NU|[U},UUUUQUQVV[UC ה$UUUUVVNVV+VU T|QgU TvQ3VUu,flEfggg,g9gDgQg^gkgxgf< ggf%g,g9gDgQg^gkgxg e6)CP]qTwQ2R} Z ÄgU~U~?Ã~*7U2T~,9= ::п `:b :}:r::_:: , 2sUwT 9 %ɌUsT|Q јTvQ0 3:g 6E:R:HGeY'UsT AQ UsڙUvT2LUvU2T1}U0T Qs9 ]  :% :}U0T QU,jjjjjjjjjkQk j jjjjjjjjkk S $Ä? cUTQvg{UsgUs^,[[[[}[ [$[$[>[,[>[3g[U|- TvQs,Y8YYYYYYYQYY@tUUTT,{X!#XXX-{X XXX՞U@T1[UU,x xxx oO/ʊ  ۊ@UsTvQ| xA hxxx߁1V۠O  o@iš%8ʊۊ@U}T|Qv yn yyzz~zA %Aˁ+5R %5ˁvT v $ &33$A %Aˁ+5R %5ˁvT v $ &33$  wODO X]%j v v[ v v v6 v vȦ v-vS K$% >#)&+v %O23@ v  v ڨ$ v $-v $*z1 ԩ"?o363A* @ 'n* A * A B1B( 1 : ; 9 I8 41B11 4: ;9 I 1RBUX YW  : ;9 IB 4: ;9 IB : ;9 I I: ; 9 I4: ;9 I1RBX YW .?<n: ; 9 4: ;9 I4: ;9 IBI41 U.: ;9 'I : ; 9 I!I/ .?: ;9 'I@B4: ; 9 I41 : ;9 I8 .?<n: ;9 I!: ;9 I" : ; 9 #: ;9 IB$1% & : ; 9 I'4: ; 9 I?<(.?: ;9 '@B) *: ;9 I+1RBX YW ,.1@B-1RBUX YW ..?: ; 9 'I 4/$ > 0(1 : ; 9 2: ;9 I34&I5 6.: ;9 'I@B7.: ;9 ' 8.?: ;9 'I 9'I:.: ;9 '@B; U<7I=!I/> 1?1B@B1A.?<n: ; B> I: ; 9 C : ; 9 D.?: ;9 'I@BE4: ;9 IF G5IH4: ;9 I?<I : ; I8 J<K : ;9 L : ; 9 I8M: ;9 IN 1UO 1PQ41 R'S1X YW T.?: ;9 '@BU 1UV4: ; 9 IW.: ; 9 'I X> I: ; 9 Y : ; 9 I8 ZB1[1UX YW \1RBX Y W ]: ; 9 I^% _$ > ` a : ; 9 b : ; 9 Ic'd&eIf : ; g: ; 9 h!i(j : ; 9 k : ; 9 l4G: ; 9 m'InB1o.?: ;9 'I@Bp4: ;9 I qrBs.: ;9 'I t.: ;9 ' u.: ;9 I v.?: ; 9 '@Bw: ; 9 IBx: ; 9 IBy4: ; 9 IBz4: ; 9 IB{1RBUX Y W |4: ; 9 I}1UX YW ~.?<n.?<n: ;9 6ddqd T)TuPPP(PPsPPKP[P"R+RRJQ^Q5Q5<v <Q{ PTt _X ~XX[TiT2TAXX[P[aQxT4T@PP{P{t XRr t;# $  %!r"p;# $  %!r"u?[gRSRbRHRQRR {RTKTiQX%vXvzr TiTTQq Ru .Q2QHQ+Q4QQoQQ;QQXP iR~Rv FRFW{ _Rz QK$KU$KKVKKUKIKTIKKSKK|hKKTK.KP.KPKQpKuKQuK}K?p K$KQ$KLKUpK}KU3KFK q 3KFK03KFKUQKpK8QKpK0QKpK\pKyK 7p yK}KQpK~K0pK}KUKK@KKUKKSKKVKKXKK0KKSKK|hJlJUlJJ]JJUJJ]JJUJJUJ0JT0JJSJJTJJTJJSJJTJJs@JJSJJSJJQJJ^JJQJJQJJ^JJ^7JTJPWJZJp?ZJaJPaJtJ\tJJPJJ_lJJUJJ | v"|JJ_|JJSJJTJJT|JJUJJ | v"JJ@JJSJJTJJs@JJ}JJ ~ JJQJJ\JJu`IIUII\IIUII\`IITIIT`IIQIIVIIvxIIVIIV`IIRII^IIRII^`IIXII]IIXII]dIITdIIUP@c@Uc@CVCrDUrDEVE.EU.EeEVeElFUlF;GV;GTIU@@P@@P@@P@APA0AS0ACAPVAiAP}AAPAAPAAPABP$B7BPKB^BPrBBPBBPBBPrDDSDDPDEPEEPEESlFFPDDsp"1DDP@@P@@PjApAPAAPAA0AAPBBPDDPDD0.E4EP:EQEP~@A0A!AP$AC\rDDPDD\DD0DD\DE0EE\lFF\FF0FH\H@I\EITI\@@P@@PAAPAAS5ACAP[AiAPAAPAAPBBP)B7BPPB^BPwBBPBBPBBPFGP"G,GP'CQCPE#EP HQHPFFPG!GP;GPGPPGTGUTGGVHHVHHQHHVI;IVEITIVFFPG!GPDGPGPPGTGUTGGVHHVHHQHHVI;IVEITIVWGpGPpGGSHHSI%IS%I6IP6I@ISEITISDGWG0DGPGPPGTGUTGWGV`GeG}eGpGQpGqG}`GpGPpGqGSGG@GG GGS]CtCP{C}C0G HP H HPfCtCPHHPHIS]>,?0,?C?]p;u<0<<P<=]=>]>,?0,?C?]p;u<0u<`=}=>}>>T>>}>,?0,?,?},?C?0p;u<0u<@=V@=V=PV==V==P=>V>>V>,?0,?0?V>?C?0p;`=S=:?S<< s $ &<<U=>0Z>c>0c>{>^{>>~>>~~>>~: ;U ;/;S/;0;U;;P99U9:S::U::S::U9S:\::S::@::6::W::4:: ::H4U4U U $$6U404^^ $^$6040000T9r0? $0404_\_\mm_ $_$60404K\KV\V\ $V$60SS 6S]] 6]USUSUST.V.T  wS  P ' S' W v(d r Pr x S     p`# p`# <$ c ~`# <$d x ~`# <$ vv" P c ^d x ^  \  0  P  S89P8:9QP+ PQQ + Q # 0 # 0 # P  U s U ) P) > S> k Pk n Sn r Pr s S 7L7UL77U 7H7TH7w7Vw7x7Tx77VM7Z7Px77P55U56V6?6U?66V66U66V66U56T6?6T?6F6TF66\66T66T66\66T66P66P66\T6g6Pg66S66UF66]66n2(3U(34\44U223T23(4V(404T044T223Q234]44Q63Y3PY3c3pc3t3Pt3~3^33p33P33S34P4,4,4h4L3p3Qp3~3R33Q33R3 4T 4 4tp 44T414^4(4V(404T0414T404|I4R4QR4S4VI4R4TR4S4]I4R4|_(l(Pl(v(u_(v(3_(l(ul(v(P''U''U''U''T''Q''T''T''Q''R''Q''QP''U''U''UP''T''Q''T''TP''Q''R''Q''Q0`U`SSU0`T`^TT0`Q`VQVQQ0`R`]R]RRD\~1$~"3$U"T $ &33$U"\~1$~"3$U"T $ &33$U"\`iP{P0%%U%&S&&}&+'U+'9'}9'@'U@'E'U0%%T%&_&9'}9'@'T@'E'}0%%Q%9'|9'@'Q@'E'|%%V%%vb%%0%%p 9'@'0%%Q&&Q%%P&&Pb%%0%%^%%~%&^&'}+'9'}9'@'0c&u&}u&&]&&}&&}&&]+'9'}K&&_+'9'_c&&S+'9'SK&X&V_&u&Vu&&}&&t&&T&&}#+'9'V%'\+'9'\&&P&'}+'9'}&&V&&v8$8&2$p"&& v8$8&2$p"c&c&5c&c& c&c&^#|$U|$$U$$U$ %U %%U%$%U#w#Tw#$S$$T$%S%%T%$%T#w#Qw#$V$$Q$%V% %Q %%V%%Q%$%Q##P##p$$0$$0$$^$%^<#w#0##r ##t %%0##Q$$q$!$qpI$Y$RY$m$q %%qp$$P$$P$%P<#w#0w##\##|#,$\,$_$|_$$\$%\ %%\%%0$!$T3$m$T %%T%%q`$!$X>$B$RB$$X %%X#$P %%P#$Y %%Y !U!7!S7!p!wp!{!{!!U!!S!*"w*""U""w !T uF!q!S!!S!!s""S""P""P{!!|I"o"|o""P{!!VD""V""v""V{!!_I""_{!!}D"d"}{!!]""]{!!^""^o""q2$u"""q2$u"o""v8$8&2$u"""v8$8&2$u"""v8$8&2$u"((U(=)S=)>)U>)Q)UQ)b)Sb))U()0) )P!)&) &)<)P>))0(( uu@()Q>)Q) uu@b)|) uu@()P( )s ))T))s()s()Pt u T p p# p`# tp# Q P 4 T2D2UD22S22~~22U22S22~~22U22U2D2TD22V22T22T22T22V22T22T2D2QD22]22Q22Q22Q22]22Q22Q2D2RD22\22R22R22R22\22R22R2)2u)22^22U#22^22U#22uU2Z2|Z2u2PU2u24U2u2^`U< ]< H UH b ]b k U`T< VH b V`Q5 SH [ S[ ^ sp^ b SP}q $ &}} $ &P\H b PP0< \H b \P\V 0 SH H S 0 VH H V 0 ^H H ^ PH b P  S  V  ^ZUZ^UH^H\UQTQ]TH]H\TZQZHQH\QZRZ\RH\H\RlSHS?ZSZ_H_HRSP\QTQZ]ZVUVVUHVH\TT__PPSS__UVU(4^(3 p $ &37 s $ &USUSUUSss $ &0yTyTMYQYn t2$x"#4nyRU)S)*UUPU0//U/0S0 0U 0#0S#0)0U./U/[/S[/\/U\/a/Ua/o/So/u/UWWUWXSXXUXYSYYUYPYSPYUYUY#YsY#YsY#YsY0Y Y#Ys U S"U"rSrU'T'V"]V]_P_rVrTdlP3  303}@3}S?LPL}\V]d2]d 3JP,2,U2,h,Vh,k,Uk,,V,<,T<,j,\j,k,Tk,,\,G,QG,,Q-,H,0H,L,Pk,,P,,R+:+U:++\++U++\+:+T:++^++T++^+:+Q:+V+SV++Q++P++p $  $-(q++ q++  U uh U T T q Rq w Rw y Ry R q Zw Z 0  [  p * X- q [q 0 0 T t  u|#- 4 T4 7 pD W T^ b tb q u|#q 00 C UC n Sn p Up w S0 G TG o Vo w TH _ P_ i sp u P U S U S U U S T V T V T V P P P0_U_VUV07T7\T\@JUJrVrvQvwU@UTUcScvRvwT@UV}U}V.U.VU@T|]|}T}.].5T5]v\S} S R.:v:\S\S P}Pv  \c c c\SWRWXuSWQWX]SWs} }d}S dUS.  (s U  S  U  S $ U$ * U Q$ * Q P ) P) * u t $ & P  \  \ T  V  V  ^  ^ P ] $ P \ V ^G P P U V U VU T _ T _T Q \ Q \Q R ^ R z^zRR P S %P%XSXdPdS R ] ]R U SS(S T VT9V 4}4]}*\kPS(P(QS*S04^0QTPThSsS'<'<S',},<\l\UvFQSs0s0s}Q | Q|V\dUdU}P_U_/0/LPLn__UdSPnSSPSdnPPQQRX))U)*^**U**U**U**U))T)*~**T**~**T**~))Q))w)*Q**Q**Q**Q**Q))Q))w)*Q))T)*~))U)*^**S)*~*`*_`*v*v**_&*f*Qf****}x**Qj**]**P{**P**]{**2{**w{**~{**P**]{**2D*T*qT*j*PD*j*6D*j*\,-U--V-T.UT..V..Q..U..U..V..U..V..U,- T.q. .. .. .. ,-W--ST.q.S..S..S..S,-U-{-V{--ST.q.S..U..V..S..V,V-0V-h-U..0r--P..P- - - -W{--_--\{--S{-- -.S*.T.S..S--P--V*.;.P;.T.V..P..V-- A--Sq..V..Q..U000U01S11U11S11U11S000T0111T1111T1111T11000Q00V01Q11Q11V11Q11V00V01Q11Q11V01111101S11S11S00]0 1T 11x1b1Tn11T11T01V11V000F1^F1R1rpR11^11^0-1_-151x511_11_0b1Yq11Y11Y11Y00R11R11 @00400T11V1111_45U5%5U%5/5U/55\55U55\55U45T5%5T%5F5TF55V55T55V55T45Q5%5Q%5P5QP55Q55Q55S55s55}%55S55}55S55P55st"%575P75F5st"1F5f5vs"1K5`5T`5b5tpb5f5Tq55Sq55Vq55|7 7U 77U77U7 7T 77T77T77U78U88U88U77T78V88T88V88T88V77Q78]88Q88]88Q88]77Q78]88Q88]88]77T78V88T88V88V77U7^8\88\K LU LWL_WLLULP_P$PU$POW_OWTWUTWW_LLP,LWL\LL\,LWLVLLV,LWLSLLS=LGLPLLP,L=L\,L=LV,L=LSLP_OPOW_TWW_qMMPLPSOPDUS\UOWSTWWSLL1LLPLLQ8MqMV8MqM\.MqM]NMXMPqMMP8MNMV8MNM\8MNM]MPSOP,RS\UUSV0VSW/WSMP_OP,R_\UU_V0V_W/W_MM p1OPQ p1MP\OP,R\\UU\V0V\W/W\MNVMNMNMNVMNMNMNPNONVNONNON!NONV!NON!NON8NONPyOO_RiR_RDU_\UV_5VV_4WOW_TWW_yOO#R,R#\UhU#yO{O0{OOPOOpOOPOOROPQ_OPQPOPkPpOPQpSPkPQkPyPp kPQp oPyPQyPPpyPQp}PPQPPpPPpPQp PPpPPpPQp PPpPPpPQpPPQPPpPPp PQp PPp!PPp$PQp$ PPp%PPp(PQp(PPQPPp)QEQPEQIQp"Q'Qp1$q""Q.Qp1$q"3QEQQ3QEQQ6QEQRiQQPQQppQRPpQRQQQPQQppQQPQRppQQRQQRQQRQQR\UU_iUUPvRRVvRR_RRPRU_UV_5VV_4WOW_TWW_RDS\DSGSPGSSwST\UU\UU0UU\RKS]KSSPSS~ST]UU]TUPRU0UV05VV04WOW0TWW0R SZ SSzhUUzhUU0 SSZUUZRRpRSXUUX_SS__SSz|_SSRSS~_SSz_SSzSS\SS}pSS@SS SS]TT0UV05VV0VV04WJW0TWW0WW0T T~UUP8VXV\VVVTT_UV_5VV_VV_4WJW_TWW_WW_^TpTPyTTPTTPTTPUUPUVVAVXVPiVVPVVPVVPVVVVVP4WIWPWWPWWVT2TP2TT]UUP5V@VP@VXV]XVzV0VV]VV]VVPTWW] TT_UU_XVzV_VV_TWW_ T3T 3T;TPTWgWPhWW_UUHUU0UU U4UU4UU4UUDU U4UPJP P$PU$PJP_.PJPP,d       9>ACFQxx| *)SX 05:@nOh"'3"'3TY}O[]dRV] 0 P P  0 P P {!!!"""{!!""`"h"p""""`"h"""%'0'9'.&5&B&G&c&c&_(e(l(v(((() )))* **`*f*{**D*D*I*Q*;+>+c+n+q++,,,-X.x.....,,- --.0.X...0111110000U2U2`2j2D3c3k3~333334%4,41464<4I4S455+5555q5w5{55777 8 888888s:}:::s:}:::::::::O<T<<<<<=>`>>@@@@BQC E0EFH HXHHHI;IEITIFGHHI;IEITIDGGHHI;IEITIQCChEpFH HXHHHIhEEXHHHIEpFHHdIdIxII_JJJJ|J|JJJJJJJJJJJJJJJpKpKuKwKyK~KKKKKKKKK,LWLLL0LWLLLWL\LL POPiSiSUUUUOWTWWMPOP,R\UUV5VW4WyOyOOOOP\PaPdPhPkP\PaPdPhPkPrPvPyPrPvPyPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPQQQQQQQQQQQQQQQQQQQQQQQRiSiSUUV5VV4W@WEWOWTW`WcWWUSeSiSiSiSSSSUS_S_SeSiSiSiSSSSiSqSSSSSTTUV8VV4W@WEWOWTW`WcWWTTTTUUUV8VV4W@WEWOWTW`WcWW T;TUUTW`WcWW T;TTW`WcWWUUUUUDUYYYYY0YYYZ ZUZaZZZ@[]^_`_`8`` aHaaa0bstruct_FILE.hFILE.hstdio.hsys_errlist.hresource.hstruct_iovec.hsocket.hsocket_type.hsockaddr.htime.hpwd.hstruct_tm.htime.hunistd.hctype.hconfname.hgetopt_core.hstdint-uintn.hin.hnetdb.hun.hlsapidef.hstring.hresource.hdlfcn.hsocket.herrno.hselect2.hsched.hmman.hsendfile.huio.hstrings.hinet.hwait.hprctl.hgrp.h KK.K5J/I#KK1 0 z zJ Z " OJJ = ...v <K gfJ.T2KxJ.n=@<YDw<<=:/;<;/u;=IK=H</փ-K-=>:X-=;=0:/;=I<//sf=H</[G-K-=18=;=0:X;=-/I=;/?Gf-K-=I<-=;=-/e=-/t0//-</-</-</-<///-<///-J=t=Y-</ȑ-</J>Xtu-=ttu;/K-=-/X-/t;/gK-=Y-=;=J;=/K-=-/X;/u-=ttu-=K;</f;=;/fu-=t.V>,>t;=/.K-=-/t-=-//-/-X.I</t.W=-/0,0,<.W=-/t/t;=;/H ># K# = l Z< < h u$I$K="IY<IJ =$J$<=;"<J = vXF.L L = /d f.L u /O7@p$tik<=<>V L a$f mX Xm< .>m<X N1+ pk " kJJ k.XX"~K k  [ X O(kX  < kX  b>= E<>:<Y<; = vk<q R< !l   l<lz/ f X< Kffkv ~*~ X$ rJ~ # .?f h ~~<  .<1 ~) < ~t)X ~<= jtt        Z-JJXft X L!s gf  fF J Y Y :"foXXXJlt0 hd/ L. XN6g J yi< X$   Z  4tKK  ;:|". < Z IY6t(f+K"JMX"X< mJ< & AJX0J XXXV$J)I!4f<9X!Jh  .$r.XX`KJ Jt5<uY"J q<% 3$x.`XYBW[$g   F x \ *2. F^ \t;:j KK-uYIX Ki+JJK2KKu\/ u  u  (tX |  x(9?JL6J9xX<u1tu6,XJK,@g L,K /sJK u XQy  X KEW \ g x. < %  /s u Z ptt  /t.X  o tK !f J/ kt Zs gY  Z Y g Y  #!xwJKxJK K!JK sJ  s< ! KJ9J!JK!s  f K =J YYt YYt YYJ YY<xK t<YL ,<W ue [A<v v .KXe#!CJ;Cg K E dX ` x DNK$ JG MY<," g <    =  &> t u X   Y r< f Kr  < r rJ huJL |   fX.X  ]u u<   Z = = y<kJK,&J"Irt &s=r< !rff  "yJD!IK L%; K%H K KKK.7 .XB#I1u#J Q  F Z  KNJ U  X  hJ.$ .Xhr / X L*~Jf-S. LKI u YZ .HJ K Y)%fX80JJ )X%<XX$%4HJL<0YBL=;B=Vv<)/Mt z0<6u  zt/  L4K"vI4H =" @"F %#K%W Yz Q*uJf  uJ K mJJ .I  <vJ uMF =0J u) Y%#K,K"9 =& =X YsJY FX:JJ Z L N*<xX<JX>tJ e < 7/t  L4K xH4 = K *vJfJ  uJ  Y.W mJt mX K t Km \x JYKWiX<JJz NS =;0WX Y)? K  LeJf<Ki*_8tK )^ ~tf<_K z.` ztf< XKJZfv*=gJ Z AK=%, =%H KM, tY,Lho!(fot(= -K l X|K<x < o.K Ms f sf tJt    Z 93JJM _< . jy 93JJ Kw ' K"f/ s XM X X mXL  f   yr rX' =P Yr J:h6t YGu  uf>= . f  K  ^tj  !tJ<   jF % =%H K  Z7)K LK)8 K! K 2%o = K%: K2 GK  _X#< ]< <& Y ZX [f<Ȃ _Xy q   KK&,N>:hZs"  [sf  "Ui Xi g Y .. - sX ... K fh00< =  h+< Y  u<   Y Jz   . L+< g  /.  L g J JK*X.X v6= Y; u/ Xl f? lJXY lf"Kl "K8G8=P.4XK%      J.Jp<J*<X v6= Y;. / Xl f lJXY"=8G8= I/..c<<jBz<  sX&`" f [Z M   L  Y 0 U= =Y K ^f 4I gYK$/ fY L y^ /K-%]  K+/X>0XX<uj Yv Xg Y IgZ$Hv&L<X(.= /.u.Z .fJOwX(WuO=.ft"<*w  <K t Y /?N&tuKK  h g G] t Y t YtM   t  Y IgYJvYY g r Y >v t YK, <Y ._ho<x }KYWJtbXK X 9    ft "u ; <u WY rXu WY X"0", XX LXJ<f?JfjK t Y*=K t ,=K t 0=K t .=K t Y,=KgjKK 2K zt/ Y Z  c    Zc  cf  Zc <<   a,<  Zci  Zc x    Zc w X     c       Yc  v    Yc  v    Zc  w    Yc  v  Z [    Zc   g     Yb  f }r       g {  g1J }  <1-u-).K.X UJ.< Z .)J KIK XxK +zz< O=>;g< 0:>< Y6 2 _< < Z    \_<   _X<   _ @ /        J       f :v ZYw Yu    Zv  .X t   tXI/ /    u ~ft  Zr> Z J  z  X/X < zX   tX /  `ggWK>X u ~X~ }XYX |X |<Y ^  X ./ XR XUJ Y   h.eX> tYvtYK   M U -/](tq $~Zv <Qyt/Z t   t Z*(t N   bX J| < y  !#J Y  Z+KZ)=1K- M< <Y v.u. }Jt ZY< gJ f"<  /  np < }2NX)     ~ |X}Y"Xg![qg!p'Y>tYK&CXK%.ZY&i fYp<x u   Zv X w ~9}5Xl t.Z7j.+"<g7/W5K/I Mu_Kg\K _SC_THREAD_SPORADIC_SERVERpthread_atfork_functotalLSAPI_Set_Max_Process_Timelsapi_parent_dead__fxstatparseContentLenFromHeaderugidLen_SC_2_SW_DEVm_pScriptFileLSAPI_Stopsi_addr_lsb_unused2_SC_TIMERSm_iReqCounter_fileno_SC_SHELL_SC_MEMORY_PROTECTION_SC_SCHAR_MAX__pathtm_secH_AUTHORIZATION_SC_THREAD_SAFE_FUNCTIONS_SC_UCHAR_MAXmax_lenfreeaddrinfogid_tverifyHeader_SC_C_LANG_SUPPORTm_pIovecEndstrcpy__uint8_tIPPROTO_TPpw_uidwaitpidHTTP_HEADER_LEN_SC_TTY_NAME_MAX_SC_PASS_MAXLSAPI_ErrResponse_rsi_uidm_bytes_SC_2_PBS_TRACKfp_lve_destroym_pHeader_IO_buf_end__RLIM_NLIMITS_SC_SELECT_shortbufrlimitsockaddr_insa_family_tSOCK_DCCP_SC_BC_STRING_MAX_ISpunctis_enough_free_meminet_addr_SC_TRACE_INHERITinit_lve_exnewSizem_tmStartliblvesetgroups_SC_SEMAPHORES_SC_EQUIV_CLASS_MAXread__environ_sigpollsa_datauint16_t__builtin_memmoveai_protocol_valuem_pChildrenStatusCurIPPROTO_UDPoverflow_arg_areatime_tsin_zero_SC_DEVICE_SPECIFICin_port_t_flagsachMD5_SC_THREAD_THREADS_MAXerror_msg_SC_LEVEL3_CACHE_SIZE_SC_TRACEreg_save_areacalloc_archm_respPktHeaderg_running__off_t_addr_bndlsapi_cleanupachHeaderNamest_size_SC_THREAD_PROCESS_SHAREDallocateBuf_SC_JOB_CONTROLgetppidtm_isdstswapIntEndianlsapi_check_child_statussignal_locks_max_idle_secslsapi_set_nblockenvirons_schedule_notifysetUID_LVE_SC_NL_NMAX__RLIMIT_NPROCRLIMIT_DATApServeratoluint32_tinitgroups_SC_POLLm_pHttpHeader_SC_V6_ILP32_OFF32_SC_TRACE_SYS_MAXm_pScriptName__builtin_va_listst_blksizeRLIMIT_NOFILEm_pEnvList_SC_BASE_sigchldLSAPI_Set_Max_Idle_Childrenint32_t_SC_LONG_BITfixEndianLSAPI_GetEnv_r_upper__fmtsa_familym_specialEnvListSize/builddir/build/BUILD/opt/alt/ruby26/lib64/ruby/gems/2.6.0/gems/ruby-lsapi-5.6/ext/lsapipw_passwd_SC_CLOCK_SELECTIONmasklsapi_resp_infosigaction__RLIMIT_RTTIME_SC_V7_LPBIG_OFFBIGbodyLeftfcntllastTime_SC_AIO_LISTIO_MAXLSAPI_Init_Prefork_ServerpErr1pErr2st_gidm_cntHeaderss_notify_scheduledm_envListSizeacceptinggettimeofdaypBufai_addrm_iAvoidForks_secret_timerlsapi_MD5Context__syscall_slong_t__builtin_memset_SC_FILE_SYSTEMsa_restorerm_pChildrenStatusEnd_IO_write_endtype_SC_SCHAR_MIN_SC_LINE_MAXLSAPI_SetRespStatus_rlsapi_MD5_CTX__resst_nlinks_addr_SC_TZNAME_MAX__va_list_tag_syscallst_ctimnameLen__builtin___snprintf_chkLSAPI_Postfork_Child_SC_2_VERSIONfree_SC_2_PBS_CHECKPOINTIPPROTO_MPLS__sigset_tm_requestMethodOffm_tmWaitBeginreadSecretreadReq__tznameatoig_initedgetaddrinfovalLens_acklsapi_jailLVE__d0_SC_LEVEL4_CACHE_ASSOClsapi_MD5Final_SC_NL_LANGMAXdoAddrInfo__stack_chk_failmemcpy_killcurSizeRLIMIT_STACKIPPROTO_IPIPdlopenbacklogsin_family_SC_LEVEL1_ICACHE_ASSOCpIovrlim_maxm_iKillSentm_fdListen_SC_AIO_PRIO_DELTA_MAXvalidateHeadersst_atimm_statusm_reqBodyLensig_numoptargSOCK_RAWsnprintfold_int_SC_2_C_BINDs_enable_lve__clock_tparseRequestIPPROTO_RAWstrdupbufLen_SC_PRIORITY_SCHEDULING_SC_SS_REPL_MAXsys_errlistsival_ptrpStderrLogsetpgid__uid_tdaylightsi_stimeoptoptLSAPI_ReqBodyGetChar_rpKeysun_family__uint16_t_SC_FSYNCsin_portgetpeernameLSAPI_is_suEXEC_DaemonLSAPI_Is_Listen_rLSAPI_End_Response_r_SC_FILE_ATTRIBUTESsetreuidserverAddr_SC_NZEROm_pQueryString__gnuc_va_list_SC_2_C_DEV_chainpContentLen_call_addrEnvForeachnewfdm_iServerMaxIdleSOCK_NONBLOCKusleepSOCK_RDM_SC_SYMLOOP_MAXsockaddr_un_ISblankunsigned charIPPROTO_MAX_SC_MQ_OPEN_MAXSOCK_DGRAMm_tmReqBegin__fd_mask__blkcnt_tlsapi_enterLVE__builtin_calloc_IO_lock_tLSAPI_Is_ListenIPPROTO_COMPLSAPI_key_value_pairlsapi_check_pathLSAPI_ForeachHeader_rpHeaderName_SC_SEM_NSEMS_MAX_SC_USHRT_MAXLSAPI_FinalizeRespHeaders_r__read_alias__fdelt_chkshouldFixEndianpBody_SC_STREAM_MAX_SC_ASYNCHRONOUS_IOserverMaxIdle__open_alias_SC_READER_WRITER_LOCKS_SC_CPUTIME__getcwd_alias_SC_2_PBS_LOCATE_SC_DEVICE_IOsa_flagspVecgeteuid_SC_SIGNALS__ctype_b_loc_SC_V7_ILP32_OFFBIGstatusoff_tchild_statuss_notified_pids_max_reqsH_X_FORWARDED_FORs_pid_dump_debug_info_ISalpha__fprintf_chktm_zone__mode_tm_queryStringOff_SC_V7_LP64_OFF64_SC_NPROCESSORS_CONF__RLIMIT_SIGPENDINGfdInlsapi_changeUGidtv_usec_SC_XOPEN_XCU_VERSIONold_childold_termLSAPI_sendfile_rlsapi_lve_erroraccept_SC_MEMLOCKallocateRespHeaderBuf_ISprintsched_yieldpMessages_liblvepValueH_CONTENT_LENGTHm_tmLastCheckPoint__vfprintf_chk_ISalnum_SC_SEM_VALUE_MAXs_req_processedstrtollopen_SC_XOPEN_XPG2_SC_XOPEN_XPG3_SC_XOPEN_XPG4LSAPI_STATE_CONNECTED_IO_write_ptr_SC_REALTIME_SIGNALSsystemlsapi_packet_headerIPPROTO_ENCAP_ISspacelsapi_suexec_authgetLFg_prefork_serverva_list__suseconds_treqsexitLSAPI_CreateListenSock2__rlim_ts_ignore_pid__RLIMIT_MEMLOCKpCurpHeaderValue__sizesizes_slow_req_msecslsapi_init_children_statusgetuidFILEH_COOKIELSAPI_ParseSockAddrdlsympthread_lib_SC_PII_INTERNET_DGRAM_SC_SINGLE_PROCESSbyteReversedump_debug_infoLSAPI_Accept_Before_Fork_SC_SHRT_MAX_ISxdigit_SC_RAW_SOCKETSfp_lve_enterLSAPI_AppendRespHeader_rsize_tH_CONNECTIONLSAPI_GetHeader_r_SC_MULTI_PROCESSs_stderr_log_pathm_statefp_lve_instance_init_SC_BC_BASE_MAXH_CONTENT_TYPELSAPI_STATE_ACCEPTING_SC_RTSIG_MAX_SC_NETWORKINGachCmdH_ACCEPT_SC_GETGR_R_SIZE_MAXperrorcompareValueLocation_SC_THREAD_ATTR_STACKADDR_SC_LEVEL2_CACHE_ASSOC_SC_IOV_MAX_SC_TRACE_EVENT_NAME_MAX_SC_PII_INTERNETIPPROTO_IGMPpServerAddrlsapi_acceptlsapi_initLVE_IO_save_baseLSAPI_Release_riovecold_usr1maxIdleChldsocklen_tm_iMaxChildren_SC_2_UPEai_canonnameIPPROTO_IPV6_SC_DELAYTIMER_MAXpw_dirsa_mask__sigval_tLSAPI_Set_Extra_Childrens_restored_ppidsin6_flowinfototalLenm_pid_SC_SYSTEM_DATABASElsapi_prefork_server_acceptm_pIovecToWritecodem_respHeaderLen_wide_dataH_IF_MATCHai_family__nlink_tsi_addrst_inost_modeLSAPI_IsRunning_SC_T_IOV_MAXCGI_HEADER_LENIPPROTO_DCCP__in6_uGetHeaderVarH_ACC_CHARSET__stream_SC_XOPEN_STREAMSm_iMaxIdleChildrensendfile_IScntrlm_reqBufSizelsapi_child_statusprctlallocateEnvList_ISupperpStatuserr_nosival_intsi_codem_pReqBufwait_timestrcasecmpH_IF_UNMOD_SINCEpw_name_SC_TRACE_USER_EVENT_MAX__socklen_tsend_notification_pktlsapi_requestpKeyEndcurTimefprintflsapi_writev__ssize_t__srclsapi_closepChrootH_IF_RANGEtimespecnameOff__u6_addr8strerror__RLIMIT_RSSavoidForkm_packetLenLSAPI_ReadReqBody_rIPPROTO_MPTCP_SC_2_FORT_RUNbindfp_lve_leave__valin6_addr_SC_ADVISORY_INFOpacketLen__timezone__ctype_toupper_locsin6_addr_SC_TIMER_MAXpBufCur_SC_THREADSunset_lsapi_envs__sighandler_t_SC_USER_GROUPS_RLSAPI_Set_Server_fdLSAPI_CreateListenSock__RLIMIT_LOCKSm_respPktHeaderEndLSAPI_On_Timer_pfLSAPI_Set_Max_Reqs_SC_UINT_MAXst_uids_conn_close_pktLSAPI_Postfork_ParentpEndpktTypelsapilib.cset_skip_write_SC_TRACE_NAME_MAX_lowers_busy_workers_SC_THREAD_DESTRUCTOR_ITERATIONSm_flagmemsetlevelstderrm_pHeaderIndexnameidle_SC_CHILD_MAXlsapi_reopen_stderr2_IO_save_endtm_min__nptrLSAPI_InitLSAPI_Request_SC_V6_LP64_OFF64flag_SC_NGROUPS_MAXm_bufProcessedfixHeaderIndexEndianstdoutfp_offsetlsapi_MD5TransformLSAPI_Write_Stderr_r__time_t_SC_THREAD_ROBUST_PRIO_INHERITgp_offset_padLSAPI_ForeachOrgHeader_rsigaddsetLSAPI_Inc_Req_Processedm_httpHeaderLendyingrealpathtm_yday_SC_SSIZE_MAX_SC_PII_OSI_CLTS_SC_SYSTEM_DATABASE_RmsecspAuth_SC_LEVEL1_DCACHE_SIZEkeyLenextraChildrenLSAPI_Flush_rshort unsigned intrlim_cursigned charLSAPI_Reset_rs_lveold_ppidLSAPI_CB_EnvHandler_valueLen__blksize_t_SC_STREAMSSOCK_STREAMdigestpBufEndGNU C17 8.5.0 20210514 (Red Hat 8.5.0-20) -mtune=generic -m64 -march=x86-64 -g -O2 -fPIC -fexceptions -fstack-protector-strong -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection=full -fplugin=annobin_SC_PAGESIZE_SC_THREAD_PRIORITY_SCHEDULINGcountsi_pidIPPROTO_MTPs_stop_SC_CHARCLASS_NAME_MAXlsapi_header_offsetstrchrvfprintfsetgid_boundstm_wday__off64_t__fd__lenachBuf_sigsys_IO_read_base_SC_XBS5_ILP32_OFFBIGsend_req_received_notification_offsetIPPROTO_EGPLSAPI_reset_server_statesockaddrsigset_ts_defaultGids_keep_listenersecsm_cntUnknownHeadersreadfdsai_addrlenlongsopterr_SC_DEVICE_SPECIFIC_RLSAPI_Set_Restored_Parent_Pidpw_gecos_modem_iExtraChildrenLSAPI_No_Check_ppid_SC_PIPE_IO_write_base_SC_XOPEN_CRYPTvalueLenm_respInfotz_dsttime_SC_PHYS_PAGESlsapi_enable_core_dumpH_CACHE_CTRLH_COOKIE2_SC_ATEXIT_MAX__desttm_monclose_SC_SHRT_MIN_SC_FIFObitstimeH_USERAGENTs_min_avail_pages_SC_USER_GROUPSm_lLastActiveLSAPI_ForeachEnv_rlong intSOCK_PACKETsa_sigactionnotify_req_received_SC_XBS5_ILP32_OFF32dumps_worker_status_IO_marker__builtin_strncpys_ppidtm_yearlimitmax_children_SC_2_PBS_MESSAGEm_pRespBufEndtimevalorig_masktmCur_SC_XOPEN_REALTIME_THREADSfp_lve_is_availablepAddrs_defaultUidm_pChildrenStatus__fds_bits_SC_SPIN_LOCKSLSAPI_Set_Server_Max_Idle_Secswritem_bufRead_SC_SPORADIC_SERVERlsapi_close_connectionuint8_t_SC_LEVEL1_DCACHE_LINESIZE__sigaction_handlerlsapi_signal_SC_PRIORITIZED_IOin_addrSOCK_SEQPACKET__pid_t_IO_codecvt_SC_GETPW_R_SIZE_MAXpUgidheadershints_SC_XOPEN_VERSIONH_RANGE_SC_BC_SCALE_MAX_SC_2_C_VERSIONdup2strtolg_reqlong doubleparseEnvai_socktype_SC_THREAD_KEYS_MAXiov_len_SC_LEVEL4_CACHE_LINESIZEfd_setlsapi_MD5Init_SC_NL_TEXTMAXnonblocklong unsigned intlsapi_req_header_SC_LOGIN_NAME_MAXfind_child_statusIPPROTO_PIM_SC_XBS5_LP64_OFF64_SC_SPAWNmaxChildrennewlensi_statussigemptyset_pkeym_headerOff__RLIMIT_OFILEHTTP_HEADERS_SC_2_PBSs_proc_group_timer_cbpw_gid__errno_location_SC_XBS5_LPBIG_OFFBIG_SC_WORD_BITchar_SC_2_PBS_ACCOUNTINGm_pSpecialEnvListsin6_scope_idstdin_SC_AIO_MAX__oflag_SC_2_CHAR_TERMresolved_path_SC_LEVEL1_ICACHE_LINESIZE_IO_buf_baseai_flagsrealloc_SC_XOPEN_SHM__dev_t_SC_XOPEN_ENH_I18Nold_quitRLIMIT_CPU__glibc_reserved_IO_read_end_SC_ULONG_MAX_SC_TYPED_MEMORY_OBJECTS_SC_TIMEOUTS_SC_LEVEL2_CACHE_SIZEfinal_SC_XOPEN_UNIXm_pRespBufPos_IO_FILEin_addr_tm_fdH_HOST_IO_wide_datacookiestrlentzname_sifields_SC_LEVEL2_CACHE_LINESIZE__u6_addr16s_pidIPPROTO_AHLSAPI_ReqBodyGetLine_rtm_hoursetsidFlush_RespBuf_r_SC_THREAD_STACK_MINisPipe_SC_PII_OSI_Mm_respHeaders_global_counterRLIMIT_AS_SC_NL_MSGMAXsi_signom_pAppData__RLIMIT_MSGQUEUEachAddrm_inProcess_SC_THREAD_ROBUST_PRIO_PROTECT_ISgraph_lsapi_prefork_servertm_mdaypIntegerlsapi_siguser1__pad0_SC_BC_DIM_MAX__pad5_SC_LEVEL1_DCACHE_ASSOCmallocs_dump_debug_infos_avail_pages__u6_addr32_headerInfom_typesi_errnofinish_closelistensigno_SC_XOPEN_REALTIME_markersLSAPI_InitRequest_SC_SAVED_IDSpBindm_scriptFileOff_SC_INT_MAXsi_bands_log_level_namess_skip_writeH_VIAmemccpy_codecvtforkIPPROTO_ESPm_pRespHeaderBufEnd_SC_TRACE_LOGgetpwnamtimeout_SC_THREAD_PRIO_PROTECTg_fnSelectRLIMIT_FSIZE__builtin_memcpyst_rdevlsapi_http_header_indexpEnv_SC_OPEN_MAXst_devssize_tdlerrorheaderIndex_SC_UIO_MAXIOVLSAPI_Logm_pRespHeaderBuf__int32_tH_PRAGMA__uint32_tqsortpSecretFile__RLIMIT_NLIMITS__daylightIPPROTO_RSVPstrncpyH_REFERERIPPROTO_UDPLITESOCK_CLOEXECLSAPI_Set_Slow_Req_MsecsLSAPI_Prefork_Accept_r_sys_siglisthandler_SC_CHAR_MAXLSAPI_Get_ppid_ISlowerpEnvEndsigprocmaskm_pUnknownHeadergetpwuidm_reqState_SC_PII_XTIpRespHeadersleftkillsysconfm_pRespBufm_iCurChildrensocketLSAPI_Write_r_SC_PII_OSI_COTSm_totalLenpasswdm_pIovecs_stderr_is_pipefstat__snprintf_chk_SC_PII_SOCKET__gid_tlsapi_sigpipe_SC_V6_LPBIG_OFFBIG_SC_MQ_PRIO_MAXgetcwdH_TRANSFER_ENCODINGH_IF_MODIFIED_SINCE__bsxai_nexts_enable_core_dump_SC_TRACE_EVENT_FILTERnodelaysin6_family__resolved_freeres_buf_sigfaultm_iChildrenMaxIdleTime_SC_THREAD_CPUTIMEsi_utimetv_sec_SC_VERSIONm_cntSpecialEnv_SC_C_LANG_SUPPORT_Rlong long unsigned intmemmovesa_handlersin_addr_cur_columnlsapi_load_lve_libtoWriteuid_t_SC_PIIsi_fd_SC_MAPPED_FILES_SC_LEVEL4_CACHE_SIZEIPPROTO_BEETPHfp_lve_jail_SC_2_FORT_DEVIPPROTO_IPm_pRespHeaderBufPosst_blockslsapi_initSuEXEC__bswap_16getpid__buf_SC_2_LOCALEDEFm_cntEnvlocaltime_r_SC_LEVEL1_ICACHE_SIZEreadBodyToReqBuftm_gmtoffIPPROTO_PUP_namesigval_IO_backup_baseH_KEEP_ALIVE_IO_read_ptr_SC_CHAR_BITLSAPI_Register_Pgrp_Timer_Callbackmd5ctx__socket_type__nbytes_nameLengetenv_freeres_list__aps_max_busy_workersIPPROTO_ETHERNETH_IF_NO_MATCHpEnvListrlim_tlsapi_readsun_pathtimezoneCGI_HEADERSsi_overrun__bswap_32pReq_SC_INT_MINlsapi_MD5Update_SC_RE_DUP_MAX_SC_PII_INTERNET_STREAMachBodyachPeerheader_SC_THREAD_ATTR_STACKSIZEfull_path_old_offset_SC_SIGQUEUE_MAXsiginfo_t_SC_FD_MGMTexpect_connected_SC_SYNCHRONIZED_IOLSAPI_STATE_IDLEvalueOffsighandler_t_SC_V7_ILP32_OFF32skipunlinksend_conn_close_notificationoptinds_accept_notifywritevH_ACC_LANG_SC_EXPR_NEST_MAX_SC_LEVEL3_CACHE_LINESIZElong long intm_pktHeaderin6addr_loopbackports_accepting_workersIPPROTO_IDP_flags2lsapi_prefork_serverallocateIovec_SC_MESSAGE_PASSING__ch_SC_REGEX_VERSIONm_iLenLSAPI_Set_Max_Children__d1setuidtv_nsecm_scriptNameOfflsapi_perror_SC_FILE_LOCKING_SC_AVPHYS_PAGES_SC_MB_LEN_MAXpHeader_ISdigitsockaddr_in6IPPROTO_SCTP_SC_PII_OSI_SC_ARG_MAX__ino_tsetsockopt_SC_MEMLOCK_RANGELSAPI_Finish_r_SC_SHARED_MEMORY_OBJECTSlsapi_resp_headersys_nerrin6addr_anym_pRequestMethodachError_SC_CHAR_MIN__realpath_chkiov_basem_lReqBegins_uids_total_pagespw_shell__namem_versionB0m_versionB1IPPROTO_GRE_SC_XOPEN_LEGACY_SC_NL_ARGMAXRLIMIT_COREsi_tidtobekilled_SC_THREAD_PRIO_INHERIT_SC_LEVEL3_CACHE_ASSOC_SC_NPROCESSORS_ONLNm_headerLenexpect_acceptingm_pIovecCurfdListenLSAPI_Init_Env_Parametersaddr_len_SC_HOST_NAME_MAXIPPROTO_TCPLSAPI_AppendRespHeader2_r_SC_COLL_WEIGHTS_MAX_SC_MONOTONIC_CLOCK__rlimit_resourcem_reqBodyReadLSAPI_Set_Max_Idle_SC_CLK_TCKLSAPI_ForeachSpecialEnv_rlsapi_buildPacketHeaderLSAPI_perror_r_SC_NL_SETMAXunsigned int_SC_BARRIERSbodyLenpBeginLSAPI_Accept_rwait_secslsapi_reopen_stderrstrcmpst_mtim__statbuf__RLIMIT_NICEfn_select_tshort intlsapi_notify_pidsi_sigvalsetrlimit_vtable_offsetaddrinfo_SC_IPV6mmapIPPROTO_ICMPlsapi_sigchild_SC_REGEXPlsapi_schedule_notifyLSAPI_Get_Slow_Req_Msecs_SC_V6_ILP32_OFFBIGstatmemchrtz_minuteswestsys_siglistH_ACC_ENCODINGsin6_portm_iMaxReqProcessTime__RLIMIT_RTPRIOGCC: (GNU) 8.5.0 20210514 (Red Hat 8.5.0-20)GNUzRx 0D LXsEIB E(A0z (A BBBI A (D BBBA  @YGJB B(A0A80F(B DBb0BFC G  AABK Hk(\GADJ n AAA 4UAGK R CAG L JCG AG] AJ t C KFLBBE A(H0H (D BBBD  (D BBBA PXvFB A(D0D (A BBBB L(A BBBA$aAAD XAAHBBB B(A0A8D@N 8C0A(B BBBH $ OAf Q C E H@HYBBB A(D0J 0A(A BBBF xFEA C(G   (A ABBD M I c A  E M A k E E E E H V HFBB B(A0A8D`` 8A0A(B BBBD lT+BBB B(A0D8JYHPC Mi 8A0A(B BBBE LTMDd6BBB B(A0A8DP 8A0A(B BBBG  8J0H(G DBBK $,7EFF IIOTh|  4FAA G>  AABG EO D  A  (Y<JEDXS l]Ph H XAHlFBB B(A0A8LP 8A0A(B BBBH < FBB A(A0 (D BBBI i`0FBB B(A0A8DP~ 8A0A(B BBBA k 8A0A(B BBBH L$FBB A(A0H Q D 0A(A BBBH LFBB B(A0A8G 8A0A(B BBBF 4FHF\$pnCXJLlFBB B(A0A8DA 8A0A(B BBBA `BBB B(A0A8G I K I L N N w 8A0A(B BBBI 0L BMD GL  AABA < =BAA G L@I@U  AABG $ TWEHG ag H SH FBB B(A0A8DPS 8D0A(B BBBF TX bIE D(C0P (F BBBM Q(H BBBAH FBB B(A0A8DP 8A0A(B BBBA T CBA A(G0` (A ABBD  (C ABBA J8T -FBD D(D@T (A ABBB  ( lECGF AAI L !cBG A(D0 (A ABBE XD0 4 ZH 10\ pFAA G@7  AABF  @LsL FBB B(A0A8G 8A0A(B BBBG   $ 8 L ` t     <  FBA K(G (A ABBG <FEE D(D0M (C BBBB X(HlFBH E(A0E8I@ 8A0A(B BBBE (FED ABH BBB B(A0A8G 8A0A(B BBBJ D0FBB A(A0G 0A(A BBBF Lx FBB B(A0A8G  8A0A(B BBBA    1 -  E2a~345.IWul -- "0s-Je s z )Y)2L0Yz+ k + w 0 Gw : X Ui s  s    x 5 P _ s(0x *  * # N0 al |  O& - =h9Y9 @ $@O e` rU+66 %  7 6S wm w   l      4 f   x    ]  '  ; ]\ m{ m     *+ *L k    \ \" k C k b    "   " $%@ `d0$%UE'xdE'''''D(m())* *+7+F+c,~, 0,.,=.u/*7u/[)0})011224C4k55667!7G7k78d X 8 8+8S:9y:9q9P q9: #h 3 (B:g0;0;H?   @  H?'^?GR^?tk?k????,?V?~???@,@T@z @+@+@?@?@;K@WK@TI ) p h d ` P H @# 80 X6TIYIzIJJJJ K(K?WTK \(b $o(|WUYUYZd Zd>qdiqdd!#$&()+2345671828F"KO(pRP [oy#)/5;AG8MXSY_ekqw+}=Nbw*@V %]+o17=CpIO@U[Tahgtms8yp6&(P,-./0) >Mcmy 1   " / 9 @C R a h v      @7      ! !'! #S!3!8!C!RK!@ Q!X!^!` p!p!Y!J!!0S!]!l!!!` "p i" %","@"#$Y"_"0%u"P'F"'F"'"(")l""""# #.#/1#00?#2P#Y#2s#z#4#5-#####7# 7l#7! $$$!$85$8ZN$@91a$9pv$:@$$0;$$$$P?$`? $p?%?%?:%?V%?u%@ % @ %0@%@@ %P@ %%%%&&& &`I4&I(B&JR&Ka&j&q&{&&&&&W&`Y &&&`d&d '.annobin_lsapilib.c.annobin_lsapilib.c_end.annobin_lsapilib.c.hot.annobin_lsapilib.c_end.hot.annobin_lsapilib.c.unlikely.annobin_lsapilib.c_end.unlikely.annobin_lsapilib.c.startup.annobin_lsapilib.c_end.startup.annobin_lsapilib.c.exit.annobin_lsapilib.c_end.exit.annobin_lsapi_sigpipe.start.annobin_lsapi_sigpipe.endlsapi_sigpipe.annobin_lsapi_siguser1.start.annobin_lsapi_siguser1.endlsapi_siguser1g_running.annobin_compareValueLocation.start.annobin_compareValueLocation.end.annobin_EnvForeach.start.annobin_EnvForeach.endEnvForeach.annobin_lsapi_cleanup.start.annobin_lsapi_cleanup.endlsapi_cleanups_stop.annobin_set_skip_write.start.annobin_set_skip_write.ends_skip_write.annobin_lsapi_MD5Transform.start.annobin_lsapi_MD5Transform.endlsapi_MD5Transform.annobin_lsapi_signal.start.annobin_lsapi_signal.endlsapi_signal.annobin_find_child_status.start.annobin_find_child_status.endfind_child_statusg_prefork_server.annobin_allocateRespHeaderBuf.start.annobin_allocateRespHeaderBuf.endallocateRespHeaderBuf.annobin_lsapi_set_nblock.start.annobin_lsapi_set_nblock.endlsapi_set_nblock.annobin_lsapi_accept.start.annobin_lsapi_accept.endlsapi_accept.annobin_parseEnv.start.annobin_parseEnv.endparseEnv.annobin_lsapi_init_children_status.start.annobin_lsapi_init_children_status.endlsapi_init_children_statuss_busy_workerss_accepting_workerss_avail_pagess_global_counter.annobin_readBodyToReqBuf.part.2.start.annobin_readBodyToReqBuf.part.2.endreadBodyToReqBuf.part.2.annobin_lsapi_close_connection.isra.4.start.annobin_lsapi_close_connection.isra.4.endlsapi_close_connection.isra.4s_worker_status.annobin_lsapi_writev.part.6.start.annobin_lsapi_writev.part.6.endlsapi_writev.part.6.annobin_lsapi_parent_dead.start.annobin_lsapi_parent_dead.endlsapi_parent_deads_ppids_restored_ppid.annobin_LSAPI_ParseSockAddr.part.13.start.annobin_LSAPI_ParseSockAddr.part.13.endLSAPI_ParseSockAddr.part.13.annobin_LSAPI_Log.start.annobin_LSAPI_Log.ends_stderr_is_pipes_log_level_namess_pid.annobin_lsapi_sigchild.start.annobin_lsapi_sigchild.endlsapi_sigchilds_pid_dump_debug_infos_ignore_pid.annobin_dump_debug_info.start.annobin_dump_debug_info.end.annobin_lsapi_check_child_status.start.annobin_lsapi_check_child_status.endlsapi_check_child_statuss_max_idle_secss_dump_debug_info.annobin_lsapi_perror.start.annobin_lsapi_perror.end.annobin_LSAPI_is_suEXEC_Daemon.start.annobin_LSAPI_is_suEXEC_Daemon.ends_uids_secret.annobin_LSAPI_Stop.start.annobin_LSAPI_Stop.end.annobin_LSAPI_IsRunning.start.annobin_LSAPI_IsRunning.end.annobin_LSAPI_Register_Pgrp_Timer_Callback.start.annobin_LSAPI_Register_Pgrp_Timer_Callback.ends_proc_group_timer_cb.annobin_LSAPI_InitRequest.start.annobin_LSAPI_InitRequest.end.annobin_LSAPI_Init.start.annobin_LSAPI_Init.endg_initedpthread_atfork_func.annobin_LSAPI_Is_Listen_r.start.annobin_LSAPI_Is_Listen_r.end.annobin_LSAPI_Is_Listen.start.annobin_LSAPI_Is_Listen.end.annobin_LSAPI_Reset_r.start.annobin_LSAPI_Reset_r.end.annobin_LSAPI_Release_r.start.annobin_LSAPI_Release_r.end.annobin_LSAPI_GetHeader_r.start.annobin_LSAPI_GetHeader_r.end.annobin_LSAPI_ReqBodyGetChar_r.start.annobin_LSAPI_ReqBodyGetChar_r.end.annobin_LSAPI_ReqBodyGetLine_r.start.annobin_LSAPI_ReqBodyGetLine_r.end.annobin_LSAPI_ReadReqBody_r.start.annobin_LSAPI_ReadReqBody_r.end.annobin_Flush_RespBuf_r.start.annobin_Flush_RespBuf_r.end.annobin_LSAPI_GetEnv_r.start.annobin_LSAPI_GetEnv_r.endCGI_HEADERS.annobin_LSAPI_ForeachOrgHeader_r.start.annobin_LSAPI_ForeachOrgHeader_r.endHTTP_HEADERSHTTP_HEADER_LEN.annobin_LSAPI_ForeachHeader_r.start.annobin_LSAPI_ForeachHeader_r.endCGI_HEADER_LEN.annobin_LSAPI_ForeachEnv_r.start.annobin_LSAPI_ForeachEnv_r.end.annobin_LSAPI_ForeachSpecialEnv_r.start.annobin_LSAPI_ForeachSpecialEnv_r.end.annobin_LSAPI_FinalizeRespHeaders_r.start.annobin_LSAPI_FinalizeRespHeaders_r.end.annobin_LSAPI_Flush_r.start.annobin_LSAPI_Flush_r.end.annobin_LSAPI_Write_Stderr_r.start.annobin_LSAPI_Write_Stderr_r.ends_stderr_log_path.annobin_LSAPI_perror_r.start.annobin_LSAPI_perror_r.endLSAPI_perror_r.annobin_lsapi_jailLVE.start.annobin_lsapi_jailLVE.endlsapi_jailLVEfp_lve_jail.annobin_lsapi_reopen_stderr.start.annobin_lsapi_reopen_stderr.endlsapi_reopen_stderr.annobin_LSAPI_Finish_r.start.annobin_LSAPI_Finish_r.endfinish_close.annobin_LSAPI_End_Response_r.start.annobin_LSAPI_End_Response_r.end.annobin_LSAPI_Write_r.start.annobin_LSAPI_Write_r.end.annobin_LSAPI_sendfile_r.start.annobin_LSAPI_sendfile_r.end.annobin_LSAPI_AppendRespHeader2_r.start.annobin_LSAPI_AppendRespHeader2_r.end.annobin_LSAPI_AppendRespHeader_r.start.annobin_LSAPI_AppendRespHeader_r.end.annobin_LSAPI_CreateListenSock2.start.annobin_LSAPI_CreateListenSock2.end.annobin_LSAPI_ParseSockAddr.start.annobin_LSAPI_ParseSockAddr.end.annobin_LSAPI_CreateListenSock.start.annobin_LSAPI_CreateListenSock.end.annobin_LSAPI_Init_Prefork_Server.start.annobin_LSAPI_Init_Prefork_Server.ends_max_busy_workersg_fnSelects_total_pages.annobin_LSAPI_Set_Server_fd.start.annobin_LSAPI_Set_Server_fd.end.annobin_LSAPI_reset_server_state.start.annobin_LSAPI_reset_server_state.end.annobin_is_enough_free_mem.start.annobin_is_enough_free_mem.ends_min_avail_pages.annobin_LSAPI_Postfork_Child.start.annobin_LSAPI_Postfork_Child.ends_req_processeds_keep_listeners_notified_pid.annobin_LSAPI_Postfork_Parent.start.annobin_LSAPI_Postfork_Parent.end.annobin_LSAPI_Accept_Before_Fork.start.annobin_LSAPI_Accept_Before_Fork.endold_childold_termold_intold_usr1old_quit.annobin_LSAPI_Set_Max_Reqs.start.annobin_LSAPI_Set_Max_Reqs.ends_max_reqs.annobin_LSAPI_Set_Max_Idle.start.annobin_LSAPI_Set_Max_Idle.end.annobin_LSAPI_Set_Max_Children.start.annobin_LSAPI_Set_Max_Children.end.annobin_LSAPI_Set_Extra_Children.start.annobin_LSAPI_Set_Extra_Children.end.annobin_LSAPI_Set_Max_Process_Time.start.annobin_LSAPI_Set_Max_Process_Time.end.annobin_LSAPI_Set_Max_Idle_Children.start.annobin_LSAPI_Set_Max_Idle_Children.end.annobin_LSAPI_Set_Server_Max_Idle_Secs.start.annobin_LSAPI_Set_Server_Max_Idle_Secs.end.annobin_LSAPI_Set_Slow_Req_Msecs.start.annobin_LSAPI_Set_Slow_Req_Msecs.ends_slow_req_msecs.annobin_LSAPI_Get_Slow_Req_Msecs.start.annobin_LSAPI_Get_Slow_Req_Msecs.end.annobin_LSAPI_No_Check_ppid.start.annobin_LSAPI_No_Check_ppid.end.annobin_LSAPI_Get_ppid.start.annobin_LSAPI_Get_ppid.end.annobin_LSAPI_Init_Env_Parameters.start.annobin_LSAPI_Init_Env_Parameters.ends_accept_notifys_enable_core_dumps_defaultUids_defaultGids_enable_lves_liblvefp_lve_is_availablefp_lve_instance_initfp_lve_enters_lve.annobin_LSAPI_ErrResponse_r.start.annobin_LSAPI_ErrResponse_r.end.annobin_lsapi_MD5Init.start.annobin_lsapi_MD5Init.end.annobin_lsapi_MD5Update.start.annobin_lsapi_MD5Update.end.annobin_lsapi_MD5Final.start.annobin_lsapi_MD5Final.end.annobin_readReq.start.annobin_readReq.endreadReqs_ackachBody.7025headers.7024.annobin_LSAPI_Accept_r.start.annobin_LSAPI_Accept_r.end.annobin_LSAPI_Prefork_Accept_r.start.annobin_LSAPI_Prefork_Accept_r.ends_conn_close_pkt.annobin_LSAPI_Set_Restored_Parent_Pid.start.annobin_LSAPI_Set_Restored_Parent_Pid.end.annobin_LSAPI_Inc_Req_Processed.start.annobin_LSAPI_Inc_Req_Processed.end.LC0.LC1.LC4.LC5.LC6.LC3.LC2.LC7.LC8.LC9.LC10.LC11.LC12.LC13.LC14.LC15.LC16.LC17.LC18.LC19.LC20.LC21.LC22.LC23.LC24.LC25.LC26.LC27.LC31.LC32.LC30.LC29.LC33.LC34.LC36.LC37.LC38.LC39.LC40.LC41.LC42.LC44.LC45.LC46.LC47.LC48.LC49.LC50.LC51.LC59.LC69.LC70.LC71.LC43.LC35.LC61.LC62.LC63.LC64.LC65.LC66.LC67.LC68.LC52.LC53.LC54.LC60.LC58.LC57.LC55.LC56.LC87.LC76.LC77.LC78.LC72.LC79.LC80.LC86.LC74.LC84.LC83.LC73.LC75.LC82.LC81.LC85.LC92.LC91.LC88.LC90.LC89.text.group.text.hot.group.text.unlikely.group.text.startup.group.text.exit.groupcompareValueLocationset_skip_write_GLOBAL_OFFSET_TABLE_sigactionsigemptyset__stack_chk_failreallocfcntlsetsockoptmmapmemsetsetsidread__errno_locationwritevkillgetppid__ctype_b_locstrncpystrchrstrcasecmpstrtolgetaddrinfomemcpyfreeaddrinfoinet_addrLSAPI_Log__vfprintf_chk__snprintf_chkgetuid__fprintf_chkgettimeofdaylocaltime_rwaitpidforksystemlsapi_perrorstrerrorLSAPI_is_suEXEC_DaemonLSAPI_StopLSAPI_IsRunningLSAPI_Register_Pgrp_Timer_CallbackLSAPI_InitRequestmallocgetpeernamedup2LSAPI_Initgeteuidg_reqdlopendlsymLSAPI_Is_Listen_rLSAPI_Is_ListenLSAPI_Reset_rLSAPI_Release_rfreeLSAPI_GetHeader_rLSAPI_ReqBodyGetChar_rLSAPI_ReqBodyGetLine_rmemchrmemmoveLSAPI_ReadReqBody_rFlush_RespBuf_rLSAPI_GetEnv_rstrcmp__ctype_toupper_locLSAPI_ForeachOrgHeader_rqsortLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rLSAPI_ForeachSpecialEnv_rLSAPI_FinalizeRespHeaders_rLSAPI_Flush_rLSAPI_Write_Stderr_rgetpidgetcwdmemccpy__realpath_chkstrdupLSAPI_Finish_rLSAPI_End_Response_rLSAPI_Write_rLSAPI_sendfile_rsendfileLSAPI_AppendRespHeader2_rstrlenLSAPI_AppendRespHeader_rLSAPI_CreateListenSock2socketbindlistenunlinkLSAPI_ParseSockAddrLSAPI_CreateListenSockLSAPI_Init_Prefork_ServercallocsetpgidsysconfLSAPI_Set_Server_fdLSAPI_reset_server_stateis_enough_free_memLSAPI_Postfork_ChildLSAPI_Postfork_ParenttimeLSAPI_Accept_Before_Fork__fdelt_chkusleepsched_yieldLSAPI_Set_Max_ReqsLSAPI_Set_Max_IdleLSAPI_Set_Max_ChildrenLSAPI_Set_Extra_ChildrenLSAPI_Set_Max_Process_TimeLSAPI_Set_Max_Idle_ChildrenLSAPI_Set_Server_Max_Idle_SecsLSAPI_Set_Slow_Req_MsecsLSAPI_Get_Slow_Req_MsecsLSAPI_No_Check_ppidLSAPI_Get_ppidLSAPI_Init_Env_Parametersgetenvgetpwnamenvirondlerrorsetrlimit__fxstatsetreuidLSAPI_ErrResponse_rlsapi_MD5Initlsapi_MD5Updatelsapi_MD5FinalgetpwuidsetgidsetgroupssetuidstrtollprctlinitgroupsLSAPI_Accept_rLSAPI_Prefork_Accept_rsigaddsetsigprocmaskLSAPI_Set_Restored_Parent_PidLSAPI_Inc_Req_Processedselectd \D   h o    2 9 H $O ,T g -o    h C M X h c z  h  h h a 8g.J5*T/0 *1%>Kw235R4Y5`6v\  "X 3/8M7`io89p3:?K_;<Rf=h{d h t8~KW>`i{h*$?*/?@GNw*"  ( h !A`!!!a"j#<q#\p$*}$$*$ %%%&A'((Y)))b***7+A+N+BW+_+}+C++++D,,{,D,,E,,h -n---F----.8.?.N.Y.~.G...H./*/ L/T/i/// /0_1111Q2v22/33-4O4|5N6h66666666I7W7777` 7` 77888#8-828<8G8T {8889'9G9$Q9L f9T 99999999999p:*:#:<:d G:Z:` d:h::::#:::: ;!;H;;;;;;|;;<<<<,<9<V<x<t<\ <<<$< :=S=e=o=}=|====<====>/>I6>@> F>w> > >>J>?K ??L#?D?Y?f?w?????@&@6@F@_@M@@@N@@@O@@@d @P@A'AQ,A@AFA%MARRAfAmAtASyAAhATAAAAAUAAAVA BBBW B4B;BBBXGB[BbBiBYnBBBBZBBB[BBB` B\BBBBhC` C\C]#C2Cd?CdEC`TC^YCqCwC\ChC*ChC_C`CazD` DDL D DbDDcE%E`1ENEUE*\EpEduEELEeEEDEE\EfEEgE<EEhEEiF4 FFjF%F,,FTGFkLFSFTXF_FPFFFFFlFFFdGm GG(G`/Gn4GQGmGG|GGGGdG`HoHH\"Hd,H`6H`DH\ZHXyHLHpHHHH<HTHHhHHDHXIh IIq+Ir7IAIKIsIIIIJJzK9LDLOLh JMUMdMh M4NOtOPuP*P.RhDR%JR$]R#}RRdR`RvSwmS|S!S"S"S# T$TT/T4GT+uT%T&T'TlThTTMTUU|*U$1UGUxSUeU}U(UyUUzUUdU`U$UTU)V{V V|,V=V%eV%V}V*V~V[VdV`V$VWW+W9WPWYWyWWW WWXh BXUXhXX$XXh XY$ YGYQYxYYYYYYYYh #Zh 3Z?ZeZ ZZZp[[[[[\C\\\t\\ \\\$] ^]u]]]]^^4^d B^$X^$]^s^^^^^_d __c +_D_c__ _ _ __I__ ` `%`\`k`-|`.```.``` a,aJ5abaqa` aa` aaaaaaabbh 3bK8bGbXb.gbpbvb{bbbbbbpb*bbbd bc` ch$cCcTcecvcccccc#ccLccd dd9dKdVdfdldd, s|2J + (LT-- -@-Hlt,4)`h)))+ (+ L+ Tw + w w  w   s @ Hs ls t s   x  x ,x 4* `x h* *  *     (LT99 9 @ 9H l t       , 4 6` h 6 6 w 6 w w  w( L T         @ H l t     ]  ], ]4 m` ]h m m  m    (LT**** @Hlt\\\k \k ,k 4 `k h  " ""$% "($%L$%TE'$%E'E''E'' ''@'H'l't('(()(),)4*`)h**+*++, +(,L,T.,..u/.u/ u/)0@u/H)0l)0t1)011212,244`2h4454556 5(6L6T7677777 78@7H8l8t8888:98:9,:94q9`:9hq9q9:q9::0; :(0;L0;TH?0;H?H?^?H?^? ^?k?@^?Hk?lk?t?k??????,?4?`?h??????@ ?(@L@T@@@@+@@+@ +@?@@+@H?@l?@tK@?@K@K@TIK@TI,TI4I`TIhIIJIJJJ J( JL JT K J K K W K W !W!UY@!WH!UYl!UYt!Zd!UY!Zd!Zd!qd"Zd"qd,"qd4"d`"qdh"d % & ' (]CC C(X 01CC3C9C> CE(CJ0CP8CU@C[HCbPCqXC`ChCpCxCCCCCCCCCCCC+C4CHCSCYCiCm C(C0C8C@CHCPCXC`ChCpC!xC+C7CDCTCgC~CCCCCCCC  $ $ $) #0 $ < $\C $7J $%Q $xV $d $7n $J z $+ $+ $! $& $ $l- $G4 $2 $ $q $k  $# $ " $. $H: $zM $Y $ e $q $J $$& $d $ $o, $ $ 4 $ $@ $ $ ) $  $ $ $y $  $, $9 $v.F $3T $\8a $9+n ${ $ $ $ $ $H) $+ $ $  $/ $  $q7  $,  $ '5 $A $rM $/b $s $  $  $(0 $ $  $/ $ $ $z5 $51 $7( $5 $B $7Y $f $s $% $m. $  $ $ $y $% $ $ $[ $D*( $/? $! L $# Y $Qp $z| $y  $2 $9 $9. $M $ $( $) $  $H) $', $18 $^ $.j $! $D $# $' $s $} $>, $w8 $2 $.. $@+: $^F $"S $v.` $n $  $# $$ $  $ $  $p $ $ $< $'( $5 $L0B $'O $\ $ i $v $ $& $I $ $/0 $ $) $  $ $.3 $1 $. $7 $o, $9 $F $y*S $` $0m $,.z $^) $ $ $" $ $E" $# $' $r $^&& $2 $M> $4Z $ f $6x $'~ $* $ $ $n5 $  $ $% $( $t $ $F $s $( $7 $8 $N $+ $U $1 $y $o $  $, $49 $$G $S $0e $k $ q $L w $c } $# $ $! $, $N $ $ $ $V $ 1 $h8 $ !( $'-5 $CB $O $\ $%i $ v $  $5 $ $ $1( $() $i! $i" $c $ $ $ 0 $*= $ I $+U $a $'m $ y $ 1 $C $;4 $m $6 $ $,+ $ $ $ $* $ $ $ $ $# $2 $U  $/ $  $Z4 $ $Y3 $$ ${4* $0 $d&6 $ < $ B $ H $-N $}.T $Z $` $xf $l $1r $x $i~ $O) $I$ $ $]6 $* $2 $ $l1 $ $j  $f  $  $^/ $R $ $/ $/ $, $]- $R $/4 $ $d $\+ $- ${1 $V  $ -& $, $l(2 $&8 $> $5D $J $$P $#%V $\ $b $$h $P(n $t $z $1 $ $5 $* $ $^ $5 $! $3 $S! $ $/$ $ $z' $  $& $& $x& $Z$ $ $ $ $ $Y0  $S, $4 $8* $P1" $f( $&. $34 $ : $@ $ F $L $R $v!X $O^ $d $*'j $p $`5v $G | $( $h $7 $$ $" $ $T% $& $O5 $) $" $ $!7 $0 $ $. $ $9 $Z. $e $ $g  $1 $!  $  $  $3 $m$ $r6* $(0 $m6 $< $!B $#H $8N $r3T $Z $` $h%f $Y#l $r $x $~ $Q' $8' $! $  $% $)& $T $" $  $l  $ $}  $ $H8 $ $- $%6 $2 $- $ $* $/ $  $& $" $e) $#  $^'& $, $'2 $8 $5> $2D $-/J $! P $$V $7\ $b $M2h $n $Lt $^z $  $9 $ $ $K $| $Q $( $E  $2 $`  $  $# $^ $ $' $# $9 $m/? $7E $cK $ Q $76W $] $0c $i $"3o $u $C{ $ $+ $C5 $* $( $ $C/ $2 $H% $# $"4 $+ $  $0 $  $D $  $ $ $' $)N $y[ $Pn $4z $2 $ $  $_  $. $ $4 $. $8 $c $ $P&- $7; $&I $W $$e $ys $O  $ $ $- $|  $?  $1 $ $e  $8 $2 $% $ " $y( $F. $'4 $I!: $'@ $+F $+L $!R $& $ $ $T $,  $ $& $ 3 $@ $4M $-Z $,g $0 t $6 $ $O# $W $z( $ $( $ $z $ $  $( $L" $/ $ < $ I $W $ $v$ $ $7+ $hO $9i $! $ $&2 $ $ $ $5" $  $gl $ $b"1: $SGP $ (]f $s| $ h  $) $ $ $^* $ $ ,5 $3BK $(X0a $0nd w $: $7- $`  $ 5X  $!P  $)( # $)09 $%Fx_ $)1l  $4 $%@ $` $L* $@2 $- p $5 l( $"6 h? $ M dV $s d `m $ r $ X $6 P $" H $T @ $0*! $8!8[! $f! $R/!0! $2!)! $K! $! $!(! $ !(" $" +" $)9"B" $)P" $"0^" $0l" $z" $" $*"" $)" $'" $" $ " $," $" $= # $C.# $8# $,# $":# $H# $W# $63d# $ar# # $## $"## $## $## $&## $^ $@ $ $$"$ $0$9$ $CF$ $R$dy$ $} $`d$ $$ $ $ $ $$ 1$ - % % j % ~$% R3% 7% pF% hJ% @V% $8 ^%Ku% $% % % X% P% $% % % ( % " %3K%3K% s % q %  &  &  &  &QK$&QKA&  E&  N&  R&  [& 8 _& 6 i&pKs& " & _ & [ &  &  &  &  &~K&K& "`&  &  &  &  & M & K 'K ' "' r !' p *'  .'  7'  ;'  A'QK_'K' $\1'J'  '  '  '  ' h ' \ '  '  ' "@ ( ( (dJD(|JN( "p_( c( l( p( y( @}( <(J(J(J( "( ( ( ( ) )  )J/)J9) "J) $N)  W) d[) bd) h) m)J{)J) $$)I) $) $Z ) $ *`I"* $K1.* 2* 7* $C* G* L* $,X* \\* Ra* $m* q* v* $.7* <* 4*dI* "* * * * *I*I*I+IB+ $6N+P@p+ t+ + + + + + + + $+ + +pF+ $q"+F ,@,@3, 7, <,@Y,@c, " t, 6x, 4},@,A,A, ], Y,A,5A,5A- - -DA:-[AD-[Aa- e- j-jA-A-A- - -A-A-A- - .A!.B+.BH. )L. 'Q.Bn.)Bx.)B. N. L.8B.PB.PB. s. q._B/wB/wB// 3/ 8/BU/B_/B|/ / /B/B/B/ / /B/B/ " 0 " 0  0 0 E 0 ?)0 " 60 :0 C0FM0Fj0 rn0 ps0F0G0G0 0 0"G0DG0 " 0 0 1 " 1 1 r 1DG*1DGG1 K1 T1 AX1 ;]1UG1`G1`G1 1 1 1 1qG1G1G 2 2 2 A2 ?%2 o)2 m.2GE2U2Gm2H2H2;I2]2F2C]2G3Co 38G3C&3'C73CVG3QCQ3 "@ ^3 "@ g3 k3 t3fC~3fC3 3 3uC3hE3 " 3H3  3 3H 4H#4I84yEM4C^4Ey4C4E4E4 " 4 " 4 Z4 V4E4C4E4C5E#5C-5FH5CR5"Fm5Cw5PF5]5\F5H5]C5C5 H5C5C5C6C*6 .6 760DL6 P6 \6Ff6F6 4 6 2 6F6F6F6@6C7@7@#7C-7@B7C+L7@a7C=k70A7CN7VA7Cb7qA7}A7Cw7A7C7A8A8A#8C-8AB8CL8BY8$Bn8Cx8?B8KB8C8fB8rB8C8B8B8C8B 9B9C*(9B=9C@G9D_9Dl9D9C9E9C95E9RE9`E9EI9 $V7: $14: ${F: $1S: $7 a: $E~: $t': $]: $&: $/; $3; $`,?;@@R; $ Z;0@m; $/8y; @; $,;@; $; $*#;?; $; $B;? < $< $5!<?8< $. H< $:P<?g< $@w< $3<p?< $r%< $6<`?< $. < $z<P?< $= \ = X = $',=`Y-= $K19=  ==  M= !!Q= !b= !f= !k= $L7w= ="{= /"= $G = $*= "= $ = $3=aZ= "= "=iZ >(_ > $,> #0> #:>@[D> "U> ($Y> $b> ($f> $o> $s> $x> "> %> %> 0&> &> 5'> +'> '> '> (> '> I)> /))? "A?]Z? W*^? S*c?]u?`_? *? *?_?_?_?c? "? +? +? "@c@ " @ +$@ +-@ +1@ +:@  ,>@ ,H@cR@co@ 1,s@ /,|@ W,@ U,@ },@ {,@c@c@E[@t[@[ A[#A[HA[mA"\AG\A\A` A\A\A\B\&Bb]LBy]YB]}B_B]B_B@`BS`B``Bo`C`EC`RC`_C`C`C]CaC9aCCCaC](CaCaD]D$J>2Ju;?J;WJ;wJJ;J;JJ<J@J!< KK=<7KAK<RK` \K<sK<K<K<K>=KW=Ks=K L=$L3L=ML\L=vL@L=LL:>L]LD>L>L> M> MC*M??MCIM'?^M]hM5?MH?M $M:M $K1M 2M  2M ;M $M a2M _2M;N%;N $U N95N $K1AN 2EN 2JN $w"VN 3ZN 3cN:mN " ~N *3N (3N " N:N " N O3N M3N u3N s3N 3N 3N:N "P N 3N 3O 3O 3O 4O 4O:'O:HO9UO9bO9oO:OO::O:O:O:O $O $O $K1 P $P $&&P $^ 3P $@P $MP $ZP $L7P $P $P $G P $*P $/P $"P $ P $3Q $Q $Q@91Q $9QLQ $TQkQ $"wQ G4{Q 94Q $hQ 4Q 4Q $5Q o5Q c5Q $Q 6Q 5Q $Q 6Q 6Q $Q ^7Q X7Q $Q 7Q 7QCR]P&RO=R[R]eR|RR R]RR $RR $R 8R 7S $"S 8S 8S $,S6SSS 8WS 8`S  9dS  9mS 69qS 29vSS]S S3S<SdS]pTm&T>TUTjTCRtTT $T T $T y9T o9T $T 9T 9T $w"T :T :T U U ;$U ;-U B;1U @;:U j;>U f;CU dU UX Us UCU $7U $U $U $2V $5V $V $= ,V $0";V $CV8ZV $fV ;jV ;oV ${V ;V ;V $6%VV $V ;V ;V $V *<V $<V V W u< W s<W <W <"W <&W <-W $5WLW $\W $|hW W $5W <W <W .=W "=W $ .W $1W Xl 0Xs NX $VX8|X $X $w"X $X $/X 7X $"*X =X =X $ X =X =Y $ Y X>#Y T>5YM7TY[7rY7Y $0Y $"*Y $"Y $(Y $Y $)$Y $V Y $ 3Z $"Z59Z $pEZ >IZ >NZ $ ZZ J?^Z :?oZ @sZ ?Z P@Z J@Z $Z $6Z @Z @ZR6Zl6Z6[6@[6^[6k[6x[6[6[ $[ $K1[ $[ $~%[ $C6 \2"\ $K1.\ @2\ @7\ $lC\ /AG\ 'AL\ $X\ A\\ Aa\ $4 m\ Aq\ Av\ $ \ LB\ FB\ B\ B\ "P \ B\ B\ " \ (C\ $C\3\ $~%\ dC] ^C]4]4)] " :] C>] CG] CK] CT] +DX] )D]]14}]I4] " ] TD] PD] D] D] D] D]S4]33]3^ $^'&^ $K19^_(C^ "P^ DT^ D]^ )Ea^ 'Ej^ QEn^ MEu^ $6^'^ $K1^ E^ E^ E^ E^ KF^ CF^'^ $!^P'_ $K1"_ F&_ F6_ G:_ FK_ kGO_ cGT_'q_ $, }_0_ $'+_ G_ G_ 6H_ .H_ H_ H_ 5I_ )I_ $_ I_ I` J ` J`{ ` $V,`0%C` $K1O` JS` Jc` Kg` Kx` L|` L` lL` hL` L` L` $?` L` L` 9M` 5M` $` }M` oM` "@` $ a &Na Na $: !a N%a N*a $6a N:a N?a $9Ka 4OOa &OTa $`a Oda Oia $ua Pya P~ax&a cPa aPa&a $a Pa Pa&ac&a "pb Pb Pb Qb P(b /Q,b -Q2b&[b%bE'b $b#b $K1b ^Qb RQb Qb Qb Rb }Rc JSc >Sc Sc S!c $?-c NT1c BTBc TFc TKc $Wc 5U[c #U`c $!$rc#c $: c Uc Uc $9c cVc [Vc $c Vc Vc $c Vc Vc$cd$4d>d$Rd$%qd $}d d $}d d $K1d EWd 3Wd $cd  Xd  Xd $67 e 4Xe 0Xe $$e "`;e "`De rXHe lXQe XUe X^e "ke Xoe Xxe RY|e JYe Ye Ye Ye Ye *Ze &Ze dZe `Ze "e Ze Ze "e Ze Zee"e!fd!(f $X:f $K1Gf $c_f $?xf $: f $f $9f $f $f $f $3f $K1g $ g $1-g $Eg $Rg $qyg $ g $Ng(g $K1g e[g Y[g [g [g o\g g\g(h "h \h \(h ],h ]5h h]9h f]>h "Lh ]Ph ]Zh)qh(h!)h])h $@(hp h $K1h $4h ]h ]h $ i T^ i R^i i " *i y^.i w^7i ^;i ^Di ^Hi ^Oi $[i2ri $K1~i ^i ^i $i _i _i y`i i`i $i 7ai 'ai $4i ai aiU2i " i bi bj b j bj bj bjU26jz2Sj2zj2j $,j $K1j $j $4j $j $ j $/k $k $`2!k $0-k`Dk $K1Pk cTk  cYk $ek cik cnk $ zk c~k ck ddk Xdk $/k  ek ekk "k nek jek ek ekl l "l e!l e*l f.l f7l Af;l =f@l "Il {fMl wfVl `l }l fl fl fl fl fl fl l! l $(ll $K1m *gm  g m $m gm gm $ *m h.m h3m $[?m thCm jhTm hXm h]m $,im (imm  irm $~m im im $m im im $m jm jm jm jmm " m km km Tkm Pkm kn kn$nCn(Mn(jn knn ksn(n ln kn4nn $# nn $K1n Tln Hloo+o l/o l4oNo mRo mWono $/o $K1o $ro $o0o $K1o $P+o ;mo 7mo zmo tmp $p(p $K14p m8p m=pJpWpdp&rp $zpp $K1p #np npp "p qnp onp np np $ p/q $K1 q nq nq/.q/Fq/fq!0{q $l4q.q $K1q Doq 8oq#/qP/qX/qm/ r $=7rW,r $K18r os(QsWisXsFXsXsXsXsXtXtKY9tUYGt $ St`jt $K1zt $tpttt $*tt $K1t Eqt ;qt qu qu $7 u Mru Kru(u "9u rr=u prFu rJu rYu3cu "@tu rxu ru ru ru "@u  su  su<uuu Esu Csu v0vCv]Mv "^v jsbv hskv sov stvdvCovvv=vOwmw&w $f0.wTw $`wsw ${ww $ww "w $Jw sw swwwwx x~ vB~ vK~ vO~ vY~+~C~;+~E+~[+~c+~+~+~+ $t $ $ 6 $+\ ${ $. $  $K1 $q $ $ $ $K14 $A $P $s^ $K1w $ $0) $$ ̀ $0؀ w܀ w $ jw fw $67 $ w w $x,& x*  x/ $9; Sx? GxD $ P xT xZ $e(x $1 $ $0 $ $́ $ $x $4 $ $&0 = $K1I yM yR $^ Fzb @zq zu zzH $K3 $K1ł $ׂ $K1 $ $ $ $|* $7 $qQ $,p $ 1 $ $m#ă $K1҃ $ $2  , z0 z5 $$A {E {V &|Z  |_  $6 $4 $҄ $%!܄ $#0 $) w| o| $K, | |5`Xp $9)Ѕ $t-؅ $P $3@, $-8 E}< =}A $M }Q }VVnwC[ $k+@ $ʆ ~Ά  ~ކ ~ ~ \ H $G 6 0.0eo "P     ܀ ڀ̇]ۇcc   / - W U$NC"YBvOS " ~ z ˆ ˈ ψ ԈX # , G0 E9 n= lBjC2~ "    ĉ ȉ ͉C8 " "#  , P0 N5)KCF\iw $ $K1 $ $- $/ $ˊ $>܊ $u $/ $0 $+ $b! $* $z7 $H $b!T $a $@r $b!~ $m3 $z $. $b! $ $z͋ $r ދ $b! $ $z $K $s $, $0? $P $s\ $j $U $ $ $$5 $!.֌ $ $ $  $ $H-( $u5 $y7I $Z $f $p&t $@1 $- $/ $- ύ Ӎ t܍   H B "    ' @+ <0 "09 |= vF P m Džq Ņz ~     Ŏ0 @ @  6 4!G 9Q Lw Vw v c Y ߆ Ն [ Q ه ͇ŏ mɏ aҏ ֏  e+5 "`BPgy [ S   & Đ Ȑ    X R''$ ( 1 ʋ5 ȋ> B G<lv " , * S Q z vϑFّ "  Nx "1 ٌ5 ׌> B K (O $Yc "Pt ex a   ͍ ˍ "˒ ϒ ؒ ܒ  k (C2P{9ؓ Cܓ ? " "$ ( |1 V5 J> B ؏K vO pX "e i r v {z”ؔ)      ?# 1T)^){  ޒ 5 1 q m)  ɕ ԓ͕ ̓֕ <ڕ 4   Ô {* " * . 7 ";  D HH FQ nU lZ " h l u Εy ̕~*D* "p Ö ̖ 0Ж .ٖ Vݖ T)**8*J,e i y|, "  y     "̗ MЗ Gٗ ݗ - "@ ԙ ҙ   -7{-A{-^ #b k ^o \t{-  -r-Ҙ].ߘ..- "p  # "p, 0 9-C-` d m q v---<.ۙC.R..%]X;x.Ex.b ٛf ӛkx..]8.00ך 1ۚ % ɜ   "0, "= 0A (J N W [ ` "i Bm 6v ɟz ş    {   J D0ƛ "ܛ    11 " + / 8 /< -A1dc1|114 `Ü R̜  М ٜ ݜ  " / # 5# ' 1>5J FN @Sg5lq5v "P      ޥ5ǝ7   ] W7=7X \ e i r v 7 " ? 5   3 -7֞8'868@88(KC G |P <T :b,Ll "} c _   ת Ӫ "   0L0Lݟ I G n l  =L!HL4L> " O S X " a e n 2r *{LL    LѠ ۬ՠ ٬8M8M   % #! J% H*@M? qC mL@MV@Ms w  έ ̭  NMYMʡMԡ "     "    ^ T'M1MN ϯR ͯ[ _ h l qMMM D B i gȢ ̢ ѢM  MNN< ް@ ܰI M V +Z )_Ny!N!N S Q x v  !Nԣ ȱأ Ʊݣ8NyO " " ' "0 4 = A JO_ @c >l ep c|OPOP  OP Ť ΤOPؤ "0 Գ ҳ "0   "  kP! "p2 G6 E; "pD nH lQ U `yPj "{   "  ߴ  P "ĥ Cȥ Aͥ "֥ jڥ h  P "`   "` ޵# ܵ, 0 ;PE "V +Z )_ "h Rl Pu {y wP "   " ۶ ٶ ¦ ͦPצ "` ( & "` O M v tP "- 1 6 "? ÷C L P ]Q{Q ' #"Q a _ç ǧ Ч3Qڧ3Q  3Q ݸ ۸ " .bQC +G %P xT v]Qg "x |  " ۹ ׹  Q "0¨ "0Ш :Ԩ 8ߨQ "p "p _ ]Q" "0 "> B P\UZ\Uw { \U κ ̺iUUթpNN P)C30VQC6[/Wu]vRvR   ê ȪvRݪ = ;R R "' j+ `0 "9 = ٻF J ~S W ` (d m q z  ~  E ?_S "p    ɫ ߾ͫ ۾֫ ګ  C = "S " " & / 3 < @ FS^SSSǬTѬ "`       6 ( "  ( *, 5U? "U Y b "t xx rhWhW  hW­W 3T&hW=]RU\UuVV] TϮ\TyTTT6UNAV[iVhVCVVCɯVJWC W"C3T@T[CeUrU]8U]pİUΰU     6 4U ". d2 b;UE " R V _UiU  UU   ñ ȱ5Uٱ(P CTWU2C< WVC&m Pw P * ( T P P ò Ȳ.P߲TW $@ $\ $. $g $' $' $7 $7 $o$ $o$( $, $4 $b8 $bA $>E $M $p!Q $p!Z $0^ $0g $*k $*s $w $ $ $ $ $ $D $D $H+ $H+ $ $ $x ³ $x ˳ $})ϳ $})س $h ܳ $h $% $% $a $a $ $ $\ $\  $! $! $/" $/+ $I#/ $I#8 $%< $%D $DH $DP $!T $!\ $,` $,i $m $u $,y $, $* $* $9( $9( $ $ $, $, $N- $< $ô $̴ $д $ٴ $7ݴ $7 $ $ $O4 $O4 $, $, ${ ${ $a $a! $)% $)- $e21 $e2: $> $F $+J $+S $j7W $j7_ $c $k $a8o $a8w $&{ $& $j$ $j$ $ $ $ $ $ $ĵ $ȵ $е $/Ե $/ܵ $j $j $ $ $2 $2 $+ $P" $r  $* $" $* $D. $D6 $': $'B $ F $ O $eS $e\ $` $h $l $t $-x $E $4 $4 $q* $q* $ $ $J $ $ $ $ $ȶ $̶ $Զ $,ض $, $T $T $ $ $3 $3 $ $T+'-(- 38]QCp(sCovC]C",C2C85CF ʿI(   4H \00L`0     \ 0  $L@ X0@Xl`p,@\0p` p 4 #0%8P'L'`'t()+P , , . / 00\ 2 2 4X 5 7  7 7$ 88 8L @9` 9 : 0; P? `?( p?< ?P ?d ?x ? @  @ 0@ @@ P@`I\IpJKK4W|`Y`dd.symtab.strtab.shstrtab.rela.text.data.bss.rela.gnu.build.attributes.text.hot.rela.gnu.build.attributes.hot.text.unlikely.rela.gnu.build.attributes.unlikely.text.startup.rela.gnu.build.attributes.startup.text.exit.rela.gnu.build.attributes.exit.rodata.str1.1.rodata.str1.8.rodata.rela.data.rel.local.rela.data.rel.rela.data.rel.ro.local.rela.debug_info.debug_abbrev.rela.debug_loc.rela.debug_aranges.debug_ranges.rela.debug_line.debug_str.comment.text.hot.zzz.text.unlikely.zzz.text.startup.zzz.text.exit.zzz.note.GNU-stack.note.gnu.property.rela.eh_frame.groupP@:PT:Pl:P:P: d@(A@G:&`ep ,n 6np"1@h : LP[PV@80: u  @h0:@0:@ȩ0:22/"D /@8 *@:Dx?@:S N@p:khf@\:!wza i@ :$/0@0:&/`LJR@H:)0]80.LLuLLL LLLLLL.P FpA@(:8`4; '8WPK% ]MJp#p#&gems/ruby-lsapi-5.6/ext/lsapi/Makefilenu[ SHELL = /bin/sh # V=0 quiet, V=1 verbose. other values don't work. V = 0 Q1 = $(V:1=) Q = $(Q1:0=@) ECHO1 = $(V:1=@ :) ECHO = $(ECHO1:0=@ echo) NULLCMD = : #### Start of system configuration section. #### srcdir = . topdir = /opt/alt/ruby26/include/ruby-2.6.0 hdrdir = $(topdir) arch_hdrdir = /opt/alt/ruby26/include/ruby-2.6.0/x86_64-linux PATH_SEPARATOR = : VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby prefix = $(DESTDIR)/opt/alt/ruby26 rubysitearchprefix = $(rubylibprefix)/$(sitearch) rubyarchprefix = $(rubylibprefix)/$(arch) rubylibprefix = $(libdir)/$(RUBY_BASE_NAME) exec_prefix = $(DESTDIR)/opt/alt/ruby26 vendorarchhdrdir = $(vendorhdrdir)/$(sitearch) sitearchhdrdir = $(sitehdrdir)/$(sitearch) rubyarchhdrdir = $(rubyhdrdir)/$(arch) vendorhdrdir = $(rubyhdrdir)/vendor_ruby sitehdrdir = $(rubyhdrdir)/site_ruby rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME) vendorarchdir = $(vendorlibdir)/$(sitearch) vendorlibdir = $(vendordir)/$(ruby_version) vendordir = $(rubylibprefix)/vendor_ruby sitearchdir = $(DESTDIR)./.gem.20240125-3712957-1hs47jp sitelibdir = $(DESTDIR)./.gem.20240125-3712957-1hs47jp sitedir = $(rubylibprefix)/site_ruby rubyarchdir = $(rubylibdir)/$(arch) rubylibdir = $(rubylibprefix)/$(ruby_version) sitearchincludedir = $(includedir)/$(sitearch) archincludedir = $(includedir)/$(arch) sitearchlibdir = $(libdir)/$(sitearch) archlibdir = $(libdir)/$(arch) ridir = $(datarootdir)/$(RI_BASE_NAME) mandir = $(DESTDIR)/opt/alt/ruby26/share/man localedir = $(datarootdir)/locale libdir = $(exec_prefix)/lib64 psdir = $(docdir) pdfdir = $(docdir) dvidir = $(docdir) htmldir = $(docdir) infodir = $(DESTDIR)/opt/alt/ruby26/share/info docdir = $(datarootdir)/doc/$(PACKAGE) oldincludedir = $(DESTDIR)/usr/include includedir = $(DESTDIR)/opt/alt/ruby26/include runstatedir = $(localstatedir)/run localstatedir = $(DESTDIR)/var sharedstatedir = $(DESTDIR)/var/lib sysconfdir = $(DESTDIR)/etc datadir = $(DESTDIR)/opt/alt/ruby26/share datarootdir = $(prefix)/share libexecdir = $(DESTDIR)/opt/alt/ruby26/libexec sbindir = $(DESTDIR)/opt/alt/ruby26/sbin bindir = $(exec_prefix)/bin archdir = $(rubyarchdir) CC_WRAPPER = CC = gcc CXX = g++ LIBRUBY = $(LIBRUBY_SO) LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a LIBRUBYARG_SHARED = -Wl,-rpath,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME) LIBRUBYARG_STATIC = -Wl,-rpath,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)-static $(MAINLIBS) empty = OUTFLAG = -o $(empty) COUTFLAG = -o $(empty) CSRCFLAG = $(empty) RUBY_EXTCONF_H = cflags = $(optflags) $(debugflags) $(warnflags) cxxflags = $(optflags) $(debugflags) $(warnflags) optflags = -O3 debugflags = -ggdb3 warnflags = -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wduplicated-cond -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wrestrict -Wwrite-strings -Wimplicit-fallthrough=0 -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-packed-bitfield-compat -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wunused-variable cppflags = CCDLFLAGS = -fPIC CFLAGS = $(CCDLFLAGS) -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection $(ARCH_FLAG) INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir) DEFS = CPPFLAGS = $(DEFS) $(cppflags) -DRUBY_2 CXXFLAGS = $(CCDLFLAGS) -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection $(ARCH_FLAG) ldflags = -L. -Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -fstack-protector-strong -rdynamic -Wl,-export-dynamic dldflags = -Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld ARCH_FLAG = -m64 DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG) LDSHARED = $(CC) -shared LDSHAREDXX = $(CXX) -shared AR = ar EXEEXT = RUBY_INSTALL_NAME = $(RUBY_BASE_NAME) RUBY_SO_NAME = ruby RUBYW_INSTALL_NAME = RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version) RUBYW_BASE_NAME = rubyw RUBY_BASE_NAME = ruby arch = x86_64-linux sitearch = $(arch) ruby_version = 2.6.0 ruby = $(bindir)/$(RUBY_BASE_NAME) RUBY = $(ruby) ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/backward.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h RM = rm -f RM_RF = $(RUBY) -run -e rm -- -rf RMDIRS = rmdir --ignore-fail-on-non-empty -p MAKEDIRS = /usr/bin/mkdir -p INSTALL = /usr/bin/install -c INSTALL_PROG = $(INSTALL) -m 0755 INSTALL_DATA = $(INSTALL) -m 644 COPY = cp TOUCH = exit > #### End of system configuration section. #### preload = libpath = . $(libdir) LIBPATH = -L. -L$(libdir) -Wl,-rpath,$(libdir) DEFFILE = CLEANFILES = mkmf.log DISTCLEANFILES = DISTCLEANDIRS = extout = extout_prefix = target_prefix = LOCAL_LIBS = LIBS = $(LIBRUBYARG_SHARED) -lm -lc ORIG_SRCS = lsapilib.c lsruby.c SRCS = $(ORIG_SRCS) OBJS = lsapilib.o lsruby.o HDRS = $(srcdir)/lsapidef.h $(srcdir)/lsapilib.h LOCAL_HDRS = TARGET = lsapi TARGET_NAME = lsapi TARGET_ENTRY = Init_$(TARGET_NAME) DLLIB = $(TARGET).so EXTSTATIC = STATIC_LIB = TIMESTAMP_DIR = . BINDIR = $(bindir) RUBYCOMMONDIR = $(sitedir)$(target_prefix) RUBYLIBDIR = $(sitelibdir)$(target_prefix) RUBYARCHDIR = $(sitearchdir)$(target_prefix) HDRDIR = $(rubyhdrdir)/ruby$(target_prefix) ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix) TARGET_SO_DIR = TARGET_SO = $(TARGET_SO_DIR)$(DLLIB) CLEANLIBS = $(TARGET_SO) CLEANOBJS = *.o *.bak all: $(DLLIB) static: $(STATIC_LIB) .PHONY: all install static install-so install-rb .PHONY: clean clean-so clean-static clean-rb clean-static:: clean-rb-default:: clean-rb:: clean-so:: clean: clean-so clean-static clean-rb-default clean-rb -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time distclean-rb-default:: distclean-rb:: distclean-so:: distclean-static:: distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true realclean: distclean install: install-so install-rb install-so: $(DLLIB) $(TIMESTAMP_DIR)/.sitearchdir.time $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR) clean-static:: -$(Q)$(RM) $(STATIC_LIB) install-rb: pre-install-rb do-install-rb install-rb-default install-rb-default: pre-install-rb-default do-install-rb-default pre-install-rb: Makefile pre-install-rb-default: Makefile do-install-rb: do-install-rb-default: pre-install-rb-default: @$(NULLCMD) $(TIMESTAMP_DIR)/.sitearchdir.time: $(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR) $(Q) $(TOUCH) $@ site-install: site-install-so site-install-rb site-install-so: install-so site-install-rb: install-rb .SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S .cc.o: $(ECHO) compiling $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< .cc.S: $(ECHO) translating $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< .mm.o: $(ECHO) compiling $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< .mm.S: $(ECHO) translating $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< .cxx.o: $(ECHO) compiling $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< .cxx.S: $(ECHO) translating $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< .cpp.o: $(ECHO) compiling $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< .cpp.S: $(ECHO) translating $(<) $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< .c.o: $(ECHO) compiling $(<) $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< .c.S: $(ECHO) translating $(<) $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< .m.o: $(ECHO) compiling $(<) $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< .m.S: $(ECHO) translating $(<) $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< $(TARGET_SO): $(OBJS) Makefile $(ECHO) linking shared-object $(DLLIB) -$(Q)$(RM) $(@) $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS) $(OBJS): $(HDRS) $(ruby_headers) PK% ] 3O8aa(gems/ruby-lsapi-5.6/ext/lsapi/lsapilib.cnu[//#define LSAPI_DEBUG /* Copyright (c) 2002-2018, Lite Speed Technologies Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Lite Speed Technologies Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lsapilib.h" #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) #include #endif #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) #include #endif #include #ifndef uint32 #define uint32 uint32_t #endif struct lsapi_MD5Context { uint32 buf[4]; uint32 bits[2]; unsigned char in[64]; }; void lsapi_MD5Init(struct lsapi_MD5Context *context); void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf, unsigned len); void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context); /* * This is needed to make RSAREF happy on some MS-DOS compilers. */ typedef struct lsapi_MD5Context lsapi_MD5_CTX; #define LSAPI_ST_REQ_HEADER 1 #define LSAPI_ST_REQ_BODY 2 #define LSAPI_ST_RESP_HEADER 4 #define LSAPI_ST_RESP_BODY 8 #define LSAPI_ST_BACKGROUND 16 #define LSAPI_RESP_BUF_SIZE 8192 #define LSAPI_INIT_RESP_HEADER_LEN 4096 enum { LSAPI_STATE_IDLE, LSAPI_STATE_CONNECTED, LSAPI_STATE_ACCEPTING, }; typedef struct lsapi_child_status { int m_pid; long m_tmStart; volatile short m_iKillSent; volatile char m_inProcess; volatile char m_state; volatile int m_iReqCounter; volatile long m_tmWaitBegin; volatile long m_tmReqBegin; volatile long m_tmLastCheckPoint; } lsapi_child_status; static lsapi_child_status * s_worker_status = NULL; static int g_inited = 0; static int g_running = 1; static int s_ppid; static int s_restored_ppid = 0; static int s_pid = 0; static int s_slow_req_msecs = 0; static int s_keep_listener = 1; static int s_dump_debug_info = 0; static int s_pid_dump_debug_info = 0; static int s_req_processed = 0; static int s_skip_write = 0; static int (*pthread_atfork_func)(void (*prepare)(void), void (*parent)(void), void (*child)(void)) = NULL; static int *s_busy_workers = NULL; static int *s_accepting_workers = NULL; static int *s_global_counter = &s_req_processed; static int s_max_busy_workers = -1; static char *s_stderr_log_path = NULL; static int s_stderr_is_pipe = 0; static int s_ignore_pid = -1; static size_t s_total_pages = 1; static size_t s_min_avail_pages = 256 * 1024; static size_t *s_avail_pages = &s_total_pages; LSAPI_Request g_req = { .m_fdListen = -1, .m_fd = -1 }; static char s_secret[24]; static LSAPI_On_Timer_pf s_proc_group_timer_cb = NULL; void Flush_RespBuf_r( LSAPI_Request * pReq ); static int lsapi_reopen_stderr(const char *p); static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] = { "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING", "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION", "HTTP_CONNECTION", "CONTENT_TYPE", "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2", "HTTP_HOST", "HTTP_PRAGMA", "HTTP_REFERER", "HTTP_USER_AGENT", "HTTP_CACHE_CONTROL", "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH", "HTTP_IF_NONE_MATCH", "HTTP_IF_RANGE", "HTTP_IF_UNMODIFIED_SINCE", "HTTP_KEEP_ALIVE", "HTTP_RANGE", "HTTP_X_FORWARDED_FOR", "HTTP_VIA", "HTTP_TRANSFER_ENCODING" }; static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] = { 11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18, 22, 13, 18, 13, 24, 15, 10, 20, 8, 22 }; static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] = { "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language", "Authorization", "Connection", "Content-Type", "Content-Length", "Cookie", "Cookie2", "Host", "Pragma", "Referer", "User-Agent", "Cache-Control", "If-Modified-Since", "If-Match", "If-None-Match", "If-Range", "If-Unmodified-Since", "Keep-Alive", "Range", "X-Forwarded-For", "Via", "Transfer-Encoding" }; static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] = { 6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent 13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17 }; static const char *s_log_level_names[8] = { "", "DEBUG","INFO", "NOTICE", "WARN", "ERROR", "CRIT", "FATAL" }; void LSAPI_Log(int flag, const char * fmt, ...) { char buf[1024]; char *p = buf; if ((flag & LSAPI_LOG_TIMESTAMP_BITS) && !(s_stderr_is_pipe)) { struct timeval tv; struct tm tm; gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &tm); if (flag & LSAPI_LOG_TIMESTAMP_FULL) { p += snprintf(p, 1024, "%04d-%02d-%02d %02d:%02d:%02d.%06d ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (int)tv.tv_usec); } else if (flag & LSAPI_LOG_TIMESTAMP_HMS) { p += snprintf(p, 1024, "%02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec); } } int level = flag & LSAPI_LOG_LEVEL_BITS; if (level && level <= LSAPI_LOG_FLAG_FATAL) { p += snprintf(p, 100, "[%s] ", s_log_level_names[level]); } if (flag & LSAPI_LOG_PID) { p += snprintf(p, 100, "[UID:%d][%d] ", getuid(), s_pid); } if (p > buf) fprintf(stderr, "%.*s", (int)(p - buf), buf); va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } #ifdef LSAPI_DEBUG #define DBGLOG_FLAG (LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_FLAG_DEBUG|LSAPI_LOG_PID) #define lsapi_dbg(...) LSAPI_Log(DBGLOG_FLAG, __VA_ARGS__) #else #define lsapi_dbg(...) #endif #define lsapi_log(...) LSAPI_Log(LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_PID, __VA_ARGS__) void lsapi_perror(const char * pMessage, int err_no) { lsapi_log("%s, errno: %d (%s)\n", pMessage, err_no, strerror(err_no)); } static int lsapi_parent_dead() { // Return non-zero if the parent is dead. 0 if still alive. if (!s_ppid) { // not checking, so not dead return(0); } if (s_restored_ppid) { if (kill(s_restored_ppid,0) == -1) { if (errno == EPERM) { return(0); // no permission, but it's still there. } return(1); // Dead } return(0); // it worked, so it's not dead } return(s_ppid != getppid()); } static void lsapi_sigpipe( int sig ) { } static void lsapi_siguser1( int sig ) { g_running = 0; } #ifndef sighandler_t typedef void (*sighandler_t)(int); #endif static void lsapi_signal(int signo, sighandler_t handler) { struct sigaction sa; sigaction(signo, NULL, &sa); if (sa.sa_handler == SIG_DFL) { sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = handler; sigaction(signo, &sa, NULL); } } static int s_enable_core_dump = 0; static void lsapi_enable_core_dump(void) { #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) int mib[2]; size_t len; #if !defined(__OpenBSD__) len = 2; if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 ) { len = sizeof(s_enable_core_dump); if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1) perror( "sysctl: Failed to set 'kern.sugid_coredump', " "core dump may not be available!"); } #else int set = 3; len = sizeof(set); mib[0] = CTL_KERN; mib[1] = KERN_NOSUIDCOREDUMP; if (sysctl(mib, 2, NULL, 0, &set, len) == 0) { s_enable_core_dump = 1; } #endif #endif #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1) perror( "prctl: Failed to set dumpable, " "core dump may not be available!"); #endif } static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader, char type, int len ) { pHeader->m_versionB0 = LSAPI_VERSION_B0; /* LSAPI protocol version */ pHeader->m_versionB1 = LSAPI_VERSION_B1; pHeader->m_type = type; pHeader->m_flag = LSAPI_ENDIAN; pHeader->m_packetLen.m_iLen = len; } static int lsapi_set_nblock( int fd, int nonblock ) { int val = fcntl( fd, F_GETFL, 0 ); if ( nonblock ) { if (!( val & O_NONBLOCK )) { return fcntl( fd, F_SETFL, val | O_NONBLOCK ); } } else { if ( val & O_NONBLOCK ) { return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) ); } } return 0; } static int lsapi_close( int fd ) { int ret; while( 1 ) { ret = close( fd ); if (( ret == -1 )&&( errno == EINTR )&&(g_running)) continue; return ret; } } static void lsapi_close_connection(LSAPI_Request *pReq) { if (pReq->m_fd == -1) return; lsapi_close(pReq->m_fd); pReq->m_fd = -1; if (s_busy_workers) __atomic_fetch_sub(s_busy_workers, 1, __ATOMIC_SEQ_CST); if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_IDLE, __ATOMIC_SEQ_CST); } static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len ) { ssize_t ret; while( 1 ) { ret = read( fd, (char *)pBuf, len ); if (( ret == -1 )&&( errno == EINTR )&&(g_running)) continue; return ret; } } /* static int lsapi_write( int fd, const void * pBuf, int len ) { int ret; const char * pCur; const char * pEnd; if ( len == 0 ) return 0; pCur = (const char *)pBuf; pEnd = pCur + len; while( g_running && (pCur < pEnd) ) { ret = write( fd, pCur, pEnd - pCur ); if ( ret >= 0) pCur += ret; else if (( ret == -1 )&&( errno != EINTR )) return ret; } return pCur - (const char *)pBuf; } */ static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen ) { int ret; int left = totalLen; int n = count; if (s_skip_write) return totalLen; while(( left > 0 )&&g_running ) { ret = writev( fd, *pVec, n ); if ( ret > 0 ) { left -= ret; if (( left <= 0)||( !g_running )) return totalLen - left; while( ret > 0 ) { if ( (*pVec)->iov_len <= (unsigned int )ret ) { ret -= (*pVec)->iov_len; ++(*pVec); } else { (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret; (*pVec)->iov_len -= ret; break; } } } else if ( ret == -1 ) { if ( errno == EAGAIN ) { if ( totalLen - left > 0 ) return totalLen - left; else return -1; } else if ( errno != EINTR ) return ret; } } return totalLen - left; } /* static int getTotalLen( struct iovec * pVec, int count ) { struct iovec * pEnd = pVec + count; int total = 0; while( pVec < pEnd ) { total += pVec->iov_len; ++pVec; } return total; } */ static inline int allocateBuf( LSAPI_Request * pReq, int size ) { char * pBuf = (char *)realloc( pReq->m_pReqBuf, size ); if ( pBuf ) { pReq->m_pReqBuf = pBuf; pReq->m_reqBufSize = size; pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf; return 0; } return -1; } static int allocateIovec( LSAPI_Request * pReq, int n ) { struct iovec * p = (struct iovec *)realloc( pReq->m_pIovec, sizeof(struct iovec) * n ); if ( !p ) return -1; pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec ); pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec ); pReq->m_pIovec = p; pReq->m_pIovecEnd = p + n; return 0; } static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size ) { char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size ); if ( !p ) return -1; pReq->m_pRespHeaderBufPos = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf ); pReq->m_pRespHeaderBuf = p; pReq->m_pRespHeaderBufEnd = p + size; return 0; } static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType ) { if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )|| ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )|| ( pktType != pHeader->m_type )) return -1; if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT )) { register char b; b = pHeader->m_packetLen.m_bytes[0]; pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3]; pHeader->m_packetLen.m_bytes[3] = b; b = pHeader->m_packetLen.m_bytes[1]; pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2]; pHeader->m_packetLen.m_bytes[2] = b; } return pHeader->m_packetLen.m_iLen; } static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList, int *curSize, int newSize ) { struct LSAPI_key_value_pair * pBuf; if ( *curSize >= newSize ) return 0; if ( newSize > 8192 ) return -1; pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize * sizeof(struct LSAPI_key_value_pair) ); if ( pBuf ) { *pEnvList = pBuf; *curSize = newSize; return 0; } else return -1; } static inline int isPipe( int fd ) { char achPeer[128]; socklen_t len = 128; if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&& ( errno == ENOTCONN )) return 0; else return 1; } static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count, char **pBegin, char * pEnd ) { struct LSAPI_key_value_pair * pEnvEnd; int keyLen = 0, valLen = 0; if ( count > 8192 ) return -1; pEnvEnd = pEnvList + count; while( pEnvList != pEnvEnd ) { if ( pEnd - *pBegin < 4 ) return -1; keyLen = *((unsigned char *)((*pBegin)++)); keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++)); valLen = *((unsigned char *)((*pBegin)++)); valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++)); if ( *pBegin + keyLen + valLen > pEnd ) return -1; if (( !keyLen )||( !valLen )) return -1; pEnvList->pKey = *pBegin; *pBegin += keyLen; pEnvList->pValue = *pBegin; *pBegin += valLen; pEnvList->keyLen = keyLen - 1; pEnvList->valLen = valLen - 1; ++pEnvList; } if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 ) return -1; *pBegin += 4; return 0; } static inline void swapIntEndian( int * pInteger ) { char * p = (char *)pInteger; register char b; b = p[0]; p[0] = p[3]; p[3] = b; b = p[1]; p[1] = p[2]; p[2] = b; } static inline void fixEndian( LSAPI_Request * pReq ) { struct lsapi_req_header *p= pReq->m_pHeader; swapIntEndian( &p->m_httpHeaderLen ); swapIntEndian( &p->m_reqBodyLen ); swapIntEndian( &p->m_scriptFileOff ); swapIntEndian( &p->m_scriptNameOff ); swapIntEndian( &p->m_queryStringOff ); swapIntEndian( &p->m_requestMethodOff ); swapIntEndian( &p->m_cntUnknownHeaders ); swapIntEndian( &p->m_cntEnv ); swapIntEndian( &p->m_cntSpecialEnv ); } static void fixHeaderIndexEndian( LSAPI_Request * pReq ) { int i; for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { register char b; char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]); b = p[0]; p[0] = p[1]; p[1] = b; swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] ); } } if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { swapIntEndian( &pCur->nameOff ); swapIntEndian( &pCur->nameLen ); swapIntEndian( &pCur->valueOff ); swapIntEndian( &pCur->valueLen ); ++pCur; } } } static int validateHeaders( LSAPI_Request * pReq ) { int totalLen = pReq->m_pHeader->m_httpHeaderLen; int i; for(i = 0; i < H_TRANSFER_ENCODING; ++i) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { if (pReq->m_pHeaderIndex->m_headerOff[i] > totalLen || pReq->m_pHeaderIndex->m_headerLen[i] + pReq->m_pHeaderIndex->m_headerOff[i] > totalLen) return -1; } } if (pReq->m_pHeader->m_cntUnknownHeaders > 0) { struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { if (pCur->nameOff > totalLen || pCur->nameOff + pCur->nameLen > totalLen || pCur->valueOff > totalLen || pCur->valueOff + pCur->valueLen > totalLen) return -1; ++pCur; } } return 0; } static uid_t s_uid = 0; static uid_t s_defaultUid; //web server need set this static gid_t s_defaultGid; #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) #define LSAPI_LVE_DISABLED 0 #define LSAPI_LVE_ENABLED 1 #define LSAPI_CAGEFS_ENABLED 2 #define LSAPI_CAGEFS_NO_SUEXEC 3 struct liblve; static int s_enable_lve = LSAPI_LVE_DISABLED; static struct liblve * s_lve = NULL; static void *s_liblve; static int (*fp_lve_is_available)(void) = NULL; static int (*fp_lve_instance_init)(struct liblve *) = NULL; static int (*fp_lve_destroy)(struct liblve *) = NULL; static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL; static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL; static int (*fp_lve_jail)( struct passwd *, char *) = NULL; static int lsapi_load_lve_lib(void) { s_liblve = dlopen("liblve.so.0", RTLD_NOW | RTLD_GLOBAL); if (s_liblve) { fp_lve_is_available = dlsym(s_liblve, "lve_is_available"); if (dlerror() == NULL) { if ( !(*fp_lve_is_available)() ) { int uid = getuid(); if ( uid ) { if (setreuid( s_uid, uid )) {}; if ( !(*fp_lve_is_available)() ) s_enable_lve = 0; if (setreuid( uid, s_uid )) {}; } } } } else { s_enable_lve = LSAPI_LVE_DISABLED; } return (s_liblve)? 0 : -1; } static int init_lve_ex(void) { int rc; if ( !s_liblve ) return -1; fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init"); fp_lve_destroy = dlsym(s_liblve, "lve_destroy"); fp_lve_enter = dlsym(s_liblve, "lve_enter"); fp_lve_leave = dlsym(s_liblve, "lve_leave"); if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED ) fp_lve_jail = dlsym(s_liblve, "jail" ); if ( s_lve == NULL ) { rc = (*fp_lve_instance_init)(NULL); s_lve = malloc(rc); } rc = (*fp_lve_instance_init)(s_lve); if (rc != 0) { perror( "LSAPI: Unable to initialize LVE" ); free( s_lve ); s_lve = NULL; return -1; } return 0; } #endif static int readSecret( const char * pSecretFile ) { struct stat st; int fd = open( pSecretFile, O_RDONLY , 0600 ); if ( fd == -1 ) { lsapi_log("LSAPI: failed to open secret file: %s!\n", pSecretFile ); return -1; } if ( fstat( fd, &st ) == -1 ) { lsapi_log("LSAPI: failed to check state of file: %s!\n", pSecretFile ); close( fd ); return -1; } /* if ( st.st_uid != s_uid ) { lsapi_log("LSAPI: file owner check failure: %s!\n", pSecretFile ); close( fd ); return -1; } */ if ( st.st_mode & 0077 ) { lsapi_log("LSAPI: file permission check failure: %s\n", pSecretFile ); close( fd ); return -1; } if ( read( fd, s_secret, 16 ) < 16 ) { lsapi_log("LSAPI: failed to read secret from secret file: %s\n", pSecretFile ); close( fd ); return -1; } close( fd ); return 0; } int LSAPI_is_suEXEC_Daemon(void) { if (( !s_uid )&&( s_secret[0] )) return 1; else return 0; } static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 ) { char achError[4096]; int n = snprintf(achError, sizeof(achError), "[UID:%d][%d] %s:%s: %s\n", getuid(), getpid(), pErr1, (pErr2)?pErr2:"", strerror(errno)); if (n > (int)sizeof(achError)) n = sizeof(achError); if ( pReq ) LSAPI_Write_Stderr_r( pReq, achError, n ); else if (write( STDERR_FILENO, achError, n )) {}; return 0; } #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) static int lsapi_lve_error( LSAPI_Request * pReq ) { static const char * headers[] = { "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0", "Pragma: no-cache", "Retry-After: 60", "Content-Type: text/html", NULL }; static const char achBody[] = "\n" "\n508 Resource Limit Is Reached\n" "\n" "

Resource Limit Is Reached

\n" "The website is temporarily unable to service your request as it exceeded resource limit.\n" "Please try again later.\n" "
\n" "\n"; LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 ); return 0; } static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid ) { if ( s_lve && uid ) //root user should not do that { uint32_t cookie; int ret = -1; ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie); if ( ret < 0 ) { //lsapi_log("enter LVE (%d) : result: %d !\n", uid, ret ); LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL ); lsapi_lve_error( pReq ); return -1; } } return 0; } static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw ) { int ret = 0; char error_msg[1024] = ""; ret = (*fp_lve_jail)( pw, error_msg ); if ( ret < 0 ) { lsapi_log("LSAPI: LVE jail(%d) result: %d, error: %s !\n", uid, ret, error_msg ); LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL ); return -1; } return ret; } static int lsapi_initLVE(void) { const char * pEnv; if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL ) { s_enable_lve = atol( pEnv ); pEnv = NULL; } else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL ) { s_enable_lve = atol( pEnv ); pEnv = NULL; } if ( s_enable_lve && !s_uid ) { lsapi_load_lve_lib(); if ( s_enable_lve ) { return init_lve_ex(); } } return 0; } #endif static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot) { int rv; struct passwd * pw; pw = getpwuid( uid ); #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) if ( s_lve ) { if( lsapi_enterLVE( pReq, uid ) == -1 ) return -1; if ( pw && fp_lve_jail) { rv = lsapi_jailLVE( pReq, uid, pw ); if ( rv == -1 ) return -1; if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC )) //this mode only use cageFS, does not use suEXEC { uid = s_defaultUid; gid = s_defaultGid; pw = getpwuid( uid ); } } } #endif //if ( !uid || !gid ) //do not allow root //{ // return -1; //} #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) if ( s_enable_core_dump ) lsapi_enable_core_dump(); #endif rv = setgid(gid); if (rv == -1) { LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL); return -1; } if ( pw && (pw->pw_gid == gid )) { rv = initgroups( pw->pw_name, gid ); if (rv == -1) { LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL); return -1; } } else { rv = setgroups(1, &gid); if (rv == -1) { LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL); } } if ( pChroot ) { rv = chroot( pChroot ); if ( rv == -1 ) { LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL); return -1; } } rv = setuid(uid); if (rv == -1) { LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL); return -1; } #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) if ( s_enable_core_dump ) lsapi_enable_core_dump(); #endif return 0; } static int lsapi_suexec_auth( LSAPI_Request *pReq, char * pAuth, int len, char * pUgid, int ugidLen ) { lsapi_MD5_CTX md5ctx; unsigned char achMD5[16]; if ( len < 32 ) return -1; memmove( achMD5, pAuth + 16, 16 ); memmove( pAuth + 16, s_secret, 16 ); lsapi_MD5Init( &md5ctx ); lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 ); lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 ); lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx); if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 ) return 0; return 1; } static int lsapi_changeUGid( LSAPI_Request * pReq ) { int uid = s_defaultUid; int gid = s_defaultGid; const char *pStderrLog; const char *pChroot = NULL; struct LSAPI_key_value_pair * pEnv; struct LSAPI_key_value_pair * pAuth; int i; if ( s_uid ) return 0; //with special ID 0x00 //authenticate the suEXEC request; //first one should be MD5( nonce + lscgid secret ) //remember to clear the secret after verification //it should be set at the end of special env i = pReq->m_pHeader->m_cntSpecialEnv - 1; if ( i >= 0 ) { pEnv = pReq->m_pSpecialEnvList + i; if (( *pEnv->pKey == '\000' )&& ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 )) { --pReq->m_pHeader->m_cntSpecialEnv; pAuth = pEnv--; if (( *pEnv->pKey == '\000' )&& ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 )) { --pReq->m_pHeader->m_cntSpecialEnv; uid = *(uint32_t *)pEnv->pValue; gid = *(((uint32_t *)pEnv->pValue) + 1 ); //lsapi_log("LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid ); } else { lsapi_log("LSAPI: missing SUEXEC_UGID env, use default user!\n" ); pEnv = NULL; } if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 ) { //read UID, GID from specialEnv } else { //authentication error lsapi_log("LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" ); uid = 0; } } else { //lsapi_log("LSAPI: no SUEXEC_AUTH env, use default user!\n" ); } } if ( !uid ) { uid = s_defaultUid; gid = s_defaultGid; } //change uid if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 ) { return -1; } s_uid = uid; if ( pReq->m_fdListen != -1 ) { close( pReq->m_fdListen ); pReq->m_fdListen = -1; } pStderrLog = LSAPI_GetEnv_r( pReq, "LSAPI_STDERR_LOG"); if (pStderrLog) lsapi_reopen_stderr(pStderrLog); return 0; } static int parseContentLenFromHeader(LSAPI_Request * pReq) { const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH ); if ( pContentLen ) pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 ); return 0; } static int parseRequest( LSAPI_Request * pReq, int totalLen ) { int shouldFixEndian; char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header ); char * pEnd = pReq->m_pReqBuf + totalLen; shouldFixEndian = ( LSAPI_ENDIAN != ( pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) ); if ( shouldFixEndian ) { fixEndian( pReq ); } if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&& allocateEnvList( &pReq->m_pSpecialEnvList, &pReq->m_specialEnvListSize, pReq->m_pHeader->m_cntSpecialEnv ) == -1 ) return -1; if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&& allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize, pReq->m_pHeader->m_cntEnv ) == -1 ) return -1; if ( parseEnv( pReq->m_pSpecialEnvList, pReq->m_pHeader->m_cntSpecialEnv, &pBegin, pEnd ) == -1 ) return -1; if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv, &pBegin, pEnd ) == -1 ) return -1; if (pReq->m_pHeader->m_scriptFileOff < 0 || pReq->m_pHeader->m_scriptFileOff >= totalLen || pReq->m_pHeader->m_scriptNameOff < 0 || pReq->m_pHeader->m_scriptNameOff >= totalLen || pReq->m_pHeader->m_queryStringOff < 0 || pReq->m_pHeader->m_queryStringOff >= totalLen || pReq->m_pHeader->m_requestMethodOff < 0 || pReq->m_pHeader->m_requestMethodOff >= totalLen) { lsapi_log("Bad request header - ERROR#1\n"); return -1; } pReq->m_pScriptFile = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff; pReq->m_pScriptName = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff; pReq->m_pQueryString = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff; pReq->m_pRequestMethod = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff; pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7)); pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin; pBegin += sizeof( struct lsapi_http_header_index ); pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin; pBegin += sizeof( struct lsapi_header_offset) * pReq->m_pHeader->m_cntUnknownHeaders; pReq->m_pHttpHeader = pBegin; pBegin += pReq->m_pHeader->m_httpHeaderLen; if ( pBegin != pEnd ) { lsapi_log("Request header does match total size, total: %d, " "real: %ld\n", totalLen, pBegin - pReq->m_pReqBuf ); return -1; } if ( shouldFixEndian ) { fixHeaderIndexEndian( pReq ); } if (validateHeaders(pReq) == -1) { lsapi_log("Bad request header - ERROR#2\n"); return -1; } pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen; if ( pReq->m_reqBodyLen == -2 ) { parseContentLenFromHeader(pReq); } return 0; } //OPTIMIZATION static char s_accept_notify = 0; static char s_schedule_notify = 0; static char s_notify_scheduled = 0; static char s_notified_pid = 0; static struct lsapi_packet_header s_ack = {'L', 'S', LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }; static struct lsapi_packet_header s_conn_close_pkt = {'L', 'S', LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }; static inline int send_notification_pkt( int fd, struct lsapi_packet_header *pkt ) { if ( write( fd, pkt, LSAPI_PACKET_HEADER_LEN ) < LSAPI_PACKET_HEADER_LEN ) return -1; return 0; } static inline int send_req_received_notification( int fd ) { return send_notification_pkt(fd, &s_ack); } static inline int send_conn_close_notification( int fd ) { return send_notification_pkt(fd, &s_conn_close_pkt); } //static void lsapi_sigalarm( int sig ) //{ // if ( s_notify_scheduled ) // { // s_notify_scheduled = 0; // if ( g_req.m_fd != -1 ) // write_req_received_notification( g_req.m_fd ); // } //} static inline int lsapi_schedule_notify(void) { if ( !s_notify_scheduled ) { alarm( 2 ); s_notify_scheduled = 1; } return 0; } static inline int notify_req_received( int fd ) { if ( s_schedule_notify ) return lsapi_schedule_notify(); return send_req_received_notification( fd ); } static inline int lsapi_notify_pid( int fd ) { char achBuf[16]; lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM, 8 + LSAPI_PACKET_HEADER_LEN ); memmove( &achBuf[8], "\0PID", 4 ); *((int *)&achBuf[12]) = getpid(); if ( write( fd, achBuf, 16 ) < 16 ) return -1; return 0; } static int readReq( LSAPI_Request * pReq ) { int len; int packetLen; if ( !pReq ) return -1; if ( pReq->m_reqBufSize < 8192 ) { if ( allocateBuf( pReq, 8192 ) == -1 ) return -1; } while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN ) { len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize ); if ( len <= 0 ) return -1; pReq->m_bufRead += len; } pReq->m_reqState = LSAPI_ST_REQ_HEADER; packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST ); if ( packetLen < 0 ) { lsapi_log("packetLen < 0\n"); return -1; } if ( packetLen > LSAPI_MAX_HEADER_LEN ) { lsapi_log("packetLen > %d\n", LSAPI_MAX_HEADER_LEN ); return -1; } if ( packetLen + 1024 > pReq->m_reqBufSize ) { if ( allocateBuf( pReq, packetLen + 1024 ) == -1 ) return -1; } while( packetLen > pReq->m_bufRead ) { len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead ); if ( len <= 0 ) return -1; pReq->m_bufRead += len; } if ( parseRequest( pReq, packetLen ) < 0 ) { lsapi_log("ParseRequest error\n"); return -1; } pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER; if ( !s_uid ) { if ( lsapi_changeUGid( pReq ) ) return -1; memset(s_secret, 0, sizeof(s_secret)); } pReq->m_bufProcessed = packetLen; //OPTIMIZATION if ( !s_accept_notify && !s_notified_pid ) return notify_req_received( pReq->m_fd ); else { s_notified_pid = 0; return 0; } } int LSAPI_Init(void) { if ( !g_inited ) { s_uid = geteuid(); s_secret[0] = 0; lsapi_signal(SIGPIPE, lsapi_sigpipe); lsapi_signal(SIGUSR1, lsapi_siguser1); #if defined(SIGXFSZ) && defined(SIG_IGN) signal(SIGXFSZ, SIG_IGN); #endif /* let STDOUT function as STDERR, just in case writing to STDOUT directly */ dup2( 2, 1 ); if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 ) return -1; g_inited = 1; s_ppid = getppid(); void *pthread_lib = dlopen("libpthread.so", RTLD_LAZY); if (pthread_lib) pthread_atfork_func = dlsym(pthread_lib, "pthread_atfork"); } return 0; } void LSAPI_Stop(void) { g_running = 0; } int LSAPI_IsRunning(void) { return g_running; } void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb) { s_proc_group_timer_cb = cb; } int LSAPI_InitRequest( LSAPI_Request * pReq, int fd ) { int newfd; if ( !pReq ) return -1; memset( pReq, 0, sizeof( LSAPI_Request ) ); if ( allocateIovec( pReq, 16 ) == -1 ) return -1; pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE ); if ( !pReq->m_pRespBuf ) return -1; pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1; pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5]; if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 ) return -1; if ( fd == STDIN_FILENO ) { fd = dup( fd ); newfd = open( "/dev/null", O_RDWR ); dup2( newfd, STDIN_FILENO ); } if ( isPipe( fd ) ) { pReq->m_fdListen = -1; pReq->m_fd = fd; } else { pReq->m_fdListen = fd; pReq->m_fd = -1; lsapi_set_nblock( fd, 1 ); } return 0; } int LSAPI_Is_Listen( void ) { return LSAPI_Is_Listen_r( &g_req ); } int LSAPI_Is_Listen_r( LSAPI_Request * pReq) { return pReq->m_fdListen != -1; } int LSAPI_Accept_r( LSAPI_Request * pReq ) { char achPeer[128]; socklen_t len; int nodelay = 1; if ( !pReq ) return -1; if ( LSAPI_Finish_r( pReq ) == -1 ) return -1; lsapi_set_nblock( pReq->m_fdListen , 0 ); while( g_running ) { if ( pReq->m_fd == -1 ) { if ( pReq->m_fdListen != -1) { len = sizeof( achPeer ); pReq->m_fd = accept( pReq->m_fdListen, (struct sockaddr *)&achPeer, &len ); if ( pReq->m_fd == -1 ) { if (( errno == EINTR )||( errno == EAGAIN)) continue; else return -1; } else { if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST); if (s_busy_workers) __atomic_fetch_add(s_busy_workers, 1, __ATOMIC_SEQ_CST); lsapi_set_nblock( pReq->m_fd , 0 ); if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) { setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); } //init_conn_key( pReq->m_fd ); //OPTIMIZATION if ( s_accept_notify ) if ( notify_req_received( pReq->m_fd ) == -1 ) return -1; } } else return -1; } if ( !readReq( pReq ) ) break; //abort(); lsapi_close_connection(pReq); LSAPI_Reset_r( pReq ); } return 0; } static struct lsapi_packet_header finish_close[2] = { {'L', 'S', LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }, {'L', 'S', LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} } }; int LSAPI_Finish_r( LSAPI_Request * pReq ) { /* finish req body */ if ( !pReq ) return -1; if (pReq->m_reqState) { if ( pReq->m_fd != -1 ) { if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { LSAPI_FinalizeRespHeaders_r( pReq ); } if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { Flush_RespBuf_r( pReq ); } pReq->m_pIovecCur->iov_base = (void *)finish_close; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN; pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN; ++pReq->m_pIovecCur; LSAPI_Flush_r( pReq ); } LSAPI_Reset_r( pReq ); } return 0; } int LSAPI_End_Response_r(LSAPI_Request * pReq) { if (!pReq) return -1; if (pReq->m_reqState & LSAPI_ST_BACKGROUND) return 0; if (pReq->m_reqState) { if ( pReq->m_fd != -1 ) { if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { if ( pReq->m_pRespHeaderBufPos <= pReq->m_pRespHeaderBuf ) return 0; LSAPI_FinalizeRespHeaders_r( pReq ); } if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { Flush_RespBuf_r( pReq ); } pReq->m_pIovecCur->iov_base = (void *)finish_close; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN << 1; pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN << 1; ++pReq->m_pIovecCur; LSAPI_Flush_r( pReq ); lsapi_close_connection(pReq); } pReq->m_reqState |= LSAPI_ST_BACKGROUND; } return 0; } void LSAPI_Reset_r( LSAPI_Request * pReq ) { pReq->m_pRespBufPos = pReq->m_pRespBuf; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1; pReq->m_pRespHeaderBufPos = pReq->m_pRespHeaderBuf; memset( &pReq->m_pHeaderIndex, 0, (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex ); } int LSAPI_Release_r( LSAPI_Request * pReq ) { if ( pReq->m_pReqBuf ) free( pReq->m_pReqBuf ); if ( pReq->m_pSpecialEnvList ) free( pReq->m_pSpecialEnvList ); if ( pReq->m_pEnvList ) free( pReq->m_pEnvList ); if ( pReq->m_pRespHeaderBuf ) free( pReq->m_pRespHeaderBuf ); return 0; } char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex ) { int off; if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) ) return NULL; off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ]; if ( !off ) return NULL; if ( *(pReq->m_pHttpHeader + off + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) ) { *( pReq->m_pHttpHeader + off + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0; } return pReq->m_pHttpHeader + off; } static int readBodyToReqBuf( LSAPI_Request * pReq ) { off_t bodyLeft; ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed; if ( len > 0 ) return len; pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen; bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead; len = pReq->m_reqBufSize - pReq->m_bufRead; if ( len < 0 ) return -1; if ( len > bodyLeft ) len = bodyLeft; len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len ); if ( len > 0 ) pReq->m_bufRead += len; return len; } int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq ) { if (!pReq || (pReq->m_fd ==-1) ) return EOF; if ( pReq->m_bufProcessed >= pReq->m_bufRead ) { if ( readBodyToReqBuf( pReq ) <= 0 ) return EOF; } ++pReq->m_reqBodyRead; return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++); } int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF ) { ssize_t len; ssize_t left; char * pBufEnd = pBuf + bufLen - 1; char * pBufCur = pBuf; char * pCur; char * p; if (!pReq || pReq->m_fd == -1 || !pBuf || !getLF) return -1; *getLF = 0; while( (left = pBufEnd - pBufCur ) > 0 ) { len = pReq->m_bufRead - pReq->m_bufProcessed; if ( len <= 0 ) { if ( (len = readBodyToReqBuf( pReq )) <= 0 ) { *getLF = 1; break; } } if ( len > left ) len = left; pCur = pReq->m_pReqBuf + pReq->m_bufProcessed; p = memchr( pCur, '\n', len ); if ( p ) len = p - pCur + 1; memmove( pBufCur, pCur, len ); pBufCur += len; pReq->m_bufProcessed += len; pReq->m_reqBodyRead += len; if ( p ) { *getLF = 1; break; } } *pBufCur = 0; return pBufCur - pBuf; } ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen ) { ssize_t len; off_t total; /* char *pOldBuf = pBuf; */ if (!pReq || pReq->m_fd == -1 || !pBuf || (ssize_t)bufLen < 0) return -1; total = pReq->m_reqBodyLen - pReq->m_reqBodyRead; if ( total <= 0 ) return 0; if ( total < (ssize_t)bufLen ) bufLen = total; total = 0; len = pReq->m_bufRead - pReq->m_bufProcessed; if ( len > 0 ) { if ( len > (ssize_t)bufLen ) len = bufLen; memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len ); pReq->m_bufProcessed += len; total += len; pBuf += len; bufLen -= len; } while( bufLen > 0 ) { len = lsapi_read( pReq->m_fd, pBuf, bufLen ); if ( len > 0 ) { total += len; pBuf += len; bufLen -= len; } else if ( len <= 0 ) { if ( !total) return -1; break; } } pReq->m_reqBodyRead += total; return total; } ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) { struct lsapi_packet_header * pHeader; const char * pEnd; const char * p; ssize_t bufLen; ssize_t toWrite; ssize_t packetLen; int skip = 0; if (!pReq || !pBuf) return -1; if (pReq->m_reqState & LSAPI_ST_BACKGROUND) return len; if (pReq->m_fd == -1) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { LSAPI_FinalizeRespHeaders_r( pReq ); /* if ( *pBuf == '\r' ) { ++skip; } if ( *pBuf == '\n' ) { ++skip; } */ } pReq->m_reqState |= LSAPI_ST_RESP_BODY; if ( ((ssize_t)len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos ) { memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip ); pReq->m_pRespBufPos += len - skip; return len; } pHeader = pReq->m_respPktHeader; p = pBuf + skip; pEnd = pBuf + len; bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf; while( ( toWrite = pEnd - p ) > 0 ) { packetLen = toWrite + bufLen; if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) { packetLen = LSAPI_MAX_DATA_PACKET_LEN; toWrite = packetLen - bufLen; } lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM, packetLen + LSAPI_PACKET_HEADER_LEN ); pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN; pReq->m_pIovecCur->iov_base = (void *)pHeader; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN; ++pReq->m_pIovecCur; ++pHeader; if ( bufLen > 0 ) { pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf; pReq->m_pIovecCur->iov_len = bufLen; pReq->m_pRespBufPos = pReq->m_pRespBuf; ++pReq->m_pIovecCur; bufLen = 0; } pReq->m_pIovecCur->iov_base = (void *)p; pReq->m_pIovecCur->iov_len = toWrite; ++pReq->m_pIovecCur; p += toWrite; if ( pHeader >= pReq->m_respPktHeaderEnd - 1) { if ( LSAPI_Flush_r( pReq ) == -1 ) return -1; pHeader = pReq->m_respPktHeader; } } if ( pHeader != pReq->m_respPktHeader ) if ( LSAPI_Flush_r( pReq ) == -1 ) return -1; return p - pBuf; } #if defined(__FreeBSD__ ) ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) { ssize_t ret; off_t written; ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 ); if ( written > 0 ) { ret = written; *off += ret; } return ret; } #endif #if defined(__OpenBSD__) || defined(__NetBSD__) ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) { ssize_t ret; off_t written = 0; const size_t bufsiz = 16384; unsigned char in[bufsiz] = {0}; if (lseek(fdIn, *off, SEEK_SET) == -1) { return -1; } while (size > 0) { size_t tor = size > sizeof(in) ? sizeof(in) : size; ssize_t c = read(fdIn, in, tor); if (c <= 0) { goto end; } ssize_t w = write(fdOut, in, c); if (w > 0) written += w; if (w != c) { goto end; } size -= c; } end: *off += written; return 0; } #endif #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) { ssize_t ret; off_t len = size; ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 ); if (( ret == 0 )&&( len > 0 )) { ret = len; *off += len; } return ret; } #endif #if defined(sun) || defined(__sun) #include ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size ) { int n = 0 ; sendfilevec_t vec[1]; vec[n].sfv_fd = fdIn; vec[n].sfv_flag = 0; vec[n].sfv_off = *off; vec[n].sfv_len = size; ++n; size_t written; ssize_t ret = sendfilev( fdOut, vec, n, &written ); if (( !ret )||( errno == EAGAIN )) ret = written; if ( ret > 0 ) *off += ret; return ret; } #endif #if defined(linux) || defined(__linux) || defined(__linux__) || \ defined(__gnu_linux__) #include #define gsendfile sendfile #endif #if defined(HPUX) ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size ) { return sendfile( fdOut, fdIn, off, size, NULL, 0 ); } #endif ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size ) { struct lsapi_packet_header * pHeader = pReq->m_respPktHeader; if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 ) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { LSAPI_FinalizeRespHeaders_r( pReq ); } pReq->m_reqState |= LSAPI_ST_RESP_BODY; LSAPI_Flush_r(pReq); lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM, size + LSAPI_PACKET_HEADER_LEN ); if (write(pReq->m_fd, (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN) return -1; return gsendfile( pReq->m_fd, fdIn, off, size ); } void Flush_RespBuf_r( LSAPI_Request * pReq ) { struct lsapi_packet_header * pHeader = pReq->m_respPktHeader; int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf; pReq->m_reqState |= LSAPI_ST_RESP_BODY; lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM, bufLen + LSAPI_PACKET_HEADER_LEN ); pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN; pReq->m_pIovecCur->iov_base = (void *)pHeader; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN; ++pReq->m_pIovecCur; ++pHeader; if ( bufLen > 0 ) { pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf; pReq->m_pIovecCur->iov_len = bufLen; pReq->m_pRespBufPos = pReq->m_pRespBuf; ++pReq->m_pIovecCur; bufLen = 0; } } int LSAPI_Flush_r( LSAPI_Request * pReq ) { int ret = 0; int n; if ( !pReq ) return -1; n = pReq->m_pIovecCur - pReq->m_pIovecToWrite; if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf )) return 0; if ( pReq->m_fd == -1 ) { pReq->m_pRespBufPos = pReq->m_pRespBuf; pReq->m_totalLen = 0; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec; return -1; } if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { LSAPI_FinalizeRespHeaders_r( pReq ); } if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { Flush_RespBuf_r( pReq ); } n = pReq->m_pIovecCur - pReq->m_pIovecToWrite; if ( n > 0 ) { ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite, n, pReq->m_totalLen ); if ( ret < pReq->m_totalLen ) { lsapi_close_connection(pReq); ret = -1; } pReq->m_totalLen = 0; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec; } return ret; } ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) { struct lsapi_packet_header header; const char * pEnd; const char * p; ssize_t packetLen; ssize_t totalLen; int ret; struct iovec iov[2]; struct iovec *pIov; if ( !pReq ) return -1; if (s_stderr_log_path || pReq->m_fd == -1 || pReq->m_fd == pReq->m_fdListen) return write( 2, pBuf, len ); if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { LSAPI_Flush_r( pReq ); } p = pBuf; pEnd = pBuf + len; while( ( packetLen = pEnd - p ) > 0 ) { if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) { packetLen = LSAPI_MAX_DATA_PACKET_LEN; } lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM, packetLen + LSAPI_PACKET_HEADER_LEN ); totalLen = packetLen + LSAPI_PACKET_HEADER_LEN; iov[0].iov_base = (void *)&header; iov[0].iov_len = LSAPI_PACKET_HEADER_LEN; iov[1].iov_base = (void *)p; iov[1].iov_len = packetLen; p += packetLen; pIov = iov; ret = lsapi_writev( pReq->m_fd, &pIov, 2, totalLen ); if ( ret < totalLen ) { lsapi_close_connection(pReq); ret = -1; } } return p - pBuf; } static char * GetHeaderVar( LSAPI_Request * pReq, const char * name ) { int i; char * pValue; for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { if ( strcmp( name, CGI_HEADERS[i] ) == 0 ) { pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i]; if ( *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) != '\0') { *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) = '\0'; } return pValue; } } } if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { const char *p; char *pKey; char *pKeyEnd; int keyLen; struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { pKey = pReq->m_pHttpHeader + pCur->nameOff; keyLen = pCur->nameLen; pKeyEnd = pKey + keyLen; p = &name[5]; while(( pKey < pKeyEnd )&&( *p )) { char ch = toupper( *pKey ); if ((ch != *p )||(( *p == '_' )&&( ch != '-'))) break; ++p; ++pKey; } if (( pKey == pKeyEnd )&& (!*p )) { pValue = pReq->m_pHttpHeader + pCur->valueOff; if ( *(pValue + pCur->valueLen) != '\0') { *(pValue + pCur->valueLen) = '\0'; } return pValue; } ++pCur; } } return NULL; } char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name ) { struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList; struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv; if ( !pReq || !name ) return NULL; if ( strncmp( name, "HTTP_", 5 ) == 0 ) { return GetHeaderVar( pReq, name ); } while( pBegin < pEnd ) { if ( strcmp( name, pBegin->pKey ) == 0 ) return pBegin->pValue; ++pBegin; } return NULL; } struct _headerInfo { const char * _name; int _nameLen; const char * _value; int _valueLen; }; int compareValueLocation(const void * v1, const void *v2 ) { return ((const struct _headerInfo *)v1)->_value - ((const struct _headerInfo *)v2)->_value; } int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { int i; int len = 0; char * pValue; int ret; int count = 0; struct _headerInfo headers[512]; if ( !pReq || !fn ) return -1; if ( !pReq->m_pHeaderIndex ) return 0; for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { len = pReq->m_pHeaderIndex->m_headerLen[i]; pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i]; *(pValue + len ) = 0; headers[count]._name = HTTP_HEADERS[i]; headers[count]._nameLen = HTTP_HEADER_LEN[i]; headers[count]._value = pValue; headers[count]._valueLen = len; ++count; //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i], // pValue, len, arg ); //if ( ret <= 0 ) // return ret; } } if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { char *pKey; int keyLen; struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { pKey = pReq->m_pHttpHeader + pCur->nameOff; keyLen = pCur->nameLen; *(pKey + keyLen ) = 0; pValue = pReq->m_pHttpHeader + pCur->valueOff; *(pValue + pCur->valueLen ) = 0; headers[count]._name = pKey; headers[count]._nameLen = keyLen; headers[count]._value = pValue; headers[count]._valueLen = pCur->valueLen; ++count; if ( count == 512 ) break; //ret = (*fn)( pKey, keyLen, // pValue, pCur->valueLen, arg ); //if ( ret <= 0 ) // return ret; ++pCur; } } qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation ); for( i = 0; i < count; ++i ) { ret = (*fn)( headers[i]._name, headers[i]._nameLen, headers[i]._value, headers[i]._valueLen, arg ); if ( ret <= 0 ) return ret; } return count; } int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { int i; int len = 0; char * pValue; int ret; int count = 0; if ( !pReq || !fn ) return -1; for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { len = pReq->m_pHeaderIndex->m_headerLen[i]; pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i]; *(pValue + len ) = 0; ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i], pValue, len, arg ); ++count; if ( ret <= 0 ) return ret; } } if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { char achHeaderName[256]; char *p; char *pKey; char *pKeyEnd ; int keyLen; struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; while( pCur < pEnd ) { pKey = pReq->m_pHttpHeader + pCur->nameOff; keyLen = pCur->nameLen; if ( keyLen > 250 ) keyLen = 250; pKeyEnd = pKey + keyLen; memcpy( achHeaderName, "HTTP_", 5 ); p = &achHeaderName[5]; while( pKey < pKeyEnd ) { char ch = *pKey++; if ( ch == '-' ) *p++ = '_'; else *p++ = toupper( ch ); } *p = 0; keyLen += 5; pValue = pReq->m_pHttpHeader + pCur->valueOff; *(pValue + pCur->valueLen ) = 0; ret = (*fn)( achHeaderName, keyLen, pValue, pCur->valueLen, arg ); if ( ret <= 0 ) return ret; ++pCur; } } return count + pReq->m_pHeader->m_cntUnknownHeaders; } static int EnvForeach( struct LSAPI_key_value_pair * pEnv, int n, LSAPI_CB_EnvHandler fn, void * arg ) { struct LSAPI_key_value_pair * pEnd = pEnv + n; int ret; if ( !pEnv || !fn ) return -1; while( pEnv < pEnd ) { ret = (*fn)( pEnv->pKey, pEnv->keyLen, pEnv->pValue, pEnv->valLen, arg ); if ( ret <= 0 ) return ret; ++pEnv; } return n; } int LSAPI_ForeachEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { if ( !pReq || !fn ) return -1; if ( pReq->m_pHeader->m_cntEnv > 0 ) { return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv, fn, arg ); } return 0; } int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { if ( !pReq || !fn ) return -1; if ( pReq->m_pHeader->m_cntSpecialEnv > 0 ) { return EnvForeach( pReq->m_pSpecialEnvList, pReq->m_pHeader->m_cntSpecialEnv, fn, arg ); } return 0; } int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq ) { if ( !pReq || !pReq->m_pIovec ) return -1; if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) ) return 0; pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER; if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf ) { pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf; pReq->m_pIovecCur->iov_len = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf; pReq->m_totalLen += pReq->m_pIovecCur->iov_len; ++pReq->m_pIovecCur; } pReq->m_pIovec->iov_len = sizeof( struct lsapi_resp_header) + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short ); pReq->m_totalLen += pReq->m_pIovec->iov_len; lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader, LSAPI_RESP_HEADER, pReq->m_totalLen ); pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader; pReq->m_pIovecToWrite = pReq->m_pIovec; return 0; } int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, const char * pHeaderValue ) { int nameLen, valLen, len; if ( !pReq || !pHeaderName || !pHeaderValue ) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) return -1; if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) return -1; nameLen = strlen( pHeaderName ); valLen = strlen( pHeaderValue ); if ( nameLen == 0 ) return -1; while( nameLen > 0 ) { char ch = *(pHeaderName + nameLen - 1 ); if (( ch == '\n' )||( ch == '\r' )) --nameLen; else break; } if ( nameLen <= 0 ) return 0; while( valLen > 0 ) { char ch = *(pHeaderValue + valLen - 1 ); if (( ch == '\n' )||( ch == '\r' )) --valLen; else break; } len = nameLen + valLen + 1; if ( len > LSAPI_RESP_HTTP_HEADER_MAX ) return -1; if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) { int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf; newlen -= newlen % 4096; if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) return -1; } memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen ); pReq->m_pRespHeaderBufPos += nameLen; *pReq->m_pRespHeaderBufPos++ = ':'; memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen ); pReq->m_pRespHeaderBufPos += valLen; *pReq->m_pRespHeaderBufPos++ = 0; ++len; /* add one byte padding for \0 */ pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len; ++pReq->m_respHeader.m_respInfo.m_cntHeaders; return 0; } int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len ) { if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX ) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) return -1; if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) return -1; while( len > 0 ) { char ch = *(pBuf + len - 1 ); if (( ch == '\n' )||( ch == '\r' )) --len; else break; } if ( len <= 0 ) return 0; if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) { int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf; newlen -= newlen % 4096; if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) return -1; } memmove( pReq->m_pRespHeaderBufPos, pBuf, len ); pReq->m_pRespHeaderBufPos += len; *pReq->m_pRespHeaderBufPos++ = 0; ++len; /* add one byte padding for \0 */ pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len; ++pReq->m_respHeader.m_respInfo.m_cntHeaders; return 0; } int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog ) { int ret; int fd; int flag = 1; int addr_len; switch( pServerAddr->sa_family ) { case AF_INET: addr_len = 16; break; case AF_INET6: addr_len = sizeof( struct sockaddr_in6 ); break; case AF_UNIX: addr_len = sizeof( struct sockaddr_un ); unlink( ((struct sockaddr_un *)pServerAddr)->sun_path ); break; default: return -1; } fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 ); if ( fd == -1 ) return -1; fcntl( fd, F_SETFD, FD_CLOEXEC ); if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (char *)( &flag ), sizeof(flag)) == 0) { ret = bind( fd, pServerAddr, addr_len ); if ( !ret ) { ret = listen( fd, backlog ); if ( !ret ) return fd; } } ret = errno; close(fd); errno = ret; return -1; } int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) { char achAddr[256]; char * p = achAddr; char * pEnd; struct addrinfo *res, hints; int doAddrInfo = 0; int port; if ( !pBind ) return -1; while( isspace( *pBind ) ) ++pBind; strncpy(achAddr, pBind, 255); achAddr[255] = 0; switch( *p ) { case '/': pAddr->sa_family = AF_UNIX; strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p, sizeof(((struct sockaddr_un *)pAddr)->sun_path) ); return 0; case '[': pAddr->sa_family = AF_INET6; ++p; pEnd = strchr( p, ']' ); if ( !pEnd ) return -1; *pEnd++ = 0; if ( *p == '*' ) { strcpy( achAddr, "::" ); p = achAddr; } doAddrInfo = 1; break; default: pAddr->sa_family = AF_INET; pEnd = strchr( p, ':' ); if ( !pEnd ) return -1; *pEnd++ = 0; doAddrInfo = 0; if ( *p == '*' ) { ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY); } else if (!strcasecmp( p, "localhost" ) ) ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK ); else { #ifdef HAVE_INET_PTON if (!inet_pton(AF_INET, p, &((struct sockaddr_in *)pAddr)->sin_addr)) #else ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p ); if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST) #endif { doAddrInfo = 1; } } break; } if ( *pEnd == ':' ) ++pEnd; port = atoi( pEnd ); if (( port <= 0 )||( port > 65535 )) return -1; if ( doAddrInfo ) { memset(&hints, 0, sizeof(hints)); hints.ai_family = pAddr->sa_family; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if ( getaddrinfo(p, NULL, &hints, &res) ) { return -1; } memcpy(pAddr, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); } if ( pAddr->sa_family == AF_INET ) ((struct sockaddr_in *)pAddr)->sin_port = htons( port ); else ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port ); return 0; } int LSAPI_CreateListenSock( const char * pBind, int backlog ) { char serverAddr[128]; int ret; int fd = -1; ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr ); if ( !ret ) { fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog ); } return fd; } static fn_select_t g_fnSelect = select; typedef struct _lsapi_prefork_server { int m_fd; int m_iMaxChildren; int m_iExtraChildren; int m_iCurChildren; int m_iMaxIdleChildren; int m_iServerMaxIdle; int m_iChildrenMaxIdleTime; int m_iMaxReqProcessTime; int m_iAvoidFork; lsapi_child_status * m_pChildrenStatus; lsapi_child_status * m_pChildrenStatusCur; lsapi_child_status * m_pChildrenStatusEnd; }lsapi_prefork_server; static lsapi_prefork_server * g_prefork_server = NULL; int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ) { if ( g_prefork_server ) return 0; if ( max_children <= 1 ) return -1; if ( max_children >= 10000) max_children = 10000; if (s_max_busy_workers == 0) s_max_busy_workers = max_children / 2 + 1; g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) ); if ( !g_prefork_server ) return -1; memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) ); if ( fp != NULL ) g_fnSelect = fp; s_ppid = getppid(); s_pid = getpid(); setpgid( s_pid, s_pid ); #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) s_total_pages = sysconf(_SC_PHYS_PAGES); #endif g_prefork_server->m_iAvoidFork = avoidFork; g_prefork_server->m_iMaxChildren = max_children; g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ; g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3); if ( g_prefork_server->m_iMaxIdleChildren == 0 ) g_prefork_server->m_iMaxIdleChildren = 1; g_prefork_server->m_iChildrenMaxIdleTime = 300; g_prefork_server->m_iMaxReqProcessTime = 3600; setsid(); return 0; } void LSAPI_Set_Server_fd( int fd ) { if( g_prefork_server ) g_prefork_server->m_fd = fd; } static int lsapi_accept( int fdListen ) { int fd; int nodelay = 1; socklen_t len; char achPeer[128]; len = sizeof( achPeer ); fd = accept( fdListen, (struct sockaddr *)&achPeer, &len ); if ( fd != -1 ) { if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) { setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); } //OPTIMIZATION //if ( s_accept_notify ) // notify_req_received( fd ); } return fd; } static unsigned int s_max_reqs = UINT_MAX; static int s_max_idle_secs = 300; static int s_stop; static void lsapi_cleanup(int signal) { s_stop = signal; } static lsapi_child_status * find_child_status( int pid ) { lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd; while( pStatus < pEnd ) { if ( pStatus->m_pid == pid ) { if (pid == 0) { memset(pStatus, 0, sizeof( *pStatus ) ); pStatus->m_pid = -1; } if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur ) g_prefork_server->m_pChildrenStatusCur = pStatus + 1; return pStatus; } ++pStatus; } return NULL; } void LSAPI_reset_server_state( void ) { /* Reset child status */ g_prefork_server->m_iCurChildren = 0; lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd; while( pStatus < pEnd ) { pStatus->m_pid = 0; ++pStatus; } if (s_busy_workers) __atomic_store_n(s_busy_workers, 0, __ATOMIC_SEQ_CST); if (s_accepting_workers) __atomic_store_n(s_accepting_workers, 0, __ATOMIC_SEQ_CST); } static void lsapi_sigchild( int signal ) { int status, pid; char expect_connected = LSAPI_STATE_CONNECTED; char expect_accepting = LSAPI_STATE_ACCEPTING; lsapi_child_status * child_status; if (g_prefork_server == NULL) return; while( 1 ) { pid = waitpid( -1, &status, WNOHANG|WUNTRACED ); if ( pid <= 0 ) { break; } if ( WIFSIGNALED( status )) { int sig_num = WTERMSIG( status ); #ifdef WCOREDUMP const char * dump = WCOREDUMP( status ) ? "yes" : "no"; #else const char * dump = "unknown"; #endif lsapi_log("Child process with pid: %d was killed by signal: " "%d, core dumped: %s\n", pid, sig_num, dump ); } if ( pid == s_pid_dump_debug_info ) { pid = 0; continue; } if ( pid == s_ignore_pid ) { pid = 0; s_ignore_pid = -1; continue; } child_status = find_child_status( pid ); if ( child_status ) { if (__atomic_compare_exchange_n(&child_status->m_state, &expect_connected, LSAPI_STATE_IDLE, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { if (s_busy_workers) __atomic_fetch_sub(s_busy_workers, 1, __ATOMIC_SEQ_CST); } else if (__atomic_compare_exchange_n(&child_status->m_state, &expect_accepting, LSAPI_STATE_IDLE, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { if (s_accepting_workers) __atomic_fetch_sub(s_accepting_workers, 1, __ATOMIC_SEQ_CST); } child_status->m_pid = 0; --g_prefork_server->m_iCurChildren; } } while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus ) &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 )) --g_prefork_server->m_pChildrenStatusCur; } static int lsapi_init_children_status(void) { char * pBuf; int size = 4096; int max_children; if (g_prefork_server->m_pChildrenStatus) return 0; max_children = g_prefork_server->m_iMaxChildren + g_prefork_server->m_iExtraChildren; size = max_children * sizeof( lsapi_child_status ) * 2 + 3 * sizeof(int); size = (size + 4095) / 4096 * 4096; pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0 ); if ( pBuf == MAP_FAILED ) { perror( "Anonymous mmap() failed" ); return -1; } memset( pBuf, 0, size ); g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf; g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf; g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + max_children; s_busy_workers = (int *)g_prefork_server->m_pChildrenStatusEnd; s_accepting_workers = s_busy_workers + 1; s_global_counter = s_accepting_workers + 1; s_avail_pages = (size_t *)(s_global_counter + 1); setsid(); return 0; } static void dump_debug_info( lsapi_child_status * pStatus, long tmCur ) { char achCmd[1024]; if ( s_pid_dump_debug_info ) { if ( kill( s_pid_dump_debug_info, 0 ) == 0 ) return; } lsapi_log("Possible runaway process, UID: %d, PPID: %d, PID: %d, " "reqCount: %d, process time: %ld, checkpoint time: %ld, start " "time: %ld\n", getuid(), getppid(), pStatus->m_pid, pStatus->m_iReqCounter, tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart ); s_pid_dump_debug_info = fork(); if (s_pid_dump_debug_info == 0) { snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" " "-ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2", pStatus->m_pid, pStatus->m_pid ); if ( system( achCmd ) == -1 ) perror( "system()" ); exit( 0 ); } } static void lsapi_check_child_status( long tmCur ) { int idle = 0; int tobekilled; int dying = 0; int count = 0; lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur; while( pStatus < pEnd ) { tobekilled = 0; if ( pStatus->m_pid != 0 && pStatus->m_pid != -1) { ++count; if ( !pStatus->m_inProcess ) { if (g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren || idle > g_prefork_server->m_iMaxIdleChildren) { ++pStatus->m_iKillSent; //tobekilled = SIGUSR1; } else { if (s_max_idle_secs> 0 && tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5) { ++pStatus->m_iKillSent; //tobekilled = SIGUSR1; } } if (!pStatus->m_iKillSent) ++idle; } else { if (tmCur - pStatus->m_tmReqBegin > g_prefork_server->m_iMaxReqProcessTime) { if ((pStatus->m_iKillSent % 5) == 0 && s_dump_debug_info) dump_debug_info( pStatus, tmCur ); if ( pStatus->m_iKillSent > 5 ) { tobekilled = SIGKILL; lsapi_log("Force killing runaway process PID: %d" " with SIGKILL\n", pStatus->m_pid ); } else { tobekilled = SIGTERM; lsapi_log("Killing runaway process PID: %d with " "SIGTERM\n", pStatus->m_pid ); } } } if ( tobekilled ) { if (( kill( pStatus->m_pid, tobekilled ) == -1 ) && ( errno == ESRCH )) { pStatus->m_pid = 0; --count; } else { ++pStatus->m_iKillSent; ++dying; } } } ++pStatus; } if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 ) { lsapi_log("Children tracking is wrong: Cur Children: %d," " count: %d, idle: %d, dying: %d\n", g_prefork_server->m_iCurChildren, count, idle, dying ); } } //static int lsapi_all_children_must_die(void) //{ // int maxWait; // int sec =0; // g_prefork_server->m_iMaxReqProcessTime = 10; // g_prefork_server->m_iMaxIdleChildren = -1; // maxWait = 15; // // while( g_prefork_server->m_iCurChildren && (sec < maxWait) ) // { // lsapi_check_child_status(time(NULL)); // sleep( 1 ); // sec++; // } // if ( g_prefork_server->m_iCurChildren != 0 ) // kill( -getpgrp(), SIGKILL ); // return 0; //} void set_skip_write(void) { s_skip_write = 1; } int is_enough_free_mem(void) { #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) //minimum 1GB or 10% available free memory return (*s_avail_pages > s_min_avail_pages || (*s_avail_pages * 10) / s_total_pages > 0); #endif return 1; } static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Request * pReq ) { struct sigaction act, old_term, old_quit, old_int, old_usr1, old_child; lsapi_child_status * child_status; int wait_secs = 0; int ret = 0; int pid; time_t lastTime = 0; time_t curTime = 0; fd_set readfds; struct timeval timeout; sigset_t mask; sigset_t orig_mask; lsapi_init_children_status(); act.sa_flags = 0; act.sa_handler = lsapi_sigchild; sigemptyset(&(act.sa_mask)); if( sigaction( SIGCHLD, &act, &old_child ) ) { perror( "Can't set signal handler for SIGCHILD" ); return -1; } /* Set up handler to kill children upon exit */ act.sa_flags = 0; act.sa_handler = lsapi_cleanup; sigemptyset(&(act.sa_mask)); if( sigaction( SIGTERM, &act, &old_term ) || sigaction( SIGINT, &act, &old_int ) || sigaction( SIGUSR1, &act, &old_usr1 ) || sigaction( SIGQUIT, &act, &old_quit )) { perror( "Can't set signals" ); return -1; } while( !s_stop ) { if (s_proc_group_timer_cb != NULL) { s_proc_group_timer_cb(&s_ignore_pid); } curTime = time( NULL ); if (curTime != lastTime ) { lastTime = curTime; if (lsapi_parent_dead()) break; lsapi_check_child_status(curTime ); if (pServer->m_iServerMaxIdle) { if ( pServer->m_iCurChildren <= 0 ) { ++wait_secs; if ( wait_secs > pServer->m_iServerMaxIdle ) return -1; } else wait_secs = 0; } } #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) *s_avail_pages = sysconf(_SC_AVPHYS_PAGES); // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n", // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages); #endif FD_ZERO( &readfds ); FD_SET( pServer->m_fd, &readfds ); timeout.tv_sec = 1; timeout.tv_usec = 0; ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout); if (ret == 1 ) { int accepting = 0; if (s_accepting_workers) accepting = __atomic_load_n(s_accepting_workers, __ATOMIC_SEQ_CST); if (pServer->m_iCurChildren > 0 && accepting > 0) { usleep(400); while(accepting-- > 0) sched_yield(); continue; } } else if ( ret == -1 ) { if ( errno == EINTR ) continue; /* perror( "select()" ); */ break; } else { continue; } if (pServer->m_iCurChildren >= pServer->m_iMaxChildren + pServer->m_iExtraChildren) { lsapi_log("Reached max children process limit: %d, extra: %d," " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n", pServer->m_iMaxChildren, pServer->m_iExtraChildren, pServer->m_iCurChildren, s_busy_workers ? *s_busy_workers : -1 ); usleep( 100000 ); continue; } pReq->m_fd = lsapi_accept( pServer->m_fd ); if ( pReq->m_fd != -1 ) { wait_secs = 0; child_status = find_child_status( 0 ); sigemptyset( &mask ); sigaddset( &mask, SIGCHLD ); if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 ) { perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" ); } pid = fork(); if ( !pid ) { setsid(); if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" ); g_prefork_server = NULL; s_ppid = getppid(); s_pid = getpid(); s_req_processed = 0; s_proc_group_timer_cb = NULL; s_worker_status = child_status; if (pthread_atfork_func) (*pthread_atfork_func)(NULL, NULL, set_skip_write); __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST); if (s_busy_workers) __atomic_add_fetch(s_busy_workers, 1, __ATOMIC_SEQ_CST); lsapi_set_nblock( pReq->m_fd, 0 ); //keep it open if busy_count is used. if (!s_keep_listener && s_busy_workers && *s_busy_workers > (pServer->m_iMaxChildren >> 1)) s_keep_listener = 1; if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem()) && pReq->m_fdListen != -1 ) { close( pReq->m_fdListen ); pReq->m_fdListen = -1; } /* don't catch our signals */ sigaction( SIGCHLD, &old_child, 0 ); sigaction( SIGTERM, &old_term, 0 ); sigaction( SIGQUIT, &old_quit, 0 ); sigaction( SIGINT, &old_int, 0 ); sigaction( SIGUSR1, &old_usr1, 0 ); //init_conn_key( pReq->m_fd ); lsapi_notify_pid( pReq->m_fd ); s_notified_pid = 1; //if ( s_accept_notify ) // return notify_req_received( pReq->m_fd ); return 0; } else if ( pid == -1 ) { lsapi_perror("fork() failed, please increase process limit", errno); if (child_status) child_status->m_pid = 0; } else { ++pServer->m_iCurChildren; if ( child_status ) { child_status->m_pid = pid; child_status->m_tmWaitBegin = curTime; child_status->m_tmStart = curTime; } } close( pReq->m_fd ); pReq->m_fd = -1; if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" ); } else { if (( errno == EINTR )||( errno == EAGAIN)) continue; lsapi_perror("accept() failed", errno); return -1; } } sigaction( SIGUSR1, &old_usr1, 0 ); //kill( -getpgrp(), SIGUSR1 ); //lsapi_all_children_must_die(); /* Sorry, children ;-) */ return -1; } static struct sigaction old_term, old_quit, old_int, old_usr1, old_child; int LSAPI_Postfork_Child(LSAPI_Request * pReq) { int max_children = g_prefork_server->m_iMaxChildren; s_pid = getpid(); __atomic_store_n(&pReq->child_status->m_pid, s_pid, __ATOMIC_SEQ_CST); s_worker_status = pReq->child_status; setsid(); g_prefork_server = NULL; s_ppid = getppid(); s_req_processed = 0; s_proc_group_timer_cb = NULL; if (pthread_atfork_func) (*pthread_atfork_func)(NULL, NULL, set_skip_write); __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST); if (s_busy_workers) __atomic_add_fetch(s_busy_workers, 1, __ATOMIC_SEQ_CST); lsapi_set_nblock( pReq->m_fd, 0 ); //keep it open if busy_count is used. if (!s_keep_listener && s_busy_workers && *s_busy_workers > (max_children >> 1)) s_keep_listener = 1; if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem()) && pReq->m_fdListen != -1 ) { close(pReq->m_fdListen); pReq->m_fdListen = -1; } //init_conn_key( pReq->m_fd ); lsapi_notify_pid(pReq->m_fd); s_notified_pid = 1; //if ( s_accept_notify ) // return notify_req_received( pReq->m_fd ); return 0; } int LSAPI_Postfork_Parent(LSAPI_Request * pReq) { ++g_prefork_server->m_iCurChildren; if (pReq->child_status) { time_t curTime = time( NULL ); pReq->child_status->m_tmWaitBegin = curTime; pReq->child_status->m_tmStart = curTime; } close(pReq->m_fd); pReq->m_fd = -1; return 0; } int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq) { time_t lastTime = 0; time_t curTime = 0; fd_set readfds; struct timeval timeout; int wait_secs = 0; int ret = 0; lsapi_prefork_server * pServer = g_prefork_server; struct sigaction act; lsapi_init_children_status(); act.sa_flags = 0; act.sa_handler = lsapi_sigchild; sigemptyset(&(act.sa_mask)); if (sigaction(SIGCHLD, &act, &old_child)) { perror( "Can't set signal handler for SIGCHILD" ); return -1; } /* Set up handler to kill children upon exit */ act.sa_flags = 0; act.sa_handler = lsapi_cleanup; sigemptyset(&(act.sa_mask)); if (sigaction(SIGTERM, &act, &old_term) || sigaction(SIGINT, &act, &old_int ) || sigaction(SIGUSR1, &act, &old_usr1) || sigaction(SIGQUIT, &act, &old_quit)) { perror( "Can't set signals" ); return -1; } s_stop = 0; pReq->m_reqState = 0; while(!s_stop) { if (s_proc_group_timer_cb != NULL) { s_proc_group_timer_cb(&s_ignore_pid); } curTime = time(NULL); if (curTime != lastTime) { lastTime = curTime; if (lsapi_parent_dead()) break; lsapi_check_child_status(curTime); if (pServer->m_iServerMaxIdle) { if (pServer->m_iCurChildren <= 0) { ++wait_secs; if ( wait_secs > pServer->m_iServerMaxIdle ) return -1; } else wait_secs = 0; } } #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) *s_avail_pages = sysconf(_SC_AVPHYS_PAGES); // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n", // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages); #endif FD_ZERO(&readfds); FD_SET(pServer->m_fd, &readfds); timeout.tv_sec = 1; timeout.tv_usec = 0; ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout); if (ret == 1 ) { int accepting = 0; if (s_accepting_workers) accepting = __atomic_load_n(s_accepting_workers, __ATOMIC_SEQ_CST); if (pServer->m_iCurChildren > 0 && accepting > 0) { usleep( 400); while(accepting-- > 0) sched_yield(); continue; } } else if (ret == -1) { if (errno == EINTR) continue; /* perror( "select()" ); */ break; } else { continue; } if (pServer->m_iCurChildren >= pServer->m_iMaxChildren + pServer->m_iExtraChildren) { lsapi_log("Reached max children process limit: %d, extra: %d," " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n", pServer->m_iMaxChildren, pServer->m_iExtraChildren, pServer->m_iCurChildren, s_busy_workers ? *s_busy_workers : -1); usleep(100000); continue; } pReq->m_fd = lsapi_accept(pServer->m_fd); if (pReq->m_fd != -1) { wait_secs = 0; pReq->child_status = find_child_status(0); ret = 0; break; } else { if ((errno == EINTR) || (errno == EAGAIN)) continue; lsapi_perror("accept() failed", errno); ret = -1; break; } } sigaction(SIGCHLD, &old_child, 0); sigaction(SIGTERM, &old_term, 0); sigaction(SIGQUIT, &old_quit, 0); sigaction(SIGINT, &old_int, 0); sigaction(SIGUSR1, &old_usr1, 0); return ret; } int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) { int fd; int ret; int wait_secs; fd_set readfds; struct timeval timeout; if (s_skip_write) return -1; LSAPI_Finish_r( pReq ); if ( g_prefork_server ) { if ( g_prefork_server->m_fd != -1 ) if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 ) return -1; } else if (s_req_processed > 0 && s_max_busy_workers > 0 && s_busy_workers) { ret = __atomic_load_n(s_busy_workers, __ATOMIC_SEQ_CST); if (ret >= s_max_busy_workers) { send_conn_close_notification(pReq->m_fd); lsapi_close_connection(pReq); } } if ( (unsigned int)s_req_processed > s_max_reqs ) return -1; if ( s_worker_status ) { s_worker_status->m_tmWaitBegin = time( NULL ); } while( g_running ) { if ( pReq->m_fd != -1 ) { fd = pReq->m_fd; } else if ( pReq->m_fdListen != -1 ) fd = pReq->m_fdListen; else { break; } wait_secs = 0; while( 1 ) { if ( !g_running ) return -1; if (s_req_processed && s_worker_status && s_worker_status->m_iKillSent) return -1; FD_ZERO( &readfds ); FD_SET( fd, &readfds ); timeout.tv_sec = 1; timeout.tv_usec = 0; if (fd == pReq->m_fdListen) { if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_ACCEPTING, __ATOMIC_SEQ_CST); if (s_accepting_workers) __atomic_fetch_add(s_accepting_workers, 1, __ATOMIC_SEQ_CST); } ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout); if (fd == pReq->m_fdListen) { if (s_accepting_workers) __atomic_fetch_sub(s_accepting_workers, 1, __ATOMIC_SEQ_CST); if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_IDLE, __ATOMIC_SEQ_CST); } if ( ret == 0 ) { if ( s_worker_status ) { s_worker_status->m_inProcess = 0; if (fd == pReq->m_fdListen) { if (s_keep_listener == 0 || !is_enough_free_mem()) return -1; if (s_keep_listener == 1) { int wait_time = 10; if (s_busy_workers) wait_time += *s_busy_workers * 10; if (s_accepting_workers) wait_time >>= (*s_accepting_workers); if (wait_secs >= wait_time) return -1; } } } ++wait_secs; if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs )) return -1; if ( lsapi_parent_dead() ) return -1; } else if ( ret == -1 ) { if ( errno == EINTR ) continue; else return -1; } else if ( ret >= 1 ) { if (s_req_processed && s_worker_status && s_worker_status->m_iKillSent) return -1; if ( fd == pReq->m_fdListen ) { pReq->m_fd = lsapi_accept( pReq->m_fdListen ); if ( pReq->m_fd != -1 ) { if (s_worker_status) __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST); if (s_busy_workers) __atomic_fetch_add(s_busy_workers, 1, __ATOMIC_SEQ_CST); fd = pReq->m_fd; lsapi_set_nblock( fd, 0 ); //init_conn_key( pReq->m_fd ); if (!s_keep_listener) { close( pReq->m_fdListen ); pReq->m_fdListen = -1; } if ( s_accept_notify ) if ( notify_req_received( pReq->m_fd ) == -1 ) return -1; } else { if (( errno == EINTR )||( errno == EAGAIN)) continue; lsapi_perror( "lsapi_accept() error", errno ); return -1; } } else break; } } if ( !readReq( pReq ) ) { if ( s_worker_status ) { s_worker_status->m_iKillSent = 0; s_worker_status->m_inProcess = 1; ++s_worker_status->m_iReqCounter; s_worker_status->m_tmReqBegin = s_worker_status->m_tmLastCheckPoint = time(NULL); } ++s_req_processed; return 0; } lsapi_close_connection(pReq); LSAPI_Reset_r( pReq ); } return -1; } void LSAPI_Set_Max_Reqs( int reqs ) { s_max_reqs = reqs - 1; } void LSAPI_Set_Max_Idle( int secs ) { s_max_idle_secs = secs; } void LSAPI_Set_Max_Children( int maxChildren ) { if ( g_prefork_server ) g_prefork_server->m_iMaxChildren = maxChildren; } void LSAPI_Set_Extra_Children( int extraChildren ) { if (( g_prefork_server )&&( extraChildren >= 0 )) g_prefork_server->m_iExtraChildren = extraChildren; } void LSAPI_Set_Max_Process_Time( int secs ) { if (( g_prefork_server )&&( secs > 0 )) g_prefork_server->m_iMaxReqProcessTime = secs; } void LSAPI_Set_Max_Idle_Children( int maxIdleChld ) { if (( g_prefork_server )&&( maxIdleChld > 0 )) g_prefork_server->m_iMaxIdleChildren = maxIdleChld; } void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle ) { if ( g_prefork_server ) g_prefork_server->m_iServerMaxIdle = serverMaxIdle; } void LSAPI_Set_Slow_Req_Msecs( int msecs ) { s_slow_req_msecs = msecs; } int LSAPI_Get_Slow_Req_Msecs(void) { return s_slow_req_msecs; } void LSAPI_No_Check_ppid(void) { s_ppid = 0; } int LSAPI_Get_ppid(void) { return(s_ppid); } #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) #include #else extern char ** environ; #endif static void unset_lsapi_envs(void) { char **env; #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) env = *_NSGetEnviron(); #else env = environ; #endif while( env != NULL && *env != NULL ) { if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 ) || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid))) { char ** del = env; do *del = del[1]; while( *del++ ); } else ++env; } } static int lsapi_initSuEXEC(void) { int i; struct passwd * pw; s_defaultUid = 0; s_defaultGid = 0; if ( s_uid == 0 ) { const char * p = getenv( "LSAPI_DEFAULT_UID" ); if ( p ) { i = atoi( p ); if ( i > 0 ) s_defaultUid = i; } p = getenv( "LSAPI_DEFAULT_GID" ); if ( p ) { i = atoi( p ); if ( i > 0 ) s_defaultGid = i; } p = getenv( "LSAPI_SECRET" ); if (( !p )||( readSecret(p) == -1 )) return -1; if ( g_prefork_server ) { if ( g_prefork_server->m_iMaxChildren < 100 ) g_prefork_server->m_iMaxChildren = 100; if ( g_prefork_server->m_iExtraChildren < 1000 ) g_prefork_server->m_iExtraChildren = 1000; } } if ( !s_defaultUid || !s_defaultGid ) { pw = getpwnam( "nobody" ); if ( pw ) { if ( !s_defaultUid ) s_defaultUid = pw->pw_uid; if ( !s_defaultGid ) s_defaultGid = pw->pw_gid; } else { if ( !s_defaultUid ) s_defaultUid = 10000; if ( !s_defaultGid ) s_defaultGid = 10000; } } return 0; } static int lsapi_check_path(const char *p, char *final, int max_len) { char resolved_path[PATH_MAX+1]; int len = 0; char *end; if (*p != '/') { if (getcwd(final, max_len) == NULL) return -1; len = strlen(final); *(final + len) = '/'; ++len; } end = memccpy(&final[len], p, '\0', PATH_MAX - len); if (!end) { errno = EINVAL; return -1; } p = final; if (realpath(p, resolved_path) == NULL && errno != ENOENT && errno != EACCES) return -1; if (strncmp(resolved_path, "/etc/", 5) == 0) { errno = EPERM; return -1; } return 0; } static int lsapi_reopen_stderr2(const char *full_path) { int newfd = open(full_path, O_WRONLY | O_CREAT | O_APPEND, 0644); if (newfd == -1) { LSAPI_perror_r(NULL, "Failed to open custom stderr log", full_path); return -1; } if (newfd != 2) { dup2(newfd, 2); close(newfd); dup2(2, 1); } if (s_stderr_log_path && full_path != s_stderr_log_path) { free(s_stderr_log_path); s_stderr_log_path = NULL; } s_stderr_log_path = strdup(full_path); return 0; } static int lsapi_reopen_stderr(const char *p) { char full_path[PATH_MAX]; if (s_uid == 0) return -1; if (lsapi_check_path(p, full_path, PATH_MAX) == -1) { LSAPI_perror_r(NULL, "Invalid custom stderr log path", p); return -1; } return lsapi_reopen_stderr2(full_path); } int LSAPI_Init_Env_Parameters( fn_select_t fp ) { const char *p; char ch; int n; int avoidFork = 0; p = getenv("LSAPI_STDERR_LOG"); if (p) { lsapi_reopen_stderr(p); } if (!s_stderr_log_path) s_stderr_is_pipe = isPipe(STDERR_FILENO); p = getenv( "PHP_LSAPI_MAX_REQUESTS" ); if ( !p ) p = getenv( "LSAPI_MAX_REQS" ); if ( p ) { n = atoi( p ); if ( n > 0 ) LSAPI_Set_Max_Reqs( n ); } p = getenv( "LSAPI_KEEP_LISTEN" ); if ( p ) { n = atoi( p ); s_keep_listener = n; } p = getenv( "LSAPI_AVOID_FORK" ); if ( p ) { avoidFork = atoi( p ); if (avoidFork) { s_keep_listener = 2; ch = *(p + strlen(p) - 1); if ( ch == 'G' || ch == 'g' ) avoidFork *= 1024 * 1024 * 1024; else if ( ch == 'M' || ch == 'm' ) avoidFork *= 1024 * 1024; if (avoidFork >= 1024 * 10240) s_min_avail_pages = avoidFork / 4096; } } p = getenv( "LSAPI_ACCEPT_NOTIFY" ); if ( p ) { s_accept_notify = atoi( p ); } p = getenv( "LSAPI_SLOW_REQ_MSECS" ); if ( p ) { n = atoi( p ); LSAPI_Set_Slow_Req_Msecs( n ); } #if defined( RLIMIT_CORE ) p = getenv( "LSAPI_ALLOW_CORE_DUMP" ); if ( !p ) { struct rlimit limit = { 0, 0 }; setrlimit( RLIMIT_CORE, &limit ); } else s_enable_core_dump = 1; #endif p = getenv( "LSAPI_MAX_IDLE" ); if ( p ) { n = atoi( p ); LSAPI_Set_Max_Idle( n ); } if ( LSAPI_Is_Listen() ) { n = 0; p = getenv( "PHP_LSAPI_CHILDREN" ); if ( !p ) p = getenv( "LSAPI_CHILDREN" ); if ( p ) n = atoi( p ); if ( n > 1 ) { LSAPI_Init_Prefork_Server( n, fp, avoidFork != 0 ); LSAPI_Set_Server_fd( g_req.m_fdListen ); } p = getenv( "LSAPI_EXTRA_CHILDREN" ); if ( p ) LSAPI_Set_Extra_Children( atoi( p ) ); p = getenv( "LSAPI_MAX_IDLE_CHILDREN" ); if ( p ) LSAPI_Set_Max_Idle_Children( atoi( p ) ); p = getenv( "LSAPI_PGRP_MAX_IDLE" ); if ( p ) { LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) ); } p = getenv( "LSAPI_MAX_PROCESS_TIME" ); if ( p ) LSAPI_Set_Max_Process_Time( atoi( p ) ); if ( getenv( "LSAPI_PPID_NO_CHECK" ) ) { LSAPI_No_Check_ppid(); } p = getenv("LSAPI_MAX_BUSY_WORKER"); if (p) { n = atoi(p); s_max_busy_workers = n; if (n >= 0) LSAPI_No_Check_ppid(); } p = getenv( "LSAPI_DUMP_DEBUG_INFO" ); if ( p ) s_dump_debug_info = atoi( p ); if ( lsapi_initSuEXEC() == -1 ) return -1; #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) lsapi_initLVE(); #endif } unset_lsapi_envs(); return 0; } int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders, const char * pBody, int bodyLen ) { LSAPI_SetRespStatus_r( pReq, code ); if ( pRespHeaders ) { while( *pRespHeaders ) { LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) ); ++pRespHeaders; } } if ( pBody &&( bodyLen > 0 )) { LSAPI_Write_r( pReq, pBody, bodyLen ); } LSAPI_Finish_r( pReq ); return 0; } static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]); /* * Note: this code is harmless on little-endian machines. */ static void byteReverse(unsigned char *buf, unsigned longs) { uint32 t; do { t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); *(uint32 *) buf = t; buf += 4; } while (--longs); } /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ void lsapi_MD5Init(struct lsapi_MD5Context *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bits[0] = 0; ctx->bits[1] = 0; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len) { register uint32 t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if (t) { unsigned char *p = (unsigned char *) ctx->in + t; t = 64 - t; if (len < t) { memmove(p, buf, len); return; } memmove(p, buf, t); byteReverse(ctx->in, 16); lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { memmove(ctx->in, buf, 64); byteReverse(ctx->in, 16); lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ memmove(ctx->in, buf, len); } /* * Final wrap-up - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx) { unsigned int count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in, 16); lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); } else { /* Pad block to 56 bytes */ memset(p, 0, count - 8); } byteReverse(ctx->in, 14); /* Append length in bits and transform */ ((uint32 *) ctx->in)[14] = ctx->bits[0]; ((uint32 *) ctx->in)[15] = ctx->bits[1]; lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memmove(digest, ctx->buf, 16); memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ } /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]) { register uint32 a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } int LSAPI_Set_Restored_Parent_Pid(int pid) { int old_ppid = s_ppid; s_restored_ppid = pid; return old_ppid; } int LSAPI_Inc_Req_Processed(int cnt) { return __atomic_add_fetch(s_global_counter, cnt, __ATOMIC_SEQ_CST); } PK% ]Sxs@--&gems/ruby-lsapi-5.6/ext/lsapi/lsapi.sonuȯELF>U@&@8 @ !!0 !!888$$hhh Stdhhh PtdPPPQtdRtd!!P P GNUIրmQ1v"C H‚3@(L`qCSlP*fRn}'3qѮl>&Sɶ ܮʼnSO`[is|&߱RD/y7řkՊ eY&09=By:%/=ejOzJ6'l#mNULCB1{!\$O#W23S=apbU06aD7jp#7ĴDIΊ=\4yݾCEкQuo rSѮIo|q%h6 󝵛 ' =qX[ u  f   d ysOq    T [M f A k &K ! , 2TRT" s G +L  } >W  9 - kH  .E   $7x9 vo | Z A 9J 4, 2> F"`| E]   r G p `}F 0rD @I  `K 5 0vi~  z@! b П. P! ] Z\ g o  v 1 r Y ` Pq@  @ sl zj V } - Ps]   `o @rY po  5 o x$ Pl! u U U E v rS o7 @oT (   0  }F rJ @pT ! P~I   Е  P!b g  @g "! l p6 o p [ !__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizecompareValueLocationset_skip_writesigactionsigemptyset__stack_chk_failreallocfcntlacceptsetsockoptmmapmemsetsetsidread__errno_locationclosewritevkillgetppid__ctype_b_locstrncpystrchrstrcasecmpstrtolgetaddrinfomemcpyfreeaddrinfoinet_addrLSAPI_Log__vfprintf_chk__snprintf_chkgetuid__fprintf_chkgettimeofdaylocaltime_rwaitpidforksystemexitlsapi_perrorstrerrorLSAPI_is_suEXEC_DaemonLSAPI_StopLSAPI_IsRunningLSAPI_Register_Pgrp_Timer_CallbackLSAPI_InitRequestmallocgetpeernamedup2LSAPI_Initgeteuidsignalg_reqdlopendlsymLSAPI_Is_Listen_rLSAPI_Is_ListenLSAPI_Reset_rLSAPI_Release_rfreeLSAPI_GetHeader_rLSAPI_ReqBodyGetChar_rLSAPI_ReqBodyGetLine_rmemchrmemmoveLSAPI_ReadReqBody_rFlush_RespBuf_rLSAPI_GetEnv_rstrcmp__ctype_toupper_locLSAPI_ForeachOrgHeader_rqsortLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rLSAPI_ForeachSpecialEnv_rLSAPI_FinalizeRespHeaders_rLSAPI_Flush_rLSAPI_Write_Stderr_rgetpidgetcwdmemccpy__realpath_chkLSAPI_Finish_rLSAPI_End_Response_rLSAPI_Write_rLSAPI_sendfile_rsendfileLSAPI_AppendRespHeader2_rstrlenLSAPI_AppendRespHeader_rLSAPI_CreateListenSock2socketbindlistenunlinkLSAPI_ParseSockAddrLSAPI_CreateListenSockLSAPI_Init_Prefork_ServercallocsetpgidsysconfLSAPI_Set_Server_fdLSAPI_reset_server_stateis_enough_free_memLSAPI_Postfork_ChildLSAPI_Postfork_ParenttimeLSAPI_Accept_Before_Fork__fdelt_chkusleepsched_yieldLSAPI_Set_Max_ReqsLSAPI_Set_Max_IdleLSAPI_Set_Max_ChildrenLSAPI_Set_Extra_ChildrenLSAPI_Set_Max_Process_TimeLSAPI_Set_Max_Idle_ChildrenLSAPI_Set_Server_Max_Idle_SecsLSAPI_Set_Slow_Req_MsecsLSAPI_Get_Slow_Req_MsecsLSAPI_No_Check_ppidLSAPI_Get_ppidLSAPI_Init_Env_Parametersgetenvgetpwnamdlerrorsetrlimit__fxstatsetreuidLSAPI_ErrResponse_rlsapi_MD5Initlsapi_MD5Updatelsapi_MD5FinalgetpwuidsetgidsetgroupssetuidstrtollprctlinitgroupsLSAPI_Accept_rLSAPI_Prefork_Accept_rsigaddsetsigprocmaskLSAPI_Set_Restored_Parent_PidLSAPI_Inc_Req_Processedselectrb_tainted_str_newrb_hash_asetrb_funcallvrb_intern2rb_gc_markmunmaprb_check_typerb_obj_as_stringrb_f_sprintfs_fn_add_envrb_safe_levelrb_string_value_ptrrb_eval_string_wraprb_string_valuerb_check_safe_objrb_ruby_verbose_ptrrb_define_global_construby_strdupmkstempftruncaterb_str_buf_newrb_str_catrb_num2intrb_fix2intrb_eSecurityErrorrb_raisememmemrb_yieldrb_gc_writebarrier_unprotectrb_io_putsrb_ary_detransientrb_str_new_staticrb_exec_recursiverb_default_rsrb_output_fsrb_output_rsrb_lastline_getInit_lsapichdirrb_stderrrb_cObjectrb_const_getrb_global_variablerb_define_global_functionrb_define_classrb_define_singleton_methodrb_define_methodrb_data_object_zallocrb_stdoutrb_stdinrb_hash_new__memcpy_chklibruby.so.2.6libm.so.6libc.so.6__environ_edata__bss_start_endGLIBC_2.14GLIBC_2.15GLIBC_2.4GLIBC_2.3.4GLIBC_2.2.5GLIBC_2.3/opt/alt/ruby26/lib64@ l w ii  ti  ui  ii  !U!pU!!!!!!!!!! !(!0! 8!@!*H!8P!CX!P`!_h!fp!nx!s!z!!!!!!!!!!!!!!!2!G !\(!o0!8!@!H!P!X!`!h!p!x!!!!2!@!Y!i!t!!!!!!!X!!!!H!P!X!`!h!p!x!!!$!5!!?!K!M!U!Y!Y!Z!!!q!!! ! ! ! ! ! ! !( !0 !8 !@ !H ! P ! X ! ` ! h ! p !x ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !( ! 0 !8 !"@ !#H !%P !&X !` !'h !(p !)x ! !* !+ ! !, ! ! ! !- !. !/ !0 ! ! ! ! !1 !2 !3 ! !4 !( !0 !68 !7@ !8H !9P !:X !;` !<h !>p !@x !A !B !C ! !D !E !F !G !H !I ! !J ! !L !N !O !P !Q !R ! !S !T( !0 !V8 !@ !WH !XP ![X !\` !]h !^p !_x !` !a ! !b !c ! !d !e !f !g !h !i !j !k !l !m !!n!o!p! !(!r0!s8!t@!uH!vP!X!w`!xh!yp!{x!|!}!~!!!!!!!!!!!!!!!!!! !(!0!8!@!HH! HtH5J %K hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhA% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݾ D%վ D%; D%ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݽ D%ս D%ͽ D%Ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݼ D%ռ D%ͼ D%ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݻ D%ջ D%ͻ D%Ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݺ D%պ D%ͺ D%ź D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E DH= H H9tH6 Ht H= H5 H)HHH?HHtH HtfD=e u+UH=b Ht H=. d= ]wff. ÐHGH+FHcAVIH@AUATL$USHtQHHtIHIL9r 0HI9v'KHSMsH;Յ[]A\A]A^[D]A\A]A^øff.f= D2 ÐO AWDD_AVAUATUSD6^nAxj׋G3G D!3G V\$ЋW^$DD1\$!3WAʋN Fp $E‰L$A1A1DD^ !D1G;νD\$DEDVDT$A!A1EE|A 1AD!E1DD*ƇGD1D!A1A1DDN DL$E F0D!DnA1D1DGFEDf Dd$D^(A!A1EEؘiA 1AD!1DDDʋ^0D1D!A1DE [D 1!D1DDN,A1DL$G\EA!Df8A1ED"kA 1AD!1DDN4EqDD1!1DE CyD 1!D1DDV<1G!I!1DDD$ Eb%1!1DDD$E@@1!1DDD$ EQZ^&1!1DE6Ƕ1!1DD]/։ 1!1DESD1!1DE ؉ 1!1DDD$E01!1DDD$ E!1!1DE7É1!1DDD$ E 1!1DDD$A0ZEAA1A!A1AA㩉A AD1!1t$DD1!A ogD1 1D!FL*1DD$Ή1AA!B9A1DD$A AD1D$qDD11‹D$ 0"amD1G 81Ɖ11DDD$ ED꾤11DDD$AKAA1A5`KA1AЉApA 1AD1D1D1A ~(D 1G'111DDD$ A0AA1A1AЋT$A2A1D1֋T$ 9ىDD11D11C|A A1A1AD$A0eVĉA1D1AD")Dt$ D D1A *CDG# 1  1DD9Ή 1DDY[e\$  1DE Dt$ щ1DE3}D\$  1DDD$E] 1DEO~oA AD 1DE ,DT$ A1ADE6CDt$ AN 1A~SADEAA A1A5:ADA AD 1Љ3*\$D D1DFӆ[ ]A\A]A^ 1։ 1DƉA4A_ OW GOW ATI1USHdH%(H$1HHH<$t)H$dH3%(uL{8IHC0L)H9>Lt$L+{(LA@LLfIM)MK H@σLSLCpNIHDI0HI@HKpM~HC(MxIH E1I@HC8HL1HMLIHHKpH9eHMthILM)MUI9t H)tDL+t$HL[]A\A]A^A_DM@@M)(+IHt$HLHk8f.HAVLAUIATIUSHu\H߉[AD${LǃLSHu0{L[L]A\A]A^K[H]A\A]A^Hff.AWAVAUATUSHHHHD$ 0xIHIHLc\CHcT t u(HDLcLH t tLÅ~6HcAT t u#H@Å~ALH t tE<AG=I|$PHHTI9T$Hs7HI+t$@L2%))I|$PLHHcAMt$PHLIFID$PA:I|$P}MD$PII@ID$PAIc$0fET8HЃA$0D$ H[]A\A]A^A_D$ ff.H HB=0AUATUSHcHfDA< t< uH؅uH[]A\A]IHPHHDI9D$Hs3HI+t$@L2%))tQI|$PHHAPI\$PHCID$PIc$0fET8HЃA$0H1[]A\A]øSDAUATAUHSH?dH%(HD$1D$ff t1fHL$dH3 %(H[]A\A]ÐA1ҾÃtʼnǺ1HL$Aߺ踿u#DH'uDo̾߻D HJDeOAkDH}An衾}NSHtff.USHdH%(H$1HHu/HH$dH3%(uHĘ[]Ŀ@1H= tAUATA'USH݋ 'DNuD H@AHH^ HHtH- t YƉlj JUDk HM DcEuSH8dH%(H$(1=HtH H=H H=_>HE1 H讹H=Y>Ht 1H膹 H=E>ijHHt 1H]IAąWE1H=">萳Ht 1H, H=>jHtHǺ 1_H==CH H==$HtHǺ 1IԶH==H1 H舸OH==òHtHǺ 1_H==蜲HtHǺ 18!H==uHtHǺ 1H==NHtHǺ 1蓲H=r='HtMH=p=Ht 1H護ۀ _H=X=Ht 1H D   EH=$=H=r u Pe 5[ H=&=cH 1H% …t% HQv HHHHD L*=L =L#=C HLt@HֹL€D t%HtAHHt9HLuHfDHJHHJHuHHu1ۉH$(dH3%(H8[]A\A]fD& H覲D9舭HHiHǺ11˵ÃHT$ƿD$(?H5/ رHgH Htxc@dx@D  E9D E)ZfH=}8贬 HK]  u t 'j X '> )fՅtbH H-DHH5?1 cAHc螲L%~ HH~ a蓮Åt=~ 0~ u ~ 5~ `HH5@?uHH5>1u HH5>Fff.AVIAUEATIUHSHt4Hu!(fDHH蔭HLgH]HuMtEL [1]A\A]A^ÐIcLLH#EgHGHHܺvT2HGAWAVAAUIATUHoSH1HGO@ƉWDW?t;AĉDHH|@D)A9rhAGt4LLDHL9A?vWEfAIIIH޺@HH@ HLL9uA?DLHH[]A\A]A^A_ܱIATLfUHSFH?LHz?)ƒw=t19rLHfCAD$AD$ ID$071)"HCHLHCP?o H{1HMHHCPH)KXH[]A\ff.fAWAVAUATUSHdH%(H$1Ht^ IAfMcg IoA_@LH3HuM88u =Yw uٽH$dH3 %( HĨ[]A\A]A^A_f~AAuIALJf8LS|xr@tPHf@HPXN MgA;G ZA9~uEo)HHcIHLD"Hu$'85Dv uAMgA9ID$,HD$HcIIDhAh(A9}A /HcIH4@HUHAIIh$A9}A HcIH4@HHAIIHl$p(ILHIILp$hMIc@o9gIcP[9SIcpG9?IcH39+IHHHHIHT$IIc@ H)IHHIHHHIHIIcHIHHHD$I9E1DL4t9dfH H IGAG IPH f@ f@ HHP P H HPPHHPPHHPPHHPPf@f@f@HH#PP H H'P#P$H$H+P'P(f@f@!f@%H(P+f@)I1 fDIHcȋL4t#fBIHT4 rfB@2JHHuMIcP IHHH9pH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@pHH9wMApIbIc@ IH0zu ALJt`!u u Au 1LHc迩IHIGAo IuID%t D-t B(AA1IcH4IILI 9HqH=W. IJDB(9xHqH=2. XIJB($AD$IKAzHL$;MbfoOt Lt$ LAoL$AT$Ml$)$踪 LL(HL$LHLLH$ID$H$I3L$H1H D$$Dl$EDDl$H=s IHIDEs MH=$s t"LDLŃP|$臨Et$A9uHt$莤D=Ń5r $A?D5r t 0AH5*L*HtHHr f)r #AH5:e 1;H@H5+1YLH 1HIH531H531D%q q DD$$H=q IHtZEW7E1111H=3H5*1耨E|$迦M2;|$藦E1H5*LuI}觧Ń1H5*LKfD=p -p p ED$AIFH5*1覧HH)H51H1聧1H5!*L 1H5C2LA#LH 3H H=NQ HL~H-> H 4> H=H HP HzH HJH*HQ H]> HH> HH=P LH5}H = H="H HP HH HJH*H踀yH(yHHP 1aH5P H=}H3H=r}yH(H[]A\A]@HPHH=L }HwHL H.XXXXXXH(Ht+H=uH=O 1HxH5,H=O 1HJfDmHzHfKHzHt -GF OkHyHu-*F 2HHAnonymous mmap() failedlocalhost%02d:%02d:%02d [%s] [UID:%d][%d] %.*syesnosystem()%s, errno: %d (%s) /dev/nulllibpthread.sopthread_atforkHTTP_[UID:%d][%d] %s:%s: %s LSAPI: jail() failure./etc/Can't set signalsaccept() failedLSAPI_STDERR_LOGPHP_LSAPI_MAX_REQUESTSLSAPI_MAX_REQSLSAPI_KEEP_LISTENLSAPI_AVOID_FORKLSAPI_ACCEPT_NOTIFYLSAPI_SLOW_REQ_MSECSLSAPI_ALLOW_CORE_DUMPLSAPI_MAX_IDLEPHP_LSAPI_CHILDRENLSAPI_EXTRA_CHILDRENLSAPI_MAX_IDLE_CHILDRENLSAPI_PGRP_MAX_IDLELSAPI_MAX_PROCESS_TIMELSAPI_PPID_NO_CHECKLSAPI_MAX_BUSY_WORKERLSAPI_DUMP_DEBUG_INFOnobodyLSAPI_DEFAULT_UIDLSAPI_DEFAULT_GIDLSAPI_SECRETLSAPI_LVE_ENABLEliblve.so.0lve_is_availablelve_instance_initlve_destroylve_enterlve_leavejailPHP_LSAPI_PHPRC=packetLen < 0 packetLen > %d Bad request header - ERROR#1 ParseRequest error SUEXEC_AUTHSUEXEC_UGIDLSAPI: setgid()LSAPI: initgroups()LSAPI: setgroups()LSAPI: setuid()Bad request header - ERROR#2 lsapi_accept() errorPragma: no-cacheRetry-After: 60Content-Type: text/htmlDEBUGNOTICEWARNERRORCRITFATALAcceptAccept-CharsetAccept-EncodingAccept-LanguageAuthorizationConnectionContent-TypeContent-LengthCookieCookie2HostPragmaRefererUser-AgentCache-ControlIf-Modified-SinceIf-MatchIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveX-Forwarded-ForViaTransfer-EncodingHTTP_ACCEPTHTTP_ACCEPT_CHARSETHTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_AUTHORIZATIONHTTP_CONNECTIONCONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_COOKIE2HTTP_HOSTHTTP_PRAGMAHTTP_REFERERHTTP_USER_AGENTHTTP_CACHE_CONTROLHTTP_IF_MODIFIED_SINCEHTTP_IF_MATCHHTTP_IF_NONE_MATCHHTTP_IF_RANGEHTTP_IF_UNMODIFIED_SINCEHTTP_KEEP_ALIVEHTTP_RANGEHTTP_X_FORWARDED_FORHTTP_VIAHTTP_TRANSFER_ENCODING%04d-%02d-%02d %02d:%02d:%02d.%06d Child process with pid: %d was killed by signal: %d, core dumped: %s Possible runaway process, UID: %d, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld gdb --batch -ex "attach %d" -ex "set height 0" -ex "bt" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2Force killing runaway process PID: %d with SIGKILL Killing runaway process PID: %d with SIGTERM Children tracking is wrong: Cur Children: %d, count: %d, idle: %d, dying: %d LSAPI: LVE jail(%d) result: %d, error: %s ! Invalid custom stderr log pathFailed to open custom stderr logCan't set signal handler for SIGCHILDReached max children process limit: %d, extra: %d, current: %d, busy: %d, please increase LSAPI_CHILDREN. LSAPI: failed to open secret file: %s! LSAPI: failed to check state of file: %s! LSAPI: file permission check failure: %s LSAPI: failed to read secret from secret file: %s LSAPI: Unable to initialize LVERequest header does match total size, total: %d, real: %ld LSAPI: missing SUEXEC_UGID env, use default user! LSAPI: SUEXEC_AUTH authentication failed, use default user! LSAPI: lve_enter() failure, reached resource limit.prctl: Failed to set dumpable, core dump may not be available!sigprocmask(SIG_BLOCK) to block SIGCHLDsigprocmask( SIG_SETMASK ) to restore SIGMASK in childfork() failed, please increase process limitsigprocmask( SIG_SETMASK ) to restore SIGMASKCache-Control: private, no-cache, no-store, must-revalidate, max-age=0PID 508 Resource Limit Is Reached

Resource Limit Is Reached

The website is temporarily unable to service your request as it exceeded resource limit. Please try again later.
          replacesrandQUERY_STRINGREQUEST_URIPATH_INFOREQUEST_PATHSCRIPT_NAMESTDERRreopenftruncate() failed. File mapping failed. Memory calloc error[...]nilLSAPI_MAX_BODYBUF_LENGTHLSAPI_TEMPFILEXXXXXXRACK_ROOTchdir()to_hashCGI/1.2eval_string_wrapLSAPIacceptaccept_new_connectionpostfork_childpostfork_parentprocessputcwriteprintprintfputs<<flushgetcgetsreadrewindeacheofeof?closebinmodeisattytty?syncsync=RACK_ENVInsecure: operation on untainted IOGATEWAY_Irewindable_input.rbNTERFACE/tmp/lsapi.XXXXX;z@Ze pp8pLp`pt q0q@qx00ydyxyPzz|$|t}~<Pd$@ppH p  0 @ Ќ 0 D PX t ` Џ 8 PL p P d `x p ph ` (pt@ @pp0<PPdx`Я,@T h@|`й4Ptp@ L $@8pL`tp00\Pxp@,`x`@ pHzRx $@V FJ w?:*3$"D` \0lp,l(l L$lsEIB E(A0z (A BBBI A (D BBBA Tl Pl@LlYGJB B(A0A80F(B DBb0ThsBFC G  AABK sk( tGADJ n AAA 4DtUAGK R CAG L JCG ltAG] AJ $tt C KFLHuBBE A(H0H (D BBBD  (D BBBA PtvvFB A(D0D (A BBBB L(A BBBA$vaAAD XAAHwBBB B(A0A8D@N 8C0A(B BBBH $`wOAf Q C E H@wYBBB A(D0J 0A(A BBBF xzFEA C(G   (A ABBD M I c A  E M A k E E E E H V HHT|FBB B(A0A8D`` 8A0A(B BBBD l}+BBB B(A0D8JYHPC Mi 8A0A(B BBBE LTMDd~6BBB B(A0A8DP 8A0A(B BBBG  8J0H(G DBBK $l`7EFF IIOx | 4xFAA G>  AABG EO D  A @ ThY|JED$S p]Ph H XAHlFBB B(A0A8LP 8A0A(B BBBH <Є FBB A(A0 (D BBBI \i`pFBB B(A0A8DP~ 8A0A(B BBBA k 8A0A(B BBBH L$FBB A(A0H Q D 0A(A BBBH L$FBB B(A0A8G 8A0A(B BBBF thFF$lnCXJLDlFBB B(A0A8DA 8A0A(B BBBA `( dBBB B(A0A8G I K I L N N w 8A0A(B BBBI 0 BMD GL  AABA < |=BAA G L@I@U  AABG $ |TWEHG ( ag H SHL pFBB B(A0A8DPS 8D0A(B BBBF T bIE D(C0P (F BBBM Q(H BBBAH lFBB B(A0A8DP 8A0A(B BBBA T< CBA A(G0` (A ABBD  (C ABBA J8 Ȗ-FBD D(D@T (A ABBB  ( ȗlECGF AAI L !cBG A(D0 (A ABBE XD0` t Z D10 ppFAA G@7  AABF  @LsL КFBB B(A0A8G 8A0A(B BBBG < P d x    Ȟ Ԟ  О  ̞Ȟ <Ğ FBA K(G (A ABBG <XFEE D(D0M (C BBBB ԧ(HFBH E(A0E8I@ 8A0A(B BBBE (FED ABH$8 BBB B(A0A8G 8A0A(B BBBJ Dp̴FBB A(A0G 0A(A BBBF L4 FBB B(A0A8G  8A0A(B BBBA 4 H\+p(BFGA kFB4zD O E  HU gHQ G <ayd(THEDL ] CAJ ELEY HW HW-Hd(EAD  DAJ ,aED y AE HP FBB E(D0C8GPm 8F0A(B BBBG ,ZAD J ABL 4PoAD  AAK pP \FBD C(G0 (D ABBE j (D ABBE | (G DBBA HdhFBB B(A0A8G@ 8D0A(B BBBD 7ٯqR_pwKJZnz9:ShX=05RCEth7qX,/[Y*wҽ:-Ry# Գ&-ozaR+I=3OP69ZLoXhGKqgD3i⺟ZjlAQ42((#U]`ikU4Sޞ^$ ߏ]FJYL_9nΙ#/.|L$S 3ɭɓ#&p6p>VnB?T֭mEn%Uc[z&Xy/=/??kF~CRPsTU-v_〝k{$*=]T6:"\1l1|eZ{DzuNZKb4/۞㜡 Rk:JI/ x^ʱٸj ;gk=$2zc.y"P,*l~<䭟 iF-Lм '?kە꠯F318'fCfSƍS^!+iAz޷`0>14X%x箌zldňY,uxA ]|S!'LdZ(1lD8V8y-'w4̕ ~nM^Ef& cǝo+f)"OuKZi!φ{= x~ɦ1NB R.:j |VOmGosF{2\f}$Lؚ6k(R-~ =v=qK{8}L^Wǁ9nq+-?ӡ,}_B֓ lkIvZ)'܋)bJᔻF*ja>Bc-@pL5oNÏމ 8nŚ),k|Z3C2M/MKȯ@ $ X:Uo۸Spy]}T:~(yy>1QOJA+>ȀQ.[H5r˙LQB"2V[lJivpg6<^ϟڏYd7ziگPSo/t1TzI!m_:XCVC;ْ 33!/{$K_D4 _{^>F-Mh[kRΫJ’0Uw+p|E%] ;ܕ0gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.data.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``p( (0 8o$$Eop&p&pT&&^Bh/h/hp?p?c?? nPJPJ wUU~}  PP008hh !!! ! !  ! ! "a $`x%(PK% ]ڛ 88&gems/ruby-lsapi-5.6/ext/lsapi/lsruby.onu[ELF>@@98 ,.+/*0)1fDHff.HHH+HHODH1f1fATIHUSHcHcLHH=HH[]A\ff.HH5dH%(HD$1HH$Ht-H=HHD$dH3%(u&H@H=HHfDHHH=HfHH=Hc5;5H=|6HHHfDf?IH=HH+9M1~+HHcHc5H5~Hfff.@UHSH HHm t]uaHHHtT؃tJ tEHH؉уu5HM u@HHpH}HH[]HD@HuHHMH tHPHpfSHCH[ff.SHHH[ÐHH=HHHH=HHHH=tHHHUSHH=H=HtHH9t H5Ht[11ҿ1HH-H;HHuHuH;HHHH[]fH=HHSHHt$~0H|$H\$H1HH[@H\$HH|$ff.@AWAVAUAATIUSHHJfDmHHfKHHt -OkHHu-2 GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA*FORTIFYGA+GLIBCXX_ASSERTIONS GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realign GA$3p1113GA$running gcc 8.5.0 20210514GA$annobin gcc 8.5.0 20210514GA$plugin name: annobin GA*GOW*GA*GA+stack_clashGA*cf_protection GA*FORTIFYGA+GLIBCXX_ASSERTIONSGA*GA!GA+omit_frame_pointerGA*GA!stack_realignreplacesrand/QUERY_STRINGREQUEST_URIPATH_INFOREQUEST_PATHSCRIPT_NAMESTDERRreopen%s: %s ftruncate() failed. File mapping failed. Memory calloc error [...]nilLSAPI_MAX_BODYBUF_LENGTHLSAPI_TEMPFILEXXXXXXLSAPI_CHILDRENRACK_ROOTchdir()ENVto_hashCGI/1.2eval_string_wrapLSAPIacceptaccept_new_connectionpostfork_childpostfork_parentprocessputcwriteprintprintfputs<<flushgetcgetsreadrewindeacheofeof?closebinmodeisattytty?syncsync=RACK_ENVInsecure: operation on untainted IOGATEWAY_Irewindable_input.rbNTERFACE/tmp/lsapi.XXXXXG K9%I'P(int)@ 9 1 3 6  7  8  9 : ( ; 0 < 8 = @ @ H A P B X D` Fh Hp It J x MP NW O Q Y [ \ ] ^ G _ - ` b  +  9  9 ? M     UJ U   U a}^q!$2 7 ;  e9:IDf9@4 @\     Hr  @`  @ @ @x@t#u :vF@  :@   3 :hlen ptr aux3ary  9(rash@  0 :elen aux ptreF0ary F 9(rask(g hri % j % k G % !G "% ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::(:+:,:-:.:/:: 9 7  8 9 : ;< = > #@,     $q %s%t kX m n  o  p  u ,                  $  (    4   9 0 9 r               "  "r 4 6 7  /7 1 2  3  4 & :R < = ? @ B C E( F0 G8 I@ JH KP L!WX O` Ph Qp Rx T' V' W' X' Y' Z' \' ]' _ ` a b c d e f g h i'k''m'('n'8'oG R   G  -] X0  9 j(9q7s) !!!!!G-.P W #  \/ l 9 /lww   #   X*r# wW| !, 7rBMXcny  !{$% % %   9  9   9 ;   ;; Ih 9 x 9@hxx+":+#:,$: ,(: ,*: ,,: ,.  9R-req;R-env<: =q)q!R!!-X>,@: ,B: ,C w,E: +F,G~  IE K L M NO,QE  x(9,R g .  /4K%%06 :1p7 08 2M3Z*K 4KD5U 5T320[6[5%0[23[K 4KD5U 5T74XD5Q05R02,0 :4eD5TH5Q 5R|2q0:4eD5TH5Q 5R|7A%:8e%<9:s%:~%89: ;K:4rD5Us5T05Q:<~D%5U <DC5Us5TM<Da5Us5Tm<D5Us5TK4D5Us5Tk8K%=9:Y%8:(*;,:; :4D5U 5Ts5Qv5R =9* k;:;9<~D5U 4D5Us89:@;K:4rD5T05Q:>D<~D 5U >D>D<~DE5U >D>E<E~5U <E5U 5T7<E5U 5TA<*E5Q}<7E5U 5T 5Q1<DE.5U <QE_5T 5Q 5R0<]E5T 5Q 5R0<]E5T 5Q 5R1<]E5T 5Q 5R1<]E$ 5T 5Q 5R <]EV 5T 5Q 5R <]E 5T 5Q 5R <]E 5T 5Q 5R1<]E 5T 5Q 5R0<]E!5T 5Q 5R0<]EL!5T 5Q 5R0<]E~!5T 5Q 5R <]E!5T 5Q 5R0<]E!5T 5Q 5R0<]E"5T 5Q 5R0<]EB"5T 5Q 5R0<]Es"5T 5Q 5R0<]E"5T 5Q 5R0<]E"5T 5Q 5R0<]E#5T 5Q 5R0<]E7#5T 5Q 5R0<]Eh#5T 5Q 5R1<]E#5T 5Q 5R <E#5U <E#5U >jE>jE>wE>l4<E+$5U <EJ$5U >jE<QE$5T 5Q 5R0<QE$5T 5Q 5R0<QE$5T 5Q 5R0<E %5U 4~D5U  F5%?:%%%@- A" e%Bp$A %Bn BpC:%D D-D9:6 :E3 *K F:gl&G :Hz+ >E>E>EF:&I":UI-:TJ:&D:C:&D!:F: 'I":UF:+{'I:UK8 L8F:C8(G:1str :=8( ';J(7+ <**(5Us>EC:X(D!:Fy:*GyGy*Gy6:1str{ :1n| 0} 0~ 89 N);9>E>E>E>/+<E)5Us $ &<R*)5U}<F)5U|5Qs $ &<F)5U|5Q} $ &4F5T CJ:R*DJ :BstrL :6MBnN BpO F5 a+G5"M7 08 09 0: 6; 88;+L8>FN0N+O N+Bfd Oz+Bfd Bsfn NC:+D :Bch F:+G!:>EF:c,Pout!:Pstr,:4.5Us5TTC:,DD*Qout6:Bi 6 :Cl:-Qaryl#:Qoutl.:Dl7Btmpn :Bio Fc:-GcGc,Poutc8:<*F-5UU5TT4.5UsF?:O.G?G?,Pout?8:1iA 3B :@819QK.;C9<7Fh.5U~5T3<..5Uv<..5Uv<..5Uv<..5Uv>DF>QFR3:/G3!:Pstr3-:051len6 897/;94ZF5Uv5T<8199 /;C94gF5UsF': 1G':Pc'+:Sch) W0*8Q9)0;c9T9W;9<E05Us>E89+0;94ZF5Uv5T<U15TW5Q1>QFF: S1I#:UF:a2G+:Pstr7:>E<ZF15T5<tF15Us<F15T0<F 25Us>FV: ]2W,:>FV: 2W+:>FV:-2W,:>FV:R4W$:Xpid 23Y + 5%Y 23, K 4KD5U 5T54XD5U85Q05R0ZR4 *4;_4>l4<F45Qs4F5Qs>F>E>D[ l4\)] z$525^,45`^24,K 4KD5U 5T74XD5Q15Rw>QF F45 9$5V B6W)W3WHWT_arg#G<E55UQ5T R $ &<E 65U|5Ts $ &4*E5QvVk L8Wk(Wk2WkGWkS_argl"GXpn `leno <E65U|5T~<E75Us5Tv $ &<*E75Q|<F;75U|5T?<E[75U|5T<E75U 5T9<*E75Qw<E75U|5T<E75U 5T<<*E75Qw<E85U5T}<E785U 5T<4*E5Q}aa 8Wa&bGc8\?Rc8\jE>jE<E;5U >jElXD5QU5RTh/+>mA+=8@<L8Hz+8/+ >9:A+8N+=9:`+:l+8Y: "=;v:;j:4 G5T15Q 5Rs<GA=5U <%GY=5Us<2Gq=5Us<E=5Us>?G>KG4E5Us<XG=5Uv5Ts<eG >5U05Ts5Q35R15Xv5Y0<qG!>5Uv<E@>5U <qGX>5Uv<Ew>5U 4qG5Uv<~G>5T14E5U h*h@;*j!*n.*j;*oF*p*J?L*9:!*j.*:;*:F*H!+_ <R*?5U <G?5U|"5Tv5Q 5R1<E?5Uv4F5U|5Qv>E>/+4F5T h+o@;+:+=+@;+qj+4F5T >E>Gh,C;,;,;,r,@:,89wSA;%9=o9yA;9;9;94G5Us88yB;8988s B;94G5Us=,'lB;,;,;,q'r,@j,<7FB5U 5T54G5U15Tw5Qv<GB5U15Tw5Qv>QFhc,PKD;u,;,;,j,j,pc,6DL,L,Lu,9:,:,819C;C9<GC5U 5Qs>gF<.D5Us5T~<.D5Us47F5U|5T34.5UsssNstswuv/tmp/lsapi.XXXXXXuv .XXXXXXst{snsts sssssstssdsss  ttL s3 sssswss snt ssswsOssTsLsSs[sss}tts^tstZ t Ds s9 t% ss t9sa ssqtv lsruby.csss=s% : ; 9 I$ >  $ > &I I7I I !I/  : ; 9  : ; 9 I8 : ; 9 <4: ; 9 I?<!4: ;9 I?<: ; 9 I> I: ;9 ( (((   : ;9  : ;9 I8  : ;9  : ;9 I : ;9  : ;9 I8  : ;9 I : ;9 I 8 '!I": ;9 I#> I: ; 9 $ : ; 9 % : ; 9 I& : ; 9 ' : ; 9 I8(!I/)'I* : ;9 +4: ; 9 I,4: ; 9 I- : ; 9 I8 .4: ; 9 I?/.?: ;9 @B04: ;9 IB14: ;9 IB2 U34: ;9 I415B64: ;9 I71RB UX YW 81RB UX YW 9 U:41B;1B<1=1RB X YW >1?!I/ @.: ;9 A.: ;9 B4: ;9 IC.: ;9 'I D: ;9 IE F.: ;9 'I@BG: ;9 IBH1RB X YW I: ;9 IJ.: ;9 'IK1RB X YW L1M4: ;9 IN.: ;9 I O.: ;9 I P: ;9 IBQ: ;9 IR.: ;9 'I@BS4: ;9 IT1RB UX YW UV.: ; 9 'I@BW: ; 9 IBX4: ; 9 IBY4: ; 9 IBZ1RB UX Y W [.: ; 9 ' \: ; 9 I].: ; 9 @B^4: ; 9 I _: ; 9 IB`4: ; 9 I a.: ; 9 '@BbB1c.: ; 9 'I d.?: ;9 '<e.?: ; 9 'I 4f.?: ;9 'I gh.1@Bi1j41k 1UlB1m41 n41o41 p1UX YW q r41s.?<n: ;9 t.?<n: ; 9 u.?<n: ; v6w.?<n`VpP!PP0V0VK0{00{00P0WPZjP@VPV}SKSRVPVZSPSSSS   PUU U  S  P P U  S  P U V U V U V  U / V/ 4 U4 L V T  \ T \  T * \* 4 T4 L \ Q S Q S Q S  Q + S+ 4 Q4 L S  P i \i l Pl \ P  \ N Sl s S P ]  S v} ? v} $0 $+(  v} $0 $+(V ^ P P U U U u@aUN $ &"^a $ &"O^PNQ^aQpUU ,U,1S12P ,T,2T@LUL_U@LTL_T@LQL^S^_QUU1T]TTWQVQQV0IoSS0' s $ &3$}"o s $ &3$}"pUVUpTSSVVPxUVSSUGVGHUH\VTFSFHTH\S!PTSHWSSHWS  U VU!UT`oUoUUUUUUU+EPP@S00@S00\SU\UTSTQQRRXX0rUrwSS S S0uTuVTTVTVTOV0Q\#Q#\:Q:O\0kRk]R]R7]7^RJ]JO^0XX#X#X:X:OX'@P@_:DPDO_`hUhmUPuUuSQUSPuTuVRTVPuQuQquQuQqVRTVqSQUSy\\bV VW a  a ~ V0I IYPYV V $ P$ ~ VBFPFiS a S> a E J pJ N UP i Ui S U S" 1 P1 s \ \ s S S P  P  U V SV \ U\ f Sf g Ug  SN [ P\ e Pg  S U S ,U,MSM\U\|U T 'V',T,MVMUTU|V Q MQM`Q`|Q ] } ],M] S S ,M  y,M y S S,MS S,6SM\U\wUM`Q`wQMUTUwV`UUUU`TTTT`QTSTaQaSQSQw0 UPS^}P^UU,K8U 8U/xx|3:@S3:@ESU\q0 ~ 0b W , ; > O s  0P 0@PWPW wSh,o;;}KERRZ}CJT]mt{xmt{x0>BUb /opt/alt/ruby26/include/ruby-2.6.0/ruby/usr/include/bits/usr/include/usr/lib/gcc/x86_64-redhat-linux/8/include/usr/include/bits/types/usr/include/sys/usr/include/netinetlsruby.clsapilib.hruby.hstdio2.hstdlib.hstring_fortified.hstddef.htypes.hstruct_FILE.hFILE.hstdio.hsys_errlist.htypes.hstdint-intn.hstdint-uintn.hunistd.hgetopt_core.hmath.hintern.hversion.hlsapidef.htime.hstruct_iovec.herrno.hsockaddr.hsocket.hin.hsignal.hstring.hmman.hutil.h  JK?K| #t>iK>KK{KY;./*X **}( // RX} t     0Yf q\:>X. t" u t/u* uZ ^  %gfu Z3 X |t |< tXX uKy 'XX" t  f. f *8u J<t  X    ot@5< t-< ti J [t %JiX W  L( ff%X< v9= t; K1 tlQJ/f J LXHKy XX" t L 2  =t<UMtUX&<< ` 0z X .    =Yl  rX[wt Z " h   m grtX  h fY:g< KXfKY sbXtv  SY|X |X<   L/$ eX< z < zt yt5Y|X |.X z  Z rh Y   *xp*suqwZ7v -uY "u{ wt JvI ;tZvpJuI==[X=XvXuv0X>f~z t gz t p((* uv #G< Y(%[$ rb_mWaitWritable_sys_errlistm_pScriptFileRUBY_Qnilrb_eNoMemError_unused2_filenorb_cMethodrb_obj_wb_unprotectrb_eSyntaxErrorm_cntUnknownHeadersH_AUTHORIZATIONsockaddr_isoblockSizem_pIovecEndstrcpym_pRespBufPosRUBY_FL_EXIVAR__uint8_tdmarkRUBY_DATA_FUNCm_pktHeaderrb_eIOErrorm_bytesm_pHeaderrb_data_object_get_shortbufsockaddr_inrb_cFilerb_eSignalunlinklsapi_dataRUBY_T_ARRAYrb_eKeyErroradd_env_rails__environlsapi_addstrsa_datauint16_tm_totalLensin_zeroRUBY_FL_UNTRUSTEDrb_eZeroDivErrorin_port_t_flagslsapi_getscallocm_respPktHeader__off_tcreateTempFiledfreeRUBY_T_IMEMOrb_global_variable_lockROBJECT_EMBED_LEN_MAXRUBY_T_UNDEFrb_cStringrb_eEOFErroratoim_pHttpHeaderLSAPI_GetReqBodyRemain_rm_pScriptNamerb_mKernelm_pEnvListrb_output_fsint32_t__fmtsa_familym_specialEnvListSize/builddir/build/BUILD/opt/alt/ruby26/lib64/ruby/gems/2.6.0/gems/ruby-lsapi-5.6/ext/lsapirb_cModulesockaddr_ns__u6_addr8RUBY_T_FALSEruby_robject_flagsrb_cIntegerRUBY_T_FILE_IO_write_endm_iLensockaddrrb_cTrueClasss_addrRUBY_FL_USER0RUBY_FL_USER1RUBY_FL_USER2RUBY_FL_USER3RUBY_FL_USER4RUBY_FL_USER5RUBY_FL_USER6RUBY_FL_USER7RUBY_FL_USER8RUBY_FL_USER9nameLenLSAPI_Postfork_Childfreerb_fsm_requestMethodOffRUBY_T_COMPLEXdata_struct_objrb_eEncCompatErrorruby_special_constsvalLenRSTRING_EMBED_LEN_SHIFT__stack_chk_failruby_rarray_flagsruby_descriptionsin_familyRStringm_fdListenMAX_BODYBUF_LENGTHlsapi_bodym_statusm_reqBodyLenrb_eNameErroroptargneedReadrb_eRegexpErrorrb_cBasicObjectRUBY_T_STRUCTrb_cRationalrb_cFloatrb_cClassrb_cStatsys_errlistin_addr_tbasicRUBY_QtrueLSAPI_ReqBodyGetChar_rpKey__uint16_tsin_portRUBY_T_STRINGrb_cContrb_cFalseClassm_flagRARRAY_EMBED_LEN_SHIFTreadMaxBodyBufLengthm_pQueryString_chainRUBY_T_MODULErb_eArgErrorrb_eInterruptrecurrb_funcallvRUBY_FL_SINGLETONsockaddr_ununsigned charcapanReadm_cntSpecialEnv_IO_lock_tRUBY_T_ZOMBIEfloatLSAPI_key_value_pairLSAPI_ForeachHeader_rrb_stderrlsapi_eachm_cntHeadersrb_str_catbodyBufRARRAY_EMBED_LEN_MAXRUBY_T_FIXNUMrb_eSecurityErrorisEofBodyBuflsapi_processlsapi_flushRARRAY_EMBED_FLAGROBJECT_EMBEDoff_tchild_statusRUBY_SYMBOL_FLAGrb_mComparableH_X_FORWARDED_FOR__fprintf_chkm_queryStringOffrb_define_global_functionRUBY_FLONUM_FLAGrb_stdoutruby_rstring_flagsH_CONTENT_LENGTHruby_engine_IO_write_ptrrb_output_rsROBJECT_ENUM_ENDlsapi_packet_headerLSAPI_ReadReqBody_rrb_eFatallsapi_http_header_indexrb_funcall_argcsTempFilerb_funcall_argsclosesharedlsapi_printfRUBY_T_OBJECTFILEH_COOKIEs_fn_add_envmunmapRSTRING_EMBED_LEN_MAXbodyCurrentLenLSAPI_Accept_Before_Forkrb_cNumerics_req_stderrrb_cHashsize_trb_array_const_ptrH_CONNECTIONrb_rsuint8_tH_CONTENT_TYPERArraylsapi_markm_headerLenRUBY_ELTS_SHAREDperrorlsapi_envruby_release_daterb_cDirsetup_cgi_env_IO_save_baseioveclsapi_eofrb_array_const_ptr_transientenvironlsapi_child_statusreadTempFileTemplatesockaddr_x25rb_eLoadErrorsin6_flowinfom_pIovecToWriteorig_stderrm_respHeaderLen_wide_dataH_IF_MATCHRUBY_FL_PROMOTED0RUBY_FL_PROMOTED1__in6_uH_ACC_CHARSETruby_versionorig_stdout__streamsigngamruby_copyrightm_reqBufSizerb_eExceptionrb_yieldadd_env_no_fixRUBY_T_FLOATRUBY_T_CLASSrb_cDataftruncateruby_fl_typelsapi_requestrb_cComplexfprintfrb_check_typeRUBY_T_HASHsyncRUBY_T_NODEchdir__ssize_t__srcrb_mErrnolsapi_closeH_IF_RANGEnameOffruby_api_versionstrerrorsa_family_tm_packetLenreadMoreRUBY_FL_WB_PROTECTEDin6_addrisBodyWriteToFilelinesin6_addrrb_mWaitReadablelsapi_setsyncm_respPktHeaderEndRUBY_FL_TAINTLSAPI_Postfork_Parentrb_check_safe_objfn_add_envlsapi_printrb_eSystemCallErrorrb_intern2stderrm_pHeaderIndexprogram_invocation_short_namerb_safe_levelrb_cUnboundMethodrb_f_sprintf_IO_save_endrb_const_get__nptrLSAPI_InitLSAPI_Requestrb_eScriptErrorrb_tainted_str_newfn_writelsapi_syncm_bufProcessedstdoutreadBodyBufoptoptlsapi_reopenrb_mGCrb_eIndexErrorm_httpHeaderLencurPosH_IF_NO_MATCHlsapi_s_acceptpreforkRUBY_T_DATAbuffssizetypekeyLenRUBY_FL_DUPPED__builtin_strchrLSAPI_Flush_rshort unsigned intsigned charrb_array_lentz_dsttimeGNU C17 8.5.0 20210514 (Red Hat 8.5.0-20) -mtune=generic -m64 -march=x86-64 -g -O2 -fPIC -fexceptions -fstack-protector-strong -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection=full -fplugin=annobinfilenamelsruby.clsapi_header_offset__off64_tsockaddr_eon_IO_read_base_offsetm_pIovecrb_string_value_ptrrb_eFloatDomainError_IO_buf_endm_respInfoopterrrb_define_singleton_methodlsapi_puts_ary_modeblkSize_IO_write_basevalueLenInit_lsapirb_eStandardErrorrb_cSymbolrb_argv0H_CACHE_CTRLH_COOKIE2__destrb_cMatchrb_cEncodinglsapi_isattyH_USERAGENTRARRAY_EMBED_LEN_MASKLSAPI_ForeachEnv_rlong intRUBY_T_NONErb_mProcessrb_mFileTestremain_IO_markerrb_cEnumeratorm_pRespBufEnd__builtin___memcpy_chkrb_io_putslsapi_s_postfork_childrb_define_global_constrb_obj_as_stringm_bufReadin_addruint32_tsockaddr_in6__pid_t_IO_codecvtrb_funcall_nargsH_RANGERDatastrtolg_reqlong doublerb_cRangeiov_lenlsapi_resp_inforb_cObjectlong unsigned intlsapi_req_headerrb_gc_markinitBodyBufruby_strdupm_headerOffrb_eNotImpError__errno_locationlsapi_s_postfork_parentcharsockaddr_inarpm_pSpecialEnvListsin6_scope_idrb_cIORSTRING_ENUM_ENDstdinsin_addrRUBY_T_BIGNUM_IO_buf_baseRSTRING_NOEMBEDRUBY_T_RATIONALRUBY_FL_PROMOTEDs_bodyrb_eTypeErrorRBasicrb_eNoMethodError_IO_read_endRUBY_T_ICLASSrb_num2intcLSAPIRUBY_SPECIAL_SHIFT_IO_FILEH_IF_UNMOD_SINCEm_fdRUBY_T_SYMBOLH_HOSTrb_num2char_inline_IO_wide_datastrlen__u6_addr16s_pidselfrb_eSystemExitisAllBodyReadm_respHeaderrb_cThreadm_envListSizem_pAppDataruby_platformsockaddr_ax25RSTRING_FSTRrb_eThreadError__pad5rb_str_new_static__u6_addr32rb_cNilClassm_type_markersrb_stdinrb_eStopIterationm_scriptFileOffRUBY_FL_USHIFTklassrb_define_classH_VIA_codecvtm_pRespHeaderBufEndH_PRAGMARUBY_FL_FINALIZErb_cRandomdoublemkstemplsapi_putcargcssize_tstrcatlsapi_writelsapi_putsorig_stdinRUBY_FIXNUM_FLAGargvRARRAY_ENUM_ENDrb_eRuntimeErrorm_pRespHeaderBuf__int32_trb_cProc__uint32_tRUBY_IMMEDIATE_MASKrb_hash_asetdataH_REFERERrb_cStructLSAPI_Prefork_Accept_rheap_sys_siglistRARRAY_TRANSIENT_FLAGm_pUnknownHeaderrb_typem_reqStateRUBY_T_NILrb_cTimerb_eSysStackErrorm_pRespBufrb_num2int_inlineprogram_invocation_namerb_cArrayrb_eEncodingErrorrb_ruby_verbose_ptrrb_cBindingrb_intern_id_cacheH_TRANSFER_ENCODINGH_IF_MODIFIED_SINCErb_ary_detransientRUBY_FL_USER10RUBY_FL_USER11RUBY_FL_USER12RUBY_FL_USER13RUBY_FL_USER14RUBY_FL_USER15RUBY_FL_USER16RUBY_FL_USER17RUBY_FL_USER18RUBY_FL_USER19_freeres_bufRUBY_T_MATCHlong long unsigned intpid_t_cur_columnlsapi_rewinds_reqrb_eRangeErrorm_pRespHeaderBufPoss_stderr_datarb_eval_string_wrapgetpidm_cntEnvRUBY_T_MASKrb_lastline_get_IO_backup_baseH_KEEP_ALIVE__memcpy_chk_IO_read_ptrrb_eMathDomainErrorrb_fix2intLSAPI_GetReqBodyLen_rrb_gc_writebarrier_unprotectrb_exec_recursivegetenv_freeres_listrb_eLocalJumpErrorrb_raise_sys_nerrlsapi_readtimezonepReqlsapi_getcrb_hash_newclear_envrb_cRegexplsapi_binmode_old_offsetstrchrm_pReqBufrb_cNameErrorMesgvalueOffoptindH_ACC_LANGlong long intin6addr_loopback_flags2VALUErb_mMathRUBY_T_TRUEmemmemsin6_familysockaddr_atruby_value_typem_scriptNameOffH_ACCEPTm_lLastActivelsapi_resp_headersys_nerrin6addr_anym_pRequestMethods_req_dataiov_basem_lReqBegincreateBodyBufm_versionB0m_versionB1rb_str_buf_newrb_define_methodRUBY_FLONUM_MASKruby_patchlevelRUBY_T_REGEXPm_pIovecCurLSAPI_Init_Env_Parametersorig_envm_reqBodyReadRUBY_Qundeflsapi_s_accept_new_connrb_eFrozenErrorsockaddr_dlRSTRING_EMBED_LEN_MASKRUBY_FL_FREEZEunsigned intbodyLensockaddr_ipxrb_default_rsshort intrb_string_value_vtable_offsetpValueenv_copymmaporig_verboserb_data_object_zallocrb_mEnumerableRUBY_Qfalseflagstz_minuteswestsys_siglistH_ACC_ENCODINGsin6_portlsapi_eval_string_wrapGCC: (GNU) 8.5.0 20210514 (Red Hat 8.5.0-20)GNUzRx  0D+Xl(BFGA kFBzD O E  HUgHQ G $ayd(<EDL ] CAJ hELEY HW HW-Hd(EAD  DAJ aED y AE H8FBB E(D0C8GPm 8F0A(B BBBG ,ZAD J ABL 4oAD  AAK pP \FBD C(G0 (D ABBE j (D ABBE | (G DBBA HLhFBB B(A0A8G@ 8D0A(B BBBD CKw oEA J F A 8FBA D(D@ (A ABBE ((EDG0 AAI HTPFBB A(A0 (F BBBH {(F BBB@OFBB A(D0D@  0A(A BBBJ <KFBA A(D0 (A ABBE   - )  ?.Yt/01 5 C _"y @"[0+[h` h)wCpPwmB pZz# < xEZ_mw` mpg0aIaUapp2 2_@_Bg`   2-Jh X  `!a!;OV0dOP  ~  @)~ CL [ fL  P h   C    o  ; |W  f |    \  \  `P 8 Q O] w K        h "$%'./0123-4   @ )  3   L S  b Z x ! ' - 3 9 ? E K Q  W (] c $i *o fu n{ s y                    1 G V    ) 9 N b ()*+,s              / < R g          ,3G^jry 0MXk}K#.;Nhx.annobin_lsruby.c.annobin_lsruby.c_end.annobin_lsruby.c.hot.annobin_lsruby.c_end.hot.annobin_lsruby.c.unlikely.annobin_lsruby.c_end.unlikely.annobin_lsruby.c.startup.annobin_lsruby.c_end.startup.annobin_lsruby.c.exit.annobin_lsruby.c_end.exit.annobin_lsapi_process.start.annobin_lsapi_process.endlsapi_process.annobin_lsapi_rewind.start.annobin_lsapi_rewind.endlsapi_rewinds_body.annobin_lsapi_eof.start.annobin_lsapi_eof.endlsapi_eof.annobin_lsapi_binmode.start.annobin_lsapi_binmode.endlsapi_binmode.annobin_lsapi_isatty.start.annobin_lsapi_isatty.endlsapi_isatty.annobin_lsapi_setsync.start.annobin_lsapi_setsync.endlsapi_setsync.annobin_add_env_no_fix.start.annobin_add_env_no_fix.endadd_env_no_fixlsapi_env.annobin_clear_env.start.annobin_clear_env.endclear_envrb_intern_id_cache.13602env_copy.annobin_lsapi_mark.start.annobin_lsapi_mark.endlsapi_mark.annobin_lsapi_flush.start.annobin_lsapi_flush.endlsapi_flush.annobin_lsapi_close.start.annobin_lsapi_close.endlsapi_closeMAX_BODYBUF_LENGTH.annobin_readBodyBuf.start.annobin_readBodyBuf.endreadBodyBuf.annobin_lsapi_write.start.annobin_lsapi_write.endlsapi_write.annobin_lsapi_addstr.start.annobin_lsapi_addstr.endlsapi_addstr.annobin_lsapi_printf.start.annobin_lsapi_printf.endlsapi_printf.annobin_lsapi_s_postfork_parent.start.annobin_lsapi_s_postfork_parent.endlsapi_s_postfork_parents_req.annobin_lsapi_s_postfork_child.start.annobin_lsapi_s_postfork_child.endlsapi_s_postfork_child.annobin_lsapi_s_accept_new_conn.start.annobin_lsapi_s_accept_new_conn.endlsapi_s_accept_new_conn.annobin_lsapi_s_accept.start.annobin_lsapi_s_accept.endlsapi_s_accepts_pidrb_intern_id_cache.13615s_req_data.annobin_lsapi_eval_string_wrap.start.annobin_lsapi_eval_string_wrap.endlsapi_eval_string_wrap.annobin_add_env_rails.start.annobin_add_env_rails.endadd_env_rails.annobin_lsapi_reopen.start.annobin_lsapi_reopen.endlsapi_reopens_req_stderrorig_stderrrb_intern_id_cache.13779.annobin_createBodyBuf.start.annobin_createBodyBuf.endcreateBodyBufsTempFile.annobin_lsapi_read.start.annobin_lsapi_read.endlsapi_read.annobin_lsapi_gets.start.annobin_lsapi_gets.endlsapi_gets.annobin_lsapi_each.start.annobin_lsapi_each.endlsapi_each.annobin_lsapi_getc.start.annobin_lsapi_getc.endlsapi_getc.annobin_lsapi_puts_ary.start.annobin_lsapi_puts_ary.endlsapi_puts_ary.annobin_lsapi_sync.start.annobin_lsapi_sync.endlsapi_sync.annobin_lsapi_putc.start.annobin_lsapi_putc.endlsapi_putc.annobin_lsapi_puts.start.annobin_lsapi_puts.endlsapi_puts.annobin_lsapi_print.start.annobin_lsapi_print.endlsapi_print.annobin_Init_lsapi.start.annobin_Init_lsapi.endrb_intern_id_cache.13795rb_intern_id_cache.13800orig_envcLSAPI.LC0.LC1.LC7.LC5.LC4.LC6.LC3.LC2.LC8.LC9.LC13.LC11.LC10.LC12.LC14.LC15.LC16.LC17.LC18.LC19.LC56.LC21.LC22.LC26.LC27.LC28.LC29.LC30.LC34.LC35.LC36.LC37.LC38.LC39.LC40.LC41.LC42.LC43.LC44.LC45.LC46.LC47.LC48.LC49.LC50.LC51.LC52.LC53.LC54.LC24.LC20.LC31.LC32.LC33.LC25.LC23.LC55.text.group.text.hot.group.text.unlikely.group.text.startup.group.text.exit.group_GLOBAL_OFFSET_TABLE_g_reqrb_tainted_str_newrb_hash_asetrb_funcallvrb_intern2__stack_chk_failrb_gc_markLSAPI_Flush_rmunmapfreeLSAPI_ReadReqBody_rrb_check_typerb_obj_as_stringrb_f_sprintfLSAPI_Postfork_ParentLSAPI_Postfork_ChildLSAPI_Accept_Before_ForkLSAPI_Prefork_Accept_rgetpids_fn_add_envLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rrb_safe_levelrb_string_value_ptrrb_eval_string_wraprb_string_valuerb_check_safe_objstrchrrb_ruby_verbose_ptrrb_define_global_construby_strdupmkstempunlinkftruncatemmapcallocperror__errno_locationstrerror__fprintf_chkrb_str_buf_newrb_str_catrb_num2intrb_fix2intrb_eSecurityErrorrb_raisememmemrb_yieldLSAPI_ReqBodyGetChar_rrb_gc_writebarrier_unprotectrb_io_putsrb_ary_detransientrb_str_new_staticrb_exec_recursiverb_default_rsrb_output_fsrb_output_rsrb_lastline_getInit_lsapiLSAPI_InitgetenvstrtolstrlenselectLSAPI_Init_Env_Parameterschdirrb_stderrrb_cObjectrb_const_getrb_global_variablerb_define_global_functionrb_define_classrb_define_singleton_methodrb_define_methodrb_data_object_zallocLSAPI_Write_rrb_stdoutrb_stdinLSAPI_Write_Stderr_rrb_hash_new__memcpy_chkH7*ltl@EOV{**D <8DH*?HF<KUHIk*pw***<8DH'-T6<TOX\d*snl LXalltll1Wrz  C*D& 3<8CV^eDo <  < @     !  ( 7 A *K S d i  p    D L H v L <  L  L D  L <  L7 *> H f  < D H  L  W La <i o L *   D H  D L E *J j *q {   DX]qx QX ;*v*:Q* *!"$"8-D3H<%S&gy %'L<%&*()T %*.*?*+FP`*,i-pw|tt.t/0d1,d<A2Hd[`2gdz2d2d2d2d2d2d.32:dJO2Vdin2ud2d2d2d2d2d2d-229dIN2Udej2qd2d2*d3**4\*5 *6.d,33*7:ET.Yam8tll<9<d+017dGL1Sdch1| %% 7B i  ( L T" ""["[ [h@[Hhlhtwhwww,4`hZZZm Z(mLmTm a@Halata22,24_`2h___ (LT  !@ H !l !t O ! O O  O , 4 ~ ` h ~ ~ L ~ L L  L (  L  T          |@  H |l |t  |   \  \, \4 ` \h       K (K      y J) . < jC L wS ^Z q_ m r ~ v   B   c     ' 4 A KN d [ h ^u  Z  t  =  N    9 L  + 8  E R _ l =y E ,   @  Q   A' 3 ? [ Xg @s      1         " ) . ; W )j p tv ,|   .      H        >  @   P     { 2  & , )2 48 > _D Q J P V X]  p v 0 | B    H    q 0 > L Z h v       & 5 D& S/ b8 qA J S ]  d 0k Ys         4  k  D N   0 & s   n m  {    D # v   n  n  Y , 9 F S ` s m ,z      _   E   D # 0 K= J bW  d ;q ~ )   V   )   = . ' O4 A N [ h =u   n } 9 k ,   O  + 8 TE R B_ l y    6   $ F    O " u/ < I FV * c p }   r  j 2   . + 7 X Q hW \ ] c i o u { G  1   7      %           '   $ 1 6> K Y |f s   a X    O     1 > K X e Zs O      U     H )* =8  F S $` qm z   X Z  e      L # 50 /= J W d 5q ~        '  {    2( 6 D S ^ h k x G A +  u $ 0 = +J x <    V   G  , 0: H V d      k  d  )   f ! . T A M ~   # w   r Ox ( p  }E rx } h  `  & rX   + d 8 F R _@y @ ~ :  c ]   A ;    ` $ ->1N W c g l y  F B  1    ~`- `6 B F K0a`v ; P P    R  @ <W@1&kDb;}    v    7 3 @/8U Y b f l1 0  1 '<1F"Sm`ux1 m(1%1$/!D1*Q`Eu1fd1n1sp 1y % : 1G @W l 1y `  1    1 p 7!1 ! !S1!1>!P M!rb!1o! !!1!!!1! !!1"0"'"14"0C"X"1e"t""1"`"6"1"p"R"1"p#n#1)#8#M#1Z#i#~#1S#P###X##]#e#q$ $"$1,$A$1LK$X$4m$11z$$P$1G$$l$1V$`$%1 %%1=% B% L% f% % % % ?% x% ]% %% } %& x& & '&0&E&R&_&m& 'y&& x& L & {& x& & x& &`' x!' n -'0D' xW'4`'4|' ' ' x' ?' 9' ' ' ' ' ' ( ( @( +( 9( K( xY( Je( |( ( ( ( ?( ( ( x( ( ( ( ( 1( '( ( ( ( ) " )  ) ) +) \ /) X 4) A) O) \) i) )V ) ) )L )m* * x/* CS* _*v* * * * * * * * * [ * Y * * * ~ * 9** +O+ T"+ 0+ O+ J{+ + c+ x+ o+p+ x+ + ++ , *, ., ?, H C, D H,-d, v, , ?, , ., G-  -@+- 7- ;- @- ?L- P- a-  e- j-M-X- -- - S - M - ?- - - # -  . . . (.o1. B. F. L.>i.I.f..... .p/ x/ S/ M(/ ,/ 1/ =/ A/ R/ *V/ (_/xh/ y/ Q}/ M/// / / // // x0  0 0 00 (30 ?0 C0 L0U0 f0 j0 s0|0 00 0 00U0 0 `0 A0 =00"1\!1 a-1D1 xT1 `1w1 x1 {1 w1 1 11111 22 %2`<2 xG2 K2 P2t^2 i22 x2 2 22 22 x2 W2 S22 23 x3 3 '3 +3 03 093 D3 H3 M3 Y3 d3 Gh3 Cm3 pv3 33313S3\3 3 3 3a3w4+484E4+S4 L `4 m4 zt44 4 4 4 4 @4 44I4145Z:5 E5\5 g5 k5 p5 ){5 5 5 H5 L5 H5 =5 5 5 5 55 66 *60A6 L6 P6 U6 )`6 d6 xi6 Ht6 Tx6 H}6 =6 6 6 6 6 W6 O6677$<7P\7eq71)7x77713778)8188M8 T8`k8 v8 z8 8m8 8 ^8 8 ^8 8 8 x 9 }29 R9 >p9 a9 p9 9 99 c9 9 : m : !: -: m :: L: /Z: * k: w: %::p:P: : : v: l; ; ;q; ,; )0; %9; j=; bF; J; O; X; 4\; 0e; n;;1S;v;~;;1L;;;<"<E<N<g<0p< P}< P< r< j<0< < < < < f< `<> < < < < < <O =1Z#=<8=@B=GZ=Zr=b=% =, =W =s= >"> 7>1bA> Y>m n>1xx>t >>>1>P > > ? ? ? #? 1? 5? >? B? K? T? i? ? ?1? ?m ?j ? @ @m#@ >@ NB@ BK@ O@ X@g a@g ~@ @ @g @ @m@ @N @ @ A@ 5A A A b A Z #A 'A 0A 9A pJA .!NA *!XA aA ~A h!A d!A !A !A !A !A A A A "A "A A A B K"B G" BH$BP-BPJB "NB "WB "[B "dB "hB "mBPBaB1BuB B|C` C =#$C 5#-C #1C #:C $>C $QC mC vC $zC $C $C $CC C U%C Q%CC C CDNDz7DLD PD YD M]D MfD jjD jsD $wD $D D D D ?D D hD _D _D 6D 6D XD XD HD HD ] D ] E "E "E lE lE _"E _+E /E 8E  @1Z{! G! G q 4H0\`pp`p (@pl @`<0P PP    ,X`.symtab.strtab.shstrtab.rela.text.data.bss.rela.gnu.build.attributes.text.hot.rela.gnu.build.attributes.hot.text.unlikely.rela.gnu.build.attributes.unlikely.text.startup.rela.gnu.build.attributes.startup.text.exit.rela.gnu.build.attributes.exit.rodata.str1.1.rodata.str1.8.rela.data.rel.local.rodata.cst16.rela.debug_info.debug_abbrev.rela.debug_loc.rela.debug_aranges.debug_ranges.rela.debug_line.debug_str.comment.text.hot.zzz.text.unlikely.zzz.text.startup.zzz.text.exit.zzz.note.GNU-stack.note.gnu.property.rela.eh_frame.group/@6/T6/l6/6/6 K@#6&,@ 6@01@(9 6 Lp([p(V@E06 u@*@*@E06,,@F06--@HF062/21M'1"@xF671J2GE@F6Vy#i %d@(86 y0t@`06"ĦTY@6%00.uL   %  @64p7 x 6PK% ]whf:!gems/ruby-lsapi-5.6/lsapi.gemspecnu[Gem::Specification.new do |s| s.name = %q{ruby-lsapi} s.version = "5.6" s.date = %q{2024-01-22} s.description = "This is a ruby extension for fast communication with LiteSpeed Web Server." s.summary = %q{A ruby extension for fast communication with LiteSpeed Web Server.} s.has_rdoc = false s.authors = ["LiteSpeed Technologies Inc."] s.email = "info@litespeedtech.com" s.homepage = "http://www.litespeedtech.com/" s.rubyforge_project = "ruby-lsapi" s.files = ["lsapi.gemspec", "README", "examples", "examples/testlsapi.rb", "examples/lsapi_with_cgi.rb", "ext", "ext/lsapi", "ext/lsapi/extconf.rb", "ext/lsapi/lsapidef.h", "ext/lsapi/lsapilib.c", "ext/lsapi/lsapilib.h", "ext/lsapi/lsruby.c", "rails", "rails/dispatch.lsapi", "scripts", "scripts/lsruby_runner.rb", "setup.rb"] s.extra_rdoc_files = ["README"] s.extensions << "ext/lsapi/extconf.rb" s.require_paths << "lib" end PK% ]^wͱgems/ruby-lsapi-5.6/READMEnu[ lsapi - LSAPI extension for Ruby ================================ INSTALL ------- $ ruby setup.rb config $ ruby setup.rb setup # ruby setup.rb install USAGE ----- General CGI scripts ^^^^^^^^^^^^^^^^^^^ The most efficient way to use LSAPI interface is to modify your CGI scripts. You need to add the following code to your CGI scripts: require 'lsapi' while LSAPI.accept != nil ... end There is no need to change the way that how CGI environment variables are being accessed in your scripts. You can find some examples under examples/ folder. Ruby Script Runner ^^^^^^^^^^^^^^^^^^ If you don't want to change your existing Ruby CGI code, you can use our Ruby script runner under scripts/ folder. You need to configure lsruby_runner.rb as a LSAPI application, then add a script handler for "rb" suffix. Rails dispatcher ^^^^^^^^^^^^^^^^ With Ruby LSAPI, we proudly provide a optimum platform for Rails application deployment. Ruby LSAPI has the following advantages over other solutions. * Easy configuration, deploy a Rails application only take a few clicks with our Rails easy configuration * Fast startup, the expensive Rails framework initialization only takes place once when multiple processes need to be started * Resource efficience, ruby processes can be started on demand, idle process will be stop. To use LSAPI with Ruby on Rails, please check out our toturial http://www.litespeedtech.com/support/wiki/doku.php There are a few environment variables that can be tweaked to tune ruby LSAPI process. * LSAPI_CHILDREN (default: 0) LSAPI_CHILDREN controls the maximum number of children processes can be started by the first ruby process started by web server. When set to <=1, the first ruby process will handle request by itself, without starting any child process. When LSAPI_CHILDREN is >1, the LSAPI application is stared in "Self Managed Mode", which will start children processes based on demand. With Rails easy configuration, LSAPI_CHILDREN is set to the value of "Max Connections" by web server, no need to set it explicitly. Usually, there is no need to set value of LSAPI_CHILDREN over 100 in most server environment. * LSAPI_AVOID_FORK (default: 0) LSAPI_AVOID_FORK specifies the policy of the internal process manager in "Self Managed Mode". When set to 0, the internal process manager will stop and start children process on demand to save system resource. This is preferred in a shared hosting environment. When set to 1, the internal process manager will try to avoid freqently stopping and starting children process. This might be preferred in a dedicate hosting environment. * LSAPI_EXTRA_CHILDREN (default: 1/3 of LSAPI_CHILDREN or 0) LSAPI_EXTRA_CHILDREN controls the maximum number of extra children processes can be started when some or all existing children processes are in malfunctioning state. Total number of children processes will be reduced to LSAPI_CHILDREN level as soon as service is back to normal. When LSAPI_AVOID_FORK is set to 0, the default value is 1/3 of LSAPI_CHIDLREN, When LSAPI_AVOID_FORK is set to 1, the default value is 0. * LSAPI_MAX_REQS (default value: 10000) LSAPI_MAX_REQS specifies the maximum number of requests each child process will handle before it exits automatically. This parameter can help reducing memory usage when there are memory leaks in the application. * LSAPI_MAX_IDLE (default value: 300 seconds) In Self Managed Mode, LSAPI_MAX_IDLE controls how long a idle child process will wait for a new request before exit. This option help releasing system resources taken by idle processes. * LSAPI_MAX_IDLE_CHILDREN (default value: 1/3 of LSAPI_CHILDREN or LSAPI_CHILDREN) In Self Managed Mode, LSAI_MAX_IDLE_CHILDREN controls how many idle children processes are allowed. Excessive idle children processes will be killed by the parent process. When LSAPI_AVOID_FORK is set to 0, the default value is 1/3 of LSAPI_CHIDLREN, When LSAPI_AVOID_FORK is set to 1, the default value is LSAPI_CHILDREN. * LSAPI_MAX_PROCESS_TIME (default value: 300 seconds) In Self Managed Mode, LSAPI_MAX_PROCESS_TIME controls the maximum processing time allowed when processing a request. If a child process can not finish processing of a request in the given time period, it will be killed by the parent process. This option can help getting rid of dead or runaway child process. * LSAPI_PGRP_MAX_IDLE (default value: FOREVER ) In Self Managed Mode, LSAPI_PGRP_MAX_IDLE controls how long the parent process will wait before exiting when there is no child process. This option help releasing system resources taken by an idle parent process. * LSAPI_PPID_NO_CHECK By default a LSAPI application check the existence of its parent process and exits automatically if the parent process died. This is to reduce orphan process when web server is restarted. However, it is desireable to disable this feature, such as when a LSAPI process was started manually from command line. LSAPI_PPID_NO_CHECK should be set when you want to disable the checking of existence of parent process. License ------- LSAPI library code is under BSD license LSAPI ruby extension code is under Ruby license * (()) (Japanese) * (()) (English) Copyright --------- Copyright (C) 2006 Lite Speed Technologies Inc. PK% ]GF(gems/ruby-lsapi-5.6/rails/dispatch.lsapinuȯ#!/opt/alt/ruby26/bin/ruby if GC.respond_to?(:copy_on_write_friendly=) GC.copy_on_write_friendly = true end require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) # If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like: # "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired require "dispatcher" require "lsapi" while LSAPI.accept != nil Dispatcher.dispatch end PK% ]H@MM,gems/ruby-lsapi-5.6/scripts/lsruby_runner.rbnuȯ#!/opt/alt/ruby26/bin/ruby require 'lsapi' class CodeCache def [](filename) mtime = File.mtime( filename ) entry = @cache[filename]; if entry != nil return entry end code = compile(filename) #entry = CodeEntry.new( filename, mtime, code ) @cache[filename] = code return code end private def initialize @cache = {} end def compile(filename) open(filename) do |f| s = f.read s.untaint binding = eval_string_wrap("binding") return eval(format("Proc.new {\n%s\n}", s), binding, filename, 0) end end end $count = 0; $cache = CodeCache.new while true $req = LSAPI.accept break if $req == nil filename = ENV['SCRIPT_FILENAME'] filename.untaint filename =~ %r{^(\/.*?)\/*([^\/]+)$} path = $1 Dir.chdir( path ) #load( filename, true ) code = $cache[filename] code.call end class CodeEntry public :path, :name, :mtime, :opcode def initizlize( filename, mtime, opcode ) filename =~ %r{^(\/.*?)\/*([^\/]+)$} @path = $1 @name = $2 @mtime = mtime @opcode = opcode end end PK% ]##BBgems/ruby-lsapi-5.6/setup.rbnu[# # setup.rb # # Copyright (c) 2000-2005 Minero Aoki # # This program is free software. # You can distribute/modify this program under the terms of # the GNU LGPL, Lesser General Public License version 2.1. # unless Enumerable.method_defined?(:map) # Ruby 1.4.6 module Enumerable alias map collect end end unless File.respond_to?(:read) # Ruby 1.6 def File.read(fname) open(fname) {|f| return f.read } end end unless Errno.const_defined?(:ENOTEMPTY) # Windows? module Errno class ENOTEMPTY # We do not raise this exception, implementation is not needed. end end end def File.binread(fname) open(fname, 'rb') {|f| return f.read } end # for corrupted Windows' stat(2) def File.dir?(path) File.directory?((path[-1,1] == '/') ? path : path + '/') end class ConfigTable include Enumerable def initialize(rbconfig) @rbconfig = rbconfig @items = [] @table = {} # options @install_prefix = nil @config_opt = nil @verbose = true @no_harm = false end attr_accessor :install_prefix attr_accessor :config_opt attr_writer :verbose def verbose? @verbose end attr_writer :no_harm def no_harm? @no_harm end def [](key) lookup(key).resolve(self) end def []=(key, val) lookup(key).set val end def names @items.map {|i| i.name } end def each(&block) @items.each(&block) end def key?(name) @table.key?(name) end def lookup(name) @table[name] or setup_rb_error "no such config item: #{name}" end def add(item) @items.push item @table[item.name] = item end def remove(name) item = lookup(name) @items.delete_if {|i| i.name == name } @table.delete_if {|name, i| i.name == name } item end def load_script(path, inst = nil) if File.file?(path) MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path end end def savefile '.config' end def load_savefile begin File.foreach(savefile()) do |line| k, v = *line.split(/=/, 2) self[k] = v.strip end rescue Errno::ENOENT setup_rb_error $!.message + "\n#{File.basename($0)} config first" end end def save @items.each {|i| i.value } File.open(savefile(), 'w') {|f| @items.each do |i| f.printf "%s=%s\n", i.name, i.value if i.value? and i.value end } end def load_standard_entries standard_entries(@rbconfig).each do |ent| add ent end end def standard_entries(rbconfig) c = rbconfig rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT']) major = c['MAJOR'].to_i minor = c['MINOR'].to_i teeny = c['TEENY'].to_i version = "#{major}.#{minor}" # ruby ver. >= 1.4.4? newpath_p = ((major >= 2) or ((major == 1) and ((minor >= 5) or ((minor == 4) and (teeny >= 4))))) if c['rubylibdir'] # V > 1.6.3 libruby = "#{c['prefix']}/lib/ruby" librubyver = c['rubylibdir'] librubyverarch = c['archdir'] siteruby = c['sitedir'] siterubyver = c['sitelibdir'] siterubyverarch = c['sitearchdir'] elsif newpath_p # 1.4.4 <= V <= 1.6.3 libruby = "#{c['prefix']}/lib/ruby" librubyver = "#{c['prefix']}/lib/ruby/#{version}" librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" siteruby = c['sitedir'] siterubyver = "$siteruby/#{version}" siterubyverarch = "$siterubyver/#{c['arch']}" else # V < 1.4.4 libruby = "#{c['prefix']}/lib/ruby" librubyver = "#{c['prefix']}/lib/ruby/#{version}" librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby" siterubyver = siteruby siterubyverarch = "$siterubyver/#{c['arch']}" end parameterize = lambda {|path| path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix') } if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } makeprog = arg.sub(/'/, '').split(/=/, 2)[1] else makeprog = 'make' end [ ExecItem.new('installdirs', 'std/site/home', 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\ {|val, table| case val when 'std' table['rbdir'] = '$librubyver' table['sodir'] = '$librubyverarch' when 'site' table['rbdir'] = '$siterubyver' table['sodir'] = '$siterubyverarch' when 'home' setup_rb_error '$HOME was not set' unless ENV['HOME'] table['prefix'] = ENV['HOME'] table['rbdir'] = '$libdir/ruby' table['sodir'] = '$libdir/ruby' end }, PathItem.new('prefix', 'path', c['prefix'], 'path prefix of target environment'), PathItem.new('bindir', 'path', parameterize.call(c['bindir']), 'the directory for commands'), PathItem.new('libdir', 'path', parameterize.call(c['libdir']), 'the directory for libraries'), PathItem.new('datadir', 'path', parameterize.call(c['datadir']), 'the directory for shared data'), PathItem.new('mandir', 'path', parameterize.call(c['mandir']), 'the directory for man pages'), PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), 'the directory for system configuration files'), PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']), 'the directory for local state data'), PathItem.new('libruby', 'path', libruby, 'the directory for ruby libraries'), PathItem.new('librubyver', 'path', librubyver, 'the directory for standard ruby libraries'), PathItem.new('librubyverarch', 'path', librubyverarch, 'the directory for standard ruby extensions'), PathItem.new('siteruby', 'path', siteruby, 'the directory for version-independent aux ruby libraries'), PathItem.new('siterubyver', 'path', siterubyver, 'the directory for aux ruby libraries'), PathItem.new('siterubyverarch', 'path', siterubyverarch, 'the directory for aux ruby binaries'), PathItem.new('rbdir', 'path', '$siterubyver', 'the directory for ruby scripts'), PathItem.new('sodir', 'path', '$siterubyverarch', 'the directory for ruby extentions'), PathItem.new('rubypath', 'path', rubypath, 'the path to set to #! line'), ProgramItem.new('rubyprog', 'name', rubypath, 'the ruby program using for installation'), ProgramItem.new('makeprog', 'name', makeprog, 'the make program to compile ruby extentions'), SelectItem.new('shebang', 'all/ruby/never', 'ruby', 'shebang line (#!) editing mode'), BoolItem.new('without-ext', 'yes/no', 'no', 'does not compile/install ruby extentions') ] end private :standard_entries def load_multipackage_entries multipackage_entries().each do |ent| add ent end end def multipackage_entries [ PackageSelectionItem.new('with', 'name,name...', '', 'ALL', 'package names that you want to install'), PackageSelectionItem.new('without', 'name,name...', '', 'NONE', 'package names that you do not want to install') ] end private :multipackage_entries ALIASES = { 'std-ruby' => 'librubyver', 'stdruby' => 'librubyver', 'rubylibdir' => 'librubyver', 'archdir' => 'librubyverarch', 'site-ruby-common' => 'siteruby', # For backward compatibility 'site-ruby' => 'siterubyver', # For backward compatibility 'bin-dir' => 'bindir', 'bin-dir' => 'bindir', 'rb-dir' => 'rbdir', 'so-dir' => 'sodir', 'data-dir' => 'datadir', 'ruby-path' => 'rubypath', 'ruby-prog' => 'rubyprog', 'ruby' => 'rubyprog', 'make-prog' => 'makeprog', 'make' => 'makeprog' } def fixup ALIASES.each do |ali, name| @table[ali] = @table[name] end @items.freeze @table.freeze @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/ end def parse_opt(opt) m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}" m.to_a[1,2] end def dllext @rbconfig['DLEXT'] end def value_config?(name) lookup(name).value? end class Item def initialize(name, template, default, desc) @name = name.freeze @template = template @value = default @default = default @description = desc end attr_reader :name attr_reader :description attr_accessor :default alias help_default default def help_opt "--#{@name}=#{@template}" end def value? true end def value @value end def resolve(table) @value.gsub(%r<\$([^/]+)>) { table[$1] } end def set(val) @value = check(val) end private def check(val) setup_rb_error "config: --#{name} requires argument" unless val val end end class BoolItem < Item def config_type 'bool' end def help_opt "--#{@name}" end private def check(val) return 'yes' unless val case val when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes' when /\An(o)?\z/i, /\Af(alse)\z/i then 'no' else setup_rb_error "config: --#{@name} accepts only yes/no for argument" end end end class PathItem < Item def config_type 'path' end private def check(path) setup_rb_error "config: --#{@name} requires argument" unless path path[0,1] == '$' ? path : File.expand_path(path) end end class ProgramItem < Item def config_type 'program' end end class SelectItem < Item def initialize(name, selection, default, desc) super @ok = selection.split('/') end def config_type 'select' end private def check(val) unless @ok.include?(val.strip) setup_rb_error "config: use --#{@name}=#{@template} (#{val})" end val.strip end end class ExecItem < Item def initialize(name, selection, desc, &block) super name, selection, nil, desc @ok = selection.split('/') @action = block end def config_type 'exec' end def value? false end def resolve(table) setup_rb_error "$#{name()} wrongly used as option value" end undef set def evaluate(val, table) v = val.strip.downcase unless @ok.include?(v) setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})" end @action.call v, table end end class PackageSelectionItem < Item def initialize(name, template, default, help_default, desc) super name, template, default, desc @help_default = help_default end attr_reader :help_default def config_type 'package' end private def check(val) unless File.dir?("packages/#{val}") setup_rb_error "config: no such package: #{val}" end val end end class MetaConfigEnvironment def initialize(config, installer) @config = config @installer = installer end def config_names @config.names end def config?(name) @config.key?(name) end def bool_config?(name) @config.lookup(name).config_type == 'bool' end def path_config?(name) @config.lookup(name).config_type == 'path' end def value_config?(name) @config.lookup(name).config_type != 'exec' end def add_config(item) @config.add item end def add_bool_config(name, default, desc) @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) end def add_path_config(name, default, desc) @config.add PathItem.new(name, 'path', default, desc) end def set_config_default(name, default) @config.lookup(name).default = default end def remove_config(name) @config.remove(name) end # For only multipackage def packages raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer @installer.packages end # For only multipackage def declare_packages(list) raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer @installer.packages = list end end end # class ConfigTable # This module requires: #verbose?, #no_harm? module FileOperations def mkdir_p(dirname, prefix = nil) dirname = prefix + File.expand_path(dirname) if prefix $stderr.puts "mkdir -p #{dirname}" if verbose? return if no_harm? # Does not check '/', it's too abnormal. dirs = File.expand_path(dirname).split(%r<(?=/)>) if /\A[a-z]:\z/i =~ dirs[0] disk = dirs.shift dirs[0] = disk + dirs[0] end dirs.each_index do |idx| path = dirs[0..idx].join('') Dir.mkdir path unless File.dir?(path) end end def rm_f(path) $stderr.puts "rm -f #{path}" if verbose? return if no_harm? force_remove_file path end def rm_rf(path) $stderr.puts "rm -rf #{path}" if verbose? return if no_harm? remove_tree path end def remove_tree(path) if File.symlink?(path) remove_file path elsif File.dir?(path) remove_tree0 path else force_remove_file path end end def remove_tree0(path) Dir.foreach(path) do |ent| next if ent == '.' next if ent == '..' entpath = "#{path}/#{ent}" if File.symlink?(entpath) remove_file entpath elsif File.dir?(entpath) remove_tree0 entpath else force_remove_file entpath end end begin Dir.rmdir path rescue Errno::ENOTEMPTY # directory may not be empty end end def move_file(src, dest) force_remove_file dest begin File.rename src, dest rescue File.open(dest, 'wb') {|f| f.write File.binread(src) } File.chmod File.stat(src).mode, dest File.unlink src end end def force_remove_file(path) begin remove_file path rescue end end def remove_file(path) File.chmod 0777, path File.unlink path end def install(from, dest, mode, prefix = nil) $stderr.puts "install #{from} #{dest}" if verbose? return if no_harm? realdest = prefix ? prefix + File.expand_path(dest) : dest realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) str = File.binread(from) if diff?(str, realdest) verbose_off { rm_f realdest if File.exist?(realdest) } File.open(realdest, 'wb') {|f| f.write str } File.chmod mode, realdest File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| if prefix f.puts realdest.sub(prefix, '') else f.puts realdest end } end end def diff?(new_content, path) return true unless File.exist?(path) new_content != File.binread(path) end def command(*args) $stderr.puts args.join(' ') if verbose? system(*args) or raise RuntimeError, "system(#{args.map{|a| a.inspect }.join(' ')}) failed" end def ruby(*args) command config('rubyprog'), *args end def make(task = nil) command(*[config('makeprog'), task].compact) end def extdir?(dir) File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb") end def files_of(dir) Dir.open(dir) {|d| return d.select {|ent| File.file?("#{dir}/#{ent}") } } end DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn ) def directories_of(dir) Dir.open(dir) {|d| return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT } end end # This module requires: #srcdir_root, #objdir_root, #relpath module HookScriptAPI def get_config(key) @config[key] end alias config get_config # obsolete: use metaconfig to change configuration def set_config(key, val) @config[key] = val end # # srcdir/objdir (works only in the package directory) # def curr_srcdir "#{srcdir_root()}/#{relpath()}" end def curr_objdir "#{objdir_root()}/#{relpath()}" end def srcfile(path) "#{curr_srcdir()}/#{path}" end def srcexist?(path) File.exist?(srcfile(path)) end def srcdirectory?(path) File.dir?(srcfile(path)) end def srcfile?(path) File.file?(srcfile(path)) end def srcentries(path = '.') Dir.open("#{curr_srcdir()}/#{path}") {|d| return d.to_a - %w(. ..) } end def srcfiles(path = '.') srcentries(path).select {|fname| File.file?(File.join(curr_srcdir(), path, fname)) } end def srcdirectories(path = '.') srcentries(path).select {|fname| File.dir?(File.join(curr_srcdir(), path, fname)) } end end class ToplevelInstaller Version = '3.4.1' Copyright = 'Copyright (c) 2000-2005 Minero Aoki' TASKS = [ [ 'all', 'do config, setup, then install' ], [ 'config', 'saves your configurations' ], [ 'show', 'shows current configuration' ], [ 'setup', 'compiles ruby extentions and others' ], [ 'install', 'installs files' ], [ 'test', 'run all tests in test/' ], [ 'clean', "does `make clean' for each extention" ], [ 'distclean',"does `make distclean' for each extention" ] ] def ToplevelInstaller.invoke config = ConfigTable.new(load_rbconfig()) config.load_standard_entries config.load_multipackage_entries if multipackage? config.fixup klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller) klass.new(File.dirname($0), config).invoke end def ToplevelInstaller.multipackage? File.dir?(File.dirname($0) + '/packages') end def ToplevelInstaller.load_rbconfig if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } ARGV.delete(arg) load File.expand_path(arg.split(/=/, 2)[1]) $".push 'rbconfig.rb' else require 'rbconfig' end ::Config::CONFIG end def initialize(ardir_root, config) @ardir = File.expand_path(ardir_root) @config = config # cache @valid_task_re = nil end def config(key) @config[key] end def inspect "#<#{self.class} #{__id__()}>" end def invoke run_metaconfigs case task = parsearg_global() when nil, 'all' parsearg_config init_installers exec_config exec_setup exec_install else case task when 'config', 'test' ; when 'clean', 'distclean' @config.load_savefile if File.exist?(@config.savefile) else @config.load_savefile end __send__ "parsearg_#{task}" init_installers __send__ "exec_#{task}" end end def run_metaconfigs @config.load_script "#{@ardir}/metaconfig" end def init_installers @installer = Installer.new(@config, @ardir, File.expand_path('.')) end # # Hook Script API bases # def srcdir_root @ardir end def objdir_root '.' end def relpath '.' end # # Option Parsing # def parsearg_global while arg = ARGV.shift case arg when /\A\w+\z/ setup_rb_error "invalid task: #{arg}" unless valid_task?(arg) return arg when '-q', '--quiet' @config.verbose = false when '--verbose' @config.verbose = true when '--help' print_usage $stdout exit 0 when '--version' puts "#{File.basename($0)} version #{Version}" exit 0 when '--copyright' puts Copyright exit 0 else setup_rb_error "unknown global option '#{arg}'" end end nil end def valid_task?(t) valid_task_re() =~ t end def valid_task_re @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/ end def parsearg_no_options unless ARGV.empty? task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1) setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}" end end alias parsearg_show parsearg_no_options alias parsearg_setup parsearg_no_options alias parsearg_test parsearg_no_options alias parsearg_clean parsearg_no_options alias parsearg_distclean parsearg_no_options def parsearg_config evalopt = [] set = [] @config.config_opt = [] while i = ARGV.shift if /\A--?\z/ =~ i @config.config_opt = ARGV.dup break end name, value = *@config.parse_opt(i) if @config.value_config?(name) @config[name] = value else evalopt.push [name, value] end set.push name end evalopt.each do |name, value| @config.lookup(name).evaluate value, @config end # Check if configuration is valid set.each do |n| @config[n] if @config.value_config?(n) end end def parsearg_install @config.no_harm = false @config.install_prefix = '' while a = ARGV.shift case a when '--no-harm' @config.no_harm = true when /\A--prefix=/ path = a.split(/=/, 2)[1] path = File.expand_path(path) unless path[0,1] == '/' @config.install_prefix = path else setup_rb_error "install: unknown option #{a}" end end end def print_usage(out) out.puts 'Typical Installation Procedure:' out.puts " $ ruby #{File.basename $0} config" out.puts " $ ruby #{File.basename $0} setup" out.puts " # ruby #{File.basename $0} install (may require root privilege)" out.puts out.puts 'Detailed Usage:' out.puts " ruby #{File.basename $0} " out.puts " ruby #{File.basename $0} [] []" fmt = " %-24s %s\n" out.puts out.puts 'Global options:' out.printf fmt, '-q,--quiet', 'suppress message outputs' out.printf fmt, ' --verbose', 'output messages verbosely' out.printf fmt, ' --help', 'print this message' out.printf fmt, ' --version', 'print version and quit' out.printf fmt, ' --copyright', 'print copyright and quit' out.puts out.puts 'Tasks:' TASKS.each do |name, desc| out.printf fmt, name, desc end fmt = " %-24s %s [%s]\n" out.puts out.puts 'Options for CONFIG or ALL:' @config.each do |item| out.printf fmt, item.help_opt, item.description, item.help_default end out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" out.puts out.puts 'Options for INSTALL:' out.printf fmt, '--no-harm', 'only display what to do if given', 'off' out.printf fmt, '--prefix=path', 'install path prefix', '' out.puts end # # Task Handlers # def exec_config @installer.exec_config @config.save # must be final end def exec_setup @installer.exec_setup end def exec_install @installer.exec_install end def exec_test @installer.exec_test end def exec_show @config.each do |i| printf "%-20s %s\n", i.name, i.value if i.value? end end def exec_clean @installer.exec_clean end def exec_distclean @installer.exec_distclean end end # class ToplevelInstaller class ToplevelInstallerMulti < ToplevelInstaller include FileOperations def initialize(ardir_root, config) super @packages = directories_of("#{@ardir}/packages") raise 'no package exists' if @packages.empty? @root_installer = Installer.new(@config, @ardir, File.expand_path('.')) end def run_metaconfigs @config.load_script "#{@ardir}/metaconfig", self @packages.each do |name| @config.load_script "#{@ardir}/packages/#{name}/metaconfig" end end attr_reader :packages def packages=(list) raise 'package list is empty' if list.empty? list.each do |name| raise "directory packages/#{name} does not exist"\ unless File.dir?("#{@ardir}/packages/#{name}") end @packages = list end def init_installers @installers = {} @packages.each do |pack| @installers[pack] = Installer.new(@config, "#{@ardir}/packages/#{pack}", "packages/#{pack}") end with = extract_selection(config('with')) without = extract_selection(config('without')) @selected = @installers.keys.select {|name| (with.empty? or with.include?(name)) \ and not without.include?(name) } end def extract_selection(list) a = list.split(/,/) a.each do |name| setup_rb_error "no such package: #{name}" unless @installers.key?(name) end a end def print_usage(f) super f.puts 'Inluded packages:' f.puts ' ' + @packages.sort.join(' ') f.puts end # # Task Handlers # def exec_config run_hook 'pre-config' each_selected_installers {|inst| inst.exec_config } run_hook 'post-config' @config.save # must be final end def exec_setup run_hook 'pre-setup' each_selected_installers {|inst| inst.exec_setup } run_hook 'post-setup' end def exec_install run_hook 'pre-install' each_selected_installers {|inst| inst.exec_install } run_hook 'post-install' end def exec_test run_hook 'pre-test' each_selected_installers {|inst| inst.exec_test } run_hook 'post-test' end def exec_clean rm_f @config.savefile run_hook 'pre-clean' each_selected_installers {|inst| inst.exec_clean } run_hook 'post-clean' end def exec_distclean rm_f @config.savefile run_hook 'pre-distclean' each_selected_installers {|inst| inst.exec_distclean } run_hook 'post-distclean' end # # lib # def each_selected_installers Dir.mkdir 'packages' unless File.dir?('packages') @selected.each do |pack| $stderr.puts "Processing the package `#{pack}' ..." if verbose? Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") Dir.chdir "packages/#{pack}" yield @installers[pack] Dir.chdir '../..' end end def run_hook(id) @root_installer.run_hook id end # module FileOperations requires this def verbose? @config.verbose? end # module FileOperations requires this def no_harm? @config.no_harm? end end # class ToplevelInstallerMulti class Installer FILETYPES = %w( bin lib ext data conf man ) include FileOperations include HookScriptAPI def initialize(config, srcroot, objroot) @config = config @srcdir = File.expand_path(srcroot) @objdir = File.expand_path(objroot) @currdir = '.' end def inspect "#<#{self.class} #{File.basename(@srcdir)}>" end def noop(rel) end # # Hook Script API base methods # def srcdir_root @srcdir end def objdir_root @objdir end def relpath @currdir end # # Config Access # # module FileOperations requires this def verbose? @config.verbose? end # module FileOperations requires this def no_harm? @config.no_harm? end def verbose_off begin save, @config.verbose = @config.verbose?, false yield ensure @config.verbose = save end end # # TASK config # def exec_config exec_task_traverse 'config' end alias config_dir_bin noop alias config_dir_lib noop def config_dir_ext(rel) extconf if extdir?(curr_srcdir()) end alias config_dir_data noop alias config_dir_conf noop alias config_dir_man noop def extconf ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt end # # TASK setup # def exec_setup exec_task_traverse 'setup' end def setup_dir_bin(rel) files_of(curr_srcdir()).each do |fname| update_shebang_line "#{curr_srcdir()}/#{fname}" end end alias setup_dir_lib noop def setup_dir_ext(rel) make if extdir?(curr_srcdir()) end alias setup_dir_data noop alias setup_dir_conf noop alias setup_dir_man noop def update_shebang_line(path) return if no_harm? return if config('shebang') == 'never' old = Shebang.load(path) if old $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1 new = new_shebang(old) return if new.to_s == old.to_s else return unless config('shebang') == 'all' new = Shebang.new(config('rubypath')) end $stderr.puts "updating shebang: #{File.basename(path)}" if verbose? open_atomic_writer(path) {|output| File.open(path, 'rb') {|f| f.gets if old # discard output.puts new.to_s output.print f.read } } end def new_shebang(old) if /\Aruby/ =~ File.basename(old.cmd) Shebang.new(config('rubypath'), old.args) elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby' Shebang.new(config('rubypath'), old.args[1..-1]) else return old unless config('shebang') == 'all' Shebang.new(config('rubypath')) end end def open_atomic_writer(path, &block) tmpfile = File.basename(path) + '.tmp' begin File.open(tmpfile, 'wb', &block) File.rename tmpfile, File.basename(path) ensure File.unlink tmpfile if File.exist?(tmpfile) end end class Shebang def Shebang.load(path) line = nil File.open(path) {|f| line = f.gets } return nil unless /\A#!/ =~ line parse(line) end def Shebang.parse(line) cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ') new(cmd, args) end def initialize(cmd, args = []) @cmd = cmd @args = args end attr_reader :cmd attr_reader :args def to_s "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}") end end # # TASK install # def exec_install rm_f 'InstalledFiles' exec_task_traverse 'install' end def install_dir_bin(rel) install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755 end def install_dir_lib(rel) install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644 end def install_dir_ext(rel) return unless extdir?(curr_srcdir()) install_files rubyextentions('.'), "#{config('sodir')}/#{File.dirname(rel)}", 0555 end def install_dir_data(rel) install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644 end def install_dir_conf(rel) # FIXME: should not remove current config files # (rename previous file to .old/.org) install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644 end def install_dir_man(rel) install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644 end def install_files(list, dest, mode) mkdir_p dest, @config.install_prefix list.each do |fname| install fname, dest, mode, @config.install_prefix end end def libfiles glob_reject(%w(*.y *.output), targetfiles()) end def rubyextentions(dir) ents = glob_select("*.#{@config.dllext}", targetfiles()) if ents.empty? setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" end ents end def targetfiles mapdir(existfiles() - hookfiles()) end def mapdir(ents) ents.map {|ent| if File.exist?(ent) then ent # objdir else "#{curr_srcdir()}/#{ent}" # srcdir end } end # picked up many entries from cvs-1.11.1/src/ignore.c JUNK_FILES = %w( core RCSLOG tags TAGS .make.state .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb *~ *.old *.bak *.BAK *.orig *.rej _$* *$ *.org *.in .* ) def existfiles glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.'))) end def hookfiles %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| %w( config setup install clean ).map {|t| sprintf(fmt, t) } }.flatten end def glob_select(pat, ents) re = globs2re([pat]) ents.select {|ent| re =~ ent } end def glob_reject(pats, ents) re = globs2re(pats) ents.reject {|ent| re =~ ent } end GLOB2REGEX = { '.' => '\.', '$' => '\$', '#' => '\#', '*' => '.*' } def globs2re(pats) /\A(?:#{ pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|') })\z/ end # # TASK test # TESTDIR = 'test' def exec_test unless File.directory?('test') $stderr.puts 'no test in this package' if verbose? return end $stderr.puts 'Running tests...' if verbose? begin require 'test/unit' rescue LoadError setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.' end runner = Test::Unit::AutoRunner.new(true) runner.to_run << TESTDIR runner.run end # # TASK clean # def exec_clean exec_task_traverse 'clean' rm_f @config.savefile rm_f 'InstalledFiles' end alias clean_dir_bin noop alias clean_dir_lib noop alias clean_dir_data noop alias clean_dir_conf noop alias clean_dir_man noop def clean_dir_ext(rel) return unless extdir?(curr_srcdir()) make 'clean' if File.file?('Makefile') end # # TASK distclean # def exec_distclean exec_task_traverse 'distclean' rm_f @config.savefile rm_f 'InstalledFiles' end alias distclean_dir_bin noop alias distclean_dir_lib noop def distclean_dir_ext(rel) return unless extdir?(curr_srcdir()) make 'distclean' if File.file?('Makefile') end alias distclean_dir_data noop alias distclean_dir_conf noop alias distclean_dir_man noop # # Traversing # def exec_task_traverse(task) run_hook "pre-#{task}" FILETYPES.each do |type| if type == 'ext' and config('without-ext') == 'yes' $stderr.puts 'skipping ext/* by user option' if verbose? next end traverse task, type, "#{task}_dir_#{type}" end run_hook "post-#{task}" end def traverse(task, rel, mid) dive_into(rel) { run_hook "pre-#{task}" __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') directories_of(curr_srcdir()).each do |d| traverse task, "#{rel}/#{d}", mid end run_hook "post-#{task}" } end def dive_into(rel) return unless File.dir?("#{@srcdir}/#{rel}") dir = File.basename(rel) Dir.mkdir dir unless File.dir?(dir) prevdir = Dir.pwd Dir.chdir dir $stderr.puts '---> ' + rel if verbose? @currdir = rel yield Dir.chdir prevdir $stderr.puts '<--- ' + rel if verbose? @currdir = File.dirname(rel) end def run_hook(id) path = [ "#{curr_srcdir()}/#{id}", "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) } return unless path begin instance_eval File.read(path), path, 1 rescue raise if $DEBUG setup_rb_error "hook #{path} failed:\n" + $!.message end end end # class Installer class SetupError < StandardError; end def setup_rb_error(msg) raise SetupError, msg end if $0 == __FILE__ begin ToplevelInstaller.invoke rescue SetupError raise if $DEBUG $stderr.puts $!.message $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." exit 1 end end PK% ]&E  )gems/ruby-lsapi-5.6/examples/testlsapi.rbnuȯ#!/opt/alt/ruby26/bin/ruby require 'lsapi' $count = 0; while LSAPI.accept != nil print "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\nHello World! \##{$count}
\r\n" ENV.each_pair {|key, value| print "#{key} is #{value}
\r\n" } $count = $count + 1 end PK% ]+.gems/ruby-lsapi-5.6/examples/lsapi_with_cgi.rbnuȯ#!/opt/alt/ruby26/bin/ruby require 'lsapi' require 'cgi' while LSAPI.accept != nil cgi = CGI.new name = cgi['name'] puts cgi.header puts "Hello #{name}!
" if name puts "You are from #{cgi.remote_addr}
" end PK% ]Lu-- gems/ruby-lsapi-5.6/lib/lsapi.sonuȯELF>U@&@8 @ !!0 !!888$$hhh Stdhhh PtdPPPQtdRtd!!P P GNUIրmQ1v"C H‚3@(L`qCSlP*fRn}'3qѮl>&Sɶ ܮʼnSO`[is|&߱RD/y7řkՊ eY&09=By:%/=ejOzJ6'l#mNULCB1{!\$O#W23S=apbU06aD7jp#7ĴDIΊ=\4yݾCEкQuo rSѮIo|q%h6 󝵛 ' =qX[ u  f   d ysOq    T [M f A k &K ! , 2TRT" s G +L  } >W  9 - kH  .E   $7x9 vo | Z A 9J 4, 2> F"`| E]   r G p `}F 0rD @I  `K 5 0vi~  z@! b П. P! ] Z\ g o  v 1 r Y ` Pq@  @ sl zj V } - Ps]   `o @rY po  5 o x$ Pl! u U U E v rS o7 @oT (   0  }F rJ @pT ! P~I   Е  P!b g  @g "! l p6 o p [ !__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizecompareValueLocationset_skip_writesigactionsigemptyset__stack_chk_failreallocfcntlacceptsetsockoptmmapmemsetsetsidread__errno_locationclosewritevkillgetppid__ctype_b_locstrncpystrchrstrcasecmpstrtolgetaddrinfomemcpyfreeaddrinfoinet_addrLSAPI_Log__vfprintf_chk__snprintf_chkgetuid__fprintf_chkgettimeofdaylocaltime_rwaitpidforksystemexitlsapi_perrorstrerrorLSAPI_is_suEXEC_DaemonLSAPI_StopLSAPI_IsRunningLSAPI_Register_Pgrp_Timer_CallbackLSAPI_InitRequestmallocgetpeernamedup2LSAPI_Initgeteuidsignalg_reqdlopendlsymLSAPI_Is_Listen_rLSAPI_Is_ListenLSAPI_Reset_rLSAPI_Release_rfreeLSAPI_GetHeader_rLSAPI_ReqBodyGetChar_rLSAPI_ReqBodyGetLine_rmemchrmemmoveLSAPI_ReadReqBody_rFlush_RespBuf_rLSAPI_GetEnv_rstrcmp__ctype_toupper_locLSAPI_ForeachOrgHeader_rqsortLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rLSAPI_ForeachSpecialEnv_rLSAPI_FinalizeRespHeaders_rLSAPI_Flush_rLSAPI_Write_Stderr_rgetpidgetcwdmemccpy__realpath_chkLSAPI_Finish_rLSAPI_End_Response_rLSAPI_Write_rLSAPI_sendfile_rsendfileLSAPI_AppendRespHeader2_rstrlenLSAPI_AppendRespHeader_rLSAPI_CreateListenSock2socketbindlistenunlinkLSAPI_ParseSockAddrLSAPI_CreateListenSockLSAPI_Init_Prefork_ServercallocsetpgidsysconfLSAPI_Set_Server_fdLSAPI_reset_server_stateis_enough_free_memLSAPI_Postfork_ChildLSAPI_Postfork_ParenttimeLSAPI_Accept_Before_Fork__fdelt_chkusleepsched_yieldLSAPI_Set_Max_ReqsLSAPI_Set_Max_IdleLSAPI_Set_Max_ChildrenLSAPI_Set_Extra_ChildrenLSAPI_Set_Max_Process_TimeLSAPI_Set_Max_Idle_ChildrenLSAPI_Set_Server_Max_Idle_SecsLSAPI_Set_Slow_Req_MsecsLSAPI_Get_Slow_Req_MsecsLSAPI_No_Check_ppidLSAPI_Get_ppidLSAPI_Init_Env_Parametersgetenvgetpwnamdlerrorsetrlimit__fxstatsetreuidLSAPI_ErrResponse_rlsapi_MD5Initlsapi_MD5Updatelsapi_MD5FinalgetpwuidsetgidsetgroupssetuidstrtollprctlinitgroupsLSAPI_Accept_rLSAPI_Prefork_Accept_rsigaddsetsigprocmaskLSAPI_Set_Restored_Parent_PidLSAPI_Inc_Req_Processedselectrb_tainted_str_newrb_hash_asetrb_funcallvrb_intern2rb_gc_markmunmaprb_check_typerb_obj_as_stringrb_f_sprintfs_fn_add_envrb_safe_levelrb_string_value_ptrrb_eval_string_wraprb_string_valuerb_check_safe_objrb_ruby_verbose_ptrrb_define_global_construby_strdupmkstempftruncaterb_str_buf_newrb_str_catrb_num2intrb_fix2intrb_eSecurityErrorrb_raisememmemrb_yieldrb_gc_writebarrier_unprotectrb_io_putsrb_ary_detransientrb_str_new_staticrb_exec_recursiverb_default_rsrb_output_fsrb_output_rsrb_lastline_getInit_lsapichdirrb_stderrrb_cObjectrb_const_getrb_global_variablerb_define_global_functionrb_define_classrb_define_singleton_methodrb_define_methodrb_data_object_zallocrb_stdoutrb_stdinrb_hash_new__memcpy_chklibruby.so.2.6libm.so.6libc.so.6__environ_edata__bss_start_endGLIBC_2.14GLIBC_2.15GLIBC_2.4GLIBC_2.3.4GLIBC_2.2.5GLIBC_2.3/opt/alt/ruby26/lib64@ l w ii  ti  ui  ii  !U!pU!!!!!!!!!! !(!0! 8!@!*H!8P!CX!P`!_h!fp!nx!s!z!!!!!!!!!!!!!!!2!G !\(!o0!8!@!H!P!X!`!h!p!x!!!!2!@!Y!i!t!!!!!!!X!!!!H!P!X!`!h!p!x!!!$!5!!?!K!M!U!Y!Y!Z!!!q!!! ! ! ! ! ! ! !( !0 !8 !@ !H ! P ! X ! ` ! h ! p !x ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !( ! 0 !8 !"@ !#H !%P !&X !` !'h !(p !)x ! !* !+ ! !, ! ! ! !- !. !/ !0 ! ! ! ! !1 !2 !3 ! !4 !( !0 !68 !7@ !8H !9P !:X !;` !<h !>p !@x !A !B !C ! !D !E !F !G !H !I ! !J ! !L !N !O !P !Q !R ! !S !T( !0 !V8 !@ !WH !XP ![X !\` !]h !^p !_x !` !a ! !b !c ! !d !e !f !g !h !i !j !k !l !m !!n!o!p! !(!r0!s8!t@!uH!vP!X!w`!xh!yp!{x!|!}!~!!!!!!!!!!!!!!!!!! !(!0!8!@!HH! HtH5J %K hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhA% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݾ D%վ D%; D%ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݽ D%ս D%ͽ D%Ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݼ D%ռ D%ͼ D%ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݻ D%ջ D%ͻ D%Ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݺ D%պ D%ͺ D%ź D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E DH= H H9tH6 Ht H= H5 H)HHH?HHtH HtfD=e u+UH=b Ht H=. d= ]wff. ÐHGH+FHcAVIH@AUATL$USHtQHHtIHIL9r 0HI9v'KHSMsH;Յ[]A\A]A^[D]A\A]A^øff.f= D2 ÐO AWDD_AVAUATUSD6^nAxj׋G3G D!3G V\$ЋW^$DD1\$!3WAʋN Fp $E‰L$A1A1DD^ !D1G;νD\$DEDVDT$A!A1EE|A 1AD!E1DD*ƇGD1D!A1A1DDN DL$E F0D!DnA1D1DGFEDf Dd$D^(A!A1EEؘiA 1AD!1DDDʋ^0D1D!A1DE [D 1!D1DDN,A1DL$G\EA!Df8A1ED"kA 1AD!1DDN4EqDD1!1DE CyD 1!D1DDV<1G!I!1DDD$ Eb%1!1DDD$E@@1!1DDD$ EQZ^&1!1DE6Ƕ1!1DD]/։ 1!1DESD1!1DE ؉ 1!1DDD$E01!1DDD$ E!1!1DE7É1!1DDD$ E 1!1DDD$A0ZEAA1A!A1AA㩉A AD1!1t$DD1!A ogD1 1D!FL*1DD$Ή1AA!B9A1DD$A AD1D$qDD11‹D$ 0"amD1G 81Ɖ11DDD$ ED꾤11DDD$AKAA1A5`KA1AЉApA 1AD1D1D1A ~(D 1G'111DDD$ A0AA1A1AЋT$A2A1D1֋T$ 9ىDD11D11C|A A1A1AD$A0eVĉA1D1AD")Dt$ D D1A *CDG# 1  1DD9Ή 1DDY[e\$  1DE Dt$ щ1DE3}D\$  1DDD$E] 1DEO~oA AD 1DE ,DT$ A1ADE6CDt$ AN 1A~SADEAA A1A5:ADA AD 1Љ3*\$D D1DFӆ[ ]A\A]A^ 1։ 1DƉA4A_ OW GOW ATI1USHdH%(H$1HHH<$t)H$dH3%(uL{8IHC0L)H9>Lt$L+{(LA@LLfIM)MK H@σLSLCpNIHDI0HI@HKpM~HC(MxIH E1I@HC8HL1HMLIHHKpH9eHMthILM)MUI9t H)tDL+t$HL[]A\A]A^A_DM@@M)(+IHt$HLHk8f.HAVLAUIATIUSHu\H߉[AD${LǃLSHu0{L[L]A\A]A^K[H]A\A]A^Hff.AWAVAUATUSHHHHD$ 0xIHIHLc\CHcT t u(HDLcLH t tLÅ~6HcAT t u#H@Å~ALH t tE<AG=I|$PHHTI9T$Hs7HI+t$@L2%))I|$PLHHcAMt$PHLIFID$PA:I|$P}MD$PII@ID$PAIc$0fET8HЃA$0D$ H[]A\A]A^A_D$ ff.H HB=0AUATUSHcHfDA< t< uH؅uH[]A\A]IHPHHDI9D$Hs3HI+t$@L2%))tQI|$PHHAPI\$PHCID$PIc$0fET8HЃA$0H1[]A\A]øSDAUATAUHSH?dH%(HD$1D$ff t1fHL$dH3 %(H[]A\A]ÐA1ҾÃtʼnǺ1HL$Aߺ踿u#DH'uDo̾߻D HJDeOAkDH}An衾}NSHtff.USHdH%(H$1HHu/HH$dH3%(uHĘ[]Ŀ@1H= tAUATA'USH݋ 'DNuD H@AHH^ HHtH- t YƉlj JUDk HM DcEuSH8dH%(H$(1=HtH H=H H=_>HE1 H讹H=Y>Ht 1H膹 H=E>ijHHt 1H]IAąWE1H=">萳Ht 1H, H=>jHtHǺ 1_H==CH H==$HtHǺ 1IԶH==H1 H舸OH==òHtHǺ 1_H==蜲HtHǺ 18!H==uHtHǺ 1H==NHtHǺ 1蓲H=r='HtMH=p=Ht 1H護ۀ _H=X=Ht 1H D   EH=$=H=r u Pe 5[ H=&=cH 1H% …t% HQv HHHHD L*=L =L#=C HLt@HֹL€D t%HtAHHt9HLuHfDHJHHJHuHHu1ۉH$(dH3%(H8[]A\A]fD& H覲D9舭HHiHǺ11˵ÃHT$ƿD$(?H5/ رHgH Htxc@dx@D  E9D E)ZfH=}8贬 HK]  u t 'j X '> )fՅtbH H-DHH5?1 cAHc螲L%~ HH~ a蓮Åt=~ 0~ u ~ 5~ `HH5@?uHH5>1u HH5>Fff.AVIAUEATIUHSHt4Hu!(fDHH蔭HLgH]HuMtEL [1]A\A]A^ÐIcLLH#EgHGHHܺvT2HGAWAVAAUIATUHoSH1HGO@ƉWDW?t;AĉDHH|@D)A9rhAGt4LLDHL9A?vWEfAIIIH޺@HH@ HLL9uA?DLHH[]A\A]A^A_ܱIATLfUHSFH?LHz?)ƒw=t19rLHfCAD$AD$ ID$071)"HCHLHCP?o H{1HMHHCPH)KXH[]A\ff.fAWAVAUATUSHdH%(H$1Ht^ IAfMcg IoA_@LH3HuM88u =Yw uٽH$dH3 %( HĨ[]A\A]A^A_f~AAuIALJf8LS|xr@tPHf@HPXN MgA;G ZA9~uEo)HHcIHLD"Hu$'85Dv uAMgA9ID$,HD$HcIIDhAh(A9}A /HcIH4@HUHAIIh$A9}A HcIH4@HHAIIHl$p(ILHIILp$hMIc@o9gIcP[9SIcpG9?IcH39+IHHHHIHT$IIc@ H)IHHIHHHIHIIcHIHHHD$I9E1DL4t9dfH H IGAG IPH f@ f@ HHP P H HPPHHPPHHPPHHPPf@f@f@HH#PP H H'P#P$H$H+P'P(f@f@!f@%H(P+f@)I1 fDIHcȋL4t#fBIHT4 rfB@2JHHuMIcP IHHH9pH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@pHH9wMApIbIc@ IH0zu ALJt`!u u Au 1LHc迩IHIGAo IuID%t D-t B(AA1IcH4IILI 9HqH=W. IJDB(9xHqH=2. XIJB($AD$IKAzHL$;MbfoOt Lt$ LAoL$AT$Ml$)$踪 LL(HL$LHLLH$ID$H$I3L$H1H D$$Dl$EDDl$H=s IHIDEs MH=$s t"LDLŃP|$臨Et$A9uHt$莤D=Ń5r $A?D5r t 0AH5*L*HtHHr f)r #AH5:e 1;H@H5+1YLH 1HIH531H531D%q q DD$$H=q IHtZEW7E1111H=3H5*1耨E|$迦M2;|$藦E1H5*LuI}觧Ń1H5*LKfD=p -p p ED$AIFH5*1覧HH)H51H1聧1H5!*L 1H5C2LA#LH 3H H=NQ HL~H-> H 4> H=H HP HzH HJH*HQ H]> HH> HH=P LH5}H = H="H HP HH HJH*H踀yH(yHHP 1aH5P H=}H3H=r}yH(H[]A\A]@HPHH=L }HwHL H.XXXXXXH(Ht+H=uH=O 1HxH5,H=O 1HJfDmHzHfKHzHt -GF OkHyHu-*F 2HHAnonymous mmap() failedlocalhost%02d:%02d:%02d [%s] [UID:%d][%d] %.*syesnosystem()%s, errno: %d (%s) /dev/nulllibpthread.sopthread_atforkHTTP_[UID:%d][%d] %s:%s: %s LSAPI: jail() failure./etc/Can't set signalsaccept() failedLSAPI_STDERR_LOGPHP_LSAPI_MAX_REQUESTSLSAPI_MAX_REQSLSAPI_KEEP_LISTENLSAPI_AVOID_FORKLSAPI_ACCEPT_NOTIFYLSAPI_SLOW_REQ_MSECSLSAPI_ALLOW_CORE_DUMPLSAPI_MAX_IDLEPHP_LSAPI_CHILDRENLSAPI_EXTRA_CHILDRENLSAPI_MAX_IDLE_CHILDRENLSAPI_PGRP_MAX_IDLELSAPI_MAX_PROCESS_TIMELSAPI_PPID_NO_CHECKLSAPI_MAX_BUSY_WORKERLSAPI_DUMP_DEBUG_INFOnobodyLSAPI_DEFAULT_UIDLSAPI_DEFAULT_GIDLSAPI_SECRETLSAPI_LVE_ENABLEliblve.so.0lve_is_availablelve_instance_initlve_destroylve_enterlve_leavejailPHP_LSAPI_PHPRC=packetLen < 0 packetLen > %d Bad request header - ERROR#1 ParseRequest error SUEXEC_AUTHSUEXEC_UGIDLSAPI: setgid()LSAPI: initgroups()LSAPI: setgroups()LSAPI: setuid()Bad request header - ERROR#2 lsapi_accept() errorPragma: no-cacheRetry-After: 60Content-Type: text/htmlDEBUGNOTICEWARNERRORCRITFATALAcceptAccept-CharsetAccept-EncodingAccept-LanguageAuthorizationConnectionContent-TypeContent-LengthCookieCookie2HostPragmaRefererUser-AgentCache-ControlIf-Modified-SinceIf-MatchIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveX-Forwarded-ForViaTransfer-EncodingHTTP_ACCEPTHTTP_ACCEPT_CHARSETHTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_AUTHORIZATIONHTTP_CONNECTIONCONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_COOKIE2HTTP_HOSTHTTP_PRAGMAHTTP_REFERERHTTP_USER_AGENTHTTP_CACHE_CONTROLHTTP_IF_MODIFIED_SINCEHTTP_IF_MATCHHTTP_IF_NONE_MATCHHTTP_IF_RANGEHTTP_IF_UNMODIFIED_SINCEHTTP_KEEP_ALIVEHTTP_RANGEHTTP_X_FORWARDED_FORHTTP_VIAHTTP_TRANSFER_ENCODING%04d-%02d-%02d %02d:%02d:%02d.%06d Child process with pid: %d was killed by signal: %d, core dumped: %s Possible runaway process, UID: %d, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld gdb --batch -ex "attach %d" -ex "set height 0" -ex "bt" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2Force killing runaway process PID: %d with SIGKILL Killing runaway process PID: %d with SIGTERM Children tracking is wrong: Cur Children: %d, count: %d, idle: %d, dying: %d LSAPI: LVE jail(%d) result: %d, error: %s ! Invalid custom stderr log pathFailed to open custom stderr logCan't set signal handler for SIGCHILDReached max children process limit: %d, extra: %d, current: %d, busy: %d, please increase LSAPI_CHILDREN. LSAPI: failed to open secret file: %s! LSAPI: failed to check state of file: %s! LSAPI: file permission check failure: %s LSAPI: failed to read secret from secret file: %s LSAPI: Unable to initialize LVERequest header does match total size, total: %d, real: %ld LSAPI: missing SUEXEC_UGID env, use default user! LSAPI: SUEXEC_AUTH authentication failed, use default user! LSAPI: lve_enter() failure, reached resource limit.prctl: Failed to set dumpable, core dump may not be available!sigprocmask(SIG_BLOCK) to block SIGCHLDsigprocmask( SIG_SETMASK ) to restore SIGMASK in childfork() failed, please increase process limitsigprocmask( SIG_SETMASK ) to restore SIGMASKCache-Control: private, no-cache, no-store, must-revalidate, max-age=0PID 508 Resource Limit Is Reached

Resource Limit Is Reached

The website is temporarily unable to service your request as it exceeded resource limit. Please try again later.
          replacesrandQUERY_STRINGREQUEST_URIPATH_INFOREQUEST_PATHSCRIPT_NAMESTDERRreopenftruncate() failed. File mapping failed. Memory calloc error[...]nilLSAPI_MAX_BODYBUF_LENGTHLSAPI_TEMPFILEXXXXXXRACK_ROOTchdir()to_hashCGI/1.2eval_string_wrapLSAPIacceptaccept_new_connectionpostfork_childpostfork_parentprocessputcwriteprintprintfputs<<flushgetcgetsreadrewindeacheofeof?closebinmodeisattytty?syncsync=RACK_ENVInsecure: operation on untainted IOGATEWAY_Irewindable_input.rbNTERFACE/tmp/lsapi.XXXXX;z@Ze pp8pLp`pt q0q@qx00ydyxyPzz|$|t}~<Pd$@ppH p  0 @ Ќ 0 D PX t ` Џ 8 PL p P d `x p ph ` (pt@ @pp0<PPdx`Я,@T h@|`й4Ptp@ L $@8pL`tp00\Pxp@,`x`@ pHzRx $@V FJ w?:*3$"D` \0lp,l(l L$lsEIB E(A0z (A BBBI A (D BBBA Tl Pl@LlYGJB B(A0A80F(B DBb0ThsBFC G  AABK sk( tGADJ n AAA 4DtUAGK R CAG L JCG ltAG] AJ $tt C KFLHuBBE A(H0H (D BBBD  (D BBBA PtvvFB A(D0D (A BBBB L(A BBBA$vaAAD XAAHwBBB B(A0A8D@N 8C0A(B BBBH $`wOAf Q C E H@wYBBB A(D0J 0A(A BBBF xzFEA C(G   (A ABBD M I c A  E M A k E E E E H V HHT|FBB B(A0A8D`` 8A0A(B BBBD l}+BBB B(A0D8JYHPC Mi 8A0A(B BBBE LTMDd~6BBB B(A0A8DP 8A0A(B BBBG  8J0H(G DBBK $l`7EFF IIOx | 4xFAA G>  AABG EO D  A @ ThY|JED$S p]Ph H XAHlFBB B(A0A8LP 8A0A(B BBBH <Є FBB A(A0 (D BBBI \i`pFBB B(A0A8DP~ 8A0A(B BBBA k 8A0A(B BBBH L$FBB A(A0H Q D 0A(A BBBH L$FBB B(A0A8G 8A0A(B BBBF thFF$lnCXJLDlFBB B(A0A8DA 8A0A(B BBBA `( dBBB B(A0A8G I K I L N N w 8A0A(B BBBI 0 BMD GL  AABA < |=BAA G L@I@U  AABG $ |TWEHG ( ag H SHL pFBB B(A0A8DPS 8D0A(B BBBF T bIE D(C0P (F BBBM Q(H BBBAH lFBB B(A0A8DP 8A0A(B BBBA T< CBA A(G0` (A ABBD  (C ABBA J8 Ȗ-FBD D(D@T (A ABBB  ( ȗlECGF AAI L !cBG A(D0 (A ABBE XD0` t Z D10 ppFAA G@7  AABF  @LsL КFBB B(A0A8G 8A0A(B BBBG < P d x    Ȟ Ԟ  О  ̞Ȟ <Ğ FBA K(G (A ABBG <XFEE D(D0M (C BBBB ԧ(HFBH E(A0E8I@ 8A0A(B BBBE (FED ABH$8 BBB B(A0A8G 8A0A(B BBBJ Dp̴FBB A(A0G 0A(A BBBF L4 FBB B(A0A8G  8A0A(B BBBA 4 H\+p(BFGA kFB4zD O E  HU gHQ G <ayd(THEDL ] CAJ ELEY HW HW-Hd(EAD  DAJ ,aED y AE HP FBB E(D0C8GPm 8F0A(B BBBG ,ZAD J ABL 4PoAD  AAK pP \FBD C(G0 (D ABBE j (D ABBE | (G DBBA HdhFBB B(A0A8G@ 8D0A(B BBBD 7ٯqR_pwKJZnz9:ShX=05RCEth7qX,/[Y*wҽ:-Ry# Գ&-ozaR+I=3OP69ZLoXhGKqgD3i⺟ZjlAQ42((#U]`ikU4Sޞ^$ ߏ]FJYL_9nΙ#/.|L$S 3ɭɓ#&p6p>VnB?T֭mEn%Uc[z&Xy/=/??kF~CRPsTU-v_〝k{$*=]T6:"\1l1|eZ{DzuNZKb4/۞㜡 Rk:JI/ x^ʱٸj ;gk=$2zc.y"P,*l~<䭟 iF-Lм '?kە꠯F318'fCfSƍS^!+iAz޷`0>14X%x箌zldňY,uxA ]|S!'LdZ(1lD8V8y-'w4̕ ~nM^Ef& cǝo+f)"OuKZi!φ{= x~ɦ1NB R.:j |VOmGosF{2\f}$Lؚ6k(R-~ =v=qK{8}L^Wǁ9nq+-?ӡ,}_B֓ lkIvZ)'܋)bJᔻF*ja>Bc-@pL5oNÏމ 8nŚ),k|Z3C2M/MKȯ@ $ X:Uo۸Spy]}T:~(yy>1QOJA+>ȀQ.[H5r˙LQB"2V[lJivpg6<^ϟڏYd7ziگPSo/t1TzI!m_:XCVC;ْ 33!/{$K_D4 _{^>F-Mh[kRΫJ’0Uw+p|E%] ;ܕ0gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.data.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``p( (0 8o$$Eop&p&pT&&^Bh/h/hp?p?c?? nPJPJ wUU~}  PP008hh !!! ! !  ! ! "a $`x%(PK% ]:n&5&5gems/test-unit-3.2.9/PSFLnu[This is the official license for the Python 2.5 release: A. HISTORY OF THE SOFTWARE ========================== Python was created in the early 1990s by Guido van Rossum at Stichting Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands as a successor of a language called ABC. Guido remains Python's principal author, although it includes many contributions from others. In 1995, Guido continued his work on Python at the Corporation for National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) in Reston, Virginia where he released several versions of the software. In May 2000, Guido and the Python core development team moved to BeOpen.com to form the BeOpen PythonLabs team. In October of the same year, the PythonLabs team moved to Digital Creations (now Zope Corporation, see http://www.zope.com). In 2001, the Python Software Foundation (PSF, see http://www.python.org/psf/) was formed, a non-profit organization created specifically to own Python-related Intellectual Property. Zope Corporation is a sponsoring member of the PSF. All Python releases are Open Source (see http://www.opensource.org for the Open Source Definition). Historically, most, but not all, Python releases have also been GPL-compatible; the table below summarizes the various releases. Release Derived Year Owner GPL- from compatible? (1) 0.9.0 thru 1.2 1991-1995 CWI yes 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes 1.6 1.5.2 2000 CNRI no 2.0 1.6 2000 BeOpen.com no 1.6.1 1.6 2001 CNRI yes (2) 2.1 2.0+1.6.1 2001 PSF no 2.0.1 2.0+1.6.1 2001 PSF yes 2.1.1 2.1+2.0.1 2001 PSF yes 2.2 2.1.1 2001 PSF yes 2.1.2 2.1.1 2002 PSF yes 2.1.3 2.1.2 2002 PSF yes 2.2.1 2.2 2002 PSF yes 2.2.2 2.2.1 2002 PSF yes 2.2.3 2.2.2 2003 PSF yes 2.3 2.2.2 2002-2003 PSF yes 2.3.1 2.3 2002-2003 PSF yes 2.3.2 2.3.1 2002-2003 PSF yes 2.3.3 2.3.2 2002-2003 PSF yes 2.3.4 2.3.3 2004 PSF yes 2.3.5 2.3.4 2005 PSF yes 2.4 2.3 2004 PSF yes 2.4.1 2.4 2005 PSF yes 2.4.2 2.4.1 2005 PSF yes 2.4.3 2.4.2 2006 PSF yes 2.5 2.4 2006 PSF yes Footnotes: (1) GPL-compatible doesn't mean that we're distributing Python under the GPL. All Python licenses, unlike the GPL, let you distribute a modified version without making your changes open source. The GPL-compatible licenses make it possible to combine Python with other software that is released under the GPL; the others don't. (2) According to Richard Stallman, 1.6.1 is not GPL-compatible, because its license has a choice of law clause. According to CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 is "not incompatible" with the GPL. Thanks to the many outside volunteers who have worked under Guido's direction to make these releases possible. B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON =============================================================== PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 -------------------------------------------- 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated documentation. 2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee. 3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python. 4. PSF is making Python available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 8. By copying, installing or otherwise using Python, Licensee agrees to be bound by the terms and conditions of this License Agreement. BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 ------------------------------------------- BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the Individual or Organization ("Licensee") accessing and otherwise using this software in source or binary form and its associated documentation ("the Software"). 2. Subject to the terms and conditions of this BeOpen Python License Agreement, BeOpen hereby grants Licensee a non-exclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use the Software alone or in any derivative version, provided, however, that the BeOpen Python License is retained in the Software, alone or in any derivative version prepared by Licensee. 3. BeOpen is making the Software available to Licensee on an "AS IS" basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 5. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 6. This License Agreement shall be governed by and interpreted in all respects by the law of the State of California, excluding conflict of law provisions. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between BeOpen and Licensee. This License Agreement does not grant permission to use BeOpen trademarks or trade names in a trademark sense to endorse or promote products or services of Licensee, or any third party. As an exception, the "BeOpen Python" logos available at http://www.pythonlabs.com/logos.html may be used according to the permissions granted on that web page. 7. By copying, installing or otherwise using the software, Licensee agrees to be bound by the terms and conditions of this License Agreement. CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 --------------------------------------- 1. This LICENSE AGREEMENT is between the Corporation for National Research Initiatives, having an office at 1895 Preston White Drive, Reston, VA 20191 ("CNRI"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 1.6.1 software in source or binary form and its associated documentation. 2. Subject to the terms and conditions of this License Agreement, CNRI hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 1.6.1 alone or in any derivative version, provided, however, that CNRI's License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) 1995-2001 Corporation for National Research Initiatives; All Rights Reserved" are retained in Python 1.6.1 alone or in any derivative version prepared by Licensee. Alternately, in lieu of CNRI's License Agreement, Licensee may substitute the following text (omitting the quotes): "Python 1.6.1 is made available subject to the terms and conditions in CNRI's License Agreement. This Agreement together with Python 1.6.1 may be located on the Internet using the following unique, persistent identifier (known as a handle): 1895.22/1013. This Agreement may also be obtained from a proxy server on the Internet using the following URL: http://hdl.handle.net/1895.22/1013". 3. In the event Licensee prepares a derivative work that is based on or incorporates Python 1.6.1 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 1.6.1. 4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 7. This License Agreement shall be governed by the federal intellectual property law of the United States, including without limitation the federal copyright law, and, to the extent such U.S. federal law does not apply, by the law of the Commonwealth of Virginia, excluding Virginia's conflict of law provisions. Notwithstanding the foregoing, with regard to derivative works based on Python 1.6.1 that incorporate non-separable material that was previously distributed under the GNU General Public License (GPL), the law of the Commonwealth of Virginia shall govern this License Agreement only as to issues arising under or with respect to Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between CNRI and Licensee. This License Agreement does not grant permission to use CNRI trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 8. By clicking on the "ACCEPT" button where indicated, or by copying, installing or otherwise using Python 1.6.1, Licensee agrees to be bound by the terms and conditions of this License Agreement. ACCEPT CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 -------------------------------------------------- Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, The Netherlands. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Stichting Mathematisch Centrum or CWI not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. PK% ]FNFFgems/test-unit-3.2.9/GPLnu[ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. PK% ]~""gems/test-unit-3.2.9/Rakefilenu[# -*- ruby -*- # # Copyright (C) 2008-2017 Kouhei Sutou # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Encoding.default_internal = "UTF-8" if defined?(Encoding.default_internal) # TODO: Remove me when we drop Ruby 1.9 support. unless "".respond_to?(:b) class String def b dup.force_encoding("ASCII-8BIT") end end end require "erb" require "yaml" require "rubygems" require "rake/clean" require "yard" require "bundler/gem_helper" require "packnga" task :default => :test base_dir = File.dirname(__FILE__) html_base_dir = File.join(base_dir, "doc", "html") helper = Bundler::GemHelper.new(base_dir) def helper.version_tag version end helper.install spec = helper.gemspec document_task = Packnga::DocumentTask.new(spec) do |task| task.original_language = "en" task.translate_languages = ["ja"] end Packnga::ReleaseTask.new(spec) do |task| test_unit_github_io_dir_candidates = [ "../../www/test-unit.github.io", ] test_unit_github_io_dir = test_unit_github_io_dir_candidates.find do |dir| File.directory?(dir) end task.index_html_dir = test_unit_github_io_dir end def rake(*arguments) ruby($0, *arguments) end namespace :html do desc "Publish HTML to Web site." task :publish do # FIXME Do nothing for now #rsync_to_rubyforge(spec, "#{html_base_dir}/", "") end end task :test do ruby("test/run-test.rb") end PK% ]s  -gems/test-unit-3.2.9/test/util/test-output.rbnu[require 'test/unit' class TestUnitOutput < Test::Unit::TestCase def test_capture_output assert_equal(["stdout\n", "stderr\n"], capture_output do puts("stdout") warn("stderr") end) end end PK% ]cʪ6gems/test-unit-3.2.9/test/util/test_backtracefilter.rbnu[require 'test/unit' require 'test/unit/util/backtracefilter' module Test::Unit::Util class TestBacktraceFilter < Test::Unit::TestCase include BacktraceFilter def test_filter_backtrace backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'}, %q{tc_thing.rb:4:in 'a'}, %q{tc_thing.rb:4:in 'test_stuff'}, %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'}, %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'}, %q{C:\some\old\path\test\unit.rb:44:in 'run'}, %q{tc_thing.rb:3}] assert_equal(backtrace[1..2], filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines") backtrace = [%q{tc_thing.rb:4:in 'a'}, %q{tc_thing.rb:4:in 'test_stuff'}, %q{tc_thing.rb:3}] assert_equal(backtrace, filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Shouldn't filter too much") backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'}, %q{tc_thing.rb:4:in 'a'}, %q{tc_thing.rb:4:in 'test_stuff'}, %q{tc_thing.rb:3}] assert_equal(backtrace[1..3], filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines") backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'}, %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'}, %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'}, %q{C:\some\old\path\test\unit.rb:44:in 'run'}] assert_equal(backtrace, filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines") end def test_nil_backtrace assert_equal(["No backtrace"], filter_backtrace(nil)) end def test_power_assert_backtrace omit('test for power_assert') unless defined?(PowerAssert) blk = Proc.new {caller.find {|i| /power_assert.*in \`start\'/ =~ i}} PowerAssert.start(blk) do |pa| backtrace = [pa.yield, %q{tc_thing.rb:4:in 'a'}, %q{tc_thing.rb:4:in 'test_stuff'}] assert_equal(backtrace[1..2], filter_backtrace(backtrace)) end end end end PK% ]`+O1gems/test-unit-3.2.9/test/util/test_observable.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit/util/observable' module Test module Unit module Util class TC_Observable < TestCase class TF_Observable include Observable end def setup @observable = TF_Observable.new end def test_simple_observation assert_raises(ArgumentError, "add_listener should throw an exception if no callback is supplied") do @observable.add_listener(:property, "a") end heard = false callback = proc { heard = true } assert_equal("a", @observable.add_listener(:property, "a", &callback), "add_listener should return the listener that was added") count = 0 @observable.instance_eval do count = notify_listeners(:property) end assert_equal(1, count, "notify_listeners should have returned the number of listeners that were notified") assert(heard, "Should have heard the property changed") heard = false assert_equal(callback, @observable.remove_listener(:property, "a"), "remove_listener should return the callback") count = 1 @observable.instance_eval do count = notify_listeners(:property) end assert_equal(0, count, "notify_listeners should have returned the number of listeners that were notified") assert(!heard, "Should not have heard the property change") end def test_value_observation value = nil @observable.add_listener(:property, "a") do |passed_value| value = passed_value end count = 0 @observable.instance_eval do count = notify_listeners(:property, "stuff") end assert_equal(1, count, "Should have update the correct number of listeners") assert_equal("stuff", value, "Should have received the value as an argument to the listener") end def test_multiple_value_observation values = [] @observable.add_listener(:property, "a") do |first_value, second_value| values = [first_value, second_value] end count = 0 @observable.instance_eval do count = notify_listeners(:property, "stuff", "more stuff") end assert_equal(1, count, "Should have update the correct number of listeners") assert_equal(["stuff", "more stuff"], values, "Should have received the value as an argument to the listener") end def test_add_remove_with_default_listener assert_raises(ArgumentError, "add_listener should throw an exception if no callback is supplied") do @observable.add_listener(:property) end heard = false callback = proc { heard = true } assert_equal(callback, @observable.add_listener(:property, &callback), "add_listener should return the listener that was added") count = 0 @observable.instance_eval do count = notify_listeners(:property) end assert_equal(1, count, "notify_listeners should have returned the number of listeners that were notified") assert(heard, "Should have heard the property changed") heard = false assert_equal(callback, @observable.remove_listener(:property, callback), "remove_listener should return the callback") count = 1 @observable.instance_eval do count = notify_listeners(:property) end assert_equal(0, count, "notify_listeners should have returned the number of listeners that were notified") assert(!heard, "Should not have heard the property change") end end end end end PK% ]2gems/test-unit-3.2.9/test/util/test_procwrapper.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit' require 'test/unit/util/procwrapper' module Test module Unit module Util class TC_ProcWrapper < TestCase def munge_proc(&a_proc) return a_proc end def setup @original = proc {} @munged = munge_proc(&@original) @wrapped_original = ProcWrapper.new(@original) @wrapped_munged = ProcWrapper.new(@munged) end def test_wrapping assert_same(@original, @wrapped_original.to_proc, "The wrapper should return what was wrapped") end def test_hashing assert_equal(@wrapped_original.hash, @wrapped_munged.hash, "The original and munged should have the same hash when wrapped") assert_equal(@wrapped_original, @wrapped_munged, "The wrappers should be equivalent") a_hash = {@wrapped_original => @original} assert(a_hash[@wrapped_original], "Should be able to access the wrapper in the hash") assert_equal(a_hash[@wrapped_original], @original, "Should be able to access the wrapper in the hash") end end end end end PK% ]^&1:gems/test-unit-3.2.9/test/util/test-method-owner-finder.rbnu[require 'test/unit' require 'test/unit/util/method-owner-finder' class TestUnitMethodOwnerFinder < Test::Unit::TestCase def test_find assert_equal(Exception, find(RuntimeError.new, :inspect)) assert_equal(Exception, find(Exception.new, :inspect)) anonymous_class = Class.new do end assert_equal(Kernel, find(anonymous_class.new, :inspect)) anonymous_parent_class = Class.new do def inspect super + " by anonymous parent class" end end anonymous_sub_class = Class.new(anonymous_parent_class) do end assert_equal(anonymous_parent_class, find(anonymous_sub_class.new, :inspect)) anonymous_module = Module.new do def inspect super + " by anonymous module" end end anonymous_include_class = Class.new do include anonymous_module end assert_equal(anonymous_module, find(anonymous_include_class.new, :inspect)) end private def find(object, method_name) Test::Unit::Util::MethodOwnerFinder.find(object, method_name) end end PK% ]z}J J -gems/test-unit-3.2.9/test/test-test-result.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit/testcase' require 'test/unit/testresult' module Test module Unit class TC_TestResult < TestCase def setup @my_result = TestResult.new @my_result.add_assertion() @failure = "failure" @my_result.add_failure(@failure) @error = "error" @my_result.add_error(@error) end def test_result_changed_notification called1 = false @my_result.add_listener(TestResult::CHANGED) do |result| assert_equal(@my_result, result) called1 = true end @my_result.add_assertion assert_true(called1) called1, called2 = false, false @my_result.add_listener(TestResult::CHANGED) do |result| assert_equal(@my_result, result) called2 = true end @my_result.add_assertion assert_equal([true, true], [called1, called2]) called1, called2 = false, false @my_result.add_failure("") assert_equal([true, true], [called1, called2]) called1, called2 = false, false @my_result.add_error("") assert_equal([true, true], [called1, called2]) called1, called2 = false, false @my_result.add_run assert_equal([true, true], [called1, called2]) end def test_fault_notification called1 = false fault = "fault" @my_result.add_listener(TestResult::FAULT) do |passed_fault| assert_equal(fault, passed_fault) called1 = true end @my_result.add_assertion assert_false(called1) @my_result.add_failure(fault) assert_true(called1) called1, called2 = false, false @my_result.add_listener(TestResult::FAULT) do |passed_fault| assert_equal(fault, passed_fault) called2 = true end @my_result.add_assertion assert_equal([false, false], [called1, called2]) called1, called2 = false, false @my_result.add_failure(fault) assert_equal([true, true], [called1, called2]) called1, called2 = false, false @my_result.add_error(fault) assert_equal([true, true], [called1, called2]) called1, called2 = false, false @my_result.add_run assert_equal([false, false], [called1, called2]) end def test_passed? result = TestResult.new assert_true(result.passed?) result.add_assertion assert_true(result.passed?) result.add_run assert_true(result.passed?) result.add_failure("") assert_false(result.passed?) result = TestResult.new result.add_error("") assert_false(result.passed?) end def test_faults assert_equal([@failure, @error], @my_result.faults) notification = "notification" @my_result.add_notification(notification) assert_equal([@failure, @error, notification], @my_result.faults) end end end end PK% ]( DD-gems/test-unit-3.2.9/test/fixtures/header.tsvnu[label expected target empty string true "" plain string false hello PK% ]DD-gems/test-unit-3.2.9/test/fixtures/header.csvnu[label,expected,target empty string,true,"" plain string,false,hello PK% ]cm..0gems/test-unit-3.2.9/test/fixtures/no-header.csvnu[empty string,true,"" plain string,false,hello PK% ]? "..0gems/test-unit-3.2.9/test/fixtures/no-header.tsvnu[empty string true "" plain string false hello PK% ]_CC3gems/test-unit-3.2.9/test/fixtures/header-label.csvnu[label,expected,label upper case,HELLO,HELLO lower case,Hello,hello PK% ]*CC3gems/test-unit-3.2.9/test/fixtures/header-label.tsvnu[label expected label upper case HELLO HELLO lower case Hello hello PK% ]:bOO+gems/test-unit-3.2.9/test/fixtures/plus.csvnu[label,expected,augend,addend positive positive,4,3,1 positive negative,-1,1,-2 PK% ]D.gems/test-unit-3.2.9/test/test-notification.rbnu[require 'test/unit' require 'testunit-test-util' class TestUnitNotification < Test::Unit::TestCase include TestUnitTestUtil class TestCase < Test::Unit::TestCase class << self def suite Test::Unit::TestSuite.new(name) end end def test_notify notify("1st notify") notify("2nd notify. Reach here.") end end def test_notify result = _run_test("test_notify") assert_equal("1 tests, 0 assertions, 0 failures, 0 errors, 0 pendings, " \ "0 omissions, 2 notifications", result.to_s) assert_fault_messages(["1st notify", "2nd notify. Reach here."], result.notifications) end private def _run_test(name) super(TestCase, name) end end PK% ]3W *gems/test-unit-3.2.9/test/test-priority.rbnu[require 'test/unit' class TestUnitPriority < Test::Unit::TestCase class TestCase < Test::Unit::TestCase class << self def suite Test::Unit::TestSuite.new(name) end end priority :must def test_must assert(true) end def test_must_inherited assert(true) end priority :important def test_important assert(true) end def test_important_inherited assert(true) end priority :high def test_high assert(true) end def test_high_inherited assert(true) end priority :normal def test_normal assert(true) end def test_normal_inherited assert(true) end priority :low def test_low assert(true) end def test_low_inherited assert(true) end priority :never def test_never assert(true) end def test_never_inherited assert(true) end end def test_priority_must assert_priority("must", 1.0, 0.0001) end def test_priority_important assert_priority("important", 0.9, 0.09) end def test_priority_high assert_priority("high", 0.70, 0.1) end def test_priority_normal assert_priority("normal", 0.5, 0.1) end def test_priority_low assert_priority("low", 0.25, 0.1) end def test_priority_never assert_priority("never", 0.0, 0.0001) end def assert_priority(priority, expected, delta) assert_need_to_run("test_#{priority}", expected, delta) assert_need_to_run("test_#{priority}_inherited", expected, delta) end def assert_need_to_run(test_name, expected, delta) test = TestCase.new(test_name) n = 1000 n_need_to_run = 0 n.times do |i| n_need_to_run += 1 if Test::Unit::Priority::Checker.need_to_run?(test) end assert_in_delta(expected, n_need_to_run.to_f / n, delta) end class TestClassName < self def test_colon assert_escaped_name("Test__Priority", "Test::Priority") end def test_space assert_escaped_name("test_priority", "test priority") end def test_slash assert_escaped_name("test_priority", "test/priority") end def test_back_slash assert_escaped_name("test_priority", "test\/priority") end def assert_escaped_name(expected, class_name) checker = Checker.new(nil) escaped_class_name = checker.send(:escape_class_name, class_name) assert_equal(expected, escaped_class_name) end end class TestFileName < self class SpecialNameTestCase < Test::Unit::TestCase class << self def suite Test::Unit::TestSuite.new(name) end end def test_question? end def test_exclamation! end def test_equal= end test "have space" do end end def test_question assert_escaped_name("test_question.predicate", "test_question?") end def test_exclamation assert_escaped_name("test_exclamation.destructive", "test_exclamation!") end def test_equal assert_escaped_name("test_equal.equal", "test_equal=") end def test_colon_and_space assert_escaped_name("test_colon__have_space", "test: have space") end def assert_escaped_name(expected, test_method_name) checker = Checker.new(SpecialNameTestCase.new(test_method_name)) passed_file = checker.send(:passed_file) method_name_component = File.basename(File.dirname(passed_file)) assert_equal(expected, method_name_component) end end end PK% ]52'gems/test-unit-3.2.9/test/test-error.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit' module Test module Unit class TC_Error < TestCase TF_Exception = Struct.new('TF_Exception', :message, :backtrace) def test_display ex = TF_Exception.new("message1\nmessage2", ['line1', 'line2']) e = Error.new("name", ex) assert_equal("name: #{TF_Exception.name}: message1", e.short_display) assert_equal(< :accessor}, test_for_accessor_category.attributes) test_for_bug_1234 = TestStack.new("test_bug_1234") assert_equal({"bug" => 1234}, test_for_bug_1234.attributes) test_no_attributes = TestStack.new("test_no_attributes") assert_equal({}, test_no_attributes.attributes) end def test_callback changed_attributes = [] observer = Proc.new do |test_case, key, old_value, value, method_name| changed_attributes << [test_case, key, old_value, value, method_name] end test_case = Class.new(TestStack) do register_attribute_observer(:bug, &observer) attribute("bug", 9876, "test_bug_1234") attribute(:description, "Test for peek", "test_peek") attribute(:bug, 29, "test_peek") end assert_equal([ [test_case, "bug", 1234, 9876, "test_bug_1234"], [test_case, "bug", nil, 29, "test_peek"], ], changed_attributes) end def test_attributes_with_prepended_module omit("Module#prepend is needed") unless Module.respond_to?(:prepend, true) test_case = Class.new(TestStack) do prepend Module.new end assert_equal({ "category" => :accessor, }, test_case.attributes("test_peek")) end class TestDescription < self def test_decoration_style test_case = Class.new(TestStack) do description "Test for push" def test_push end end test_push = test_case.new("test_push") assert_equal({"description" => "Test for push"}, test_push.attributes) end def test_explicit_test_name_style test_case = Class.new(TestStack) do def test_push end description "Test for push", :test_push end test_push = test_case.new("test_push") assert_equal({"description" => "Test for push"}, test_push.attributes) end end end PK% ]d)gems/test-unit-3.2.9/test/test-pending.rbnu[require 'test/unit' require 'testunit-test-util' class TestUnitPending < Test::Unit::TestCase include TestUnitTestUtil class TestCase < Test::Unit::TestCase class << self def suite Test::Unit::TestSuite.new(name) end end def test_pend pend("1st pend") pend("2nd pend. Should not be reached here.") assert(true, "Should not be reached here too.") end def test_pend_with_failure_in_block pend("Wait a minute") do raise "Not implemented yet" end assert(true, "Reached here.") end def test_pend_with_no_failure_in_block pend("Wait a minute") do "Nothing raised" end assert(true, "Not reached here.") end end def test_pend test = nil result = _run_test("test_pend") {|t| test = t} assert_equal("1 tests, 0 assertions, 0 failures, 0 errors, 1 pendings, " \ "0 omissions, 0 notifications", result.to_s) assert_fault_messages(["1st pend"], result.pendings) assert_true(test.interrupted?) end def test_pend_with_failure_in_block test = nil result = _run_test("test_pend_with_failure_in_block") {|t| test = t} assert_equal("1 tests, 1 assertions, 0 failures, 0 errors, 1 pendings, " \ "0 omissions, 0 notifications", result.to_s) assert_fault_messages(["Wait a minute"], result.pendings) assert_false(test.interrupted?) end def test_pend_with_no_failure_in_block test = nil result = _run_test("test_pend_with_no_failure_in_block") {|t| test = t} assert_equal("1 tests, 1 assertions, 1 failures, 0 errors, 0 pendings, " \ "0 omissions, 0 notifications", result.to_s) assert_fault_messages(["Pending block should not be passed: Wait a minute."], result.failures) assert_true(test.interrupted?) end private def _run_test(name, &block) super(TestCase, name, &block) end end PK% ]ad  4gems/test-unit-3.2.9/test/test-test-suite-creator.rbnu[require "test/unit" module Test module Unit class TestTestSuiteCreator < TestCase def collect_test_names(test_case) creator = TestSuiteCreator.new(test_case) creator.send(:collect_test_names) end class TestStandalone < self def setup @test_case = Class.new(TestCase) do def test_in_test_case end end end def test_collect_test_names assert_equal(["test_in_test_case"], collect_test_names(@test_case)) end end class TestInherited < self def setup @parent_test_case = Class.new(TestCase) do def test_in_parent end end @child_test_case = Class.new(@parent_test_case) do def test_in_child end end end def test_collect_test_names assert_equal(["test_in_child"], collect_test_names(@child_test_case)) end end class TestModule < self def setup test_module = Module.new do def test_in_module end end @test_case = Class.new(TestCase) do include test_module def test_in_test_case end end end def test_collect_test_names assert_equal(["test_in_module", "test_in_test_case"].sort, collect_test_names(@test_case).sort) end end class TestInheritedModule < self def setup parent_test_module = Module.new do def test_in_module_in_parent end end child_test_module = Module.new do def test_in_module_in_child end end @parent_test_case = Class.new(TestCase) do include parent_test_module def test_in_parent end end @child_test_case = Class.new(@parent_test_case) do include child_test_module def test_in_child end end end def test_collect_test_names assert_equal(["test_in_child", "test_in_module_in_child"].sort, collect_test_names(@child_test_case).sort) end end end end end PK% ]sEv v .gems/test-unit-3.2.9/test/test-color-scheme.rbnu[class TestUnitColorScheme < Test::Unit::TestCase def test_register inverted_scheme_spec = { "success" => {:name => "red"}, "failure" => {:name => "green"}, } Test::Unit::ColorScheme["inverted"] = inverted_scheme_spec assert_equal({ "success" => color("red"), "failure" => color("green"), }, Test::Unit::ColorScheme["inverted"].to_hash) end def test_new_with_colors scheme = Test::Unit::ColorScheme.new(:success => color("blue"), "failure" => color("green", :underline => true)) assert_equal({ "success" => color("blue"), "failure" => color("green", :underline => true), }, scheme.to_hash) end def test_new_with_spec scheme = Test::Unit::ColorScheme.new(:success => { :name => "blue", :bold => true }, "failure" => {:name => "green"}) assert_equal({ "success" => color("blue", :bold => true), "failure" => color("green"), }, scheme.to_hash) end private def color(name, options={}) Test::Unit::Color.new(name, options) end class TestFor8Colors < self def setup @original_term, ENV["TERM"] = ENV["TERM"], nil @original_color_term, ENV["COLORTERM"] = ENV["COLORTERM"], nil ENV["TERM"] = "xterm" end def teardown ENV["TERM"] = @original_term ENV["COLORTERM"] = @original_color_term end def test_default expected_schema_keys = [ "pass", "pass-marker", "failure", "failure-marker", "pending", "pending-marker", "omission", "omission-marker", "notification", "notification-marker", "error", "error-marker", "case", "suite", "diff-inserted-tag", "diff-deleted-tag", "diff-difference-tag", "diff-inserted", "diff-deleted", ] assert_equal(expected_schema_keys.sort, Test::Unit::ColorScheme.default.to_hash.keys.sort) end end end PK% ]7C6gems/test-unit-3.2.9/test/collector/test-descendant.rbnu[require 'test/unit' require 'test/unit/collector/descendant' class TestUnitCollectorDescendant < Test::Unit::TestCase def setup @previous_descendants = Test::Unit::TestCase::DESCENDANTS.dup Test::Unit::TestCase::DESCENDANTS.clear end def teardown Test::Unit::TestCase::DESCENDANTS.replace(@previous_descendants) end private def assert_collect(expected, *collect_args) collector = Test::Unit::Collector::Descendant.new yield(collector) if block_given? assert_equal(expected, collector.send(:collect, *collect_args)) end def default_name Test::Unit::Collector::Descendant::NAME end def empty_suite(name=nil) Test::Unit::TestSuite.new(name || default_name) end class TestCollect < self def setup super @test_case1 = Class.new(Test::Unit::TestCase) do self.test_order = :alphabetic def self.name "test-case1" end def test_1 end def test_2 end end @test_case2 = Class.new(Test::Unit::TestCase) do self.test_order = :alphabetic def self.name "test-case2" end def test_0 end end @no_test_case = Class.new do def self.name "no-test-case" end def test_4 end end end def test_basic assert_collect(full_suite("name"), "name") assert_collect(full_suite("name"), "name") do |collector| collector.filter = [] end end def test_filtered assert_collect(empty_suite) do |collector| collector.filter = Proc.new {false} end assert_collect(full_suite) do |collector| collector.filter = Proc.new {true} end assert_collect(full_suite) do |collector| collector.filter = Proc.new {nil} end assert_collect(empty_suite) do |collector| collector.filter = [Proc.new {false}, Proc.new {true}] end assert_collect(empty_suite) do |collector| collector.filter = [Proc.new {true}, Proc.new {false}] end assert_collect(empty_suite) do |collector| collector.filter = [Proc.new {nil}, Proc.new {false}] end assert_collect(full_suite) do |collector| collector.filter = [Proc.new {nil}, Proc.new {true}] end expected = empty_suite suite1 = Test::Unit::TestSuite.new(@test_case1.name) suite1 << @test_case1.new("test_1") suite2 = Test::Unit::TestSuite.new(@test_case2.name) suite2 << @test_case2.new("test_0") expected << suite1 << suite2 assert_collect(expected) do |collector| collector.filter = Proc.new do |test| ['test_1', 'test_0'].include?(test.method_name) end end suite1 = Test::Unit::TestSuite.new(@test_case1.name) suite1 << @test_case1.new("test_1") suite2 = Test::Unit::TestSuite.new(@test_case2.name) suite2 << @test_case2.new("test_0") assert_collect(empty_suite) do |collector| filters = [Proc.new {|test| test.method_name == 'test_1' ? true : nil}, Proc.new {|test| test.method_name == 'test_0' ? true : nil}, Proc.new {false}] collector.filter = filters end end private def full_suite(name=nil) sub_suite1 = Test::Unit::TestSuite.new(@test_case1.name) sub_suite1 << @test_case1.new('test_1') sub_suite1 << @test_case1.new('test_2') sub_suite2 = Test::Unit::TestSuite.new(@test_case2.name) sub_suite2 << @test_case2.new('test_0') suite = empty_suite(name) suite << sub_suite1 suite << sub_suite2 suite end end class TestModule < self def test_included_in_child tests = Module.new do def test_in_module end end parent_test_case = Class.new(Test::Unit::TestCase) do class << self def name "Parent" end end end child_test_case = Class.new(parent_test_case) do include tests class << self def name "Child" end end end child_suite = Test::Unit::TestSuite.new(child_test_case.name) child_suite << child_test_case.new("test_in_module") parent_suite = Test::Unit::TestSuite.new(parent_test_case.name) parent_suite << child_suite suite = empty_suite("all") suite << parent_suite assert_collect(suite, "all") end end end PK% ]+ߪ110gems/test-unit-3.2.9/test/collector/test-load.rbnu[require 'tmpdir' require 'pathname' require 'test/unit' require 'test/unit/collector/load' class TestUnitCollectorLoad < Test::Unit::TestCase def setup @previous_descendants = Test::Unit::TestCase::DESCENDANTS.dup Test::Unit::TestCase::DESCENDANTS.clear @temporary_test_cases_module_name = "TempTestCases" ::Object.const_set(@temporary_test_cases_module_name, Module.new) @test_dir = Pathname(Dir.tmpdir) + "test-unit" @extra_test_dir = Pathname(Dir.tmpdir) + "test-unit-extra" ensure_clean_directory(@test_dir) ensure_clean_directory(@extra_test_dir) end setup def setup_top_level_test_cases @test_case1 = @test_dir + "test_case1.rb" @test_case2 = @test_dir + "test_case2.rb" @no_load_test_case3 = @test_dir + "case3.rb" @test_case1.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class TestCase1 < Test::Unit::TestCase def test1_1 end def test1_2 end end end EOT end @test_case2.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class TestCase2 < Test::Unit::TestCase def test2 end end end EOT end @no_load_test_case3.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class NoLoadTestCase3 < Test::Unit::TestCase def test3 end end end EOT end end setup def setup_sub_level_test_cases @sub_test_dir = @test_dir + "sub" @sub_test_dir.mkpath @sub_test_case4 = @sub_test_dir + "test_case4.rb" @no_load_sub_test_case5 = @sub_test_dir + "case5.rb" @sub_test_case6 = @sub_test_dir + "test_case6.rb" @sub_test_case4.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class SubTestCase4 < Test::Unit::TestCase def test4_1 end def test4_2 end end end EOT end @no_load_sub_test_case5.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class NoLoadSubTestCase5 < Test::Unit::TestCase def test5_1 end def test5_2 end end end EOT end @sub_test_case6.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class SubTestCase6 < Test::Unit::TestCase def test6 end end end EOT end end setup def setup_sub_level_test_cases2 @sub2_test_dir = @test_dir + "sub2" @sub2_test_dir.mkpath @no_load_sub2_test_case7 = @sub2_test_dir + "case7.rb" @sub2_test_case8 = @sub2_test_dir + "test_case8.rb" @sub2_test_case9 = @sub2_test_dir + "test_case9.rb" @no_load_sub2_test_case7.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class NoLoadSub2TestCase7 < Test::Unit::TestCase def test7_1 end def test7_2 end end end EOT end @sub2_test_case8.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class Sub2TestCase8 < Test::Unit::TestCase def test8_1 end def test8_2 end end end EOT end @sub2_test_case9.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class Sub2TestCase9 < Test::Unit::TestCase def test9 end end end EOT end end setup def setup_svn_test_cases @svn_test_dir = @test_dir + ".svn" @svn_test_dir.mkpath @svn_test_case10 = @svn_test_dir + "test_case10.rb" @svn_test_case10.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class SvnTestCase10 < Test::Unit::TestCase def test7 end end end EOT end end setup def setup_sub_cvs_test_cases @sub_cvs_test_dir = @sub_test_dir + "CVS" @sub_cvs_test_dir.mkpath @sub_cvs_test_case11 = @sub_cvs_test_dir + "test_case11.rb" @sub_cvs_test_case11.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class SubCVSTestCase11 < Test::Unit::TestCase def test11 end end end EOT end end setup def setup_sub_git_test_cases @sub_git_test_dir = @sub_test_dir + ".git" @sub_git_test_dir.mkpath @sub_git_test_case11 = @sub_git_test_dir + "test_case11.rb" @sub_git_test_case11.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class SubGitTestCase11 < Test::Unit::TestCase def test11 end end end EOT end end setup def setup_extra_top_level_test_cases @test_cases12 = @extra_test_dir + "test_cases12.rb" @test_cases12.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class TestCase121 < Test::Unit::TestCase def test121_1 end def test121_2 end end class TestCase122 < Test::Unit::TestCase def test122_1 end def test122_2 end end end EOT end end setup def setup_sub_level_extra_test_cases @sub_extra_test_dir = @extra_test_dir + "sub" @sub_extra_test_dir.mkpath @cases13_test = @sub_extra_test_dir + "13cases_test.rb" @cases13_test.open("w") do |test_case| test_case.puts(<<-EOT) module #{@temporary_test_cases_module_name} class SubTestCase13 < Test::Unit::TestCase def test13_1 end def test13_2 end end end EOT end end def teardown @test_dir.rmtree if @test_dir.exist? ::Object.send(:remove_const, @temporary_test_cases_module_name) Test::Unit::TestCase::DESCENDANTS.replace(@previous_descendants) end def test_simple_collect assert_collect([:suite, {:name => @sub_test_dir.basename.to_s}, [:suite, {:name => _test_case_name("SubTestCase4")}, [:test, {:name => "test4_1"}], [:test, {:name => "test4_2"}]], [:suite, {:name => _test_case_name("SubTestCase6")}, [:test, {:name => "test6"}]]], @sub_test_dir.to_s) end def test_simple_collect_test_suffix assert_collect([:suite, {:name => @extra_test_dir.basename.to_s}, [:suite, {:name => _test_case_name("TestCase121")}, [:test, {:name => "test121_1"}], [:test, {:name => "test121_2"}]], [:suite, {:name => _test_case_name("TestCase122")}, [:test, {:name => "test122_1"}], [:test, {:name => "test122_2"}]], [:suite, {:name => @sub_extra_test_dir.basename.to_s}, [:suite, {:name => _test_case_name("SubTestCase13")}, [:test, {:name => "test13_1"}], [:test, {:name => "test13_2"}]]]], @extra_test_dir.to_s) end def test_multilevel_collect assert_collect([:suite, {:name => "."}, [:suite, {:name => _test_case_name("TestCase1")}, [:test, {:name => "test1_1"}], [:test, {:name => "test1_2"}]], [:suite, {:name => _test_case_name("TestCase2")}, [:test, {:name => "test2"}]], [:suite, {:name => @sub_test_dir.basename.to_s}, [:suite, {:name => _test_case_name("SubTestCase4")}, [:test, {:name => "test4_1"}], [:test, {:name => "test4_2"}]], [:suite, {:name => _test_case_name("SubTestCase6")}, [:test, {:name => "test6"}]]], [:suite, {:name => @sub2_test_dir.basename.to_s}, [:suite, {:name => _test_case_name("Sub2TestCase8")}, [:test, {:name => "test8_1"}], [:test, {:name => "test8_2"}]], [:suite, {:name => _test_case_name("Sub2TestCase9")}, [:test, {:name => "test9"}]]]]) end def test_collect_file assert_collect([:suite, {:name => _test_case_name("TestCase1")}, [:test, {:name => "test1_1"}], [:test, {:name => "test1_2"}]], @test_case1.to_s) end def test_collect_file_no_pattern_match_file_name assert_collect([:suite, {:name => _test_case_name("NoLoadSubTestCase5")}, [:test, {:name => "test5_1"}], [:test, {:name => "test5_2"}]], @no_load_sub_test_case5.to_s) end def test_collect_file_test_cases assert_collect([:suite, {:name => "[#{@test_cases12}]"}, [:suite, {:name => _test_case_name("TestCase121")}, [:test, {:name => "test121_1"}], [:test, {:name => "test121_2"}]], [:suite, {:name => _test_case_name("TestCase122")}, [:test, {:name => "test122_1"}], [:test, {:name => "test122_2"}]]], @test_cases12.to_s) end def test_collect_files assert_collect([:suite, {:name => "[#{@test_case1}, #{@test_case2}]"}, [:suite, {:name => _test_case_name("TestCase1")}, [:test, {:name => "test1_1"}], [:test, {:name => "test1_2"}]], [:suite, {:name => _test_case_name("TestCase2")}, [:test, {:name => "test2"}]]], @test_case1.to_s, @test_case2.to_s) end def test_nil_pattern assert_collect([:suite, {:name => @sub_test_dir.basename.to_s}, [:suite, {:name => _test_case_name("NoLoadSubTestCase5")}, [:test, {:name => "test5_1"}], [:test, {:name => "test5_2"}]], [:suite, {:name => _test_case_name("SubTestCase4")}, [:test, {:name => "test4_1"}], [:test, {:name => "test4_2"}]], [:suite, {:name => _test_case_name("SubTestCase6")}, [:test, {:name => "test6"}]]], @sub_test_dir.to_s) do |collector| collector.patterns.clear end end def test_filtering assert_collect([:suite, {:name => "."}, [:suite, {:name => _test_case_name("TestCase1")}, [:test, {:name => "test1_1"}], [:test, {:name => "test1_2"}]]]) do |collector| collector.filter = Proc.new do |test| !/\Atest1/.match(test.method_name).nil? end end end def test_collect_multi test_dirs = [@sub_test_dir.to_s, @sub2_test_dir.to_s] assert_collect([:suite, {:name => "[#{test_dirs.join(', ')}]"}, [:suite, {:name => @sub_test_dir.basename.to_s}, [:suite, {:name => _test_case_name("SubTestCase4")}, [:test, {:name => "test4_1"}], [:test, {:name => "test4_2"}]], [:suite, {:name => _test_case_name("SubTestCase6")}, [:test, {:name => "test6"}]]], [:suite, {:name => @sub2_test_dir.basename.to_s}, [:suite, {:name => _test_case_name("Sub2TestCase8")}, [:test, {:name => "test8_1"}], [:test, {:name => "test8_2"}]], [:suite, {:name => _test_case_name("Sub2TestCase9")}, [:test, {:name => "test9"}]]]], *test_dirs) end private def assert_collect(expected, *collect_args) keep_required_files do Dir.chdir(@test_dir.to_s) do collector = Test::Unit::Collector::Load.new yield(collector) if block_given? actual = inspect_test_object(collector.send(:collect, *collect_args)) assert_equal(expected, actual) end end end def ensure_clean_directory(directory) directory.rmtree if directory.exist? directory.mkpath end def keep_required_files required_files = $".dup yield ensure $".replace(required_files) end def _test_case_name(test_case_class_name) "#{@temporary_test_cases_module_name}::#{test_case_class_name}" end def inspect_test_object(test_object) return nil if test_object.nil? case test_object when Test::Unit::TestSuite sub_tests = test_object.tests.collect do |test| inspect_test_object(test) end.sort_by do |type, attributes, *children| attributes[:name] end [:suite, {:name => test_object.name}, *sub_tests] when Test::Unit::TestCase [:test, {:name => test_object.method_name}] else raise "unexpected test object: #{test_object.inspect}" end end end PK% ])**/gems/test-unit-3.2.9/test/collector/test_dir.rbnu[require 'test/unit' require 'test/unit/collector/dir' require 'pp' module Test module Unit module Collector class TestDir < TestCase class FileSystem class Directory def initialize(name, fs, parent=self, &block) @name = name @fs = fs @parent = parent @contents = {'.' => self, '..' => parent} instance_eval(&block) if(block) end def file(name, contents) @contents[name] = contents end def dir(name, &block) @contents[name] = self.class.new(name, @fs, self, &block) end def entries @contents.keys end def directory?(name) return true if(name.nil? || name.empty?) return false unless(@contents.include?(name)) @contents[name].kind_of?(self.class) end def file?(name) return false unless(@contents.include?(name)) !directory?(name) end def exist?(name) @contents.include?(name) end def [](name) raise Errno::ENOENT, name unless(@contents.include?(name)) @contents[name] end def path_to(name=nil) if(!name) @parent.path_to(@name) elsif(@parent == self) @fs.join('/', name) else @fs.join(@parent.path_to(@name), name) end end end class ObjectSpace def initialize @objects = [] end def each_object(klass, &block) @objects.find_all{|o| o.kind_of?(klass)}.each(&block) end def <<(object) @objects << object end end attr_reader :object_space def initialize(&block) @root = Directory.new('/', self, &block) @pwd = @root @object_space = ObjectSpace.new @required = [] end def entries(dir) e = find(dir) require_directory(dir) e.entries end def directory?(name) return true if (base = basename(name)) == '/' e = find(dirname(name)) return false unless(e) e.directory?(base) end def find(path) if(/\A\// =~ path) thing = @root else thing = @pwd end path.scan(/[^\/]+/) do |e| break thing = false unless(thing.kind_of?(Directory)) thing = thing[e] end thing end def dirname(name) if (name = name.tr_s('/', '/')) == '/' name else name[%r"\A.+(?=/[^/]+/?\z)|\A/"] || "." end end def basename(name) name[%r"(\A/|[^/]+)/*\z", 1] end def split(name) [dirname(name), basename(name)] end def join(*parts) parts.join('/').gsub(%r{/+}, '/') end def file?(name) e = find(dirname(name)) return false unless(e) e.file?(basename(name)) end def pwd @pwd.path_to end def chdir(to) e = find(to) require_directory(to) @pwd = e end def expand_path(path, base = nil) until /\A\// =~ path base ||= pwd path = join(base, path) base = nil end path.gsub!(%r"(?:/\.)+(?=/)", '') nil while path.sub!(%r"/(?!\.\./)[^/]+/\.\.(?=/)", '') path.sub!(%r"\A(?:/\.\.)+(?=/)", '') path.sub!(%r"(?:\A(/)|/)\.\.?\z", '\1') path end def require_directory(path) raise Errno::ENOTDIR, path unless(directory?(path)) end def require(file) return false if(@required.include?(file)) begin e = find(file) rescue Errno::ENOENT => e if(/\.rb\Z/ =~ file) raise LoadError, file end e = find(file + '.rb') end @required << file @object_space << e true rescue Errno::ENOENT raise LoadError, file end end def test_dir inner_dir = nil dirs = FileSystem::Directory.new('/', nil) do file 'a', nil inner_dir = dir 'b' end assert_equal(inner_dir, dirs['b']) end def test_fs fs = FileSystem.new do file 'a', nil dir 'b' end assert_equal(['.', '..', 'a', 'b'].sort, fs.entries('/').sort) assert(fs.directory?('/')) assert(!fs.directory?('/a')) assert(!fs.directory?('/bogus')) assert(fs.file?('/a')) assert(!fs.file?('/')) assert(!fs.file?('/bogus')) assert(fs.directory?('/b')) assert(fs.file?('a')) assert(fs.directory?('b')) end def test_fs_sub fs = FileSystem.new do dir 'a' do file 'b', nil dir 'c' do file 'd', nil end end end assert(fs.file?('/a/b')) assert(!fs.file?('/a/b/c/d')) assert(fs.file?('/a/c/d')) end def test_fs_pwd fs = FileSystem.new do file 'a', nil dir 'b' do file 'c', nil dir 'd' do file 'e', nil end end end assert_equal('/', fs.pwd) assert_raises(Errno::ENOENT) do fs.chdir('bogus') end assert_raises(Errno::ENOTDIR) do fs.chdir('a') end fs.chdir('b') assert_equal('/b', fs.pwd) fs.chdir('d') assert_equal('/b/d', fs.pwd) fs.chdir('..') assert_equal('/b', fs.pwd) fs.chdir('..') assert_equal('/', fs.pwd) end def test_fs_entries fs = FileSystem.new do file 'a', nil dir 'b' do file 'c', nil file 'd', nil end file 'e', nil dir 'f' do file 'g', nil dir 'h' do file 'i', nil end end end assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('/').sort) assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('.').sort) assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('b/..').sort) assert_equal(['.', '..', 'c', 'd'], fs.entries('b').sort) assert_raises(Errno::ENOENT) do fs.entries('z') end assert_raises(Errno::ENOTDIR) do fs.entries('a') end fs.chdir('f') assert_equal(['.', '..', 'i'], fs.entries('h').sort) end class TestClass1 end class TestClass2 end def test_fs_require fs = FileSystem.new do file 'test_class1.rb', TestClass1 dir 'dir' do file 'test_class2.rb', TestClass2 end end c = [] fs.object_space.each_object(Class) do |o| c << o end assert_equal([], c) assert_raises(LoadError) do fs.require('bogus') end assert(fs.require('test_class1.rb')) assert(!fs.require('test_class1.rb')) c = [] fs.object_space.each_object(Class) do |o| c << o end assert_equal([TestClass1], c) fs.require('dir/test_class2') c = [] fs.object_space.each_object(Class) do |o| c << o end assert_equal([TestClass1, TestClass2], c) c = [] fs.object_space.each_object(Time) do |o| c << o end assert_equal([], c) end def setup @t1 = t1 = create_test(1) @t2 = t2 = create_test(2) @t3 = t3 = create_test(3) @t4 = t4 = create_test(4) @t5 = t5 = create_test(5) @t6 = t6 = create_test(6) fs = FileSystem.new do file 'test_1.rb', t1 file 'test_2.rb', t2 dir 'd1' do file 'test_3.rb', t3 end file 't4.rb', t4 dir 'd2' do file 'test_5', t5 file 'test_6.rb', Time end file 't6.rb', t6 end fs.require('t6') @c = Dir.new(fs, fs, fs.object_space, fs) end def create_test(name) t = Class.new(TestCase) t.class_eval <<-EOC self.test_order = :alphabetic def self.name "T\#{#{name}}" end def test_#{name}a end def test_#{name}b end EOC t end def test_simple_collect expected = TestSuite.new('d1') expected << (@t3.suite) assert_equal(expected, @c.collect('d1')) end def test_multilevel_collect expected = TestSuite.new('.') expected << @t1.suite << @t2.suite expected << (TestSuite.new('d1') << @t3.suite) assert_equal(expected, @c.collect) end def test_collect_file expected = TestSuite.new('test_1.rb') expected << @t1.suite assert_equal(expected, @c.collect('test_1.rb')) expected = TestSuite.new('t4.rb') expected << @t4.suite assert_equal(expected, @c.collect('t4.rb')) end def test_nil_pattern expected = TestSuite.new('d2') expected << @t5.suite @c.pattern.clear assert_equal(expected, @c.collect('d2')) end def test_filtering expected = TestSuite.new('.') expected << @t1.suite @c.filter = proc{|t| t.method_name == 'test_1a' || t.method_name == 'test_1b'} assert_equal(expected, @c.collect) end def test_collect_multi expected = TestSuite.new('[d1, d2]') expected << (TestSuite.new('d1') << @t3.suite) expected << (TestSuite.new('d2') << @t5.suite) @c.pattern.replace([/\btest_/]) assert_equal(expected, @c.collect('d1', 'd2')) end end end end end PK% ]2\ 7gems/test-unit-3.2.9/test/collector/test_objectspace.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit' require 'test/unit/collector/objectspace' module Test module Unit module Collector class TC_ObjectSpace < TestCase def setup @tc1 = Class.new(TestCase) do self.test_order = :alphabetic def self.name "tc_1" end def test_1 end def test_2 end end @tc2 = Class.new(TestCase) do self.test_order = :alphabetic def self.name "tc_2" end def test_0 end end @no_tc = Class.new do def test_4 end end @object_space = {Class => [@tc1, @tc2, @no_tc], String => ['']} def @object_space.each_object(type) self[type].each{|item| yield(item) } end @c = ObjectSpace.new(@object_space) end def full_suite(name=ObjectSpace::NAME) expected = TestSuite.new(name) expected << (TestSuite.new(@tc1.name) << @tc1.new('test_1') << @tc1.new('test_2')) expected << (TestSuite.new(@tc2.name) << @tc2.new('test_0')) end def empty_suite TestSuite.new(ObjectSpace::NAME) end def test_basic_collection assert_equal(full_suite("name"), @c.collect("name")) @c.filter = [] assert_equal(full_suite("name"), @c.collect("name")) end def test_filtered_collection @c.filter = proc{false} assert_equal(empty_suite, @c.collect) @c.filter = proc{true} assert_equal(full_suite, @c.collect) @c.filter = proc{nil} assert_equal(full_suite, @c.collect) @c.filter = [proc{false}, proc{true}] assert_equal(empty_suite, @c.collect) @c.filter = [proc{true}, proc{false}] assert_equal(empty_suite, @c.collect) @c.filter = [proc{nil}, proc{false}] assert_equal(empty_suite, @c.collect) @c.filter = [proc{nil}, proc{true}] assert_equal(full_suite, @c.collect) expected = TestSuite.new(ObjectSpace::NAME) expected << (TestSuite.new(@tc1.name) << @tc1.new('test_1')) expected << (TestSuite.new(@tc2.name) << @tc2.new('test_0')) @c.filter = proc{|test| ['test_1', 'test_0'].include?(test.method_name)} assert_equal(expected, @c.collect) expected = TestSuite.new(ObjectSpace::NAME) TestSuite.new(@tc1.name) << @tc1.new('test_1') TestSuite.new(@tc2.name) << @tc2.new('test_0') @c.filter = [proc{|t| t.method_name == 'test_1' ? true : nil}, proc{|t| t.method_name == 'test_0' ? true : nil}, proc{false}] assert_equal(empty_suite, @c.collect) end end end end end PK% ]ӪU,gems/test-unit-3.2.9/test/test-test-suite.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit' module Test module Unit class TestTestSuite < TestCase def setup @testcase1 = Class.new(TestCase) do def test_succeed1 assert_block { true } end def test_fail assert_block { false } end end @testcase2 = Class.new(TestCase) do def test_succeed2 assert_block { true } end def test_error raise end end end def test_add s = TestSuite.new assert_equal(s, s << self.class.new("test_add")) end def test_delete s = TestSuite.new t1 = self.class.new("test_delete") s << t1 t2 = self.class.new("test_add") s << t2 assert_equal(t1, s.delete(t1)) assert_nil(s.delete(t1)) assert_equal(TestSuite.new << t2, s) end def test_delete_tests suite = TestSuite.new test1 = self.class.new("test_delete_1") suite << test1 test2 = self.class.new("test_delete_2") suite << test2 test3 = self.class.new("test_add") suite << test3 suite.delete_tests([test1, test2]) assert_equal(1, suite.size) assert_equal(TestSuite.new << test3, suite) end def test_size suite = TestSuite.new suite2 = TestSuite.new suite2 << self.class.new("test_size") suite << suite2 suite << self.class.new("test_size") assert_equal(2, suite.size, "The count should be correct") end def test_run progress = [] @testcase1.test_order = :alphabetic suite = @testcase1.suite tests = suite.tests.dup result = TestResult.new suite.run(result) { |*values| progress << values } assert_equal(2, result.run_count, "Should have had four test runs") assert_equal(1, result.failure_count, "Should have had one test failure") assert_equal(0, result.error_count, "Should have had one test error") assert_equal([[TestSuite::STARTED, suite.name], [TestSuite::STARTED_OBJECT, suite], [TestCase::STARTED, "test_fail(#{suite.name})"], [TestCase::STARTED_OBJECT, tests[0]], [TestCase::FINISHED, "test_fail(#{suite.name})"], [TestCase::FINISHED_OBJECT, tests[0]], [TestCase::STARTED, "test_succeed1(#{suite.name})"], [TestCase::STARTED_OBJECT, tests[1]], [TestCase::FINISHED, "test_succeed1(#{suite.name})"], [TestCase::FINISHED_OBJECT, tests[1]], [TestSuite::FINISHED, suite.name], [TestSuite::FINISHED_OBJECT, suite]], progress, "Should have had the correct progress") suite = TestSuite.new suite << @testcase1.suite suite << @testcase2.suite result = TestResult.new progress = [] suite.run(result) { |*values| progress << values } assert_equal(4, result.run_count, "Should have had four test runs") assert_equal(1, result.failure_count, "Should have had one test failure") assert_equal(1, result.error_count, "Should have had one test error") assert_equal(28, progress.size, "Should have had the correct number of progress calls") end def test_empty? assert(TestSuite.new.empty?, "A new test suite should be empty?") assert(!@testcase2.suite.empty?, "A test suite with tests should not be empty") end def test_equality suite1 = TestSuite.new suite2 = TestSuite.new assert_equal(suite1, suite2) assert_equal(suite2, suite1) suite1 = TestSuite.new('name') assert_not_equal(suite1, suite2) assert_not_equal(suite2, suite1) suite2 = TestSuite.new('name') assert_equal(suite1, suite2) assert_equal(suite2, suite1) suite1 << 'test' assert_not_equal(suite1, suite2) assert_not_equal(suite2, suite1) suite2 << 'test' assert_equal(suite1, suite2) assert_equal(suite2, suite1) suite2 = Object.new class << suite2 def name 'name' end def tests ['test'] end end assert_not_equal(suite1, suite2) assert_not_equal(suite2, suite1) assert_not_equal(suite1, Object.new) assert_not_equal(Object.new, suite1) end end end end PK% ]U_m77)gems/test-unit-3.2.9/test/test-failure.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2003 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit' require 'test/unit/failure' module Test::Unit class TestFailure < TestCase def test_display f = Failure.new("name", [%q{location:1 in 'l'}], "message1\nmessage2") assert_equal("name: message1", f.short_display) assert_equal(< # # License: Ruby's require "test-unit" require "test/unit/fault-location-detector" require "testunit-test-util" class TestFaultLocationDetector < Test::Unit::TestCase include TestUnitTestUtil def setup @fetcher = Test::Unit::CodeSnippetFetcher.new end private def run_test_case(test_case) suite = test_case.suite result = Test::Unit::TestResult.new suite.run(result) {} result.faults[0] end def assert_detect(fault, target_line_number) detector = Test::Unit::FaultLocationDetector.new(fault, @fetcher) expected_backtrace_entries_until_detected = [] fault.location.each do |backtrace_entry| expected_backtrace_entries_until_detected << backtrace_entry _, line_number, = detector.split_backtrace_entry(backtrace_entry) break if target_line_number == line_number end actual_backtrace_entries_until_detected = [] fault.location.each do |backtrace_entry| actual_backtrace_entries_until_detected << backtrace_entry break if detector.target?(backtrace_entry) end assert_equal(expected_backtrace_entries_until_detected, actual_backtrace_entries_until_detected) end module AlwaysFailAssertion private def assert_always_failed assert_true(false) end end class TestSourceLocation < self setup def setup_check_source_location unless lambda {}.respond_to?(:source_location) omit("Need Proc#source_location") end end def test_detected target_line_number = nil test_case = Class.new(Test::Unit::TestCase) do include AlwaysFailAssertion test "failed" do target_line_number = __LINE__; assert_always_failed end end fault = run_test_case(test_case) assert_detect(fault, target_line_number) end class TestOneLine < self def test_brace target_line_number = nil test_case = Class.new(Test::Unit::TestCase) do include AlwaysFailAssertion test("failed") {target_line_number = __LINE__; assert_always_failed} def other_method # body end end fault = run_test_case(test_case) assert_detect(fault, target_line_number) end def test_do_end target_line_number = nil test_case = Class.new(Test::Unit::TestCase) do include AlwaysFailAssertion test "failed" do target_line_number = __LINE__; assert_always_failed; end def other_method # body end end fault = run_test_case(test_case) assert_detect(fault, target_line_number) end end end class TestMethodName < self def test_detected test_case = Class.new(Test::Unit::TestCase) do include AlwaysFailAssertion class << self def target_line_number @@target_line_number end def target_line_number=(line_number) @@target_line_number = line_number end end def test_failed self.class.target_line_number = __LINE__; assert_always_failed end end fault = run_test_case(test_case) assert_detect(fault, test_case.target_line_number) end end class TestInBlock < self def test_in_block test_case = Class.new(Test::Unit::TestCase) do include AlwaysFailAssertion class << self def target_line_number @@target_line_number end def target_line_number=(line_number) @@target_line_number = line_number end end def run_yield yield end def test_failed run_yield do self.class.target_line_number = __LINE__; assert_always_failed end end end fault = run_test_case(test_case) assert_detect(fault, test_case.target_line_number) end end end PK% ]G-44&gems/test-unit-3.2.9/test/test-data.rbnu[require "testunit-test-util" class TestData < Test::Unit::TestCase class Calc def initialize end def plus(augend, addend) augend + addend end end class TestCalc < Test::Unit::TestCase @@testing = false class << self def testing=(testing) @@testing = testing end end def valid? @@testing end def setup @calc = Calc.new end class TestDataSet < TestCalc data("positive positive" => {:expected => 4, :augend => 3, :addend => 1}, "positive negative" => {:expected => -1, :augend => 1, :addend => -2}) def test_plus(data) assert_equal(data[:expected], @calc.plus(data[:augend], data[:addend])) end end class TestNData < TestCalc data("positive positive", {:expected => 4, :augend => 3, :addend => 1}) data("positive negative", {:expected => -1, :augend => 1, :addend => -2}) def test_plus(data) assert_equal(data[:expected], @calc.plus(data[:augend], data[:addend])) end end class TestDynamicDataSet < TestCalc DATA_PROC = lambda do data_set = {} data_set["positive positive"] = { :expected => 3, :augend => 1, :addend => 2 } data_set["positive negative"] = { :expected => -1, :augend => 1, :addend => -2 } data_set end data(&DATA_PROC) def test_plus(data) assert_equal(data[:expected], @calc.plus(data[:augend], data[:addend])) end end class TestLoadDataSet < TestCalc extend TestUnitTestUtil load_data(fixture_file_path("plus.csv")) def test_plus(data) assert_equal(data["expected"], @calc.plus(data["augend"], data["addend"])) end end class TestSuperclass < TestCalc data("positive positive" => {:expected => 4, :augend => 3, :addend => 1}, "positive negative" => {:expected => -1, :augend => 1, :addend => -2}) def test_plus(data) assert_equal(data[:expected], @calc.plus(data[:augend], data[:addend])) end class TestNormalTestInSubclass < self def test_plus assert_equal(2, @calc.plus(1, 1)) end end end class TestMethod < TestCalc def data_test_plus { "positive positive" => {:expected => 4, :augend => 3, :addend => 1}, "positive negative" => {:expected => -1, :augend => 1, :addend => -2}, } end def test_plus(data) assert_equal(data[:expected], @calc.plus(data[:augend], data[:addend])) end end class TestPatterns < TestCalc data(:x, [-1, 1, 0]) data(:y, [-100, 100]) data(:z, ["a", "b", "c"]) def test_use_data(data) end end class TestPatternsKeep < TestCalc data(:x, [-1, 1, 0], keep: true) data(:y, [-100, 100]) data(:z, ["a", "b", "c"], keep: true) def test_use_data(data) end def test_use_data_keep(data) end end class TestPatternsGroup < TestCalc data(:a, [-1, 1, 0], group: 1) data(:b, [:a, :b], group: 1) data(:x, [2, 9], group: :z) data(:y, ["a", "b", "c"], group: :z) def test_use_data(data) end end end def setup TestCalc.testing = true end def teardown TestCalc.testing = false end def test_data_no_arguments_without_block assert_raise(ArgumentError) do self.class.data end end data("data set", { :test_case => TestCalc::TestDataSet, :data_sets => [ { "positive positive" => { :expected => 4, :augend => 3, :addend => 1, }, "positive negative" => { :expected => -1, :augend => 1, :addend => -2, }, }, ], }) data("n-data", { :test_case => TestCalc::TestNData, :data_sets => [ { "positive positive" => { :expected => 4, :augend => 3, :addend => 1, }, }, { "positive negative" => { :expected => -1, :augend => 1, :addend => -2, }, }, ], }) data("dynamic-data-set", { :test_case => TestCalc::TestDynamicDataSet, :data_sets => [TestCalc::TestDynamicDataSet::DATA_PROC], }) data("load-data-set", { :test_case => TestCalc::TestLoadDataSet, :data_sets => [ { "positive positive" => { "expected" => 4, "augend" => 3, "addend" => 1, }, }, { "positive negative" => { "expected" => -1, "augend" => 1, "addend" => -2, }, }, ], }) def test_data(data) test_plus = data[:test_case].new("test_plus") data_sets = Test::Unit::DataSets.new data[:data_sets].each do |data_set| data_sets.add(data_set) end assert_equal(data_sets, test_plus[:data]) end def test_data_patterns test = TestCalc::TestPatterns.new("test_use_data") data_sets = Test::Unit::DataSets.new data_sets << [:x, [-1, 1, 0]] data_sets << [:y, [-100, 100]] data_sets << [:z, ["a", "b", "c"]] assert_equal(data_sets, test[:data]) end def test_data_patterns_keep test = TestCalc::TestPatternsKeep.new("test_use_data_keep") data_sets = Test::Unit::DataSets.new data_sets.add([:x, [-1, 1, 0]], {keep: true}) data_sets.add([:z, ["a", "b", "c"]], {keep: true}) assert_equal(data_sets, test[:data]) end data("data set" => TestCalc::TestDataSet, "n-data" => TestCalc::TestNData, "dynamic-data-set" => TestCalc::TestDynamicDataSet, "load-data-set" => TestCalc::TestLoadDataSet) def test_suite(test_case) suite = test_case.suite assert_equal(["test_plus[positive negative](#{test_case.name})", "test_plus[positive positive](#{test_case.name})"], suite.tests.collect {|test| test.name}.sort) end def test_suite_patterns test_case = TestCalc::TestPatterns suite = test_case.suite assert_equal([ "test_use_data[x: -1, y: -100, z: \"a\"](#{test_case.name})", "test_use_data[x: -1, y: -100, z: \"b\"](#{test_case.name})", "test_use_data[x: -1, y: -100, z: \"c\"](#{test_case.name})", "test_use_data[x: -1, y: 100, z: \"a\"](#{test_case.name})", "test_use_data[x: -1, y: 100, z: \"b\"](#{test_case.name})", "test_use_data[x: -1, y: 100, z: \"c\"](#{test_case.name})", "test_use_data[x: 0, y: -100, z: \"a\"](#{test_case.name})", "test_use_data[x: 0, y: -100, z: \"b\"](#{test_case.name})", "test_use_data[x: 0, y: -100, z: \"c\"](#{test_case.name})", "test_use_data[x: 0, y: 100, z: \"a\"](#{test_case.name})", "test_use_data[x: 0, y: 100, z: \"b\"](#{test_case.name})", "test_use_data[x: 0, y: 100, z: \"c\"](#{test_case.name})", "test_use_data[x: 1, y: -100, z: \"a\"](#{test_case.name})", "test_use_data[x: 1, y: -100, z: \"b\"](#{test_case.name})", "test_use_data[x: 1, y: -100, z: \"c\"](#{test_case.name})", "test_use_data[x: 1, y: 100, z: \"a\"](#{test_case.name})", "test_use_data[x: 1, y: 100, z: \"b\"](#{test_case.name})", "test_use_data[x: 1, y: 100, z: \"c\"](#{test_case.name})", ], suite.tests.collect {|test| test.name}.sort) end def test_suite_patterns_group test_case = TestCalc::TestPatternsGroup suite = test_case.suite assert_equal([ "test_use_data[group: 1, a: -1, b: :a](#{test_case.name})", "test_use_data[group: 1, a: -1, b: :b](#{test_case.name})", "test_use_data[group: 1, a: 0, b: :a](#{test_case.name})", "test_use_data[group: 1, a: 0, b: :b](#{test_case.name})", "test_use_data[group: 1, a: 1, b: :a](#{test_case.name})", "test_use_data[group: 1, a: 1, b: :b](#{test_case.name})", "test_use_data[group: :z, x: 2, y: \"a\"](#{test_case.name})", "test_use_data[group: :z, x: 2, y: \"b\"](#{test_case.name})", "test_use_data[group: :z, x: 2, y: \"c\"](#{test_case.name})", "test_use_data[group: :z, x: 9, y: \"a\"](#{test_case.name})", "test_use_data[group: :z, x: 9, y: \"b\"](#{test_case.name})", "test_use_data[group: :z, x: 9, y: \"c\"](#{test_case.name})", ], suite.tests.collect {|test| test.name}.sort) end data("data set" => TestCalc::TestDataSet, "n-data" => TestCalc::TestNData, "dynamic-data-set" => TestCalc::TestDynamicDataSet, "load-data-set" => TestCalc::TestLoadDataSet, "superclass" => TestCalc::TestSuperclass, "method" => TestCalc::TestMethod) def test_run(test_case) result = _run_test(test_case) assert_equal("2 tests, 2 assertions, 0 failures, 0 errors, 0 pendings, " \ "0 omissions, 0 notifications", result.to_s) end def test_run_normal_test_in_subclass result = _run_test(TestCalc::TestSuperclass::TestNormalTestInSubclass) assert_equal("1 tests, 1 assertions, 0 failures, 0 errors, 0 pendings, " \ "0 omissions, 0 notifications", result.to_s) end data("data set" => TestCalc::TestDataSet, "n-data" => TestCalc::TestNData, "dynamic-data-set" => TestCalc::TestDynamicDataSet, "load-data-set" => TestCalc::TestLoadDataSet) def test_equal(test_case) suite = test_case.suite positive_positive_test = suite.tests.find do |test| test.data_label == "positive positive" end suite.tests.delete(positive_positive_test) assert_equal(["test_plus[positive negative](#{test_case.name})"], suite.tests.collect {|test| test.name}.sort) end data("true" => {:expected => true, :target => "true"}, "false" => {:expected => false, :target => "false"}, "integer" => {:expected => 1, :target => "1"}, "float" => {:expected => 1.5, :target => "1.5"}, "string" => {:expected => "hello", :target => "hello"}) def test_normalize_value(data) loader = Test::Unit::Data::ClassMethods::Loader.new(self) assert_equal(data[:expected], loader.__send__(:normalize_value, data[:target])) end def _run_test(test_case) result = Test::Unit::TestResult.new test = test_case.suite yield(test) if block_given? test.run(result) {} result end class TestLoadData < Test::Unit::TestCase include TestUnitTestUtil def test_invalid_csv_file_name garbage = "X" file_name = "data.csv#{garbage}" assert_raise(ArgumentError, "unsupported file format: <#{file_name}>") do self.class.load_data(file_name) end end class TestFileFormat < self def setup self.class.current_attribute(:data).clear end class TestHeader < self data("csv" => "header.csv", "tsv" => "header.tsv") def test_normal(file_name) self.class.load_data(fixture_file_path(file_name)) data_sets = Test::Unit::DataSets.new data_sets << { "empty string" => { "expected" => true, "target" => "" } } data_sets << { "plain string" => { "expected" => false, "target" => "hello" } } assert_equal(data_sets, self.class.current_attribute(:data)[:value]) end data("csv" => "header-label.csv", "tsv" => "header-label.tsv") def test_label(file_name) self.class.load_data(fixture_file_path(file_name)) data_sets = Test::Unit::DataSets.new data_sets << { "upper case" => { "expected" => "HELLO", "label" => "HELLO" } } data_sets << { "lower case" => { "expected" => "Hello", "label" => "hello" } } assert_equal(data_sets, self.class.current_attribute(:data)[:value]) end end data("csv" => "no-header.csv", "tsv" => "no-header.tsv") def test_without_header(file_name) self.class.load_data(fixture_file_path(file_name)) data_sets = Test::Unit::DataSets.new data_sets << {"empty string" => [true, ""]} data_sets << {"plain string" => [false, "hello"]} assert_equal(data_sets, self.class.current_attribute(:data)[:value]) end end end end PK% ]7aa.gems/test-unit-3.2.9/test/test-code-snippet.rbnu[require "test-unit" require "testunit-test-util" class TestCodeSnippet < Test::Unit::TestCase include TestUnitTestUtil class TestJRuby < self def test_error_inside_jruby jruby_only_test backtrace = backtrace_from_jruby no_rb_entries = backtrace.find_all do |(file, _, _)| File.extname(file) != ".rb" end fetcher = Test::Unit::CodeSnippetFetcher.new snippets = no_rb_entries.collect do |(file, line, _)| fetcher.fetch(file, line) end assert_equal([[]] * no_rb_entries.size, snippets) end private def backtrace_from_jruby begin java.util.Vector.new(-1) rescue Exception $@.collect do |entry| entry.split(/:/, 3) end else flunk("failed to raise an exception from JRuby.") end end end end PK% ]w22'gems/test-unit-3.2.9/test/test-color.rbnu[class TestUnitColor < Test::Unit::TestCase def test_color_escape_sequence assert_escape_sequence(["31"], color("red")) assert_escape_sequence(["32", "1"], color("green", :bold => true)) assert_escape_sequence(["0"], color("reset")) assert_escape_sequence(["45"], color("magenta", :background => true)) end def test_mix_color_escape_sequence assert_escape_sequence(["34", "1"], mix_color([color("blue"), color("none", :bold => true)])) assert_escape_sequence(["34", "1", "4"], mix_color([color("blue"), color("none", :bold => true)]) + color("none", :underline => true)) assert_escape_sequence(["34", "1", "4"], color("blue") + color("none", :bold => true) + color("none", :underline => true)) end def test_equal red = color("red") red_bold = color("red", :bold => true) assert_operator(red, :==, red) assert_not_equal(red, nil) assert_equal(red, color("red")) assert_not_equal(red, red_bold) end private def color(name, options={}) Test::Unit::Color.new(name, options) end def mix_color(colors) Test::Unit::MixColor.new(colors) end def assert_escape_sequence(expected, color) assert_equal(expected, color.sequence) assert_match(/\e\[(?:\d+;)*\d+m/, color.escape_sequence) assert_equal(expected, color.escape_sequence[2..-2].split(";")) end end PK% ] Hll/gems/test-unit-3.2.9/test/testunit-test-util.rbnu[module TestUnitTestUtil private def jruby? RUBY_PLATFORM == "java" end def jruby_only_test if jruby? require "java" else omit("test for JRuby") end end def assert_fault_messages(expected, faults) assert_equal(expected, faults.collect {|fault| fault.message}) end def _run_test(test_case, name) result = Test::Unit::TestResult.new test = test_case.new(name) yield(test) if block_given? test.run(result) {} result end def fixture_file_path(file_name) base_dir = File.dirname(__FILE__) File.join(base_dir, "fixtures", file_name) end end PK% ]:QQ+gems/test-unit-3.2.9/test/test-test-case.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2008-2014 Kouhei Sutou # Copyright:: Copyright (c) 2011 Haruka Yoshihara # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott # License:: Ruby license. require 'test/unit' module Test module Unit class TestTestCase < TestCase self.test_order = :random def test_creation test_case = Class.new(TestCase) do def test_with_arguments(arg1, arg2) end end test = test_case.new(:test_with_arguments) check("Should have caught an invalid test when there are arguments", !test.valid?) test = test_case.new(:non_existent_test) check("Should have caught an invalid test when the method does not exist", !test.valid?) end def setup @tc_failure_error = Class.new(TestCase) do def test_failure assert_block("failure") do false end end def test_error 1 / 0 end def test_nested_failure nested end def nested assert_block("nested") do false end end def return_passed? return passed? end end def @tc_failure_error.name "TC_FailureError" end end def jruby_backtrace_entry?(entry) entry.start_with?("org/jruby/") end def rubinius_backtrace_entry?(entry) entry.start_with?("kernel/") end def normalize_location(location) filtered_location = location.reject do |entry| jruby_backtrace_entry?(entry) or rubinius_backtrace_entry?(entry) end filtered_location.collect do |entry| entry.sub(/:\d+:/, ":0:") end end def test_add_failed_assertion test_case = @tc_failure_error.new(:test_failure) assert do test_case.passed? end result = TestResult.new faults = [] result.add_listener(TestResult::FAULT) do |fault| faults << fault end progress = [] test_case.run(result) do |*arguments| progress << arguments end fault_details = faults.collect do |fault| { :class => fault.class, :message => fault.message, :test_name => fault.test_name, :location => normalize_location(fault.location), } end assert_equal([ { :class => Failure, :message => "failure", :test_name => "test_failure(TC_FailureError)", :location => [ "#{__FILE__}:0:in `test_failure'", "#{__FILE__}:0:in `#{__method__}'", ], }, ], fault_details) assert do not test_case.passed? end assert_equal([ [TestCase::STARTED, test_case.name], [TestCase::STARTED_OBJECT, test_case], [TestCase::FINISHED, test_case.name], [TestCase::FINISHED_OBJECT, test_case], ], progress) end def test_add_failure_nested test_case = @tc_failure_error.new(:test_nested_failure) assert do test_case.passed? end result = TestResult.new faults = [] result.add_listener(TestResult::FAULT) do |fault| faults << fault end test_case.run(result) do end fault_details = faults.collect do |fault| { :class => fault.class, :message => fault.message, :test_name => fault.test_name, :location => normalize_location(fault.location), } end assert_equal([ { :class => Failure, :message => "nested", :test_name => "test_nested_failure(TC_FailureError)", :location => [ "#{__FILE__}:0:in `nested'", "#{__FILE__}:0:in `test_nested_failure'", "#{__FILE__}:0:in `#{__method__}'", ], }, ], fault_details) assert do not test_case.passed? end end def jruby? defined?(JRUBY_VERSION) end def rubinius? false # TODO end def cruby? (not jruby?) and (not rubinius?) end def test_add_error test_case = @tc_failure_error.new(:test_error) assert do test_case.passed? end result = TestResult.new faults = [] result.add_listener(TestResult::FAULT) do |fault| faults << fault end test_case.run(result) do end fault_details = faults.collect do |fault| { :class => fault.class, :message => fault.message, :test_name => fault.test_name, :location => normalize_location(fault.location), } end location = [] location << "#{__FILE__}:0:in `/'" if cruby? location << "#{__FILE__}:0:in `test_error'" location << "#{__FILE__}:0:in `#{__method__}'" assert_equal([ { :class => Error, :message => "ZeroDivisionError: divided by 0", :test_name => "test_error(TC_FailureError)", :location => location, }, ], fault_details) assert do not test_case.passed? end end def test_no_tests suite = TestCase.suite check("Should have a test suite", suite.instance_of?(TestSuite)) check("Should have one test", suite.size == 1) check("Should have the default test", suite.tests.first.name == "default_test(Test::Unit::TestCase)") result = TestResult.new suite.run(result) {} check("Should have had one test run", result.run_count == 1) check("Should have had one test failure", result.failure_count == 1) check("Should have had no errors", result.error_count == 0) end def test_suite tc = Class.new(TestCase) do def test_succeed assert_block {true} end def test_fail assert_block {false} end def test_error 1/0 end def dont_run assert_block {true} end def test_dont_run(argument) assert_block {true} end def test assert_block {true} end end suite = tc.suite check("Should have a test suite", suite.instance_of?(TestSuite)) check("Should have three tests", suite.size == 3) result = TestResult.new suite.run(result) {} check("Should have had three test runs", result.run_count == 3) check("Should have had one test failure", result.failure_count == 1) check("Should have had one test error", result.error_count == 1) end def test_setup_teardown tc = Class.new(TestCase) do attr_reader(:setup_called, :teardown_called) def initialize(test) super(test) @setup_called = false @teardown_called = false end def setup @setup_called = true end def teardown @teardown_called = true end def test_succeed assert_block {true} end def test_fail assert_block {false} end def test_error raise "Error!" end end result = TestResult.new test = tc.new(:test_succeed) test.run(result) {} check("Should have called setup the correct number of times", test.setup_called) check("Should have called teardown the correct number of times", test.teardown_called) test = tc.new(:test_fail) test.run(result) {} check("Should have called setup the correct number of times", test.setup_called) check("Should have called teardown the correct number of times", test.teardown_called) test = tc.new(:test_error) test.run(result) {} check("Should have called setup the correct number of times", test.setup_called) check("Should have called teardown the correct number of times", test.teardown_called) check("Should have had two test runs", result.run_count == 3) check("Should have had a test failure", result.failure_count == 1) check("Should have had a test error", result.error_count == 1) end def test_assertion_failed_not_called tc = Class.new(TestCase) do def test_thing raise AssertionFailedError.new end end suite = tc.suite check("Should have one test", suite.size == 1) result = TestResult.new suite.run(result) {} check("Should have had one test run", result.run_count == 1) check("Should have had one assertion failure", result.failure_count == 1) check("Should not have any assertion errors but had #{result.error_count}", result.error_count == 0) end def test_equality tc1 = Class.new(TestCase) do def test_1 end def test_2 end end tc2 = Class.new(TestCase) do def test_1 end end test1 = tc1.new('test_1') test2 = tc1.new('test_1') check("Should be equal", test1 == test2) check("Should be equal", test2 == test1) test1 = tc1.new('test_2') check("Should not be equal", test1 != test2) check("Should not be equal", test2 != test1) test2 = tc1.new('test_2') check("Should be equal", test1 == test2) check("Should be equal", test2 == test1) test1 = tc1.new('test_1') test2 = tc2.new('test_1') check("Should not be equal", test1 != test2) check("Should not be equal", test2 != test1) check("Should not be equal", test1 != Object.new) check("Should not be equal", Object.new != test1) end def test_re_raise_exception test_case = Class.new(TestCase) do def test_raise_interrupt raise Interrupt, "from test" end end test = test_case.new("test_raise_interrupt") begin test.run(TestResult.new) {} check("Should not be reached", false) rescue Exception check("Interrupt exception should be re-raised", $!.class == Interrupt) end end def test_timeout_error test_case = Class.new(TestCase) do def test_raise_timeout_error require "timeout" raise Timeout::Error end end test_suite = test_case.suite result = TestResult.new begin test_suite.run(result) {} check("Timeout::Error should be handled as error", result.error_count == 1) rescue Exception check("Timeout::Error should not be passed through: #{$!}", false) end end def test_interrupted test_case = Class.new(TestCase) do def test_fail flunk end def test_nothing end end failed_test = test_case.new(:test_fail) failed_test.run(TestResult.new) {} check("Should be interrupted", failed_test.interrupted?) success_test = test_case.new(:test_nothing) success_test.run(TestResult.new) {} check("Should not be interrupted", !success_test.interrupted?) end def test_inherited_test_should_be_ignored test_case = Class.new(TestCase) do def test_nothing end end sub_test_case = Class.new(test_case) do def test_fail flunk end end test = test_case.new("test_nothing") assert_predicate(test, :valid?) test = sub_test_case.new("test_fail") assert_predicate(test, :valid?) test = sub_test_case.new("test_nothing") assert_not_predicate(test, :valid?) end def test_mixin_test_should_not_be_ignored test_module = Module.new do def test_nothing end end test_case = Class.new(Test::Unit::TestCase) do include test_module def test_fail flunk end end assert_nothing_thrown do test_case.new("test_nothing") end assert_nothing_thrown do test_case.new("test_fail") end end def test_defined_order test_case = Class.new(Test::Unit::TestCase) do def test_z end def test_1 end def test_a end end test_case.test_order = :defined assert_equal(["test_z", "test_1", "test_a"], test_case.suite.tests.collect {|test| test.method_name}) end def test_declarative_style test_case = Class.new(Test::Unit::TestCase) do test "declarative style test definition" do end test "include parenthesis" do end test "1 + 2 = 3" do end end test_case.test_order = :defined assert_equal(["test: declarative style test definition", "test: include parenthesis", "test: 1 + 2 = 3"], test_case.suite.tests.collect {|test| test.method_name}) assert_equal(["declarative style test definition", "include parenthesis", "1 + 2 = 3"], test_case.suite.tests.collect {|test| test.description}) end def test_test_mark test_case = Class.new(Test::Unit::TestCase) do test def my_test_method end end test_case.test_order = :defined assert_equal(["my_test_method"], test_case.suite.tests.collect {|test| test.method_name}) end def test_redefine_method test_case = Class.new(Test::Unit::TestCase) do self.test_order = :alphabetic def test_name end alias_method :test_name2, :test_name def test_name end end suite = test_case.suite assert_equal(["test_name", "test_name2"], suite.tests.collect {|test| test.method_name}) result = TestResult.new suite.run(result) {} assert_equal("2 tests, 0 assertions, 0 failures, " + "0 errors, 0 pendings, 0 omissions, 1 notifications", result.summary) end def test_data_driven_test test_case = Class.new(TestCase) do def test_with_data(data) end end test = test_case.new("test_with_data") assert_not_predicate(test, :valid?) test.assign_test_data("label1", :test_data1) assert_predicate(test, :valid?) end def test_data_driven_test_without_parameter test_case = Class.new(TestCase) do data("label" => "value") def test_without_parameter assert_equal("value", data) end end suite = test_case.suite assert_equal(["test_without_parameter"], suite.tests.collect {|test| test.method_name}) result = TestResult.new suite.run(result) {} assert_equal("1 tests, 1 assertions, 0 failures, " + "0 errors, 0 pendings, 0 omissions, 0 notifications", result.summary) end private def check(message, passed) add_assertion raise AssertionFailedError.new(message) unless passed end class TestTestDefined < self class TestNoQuery < self def test_no_test test_case = Class.new(TestCase) do end assert_false(test_case.test_defined?({})) end def test_have_def_style_test test_case = Class.new(TestCase) do def test_nothing end end assert_true(test_case.test_defined?({})) end def test_have_method_style_test test_case = Class.new(TestCase) do test "nothing" do end end assert_true(test_case.test_defined?({})) end end class TestPath < self class TestDefStyle < self def test_base_name test_case = Class.new(TestCase) do def test_nothing end end base_name = File.basename(__FILE__) assert_true(test_case.test_defined?(:path => base_name)) end def test_absolute_path test_case = Class.new(TestCase) do def test_nothing end end assert_true(test_case.test_defined?(:path => __FILE__)) end def test_not_match test_case = Class.new(TestCase) do def test_nothing end end assert_false(test_case.test_defined?(:path => "nonexistent.rb")) end end class TestMethodStyle < self def test_base_name test_case = Class.new(TestCase) do test "nothing" do end end base_name = File.basename(__FILE__) assert_true(test_case.test_defined?(:path => base_name)) end def test_absolute_path test_case = Class.new(TestCase) do test "nothing" do end end assert_true(test_case.test_defined?(:path => __FILE__)) end def test_not_match test_case = Class.new(TestCase) do test "nothing" do end end assert_false(test_case.test_defined?(:path => "nonexistent.rb")) end end end class TestLine < self class TestDefStyle < self def test_before line_before = nil test_case = Class.new(TestCase) do line_before = __LINE__ def test_nothing end end assert_false(test_case.test_defined?(:line => line_before)) end def test_def line_def = nil test_case = Class.new(TestCase) do line_def = __LINE__; def test_nothing end end assert_true(test_case.test_defined?(:line => line_def)) end def test_after line_after = nil test_case = Class.new(TestCase) do def test_nothing end line_after = __LINE__ end assert_true(test_case.test_defined?(:line => line_after)) end def test_child child_test_case = nil line_child = nil parent_test_case = Class.new(TestCase) do test "parent" do end child_test_case = Class.new(self) do line_child = __LINE__; test "child" do end end end assert_equal([ false, true, ], [ parent_test_case.test_defined?(:line => line_child), child_test_case.test_defined?(:line => line_child), ]) end end class TestMethodStyle < self def test_before line_before = nil test_case = Class.new(TestCase) do line_before = __LINE__ test "nothing" do end end assert_false(test_case.test_defined?(:line => line_before)) end def test_method line_method = nil test_case = Class.new(TestCase) do line_method = __LINE__; test "nothing" do end end assert_true(test_case.test_defined?(:line => line_method)) end def test_after line_after = nil test_case = Class.new(TestCase) do test "nothing" do end line_after = __LINE__ end assert_true(test_case.test_defined?(:line => line_after)) end def test_child child_test_case = nil line_child = nil parent_test_case = Class.new(TestCase) do test "parent" do end child_test_case = Class.new(self) do line_child = __LINE__; test "child" do end end end assert_equal([ false, true, ], [ parent_test_case.test_defined?(:line => line_child), child_test_case.test_defined?(:line => line_child), ]) end def test_with_setup line = nil test_case = Class.new(TestCase) do setup do end line = __LINE__; test "with setup" do end end assert do test_case.test_defined?(:line => line, :method_name => "test: with setup") end end end end class TestMethodName < self class TestDefStyle < self def test_match test_case = Class.new(TestCase) do def test_nothing end end query = {:method_name => "test_nothing"} assert_true(test_case.test_defined?(query)) end def test_not_match test_case = Class.new(TestCase) do def test_nothing end end query = {:method_name => "test_nonexistent"} assert_false(test_case.test_defined?(query)) end end class TestMethodStyle < self def test_match test_case = Class.new(TestCase) do test "nothing" do end end query = {:method_name => "test: nothing"} assert_true(test_case.test_defined?(query)) end def test_not_match test_case = Class.new(TestCase) do test "nothing" do end end query = {:method_name => "test: nonexistent"} assert_false(test_case.test_defined?(query)) end end end class TestCombine < self class TestDefStyle < self def test_line_middle line_middle = nil test_case = Class.new(TestCase) do def test_before end line_middle = __LINE__ def test_after end end query = { :path => __FILE__, :line => line_middle, :method_name => "test_before", } assert_true(test_case.test_defined?(query)) end def test_line_after_def line_after_def = nil test_case = Class.new(TestCase) do def test_before end line_after_def = __LINE__; def test_after end end query = { :path => __FILE__, :line => line_after_def, :method_name => "test_before", } assert_false(test_case.test_defined?(query)) end end class TestMethodStyle < self def test_line_middle line_middle = nil test_case = Class.new(TestCase) do test "before" do end line_middle = __LINE__ test "after" do end end query = { :path => __FILE__, :line => line_middle, :method_name => "test: before", } assert_true(test_case.test_defined?(query)) end def test_line_after_method line_after_method = nil test_case = Class.new(TestCase) do test "before" do end line_after_method = __LINE__; test "after" do end end query = { :path => __FILE__, :line => line_after_method, :method_name => "test: before", } assert_false(test_case.test_defined?(query)) end end end end class TestSubTestCase < self class TestName < self def test_anonymous test_case = Class.new(TestCase) sub_test_case = test_case.sub_test_case("sub test case") do end assert_equal("sub test case", sub_test_case.name) end def test_named test_case = Class.new(TestCase) def test_case.name "ParentTestCase" end sub_test_case = test_case.sub_test_case("sub test case") do end assert_equal("ParentTestCase::sub test case", sub_test_case.name) end end def test_suite test_case = Class.new(TestCase) sub_test_case = test_case.sub_test_case("sub test case") do def test_nothing end end test_method_names = sub_test_case.suite.tests.collect do |test| test.method_name end assert_equal(["test_nothing"], test_method_names) end def test_duplicated_name test_case = Class.new(TestCase) do def test_nothing end end sub_test_case = test_case.sub_test_case("sub test case") do def test_nothing end end test_method_names = test_case.suite.tests.collect do |test| test.method_name end sub_test_method_names = sub_test_case.suite.tests.collect do |test| test.method_name end assert_equal([ ["test_nothing"], ["test_nothing"], ], [ test_method_names, sub_test_method_names, ]) end end class TestStartupShutdown < self class TestOrder < self module CallLogger def called @@called ||= [] end end def call_order(test_case) test_case.called.clear test_suite = test_case.suite test_suite.run(TestResult.new) {} test_case.called end class TestNoInheritance < self def setup @test_case = Class.new(TestCase) do extend CallLogger class << self def startup called << :startup end def shutdown called << :shutdown end end def setup self.class.called << :setup end def teardown self.class.called << :teardown end def test1 end def test2 end end end def test_call_order assert_equal([ :startup, :setup, :teardown, :setup, :teardown, :shutdown, ], call_order(@test_case)) end end class TestInheritance < self def setup @original_descendants = TestCase::DESCENDANTS.dup TestCase::DESCENDANTS.clear @parent_test_case = Class.new(TestCase) do extend CallLogger self.test_order = :alphabetic class << self def startup called << :startup_parent end def shutdown called << :shutdown_parent end end def setup self.class.called << :setup_parent end def teardown self.class.called << :teardown_parent end def test1_parent self.class.called << :test1_parent end def test2_parent self.class.called << :test2_parent end end @child_test_case = Class.new(@parent_test_case) do class << self def startup called << :startup_child end def shutdown called << :shutdown_child end end def setup self.class.called << :setup_child end def teardown self.class.called << :teardown_child end def test1_child self.class.called << :test1_child end def test2_child self.class.called << :test2_child end end end def teardown TestCase::DESCENDANTS.replace(@original_descendants) end def test_call_order collector = Collector::Descendant.new test_suite = collector.collect test_suite.run(TestResult.new) {} called = @parent_test_case.called assert_equal([ :startup_parent, :setup_parent, :test1_parent, :teardown_parent, :setup_parent, :test2_parent, :teardown_parent, :startup_child, :setup_child, :test1_child, :teardown_child, :setup_child, :test2_child, :teardown_child, :shutdown_child, :shutdown_parent, ], called) end end end class TestError < self def run_test_case(test_case) test_suite = test_case.suite result = TestResult.new test_suite.run(result) {} result end def error_count(test_case) run_test_case(test_case).error_count end def test_on_startup test_case = Class.new(TestCase) do class << self def startup raise "from startup" end end def test_nothing end end assert_equal(1, error_count(test_case)) end def test_pass_through_on_startup test_case = Class.new(TestCase) do class << self def startup raise Interrupt, "from startup" end end def test_nothing end end assert_raise(Interrupt) do run_test_case(test_case) end end def test_on_shutdown test_case = Class.new(TestCase) do class << self def shutdown raise "from shutdown" end end def test_nothing end end assert_equal(1, error_count(test_case)) end def test_pass_through_on_shutdown test_case = Class.new(TestCase) do class << self def shutdown raise Interrupt, "from shutdown" end end def test_nothing end end assert_raise(Interrupt) do run_test_case(test_case) end end def test_pass_through_in_test test_case = Class.new(TestCase) do @called = [] class << self def called @called end def startup @called << :startup end def shutdown @called << :shutdown end end def test_error raise Interrupt, "from test" end end assert_raise(Interrupt) do run_test_case(test_case) end assert_equal([:startup, :shutdown], test_case.called) end class TestName < self def test_no_data test_case = Class.new(TestCase) do class << self def name "TestCase" end end def test_nothing end end test = test_case.new("test_nothing") assert_equal("test_nothing(TestCase)", test.name) end def test_data test_case = Class.new(TestCase) do class << self def name "TestCase" end end def test_nothing end end test = test_case.new("test_nothing") test.assign_test_data("(nil)", nil) assert_equal("test_nothing[(nil)](TestCase)", test.name) end end class TestLocalName < self def test_no_data test_case = Class.new(TestCase) do class << self def name "TestCase" end end def test_nothing end end test = test_case.new("test_nothing") assert_equal("test_nothing", test.local_name) end def test_data test_case = Class.new(TestCase) do class << self def name "TestCase" end end def test_nothing end end test = test_case.new("test_nothing") test.assign_test_data("(nil)", nil) assert_equal("test_nothing[(nil)]", test.local_name) end end end end end end end PK% ]Қ,gems/test-unit-3.2.9/test/test-assertions.rbnu[# -*- coding: utf-8 -*- # # Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # Copyright (c) 2009-2014 Kouhei Sutou. All rights reserved. # License:: Ruby license. require 'test/unit' require "testunit-test-util" module Test module Unit module AssertionCheckable include TestUnitTestUtil private def check(value, message="") add_assertion raise AssertionFailedError.new(message) unless value end def check_assertions(expect_fail, options={}) expected_message = options[:expected_message] actual_message_normalizer = options[:actual_message_normalizer] return_value_expected = options[:return_value_expected] @actual_assertion_count = 0 failed = true actual_message = nil @catch_assertions = true return_value = nil begin return_value = yield failed = false rescue AssertionFailedError => error actual_message = error.message end @catch_assertions = false if expect_fail message = "Should have failed, but didn't" else message = "Should not have failed, but did with message\n" + "<#{actual_message}>" end check(expect_fail == failed, message) message = "Should have made one assertion but made\n" + "<#{@actual_assertion_count}>" check(1 == @actual_assertion_count, message) if expect_fail if actual_message_normalizer actual_message = actual_message_normalizer.call(actual_message) end case expected_message when String check(expected_message == actual_message, "Should have the correct message.\n" + "<#{expected_message.inspect}> expected but was\n" + "<#{actual_message.inspect}>") when Regexp check(expected_message =~ actual_message, "The message should match correctly.\n" + " expected to match\n" + "<#{actual_message.inspect}>") else check(false, "Incorrect expected message type in assert_nothing_failed") end else case return_value_expected when :dont_care # do nothing when true check(!return_value.nil?, "Should return a value") else check(return_value.nil?, "Should not return a value but returned <#{return_value}>") end end return_value end def check_nothing_fails(return_value_expected=false, &proc) check_assertions(false, {:expected_message => nil, :return_value_expected => return_value_expected}, &proc) end def check_fail(expected_message, options={}, &proc) check_assertions(true, options.merge(:expected_message => expected_message), &proc) end def check_fail_exception(expected_message, options={}, &proc) normalizer = lambda do |actual_message| actual_message.gsub(/(^[^:\n]+:\d+:.+\n?)+\z/, "") end check_assertions(true, options.merge(:expected_message => expected_message, :actual_message_normalizer => normalizer), &proc) end def inspect_tag(tag) tag.inspect end def add_failure(message, location=caller, options=nil) unless @catch_assertions super end end def add_assertion if @catch_assertions @actual_assertion_count += 1 else super end end end class TestAssertions < TestCase include AssertionCheckable class TestAssertBlock < self def test_pass_without_message check_nothing_fails { assert_block {true} } end def test_pass_with_message check_nothing_fails { assert_block("successful assert_block") {true} } end def test_failure_without_message check_fail("assert_block failed.") { assert_block {false} } end def test_failure_with_message check_fail("failed assert_block") { assert_block("failed assert_block") {false} } end end class TestAssertEqual < self class TestSuccess < self def test_without_message check_nothing_fails { assert_equal("string1", "string1") } end def test_with_message check_nothing_fails { assert_equal("string1", "string1", "successful assert_equal") } end end class TestFailure < self def test_without_message message = <<-EOM.chomp <"string1"> expected but was <"string2">. diff: - string1 ? ^ + string2 ? ^ EOM check_fail(message) { assert_equal("string1", "string2") } end def test_with_message message = <<-EOM.chomp failed assert_equal. <"string1"> expected but was <"string2">. diff: - string1 ? ^ + string2 ? ^ EOM check_fail(message) { assert_equal("string1", "string2", "failed assert_equal") } end def test_with_message_proc message = <<-EOM.chomp failed assert_equal. <"string1"> expected but was <"string2">. diff: - string1 ? ^ + string2 ? ^ EOM check_fail(message) do assert_equal("string1", "string2", lambda {"failed assert_equal"}) end end end class TestSystemMessage < self def test_different_type message = <<-EOM.chomp <"111111"> expected but was <111111>. diff: - "111111" ? - - + 111111 EOM check_fail(message) do assert_equal("111111", 111111) end end def test_long_line expected = ["0123456789", "1123456789", "2123456789", "3123456789", "4123456789", "5123456789", "6123456789", "7123456789", "8123456789"].join actual = ["0000000000", "1123456789", "2123456789", "3123456789", "4123456789", "5123456789", "6123456789", "7123456789", "8123456789"].join message = <<-EOM.chomp <"#{expected}"> expected but was <"#{actual}">. diff: - #{expected} ? ^^^^^^^^^ + #{actual} ? ^^^^^^^^^ folded diff: - 012345678911234567892123456789312345678941234567895123456789612345678971234567 ? ^^^^^^^^^ + 000000000011234567892123456789312345678941234567895123456789612345678971234567 ? ^^^^^^^^^ 898123456789 EOM check_fail(message) do assert_equal(expected, actual) end end def test_too_small_difference message = <<-EOM.chomp <1> expected but was <2>. EOM check_fail(message) do assert_equal(1, 2) end end def test_same_inspected_objects now = Time.now now_without_usec = Time.at(now.to_i) message = <<-EOM.chomp <#{now.inspect}> expected but was <#{now.inspect}>. EOM check_fail(message) do assert_equal(now, now_without_usec) end end def test_multi_lines_result message = <<-EOM.chomp <#{AssertionMessage.convert("a\nb")}> expected but was <#{AssertionMessage.convert("x")}>. diff: + x - a - b EOM check_fail(message) do assert_equal("a\nb", "x") end end def test_large_string message = <<-EOM.chomp <#{AssertionMessage.convert("a\n" + "x" * 997)}> expected but was <#{AssertionMessage.convert("x")}>. diff: + x - a - #{"x" * 997} folded diff: + x - a #{(["- " + ("x" * 78)] * 12).join("\n")} - #{"x" * 61} EOM check_fail(message) do assert_equal("a\n" + "x" * 997, "x") end message = <<-EOM.chomp <#{AssertionMessage.convert("a\n" + "x" * 998)}> expected but was <#{AssertionMessage.convert("x")}>. EOM check_fail(message) do assert_equal("a\n" + "x" * 998, "x") end end def test_max_diff_target_string_size key = "TEST_UNIT_MAX_DIFF_TARGET_STRING_SIZE" before_value = ENV[key] ENV[key] = "100" begin message = <<-EOM.chomp <#{AssertionMessage.convert("a\n" + "x" * 97)}> expected but was <#{AssertionMessage.convert("x")}>. diff: + x - a - #{"x" * 97} folded diff: + x - a #{(["- " + ("x" * 78)]).join("\n")} - #{"x" * 19} EOM check_fail(message) do assert_equal("a\n" + "x" * 97, "x") end message = <<-EOM.chomp <#{AssertionMessage.convert("a\n" + "x" * 98)}> expected but was <#{AssertionMessage.convert("x")}>. EOM check_fail(message) do assert_equal("a\n" + "x" * 98, "x") end ensure ENV[key] = before_value end end def test_different_encoding utf8_string = "こんにちは" unless utf8_string.respond_to?(:force_encoding) omit("encoding test is for Ruby >= 1.9") end ascii_8bit_string = utf8_string.dup.force_encoding("ascii-8bit") message = <<-EOM.chomp <#{utf8_string.inspect}>("UTF-8") expected but was <#{ascii_8bit_string.inspect}>("ASCII-8BIT"). EOM check_fail(message) do assert_equal(utf8_string, ascii_8bit_string) end end def test_different_hash designers = { "Ruby" => "Matz", "Lisp" => "John McCarthy", } categories = { "LL" => ["Ruby", "Python"], "Heavy" => ["C", "C++"], } message = <<-EOM.chomp <{"Lisp"=>"John McCarthy", "Ruby"=>"Matz"}> expected but was <{"Heavy"=>["C", "C++"], "LL"=>["Ruby", "Python"]}>. EOM check_fail(message) do assert_equal(designers, categories) end end def test_recursive_hash alice = {"name" => "Alice"} bob = {"name" => "Bob"} alice["followers"] = [bob] bob["followers"] = [alice] message = <<-EOM.chomp <{"followers"=>[{"followers"=>[{...}], "name"=>"Bob"}], "name"=>"Alice"}> expected but was <{"followers"=>[{"followers"=>[{...}], "name"=>"Alice"}], "name"=>"Bob"}>. diff: - {"followers"=>[{"followers"=>[{...}], "name"=>"Bob"}], "name"=>"Alice"} ? ----------------- + {"followers"=>[{"followers"=>[{...}], "name"=>"Alice"}], "name"=>"Bob"} ? +++++++++++++++++ EOM check_fail(message) do assert_equal(alice, bob) end end def test_numeric numeric_family_class = Class.new(Numeric) do def inspect "inspect is called" end def to_s "to_s is called" end end numeric = numeric_family_class.new message = <<-MESSAGE.chomp expected but was <"must be failed">. MESSAGE check_fail(message) do assert_equal(numeric, "must be failed") end end end end def test_assert_raise_success return_value = nil check_nothing_fails(true) do return_value = assert_raise(RuntimeError) do raise "Error" end end check(return_value.kind_of?(Exception), "Should have returned the exception " + "from a successful assert_raise") check(return_value.message == "Error", "Should have returned the correct exception " + "from a successful assert_raise") check_nothing_fails(true) do assert_raise(ArgumentError, "successful assert_raise") do raise ArgumentError.new("Error") end end check_nothing_fails(true) do assert_raise(RuntimeError) do raise "Error" end end check_nothing_fails(true) do assert_raise(RuntimeError, "successful assert_raise") do raise "Error" end end check_nothing_fails(true) do assert_raise do raise Exception, "Any exception" end end end def test_assert_raise_fail check_fail(" exception was expected but none was thrown.") do assert_raise(RuntimeError) do 1 + 1 end end message = <<-EOM.chomp failed assert_raise. exception expected but was )>. EOM check_fail_exception(message) do assert_raise(ArgumentError, "failed assert_raise") do raise "Error" end end message = <<-EOM must be a subclass of Exception, an object of Exception subclasses or a Module. EOM check_fail(message.chomp) do assert_nothing_raised(Object) do 1 + 1 end end end def test_assert_raise_module exceptions = [ArgumentError, TypeError] modules = [Math, Comparable] rescues = exceptions + modules exceptions.each do |exc| return_value = nil check_nothing_fails(true) do return_value = assert_raise(*rescues) do raise exc, "Error" end end check(return_value.instance_of?(exc), "Should have returned #{exc} but was #{return_value.class}") check(return_value.message == "Error", "Should have returned the correct exception " + "from a successful assert_raise") end modules.each do |mod| return_value = nil check_nothing_fails(true) do return_value = assert_raise(*rescues) do raise Exception.new("Error").extend(mod) end end check(mod === return_value, "Should have returned #{mod}") check(return_value.message == "Error", "Should have returned the correct exception " + "from a successful assert_raise") end check_fail("<[ArgumentError, TypeError, Math, Comparable]> exception " + "was expected but none was thrown.") do assert_raise(*rescues) do 1 + 1 end end message = <<-EOM.chomp failed assert_raise. <[ArgumentError, TypeError]> exception expected but was )>. EOM check_fail_exception(message) do assert_raise(ArgumentError, TypeError, "failed assert_raise") do raise "Error" end end end def test_assert_raise_instance return_value = nil check_nothing_fails(true) do return_value = assert_raise(RuntimeError.new("Error")) do raise "Error" end end check(return_value.kind_of?(Exception), "Should have returned the exception " + "from a successful assert_raise") check(return_value.message == "Error", "Should have returned the correct exception " + "from a successful assert_raise") message = <<-EOM.chomp )> exception expected but was )>. diff: - RuntimeError() ? ^^^ + RuntimeError() ? ^^^^^ EOM check_fail_exception(message) do return_value = assert_raise(RuntimeError.new("XXX")) do raise "Error" end end different_error_class = Class.new(StandardError) message = <<-EOM.chomp <#{different_error_class.inspect}()> exception expected but was )>. EOM check_fail_exception(message) do assert_raise(different_error_class.new("Error")) do raise "Error" end end different_error = different_error_class.new("Error") def different_error.inspect "DifferentError: \"Error\"" end message = <<-EOM.chomp exception expected but was )>. EOM check_fail_exception(message) do assert_raise(different_error) do raise "Error" end end check_nothing_fails(true) do assert_raise(different_error_class.new("Error"), RuntimeError.new("Error"), RuntimeError.new("XXX")) do raise "Error" end end end def test_assert_raise_jruby omit("For JRuby") unless Object.const_defined?(:Java) exception = Java::JavaLang::StringIndexOutOfBoundsException return_value = nil check_nothing_fails(true) do return_value = assert_raise(exception) do Java::JavaLang::String.new("abc").char_at(4) end end check(return_value.instance_of?(exception), "Should have returned #{exception} but was #{return_value.class}") end def test_assert_instance_of check_nothing_fails { assert_instance_of(String, "string") } check_nothing_fails { assert_instance_of(String, "string", "successful assert_instance_of") } check_nothing_fails { assert_instance_of(String, "string", "successful assert_instance_of") } check_fail(%Q{<"string"> was expected to be instance_of?\n but was\n.}) { assert_instance_of(Hash, "string") } check_fail(%Q{failed assert_instance_of.\n<"string"> was expected to be instance_of?\n but was\n.}) { assert_instance_of(Hash, "string", "failed assert_instance_of") } check_nothing_fails do assert_instance_of([Class, NilClass], Array) end check_fail(%Q{<"string"> was expected to be instance_of?\n[, ] but was\n.}) do assert_instance_of([Class, NilClass], "string") end check_fail(%Q{ was expected to be instance_of?\n[, ] but was\n.}) do assert_instance_of([Module, NilClass], Array) end end def test_assert_not_instance_of check_nothing_fails { assert_not_instance_of(NilClass, "string") } check_nothing_fails { assert_not_instance_of(NilClass, "string", "successful assert_instance_of") } check_fail(%Q{<"string"> was expected to not be instance_of?\n but was.}) { assert_not_instance_of(String, "string") } check_fail(%Q{failed assert.\n<"string"> was expected to not be instance_of?\n but was.}) { assert_not_instance_of(String, "string", "failed assert") } check_nothing_fails do assert_not_instance_of([Module, NilClass], Array) end check_fail(%Q{ was expected to not be instance_of?\n[, ] but was.}) do assert_not_instance_of([Class, NilClass], Array) end check_fail(%Q{<"str"> was expected to not be instance_of?\n[, ] but was.}) do assert_not_instance_of([Numeric, String], 'str') end end def test_assert_nil check_nothing_fails { assert_nil(nil) } check_nothing_fails { assert_nil(nil, "successful assert_nil") } check_nothing_fails { assert_nil(nil, "successful assert_nil") } check_fail(%Q{<"string"> was expected to be nil.}) { assert_nil("string") } check_fail(%Q{failed assert_nil.\n<"string"> was expected to be nil.}) { assert_nil("string", "failed assert_nil") } end def test_assert_not_nil check_nothing_fails{assert_not_nil(false)} check_nothing_fails{assert_not_nil(false, "message")} check_fail(" was expected to not be nil."){assert_not_nil(nil)} check_fail("message.\n was expected to not be nil.") {assert_not_nil(nil, "message")} end def test_assert_kind_of check_nothing_fails { assert_kind_of(Module, Array) } check_nothing_fails { assert_kind_of(Object, "string", "successful assert_kind_of") } check_nothing_fails { assert_kind_of(String, "string", "successful assert_kind_of") } check_nothing_fails { assert_kind_of(Comparable, 1) } check_fail(%Q{<"string"> was expected to be kind_of?\n but was\n.}) { assert_kind_of(Class, "string") } check_fail(%Q{failed assert_kind_of.\n<"string"> was expected to be kind_of?\n but was\n.}) { assert_kind_of(Class, "string", "failed assert_kind_of") } check_nothing_fails do assert_kind_of([Class, NilClass], Array) end check_fail(%Q{<"string"> was expected to be kind_of?\n[, ] but was\n.}) do assert_kind_of([Class, NilClass], "string") end end def test_assert_not_kind_of check_nothing_fails { assert_not_kind_of(Class, 42) } check_nothing_fails { assert_not_kind_of(Symbol, "string", "successful assert_not_kind_of") } check_nothing_fails { assert_not_kind_of(Integer, 1.1) } check_fail(%Q{<1> was expected to not be kind_of?\n but was.}) { assert_not_kind_of(Integer, 1) } check_fail(%Q{failed assert_not_kind_of.\n<"string"> was expected to not be kind_of?\n but was.}) { assert_not_kind_of(String, "string", "failed assert_not_kind_of") } check_nothing_fails do assert_not_kind_of([String, NilClass], 100) end check_fail(%Q{ was expected to not be kind_of?\n[, ] but was.}) do assert_not_kind_of([Class, NilClass], Array) end end def test_assert_match check_nothing_fails { assert_match(/strin./, "string") } check_nothing_fails { assert_match("strin", "string") } check_nothing_fails { assert_match(/strin./, "string", "successful assert_match") } check_nothing_fails { assert_match(/strin./, "string", "successful assert_match") } check_fail(%Q{ was expected to be =~\n<"string">.}) { assert_match(/slin./, "string") } check_fail(%Q{ was expected to be =~\n<"string">.}) { assert_match("strin.", "string") } check_fail(%Q{failed assert_match.\n was expected to be =~\n<"string">.}) { assert_match(/slin./, "string", "failed assert_match") } end def test_assert_same thing = "thing" check_nothing_fails { assert_same(thing, thing) } check_nothing_fails { assert_same(thing, thing, "successful assert_same") } check_nothing_fails { assert_same(thing, thing, "successful assert_same") } thing2 = thing.dup check_fail(%Q{<"thing">\nwith id <#{thing.__id__}> was expected to be equal? to\n<"thing">\nwith id <#{thing2.__id__}>.}) { assert_same(thing, thing2) } check_fail(%Q{failed assert_same.\n<"thing">\nwith id <#{thing.__id__}> was expected to be equal? to\n<"thing">\nwith id <#{thing2.__id__}>.}) { assert_same(thing, thing2, "failed assert_same") } end def test_assert_nothing_raised check_nothing_fails(:dont_care) { assert_nothing_raised { 1 + 1 } } check_nothing_fails(:dont_care) { assert_nothing_raised("successful assert_nothing_raised") { 1 + 1 } } check_nothing_fails(:dont_care) { assert_nothing_raised("successful assert_nothing_raised") { 1 + 1 } } check_nothing_fails(:dont_care) { begin assert_nothing_raised(RuntimeError, StandardError, Comparable, "successful assert_nothing_raised") { raise ZeroDivisionError.new("ArgumentError") } rescue ZeroDivisionError end } expected_message = " must be a subclass of Exception, " + "an object of Exception subclasses or a Module." check_fail(expected_message) { assert_nothing_raised(Object) { 1 + 1 } } expected_message = <<-EOM.chomp Exception raised: RuntimeError() EOM check_fail_exception(expected_message) { assert_nothing_raised { raise "Error" } } expected_message = <<-EOM.chomp failed assert_nothing_raised. Exception raised: RuntimeError() EOM check_fail_exception(expected_message) { assert_nothing_raised("failed assert_nothing_raised") { raise "Error" } } expected_message = <<-EOM.chomp Exception raised: RuntimeError() EOM check_fail_exception(expected_message) { assert_nothing_raised(StandardError, RuntimeError) { raise "Error" } } check_fail("Failure.") do assert_nothing_raised do flunk("Failure") end end end def test_flunk check_fail("Flunked.") { flunk } check_fail("flunk message.") { flunk("flunk message") } end def test_assert_not_same thing = "thing" thing2 = thing.dup check_nothing_fails { assert_not_same(thing, thing2) } check_nothing_fails { assert_not_same(thing, thing2, "message") } check_fail(%Q{<"thing">\nwith id <#{thing.__id__}> was expected to not be equal? to\n<"thing">\nwith id <#{thing.__id__}>.}) { assert_not_same(thing, thing) } check_fail(%Q{message.\n<"thing">\nwith id <#{thing.__id__}> was expected to not be equal? to\n<"thing">\nwith id <#{thing.__id__}>.}) { assert_not_same(thing, thing, "message") } end def test_assert_not_equal check_nothing_fails { assert_not_equal("string1", "string2") } check_nothing_fails { assert_not_equal("string1", "string2", "message") } check_fail(%Q{<"string"> was expected to be != to\n<"string">.}) { assert_not_equal("string", "string") } check_fail(%Q{message.\n<"string"> was expected to be != to\n<"string">.}) { assert_not_equal("string", "string", "message") } end def test_assert_not_match_pass check_nothing_fails do assert_not_match(/sling/, "string") end end def test_assert_not_match_pass_with_message check_nothing_fails do assert_not_match(/sling/, "string", "message") end end def test_assert_not_match_fail_not_regexp check_fail(" in assert_not_match(, ...) " + "should be a Regexp.\n" + "<\"asdf\"> was expected to be instance_of?\n" + " but was\n" + ".") do assert_not_match("asdf", "asdf") end end def test_assert_not_match_fail_match check_fail(" was expected to not match\n" + "<\"string\">.") do assert_not_match(/string/, "string") end end def test_assert_not_match_fail_match_with_message check_fail("message.\n" + " was expected to not match\n" + "<\"string\">.") do assert_not_match(/string/, "string", "message") end end def test_assert_no_match check_nothing_fails{assert_no_match(/sling/, "string")} check_nothing_fails{assert_no_match(/sling/, "string", "message")} check_fail(%Q{The first argument to assert_no_match should be a Regexp.\n<"asdf"> was expected to be instance_of?\n but was\n.}) do assert_no_match("asdf", "asdf") end check_fail(%Q{ was expected to not match\n<"string">.}) do assert_no_match(/string/, "string") end check_fail(%Q{message.\n was expected to not match\n<"string">.}) do assert_no_match(/string/, "string", "message") end end def test_assert_throw check_nothing_fails do assert_throw(:thing, "message") do throw :thing end end tag = :thing2 check_fail("message.\n" + "<:thing> was expected to be thrown but\n" + "<#{inspect_tag(tag)}> was thrown.") do assert_throw(:thing, "message") do throw :thing2 end end check_fail("message.\n" + "<:thing> should have been thrown.") do assert_throw(:thing, "message") do 1 + 1 end end end def test_assert_nothing_thrown check_nothing_fails do assert_nothing_thrown("message") do 1 + 1 end end tag = :thing inspected = inspect_tag(tag) check_fail("message.\n" + "<#{inspected}> was thrown when nothing was expected.") do assert_nothing_thrown("message") do throw tag end end end def test_assert_operator check_nothing_fails { assert_operator("thing", :==, "thing", "message") } check_fail(%Q{<0.15>\ngiven as the operator for #assert_operator must be a Symbol or #respond_to?(:to_str).}) do assert_operator("thing", 0.15, "thing") end check_fail(%Q{message.\n<"thing1"> was expected to be\n==\n<"thing2">.}) { assert_operator("thing1", :==, "thing2", "message") } end def test_assert_not_operator check_nothing_fails { assert_not_operator("thing", :==, "Thing", "message") } check_fail(%Q{<42>\ngiven as the operator for #assert_not_operator must be a Symbol or #respond_to?(:to_str).}) do assert_not_operator("thing", 42, "message") end check_fail(%Q{message.\n<0> was expected to not be\n==\n<0.0>.}) { assert_not_operator(0, :==, 0.0, "message") } end def test_assert_respond_to check_nothing_fails { assert_respond_to("thing", :to_s, "message") } check_nothing_fails { assert_respond_to("thing", "to_s", "message") } check_fail("<0.15>.kind_of?(Symbol) or\n" + "<0.15>.respond_to?(:to_str) expected") { assert_respond_to("thing", 0.15) } check_fail("message.\n" + "<:symbol>.respond_to?(:nonexistence) expected\n" + "(Class: )") { assert_respond_to(:symbol, :nonexistence, "message") } end def test_assert_not_respond_to_pass_symbol check_nothing_fails do assert_not_respond_to("thing", :nonexistent, "message") end end def test_assert_not_respond_to_pass_string check_nothing_fails do assert_not_respond_to("thing", :nonexistent, "message") end end def test_assert_not_respond_to_fail_number check_fail("<0.15>.kind_of?(Symbol) or\n" + "<0.15>.respond_to?(:to_str) expected") do assert_respond_to("thing", 0.15) end end def tset_assert_not_respond_to_fail_existence check_fail("message.\n" + "!<:symbol>.respond_to?(:to_s) expected\n" + "(Class: )") do assert_respond_to(:symbol, :to_s, "message") end end def test_assert_send object = Object.new class << object private def return_argument(argument, bogus) return argument end end check_nothing_fails do assert_send([object, :return_argument, true, "bogus"], "message") end inspected_object = AssertionMessage.convert(object) expected_message = <<-EOM message. <#{inspected_object}> was expected to respond to with a true value but was . EOM check_fail(expected_message.chomp) do assert_send([object, :return_argument, false, "bogus"], "message") end end def test_condition_invariant object = Object.new def object.inspect @changed = true end def object.==(other) @changed ||= false return (!@changed) end check_nothing_fails do assert_equal(object, object, "message") end end def test_assert_boolean check_nothing_fails do assert_boolean(true) end check_nothing_fails do assert_boolean(false) end check_fail(" or expected but was\n<1>") do assert_boolean(1) end check_fail(" or expected but was\n") do assert_boolean(nil) end check_fail("message.\n or expected but was\n<\"XXX\">") do assert_boolean("XXX", "message") end end def test_assert_true check_nothing_fails do assert_true(true) end check_fail(" expected but was\n") do assert_true(false) end check_fail(" expected but was\n<1>") do assert_true(1) end check_fail("message.\n expected but was\n") do assert_true(nil, "message") end end def test_assert_false check_nothing_fails do assert_false(false) end check_fail(" expected but was\n") do assert_false(true) end check_fail(" expected but was\n") do assert_false(nil) end check_fail("message.\n expected but was\n<:false>") do assert_false(:false, "message") end end def test_assert_compare check_nothing_fails do assert_compare(1.4, "<", 10.0) end check_nothing_fails do assert_compare(2, "<=", 2) end check_nothing_fails do assert_compare(14, ">=", 10.0) end check_nothing_fails do assert_compare(14, ">", 13.9) end expected_message = <<-EOM <15> < <10> should be true <15> was expected to be less than <10>. EOM check_fail(expected_message.chomp) do assert_compare(15, "<", 10) end expected_message = <<-EOM <15> <= <10> should be true <15> was expected to be less than or equal to <10>. EOM check_fail(expected_message.chomp) do assert_compare(15, "<=", 10) end expected_message = <<-EOM <10> > <15> should be true <10> was expected to be greater than <15>. EOM check_fail(expected_message.chomp) do assert_compare(10, ">", 15) end expected_message = <<-EOM <10> >= <15> should be true <10> was expected to be greater than or equal to <15>. EOM check_fail(expected_message.chomp) do assert_compare(10, ">=", 15) end end def test_assert_fail_assertion check_nothing_fails do assert_fail_assertion do flunk end end check_fail("Failed assertion was expected.") do assert_fail_assertion do end end end def test_assert_raise_message check_nothing_fails do assert_raise_message("Raise!") do raise "Raise!" end end check_nothing_fails do assert_raise_message("Raise!") do raise Exception, "Raise!" end end check_nothing_fails do assert_raise_message(/raise/i) do raise "Raise!" end end expected_message = <<-EOM <"Expected message"> exception message expected but was <"Actual message">. EOM check_fail(expected_message.chomp) do assert_raise_message("Expected message") do raise "Actual message" end end expected_message = <<-EOM <"Expected message"> exception message was expected but none was thrown. EOM check_fail(expected_message.chomp) do assert_raise_message("Expected message") do end end end def test_assert_raise_kind_of check_nothing_fails(true) do assert_raise_kind_of(SystemCallError) do raise Errno::EACCES end end expected_message = <<-EOM.chomp family exception expected but was )>. EOM check_fail_exception(expected_message) do assert_raise_kind_of(SystemCallError) do raise RuntimeError, "XXX" end end end def test_assert_const_defined check_nothing_fails do assert_const_defined(Test, :Unit) end check_nothing_fails do assert_const_defined(Test, "Unit") end check_fail(".const_defined?(<:Nonexistence>) expected.") do assert_const_defined(Test, :Nonexistence) end end def test_assert_not_const_defined check_nothing_fails do assert_not_const_defined(Test, :Nonexistence) end check_fail("!.const_defined?(<:Unit>) expected.") do assert_not_const_defined(Test, :Unit) end check_fail("!.const_defined?(<\"Unit\">) expected.") do assert_not_const_defined(Test, "Unit") end end def test_assert_predicate check_nothing_fails do assert_predicate([], :empty?) end check_fail("<[1]>.empty? is true value expected but was\n") do assert_predicate([1], :empty?) end check_fail("<[1]>.respond_to?(:nonexistent?) expected\n" + "(Class: )") do assert_predicate([1], :nonexistent?) end end def test_assert_not_predicate check_nothing_fails do assert_not_predicate([1], :empty?) end check_fail("<[]>.empty? is false value expected but was\n") do assert_not_predicate([], :empty?) end check_fail("<[]>.respond_to?(:nonexistent?) expected\n" + "(Class: )") do assert_not_predicate([], :nonexistent?) end end def test_assert_alias_method object = Object.new class << object def original_method end alias_method :alias_method, :original_method def other end end check_nothing_fails do assert_alias_method(object, :alias_method, :original_method) end check_nothing_fails do assert_alias_method(object, :original_method, :alias_method) end check_fail("<#{object.method(:other).inspect}> is alias of\n" + "<#{object.method(:original_method).inspect}> expected") do assert_alias_method(object, :other, :original_method) end inspected_object = AssertionMessage.convert(object) check_fail("<#{inspected_object}>.nonexistent doesn't exist\n" + "(Class: )") do assert_alias_method(object, :nonexistent, :original_method) end check_fail("<#{inspected_object}>.nonexistent doesn't exist\n" + "(Class: )") do assert_alias_method(object, :alias_method, :nonexistent) end end def test_assert_path_exist check_nothing_fails do assert_path_exist(__FILE__) end nonexistent_file = __FILE__ + ".nonexistent" check_fail("<#{nonexistent_file.inspect}> was expected to exist") do assert_path_exist(nonexistent_file) end end def test_assert_path_not_exist nonexistent_file = __FILE__ + ".nonexistent" check_nothing_fails do assert_path_not_exist(nonexistent_file) end check_fail("<#{__FILE__.inspect}> was expected to not exist") do assert_path_not_exist(__FILE__) end end end class TestAssert < TestCase include AssertionCheckable def test_pass check_nothing_fails do assert(true) end end def test_pass_neither_false_or_nil check_nothing_fails do assert("a") end end def test_pass_with_message check_nothing_fails do assert(true, "successful assert") end end def test_pass_block check_nothing_fails do assert do true end end end def test_fail_nil check_fail(" is not true.") do assert(nil) end end def test_fail_false check_fail(" is not true.") do assert(false) end end def test_fail_false_with_message check_fail("failed assert.\n" + " is not true.") do assert(false, "failed assert") end end def test_fail_with_assertion_message check_fail("user message.\n" + "placeholder <:in> message") do assert(false, build_message("user message", "placeholder message", :in)) end end def test_fail_block check_fail(//) do assert do 0.odd? end end end def test_error_invalid_message_true check_fail("assertion message must be String, Proc or " + "Test::Unit::Assertions::AssertionMessage: " + "()") do begin assert(true, true) rescue ArgumentError raise AssertionFailedError, $!.message end end end def test_error_wrong_number_of_arguments check_fail("wrong number of arguments (0 for 1..2)") do begin assert rescue ArgumentError raise AssertionFailedError, $!.message end end end class TestBlock < self def test_with_message if defined?(PowerAssert) system_message = <<-MESSAGE.chomp 1.to_s == "2" | | | false "1" MESSAGE else system_message = " is not true." end check_fail("user message.\n#{system_message}") do assert("user message") do 1.to_s == "2" end end end end end class TestRefute < TestCase include AssertionCheckable class TestPass < self def test_nil check_nothing_fails do refute(nil) end end def test_false check_nothing_fails do refute(false) end end def test_with_message check_nothing_fails do refute(nil, "successful refute") end end end class TestFailure < self def test_true check_fail(" is neither nil or false.") do refute(true) end end def test_with_message check_fail("failed refute.\n" + " is neither nil or false.") do refute(true, "failed refute") end end def test_fail_with_assertion_message check_fail("user message.\n" + "placeholder <:in> message") do refute(true, build_message("user message", "placeholder message", :in)) end end def test_error_invalid_message_true check_fail("assertion message must be String, Proc or " + "Test::Unit::Assertions::AssertionMessage: " + "()") do begin refute(true, false) rescue ArgumentError raise AssertionFailedError, $!.message end end end end end class TestAssertInDelta < TestCase include AssertionCheckable def test_pass check_nothing_fails do assert_in_delta(1.4, 1.4, 0) end end def test_pass_without_delta check_nothing_fails do assert_in_delta(1.401, 1.402) end end def test_pass_with_message check_nothing_fails do assert_in_delta(0.5, 0.4, 0.1, "message") end end def test_pass_float_like_object check_nothing_fails do float_thing = Object.new def float_thing.to_f 0.2 end assert_in_delta(0.1, float_thing, 0.1) end end def test_pass_string_expected check_nothing_fails do assert_in_delta("0.5", 0.4, 0.1) end end def test_fail_with_message check_fail("message.\n" + "<0.5> -/+ <0.05> was expected to include\n" + "<0.4>.\n" + "\n" + "Relation:\n" + "<<0.4> < <0.5>-<0.05>[0.45] <= <0.5>+<0.05>[0.55]>") do assert_in_delta(0.5, 0.4, 0.05, "message") end end def test_fail_because_not_float_like_object object = Object.new inspected_object = AssertionMessage.convert(object) check_fail("The arguments must respond to to_f; " + "the first float did not.\n" + "<#{inspected_object}>.respond_to?(:to_f) expected\n" + "(Class: )") do assert_in_delta(object, 0.4, 0.1) end end def test_fail_because_negaitve_delta check_fail("The delta should not be negative.\n" + "<-0.1> was expected to be\n>=\n<0.0>.") do assert_in_delta(0.5, 0.4, -0.1, "message") end end def test_fail_without_delta check_fail("<1.402> -/+ <0.001> was expected to include\n" + "<1.404>.\n" + "\n" + "Relation:\n" + "<" + "<1.402>-<0.001>[#{1.402 - 0.001}] <= " + "<1.402>+<0.001>[#{1.402 + 0.001}] < " + "<1.404>" + ">") do assert_in_delta(1.402, 1.404) end end end class TestAssertNotInDelta < Test::Unit::TestCase include AssertionCheckable def test_pass check_nothing_fails do assert_not_in_delta(1.42, 1.44, 0.01) end end def test_pass_without_delta check_nothing_fails do assert_not_in_delta(1.402, 1.404) end end def test_pass_with_message check_nothing_fails do assert_not_in_delta(0.5, 0.4, 0.09, "message") end end def test_pass_float_like_object check_nothing_fails do float_thing = Object.new def float_thing.to_f 0.2 end assert_not_in_delta(0.1, float_thing, 0.09) end end def test_pass_string_epxected check_nothing_fails do assert_not_in_delta("0.5", 0.4, 0.09) end end def test_fail check_fail("<1.4> -/+ <0.11> was expected to not include\n" + "<1.5>.\n" + "\n" + "Relation:\n" + "<" + "<1.4>-<0.11>[#{1.4 - 0.11}] <= " + "<1.5> <= " + "<1.4>+<0.11>[#{1.4 + 0.11}]" + ">") do assert_not_in_delta(1.4, 1.5, 0.11) end end def test_fail_without_delta check_fail("<1.402> -/+ <0.001> was expected to not include\n" + "<1.4021>.\n" + "\n" + "Relation:\n" + "<" + "<1.402>-<0.001>[#{1.402 - 0.001}] <= " + "<1.4021> <= " + "<1.402>+<0.001>[#{1.402 + 0.001}]" + ">") do assert_not_in_delta(1.402, 1.4021) end end def test_fail_with_message check_fail("message.\n" + "<0.5> -/+ <0.11> was expected to not include\n" + "<0.4>.\n" + "\n" + "Relation:\n" + "<" + "<0.5>-<0.11>[0.39] <= " + "<0.4> <= " + "<0.5>+<0.11>[0.61]" + ">") do assert_not_in_delta(0.5, 0.4, 0.11, "message") end end def test_fail_because_not_float_like_object object = Object.new inspected_object = AssertionMessage.convert(object) check_fail("The arguments must respond to to_f; " + "the first float did not.\n" + "<#{inspected_object}>.respond_to?(:to_f) expected\n" + "(Class: )") do assert_not_in_delta(object, 0.4, 0.1) end end def test_fail_because_negaitve_delta check_fail("The delta should not be negative.\n" + "<-0.11> was expected to be\n>=\n<0.0>.") do assert_not_in_delta(0.5, 0.4, -0.11, "message") end end end class TestAssertInEpsilon < TestCase include AssertionCheckable def test_pass check_nothing_fails do assert_in_epsilon(10000, 9000, 0.1) end end def test_pass_without_epsilon check_nothing_fails do assert_in_epsilon(10000, 9991) end end def test_pass_with_message check_nothing_fails do assert_in_epsilon(10000, 9000, 0.1, "message") end end def test_pass_float_like_object check_nothing_fails do float_thing = Object.new def float_thing.to_f 9000.0 end assert_in_epsilon(10000, float_thing, 0.1) end end def test_pass_string_expected check_nothing_fails do assert_in_epsilon("10000", 9000, 0.1) end end def test_pass_zero_expected check_nothing_fails do assert_in_epsilon(0, 0.00000001) end end def test_pass_minus_expected check_nothing_fails do assert_in_epsilon(-1, -1) end end def test_fail_with_message check_fail("message.\n" + "<10000> -/+ (<10000> * <0.1>)[1000.0] " + "was expected to include\n" + "<8999>.\n" + "\n" + "Relation:\n" + "<" + "<8999> < " + "<10000>-(<10000>*<0.1>)[9000.0] <= " + "<10000>+(<10000>*<0.1>)[11000.0]" + ">") do assert_in_epsilon(10000, 8999, 0.1, "message") end end def test_fail_because_not_float_like_object object = Object.new inspected_object = AssertionMessage.convert(object) check_fail("The arguments must respond to to_f; " + "the first float did not.\n" + "<#{inspected_object}>.respond_to?(:to_f) expected\n" + "(Class: )") do assert_in_epsilon(object, 9000, 0.1) end end def test_fail_because_negaitve_epsilon check_fail("The epsilon should not be negative.\n" + "<-0.1> was expected to be\n>=\n<0.0>.") do assert_in_epsilon(10000, 9000, -0.1, "message") end end def test_fail_without_epsilon check_fail("<10000> -/+ (<10000> * <0.001>)[10.0] " + "was expected to include\n" + "<10011>.\n" + "\n" + "Relation:\n" + "<" + "<10000>-(<10000>*<0.001>)[9990.0] <= " + "<10000>+(<10000>*<0.001>)[10010.0] < " + "<10011>" + ">") do assert_in_epsilon(10000, 10011) end end end class TestAssertNotInEpsilon < Test::Unit::TestCase include AssertionCheckable def test_pass check_nothing_fails do assert_not_in_epsilon(10000, 8999, 0.1) end end def test_pass_without_epsilon check_nothing_fails do assert_not_in_epsilon(10000, 9989) end end def test_pass_with_message check_nothing_fails do assert_not_in_epsilon(10000, 8999, 0.1, "message") end end def test_pass_float_like_object check_nothing_fails do float_thing = Object.new def float_thing.to_f 8999.0 end assert_not_in_epsilon(10000, float_thing, 0.1) end end def test_pass_string_epxected check_nothing_fails do assert_not_in_epsilon("10000", 8999, 0.1) end end def test_fail check_fail("<10000> -/+ (<10000> * <0.1>)[1000.0] " + "was expected to not include\n" + "<9000>.\n" + "\n" + "Relation:\n" + "<" + "<10000>-(<10000>*<0.1>)[9000.0] <= " + "<9000> <= " + "<10000>+(<10000>*<0.1>)[11000.0]" + ">") do assert_not_in_epsilon(10000, 9000, 0.1) end end def test_fail_without_epsilon check_fail("<10000> -/+ (<10000> * <0.001>)[10.0] " + "was expected to not include\n" + "<9990>.\n" + "\n" + "Relation:\n" + "<" + "<10000>-(<10000>*<0.001>)[9990.0] <= " + "<9990> <= " + "<10000>+(<10000>*<0.001>)[10010.0]" + ">") do assert_not_in_epsilon(10000, 9990) end end def test_fail_with_message check_fail("message.\n" + "<10000> -/+ (<10000> * <0.1>)[1000.0] " + "was expected to not include\n" + "<9000>.\n" + "\n" + "Relation:\n" + "<" + "<10000>-(<10000>*<0.1>)[9000.0] <= " + "<9000> <= " + "<10000>+(<10000>*<0.1>)[11000.0]" + ">") do assert_not_in_epsilon(10000, 9000, 0.1, "message") end end def test_fail_because_not_float_like_object object = Object.new inspected_object = AssertionMessage.convert(object) check_fail("The arguments must respond to to_f; " + "the first float did not.\n" + "<#{inspected_object}>.respond_to?(:to_f) expected\n" + "(Class: )") do assert_not_in_epsilon(object, 9000, 0.1) end end def test_fail_because_negaitve_epsilon check_fail("The epsilon should not be negative.\n" + "<-0.1> was expected to be\n>=\n<0.0>.") do assert_not_in_epsilon(10000, 9000, -0.1, "message") end end end class TestAssertInclude < Test::Unit::TestCase include AssertionCheckable def test_pass check_nothing_fails do assert_include([1, 2, 3], 1) end end def test_pass_with_message check_nothing_fails do assert_include([1, 2, 3], 1, "message") end end def test_fail check_fail("<[1, 2, 3]> was expected to include\n" + "<4>.") do assert_include([1, 2, 3], 4) end end def test_fail_with_message check_fail("message.\n" + "<[1, 2, 3]> was expected to include\n" + "<4>.") do assert_include([1, 2, 3], 4, "message") end end def test_fail_because_not_collection_like_object object = Object.new inspected_object = AssertionMessage.convert(object) check_fail("The collection must respond to :include?.\n" + "<#{inspected_object}>.respond_to?(:include?) expected\n" + "(Class: )") do assert_include(object, 1) end end end class TestAssertNotInclude < Test::Unit::TestCase include AssertionCheckable def test_pass check_nothing_fails do assert_not_include([1, 2, 3], 5) end end def test_pass_with_message check_nothing_fails do assert_not_include([1, 2, 3], 5, "message") end end def test_fail check_fail("<[1, 2, 3]> was expected to not include\n" + "<2>.") do assert_not_include([1, 2, 3], 2) end end def test_fail_with_message check_fail("message.\n" + "<[1, 2, 3]> was expected to not include\n" + "<2>.") do assert_not_include([1, 2, 3], 2, "message") end end def test_fail_because_not_collection_like_object object = Object.new inspected_object = AssertionMessage.convert(object) check_fail("The collection must respond to :include?.\n" + "<#{inspected_object}>.respond_to?(:include?) expected\n" + "(Class: )") do assert_not_include(object, 1) end end end class TestAssertEmpty < Test::Unit::TestCase include AssertionCheckable def test_pass check_nothing_fails do assert_empty([]) end end def test_pass_with_message check_nothing_fails do assert_empty([], "message") end end def test_fail check_fail("<[1]> was expected to be empty.") do assert_empty([1]) end end def test_fail_with_message check_fail("message.\n" + "<[1]> was expected to be empty.") do assert_empty([1], "message") end end def test_fail_because_no_empty_method object = Object.new inspected_object = AssertionMessage.convert(object) check_fail("The object must respond to :empty?.\n" + "<#{inspected_object}>.respond_to?(:empty?) expected\n" + "(Class: )") do assert_empty(object) end end end class TestAssertNotEmpty < Test::Unit::TestCase include AssertionCheckable def test_pass check_nothing_fails do assert_not_empty([1]) end end def test_pass_with_message check_nothing_fails do assert_not_empty([1], "message") end end def test_fail check_fail("<[]> was expected to not be empty.") do assert_not_empty([]) end end def test_fail_with_message check_fail("message.\n" + "<[]> was expected to not be empty.") do assert_not_empty([], "message") end end def test_fail_because_no_empty_method object = Object.new inspected_object = AssertionMessage.convert(object) check_fail("The object must respond to :empty?.\n" + "<#{inspected_object}>.respond_to?(:empty?) expected\n" + "(Class: )") do assert_not_empty(object) end end end class TestAssertNotSend < Test::Unit::TestCase include AssertionCheckable def test_pass check_nothing_fails do assert_not_send([[1, 2], :member?, 4], "message") end end def test_fail expected_message = <<-EOM message. <[1, 2]> was expected to respond to with not a true value but was . EOM check_fail(expected_message.chomp) do assert_not_send([[1, 2], :member?, 2], "message") end end end class TestTemplate < Test::Unit::TestCase def test_incompatible_encoding_by_diff need_encoding assert_raise(AssertionFailedError) do assert_equal("UTF-8の日本語\n" * 3, ("Shift_JISの日本語\n" * 3).force_encoding("ASCII-8BIT")) end end private def need_encoding omit("need Encoding") unless Object.const_defined?(:Encoding) end end end end PK% ]kVV)gems/test-unit-3.2.9/test/test-fixture.rbnu[class TestUnitFixture < Test::Unit::TestCase module EmptyModule end class TestSetup < self def test_without_option expected_setup_calls = [:setup, :custom_setup_method0, :custom_setup_callback0, :custom_setup_method1, :custom_setup_callback1, :custom_setup_method3, :custom_setup_callback3] test_case = assert_setup(expected_setup_calls, []) assert_inherited_setup(expected_setup_calls, test_case) assert_inherited_setup([:setup], nil) assert_called_fixtures(expected_setup_calls, test_case) end def test_with_before_option expected_setup_calls = [:custom_setup_callback3, :custom_setup_method3, :custom_setup_method0, :custom_setup_callback0, :custom_setup_method1, :custom_setup_callback1, :setup] test_case = assert_setup(expected_setup_calls, [[{:before => :append}], [{:before => :append}], [{:before => :prepend}], [{:before => :prepend}]]) assert_inherited_setup(expected_setup_calls, test_case) assert_inherited_setup([:setup], nil) assert_called_fixtures(expected_setup_calls, test_case) end def test_with_after_option expected_setup_calls = [:setup, :custom_setup_callback3, :custom_setup_method3, :custom_setup_method0, :custom_setup_callback0, :custom_setup_method1, :custom_setup_callback1] test_case = assert_setup(expected_setup_calls, [[{:after => :append}], [{:after => :append}], [{:after => :prepend}], [{:after => :prepend}]]) assert_inherited_setup(expected_setup_calls, test_case) assert_inherited_setup([:setup], nil) assert_called_fixtures(expected_setup_calls, test_case) end def test_with_invalid_option assert_invalid_setup_option(:unknown => true) assert_invalid_setup_option(:before => :unknown) assert_invalid_setup_option(:after => :unknown) end def test_with_option_to_inherited expected_setup_calls = [:setup] test_case = assert_setup(expected_setup_calls, nil) assert_inherited_setup([:setup, :custom_setup_method0, :custom_setup_callback0, :custom_setup_method1, :custom_setup_callback1, :custom_setup_method3, :custom_setup_callback3], test_case, []) assert_inherited_setup([:setup], nil) assert_called_fixtures(expected_setup_calls, test_case) end private def assert_setup_customizable(expected, parent, options) test_case = Class.new(parent || Test::Unit::TestCase) do yield(self, :before) if block_given? def called_ids @called_ids ||= [] end def called(id) called_ids << id end def setup called(:setup) end setup(*(options[0] || [])) if options def custom_setup_method0 called(:custom_setup_method0) end if options setup(*(options[0] || [])) do called(:custom_setup_callback0) end end def custom_setup_method1 called(:custom_setup_method1) end setup(*[:custom_setup_method1, *(options[1] || [])]) if options if options setup(*(options[1] || [])) do called(:custom_setup_callback1) end end setup(*(options[2] || [])) if options def custom_setup_method2 called(:custom_setup_method2) end unregister_setup(:custom_setup_method2) if options if options callback = lambda do called(:custom_setup_callback2) end setup(*(options[2] || []), &callback) unregister_setup(callback) end setup(*(options[3] || [])) if options def custom_setup_method3 called(:custom_setup_method3) end if options setup(*(options[3] || [])) do called(:custom_setup_callback3) end end def test_nothing end yield(self, :after) if block_given? end assert_called_fixtures(expected, test_case) test_case end def assert_setup(expected, options) _test_case = assert_setup_customizable(expected, nil, options) assert_setup_customizable(expected, nil, options) do |test_case, tag| test_case.send(:include, EmptyModule) if tag == :before end _test_case end def assert_inherited_setup(expected, parent, options=nil) _test_case = assert_setup_customizable(expected, parent, options) assert_setup_customizable(expected, parent, options) do |test_case, tag| test_case.send(:include, EmptyModule) if tag == :before end _test_case end def assert_invalid_setup_option(option) assert_invalid_option(:setup, option) end end class TestCleanup < self def test_without_option expected_cleanup_calls = [:custom_cleanup_callback3, :custom_cleanup_method3, :custom_cleanup_callback1, :custom_cleanup_method1, :custom_cleanup_callback0, :custom_cleanup_method0, :cleanup] test_case = assert_cleanup(expected_cleanup_calls, []) assert_inherited_cleanup(expected_cleanup_calls, test_case) assert_inherited_cleanup([:cleanup], nil) assert_called_fixtures(expected_cleanup_calls, test_case) end def test_with_before_option expected_cleanup_calls = [:custom_cleanup_callback3, :custom_cleanup_method3, :custom_cleanup_method0, :custom_cleanup_callback0, :custom_cleanup_method1, :custom_cleanup_callback1, :cleanup] test_case = assert_cleanup(expected_cleanup_calls, [[{:before => :append}], [{:before => :append}], [{:before => :prepend}], [{:before => :prepend}]]) assert_inherited_cleanup(expected_cleanup_calls, test_case) assert_inherited_cleanup([:cleanup], nil) assert_called_fixtures(expected_cleanup_calls, test_case) end def test_with_after_option expected_cleanup_calls = [:cleanup, :custom_cleanup_callback3, :custom_cleanup_method3, :custom_cleanup_method0, :custom_cleanup_callback0, :custom_cleanup_method1, :custom_cleanup_callback1] test_case = assert_cleanup(expected_cleanup_calls, [[{:after => :append}], [{:after => :append}], [{:after => :prepend}], [{:after => :prepend}]]) assert_inherited_cleanup(expected_cleanup_calls, test_case) assert_inherited_cleanup([:cleanup], nil) assert_called_fixtures(expected_cleanup_calls, test_case) end def test_with_invalid_option assert_invalid_cleanup_option(:unknown => true) assert_invalid_cleanup_option(:before => :unknown) assert_invalid_cleanup_option(:after => :unknown) end def test_with_option_to_inherited expected_cleanup_calls = [:cleanup] test_case = assert_cleanup(expected_cleanup_calls, nil) assert_inherited_cleanup([:custom_cleanup_callback3, :custom_cleanup_method3, :custom_cleanup_callback1, :custom_cleanup_method1, :custom_cleanup_callback0, :custom_cleanup_method0, :cleanup], test_case, []) assert_inherited_cleanup([:cleanup], nil) assert_called_fixtures(expected_cleanup_calls, test_case) end def test_with_exception test_case = Class.new(Test::Unit::TestCase) do def called_ids @called_ids ||= [] end def called(id) called_ids << id end def cleanup called(:cleanup) raise "cleanup" end cleanup def custom_cleanup_method0 called(:custom_cleanup_method0) raise "custom_cleanup_method0" end cleanup do called(:custom_cleanup_callback0) raise "custom_cleanup_callback0" end cleanup def custom_cleanup_method1 called(:custom_cleanup_method1) raise "custom_cleanup_method1" end cleanup do called(:custom_cleanup_callback1) raise "custom_cleanup_callback1" end def test_nothing end end assert_called_fixtures([:custom_cleanup_callback1], test_case) end private def assert_cleanup_customizable(expected, parent, options) test_case = Class.new(parent || Test::Unit::TestCase) do yield(self, :before) if block_given? def called_ids @called_ids ||= [] end def called(id) called_ids << id end def cleanup called(:cleanup) end cleanup(*(options[0] || [])) if options def custom_cleanup_method0 called(:custom_cleanup_method0) end if options cleanup(*(options[0] || [])) do called(:custom_cleanup_callback0) end end def custom_cleanup_method1 called(:custom_cleanup_method1) end cleanup(*[:custom_cleanup_method1, *(options[1] || [])]) if options if options cleanup(*(options[1] || [])) do called(:custom_cleanup_callback1) end end cleanup(*(options[2] || [])) if options def custom_cleanup_method2 called(:custom_cleanup_method2) end unregister_cleanup(:custom_cleanup_method2) if options if options callback = lambda do called(:custom_cleanup_callback2) end cleanup(*(options[2] || []), &callback) unregister_cleanup(callback) end cleanup(*(options[3] || [])) if options def custom_cleanup_method3 called(:custom_cleanup_method3) end if options cleanup(*(options[3] || [])) do called(:custom_cleanup_callback3) end end def test_nothing end yield(self, :after) if block_given? end assert_called_fixtures(expected, test_case) test_case end def assert_cleanup(expected, options) assert_cleanup_customizable(expected, nil, options) assert_cleanup_customizable(expected, nil, options) do |test_case, tag| test_case.send(:include, EmptyModule) if tag == :before end end def assert_inherited_cleanup(expected, parent, options=nil) assert_cleanup_customizable(expected, parent, options) assert_cleanup_customizable(expected, parent, options) do |test_case, tag| test_case.send(:include, EmptyModule) if tag == :before end end def assert_invalid_cleanup_option(option) assert_invalid_option(:cleanup, option) end end class TestTeardown < self def test_without_option expected_teardown_calls = [:custom_teardown_callback3, :custom_teardown_method3, :custom_teardown_callback1, :custom_teardown_method1, :custom_teardown_callback0, :custom_teardown_method0, :teardown] test_case = assert_teardown(expected_teardown_calls, []) assert_inherited_teardown(expected_teardown_calls, test_case) assert_inherited_teardown([:teardown], nil) assert_called_fixtures(expected_teardown_calls, test_case) end def test_with_before_option expected_teardown_calls = [:custom_teardown_callback3, :custom_teardown_method3, :custom_teardown_method0, :custom_teardown_callback0, :custom_teardown_method1, :custom_teardown_callback1, :teardown] test_case = assert_teardown(expected_teardown_calls, [[{:before => :append}], [{:before => :append}], [{:before => :prepend}], [{:before => :prepend}]]) assert_inherited_teardown(expected_teardown_calls, test_case) assert_inherited_teardown([:teardown], nil) assert_called_fixtures(expected_teardown_calls, test_case) end def test_with_after_option expected_teardown_calls = [:teardown, :custom_teardown_callback3, :custom_teardown_method3, :custom_teardown_method0, :custom_teardown_callback0, :custom_teardown_method1, :custom_teardown_callback1] test_case = assert_teardown(expected_teardown_calls, [[{:after => :append}], [{:after => :append}], [{:after => :prepend}], [{:after => :prepend}]]) assert_inherited_teardown(expected_teardown_calls, test_case) assert_inherited_teardown([:teardown], nil) assert_called_fixtures(expected_teardown_calls, test_case) end def test_with_invalid_option assert_invalid_teardown_option(:unknown => true) assert_invalid_teardown_option(:before => :unknown) assert_invalid_teardown_option(:after => :unknown) end def test_with_option_to_inherited expected_teardown_calls = [:teardown] test_case = assert_teardown(expected_teardown_calls, nil) assert_inherited_teardown([:custom_teardown_callback3, :custom_teardown_method3, :custom_teardown_callback1, :custom_teardown_method1, :custom_teardown_callback0, :custom_teardown_method0, :teardown], test_case, []) assert_inherited_teardown([:teardown], nil) assert_called_fixtures(expected_teardown_calls, test_case) end def test_with_exception test_case = Class.new(Test::Unit::TestCase) do def called_ids @called_ids ||= [] end def called(id) called_ids << id end def teardown called(:teardown) raise "teardown" end teardown def custom_teardown_method0 called(:custom_teardown_method0) raise "custom_teardown_method0" end teardown do called(:custom_teardown_callback0) raise "custom_teardown_callback0" end teardown def custom_teardown_method1 called(:custom_teardown_method1) raise "custom_teardown_method1" end teardown do called(:custom_teardown_callback1) raise "custom_teardown_callback1" end def test_nothing end end assert_called_fixtures([:custom_teardown_callback1, :custom_teardown_method1, :custom_teardown_callback0, :custom_teardown_method0, :teardown], test_case) end def test_nested called = [] parent_test_case = Class.new(Test::Unit::TestCase) do teardown do called << :parent end end child_test_case = Class.new(parent_test_case) do teardown do called << :child end def test_nothing end end run_test_nothing(child_test_case) assert_equal([:child, :parent], called) end def test_setup_with_block test_case = Class.new(Test::Unit::TestCase) do def called_ids @called_ids ||= [] end def called(id) called_ids << id end setup def setup1 called(:setup1) begin yield called(:setup1_after_yield) ensure called(:setup1_teardown) end end setup def setup2 called(:setup2) begin yield called(:setup2_after_yield) ensure called(:setup2_teardown) end end def teardown called(:teardown) end def test_nothing called(:test) flunk called(:test_after_failure) end end assert_called_fixtures([ :setup1, :setup2, :test, :setup2_teardown, :setup1_teardown, :teardown, ], test_case) end private def assert_teardown_customizable(expected, parent, options) test_case = Class.new(parent || Test::Unit::TestCase) do yield(self, :before) if block_given? def called_ids @called_ids ||= [] end def called(id) called_ids << id end def teardown called(:teardown) end teardown(*(options[0] || [])) if options def custom_teardown_method0 called(:custom_teardown_method0) end if options teardown(*(options[0] || [])) do called(:custom_teardown_callback0) end end def custom_teardown_method1 called(:custom_teardown_method1) end teardown(*[:custom_teardown_method1, *(options[1] || [])]) if options if options teardown(*(options[1] || [])) do called(:custom_teardown_callback1) end end teardown(*(options[2] || [])) if options def custom_teardown_method2 called(:custom_teardown_method2) end unregister_teardown(:custom_teardown_method2) if options if options callback = lambda do called(:custom_teardown_callback2) end teardown(*(options[2] || []), &callback) unregister_teardown(callback) end teardown(*(options[3] || [])) if options def custom_teardown_method3 called(:custom_teardown_method3) end if options teardown(*(options[3] || [])) do called(:custom_teardown_callback3) end end def test_nothing end yield(self, :after) if block_given? end assert_called_fixtures(expected, test_case) test_case end def assert_teardown(expected, options) assert_teardown_customizable(expected, nil, options) assert_teardown_customizable(expected, nil, options) do |test_case, tag| test_case.send(:include, EmptyModule) if tag == :before end end def assert_inherited_teardown(expected, parent, options=nil) assert_teardown_customizable(expected, parent, options) assert_teardown_customizable(expected, parent, options) do |test_case, tag| test_case.send(:include, EmptyModule) if tag == :before end end def assert_invalid_teardown_option(option) assert_invalid_option(:teardown, option) end end private def run_test_nothing(test_case) test = test_case.new("test_nothing") test.run(Test::Unit::TestResult.new) {} test end def assert_called_fixtures(expected, test_case) test = run_test_nothing(test_case) assert_equal(expected, test.called_ids) end def assert_invalid_option(fixture_type, option) exception = assert_raise(ArgumentError) do Class.new(Test::Unit::TestCase) do def test_nothing end send(fixture_type, option) def fixture end end end assert_equal("must be {:before => :prepend}, {:before => :append}, " + "{:after => :prepend} or {:after => :append}" + ": #{option.inspect}", exception.message) end end PK% ]?"= = *gems/test-unit-3.2.9/test/test-omission.rbnu[require 'test/unit' require 'testunit-test-util' class TestUnitOmission < Test::Unit::TestCase include TestUnitTestUtil class TestCase < Test::Unit::TestCase class << self def suite Test::Unit::TestSuite.new(name) end end def test_omit omit("1st omit") omit("2nd omit. Should not be reached here.") assert(true, "Should not be reached here too.") end def test_omit_with_condition omit_if(false, "Never omit.") omit_unless(true, "Never omit too.") omit_if(true, "Should omit.") omit("The last omit. Should not be reached here.") end def test_omit_with_block omit("Omit block") do flunk("Should not be reached here.") end assert(true, "Should be reached here.") end def test_omit_with_block_and_condition omit_if(false, "Never omit.") do assert(true, "Should be reached here.") end omit_if(true, "Should omit.") do flunk("Never reached here.") end assert(true, "Should be reached here too.") end end def test_omit result = _run_test("test_omit") assert_equal("1 tests, 0 assertions, 0 failures, 0 errors, 0 pendings, " \ "1 omissions, 0 notifications", result.to_s) assert_fault_messages(["1st omit"], result.omissions) end def test_omit_with_condition result = _run_test("test_omit_with_condition") assert_equal("1 tests, 0 assertions, 0 failures, 0 errors, 0 pendings, " \ "1 omissions, 0 notifications", result.to_s) assert_fault_messages(["Should omit."], result.omissions) end def test_omit_with_block result = _run_test("test_omit_with_block") assert_equal("1 tests, 1 assertions, 0 failures, 0 errors, 0 pendings, " \ "1 omissions, 0 notifications", result.to_s) assert_fault_messages(["Omit block"], result.omissions) end def test_omit_with_condition_and_block result = _run_test("test_omit_with_block_and_condition") assert_equal("1 tests, 2 assertions, 0 failures, 0 errors, 0 pendings, " \ "1 omissions, 0 notifications", result.to_s) assert_fault_messages(["Should omit."], result.omissions) end private def _run_test(name) super(TestCase, name) end end PK% ]q$G;H;H&gems/test-unit-3.2.9/test/test-diff.rbnu[class TestUnitDiff < Test::Unit::TestCase def test_binary_search_ranges assert_found_binary_search_ranges(5, [1..2, 4..5, 7..9]) assert_not_found_binary_search_ranges(3, [1..2, 4..5, 7..9]) end def test_to_indexes assert_to_indexes({"abc def" => [0, 2], "abc" => [1]}, ["abc def", "abc", "abc def"]) assert_to_indexes({?a => [0, 3], ?b => [1], ?c => [2], ?d => [4]}, "abcad") assert_to_indexes({ ?1 => [0, 35], ?t => [2, 5, 16], ?e => [3, 14, 31, 38], ?s => [4, 6, 12, 13, 20, 32, 44], ?, => [7, 21, 33], ?0 => [9, 23], ?a => [11, 26], ?r => [15, 30], ?i => [17, 27, 41], ?o => [18], ?n => [19, 39, 42], ?f => [25], ?l => [28], ?u => [29], ?p => [37], ?d => [40], ?g => [43], }, "1 tests, 0 assertions, 0 failures, 1 pendings") do |x| x == " "[0] end end def test_longest_match assert_longest_match([0, 1, 3], %w(b c d), %w(a b c d x y z), 0, 2, 0, 7) assert_longest_match([1, 2, 2], %w(b c d), %w(a b c d x y z), 1, 2, 0, 6) assert_longest_match([0, 0, 0], %w(a b), %w(c), 0, 1, 0, 0) assert_longest_match([1, 0, 2], %w(q a b x c d), %w(a b y c d f), 0, 5, 0, 5) assert_longest_match([4, 3, 2], %w(q a b x c d), %w(a b y c d f), 3, 5, 2, 5) assert_longest_match([1, 0, 2], "qabxcd", "abycdf", 0, 5, 0, 5) assert_longest_match([0, 0, 1], "efg", "eg", 0, 2, 0, 1) assert_longest_match([2, 1, 1], "efg", "eg", 1, 2, 1, 1) end def test_longest_match_with_junk_predicate assert_longest_match([0, 4, 5], " abcd", "abcd abcd", 0, 4, 0, 8) assert_longest_match([1, 0, 4], " abcd", "abcd abcd", 0, 4, 0, 8) do |x| x == ' '[0] end end def test_matches assert_matches([[0, 0, 2], [3, 2, 2]], %w(a b x c d), %w(a b c d)) assert_matches([[1, 0, 2], [4, 3, 2]], %w(q a b x c d), %w(a b y c d f)) assert_matches([[1, 0, 2], [4, 3, 2]], "qabxcd", "abycdf") assert_matches([[0, 0, 1], [2, 1, 1]], "efg", "eg") end def test_matches_with_junk_predicate assert_matches([[0, 0, 23], [24, 24, 11], [36, 36, 9]], "1 tests, 0 assertions, 1 failures, 0 pendings", "1 tests, 0 assertions, 0 failures, 1 pendings") assert_matches([[0, 0, 1], [1, 1, 8], [9, 9, 1], [10, 10, 13], [24, 24, 11], [36, 36, 9]], "1 tests, 0 assertions, 1 failures, 0 pendings", "1 tests, 0 assertions, 0 failures, 1 pendings") do |x| x == " "[0] end end def test_blocks assert_blocks([[0, 0, 2], [3, 2, 2], [5, 4, 0]], %w(a b x c d), %w(a b c d)) assert_blocks([[1, 0, 2], [4, 3, 2], [6, 6, 0]], %w(q a b x c d), %w(a b y c d f)) assert_blocks([[1, 0, 2], [4, 3, 2], [6, 6, 0]], "qabxcd", "abycdf") assert_blocks([[0, 0, 1], [2, 1, 1], [3, 2, 0]], "efg", "eg") end def test_blocks_with_junk_predicate assert_blocks([[0, 0, 23], [24, 24, 11], [36, 36, 9], [45, 45, 0]], "1 tests, 0 assertions, 1 failures, 0 pendings", "1 tests, 0 assertions, 0 failures, 1 pendings") do |x| x == " "[0] end end def test_operations assert_operations([], %w(), %w()) assert_operations([[:delete, 0, 1, 0, 0], [:equal, 1, 3, 0, 2], [:replace, 3, 4, 2, 3], [:equal, 4, 6, 3, 5], [:insert, 6, 6, 5, 6]], %w(q a b x c d), %w(a b y c d f)) assert_operations([[:delete, 0, 1, 0, 0], [:equal, 1, 3, 0, 2], [:replace, 3, 4, 2, 3], [:equal, 4, 6, 3, 5], [:insert, 6, 6, 5, 6]], "qabxcd", "abycdf") assert_operations([[:equal, 0, 23, 0, 23], [:replace, 23, 24, 23, 24], [:equal, 24, 35, 24, 35], [:replace, 35, 36, 35, 36], [:equal, 36, 45, 36, 45]], "1 tests, 0 assertions, 1 failures, 0 pendings", "1 tests, 0 assertions, 0 failures, 1 pendings") assert_operations([[:equal, 0, 23, 0, 23], [:replace, 23, 24, 23, 24], [:equal, 24, 35, 24, 35], [:replace, 35, 36, 35, 36], [:equal, 36, 45, 36, 45]], "1 tests, 0 assertions, 1 failures, 0 pendings", "1 tests, 0 assertions, 0 failures, 1 pendings") do |x| x == " "[0] end end def test_grouped_operations assert_grouped_operations([[[:equal, 0, 0, 0, 0]]], %w(), %w()) assert_grouped_operations([[[:equal, 0, 3, 0, 3]]], %w(a b c), %w(a b c)) assert_grouped_operations([[[:equal, 0, 1, 0, 1], [:replace, 1, 2, 1, 2], [:equal, 2, 5, 2, 5]], [[:equal, 8, 11, 8, 11], [:replace, 11, 12, 11, 12], [:equal, 12, 13, 12, 13], [:delete, 13, 16, 13, 13], [:equal, 16, 17, 13, 14], [:replace, 17, 18, 14, 15], [:equal, 18, 20, 15, 17]]], %w(1 2 3 4 5 6 7 8 9 a b c d e f g h i j k), %w(1 i 3 4 5 6 7 8 9 a b cX d h iX j k)) end def test_ratio assert_ratio(0.75, "abcd", "bcde") assert_ratio(0.80, "efg", "eg") end def test_1_length_readable_diff differ = Test::Unit::Diff::ReadableDiffer.new(["0"], ["1"]) def differ.cut_off_ratio 0 end def differ.default_ratio 0 end assert_equal("- 0\n" + "? ^\n" + "+ 1\n" + "? ^", differ.diff.join("\n")) end def test_same_contents_readable_diff assert_readable_diff(" aaa", ["aaa"], ["aaa"]) assert_readable_diff(" aaa\n" \ " bbb", ["aaa", "bbb"], ["aaa", "bbb"]) end def test_deleted_readable_diff assert_readable_diff(" aaa\n" \ "- bbb", ["aaa", "bbb"], ["aaa"]) assert_readable_diff(" aaa\n" \ "- bbb\n" \ "- ccc\n" \ "- ddd", ["aaa", "bbb", "ccc", "ddd"], ["aaa"]) end def test_inserted_readable_diff assert_readable_diff(" aaa\n" \ "+ bbb\n" \ "+ ccc\n" \ "+ ddd", ["aaa"], ["aaa", "bbb", "ccc", "ddd"]) end def test_replace_readable_diff assert_readable_diff(" aaa\n" \ "- bbb\n" \ "+ BbB\n" \ " ccc\n" \ "- ddd\n" \ "- efg\n" \ "? -\n" \ "+ eg", ["aaa", "bbb", "ccc", "ddd", "efg"], ["aaa", "BbB", "ccc", "eg"]) assert_readable_diff("- abcd xyz abc\n" \ "? -\n" \ "+ abcd abcd xyz abc\n" \ "? +++++", [" abcd xyz abc"], ["abcd abcd xyz abc"]) end def test_difference_readable_diff assert_readable_diff("- 1 tests, 0 assertions, 1 failures, 0 pendings\n" \ "? ^ ^\n" \ "+ 1 tests, 0 assertions, 0 failures, 1 pendings\n" \ "? ^ ^", ["1 tests, 0 assertions, 1 failures, 0 pendings"], ["1 tests, 0 assertions, 0 failures, 1 pendings"]) end def test_complex_readable_diff assert_readable_diff(" aaa\n" \ "- bbb\n" \ "- ccc\n" \ "+ \n" \ "+ # \n" \ " ddd", ["aaa", "bbb", "ccc", "ddd"], ["aaa", "", " # ", "ddd"]) assert_readable_diff("- one1\n" \ "? ^\n" \ "+ ore1\n" \ "? ^\n" \ "- two2\n" \ "- three3\n" \ "? - -\n" \ "+ tree\n" \ "+ emu", ["one1", "two2", "three3"], ["ore1", "tree", "emu"]) end def test_empty_readable_diff assert_readable_diff("", [""], [""]) end def test_unified_diff assert_unified_diff("", ["one", "two", "three"], ["one", "two", "three"], "content 1", "content 2") assert_unified_diff("--- Original Sat Jan 26 23:30:50 1991\n" \ "+++ Current Fri Jun 06 10:20:52 2003\n" \ "@@ -1,4 +1,4 @@\n" \ "+zero\n" \ " one\n" \ "-two\n" \ "-three\n" \ "+tree\n" \ " four", ["one", "two", "three", "four"], ["zero", "one", "tree", "four"], "Original Sat Jan 26 23:30:50 1991", "Current Fri Jun 06 10:20:52 2003", :show_context => false) from = File.read(__FILE__).split(/\n/) to = from.dup target_line = __LINE__ to[target_line - 1, 1] = [] context = " def test_unified_diff" summary = "@@ -#{target_line - 3},7 +#{target_line - 3},6 @@ #{context}" assert_unified_diff((["--- revision 10", "+++ revision 11", summary] + from[target_line - 4, 3].collect {|line| " #{line}"} + ["-#{from[target_line - 1]}"] + from[target_line, 3].collect {|line| " #{line}"} ).join("\n"), from, to, "revision 10", "revision 11") end def test_empty_unified_diff assert_unified_diff("", [""], [""], "From", "To") assert_unified_diff("", [], [], "From", "To") end def test_diff_lines assert_diff_lines(["- ddd", "- efg", "? -", "+ eg"], ["aaa", "bbb", "ccc", "ddd", "efg"], ["aaa", "BbB", "ccc", "eg"], 3, 5, 3, 4) end def test_diff_line assert_diff_line(["- abcDefghiJkl", "? ^ ^ ^", "+ abcdefGhijkl", "? ^ ^ ^"], "abcDefghiJkl", "abcdefGhijkl") assert_diff_line(["- bcDefghiJklx", "? ^ ^ ^ -", "+ abcdefGhijkl", "? + ^ ^ ^"], "bcDefghiJklx", "abcdefGhijkl") end def test_empty_diff_line assert_diff_line(["- ", "+ "], "", "") end def test_format_diff_point assert_format_diff_point(["- \tabcDefghiJkl", "? \t ^ ^ ^", "+ \t\tabcdefGhijkl", "? \t ^ ^ ^"], "\tabcDefghiJkl", "\t\tabcdefGhijkl", " ^ ^ ^ ", "+ ^ ^ ^ ") assert_format_diff_point(["- efg", "? ^", "+ eg"], "efg", "eg", " ^", "") end def test_interesting_line from = ["class X", " def find(x=0)", " body", " end", "end"] to = ["def xxx", " raise 'not call me'", "end"] assert_interesting_line(" def find(x=0)", from, to, 2, 1) assert_interesting_line("def xxx", from, to, 2, 0) assert_interesting_line("class X", from, to, 0, 0) end private def assert_found_binary_search_ranges(numeric, ranges) assert_true(Test::Unit::Diff::UTF8Line.send(:binary_search_ranges, numeric, ranges)) end def assert_not_found_binary_search_ranges(numeric, ranges) assert_false(Test::Unit::Diff::UTF8Line.send(:binary_search_ranges, numeric, ranges)) end def assert_to_indexes(expected, to, &junk_predicate) matcher = Test::Unit::Diff::SequenceMatcher.new([""], to, &junk_predicate) assert_equal(expected, matcher.instance_variable_get("@to_indexes")) end def assert_find_best_match_position(expected, from, to, from_start, from_end, to_start, to_end, &junk_predicate) matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate) assert_equal(expected, matcher.send(:find_best_match_position, from_start, from_end, to_start, to_end)) end def assert_longest_match(expected, from, to, from_start, from_end, to_start, to_end, &junk_predicate) matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate) assert_equal(expected, matcher.longest_match(from_start, from_end, to_start, to_end)) end def assert_matches(expected, from, to, &junk_predicate) matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate) assert_equal(expected, matcher.send(:matches)) end def assert_blocks(expected, from, to, &junk_predicate) matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate) assert_equal(expected, matcher.blocks) end def assert_operations(expected, from, to, &junk_predicate) matcher = Test::Unit::Diff::SequenceMatcher.new(from, to, &junk_predicate) assert_equal(expected, matcher.operations) end def assert_grouped_operations(expected, from, to) matcher = Test::Unit::Diff::SequenceMatcher.new(from, to) assert_equal(expected, matcher.grouped_operations) end def assert_ratio(expected, from, to) matcher = Test::Unit::Diff::SequenceMatcher.new(from, to) assert_in_delta(expected, 0.001, matcher.ratio) end def assert_readable_diff(expected, from, to) assert_equal(expected, Test::Unit::Diff.readable(from.join("\n"), to.join("\n"))) end def assert_unified_diff(expected, from, to, from_label, to_label, options={}) options = options.merge(:from_label => from_label, :to_label => to_label) assert_equal(expected, Test::Unit::Diff.unified(from.join("\n"), to.join("\n"), options)) end def assert_diff_lines(expected, from, to, from_start, from_end, to_start, to_end) differ = Test::Unit::Diff::ReadableDiffer.new(from, to) result = [] differ.instance_variable_set("@result", result) differ.send(:diff_lines, from_start, from_end, to_start, to_end) assert_equal(expected, result) end def assert_diff_line(expected, from_line, to_line) differ = Test::Unit::Diff::ReadableDiffer.new([""], [""]) result = [] differ.instance_variable_set("@result", result) differ.send(:diff_line, from_line, to_line) assert_equal(expected, result) end def assert_format_diff_point(expected, from_line, to_line, from_tags, to_tags) differ = Test::Unit::Diff::ReadableDiffer.new([""], [""]) result = [] differ.instance_variable_set("@result", result) differ.send(:format_diff_point, from_line, to_line, from_tags, to_tags) assert_equal(expected, result) end def assert_interesting_line(expected, from, to, from_start, to_start) differ = Test::Unit::Diff::UnifiedDiffer.new(from, to) assert_equal(expected, differ.send(:find_interesting_line, from_start, to_start, :define_line?)) end end PK% ]X_3gems/test-unit-3.2.9/test/test-attribute-matcher.rbnu[require 'test/unit' require 'testunit-test-util' class TestAttributeMatcher < Test::Unit::TestCase include TestUnitTestUtil def setup @test = {} @matcher = Test::Unit::AttributeMatcher.new(@test) end def test_nonexistent assert_false(@matcher.match?("nonexistent")) end def test_existent @test[:existent] = true assert_true(@matcher.match?("existent")) end def test_and @test[:slow] = true @test[:important] = true assert_true(@matcher.match?("important and slow")) end def test_complex @test[:tags] = [:slow, :web] @test[:bug] = "2929" assert_true(@matcher.match?("tags.include?(:web) or bug == '29'")) end def test_exception assert_raise(NoMethodError) do @matcher.match?("nonexistent > 100") end end end PK% ]Fill%gems/test-unit-3.2.9/test/run-test.rbnu[#!/usr/bin/env ruby $VERBOSE = true $KCODE = "utf8" unless "".respond_to?(:encoding) base_dir = File.expand_path(File.join(File.dirname(__FILE__), "..")) lib_dir = File.join(base_dir, "lib") test_dir = File.join(base_dir, "test") $LOAD_PATH.unshift(lib_dir) require 'test/unit' test_unit_notify_base_dir = File.join(base_dir, "..", "test-unit-notify") test_unit_notify_base_dir = File.expand_path(test_unit_notify_base_dir) if File.exist?(test_unit_notify_base_dir) $LOAD_PATH.unshift(File.join(test_unit_notify_base_dir, "lib")) require 'test/unit/notify' end exit Test::Unit::AutoRunner.run(true, test_dir) PK% ]7w004gems/test-unit-3.2.9/test/ui/test_testrunmediator.rbnu[require 'test/unit/ui/testrunnermediator' class TestUnitUIMediator < Test::Unit::TestCase def test_run_suite_with_interrupt_exception test_case = Class.new(Test::Unit::TestCase) do def test_raise_interrupt raise Interrupt, "from test" end end mediator = Test::Unit::UI::TestRunnerMediator.new(test_case.suite) finished = false mediator.add_listener(Test::Unit::UI::TestRunnerMediator::FINISHED) do finished = true end assert_raise(Interrupt) do mediator.run end assert(finished) end end PK% ]f*k gems/test-unit-3.2.9/README.mdnu[# test-unit [![](https://badge.fury.io/rb/test-unit.svg)](http://badge.fury.io/rb/test-unit) [![](https://travis-ci.org/test-unit/test-unit.svg?branch=master)](https://travis-ci.org/test-unit/test-unit) * http://test-unit.github.io/ * https://github.com/test-unit/test-unit ## Description An xUnit family unit testing framework for Ruby. test-unit (Test::Unit) is unit testing framework for Ruby, based on xUnit principles. These were originally designed by Kent Beck, creator of extreme programming software development methodology, for Smalltalk's SUnit. It allows writing tests, checking results and automated testing in Ruby. ## Features * test-unit 1.2.3 is the original test-unit, taken straight from the ruby distribution. It is being distributed as a gem to allow tool builders to use it as a stand-alone package. (The test framework in ruby is going to radically change very soon). * test-unit will be improved actively and may break compatiblity with test-unit 1.2.3. (We will not hope it if it isn't needed.) * Some features exist as separated gems like GUI test runner. (Tk, GTK+ and Fox) test-unit-full gem package provides for installing all test-unit related gems easily. ## How To * [How To](https://github.com/test-unit/test-unit/blob/master/doc/text/how-to.md) (link for GitHub) * {file:doc/text/how-to.md How To} (link for YARD) ## Install
% sudo gem install test-unit
If you want to use full test-unit features:
% sudo gem install test-unit-full
## License (The Ruby License) This software is distributed under the same terms as ruby. Exception: * lib/test/unit/diff.rb is a triple license of the Ruby license, PSF license and LGPLv2.1 or later. * lib/test-unit.rb is a dual license of the Ruby license and LGPLv2.1 or later. ## Authors ### Active * Kouhei Sutou: The current maintainer * Haruka Yoshihara: Data driven test supports. ### Inactive * Nathaniel Talbott: The original author * Ryan Davis: The second maintainer ### Images * Mayu & Co.: kinotan icons ## Thanks * Daniel Berger: Suggestions and bug reports. * Designing Patterns: Suggestions. * Erik Hollensbe: Suggestions and bug reports. * Bill Lear: A suggestion. * Diego Pettenò: A bug report. * Angelo Lakra: A bug report. * Mike Pomraning: A bug report. * David MARCHALAND: Suggestions and bug reports. * Andrew Grimm: A bug report. * Champak Ch: A bug report. * Florian Frank: A bug report. * grafi-tt: Bug fixes and reports. * Jeremy Stephens: A bug report. * Hans de Graaff: Bug reports. * James Mead: A bug report. * Marc Seeger (Acquia): A bug report. * boutil: A bug report. * Vladislav Rassokhin: A bug report. PK% ]>X"Vgggems/test-unit-3.2.9/LGPLnu[ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! PK% ]vm gems/test-unit-3.2.9/COPYINGnu[test-unit is copyrighted free software by Kouhei Sutou , Ryan Davis and Nathaniel Talbott . You can redistribute it and/or modify it under either the terms of the GPL version 2 (see the file GPL), or the conditions below: 1. You may make and give away verbatim copies of the source form of the software without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may modify your copy of the software in any way, provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or by allowing the author to include your modifications in the software. b) use the modified software only within your corporation or organization. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 3. You may distribute the software in object code or binary form, provided that you do at least ONE of the following: a) distribute the binaries and library files of the software, together with instructions (in the manual page or equivalent) on where to get the original distribution. b) accompany the distribution with the machine-readable source of the software. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 4. You may modify and include the part of the software into any other software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under these terms. For the list of those files and their copying conditions, see the file LEGAL. 5. The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the copyright of the software, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this software. 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Exceptions ---------- * lib/test/unit/diff.rb: This license, PSF license and/or LGPLv2.1 or later * lib/test-unit.rb: This license and/or LGPLv2.1 or later PK% ]oc)gems/test-unit-3.2.9/sample/test_adder.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit' require_relative 'adder' class TestAdder < Test::Unit::TestCase def setup @adder = Adder.new(5) end def test_add assert_equal(7, @adder.add(2), "Should have added correctly") end def teardown @adder = nil end end PK% ]c: $gems/test-unit-3.2.9/sample/adder.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. class Adder def initialize(number) @number = number end def add(number) @number + number end end PK% ]d@.gems/test-unit-3.2.9/sample/test_subtracter.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit' require_relative 'subtracter' class TestSubtracter < Test::Unit::TestCase def setup @subtracter = Subtracter.new(5) end def test_subtract assert_equal(3, @subtracter.subtract(2), "Should have subtracted correctly") end def teardown @subtracter = nil end end PK% ]/jj(gems/test-unit-3.2.9/sample/test_user.rbnu[# nested test case example. require 'test/unit' class UserTest < Test::Unit::TestCase def setup @user = "me" end def test_full_name assert_equal("me", @user) end class ProfileTest < UserTest setup def setup_profile @user += ": profile" end def test_has_profile assert_match(/: profile/, @user) end end end PK% ]Z)gems/test-unit-3.2.9/sample/subtracter.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. class Subtracter def initialize(number) @number = number end def subtract(number) @number - number end end PK% ]$yӱ'gems/test-unit-3.2.9/doc/text/how-to.mdnu[# How To ## Run all tests To make it easy to run all your tests, you can add a `run_test.rb` script to your `test` directory. A simple example might look like: base_dir = File.expand_path(File.join(File.dirname(__FILE__), "..")) lib_dir = File.join(base_dir, "lib") test_dir = File.join(base_dir, "test") $LOAD_PATH.unshift(lib_dir) require 'test/unit' exit Test::Unit::AutoRunner.run(true, test_dir) Then it's easy to run tests via the command line with, $ ruby test/run_test.rb ## Change test runner via the command line The output format can be changed via the command line with the `--runner` option. Simply tack it to the end: ruby test/run_test.rb --runner tap ## Configure test-unit per-project Test::Unit reads `test-unit.yml` or `.test-unit.yml` in the current working directory as Test::Unit's configuration file. It can contain the following settings: * color scheme definitions * test runner to be used * test runner options * test collector to be used Except color scheme definitions, all of them can be specified by command line option. Here are sample color scheme definitions: color_schemes: inverted: success: name: red bold: true failure: name: green bold: true other_scheme: ... Here are the syntax of color scheme definitions: color_schemes: SCHEME_NAME: EVENT_NAME: name: COLOR_NAME intensity: BOOLEAN bold: BOOLEAN italic: BOOLEAN underline: BOOLEAN ... ... | Definition | Description | |-------------|------------------------------| | SCHEME_NAME | the name of the color scheme | | EVENT_NAME | success, failure, pending, omission, notification, error | | COLOR_NAME | black, red, green, yellow, blue, magenta, cyan, white | | BOOLEAN | true or false | You can use the above 'inverted' color scheme with the following configuration: runner: console console_options: color_scheme: inverted color_schemes: inverted: success: name: red bold: true failure: name: green bold: true PK% ]Maa%gems/test-unit-3.2.9/doc/text/news.mdnu[# News ## 3.2.9 - 2018-12-01 {#version-3-2-9} ### Improvements * Added support for data generation by method. `data_#{test_name}` is called to generate data for `test_name` test. * Added support for data matrix generation. Example: ```ruby data(:a, [0, 1, 2]) data(:b, [:x, :y]) def test_data(data) end ``` This example generates the following data matrix: * label: `"a: 0, b: :x"`, data: `{a: 0, b: :x}` * label: `"a: 0, b: :y"`, data: `{a: 0, b: :y}` * label: `"a: 1, b: :x"`, data: `{a: 1, b: :x}` * label: `"a: 1, b: :y"`, data: `{a: 1, b: :y}` * label: `"a: 2, b: :x"`, data: `{a: 2, b: :x}` * label: `"a: 2, b: :y"`, data: `{a: 2, b: :y}` * Added `Test::Unit::TestCase#data` that returns the current data. * Added support for using test method that doesn't have no parameters as data driven test. Example: ```ruby data("label", :value) def test_data # Available since this release p data # :value end ``` * Added support for `:keep` option to `Test::Unit::TestCase.data`. * Added support for `:group` option to `Test::Unit::TestCase.data`. It's useful to generate multiple data matrix groups. ```ruby # Group1 data(:a, [0, 1, 2], group: :g1) data(:b, [:x, :y], group: :g1) # Group2 data(:a, [:x, :y], group: :g2) data(:c, [-1, -2], group: :g2) def test_data(data) end ``` This example generates the following data matrix: * label: `"group: :g1, a: 0, b: :x"`, data: `{a: 0, b: :x}` * label: `"group: :g1, a: 0, b: :y"`, data: `{a: 0, b: :y}` * label: `"group: :g1, a: 1, b: :x"`, data: `{a: 1, b: :x}` * label: `"group: :g1, a: 1, b: :y"`, data: `{a: 1, b: :y}` * label: `"group: :g1, a: 2, b: :x"`, data: `{a: 2, b: :x}` * label: `"group: :g1, a: 2, b: :y"`, data: `{a: 2, b: :y}` * label: `"group: :g2, a: :x, b: -1"`, data: `{a: :x, b: -1}` * label: `"group: :g2, a: :x, b: -2"`, data: `{a: :x, b: -2}` * label: `"group: :g2, a: :y, b: -1"`, data: `{a: :y, b: -1}` * label: `"group: :g2, a: :y, b: -2"`, data: `{a: :y, b: -2}` ## 3.2.8 - 2018-05-13 {#version-3-2-8} ### Improvements * [UI][console]: Changed to put code snippet before backtrace on reverse mode. ## 3.2.7 - 2017-12-12 {#version-3-2-7} ### Improvements * Added source code link to gemspec. [GitHub#157][Patch by Grey Baker] * Changed to use SVG image for badges in README. [GitHub#158][Patch by Olle Jonsson] * [UI][console]: Added `--reverse-output` option to output fault details in reverse like Ruby 2.5. It's enabled by default only for tty output. ### Fixes * Fixed a typo. [GitHub#156][Patch by masa kunikata] * [UI][console]: Fixed a bug that broken align in verbose mode. ### Thanks * masa kunikata * Grey Baker * Olle Jonsson ## 3.2.6 - 2017-09-21 {#version-3-2-6} ### Improvements * Changed test file require failure to error from omission. [GitHub#154][Patch by naofumi-fujii] ### Thanks * naofumi-fujii ## 3.2.5 - 2017-06-24 {#version-3-2-5} ### Improvements * Supported `--enable-frozen-string-literal` `ruby` option. [GitHub#149][Reported by Pat Allan] ### Thanks * Pat Allan ## 3.2.4 - 2017-05-23 {#version-3-2-4} ### Improvements * Updated tests for Ruby 2.4. [GitHUb#136][Patch by Kazuki Tsujimoto] * Supported power\_assert 1.0.0. [GitHub#137][Patch by Kazuki Tsujimoto] * Added the getting started document. [GitHub#139][GitHub#141][Patch by Hiroyuki Sato] * Added the document for `attribute`. [GitHub#143][Patch by Fumiaki MATSUSHIMA] * Improved a link for GitHub. [GitHub#144][Patch by rochefort] * Updated `.travis.yml`. [GitHub#145][Patch by Jun Aruga] ### Fixes * Fixed a contributor name. [GitHub#131][Patch by Akira Matsuda] * Fixed typos in document. [GitHub#132][Patch by Akira Matsuda] * Fixed typos in document. [GitHub#134][Patch by Yuji Yaginuma] * Fixed a bug that data label with "(" isn't supported. [GitHub#135][Reported by Kazuki Tsujimoto] * Fixed assertion message in English. [GitHub#133][Reported by Khalil Fazal] * Fixed a typo in typo fix. [GitHub#138][Patch by kami] * Fixed a bug that target location finder may return wrong location. [GitHub#146][Patch by Yuki Ito] * Fixed a bug that `--no-show-detail-immediately` raises an error. [GitHub#147][Reported by MSP-Greg] ### Thanks * Akira Matsuda * Yuji Yaginuma * Kazuki Tsujimoto * Khalil Fazal * kami * Hiroyuki Sato * Fumiaki MATSUSHIMA * rochefort * Jun Aruga * Yuki Ito * MSP-Greg ## 3.2.3 - 2016-11-25 {#version-3-2-3} ### Fixes * Fixed a bug that `--order` isn't applied. [GitHub#129][Reported by Vít Ondruch] ### Thanks * Vít Ondruch ## 3.2.2 - 2016-11-02 {#version-3-2-2} ### Improvements * Improved Travis CI configuration. [GitHub#123][Patch by Ryunosuke Sato] * Supported Java native exception. [GitHub#126][Reported by Bob Saveland] ### Fixes * doc: Fixed markup. [GitHub#127][Patch by Tomohiro Hashidate] * Fixed a bug that `--location=LINE` may not detect a test when fixtures are defined before any tests: 1 class MyTestCase < Test::Unit::TestCase 2 setup do 3 end 4 5 test "xxx" do 6 end 7 end `--location=5` couldn't find the `xxx` test. [Reported by Ryota Sasabe] ### Thanks * Ryunosuke Sato * Tomohiro Hashidate * Bob Saveland * Ryota Sasabe ## 3.2.1 - 2016-07-19 {#version-3-2-1} ### Improvements * Clarified lib/test/unit/diff.rb license. It's a triple license of the Ruby license, PSF license and LGPLv2.1 or later. [Reported by Luisa Pace] * Reported norification when data driven test doesn't have parameter. [GitHub#122][Reported by Satoshi "Moris" Tagomori] ### Thanks * Luisa Pace * Satoshi "Moris" Tagomori ## 3.2.0 - 2016-06-12 {#version-3-2-0} ### Improvements * Supported rxvt family terminals as color available terminals. [GitHub#121][Reported by Ippei Kishida] ### Thanks * Ippei Kishida ## 3.1.9 - 2016-05-20 {#version-3-1-9} ### Fixes * Fixed conflict with test-unit-power_assert. [GitHub#120][Patch by Kazuki Tsujimoto] * Fixed a bug that path in `$LOAD_PATH` may be removed. ### Thanks * Kazuki Tsujimoto ## 3.1.8 - 2016-03-19 {#version-3-1-8} ### Improvements * Added `--stop-on-failure` command line option. With this option, running test suite is stopped immediately when one test is failed or an error is raised in one test. ## 3.1.7 - 2016-01-17 {#version-3-1-7} ### Fixes * Added a missing require. ## 3.1.6 - 2016-01-17 {#version-3-1-6} It's a Ruby on Rails integration improvement release. ### Improvements * Filtered backtrace of power\_assert. [GitHub#114] * Improved performance to retrieve test defined location. * Improved performance to run fixtures in a test. * Supported running a test by `yield` in `setup`: Before: def setup @file = File.open("x") end def teardown @file.close end After: def setup File.open("x") do |file| @file = file yield end end * Added `--default-test-path` option that specifies the default path that has tests. * Made auto runner registration more lazily. Auto runner isn't registered automatically until user defines a test. In the previous releases, auto runner is registered automatically when user defines a test case. * Supported specifying a test by location in command line. For example, the following command line runs a test that is defined in /tmp/test_a.rb at line 10: % ruby -r test-unit -e run_test /tmp/test_a.rb:10 ### Fixes * Fixed a bug that test isn't ran. The test has the same name as data driven test that is defined in parent test case. [GitHub#115] ## 3.1.5 - 2015-10-09 {#version-3-1-5} It's a Rack integration improvement release. ### Improvements * Renamed experimental top-level `run` method to `run_test` method because `run` is conflicted with Rack. [GitHub#32][GitHub:basecamp/pow#303] [Reported by Yevhen Viktorov] ### Thanks * Yevhen Viktorov ## 3.1.4 - 2015-09-26 {#version-3-1-4} It's a minor improvement release. ### Improvements * Updated sample code. [GitHub#109][Patch by takiy33] * Updated .travis.yml. [GitHub#110][Patch by takiy33] * document: Added table header in how to document. [GitHub#111][Patch by takiy33] * Removed duplicated code. [GitHub#112][Patch by takiy33] * Removed needless encoding conversion in fetching code snippet. [GitHub#113][Patch by NARUSE, Yui] ### Thanks * takiy33 * NARUSE, Yui ## 3.1.3 - 2015-07-26 {#version-3-1-3} It's a bug fix release. ### Improvements * Removed unused `TODO` file. [GitHub#108][Patch by takiy33] ### Fixes * `--location`: Fixed a bug that `--location LINE` doesn't work when test script is specified as relative path. [Reported by TOMITA Masahiro] The following doesn't work: % ruby ./test.rb --location 10 The following works: % ruby test.rb --location 10 ### Thanks * takiy33 * TOMITA Masahiro ## 3.1.2 - 2015-06-09 {#version-3-1-2} It's command line option improvements fix release. ### Improvements * `--location`: Made path match rule more strict. [Suggested by kimura wataru] * Before: * If test defined path ends with the specified path, the test is matched. * After: * If base name of test defined path equals to the specified path, the test is matched. * If relative path of test defined path equals to the specified path, the test is matched. * If the specified path is absolute path and test defined path equals to the specified path, the test is matched. * `--pattern`: If the option is specified, the default patterns aren't used. In the earlier versions, both the default patterns and the specified patterns are used. [Suggested by kimura wataru] ### Thanks * kimura wataru ## 3.1.1 - 2015-05-29 {#version-3-1-1} It's a bug fix release. ### Fixes * Fixed a bug that `--location` detects tests not only in sub test case but also parent test case. [GitHub#105][Reported by wanabe] ### Thanks * wanabe ## 3.1.0 - 2015-05-28 {#version-3-1-0} It's a bug fix release. ### Improvements * [ui][console] Removed needless new line. ### Fixes * Fixed a bug that priority mode can't be used on Windows. [GitHub#95][Reported by Daniel Berger] * Fixed a homepage URL RubyGems spec. [GitHub#96][Patch by Masayoshi Takahashi] supported.) [GitHub#89][Patch by Aaron Stone] * Fixed a bug that shutdown hook isn't called when pass throw exception such as `Interrupt` is raised. [GitHub#98][Reported by jeremiahishere.] * Fixed typos in documents. [GitHub#100][Reported by scivola] [GitHub#102][GitHub#103][Patch by Masafumi Yokoyama] * Fixed a bug that the same name test isn't executed in sub test case. [GitHub#104][Reported by wanabe] ### Thanks * Daniel Berger * Masayoshi Takahashi * jeremiahishere * scivola * Masafumi Yokoyama * wanabe ## 3.0.9 - 2014-12-31 {#version-3-0-9} It's a release that improves colors. ### Improvements * Added a work around for Ruby 1.8. (Note: Ruby 1.8 isn't supported.) [GitHub#89][Patch by Aaron Stone] * Supported colorized output on Windows. [GitHub#90][Patch by usa] * Improved colorized output. http://www.a-k-r.org/d/2014-12.html#a2014_12_27_1 [Suggested by Tanaka Akira] ### Thanks * Aaron Stone * usa * Tanaka Akira ## 3.0.8 - 2014-12-12 {#version-3-0-8} It's a release that supports Ruby 2.2.0 preview2. ### Improvements * Added a link for YARD in README. [GitHub:test-unit.github.io#2][Reported by sunnyone] * Added description about "/PATTERN/" style value in auto runner usage. [GitHub#86][Suggested by sunnyone] * Supported Ruby 2.2.0 preview2 in `assert_throw` and `assert_nothing_thrown`. ### Fixes * Fixed a bug that error report is failed when source encoding and locale encoding are different. [GitHub#87][Reported by scivola] ### Thanks * sunnyone * scivola ## 3.0.7 - 2014-11-14 {#version-3-0-7} It's a minor update release. ### Fixes * Fixed a bug that teardown blocks aren't called with sub class to parent class order. [GitHub#85][Reported by TOMITA Masahiro] ### Thanks * TOMITA Masahiro ## 3.0.6 - 2014-11-09 {#version-3-0-6} It's a minor update release. ### Improvements * Improved code snippet location. [GitHub#84][Patch by Yuki Kurihara] ### Thanks * Yuki Kurihara ## 3.0.5 - 2014-11-08 {#version-3-0-5} It's a minor update release. ### Fixes * Fixed a bug that startup/shutdown of parent test case isn't called when the test case includes one or more modules. [GitHub#83][Reported by Chadderton Odwazny] ### Thanks * Chadderton Odwazny ## 3.0.4 - 2014-11-01 {#version-3-0-4} It's a minor update release. ### Improvements * Stopped to remove JRuby and Rubinius internal backtrace entries from backtrace on failure/error. [GitHub#82][Patch by Charles Oliver Nutter] ### Thanks * Charles Oliver Nutter ## 3.0.3 - 2014-10-29 {#version-3-0-3} It's a minor update release. ### Improvements * Improved `Test::Unit::TestCase.test` performance. 100 times faster. * Supported `Proc` for user message. [Sugested by Nobuyoshi Nakada] ### Fixes * Fixed markup in document. [GitHub#81][Patch by Masafumi Yokoyama] ### Thanks * Masafumi Yokoyama * Nobuyoshi Nakada ## 3.0.2 - 2014-10-15 {#version-3-0-2} It's a minor update release. ### Improvements * Supported broken `==` implementation. `==` implementation should be fixed but it's not work of test-unit. :< [GitHub#71][Reported by Emily] * [UI][console]: Accepted no message failure. [GitHub#66][Reported by Brian Tatnall] * Updated gem description. [GitHub#74][Patch by Vít Ondruch] * Updated GPL text. [GitHub#78][Patch by Vít Ondruch] ### Fixes * Removed needless executable bit from README file. [GitHub#79][Patch by Vít Ondruch] ### Thanks * Emily * Brian Tatnall * Vít Ondruch ## 3.0.1 - 2014-08-05 {#version-3-0-1} It's a minor update release. ### Improvements * Improved Ruby 1.8.7 support. Note that we don't support Ruby 1.8.7 actively. We just support if its support is painless. [GitHub#71][Patch by estolfo] ### Thanks * estolfo ## 3.0.0 - 2014-08-03 {#version-3-0-0} It's Power Assert supported release! ### Improvements * Improved Rubinius support. [Ryo Onodera] * Updated RR repository link. [GitHub#56][Patch by Kenichi Kamiya] * Added some minitest compatible assertions. We don't recommend using these assertions. They are just for migrating from minitest. [GitHub#57][Patch by Karol Bucek] * {Test::Unit::Assertions#refute} * {Test::Unit::Assertions#refute_predicate} * {Test::Unit::Assertions#refute_empty} * {Test::Unit::Assertions#assert_not_includes} * {Test::Unit::Assertions#refute_includes} * {Test::Unit::Assertions#assert_not_instance_of} * {Test::Unit::Assertions#refute_instance_of} * {Test::Unit::Assertions#assert_not_kind_of} * {Test::Unit::Assertions#refute_kind_of} * {Test::Unit::Assertions#assert_not_operator} * {Test::Unit::Assertions#refute_operator} * Improved code readability. [Suggested by Kenichi Kamiya] * Made license field in RubyGems parseable. [GitHub#60][Patch by Michael Grosser] * Improved test case match feature by `--testcase` and `--ignore-testcase` options. They also checks parent class names. * Made inspected representation of Numeric objects especially BigDecimal more readable. [GitHub#64][Reported by Byron Appelt] * Added badges for Traivs CI and RubyGems. [GitHub#65][Patch by Byron Appelt] * Supported Power Assert. You can use Power Assert with {Test::Unit::Assertions#assert} with block. See method document for details. We recommend using Power Assert for predicate method checks. For example, we recommend Power Assert rather than {Test::Unit::Assertions#assert_true}, {Test::Unit::Assertions#assert_predicate} and so on. We don't recommend using Power Assert for equality check assertion. {Test::Unit::Assertions#assert_equal} should be used for the case. [Kazuki Tsujimoto] ### Fixes * Fixed a bug that test case defined by block has wrong location. [GitHub#58][Patch by Narihiro Nakamura] * Fixed a bug that test methods defined in included modules in super-class are also collected. [GitHub#62][GitHub#63][Patch by Karol Bucek] ### Thanks * Ryo Onodera * Kenichi Kamiya * Karol Bucek * Narihiro Nakamura * Michael Grosser * Byron Appelt * Kazuki Tsujimoto ## 2.5.5 - 2013-05-18 {#version-2-5-5} It's Ruby 2.0.0 supported release! ### Improvements * Supported Ruby 2.0.0. [GitHub#54] [Reported by mtasaka] * Accepted screen-256color TERM as 256 colors available environment. [GitHub#55] [Reported by Tom Miller] ### Fixes * Fixed a typo in document. [GitHub#53] [Patch by Baptiste Fontaine] * Fixed a bug in {Test::Unit::Assertions#assert_in_epsilon}. It doesn't work as expected if expected value is negative value. [Ruby Bug #8317] [Reported by Nobuhiro IMAI] ### Thanks * Baptiste Fontaine * mtasaka * Tom Miller * Nobuhiro IMAI ## 2.5.4 - 2013-01-23 {#version-2-5-4} It's a bug fix release. ### Improvements * Added documents for data driven test functionality. * Added TSV support for data driven test functionality. * Support tag inspection on JRuby. ### Fixes * Fixed a bug. It is too slow to filter tests when there are many tests. [GitHub#46] * Accept anonymous test suite. [GitHub:#49] [Reported by Matthew Rudy Jacobs] ### Thanks * Matthew Rudy Jacobs ## 2.5.3 - 2012-11-28 {#version-2-5-3} It's a release for minitest compatibility and bug fix. ### Improvements * Supported diff in invalid encoding. * Added some assersion methods just for minitest compatibility. Added methods are assert_includes(), refute_*() and refute(). If you are test-unit user, please don't use them. [GitHub#40] [Suggested by Michael Grosser] * Added --attribute option to select target tests by attribute. [test-unit-users-en:00098] [Suggested by Piotr Nestorow] ### Fixes * Allowed use of test for inheritance in ActionController::TestCase. [GitHub#42] [Patch by David Rasch] * Ensured evaluating at_exit block in top level. In IRB context, exit() specifies irb_exit(). [test-unit-users-en:00089] [Reported by Daniel Berger] * Fixed a bug that decoration style description is ignored. "decoration style description" are using description method above "def test_name" or with Symbol specifying test_name. [GitHub#45] [Reported by Piotr Nestorow] ### Thanks * Michael Grosser * David Rasch * Daniel Berger * Piotr Nestorow ## 2.5.2 - 2012-08-29 {#version-2-5-2} It's an improvement release for tmtms. `--location` is a similar feature to `--line_number` in RSpec. `sub_test_case` is a similar feature to `context` in shoulda-context and RSpec. ### Improvements * Cleaned up tests. [GitHub#34] [Patch by Michael Grosser] * Added missing background color for 8 color environment. * Added workaround for NetBeans. [GitHub#38] [Reported by Marc Cooper] * Added `--location` command line option that selects target tests by test defined location. * Created sub test suite for each subclassed test case. * [ui][console] Supported nested test suites. * Added {Test::Unit.at_start} and {Test::Unit.at_exit} hooks that are run before/after all tests are run. [Good hook name is suggested by kdmsnr] * Improved code snippet target on failure. Test method is always used for code snippet target. [GitHub#39] [Suggested by Michael Grosser] * Added {Test::Unit::TestCase.sub_test_case} that creates sub test case. The sub test case name isn't limited Ruby's constant name rule. You can specify the sub test case name in free form. ### Thanks * Michael Grosser * Marc Cooper * kdmsnr ## 2.5.1 - 2012-07-05 {#version-2-5-1} It's a bug fix release. ### Improvements * Supported installing from GitHub. [GitHub#29] [Suggested by Michael Grosser] * Supported ActiveSupport::TestCase. [GitHub#30] [Reported by Michael Grosser] * [ui][console] Improved multiline falut message display. ### Fixes * [ui][console] Fixed a bug that expected and actual values are empty. [GitHub#31][GitHub#33] [Reported by Kendall Buchanan][Reported by Mathieu Martin] [Hinted by Michael Grosser] * Fixed a bug that .gemspec can't be loaded on LANG=C. [RubyForge#29595] [Reported by Jean-Denis Koeck] ### Thanks * Michael Grosser * Kendall Buchanan * Mathieu Martin * Jean-Denis Koeck ## 2.5.0 - 2012-06-06 {#version-2-5-0} It's a bug fix release. ### Fixes * Fixed a backward incompatibility of `TestUnitMediator#run_suite` introduced in 2.4.9. [GitHub#28] [Reported by Vladislav Rassokhin] ### Thanks * Vladislav Rassokhin ## 2.4.9 - 2012-06-03 {#version-2-4-9} It's a bug fix release. ### Improvements * `Test::Unit.run?` -> `Test::Unit::AutoRunner.need_auto_run?`. `Test::Unit.run?` is marked as deprecated but it is still available. * [experimental] Added top level "run" method for `"ruby -rtest-unit -e run test/test_*.rb"`. Is this API OK or dirty? * Made failure output more readable on no color mode. * Supported showing ASCII-8BIT diff in failure message. * [ui][console] Supported `ENV["TERM"] == "xterm-256color"` as color available terminal. [GitHub#26] [Reported by Michael Grosser] * [ui][console] Supported "-256color" suffix `ENV["TERM"]` terminal as 256 color supported terminal. ### Fixes * Fixed a bug that `--workdir` doesn't work. * Consumed processed command line parameters in `ARGV` as `--help` says. [RubyForge#29554] [Reported by Bob Saveland] * Added missing `require "test/unit/diff"`. [GitHub#25] [Reported by Stephan Kulow] ### Thanks * Bob Saveland * Stephan Kulow * Michael Grosser ## 2.4.8 - 2012-3-6 {#version-2-4-8} It's a bug fix release. ### Improvements * Delayed at_exit registration until Test::Unit is used. [GitHub:#21] [Reported by Jason Lunn] * Added workaround for test-spec. [GitHub:#22] [Reported by Cédric Boutillier] ### Fixes * Fixed an error on code snippet display on JRuby. [GitHub:#19][GitHub:#20] [Reported by Jørgen P. Tjernø][Patch by Junegunn Choi] ### Thanks * Jørgen P. Tjernø * Junegunn Choi * Jason Lunn ## 2.4.7 - 2012-2-10 {#version-2-4-7} It's a code snippet improvement release. ### Improvements * Supported code snippet display on all faults. ## 2.4.6 - 2012-2-9 {#version-2-4-6} It's a TAP runner separated release. ### Improvements * Moved TAP runner to test-unit-runner-tap gem from test-unit gem. * Supported code snippet display on failure. ## 2.4.5 - 2012-1-16 {#version-2-4-5} It's a failure message readability improvement release. ### Improvements * Removed needless information from exception inspected text on failure. It's for easy to read. * Supported custom inspector. ## 2.4.4 - 2012-1-2 {#version-2-4-4} It's a Rails integration improved release. ### Improvements * [ui][console] Don't break progress display when a test is failed. * [ui][console] Added markers betwen a failure detail message in progress to improve visibility. * [travis] Dropped Ruby 1.8.6 as a test target. [GitHub:#13] [Patch by Josh Kalderimis] * Supported expected value == 0 case in assert_in_epsilon. [RubyForge#29485] [Reported by Syver Enstad] * Supported a block style setup/teardown/cleanup. ### Thanks * Josh Kalderimis * Syver Enstad ## 2.4.3 - 2011-12-11 {#version-2-4-3} ### Improvements * Improved SimpleCov integration by stopping to modify `ARGV` in auto runner. [GitHub:#12] [Reported by Nikos Dimitrakopoulos] * Improved JRuby integration by removing JRuby internal backtrace. ### Thanks * Nikos Dimitrakopoulos ## 2.4.2 - 2011-11-26 {#version-2-4-2} ### Improvements * `--name` supported data label. ## 2.4.1 - 2011-11-09 ### Improvements * Accepted AssertionMessage as assertion's user message. It is used in assert_select in actionpack. [Reported by David Heath] ### Fixes * Fixed test failure on LANG=C. #11 [Reported by boutil] * Suppress warnings on Ruby 1.9.2. ### Thanks * boutil * David Heath ## 2.4.0 - 2011-09-18 ### Improvements * Supported Travis CI. #5 [Suggested by James Mead] * Added Gemfile. #6 [Suggested by James Mead] * [ui][console] Supported notification in show-detail-immediately. * [ui][console] enable --show-detail-immediately by default. * [ui] Added --max-diff-target-string-size option. * [ui][console] Supported 256 colors. ### Fixes * Added missing fixture file. #7 [Reported by grafi-tt] * [ui][console] Added missing the last newline for progress level. * Supported correct backtrace for redefined notification. * Don't handle Timeout::Error as pass through exception on Ruby 1.8. #8 [Reported by Marc Seeger (Acquia)] ### Thanks * James Mead * grafi-tt * Marc Seeger (Acquia) ## 2.3.2 - 2011-08-15 A bug fix release. ### Improvements * [ui][console] Added some newlines to improve readability. ### Fixes * [ui][console] Worked --verbose again. * Re-supported Ruby 1.8.6. [Reported by James Mead] ### Thanks * James Mead ## 2.3.1 - 2011-08-06 {#version-2-3-1} Output improvement release! ### Improvements * [ui][console] Outputs omissions and notifications in short. * [ui][console] Added "important-only" verbose level. * Intelligence diff supports recursive references. * [rubyforge #29325] Supported Ruby Enterprise Edition. [Reported by Hans de Graaff] * [rubyforge #29326] Supported JRuby. [Reported by Hans de Graaff] * Added --show-detail-immediately option that shows fault details when a fault is occurred. ### Fixes * [pull request #1] Fixed a problem that load collector can't load a test file on Ruby 1.9. [Patch by grafi-tt] * [issue #3] Fixed a problem that implicit method name override by declarative style test definition. [Reported by Jeremy Stephens] ### Thanks * grafi-tt * Jeremy Stephens * Hans de Graaff ## 2.3.0 / 2011-04-17 * 13 enhancements * improve Hash key sorting for diff. * [#28928] support any characters in declarative style description. [Daniel Berger] * add Error#location and make #backtrace deprecated. * make TestCase#passed? public. * add result finished and pass assertion notifications. * add TestSuite#passed? public. * add XML test runner. * add --output-file-descriptor option. * measure elapsed time for each test. * add --collector option. * support test driven test. [Haruka Yoshihara] * add cleanup hook it runs between after test and before teardown. * support recursive collection sort for diff. * Thanks * Daniel Berger * Haruka Yoshihara ## 2.2.0 / 2011-02-14 * 22 enhancements * [#28808] accept String as delta for assert_in_delta. [Daniel Berger] * [test-unit-users-en:00035] make GC-able finished tests. [Daniel Berger] * use also COLUMNS environment variable to guess terminal width. * make delta for assert_in_delta optional. [Nobuyoshi Nakada] * add assert_not_respond_to. [Nobuyoshi Nakada] * add assert_not_match. assert_no_match is deprecated. [Nobuyoshi Nakada] * add assert_not_in_delta. [Nobuyoshi Nakada] * add assert_in_epsilon. [Nobuyoshi Nakada] * add assert_not_in_epsilon. [Nobuyoshi Nakada] * add assert_include. [Nobuyoshi Nakada] * add assert_not_include. [Nobuyoshi Nakada] * add assert_empty. [Nobuyoshi Nakada] * add assert_not_empty. [Nobuyoshi Nakada] * notify require failed paths. * validate message value for assert. * show throughputs at the last. * support not ASCII compatible string diff. * support colorized diff on encoding different string. * normalize entry order of Hash for readable diff. * add --ignore-name option. * add --ignore-testcase option. * add assert_not_send. * Thanks * Daniel Berger * Nobuyoshi Nakada ## 2.1.2 / 2010-11-25 * 1 enhancement * support auto runner prepare hook. ## 2.1.1 / 2010-07-29 * 1 bug fix * [test-unit-users-en:00026] re-work tap runner. [Daniel Berger] * Thanks * Daniel Berger === 2.1.0 / 2010-07-17 * 1 bug fix * [#28267] global config file ignored [Daniel Berger] * Thanks * Daniel Berger ## 2.0.8 / 2010-06-02 * 5 major enchancements * collect *_test.rb and *-test.rb files as test files. * [#28181] improve assert_in_delta message. [Suggested by David MARCHALAND] * show string encoding in assert_equal failure message if they are different. * change default color scheme: * success: green back + white * failure: red back + white * add capture_output. * 2 bug fixes * fix a bug that console runner on verbose mode causes an error for long test name (>= 61). * [#28093] Autorunner ignores all files in a directory named test by default [Reported by Florian Frank] * Thanks * Florian Frank * David MARCHALAND ## 2.0.7 / 2010-03-09 * 4 major enhancements * detect redefined test methods. * [INTERFACE IMCOMPATIBLE] multiple --name and --testcase options narrow down targets instead of adding targets. * [#27764] accept custom test_order for each test case. [Suggested by David MARCHALAND] * [#27790] ignore omitted tests from 'n% passed' report. [Suggested by Daniel Berger] * 2 minor enchancements * [#27832] ignore .git directory. [Suggested by Daniel Berger] * [#27792] require 'fileutils' and 'tmpdir' lazily for non-priority mode users. [Suggested by David MARCHALAND] * 2 bug fixes * [#27892] modify processed arguments array destructively. [Reported by Bob Saveland] * work without HOME environment variable. [Reported by Champak Ch] * Thanks * David MARCHALAND * Daniel Berger * Bob Saveland * Champak Ch ## 2.0.6 / 2010-01-09 * 3 major enhancements * [#27380] Declarative syntax? [Daniel Berger] support declarative syntax: test "test description in natural language" do ... end * support test description: description "test description in natural language" def test_my_test ... end * make max diff target string size customizable by TEST_UNIT_MAX_DIFF_TARGET_STRING_SIZE environment variable. * 2 bug fixes * [#27374] omit_if unexpected behavior [David MARCHALAND] * fix a bug that tests in sub directories aren't load with --basedir. [Daniel Berger] * Thanks * David MARCHALAND * Daniel Berger ## 2.0.5 / 2009-10-18 * 1 bug fixes * [#27314] fix diff may raise an exception. [Erik Hollensbe] * Thanks * Erik Hollensbe ## 2.0.4 / 2009-10-17 * 4 major enhancements * use ~/.test-unit.yml as global configuration file. * add TAP runner. (--runner tap) * support colorized diff: http://test-unit.github.io/color-diff.png * add Test::Unit::AutoRunner.default_runner= to specify default test runner. * 4 minor enhancements * improve verbose mode output format. (use indent) * support `NOT_PASS_THROUGH_EXCEPTIONS`. * support arguments option in `#{runner}_options`. * TC_ -> Test in sample test case name. * 1 bug fixes * [#27195] test-unit-2.0.3 + ruby-1.9.1 cannot properly test DelegateClass subclasses [Mike Pomraning] * Thanks * Mike Pomraning ## 2.0.3 / 2009-07-19 * 6 major enhancements * add assert_predicate. * add assert_not_predicate. * [#24210] assert_kind_of supports an array of classes or modules. [Daniel Berger] * assert_instance_of supports an array of classes or modules. * add --default-priority option. * [#26627] add --order option. [Daniel Berger] * 4 minor enhancements * use yellow foreground + black background for error. * don't show diff for long string. * accept "*term-color" TERM environment as colorizable terminal. (e.g. Apple's Terminal) * [#26268] add a workaround for test-spec's after_all. [Angelo Lakra] * 1 bug fix * [#23586] re-support ruby 1.9.1. [Diego Pettenò] * Thanks * Diego Pettenò * Daniel Berger * Angelo Lakra ## 2.0.2 / 2008-12-21 * 2 major enhancements * re-support ruby 1.8.5. * improve exception object comparison. * 3 bug fixes * [#22723]: collector fails on anonymous classes * [#22986]: Test names with '?' blow up on Windows * [#22988]: don't create .test-result on non-priority mode. * Thanks * Erik Hollensbe * Daniel Berger * Bill Lear ## 2.0.1 / 2008-11-09 * 19 major enhancements * support ruby 1.9.1. * add run_test method to be extensible. * improve priority-mode auto off. * improve startup/shutdown RDoc. [Daniel Berger] * add assert_compare. [#20851] [Designing Patterns] * add assert_fail_assertion. [#20851] [Designing Patterns] * add assert_raise_message. [#20851] [Designing Patterns] * support folded diff. * add assert_raise_kind_of. [Daniel Berger] * ingore inherited test for nested test case. * add assert_const_defined. * add assert_not_const_defined. * support assert_raise with an exception object. * support assert_raise with no arguments that asserts any exception is raised. [#22602] [Daniel Berger] * support folded dot progress. * add --progress-row-max option. * support color scheme customize. * support configuration file. (YAML) * recognize test-XXX.rb files as test files not only test_XXX.rb * Thanks * Daniel Berger * Designing Patterns ## 2.0.0 / 2008-06-18 * 15 major enhancements * support startup/shutdown. (test case level setup/teardown) * support multiple setup/teardown. * support pending. * support omission. * support notification. * support colorize. * support diff. * support test attribute. * add assert_boolean. * add assert_true. * add assert_false. * add --priority-mode option. * don't use ObjectSpace to collect test cases. * make more customizable. (additional options, exception handling and so on) * improve Emacs integration. * 4 major changes * remove GTK+1 support. * split GTK+ runner as another gem. * split FOX runner as another gem. * split Tk runner as another gem. ## 1.2.3 / 2008-02-25 * 1 major enhancement * Birthday (as a gem)! PK% ]p0gems/test-unit-3.2.9/doc/text/getting-started.mdnu[## 1. First step of the `test-unit` Let's getting start `test-unit`. This document creates an example gem package called `sample` with the `test-unit` testing framework. ## 2. Install bundler and test-unit. * First, install the `bundler` gem for generating gem template. * Second, install the `test-unit` itself. ~~~ !!!plain gem install bundler gem install test-unit ~~~ The `gem list` command output installed packages. You will find the following lines. ~~~ !!!plain gem list ... bundler (1.14.6) ... test-unit (3.2.3) ~~~ ## 3. Create gem template. Next, create a gem template using `bundler` command. This command generates package skeleton with a testing framework. However, this command can't generate test templates for `test-unit`. So, First create gem template with the `minitest` testing framework. (It's similar to `unit-test`). After that, replace some files for `test-unit`. The `bundle gem -t minitest sample` command will generate the following files. ~~~ !!!plain . |-- Gemfile |-- README.md |-- Rakefile |-- bin | |-- console | `-- setup |-- lib | |-- sample | | `-- version.rb | `-- sample.rb |-- sample.gemspec # <- Modify `-- test |-- sample_test.rb # <- Modify `-- test_helper.rb # <- Modify ~~~ ## 4. Edit files for `test-unit` ### 4.1. Edit gemspec Edit `sample.gemspec` like the below. Replace `minitest` line to `test-unit`. Before ~~~ !!!ruby spec.add_development_dependency "minitest", "~> 5.0" ~~~ After ~~~ !!!ruby spec.add_development_dependency "test-unit", "~> 3.2.3" ~~~ ### 4.2. Edit `test/test_helper.rb` Next, edit the `test/test_helper.rb` file. Before ~~~ !!!ruby $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) require 'sample' require 'minitest/autorun' # <-- Modify this line. ~~~ After ~~~ !!!ruby $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) require 'sample' require 'test/unit' # <-- After modification. ~~~ ### 4.3 Rakefile (No edit) This file doesn't need to modify. The output is the below. ~~~ !!!ruby require "bundler/gem_tasks" require "rake/testtask" Rake::TestTask.new(:test) do |t| t.libs << "test" t.libs << "lib" t.test_files = FileList['test/**/*_test.rb'] end task :default => :test ~~~ ### 4.4 Edit `test/sample_test.rb` The bundler generate the file `test/sample_test.rb`. This file originally templates for `minitest`. Let's modify this file for `test-unit` before ~~~ !!!ruby require 'test_helper' class SampleTest < Minitest::Test # <- Modify here def test_that_it_has_a_version_number refute_nil ::Sample::VERSION end def test_it_does_something_useful assert false end end ~~~ After ~~~ !!!ruby require 'test_helper' class SampleTest < Test::Unit::TestCase # <- After modification def test_that_it_has_a_version_number refute_nil ::Sample::VERSION end def test_it_does_something_useful assert false end end ~~~ ## 5. Execute test. The `rake test` command execute test scenarios in the `test` directory. Now it tries to two tests. One will success the other one fails. ~~~ !!!plain rake test Loaded suite /path/to/ruby/lib/ruby/gems/2.3.0/gems/rake-12.0.0/lib/rake/rake_test_loader Started F ================================================================================ Failure: is not true. test_it_does_something_useful(SampleTest) /path/to/sample/test/sample_test.rb:9:in `test_it_does_something_useful' 6: end 7: 8: def test_it_does_something_useful => 9: assert false 10: end 11: end ================================================================================ . Finished in 0.011521 seconds. -------------------------------------------------------------------------------- 2 tests, 2 assertions, 1 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications 50% passed -------------------------------------------------------------------------------- 173.60 tests/s, 173.60 assertions/s rake aborted! Command failed with status (1) Tasks: TOP => test (See full trace by running task with --trace) ~~~ ## 6. Create original tests. Let's create your original tests with the following rules. * Create a test file in the `test` directory. * The file needs suffix `xxx_test.rb`. * You can put test file into the subdirectory like `test/sub`. Example directory layout. ~~~ !!!plain test |-- sample_test.rb |-- sub | `-- sample2_test.rb `-- test_helper.rb ~~~ Example test file in the sub directory. ~~~ !!!ruby require 'test_helper' module Sub class Sample2Test < Test::Unit::TestCase def test_that_it_has_a_version_number refute_nil ::Sample::VERSION end def test_it_does_something_useful assert false end end end ~~~ ## 7. For more inforomation Let's read the official document. * [test-unit](http://test-unit.github.io/index.html) PK% ]2)5:gems/test-unit-3.2.9/lib/test/unit/code-snippet-fetcher.rbnu[module Test module Unit class CodeSnippetFetcher def initialize @sources = {} end def fetch(path, line, options={}) n_context_line = options[:n_context_line] || 3 lines = source(path) return [] if lines.nil? min_line = [line - n_context_line, 1].max max_line = [line + n_context_line, lines.length].min window = min_line..max_line window.collect do |n| attributes = {:target_line? => (n == line)} [n, lines[n - 1].chomp, attributes] end end def source(path) @sources[path] ||= read_source(path) end private def read_source(path) return nil unless File.exist?(path) lines = [] File.open(path) do |file| first_line = file.gets break if first_line.nil? encoding = detect_encoding(first_line) if encoding first_line.force_encoding(encoding) file.set_encoding(encoding, encoding) end lines << first_line lines.concat(file.readlines) end lines end def detect_encoding(first_line) return nil unless first_line.respond_to?(:ascii_only?) return nil unless first_line.ascii_only? if /\b(?:en)?coding[:=]\s*([a-z\d_-]+)/i =~ first_line begin Encoding.find($1) rescue ArgumentError nil end else nil end end end end end PK% ]y3 3 5gems/test-unit-3.2.9/lib/test/unit/util/observable.rbnu[#-- # # Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit/util/procwrapper' module Test module Unit module Util # This is a utility class that allows anything mixing # it in to notify a set of listeners about interesting # events. module Observable # We use this for defaults since nil might mean something NOTHING = "NOTHING/#{__id__}" # Adds the passed proc as a listener on the # channel indicated by channel_name. listener_key # is used to remove the listener later; if none is # specified, the proc itself is used. # # Whatever is used as the listener_key is # returned, making it very easy to use the proc # itself as the listener_key: # # listener = add_listener("Channel") { ... } # remove_listener("Channel", listener) def add_listener(channel_name, listener_key=NOTHING, &listener) # :yields: value unless(block_given?) raise ArgumentError.new("No callback was passed as a listener") end key = listener_key if (listener_key == NOTHING) listener_key = listener key = ProcWrapper.new(listener) end channels[channel_name] ||= {} channels[channel_name][key] = listener return listener_key end # Removes the listener indicated by listener_key # from the channel indicated by # channel_name. Returns the registered proc, or # nil if none was found. def remove_listener(channel_name, listener_key) channel = channels[channel_name] return nil unless (channel) key = listener_key if (listener_key.instance_of?(Proc)) key = ProcWrapper.new(listener_key) end if (channel.has_key?(key)) return channel.delete(key) end return nil end # Calls all the procs registered on the channel # indicated by channel_name. If value is # specified, it is passed in to the procs, # otherwise they are called with no arguments. # #-- # # Perhaps this should be private? Would it ever # make sense for an external class to call this # method directly? def notify_listeners(channel_name, *arguments) channel = channels[channel_name] return 0 unless (channel) listeners = channel.values listeners.each { |listener| listener.call(*arguments) } return listeners.size end private def channels @channels ||= {} return @channels end end end end end PK% ]b1gems/test-unit-3.2.9/lib/test/unit/util/output.rbnu[module Test module Unit module Util module Output ## # Returns output for standard output and standard # error as string. # # Example: # capture_output do # puts("stdout") # warn("stderr") # end # -> ["stdout\n", "stderr\n"] def capture_output require 'stringio' output = StringIO.new error = StringIO.new stdout_save, stderr_save = $stdout, $stderr $stdout, $stderr = output, error begin yield [output.string, error.string] ensure $stdout, $stderr = stdout_save, stderr_save end end end end end end PK% ]S<>gems/test-unit-3.2.9/lib/test/unit/util/method-owner-finder.rbnu[module Test module Unit module Util module MethodOwnerFinder module_function def find(object, method_name) method = object.method(method_name) return method.owner if method.respond_to?(:owner) if /\((.+?)\)\#/ =~ method.to_s owner_name = $1 if /\A#\MM6gems/test-unit-3.2.9/lib/test/unit/util/procwrapper.rbnu[#-- # # Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. module Test module Unit module Util # Allows the storage of a Proc passed through '&' in a # hash. # # Note: this may be inefficient, since the hash being # used is not necessarily very good. In Observable, # efficiency is not too important, since the hash is # only accessed when adding and removing listeners, # not when notifying. class ProcWrapper # Creates a new wrapper for a_proc. def initialize(a_proc) @a_proc = a_proc @hash = a_proc.inspect.sub(/^(#<#{a_proc.class}:)/){''}.sub(/(>)$/){''}.hex end def hash return @hash end def ==(other) case(other) when ProcWrapper return @a_proc == other.to_proc else return super end end alias :eql? :== def to_proc return @a_proc end end end end end PK% ]00:gems/test-unit-3.2.9/lib/test/unit/util/backtracefilter.rbnu[begin require 'power_assert' rescue LoadError, SyntaxError end module Test module Unit module Util module BacktraceFilter TESTUNIT_FILE_SEPARATORS = %r{[\\/:]} TESTUNIT_PREFIX = __FILE__.split(TESTUNIT_FILE_SEPARATORS)[0..-3] TESTUNIT_RB_FILE = /\.rb\Z/ POWERASSERT_PREFIX = defined?(::PowerAssert) ? ::PowerAssert.method(:start).source_location[0].split(TESTUNIT_FILE_SEPARATORS)[0..-2] : nil module_function def filter_backtrace(backtrace, prefix=nil) return ["No backtrace"] unless backtrace return backtrace if ENV["TEST_UNIT_ALL_BACKTRACE"] if prefix split_prefixes = [prefix.split(TESTUNIT_FILE_SEPARATORS)] else split_prefixes = [TESTUNIT_PREFIX, POWERASSERT_PREFIX].compact end test_unit_internal_p = lambda do |entry| components = entry.split(TESTUNIT_FILE_SEPARATORS) split_prefixes.any? do |split_prefix| split_entry = components[0, split_prefix.size] next false unless split_entry[0..-2] == split_prefix[0..-2] split_entry[-1].sub(TESTUNIT_RB_FILE, '') == split_prefix[-1] end end in_user_code = false new_backtrace = backtrace.reverse.reject do |entry| if test_unit_internal_p.call(entry) in_user_code = true true else not in_user_code end end.reverse if new_backtrace.empty? new_backtrace = backtrace.reject do |entry| test_unit_internal_p.call(entry) end new_backtrace = backtrace if new_backtrace.empty? end new_backtrace end end end end end PK% ]9'ee*gems/test-unit-3.2.9/lib/test/unit/diff.rbnu[# port of Python's difflib. # # Copyright (c) 2001-2008 Python Software Foundation; All Rights Reserved # Copyright (c) 2008-2011 Kouhei Sutou; All Rights Reserved # # It is free software, and is distributed under the Ruby license, the # PSF license and/or LGPLv2.1 or later. See the COPYING file, the PSFL # file and the LGPL file. module Test module Unit module Diff class SequenceMatcher def initialize(from, to, &junk_predicate) @from = from @to = to @junk_predicate = junk_predicate update_to_indexes end def longest_match(from_start, from_end, to_start, to_end) best_info = find_best_match_position(from_start, from_end, to_start, to_end) unless @junks.empty? args = [from_start, from_end, to_start, to_end] best_info = adjust_best_info_with_junk_predicate(false, best_info, *args) best_info = adjust_best_info_with_junk_predicate(true, best_info, *args) end best_info end def blocks @blocks ||= compute_blocks end def operations @operations ||= compute_operations end def grouped_operations(context_size=nil) context_size ||= 3 _operations = operations.dup _operations = [[:equal, 0, 0, 0, 0]] if _operations.empty? expand_edge_equal_operations!(_operations, context_size) group_window = context_size * 2 groups = [] group = [] _operations.each do |tag, from_start, from_end, to_start, to_end| if tag == :equal and from_end - from_start > group_window group << [tag, from_start, [from_end, from_start + context_size].min, to_start, [to_end, to_start + context_size].min] groups << group group = [] from_start = [from_start, from_end - context_size].max to_start = [to_start, to_end - context_size].max end group << [tag, from_start, from_end, to_start, to_end] end groups << group unless group.empty? groups end def ratio @ratio ||= compute_ratio end private def update_to_indexes @to_indexes = {} @junks = {} if @to.is_a?(String) each = " "[0].is_a?(Integer) ? :each_byte : :each_char else each = :each end i = 0 @to.__send__(each) do |item| @to_indexes[item] ||= [] @to_indexes[item] << i i += 1 end return if @junk_predicate.nil? @to_indexes = @to_indexes.reject do |key, value| junk = @junk_predicate.call(key) @junks[key] = true if junk junk end end def find_best_match_position(from_start, from_end, to_start, to_end) best_from, best_to, best_size = from_start, to_start, 0 sizes = {} from_start.upto(from_end) do |from_index| _sizes = {} (@to_indexes[@from[from_index]] || []).each do |to_index| next if to_index < to_start break if to_index > to_end size = _sizes[to_index] = (sizes[to_index - 1] || 0) + 1 if size > best_size best_from = from_index - size + 1 best_to = to_index - size + 1 best_size = size end end sizes = _sizes end [best_from, best_to, best_size] end def adjust_best_info_with_junk_predicate(should_junk, best_info, from_start, from_end, to_start, to_end) best_from, best_to, best_size = best_info while best_from > from_start and best_to > to_start and (should_junk ? @junks.has_key?(@to[best_to - 1]) : !@junks.has_key?(@to[best_to - 1])) and @from[best_from - 1] == @to[best_to - 1] best_from -= 1 best_to -= 1 best_size += 1 end while best_from + best_size < from_end and best_to + best_size < to_end and (should_junk ? @junks.has_key?(@to[best_to + best_size]) : !@junks.has_key?(@to[best_to + best_size])) and @from[best_from + best_size] == @to[best_to + best_size] best_size += 1 end [best_from, best_to, best_size] end def matches @matches ||= compute_matches end def compute_matches matches = [] queue = [[0, @from.size, 0, @to.size]] until queue.empty? from_start, from_end, to_start, to_end = queue.pop match = longest_match(from_start, from_end - 1, to_start, to_end - 1) match_from_index, match_to_index, size = match unless size.zero? if from_start < match_from_index and to_start < match_to_index queue.push([from_start, match_from_index, to_start, match_to_index]) end matches << match if match_from_index + size < from_end and match_to_index + size < to_end queue.push([match_from_index + size, from_end, match_to_index + size, to_end]) end end end matches.sort_by do |(from_index, _, _)| from_index end end def compute_blocks blocks = [] current_from_index = current_to_index = current_size = 0 matches.each do |from_index, to_index, size| if current_from_index + current_size == from_index and current_to_index + current_size == to_index current_size += size else unless current_size.zero? blocks << [current_from_index, current_to_index, current_size] end current_from_index = from_index current_to_index = to_index current_size = size end end unless current_size.zero? blocks << [current_from_index, current_to_index, current_size] end blocks << [@from.size, @to.size, 0] blocks end def compute_operations from_index = to_index = 0 operations = [] blocks.each do |match_from_index, match_to_index, size| tag = determine_tag(from_index, to_index, match_from_index, match_to_index) if tag != :equal operations << [tag, from_index, match_from_index, to_index, match_to_index] end from_index, to_index = match_from_index + size, match_to_index + size if size > 0 operations << [:equal, match_from_index, from_index, match_to_index, to_index] end end operations end def compute_ratio matches = blocks.inject(0) {|result, block| result + block[-1]} length = @from.length + @to.length if length.zero? 1.0 else 2.0 * matches / length end end def determine_tag(from_index, to_index, match_from_index, match_to_index) if from_index < match_from_index and to_index < match_to_index :replace elsif from_index < match_from_index :delete elsif to_index < match_to_index :insert else :equal end end def expand_edge_equal_operations!(_operations, context_size) tag, from_start, from_end, to_start, to_end = _operations[0] if tag == :equal _operations[0] = [tag, [from_start, from_end - context_size].max, from_end, [to_start, to_end - context_size].max, to_end] end tag, from_start, from_end, to_start, to_end = _operations[-1] if tag == :equal _operations[-1] = [tag, from_start, [from_end, from_start + context_size].min, to_start, [to_end, to_start + context_size].min] end end end class Differ def initialize(from, to) @from = from @to = to end private def tag(mark, contents) contents.collect {|content| mark + content} end end class UTF8Line class << self # from http://unicode.org/reports/tr11/ WIDE_CHARACTERS = [0x1100..0x1159, 0x115F..0x115F, 0x2329..0x232A, 0x2E80..0x2E99, 0x2E9B..0x2EF3, 0x2F00..0x2FD5, 0x2FF0..0x2FFB, 0x3000..0x303E, 0x3041..0x3096, 0x3099..0x30FF, 0x3105..0x312D, 0x3131..0x318E, 0x3190..0x31B7, 0x31C0..0x31E3, 0x31F0..0x321E, 0x3220..0x3243, 0x3250..0x32FE, 0x3300..0x4DB5, 0x4E00..0x9FC3, 0xA000..0xA48C, 0xA490..0xA4C6, 0xAC00..0xD7A3, 0xF900..0xFA2D, 0xFA30..0xFA6A, 0xFA70..0xFAD9, 0xFE10..0xFE19, 0xFE30..0xFE52, 0xFE54..0xFE66, 0xFE68..0xFE6B, 0xFF01..0xFF60, 0xFFE0..0xFFE6, 0x20000..0x2FFFD, 0x30000..0x3FFFD, ] AMBIGUOUS = [0x00A1..0x00A1, 0x00A4..0x00A4, 0x00A7..0x00A8, 0x00AA..0x00AA, 0x00AD..0x00AE, 0x00B0..0x00B4, 0x00B6..0x00BA, 0x00BC..0x00BF, 0x00C6..0x00C6, 0x00D0..0x00D0, 0x00D7..0x00D8, 0x00DE..0x00E1, 0x00E6..0x00E6, 0x00E8..0x00EA, 0x00EC..0x00ED, 0x00F0..0x00F0, 0x00F2..0x00F3, 0x00F7..0x00FA, 0x00FC..0x00FC, 0x00FE..0x00FE, 0x0101..0x0101, 0x0111..0x0111, 0x0113..0x0113, 0x011B..0x011B, 0x0126..0x0127, 0x012B..0x012B, 0x0131..0x0133, 0x0138..0x0138, 0x013F..0x0142, 0x0144..0x0144, 0x0148..0x014B, 0x014D..0x014D, 0x0152..0x0153, 0x0166..0x0167, 0x016B..0x016B, 0x01CE..0x01CE, 0x01D0..0x01D0, 0x01D2..0x01D2, 0x01D4..0x01D4, 0x01D6..0x01D6, 0x01D8..0x01D8, 0x01DA..0x01DA, 0x01DC..0x01DC, 0x0251..0x0251, 0x0261..0x0261, 0x02C4..0x02C4, 0x02C7..0x02C7, 0x02C9..0x02CB, 0x02CD..0x02CD, 0x02D0..0x02D0, 0x02D8..0x02DB, 0x02DD..0x02DD, 0x02DF..0x02DF, 0x0300..0x036F, 0x0391..0x03A1, 0x03A3..0x03A9, 0x03B1..0x03C1, 0x03C3..0x03C9, 0x0401..0x0401, 0x0410..0x044F, 0x0451..0x0451, 0x2010..0x2010, 0x2013..0x2016, 0x2018..0x2019, 0x201C..0x201D, 0x2020..0x2022, 0x2024..0x2027, 0x2030..0x2030, 0x2032..0x2033, 0x2035..0x2035, 0x203B..0x203B, 0x203E..0x203E, 0x2074..0x2074, 0x207F..0x207F, 0x2081..0x2084, 0x20AC..0x20AC, 0x2103..0x2103, 0x2105..0x2105, 0x2109..0x2109, 0x2113..0x2113, 0x2116..0x2116, 0x2121..0x2122, 0x2126..0x2126, 0x212B..0x212B, 0x2153..0x2154, 0x215B..0x215E, 0x2160..0x216B, 0x2170..0x2179, 0x2190..0x2199, 0x21B8..0x21B9, 0x21D2..0x21D2, 0x21D4..0x21D4, 0x21E7..0x21E7, 0x2200..0x2200, 0x2202..0x2203, 0x2207..0x2208, 0x220B..0x220B, 0x220F..0x220F, 0x2211..0x2211, 0x2215..0x2215, 0x221A..0x221A, 0x221D..0x2220, 0x2223..0x2223, 0x2225..0x2225, 0x2227..0x222C, 0x222E..0x222E, 0x2234..0x2237, 0x223C..0x223D, 0x2248..0x2248, 0x224C..0x224C, 0x2252..0x2252, 0x2260..0x2261, 0x2264..0x2267, 0x226A..0x226B, 0x226E..0x226F, 0x2282..0x2283, 0x2286..0x2287, 0x2295..0x2295, 0x2299..0x2299, 0x22A5..0x22A5, 0x22BF..0x22BF, 0x2312..0x2312, 0x2460..0x24E9, 0x24EB..0x254B, 0x2550..0x2573, 0x2580..0x258F, 0x2592..0x2595, 0x25A0..0x25A1, 0x25A3..0x25A9, 0x25B2..0x25B3, 0x25B6..0x25B7, 0x25BC..0x25BD, 0x25C0..0x25C1, 0x25C6..0x25C8, 0x25CB..0x25CB, 0x25CE..0x25D1, 0x25E2..0x25E5, 0x25EF..0x25EF, 0x2605..0x2606, 0x2609..0x2609, 0x260E..0x260F, 0x2614..0x2615, 0x261C..0x261C, 0x261E..0x261E, 0x2640..0x2640, 0x2642..0x2642, 0x2660..0x2661, 0x2663..0x2665, 0x2667..0x266A, 0x266C..0x266D, 0x266F..0x266F, 0x273D..0x273D, 0x2776..0x277F, 0xE000..0xF8FF, 0xFE00..0xFE0F, 0xFFFD..0xFFFD, 0xE0100..0xE01EF, 0xF0000..0xFFFFD, 0x100000..0x10FFFD, ] def wide_character?(character) binary_search_ranges(character, WIDE_CHARACTERS) or binary_search_ranges(character, AMBIGUOUS) end private def binary_search_ranges(character, ranges) if ranges.size.zero? false elsif ranges.size == 1 ranges[0].include?(character) else half = ranges.size / 2 range = ranges[half] if range.include?(character) true elsif character < range.begin binary_search_ranges(character, ranges[0...half]) else binary_search_ranges(character, ranges[(half + 1)..-1]) end end end end def initialize(line) @line = line @characters = @line.unpack("U*") end def [](*args) result = @characters[*args] if result.respond_to?(:pack) result.pack("U*") else result end end def each(&block) @characters.each(&block) end def size @characters.size end def to_s @line end def compute_width(start, _end) width = 0 start.upto(_end - 1) do |i| if self.class.wide_character?(@characters[i]) width += 2 else width += 1 end end width end end class ReadableDiffer < Differ def diff(options={}) @result = [] operations.each do |tag, from_start, from_end, to_start, to_end| case tag when :replace diff_lines(from_start, from_end, to_start, to_end) when :delete tag_deleted(@from[from_start...from_end]) when :insert tag_inserted(@to[to_start...to_end]) when :equal tag_equal(@from[from_start...from_end]) else raise "unknown tag: #{tag}" end end @result end private def operations @operations ||= nil if @operations.nil? matcher = SequenceMatcher.new(@from, @to) @operations = matcher.operations end @operations end def default_ratio 0.74 end def cut_off_ratio 0.75 end def tag(mark, contents) contents.each do |content| @result << (mark + content) end end def tag_deleted(contents) tag("- ", contents) end def tag_inserted(contents) tag("+ ", contents) end def tag_equal(contents) tag(" ", contents) end def tag_difference(contents) tag("? ", contents) end def find_diff_line_info(from_start, from_end, to_start, to_end) best_ratio = default_ratio from_equal_index = to_equal_index = nil from_best_index = to_best_index = nil to_start.upto(to_end - 1) do |to_index| from_start.upto(from_end - 1) do |from_index| if @from[from_index] == @to[to_index] from_equal_index ||= from_index to_equal_index ||= to_index next end matcher = SequenceMatcher.new(@from[from_index], @to[to_index], &method(:space_character?)) if matcher.ratio > best_ratio best_ratio = matcher.ratio from_best_index = from_index to_best_index = to_index end end end [best_ratio, from_equal_index, to_equal_index, from_best_index, to_best_index] end def diff_lines(from_start, from_end, to_start, to_end) info = find_diff_line_info(from_start, from_end, to_start, to_end) best_ratio, from_equal_index, to_equal_index, *info = info from_best_index, to_best_index = info from_best_index ||= from_start to_best_index ||= to_start if best_ratio < cut_off_ratio if from_equal_index.nil? if to_end - to_start < from_end - from_start tag_inserted(@to[to_start...to_end]) tag_deleted(@from[from_start...from_end]) else tag_deleted(@from[from_start...from_end]) tag_inserted(@to[to_start...to_end]) end return end from_best_index = from_equal_index to_best_index = to_equal_index best_ratio = 1.0 end _diff_lines(from_start, from_best_index, to_start, to_best_index) diff_line(@from[from_best_index], @to[to_best_index]) _diff_lines(from_best_index + 1, from_end, to_best_index + 1, to_end) end def _diff_lines(from_start, from_end, to_start, to_end) if from_start < from_end if to_start < to_end diff_lines(from_start, from_end, to_start, to_end) else tag_deleted(@from[from_start...from_end]) end else tag_inserted(@to[to_start...to_end]) end end def line_operations(from_line, to_line) if !from_line.respond_to?(:force_encoding) and $KCODE == "UTF8" from_line = UTF8Line.new(from_line) to_line = UTF8Line.new(to_line) end matcher = SequenceMatcher.new(from_line, to_line, &method(:space_character?)) [from_line, to_line, matcher.operations] end def compute_width(line, start, _end) if line.respond_to?(:encoding) and Encoding.compatible?(Encoding::UTF_8, line.encoding) utf8_line = line[start..._end].encode(Encoding::UTF_8) width = 0 utf8_line.each_codepoint do |unicode_codepoint| if UTF8Line.wide_character?(unicode_codepoint) width += 2 else width += 1 end end width elsif line.is_a?(UTF8Line) line.compute_width(start, _end) else _end - start end end def diff_line(from_line, to_line) from_tags = "" to_tags = "" from_line, to_line, _operations = line_operations(from_line, to_line) _operations.each do |tag, from_start, from_end, to_start, to_end| from_width = compute_width(from_line, from_start, from_end) to_width = compute_width(to_line, to_start, to_end) case tag when :replace from_tags += "^" * from_width to_tags += "^" * to_width when :delete from_tags += "-" * from_width when :insert to_tags += "+" * to_width when :equal from_tags += " " * from_width to_tags += " " * to_width else raise "unknown tag: #{tag}" end end format_diff_point(from_line, to_line, from_tags, to_tags) end def format_diff_point(from_line, to_line, from_tags, to_tags) common = [n_leading_characters(from_line, ?\t), n_leading_characters(to_line, ?\t)].min common = [common, n_leading_characters(from_tags[0, common], " "[0])].min from_tags = from_tags[common..-1].rstrip to_tags = to_tags[common..-1].rstrip tag_deleted([from_line]) unless from_tags.empty? tag_difference(["#{"\t" * common}#{from_tags}"]) end tag_inserted([to_line]) unless to_tags.empty? tag_difference(["#{"\t" * common}#{to_tags}"]) end end def n_leading_characters(string, character) n = 0 while string[n] == character n += 1 end n end def space_character?(character) [" "[0], "\t"[0]].include?(character) end end class UnifiedDiffer < Differ def diff(options={}) groups = SequenceMatcher.new(@from, @to).grouped_operations return [] if groups.empty? return [] if same_content?(groups) show_context = options[:show_context] show_context = true if show_context.nil? result = ["--- #{options[:from_label]}".rstrip, "+++ #{options[:to_label]}".rstrip] groups.each do |operations| result << format_summary(operations, show_context) operations.each do |args| operation_tag, from_start, from_end, to_start, to_end = args case operation_tag when :replace result.concat(tag("-", @from[from_start...from_end])) result.concat(tag("+", @to[to_start...to_end])) when :delete result.concat(tag("-", @from[from_start...from_end])) when :insert result.concat(tag("+", @to[to_start...to_end])) when :equal result.concat(tag(" ", @from[from_start...from_end])) end end end result end private def same_content?(groups) return false if groups.size != 1 group = groups[0] return false if group.size != 1 tag, from_start, from_end, to_start, to_end = group[0] tag == :equal and [from_start, from_end] == [to_start, to_end] end def format_summary(operations, show_context) _, first_from_start, _, first_to_start, _ = operations[0] _, _, last_from_end, _, last_to_end = operations[-1] summary = "@@ -%d,%d +%d,%d @@" % [first_from_start + 1, last_from_end - first_from_start, first_to_start + 1, last_to_end - first_to_start,] if show_context interesting_line = find_interesting_line(first_from_start, first_to_start, :define_line?) summary << " #{interesting_line}" if interesting_line end summary end def find_interesting_line(from_start, to_start, predicate) from_index = from_start to_index = to_start while from_index >= 0 or to_index >= 0 [@from[from_index], @to[to_index]].each do |line| return line if line and __send__(predicate, line) end from_index -= 1 to_index -= 1 end nil end def define_line?(line) /\A(?:[_a-zA-Z$]|\s*(?:class|module|def)\b)/ =~ line end end module_function def need_fold?(diff) /^[-+].{79}/ =~ diff end def fold(string) string.split(/\r?\n/).collect do |line| line.gsub(/(.{78})/, "\\1\n") end.join("\n") end def folded_readable(from, to, options={}) readable(fold(from), fold(to), options) end def readable(from, to, options={}) diff(ReadableDiffer, from, to, options) end def unified(from, to, options={}) diff(UnifiedDiffer, from, to, options) end def diff(differ_class, from, to, options={}) if from.respond_to?(:valid_encoding?) and not from.valid_encoding? from = from.dup.force_encoding("ASCII-8BIT") end if to.respond_to?(:valid_encoding?) and not to.valid_encoding? to = to.dup.force_encoding("ASCII-8BIT") end differ = differ_class.new(from.split(/\r?\n/), to.split(/\r?\n/)) lines = differ.diff(options) if Object.const_defined?(:EncodingError) begin lines.join("\n") rescue EncodingError lines.collect {|line| line.force_encoding("ASCII-8BIT")}.join("\n") end else lines.join("\n") end end end end end PK% ]*6r +gems/test-unit-3.2.9/lib/test/unit/color.rbnu[module Test module Unit class Color class Error < StandardError end class ParseError < Error end class << self def parse_256_color(string) case string when /\A([0-5])([0-5])([0-5])\z/ red, green, blue = $1, $2, $3 red.to_i * 36 + green.to_i * 6 + blue.to_i + 16 else message = "must be 'RGB' format and R, G and B " + "are in 0-5: #{string.inspect}" raise ParseError, message end end end NAMES = ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"] attr_reader :name def initialize(name, options={}) @name = name if options.has_key?(:foreground) if options[:foreground].nil? @background = false else @background = !options[:foreground] end else @background = options[:background] end @intensity = options[:intensity] @bold = options[:bold] @italic = options[:italic] @underline = options[:underline] end def foreground? not background? end def background? @background end def intensity? @intensity end def bold? @bold end def italic? @italic end def underline? @underline end def ==(other) self.class === other and [name, background?, intensity?, bold?, italic?, underline?] == [other.name, other.background?, other.intensity?, other.bold?, other.italic?, other.underline?] end def sequence sequence = [] if @name == "none" elsif @name == "reset" sequence << "0" else if NAMES.include?(@name) color_parameter = foreground? ? 3 : 4 color_parameter += 6 if intensity? color = NAMES.index(@name) sequence << "#{color_parameter}#{color}" else sequence << (foreground? ? "38" : "48") sequence << "5" sequence << self.class.parse_256_color(@name).to_s end end sequence << "1" if bold? sequence << "3" if italic? sequence << "4" if underline? sequence end def escape_sequence "\e[#{sequence.join(';')}m" end def +(other) MixColor.new([self, other]) end end class MixColor attr_reader :colors def initialize(colors) @colors = colors end def sequence @colors.inject([]) do |result, color| result + color.sequence end end def escape_sequence "\e[#{sequence.join(';')}m" end def +(other) self.class.new([self, other]) end def ==(other) self.class === other and colors == other.colors end end end end PK% ]jx /gems/test-unit-3.2.9/lib/test/unit/data-sets.rbnu[module Test module Unit class DataSets def initialize @variables = [] @procs = [] @value_sets = [] end def add(data_set, options=nil) options ||= {} if data_set.respond_to?(:call) @procs << [data_set, options] elsif data_set.is_a?(Array) @variables << [data_set, options] else @value_sets << [data_set, options] end end def <<(data_set) add(data_set) end def keep new_data_sets = self.class.new all_data_sets = Enumerator.new do |yielder| block = lambda do |(data_set, options)| yielder << [data_set, options] end @procs.each(&block) @variables.each(&block) @value_sets.each(&block) end all_data_sets.each do |data_set, options| next if options.nil? next unless options[:keep] new_data_sets.add(data_set, options) end new_data_sets end def each variables = @variables value_sets = @value_sets @procs.each do |proc, options| data_set = proc.call case data_set when Array variables += [[data_set, options]] else value_sets += [[data_set, options]] end end value_sets.each do |values, _options| values.each do |label, data| yield(label, data) end end each_pattern(variables) do |label, data| yield(label, data) end end def ==(other) @variables == other.instance_variable_get(:@variables) and @procs == other.instance_variable_get(:@procs) and @value_sets == other.instance_variable_get(:@value_sets) end def eql?(other) self == other end def hash [@variables, @procs, @value_sets].hash end private def each_pattern(variables) grouped_variables = variables.group_by do |_, options| options[:group] end grouped_variables.each do |group, variables| each_raw_pattern(variables) do |cell| label = String.new label << "group: #{group.inspect}" unless group.nil? data = {} cell.each do |variable, pattern| label << ", " unless label.empty? label << "#{variable}: #{pattern.inspect}" data[variable] = pattern end yield(label, data) end end end def each_raw_pattern(variables, &block) return if variables.empty? sorted_variables = variables.sort_by do |(variable, _), _| variable end all_patterns = sorted_variables.collect do |(variable, patterns), _| patterns.collect do |pattern| [variable, pattern] end end all_patterns[0].product(*all_patterns[1..-1], &block) end end end end PK% ]Z((0gems/test-unit-3.2.9/lib/test/unit/assertions.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. # Copyright (c) 2009-2013 Kouhei Sutou. All rights reserved. # License:: Ruby license. require 'test/unit/assertion-failed-error' require 'test/unit/util/backtracefilter' require 'test/unit/util/method-owner-finder' require 'test/unit/diff' begin require 'power_assert' rescue LoadError, SyntaxError end module Test module Unit ## # Test::Unit::Assertions contains the standard Test::Unit assertions. # Assertions is included in Test::Unit::TestCase. # # To include it in your own code and use its functionality, you simply # need to rescue Test::Unit::AssertionFailedError. Additionally you may # override add_assertion to get notified whenever an assertion is made. # # Notes: # # * The message to each assertion, if given, will be propagated with the # failure. # * It is easy to add your own assertions based on assert_block(). # # @example Example Custom Assertion # # def deny(boolean, message = nil) # message = build_message message, ' is not false or nil.', boolean # assert_block message do # not boolean # end # end module Assertions ## # The assertion upon which all other assertions are based. Passes if the # block yields true. # # @example # assert_block "Couldn't do the thing" do # do_the_thing # end def assert_block(message="assert_block failed.") _wrap_assertion do if (! yield) raise AssertionFailedError.new(message.to_s) end end end # @private NOT_SPECIFIED = Object.new # @overload assert(object, message=nil) # # Asserts that `object` is not false nor nil. # # Normally, you don't need to use this assertion. Use more # specific assertions such as #assert_equal and # #assert_include. # # @example Pass patterns # assert(true) # => pass # assert([1, 2].include?(1)) # => pass # # @example Failure patterns # assert(nil) # => failure # assert(false) # => failure # assert([1, 2].include?(5)) # => failure # # @param [Object] object The check target. # @param [String] message The additional user message. It is # showed when the assertion is failed. # @return [void] # # @overload assert(message=nil) {} # # Asserts that the givens block returns not false nor nil. # # This style uses Power Assert. It means that you can see each # object values in method chains on failure. See the following # example about Power Assert. # # @example Power Assert # coins = [1, 5, 50] # target_coin = 10 # assert do # coins.include?(target_coin) # end # # => # # coins.include?(target_coin) # # | | | # # | | 10 # # | false # # [1, 5, 50] # # We recommend you to use Power Assert for predicate method # checks rather than existing assertions such as # #assert_include and #assert_predicate. Power Assert shows # useful message for debugging. # # We don't recommend you use Power Assert for equality # check. You should use #assert_equal for the case. Because # #assert_equal shows more useful message for debugging. # # @example Pass patterns # assert {true} # => pass # assert {[1, 2].include?(1)} # => pass # # @example Failure patterns # assert {nil} # => failure # assert {false} # => failure # assert {[1, 2].include?(5)} # => failure # # @param [String] message The additional user message. It is # showed when the assertion is failed. # @yield [] Given no parameters to the block. # @yieldreturn [Object] The checked object. # @return [void] def assert(object=NOT_SPECIFIED, message=nil, &block) _wrap_assertion do have_object = !NOT_SPECIFIED.equal?(object) if block message = object if have_object if defined?(PowerAssert) PowerAssert.start(block, :assertion_method => __callee__) do |pa| pa_message = AssertionMessage.delayed_literal(&pa.message_proc) assertion_message = build_message(message, "?", pa_message) assert_block(assertion_message) do pa.yield end end else assert(yield, message) end else unless have_object raise ArgumentError, "wrong number of arguments (0 for 1..2)" end assertion_message = nil case message when nil, String, Proc when AssertionMessage assertion_message = message else error_message = "assertion message must be String, Proc or " error_message += "#{AssertionMessage}: " error_message += "<#{message.inspect}>(<#{message.class}>)" raise ArgumentError, error_message, filter_backtrace(caller) end assertion_message ||= build_message(message, " is not true.", object) assert_block(assertion_message) do object end end end end # Asserts that +object+ is false or nil. # # @note Just for minitest compatibility. :< # # @param [Object] object The object to be asserted. # @return [void] # # @example Pass patterns # refute(false) # => pass # refute(nil) # => pass # # @example Failure patterns # refute(true) # => failure # refute("string") # => failure # # @since 2.5.3 def refute(object, message=nil) _wrap_assertion do assertion_message = nil case message when nil, String, Proc when AssertionMessage assertion_message = message else error_message = "assertion message must be String, Proc or " error_message += "#{AssertionMessage}: " error_message += "<#{message.inspect}>(<#{message.class}>)" raise ArgumentError, error_message, filter_backtrace(caller) end assert_block("refute should not be called with a block.") do !block_given? end assertion_message ||= build_message(message, " is neither nil or false.", object) assert_block(assertion_message) do not object end end end ## # Passes if +expected+ == +actual+. # # Note that the ordering of arguments is important, since a helpful # error message is generated when this one fails that tells you the # values of expected and actual. # # @example # assert_equal 'MY STRING', 'my string'.upcase def assert_equal(expected, actual, message=nil) diff = AssertionMessage.delayed_diff(expected, actual) if expected.respond_to?(:encoding) and actual.respond_to?(:encoding) and expected.encoding != actual.encoding format = <(?) expected but was (?).? EOT full_message = build_message(message, format, expected, expected.encoding.name, actual, actual.encoding.name, diff) else full_message = build_message(message, < expected but was .? EOT end begin assert_block(full_message) { expected == actual } rescue AssertionFailedError => failure _set_failed_information(failure, expected, actual, message) raise failure # For JRuby. :< end end ## # Passes if the block raises one of the expected # exceptions. When an expected exception is an Exception # object, passes if expected_exception == actual_exception. # # @example # assert_raise(RuntimeError, LoadError) do # raise 'Boom!!!' # end # -> pass # # assert_raise do # raise Exception, 'Any exception should be raised!!!' # end # -> pass # # assert_raise(RuntimeError.new("XXX")) {raise "XXX"} # -> pass # assert_raise(MyError.new("XXX")) {raise "XXX"} # -> fail # assert_raise(RuntimeError.new("ZZZ")) {raise "XXX"} # -> fail def assert_raise(*args, &block) assert_expected_exception = Proc.new do |*_args| message, assert_exception_helper, actual_exception = _args expected = assert_exception_helper.expected_exceptions diff = AssertionMessage.delayed_diff(expected, actual_exception) full_message = build_message(message, " exception expected but was\n.?", expected, actual_exception, diff) begin assert_block(full_message) do expected == [] or assert_exception_helper.expected?(actual_exception) end rescue AssertionFailedError => failure _set_failed_information(failure, expected, actual_exception, message) raise failure # For JRuby. :< end end _assert_raise(assert_expected_exception, *args, &block) end # Just for minitest compatibility. :< alias_method :assert_raises, :assert_raise ## # Passes if the block raises one of the given # exceptions or sub exceptions of the given exceptions. # # @example # assert_raise_kind_of(SystemCallError) do # raise Errno::EACCES # end def assert_raise_kind_of(*args, &block) assert_expected_exception = Proc.new do |*_args| message, assert_exception_helper, actual_exception = _args expected = assert_exception_helper.expected_exceptions full_message = build_message(message, " family exception expected " + "but was\n.", expected, actual_exception) assert_block(full_message) do assert_exception_helper.expected?(actual_exception, :kind_of?) end end _assert_raise(assert_expected_exception, *args, &block) end ## # Passes if +object+.instance_of?(+klass+). When +klass+ is # an array of classes, it passes if any class # satisfies +object.instance_of?(class). # # @example # assert_instance_of(String, 'foo') # -> pass # assert_instance_of([Fixnum, NilClass], 100) # -> pass # assert_instance_of([Numeric, NilClass], 100) # -> fail def assert_instance_of(klass, object, message="") _wrap_assertion do if klass.is_a?(Array) klasses = klass else klasses = [klass] end assert_block("The first parameter to assert_instance_of should be " + "a Class or an Array of Class.") do klasses.all? {|k| k.is_a?(Class)} end klass_message = AssertionMessage.maybe_container(klass) do |value| "<#{value}>" end full_message = build_message(message, < was expected to be instance_of\\? ? but was . EOT assert_block(full_message) do klasses.any? {|k| object.instance_of?(k)} end end end ## # Passes if +object+.instance_of?(+klass+) does not hold. # When +klass+ is an array of classes, it passes if no class # satisfies +object.instance_of?(class). # # @example # assert_not_instance_of(String, 100) # -> pass # assert_not_instance_of([Fixnum, NilClass], '100') # -> pass # assert_not_instance_of([Numeric, NilClass], 100) # -> fail # # @since 3.0.0 def assert_not_instance_of(klass, object, message="") _wrap_assertion do if klass.is_a?(Array) klasses = klass else klasses = [klass] end assert_block("The first parameter to assert_not_instance_of should be " + "a Class or an Array of Class.") do klasses.all? {|k| k.is_a?(Class)} end klass_message = AssertionMessage.maybe_container(klass) do |value| "<#{value}>" end full_message = build_message(message, " was expected to not be instance_of\\?\n" + "? but was.", object, klass_message) assert_block(full_message) do klasses.none? {|k| object.instance_of?(k)} end end end # Just for minitest compatibility. :< # # @since 3.0.0 alias_method :refute_instance_of, :assert_not_instance_of ## # Passes if +object+ is nil. # # @example # assert_nil [1, 2].uniq! def assert_nil(object, message="") full_message = build_message(message, < was expected to be nil. EOT assert_block(full_message) { object.nil? } end ## # Passes if +object+.kind_of?(+klass+). When +klass+ is # an array of classes or modules, it passes if any # class or module satisfies +object.kind_of?(class_or_module). # # @example # assert_kind_of(Object, 'foo') # -> pass # assert_kind_of([Fixnum, NilClass], 100) # -> pass # assert_kind_of([Fixnum, NilClass], "string") # -> fail def assert_kind_of(klass, object, message="") _wrap_assertion do if klass.is_a?(Array) klasses = klass else klasses = [klass] end assert_block("The first parameter to assert_kind_of should be " + "a kind_of Module or an Array of a kind_of Module.") do klasses.all? {|k| k.kind_of?(Module)} end klass_message = AssertionMessage.maybe_container(klass) do |value| "<#{value}>" end full_message = build_message(message, " was expected to be kind_of\\?\n" + "? but was\n" + ".", object, klass_message, object.class) assert_block(full_message) do klasses.any? {|k| object.kind_of?(k)} end end end ## # Passes if +object+.kind_of?(+klass+) does not hold. # When +klass+ is an array of classes or modules, it passes only if all # classes (and modules) do not satisfy +object.kind_of?(class_or_module). # # @example # assert_not_kind_of(Fixnum, 'foo') # -> pass # assert_not_kind_of([Fixnum, NilClass], '0') # -> pass # assert_not_kind_of([Fixnum, NilClass], 100) # -> fail # # @since 3.0.0 def assert_not_kind_of(klass, object, message="") _wrap_assertion do if klass.is_a?(Array) klasses = klass else klasses = [klass] end assert_block("The first parameter to assert_not_kind_of should be " + "a kind_of Module or an Array of a kind_of Module.") do klasses.all? {|k| k.kind_of?(Module)} end klass_message = AssertionMessage.maybe_container(klass) do |value| "<#{value}>" end full_message = build_message(message, " was expected to not be kind_of\\?\n" + "? but was.", object, klass_message) assert_block(full_message) do klasses.none? {|k| object.kind_of?(k)} end end end # Just for minitest compatibility. :< # # @since 3.0.0 alias_method :refute_kind_of, :assert_not_kind_of ## # Passes if +object+ .respond_to? +method+ # # @example # assert_respond_to 'bugbear', :slice def assert_respond_to(object, method, message="") _wrap_assertion do full_message = build_message(message, ".kind_of\\?(Symbol) or\n" + ".respond_to\\?(:to_str) expected", method, method) assert_block(full_message) do method.kind_of?(Symbol) or method.respond_to?(:to_str) end full_message = build_message(message, ".respond_to\\?(?) expected\n" + "(Class: )", object, method, object.class) assert_block(full_message) {object.respond_to?(method)} end end ## # Passes if +object+ does not .respond_to? +method+. # # @example # assert_not_respond_to('bugbear', :nonexistence) # -> pass # assert_not_respond_to('bugbear', :size) # -> fail def assert_not_respond_to(object, method, message="") _wrap_assertion do full_message = build_message(message, ".kind_of\\?(Symbol) or\n" + ".respond_to\\?(:to_str) expected", method, method) assert_block(full_message) do method.kind_of?(Symbol) or method.respond_to?(:to_str) end full_message = build_message(message, "!.respond_to\\?(?) expected\n" + "(Class: )", object, method, object.class) assert_block(full_message) {!object.respond_to?(method)} end end # Just for minitest compatibility. :< # # @since 2.5.3 alias_method :refute_respond_to, :assert_not_respond_to ## # Passes if +pattern+ =~ +string+. # # @example # assert_match(/\d+/, 'five, 6, seven') def assert_match(pattern, string, message="") _wrap_assertion do pattern = case(pattern) when String Regexp.new(Regexp.escape(pattern)) else pattern end full_message = build_message(message, " was expected to be =~\n.", pattern, string) assert_block(full_message) { pattern =~ string } end end ## # Passes if +actual+ .equal? +expected+ (i.e. they are the same # instance). # # @example # o = Object.new # assert_same o, o def assert_same(expected, actual, message="") full_message = build_message(message, < with id was expected to be equal\\? to with id . EOT assert_block(full_message) { actual.equal?(expected) } end ## # Compares the +object1+ with +object2+ using +operator+. # # Passes if object1.__send__(operator, object2) is true. # # @example # assert_operator 5, :>=, 4 def assert_operator(object1, operator, object2, message="") _wrap_assertion do full_message = build_message(nil, "\ngiven as the operator for #assert_operator must be a Symbol or #respond_to\\?(:to_str).", operator) assert_block(full_message){operator.kind_of?(Symbol) || operator.respond_to?(:to_str)} full_message = build_message(message, < was expected to be ? . EOT assert_block(full_message) { object1.__send__(operator, object2) } end end ## # Compares the +object1+ with +object2+ using +operator+. # # Passes if object1.__send__(operator, object2) is not true. # # @example # assert_not_operator(5, :<, 4) # => pass # assert_not_operator(5, :>, 4) # => fail # # @since 3.0.0 def assert_not_operator(object1, operator, object2, message="") _wrap_assertion do full_message = build_message(nil, "\ngiven as the operator for #assert_not_operator must be a Symbol or #respond_to\\?(:to_str).", operator) assert_block(full_message){operator.kind_of?(Symbol) || operator.respond_to?(:to_str)} full_message = build_message(message, < was expected to not be ? . EOT assert_block(full_message) { ! object1.__send__(operator, object2) } end end # Just for minitest compatibility. :< # # @since 3.0.0 alias_method :refute_operator, :assert_not_operator ## # Passes if block does not raise an exception. # # @example # assert_nothing_raised do # [1, 2].uniq # end def assert_nothing_raised(*args) _wrap_assertion do if args.last.is_a?(String) message = args.pop else message = "" end assert_exception_helper = AssertExceptionHelper.new(self, args) begin yield rescue Exception => e if ((args.empty? && !e.instance_of?(AssertionFailedError)) || assert_exception_helper.expected?(e)) failure_message = build_message(message, "Exception raised:\n?", e) assert_block(failure_message) {false} else raise end end end end ## # Flunk always fails. # # @example # flunk 'Not done testing yet.' def flunk(message="Flunked") assert_block(build_message(message)){false} end ## # Passes if ! +actual+ .equal? +expected+ # # @example # assert_not_same Object.new, Object.new def assert_not_same(expected, actual, message="") full_message = build_message(message, < with id was expected to not be equal\\? to with id . EOT assert_block(full_message) { !actual.equal?(expected) } end # Just for minitest compatibility. :< # # @since 2.5.3 alias_method :refute_same, :assert_not_same ## # Passes if +expected+ != +actual+ # # @example # assert_not_equal 'some string', 5 def assert_not_equal(expected, actual, message="") full_message = build_message(message, " was expected to be != to\n.", expected, actual) assert_block(full_message) { expected != actual } end # Just for minitest compatibility. :< # # @since 2.5.3 alias_method :refute_equal, :assert_not_equal ## # Passes if ! +object+ .nil? # # @example # assert_not_nil '1 two 3'.sub!(/two/, '2') def assert_not_nil(object, message="") full_message = build_message(message, " was expected to not be nil.", object) assert_block(full_message){!object.nil?} end # Just for minitest compatibility. :< # # @since 2.5.3 alias_method :refute_nil, :assert_not_nil ## # Passes if +regexp+ !~ +string+ # # @example # assert_not_match(/two/, 'one 2 three') # -> pass # assert_not_match(/three/, 'one 2 three') # -> fail def assert_not_match(regexp, string, message="") _wrap_assertion do assert_instance_of(Regexp, regexp, " in assert_not_match(, ...) " + "should be a Regexp.") full_message = build_message(message, " was expected to not match\n.", regexp, string) assert_block(full_message) { regexp !~ string } end end # Just for minitest compatibility. :< # # @since 2.5.3 alias_method :refute_match, :assert_not_match ## # Deprecated. Use #assert_not_match instead. # # Passes if +regexp+ !~ +string+ # # @example # assert_no_match(/two/, 'one 2 three') # -> pass # assert_no_match(/three/, 'one 2 three') # -> fail def assert_no_match(regexp, string, message="") _wrap_assertion do assert_instance_of(Regexp, regexp, "The first argument to assert_no_match " + "should be a Regexp.") assert_not_match(regexp, string, message) end end # @private class ThrowTagExtractor @@have_uncaught_throw_error = const_defined?(:UncaughtThrowError) UncaughtThrowPatterns = { NameError => /^uncaught throw `(.+)'$/, ArgumentError => /^uncaught throw (`.+'|.+)$/, ThreadError => /^uncaught throw `(.+)' in thread /, } def initialize(error) @error = error end def extract_tag tag = nil if @@have_uncaught_throw_error return nil unless @error.is_a?(UncaughtThrowError) tag = @error.tag else pattern = UncaughtThrowPatterns[@error.class] return nil if pattern.nil? return nil unless pattern =~ @error.message tag = $1 end normalize_tag(tag) end private def normalize_tag(tag) case tag when /\A:/ tag[1..-1].intern when /\A`(.+)'\z/ $1.intern when String tag.intern else tag end end end ## # Passes if the block throws +expected_object+ # # @example # assert_throw(:done) do # throw(:done) # end def assert_throw(expected_object, message="", &proc) _wrap_assertion do begin catch([]) {} rescue TypeError assert_instance_of(Symbol, expected_object, "assert_throws expects the symbol that should be thrown for its first argument") end assert_block("Should have passed a block to assert_throw.") do block_given? end caught = true begin catch(expected_object) do proc.call caught = false end full_message = build_message(message, " should have been thrown.", expected_object) assert_block(full_message) {caught} rescue => error extractor = ThrowTagExtractor.new(error) tag = extractor.extract_tag raise if tag.nil? full_message = build_message(message, " was expected to be thrown but\n" + " was thrown.", expected_object, tag) flunk(full_message) end end end # Just for minitest compatibility. :< # # @since 2.5.3 alias_method :assert_throws, :assert_throw ## # Passes if block does not throw anything. # # @example # assert_nothing_thrown do # [1, 2].uniq # end def assert_nothing_thrown(message="", &proc) _wrap_assertion do assert(block_given?, "Should have passed a block to assert_nothing_thrown") begin proc.call rescue => error extractor = ThrowTagExtractor.new(error) tag = extractor.extract_tag raise if tag.nil? full_message = build_message(message, " was thrown when nothing was expected", tag) flunk(full_message) end assert(true, "Expected nothing to be thrown") end end ## # Passes if +expected_float+ and +actual_float+ are equal # within +delta+ tolerance. # # @example # assert_in_delta 0.05, (50000.0 / 10**6), 0.00001 def assert_in_delta(expected_float, actual_float, delta=0.001, message="") _wrap_assertion do _assert_in_delta_validate_arguments(expected_float, actual_float, delta) full_message = _assert_in_delta_message(expected_float, actual_float, delta, message) assert_block(full_message) do (expected_float.to_f - actual_float.to_f).abs <= delta.to_f end end end ## # Passes if +expected_float+ and +actual_float+ are # not equal within +delta+ tolerance. # # @example # assert_not_in_delta(0.05, (50000.0 / 10**6), 0.00002) # -> pass # assert_not_in_delta(0.05, (50000.0 / 10**6), 0.00001) # -> fail def assert_not_in_delta(expected_float, actual_float, delta=0.001, message="") _wrap_assertion do _assert_in_delta_validate_arguments(expected_float, actual_float, delta) full_message = _assert_in_delta_message(expected_float, actual_float, delta, message, :negative_assertion => true) assert_block(full_message) do (expected_float.to_f - actual_float.to_f).abs > delta.to_f end end end # Just for minitest compatibility. :< # # @since 2.5.3 alias_method :refute_in_delta, :assert_not_in_delta private def _assert_in_delta_validate_arguments(expected_float, actual_float, delta) { expected_float => "first float", actual_float => "second float", delta => "delta" }.each do |float, name| assert_respond_to(float, :to_f, "The arguments must respond to to_f; " + "the #{name} did not") end delta = delta.to_f assert_operator(delta, :>=, 0.0, "The delta should not be negative") end def _assert_in_delta_message(expected_float, actual_float, delta, message, options={}) if options[:negative_assertion] format = <<-EOT -/+ was expected to not include . EOT else format = <<-EOT -/+ was expected to include . EOT end arguments = [expected_float, delta, actual_float] normalized_expected = expected_float.to_f normalized_actual = actual_float.to_f normalized_delta = delta.to_f relation_format = nil relation_arguments = nil if normalized_actual < normalized_expected - normalized_delta relation_format = "< < -[?] <= +[?]>" relation_arguments = [actual_float, expected_float, delta, normalized_expected - normalized_delta, expected_float, delta, normalized_expected + normalized_delta] elsif normalized_actual <= normalized_expected + normalized_delta relation_format = "<-[?] <= <= +[?]>" relation_arguments = [expected_float, delta, normalized_expected - normalized_delta, actual_float, expected_float, delta, normalized_expected + normalized_delta] else relation_format = "<-[?] <= +[?] < >" relation_arguments = [expected_float, delta, normalized_expected - normalized_delta, expected_float, delta, normalized_expected + normalized_delta, actual_float] end if relation_format format += <<-EOT Relation: #{relation_format} EOT arguments.concat(relation_arguments) end build_message(message, format, *arguments) end public ## # Passes if +expected_float+ and +actual_float+ are equal # within +epsilon+ relative error of +expected_float+. # # @example # assert_in_epsilon(10000.0, 9900.0, 0.1) # -> pass # assert_in_epsilon(10000.0, 9899.0, 0.1) # -> fail def assert_in_epsilon(expected_float, actual_float, epsilon=0.001, message="") _wrap_assertion do _assert_in_epsilon_validate_arguments(expected_float, actual_float, epsilon) full_message = _assert_in_epsilon_message(expected_float, actual_float, epsilon, message) assert_block(full_message) do normalized_expected_float = expected_float.to_f if normalized_expected_float.zero? delta = epsilon.to_f ** 2 else delta = normalized_expected_float * epsilon.to_f end delta = delta.abs (normalized_expected_float - actual_float.to_f).abs <= delta end end end ## # Passes if +expected_float+ and +actual_float+ are # not equal within +epsilon+ relative error of # +expected_float+. # # @example # assert_not_in_epsilon(10000.0, 9900.0, 0.1) # -> fail # assert_not_in_epsilon(10000.0, 9899.0, 0.1) # -> pass def assert_not_in_epsilon(expected_float, actual_float, epsilon=0.001, message="") _wrap_assertion do _assert_in_epsilon_validate_arguments(expected_float, actual_float, epsilon) full_message = _assert_in_epsilon_message(expected_float, actual_float, epsilon, message, :negative_assertion => true) assert_block(full_message) do normalized_expected_float = expected_float.to_f delta = normalized_expected_float * epsilon.to_f (normalized_expected_float - actual_float.to_f).abs > delta end end end # Just for minitest compatibility. :< # # @since 3.0.0 alias_method :refute_in_epsilon, :assert_not_in_epsilon private def _assert_in_epsilon_validate_arguments(expected_float, actual_float, epsilon) { expected_float => "first float", actual_float => "second float", epsilon => "epsilon" }.each do |float, name| assert_respond_to(float, :to_f, "The arguments must respond to to_f; " + "the #{name} did not") end epsilon = epsilon.to_f assert_operator(epsilon, :>=, 0.0, "The epsilon should not be negative") end def _assert_in_epsilon_message(expected_float, actual_float, epsilon, message, options={}) normalized_expected = expected_float.to_f normalized_actual = actual_float.to_f normalized_epsilon = epsilon.to_f delta = normalized_expected * normalized_epsilon if options[:negative_assertion] format = <<-EOT -/+ ( * )[?] was expected to not include . EOT else format = <<-EOT -/+ ( * )[?] was expected to include . EOT end arguments = [expected_float, expected_float, epsilon, delta, actual_float] relation_format = nil relation_arguments = nil if normalized_actual < normalized_expected - delta relation_format = "< < -(*)[?] <= +(*)[?]>" relation_arguments = [actual_float, expected_float, expected_float, epsilon, normalized_expected - delta, expected_float, expected_float, epsilon, normalized_expected + delta] elsif normalized_actual <= normalized_expected + delta relation_format = "<-(*)[?] <= <= +(*)[?]>" relation_arguments = [expected_float, expected_float, epsilon, normalized_expected - delta, actual_float, expected_float, expected_float, epsilon, normalized_expected + delta] else relation_format = "<-(*)[?] <= +(*)[?] < >" relation_arguments = [expected_float, expected_float, epsilon, normalized_expected - delta, expected_float, expected_float, epsilon, normalized_expected + delta, actual_float] end if relation_format format += <<-EOT Relation: #{relation_format} EOT arguments.concat(relation_arguments) end build_message(message, format, *arguments) end public ## # Passes if the method send returns a true value. # # +send_array+ is composed of: # * A receiver # * A method # * Arguments to the method # # @example # assert_send([[1, 2], :member?, 1]) # -> pass # assert_send([[1, 2], :member?, 4]) # -> fail def assert_send(send_array, message=nil) _wrap_assertion do assert_instance_of(Array, send_array, "assert_send requires an array " + "of send information") assert_operator(send_array.size, :>=, 2, "assert_send requires at least a receiver " + "and a message name") format = < was expected to respond to with a true value but was . EOT receiver, message_name, *arguments = send_array result = nil full_message = build_message(message, format, receiver, AssertionMessage.literal(message_name.to_s), arguments, AssertionMessage.delayed_literal {result}) assert_block(full_message) do result = receiver.__send__(message_name, *arguments) result end end end ## # Passes if the method send doesn't return a true value. # # +send_array+ is composed of: # * A receiver # * A method # * Arguments to the method # # @example # assert_not_send([[1, 2], :member?, 1]) # -> fail # assert_not_send([[1, 2], :member?, 4]) # -> pass def assert_not_send(send_array, message=nil) _wrap_assertion do assert_instance_of(Array, send_array, "assert_not_send requires an array " + "of send information") assert_operator(send_array.size, :>=, 2, "assert_not_send requires at least a receiver " + "and a message name") format = < was expected to respond to with not a true value but was . EOT receiver, message_name, *arguments = send_array result = nil full_message = build_message(message, format, receiver, AssertionMessage.literal(message_name.to_s), arguments, AssertionMessage.delayed_literal {result}) assert_block(full_message) do result = receiver.__send__(message_name, *arguments) not result end end end ## # Passes if +actual+ is a boolean value. # # @example # assert_boolean(true) # -> pass # assert_boolean(nil) # -> fail def assert_boolean(actual, message=nil) _wrap_assertion do assert_block(build_message(message, " or expected but was\n", actual)) do [true, false].include?(actual) end end end ## # Passes if +actual+ is true. # # @example # assert_true(true) # -> pass # assert_true(:true) # -> fail def assert_true(actual, message=nil) _wrap_assertion do assert_block(build_message(message, " expected but was\n", actual)) do actual == true end end end ## # Passes if +actual+ is false. # # @example # assert_false(false) # -> pass # assert_false(nil) # -> fail def assert_false(actual, message=nil) _wrap_assertion do assert_block(build_message(message, " expected but was\n", actual)) do actual == false end end end ## # Passes if expression "+expected+ +operator+ # +actual+" is true. # # @example # assert_compare(1, "<", 10) # -> pass # assert_compare(1, ">=", 10) # -> fail def assert_compare(expected, operator, actual, message=nil) _wrap_assertion do assert_send([["<", "<=", ">", ">="], :include?, operator.to_s]) case operator.to_s when "<" operator_description = "less than" when "<=" operator_description = "less than or equal to" when ">" operator_description = "greater than" when ">=" operator_description = "greater than or equal to" end template = <<-EOT #{operator} should be true was expected to be #{operator_description} . EOT full_message = build_message(message, template, expected, actual, expected, actual) assert_block(full_message) do expected.__send__(operator, actual) end end end ## # Passes if assertion is failed in block. # # @example # assert_fail_assertion {assert_equal("A", "B")} # -> pass # assert_fail_assertion {assert_equal("A", "A")} # -> fail def assert_fail_assertion(message=nil) _wrap_assertion do full_message = build_message(message, "Failed assertion was expected.") assert_block(full_message) do begin yield false rescue AssertionFailedError true end end end end ## # Passes if an exception is raised in block and its # message is +expected+. # # @example # assert_raise_message("exception") {raise "exception"} # -> pass # assert_raise_message(/exc/i) {raise "exception"} # -> pass # assert_raise_message("exception") {raise "EXCEPTION"} # -> fail # assert_raise_message("exception") {} # -> fail def assert_raise_message(expected, message=nil) _wrap_assertion do full_message = build_message(message, " exception message was expected " + "but none was thrown.", expected) exception = nil assert_block(full_message) do begin yield false rescue Exception => exception true end end actual = exception.message diff = AssertionMessage.delayed_diff(expected, actual) full_message = build_message(message, " exception message expected but was\n" + ".?", expected, actual, diff) assert_block(full_message) do if expected.is_a?(Regexp) expected =~ actual else expected == actual end end end end ## # Passes if +object+.const_defined?(+constant_name+) # # @example # assert_const_defined(Test, :Unit) # -> pass # assert_const_defined(Object, :Nonexistent) # -> fail def assert_const_defined(object, constant_name, message=nil) _wrap_assertion do full_message = build_message(message, ".const_defined\\?() expected.", object, constant_name) assert_block(full_message) do object.const_defined?(constant_name) end end end ## # Passes if !+object+.const_defined?(+constant_name+) # # @example # assert_not_const_defined(Object, :Nonexistent) # -> pass # assert_not_const_defined(Test, :Unit) # -> fail def assert_not_const_defined(object, constant_name, message=nil) _wrap_assertion do full_message = build_message(message, "!.const_defined\\?() expected.", object, constant_name) assert_block(full_message) do !object.const_defined?(constant_name) end end end ## # Passes if +object+.+predicate+ is _true_. # # @example # assert_predicate([], :empty?) # -> pass # assert_predicate([1], :empty?) # -> fail def assert_predicate(object, predicate, message=nil) _wrap_assertion do assert_respond_to(object, predicate, message) actual = object.__send__(predicate) full_message = build_message(message, ".? is true value expected but was\n" + "", object, AssertionMessage.literal(predicate), actual) assert_block(full_message) do actual end end end ## # Passes if +object+.+predicate+ is not _true_. # # @example # assert_not_predicate([1], :empty?) # -> pass # assert_not_predicate([], :empty?) # -> fail def assert_not_predicate(object, predicate, message=nil) _wrap_assertion do assert_respond_to(object, predicate, message) actual = object.__send__(predicate) full_message = build_message(message, ".? is false value expected but was\n" + "", object, AssertionMessage.literal(predicate), actual) assert_block(full_message) do not actual end end end # Just for minitest compatibility. :< # # @since 3.0.0 alias_method :refute_predicate, :assert_not_predicate ## # Passes if +object+#+alias_name+ is an alias method of # +object+#+original_name+. # # @example # assert_alias_method([], :length, :size) # -> pass # assert_alias_method([], :size, :length) # -> pass # assert_alias_method([], :each, :size) # -> fail def assert_alias_method(object, alias_name, original_name, message=nil) _wrap_assertion do find_method_failure_message = Proc.new do |method_name| build_message(message, ".? doesn't exist\n" + "(Class: )", object, AssertionMessage.literal(method_name), object.class) end alias_method = original_method = nil assert_block(find_method_failure_message.call(alias_name)) do begin alias_method = object.method(alias_name) true rescue NameError false end end assert_block(find_method_failure_message.call(original_name)) do begin original_method = object.method(original_name) true rescue NameError false end end full_message = build_message(message, " is alias of\n" + " expected", alias_method, original_method) assert_block(full_message) do alias_method == original_method end end end ## # Passes if +path+ exists. # # @example # assert_path_exist("/tmp") # -> pass # assert_path_exist("/bin/sh") # -> pass # assert_path_exist("/nonexistent") # -> fail def assert_path_exist(path, message=nil) _wrap_assertion do failure_message = build_message(message, " was expected to exist", path) assert_block(failure_message) do File.exist?(path) end end end ## # Passes if +path+ doesn't exist. # # @example # assert_path_not_exist("/nonexistent") # -> pass # assert_path_not_exist("/tmp") # -> fail # assert_path_not_exist("/bin/sh") # -> fail def assert_path_not_exist(path, message=nil) _wrap_assertion do failure_message = build_message(message, " was expected to not exist", path) assert_block(failure_message) do not File.exist?(path) end end end ## # Passes if +collection+ includes +object+. # # @example # assert_include([1, 10], 1) # -> pass # assert_include(1..10, 5) # -> pass # assert_include([1, 10], 5) # -> fail # assert_include(1..10, 20) # -> fail def assert_include(collection, object, message=nil) _wrap_assertion do assert_respond_to(collection, :include?, "The collection must respond to :include?.") full_message = build_message(message, " was expected to include\n.", collection, object) assert_block(full_message) do collection.include?(object) end end end # Just for minitest compatibility. :< # # @since 2.5.3 alias_method :assert_includes, :assert_include ## # Passes if +collection+ doesn't include +object+. # # @example # assert_not_include([1, 10], 5) # -> pass # assert_not_include(1..10, 20) # -> pass # assert_not_include([1, 10], 1) # -> fail # assert_not_include(1..10, 5) # -> fail def assert_not_include(collection, object, message=nil) _wrap_assertion do assert_respond_to(collection, :include?, "The collection must respond to :include?.") full_message = build_message(message, " was expected to not include\n.", collection, object) assert_block(full_message) do not collection.include?(object) end end end # Just for minitest compatibility. :< # # @since 3.0.0 alias_method :assert_not_includes, :assert_not_include # Just for minitest compatibility. :< # # @since 3.0.0 alias_method :refute_includes, :assert_not_include ## # Passes if +object+ is empty. # # @example # assert_empty("") # -> pass # assert_empty([]) # -> pass # assert_empty({}) # -> pass # assert_empty(" ") # -> fail # assert_empty([nil]) # -> fail # assert_empty({1 => 2}) # -> fail def assert_empty(object, message=nil) _wrap_assertion do assert_respond_to(object, :empty?, "The object must respond to :empty?.") full_message = build_message(message, " was expected to be empty.", object) assert_block(full_message) do object.empty? end end end ## # Passes if +object+ is not empty. # # @example # assert_not_empty(" ") # -> pass # assert_not_empty([nil]) # -> pass # assert_not_empty({1 => 2}) # -> pass # assert_not_empty("") # -> fail # assert_not_empty([]) # -> fail # assert_not_empty({}) # -> fail def assert_not_empty(object, message=nil) _wrap_assertion do assert_respond_to(object, :empty?, "The object must respond to :empty?.") full_message = build_message(message, " was expected to not be empty.", object) assert_block(full_message) do not object.empty? end end end # Just for minitest compatibility. :< # # @since 3.0.0 alias_method :refute_empty, :assert_not_empty ## # Builds a failure message. +head+ is added before the +template+ and # +arguments+ replaces the '?'s positionally in the template. def build_message(head, template=nil, *arguments) template &&= template.chomp return AssertionMessage.new(head, template, arguments) end private def _wrap_assertion(&block) @_assertion_wrapped ||= false if @_assertion_wrapped block.call else @_assertion_wrapped = true begin add_assertion block.call ensure @_assertion_wrapped = false end end end public # Called whenever an assertion is made. Define this in classes # that include Test::Unit::Assertions to record assertion # counts. # # This is a public API for developers who extend test-unit. # # @return [void] def add_assertion end ## # Select whether or not to use the pretty-printer. If this option is set # to false before any assertions are made, pp.rb will not be required. def self.use_pp=(value) AssertionMessage.use_pp = value end private def _assert_raise(assert_expected_exception, *args, &block) _wrap_assertion do if args.last.is_a?(String) message = args.pop else message = "" end assert_exception_helper = AssertExceptionHelper.new(self, args) expected = assert_exception_helper.expected_exceptions actual_exception = nil full_message = build_message(message, " exception was expected " + "but none was thrown.", expected) assert_block(full_message) do begin yield false rescue Exception => actual_exception true end end assert_expected_exception.call(message, assert_exception_helper, actual_exception) actual_exception end end def _set_failed_information(failure, expected, actual, user_message) failure.expected = expected failure.actual = actual failure.inspected_expected = AssertionMessage.convert(expected) failure.inspected_actual = AssertionMessage.convert(actual) failure.user_message = user_message end class AssertionMessage @use_pp = true class << self attr_accessor :use_pp def literal(value) Literal.new(value) end def delayed_literal(&block) DelayedLiteral.new(block) end def maybe_container(value, &formatter) MaybeContainer.new(value, &formatter) end MAX_DIFF_TARGET_STRING_SIZE = 1000 def max_diff_target_string_size return @@max_diff_target_string_size if @@max_diff_target_string_size size = ENV["TEST_UNIT_MAX_DIFF_TARGET_STRING_SIZE"] if size begin size = Integer(size) rescue ArgumentError size = nil end end size || MAX_DIFF_TARGET_STRING_SIZE end @@max_diff_target_string_size = nil def max_diff_target_string_size=(size) @@max_diff_target_string_size = size end def diff_target_string?(string) if string.respond_to?(:bytesize) string.bytesize < max_diff_target_string_size else string.size < max_diff_target_string_size end end def ensure_diffable_string(string) if string.respond_to?(:encoding) and !string.encoding.ascii_compatible? string = string.dup.force_encoding("ASCII-8BIT") end string end def prepare_for_diff(from, to) if !from.is_a?(String) or !to.is_a?(String) from = convert(from) to = convert(to) end if diff_target_string?(from) and diff_target_string?(to) from = ensure_diffable_string(from) to = ensure_diffable_string(to) [from, to] else [nil, nil] end end def delayed_diff(from, to) delayed_literal do from, to = prepare_for_diff(from, to) diff = "" if from.nil? or to.nil? diff ||= Diff.readable(from, to) if /^[-+]/ !~ diff diff = "" elsif /^[ ?]/ =~ diff or /(?:.*\n){2,}/ =~ diff diff = "\n\ndiff:\n#{diff}" else diff = "" end if Diff.need_fold?(diff) folded_diff = Diff.folded_readable(from, to) diff += "\n\nfolded diff:\n#{folded_diff}" end diff end end def convert(object) if object.is_a?(Exception) object = AssertExceptionHelper::WrappedException.new(object) end inspector = Inspector.new(object) if use_pp begin require "pp" unless defined?(PP) begin return PP.pp(inspector, String.new).chomp rescue NameError end rescue LoadError self.use_pp = false end end inspector.inspect end end class Inspector include Comparable class << self def cached_new(object, inspected_objects) inspected_objects[object.object_id] ||= new(object, inspected_objects) end @@inspector_classes = [] def inspector_classes @@inspector_classes end def register_inspector_class(inspector_class) @@inspector_classes << inspector_class end def unregister_inspector_class(inspector_class) @@inspector_classes.delete(inspector_class) end end attr_reader :object def initialize(object, inspected_objects={}) @inspected_objects = inspected_objects @object = object @inspected_objects[@object.object_id] = self @inspect_target = inspect_target end alias_method :native_inspect, :inspect def inspect @inspect_target.inspect end def pretty_print(q) @inspect_target.pretty_print(q) end def pretty_print_cycle(q) @inspect_target.pretty_print_cycle(q) end def <=>(other) if other.is_a?(self.class) @object <=> other.object else @object <=> other end end private def inspect_target self.class.inspector_classes.each do |inspector_class| if inspector_class.target?(@object) return inspector_class.new(@object, @inspected_objects) end end @object end end class NumericInspector Inspector.register_inspector_class(self) class << self def target?(object) object.is_a?(Numeric) end end def initialize(numeric, inspected_objects) @inspected_objects = inspected_objects @numeric = numeric end def inspect @numeric.to_s end def pretty_print(q) q.text(@numeric.to_s) end def pretty_print_cycle(q) q.text(@numeric.to_s) end end class HashInspector Inspector.register_inspector_class(self) class << self def target?(object) object.is_a?(Hash) or ENV.equal?(object) end end def initialize(hash, inspected_objects) @inspected_objects = inspected_objects @hash = {} hash.each do |key, value| key = Inspector.cached_new(key, @inspected_objects) value = Inspector.cached_new(value, @inspected_objects) @hash[key] = value end end def inspect @hash.inspect end def pretty_print(q) q.group(1, '{', '}') do q.seplist(self, nil, :each_pair) do |k, v| q.group do q.pp(k) q.text('=>') q.group(1) do q.breakable('') q.pp(v) end end end end end def pretty_print_cycle(q) @hash.pretty_print_cycle(q) end def each_pair keys = @hash.keys begin keys = keys.sort # FIXME: more cleverly rescue ArgumentError end keys.each do |key| yield(key, @hash[key]) end end end class ArrayInspector Inspector.register_inspector_class(self) class << self def target?(object) object.is_a?(Array) end end def initialize(array, inspected_objects) @inspected_objects = inspected_objects @array = array.collect do |element| Inspector.cached_new(element, @inspected_objects) end end def inspect @array.inspect end def pretty_print(q) q.group(1, '[', ']') do q.seplist(self) do |v| q.pp(v) end end end def pretty_print_cycle(q) @array.pretty_print_cycle(q) end def each(&block) @array.each(&block) end end class Literal def initialize(value) @value = value end def inspect @value.to_s end end class DelayedLiteral def initialize(value) @value = value end def inspect @value.call.to_s end end class MaybeContainer def initialize(value, &formatter) @value = value @formatter = formatter end def inspect if @value.is_a?(Array) values = @value.collect do |value| @formatter.call(AssertionMessage.convert(value)) end "[#{values.join(', ')}]" else @formatter.call(AssertionMessage.convert(@value)) end end end class Template def self.create(string) parts = (string ? string.scan(/(?=[^\\])\?|(?:\\\?|[^\?])+/m) : []) self.new(parts) end attr_reader :count def initialize(parts) @parts = parts @count = parts.find_all{|e| e == '?'}.size end def result(parameters) raise "The number of parameters does not match the number of substitutions." if(parameters.size != count) params = parameters.dup expanded_template = "" @parts.each do |part| if part == '?' param = params.shift if Object.const_defined?(:Encoding) expanded_template += concatenatable(param, expanded_template.encoding) else expanded_template += param end else expanded_template += part.gsub(/\\\?/m, '?') end end expanded_template end private def concatenatable(text, encoding) if Encoding.compatible?(text, encoding) text else text.dup.force_encoding(encoding) end end end include Util::BacktraceFilter def initialize(head, template_string, parameters) @head = head @template_string = template_string @parameters = parameters end def convert(object) self.class.convert(object) end def template @template ||= Template.create(@template_string) end def add_period(string) (string =~ /\.\Z/ ? string : string + '.') end def to_s message_parts = [] if (@head) head = @head head = head.call if head.respond_to?(:call) head = head.to_s unless(head.empty?) message_parts << add_period(head) end end tail = template.result(@parameters.collect{|e| convert(e)}) message_parts << tail unless(tail.empty?) message_parts.join("\n") end end class AssertExceptionHelper class WrappedException attr_reader :exception def initialize(exception) @exception = exception end def inspect if default_inspect? "#{@exception.class.inspect}(<#{@exception.message}>)" else @exception.inspect end end def method_missing(name, *args, &block) @exception.__send__(name, *args, &block) end private def default_inspect? inspect_method = @exception.method(:inspect) if inspect_method.respond_to?(:owner) and inspect_method.owner == Exception true else default_inspect_method = Exception.instance_method(:inspect) default_inspect_method.bind(@exception).call == @exception.inspect end end end def initialize(test_case, expected_exceptions) @test_case = test_case @expected_exceptions = expected_exceptions @expected_classes, @expected_modules, @expected_objects = split_expected_exceptions(expected_exceptions) end def expected_exceptions exceptions = @expected_exceptions.collect do |exception| if exception.is_a?(Exception) WrappedException.new(exception) else exception end end if exceptions.size == 1 exceptions[0] else exceptions end end def expected?(actual_exception, equality=nil) equality ||= :instance_of? expected_class?(actual_exception, equality) or expected_module?(actual_exception) or expected_object?(actual_exception) end private def split_expected_exceptions(expected_exceptions) exception_modules = [] exception_objects = [] exception_classes = [] expected_exceptions.each do |exception_type| if exception_type.instance_of?(Module) exception_modules << exception_type elsif exception_object?(exception_type) exception_objects << exception_type elsif exception_class?(exception_type) exception_classes << exception_type else full_message = @test_case.__send__(:build_message, nil, " must be " + "a subclass of Exception, " + "an object of Exception subclasses " + "or a Module", exception_type) @test_case.flunk(full_message) end end [exception_classes, exception_modules, exception_objects] end def exception_object?(exception_type) return true if exception_type.is_a?(Exception) if Object.const_defined?(:Java) return true if exception_type.is_a?(Java::JavaLang::Throwable) end false end def exception_class?(exception_type) return true if exception_type <= Exception if Object.const_defined?(:Java) return true if exception_type <= Java::JavaLang::Throwable end false end def expected_class?(actual_exception, equality) @expected_classes.any? do |expected_class| actual_exception.__send__(equality, expected_class) end end def expected_module?(actual_exception) @expected_modules.any? do |expected_module| actual_exception.is_a?(expected_module) end end def expected_object?(actual_exception) @expected_objects.any? do |expected_object| expected_object == actual_exception or fallback_exception_object_equal(expected_object, actual_exception) end end def fallback_exception_object_equal(expected_object, actual_exception) owner = Util::MethodOwnerFinder.find(expected_object, :==) if owner == Kernel or owner == Exception expected_object.class == actual_exception.class and expected_object.message == actual_exception.message else false end end end # :startdoc: end end end PK% ] 0gems/test-unit-3.2.9/lib/test/unit/testresult.rbnu[#-- # Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit/util/observable' require 'test/unit/failure' require 'test/unit/error' require 'test/unit/omission' require 'test/unit/pending' require 'test/unit/notification' module Test module Unit module NullResultContainerInitializer private def initialize_containers end end # Collects Test::Unit::Failure and Test::Unit::Error so that # they can be displayed to the user. To this end, observers # can be added to it, allowing the dynamic updating of, say, a # UI. class TestResult include Util::Observable include NullResultContainerInitializer include TestResultFailureSupport include TestResultErrorSupport include TestResultPendingSupport include TestResultOmissionSupport include TestResultNotificationSupport FINISHED = name + "::FINISHED" CHANGED = name + "::CHANGED" PASS_ASSERTION = name + "::PASS_ASSERTION" FAULT = name + "::FAULT" attr_reader :run_count, :pass_count, :assertion_count, :faults attr_accessor :stop_tag # Constructs a new, empty TestResult. def initialize @run_count, @pass_count, @assertion_count = 0, 0, 0 @summary_generators = [] @problem_checkers = [] @faults = [] @stop_tag = nil initialize_containers end # Records a test run. def add_run @run_count += 1 notify_listeners(FINISHED, self) notify_changed end def add_pass @pass_count += 1 end # Records an individual assertion. def add_assertion @assertion_count += 1 notify_listeners(PASS_ASSERTION, self) notify_changed end # Returns a string contain the recorded runs, assertions, # failures and errors in this TestResult. def summary ["#{run_count} tests", "#{assertion_count} assertions", *@summary_generators.collect {|generator| __send__(generator)}].join(", ") end # Returnes a string that shows result status. def status if passed? if pending_count > 0 "pending" elsif omission_count > 0 "omission" elsif notification_count > 0 "notification" else "pass" end elsif error_count > 0 "error" elsif failure_count > 0 "failure" end end def stop throw @stop_tag end def to_s summary end # Returns whether or not this TestResult represents # successful completion. def passed? @problem_checkers.all? {|checker| not __send__(checker)} end def pass_percentage n_tests = @run_count - omission_count if n_tests.zero? 0 else 100.0 * (@pass_count / n_tests.to_f) end end private def notify_changed notify_listeners(CHANGED, self) end def notify_fault(fault) @faults << fault notify_listeners(FAULT, fault) end end end end PK% ]"ss-gems/test-unit-3.2.9/lib/test/unit/pending.rbnu[require 'test/unit/util/backtracefilter' module Test module Unit class Pending include Util::BacktraceFilter attr_reader :test_name, :location, :message attr_reader :method_name SINGLE_CHARACTER = 'P' LABEL = "Pending" # Creates a new Pending with the given location and # message. def initialize(test_name, location, message, options={}) @test_name = test_name @location = location @message = message @method_name = options[:method_name] end # Returns a single character representation of a pending. def single_character_display SINGLE_CHARACTER end def label LABEL end # Returns a brief version of the error description. def short_display "#{@test_name}: #{@message.split("\n")[0]}" end # Returns a verbose version of the error description. def long_display backtrace = filter_backtrace(location).join("\n") "#{label}: #{@message}\n#{@test_name}\n#{backtrace}" end # Overridden to return long_display. def to_s long_display end def critical? true end end class PendedError < StandardError end module TestCasePendingSupport class << self def included(base) base.class_eval do include PendingHandler end end end # Marks the test or part of the test is pending. # # Example: # def test_pending # pend # # Not reached here # end # # def test_pending_with_here # pend do # # Ran here # # Fails if the block doesn't raise any error. # # Because it means the block is passed unexpectedly. # end # # Reached here # end def pend(message=nil, &block) message ||= "pended." if block_given? pending = nil begin yield rescue Exception pending = Pending.new(name, filter_backtrace(caller), message, :method_name => @method_name) add_pending(pending) end unless pending flunk("Pending block should not be passed: #{message}") end else raise PendedError.new(message) end end private def add_pending(pending) problem_occurred current_result.add_pending(pending) end end module PendingHandler class << self def included(base) base.exception_handler(:handle_pended_error) end end private def handle_pended_error(exception) return false unless exception.is_a?(PendedError) pending = Pending.new(name, filter_backtrace(exception.backtrace), exception.message, :method_name => @method_name) add_pending(pending) true end end module TestResultPendingSupport attr_reader :pendings # Records a Test::Unit::Pending. def add_pending(pending) @pendings << pending notify_fault(pending) notify_changed end # Returns the number of pendings this TestResult has # recorded. def pending_count @pendings.size end private def initialize_containers super @pendings = [] @summary_generators << :pending_summary end def pending_summary "#{pending_count} pendings" end end end end PK% ]AV.gems/test-unit-3.2.9/lib/test/unit/omission.rbnu[require 'test/unit/util/backtracefilter' module Test module Unit class Omission include Util::BacktraceFilter attr_reader :test_name, :location, :message attr_reader :method_name SINGLE_CHARACTER = 'O' LABEL = "Omission" # Creates a new Omission with the given location and # message. def initialize(test_name, location, message, options={}) @test_name = test_name @location = location @message = message @method_name = options[:method_name] end # Returns a single character representation of a omission. def single_character_display SINGLE_CHARACTER end def label LABEL end # Returns a brief version of the error description. def short_display "#{@test_name}: #{@message.split("\n")[0]}" end # Returns a verbose version of the error description. def long_display backtrace = filter_backtrace(location).join("\n") "#{label}: #{@message}\n#{@test_name}\n#{backtrace}" end # Overridden to return long_display. def to_s long_display end def critical? true end end class OmittedError < StandardError end module TestCaseOmissionSupport class << self def included(base) base.class_eval do include OmissionHandler end end end # Omit the test or part of the test. # # Example: # def test_omission # omit # # Not reached here # end # # def test_omission_with_here # omit do # # Not ran here # end # # Reached here # end def omit(message=nil, &block) message ||= "omitted." if block_given? omission = Omission.new(name, filter_backtrace(caller), message, :method_name => @method_name) add_omission(omission) else raise OmittedError.new(message) end end # Omit the test or part of the test if _condition_ is # true. # # Example: # def test_omission # omit_if("".empty?) # # Not reached here # end # # def test_omission_with_here # omit_if(true) do # # Not ran here # end # omit_if(false) do # # Reached here # end # # Reached here too # end def omit_if(condition, *args, &block) if condition omit(*args, &block) else block.call if block end end # Omit the test or part of the test if _condition_ is # not true. # # Example: # def test_omission # omit_unless("string".empty?) # # Not reached here # end # # def test_omission_with_here # omit_unless(true) do # # Reached here # end # omit_unless(false) do # # Not ran here # end # # Reached here too # end def omit_unless(condition, *args, &block) if condition block.call if block else omit(*args, &block) end end private def add_omission(omission) current_result.add_omission(omission) end end module OmissionHandler class << self def included(base) base.exception_handler(:handle_omitted_error) end end private def handle_omitted_error(exception) return false unless exception.is_a?(OmittedError) omission = Omission.new(name, filter_backtrace(exception.backtrace), exception.message, :method_name => @method_name) add_omission(omission) true end end module TestResultOmissionSupport attr_reader :omissions # Records a Test::Unit::Omission. def add_omission(omission) @omissions << omission notify_fault(omission) notify_changed end # Returns the number of omissions this TestResult has # recorded. def omission_count @omissions.size end private def initialize_containers super @omissions = [] @summary_generators << :omission_summary end def omission_summary "#{omission_count} omissions" end end end end PK% ]soo+gems/test-unit-3.2.9/lib/test/unit/error.rbnu[#-- # # Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit/util/backtracefilter' module Test module Unit # Encapsulates an error in a test. Created by # Test::Unit::TestCase when it rescues an exception thrown # during the processing of a test. class Error include Util::BacktraceFilter attr_reader :test_name, :exception attr_reader :method_name SINGLE_CHARACTER = 'E' LABEL = "Error" # Creates a new Error with the given test_name and # exception. def initialize(test_name, exception, options={}) @test_name = test_name @exception = exception @method_name = options[:method_name] end # Returns a single character representation of an error. def single_character_display SINGLE_CHARACTER end def label LABEL end # Returns the message associated with the error. def message "#{@exception.class.name}: #{@exception.message}" end # Returns a brief version of the error description. def short_display "#@test_name: #{message.split("\n")[0]}" end # Returns a verbose version of the error description. def long_display backtrace_display = location.join("\n ") "#{label}:\n#@test_name:\n#{message}\n #{backtrace_display}" end def location @location ||= filter_backtrace(@exception.backtrace) end alias_method :backtrace, :location # Deprecated # Overridden to return long_display. def to_s long_display end def critical? true end end module ErrorHandler class << self def included(base) base.exception_handler(:handle_all_exception) end end NOT_PASS_THROUGH_EXCEPTIONS = [] NOT_PASS_THROUGH_EXCEPTION_NAMES = ["Timeout::Error"] PASS_THROUGH_EXCEPTIONS = [ NoMemoryError, SignalException, Interrupt, SystemExit, ] PASS_THROUGH_EXCEPTION_NAMES = [] private def handle_all_exception(exception) return false if pass_through_exception?(exception) problem_occurred add_error(exception) true end def pass_through_exception?(exception) case exception when *NOT_PASS_THROUGH_EXCEPTIONS return false end case exception.class.name when *NOT_PASS_THROUGH_EXCEPTION_NAMES return false end case exception when *PASS_THROUGH_EXCEPTIONS return true end case exception.class.name when *PASS_THROUGH_EXCEPTION_NAMES return true end false end def add_error(exception) error = Error.new(name, exception, :method_name => @method_name) current_result.add_error(error) end end module TestResultErrorSupport attr_reader :errors # Records a Test::Unit::Error. def add_error(error) @errors << error notify_fault(error) notify_changed end # Returns the number of errors this TestResult has # recorded. def error_count @errors.size end def error_occurred? not @errors.empty? end private def initialize_containers super @errors = [] @summary_generators << :error_summary @problem_checkers << :error_occurred? end def error_summary "#{error_count} errors" end end end end PK% ] /44/gems/test-unit-3.2.9/lib/test/unit/testsuite.rbnu[#-- # # Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. # Copyright:: Copyright (c) 2008-2011 Kouhei Sutou. All rights reserved. # License:: Ruby license. require 'test/unit/error' module Test module Unit # A collection of tests which can be #run. # # Note: It is easy to confuse a TestSuite instance with # something that has a static suite method; I know because _I_ # have trouble keeping them straight. Think of something that # has a suite method as simply providing a way to get a # meaningful TestSuite instance. class TestSuite attr_reader :name, :tests, :test_case, :start_time, :elapsed_time # Test suite that has higher priority is ran prior to # test suites that have lower priority. attr_accessor :priority STARTED = name + "::STARTED" STARTED_OBJECT = name + "::STARTED::OBJECT" FINISHED = name + "::FINISHED" FINISHED_OBJECT = name + "::FINISHED::OBJECT" # Creates a new TestSuite with the given name. def initialize(name="Unnamed TestSuite", test_case=nil) @name = name @tests = [] @test_case = test_case @n_tests = 0 @priority = 0 @start_time = nil @elapsed_time = nil @passed = true end # Runs the tests and/or suites contained in this # TestSuite. def run(result, &progress_block) @start_time = Time.now yield(STARTED, name) yield(STARTED_OBJECT, self) run_startup(result) while test = @tests.shift @n_tests += test.size run_test(test, result, &progress_block) @passed = false unless test.passed? end ensure begin run_shutdown(result) ensure @elapsed_time = Time.now - @start_time yield(FINISHED, name) yield(FINISHED_OBJECT, self) end end # Adds the test to the suite. def <<(test) @tests << test self end def delete(test) @tests.delete(test) end def delete_tests(tests) @tests -= tests end # Retuns the rolled up number of tests in this suite; # i.e. if the suite contains other suites, it counts the # tests within those suites, not the suites themselves. def size total_size = @n_tests @tests.each { |test| total_size += test.size } total_size end def empty? size.zero? end # Overridden to return the name given the suite at # creation. def to_s @name end # It's handy to be able to compare TestSuite instances. def ==(other) return false unless(other.kind_of?(self.class)) return false unless(@name == other.name) @tests == other.tests end def passed? @passed end private def run_startup(result) return if @test_case.nil? or !@test_case.respond_to?(:startup) begin @test_case.startup rescue Exception raise unless handle_exception($!, result) end end def run_test(test, result) finished_is_yielded = false finished_object_is_yielded = false previous_event_name = nil test.run(result) do |event_name, *args| case previous_event_name when Test::Unit::TestCase::STARTED if event_name != Test::Unit::TestCase::STARTED_OBJECT yield(Test::Unit::TestCase::STARTED_OBJECT, test) end when Test::Unit::TestCase::FINISHED if event_name != Test::Unit::TestCase::FINISHED_OBJECT yield(Test::Unit::TestCase::FINISHED_OBJECT, test) end finished_object_is_yielded = true end case event_name when Test::Unit::TestCase::STARTED finished_is_yielded = false finished_object_is_yielded = false when Test::Unit::TestCase::FINISHED finished_is_yielded = true end previous_event_name = event_name yield(event_name, *args) end if finished_is_yielded and not finished_object_is_yielded yield(Test::Unit::TestCase::FINISHED_OBJECT, test) end end def run_shutdown(result) return if @test_case.nil? or !@test_case.respond_to?(:shutdown) begin @test_case.shutdown rescue Exception raise unless handle_exception($!, result) end end def handle_exception(exception, result) case exception when *ErrorHandler::PASS_THROUGH_EXCEPTIONS false else result.add_error(Error.new(@test_case.name, exception)) @passed = false true end end end end end PK% ]E/gems/test-unit-3.2.9/lib/test/unit/attribute.rbnu[module Test module Unit module Attribute class StringifyKeyHash < Hash class << self def stringify(object) object.to_s end end def key?(key) super(self.class.stringify(key)) end def [](key) super(self.class.stringify(key)) end def []=(key, value) super(self.class.stringify(key), value) end end class << self def included(base) base.extend(BaseClassMethods) base.extend(ClassMethods) end end module BaseClassMethods def attributes_table {} end end module ClassMethods def method_added(name) super return unless defined?(@current_attributes) attributes = {} kept_attributes = StringifyKeyHash.new @current_attributes.each do |attribute_name, attribute| attributes[attribute_name] = attribute[:value] if attribute[:keep] keep_hook = attribute[:keep_hook] attribute = keep_hook.call(attribute) if keep_hook kept_attributes[attribute_name] = attribute end end set_attributes(name, attributes) @current_attributes = kept_attributes end # Set an attribute to test methods. # # @overload attribute(name, value) # @example # attribute :speed, :slow # def test_my_slow_method # self[:speed] # => :slow # end # # @param [Object] name the attribute name # @param [Object] value the attribute value # @return [void] # # @overload attribute(name, value, *method_names) # @example # def test_my_slow_method1 # self[:speed] # => :slow # end # # attribute :speed, :slow, :test_my_slow_method1, :test_my_slow_method2 # # def test_my_slow_method2 # self[:speed] # => :slow # end # # @param [Object] name the attribute name # @param [Object] value the attribute value # @param [Array] method_names the test method names set the attribute # @return [void] # # @overload attribute(name, value, options) # @example # attribute :speed, :slow, keep: true # def test_my_slow_method1 # self[:speed] # => :slow # end # # def test_my_slow_method2 # self[:speed] # => :slow # end # # @param [Object] name the attribute name # @param [Object] value the attribute value # @option options [Boolean] :keep whether or not to set attribute to following test methods # @return [void] # # @overload attribute(name, value, options, *method_names) # @example # def test_my_slow_method1 # self[:speed] # => :slow # end # # # There are no valid options for now. # attribute :speed, :slow, {}, :test_my_slow_method1 # # def test_my_slow_method2 # self[:speed] # => nil # end # # @param [Object] name the attribute name # @param [Object] value the attribute value # @param [Hash] options ignored # @param [Array] method_names the test method names set the attribute # @return [void] def attribute(name, value, options={}, *method_names) unless options.is_a?(Hash) method_names << options options = {} end if method_names.empty? current_attributes[name] = options.merge(:value => value) else method_names.each do |method_name| set_attributes(method_name, {name => value}) end end end def current_attributes @current_attributes ||= StringifyKeyHash.new end def current_attribute(name) current_attributes[name] || StringifyKeyHash.new end def attributes_table @attributes_table ||= StringifyKeyHash.new super.merge(@attributes_table) end def set_attributes(method_name, new_attributes) return if new_attributes.empty? @attributes_table ||= StringifyKeyHash.new @attributes_table[method_name] ||= StringifyKeyHash.new current_attributes = @attributes_table[method_name] new_attributes.each do |key, value| observers = attribute_observers(key) || [] observers.each do |observer| observer.call(self, StringifyKeyHash.stringify(key), (attributes(method_name) || {})[key], value, method_name) end current_attributes[key] = value end end def attributes(method_name) attributes = attributes_table[method_name] ancestors.each do |ancestor| next if ancestor == self if ancestor.is_a?(Class) and ancestor < Test::Unit::Attribute parent_attributes = ancestor.attributes(method_name) if attributes attributes = (parent_attributes || {}).merge(attributes) else attributes = parent_attributes end break end end attributes || StringifyKeyHash.new end def find_attribute(method_name, name, options={}) recursive_p = options[:recursive] recursive_p = true if recursive_p.nil? @attributes_table ||= StringifyKeyHash.new if @attributes_table.key?(method_name) attributes = @attributes_table[method_name] if attributes.key?(name) return attributes[name] end end return nil unless recursive_p return nil if self == TestCase @cached_parent_test_case ||= ancestors.find do |ancestor| ancestor != self and ancestor.is_a?(Class) and ancestor < Test::Unit::Attribute end @cached_parent_test_case.find_attribute(method_name, name, options) end @@attribute_observers = StringifyKeyHash.new def register_attribute_observer(attribute_name, observer=Proc.new) @@attribute_observers[attribute_name] ||= [] @@attribute_observers[attribute_name] << observer end def attribute_observers(attribute_name) @@attribute_observers[attribute_name] end end def attributes self.class.attributes(@method_name) || StringifyKeyHash.new end def [](name) self.class.find_attribute(@method_name, name) end end end end PK% ].gems/test-unit-3.2.9/lib/test/unit/priority.rbnu[require "fileutils" module Test module Unit module Priority class << self def included(base) base.extend(ClassMethods) base.class_eval do setup :priority_setup, :before => :prepend teardown :priority_teardown, :after => :append end end @@enabled = false def enabled? @@enabled end def enable require "fileutils" require "tmpdir" @@enabled = true end def disable @@enabled = false end @@default = :normal def default @@default || :normal end def default=(default) @@default = default end def available_values Checker.available_priorities end end class Checker class << self def have_priority?(name) singleton_class = (class << self; self; end) singleton_class.method_defined?(priority_check_method_name(name)) end def need_to_run?(test) priority = test[:priority] || Priority.default if have_priority?(priority) __send__(priority_check_method_name(priority), test) else true end end def available_priorities methods(false).collect do |name| /\Arun_priority_(.+)\?\z/ =~ name.to_s $1 end.compact end def run_priority_must?(test) true end def run_priority_important?(test) rand > 0.1 end def run_priority_high?(test) rand > 0.3 end def run_priority_normal?(test) rand > 0.5 end def run_priority_low?(test) rand > 0.75 end def run_priority_never?(test) false end private def priority_check_method_name(priority_name) "run_priority_#{priority_name}?" end end attr_reader :test def initialize(test) @test = test end def setup FileUtils.rm_f(passed_file) end def teardown if @test.__send__(:passed?) FileUtils.touch(passed_file) else FileUtils.rm_f(passed_file) end end def need_to_run? !previous_test_success? or self.class.need_to_run?(@test) end private def previous_test_success? File.exist?(passed_file) end def result_dir components = [ ".test-result", escape_class_name(@test.class.name || "AnonymousTestCase"), escaped_method_name, ] parent_directories = [File.dirname($0), Dir.pwd] if Process.respond_to?(:uid) parent_directories << File.join(Dir.tmpdir, Process.uid.to_s) end parent_directories.each do |parent_directory| dir = File.expand_path(File.join(parent_directory, *components)) begin FileUtils.mkdir_p(dir) return dir rescue Errno::EACCES end end raise Errno::EACCES, parent_directories.join(", ") end def passed_file File.join(result_dir, "passed") end def escape_class_name(class_name) class_name.gsub(/(?:[: \\\/])/, "_") end def escaped_method_name @test.method_name.to_s.gsub(/(?:[: ]|[!?=]$)/) do |matched| case matched when ":" "_colon_" when " " "_" when "!" ".destructive" when "?" ".predicate" when "=" ".equal" end end end end module ClassMethods def priority(name, *tests) unless Checker.have_priority?(name) raise ArgumentError, "unknown priority: #{name}" end attribute(:priority, name, {:keep => true}, *tests) end end def priority_setup return unless Priority.enabled? Checker.new(self).setup end def priority_teardown return unless Priority.enabled? Checker.new(self).teardown end end end end PK% ] \'____.gems/test-unit-3.2.9/lib/test/unit/testcase.rbnu[#-- # # Author:: Nathaniel Talbott. # Copyright:: # * Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. # * Copyright (c) 2008-2012 Kouhei Sutou # License:: Ruby license. require 'test/unit/attribute' require 'test/unit/fixture' require 'test/unit/exception-handler' require 'test/unit/assertions' require 'test/unit/failure' require 'test/unit/error' require 'test/unit/pending' require 'test/unit/omission' require 'test/unit/notification' require 'test/unit/priority' require 'test/unit/data' require 'test/unit/testsuite' require 'test/unit/test-suite-creator' require 'test/unit/assertion-failed-error' require 'test/unit/auto-runner-loader' require 'test/unit/util/backtracefilter' require 'test/unit/util/output' require 'test/unit/util/method-owner-finder' module Test module Unit # Ties everything together. If you subclass and add your own # test methods, it takes care of making them into tests and # wrapping those tests into a suite. It also does the # nitty-gritty of actually running an individual test and # collecting its results into a Test::Unit::TestResult object. # # You can run two hooks before/after a TestCase run. # # Example: # # class TestMyClass < Test::Unit::TestCase # class << self # def startup # ... # end # # def shutdown # ... # end # end # # def setup # ... # end # # def cleanup # ... # end # # def teardown # ... # end # # def test_my_method1 # ... # end # # def test_my_method2 # ... # end # end # # Here is a call order: # # 1. startup # 1. setup # 1. test_my_method1 # 1. cleanup # 1. teardown # 1. setup # 1. test_my_method2 # 1. cleanup # 1. teardown # 1. shutdown # # You can set an attribute to each test. # # Example: # # class TestMyClass < Test::Unit::TestCase # attribute :speed, :fast # def test_my_fast_method # # You can get the attribute via `self[]` # self[:speed] # => :fast # ... # end # # attribute :speed, :slow # def test_my_slow_method # self[:speed] # => :slow # ... # end # end class TestCase include Attribute include Fixture include ExceptionHandler include ErrorHandler include FailureHandler include TestCasePendingSupport include TestCaseOmissionSupport include TestCaseNotificationSupport include Priority include Data include Assertions include Util::BacktraceFilter include Util::Output STARTED = name + "::STARTED" # :nodoc: FINISHED = name + "::FINISHED" # :nodoc: STARTED_OBJECT = name + "::STARTED::OBJECT" # :nodoc: FINISHED_OBJECT = name + "::FINISHED::OBJECT" # :nodoc: DESCENDANTS = [] # :nodoc: AVAILABLE_ORDERS = [:alphabetic, :random, :defined] # :nodoc: class << self def inherited(sub_class) # :nodoc: DESCENDANTS << sub_class super end @@added_method_names = {} def method_added(name) # :nodoc: super added_method_names = (@@added_method_names[self] ||= {}) stringified_name = name.to_s if added_method_names.key?(stringified_name) attribute(:redefined, {:backtrace => caller}, {}, stringified_name) end source_location = find_attribute(stringified_name, :source_location) if source_location path, line = source_location elsif respond_to?(:caller_locations, true) location = caller_locations(1, 1)[0] path = location.absolute_path || location.path line = location.lineno else # TODO: Remove me when Ruby 1.9 support is dropped path, line, = caller[0].split(/:(\d+)/, 2) line = line.to_i if line end method_locations << { :method_name => stringified_name, :path => File.expand_path(path), :line => line, } added_method_names[stringified_name] = true AutoRunnerLoader.check(self, stringified_name) end def added_method_names # :nodoc: (@@added_method_names[self] ||= {}).keys end # Rolls up all of the test* methods in the fixture into # one suite, creating a new instance of the fixture for # each method. def suite suite_creator = TestSuiteCreator.new(self) suite_creator.create end # Called before every test case runs. Can be used # to set up fixture information used in test case # scope. # # Here is an example test case: # class TestMyClass < Test::Unit::TestCase # class << self # def startup # ... # end # end # # def setup # ... # end # # def test_my_class1 # ... # end # # def test_my_class2 # ... # end # end # # Here is a call order: # * startup # * setup # * test_my_class1 (or test_my_class2) # * setup # * test_my_class2 (or test_my_class1) # # Note that you should not assume test order. Tests # should be worked in any order. def startup end # Called after every test case runs. Can be used to tear # down fixture information used in test case scope. # # Here is an example test case: # class TestMyClass < Test::Unit::TestCase # class << self # def shutdown # ... # end # end # # def teardown # ... # end # # def test_my_class1 # ... # end # # def test_my_class2 # ... # end # end # # Here is a call order: # * test_my_class1 (or test_my_class2) # * teardown # * test_my_class2 (or test_my_class1) # * teardown # * shutdown # # Note that you should not assume test order. Tests # should be worked in any order. def shutdown end @@test_orders = {} # Returns the current test order. This returns # +:alphabetic+ by default. def test_order ancestors.each do |ancestor| order = @@test_orders[ancestor] return order if order end AVAILABLE_ORDERS.first end # Sets the current test order. # # Here are the available _order_: # [:alphabetic] # Default. Tests are sorted in alphabetic order. # [:random] # Tests are sorted in random order. # [:defined] # Tests are sorted in defined order. def test_order=(order) @@test_orders[self] = order end # Defines a test in declarative syntax or marks # following method as a test method. # # In declarative syntax usage, the following two # test definitions are the almost same: # # description "register user" # def test_register_user # ... # end # # test "register user" do # ... # end # # In test method mark usage, the "my_test_method" is # treated as a test method: # # test # def my_test_method # assert_equal("call me", ...) # end def test(*test_description_or_targets, &block) if block_given? test_description = test_description_or_targets.first if test_description.nil? raise ArgumentError, "test description is missing" end n_arguments = test_description_or_targets.size if n_arguments > 1 message = "wrong number of arguments (#{n_arguments} for 1)" raise ArgumentError, message end method_name = "test: #{test_description}" description(test_description, method_name) attribute(:test, true, {}, method_name) if block.respond_to?(:source_location) attribute(:source_location, block.source_location, {}, method_name) end define_method(method_name, &block) else targets = test_description_or_targets attribute(:test, true, {}, *targets) targets.each do |target| AutoRunnerLoader.check(self, target) end end end # Describes a test. # # The following example associates "register a # normal user" description with "test_register" # test. # # description "register a normal user" # def test_register # ... # end def description(value, target=nil) targets = [target].compact attribute(:description, value, {}, *targets) end # Defines a sub test case. # # This is a syntax sugar. The both of the following codes are # the same in meaning: # # Standard: # class TestParent < Test::Unit::TestCase # class TestChild < self # def test_in_child # end # end # end # # Syntax sugar: # class TestParent < Test::Unit::TestCase # sub_test_case("TestChild") do # def test_in_child # end # end # end # # The difference of them are the following: # # * Test case created by {sub_test_case} is an anonymous class. # So you can't refer the test case by name. # * The class name of class style must follow # constant naming rule in Ruby. But the name of test case # created by {sub_test_case} doesn't need to follow the rule. # For example, you can use a space in name such as "child test". # # @param name [String] The name of newly created sub test case. # @yield # The block is evaluated under the newly created sub test # case class context. # @return [Test::Unit::TestCase] Created sub test case class. def sub_test_case(name, &block) parent_test_case = self sub_test_case = Class.new(self) do singleton_class = class << self; self; end singleton_class.__send__(:define_method, :name) do [parent_test_case.name, name].compact.join("::") end end sub_test_case.class_eval(&block) sub_test_case end # Checks whether a test that is matched the query is # defined. # # @option query [String] :path (nil) # the path where a test is defined in. # @option query [Numeric] :line (nil) # the line number where a test is defined at. # @option query [String] :method_name (nil) # the method name for a test. def test_defined?(query) locations = find_locations(query) not locations.empty? end def find_locations(query) query_path = query[:path] query_line = query[:line] query_method_name = query[:method_name] available_locations = target_method_locations(query_path) if query_line available_locations = available_locations.sort_by do |location| -location[:line] end available_location = available_locations.find do |location| query_line >= location[:line] end return [] if available_location.nil? return [] if available_location[:test_case] != self available_locations = [available_location] end if query_method_name available_location = available_locations.find do |location| location[:test_case] == self and query_method_name == location[:method_name] end return [] if available_location.nil? available_locations = [available_location] end available_locations end private # @private @@method_locations = {} # @private def method_locations @@method_locations[self] ||= [] end # @private def target_method_locations(path) if path.nil? self_location = method_locations.first path = self_location[:path] if self_location end return [] if path.nil? target_locations = [] @@method_locations.each do |test_case, locations| locations.each do |location| absolete_path = File.expand_path(path) location_path = location[:path] location_basename = File.basename(location_path) if location_path == absolete_path or location_basename == path target_locations << location.merge(:test_case => test_case) end end end target_locations end end attr_reader :method_name # Creates a new instance of the fixture for running the # test represented by test_method_name. def initialize(test_method_name) @method_name = test_method_name @internal_data = InternalData.new end # Assigns test data to the test. It is used in internal. def assign_test_data(label, data) # :nodoc: @internal_data.assign_test_data(label, data) end # Returns the test is valid test. It is used in internal. def valid? # :nodoc: return false unless respond_to?(@method_name) test_method = method(@method_name) unless @internal_data.have_test_data? return false unless test_method.arity <= 0 end owner = Util::MethodOwnerFinder.find(self, @method_name) if owner.class != Module and self.class != owner return false end true end # Runs the individual test method represented by this # instance of the fixture, collecting statistics, failures # and errors in result. def run(result) begin @_result = result @internal_data.test_started yield(STARTED, name) yield(STARTED_OBJECT, self) processed_exception_in_setup = false begin catch do |tag| run_setup do begin run_test run_cleanup add_pass rescue Exception @internal_data.interrupted unless handle_exception($!) processed_exception_in_setup = true raise end throw(tag) end end end rescue Exception if processed_exception_in_setup raise else @internal_data.interrupted raise unless handle_exception($!) end ensure begin run_teardown rescue Exception raise unless handle_exception($!) end end @internal_data.test_finished result.add_run yield(FINISHED, name) yield(FINISHED_OBJECT, self) ensure # @_result = nil # For test-spec's after_all :< end end # Called before every test method runs. Can be used # to set up fixture information. # # You can add additional setup tasks by the following # code: # class TestMyClass < Test::Unit::TestCase # def setup # ... # end # # setup # def my_setup1 # ... # end # # setup do # ... # setup callback1 # end # # setup # def my_setup2 # ... # end # # setup do # ... # setup callback2 # end # # def test_my_class # ... # end # end # # Here is a call order: # * setup # * my_setup1 # * setup callback1 # * my_setup2 # * setup callback2 # * test_my_class def setup end # Called after every test method runs but the test # method isn't marked as 'passed'. Can be used to # clean up and/or verify tested condition. # e.g. Can be used to verify mock. # # You can add additional cleanup tasks by the following # code: # class TestMyClass < Test::Unit::TestCase # def cleanup # ... # end # # cleanup # def my_cleanup1 # ... # end # # cleanup do # ... # cleanup callback1 # end # # cleanup # def my_cleanup2 # ... # end # # cleanup do # ... # cleanup callback2 # end # # def test_my_class # ... # end # end # # Here is a call order: # * test_my_class # * cleanup callback2 # * my_cleanup2 # * cleanup callback1 # * my_cleanup1 # * cleanup def cleanup end # Called after every test method runs. Can be used to tear # down fixture information. # # You can add additional teardown tasks by the following # code: # class TestMyClass < Test::Unit::TestCase # def teardown # ... # end # # teardown # def my_teardown1 # ... # end # # teardown do # ... # teardown callback1 # end # # teardown # def my_teardown2 # ... # end # # teardown do # ... # teardown callback2 # end # # def test_my_class # ... # end # end # # Here is a call order: # * test_my_class # * teardown callback2 # * my_teardown2 # * teardown callback1 # * my_teardown1 # * teardown def teardown end def default_test flunk("No tests were specified") end def size 1 end # Returns a label of test data for the test. If the # test isn't associated with any test data, it returns # +nil+. def data_label @internal_data.test_data_label end # Returns test data for the test. If the test isn't associated # with any test data, it returns +nil+. def data @internal_data.test_data end # Returns a human-readable name for the specific test that # this instance of TestCase represents. def name "#{local_name}(#{self.class.name})" end # Returns a human-readable name for the specific test that this # instance of TestCase represents. # # `#local_name` doesn't include class name. `#name` includes # class name. def local_name if @internal_data.have_test_data? "#{@method_name}[#{data_label}]" else @method_name.to_s end end # Returns a description for the test. A description # will be associated by Test::Unit::TestCase.test or # Test::Unit::TestCase.description. # # Returns a name for the test for no description test. def description self[:description] || name end # Overridden to return #name. def to_s name end # It's handy to be able to compare TestCase instances. def ==(other) return false unless other.kind_of?(self.class) return false unless @method_name == other.method_name return false unless data_label == other.data_label self.class == other.class end # Returns a Time at the test was started. def start_time @internal_data.start_time end # Returns elapsed time for the test was ran. def elapsed_time @internal_data.elapsed_time end # Returns whether the test is interrupted. def interrupted? @internal_data.interrupted? end # Returns whether this individual test passed or # not. Primarily for use in teardown so that artifacts # can be left behind if the test fails. def passed? @internal_data.passed? end # Notify that a problem is occurred in the test. It means that # the test is a failed test. If any failed tests exist in test # suites, the test process exits with failure exit status. # # This is a public API for developers who extend test-unit. # # @return [void] def problem_occurred @internal_data.problem_occurred end # Notify that the test is passed. Normally, it is not needed # because #run calls it automatically. If you want to override # #run, it is not a good idea. Please contact test-unit # developers. We will help you without your custom #run. For # example, we may add a new hook in #run. # # This is a public API for developers who extend test-unit. # # @return [void] def add_pass current_result.add_pass end private def current_result @_result end def run_test signature = "#{self.class}\##{@method_name}" redefined_info = self[:redefined] if redefined_info notify("<#{signature}> was redefined", :backtrace => redefined_info[:backtrace]) end if @internal_data.have_test_data? test_method = method(@method_name) arity = test_method.arity if arity.zero? __send__(@method_name) else __send__(@method_name, @internal_data.test_data) end else __send__(@method_name) end end def handle_exception(exception) self.class.exception_handlers.each do |handler| if handler.respond_to?(:call) handled = handler.call(self, exception) else handled = __send__(handler, exception) end return true if handled end false end def add_assertion current_result.add_assertion end class InternalData attr_reader :start_time, :elapsed_time attr_reader :test_data_label, :test_data def initialize @start_time = nil @elapsed_time = nil @passed = true @interrupted = false @test_data_label = nil @test_data = nil end def passed? @passed end def interrupted? @interrupted end def assign_test_data(label, data) @test_data_label = label @test_data = data end def have_test_data? not @test_data_label.nil? end def test_started @start_time = Time.now end def test_finished @elapsed_time = Time.now - @start_time end def problem_occurred @passed = false end def interrupted @interrupted = true end end end end end PK% ]<gems/test-unit-3.2.9/lib/test/unit/assertion-failed-error.rbnu[#-- # # Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. module Test module Unit # Thrown by Test::Unit::Assertions when an assertion fails. class AssertionFailedError < StandardError attr_accessor :expected, :actual, :user_message attr_accessor :inspected_expected, :inspected_actual def initialize(message=nil, options=nil) options ||= {} @expected = options[:expected] @actual = options[:actual] @inspected_expected = options[:inspected_expected] @inspected_actual = options[:inspected_actual] @user_message = options[:user_message] super(message) end end end end PK% ]=@Z Z 2gems/test-unit-3.2.9/lib/test/unit/notification.rbnu[require 'test/unit/util/backtracefilter' module Test module Unit class Notification include Util::BacktraceFilter attr_reader :test_name, :location, :message attr_reader :method_name SINGLE_CHARACTER = 'N' LABEL = "Notification" # Creates a new Notification with the given location and # message. def initialize(test_name, location, message, options={}) @test_name = test_name @location = location @message = message @method_name = options[:method_name] end # Returns a single character representation of a notification. def single_character_display SINGLE_CHARACTER end def label LABEL end # Returns a brief version of the error description. def short_display "#{@test_name}: #{@message.split("\n")[0]}" end # Returns a verbose version of the error description. def long_display backtrace = filter_backtrace(location).join("\n") "#{label}: #{@message}\n#{@test_name}\n#{backtrace}" end # Overridden to return long_display. def to_s long_display end def critical? false end end class NotifiedError < StandardError end module TestCaseNotificationSupport class << self def included(base) base.class_eval do include NotificationHandler end end end # Notify some information. # # Example: # def test_notification # notify("I'm here!") # # Reached here # notify("Special!") if special_case? # # Reached here too # end # # options: # :backtrace override backtrace. def notify(message, options={}, &block) backtrace = filter_backtrace(options[:backtrace] || caller) notification = Notification.new(name, backtrace, message, :method_name => @method_name) add_notification(notification) end private def add_notification(notification) current_result.add_notification(notification) end end module NotificationHandler class << self def included(base) base.exception_handler(:handle_notified_error) end end private def handle_notified_error(exception) return false unless exception.is_a?(NotifiedError) notification = Notification.new(name, filter_backtrace(exception.backtrace), exception.message) add_notification(notification) true end end module TestResultNotificationSupport attr_reader :notifications # Records a Test::Unit::Notification. def add_notification(notification) @notifications << notification notify_fault(notification) notify_changed end # Returns the number of notifications this TestResult has # recorded. def notification_count @notifications.size end private def initialize_containers super @notifications = [] @summary_generators << :notification_summary end def notification_summary "#{notification_count} notifications" end end end end PK% ] ::-gems/test-unit-3.2.9/lib/test/unit/version.rbnu[module Test module Unit VERSION = "3.2.9" end end PK% ]tH(A(A0gems/test-unit-3.2.9/lib/test/unit/autorunner.rbnu[require "English" require "test/unit/color-scheme" require "test/unit/priority" require "test/unit/attribute-matcher" require "test/unit/testcase" require "optparse" module Test module Unit class AutoRunner RUNNERS = {} COLLECTORS = {} ADDITIONAL_OPTIONS = [] PREPARE_HOOKS = [] class << self def register_runner(id, runner_builder=Proc.new) RUNNERS[id] = runner_builder RUNNERS[id.to_s] = runner_builder end def runner(id) RUNNERS[id.to_s] end @@default_runner = nil def default_runner runner(@@default_runner) end def default_runner=(id) @@default_runner = id end def register_collector(id, collector_builder=Proc.new) COLLECTORS[id] = collector_builder COLLECTORS[id.to_s] = collector_builder end def collector(id) COLLECTORS[id.to_s] end def register_color_scheme(id, scheme) ColorScheme[id] = scheme end def setup_option(option_builder=Proc.new) ADDITIONAL_OPTIONS << option_builder end def prepare(hook=Proc.new) PREPARE_HOOKS << hook end def run(force_standalone=false, default_dir=nil, argv=ARGV, &block) r = new(force_standalone || standalone?, &block) r.base = default_dir r.prepare r.process_args(argv) r.run end def standalone? return false unless("-e" == $0) ObjectSpace.each_object(Class) do |klass| return false if(klass < TestCase) end true end @@need_auto_run = true def need_auto_run? @@need_auto_run end def need_auto_run=(need) @@need_auto_run = need end end register_collector(:descendant) do |auto_runner| require "test/unit/collector/descendant" collector = Collector::Descendant.new collector.filter = auto_runner.filters collector.collect($0.sub(/\.rb\Z/, "")) end register_collector(:load) do |auto_runner| require "test/unit/collector/load" collector = Collector::Load.new unless auto_runner.pattern.empty? collector.patterns.replace(auto_runner.pattern) end unless auto_runner.exclude.empty? collector.excludes.replace(auto_runner.exclude) end collector.base = auto_runner.base collector.default_test_paths = auto_runner.default_test_paths collector.filter = auto_runner.filters collector.collect(*auto_runner.to_run) end # JUST TEST! # register_collector(:xml) do |auto_runner| # require "test/unit/collector/xml" # collector = Collector::XML.new # collector.filter = auto_runner.filters # collector.collect(auto_runner.to_run[0]) # end # deprecated register_collector(:object_space) do |auto_runner| require "test/unit/collector/objectspace" c = Collector::ObjectSpace.new c.filter = auto_runner.filters c.collect($0.sub(/\.rb\Z/, "")) end # deprecated register_collector(:dir) do |auto_runner| require "test/unit/collector/dir" c = Collector::Dir.new c.filter = auto_runner.filters unless auto_runner.pattern.empty? c.pattern.replace(auto_runner.pattern) end unless auto_runner.exclude.empty? c.exclude.replace(auto_runner.exclude) end c.base = auto_runner.base $:.push(auto_runner.base) if auto_runner.base c.collect(*(auto_runner.to_run.empty? ? ["."] : auto_runner.to_run)) end attr_reader :suite, :runner_options attr_accessor :filters, :to_run attr_accessor :default_test_paths attr_accessor :pattern, :exclude, :base, :workdir attr_accessor :color_scheme, :listeners attr_writer :stop_on_failure attr_writer :runner, :collector def initialize(standalone) @standalone = standalone @runner = default_runner @collector = default_collector @filters = [] @to_run = [] @default_test_paths = [] @color_scheme = ColorScheme.default @runner_options = {} @default_arguments = [] @workdir = nil @listeners = [] @stop_on_failure = false config_file = "test-unit.yml" if File.exist?(config_file) load_config(config_file) else load_global_config end yield(self) if block_given? end def stop_on_failure? @stop_on_failure end def prepare PREPARE_HOOKS.each do |handler| handler.call(self) end end def process_args(args=ARGV) begin args.unshift(*@default_arguments) options.order!(args) {|arg| add_test_path(arg)} rescue OptionParser::ParseError => e puts e puts options exit(false) end not @to_run.empty? end def options @options ||= OptionParser.new do |o| o.banner = "Test::Unit automatic runner." o.banner += "\nUsage: #{$0} [options] [-- untouched arguments]" o.on("-r", "--runner=RUNNER", RUNNERS, "Use the given RUNNER.", "(" + keyword_display(RUNNERS) + ")") do |r| @runner = r end o.on("--collector=COLLECTOR", COLLECTORS, "Use the given COLLECTOR.", "(" + keyword_display(COLLECTORS) + ")") do |collector| @collector = collector end if (@standalone) o.on("-b", "--basedir=DIR", "Base directory of test suites.") do |b| @base = b end o.on("-w", "--workdir=DIR", "Working directory to run tests.") do |w| @workdir = w end o.on("--default-test-path=PATH", "Add PATH to the default test paths.", "The PATH is used when user doesn't specify any test path.", "You can specify this option multiple times.") do |path| @default_test_paths << path end o.on("-a", "--add=TORUN", Array, "Add TORUN to the list of things to run;", "can be a file or a directory.") do |paths| paths.each do |path| add_test_path(path) end end @pattern = [] o.on("-p", "--pattern=PATTERN", Regexp, "Match files to collect against PATTERN.") do |e| @pattern << e end @exclude = [] o.on("-x", "--exclude=PATTERN", Regexp, "Ignore files to collect against PATTERN.") do |e| @exclude << e end end o.on("-n", "--name=NAME", String, "Runs tests matching NAME.", "Use '/PATTERN/' for NAME to use regular expression.") do |name| name = (%r{\A/(.*)/\Z} =~ name ? Regexp.new($1) : name) @filters << lambda do |test| return true if name === test.method_name return true if name === test.local_name false end end o.on("--ignore-name=NAME", String, "Ignores tests matching NAME.", "Use '/PATTERN/' for NAME to use regular expression.") do |n| n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n) case n when Regexp @filters << proc {|t| n =~ t.method_name ? false : true} else @filters << proc {|t| n != t.method_name} end end o.on("-t", "--testcase=TESTCASE", String, "Runs tests in TestCases matching TESTCASE.", "Use '/PATTERN/' for TESTCASE to use regular expression.") do |n| n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n) @filters << lambda do |test| match_test_case_name(test, n) end end o.on("--ignore-testcase=TESTCASE", String, "Ignores tests in TestCases matching TESTCASE.", "Use '/PATTERN/' for TESTCASE to use regular expression.") do |n| n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n) @filters << lambda do |test| not match_test_case_name(test, n) end end o.on("--location=LOCATION", String, "Runs tests that defined in LOCATION.", "LOCATION is one of PATH:LINE, PATH or LINE") do |location| if /\A\d+\z/ =~ location path = nil line = location.to_i else path, line, = location.split(/:(\d+)/, 2) line = line.to_i unless line.nil? end add_location_filter(path, line) end o.on("--attribute=EXPRESSION", String, "Runs tests that matches EXPRESSION.", "EXPRESSION is evaluated as Ruby's expression.", "Test attribute name can be used with no receiver in EXPRESSION.", "EXPRESSION examples:", " !slow", " tag == 'important' and !slow") do |expression| @filters << lambda do |test| matcher = AttributeMatcher.new(test) matcher.match?(expression) end end priority_filter = Proc.new do |test| if @filters == [priority_filter] Priority::Checker.new(test).need_to_run? else nil end end o.on("--[no-]priority-mode", "Runs some tests based on their priority.") do |priority_mode| if priority_mode Priority.enable @filters |= [priority_filter] else Priority.disable @filters -= [priority_filter] end end o.on("--default-priority=PRIORITY", Priority.available_values, "Uses PRIORITY as default priority", "(#{keyword_display(Priority.available_values)})") do |priority| Priority.default = priority end o.on("-I", "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]", "Appends directory list to $LOAD_PATH.") do |dirs| $LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR)) end color_schemes = ColorScheme.all o.on("--color-scheme=SCHEME", color_schemes, "Use SCHEME as color scheme.", "(#{keyword_display(color_schemes)})") do |scheme| @color_scheme = scheme end o.on("--config=FILE", "Use YAML fomat FILE content as configuration file.") do |file| load_config(file) end o.on("--order=ORDER", TestCase::AVAILABLE_ORDERS, "Run tests in a test case in ORDER order.", "(#{keyword_display(TestCase::AVAILABLE_ORDERS)})") do |order| TestCase.test_order = order end assertion_message_class = Test::Unit::Assertions::AssertionMessage o.on("--max-diff-target-string-size=SIZE", Integer, "Shows diff if both expected result string size and " + "actual result string size are " + "less than or equal SIZE in bytes.", "(#{assertion_message_class.max_diff_target_string_size})") do |size| assertion_message_class.max_diff_target_string_size = size end o.on("--[no-]stop-on-failure", "Stops immediately on the first non success test", "(#{@stop_on_failure})") do |boolean| @stop_on_failure = boolean end ADDITIONAL_OPTIONS.each do |option_builder| option_builder.call(self, o) end o.on("--", "Stop processing options so that the", "remaining options will be passed to the", "test."){o.terminate} o.on("-h", "--help", "Display this help."){puts o; exit} o.on_tail o.on_tail("Deprecated options:") o.on_tail("--console", "Console runner (use --runner).") do warn("Deprecated option (--console).") @runner = self.class.runner(:console) end if RUNNERS[:fox] o.on_tail("--fox", "Fox runner (use --runner).") do warn("Deprecated option (--fox).") @runner = self.class.runner(:fox) end end o.on_tail end end def keyword_display(keywords) keywords = keywords.collect do |keyword, _| keyword.to_s end.uniq.sort i = 0 keywords.collect do |keyword| if (i > 0 and keyword[0] == keywords[i - 1][0]) or ((i < keywords.size - 1) and (keyword[0] == keywords[i + 1][0])) n = 2 else n = 1 end i += 1 keyword.sub(/^(.{#{n}})([A-Za-z]+)(?=\w*$)/, '\\1[\\2]') end.join(", ") end def run self.class.need_auto_run = false suite = @collector[self] return false if suite.nil? return true if suite.empty? runner = @runner[self] return false if runner.nil? @runner_options[:color_scheme] ||= @color_scheme @runner_options[:listeners] ||= [] @runner_options[:listeners].concat(@listeners) if @stop_on_failure @runner_options[:listeners] << StopOnFailureListener.new end change_work_directory do runner.run(suite, @runner_options).passed? end end def load_config(file) require "yaml" config = YAML.load(File.read(file)) runner_name = config["runner"] @runner = self.class.runner(runner_name) || @runner @collector = self.class.collector(config["collector"]) || @collector (config["color_schemes"] || {}).each do |name, options| ColorScheme[name] = options end runner_options = {} (config["#{runner_name}_options"] || {}).each do |key, value| key = key.to_sym value = ColorScheme[value] if key == :color_scheme if key == :arguments @default_arguments.concat(value.split) else runner_options[key.to_sym] = value end end @runner_options = @runner_options.merge(runner_options) end private def default_runner runner = self.class.default_runner if ENV["EMACS"] == "t" runner ||= self.class.runner(:emacs) else runner ||= self.class.runner(:console) end runner end def default_collector self.class.collector(@standalone ? :load : :descendant) end def global_config_file File.expand_path("~/.test-unit.yml") rescue ArgumentError nil end def load_global_config file = global_config_file load_config(file) if file and File.exist?(file) end def change_work_directory(&block) if @workdir Dir.chdir(@workdir, &block) else yield end end def match_test_case_name(test, pattern) test.class.ancestors.each do |test_class| break if test_class == TestCase return true if pattern === test_class.name end false end def add_test_path(path) if /:(\d+)\z/ =~ path line = $1.to_i path = $PREMATCH add_location_filter(path, line) end @to_run << path end def add_location_filter(path, line) @filters << lambda do |test| test.class.test_defined?(:path => path, :line => line, :method_name => test.method_name) end end class StopOnFailureListener def attach_to_mediator(mediator) mediator.add_listener(TestResult::FINISHED) do |result| result.stop unless result.passed? end end end end end end require "test/unit/runner/console" require "test/unit/runner/emacs" require "test/unit/runner/xml" PK% ]n$$-gems/test-unit-3.2.9/lib/test/unit/fixture.rbnu[module Test module Unit module Fixture class << self def included(base) base.extend(ClassMethods) [:setup, :cleanup, :teardown].each do |type| observer = lambda do |test_case, _, _, value, callback| if value.nil? test_case.fixture[type].unregister(callback) else test_case.fixture[type].register(callback, value) end end base.register_attribute_observer(type, &observer) end end end class Fixture attr_reader :setup attr_reader :cleanup attr_reader :teardown def initialize(test_case) @test_case = test_case @setup = HookPoint.new(@test_case, :setup, :after => :append) @cleanup = HookPoint.new(@test_case, :cleanup, :before => :prepend) @teardown = HookPoint.new(@test_case, :teardown, :before => :prepend) @cached_before_callbacks = {} @cached_after_callbacks = {} end def [](type) case type when :setup @setup when :cleanup @cleanup when :teardown @teardown end end def before_callbacks(type) @cached_before_callbacks[type] ||= collect_before_callbacks(type) end def after_callbacks(type) @cached_after_callbacks[type] ||= collect_after_callbacks(type) end private def target_test_cases @cached_target_test_cases ||= collect_target_test_cases end def collect_before_callbacks(type) prepend_callbacks = [] append_callbacks = [] target_test_cases.each do |ancestor| prepend_callbacks << ancestor.fixture[type].before_prepend_callbacks append_callbacks << ancestor.fixture[type].before_append_callbacks end merge_callbacks(prepend_callbacks, append_callbacks) end def collect_after_callbacks(type) prepend_callbacks = [] append_callbacks = [] target_test_cases.each do |ancestor| prepend_callbacks << ancestor.fixture[type].after_prepend_callbacks append_callbacks << ancestor.fixture[type].after_append_callbacks end merge_callbacks(prepend_callbacks, append_callbacks) end def collect_target_test_cases ancestors = @test_case.ancestors base_index = ancestors.index(::Test::Unit::Fixture) interested_ancestors = ancestors[0, base_index].find_all do |ancestor| ancestor.is_a?(Class) end interested_ancestors.reverse end def merge_callbacks(prepend_callbacks, append_callbacks) all_callbacks = [] prepend_callbacks.reverse_each do |callbacks| all_callbacks.concat(callbacks) end append_callbacks.each do |callbacks| all_callbacks.concat(callbacks) end all_callbacks end end class HookPoint def initialize(test_case, type, default_options) @test_case = test_case @type = type @default_options = default_options @before_prepend_callbacks = [] @before_append_callbacks = [] @after_prepend_callbacks = [] @after_append_callbacks = [] @unregistered_callbacks = [] end def register(method_name_or_callback, options=nil) options ||= {} unless valid_register_options?(options) message = "must be {:before => :prepend}, " + "{:before => :append}, {:after => :prepend} or " + "{:after => :append}: #{options.inspect}" raise ArgumentError, message end if options.empty? options = @default_options end before_how = options[:before] after_how = options[:after] if method_name_or_callback.respond_to?(:call) callback = method_name_or_callback method_name = callback_method_name(callback) @test_case.attribute(:source_location, callback.source_location, method_name) @test_case.__send__(:define_method, method_name, &callback) else method_name = method_name_or_callback end add_callback(method_name, before_how, after_how) end def unregister(method_name_or_callback) if method_name_or_callback.respond_to?(:call) callback = method_name_or_callback method_name = callback_method_name(callback) else method_name = method_name_or_callback end @unregistered_callbacks << method_name end def before_prepend_callbacks @before_prepend_callbacks - @unregistered_callbacks end def before_append_callbacks @before_append_callbacks - @unregistered_callbacks end def after_prepend_callbacks @after_prepend_callbacks - @unregistered_callbacks end def after_append_callbacks @after_append_callbacks - @unregistered_callbacks end private def valid_register_options?(options) return true if options.empty? return false if options.size > 1 key = options.keys.first [:before, :after].include?(key) and [:prepend, :append].include?(options[key]) end def callback_method_name(callback) "#{@type}_#{callback.object_id}" end def add_callback(method_name_or_callback, before_how, after_how) case before_how when :prepend @before_prepend_callbacks = [method_name_or_callback] | @before_prepend_callbacks when :append @before_append_callbacks |= [method_name_or_callback] else case after_how when :prepend @after_prepend_callbacks = [method_name_or_callback] | @after_prepend_callbacks when :append @after_append_callbacks |= [method_name_or_callback] end end end end module ClassMethods def fixture @fixture ||= Fixture.new(self) end def setup(*method_names, &callback) register_fixture(:setup, *method_names, &callback) end def unregister_setup(*method_names_or_callbacks) unregister_fixture(:setup, *method_names_or_callbacks) end def cleanup(*method_names, &callback) register_fixture(:cleanup, *method_names, &callback) end def unregister_cleanup(*method_names_or_callbacks) unregister_fixture(:cleanup, *method_names_or_callbacks) end def teardown(*method_names, &callback) register_fixture(:teardown, *method_names, &callback) end def unregister_teardown(*method_names_or_callbacks) unregister_fixture(:teardown, *method_names_or_callbacks) end private def register_fixture(fixture, *method_names, &callback) options = {} options = method_names.pop if method_names.last.is_a?(Hash) callbacks = method_names callbacks << callback if callback attribute(fixture, options, *callbacks) end def unregister_fixture(fixture, *method_names_or_callbacks) attribute(fixture, nil, *method_names_or_callbacks) end end private def run_fixture(type, options={}, &block) fixtures = [ self.class.fixture.before_callbacks(type), type, self.class.fixture.after_callbacks(type), ].flatten if block runner = create_fixtures_runner(fixtures, options, &block) runner.call else fixtures.each do |method_name| run_fixture_callback(method_name, options) end end end def create_fixtures_runner(fixtures, options, &block) if fixtures.empty? block else last_fixture = fixtures.pop create_fixtures_runner(fixtures, options) do block_is_called = false run_fixture_callback(last_fixture, options) do block_is_called = true block.call end block.call unless block_is_called end end end def run_fixture_callback(method_name, options, &block) return unless respond_to?(method_name, true) begin __send__(method_name, &block) rescue Exception raise unless options[:handle_exception] raise unless handle_exception($!) end end def run_setup(&block) run_fixture(:setup, &block) end def run_cleanup run_fixture(:cleanup) end def run_teardown run_fixture(:teardown, :handle_exception => true) end end end end PK% ]l 4gems/test-unit-3.2.9/lib/test/unit/runner/console.rbnu[# Copyright (C) 2008-2017 Kouhei Sutou # # License: Ruby OR LGPL-2.1+ # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 USA module Test module Unit AutoRunner.register_runner(:console) do |auto_runner| require 'test/unit/ui/console/testrunner' Test::Unit::UI::Console::TestRunner end AutoRunner.setup_option do |auto_runner, opts| require 'test/unit/ui/console/outputlevel' output_levels = [ ["silent", UI::Console::OutputLevel::SILENT], ["progress", UI::Console::OutputLevel::PROGRESS_ONLY], ["important-only", UI::Console::OutputLevel::IMPORTANT_FAULTS_ONLY], ["normal", UI::Console::OutputLevel::NORMAL], ["verbose", UI::Console::OutputLevel::VERBOSE], ] opts.on('-v', '--verbose=[LEVEL]', output_levels, "Set the output level (default is verbose).", "(#{auto_runner.keyword_display(output_levels)})") do |level| level ||= output_levels.assoc("verbose")[1] auto_runner.runner_options[:output_level] = level end use_color_options = [ [:auto, :auto], ["-", false], ["no", false], ["false", false], ["+", true], ["yes", true], ["true", true], ] opts.on("--[no-]use-color=[auto]", use_color_options, "Uses color output", "(default is auto)") do |use_color| case use_color when nil use_color = true when :auto use_color = nil end auto_runner.runner_options[:use_color] = use_color end opts.on("--progress-row-max=MAX", Integer, "Uses MAX as max terminal width for progress mark", "(default is auto)") do |max| auto_runner.runner_options[:progress_row_max] = max end opts.on("--no-show-detail-immediately", "Shows not passed test details immediately.", "(default is yes)") do |boolean| auto_runner.runner_options[:show_detail_immediately] = boolean end opts.on("--[no-]reverse-output", "Shows fault details in reverse.", "(default is yes for tty output, no otherwise)") do |boolean| auto_runner.runner_options[:reverse_output] = boolean end end end end PK% ]qo0gems/test-unit-3.2.9/lib/test/unit/runner/xml.rbnu[module Test module Unit AutoRunner.register_runner(:xml) do |auto_runner| require 'test/unit/ui/xml/testrunner' Test::Unit::UI::XML::TestRunner end AutoRunner.setup_option do |auto_runner, opts| opts.on("--output-file-descriptor=FD", Integer, "Outputs to file descriptor FD") do |fd| auto_runner.runner_options[:output_file_descriptor] = fd end end end end PK% ]l2gems/test-unit-3.2.9/lib/test/unit/runner/emacs.rbnu[module Test module Unit AutoRunner.register_runner(:emacs) do |auto_runner| require 'test/unit/ui/emacs/testrunner' Test::Unit::UI::Emacs::TestRunner end end end PK% ] 11*gems/test-unit-3.2.9/lib/test/unit/data.rbnu[require "test/unit/data-sets" module Test module Unit module Data class << self def included(base) base.extend(ClassMethods) end end module ClassMethods # This method provides Data-Driven-Test functionality. # # Define test data in the test code. # # @overload data(label, data, options={}) # @param [String] label specify test case name. # @param data specify test data. # @param [Hash] options specify options. # @option options [Boolean] :keep whether or not to use # this data in the following test methods # # @example data(label, data) # data("empty string", [true, ""]) # data("plain string", [false, "hello"]) # def test_empty?(data) # expected, target = data # assert_equal(expected, target.empty?) # end # # @overload data(variable, patterns, options={}) # @param [Symbol] variable specify test pattern variable name. # @param [Array] patterns specify test patterns for the variable. # @param [Hash] options specify options. # @option options [Boolean] :keep whether or not to use # this data in the following test methods # @option options [Object] :group the test pattern group. # Test matrix is generated for each test pattern group separately. # # @example data(variable, patterns) # data(:x, [1, 2, 3]) # data(:y, ["a", "b"]) # def test_patterns(data) # # 3 * 2 times executed # # 3: the number of patterns of :x # # 2: the number of patterns of :y # p data # # => {:x => 1, :y => "a"} # # => {:x => 1, :y => "b"} # # => {:x => 2, :y => "a"} # # => {:x => 2, :y => "b"} # # => {:x => 3, :y => "a"} # # => {:x => 3, :y => "b"} # end # # Generates test matrix from variable and patterns pairs. # # @overload data(data_set, options={}) # @param [Hash] data_set specify test data as a Hash that # key is test label and value is test data. # @param [Hash] options specify options. # @option options [Boolean] :keep whether or not to use # this data in the following test methods # # @example data(data_set) # data("empty string" => [true, ""], # "plain string" => [false, "hello"]) # def test_empty?(data) # expected, target = data # assert_equal(expected, target.empty?) # end # # @overload data(options={}, &block) # @param [Hash] options specify options. # @option options [Boolean] :keep whether or not to use # this data in the following test methods # @yieldreturn [Hash] return test data set # as a Hash that key is test label and value is test data. # # @example data(&block) # data do # data_set = {} # data_set["empty string"] = [true, ""] # data_set["plain string"] = [false, "hello"] # data_set # end # def test_empty?(data) # expected, target = data # assert_equal(expected, target.empty?) # end # # @overload data(options={}, &block) # @param [Hash] options specify options. # @option options [Boolean] :keep whether or not to use # this data in the following test methods # @yieldreturn [Array] return test data set # as an Array of variable and patterns. # # @example data(&block) # data do # patterns = 3.times.to_a # [:x, patterns] # end # data do # patterns = [] # character = "a" # 2.times.each do # patterns << character # character = character.succ # end # [:y, patterns] # end # def test_patterns(data) # # 3 * 2 times executed # # 3: the number of patterns of :x # # 2: the number of patterns of :y # p data # # => {:x => 0, :y => "a"} # # => {:x => 0, :y => "b"} # # => {:x => 1, :y => "a"} # # => {:x => 1, :y => "b"} # # => {:x => 2, :y => "a"} # # => {:x => 2, :y => "b"} # end # # Generates test matrix from variable and patterns pairs. # def data(*arguments, &block) options = nil n_arguments = arguments.size case n_arguments when 0 raise ArgumentError, "no block is given" unless block_given? data_set = block when 1 if block_given? data_set = block options = arguments[1] else data_set = arguments[0] end when 2 case arguments[0] when String data_set = {arguments[0] => arguments[1]} when Hash data_set = arguments[0] options = arguments[1] else variable = arguments[0] patterns = arguments[1] data_set = [variable, patterns] end when 3 case arguments[0] when String data_set = {arguments[0] => arguments[1]} options = arguments[2] else variable = arguments[0] patterns = arguments[1] data_set = [variable, patterns] options = arguments[2] end else message = "wrong number arguments(#{n_arguments} for 0..3)" raise ArgumentError, message end options ||= {} data_sets = current_attribute(:data)[:value] || DataSets.new data_sets.add(data_set, options) if options[:keep] keep_hook = lambda do |attr| attr.merge(value: attr[:value].keep) end options = options.merge(keep_hook: keep_hook) end attribute(:data, data_sets, options) end # This method provides Data-Driven-Test functionality. # # Load test data from the file. This is shorthand to load # test data from file. If you want to load complex file, you # can use {#data} with block. # # @param [String] file_name full path to test data file. # File format is automatically detected from filename extension. # @raise [ArgumentError] if +file_name+ is not supported file format. # @see Loader#load # # @example Load data from CSV file # load_data("/path/to/test-data.csv") # def test_empty?(data) # assert_equal(data["expected"], data["target"].empty?) # end # def load_data(file_name) loader = Loader.new(self) loader.load(file_name) end class Loader # @api private def initialize(test_case) @test_case = test_case end # Load data from file. # # @param [String] file_name full path to test data file. # File format is automatically detected from filename extension. # @raise [ArgumentError] if +file_name+ is not supported file format. # @see #load_csv # @see #load_tsv # @api private def load(file_name) case File.extname(file_name).downcase when ".csv" load_csv(file_name) when ".tsv" load_tsv(file_name) else raise ArgumentError, "unsupported file format: <#{file_name}>" end end # Load data from CSV file. # # There are 2 types of CSV file as following examples. # First, there is a header on first row and it's first column is "label". # Another, there is no header in the file. # # @example Load data from CSV file with header # # test-data.csv: # # label,expected,target # # empty string,true,"" # # plain string,false,hello # # # load_data("/path/to/test-data.csv") # def test_empty?(data) # assert_equal(data["expected"], data["target"].empty?) # end # # @example Load data from CSV file without header # # test-data-without-header.csv: # # empty string,true,"" # # plain string,false,hello # # # load_data("/path/to/test-data-without-header.csv") # def test_empty?(data) # expected, target = data # assert_equal(expected, target.empty?) # end # # @api private def load_csv(file_name) require 'csv' first_row = true header = nil CSV.foreach(file_name) do |row| if first_row first_row = false if row.first == "label" header = row[1..-1] next end end set_test_data(header, row) end end # Load data from TSV file. # # There are 2 types of TSV file as following examples. # First, there is a header on first row and it's first column is "label". # Another, there is no header in the file. # # @example Load data from TSV file with header # # test-data.tsv: # # label expected target # # empty string true "" # # plain string false hello # # # load_data("/path/to/test-data.tsv") # def test_empty?(data) # assert_equal(data["expected"], data["target"].empty?) # end # # @example Load data from TSV file without header # # test-data-without-header.tsv: # # empty string true "" # # plain string false hello # # # load_data("/path/to/test-data-without-header.tsv") # def test_empty?(data) # expected, target = data # assert_equal(expected, target.empty?) # end # # @api private def load_tsv(file_name) require "csv" if CSV.const_defined?(:VERSION) first_row = true header = nil CSV.foreach(file_name, :col_sep => "\t") do |row| if first_row first_row = false if row.first == "label" header = row[1..-1] next end end set_test_data(header, row) end else # for old CSV library first_row = true header = nil CSV.open(file_name, "r", "\t") do |row| if first_row first_row = false if row.first == "label" header = row[1..-1] next end end set_test_data(header, row) end end end private def normalize_value(value) return true if value == "true" return false if value == "false" begin Integer(value) rescue ArgumentError begin Float(value) rescue ArgumentError value end end end def set_test_data(header, row) label = row.shift if header data = {} header.each_with_index do |key, i| data[key] = normalize_value(row[i]) end else data = row.collect do |cell| normalize_value(cell) end end @test_case.data(label, data) end end end end end end PK% ]z|{{8gems/test-unit-3.2.9/lib/test/unit/auto-runner-loader.rbnu[require "test/unit/test-suite-creator" module Test module Unit module AutoRunnerLoader @loaded = false class << self def check(test_case, method_name) return if @loaded return unless TestSuiteCreator.test_method?(test_case, method_name) require "test/unit" @loaded = true end end end end end PK% ]xpp:gems/test-unit-3.2.9/lib/test/unit/collector/descendant.rbnu[require 'test/unit/collector' module Test module Unit module Collector class Descendant include Collector NAME = 'collected from the subclasses of TestCase' def collect(name=NAME) suite = TestSuite.new(name) add_test_cases(suite, TestCase::DESCENDANTS) suite end end end end end PK% ]W"DD3gems/test-unit-3.2.9/lib/test/unit/collector/xml.rbnu[#-- # # Author:: Kouhei Sutou # Copyright:: # * Copyright (c) 2011 Kouhei Sutou # License:: Ruby license. # just test!!! don't use it yet!!! require 'test/unit/collector' require 'rexml/document' require 'rexml/streamlistener' module Test module Unit module Collector class XML include Collector def collect(xml_log_path) listener = Listener.new File.open(xml_log_path) do |xml_log| parser = REXML::Parsers::StreamParser.new(xml_log, listener) parser.parse end suite = TestSuite.new("tests in #{xml_log_path}") suites = listener.test_suites sort(suites).each {|s| add_suite(suite, s)} suite end class Listener include REXML::StreamListener attr_reader :test_suites def initialize @ns_stack = [{"xml" => :xml}] @tag_stack = [["", :root]] @text_stack = [''] @state_stack = [:root] @values = {} @test_suites = [] end def tag_start(name, attributes) @text_stack.push('') ns = @ns_stack.last.dup attrs = {} attributes.each do |n, v| if /\Axmlns(?:\z|:)/ =~ n ns[$POSTMATCH] = v else attrs[n] = v end end @ns_stack.push(ns) _parent_tag = parent_tag prefix, local = split_name(name) uri = _ns(ns, prefix) @tag_stack.push([uri, local]) state = next_state(@state_stack.last, uri, local) @state_stack.push(state) @values = {} case state when :test_suite, :test_case # do nothing when :test @n_pass_assertions = 0 if _parent_tag == "start-test" when :backtrace @backtrace = [] @values_backup = @values end end def tag_end(name) state = @state_stack.pop text = @text_stack.pop uri, local = @tag_stack.pop no_action_states = [:root, :stream] case state when *no_action_states # do nothing when :test_suite test_suite_end when :complete_test_case @test_suites.last << @test_case.suite when :test_case test_case_end when :result @result = @values when :test test_end when :pass_assertion @n_pass_assertions += 1 when :backtrace @values = @values_backup @values["backtrace"] = @backtrace when :entry file = @values['file'] line = @values['line'] info = @values['info'] @backtrace << "#{file}:#{line}: #{info}" @values = {} else local = normalize_local(local) @values[local] = text end @ns_stack.pop end def text(data) @text_stack.last << data end private def _ns(ns, prefix) ns.fetch(prefix, "") end NAME_SPLIT = /^(?:([\w:][-\w\d.]*):)?([\w:][-\w\d.]*)/ def split_name(name) name =~ NAME_SPLIT [$1 || '', $2] end STATE_TABLE = { :root => [:stream], :stream => [:ready_test_suite, :start_test_suite, :ready_test_case, :start_test_case, :start_test, :pass_assertion, :test_result, :complete_test, :complete_test_case, :complete_test_suite, :success], :ready_test_suite => [:n_tests], :start_test_suite => [:test_suite], :ready_test_case => [:test_case, :n_tests], :start_test_case => [:test_case], :start_test => [:test], :pass_assertion => [:test], :complete_test => [:test, :success], :complete_test_case => [:test_case, :elapsed, :success], :complete_test_suite => [:test_suite, :success], :test_suite => [:start_time, :elapsed], :test_case => [:name, :start_time, :elapsed], :test => [:name, :start_time, :elapsed], :test_result => [:test, :result], :result => [:test_case, :test, :status, :backtrace, :detail], :backtrace => [:entry], :entry => [:file, :line, :info], } def next_state(current_state, uri, local) local = normalize_local(local) valid_elements = STATE_TABLE[current_state] if valid_elements.nil? raise "unexpected element: #{current_path}" end next_state = local.to_sym unless valid_elements.include?(next_state) raise "unexpected element: #{current_path}" end next_state end def current_path locals = @tag_stack.collect do |uri, local| local end ["", *locals].join("/") end def normalize_local(local) local.gsub(/-/, "_") end def parent_tag @tag_stack.last[1] end def test_suite_end return unless parent_tag == "start-test-suite" suite = TestSuite.new ["start_time", "elapsed_time", "n_tests"].each do |key| if @values.has_key?(key) suite.instance_variable_set("@#{key}", @values[key]) end end @test_suites << suite end def test_case_end return unless parent_tag == "start-test-case" name = @values["name"] @test_case = Class.new(TestCase) do define_method(:name) do name end end end def test_end return unless parent_tag == "complete-test" name = @values["name"] n_pass_assertions = @n_pass_assertions result = @result @test_case.module_eval do test define_method(name) do n_pass_assertions.times do add_assertion end case result["status"] when "omission" add_omission(Omission.new(name, result["backtrace"], result["detail"])) end end end end end end end end end PK% ] z4gems/test-unit-3.2.9/lib/test/unit/collector/load.rbnu[require 'pathname' require 'test/unit/testsuite' require 'test/unit/collector' module Test module Unit module Collector class Load include Collector attr_reader :patterns, :excludes, :base attr_reader :default_test_paths def initialize super @system_excludes = [/~\z/, /\A\.\#/] @system_directory_excludes = [/\A(?:CVS|\.svn|\.git)\z/] @patterns = [/\Atest[_\-].+\.rb\z/m, /[_\-]test\.rb\z/] @excludes = [] @base = nil @default_test_paths = [] @require_failed_infos = [] end def base=(base) base = Pathname(base) unless base.nil? @base = base end def default_test_paths=(paths) @default_test_paths = paths.collect do |path| Pathname(path) end end def collect(*froms) add_load_path(@base) do froms = @default_test_paths if froms.empty? froms = ["."] if froms.empty? test_suites = [] already_gathered = find_test_cases froms.each do |from| from = resolve_path(from) if from.directory? test_suite = collect_recursive(from, already_gathered) test_suites << test_suite unless test_suite.tests.empty? else collect_file(from, test_suites, already_gathered) end end add_require_failed_test_suite(test_suites) if test_suites.size > 1 test_suite = TestSuite.new("[#{froms.join(', ')}]") sort(test_suites).each do |sub_test_suite| test_suite << sub_test_suite end else test_suite = test_suites.first end test_suite end end def find_test_cases(ignore=[]) test_cases = [] TestCase::DESCENDANTS.each do |test_case| test_cases << test_case unless ignore.include?(test_case) end ignore.concat(test_cases) test_cases end private def collect_recursive(path, already_gathered) sub_test_suites = [] if path.directory? directories, files = path.children.partition do |child| child.directory? end files.each do |child| next if excluded_file?(child.basename.to_s) collect_file(child, sub_test_suites, already_gathered) end directories.each do |child| next if excluded_directory?(child.basename.to_s) sub_test_suite = collect_recursive(child, already_gathered) sub_test_suites << sub_test_suite unless sub_test_suite.empty? end else unless excluded_file?(path.basename.to_s) collect_file(path, sub_test_suites, already_gathered) end end test_suite = TestSuite.new(path.basename.to_s) sort(sub_test_suites).each do |sub_test_suite| test_suite << sub_test_suite end test_suite end def collect_file(path, test_suites, already_gathered) @program_file ||= File.expand_path($0) expanded_path = path.expand_path return if @program_file == expanded_path.to_s add_load_path(expanded_path.dirname) do begin require(path.basename.to_s) rescue LoadError @require_failed_infos << {:path => expanded_path, :exception => $!} end add_test_cases(test_suites, find_test_cases(already_gathered)) end end def resolve_path(path) if @base @base + path else Pathname(path) end end def add_load_path(path) return yield if path.nil? path = path.to_s return yield if $LOAD_PATH.index(path) begin $LOAD_PATH.unshift(path) yield ensure index = $LOAD_PATH.index(path) $LOAD_PATH.delete_at(index) if index end end def excluded_directory?(base) @system_directory_excludes.any? {|pattern| pattern =~ base} end def excluded_file?(base) return true if @system_excludes.any? {|pattern| pattern =~ base} patterns = @patterns || [] unless patterns.empty? return true unless patterns.any? {|pattern| pattern =~ base} end excludes = @excludes || [] unless excludes.empty? return true if excludes.any? {|pattern| pattern =~ base} end false end def add_require_failed_test_suite(test_suites) return if @require_failed_infos.empty? require_failed_infos = @require_failed_infos require_failed_errors = Class.new(Test::Unit::TestCase) require_failed_errors.class_eval do class << self def name "RequireFailedErrors" end end require_failed_infos.each do |info| path = info[:path] normalized_path = path.to_s.gsub(/[^a-z0-9\_]+/i, '_') normalized_path = normalized_path.gsub(/\A_+/, '') exception = info[:exception] define_method("test_require_#{normalized_path}") do raise(exception.class, "failed to load <#{path}>: #{exception.message}", exception.backtrace) end end def priority 100 end end add_suite(test_suites, require_failed_errors.suite) end end end end end PK% ]Q$ 3gems/test-unit-3.2.9/lib/test/unit/collector/dir.rbnu[require 'test/unit/testsuite' require 'test/unit/collector' module Test module Unit module Collector class Dir include Collector attr_reader :pattern, :exclude attr_accessor :base def initialize(dir=::Dir, file=::File, object_space=::ObjectSpace, req=nil) super() @dir = dir @file = file @object_space = object_space @req = req @pattern = [/\btest_.*\.rb\Z/m] @exclude = [] @base = nil end def collect(*from) basedir = @base $:.push(basedir) if basedir if(from.empty?) recursive_collect('.', find_test_cases) elsif(from.size == 1) recursive_collect(from.first, find_test_cases) else suites = [] from.each do |f| suite = recursive_collect(f, find_test_cases) suites << suite unless(suite.tests.empty?) end suite = TestSuite.new("[#{from.join(', ')}]") sort(suites).each{|s| suite << s} suite end ensure $:.delete_at($:.rindex(basedir)) if basedir end def find_test_cases(ignore=[]) cases = [] @object_space.each_object(Class) do |c| cases << c if(c < TestCase && !ignore.include?(c)) end ignore.concat(cases) cases end def recursive_collect(name, already_gathered) sub_suites = [] path = realdir(name) if @file.directory?(path) dir_name = name unless name == '.' @dir.entries(path).each do |e| next if(e == '.' || e == '..') e_name = dir_name ? @file.join(dir_name, e) : e if @file.directory?(realdir(e_name)) next if /\A(?:CVS|\.svn|\.git)\z/ =~ e sub_suite = recursive_collect(e_name, already_gathered) sub_suites << sub_suite unless(sub_suite.empty?) else next if /~\z/ =~ e_name or /\A\.\#/ =~ e if @pattern and !@pattern.empty? next unless @pattern.any? {|pat| pat =~ e_name} end if @exclude and !@exclude.empty? next if @exclude.any? {|pat| pat =~ e_name} end collect_file(e_name, sub_suites, already_gathered) end end else collect_file(name, sub_suites, already_gathered) end suite = TestSuite.new(@file.basename(name)) sort(sub_suites).each{|s| suite << s} suite end def collect_file(name, suites, already_gathered) dir = @file.dirname(@file.expand_path(name, @base)) $:.unshift(dir) if(@req) @req.require(name) else require(name) end find_test_cases(already_gathered).each{|t| add_suite(suites, t.suite)} ensure $:.delete_at($:.rindex(dir)) if(dir) end def realdir(path) if @base @file.join(@base, path) else path end end end end end end PK% ]>;gems/test-unit-3.2.9/lib/test/unit/collector/objectspace.rbnu[# Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit/collector' module Test module Unit module Collector class ObjectSpace include Collector NAME = 'collected from the ObjectSpace' def initialize(source=::ObjectSpace) super() @source = source end def collect(name=NAME) suite = TestSuite.new(name) sub_suites = [] @source.each_object(Class) do |klass| if(Test::Unit::TestCase > klass) add_suite(sub_suites, klass.suite) end end sort(sub_suites).each{|s| suite << s} suite end end end end end PK% ]], =gems/test-unit-3.2.9/lib/test/unit/fault-location-detector.rbnu[# Copyright (C) 2012 Kouhei Sutou # # License: Ruby's require "English" module Test module Unit class FaultLocationDetector def initialize(fault, code_snippet_fetcher) @fault = fault @code_snippet_fetcher = code_snippet_fetcher extract_fault_information end def split_backtrace_entry(entry) match_data = /\A(.+):(\d+)(?::(.*))?\z/.match(entry) return nil if match_data.nil? file, line_number, context = match_data.to_a[1..-1] line_number = line_number.to_i if /\Ain `(.+?)'/ =~ context method_name = $1 if /\Ablock (?:\(.+?\) )?in / =~ method_name method_name = $POSTMATCH end else method_name = nil end [file, line_number, context, method_name] end def target?(backtrace_entry) file, line_number, context, method_name = split_backtrace_entry(backtrace_entry) _ = context return false if file.nil? if @fault_source_location target_source_location?(file, line_number, method_name) elsif @fault_method_name target_method?(method_name) else true end end private def target_source_location?(file, line_number, method_name) fault_file, fault_line_number = @fault_source_location return false unless file.end_with?(fault_file) return false if line_number < fault_line_number lines = @code_snippet_fetcher.source(file) return false if lines.nil? base_indent_level = nil fault_line_number.step(lines.size) do |current_line_number| line = lines[current_line_number - 1] current_indent_level = guess_indent_level(line) base_indent_level ||= current_indent_level return true if current_line_number == line_number if current_line_number == fault_line_number break if /(?:\send|\})\s*$/ =~ line else break if current_indent_level == base_indent_level end end false end def target_method?(method_name) @fault_method_name == method_name end def guess_indent_level(line) if /\A(\s*)/ =~ line $1.sub(/\t/, " " * 8).count(" ") else 0 end end def extract_fault_information if @fault.respond_to?(:source_location) @fault_source_location = @fault.source_location else @fault_source_location = nil end if @fault.respond_to?(:method_name) @fault_method_name = @fault.method_name else @fault_method_name = nil end end end end end PK% ]j V 7gems/test-unit-3.2.9/lib/test/unit/exception-handler.rbnu[module Test module Unit module ExceptionHandler @@exception_handlers = [] class << self def exception_handlers @@exception_handlers end def included(base) base.extend(ClassMethods) observer = Proc.new do |test_case, _, _, value, method_name| if value @@exception_handlers.unshift(method_name) else @@exception_handlers.delete(method_name) end end base.register_attribute_observer(:exception_handler, &observer) end end module ClassMethods def exception_handlers ExceptionHandler.exception_handlers end # @overload exception_handler(method_name) # Add an exception handler method. # # @param method_name [Symbol] # The method name that handles exception raised in tests. # @return [void] # # @overload exception_handler(&callback) # Add an exception handler. # # @yield [test, exception] # Gives the test and the exception. # @yieldparam test [Test::Unit::TestCase] # The test where the exception is raised. # @yieldparam exception [Exception] # The exception that is raised in running the test. # @yieldreturn [Boolean] # Whether the handler handles the exception or not. # The handler must return _true_ if the handler handles # test exception, _false_ otherwise. # @return [void] # # This is a public API for developers who extend test-unit. def exception_handler(*method_name_or_handlers, &block) if block_given? exception_handlers.unshift(block) else method_name_or_handlers.each do |method_name_or_handler| if method_name_or_handler.respond_to?(:call) handler = method_name_or_handler exception_handlers.unshift(handler) else method_name = method_name_or_handler attribute(:exception_handler, true, {}, method_name) end end end end def unregister_exception_handler(*method_name_or_handlers) method_name_or_handlers.each do |method_name_or_handler| if method_name_or_handler.respond_to?(:call) handler = method_name_or_handler exception_handlers.delete(handler) else method_name = method_name_or_handler attribute(:exception_handler, false, {}, method_name) end end end end end end end PK% ]"zz2gems/test-unit-3.2.9/lib/test/unit/color-scheme.rbnu[require 'test/unit/color' module Test module Unit class ColorScheme include Enumerable class << self def default if available_colors == 256 default_for_256_colors else default_for_8_colors end end @@default_for_8_colors = nil def default_for_8_colors @@default_for_8_colors ||= new("pass" => Color.new("green", :background => true) + Color.new("white", :bold => true), "pass-marker" => Color.new("green", :bold => true), "failure" => Color.new("red", :background => true) + Color.new("white", :bold => true), "failure-marker" => Color.new("red"), "pending" => Color.new("magenta", :background => true) + Color.new("white", :bold => true), "pending-marker" => Color.new("magenta"), "omission" => Color.new("blue", :background => true) + Color.new("white", :bold => true), "omission-marker" => Color.new("blue"), "notification" => Color.new("cyan", :background => true) + Color.new("white", :bold => true), "notification-marker" => Color.new("cyan"), "error" => Color.new("black", :background => true) + Color.new("yellow", :bold => true), "error-marker" => Color.new("yellow"), "case" => Color.new("blue", :background => true) + Color.new("white", :bold => true), "suite" => Color.new("green", :background => true) + Color.new("white", :bold => true), "diff-inserted-tag" => Color.new("red", :background => true) + Color.new("black", :bold => true), "diff-deleted-tag" => Color.new("green", :background => true) + Color.new("black", :bold => true), "diff-difference-tag" => Color.new("cyan", :background => true) + Color.new("white", :bold => true), "diff-inserted" => Color.new("red", :background => true) + Color.new("white", :bold => true), "diff-deleted" => Color.new("green", :background => true) + Color.new("white", :bold => true)) end @@default_for_256_colors = nil def default_for_256_colors @@default_for_256_colors ||= new("pass" => Color.new("030", :background => true) + Color.new("555", :bold => true), "pass-marker" => Color.new("050", :bold => true), "failure" => Color.new("300", :background => true) + Color.new("555", :bold => true), "failure-marker" => Color.new("500"), "pending" => Color.new("303", :background => true) + Color.new("555", :bold => true), "pending-marker" => Color.new("303"), "omission" => Color.new("001", :background => true) + Color.new("555", :bold => true), "omission-marker" => Color.new("001"), "notification" => Color.new("011", :background => true) + Color.new("555", :bold => true), "notification-marker" => Color.new("011"), "error" => Color.new("000", :background => true) + Color.new("550", :bold => true), "error-marker" => Color.new("550"), "case" => Color.new("220", :background => true) + Color.new("555", :bold => true), "suite" => Color.new("110", :background => true) + Color.new("555", :bold => true), "diff-inserted-tag" => Color.new("500", :background => true) + Color.new("000", :bold => true), "diff-deleted-tag" => Color.new("050", :background => true) + Color.new("000", :bold => true), "diff-difference-tag" => Color.new("005", :background => true) + Color.new("555", :bold => true), "diff-inserted" => Color.new("300", :background => true) + Color.new("555", :bold => true), "diff-deleted" => Color.new("030", :background => true) + Color.new("555", :bold => true)) end @@schemes = {} def all @@schemes.merge("default" => default) end def [](id) @@schemes[id.to_s] end def []=(id, scheme_or_spec) if scheme_or_spec.is_a?(self) scheme = scheme_or_spec else scheme = new(scheme_or_spec) end @@schemes[id.to_s] = scheme end def available_colors guess_available_colors_from_vte_version_env || guess_available_colors_from_colorterm_env || guess_available_colors_from_term_env || 8 end private def guess_available_colors_from_vte_version_env vte_version = ENV["VTE_VERSION"] return nil if vte_version.nil? major = 0 minor = 13 micro = 0 packed_version = major * 10000 + minor * 100 + micro if vte_version.to_i >= packed_version 256 else 8 end end def guess_available_colors_from_colorterm_env case ENV["COLORTERM"] when "gnome-terminal", "xfce4-terminal" 256 else nil end end def guess_available_colors_from_term_env case ENV["TERM"] when /-256color\z/ 256 else nil end end end def initialize(scheme_spec) @scheme = {} scheme_spec.each do |key, color_spec| self[key] = color_spec end end def [](name) @scheme[name.to_s] end def []=(name, color_spec) @scheme[name.to_s] = make_color(color_spec) end def each(&block) @scheme.each(&block) end def to_hash hash = {} @scheme.each do |key, color| hash[key] = color end hash end private def make_color(color_spec) if color_spec.is_a?(Color) or color_spec.is_a?(MixColor) color_spec else color_name = nil normalized_color_spec = {} color_spec.each do |key, value| key = key.to_sym if key == :name color_name = value else normalized_color_spec[key] = value end end Color.new(color_name, normalized_color_spec) end end end end end PK% ]= = 8gems/test-unit-3.2.9/lib/test/unit/test-suite-creator.rbnu[#-- # # Author:: Kouhei Sutou # Copyright:: # * Copyright (c) 2011 Kouhei Sutou # License:: Ruby license. require "test/unit/data-sets" module Test module Unit class TestSuiteCreator # :nodoc: class << self def test_method?(test_case, method_name) /\Atest./ =~ method_name.to_s or test_case.find_attribute(method_name, :test) end end def initialize(test_case) @test_case = test_case end def create suite = TestSuite.new(@test_case.name, @test_case) collect_test_names.each do |test_name| data_sets = extract_data_sets(test_name) if data_sets data_sets.each do |label, data| append_test(suite, test_name) do |test| test.assign_test_data(label, data) end end else append_test(suite, test_name) end end append_test(suite, "default_test") if suite.empty? suite end private def extract_data_sets(test_name) data_sets = @test_case.find_attribute(test_name, :data, :recursive => false) data_method_name = "data_#{test_name}" test = @test_case.new(test_name) if test.respond_to?(data_method_name) data_method = test.method(data_method_name) if data_method.arity <= 0 data_sets ||= DataSets.new data_sets << data_method end end data_sets end def append_test(suite, test_name) test = @test_case.new(test_name) yield(test) if block_given? suite << test if test.valid? end def collect_test_names methods = @test_case.public_instance_methods(true) super_test_case = @test_case.superclass methods -= super_test_case.public_instance_methods(true) methods |= @test_case.public_instance_methods(false) method_names = methods.collect(&:to_s) test_names = method_names.find_all do |method_name| self.class.test_method?(@test_case, method_name) end __send__("sort_test_names_in_#{@test_case.test_order}_order", test_names) end def sort_test_names_in_alphabetic_order(test_names) test_names.sort end def sort_test_names_in_random_order(test_names) test_names.sort_by {rand(test_names.size)} end def sort_test_names_in_defined_order(test_names) added_method_names = @test_case.added_method_names test_names.sort do |test1, test2| test1_defined_order = added_method_names.index(test1) test2_defined_order = added_method_names.index(test2) if test1_defined_order and test2_defined_order test1_defined_order <=> test2_defined_order elsif test1_defined_order 1 elsif test2_defined_order -1 else test1 <=> test2 end end end end end end PK% ]H~XX-gems/test-unit-3.2.9/lib/test/unit/failure.rbnu[#-- # # Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. module Test module Unit # Encapsulates a test failure. Created by Test::Unit::TestCase # when an assertion fails. class Failure attr_reader :test_name, :location, :message attr_reader :method_name, :source_location attr_reader :expected, :actual, :user_message attr_reader :inspected_expected, :inspected_actual SINGLE_CHARACTER = 'F' LABEL = "Failure" # Creates a new Failure with the given location and # message. def initialize(test_name, location, message, options={}) @test_name = test_name @location = location @message = message @method_name = options[:method_name] @source_location = options[:source_location] @expected = options[:expected] @actual = options[:actual] @inspected_expected = options[:inspected_expected] @inspected_actual = options[:inspected_actual] @user_message = options[:user_message] end # Returns a single character representation of a failure. def single_character_display SINGLE_CHARACTER end def label LABEL end # Returns a brief version of the error description. def short_display "#@test_name: #{@message.split("\n")[0]}" end # Returns a verbose version of the error description. def long_display if location.size == 1 location_display = location[0].sub(/\A(.+:\d+).*/, ' [\\1]') else location_display = "\n [#{location.join("\n ")}]" end "#{label}:\n#@test_name#{location_display}:\n#@message" end # Overridden to return long_display. def to_s long_display end def critical? true end def diff @diff ||= compute_diff end private def compute_diff Assertions::AssertionMessage.delayed_diff(@expected, @actual).inspect end end module FailureHandler class << self def included(base) base.exception_handler(:handle_assertion_failed_error) end end # Report a failure. # # This is a public API for developers who extend test-unit. # # @param message [String] The description about the failure. # @param backtrace [Array] The backtrace for the failure. # @option options [Object] :expected # The expected value of the assertion. # @option options [Object] :actual # The actual value of the assertion. # @option options [String] :inspected_expected # The inspected expected value of the assertion. # It is used for diff between expected and actual of the failure. # @option options [String] :inspected_actual # The inspected actual value of the assertion. # It is used for diff between expected and actual of the failure. # @option options [String] :user_message # The message of the assertion from user. # @option options [String] :method_name (@method_name) # The method name of the test. # @option options [Array] :source_location # The location where the test is defined. It is the same # format as Proc#source_location. That is, it's an array of # path and and line number where the test definition is # started. # @return [void] def add_failure(message, backtrace, options={}) default_options = { :method_name => @method_name, :source_location => self[:source_location], } failure = Failure.new(name, filter_backtrace(backtrace), message, default_options.merge(options)) current_result.add_failure(failure) end private def handle_assertion_failed_error(exception) return false unless exception.is_a?(AssertionFailedError) problem_occurred add_failure(exception.message, exception.backtrace, :expected => exception.expected, :actual => exception.actual, :inspected_expected => exception.inspected_expected, :inspected_actual => exception.inspected_actual, :user_message => exception.user_message) true end end module TestResultFailureSupport attr_reader :failures # Records a Test::Unit::Failure. def add_failure(failure) @failures << failure notify_fault(failure) notify_changed end # Returns the number of failures this TestResult has # recorded. def failure_count @failures.size end def failure_occurred? not @failures.empty? end private def initialize_containers super @failures = [] @summary_generators << :failure_summary @problem_checkers << :failure_occurred? end def failure_summary "#{failure_count} failures" end end end end PK% ]xZZ9gems/test-unit-3.2.9/lib/test/unit/ui/emacs/testrunner.rbnu[require 'test/unit/ui/console/testrunner' module Test module Unit module UI module Emacs class TestRunner < Console::TestRunner private def output_setup_end end def output_started end def format_fault(fault) return super unless fault.respond_to?(:label) format_method_name = "format_fault_#{fault.label.downcase}" if respond_to?(format_method_name, true) __send__(format_method_name, fault) else super end end def format_fault_failure(failure) if failure.location.size == 1 location = failure.location[0] location_display = location.sub(/\A(.+:\d+).*/, ' [\\1]') else location_display = "\n" + failure.location.join("\n") end result = "#{failure.label}:\n" result += "#{failure.test_name}#{location_display}:\n" result += failure.message result end def format_fault_error(error) result = "#{error.label}:\n" result += "#{error.test_name}:\n" result += "#{error.message}\n" result += error.backtrace.join("\n") result end end end end end end PK% ]u$$<gems/test-unit-3.2.9/lib/test/unit/ui/testrunnerutilities.rbnu[#-- # # Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. module Test module Unit module UI # Provides some utilities common to most, if not all, # TestRunners. # #-- # # Perhaps there ought to be a TestRunner superclass? There # seems to be a decent amount of shared code between test # runners. module TestRunnerUtilities # Creates a new TestRunner and runs the suite. def run(suite, options={}) return new(suite, options).start end # Takes care of the ARGV parsing and suite # determination necessary for running one of the # TestRunners from the command line. def start_command_line_test if ARGV.empty? puts "You should supply the name of a test suite file to the runner" exit end require ARGV[0].gsub(/.+::/, '') new(eval(ARGV[0])).start end end end end end PK% ]d7gems/test-unit-3.2.9/lib/test/unit/ui/xml/testrunner.rbnu[#-- # # Author:: Kouhei Sutou # Copyright:: # * Copyright (c) 2011 Kouhei Sutou # License:: Ruby license. require 'erb' require 'time' require 'test/unit/ui/testrunner' require 'test/unit/ui/testrunnermediator' module Test module Unit module UI module XML # Runs a Test::Unit::TestSuite and outputs XML. class TestRunner < UI::TestRunner include ERB::Util # Creates a new TestRunner for running the passed # suite. :output option specifies where runner # output should go to; defaults to STDOUT. def initialize(suite, options={}) super @output = @options[:output] || STDOUT if @options[:output_file_descriptor] @output = IO.new(@options[:output_file_descriptor], "w") end @already_outputted = false @indent = 0 @top_level = true @current_test = nil @current_test_suite = nil @already_outputted = false end private def attach_to_mediator @mediator.add_listener(TestResult::PASS_ASSERTION, &method(:result_pass_assertion)) @mediator.add_listener(TestResult::FAULT, &method(:result_fault)) @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started)) @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished)) @mediator.add_listener(TestCase::STARTED_OBJECT, &method(:test_started)) @mediator.add_listener(TestCase::FINISHED_OBJECT, &method(:test_finished)) @mediator.add_listener(TestSuite::STARTED_OBJECT, &method(:test_suite_started)) @mediator.add_listener(TestSuite::FINISHED_OBJECT, &method(:test_suite_finished)) end def result_pass_assertion(result) open_tag("pass-assertion") do output_test(@current_test) end end def result_fault(fault) open_tag("test-result") do open_tag("result") do output_test_suite(@current_test_suite) output_test(@current_test) open_tag("backtrace") do fault.location.each do |entry| file, line, info = entry.split(/:/, 3) open_tag("entry") do add_content("file", file) add_content("line", line) add_content("info", info) end end end if fault.respond_to?(:expected) add_content("expected", fault.expected) end if fault.respond_to?(:actual) add_content("actual", fault.actual) end add_content("detail", fault.message) add_content("status", fault.label.downcase) end end @already_outputted = true if fault.critical? end def started(result) @result = result output_started end def output_started open_tag("stream") end def finished(elapsed_time) add_content("success", @result.passed?) close_tag("stream") end def test_started(test) @already_outputted = false @current_test = test open_tag("start-test") do output_test(test) end end def test_finished(test) unless @already_outputted open_tag("test-result") do output_test(test) open_tag("result") do output_test_suite(@current_test_suite) output_test(test) add_content("status", "success") end end end open_tag("complete-test") do output_test(test) add_content("success", test.passed?) end @current_test = nil end def test_suite_started(suite) @current_test_suite = suite if suite.test_case.nil? open_tag("ready-test-suite") do add_content("n-tests", suite.size) end open_tag("start-test-suite") do output_test_suite(suite) end else open_tag("ready-test-case") do output_test_suite(suite) add_content("n-tests", suite.size) end open_tag("start-test-case") do output_test_suite(suite) end end end def test_suite_finished(suite) if suite.test_case.nil? open_tag("complete-test-suite") do output_test_suite(suite) add_content("success", suite.passed?) end else open_tag("complete-test-case") do output_test_suite(suite) add_content("success", suite.passed?) end end @current_test_suite = nil end def indent " " * @indent end def open_tag(name) @output.puts("#{indent}<#{name}>") @indent += 2 if block_given? yield close_tag(name) end end def add_content(name, content) return if content.nil? case content when Time content = content.iso8601 end @output.puts("#{indent}<#{name}>#{h(content)}") end def close_tag(name) @indent -= 2 @output.puts("#{indent}") end def output_test(test) open_tag("test") do add_content("name", test.method_name) add_content("start-time", test.start_time) add_content("elapsed", test.elapsed_time) end end def output_test_suite(test_suite) test_case = test_suite.test_case if test_case.nil? open_tag("test-suite") do add_content("name", test_suite.name) add_content("start-time", test_suite.start_time) add_content("elapsed", test_suite.elapsed_time) end else open_tag("test-case") do add_content("name", test_suite.name) add_content("start-time", test_suite.start_time) add_content("elapsed", test_suite.elapsed_time) end end end end end end end end PK% ]l~<gems/test-unit-3.2.9/lib/test/unit/ui/console/outputlevel.rbnu[module Test module Unit module UI module Console module OutputLevel SILENT = 0 PROGRESS_ONLY = 1 IMPORTANT_FAULTS_ONLY = 2 NORMAL = 3 VERBOSE = 4 end end end end end PK% ]!=(__;gems/test-unit-3.2.9/lib/test/unit/ui/console/testrunner.rbnu[#-- # # Author:: Nathaniel Talbott. # Copyright:: # * Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. # * Copyright (c) 2008-2017 Kouhei Sutou # License:: Ruby license. begin require 'io/console' rescue LoadError end require 'test/unit/color-scheme' require 'test/unit/code-snippet-fetcher' require 'test/unit/fault-location-detector' require 'test/unit/diff' require 'test/unit/ui/testrunner' require 'test/unit/ui/testrunnermediator' require 'test/unit/ui/console/outputlevel' module Test module Unit module UI module Console # Runs a Test::Unit::TestSuite on the console. class TestRunner < UI::TestRunner include OutputLevel # Creates a new TestRunner for running the passed # suite. If quiet_mode is true, the output while # running is limited to progress dots, errors and # failures, and the final result. io specifies # where runner output should go to; defaults to # STDOUT. def initialize(suite, options={}) super @output_level = @options[:output_level] || NORMAL @output = @options[:output] || STDOUT @use_color = @options[:use_color] @use_color = guess_color_availability if @use_color.nil? @color_scheme = @options[:color_scheme] || ColorScheme.default @reset_color = Color.new("reset") @progress_row = 0 @progress_row_max = @options[:progress_row_max] @progress_row_max ||= guess_progress_row_max @show_detail_immediately = @options[:show_detail_immediately] @show_detail_immediately = true if @show_detail_immediately.nil? @reverse_output = @options[:reverse_output] @reverse_output = @output.tty? if @reverse_output.nil? @already_outputted = false @indent = 0 @top_level = true @current_output_level = NORMAL @faults = [] @code_snippet_fetcher = CodeSnippetFetcher.new @test_suites = [] end private def change_output_level(level) old_output_level = @current_output_level @current_output_level = level yield @current_output_level = old_output_level end def setup_mediator super output_setup_end end def output_setup_end suite_name = @suite.to_s suite_name = @suite.name if @suite.kind_of?(Module) output("Loaded suite #{suite_name}") end def attach_to_mediator @mediator.add_listener(TestResult::FAULT, &method(:add_fault)) @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started)) @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished)) @mediator.add_listener(TestCase::STARTED_OBJECT, &method(:test_started)) @mediator.add_listener(TestCase::FINISHED_OBJECT, &method(:test_finished)) @mediator.add_listener(TestSuite::STARTED_OBJECT, &method(:test_suite_started)) @mediator.add_listener(TestSuite::FINISHED_OBJECT, &method(:test_suite_finished)) end def add_fault(fault) @faults << fault output_progress(fault.single_character_display, fault_marker_color(fault)) output_progress_in_detail(fault) if @show_detail_immediately @already_outputted = true if fault.critical? end def started(result) @result = result output_started end def output_started output("Started") end def finished(elapsed_time) unless @show_detail_immediately nl if output?(NORMAL) and !output?(VERBOSE) output_faults end nl(PROGRESS_ONLY) change_output_level(IMPORTANT_FAULTS_ONLY) do output_statistics(elapsed_time) end end def output_faults categorized_faults = categorize_faults change_output_level(IMPORTANT_FAULTS_ONLY) do output_faults_in_detail(categorized_faults[:need_detail_faults]) end output_faults_in_short("Omissions", Omission, categorized_faults[:omissions]) output_faults_in_short("Notifications", Notification, categorized_faults[:notifications]) end def max_digit(max_number) (Math.log10(max_number) + 1).truncate end def output_faults_in_detail(faults) return if faults.nil? digit = max_digit(faults.size) faults.each_with_index do |fault, index| nl output_single("%#{digit}d) " % (index + 1)) output_fault_in_detail(fault) end end def output_faults_in_short(label, fault_class, faults) return if faults.nil? digit = max_digit(faults.size) nl output_single(label, fault_class_color(fault_class)) output(":") faults.each_with_index do |fault, index| output_single("%#{digit}d) " % (index + 1)) output_fault_in_short(fault) end end def categorize_faults faults = {} @faults.each do |fault| category = categorize_fault(fault) faults[category] ||= [] faults[category] << fault end faults end def categorize_fault(fault) case fault when Omission :omissions when Notification :notifications else :need_detail_faults end end def output_fault_in_detail(fault) if fault.is_a?(Failure) and fault.inspected_expected and fault.inspected_actual if @reverse_output output_fault_backtrace(fault) output_failure_message(fault) output_single("#{fault.label}: ") output(fault.test_name, fault_color(fault)) else output_single("#{fault.label}: ") output(fault.test_name, fault_color(fault)) output_fault_backtrace(fault) output_failure_message(fault) end else if @reverse_output output_fault_backtrace(fault) output_single("#{fault.label}: ") output_single(fault.test_name, fault_color(fault)) output_fault_message(fault) else output_single("#{fault.label}: ") output_single(fault.test_name, fault_color(fault)) output_fault_message(fault) output_fault_backtrace(fault) end end end def output_fault_message(fault) message = fault.message return if message.nil? if message.include?("\n") output(":") message.each_line do |line| output(" #{line.chomp}") end else output(": #{message}") end end def output_fault_backtrace(fault) detector = FaultLocationDetector.new(fault, @code_snippet_fetcher) backtrace = fault.location # workaround for test-spec. :< # see also GitHub:#22 backtrace ||= [] code_snippet_backtrace_index = nil code_snippet_lines = nil backtrace.each_with_index do |entry, i| next unless detector.target?(entry) file, line_number, = detector.split_backtrace_entry(entry) lines = fetch_code_snippet(file, line_number) unless lines.empty? code_snippet_backtrace_index = i code_snippet_lines = lines break end end if @reverse_output backtrace.each_with_index.reverse_each do |entry, i| if i == code_snippet_backtrace_index output_code_snippet(code_snippet_lines, fault_color(fault)) end output(entry) end else backtrace.each_with_index do |entry, i| output(entry) if i == code_snippet_backtrace_index output_code_snippet(code_snippet_lines, fault_color(fault)) end end end end def fetch_code_snippet(file, line_number) @code_snippet_fetcher.fetch(file, line_number) end def output_code_snippet(lines, target_line_color=nil) max_n = lines.collect {|n, line, attributes| n}.max digits = (Math.log10(max_n) + 1).truncate lines.each do |n, line, attributes| if attributes[:target_line?] line_color = target_line_color current_line_mark = "=>" else line_color = nil current_line_mark = "" end output(" %2s %*d: %s" % [current_line_mark, digits, n, line], line_color) end end def output_failure_message(failure) if failure.expected.respond_to?(:encoding) and failure.actual.respond_to?(:encoding) and failure.expected.encoding != failure.actual.encoding need_encoding = true else need_encoding = false end output(failure.user_message) if failure.user_message output_single("<") output_single(failure.inspected_expected, color("pass")) output_single(">") if need_encoding output_single("(") output_single(failure.expected.encoding.name, color("pass")) output_single(")") end output(" expected but was") output_single("<") output_single(failure.inspected_actual, color("failure")) output_single(">") if need_encoding output_single("(") output_single(failure.actual.encoding.name, color("failure")) output_single(")") end output("") from, to = prepare_for_diff(failure.expected, failure.actual) if from and to if need_encoding unless from.valid_encoding? from = from.dup.force_encoding("ASCII-8BIT") end unless to.valid_encoding? to = to.dup.force_encoding("ASCII-8BIT") end end from_lines = from.split(/\r?\n/) to_lines = to.split(/\r?\n/) if need_encoding from_lines << "" to_lines << "" from_lines << "Encoding: #{failure.expected.encoding.name}" to_lines << "Encoding: #{failure.actual.encoding.name}" end differ = ColorizedReadableDiffer.new(from_lines, to_lines, self) if differ.need_diff? output("") output("diff:") differ.diff end end end def output_fault_in_short(fault) if @reverse_output output(fault.location.first) output_single("#{fault.label}: ") output_single(fault.message, fault_color(fault)) output(" [#{fault.test_name}]") else output_single("#{fault.label}: ") output_single(fault.message, fault_color(fault)) output(" [#{fault.test_name}]") output(fault.location.first) end end def format_fault(fault) fault.long_display end def output_statistics(elapsed_time) output("Finished in #{elapsed_time} seconds.") output_summary_marker output(@result) output("%g%% passed" % @result.pass_percentage) unless elapsed_time.zero? output_summary_marker test_throughput = @result.run_count / elapsed_time assertion_throughput = @result.assertion_count / elapsed_time throughput = [ "%.2f tests/s" % test_throughput, "%.2f assertions/s" % assertion_throughput, ] output(throughput.join(", ")) end end def output_summary_marker if @progress_row_max > 0 output("-" * @progress_row_max, summary_marker_color) else nl end end def test_started(test) return unless output?(VERBOSE) tab_width = 8 name = test.local_name separator = ":" left_used = indent.size + name.size + separator.size right_space = tab_width * 2 left_space = @progress_row_max - right_space if (left_used % tab_width).zero? left_space -= left_used n_tabs = 0 else left_space -= ((left_used / tab_width) + 1) * tab_width n_tabs = 1 end n_tabs += [left_space, 0].max / tab_width tab_stop = "\t" * n_tabs output_single("#{indent}#{name}#{separator}#{tab_stop}", nil, VERBOSE) @test_start = Time.now end def test_finished(test) unless @already_outputted output_progress(".", color("pass-marker")) end @already_outputted = false return unless output?(VERBOSE) output(": (%f)" % (Time.now - @test_start), nil, VERBOSE) end def suite_name(prefix, suite) name = suite.name if name.nil? "(anonymous)" else name.sub(/\A#{Regexp.escape(prefix)}/, "") end end def test_suite_started(suite) last_test_suite = @test_suites.last @test_suites << suite if @top_level @top_level = false return end output_single(indent, nil, VERBOSE) if suite.test_case.nil? _color = color("suite") else _color = color("case") end prefix = "#{last_test_suite.name}::" output_single(suite_name(prefix, suite), _color, VERBOSE) output(": ", nil, VERBOSE) @indent += 2 end def test_suite_finished(suite) @indent -= 2 @test_suites.pop end def indent if output?(VERBOSE) " " * @indent else "" end end def nl(level=nil) output("", nil, level) end def output(something, color=nil, level=nil) return unless output?(level) output_single(something, color, level) @output.puts end def output_single(something, color=nil, level=nil) return false unless output?(level) if @use_color and color something = "%s%s%s" % [color.escape_sequence, something, @reset_color.escape_sequence] end @output.write(something) @output.flush true end def output_progress(mark, color=nil) if output_single(mark, color, PROGRESS_ONLY) return unless @progress_row_max > 0 @progress_row += mark.size if @progress_row >= @progress_row_max nl unless @output_level == VERBOSE @progress_row = 0 end end end def output_progress_in_detail_marker(fault) if @progress_row_max > 0 output("=" * @progress_row_max) else nl end end def output_progress_in_detail(fault) return if @output_level == SILENT nl output_progress_in_detail_marker(fault) if categorize_fault(fault) == :need_detail_faults output_fault_in_detail(fault) else output_fault_in_short(fault) end output_progress_in_detail_marker(fault) @progress_row = 0 end def output?(level) (level || @current_output_level) <= @output_level end def color(name) _color = @color_scheme[name] _color ||= @color_scheme["success"] if name == "pass" _color ||= ColorScheme.default[name] _color end def fault_class_color_name(fault_class) fault_class.name.split(/::/).last.downcase end def fault_class_color(fault_class) color(fault_class_color_name(fault_class)) end def fault_color(fault) fault_class_color(fault.class) end def fault_marker_color(fault) color("#{fault_class_color_name(fault.class)}-marker") end def summary_marker_color color("#{@result.status}-marker") end def guess_color_availability return false unless @output.tty? return true if windows? and ruby_2_0_or_later? case ENV["TERM"] when /(?:term|screen)(?:-(?:256)?color)?\z/ true when /\Arxvt/ true else return true if ENV["EMACS"] == "t" false end end def windows? /mswin|mingw/ === RUBY_PLATFORM end def ruby_2_0_or_later? RUBY_VERSION >= "2.0.0" end def guess_progress_row_max term_width = guess_term_width if term_width.zero? if ENV["EMACS"] == "t" -1 else 79 end else term_width end end def guess_term_width guess_term_width_from_io || guess_term_width_from_env || 0 end def guess_term_width_from_io if @output.respond_to?(:winsize) begin @output.winsize[1] rescue SystemCallError nil end else nil end end def guess_term_width_from_env env = ENV["COLUMNS"] || ENV["TERM_WIDTH"] return nil if env.nil? begin Integer(env) rescue ArgumentError nil end end end class ColorizedReadableDiffer < Diff::ReadableDiffer def initialize(from, to, runner) @runner = runner super(from, to) end def need_diff?(options={}) return false if one_line_all_change? operations.each do |tag,| return true if [:replace, :equal].include?(tag) end false end private def one_line_all_change? return false if operations.size != 1 tag, from_start, from_end, to_start, to_end = operations.first return false if tag != :replace return false if [from_start, from_end] != [0, 1] return false if [from_start, from_end] != [to_start, to_end] _, _, _line_operations = line_operations(@from.first, @to.first) _line_operations.size == 1 end def output_single(something, color=nil) @runner.__send__(:output_single, something, color) end def output(something, color=nil) @runner.__send__(:output, something, color) end def color(name) @runner.__send__(:color, name) end def cut_off_ratio 0 end def default_ratio 0 end def tag(mark, color_name, contents) _color = color(color_name) contents.each do |content| output_single(mark, _color) output_single(" ") output(content) end end def tag_deleted(contents) tag("-", "diff-deleted-tag", contents) end def tag_inserted(contents) tag("+", "diff-inserted-tag", contents) end def tag_equal(contents) tag(" ", "normal", contents) end def tag_difference(contents) tag("?", "diff-difference-tag", contents) end def diff_line(from_line, to_line) to_operations = [] from_line, to_line, _operations = line_operations(from_line, to_line) no_replace = true _operations.each do |tag,| if tag == :replace no_replace = false break end end output_single("?", color("diff-difference-tag")) output_single(" ") _operations.each do |tag, from_start, from_end, to_start, to_end| from_width = compute_width(from_line, from_start, from_end) to_width = compute_width(to_line, to_start, to_end) case tag when :replace output_single(from_line[from_start...from_end], color("diff-deleted")) if (from_width < to_width) output_single(" " * (to_width - from_width)) end to_operations << Proc.new do output_single(to_line[to_start...to_end], color("diff-inserted")) if (to_width < from_width) output_single(" " * (from_width - to_width)) end end when :delete output_single(from_line[from_start...from_end], color("diff-deleted")) unless no_replace to_operations << Proc.new {output_single(" " * from_width)} end when :insert if no_replace output_single(to_line[to_start...to_end], color("diff-inserted")) else output_single(" " * to_width) to_operations << Proc.new do output_single(to_line[to_start...to_end], color("diff-inserted")) end end when :equal output_single(from_line[from_start...from_end]) unless no_replace to_operations << Proc.new {output_single(" " * to_width)} end else raise "unknown tag: #{tag}" end end output("") unless to_operations.empty? output_single("?", color("diff-difference-tag")) output_single(" ") to_operations.each do |operation| operation.call end output("") end end end end end end end PK% ]޸3gems/test-unit-3.2.9/lib/test/unit/ui/testrunner.rbnu[require 'test/unit/ui/testrunnerutilities' module Test module Unit module UI class TestRunner extend TestRunnerUtilities attr_reader :listeners def initialize(suite, options={}) if suite.respond_to?(:suite) @suite = suite.suite else @suite = suite end @options = options @listeners = @options[:listeners] || [] end # Begins the test run. def start setup_mediator attach_to_mediator attach_listeners start_mediator end private def setup_mediator @mediator = TestRunnerMediator.new(@suite) end def attach_listeners @listeners.each do |listener| listener.attach_to_mediator(@mediator) end end def start_mediator @mediator.run end def diff_target_string?(string) Assertions::AssertionMessage.diff_target_string?(string) end def prepare_for_diff(from, to) Assertions::AssertionMessage.prepare_for_diff(from, to) end end end end end PK% ]N N ;gems/test-unit-3.2.9/lib/test/unit/ui/testrunnermediator.rbnu[#-- # # Author:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. # License:: Ruby license. require 'test/unit/util/observable' require 'test/unit/testresult' module Test module Unit module UI # Provides an interface to write any given UI against, # hopefully making it easy to write new UIs. class TestRunnerMediator RESET = name + "::RESET" STARTED = name + "::STARTED" FINISHED = name + "::FINISHED" include Util::Observable # Creates a new TestRunnerMediator initialized to run # the passed suite. def initialize(suite) @suite = suite end # Runs the suite the TestRunnerMediator was created # with. def run AutoRunner.need_auto_run = false result = create_result Test::Unit.run_at_start_hooks start_time = Time.now begin catch do |stop_tag| result.stop_tag = stop_tag with_listener(result) do notify_listeners(RESET, @suite.size) notify_listeners(STARTED, result) run_suite(result) end end ensure elapsed_time = Time.now - start_time notify_listeners(FINISHED, elapsed_time) end Test::Unit.run_at_exit_hooks result end # Just for backward compatibility for NetBeans. # NetBeans should not use monkey patching. NetBeans # should use runner change public API. # # See GitHub#38 # https://github.com/test-unit/test-unit/issues/38 def run_suite(result=nil) if result.nil? run else @suite.run(result) do |channel, value| notify_listeners(channel, value) end end end private # A factory method to create the result the mediator # should run with. Can be overridden by subclasses if # one wants to use a different result. def create_result TestResult.new end def measure_time begin_time = Time.now yield Time.now - begin_time end def with_listener(result) finished_listener = result.add_listener(TestResult::FINISHED) do |*args| notify_listeners(TestResult::FINISHED, *args) end changed_listener = result.add_listener(TestResult::CHANGED) do |*args| notify_listeners(TestResult::CHANGED, *args) end pass_assertion_listener = result.add_listener(TestResult::PASS_ASSERTION) do |*args| notify_listeners(TestResult::PASS_ASSERTION, *args) end fault_listener = result.add_listener(TestResult::FAULT) do |*args| notify_listeners(TestResult::FAULT, *args) end begin yield ensure result.remove_listener(TestResult::FAULT, fault_listener) result.remove_listener(TestResult::CHANGED, changed_listener) result.remove_listener(TestResult::FINISHED, finished_listener) result.remove_listener(TestResult::PASS_ASSERTION, pass_assertion_listener) end end end end end end PK% ]KE::/gems/test-unit-3.2.9/lib/test/unit/collector.rbnu[module Test module Unit module Collector def initialize @filters = [] end def filter=(filters) @filters = case(filters) when Proc [filters] when Array filters end end def add_suite(destination, suite) to_delete = suite.tests.find_all do |test| test.is_a?(TestCase) and !include?(test) end suite.delete_tests(to_delete) destination << suite unless suite.empty? end def add_test_cases(suite, test_cases) children_map = {} test_cases.each do |test_case| ancestor_classes = test_case.ancestors.find_all do |ancestor| ancestor.is_a?(Class) end parent = ancestor_classes[1] children_map[parent] ||= [] children_map[parent] << test_case end root_test_cases = children_map.keys - test_cases root_test_cases.each do |root_test_case| add_test_case(suite, root_test_case, children_map) end end def include?(test) return true if(@filters.empty?) @filters.each do |filter| return false if filter[test] == false end true end def sort(suites) suites.sort_by do |suite| [suite.priority, suite.name || suite.to_s] end end private def add_test_case(suite, test_case, children_map) children = children_map[test_case] return if children.nil? sub_suites = [] children.each do |child| sub_suite = child.suite add_test_case(sub_suite, child, children_map) add_suite(sub_suites, sub_suite) end sort(sub_suites).each do |sub_suite| suite << sub_suite end end end end end PK% ]Vݯ7gems/test-unit-3.2.9/lib/test/unit/attribute-matcher.rbnu[module Test module Unit class AttributeMatcher def initialize(test) @test = test end def match?(expression) matched = instance_eval(expression) if matched.nil? false else matched end end def method_missing(name, *args) if args.empty? @test[name] else super end end end end end PK% ]kO?O?%gems/test-unit-3.2.9/lib/test/unit.rbnu[require 'test/unit/testcase' require 'test/unit/autorunner' module Test # :nodoc: # # = Test::Unit - Ruby Unit Testing Framework # # == Introduction # # Unit testing is making waves all over the place, largely due to the # fact that it is a core practice of XP. While XP is great, unit testing # has been around for a long time and has always been a good idea. One # of the keys to good unit testing, though, is not just writing tests, # but having tests. What's the difference? Well, if you just _write_ a # test and throw it away, you have no guarantee that something won't # change later which breaks your code. If, on the other hand, you _have_ # tests (obviously you have to write them first), and run them as often # as possible, you slowly build up a wall of things that cannot break # without you immediately knowing about it. This is when unit testing # hits its peak usefulness. # # Enter Test::Unit, a framework for unit testing in Ruby, helping you to # design, debug and evaluate your code by making it easy to write and # have tests for it. # # # == Notes # # Test::Unit has grown out of and superceded Lapidary. # # # == Feedback # # I like (and do my best to practice) XP, so I value early releases, # user feedback, and clean, simple, expressive code. There is always # room for improvement in everything I do, and Test::Unit is no # exception. Please, let me know what you think of Test::Unit as it # stands, and what you'd like to see expanded/changed/improved/etc. If # you find a bug, let me know ASAP; one good way to let me know what the # bug is is to submit a new test that catches it :-) Also, I'd love to # hear about any successes you have with Test::Unit, and any # documentation you might add will be greatly appreciated. My contact # info is below. # # # == Contact Information # # A lot of discussion happens about Ruby in general on the ruby-talk # mailing list (http://www.ruby-lang.org/en/ml.html), and you can ask # any questions you might have there. I monitor the list, as do many # other helpful Rubyists, and you're sure to get a quick answer. Of # course, you're also welcome to email me (Nathaniel Talbott) directly # at mailto:testunit@talbott.ws, and I'll do my best to help you out. # # # == Credits # # I'd like to thank... # # Matz, for a great language! # # Masaki Suketa, for his work on RubyUnit, which filled a vital need in # the Ruby world for a very long time. I'm also grateful for his help in # polishing Test::Unit and getting the RubyUnit compatibility layer # right. His graciousness in allowing Test::Unit to supercede RubyUnit # continues to be a challenge to me to be more willing to defer my own # rights. # # Ken McKinlay, for his interest and work on unit testing, and for his # willingness to dialog about it. He was also a great help in pointing # out some of the holes in the RubyUnit compatibility layer. # # Dave Thomas, for the original idea that led to the extremely simple # "require 'test/unit'", plus his code to improve it even more by # allowing the selection of tests from the command-line. Also, without # RDoc, the documentation for Test::Unit would stink a lot more than it # does now. # # Everyone who's helped out with bug reports, feature ideas, # encouragement to continue, etc. It's a real privilege to be a part of # the Ruby community. # # The guys at RoleModel Software, for putting up with me repeating, "But # this would be so much easier in Ruby!" whenever we're coding in Java. # # My Creator, for giving me life, and giving it more abundantly. # # # == License # # Test::Unit is copyright (c) 2000-2003 Nathaniel Talbott. It is free # software, and is distributed under the Ruby license. See the COPYING # file. # # Exception: lib/test/unit/diff.rb is copyright (c) # 2008-2010 Kouhei Sutou and 2001-2008 Python Software # Foundation. It is free software, and is distributed # under the Ruby license and/or the PSF license. See the # COPYING file and PSFL file. # # == Warranty # # This software is provided "as is" and without any express or # implied warranties, including, without limitation, the implied # warranties of merchantibility and fitness for a particular # purpose. # # # == Author # # Nathaniel Talbott. # Copyright (c) 2000-2003, Nathaniel Talbott # # ---- # # = Usage # # The general idea behind unit testing is that you write a _test_ # _method_ that makes certain _assertions_ about your code, working # against a _test_ _fixture_. A bunch of these _test_ _methods_ are # bundled up into a _test_ _suite_ and can be run any time the # developer wants. The results of a run are gathered in a _test_ # _result_ and displayed to the user through some UI. So, lets break # this down and see how Test::Unit provides each of these necessary # pieces. # # # == Assertions # # These are the heart of the framework. Think of an assertion as a # statement of expected outcome, i.e. "I assert that x should be equal # to y". If, when the assertion is executed, it turns out to be # correct, nothing happens, and life is good. If, on the other hand, # your assertion turns out to be false, an error is propagated with # pertinent information so that you can go back and make your # assertion succeed, and, once again, life is good. For an explanation # of the current assertions, see Test::Unit::Assertions. # # # == Test Method & Test Fixture # # Obviously, these assertions have to be called within a context that # knows about them and can do something meaningful with their # pass/fail value. Also, it's handy to collect a bunch of related # tests, each test represented by a method, into a common test class # that knows how to run them. The tests will be in a separate class # from the code they're testing for a couple of reasons. First of all, # it allows your code to stay uncluttered with test code, making it # easier to maintain. Second, it allows the tests to be stripped out # for deployment, since they're really there for you, the developer, # and your users don't need them. Third, and most importantly, it # allows you to set up a common test fixture for your tests to run # against. # # What's a test fixture? Well, tests do not live in a vacuum; rather, # they're run against the code they are testing. Often, a collection # of tests will run against a common set of data, also called a # fixture. If they're all bundled into the same test class, they can # all share the setting up and tearing down of that data, eliminating # unnecessary duplication and making it much easier to add related # tests. # # Test::Unit::TestCase wraps up a collection of test methods together # and allows you to easily set up and tear down the same test fixture # for each test. This is done by overriding #setup and/or #teardown, # which will be called before and after each test method that is # run. The TestCase also knows how to collect the results of your # assertions into a Test::Unit::TestResult, which can then be reported # back to you... but I'm getting ahead of myself. To write a test, # follow these steps: # # * Make sure Test::Unit is in your library path. # * require 'test/unit' in your test script. # * Create a class that subclasses Test::Unit::TestCase. # * Add a method that begins with "test" to your class. # * Make assertions in your test method. # * Optionally define #setup and/or #teardown to set up and/or tear # down your common test fixture. # * You can now run your test as you would any other Ruby # script... try it and see! # # A really simple test might look like this (#setup and #teardown are # commented out to indicate that they are completely optional): # # require 'test/unit' # # class MyTest < Test::Unit::TestCase # # def setup # # end # # # def teardown # # end # # def test_fail # assert(false, 'Assertion was false.') # end # end # # # == Test Runners # # So, now you have this great test class, but you still # need a way to run it and view any failures that occur # during the run. There are some test runner; console test # runner, GTK+ test runner and so on. The console test # runner is automatically invoked for you if you require # 'test/unit' and simply run the file. To use another # runner simply set default test runner ID to # Test::Unit::AutoRunner: # # require 'test/unit' # Test::Unit::AutoRunner.default_runner = "gtk2" # # == Test Suite # # As more and more unit tests accumulate for a given project, it # becomes a real drag running them one at a time, and it also # introduces the potential to overlook a failing test because you # forget to run it. Suddenly it becomes very handy that the # TestRunners can take any object that returns a Test::Unit::TestSuite # in response to a suite method. The TestSuite can, in turn, contain # other TestSuites or individual tests (typically created by a # TestCase). In other words, you can easily wrap up a group of # TestCases and TestSuites. # # Test::Unit does a little bit more for you, by wrapping # these up automatically when you require # 'test/unit'. What does this mean? It means you could # write the above test case like this instead: # # require 'test/unit' # require 'test_myfirsttests' # require 'test_moretestsbyme' # require 'test_anothersetoftests' # # Test::Unit is smart enough to find all the test cases existing in # the ObjectSpace and wrap them up into a suite for you. It then runs # the dynamic suite using the console TestRunner. # # # == Configuration file # # Test::Unit reads 'test-unit.yml' in the current working # directory as Test::Unit's configuration file. It can # contain the following configurations: # # * color scheme definitions # * test runner to be used # * test runner options # * test collector to be used # # Except color scheme definitions, all of them are # specified by command line option. # # Here are sample color scheme definitions: # # color_schemes: # inverted: # success: # name: red # bold: true # failure: # name: green # bold: true # other_scheme: # ... # # Here are the syntax of color scheme definitions: # # color_schemes: # SCHEME_NAME: # EVENT_NAME: # name: COLOR_NAME # intensity: BOOLEAN # bold: BOOLEAN # italic: BOOLEAN # underline: BOOLEAN # ... # ... # # SCHEME_NAME:: the name of the color scheme # EVENT_NAME:: one of [success, failure, pending, # omission, notification, error] # COLOR_NAME:: one of [black, red, green, yellow, blue, # magenta, cyan, white] # BOOLEAN:: true or false # # You can use the above 'inverted' color scheme with the # following configuration: # # runner: console # console_options: # color_scheme: inverted # color_schemes: # inverted: # success: # name: red # bold: true # failure: # name: green # bold: true # # == Questions? # # I'd really like to get feedback from all levels of Ruby # practitioners about typos, grammatical errors, unclear statements, # missing points, etc., in this document (or any other). # module Unit class << self # Set true when Test::Unit has run. If set to true Test::Unit # will not automatically run at exit. # # @deprecated Use Test::Unit::AutoRunner.need_auto_run= instead. def run=(have_run) AutoRunner.need_auto_run = (not have_run) end # Already tests have run? # # @deprecated Use Test::Unit::AutoRunner.need_auto_run? instead. def run? not AutoRunner.need_auto_run? end # @api private @@at_start_hooks = [] # Regsiter a hook that is run before running tests. # To register multiple hooks, call this method multiple times. # # Here is an example test case: # Test::Unit.at_start do # # ... # end # # class TestMyClass1 < Test::Unit::TestCase # class << self # def startup # # ... # end # end # # def setup # # ... # end # # def test_my_class1 # # ... # end # # def test_my_class2 # # ... # end # end # # class TestMyClass2 < Test::Unit::TestCase # class << self # def startup # # ... # end # end # # def setup # # ... # end # # def test_my_class1 # # ... # end # # def test_my_class2 # # ... # end # end # # Here is a call order: # * at_start # * TestMyClass1.startup # * TestMyClass1#setup # * TestMyClass1#test_my_class1 # * TestMyClass1#setup # * TestMyClass1#test_my_class2 # * TestMyClass2#setup # * TestMyClass2#test_my_class1 # * TestMyClass2#setup # * TestMyClass2#test_my_class2 # # @example # Test::Unit.at_start do # puts "Start!" # end # # @yield A block that is run before running tests. # @yieldreturn [void] # @return [void] # # @since 2.5.2 def at_start(&hook) @@at_start_hooks << hook end # @api private def run_at_start_hooks @@at_start_hooks.each do |hook| hook.call end end # @api private @@at_exit_hooks = [] # Regsiter a hook that is run after running tests. # To register multiple hooks, call this method multiple times. # # Here is an example test case: # Test::Unit.at_exit do # # ... # end # # class TestMyClass1 < Test::Unit::TestCase # class << self # def shutdown # # ... # end # end # # def teardown # # ... # end # # def test_my_class1 # # ... # end # # def test_my_class2 # # ... # end # end # # class TestMyClass2 < Test::Unit::TestCase # class << self # def shutdown # # ... # end # end # # def teardown # # ... # end # # def test_my_class1 # # ... # end # # def test_my_class2 # # ... # end # end # # Here is a call order: # * TestMyClass1#test_my_class1 # * TestMyClass1#teardown # * TestMyClass1#test_my_class2 # * TestMyClass1#teardown # * TestMyClass1.shutdown # * TestMyClass2#test_my_class1 # * TestMyClass2#teardown # * TestMyClass2#test_my_class2 # * TestMyClass2#teardown # * TestMyClass2.shutdown # * at_exit # # @example # Test::Unit.at_exit do # puts "Exit!" # end # # @yield A block that is run after running tests. # @yieldreturn [void] # @return [void] # # @since 2.5.2 def at_exit(&hook) @@at_exit_hooks << hook end # @api private def run_at_exit_hooks @@at_exit_hooks.each do |hook| hook.call end end end end end Module.new do at_exit do if $!.nil? and Test::Unit::AutoRunner.need_auto_run? exit Test::Unit::AutoRunner.run end end end PK% ] O%gems/test-unit-3.2.9/lib/test-unit.rbnu[# Copyright (C) 2012-2015 Kouhei Sutou # # License: Ruby's or LGPLv2.1 or later # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 USA module Test module Unit autoload :TestCase, "test/unit/testcase" autoload :AutoRunner, "test/unit/autorunner" end end unless respond_to?(:run_test, true) # experimental. It is for "ruby -rtest-unit -e run_test test/test_*.rb". # Is this API OK or dirty? def run_test self.class.send(:undef_method, :run_test) require "test/unit" end end PK% ]Y44#gems/did_you_mean-1.3.0/LICENSE.txtnu[Copyright (c) 2014-2016 Yuki Nishijima MIT License 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. PK% ]PDD$gems/did_you_mean-1.3.0/CHANGELOG.mdnu[## [v1.2.1](https://github.com/yuki24/did_you_mean/tree/v1.2.1) _released at 2018-04-03 04:44:47 UTC_ #### Bug Fixes - Fixed a bug where DYM suggests the same class name in the error message ([#102](https://github.com/yuki24/did_you_mean/issues/102), [@schneems](https://github.com/schneems)) - Fixed a bug where the deprecated `DidYouMean::Formatter` has been removed unexpectedly ([#103](https://github.com/yuki24/did_you_mean/issues/103), [4b5ba32](https://github.com/yuki24/did_you_mean/commit/4b5ba3215975df1dd8e9c7eacffcf02abfffa92e)) #### Other Changes - Non-production code that has a non-commercial lisence has been removed from gem releases ([#105](https://github.com/yuki24/did_you_mean/issues/105), [@jbotelho2-bb](https://github.com/jbotelho2-bb)) ## [v1.2.0](https://github.com/yuki24/did_you_mean/tree/v1.2.0) _released at 2018-01-02 20:49:35 UTC_ **This version 1.2.0 only has support for Ruby 2.5.0 and later as it uses new features that are only available in 2.5. All future patch releases under 1.2.\* will only be compatible with Ruby 2.5.0 and later as well. Versions earlier than 1.1.\* will still be maintained until Ruby 2.4 is deprecated. Any other versions below 1.0 will no longer be maintained.** #### New features - The `KeyError` name suggestion feature has been promoted to a stable feature and is available by default ([acf5945](https://github.com/yuki24/did_you_mean/commit/acf59450dfb67eefae9b465ccc8029af46ae7dd0), [https://bugs.ruby-lang.org/issues/12063](https://bugs.ruby-lang.org/issues/12063)) - Now suggests `true`, `false` or `nil` if a NameError occurs because of a typo in these names ([#94](https://github.com/yuki24/did_you_mean/pull/94), [@styd](https://github.com/styd)) - New Formatter API: This provides a clean way to customize DidYouMean’s formatter without overriding the default formatter. Please refer to [the built-in verbose formatter](https://github.com/yuki24/did_you_mean/blob/671cdff/lib/did_you_mean/verbose.rb) for how to use it ## [v1.1.2](https://github.com/yuki24/did_you_mean/tree/v1.1.2) _released at 2017-09-24 07:28:48 UTC_ **This version is only compatible with Ruby 2.4 and later.** #### Bug Fixes - Fixed a bug where `did_you_mean` shows duplicate suggestions when the exception is raised multiple times ([#84](https://github.com/yuki24/did_you_mean/pull/84), [c2e4008](https://github.com/yuki24/did_you_mean/commit/c2e40083cef604c00ccd10efc6d7a5036ad9eb5b)) ## [v1.1.1](https://github.com/yuki24/did_you_mean/tree/v1.1.1) _released at 2017-09-24 07:24:02 UTC_ ### This version has been yanked from Rubygems.org and is not available. ## [v1.1.0](https://github.com/yuki24/did_you_mean/tree/v1.1.0) _released at 2016-12-19 23:19:06 UTC_ The version `1.1.0` only has support for Ruby 2.4.0 and later. Also, all patch releases under `1.1.*` will only be compatible with Ruby 2.4.0 and later as well. Versions under `1.0.*` will still be maintained until Ruby 2.3 is deprecated. Any other versions below `1.0` will no longer be maintained. #### New Features - Suggest a method name on a NameError from the `Struct#[]` or `Struct#[]=` method ([#73](https://github.com/yuki24/did_you_mean/pull/73)): ```ruby Struct.new(:foo).new[:fooo] # => NameError: no member 'fooo' in struct # Did you mean? foo # foo= ``` - Added a public interface for the gem's spell checker: ```ruby DidYouMean::SpellChecker.new(dictionary: ['email', 'fail', 'eval']).correct('meail') # => ['email'] ``` - Methods defined on `nil` by default are no longer suggested. Note that methods, defined after the gem is loaded, will still be suggested (e.g. ActiveSupport). #### Bug Fixes - Fixed a bug where private method names were added to the dictionary when an argument was passed in to a public method. Use the `NoMethodError#private_call?` method instead ([0a1b761](https://github.com/yuki24/did_you_mean/commit/0a1b7612252055e583a373b473932f789381ca0f)) ## [v1.0.3](https://github.com/yuki24/did_you_mean/tree/v1.0.3) _released at 2017-09-24 07:22:07 UTC_ **This version is compatible with Ruby 2.3 and older** #### Bug Fixes - Fixed a bug where `did_you_mean` shows duplicate suggestions when the exception is raised multiple times ([#84](https://github.com/yuki24/did_you_mean/pull/84), [c2e4008](https://github.com/yuki24/did_you_mean/commit/c2e40083cef604c00ccd10efc6d7a5036ad9eb5b)) ## [v1.0.2](https://github.com/yuki24/did_you_mean/tree/v1.0.2) _released at 2016-11-20 18:03:07 UTC_ **This version is compatible with Ruby 2.3 and older** #### Features - Experimental features are officially available through `require 'did_you_mean/experimental'` #### Deprecations - `require 'did_you_mean/extra_features'` is now deprecated in favor of `require 'did_you_mean/experimental'` #### Internal Changes - Replaced the `DidYouMean::SpellCheckable` module with the `DidYouMean::SpellChecker` class. This is a slower implementation but close to the model explained in [this talk](https://speakerdeck.com/yuki24/saving-people-from-typos), more reusable and possibly makes it easier to expose the class as a public interface. ## [v1.0.1](https://github.com/yuki24/did_you_mean/tree/v1.0.1) _released at 2016-05-15 05:17:22 UTC_ #### Bug Fixes - Fixed a bug where the gem suggests what is actually typed by the user: [1c52c88](https://github.com/yuki24/did_you_mean/commit/1c52c887c62b0921e799f94bcc4a846dc7cbc057) - Fixed features that didn't work on JRuby 9.1.0.0: [dc48dde](https://github.com/yuki24/did_you_mean/commit/dc48dde1b2a8f05aab1fcf897e1cb3075a206f53), [4de23f8](https://github.com/yuki24/did_you_mean/commit/4de23f880502c80c5f321371d39c08bb0fa34040), [00e3059](https://github.com/yuki24/did_you_mean/commit/00e305971060d150fae4817b5e895d6478b37579). The local variable name correction is still disabled. Also see: [jruby/jruby#3480](https://github.com/jruby/jruby/issues/3480) ## [v1.0.0](https://github.com/yuki24/did_you_mean/tree/v1.0.0) _released at 2015-12-25 05:13:04 UTC_ #### Features - Introduced a [verbose formatter](https://github.com/yuki24/did_you_mean#verbose-formatter) - Introduced an easy way to enabling [experimental features](https://github.com/yuki24/did_you_mean#experimental-features) #### Bug Fixes - Fixed a bug where the Jaro-Winkler implementation returns the wrong distance when 2 identical strings are given. fixes [#58](https://github.com/yuki24/did_you_mean/pull/58) #### Internal Changes - Slightly changed the spell checking algorithm. Take a look at [e2f5b24](https://github.com/yuki24/did_you_mean/commit/e2f5b2437f967565e4830eab6077f73ae166e0a7) for more details. fixes [#60](https://github.com/yuki24/did_you_mean/issues/60) ## [v1.0.0.rc1](https://github.com/yuki24/did_you_mean/tree/v1.0.0.rc1) _released at 2015-12-25 05:02:25 UTC_ #### Internal Changes - No longer uses `TracePoint` API by default. fixes [#55](https://github.com/yuki24/did_you_mean/issues/55) and [#56](https://github.com/yuki24/did_you_mean/issues/56) ## [v1.0.0.beta3](https://github.com/yuki24/did_you_mean/tree/v1.0.0.beta3) _released at 2015-12-25 04:56:13 UTC_ #### Internal Changes - Use the `frozen-string-literal` pragma rather than calling `.freeze` everywhere - Use the `NameError#receiver` method in `DidYouMean:: ClassNameChecker` to know the namespace where the constant call is made - Refactored the `SpellCheckerTest` ## [v1.0.0.beta2](https://github.com/yuki24/did_you_mean/tree/v1.0.0.beta2) _released at 2015-12-25 04:50:36 UTC_ #### Bug Fixes - Fixed a bug where the gem doesn't install properly on Ruby 2.3.0dev ## [v1.0.0.beta1](https://github.com/yuki24/did_you_mean/tree/v1.0.0.beta1) _released at 2015-12-25 05:27:53 UTC_ #### Breaking Changes - Dropped support for MRIs older than 2.3, JRuby and Rubinus #### Internal Changes - The C extension has been removed since the `NameError#receiver` method has become part of the MRI 2.3 - The interception gem has been removed from the dependencies - Removed code that was needed to support multiple Ruby implementations ## [v0.10.0](https://github.com/yuki24/did_you_mean/tree/v0.10.0) _released at 2015-08-21 06:44:11 UTC_ #### Features - Now it corrects an instance variable name if the ivar name is mistyped and `NoMethodError` is raised: ```ruby @number = 1 @nubmer.zero? # => NoMethodError: undefined method `zero?' for nil:NilClass # # Did you mean? @number # ``` - Support for JRuby 9.0.0.0 - Prefix-based correction ( [@tjohn](https://github.com/tjohn), [#50](https://github.com/yuki24/did_you_mean/issues/50 "Match start of method name"), [#49](https://github.com/yuki24/did_you_mean/issues/49 "Use Jaro distance instead of Jaro-Winkler distance")) - Correction search is about 75% faster than 0.9.10 #### Breaking Changes - The ActiveRecord integration has been removed ## [v0.9.10](https://github.com/yuki24/did_you_mean/tree/v0.9.10) _released at 2015-05-14 03:04:47 UTC_ #### Bug Fixes - Fixed a bug where a duplicate "did you mean?" message was appended each time `#to_s` is called ( [@danfinnie](https://github.com/danfinnie), [#51](https://github.com/yuki24/did_you_mean/issues/51 "Duplicate output for constants in separate gem")) ## [v0.9.9](https://github.com/yuki24/did_you_mean/tree/v0.9.9) _released at 2015-05-13 03:48:19 UTC_ #### Features - Order word suggestions based on Levenshtein distance ( [@tleish](https://github.com/tleish), [#31](https://github.com/yuki24/did_you_mean/pull/31)) #### Internal Changes - Reduce memory allocation by about 40% - Speed up Levenshtein distance calculation by about 40% - The Java extension has been replaced with a pure JRuby implementation ## [v0.9.8](https://github.com/yuki24/did_you_mean/tree/v0.9.8) _released at 2015-04-12 01:55:27 UTC_ #### Internal Changes - Speed up Levenshtein by 50% and reduce 97% of memory usage ## [v0.9.7](https://github.com/yuki24/did_you_mean/tree/v0.9.7) _released at 2015-04-02 04:20:26 UTC_ #### Bug Fixes - Fixed an issue where _did\_you\_mean_ doesn't install on JRuby properly. ## [v0.9.6](https://github.com/yuki24/did_you_mean/tree/v0.9.6) _released at 2015-01-24 23:19:27 UTC_ #### Bug Fixes - Fixed a bug where did\_you\_mean incorrectly suggests protected methods when it just isn't callable ( [@glittershark](https://github.com/glittershark), [#34](https://github.com/yuki24/did_you_mean/issues/34 "Did\_you\_mean incorrectly called when attempting to call protected/private method")) ## [v0.9.5](https://github.com/yuki24/did_you_mean/tree/v0.9.5) _released at 2015-01-07 12:41:23 UTC_ #### Bug Fixes - Whitelist `#safe_constantize` method from `ActiveSupport::Inflector` to avoid significant performance slowdown ( [@tleish](https://github.com/tleish), [#19](https://github.com/yuki24/did_you_mean/issues/19 "Significant Slowdown when Using Debugger"), [#20](https://github.com/yuki24/did_you_mean/pull/20 "Whitelisting safe\_constantize (ActiveSupport::Inflector) method")) ## [v0.9.4](https://github.com/yuki24/did_you_mean/tree/v0.9.4) _released at 2014-11-19 20:00:00 UTC_ #### Bug Fixes - Fixed a bug where no suggestions will be made on JRuby ## [v0.9.3](https://github.com/yuki24/did_you_mean/tree/v0.9.3) _released at 2014-11-18 03:50:11 UTC_ **This version has been yanked from rubygems.org as it doesn't work with jRuby at all. Please upgrade to 0.9.4 or higher as soon as possible.** #### Internal Changes - Replaced the crazy C extension with a so much better one (thanks to [@nobu](https://github.com/nobu)!) ## [v0.9.2](https://github.com/yuki24/did_you_mean/tree/v0.9.2) _released at 2014-11-17 15:32:33 UTC_ #### Bug Fixes - Fixed a bug where did\_you\_mean doesn't compile on Ruby 2.1.2/2.1.5 ( [#16](https://github.com/yuki24/did_you_mean/issues/16 "Gem building failed on Debian 6.0.10 x86\_64")) ## [v0.9.1](https://github.com/yuki24/did_you_mean/tree/v0.9.1) _released at 2014-11-16 18:54:24 UTC_ **This version has been yanked from rubygems.org as it doesn't compile on Ruby 2.1.2 and 2.1.5. Please upgrade to 0.9.4 or higher as soon as possible.** #### Internal Changes - Shrink the gem size by removing unneeded ruby header files. - Now it forces everyone to upgrade the gem when they upgrade Ruby to a new version. This avoids introducing a bug like [#14](https://github.com/yuki24/did_you_mean/issues/14 "Compatibility with `letter\_opener` gem"). ## [v0.9.0](https://github.com/yuki24/did_you_mean/tree/v0.9.0) _released at 2014-11-09 01:26:31 UTC_ #### Features - did\_you\_mean now suggests instance variable names if `@` is missing ( [#12](https://github.com/yuki24/did_you_mean/issues/12 "Suggest instance- and class-vars"), [39d1e2b](https://github.com/yuki24/did_you_mean/commit/39d1e2bd66d6ff8acbc4dd5da922fc7e5fcefb20)) ```ruby @full_name = "Yuki Nishijima" first_name, last_name = full_name.split(" ") # => NameError: undefined local variable or method `full_name' for main:Object # # Did you mean? @full_name # ``` #### Bug Fixes - Fixed a bug where did\_you\_mean changes some behaviours of Ruby 2.1.3/2.1.4 installed on Max OS X ( [#14](https://github.com/yuki24/did_you_mean/issues/14 "Compatibility with `letter\_opener` gem"), [44c451f](https://github.com/yuki24/did_you_mean/commit/44c451f8c38b11763ba28ddf1ceb9696707ccea0), [9ebde21](https://github.com/yuki24/did_you_mean/commit/9ebde211e92eac8494e704f627c62fea7fdbee16)) - Fixed a bug where sometimes `NoMethodError` suggests duplicate method names ( [9865cc5](https://github.com/yuki24/did_you_mean/commit/9865cc5a9ce926dd9ad4c20d575b710e5f257a4b)) ## [v0.8.0](https://github.com/yuki24/did_you_mean/tree/v0.8.0) _released at 2014-10-27 02:03:13 UTC_ **This version has been yanked from rubygems.org as it has a serious bug with Ruby 2.1.3 and 2.1.4 installed on Max OS X. Please upgrade to 0.9.4 or higher as soon as possible.** #### Features - JRuby support! #### Bug Fixes - Fixed a bug where did\_you\_mean unexpectedly disables [better\_errors](https://github.com/charliesome/better_errors)'s REPL - Replaced [binding\_of\_caller](https://github.com/banister/binding_of_caller) dependency with [interception](https://github.com/ConradIrwin/interception) - Fixed the wrong implementation of Levenshtein algorithm ( [#2](https://github.com/yuki24/did_you_mean/pull/2 "Fix bug of DidYouMean::Levenshtein#min3."), [@fortissimo1997](https://github.com/fortissimo1997)) ## [v0.7.0](https://github.com/yuki24/did_you_mean/tree/v0.7.0) _released at 2014-09-26 03:37:18 UTC_ **This version has been yanked from rubygems.org as it has a serious bug with Ruby 2.1.3 and 2.1.4 installed on Max OS X. Please upgrade to 0.9.4 or higher as soon as possible.** #### Features - Added support for Ruby 2.1.3, 2.2.0-preview1 and ruby-head - Added support for ActiveRecord 4.2.0.beta1 - Word searching is now about 40% faster than v0.6.0 - Removed `text` gem dependency - Better output on pry and Rspec #### Internal Changes - A lot of internal refactoring ## [v0.6.0](https://github.com/yuki24/did_you_mean/tree/v0.6.0) _released at 2014-05-18 00:23:24 UTC_ **This version has been yanked from rubygems.org as it has a serious bug with Ruby 2.1.3 and 2.1.4 installed on Max OS X. Please upgrade to 0.9.4 or higher as soon as possible.** #### Features - Added basic support for constants. Now you'll see class name suggestions when you misspelled a class names/module names: ```ruby > Ocject # => NameError: uninitialized constant Ocject # # Did you mean? Object # ``` #### Bug Fixes - Fixed a bug where did\_you\_mean segfaults on Ruby head(2.2.0dev) ## [v0.5.0](https://github.com/yuki24/did_you_mean/tree/v0.5.0) _released at 2014-05-10 17:59:54 UTC_ #### Features - Added support for Ruby 2.1.2 ## [v0.4.0](https://github.com/yuki24/did_you_mean/tree/v0.4.0) _released at 2014-04-20 02:10:31 UTC_ #### Features - did\_you\_mean now suggests a similar attribute name when you misspelled it. ```ruby User.new(flrst_name: "wrong flrst name") # => ActiveRecord::UnknownAttributeError: unknown attribute: flrst_name # # Did you mean? first_name: string # ``` #### Bug Fixes - Fixed a bug where did\_you\_mean doesn't work with `ActiveRecord::UnknownAttributeError` ## [v0.3.1](https://github.com/yuki24/did_you_mean/tree/v0.3.1) _released at 2014-03-20 23:16:20 UTC_ #### Features - Changed output for readability. - Made the spell checking algorithm slight better to find the correct method. ## [v0.3.0](https://github.com/yuki24/did_you_mean/tree/v0.3.0) _released at 2014-03-20 23:13:13 UTC_ #### Features - Added support for Ruby 2.1.1 and 2.2.0(head). ## [v0.2.0](https://github.com/yuki24/did_you_mean/tree/v0.2.0) _released on 2014-03-20 23:12:13 UTC_ #### Features - did\_you\_mean no longer makes Ruby slow. #### Breaking Changes - dropped support for JRuby and Rubbinious. ## [v0.1.0: First Release](https://github.com/yuki24/did_you_mean/tree/v0.1.0) _released on 2014-03-20 23:11:14 UTC_ - Now you will have "did you mean?" experience in Ruby! - but still very experimental since this gem makes Ruby a lot slower. PK% ]yCygems/did_you_mean-1.3.0/Gemfilenu[source 'https://rubygems.org' # Specify your gem's dependencies in did_you_mean.gemspec gemspec gem 'benchmark-ips' gem 'memory_profiler' gem 'jaro_winkler', '>= 1.4.0' PK% ]Ɛ gems/did_you_mean-1.3.0/Rakefilenu[require 'bundler/gem_tasks' require 'rake/testtask' Rake::TestTask.new do |task| task.libs << "test" task.test_files = Dir['test/**/*_test.rb'].reject {|path| /(experimental)/ =~ path } task.verbose = true task.warning = true end Rake::TestTask.new("test:experimental") do |task| task.libs << "test" task.pattern = 'test/experimental/**/*_test.rb' task.verbose = true task.warning = true task.ruby_opts << "-rdid_you_mean/experimental" end task default: %i(test test:experimental) namespace :test do namespace :accuracy do desc "Download Wiktionary's Simple English data and save it as a dictionary" task :prepare do sh 'ruby evaluation/dictionary_generator.rb' end end desc "Calculate accuracy of the gems' spell checker" task :accuracy do if !File.exist?("evaluation/dictionary.yml") puts 'Generating dictionary for evaluation:' Rake::Task["test:accuracy:prepare"].execute puts "\n" end sh 'ruby evaluation/calculator.rb' end end namespace :benchmark do desc "Measure memory usage by the did_you_mean gem" task :memory do sh 'ruby benchmark/memory_usage.rb' end end PK% ]+Jx##-gems/did_you_mean-1.3.0/test/fixtures/book.rbnu[class Book class Cover end end PK% ]o||?gems/did_you_mean-1.3.0/test/edit_distance/jaro_winkler_test.rbnu[require 'test_helper' # These tests were originally written by Jian Weihang (簡煒航) as part of his work # on the jaro_winkler gem. The original code could be found here: # https://github.com/tonytonyjan/jaro_winkler/blob/9bd12421/spec/jaro_winkler_spec.rb # # Copyright (c) 2014 Jian Weihang class JaroWinklerTest < Minitest::Test def test_jaro_winkler_distance assert_distance 0.9667, 'henka', 'henkan' assert_distance 1.0, 'al', 'al' assert_distance 0.9611, 'martha', 'marhta' assert_distance 0.8324, 'jones', 'johnson' assert_distance 0.9167, 'abcvwxyz', 'zabcvwxy' assert_distance 0.9583, 'abcvwxyz', 'cabvwxyz' assert_distance 0.84, 'dwayne', 'duane' assert_distance 0.8133, 'dixon', 'dicksonx' assert_distance 0.0, 'fvie', 'ten' assert_distance 0.9067, 'does_exist', 'doesnt_exist' assert_distance 1.0, 'x', 'x' end def test_jarowinkler_distance_with_utf8_strings assert_distance 0.9818, '變形金剛4:絕跡重生', '變形金剛4: 絕跡重生' assert_distance 0.8222, '連勝文', '連勝丼' assert_distance 0.8222, '馬英九', '馬英丸' assert_distance 0.6667, '良い', 'いい' end private def assert_distance(score, str1, str2) assert_equal score, DidYouMean::JaroWinkler.distance(str1, str2).round(4) end end PK% ]}؝Mgems/did_you_mean-1.3.0/test/experimental/initializer_name_correction_test.rbnu[require 'test_helper' class InitializerNameCorrectionTest < Minitest::Test def test_corrects_wrong_initializer_name assert_output nil, "warning: intialize might be misspelled, perhaps you meant initialize?\n" do Class.new { def intialize; end } end end def test_does_not_correct_correct_initializer_name assert_output nil, "" do Class.new { def initialize; end } end end end PK% ]無qqEgems/did_you_mean-1.3.0/test/experimental/method_name_checker_test.rbnu[require 'test_helper' class ExperimentalMethodNameCorrectionTest < Minitest::Test def test_corrects_incorrect_ivar_name @number = 1 @nubmer = nil error = assert_raises(NoMethodError) { @nubmer.zero? } remove_instance_variable :@nubmer assert_correction :@number, error.corrections assert_match "Did you mean? @number", error.to_s end end PK% ] Bgems/did_you_mean-1.3.0/test/core_ext/name_error_extension_test.rbnu[require 'test_helper' class NameErrorExtensionTest < Minitest::Test SPELL_CHECKERS = DidYouMean::SPELL_CHECKERS class TestSpellChecker def initialize(*); end def corrections; ["does_exist"]; end end def setup @org, SPELL_CHECKERS['NameError'] = SPELL_CHECKERS['NameError'], TestSpellChecker @error = assert_raises(NameError){ doesnt_exist } end def teardown SPELL_CHECKERS['NameError'] = @org end def test_message message = <<~MESSAGE.chomp undefined local variable or method `doesnt_exist' for #{to_s} Did you mean? does_exist MESSAGE assert_equal message, @error.to_s assert_equal message, @error.message end def test_to_s_does_not_make_disruptive_changes_to_error_message error = assert_raises(NameError) do raise NameError, "uninitialized constant Object" end error.to_s assert_equal 1, error.to_s.scan("Did you mean?").count end def test_correctable_error_objects_are_dumpable error = begin File.open('./tmp/.keep').sizee rescue NoMethodError => e e end error.to_s assert_equal "undefined method `sizee' for #", Marshal.load(Marshal.dump(error)).original_message end end PK% ]D}7ii+gems/did_you_mean-1.3.0/test/test_helper.rbnu[require 'minitest/autorun' require 'minitest/pride' require 'did_you_mean' puts "DidYouMean version: #{DidYouMean::VERSION}" module DidYouMean::TestHelper def assert_correction(expected, array) assert_equal Array(expected), array, "Expected #{array.inspect} to only include #{expected.inspect}" end end MiniTest::Test.include(DidYouMean::TestHelper) PK% ]41Bgems/did_you_mean-1.3.0/test/spell_checking/key_name_check_test.rbnu[require "test_helper" class KeyNameCheckTest < Minitest::Test def test_corrects_hash_key_name_with_fetch hash = { "foo" => 1, bar: 2 } error = assert_raises(KeyError) { hash.fetch(:bax) } assert_correction ":bar", error.corrections assert_match "Did you mean? :bar", error.to_s error = assert_raises(KeyError) { hash.fetch("fooo") } assert_correction %("foo"), error.corrections assert_match %(Did you mean? "foo"), error.to_s end def test_corrects_hash_key_name_with_fetch_values hash = { "foo" => 1, bar: 2 } error = assert_raises(KeyError) { hash.fetch_values("foo", :bar, :bax) } assert_correction ":bar", error.corrections assert_match "Did you mean? :bar", error.to_s error = assert_raises(KeyError) { hash.fetch_values("foo", :bar, "fooo") } assert_correction %("foo"), error.corrections assert_match %(Did you mean? "foo"), error.to_s end def test_corrects_sprintf_key_name error = assert_raises(KeyError) { sprintf("%d", {fooo: 1}) } assert_correction ":fooo", error.corrections assert_match "Did you mean? :fooo", error.to_s end def test_corrects_env_key_name ENV["FOO"] = "1" ENV["BAR"] = "2" error = assert_raises(KeyError) { ENV.fetch("BAX") } assert_correction %("BAR"), error.corrections assert_match %(Did you mean? "BAR"), error.to_s ensure ENV.delete("FOO") ENV.delete("BAR") end end PK% ]LyD Egems/did_you_mean-1.3.0/test/spell_checking/method_name_check_test.rbnu[require 'test_helper' class MethodNameCheckTest < Minitest::Test class User def friends; end def first_name; end def descendants; end def call_incorrect_private_method raiae NoMethodError end def raise_no_method_error self.firstname rescue NoMethodError => e raise e, e.message, e.backtrace end protected def the_protected_method; end private def friend; end def the_private_method; end class << self def load; end end end module UserModule def from_module; end end def setup @user = User.new.extend(UserModule) end def test_corrections_include_instance_method error = assert_raises(NoMethodError){ @user.flrst_name } assert_correction :first_name, error.corrections assert_match "Did you mean? first_name", error.to_s end def test_corrections_include_private_method error = assert_raises(NoMethodError){ @user.friend } assert_correction :friends, error.corrections assert_match "Did you mean? friends", error.to_s end def test_corrections_include_method_from_module error = assert_raises(NoMethodError){ @user.fr0m_module } assert_correction :from_module, error.corrections assert_match "Did you mean? from_module", error.to_s end def test_corrections_include_class_method error = assert_raises(NoMethodError){ User.l0ad } assert_correction :load, error.corrections assert_match "Did you mean? load", error.to_s end def test_private_methods_should_not_be_suggested error = assert_raises(NoMethodError){ User.new.the_protected_method } refute_includes error.corrections, :the_protected_method error = assert_raises(NoMethodError){ User.new.the_private_method } refute_includes error.corrections, :the_private_method end def test_corrections_when_private_method_is_called_with_args error = assert_raises(NoMethodError){ @user.call_incorrect_private_method } assert_correction :raise, error.corrections assert_match "Did you mean? raise", error.to_s end def test_exclude_methods_on_nil error = assert_raises(NoMethodError){ nil.map } assert_empty error.corrections end def test_does_not_exclude_custom_methods_on_nil def nil.empty? end error = assert_raises(NoMethodError){ nil.empty } assert_correction :empty?, error.corrections ensure NilClass.class_eval { undef empty? } end def test_does_not_append_suggestions_twice error = assert_raises NoMethodError do begin @user.firstname rescue NoMethodError => e raise e, e.message, e.backtrace end end assert_equal 1, error.to_s.scan(/Did you mean/).count end def test_does_not_append_suggestions_three_times error = assert_raises NoMethodError do begin @user.raise_no_method_error rescue NoMethodError => e raise e, e.message, e.backtrace end end assert_equal 1, error.to_s.scan(/Did you mean/).count end def test_suggests_yield error = assert_raises(NoMethodError) { yeild(1) } assert_correction :yield, error.corrections assert_match "Did you mean? yield", error.to_s end end PK% ](*; Ggems/did_you_mean-1.3.0/test/spell_checking/variable_name_check_test.rbnu[require 'test_helper' class VariableNameCheckTest < Minitest::Test class User def initialize @email_address = 'email_address@address.net' @first_name = nil @last_name = nil end def first_name; end def to_s "#{@first_name} #{@last_name} <#{email_address}>" end private def cia_codename; "Alexa" end end module UserModule def from_module; end end def setup @user = User.new.extend(UserModule) end def test_corrections_include_instance_method error = assert_raises(NameError) do @user.instance_eval { flrst_name } end @user.instance_eval do remove_instance_variable :@first_name remove_instance_variable :@last_name end assert_correction :first_name, error.corrections assert_match "Did you mean? first_name", error.to_s end def test_corrections_include_method_from_module error = assert_raises(NameError) do @user.instance_eval { fr0m_module } end assert_correction :from_module, error.corrections assert_match "Did you mean? from_module", error.to_s end def test_corrections_include_local_variable_name person = person = nil error = (eprson rescue $!) # Do not use @assert_raises here as it changes a scope. assert_correction :person, error.corrections assert_match "Did you mean? person", error.to_s end def test_corrections_include_ruby_predefined_objects some_var = nil false_error = assert_raises(NameError) do some_var = fals end true_error = assert_raises(NameError) do some_var = treu end nil_error = assert_raises(NameError) do some_var = nul end file_error = assert_raises(NameError) do __FIEL__ end assert_correction :false, false_error.corrections assert_match "Did you mean? false", false_error.to_s assert_correction :true, true_error.corrections assert_match "Did you mean? true", true_error.to_s assert_correction :nil, nil_error.corrections assert_match "Did you mean? nil", nil_error.to_s assert_correction :__FILE__, file_error.corrections assert_match "Did you mean? __FILE__", file_error.to_s end def test_suggests_yield error = assert_raises(NameError) { yeild } assert_correction :yield, error.corrections assert_match "Did you mean? yield", error.to_s end def test_corrections_include_instance_variable_name error = assert_raises(NameError){ @user.to_s } assert_correction :@email_address, error.corrections assert_match "Did you mean? @email_address", error.to_s end def test_corrections_include_private_method error = assert_raises(NameError) do @user.instance_eval { cia_code_name } end assert_correction :cia_codename, error.corrections assert_match "Did you mean? cia_codename", error.to_s end @@does_exist = true def test_corrections_include_class_variable_name error = assert_raises(NameError){ @@doesnt_exist } assert_correction :@@does_exist, error.corrections assert_match "Did you mean? @@does_exist", error.to_s end def test_struct_name_error value = Struct.new(:does_exist).new error = assert_raises(NameError){ value[:doesnt_exist] } assert_correction [:does_exist, :does_exist=], error.corrections assert_match "Did you mean? does_exist", error.to_s end def test_exclude_typical_incorrect_suggestions error = assert_raises(NameError){ foo } assert_empty error.corrections end end PK% ]g00Dgems/did_you_mean-1.3.0/test/spell_checking/class_name_check_test.rbnu[require 'test_helper' module ACRONYM end class Project def self.bo0k Bo0k end end class Book class TableOfContents; end def tableof_contents TableofContents end class Page def tableof_contents TableofContents end def self.tableof_contents TableofContents end end end class ClassNameCheckTest < Minitest::Test def test_corrections error = assert_raises(NameError) { ::Bo0k } assert_correction "Book", error.corrections end def test_corrections_include_case_specific_class_name error = assert_raises(NameError) { ::Acronym } assert_correction "ACRONYM", error.corrections end def test_corrections_include_top_level_class_name error = assert_raises(NameError) { Project.bo0k } assert_correction "Book", error.corrections end def test_names_in_corrections_have_namespaces error = assert_raises(NameError) { ::Book::TableofContents } assert_correction "Book::TableOfContents", error.corrections end def test_corrections_candidates_for_names_in_upper_level_scopes error = assert_raises(NameError) { Book::Page.tableof_contents } assert_correction "Book::TableOfContents", error.corrections end def test_corrections_should_work_from_within_instance_method error = assert_raises(NameError) { ::Book.new.tableof_contents } assert_correction "Book::TableOfContents", error.corrections end def test_corrections_should_work_from_within_instance_method_on_nested_class error = assert_raises(NameError) { ::Book::Page.new.tableof_contents } assert_correction "Book::TableOfContents", error.corrections end def test_does_not_suggest_user_input error = assert_raises(NameError) { ::Book::Cover } # This is a weird require, but in a multi-threaded condition, a constant may # be loaded between when a NameError occurred and when the spell checker # attemps to find a possible suggestion. The manual require here simulates # a race condition a single test. require_relative '../fixtures/book' assert_empty error.corrections end end PK% ]NX;;Lgems/did_you_mean-1.3.0/test/spell_checking/uncorrectable_name_check_test.rbnu[require 'test_helper' class UncorrectableNameCheckTest < Minitest::Test class FirstNameError < NameError; end def setup @error = assert_raises(FirstNameError) do raise FirstNameError, "Other name error" end end def test_message assert_equal "Other name error", @error.message end end PK% ]S9 2gems/did_you_mean-1.3.0/test/spell_checker_test.rbnu[require 'test_helper' class SpellCheckerTest < Minitest::Test def test_spell_checker_corrects_mistypes assert_spell 'foo', input: 'doo', dictionary: ['foo', 'fork'] assert_spell 'email', input: 'meail', dictionary: ['email', 'fail', 'eval'] assert_spell 'fail', input: 'fial', dictionary: ['email', 'fail', 'eval'] assert_spell 'fail', input: 'afil', dictionary: ['email', 'fail', 'eval'] assert_spell 'eval', input: 'eavl', dictionary: ['email', 'fail', 'eval'] assert_spell 'eval', input: 'veal', dictionary: ['email', 'fail', 'eval'] assert_spell 'sub!', input: 'suv!', dictionary: ['sub', 'gsub', 'sub!'] assert_spell 'sub', input: 'suv', dictionary: ['sub', 'gsub', 'sub!'] assert_spell %w(gsub! gsub), input: 'gsuv!', dictionary: %w(sub gsub gsub!) assert_spell %w(sub! sub gsub!), input: 'ssub!', dictionary: %w(sub sub! gsub gsub!) group_methods = %w(groups group_url groups_url group_path) assert_spell 'groups', input: 'group', dictionary: group_methods group_classes = %w( GroupMembership GroupMembershipPolicy GroupMembershipDecorator GroupMembershipSerializer GroupHelper Group GroupMailer NullGroupMembership ) assert_spell 'GroupMembership', dictionary: group_classes, input: 'GroupMemberhip' assert_spell 'GroupMembershipDecorator', dictionary: group_classes, input: 'GroupMemberhipDecorator' names = %w(first_name_change first_name_changed? first_name_will_change!) assert_spell names, input: 'first_name_change!', dictionary: names assert_empty DidYouMean::SpellChecker.new(dictionary: ['proc']).correct('product_path') assert_empty DidYouMean::SpellChecker.new(dictionary: ['fork']).correct('fooo') end def test_spell_checker_corrects_misspells assert_spell 'descendants', input: 'dependents', dictionary: ['descendants'] assert_spell 'drag_to', input: 'drag', dictionary: ['drag_to'] assert_spell 'set_result_count', input: 'set_result', dictionary: ['set_result_count'] end def test_spell_checker_sorts_results_by_simiarity expected = %w( name12345 name1234 name123 ) actual = DidYouMean::SpellChecker.new(dictionary: %w( name12 name123 name1234 name12345 name123456 )).correct('name123456') assert_equal expected, actual end def test_spell_checker_excludes_input_from_dictionary assert_empty DidYouMean::SpellChecker.new(dictionary: ['input']).correct('input') assert_empty DidYouMean::SpellChecker.new(dictionary: [:input]).correct('input') assert_empty DidYouMean::SpellChecker.new(dictionary: ['input']).correct(:input) end private def assert_spell(expected, input: , dictionary: ) corrections = DidYouMean::SpellChecker.new(dictionary: dictionary).correct(input) assert_equal Array(expected), corrections, "Expected to suggest #{expected}, but got #{corrections.inspect}" end end PK% ]ٮ͇6gems/did_you_mean-1.3.0/test/verbose_formatter_test.rbnu[require 'test_helper' class VerboseFormatterTest < Minitest::Test def setup require 'did_you_mean/verbose' does_exist = does_exist = nil @error = assert_raises(NameError){ doesnt_exist } end def teardown DidYouMean.formatter = DidYouMean::PlainFormatter.new end def test_message assert_equal <<~MESSAGE.chomp, @error.message undefined local variable or method `doesnt_exist' for #{to_s} Did you mean? does_exist MESSAGE end end PK% ]EwΝ!gems/did_you_mean-1.3.0/README.mdnu[# did_you_mean [![Gem Version](https://badge.fury.io/rb/did_you_mean.svg)](https://rubygems.org/gems/did_you_mean) [![Build Status](https://travis-ci.org/yuki24/did_you_mean.svg?branch=master)](https://travis-ci.org/yuki24/did_you_mean) ## Installation Ruby 2.3 and later ships with this gem and it will automatically be `require`d when a Ruby process starts up. No special setup is required. ## Examples ### NameError #### Correcting a Misspelled Method Name ```ruby methosd # => NameError: undefined local variable or method `methosd' for main:Object # Did you mean? methods # method ``` #### Correcting a Misspelled Class Name ```ruby OBject # => NameError: uninitialized constant OBject # Did you mean? Object ``` #### Suggesting an Instance Variable Name ```ruby @full_name = "Yuki Nishijima" first_name, last_name = full_name.split(" ") # => NameError: undefined local variable or method `full_name' for main:Object # Did you mean? @full_name ``` #### Correcting a Class Variable Name ```ruby @@full_name = "Yuki Nishijima" @@full_anme # => NameError: uninitialized class variable @@full_anme in Object # Did you mean? @@full_name ``` ### NoMethodError ```ruby full_name = "Yuki Nishijima" full_name.starts_with?("Y") # => NoMethodError: undefined method `starts_with?' for "Yuki Nishijima":String # Did you mean? start_with? ``` ### KeyError ```ruby hash = {foo: 1, bar: 2, baz: 3} hash.fetch(:fooo) # => KeyError: key not found: :fooo # Did you mean? :foo ``` ## Experimental Features Aside from the basic features above, the `did_you_mean` gem comes with experimental features. They can be enabled by calling `require 'did_you_mean/experimental'`. Note that **these experimental features should never be enabled in production as they would impact Ruby's performance and use some unstable Ruby APIs.** ### Correcting an Instance Variable When It's Incorrectly Spelled ```ruby require 'did_you_mean/experimental' @full_name = "Yuki Nishijima" @full_anme.split(" ") # => NoMethodError: undefined method `split' for nil:NilClass # Did you mean? @full_name ``` ### Displaying a Warning When `initialize` is Incorrectly Spelled ```ruby require 'did_you_mean/experimental' class Person def intialize ... end end # => warning: intialize might be misspelled, perhaps you meant initialize? ``` ## Verbose Formatter This verbose formatter changes the error message format to take more lines/spaces so it'll be slightly easier to read the suggestions. This formatter can totally be used in any environment including production. ```ruby OBject # => NameError: uninitialized constant OBject # Did you mean? Object require 'did_you_mean/verbose' OBject # => NameError: uninitialized constant OBject # # Did you mean? Object # ``` ## Disabling `did_you_mean` Occasionally, you may want to disable the `did_you_mean` gem for e.g. debugging issues in the error object itself. You can disable it entirely by specifying `--disable-did_you_mean` option to the `ruby` command: ```bash $ ruby --disable-did_you_mean -e "1.zeor?" -e:1:in `
': undefined method `zeor?' for 1:Integer (NameError) ``` When you do not have direct access to the `ruby` command (e.g. `rails console`, `irb`), you could applyoptions using the `RUBYOPT` environment variable: ```bash $ RUBYOPT='--disable-did_you_mean' irb irb:0> 1.zeor? # => NoMethodError (undefined method `zeor?' for 1:Integer) ``` ### Getting the original error message Sometimes, you do not want to disable the gem entirely, but need to get the original error message without suggestions (e.g. testing). In this case, you could use the `#original_message` method on the error object: ```ruby no_method_error = begin 1.zeor? rescue NoMethodError => error error end no_method_error.message # => NoMethodError (undefined method `zeor?' for 1:Integer) # Did you mean? zero? no_method_error.original_message # => NoMethodError (undefined method `zeor?' for 1:Integer) ``` ## Contributing 1. Fork it (http://github.com/yuki24/did_you_mean/fork) 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Make sure all tests pass (`bundle exec rake`) 5. Push to the branch (`git push origin my-new-feature`) 6. Create new Pull Request ## License Copyright (c) 2014-16 Yuki Nishijima. See MIT-LICENSE for further details. PK% ]ON,gems/did_you_mean-1.3.0/did_you_mean.gemspecnu[# -*- encoding: utf-8 -*- # stub: did_you_mean 1.3.0 ruby lib Gem::Specification.new do |s| s.name = "did_you_mean".freeze s.version = "1.3.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Yuki Nishijima".freeze] s.date = "2018-12-18" s.description = "The gem that has been saving people from typos since 2014.".freeze s.email = ["mail@yukinishijima.net".freeze] s.files = [".gitignore".freeze, ".ruby-version".freeze, ".travis.yml".freeze, "CHANGELOG.md".freeze, "Gemfile".freeze, "LICENSE.txt".freeze, "README.md".freeze, "Rakefile".freeze, "benchmark/jaro_winkler/memory_usage.rb".freeze, "benchmark/jaro_winkler/speed.rb".freeze, "benchmark/levenshtein/memory_usage.rb".freeze, "benchmark/levenshtein/speed.rb".freeze, "benchmark/memory_usage.rb".freeze, "did_you_mean.gemspec".freeze, "doc/CHANGELOG.md.erb".freeze, "doc/changelog_generator.rb".freeze, "lib/did_you_mean.rb".freeze, "lib/did_you_mean/core_ext/name_error.rb".freeze, "lib/did_you_mean/experimental.rb".freeze, "lib/did_you_mean/experimental/initializer_name_correction.rb".freeze, "lib/did_you_mean/experimental/ivar_name_correction.rb".freeze, "lib/did_you_mean/formatters/plain_formatter.rb".freeze, "lib/did_you_mean/formatters/verbose_formatter.rb".freeze, "lib/did_you_mean/jaro_winkler.rb".freeze, "lib/did_you_mean/levenshtein.rb".freeze, "lib/did_you_mean/spell_checker.rb".freeze, "lib/did_you_mean/spell_checkers/key_error_checker.rb".freeze, "lib/did_you_mean/spell_checkers/method_name_checker.rb".freeze, "lib/did_you_mean/spell_checkers/name_error_checkers.rb".freeze, "lib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb".freeze, "lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb".freeze, "lib/did_you_mean/spell_checkers/null_checker.rb".freeze, "lib/did_you_mean/verbose.rb".freeze, "lib/did_you_mean/version.rb".freeze, "test/core_ext/name_error_extension_test.rb".freeze, "test/edit_distance/jaro_winkler_test.rb".freeze, "test/experimental/initializer_name_correction_test.rb".freeze, "test/experimental/method_name_checker_test.rb".freeze, "test/fixtures/book.rb".freeze, "test/spell_checker_test.rb".freeze, "test/spell_checking/class_name_check_test.rb".freeze, "test/spell_checking/key_name_check_test.rb".freeze, "test/spell_checking/method_name_check_test.rb".freeze, "test/spell_checking/uncorrectable_name_check_test.rb".freeze, "test/spell_checking/variable_name_check_test.rb".freeze, "test/test_helper.rb".freeze, "test/verbose_formatter_test.rb".freeze, "tmp/.keep".freeze] s.homepage = "https://github.com/yuki24/did_you_mean".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.5.0".freeze) s.rubygems_version = "3.1.2".freeze s.summary = "\"Did you mean?\" experience in Ruby".freeze s.test_files = ["test/core_ext/name_error_extension_test.rb".freeze, "test/edit_distance/jaro_winkler_test.rb".freeze, "test/experimental/initializer_name_correction_test.rb".freeze, "test/experimental/method_name_checker_test.rb".freeze, "test/fixtures/book.rb".freeze, "test/spell_checker_test.rb".freeze, "test/spell_checking/class_name_check_test.rb".freeze, "test/spell_checking/key_name_check_test.rb".freeze, "test/spell_checking/method_name_check_test.rb".freeze, "test/spell_checking/uncorrectable_name_check_test.rb".freeze, "test/spell_checking/variable_name_check_test.rb".freeze, "test/test_helper.rb".freeze, "test/verbose_formatter_test.rb".freeze] if s.respond_to? :specification_version then s.specification_version = 4 end if s.respond_to? :add_runtime_dependency then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]8XX6gems/did_you_mean-1.3.0/benchmark/levenshtein/speed.rbnu[require 'benchmark/ips' require 'did_you_mean' require 'did_you_mean/levenshtein' STR1, STR2 = "user_signed_in?", "user_logged_in?" Benchmark.ips do |x| x.report "enumerable" do DidYouMean::Levenshtein.before_distance STR1, STR2 end x.report "while" do DidYouMean::Levenshtein.after_distance STR1, STR2 end x.compare! end PK% ]ol=gems/did_you_mean-1.3.0/benchmark/levenshtein/memory_usage.rbnu[require 'memory_profiler' require 'did_you_mean/levenshtein' str1, str2 = "user_signed_in?", "user_logged_in?" report = MemoryProfiler.report do 80.times do DidYouMean::Levenshtein.distance str1, str2 end end report.pretty_print PK% ]&&n($$7gems/did_you_mean-1.3.0/benchmark/jaro_winkler/speed.rbnu[require 'benchmark/ips' require 'did_you_mean' Benchmark.ips do |x| x.report "before" do DidYouMean::Jaro.before_distance "user_signed_in?", "user_logged_in?" end x.report "after" do DidYouMean::Jaro.after_distance "user_signed_in?", "user_logged_in?" end x.compare! end PK% ]2>gems/did_you_mean-1.3.0/benchmark/jaro_winkler/memory_usage.rbnu[require 'memory_profiler' require 'did_you_mean/jaro_winkler' str1, str2 = "user_signed_in?", "user_logged_in?" report = MemoryProfiler.report do 80.times do DidYouMean::Jaro.distance str1, str2 end end report.pretty_print PK% ]ӯK1gems/did_you_mean-1.3.0/benchmark/memory_usage.rbnu[# frozen-string-literal: true require 'memory_profiler' require 'did_you_mean' # public def foo; end # error = (self.fooo rescue $!) # executable = -> { error.to_s } METHODS = ''.methods INPUT = 'start_with?' collection = DidYouMean::SpellChecker.new(dictionary: METHODS) executable = proc { collection.correct(INPUT) } GC.disable MemoryProfiler.report { 100.times(&executable) }.pretty_print PK% ]rr2gems/did_you_mean-1.3.0/doc/changelog_generator.rbnu[require 'octokit' require 'reverse_markdown' require 'erb' class ChangeLogGenerator attr :repository, :template_path, :changelog_path def initialize(repository, template_path: "CHANGELOG.md.erb", changelog_path: "CHANGELOG.md") @repository = repository @template_path = template_path @changelog_path = changelog_path end def generate_and_save! changelog_in_md = ERB.new(template).result(binding) changelog_in_html = Octokit.markdown(changelog_in_md, context: repository, mode: "gfm") File.open(changelog_path, 'w') do |file| file.write ReverseMarkdown.convert(changelog_in_html, github_flavored: true) end end private def template open("#{__dir__}/#{template_path}").read end def releases @releases ||= Octokit.releases(repository) end end ChangeLogGenerator.new("yuki24/did_you_mean").generate_and_save! PK% ]ݪ,gems/did_you_mean-1.3.0/doc/CHANGELOG.md.erbnu[<% releases.each do |release| %> ## [<%= release.name %>](https://github.com/<%= repository %>/tree/<%= release.tag_name %>) _released at <%= release.published_at %>_ <%= release.body.gsub(/\r\n/, "\n") %> <% end %> PK% ]m2_ +gems/did_you_mean-1.3.0/lib/did_you_mean.rbnu[require "did_you_mean/version" require "did_you_mean/core_ext/name_error" require "did_you_mean/spell_checker" require 'did_you_mean/spell_checkers/name_error_checkers' require 'did_you_mean/spell_checkers/method_name_checker' require 'did_you_mean/spell_checkers/key_error_checker' require 'did_you_mean/spell_checkers/null_checker' require "did_you_mean/formatters/plain_formatter" # The +DidYouMean+ gem adds functionality to suggest possible method/class # names upon errors such as +NameError+ and +NoMethodError+. In Ruby 2.3 or # later, it is automatically activated during startup. # # @example # # methosd # # => NameError: undefined local variable or method `methosd' for main:Object # # Did you mean? methods # # method # # OBject # # => NameError: uninitialized constant OBject # # Did you mean? Object # # @full_name = "Yuki Nishijima" # first_name, last_name = full_name.split(" ") # # => NameError: undefined local variable or method `full_name' for main:Object # # Did you mean? @full_name # # @@full_name = "Yuki Nishijima" # @@full_anme # # => NameError: uninitialized class variable @@full_anme in Object # # Did you mean? @@full_name # # full_name = "Yuki Nishijima" # full_name.starts_with?("Y") # # => NoMethodError: undefined method `starts_with?' for "Yuki Nishijima":String # # Did you mean? start_with? # # hash = {foo: 1, bar: 2, baz: 3} # hash.fetch(:fooo) # # => KeyError: key not found: :fooo # # Did you mean? :foo # # # == Disabling +did_you_mean+ # # Occasionally, you may want to disable the +did_you_mean+ gem for e.g. # debugging issues in the error object itself. You can disable it entirely by # specifying +--disable-did_you_mean+ option to the +ruby+ command: # # $ ruby --disable-did_you_mean -e "1.zeor?" # -e:1:in `
': undefined method `zeor?' for 1:Integer (NameError) # # When you do not have direct access to the +ruby+ command (e.g. # +rails console+, +irb+), you could applyoptions using the +RUBYOPT+ # environment variable: # # $ RUBYOPT='--disable-did_you_mean' irb # irb:0> 1.zeor? # # => NoMethodError (undefined method `zeor?' for 1:Integer) # # # == Getting the original error message # # Sometimes, you do not want to disable the gem entirely, but need to get the # original error message without suggestions (e.g. testing). In this case, you # could use the +#original_message+ method on the error object: # # no_method_error = begin # 1.zeor? # rescue NoMethodError => error # error # end # # no_method_error.message # # => NoMethodError (undefined method `zeor?' for 1:Integer) # # Did you mean? zero? # # no_method_error.original_message # # => NoMethodError (undefined method `zeor?' for 1:Integer) # module DidYouMean # Map of error types and spell checker objects. SPELL_CHECKERS = Hash.new(NullChecker) SPELL_CHECKERS.merge!({ "NameError" => NameErrorCheckers, "NoMethodError" => MethodNameChecker, "KeyError" => KeyErrorChecker }) NameError.prepend DidYouMean::Correctable KeyError.prepend DidYouMean::Correctable # Returns the currenctly set formatter. By default, it is set to +DidYouMean::Formatter+. def self.formatter @@formatter end # Updates the primary formatter used to format the suggestions. def self.formatter=(formatter) @@formatter = formatter end self.formatter = PlainFormatter.new end PK% ]aɣ))8gems/did_you_mean-1.3.0/lib/did_you_mean/jaro_winkler.rbnu[module DidYouMean module Jaro module_function def distance(str1, str2) str1, str2 = str2, str1 if str1.length > str2.length length1, length2 = str1.length, str2.length m = 0.0 t = 0.0 range = (length2 / 2).floor - 1 range = 0 if range < 0 flags1 = 0 flags2 = 0 # Avoid duplicating enumerable objects str1_codepoints = str1.codepoints str2_codepoints = str2.codepoints i = 0 while i < length1 last = i + range j = (i >= range) ? i - range : 0 while j <= last if flags2[j] == 0 && str1_codepoints[i] == str2_codepoints[j] flags2 |= (1 << j) flags1 |= (1 << i) m += 1 break end j += 1 end i += 1 end k = i = 0 while i < length1 if flags1[i] != 0 j = index = k k = while j < length2 index = j break(j + 1) if flags2[j] != 0 j += 1 end t += 1 if str1_codepoints[i] != str2_codepoints[index] end i += 1 end t = (t / 2).floor m == 0 ? 0 : (m / length1 + m / length2 + (m - t) / m) / 3 end end module JaroWinkler WEIGHT = 0.1 THRESHOLD = 0.7 module_function def distance(str1, str2) jaro_distance = Jaro.distance(str1, str2) if jaro_distance > THRESHOLD codepoints2 = str2.codepoints prefix_bonus = 0 i = 0 str1.each_codepoint do |char1| char1 == codepoints2[i] && i < 4 ? prefix_bonus += 1 : break i += 1 end jaro_distance + (prefix_bonus * WEIGHT * (1 - jaro_distance)) else jaro_distance end end end end PK% ] Mgems/did_you_mean-1.3.0/lib/did_you_mean/experimental/ivar_name_correction.rbnu[# frozen-string-literal: true require 'did_you_mean' module DidYouMean module Experimental #:nodoc: class IvarNameCheckerBuilder #:nodoc: attr_reader :original_checker def initialize(original_checker) #:nodoc: @original_checker = original_checker end def new(no_method_error) #:nodoc: IvarNameChecker.new(no_method_error, original_checker: @original_checker) end end class IvarNameChecker #:nodoc: REPLS = { "(irb)" => -> { Readline::HISTORY.to_a.last } } TRACE = TracePoint.trace(:raise) do |tp| e = tp.raised_exception if SPELL_CHECKERS.include?(e.class.to_s) && !e.instance_variable_defined?(:@frame_binding) e.instance_variable_set(:@frame_binding, tp.binding) end end attr_reader :original_checker def initialize(no_method_error, original_checker: ) @original_checker = original_checker.new(no_method_error) @location = no_method_error.backtrace_locations.first @ivar_names = no_method_error.frame_binding.receiver.instance_variables end def corrections original_checker.corrections + ivar_name_corrections end def ivar_name_corrections @ivar_name_corrections ||= SpellChecker.new(dictionary: @ivar_names).correct(receiver_name.to_s) end private def receiver_name return unless @original_checker.receiver.nil? abs_path = @location.absolute_path lineno = @location.lineno /@(\w+)*\.#{@original_checker.method_name}/ =~ line(abs_path, lineno).to_s && $1 end def line(abs_path, lineno) if REPLS[abs_path] REPLS[abs_path].call elsif File.exist?(abs_path) File.open(abs_path) do |file| file.detect { file.lineno == lineno } end end end end end NameError.send(:attr, :frame_binding) SPELL_CHECKERS['NoMethodError'] = Experimental::IvarNameCheckerBuilder.new(SPELL_CHECKERS['NoMethodError']) end PK% ]wTgems/did_you_mean-1.3.0/lib/did_you_mean/experimental/initializer_name_correction.rbnu[# frozen-string-literal: true require 'did_you_mean/levenshtein' module DidYouMean module Experimental module InitializerNameCorrection def method_added(name) super distance = Levenshtein.distance(name.to_s, 'initialize') if distance != 0 && distance <= 2 warn "warning: #{name} might be misspelled, perhaps you meant initialize?" end end end ::Class.prepend(InitializerNameCorrection) end end PK% ]Z-**3gems/did_you_mean-1.3.0/lib/did_you_mean/version.rbnu[module DidYouMean VERSION = "1.3.0" end PK% ]#yy8gems/did_you_mean-1.3.0/lib/did_you_mean/experimental.rbnu[require 'did_you_mean/experimental/initializer_name_correction' require 'did_you_mean/experimental/ivar_name_correction' PK% ]?Naa7gems/did_you_mean-1.3.0/lib/did_you_mean/levenshtein.rbnu[module DidYouMean module Levenshtein # :nodoc: # This code is based directly on the Text gem implementation # Copyright (c) 2006-2013 Paul Battley, Michael Neumann, Tim Fletcher. # # Returns a value representing the "cost" of transforming str1 into str2 def distance(str1, str2) n = str1.length m = str2.length return m if n.zero? return n if m.zero? d = (0..m).to_a x = nil # to avoid duplicating an enumerable object, create it outside of the loop str2_codepoints = str2.codepoints str1.each_codepoint.with_index(1) do |char1, i| j = 0 while j < m cost = (char1 == str2_codepoints[j]) ? 0 : 1 x = min3( d[j+1] + 1, # insertion i + 1, # deletion d[j] + cost # substitution ) d[j] = i i = x j += 1 end d[m] = x end x end module_function :distance private # detects the minimum value out of three arguments. This method is # faster than `[a, b, c].min` and puts less GC pressure. # See https://github.com/yuki24/did_you_mean/pull/1 for a performance # benchmark. def min3(a, b, c) if a < b && a < c a elsif b < c b else c end end module_function :min3 end end PK% ]<?gems/did_you_mean-1.3.0/lib/did_you_mean/core_ext/name_error.rbnu[module DidYouMean module Correctable def original_message method(:to_s).super_method.call end def to_s msg = super.dup if !cause.respond_to?(:corrections) || cause.corrections.empty? msg << DidYouMean.formatter.message_for(corrections) end msg rescue super end def corrections @corrections ||= spell_checker.corrections end def spell_checker SPELL_CHECKERS[self.class.to_s].new(self) end end end PK% ] 3gems/did_you_mean-1.3.0/lib/did_you_mean/verbose.rbnu[require 'did_you_mean' require 'did_you_mean/formatters/verbose_formatter' DidYouMean.formatter = DidYouMean::VerboseFormatter.new PK% ]m,,9gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checker.rbnu[# frozen-string-literal: true require "did_you_mean/levenshtein" require "did_you_mean/jaro_winkler" module DidYouMean class SpellChecker def initialize(dictionary: ) @dictionary = dictionary end def correct(input) input = normalize(input) threshold = input.length > 3 ? 0.834 : 0.77 words = @dictionary.select {|word| JaroWinkler.distance(normalize(word), input) >= threshold } words.reject! {|word| input == word.to_s } words.sort_by! {|word| JaroWinkler.distance(word.to_s, input) } words.reverse! # Correct mistypes threshold = (input.length * 0.25).ceil corrections = words.select {|c| Levenshtein.distance(normalize(c), input) <= threshold } # Correct misspells if corrections.empty? corrections = words.select do |word| word = normalize(word) length = input.length < word.length ? input.length : word.length Levenshtein.distance(word, input) < length end.first(1) end corrections end private def normalize(str_or_symbol) #:nodoc: str = if str_or_symbol.is_a?(String) str_or_symbol.dup else str_or_symbol.to_s end str.downcase! str.tr!("@", "") str end end end PK% ]k=8Ngems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/method_name_checker.rbnu[require "did_you_mean/spell_checker" module DidYouMean class MethodNameChecker attr_reader :method_name, :receiver NAMES_TO_EXCLUDE = { NilClass => nil.methods } NAMES_TO_EXCLUDE.default = [] # +MethodNameChecker::RB_RESERVED_WORDS+ is the list of reserved words in # Ruby that take an argument. Unlike # +VariableNameChecker::RB_RESERVED_WORDS+, those reserved words reqquires # an argument, and a +NoMethodError+ is raised due to the presence of the # argument. # # The +MethodNameChecker+ will use this list to suggest a reversed word if # a +NoMethodError+ is raised and found closest matches. # # Also see +VariableNameChecker::RB_RESERVED_WORDS+. RB_RESERVED_WORDS = %i( alias case def defined? elsif end ensure for rescue super undef unless until when while yield ) def initialize(exception) @method_name = exception.name @receiver = exception.receiver @private_call = exception.respond_to?(:private_call?) ? exception.private_call? : false end def corrections @corrections ||= SpellChecker.new(dictionary: RB_RESERVED_WORDS + method_names).correct(method_name) - NAMES_TO_EXCLUDE[@receiver.class] end def method_names method_names = receiver.methods + receiver.singleton_methods method_names += receiver.private_methods if @private_call method_names.uniq! method_names end end end PK% ](F66Lgems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/key_error_checker.rbnu[require "did_you_mean/spell_checker" module DidYouMean class KeyErrorChecker def initialize(key_error) @key = key_error.key @keys = key_error.receiver.keys end def corrections @corrections ||= SpellChecker.new(dictionary: @keys).correct(@key).map(&:inspect) end end end PK% ] hhGgems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/null_checker.rbnu[module DidYouMean class NullChecker def initialize(*); end def corrections; [] end end end PK% ] ]]Ngems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/name_error_checkers.rbnu[require 'did_you_mean/spell_checkers/name_error_checkers/class_name_checker' require 'did_you_mean/spell_checkers/name_error_checkers/variable_name_checker' module DidYouMean class << (NameErrorCheckers = Object.new) def new(exception) case exception.original_message when /uninitialized constant/ ClassNameChecker when /undefined local variable or method/, /undefined method/, /uninitialized class variable/, /no member '.*' in struct/ VariableNameChecker else NullChecker end.new(exception) end end end PK% ]*w,dgems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rbnu[# frozen-string-literal: true require "did_you_mean/spell_checker" module DidYouMean class VariableNameChecker attr_reader :name, :method_names, :lvar_names, :ivar_names, :cvar_names NAMES_TO_EXCLUDE = { 'foo' => [:fork, :for] } NAMES_TO_EXCLUDE.default = [] # +VariableNameChecker::RB_RESERVED_WORDS+ is the list of all reserved # words in Ruby. They could be declared like methods are, and a typo would # cause Ruby to raise a +NameError+ because of the way they are declared. # # The +:VariableNameChecker+ will use this list to suggest a reversed word # if a +NameError+ is raised and found closest matches, excluding: # # * +do+ # * +if+ # * +in+ # * +or+ # # Also see +MethodNameChecker::RB_RESERVED_WORDS+. RB_RESERVED_WORDS = %i( BEGIN END alias and begin break case class def defined? else elsif end ensure false for module next nil not redo rescue retry return self super then true undef unless until when while yield __LINE__ __FILE__ __ENCODING__ ) def initialize(exception) @name = exception.name.to_s.tr("@", "") @lvar_names = exception.respond_to?(:local_variables) ? exception.local_variables : [] receiver = exception.receiver @method_names = receiver.methods + receiver.private_methods @ivar_names = receiver.instance_variables @cvar_names = receiver.class.class_variables @cvar_names += receiver.class_variables if receiver.kind_of?(Module) end def corrections @corrections ||= SpellChecker .new(dictionary: (RB_RESERVED_WORDS + lvar_names + method_names + ivar_names + cvar_names)) .correct(name) - NAMES_TO_EXCLUDE[@name] end end end PK% ]`agems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rbnu[# frozen-string-literal: true require 'delegate' require "did_you_mean/spell_checker" module DidYouMean class ClassNameChecker attr_reader :class_name def initialize(exception) @class_name, @receiver, @original_message = exception.name, exception.receiver, exception.original_message end def corrections @corrections ||= SpellChecker.new(dictionary: class_names) .correct(class_name) .map(&:full_name) .reject {|qualified_name| @original_message.include?(qualified_name) } end def class_names scopes.flat_map do |scope| scope.constants.map do |c| ClassName.new(c, scope == Object ? "" : "#{scope}::") end end end def scopes @scopes ||= @receiver.to_s.split("::").inject([Object]) do |_scopes, scope| _scopes << _scopes.last.const_get(scope) end.uniq end class ClassName < SimpleDelegator attr :namespace def initialize(name, namespace = '') super(name) @namespace = namespace end def full_name self.class.new("#{namespace}#{__getobj__}") end end private_constant :ClassName end end PK% ]Fgems/did_you_mean-1.3.0/lib/did_you_mean/formatters/plain_formatter.rbnu[# frozen-string-literal: true module DidYouMean # The +DidYouMean::PlainFormatter+ is the basic, default formatter for the # gem. The formatter responds to the +message_for+ method and it returns a # human readable string. class PlainFormatter # Returns a human readable string that contains +corrections+. This # formatter is designed to be less verbose to not take too much screen # space while being helpful enough to the user. # # @example # # formatter = DidYouMean::PlainFormatter.new # # # displays suggestions in two lines with the leading empty line # puts formatter.message_for(["methods", "method"]) # # Did you mean? methods # method # # => nil # # # displays an empty line # puts formatter.message_for([]) # # # => nil # def message_for(corrections) corrections.empty? ? "" : "\nDid you mean? #{corrections.join("\n ")}" end end end PK% ] ӰHgems/did_you_mean-1.3.0/lib/did_you_mean/formatters/verbose_formatter.rbnu[# frozen-string-literal: true module DidYouMean # The +DidYouMean::VerboseFormatter+ uses extra empty lines to make the # suggestion stand out more in the error message. # # In order to activate the verbose formatter, # # @example # # OBject # # => NameError: uninitialized constant OBject # # Did you mean? Object # # require 'did_you_mean/verbose' # # OBject # # => NameError: uninitialized constant OBject # # # # Did you mean? Object # # # class VerboseFormatter # Returns a human readable string that contains +corrections+. This # formatter is designed to be less verbose to not take too much screen # space while being helpful enough to the user. # # @example # # formatter = DidYouMean::PlainFormatter.new # # puts formatter.message_for(["methods", "method"]) # # # Did you mean? methods # method # # # => nil # def message_for(corrections) return "" if corrections.empty? output = "\n\n Did you mean? ".dup output << corrections.join("\n ") output << "\n " end end end PK% ] !gems/net-telnet-0.2.0/LICENSE.txtnu[Ruby is copyrighted free software by Yukihiro Matsumoto . You can redistribute it and/or modify it under either the terms of the 2-clause BSDL (see the file BSDL), or the conditions below: 1. You may make and give away verbatim copies of the source form of the software without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may modify your copy of the software in any way, provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or by allowing the author to include your modifications in the software. b) use the modified software only within your corporation or organization. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 3. You may distribute the software in object code or binary form, provided that you do at least ONE of the following: a) distribute the binaries and library files of the software, together with instructions (in the manual page or equivalent) on where to get the original distribution. b) accompany the distribution with the machine-readable source of the software. c) give non-standard binaries non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 4. You may modify and include the part of the software into any other software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under these terms. For the list of those files and their copying conditions, see the file LEGAL. 5. The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the copyright of the software, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this software. 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. PK% ]V__gems/net-telnet-0.2.0/Gemfilenu[source 'https://rubygems.org' # Specify your gem's dependencies in net-telnet.gemspec gemspec PK% ]nn(gems/net-telnet-0.2.0/net-telnet.gemspecnu[# -*- encoding: utf-8 -*- # stub: net-telnet 0.2.0 ruby lib Gem::Specification.new do |s| s.name = "net-telnet".freeze s.version = "0.2.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["SHIBATA Hiroshi".freeze] s.bindir = "exe".freeze s.date = "2018-07-25" s.description = "Provides telnet client functionality.".freeze s.email = ["hsbt@ruby-lang.org".freeze] s.files = [".gitignore".freeze, ".travis.yml".freeze, "Gemfile".freeze, "LICENSE.txt".freeze, "README.md".freeze, "Rakefile".freeze, "bin/console".freeze, "bin/setup".freeze, "lib/net-telnet.rb".freeze, "lib/net/telnet.rb".freeze, "lib/net/telnet/version.rb".freeze, "net-telnet.gemspec".freeze] s.homepage = "https://github.com/ruby/net-telnet".freeze s.licenses = ["ruby".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) s.rubygems_version = "3.1.2".freeze s.summary = "Provides telnet client functionality.".freeze if s.respond_to? :specification_version then s.specification_version = 4 end if s.respond_to? :add_runtime_dependency then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end PK% ]77gems/net-telnet-0.2.0/Rakefilenu[require "bundler/gem_tasks" require 'rake/testtask' Rake::TestTask.new do |t| t.libs << "test" t.test_files = FileList['test/test_*.rb'] end task(default: :test) PK% ]ɷ׽F F gems/net-telnet-0.2.0/README.mdnu[# Net::Telnet [![Build Status](https://travis-ci.org/ruby/net-telnet.svg?branch=master)](https://travis-ci.org/ruby/net-telnet) Provides telnet client functionality. This class also has, through delegation, all the methods of a socket object (by default, a **TCPSocket**, but can be set by the **Proxy** option to ```new()```). This provides methods such as ```close()``` to end the session and ```sysread()``` to read data directly from the host, instead of via the ```waitfor()``` mechanism. Note that if you do use ```sysread()``` directly when in telnet mode, you should probably pass the output through ```preprocess()``` to extract telnet command sequences. ## Installation Add this line to your application's Gemfile: ```ruby gem 'net-telnet' ``` And then execute: $ bundle Or install it yourself as: $ gem install net-telnet ## Usage ### Log in and send a command, echoing all output to stdout ```ruby localhost = Net::Telnet::new("Host" => "localhost", "Timeout" => 10, "Prompt" => /[$%#>] \z/n) localhost.login("username", "password") { |c| print c } localhost.cmd("command") { |c| print c } localhost.close ``` ### Check a POP server to see if you have mail ```ruby pop = Net::Telnet::new("Host" => "your_destination_host_here", "Port" => 110, "Telnetmode" => false, "Prompt" => /^\+OK/n) pop.cmd("user " + "your_username_here") { |c| print c } pop.cmd("pass " + "your_password_here") { |c| print c } pop.cmd("list") { |c| print c } ``` ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment. To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). ## Contributing 1. Fork it ( https://github.com/ruby/net-telnet/fork ) 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create a new Pull Request PK% ]Gssgems/net-telnet-0.2.0/bin/setupnu[#!/bin/bash set -euo pipefail IFS=$'\n\t' bundle install # Do any other automated setup that you need to do here PK% ]V?OO!gems/net-telnet-0.2.0/bin/consolenu[#!/usr/bin/env ruby require "bundler/setup" require "net/telnet" # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. # (If you use this, don't forget to add pry to your Gemfile!) # require "pry" # Pry.start require "irb" IRB.start PK% ]]8HH'gems/net-telnet-0.2.0/lib/net/telnet.rbnu[# = net/telnet.rb - Simple Telnet Client Library # # Author:: Wakou Aoyama # Documentation:: William Webber and Wakou Aoyama # # This file holds the class Net::Telnet, which provides client-side # telnet functionality. # # For documentation, see Net::Telnet. # require "net/protocol" require "English" module Net # # == Net::Telnet # # Provides telnet client functionality. # # This class also has, through delegation, all the methods of a # socket object (by default, a +TCPSocket+, but can be set by the # +Proxy+ option to new()). This provides methods such as # close() to end the session and sysread() to read # data directly from the host, instead of via the waitfor() # mechanism. Note that if you do use sysread() directly # when in telnet mode, you should probably pass the output through # preprocess() to extract telnet command sequences. # # == Overview # # The telnet protocol allows a client to login remotely to a user # account on a server and execute commands via a shell. The equivalent # is done by creating a Net::Telnet class with the +Host+ option # set to your host, calling #login() with your user and password, # issuing one or more #cmd() calls, and then calling #close() # to end the session. The #waitfor(), #print(), #puts(), and # #write() methods, which #cmd() is implemented on top of, are # only needed if you are doing something more complicated. # # A Net::Telnet object can also be used to connect to non-telnet # services, such as SMTP or HTTP. In this case, you normally # want to provide the +Port+ option to specify the port to # connect to, and set the +Telnetmode+ option to false to prevent # the client from attempting to interpret telnet command sequences. # Generally, #login() will not work with other protocols, and you # have to handle authentication yourself. # # For some protocols, it will be possible to specify the +Prompt+ # option once when you create the Telnet object and use #cmd() calls; # for others, you will have to specify the response sequence to # look for as the Match option to every #cmd() call, or call # #puts() and #waitfor() directly; for yet others, you will have # to use #sysread() instead of #waitfor() and parse server # responses yourself. # # It is worth noting that when you create a new Net::Telnet object, # you can supply a proxy IO channel via the Proxy option. This # can be used to attach the Telnet object to other Telnet objects, # to already open sockets, or to any read-write IO object. This # can be useful, for instance, for setting up a test fixture for # unit testing. # # == Examples # # === Log in and send a command, echoing all output to stdout # # localhost = Net::Telnet::new("Host" => "localhost", # "Timeout" => 10, # "Prompt" => /[$%#>] \z/n) # localhost.login("username", "password") { |c| print c } # localhost.cmd("command") { |c| print c } # localhost.close # # # === Check a POP server to see if you have mail # # pop = Net::Telnet::new("Host" => "your_destination_host_here", # "Port" => 110, # "Telnetmode" => false, # "Prompt" => /^\+OK/n) # pop.cmd("user " + "your_username_here") { |c| print c } # pop.cmd("pass " + "your_password_here") { |c| print c } # pop.cmd("list") { |c| print c } # # == References # # There are a large number of RFCs relevant to the Telnet protocol. # RFCs 854-861 define the base protocol. For a complete listing # of relevant RFCs, see # http://www.omnifarious.org/~hopper/technical/telnet-rfc.html # class Telnet # :stopdoc: IAC = 255.chr # "\377" # "\xff" # interpret as command DONT = 254.chr # "\376" # "\xfe" # you are not to use option DO = 253.chr # "\375" # "\xfd" # please, you use option WONT = 252.chr # "\374" # "\xfc" # I won't use option WILL = 251.chr # "\373" # "\xfb" # I will use option SB = 250.chr # "\372" # "\xfa" # interpret as subnegotiation GA = 249.chr # "\371" # "\xf9" # you may reverse the line EL = 248.chr # "\370" # "\xf8" # erase the current line EC = 247.chr # "\367" # "\xf7" # erase the current character AYT = 246.chr # "\366" # "\xf6" # are you there AO = 245.chr # "\365" # "\xf5" # abort output--but let prog finish IP = 244.chr # "\364" # "\xf4" # interrupt process--permanently BREAK = 243.chr # "\363" # "\xf3" # break DM = 242.chr # "\362" # "\xf2" # data mark--for connect. cleaning NOP = 241.chr # "\361" # "\xf1" # nop SE = 240.chr # "\360" # "\xf0" # end sub negotiation EOR = 239.chr # "\357" # "\xef" # end of record (transparent mode) ABORT = 238.chr # "\356" # "\xee" # Abort process SUSP = 237.chr # "\355" # "\xed" # Suspend process EOF = 236.chr # "\354" # "\xec" # End of file SYNCH = 242.chr # "\362" # "\xf2" # for telfunc calls OPT_BINARY = 0.chr # "\000" # "\x00" # Binary Transmission OPT_ECHO = 1.chr # "\001" # "\x01" # Echo OPT_RCP = 2.chr # "\002" # "\x02" # Reconnection OPT_SGA = 3.chr # "\003" # "\x03" # Suppress Go Ahead OPT_NAMS = 4.chr # "\004" # "\x04" # Approx Message Size Negotiation OPT_STATUS = 5.chr # "\005" # "\x05" # Status OPT_TM = 6.chr # "\006" # "\x06" # Timing Mark OPT_RCTE = 7.chr # "\a" # "\x07" # Remote Controlled Trans and Echo OPT_NAOL = 8.chr # "\010" # "\x08" # Output Line Width OPT_NAOP = 9.chr # "\t" # "\x09" # Output Page Size OPT_NAOCRD = 10.chr # "\n" # "\x0a" # Output Carriage-Return Disposition OPT_NAOHTS = 11.chr # "\v" # "\x0b" # Output Horizontal Tab Stops OPT_NAOHTD = 12.chr # "\f" # "\x0c" # Output Horizontal Tab Disposition OPT_NAOFFD = 13.chr # "\r" # "\x0d" # Output Formfeed Disposition OPT_NAOVTS = 14.chr # "\016" # "\x0e" # Output Vertical Tabstops OPT_NAOVTD = 15.chr # "\017" # "\x0f" # Output Vertical Tab Disposition OPT_NAOLFD = 16.chr # "\020" # "\x10" # Output Linefeed Disposition OPT_XASCII = 17.chr # "\021" # "\x11" # Extended ASCII OPT_LOGOUT = 18.chr # "\022" # "\x12" # Logout OPT_BM = 19.chr # "\023" # "\x13" # Byte Macro OPT_DET = 20.chr # "\024" # "\x14" # Data Entry Terminal OPT_SUPDUP = 21.chr # "\025" # "\x15" # SUPDUP OPT_SUPDUPOUTPUT = 22.chr # "\026" # "\x16" # SUPDUP Output OPT_SNDLOC = 23.chr # "\027" # "\x17" # Send Location OPT_TTYPE = 24.chr # "\030" # "\x18" # Terminal Type OPT_EOR = 25.chr # "\031" # "\x19" # End of Record OPT_TUID = 26.chr # "\032" # "\x1a" # TACACS User Identification OPT_OUTMRK = 27.chr # "\e" # "\x1b" # Output Marking OPT_TTYLOC = 28.chr # "\034" # "\x1c" # Terminal Location Number OPT_3270REGIME = 29.chr # "\035" # "\x1d" # Telnet 3270 Regime OPT_X3PAD = 30.chr # "\036" # "\x1e" # X.3 PAD OPT_NAWS = 31.chr # "\037" # "\x1f" # Negotiate About Window Size OPT_TSPEED = 32.chr # " " # "\x20" # Terminal Speed OPT_LFLOW = 33.chr # "!" # "\x21" # Remote Flow Control OPT_LINEMODE = 34.chr # "\"" # "\x22" # Linemode OPT_XDISPLOC = 35.chr # "#" # "\x23" # X Display Location OPT_OLD_ENVIRON = 36.chr # "$" # "\x24" # Environment Option OPT_AUTHENTICATION = 37.chr # "%" # "\x25" # Authentication Option OPT_ENCRYPT = 38.chr # "&" # "\x26" # Encryption Option OPT_NEW_ENVIRON = 39.chr # "'" # "\x27" # New Environment Option OPT_EXOPL = 255.chr # "\377" # "\xff" # Extended-Options-List NULL = "\000" CR = "\015" LF = "\012" EOL = CR + LF REVISION = '$Id$' # :startdoc: # # Creates a new Net::Telnet object. # # Attempts to connect to the host (unless the Proxy option is # provided: see below). If a block is provided, it is yielded # status messages on the attempt to connect to the server, of # the form: # # Trying localhost... # Connected to localhost. # # +options+ is a hash of options. The following example lists # all options and their default values. # # host = Net::Telnet::new( # "Host" => "localhost", # default: "localhost" # "Port" => 23, # default: 23 # "Binmode" => false, # default: false # "Output_log" => "output_log", # default: nil (no output) # "Dump_log" => "dump_log", # default: nil (no output) # "Prompt" => /[$%#>] \z/n, # default: /[$%#>] \z/n # "Telnetmode" => true, # default: true # "Timeout" => 10, # default: 10 # # if ignore timeout then set "Timeout" to false. # "Waittime" => 0, # default: 0 # "Proxy" => proxy # default: nil # # proxy is Net::Telnet or IO object # ) # # The options have the following meanings: # # Host:: the hostname or IP address of the host to connect to, as a String. # Defaults to "localhost". # # Port:: the port to connect to. Defaults to 23. # # Binmode:: if false (the default), newline substitution is performed. # Outgoing LF is # converted to CRLF, and incoming CRLF is converted to LF. If # true, this substitution is not performed. This value can # also be set with the #binmode() method. The # outgoing conversion only applies to the #puts() and #print() # methods, not the #write() method. The precise nature of # the newline conversion is also affected by the telnet options # SGA and BIN. # # Output_log:: the name of the file to write connection status messages # and all received traffic to. In the case of a proper # Telnet session, this will include the client input as # echoed by the host; otherwise, it only includes server # responses. Output is appended verbatim to this file. # By default, no output log is kept. # # Dump_log:: as for Output_log, except that output is written in hexdump # format (16 bytes per line as hex pairs, followed by their # printable equivalent), with connection status messages # preceded by '#', sent traffic preceded by '>', and # received traffic preceded by '<'. By default, not dump log # is kept. # # Prompt:: a regular expression matching the host's command-line prompt # sequence. This is needed by the Telnet class to determine # when the output from a command has finished and the host is # ready to receive a new command. By default, this regular # expression is /[$%#>] \z/n. # # Telnetmode:: a boolean value, true by default. In telnet mode, # traffic received from the host is parsed for special # command sequences, and these sequences are escaped # in outgoing traffic sent using #puts() or #print() # (but not #write()). If you are using the Net::Telnet # object to connect to a non-telnet service (such as # SMTP or POP), this should be set to "false" to prevent # undesired data corruption. This value can also be set # by the #telnetmode() method. # # Timeout:: the number of seconds to wait before timing out both the # initial attempt to connect to host (in this constructor), # which raises a Net::OpenTimeout, and all attempts to read data # from the host, which raises a Net::ReadTimeout (in #waitfor(), # #cmd(), and #login()). The default value is 10 seconds. # You can disable the timeout by setting this value to false. # In this case, the connect attempt will eventually timeout # on the underlying connect(2) socket call with an # Errno::ETIMEDOUT error (but generally only after a few # minutes), but other attempts to read data from the host # will hang indefinitely if no data is forthcoming. # # Waittime:: the amount of time to wait after seeing what looks like a # prompt (that is, received data that matches the Prompt # option regular expression) to see if more data arrives. # If more data does arrive in this time, Net::Telnet assumes # that what it saw was not really a prompt. This is to try to # avoid false matches, but it can also lead to missing real # prompts (if, for instance, a background process writes to # the terminal soon after the prompt is displayed). By # default, set to 0, meaning not to wait for more data. # # Proxy:: a proxy object to used instead of opening a direct connection # to the host. Must be either another Net::Telnet object or # an IO object. If it is another Net::Telnet object, this # instance will use that one's socket for communication. If an # IO object, it is used directly for communication. Any other # kind of object will cause an error to be raised. # def initialize(options) # :yield: mesg @options = options @options["Host"] = "localhost" unless @options.has_key?("Host") @options["Port"] = 23 unless @options.has_key?("Port") @options["Prompt"] = /[$%#>] \z/n unless @options.has_key?("Prompt") @options["Timeout"] = 10 unless @options.has_key?("Timeout") @options["Waittime"] = 0 unless @options.has_key?("Waittime") unless @options.has_key?("Binmode") @options["Binmode"] = false else unless (true == @options["Binmode"] or false == @options["Binmode"]) raise ArgumentError, "Binmode option must be true or false" end end unless @options.has_key?("Telnetmode") @options["Telnetmode"] = true else unless (true == @options["Telnetmode"] or false == @options["Telnetmode"]) raise ArgumentError, "Telnetmode option must be true or false" end end @telnet_option = { "SGA" => false, "BINARY" => false } if @options.has_key?("Output_log") @log = File.open(@options["Output_log"], 'a+') @log.sync = true @log.binmode end if @options.has_key?("Dump_log") @dumplog = File.open(@options["Dump_log"], 'a+') @dumplog.sync = true @dumplog.binmode def @dumplog.log_dump(dir, x) # :nodoc: len = x.length addr = 0 offset = 0 while 0 < len if len < 16 line = x[offset, len] else line = x[offset, 16] end hexvals = line.unpack('H*')[0] hexvals += ' ' * (32 - hexvals.length) hexvals = format("%s %s %s %s " * 4, *hexvals.unpack('a2' * 16)) line = line.gsub(/[\000-\037\177-\377]/n, '.') printf "%s 0x%5.5x: %s%s\n", dir, addr, hexvals, line addr += 16 offset += 16 len -= 16 end print "\n" end end if @options.has_key?("Proxy") if @options["Proxy"].kind_of?(Net::Telnet) @sock = @options["Proxy"].sock elsif @options["Proxy"].kind_of?(IO) @sock = @options["Proxy"] else raise "Error: Proxy must be an instance of Net::Telnet or IO." end else message = "Trying " + @options["Host"] + "...\n" yield(message) if block_given? @log.write(message) if @options.has_key?("Output_log") @dumplog.log_dump('#', message) if @options.has_key?("Dump_log") begin if @options["Timeout"] == false @sock = TCPSocket.open(@options["Host"], @options["Port"]) else Timeout.timeout(@options["Timeout"], Net::OpenTimeout) do @sock = TCPSocket.open(@options["Host"], @options["Port"]) end end rescue Net::OpenTimeout raise Net::OpenTimeout, "timed out while opening a connection to the host" rescue @log.write($ERROR_INFO.to_s + "\n") if @options.has_key?("Output_log") @dumplog.log_dump('#', $ERROR_INFO.to_s + "\n") if @options.has_key?("Dump_log") raise end @sock.sync = true @sock.binmode message = "Connected to " + @options["Host"] + ".\n" yield(message) if block_given? @log.write(message) if @options.has_key?("Output_log") @dumplog.log_dump('#', message) if @options.has_key?("Dump_log") end end # initialize # The socket the Telnet object is using. Note that this object becomes # a delegate of the Telnet object, so normally you invoke its methods # directly on the Telnet object. attr_reader :sock # Set telnet command interpretation on (+mode+ == true) or off # (+mode+ == false), or return the current value (+mode+ not # provided). It should be on for true telnet sessions, off if # using Net::Telnet to connect to a non-telnet service such # as SMTP. def telnetmode(mode = nil) case mode when nil @options["Telnetmode"] when true, false @options["Telnetmode"] = mode else raise ArgumentError, "argument must be true or false, or missing" end end # Turn telnet command interpretation on (true) or off (false). It # should be on for true telnet sessions, off if using Net::Telnet # to connect to a non-telnet service such as SMTP. def telnetmode=(mode) if (true == mode or false == mode) @options["Telnetmode"] = mode else raise ArgumentError, "argument must be true or false" end end # Turn newline conversion on (+mode+ == false) or off (+mode+ == true), # or return the current value (+mode+ is not specified). def binmode(mode = nil) case mode when nil @options["Binmode"] when true, false @options["Binmode"] = mode else raise ArgumentError, "argument must be true or false" end end # Turn newline conversion on (false) or off (true). def binmode=(mode) if (true == mode or false == mode) @options["Binmode"] = mode else raise ArgumentError, "argument must be true or false" end end # Preprocess received data from the host. # # Performs newline conversion and detects telnet command sequences. # Called automatically by #waitfor(). You should only use this # method yourself if you have read input directly using sysread() # or similar, and even then only if in telnet mode. def preprocess(string) # combine CR+NULL into CR string = string.gsub(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"] # combine EOL into "\n" string = string.gsub(/#{EOL}/no, "\n") unless @options["Binmode"] # remove NULL string = string.gsub(/#{NULL}/no, '') unless @options["Binmode"] string.gsub(/#{IAC}( [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]| [#{DO}#{DONT}#{WILL}#{WONT}] [#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}]| #{SB}[^#{IAC}]*#{IAC}#{SE} )/xno) do if IAC == $1 # handle escaped IAC characters IAC elsif AYT == $1 # respond to "IAC AYT" (are you there) self.write("nobody here but us pigeons" + EOL) '' elsif DO[0] == $1[0] # respond to "IAC DO x" if OPT_BINARY[0] == $1[1] @telnet_option["BINARY"] = true self.write(IAC + WILL + OPT_BINARY) else self.write(IAC + WONT + $1[1..1]) end '' elsif DONT[0] == $1[0] # respond to "IAC DON'T x" with "IAC WON'T x" self.write(IAC + WONT + $1[1..1]) '' elsif WILL[0] == $1[0] # respond to "IAC WILL x" if OPT_BINARY[0] == $1[1] self.write(IAC + DO + OPT_BINARY) elsif OPT_ECHO[0] == $1[1] self.write(IAC + DO + OPT_ECHO) elsif OPT_SGA[0] == $1[1] @telnet_option["SGA"] = true self.write(IAC + DO + OPT_SGA) else self.write(IAC + DONT + $1[1..1]) end '' elsif WONT[0] == $1[0] # respond to "IAC WON'T x" if OPT_ECHO[0] == $1[1] self.write(IAC + DONT + OPT_ECHO) elsif OPT_SGA[0] == $1[1] @telnet_option["SGA"] = false self.write(IAC + DONT + OPT_SGA) else self.write(IAC + DONT + $1[1..1]) end '' else '' end end end # preprocess # Read data from the host until a certain sequence is matched. # # If a block is given, the received data will be yielded as it # is read in (not necessarily all in one go), or nil if EOF # occurs before any data is received. Whether a block is given # or not, all data read will be returned in a single string, or again # nil if EOF occurs before any data is received. Note that # received data includes the matched sequence we were looking for. # # +options+ can be either a regular expression or a hash of options. # If a regular expression, this specifies the data to wait for. # If a hash, this can specify the following options: # # Match:: a regular expression, specifying the data to wait for. # Prompt:: as for Match; used only if Match is not specified. # String:: as for Match, except a string that will be converted # into a regular expression. Used only if Match and # Prompt are not specified. # Timeout:: the number of seconds to wait for data from the host # before raising a Timeout::Error. If set to false, # no timeout will occur. If not specified, the # Timeout option value specified when this instance # was created will be used, or, failing that, the # default value of 10 seconds. # Waittime:: the number of seconds to wait after matching against # the input data to see if more data arrives. If more # data arrives within this time, we will judge ourselves # not to have matched successfully, and will continue # trying to match. If not specified, the Waittime option # value specified when this instance was created will be # used, or, failing that, the default value of 0 seconds, # which means not to wait for more input. # FailEOF:: if true, when the remote end closes the connection then an # EOFError will be raised. Otherwise, defaults to the old # behaviour that the function will return whatever data # has been received already, or nil if nothing was received. # def waitfor(options) # :yield: recvdata time_out = @options["Timeout"] waittime = @options["Waittime"] fail_eof = @options["FailEOF"] if options.kind_of?(Hash) prompt = if options.has_key?("Match") options["Match"] elsif options.has_key?("Prompt") options["Prompt"] elsif options.has_key?("String") Regexp.new( Regexp.quote(options["String"]) ) end time_out = options["Timeout"] if options.has_key?("Timeout") waittime = options["Waittime"] if options.has_key?("Waittime") fail_eof = options["FailEOF"] if options.has_key?("FailEOF") else prompt = options end if time_out == false time_out = nil end line = '' buf = '' rest = '' until(prompt === line and not @sock.wait_readable(waittime)) unless @sock.wait_readable(time_out) raise Net::ReadTimeout, "timed out while waiting for more data" end begin c = @sock.readpartial(1024 * 1024) @dumplog.log_dump('<', c) if @options.has_key?("Dump_log") if @options["Telnetmode"] c = rest + c if Integer(c.rindex(/#{IAC}#{SE}/no) || 0) < Integer(c.rindex(/#{IAC}#{SB}/no) || 0) buf = preprocess(c[0 ... c.rindex(/#{IAC}#{SB}/no)]) rest = c[c.rindex(/#{IAC}#{SB}/no) .. -1] elsif pt = c.rindex(/#{IAC}[^#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]?\z/no) || c.rindex(/\r\z/no) buf = preprocess(c[0 ... pt]) rest = c[pt .. -1] else buf = preprocess(c) rest = '' end else # Not Telnetmode. # # We cannot use preprocess() on this data, because that # method makes some Telnetmode-specific assumptions. buf = rest + c rest = '' unless @options["Binmode"] if pt = buf.rindex(/\r\z/no) buf = buf[0 ... pt] rest = buf[pt .. -1] end buf.gsub!(/#{EOL}/no, "\n") end end @log.print(buf) if @options.has_key?("Output_log") line += buf yield buf if block_given? rescue EOFError # End of file reached raise if fail_eof if line == '' line = nil yield nil if block_given? end break end end line end # Write +string+ to the host. # # Does not perform any conversions on +string+. Will log +string+ to the # dumplog, if the Dump_log option is set. def write(string) length = string.length while 0 < length @sock.wait_writable @dumplog.log_dump('>', string[-length..-1]) if @options.has_key?("Dump_log") length -= @sock.syswrite(string[-length..-1]) end end # Sends a string to the host. # # This does _not_ automatically append a newline to the string. Embedded # newlines may be converted and telnet command sequences escaped # depending upon the values of telnetmode, binmode, and telnet options # set by the host. def print(string) string = string.gsub(/#{IAC}/no, IAC + IAC) if @options["Telnetmode"] if @options["Binmode"] self.write(string) else if @telnet_option["BINARY"] and @telnet_option["SGA"] # IAC WILL SGA IAC DO BIN send EOL --> CR self.write(string.gsub(/\n/n, CR)) elsif @telnet_option["SGA"] # IAC WILL SGA send EOL --> CR+NULL self.write(string.gsub(/\n/n, CR + NULL)) else # NONE send EOL --> CR+LF self.write(string.gsub(/\n/n, EOL)) end end end # Sends a string to the host. # # Same as #print(), but appends a newline to the string. def puts(string) self.print(string + "\n") end # Send a command to the host. # # More exactly, sends a string to the host, and reads in all received # data until is sees the prompt or other matched sequence. # # If a block is given, the received data will be yielded to it as # it is read in. Whether a block is given or not, the received data # will be return as a string. Note that the received data includes # the prompt and in most cases the host's echo of our command. # # +options+ is either a String, specified the string or command to # send to the host; or it is a hash of options. If a hash, the # following options can be specified: # # String:: the command or other string to send to the host. # Match:: a regular expression, the sequence to look for in # the received data before returning. If not specified, # the Prompt option value specified when this instance # was created will be used, or, failing that, the default # prompt of /[$%#>] \z/n. # Timeout:: the seconds to wait for data from the host before raising # a Timeout error. If not specified, the Timeout option # value specified when this instance was created will be # used, or, failing that, the default value of 10 seconds. # # The command or other string will have the newline sequence appended # to it. def cmd(options) # :yield: recvdata match = @options["Prompt"] time_out = @options["Timeout"] fail_eof = @options["FailEOF"] if options.kind_of?(Hash) string = options["String"] match = options["Match"] if options.has_key?("Match") time_out = options["Timeout"] if options.has_key?("Timeout") fail_eof = options["FailEOF"] if options.has_key?("FailEOF") else string = options end self.puts(string) if block_given? waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof}){|c| yield c } else waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof}) end end # Login to the host with a given username and password. # # The username and password can either be provided as two string # arguments in that order, or as a hash with keys "Name" and # "Password". # # This method looks for the strings "login" and "Password" from the # host to determine when to send the username and password. If the # login sequence does not follow this pattern (for instance, you # are connecting to a service other than telnet), you will need # to handle login yourself. # # The password can be omitted, either by only # provided one String argument, which will be used as the username, # or by providing a has that has no "Password" key. In this case, # the method will not look for the "Password:" prompt; if it is # sent, it will have to be dealt with by later calls. # # The method returns all data received during the login process from # the host, including the echoed username but not the password (which # the host should not echo). If a block is passed in, this received # data is also yielded to the block as it is received. def login(options, password = nil) # :yield: recvdata login_prompt = /[Ll]ogin[: ]*\z/n password_prompt = /[Pp]ass(?:word|phrase)[: ]*\z/n if options.kind_of?(Hash) username = options["Name"] password = options["Password"] login_prompt = options["LoginPrompt"] if options["LoginPrompt"] password_prompt = options["PasswordPrompt"] if options["PasswordPrompt"] else username = options end if block_given? line = waitfor(login_prompt){|c| yield c } if password line += cmd({"String" => username, "Match" => password_prompt}){|c| yield c } line += cmd(password){|c| yield c } else line += cmd(username){|c| yield c } end else line = waitfor(login_prompt) if password line += cmd({"String" => username, "Match" => password_prompt}) line += cmd(password) else line += cmd(username) end end line end # Closes the connection def close @sock.close end end # class Telnet end # module Net PK% ]>7C::/gems/net-telnet-0.2.0/lib/net/telnet/version.rbnu[module Net class Telnet VERSION = "0.2.0" end end PK% ][J¼'gems/net-telnet-0.2.0/lib/net-telnet.rbnu[require 'net/telnet' PK% ]D\\gems/bundler-1.17.2/exe/bundlernuȯ#!/usr/bin/ruby # frozen_string_literal: true load File.expand_path("../bundle", __FILE__) PK% ]'u"gems/bundler-1.17.2/exe/bundlenuȯ#!/usr/bin/ruby # frozen_string_literal: true # Exit cleanly from an early interrupt Signal.trap("INT") do Bundler.ui.debug("\n#{caller.join("\n")}") if defined?(Bundler) exit 1 end require "bundler" # Check if an older version of bundler is installed $LOAD_PATH.each do |path| next unless path =~ %r{/bundler-0\.(\d+)} && $1.to_i < 9 err = String.new err << "Looks like you have a version of bundler that's older than 0.9.\n" err << "Please remove your old versions.\n" err << "An easy way to do this is by running `gem cleanup bundler`." abort(err) end require "bundler/friendly_errors" Bundler.with_friendly_errors do require "bundler/cli" # Allow any command to use --help flag to show help for that command help_flags = %w[--help -h] help_flag_used = ARGV.any? {|a| help_flags.include? a } args = help_flag_used ? Bundler::CLI.reformatted_help_args(ARGV) : ARGV Bundler::CLI.start(args, :debug => true) end PK% ]I>>cache/rackup-2.1.0.gemnu[metadata.gz0000444000000000000000000000127114364637605013455 0ustar00wheelwheel00000000000000?cW]o0}0{S> ,1 @eC Pt&fclB۹ڮe+K+%>>>(拤?a BY,Ldc;([1ӣ(DGK K|kM R(+ {!|C}`_O(P5Bw'k"8GرeȀ>*GSRM* ZBd{ߍ#o4^+sK􅓶.m\ ;qoMWJ dll&mC^ĕ _gc*ګ+<)*ӲqUNFvRC[(/H&uIPٓNEՍF 9z$ uEQFzM_|4<4>RFY?%M?ä,o/2]snٴUn[;gD=| ;Ŷ 2T9.U1?t'Nɑ{&jlǬ[3^t~data.tar.gz0000444000000000000000000002611414364637605013376 0ustar00wheelwheel00000000000000?c}v7`.2!Pԇ/6%mIԐGM;jv9߾9o>}$[UqL4K(P*Tlwͷ⛯oOƃo6?zxu۸7l?' BT.g;T?ʽ(F {h,}0}=:v}iЏxl}X}YXs\GR~7}_pK#y[YāG_nmo=zy_+n|"w}8; ؁=n-}6 ls}ss_g%[;85ҥ廬 VKcPDBҧGH+7NKMu͚Ts%NJwaFOÇ[wܒ/Vpe/:Wwo*RGw,wB݅P؞[K>yf])g9Z[aKM<=w27jvN4S l#v_uZ1TD,sfIl(bȭΗbQ{ k~yD尙̠8[X+r4=6>| [f%meLa>_ș,1zPl@ )L"h#H@aCyO+@2&]I7,bb\ijkrvHx mwK( 3VuM-' GT8<7 sU O* :9%Jnlvwcӝ|_@8Jھqk+sz>ohGW4F0k:7ɞE* /#$ Y⛴P$Il/0&DϚDm Uc1@f:;h`C=N$o*~}]]Ds 'I ֘TcᓰҚܐ56wAނ~2²k$Efg ǖ[ˏ̋,eJ; 1&Gh׋Pld5d=ƞѓ Rg2 2ٔ\RU7$Ԭ4`d[xKl̵eMUK~Жc:Ͳk°Hl"gVpD>d+1nv(Ê0hd>@ѻs)' GsmK: &&rPAǐD *+l[nj3&YX1)MsmPp v8B]6.G6jRN9E! ~3m煂 n;'\@3Ō/=~UW_X~R2Y^)vGz9'vO&O1V.`F7,Yk;itZ}f_/ Vyc]cRUƒ^  RM6/sm ADV+% e?y_oz{_˱yR@Mc҆\.*`mVg/L ѿ ‰6F 0ݠf i;P`p< GA`\!O+4Eeک%PfVmD lUM=stvހ㮧ڽ^7ga[<uF!yurƞ, A5_Ɏ^3I׷އaBK ` [} 6q Fh @# mԮPVM7 ރI*.<zYʮW uVMf.l/ `OQinBPY]hͰgEEE2Tp:LӕWE7ƮJٿR*pD1W[ F+ꈛ=ciNsvFO·t<Ӽ,:/,Ǟ %v ޠU~fʨ{#Ԅspu粪ZYWg˸.=>5 G}u"2B<@ڋi67ih})!_ݨڮ0<, Z@c)^ЉycP(ڕBg϶-EH$ĐZ %}#tη%—Hxh'Y䞛 -ӪP3 OFTH"ϸ)ΌJ`l%u={(i.&`hi ^H6n.5=VN|&6oyh /,?1mҌ.0JۜhnEIBdH071AbP["0iPfR`Pօuk A^dj҃ãIzGᷰYr *F%z3YGY83"CĭoY2OI+"tݟҩͧ/nw +!@XiGx.;81fZL!dloXĂJT(yvO-"kܮvnm숕JX x:sWNc+ '"TfqΗuX tZ䇸SR X xiw())Ƃ/6zϫd4*b ف/=t Z1_)NET9D !XeO` j~l0**o@TCyk ~:YhYWBo9tQBˢřVNMABjwGO:q,o>PYR2.;T3$̽*(7vs,WԖMy XCV <2pE)" &>CZx4}vEB}(5@TT+0 NeWgIdŸ}{9n_|qwfOnq' 2}-dv%/؂Ōq`{BŁXJʆ/JGY*'ȵfNؔA{2v{lt_'b3Ӱԅhh_FVMGpAR+_b-jP_ˮD`Г׭l6Cȱo"J?*ͽ:oc|O,yh _zv A*+Wnͩ]-I4ڷ8QA{8rMֽnUͼ! PCk /8a&,b;nW@+#6#juGMd 5cTw7o>JN"\X>+B 2v(潏ͅswvWHP(Ҍh3P3߅|@AY /U~]A\-#2&0L[O^\Ԑ9SW\^ a1=-7B1\( 3dB|=G4GN˥t̬MBu4ZAtutU'rA稍!B؛r-̓.l=>hk w:G{``؃@¨%D쪔D`9 x -O3Vŗw޾k 5D5|xRK )+]=@9.gطaqXֽxqtʐnJn?uDGGNtKAGn#V[K0{t0 ?3sTcDetZS reIˣY6\c9Z:̧=#rg&>Eekѿ-kYΥH@n lm`^l<%85yהKcz [V gWT\QA2Q%O B:ZI ahYExF*b!X`#ÿQWE]m 7w] 'ZoۧX׵=K` Ju$A& *`e`}~V5 B'p e\4^[ttJ6X\g{S)>"%gLq퀖c媆;ܟͥZȬrq>:"0S*}(e<ª5D` {Iz+[ƄN!(G[K)ʚ ?VE=DdX E?R$[esT7kbUsUE2[eɸΒ9V1DM匯\ U=u7 E+ӭg*@"V 7rE߮Pr؏\ 잎.=ߙTN48u?%J'Kj/#B?&ur6Z"C1$̄b ҕ%sBxZaC賦bVIq F3H[jS_lUjQBx@n:3}u"3;3-,om z..зqjp 撒$6y0uHK5aA!ŵ{EMR8MA:k0$=VhljX8[uibp:UA aqlIٶp"ȴ?vv֖Z_o14iZS@:SkK@yF*p搓gO[+ix!} c@V֪* <d/6Afk\:t GC!^ѩJP^ڨToW/mDd"ݓ<*qm6Z-?z">.Jlu!gBBs] kxv1v GIְvP5yQ-i|F-4Ed& ={PʹiZj : `Zd;H 2X?SJ1ȋt*Pѵ~ITpUje}4Ѥ{Οԛի*,jc0~8Wɽ\$<53Nu_?]oλ Z ]O$QI;Mɤ,MXk5Y9=CB/-P<κ  @OkeMhq"Tu 1quuk{ آV&ҦsrᄚiXM׷մ$hGaZKk0^ _NŞͭLxcdɘ9PSQc=[} enOAX+a*9֞$#ȟu9̕D^J*3k-%a%(!h+(Q8Zc]* f4~*d3Zr +5ܛHt-beHE,2^h ^-|b^F(0J CrQ+1V2SLD܊R녶T&Ƴ CcaUNz7^1N۳DDY CR7yAK:#R`T.@ >6UjZ,6"u' PFnUt~LraJONUD@n?UYsb_3ClhUQﮐgٌ:K7[--sL_8anMa @3L&AG1PO|ў_6 5dK5jia,y14RBBr^ ?:W)5n55 yd8!+9dnn5gؓH 3͌r ÑB kݻyI+ԧQL/lAJ5{|AΣ閠֖P3gCt%0 B]*%iQ L#֌D^a{ >*FB9ka\!b+tp_aؼ4y=m8ՋGnN(KhddZ>Օ9=r)a>t kfMؓ\Nխa&Uŧok" .JW *cDrzq}dGKЉ"4sfu(Lw^CҖ^IW̠W }.j[%~n{=u>;^[YZ*뻦Q\n+xw>|85QHHs]hӓ*Е<{nB$*gA X)HS$>6[/e&[#f@jE)`Sɭ~gpL4ĆҽQnt!ʋ8_մD` w3x'ОZ$:U 6٠`Pe[ Sc0Bޣ[zGh t@>:;(f5VY}OΤq[#۵%3x8AQG`Fv8ԖTUPr8Q/^LP.mCyK2 jk9_U槉Zy* *+R<:m0g<G8CL!I??*E*ԛ3bd'a`':9b &8"H_6Zd%}gثU-2S6 ~ A2Ŧɖ|=S: k(ꋿe+nKFgЁ%7XX$\ 'uDܛ1/U(ƥL\jq1 ԛƺrŕ.g9(s`F4I;`>y& =&- 1iFߠ;Z08(zXƑ +kw_JI 9˾ad?&Hv!vSIUż*J~ZֿsrNE$,zqV1Q#p#^N/lW>7.Dko*dYtU@ԔdbkI+RiT%54J\[uqSKFxSGJPJ0Y9S0tkeW<wDpBT,u}/ WϋµT73l.ݩO{vo\`R^C|h\5ii% a恧0I=),NW٠T_eƶ/qЊs|]iM"n}'3^'&aЯmЬ}&Nnr1A".d-Y4{0䵹%ƒsw 5p$D<>YOW9}/אD2N+E<T)W12M' q쒆+qt(K,5 ʫDH2SZfH{ I)}g6"#64raEx3wbSͽ-s97뛛[-(;]t0fc^8yO^7ͭ)Gͥ돀ן/pkƎxtnw`ءW[}[Ÿm,t)@ƺhY.۱B]gg_qƣX;"^0,vy>&{cl u r#>z9`8֚ y`e{{HlAW"Y~v" <,uP  X̑ Hl1ޙB1Or3D'2Š<Ä~ [+HMKq72$ IY/kkurJ2*8H#VՇ .{ 7= (Auu*ӰDӬ&66=0#Qxfhէ-؀75N`@/ $h(ID7/gJSl Q%]S6\!hJe  *PdVeQ0KU!8!KO%-_Pj`g۬}9xYu{swݷdMh?>JNuvbo5w@wF]ʦ:>6vcks|^vGnq7=hq߆٣KR6Wx0jup]ZovzWL}Z;m j9aUju^ v~_a-owf9 ?ӃGLyUw:k+=PK@hI͌|~o vcen|<]&ol}a\8L'6(>1*l_$ZUqsDɽ$7- JnP}M|OEcv`m;ȚFpqVEn\=˗VVXmD!`?oSn?,:Rf0a}r}odF҅yϜ4қJ:|\cX˅MHBߤyH>6i@*^+]oNWeC!+Jo16aP\Ĉ@X#̀P*͗.\pk}lh*T(YҚL@e V߂Q0Sچ <%!yLqԪ(OǑ_q6 ߗ+{ `n Nk72:)ZC checksums.yaml.gz0000444000000000000000000000045014364637605014621 0ustar00wheelwheel00000000000000?ce=V@"o[ZRyz7)cfn e^ׯNJ{|^c$A+42a0hn)rmV{|?y3=}kMG^ThLFW]f)|"DeYK ljZu-iPGdu3q/jRF3m.4цaBZoN+9p-^r.qTm2KuBYN35GS?`R὎[I[@8As*u_~ PK% ]"cache/rack-3.0.8.gemnu[metadata.gz0000444000000000000000000000230414442217575013450 0ustar00wheelwheel00000000000000}dX[OF~%-!meQ Y$B>=ݹsaYo,]9gfss>1b7(]v 2ˮ(q"E%dr݂(&ԩ"B6F/Y]HDԻZE19Z KnTPi{n 7Q eM9n˯_ijo⯏l?1h@1P%17kDy)CADrS^=x Yڄdn -5 U *,<=߂`XǕ9aٹW#4ƾ 0߆%|Gf`K @+AYrT6IyA hh!p,h =VP4qmK5YTy{ssMʶ CXZ\6 ȊIxx3[Dž˳M,A janV,9zVgHnȗ:.p^`UpZch,HaHL"`nO"ҷl;*`hhn. y7O$'o/NO7Wg9h%5OM|~v2$~HIL) "EKk6}Vl jy9`ڱӤܣUZGP̽c0l㥸[ 6 CImIGY{6j)]U}4ҳpwppWB(kTп* #dh38:D-a 'hhVe"+9Q OYt^lJ.GAOTzPXn<@noH|" 1]05r #y{|*(;a`o*\5~+7NE0ᜭ ip гSZAΏ45{ل30荐 qF GrZBC+$ sҴE6$T0#GX8 U:L ߿SʭD2|S&EM8T5t=iGF:j]93Z{SB^jO#8, ֪kC̢v.l`a,=kȾksar̶AT $m "6~Y^)$<Yd(^Jj98cLbSp_u:(data.tar.gz0000444000000000000000000031257414442217575013403 0ustar00wheelwheel00000000000000}dvٕ6QT-2ML)DIY_"@$GHAUV?{ܫ=Iz7'%]]UL"7^nO+t#t[[{{~gkoAyfqMiQp4Q4IGd$i&QHb,KEpS^ |%E4D I^2L4 4,z=w Qy'l>lF3hEt& ҢvG;nO{;?i<.%x(Â8y-u8Ωu=9:]^a2o~}O" wE.g`شk]E43ky5<5nP|[mt>'I9t>)bZqq][\N)mVo`[Eb־?vkwwo?'INk3ERߝ:\/IEuoQD?쥾۟t{r{۠䲸7'I,9.o+ U7Mx<{N"˜}eiF~DE؁PGϳppBKMo,D&R< G!`^:N[|:)AlWVL<G룳wWﮮ~m`ǟfo#Bq[Zp< D@x *s`*M_=tfOԧ^6=>|x#D8}κ<'pLҤ5fYAWtHMQyN;9JЎ}_ݨ_g~yy<\'q`7=lQ$DODG{XuDX2!rk_E>&w< s,ƄZ(b^:іwx4;+19!g՝Wo$MoЛMs~ۮB$ 3+:*>dlӌ`hF=π0]&AHCfЍ}bXYXW.z϶v϶Vbbyʻpc^v*5ݕRv)gZو5!t8-<`{qI `WA)1z]4ml^ E[;{]Ԯo\Wf3:-ք?0KDIo%IR D#9WC:t ķ@Š.4OdZƸEכh3iNQJj^o߱uC({iIvO͘T)1fA 5Ƹ>(͉SX`# %dؠL~1 ֣^^x1aixr$wEq:B9$&,m<ށa]v4X#m8oK n6j}ܛ:"> ^] m׍oQw>qOl\$u넋n(4a //~w|q}~qvuvtvSRׯIx H .:Lܾƈ;/B=6dHO}&p:pN3\iס:D.IdѾu批cW概Y2- i:~? oyQM7b+_FP{8pl y@KJv ^QHP%(T^M1 MFn[OL- l< c ^A?0qy0 W8 tҔe#}tJ;#\9immxzI;8Q}?{ zÐ0u bCCeLd&ΕՖ=Sŷo[Ӯ(Cz).lԎN&ڎ~ƬK+hF({y)qkK4zƇ$ȏMET DԲ\A(0KNl4/T5JHu3ZˠI1dGX xu^~lWĉ>*l2*Y:6+%a,Vzq;~;]4rQt el9Ecz+aDC;hoxbxL[ӡS;- Kqcc1և1w %3"W,f<55>QS\&gh"$ϋޱ8 ֝gAwivG@3ľ!Lϸ~S[ͩb'l](#@r6jzU{2bg.0})Z0T,qzU|j=k1i0VQsRԮu?bf"YDm#!~^ v;v$p2՛.Ia}9,a*=<  SΉaNՎ2.P_ugPSB1I5PaEn,!7F0r!Ō;C }ݧ |vE4N [FbSBl?zh% h< &ÔE=jFЈz݃uV #E>8T)gG7aln:?ugۀԙvpu@JRp'}9]&k7Yz#ֳiڨ݆ȏTm S=K%Mh`TZwjY }UKѡjs0OkEcIg!4YcnZ \D 5{p"gxRVa)t=^~zDl_;3je '¦{SU;M7avO](xGOᒱx5{+cq@g~7E9!4ل"ΚO0̸֞Fb&LIo(H@/3bQ>>Ў7yxsЌA&<#nĬ6$2zt;vg Ɖ`ՓL ia&S1݊BCg{0k9XÐnb$@]P7Ě |"Һ6O=XXqƆFY.GPM8gO>m|r<&[_/YNR/̖0UHgNģRmo+߯;>w17J g*M|TԹ佁K^;$y@n?ºP+U* ,ɉS%i={qreJ'SVn#>M ,P}{;|{4]\i͙xe>} :x_aʺR50e(Ɯ@}*оKY6b&o)wğ! ]u3{| V7tYaWSG De5oO=h 0mDOOhhAbU6u^/e6Fi$ sUʚ8 ro։QAa/gEx4G0*kƗ@W^ bՒo ;V} ѷX)㍾S1۰}{׬]C1 yX5,KUHK-f)mʊ1cTqn}>;iT: Q:x,2͇Z!kzDx Wt旄*@ kK̈9"g_ rJZ{m˒K& oY^4.QTRb_l!k@|Ì7Ǔۧ`F 5O-< TBHٖH'G<)~ vv6t h((n6RV7uZ8E_@ u ~_Z`J ᘨG(V.\zPœp9<;4ZˍizP.tGnwꇗ郃wNޝ\d~~ww;L0%W ;o;Jn!Ur \DڈqF"1 FliDX&faMD4t 6|_fZ>)(LPr veg,1/d 3;z!ZSX.m5M/QJ>XE!a_"ć#*y!t-#`3PQCaφr?x vM<'q:W9^UnU (a0fct`kߋ4eè6J@ރܤXԅ\S"R:!2ßb=$i{{OOˣѺ/dp(^qzwlTFFbe8JZ%F}C^+aǠ ͒ ϵ~i%9N A(~5z/4F}yyzg r4k(m4!A$a-++$.7gF_Y3p&W]%8Vi :<4 GQ+ONeGI" %0OyXo>ȩʄItOk| Ϛ!\}HwcY/]/5ud4(qYSuT>mh=ُH:uqɻןӁ(V;|rNy՘<#3X`"dya`vIL-ð!K5d "G6^\d~px:Xo(f>Y(|O-E);v/q/(ψ?A9"&덡X`nTr9,_3h&ƞ/' aPH=q]TȖC/ib1 ۨ2@,2gMLuF"}:ƭ/La~,[gk$ Cp3LLR lwa/jW'zEbNņW{ f'7.3Q΄Ţ>$>,|8|˝9%\VD+qg;P8b2K7;#&4!wV h-QiVHon\SΊ . z}|G! ]~ /)~x-=UAx4-Zlne) LK84m bM>0Xnooz+s㽪Y>+$4?_$}…$u[8&.1@X]aE_kZ ߖY[6mAUxpw+c!֨Eo=)7/q!t..Z'-c22< l\2ꅲfaȬfp1A~=QsNqC,B[7]08[\Sޱ3&a.Q|W\}"N7$y:i/3*?^#*Sb&uYݕ4|xzz4\|!".7ܳwtչ'XrOD oq |XZ* Kj;_|J3xj-I zd%5np^s-mսF9QB+$:!}MQr#66s6i[8{ͫrh֯ˑBl}-I (!' 3xvq迢pcC_JZEdj Yjue|Mu[6cVZ冷bFf-[ƎJ }>WS( JQ}c HߊDCxs iny8ו=s7C: [o贊/j\[@3\|4IZ]9<[̤LdH }Yg8v==EKKW"E9~ 9(R A8A%+B^'ɉSE5{㞉?[zOm?8t*@+"(fjDN^rJ&ҵYY>YJVª2pz?{Ot E:~#vX+mTBtt=pBxnS|2bx`DXl+<:GF;^^7U ZNWX-2&Ǵ8Ze/UFka1\$fA#OqbI:,*jH8opOD٠DUt _õ̰YEZ/i4h =-:c1rnhXtN[ gC Lj>uyj>ɉ˪K7{nQm,=>tF NB|LhHC3yZ2 ͎"~dYDOjwjZ;[Kc?MB`& SP2pB ?le,nEc*;$)%B̗h121K8<&nһ(p7RPj\毹=NA6i:jJ*P }^MBHp2xjH])%|ّQZ8Ұ,Pq7ƒo#Ē/?fHV/.Lu?Q>iä"H|s87zD`9U\ȶ sf$Iж!"ͅZd|U1p֦EL!͢DM6"jz{Z ^8fɆK4R%rWY=$JE$,=6dgdzܜy4o$}*Zf-20lwj cj{ŠH[4 &dv˨T߽?=r8_^.fSXHlUoV'1vms"B$+zy 뛸;%=Og8D_F|};lPiio04@3`+Q4a<M4%ߧk|·+|/pVpdx##VE˨ѤtEX.Hu'їtz@K1k\ֈfz0tES!zj2To/ޭ`8\&IaƣMe,6EwypF""M"0% {7Ń&Sx1Qur|nZbLZdMIz5\jJ|+dip2= E rO5~at80 6f:lc[SA 1$rk3pX_7XN:-zwCy<]0M78Œ)&93M@?o(NRM.GzMLsøM5thu8Tܫ0ETĒE NSxRG^b /~0b0 4?hc*x=> o aBP#@mKNJHm?3G㶲OvY`6% ϑ^{w& eMH)H ]~'lba]ġ^cTezt&&cYkk4- aoVE=bNK(*JQˇ`v-Hi@^-61ջĞ_٫'Nz ož^.8Ðk]J.^&`Ua1. AJq X{FS"$u_]on.=0uck;oc#4 aڥ$Ϝ+˥Cɵ3瑘ljOVpb3GZN#kᖠ}Ko+42R؍\pB+ȗs$dRh Ns=e?B{+Nr^6~_Es&=W)Hp<0D4 `4JdG~=# !_W-}d$3}#W$Iœg;P.wG2l.d#bԕ5k{Y}_dN!x݉~S[ҊǝG32SZauǽ瑠°jfM,Ȯ@g7ӄ{2)2iB`ϋ] ~iJpNjã߾?:9?>=y{r!|v-c1)K~owo#xA? 5$U{8Ϻa,0 '*f}3;H6R}2IKAA̠EXXhA*\~HL4t9 Vg"uxtt|NCcsdMo30OZFL4rl*Oڣt k4\zj3c -͌%:o?ݒks>݅}^4Gsv^!<yms% oJs jHXOk?&k뛨L6 ?4H^IO i@xK gv 30=Ay xҙTn 3./N/%a%旰ñ4.M⅖SDT;vלtSy{XR򰌐C#พE~u2o#&)>IL\nggRXQ(4:]4aOA&Wo2\e2N#WiyRw/n;`1a[9%V@=9]tHQ D!Q9p _λI~:EgeFjm+<%Q0#f c<-%+AUDE{5;>I[2ꪂ3-W&1*0IwРAq- J*-恄VӕlaslL8O M&Ŏ@%^bү֔kRv<ȑ:Q:jBb=yƴWu8 z2bWZƙNgDʉ .,vvV8NәsڤD??SroN&; .q"E @G޶ /ٔחeRsVX7yu80uBj2s(Eih9Sޠ*9I'>=Z.iL{,]U5j{/>[f+p҆O8h<8T,H >yvHVM|}@ nzth8E~q㍟Jm=kj;Q1+J g1;D1[2h|a-쑗s64yRm)y_^ Z\.zR9Ѱkw.iQ`W2İ똑A1"[8F+Jrdb@@"~^`ё 籍a=UXO:۬VbPDrjW] z&4脮C6bjbU\BrLLPC0ۚG]W9)}֊uw;{u: #vvy]..2J& 7LJ/7IWyEV+qE&#M+azzqx iUMY@',).$%fޟbdi>x)|!pI ޽`e,YsKI$$Q:÷k]ZȔYY!%fW٭h9u2 ˮ`f.jDtxVeRΥ7bj,E vNJd*3#KAd/S-)6MX3=o\=qJs]}8͛DM)xN8'x\ڀY)1s:ѓ8ĆKZ6眓#iI3pDPU|K jQ_EiL "kŊ@#\m'!{DR0T׏R^]蝼 QuNFh Q%ׯ.>^y['PMud$eh ^<Ӽygq i0lnݵ>INMneMCt:;mc+$\rz) fğh%  77Vik8=Nk˙P`Znq fp *D&yGic$v!_p tW'+{G8%f@K]ˤ2zMA !jc-w³DzK Fb ߃uۤ#'1{; fmVF[m( S!/0Yܐ{acaůBDq.0s(m3UctNiۜҾJYRzYAq\{nyQ[<쯿mr^#Ӌ!ke65 53oc>R;dB&c_e9(]/rܢMGQV+]:aUt@Y]Έw"ByC2e)O./rR{E1n $jdz84. Pʾ0$Xr^\hշ!vZZ}rv #H.%{n?0ĤT&94Txivu [I>g-;a!%|R Nάcaֶ6F[lDg9]a"$@Lо(s1OMAc>9u\د7$(Mfm{zs] ɼv<(:bC+Of? ]`e4fδ?G>h?d|Bph L*-ߣW:q4 V-3gط7prk}w'*gcY`FYN6ív+A|֞69%f*q(\Epl_f ,XMֈVҞF-eG5Q8ZpF t`N+[q^iTNn\{!N-DVa]S=q}K {K bw9p)mGĵ x/g(9yz0l{miƒ.Qt)$ČhSPkDB$Y!syB%eWVU bS˺W.ReX#An~暹>A8Hv:+ |[/D= ~*IBH * =OqL=֐05xKsb6yb~Ü *P_QR#&V!)J$4oRᓶi0$4ȵ ʒ1SEQqnS6lڹ:RaY9#:|M_L\mHߪhՑ<[u4"Rk;%>_8!2ޥ8a=3,rć |ͳuy-LJMlPa3 .Did 7hf! %<'2|X0"vHnS3s"@h;B!iwLËt)IQ͎n5eW 2H%є=٬\n@|kiji ma}،)jT)b3LqUK^)N#ʔ.4ڛ\Fs\# #2Ѯή}Vhds;wc+|Z^iBϞ,+꛱H&dDN%% +7]վW5~S3.@ԊWcM6,ʱ>9+(}h+բIc3;5ڛ2Le8rutyEy[2j(jM5lC^h&zT^r#WsEQ NkŧrJF^ Py8EZjgr)q\ Fc/Xב gjd-U*!B`XցN}`C іɨ53U,dBYOTʸYQ4GG 8exG$0ZBydRx@Δ0g!0fC܀/7- 7yD3?u,Ml)+a4EQo9fDtPbӚ$ pXi tZ4;De\1pJ,H(wt,]EC<-/Ф  Oz^Oj!]ArFub(!* EcCgk ecW-x,1Z X"'eICv6L=N+vZ@hV"z﬋Hۧn5u%z۞>(?!vvUTFVͧG4XSIjJ;ltjOMV)t`qhOj˜n /}X+WΘ7'!LbBkr^`ON"kvxg!wm ¤~ ְPB^L1Zj~*u*st:?mbkwww{{koo"-`Z v_^1JܤPk4 'ι IRHr /}%]@U;7t8YyCyQza=m "5Ys0;g6Wޟ#;|e4i!Xv,ez81ķX2Xr7Tɰ$D4Sm7oa<V (U:#[ƍSq!zYH[,+L;3H%wYC`p.%/ vg۰ ڒ>^٩D\xu4 F֗"D=~J3Ͳ[C\+Oѓգ.h&P1{vmCma - %d xVm<V),WW5678y+HCks(MC>NZׇH,h`|$yJO\јM~FtQ+j6U|d>7&Ѭ]K-{ N}-ʌONe5IYLJ/ZUtV.6IGL/- iݯHZD/D&p6G" zFkd%9Tͽ~?Va<9z qQa$4;pIflu;ռۜ5jSv (5JZ߃Tom&RǜSp9F{14Bl$~8Bkn8o Y;a<Y8d1i6MF!`iEAM+s߽S?Pwj[( syUﹼMCWo˳WW/Gw'/_kZ3prU@-.] pe38epv8y{~zrL;:}S_PwgHBJ^P:9`o/l_89=xurc: YLOޟ^/.i4컓w.h4+./.Ǵ2*m3xy5rQ n& >9O  ~bVџMŕ^\b.hx&'ݱS JOMcLJ4%67n]_+縟o?%JnmO*o"/ g:k1RLnSWUADCǃ/[.Cr!Ɖv-ytS-FR,+H«xt3rQ4 M՚04-k[D$pҔa& x fP=Q؄ Vlu~2b?…-1܄(9O``"P>De`ĉIXzT!8l ,-# ? gĚ 5ZȗlMl;)Sb(s2n6IU}gGԊ6D''3A%61?ڴ{|$>?_ZpCk=WErFI.+4:e^r 2(h3qavK[b,^eEh5HRJ.W!ɦ8t<  ]Wx,hVs<a()8k3,t5OiS*1ӀxiG`?k3X4fڧO hRtn ]X"9z Аgt6= ?[Xu톷h{b%H4)Iέ^eG[R 7QZ_8Oloo3h*WTl96DDyU;PS7`8W_<E17i߽>y}!,xr "IH,03'\ΐ]g祪ŀ'y =q*K#݊0{&"6ޞy**6E|}m.-v6>i Q ~DvMXچS:p $GvX˧uW W<([Zph}lIZ %mDbRbpbLo"'69KR%/ϙK(KZT!7 ϔ0-F``~gj *)cNľS0e_\n3oy}Rŋ/SD aSR ,B]VTo wo$ƮzK^aɠ"UkfF5ː&aHQm|U]pMޏe}8|1ޅyo+6.E,xENv^_У3JCl6'y$/-P|tM|"/dE'gл"&C^H^"48r>$zF-IF"]uGz|"wV4B,dM`Qontv%rũLjP둊-Hb*`Ai8f"DCH4- EcЉ~Vo֞, PzyLVG4vy^P]gS!Mlqԕtr'; Df%t,{N3mpaND.Mo]X>tNĦwiz%Z^}'dAP,@GWM.(Oy}/b6=s+z3-Ӕ!@#,GP<38f-nӲeh4jE MͥhvN^,Fy=fzvAp46_}ȸ\m͆-91YjRiIKJ{NZN 5)ư"}5jooï,_e4ήOK :#o%]Lru+ aWHdXl h0nBgHmқ_>!4<\ͶqbJ6opm+#3nt4Iٙ_i$/(|lUSתImJR l]Y:0+L L<_J5 zJ 8I#[7W!gq.J @rHO!ϗ.TxzIE(vNvi71>;|1#kP^,j 0xQklq)MDqK6>o^]8Y6{ 0fX-0ԖJqTph6~VܯϦ*y8.0ۅ!Mk t%>9hkFO?095pDŽx#VcĿp-wL2|߃@0 O[" \8\sFr8Op N !P?`A?,= ?:V}?m035r֯yǘQ wHrHQA~Gǔ[G0NWu|D܇\0l~3\G) Ѩ%Fdc>3]3A 5ѥ Ag>f7 RUeA)WFf]J٫&O!JY |*1 ‚bz%Jӕ(NXG9_?9;LJ^I>!$W7򉴞DF0B{/! ?ߨu!sSD3[4[Bee^X?ZѩIN 9BG+c 6v"tiIEӫ~K;Oh} ī?i3x%7qpE{"Hܯ3ǥ~;^J'I?HZx1u"d9y*G|Lc.v 桻~KD<\ҡlvrjAV!GOi148#271/bѬ Fq9:T\:L8ъilRRL #TJC45%t̹p)AcBCu1b_QMVp$sVG|d۠a% -_gt=SCIq2.F"g$搄)~ē@#E(w43ʒbѪhی%s3R^85&MSBTmۤ+DTf/4kTu4UKU_QdNTroìO~dKJ`5!f@ ъ#h]構3 խZo P5 6`{ 䢠w }?7+p0]p9"PqU%HO^hĤZPh[OǞR62cPV~qk d KIbf:k${C2(uY:+ZdHٱ8,< ,bSnXv8\A(Im,yU Mʇ.Oڍ8s5T16O[MC%a~LT6>HHik@IO47pƱY=ŝO s{` 9J>,rq"V&mB ǎl n/)Iٟ)Jѭt>Kο~N,o8hSա6jRl`Tlɣ#k7-__˫Wo^~I? A>Zip Ip|p8Ef)?IVM9Τ9\',^𥉽l_>΃5aY?Snu+dYCI%h*dU58ϣ9xx{Ǻ9m)mtUoeiZ܅D)ć]?@( -zﱸCDWZ zŵkʁTo +Y2Z]~q(@땔n$!%=qӤ z!$WM+](@yVm?1m¢M{FA„Y0k){j|{P-RQ27ޯP"8gTx%a6WJ ,pG`+j$H\t8UY-+Ϛ@~e I. h&] ({< 0ںs7aK{6=}GU72\`qa6ൔrqvuvtvjcxDͥ>tfeH xr;3@OS=K[4=ƥB؃e:<} vnz/A|J,p`P-ϭц|r +W̬N4}az[IQ1d)T6a}i5s ŪSPY:``礒lr42 ?ijC};VG_] 3L753$E|Wݥ>'5 ؖl 0,jVRe\Ț*]s3vUd[rKjMJ&[nxe})rf& |0=Iڞ8Q@no D_x+D-牵mIY3t$aHYz&Z4Aݰ_=ߨjF6ø}1Bba{'Q\\nlX⁦%!e@|W&ϰtRDdWo>zxsT xkEo>$,7'ā]/Gc吲g(Mݎ, 82ڔ"p:3ha!*zPz8d%&(NJf^: vL/HG''( RhnzV5fxy &XyČ7p5;^8^Ww9RgzQ; cɩ_8`B}"שbNw2‰ՙ?c0q~5-x֎O&8>V/Fs0fIjM ݂E S; <[UUZҘh<Q]#+/7QH*"5t\mZ$9Vt+r5(e5uno%*;ZTi/o r>I.'µ>[i,KJהi jEL%@ s|GE]Io:G<4G >ӆzt(4{h $ѩFZwAgî8=J%pzlD SQSKPr$*zS{dI[V3-υd>D䬞 [C0П] :hVqjѱi3v}W1^@W$`8X-ҨbY .R*T-<;Yk彚w)rDE w0,MI(UsiS@eGDsdvi! WkE+jx7P@ƒb űQ~գv`OIþKIHN G } `" 捊˗ Pfmj<%IM(l9(͡jMet<6NJk'_LXmE2#ƻ]cI H*QvkJ)/-U d`ƛ]mV'otD[V֤oGmamYN`X0n/1K̓_}ݯ?|]_,(wTUaoq5G:N+ hMt]70K&?&5 ~+ђ9r)!vg%n͔"}}RirFuڠ~Z /y1LeugXX$;vF@ !PNj֐b$uAg,?*NVzax<2\lۭr{a2[1 3"1eTZ Fem@""*AmQ֛ٳ:g.a*L0砤uGt aϱI/Eն ˻} ̩$e%ud cA1Ne֖T W:˩ָZ_7IoJ"րEIpVM7gGroXSr.ڀ۬ӎ@2e$TR%򄰼Ve3aܡR5}D7|HG\RP'v,dJR#+Ir砬ak-f-g%u=lS5^ ;Tʏ~hc?Q`B JKe@˲ș #0NFm6 5$r^uIn j2[oApD% \%|RȥyA NvòdKGkHJ]ʍV4Nع?ĎFP);'9ǓxWd9L D⛥8a˂ړP >aJޔ=#Xi蠤pXqH.Uc҉kl3i&l bڳ)C֙eiU:ް JniL2eZzɺkʜ"<%!gNM5omnDki$Me!Yӓ3K ؃KXMi1ʫE,B6MtV60ESϾm0Iγp$WZ4flM$M yhi ܏ɳ/&Hp QtBPھVtM)Lmٲb@9sgxc!Ajw8y\}і A35eBs?/W8{jϪ]M?Qm]Ki䀣P}@%GGI"t2 -q.6Qؔ #d,W x)ߤh"ڧRs)LRfQr̸K LzOt!يcaYd#Y8/R2YBm4ĭFbK#xɏ-+1ޑXMN˂n%}Mє?n4dK&ÌYnpfdfO\+!4owvE3F`"&5>$97 w`oO b~RuEfI+o>&1QJTL[FvI@/;kr Vs6`yM)nF-cNNFku,K=, MuDW)h̪!5?DLJ.[TeǘfTf;]tP퍽UGo-S>=†XeT0_}?\{t- &9_EZ>N>K,(pOypdq8uX _h<u n\.)- 96#>i@y'(1\\C %$췸_X0b;C46Qj<@`IPǟ͋FU7;BmW&UͲ=*6jpczdRۋ`&ݍ?х5:S/ߊC?Zٸ0WfQ TBZGz_@Ť'O[S C=ET頿8p`G9Pd(>7am:N Tv;UFV2=5@oc(w!fJFk~ȢswhX@Ͼvޛ_ۿU)$yrNc{c!?p|Fi³(O);FpStk^.'i竛fGxkBk࣍[J $۲yG^ ? tE,z 2K84䋨 b5RV~⊑$hE_%n G$Yl&HЖގxX~ҷ(]wgma> bD!扺jPWuzywޯԃ0-,9[|;)pf3! NV~Vi77GWa?F1Dr捗]íwD}aVz`kKydQ^C6/Uu1XZ,܋hKzQcx̓"e#_gmf+Gw-ưylS`8ZN@9Xʜjy@+X-R [VM*Rv!=eeT@?|_ %#@)J+I x;V W/2,g6f dM*R+\ps3@/YvԱALAx!)k(6_\JfX=N8 ؀ `opi9)UB]21W֏88 #kP#ӳ+j;Z^yf?}ՠɅQxMlW+u͌,傓8=̀B7Kjۭ?W*8^7sZ8"@"yC`qIJ`C ڪ!6} @x=BoCEa(ر@I>l-^P2Po`y0 )7-;M5ɔ}%FVAF\G5޿-ocduo#}ydͥ)۝ݟv켒 Ic'A,b``$)$&g;QOiQ( @Ar8;f EQ  (ϪSvaZlЈ8ݮeWA`-DT4qŭ<0@`GӬהp7B-5FaײvhJ R:_؛9esۑ0v~%t@k Xzep?C~\<84g&CzVPDԂ6\ǷPiJ1F mT\o)MI^Dp,_\&0epysN_R 0-P("4uu)pX<94n;U Z/t{v1~G/Q`㗨ptgUP#"ǿWSXm, 4@W= jVȜs N8=_{ 8RϿxj$v;ڝi3_8gee|OWhP# 揾ûwSοqwwsWοIlM&҇f#sТw&k[Y_:TYlm+L]5R-  yȴ.d#;o%^k|bQ3=&Wȳ𬄝etf~k,i ^&ݫ5"SL厢[l۾$ssھ?"mucw7pVͳlؖdv~6UN` O'iԞsm!t? 4\Fy4JUi3XhD3.Dp8+,ffgJonqM'lqfc\GlgE5-R][Ay^#%vJ+C&ǃۏ%~4]dgiGսV_eѺov3OF3Wq/M"CǤ DK&.0wIpSka"EJpnK9K.&GӃT ~@Ź򪩫Vea`C&eH4ֿ~yyer?Z/w%˓ˀ\HEΏ{чnwRUCE|ҸL4VNJ0T,#G!y4 F* KNC5EBn(٬qW D 9 q_׍ȪC.9N'.TWanqP< Iת^Vb3d ƒ>G G]'Y4J;n-hxeeE5>DE\#aI ,;@|rZ:DJ_pƦ־dr.+{w..\+[U73L};i@'M(wp cE|Po(+'5Ekzrmp LC[;>>xvL"!~>x9}Uyz!^IqF1B++_鮓FxIB6r~XbnhXW|G`+ ubs5_AgGp޾jo~h3\UZ m\RN VZLuH7k|5jW p%$`po!Qݤ340S)ukb.\QR=hkL*Y XleI̢*SODi*#E(Q<=QJb_K &Jib"WՄe2{>E )z$l+ 6OXXc"8 czyFl}Vq$e * _^,u햺M zh4q-zW/PSrj]VzE+ꆫfy,QdxJ'ZA5Jʢj̶\&*P\AbJRqeM_XD_ \h?+6ՔQjO(cYXXB!Wu5pQ:딫&Tt(hAK[M Y9T:9)3X ͧ.Lѭ6SJTU)6wYE4)u=[>m*үϬ1<xis:)=j4TS0,>EʇhΗq4wh<Ż8&l(z(ʀ쑓a)<7d"̤^3w߹{cϟ-ú>#;]_#AXZ7h#^G`w㓴N."D`*/Ea8XX{fp*o(2RϵQ6-F񵄕J&R=.FVK3Lؤl!<9?OqיU'm]BWKozXx }UV_ pC q8rnen-MnseT-%KiSL4isBdkFHSrUY4JFrq1=u5 [p_mPF_$1FVyB:zZ钙ƒ9g :.a.MJj 7*2 5ښeKHmsZaXMD:*9 "7=[ io'Gq( 9 j0:[7Sq{:~@#R_>g" څ&THpJEtkg_Uzo޵N]aHDM[%]~&C%ğ(:<9T 4bܕL)?4}N5 ws}.mI\ 5̊a2rcJ TR[RF3iwmD;odeOҨCL/;b-4!L7 J^Oi)-fRF~׭vX|v6Hh =][hE^.7%4'T3G7Fjhs;2G?UoC4oj["mz{G7𩽻Boς,#)Oؤ"\.!;-*K&%+=ab=#ǭǚ2զO23&k0|<h\D `9L$&+") {8$ 7F}atsi%60nBynb=#'$X~M<ŹIȚ51%$FZAL~ξ;Td_qf%Vaˍ1Ș1+·Y$.@jk]XW 7[Ji-\ksW_N)&p|ƣ|]7`Zéu\1.o% RG0;jQƬ i^+M ;%CjW z)|B d%@Yj$FH]d:j@_1qU8 cfh8tĬ"? y5(Xgd=(NU)t[&رelbeQeˮ!ZKyOVCq#צk]##B5TD?ش/B`RiγD0>q>u jn5\Ptb]_tD;&Pvs5\ jɐLfBOW¿T<&'lkCT1+k4dz!)UU;TU_U+9!AV~StPΆv%NƆ{q|.PgLw)\.Vzh sϠ|a+J%|[{vpޫcnểϻ/;o:7t~{KHaxD]p1)ګ_7:ys~ljOm0TVjV_hةYku[ԇ.Rp?-,i (2jfWra?d+zĖYEijDYE)nt >%^j[0qB7Gj6G?YND|_بRSib n{xBt nݽ 8H h,pZךA6En=n/ e&ڡpԢcۉTϔK2ݍ aׯ$@-$V[qCAW u,x l {LG?-vKe3D/gvK%HEjˠdWU`\u7>Xm+J:={JnbhdQi vvDߑ^ C3p|Rc X&SY_ƪnb>!Bkz*_Z_n?V;b̿j8{࿣+ı *TL_OγbDh% ׏+$<.3xa6NM>Q6u~x$?g?TiKM+Um-w U(dĺC77U.4W.}⇒ o~1q|Q b FR%OcY =fA( x8ǨEVJwN%<̈́;"9FR.C7J%iuV/lv  _]ӛ;X'zQõ;TwBc~<%mFzI 8!=bH1+ qtӉmӃP Zu}y"$uFq6l o' xfW6P` ^؍{Ž d ^*%pCG!XTˢ mZti/ 3p L>(qy?ЉK^-Ń௃$;K0kSO;)¤K/`9|n6:уe˸EDVW?/$I񎴛wό΢Z5̄RdUBy}×{Ϗm*/e{yB@"K؅ ?ζYG.[A zlqfg7c^j5ZG<:Yϵ0{/b' k;{'[/Dň4e=RLhGtaHlqElRvv_tiw@|Ҳ!ٮs#E55睃7U2|l褷ښΪ7=?|ѕ''r_ zYh]]%6wemiWcecf|$oS䖭 i:B4ӓ-d% DiTQ á ,{S0 _^(Ț#>h|fǦ"(πn"m| 8XK`8$ uXUO ٍVD!L;O%a#JKɷ,OՐ8A {Ȋ+xwn!J`>UYAB1[j),bz@`\%m!W}3܄hz.(wYh׷XG|B21y6,,k;Vd ~|_y<{LOc{yQ:>\Yr,fx(I4B 7e z_owK ՠ9tJ?` yb리 Ɋg6]\TI d0QO;~t}R#3BW6=_i; WW|pw>_7+>z#UfWaϔN5x&$ht%9sjU}v~дEuyl f'#W{?ޟWoM*^L< r YGmB.o>>oSOg饘p^nUα$&A'}/_o1sΒfm~~?o?{6lγW?Ž Xj߽:} <oOq؝Yw (oww}J8=B(飗hrĿ:K! 3`GI1,n$5=P$^8g4p̰ :I>r8Pl2ÊyBN  v8+ 9䦹#\:׾k_t_3tU@#룕G3G4+lI49FAJC/&); ':hQ~4]ڂrDl*bZ?vz[c9L h/9:\67G)qF1e~Ag-:woQ*O %[)V܎Ϩ ;dETYޤD򵨐| \whjE=N'ϸrT~d&s҃B~e8FWC攲&hl$K=!JJ(c\1=uQ5Z\p}u.V90,BڏU?8`a/ 1jpzYv#D]RN\(YABnV^M5h;nnZ)'DH;rZFEG*VP8<0K5'V5,~U8Z!0ieB Q.7?У'յ6; [6&NWů:' V\FүaS< l~߂Eemfd_$QhPd!ؚ֪jt OfyV9Lu:<LP,90]%`Jҋ3?1 2,S4#AFgJUcHxS8yBVKxY,G*x*[nX8l>6epwn[.I2>sbV+6ߕFEUFD+dyDi4ھ |10Gkl79!E#@pjLՓHq_Aqgv禎=w%ףQQƳ\)ZTrkn5zJIֹO+~=ё g^kЮ2]tSN M2Wqr g\͑\_r:`p:7P f e2c/ 0{hVUpLG^%ՃCd,AuHl}jgemP<5y7c?| P/\~Kusp ;B Ah1z![ުdƔm:KCwb2+9R3=_MO{ Rzb1!iW'(J>əxҙdkpOL?PL'c'}e`W PW''T5t@{jݫsS-bQ0R)1H KF ' _*Ҹi0?i*Il:jiyKN3[$Frf5QRx]-SB2>plRDKnnel }RҶr+`La O P NM]hp 'd,\.Reܻ wgQ֡ut3M/5q^8S%Hn=Ek-[S |ȫ&CH]Mو)A~\`W,,m q99)w)ȼrJ.c߷d"]zVEϩsq/G{p;ePnjm,t@ޡ T={)os);{.{R*Sl'&0@(a?$l$cbA!+]\ҝfl'JePt<\/7cQ~Qo9=VM0'Qp6Of3zMRd8 ݪ8;?;EއQmn.ヅM\'mO&pOao<Gd\&Ap+[/mό@,Ljd|}%hl|$m//>?>k%?B\(x-Ar?ɘ^4d&#̝JmCC]D?0&fb9l~#&kwo࿰g׼׼'SZvfPIlTCo{{7ejNM&%Bu9BE(\d'0iS$ϰiᑊ @[{ok-."2WU>trv^yZf!q֋.. I5պWܰ:98E[O}΀U:ؓ_i}Mf:<30)^@j&NQHq?|QBdmZdN`Ѩ뷚MfJUyD#e a;+Tş pRIQ۝G۳Q* X""|;Ŵ"tE[ QPpϫa8/,@_dM;1atX苼UmYtKx4B0SGus5 .jA %8"=#/+7h(U81lAr sDBs,(XHp}i ì*9{\eйZ5ɛ ai3D|$HI;{:ݨߑtdz0nC>G= t!sSFנ'-v {dwJ Iɓ*#'n< 3;w |ڔP Є &p9 9oSazF1RHә֕ORB T8 S7:3 6x [w1jjCٍb5!)4۵jΞ{f< Lj69H: ! 9Y8%kc Ƶ873!/ 4H]HFNblF>8vƦ0ߚJzay;E #pЊҟ2gs`c|v)8ʭqyA$eZąd$%U/?X]77OŏX]7Ѡ~TFTAyQ0kL5.jgH?_ӔakgLa'W2[᪘o,)rP(X+2H Gpr"[Mps*& )p)Ѳ{!$"Kh4L[=FCjoK'D2sY|rǰ *_àO&QH8˸K*Y•WkݞO(ҡ*E0a{`s3 жdc.|2M%a{ۄj&õ%GpL0GqL(M1KTece2Zsco1ۢ6mwrݫXddr E I`E+RCL.?*̮=bv)]JO2F_1H*ܔ&iClЎ7R $+5=/7#{Zc HU3xݒLBݕ$B6zaЩVi oگBtڷm2r!gk uc"̠/#UQrz<*Y_ь4[.G pjdy_k@Z3o(bqWƼ_*Ului>2f|D}Fn!U=1{ĝNQ4 pĕ*-UI-iVԄKYc‘Tn15,oGqjdw-C"$.#}FCuhfHьQ;8`Wl00=z5cZx P;H>o+H*(wZ'y-uj:PJG3ˋ Z(LS3?Rs QrP}~ k5~ 9!?"ZsG)-%hَNg6чXy j@v&ÙuIBT9!8u27qښ= <Ү j 2}B[—` ݗLISd~T0w|Jzh~eRԹ}m(wF>gIO hI_ ZW6rL ~őhTLl)bl }Y!$zZiw3;w?1柙r76nܝ0/̩J2pkTJ>NCPN MeVuFy@V>=4[=[^:[3ڒ&G+sYG!e',UP5o  +GLP}x^lGI ?FYKn)5k_[@*' 9S*:Dm!OmG.0o&iͣČShV$%y`ZrٔXܑK[ % -cScN䅩 zmk)Uxeԭp#s`MuLvD4NƦDKdok)9 x|wz7ƒ/+h:zD"Yd>&M69s1e맏b4&Y`5!lEe1ay_, y6aΗr{BɼL]DӋcAnxJb֘CؾA'ESw:Խ}*}̩ztʍc%Q'KrNψA"Sч X}GFc|L"FQ(VtWy&{FwpsʣP#eD?#y@Sz)/cn9INŽ:{E9E˳T'Cs#g[ sS쿫+;7ijZ(EfQ h5*$p_r 0+ {7UGݩN61ÏG|>8n{Nqf% B;WPA-1_Bɧgrʿr"M6@R2eI.9_ebMNR~c (!hH+ %m?#@5|q2GTfѱ> G̬[+Yea2z)Mw.&M2 N£3KNҹޖ% P7~H6X {sM_*j\/r5-UJyGѕ; q` GeΦw;@]0g[V@";KNlJ81\SUEEgS+w& G:c}"z[/n _5k{x댆'8ƄV;51F<0/}ٸPLXC-8> p)*T7#jVK)/t?9|4qg* tf7*-pp)њ?\w|C.rEnLUτc? zecMH_h7jhşx͂w\Ol\5|Jr;QL hs5@^A"Az[J6Rg;(n:ߠP7J{Aן?}9t\+)l͚ͯc4mDrA aF6]vu躠$=T ƣˮTqbēɚtq1P9zx7v3y:{kBG aey`,=0P&ȣKlZSZăiY抱؃M|< 7L`lgg:cU_t ڞp|{wٟ\JheXrE!W!gہi-wZ`8{aNl_F#rz}IjUҾ ]GN^!C}\fѮyru,f u@k^˒9s3؟ W4λ×{`v9"Q4l„/<)(:Eg${PpU 8^BJK0 @Ŵᱯs3ndJ&&6 9bjXc%e $sűӭB<2FN$E,#=5T+oalss#o*n+a{䇩Q!1` DsRCEHA6~\{vKql6% DX])Klkb># ?Z;ns4\7EKu#Lyii@2DͫȏzLJ Bh~̯,+u[*M?̡LBYBU (@QqAE .jP@)peI<̥U`%ģf Y5!̆e Sf1_vF0B Q8z%x a{o4٣*-0"Ldi9D' VD{ PnN9~W d4J sCTr=e`/ j1㞵3sP{Y2 o+W)a~guuK{_ٳ&A;.!~64ʼipe Lv<0f>73*- gl)gZ&+p4R dԹ&Ӛ 8^We QrV! % /ƨb Kd$F,]m|ڕhx盾Uu^w) zy7EdR(Hf7dE+b<'_%e\Ɣ9a~Qs. R$UdSr/q;_H=}?T3p({i3@&9h;{JXV9yR!> S!yAN:k?Bzc#9Vv҃9x^\XҕՒ0ji;5YF@6!/%Njs h_6 LsOؗ̀t20E/}&AnMtzKy;@`)D,.AS*JG q*:6=F$+ɻ/,n_UT|]e\VBe jJ;|_`|-k|sꤏ:&RކVQZJe6dnXwvcAFB"m[ܤqp,K ҹƗ(TPVH> jHYDlQ/{u(@<׻ۯ߾}yv-'ׅHio1}д[Z!N4pSK%N47*~[a8^$ucs|γwh4r+*VK\[ҳpTja ]Fw+ 1fԵV<hH>٘ WAC4>L'"N?4e@pC,:Q'X'{Q/=0T R)=[`̎Mҹ~z2a<2sƄKK(IEƗc`,0Ly*3ZV)&QW\zYWiv{>kQN-I\z ^z쉏!g)\Wi&ch*ÍПhnHD" ]YD s]K7cϗ̶'c 8}Ί<֋`~뢚kMHo<#ul+x:v=aW+{ h%W+s*w"8h)ZXE!W-z|o_ۙ aCVXRQ%gpr/OpvDp{ u7[sVJV5Ʋ{ygGpyL_C~eƣ,Z_/B$׹2Xpxׇ Ն~.z_)Fq0 "Y^뢸ʉӪS,ZJX<ZJjg[y-e{Pu) fWxٮ,:r[~oh:Pe'hO''N/{Jx6ߴ+d~UdYb מ5A=X(oB2"܀9p>o :\K\_ulQ-@6:lvXۦfU ~ӗmv~gT؛]Jgl .bgٗ r}l9N?vay|sG˿{W}Y>^z[s*xb(nar~1 I } Xi\Q{4n"JZKa}_Rw3|o?F4]JtYʕX<>,lZs_)g" A!wTcBGZa]P5,^hb b< ;4b9 2udyz8aR]Y UìWؑh}IZ"UuӬM $ôTjgҕيwK(ee㾥oT8*:j8 ]nB&Nc_]HN9(eYL-*gaE,[A$wZR&9O!O4DXX;9C@hdrZ.UЗ^:G#DmR"0*ECZ(+ aE k!-bN3lv>xyfe&26&K=|Qr6Y:Szy~~"\I$AٖseOBFr( jAC5s6.v:9p&ĔzR C눝 ERP1W]b5 'd]FeD5:g†wHgH%xM?o@'K،u*Ŋ+͎C@=HEU^eg Ŗ@.%v \BH,9i6)`"B'<9}!tGƙ߮zN2ὯL)V4\e_7p+kBcfjj h,z*(\ܜuA]T| fWG+yD1E8Z )(mqmJ\| /HRuKX/_5:H$l2S0 %:v7P8J*C ó!GԇeJζɰ7,Xy5)[#$W2M?*CtIguQ.:{&Lq+ n:>#+I $tŗZxdb m/U!2}`.v[ uuka#'Þ C0c49p{&6'8ҭ"@iΊcwv6XgZؒ׵rK qwgEucUL0A]Qـt+ QXhL8'  dªQDI Kt°Rn嗖ϑ!.)oU|DYr)Y7 jɸq ϒ$k|P,ӐM"㊾~(E"&)eXu.I5˝\wK{K&)NV(KsWx.vJ. 88eN,Ccm{dvLL}"Qe{Nf]][Ri"4,sFUNTah@,!L٩&PcЖW@U .ِ(XҌN .łCd&M0مr:.$*;sA!\AFZK Ł94hPQ chE"v"1}j4Ch'RW/W*&KS |7"b(<"٧,E3{@wIIx@>TrTziǟ`I^[]ƑtQ=+`+<B(%bV}'謼.9a.UϹD^KހԕEL@',+oἇQXl&$N )Ov[6Y{FpfaLE͵DbxW牾4u+Qw)`rH;[dAb7 \2TfZ]r |h4LϡS,6߂o+I)7eW ctRVA㣓eUrϬ(8y˓ ոtCe2IcdI :(,18yq5E‡q^S`ng-1}TF/S_SKD~HmHR?PɐXCHwP u;خ20XoToMfSVL^7e͑0MzR؃y\+7KJMfeee=48nC\֔ùYI屌<ȍ[/v#Ww=:,%: ذSÅA?+H݋kƚT\lwt~=|yi9=_V8$3MvjZ'dH25BD1DfK,o2~D)UwUg|p> a͟R"EƝ[x&P9x\6=-vJn9 <x@:&'dHM*rc̣K8ȏ1\[4llKvi?tb,Vx)}#T׳.rZ[8ҙ 'H[MVYv̳_H1VX(ͱp9K :G.$Yc >  D+x{8$I؅"y[TO:u)OX4p{)7|!,0P-O.A(N?KOmUV!79s*N ?]BB/G`0P"0YuXȚNFˑTK9]pOІއzHq3+_Y/kHZe}wrL]BG'rWtаMrh$e~I;8V^m޲/|)F!zy5zE .gTv>!2B螥`=Yɓ\16Vw4\vD?[ӟfvٯnOb*# 'tڒW :}ajJCvpρkRtNq%鈪kYMlV*%Ha^)Aݲ#۝@kԥC[K 8fvsw cᛞ[Bm,.Fi"wy7UT^RG:Pxp0$%d[x|<@^C|%6Dh_a֦sA : ̂V y0dmb9Tˆ`B&]E wW{0U ΂L{02(c0eDA nypc#v/(\7&O" u˕)BQurZšHmLy!~cvNpni4='q(,|5rʷϼ%vTAZ]p]XoJ)}V)N)V^?:DF*jؕ]Yմ\’6a04X`v8mV s*ޢhBSgG0ĕSU$zs9 s,qSEHQdFCgaiK0"ɂAMx*[WC5K-)ʄX~GDQ 8@;(s"`+?Gd;a-7_B=.5]Naynhl] u7|NdnH msGEKV(X$/kGق՜XwT 'P? ]$y8્ xG 50bƭaw@FP``aTcu)xv2ׅguiigRH1EdV/ýr%{EƅCN >=C.~C*#(ѢXt$FT*0e[A3k0~řYԯ.ZVM-Zt;tuNq z8܉?@Ib"[m>X#f1zu8U;lzj]E~N$[\N ?dAz&qW~J5(c`}}=7x{#?]AhVgW{\ WLً" /3= /1g/̎ ?ix1>W1]߷ot(6U8}<\]y?V766V?WV7ug,O& ,SzO_ߢvXC.‚] bYP>[Uua~̱+@%TzȘJh /;ǟA&ӊQ 3{*qs5읍a:8'.-BMn{5D6Hzo/8D\sVtRA -%L-xsxįi]EzQ~)l\bvӺ%b0s Z܋|;mʣG>zGT=E7`Vp!`&E`UΥ*"uZ rK . D 6l(׻KU#l+*DnPu=.,xR YEŸM`?ID_8kxp b5!DSp' iIe2yćm2A}{ysx}1s e1c5MT2@ʩ"唁Z49W6@30Ӱ$K%4n^ ddxk2>Y?AZF{h$CΕ@3a3ƄuefqEZ#`㸥HrdRt,kNzkVY[Em hZV ?бa]՜]oku8.jߵՋt+޾['ɂH5l辤Esx,@~`v25 l4!>hhnbU1iBSd l:9* ֓JpZj`8l^^P|{\%ͬRU4Q_U:i0!;w2xխ*>uENTq>HAjq xo'~ZJ(?{6$ g <Ӗn%nǝ(?YۙYۣP%1-$uqo %gһ}>g'Q( BUAڲ0 ػ\dktmS%@RXu??=C$i\M8F4! pң@;7]\;g%oߝ^{7g̳֫7޽?;{N^'m7F plwT ?z7f]ڨcd})L|˂xS;ٱeSjY-cOo^/_鯳y?B'f@)#Yªӡل [~ zAY<,G2eU5Q3{IV)H{۟FUF+Xbm; Pczv_H 7q!#+1~KϨa[Dpq3tܔ漥9Er?ƛlՐ;yq78t.k _o#.?;;`џ?a2/X>^[=-|h <2 M"ySy3dP7#  EYVirgJw3J77™a[颭R3OudYQc7N9ʶ%E`mG:̲Ւxv%λlK- v M@(5EWwcC'>≙:Ms!6 (D,+4ZזSE:Bpf=P@&XND{R|HQHKj/7S绠J8rOo3}K! qfK`ӏ`fr(ch^gOJDu%K&-6*=ex,x% Q^BF/A3!{L g0 Qϭq*mG95.yxF"uu:kK鋶9!P t(`Tcb<),l qM&wMlDCo_l$ fa6cbp>Hq倅 ʞ}yBJ.s,0Scxo~:4e*AW|N {woY?lc&*^g?5Q7J GP e/ޟ$;zOe6+ tᄣ8aJrmXzT5ms8FH ǍkkF^4Ix* $2tUHg Xi#cjX x+MJA^ @,ئ2 h}s҇N~8YMTVRQ<;cmJqʴ GK"Nzf~,W]׍lf(h+`6*OCt>E 'iF!ȡr홺1N)`Reŏ̀͆)xB5\Jn:+Qp1Pq0ݫ8}tfGNzI*ݘ% f0~&?J Q- {ŏ- kdܧJ SiQ +Cl@I~^#P^ A]5`a>ɊóOåtTh0 IjOn#׺vo#ĔV D0FKj 37JEi<7K[yMd4eǏ4g&e:B6XA 9M]_!iRV5ޔ* <ʆzrAod|/Mgt >O*ܠZ#MwvCf/(@ăIFjxYv:[:0HPcp u+s*(Ԋ1( " SF2)Kd@UԊ7.^${8KAbkx0Ť!,Y+ eyQ6OpE-שp \cуwvڬ37qbʣPV姇P\%p*v n(ț'ZYKVݱb^)fag=5L`:/J}$d" !nZ+OA'*IHK]C[w<^ZSmQsBQCҚ)3n?TFF'7=jzpN Q:u9j`(c;O2*Ǹ'huĒu䇵ێ} }ldU6GJToK+@:d枊h*ec ˒8P蕇ad )Id=D~! w)PU`W.WUc]3 5j'q0=GǙ*I>6!.  O2'ui!7ZU)j>U>>7͆& a]uv84+{} RrA浆'p@uF*#Oy^ŒջAqDm: ( JD>(J,אF AB.ݓ\Ù%`-Lzw:6 vGa>2I+GHޛ\SGH7pq!|SN Ou?/HW Bݲ%*WěL}⠪fzOč[Ѷ&xi⢗w7׫^2>tT8[|նt@T،"f}pj2;l;f2Pg+NLMB?Gјhu*ҌLl\!v˞Q0V ʺ!~@JYgtLaBPQy$[i` Rq܁[p1]{7c(DWsbENMVc4;ԖЭmQrJ;S*{S%r^;P4rv*ie ,F+[..u$7}FY4}>|Xhr0hRn|l\c1Y徇|6^`R%`oHoWu_īT-؟ ` Xy8eAA @1eSN6u1Q*^CL5cΒ %c°xu"s՚]z DU7\ wk#IJ k KAeH% h)ѰjmܲScAɧz_(sqE x#{꘼X S贈Xu0k %"pC@RT@`YDװavzm1Pтj ƼV#sG{AH^81F(OAxSGA*Ad`xgoLT@mO'^I*"1U6~4 L[IXua=I.JJj9T_Ugb4AF.{<]KO±oyR5\c6JxDNs⛕^T:GGNR qêB `LH~uS.uBTܴl>>U`;ΤPkb@|a(.q47KyZɂ*s(:P܂e\k)I\6 |Arڲv_]kWe=f~Bמc vzGZ2aͅ^fC+D65A4kͅ; J "T>&ݐ+zrnVu0\UqZU :)!&*E{J+ҵ* Gv3,kE臗tkQOC&w! 3 H 1pK.nD􎈘MwӉFh`&:\A4:rM\d^ R;*znv+ ׌k)،m뮱(`O5 4V}1bw+F,ΓIb;0CG(ݝ0aք|$ŏЏTQ'PQNKa+LINb'm3Wqp|T LQ:/ 6_qW &/\,H)KdJ.+kwǕ l~'h= kbbn Dن.|O s,`_{uQC\ _FU(j&61)<0KNBgNN?\CG(θ~$ H`;,ŝRvs!a}5}T֓TfeOax[ Tgyi'\pD,3W^։LY6_ƱUGF^X7ĸ`XHq=R#8a3AOѢv7[ͼ=m|Q;oGjdԲ$qWTuɉAX-"|U\L/N>X@5lqFiE@"VjݩG }tKVY:*%ՆDqqL 9o8Ռl}j&ߴ>TBA .ik7#zHp`:\ pjRN+N]M;Oj uábeI*y;R{[5S5'6@Y}*RV·nP@ zB t21ȭnP;2G@LulK3 P`\+lMoFID ^Jv?ӵ TkRuo R uA5N ʯjHEI#HNorW1fg*\>"HqI#j:ңPTb#V]İk N㵙y<YY&wx JA]ʰq-oյJ̸,/-j NiE/Iԓȹ6G̥\ViH^d!WOob7IY"g3yUᠸcNDX?*83Hc lG}7}-آ&uB: gv\gA9qE]ȜZ S2|S}z^WgFMn{ HS36B3*QhkԀ J6g(gD5=5SSaǛ;ɖ>jf! LK5bD-k%ވ`jW,q\5sEf$B+!K V SjH9Plq 6= &˕Y5# 2w8@G*ZVoaܜ͖H:39[f+g<ˋ0 >B;7 ʠlb< 2`v4DFf/,9kX\;>J(滋08HשÑo>vCpC(J͸K|X{A0WiQRs -0O1BtyvWq~!f,)V)&NB5rd2ghi M; ܺ(QM 'f2l-̏>d)s2}5UqA)>*0G &0_PPNդ)EPk,C"GdvP}qrMHKA+ iw 5VUSjS5b勦zPr[kԃzwUW2*hZQ!ˤ6 9tR[|$ #(iY^#u=M|1L]z 駰?`:1=#ҩ @9uߴ3Z^4.KuSgyY OTmqǡɕݰaT_Ro'ӎǣ:=y9ɸKU^J"C^E.U|rdx+J޹멶e m@鲾_m&QEu~O뺘yo5(`Y˫_TF;lh˨Ű˒>vB_Eaxle/V8OQ8rCXu'q)B>CLT'WXيO;W\8DLQ7*2qʗ~M1'V;ֆy+)?2uGJ6HgRc9y?l'z;v2=ywv=>`g? {te߯[U6q}r~%^8$ߵJ7^ѵ,段t[_ߘݽkomoŀh!@ƒ9 t}0 .S A87n5@2Z-OhҺf Y`-l2 7;Oom,£1 BQwj˱8[Ʊޝ"d(d;eLmc$n6K*޲!ڳ|:4лQjA;FL*hf UyS5I[ݛ̘OEV6e*L'Ys 6ٵ3ZH :v|k \rR YMu$c's|`Ԏ?$!)\"L])%\d8H%d>hȮ X`b 6 dmIB!u: 1L (MnՑ;`is6>Р#ghh?K"'sԍ?8z{wNsIieq|b-NOONom 6{>MXV1 OHp^nZk$_{ŀ;m֙Zۄ-ն8Kq-6 VR&,ۓ #M}]@z]x`V? |I8:#C/> z><{!:(uewa::j@쫨!Nޞ9nn`i'')g'- ˿νcsAaգOXykH$x^‰vy/-;v`6LsStJفL\ˇj \t]ܙ1=0|*EO] g*C.$,BY&scnõ '5hTk쑱r ;%X _L٥_}L=|eZHN =¥B:amO_<z(qIR/A>/<`rd-nA6m/;MV l_%=d$ej}_ƾHbyH\Snyyo{ lFLY,۠3K|T9jHHxS8\yb6eC 8nc "ȫޛ__6tEh=ɦ?kkSiX1C̛HOoN{ -ҍ[{ye1a0W/'ѹaYA@,>;խܔRRՀ\j}Qhti 8= Jm'7H<-y~mN֗E_vH%E*'J9bYP7 `%ޟ(pmsk4syD;fsf/Wp rlmnp+7f.F v=rAe\9T,-}»+>H'OHY;='.,%%S闓eI?V s˦8U{E5S@0-]J;sW$NRar`|F:ciL9Q LZX.f@MymL9~',W>Pu%l1t;#E2hjB# *"{6բ|ț֋uq78 GW]vX^wL2#+dMq-Fl-J%#7bH#[hL{}Vn ` Z}g#[o55:e۶lpt}軆UH]l."s $$7"p: cnAQ +S!m[{;΃+ lQvCDA|cKG+lj7n!wWQPeRis43"1wVVGI4K[Œ}M,;&5f2lH5/[a3=' ض`Z=8h 3o|/ (hIF`yqlaNҔȰEZ0V*Qk#RQ8^X_T`HZBU`مQp5vUشxLFTGYZʠI,* [Bچ/8@CoQ]i7/ ~,F.k[lCz>ǣжZjFpZުxcƇgفhbǜoº_1ٓ^wOɢg-lxҔʳs7w^??|h(uf ‘á `lgpTu|Q[ NO&yd5 [x Zދ3 mEټzQi)(vqL: vEV!/>s-Ոu8Z1ukf77F-gUQr<~U?邋wzh5׌w/^NgSw&Y89}+{Q[2v>XV"M Ұ9; bܴW X(|e;H_9dn4-s"$[U:UjROؖO?}~+I`Cpyb|%VdYxRc0(~*x o}y@%c%[{j00`Pըװȷ_9=_Pu1L0)0ss/u8;pbҎEW T|n"8ACfv_` P7s Zԋx;]_1[*Wz7웑*+.edoiC(6:'N21\lArbv%'W#pYR!26'-CYf_,Ha JbEYDMӥX u'J{ ʁl=.nVkG] rUcC%7ӺUXHmY3F" ha$|>.ۋ vDRۍf5=^\[-WU ^!ulD5]}$&nmQP[c(@%q.=J cl46].4¿\lYC !_P|6pE6e(so=pybXޯ^aG{<ECu#=5`n[2bLˊFQ{z9%D7=},o֎^G;N4Q)ʅt/eޖ/X+G(Uң҂) r\ˁFT a 4 *!1j|lo}E@΃?T>絺 qa+l]ݥm)hY7n~[K؛2X3i<^ՒTj W5MyJj厹V/n7W1犸*y9?Kw}!;a=U&KԋxaF/|ehF}@9/̎d$Զ̚D|^X3V&2w̼ծnQViAvݭX?P-nJtQ2b뮚wfw qGhzeyp* lbUV7t*52Q[98vwž1,/ ՄYe MRSeu^2|`bں\IWa<U6#J1wPVQIdŘ_1Kc!Ʒ/~>DavjDݲ G 2hynɭAUɇ//NN;:}.m]`z:6I?O> fKalڈ~8㌒UJO#7rUft(;m뎔X/q~\Wڥ-@m ZR\.!{_ѝz՗2 pb*2Sli aXZD%yŀ6k<*YW'%6%HPr-i0=5[stREm ԰j M2}MIlii+Ўŭ!/̮,mKsϊ:V5őYr Z%#~6]k<&;C\nSQlOUC9BMjmg(ҭNw2+Eb;2A6. -iPT2ګ܉͝pqDoY7l঵r6:lo~ڸբCA-CQIj7, ,o[{Ёڋ^"خnWJ3k-ugOӅ4N>ᣀ<Ч $$uguԄ1JbWL[#d3#[$1A_J/氙[R`q0tUGw0ˋ]^6M^w`rweJ|(ǀ`d:i*>tr=롫xJR7k2N!lH !n}NLbgvUqJz|VE 6;llgt@(dWܲJHs>,9)" 6ðlSߩF=P5ª ̼܆bz(uۚ >SŊTwk۝+!q#f hosoGJNeFk#=&%L (A#+k֤fv}YqXe7,B%E45YLP2<|0U@=9O \r/{J<,Lp!HaI^U$tZVv?V06@bG*\AT ( n]-9R^UcfU8*}gz9"7%j=Iam^]8HR#[ʨK-쪝].WI&{ѢHPQ|Cm7يAȧS͢k,KR/܃}JjorѐTAαsҸܶ 5s{;"2ʇ@=LgO|u믽+&I{R͉fDo} f@ )m=Pzm=YxF53ph=ʃůJ4$Y T]#]_O#'s3>FL}ī{ΩiL4韖j{s>*wl@ì7g4:ne7m񜆠h ΌÓ' h;硷_q@ã_;ϟH%^ŁH8R&nY\|eyׯOVqؾxL m_ C# lb+Y² Agt@ ТR ʱ[j5٣fX~"E* ƾG1dEHm5޹'V蘹5" n2ry¡+'[%Qu5Z1'{] 7!͹O(ʤj[8)FNؾ3euC[zp).x%;qbwMyʥ,)R5GT(9y0t^gZ@X:zUuk֕k'@2wFŇ%Ѽm9+YG`H34;@q茄zN ;1q'G0'܅mYIeIv2)V"c'k4&,Oc=x9B ж a:L[iS#UϒLGI/E\+DڶvZ_E&w ( -RC%7˂^K$j!̭za52yUԑbdʫtj$6yDg6+$ 3\c]+VBBR5|AW'#6.|yǕ(GuyE`6.۷(*8֋WDy *Q]qUr}EzHbԶoX-F ,zbpLL- Y񱆭/goF-v+b5 1dyquqse51b[C-I|^wػbIڔ<>^NQ$A/m΃+.}n\p23C#3 SSye҇7`|O9lu0HJi!"u_>5+6u9[f nŊҲttx[+g\>hN93*CT+<ՉR >r_ҊGz-6oh 1D4>l* 4ϒVH4.C@Oc=K!@l(O+@W[>ZהL8SI;.+)gJxj]+zO/bIxh!WPfInDg6ޝ#8JFnXЅyE(mG[*)IJܜvqTSgܛm(sM=! U[/Q O%{.̐Ol#}51yNMlV#㾳aS'vY,ViˢߐUp}فsThbSeh[-p<6i,; G/UijGq <:Ob 06o"91M]LcJ60XFVn f껉fHB7%  R>NW6{fa:޷_ܡ#TfI|6Mل%y =caS f*wƮBXE #:r8!8VqGņ̟F,,mE ~Or$͡ g Z2vXSMmտypӁ|9b͋sfuviHjr< ѐ7ٔӆ^m9S:xa z{dTOKo1T]V潔owG;&KtBF342\$I FȐR2>&,y'C4 |qnn0T*aarEr"Q͍܍I'**@{pntQR($i1vD~zWcb_.yqr c}FwOz%+=0]ٹQ?KޞvR?jUޕnO1,j3Ï@ۆK%ZE rE(1`XoJHn LBP04bI*Og[tRpPk¶'7,]2'zU]63ץWzozxN,N&Fd/ROytmIEFiT90>|,Ad,%rɒ?Y`I`E5<_؈877C?ON`эf}Ai\tQ\0wNm\;&!m+oڄPX;mLΆ9۝BpS>0g%$7ħ d#إ2ѿbE%GAj)^7F{3@<'ۚM;JN!vz@w[5Z`z#R"`oz$_Dܘ&=- wEOQa+u.?QcM zP8 jC:w ;",ei؏F5Vv4E@D]sCrTl3ؔ t]aGxgIoo I5W೛0s;',q—@^|ɀXNn[IF6:9Ga_ߝήY}ܐE}޲xmEg"*Yۗv3 fhn% 'JoJApx6XUIE/T/"i|fiI֑F}~܇C)MY;7 ()TB2ǣ{4-z+rە γC7Oo-CJ6 U_BSd/J(BnҤ{5hDO;h\ts]_"-?Fe Q>oϢf8^#j6E=a.zpI@=職§)-|T (8xg|~2d+> .\$gBtId,Һ;)YuX6G %4@10,f@ybf( MF?!yX$3wpe~ :VDK-uFW2E 0mK "'0 pv(hYBrsuWExM]ravgMZ}Axbe{>믲KPX1MG&W1:#rlIKLO)@ J*Uc±(hkl*p S_}ٽ:? `Z*6pw$(Q3}yh}|]}iQEc?~;`%l_@ghݭGVsA-/+7Nm k+HEd#wv,۶ƣX$|vI^<c +2'Z5cg>wlߵ~Oj'hqᏵOnل-ujSvU18ǘjy51.%{&S]!SRYPL9%y5l.n#̕`w-x {i << %ihDocAJ6$z;!5]l]d0Z`iͽgRLbSK$v%xM+4cy>;wpɭ2|iQLa}jXsXࠩczM SX/`x,fB҅g3CpF篢(NsoFm޿qXH\*kX['xug[0{.K䕓C>fF#Z`{8c7)/e-ʻX4kS]֖8w;'[kW}o*3>qFvRhUBCw{{X؋}et;>vRwfIIPt(sEהj*m|->>U KtQuUןz92we%h&\㣏Mr,"&G~t{eg2%6퐫%Y:<?`ۃx@ חUDy'vr]ߛxr Neѓm?s8}qrP)$eCXgOhhS*țj4W3̊8uYClnTO,[|WXL f$ Ì=>kLUD#SkˊbYެ !i C9H~gr ^MfR~ "[ri ^$4m! '<湉j蔮ON11UT# d,Һ9"Yit-7yTYX[j]E!s"_oL[1m,v4Tq_Z{{zr~blJԾ>s3P rKΖ'LspXni<{eóW[򩂏K=UIB(t[mqHU?ֱI~-z.i,I%J[&l}`<ܻkzrlk Q`Zs\AjuPܳ[kt%fWFA)UUWMX o[7Vke)!Z`$}uq wgѯǭez k&*Wx)^1 {L;!CC΁,aV~.{,X.j)Y uFAs[Q%qei6.F.ԺgUiV]F(U[ Rr]yz~Lc/d/衭0%"?=7] _h LJhCϭ`I8$m3͞'{2Ӡ luԪdv0I.R#/ KQ0L:mIJK|AUH2wS"j;`Q_R6RRfSpi汍궻nu9/4|%YwYG*U@yNutYr`oǽˣ-#,13oS%ZRso]QᠴqeFN\S ly8M-2R)Oi /kH+4I ɵG4rvxr9MM༟ߎ_67K٨:#SC>իF iE`O#Z Ci[v90_[ыTeCL+p x+/䏍x1P9(V%8TPjstsUۑ0z@ȟ3GV9HHF(.Ֆ")sϟ8`!&#N?Μ@V$'makO¹WMnEj9{{ґ]"X9jHT x_Ĝ]gFʒH XKq,%u*;9k) '*Дs,Q-- h*Y ,W>l}{Q2ʂCjobl\#1 P=zUa=M%5){f%*3̬ݩIا rj~IӼkT@_1C /J[ִh.WJZ ->ώ"M*b).2ϏjrU" Ƨ'[R L \}1EiSoQoK`UBXX~|dY< "Fd4C LQgu.wVg"ALfOۤZ<'@c}_Q`m X(t~)&HJ^d:jc*1o>>3M\ޓAo2q/]G'D.Kvb7-oe0%M6lHBRʊ'rDiERHDX+l!y/}0Ɲ1jPe@ADQ7L0J1}@} |ۏ$Vk?ax?7eeJI,;R%JCߖKDKPDj5bVmK^ˤ/tZ$iƈKX&*}=)?[[%9lޭ< :zb x!Pzɞ:AڛjH&qro`ti|"Eu_J73ey !l{ iA]߼{8XD9"z_Z:>;?uvmъW4]='Yn³4 #`"3sLWKa_މGi`L#RTIY{%QKWè y]'qJsU=c,Mh%wzz?9=ѫjOn2~D2J(,Ҁ6+y](v-b-&r&X m?2Qna@6. [u=- q.0UJ OQ+nGRRMZn!l #P^}jkޮ_ۖZ[ 2U5 gIYJ>Gc|K[}UKJum ?LIot0Ayxݧ bjq<1s1 % > AkWIVy@_[n"m̦f1 Ն 6VeN .%ؔ;1H7Cœ+@]O% e8Ӭc$;ۚ00 &uYys -N8&-:z뻣_{-Y@n(Gޘ,O$* S%JSxu19 eE|n^\Ɛ ,ܸ X:8[$=G3֛+ 11+g_J~^5شzskE.j+!uX?fżro+D¯scEtFaw'fXpq&/)![dAY% n)uN@ML9E /7K#dWj=I;n\IGD8gap*(5IMq߸W!T*JN+R<"nx*._wÖ>0. fۖ֙ ta#3O]{Gs/p"+ؾ课GQۨvQ'2I_mhȄy#2`1wJ)g,Vikޮݪ5mYjdcg視/Z(iMrM3*s=\n>ՉZѢR栒p.Xի 7exGIy'8Mzc}?-㻚foQ\Y%‘j k JuȈDWnc f(We"]dllZ0F!vo .`ޒ¢l_vk z[{0Rn y*:oŐO.?C3Vn:{)B1Fg;XR6ݖC0;E[$#$ؑ1?IaE;HZjF1|9#&NtW_uѼJ8[ n = D U JNiy ?㎸7`}HJ>L.V<fCԡdحST 2 YԞ(f"?,cj"VEIwNLKTkh )+d1lVLН7 EdËyI%=:>pDQ c ?x]uev&ÜG]R. J^Y [si jqDŔec}>vTm͌bTD}|Xy3Ɯ&ZQ4 ʒHOc7q(+R4L'R>Kp>x Zd{zPb&)d{XvIqIK~=U\WDbiNS?+0Nԏ@' /9;^ RVlRK+xY ٚ*.2YTfJڀaV-ijƁJ K YmW$*p|- xCÏ` (%S%b^{HEWP縂C4e~i ?1t8?M nazT_dj0cE&KQԢyFmɊ% JH)l_a˾s3- 8ig^ FrFcѶAȱ]K#'}땢r| k%gk* j]|+Dwz|@Zr>:- xK|7k[0D݃Vj@~[E 9ya 6Ajdv ]!0Q Y"p{k*ȸp˱4u IcZ gip %BEBJ)-|]/gN$/R%Kܹoz͊erLR殘ICTu}L)~:)i?I(|ӕ-ێ!p4WȳLf\G'ch<3ۙ*a" 77{OlckϩyR/ڥE&C|Fp:{R!*ȏ/uހs20W7ø^-C͊t" ƒ;l3S/ԲfgBure2Pǻ]^Lk!XXfxtmzdUf'(\#zM(sPH;+)!=xBz7@F6'_')?UlHF:"QmH p8S~ixꃱ@aۃ!.T@܍w=ſ[:lT˭l]ۻCk얓hkjŊ^zv8^v(ha͒ v1w<]6i9lRJ;)8Дtns(\r(| p: #H~EY/i0١@ eD@q'iks-*'(+(.gzZ,nВZif[gTa{X,5Td{t.1Hc*>-V-̳^+40+2l6cMfr\]Nt_:-kJxPaW3_шBq|w{t#c?c|J(an҃MÃ,k3!b(F Imq(h2鍱4O%Ǡ:0G~ːkQ/&簛x^IGEx!.#`MKx*EtڄF% [P\d4I9Hr^58\NE)xF8x,S6}q'۵/ܬ>* `'稃.htQcG2!˗v`}+;J1P$&k$b9{%Mt5AR0O)&$4h(Z +Tlea HfEW$ cnci@asI+#jT $j}aWpBk;bj~}cI`~kY(܃)PAL VFXÚpȫcuO(K@X1U;(^x:UxΉN{u]< Y>S31F5ԃA>*`{[elB)){H|my&ƽ+d=z~Y m<㆝(ƀLGr_t +sDpj(5Q01kaQ"NK]'! %;znZbT8 Ȟ̅1єfEإ5^V(Վ#ԁÎ*/ z=FG8a@(`Ob1 "б d(abV !~LreI%>Ehd70oIgMh*}Z րp.!+jaإtbc=}8|Se /n `jy{(NzМ|Av(0cf/.,EPU+Г+W BBc@g׆uڭ[rDQ laԉ_E?/6K"Tʤ1&K*x]w"GBy@pZ0 1o bJ', 7 7 (N~~a: ؐzq7qwi!@{VZOa.4$IZI@z:Ke:o oH (o67V,k]=YCaBLͯy? Ehgmmm#xt=(U&孻4N -۲Y ]Ou)˗}D4LH)X2JʜW,,HאQirE& h8(G MڔypJ`YR2vQbE>iy9 t=sH@Њ^28@7vۑtC0׋  E5$Y^ēiQ!c $3yPPJ["< erGd䝎!_UpШ,\=S%ewh5[ӷ\G tF<.Y¦##PQ.]tVP$HuY#S$ُcjbr4i| ֆuU(>KIKՋٲ"i^`Bc3~Y|HKj8WG:ND GFgZּ~xs,k({=8wo,9nK&`mjU'|`8-,*ގ4[Z_u3?JBjWX<>$ve5$F騢2n1YUz dݜKAsěeBojS> S\ /0vڛggBC֫8M,Ý7{ua:^l~ۻC|D'/6[\TOқ1DdGIRS\<14喻dwMz?|AfG|5 tl&HZD*Cr$]L&D %q7kzwz^ .lis8%0IEI06/ar=ܔ -c܃VTzin vSvZØ pg9Ca}ggÒtث e($%ka/d(-ij>^ve x<.,Օ@Wngy1W޼Lq3pkD:0?Q6kL _ |l6/,hq%=rC15WG1Eny (]ЉFr-(%sgk5L+ŴfIw5ʉaox fpfId{o-ָ|lڗa%9]HMpv͎s|Az&Z;F.3P(?5Wo9lFM`es@CeA!՘PgFAf+CUh}yݬLLg?/!)5#PrU)Pѓ>Lf!*?6+mƇTJ_?&Xq[Y|z 8ZG|`w,ۑ+sdHc+O,&9 ȇOG.,sg8JlL]z;+0`Q.m]b4gcrOݜ؏ Oon VȗcW#:/$ ֕r-D|(nOT8Რ򜂰+> mS[Q\68UJ:݁Z:xZqJ#/F?f|4WMgb[$ F~RP#AI߅`էrWM|c/rubU%j&( Z-THٯ~lcw{??tr񟟮=g= R z ?PuNO,pO F*T',㡹=ICl ӉJ049L߈\JypY Yn92[Bt QD2ǀ>4LgĔY_7ޡ;R,=sOTd>L&{x e0dY+CAG/i-{eA8fOSŐ2:kN15C F5P.{6ZPuٵћo8={k|M~G꟥|!gZ..yHʱ=:f },9wՏ+CR8(!= M/<în-mn=闸(t_eK=[TdRH{^>Gאk+{k]G/\Ztw-v.*1B?RCѺu*9W[{X> |Bz,/tKĎ5@gHRszY~]L@+kMu.1!CֆF(o_XvҐ+4xq Yt]ِښ[nRƇ÷NxXӒiŝ:KƂbUiiF `~om_YtXb?"׽_>}o<0 /0 'AQL, _i"K1Oqpo) c ,] A , 4#ByAyX_FZ`,$g`ђm#!h*.]e@h.〿)E896>~K~ȥveS ;'d^I0 }B w)eHU10׻Nu<\Ul.lN*tozl@ Q:tJ$g ^%jyuDvӲc#\28+ /r:[1LMj:|"iƁs6kx)fT̍c3 q?yWKN!ve*M"/'>ߕ+`EPOe 0vgeொGA/S+>돚5+U|gΫpMFF!k3"l =lq> 2耋,S:o|vH7,);;ov;CK(P‚PqN̉,;\Wx.InC|b!p :ȤJu rcJB/PwwsvoI o}( 2blnb|:)LL<9mn .!IkQ`"06|:۳VrщםUՈiW#ځa>''uZJHKegZwl-SnWȶ$vϱ|x{,n?&dh~VJLIQ;*R]1ιH!į{VK[2Ua<+HGG@($G3'e!MZU{% AH\~w.(J>J4MYjeqp2@ RklX(ނ֨V`H)`BGU :Xa.Ђa5-\ cyRx$7zk9ˆ+ u +דPPLHB,E,QO-nP2t`LH~c^ .%T _DHUyd_0c uw(}M=;Ac%47V sT'd,^ j'p]2[N⌽cZ▬$9q*"{O^mHk|eAMW[nl} UrdNHĝ7I \/gk o]bK4_X#5Ň;!zԔKT)ئ\ĢbC7GIb8=tBDZB@3$ȱ?Lj 8jeU_w&)+ 8]>+-37K}n>xsOEſ3[SLi#Z¢~ ].P`(7uVYf?),Ia;GaU'+9=" *HTA>DuG5s6GTѐ1`o hT*,FvIX&Si#R760sV k~fÙ& d> {+ܤ㷆8FK8.WZF.g@x!J<Ɯr:'|!Lj5/;FK6 $%<*VU+ (rQ?)I_f0E/Y]yTPTݍ5%_8B:*4d?WظƯ5)N/3 `K:@潏QaޏoL,4'nU1ºLq iyN jǃ'xݻ [pso;tu5 Iqk$ܢ`|&ɺH$f28S\#S`ya)I1Us%r'^yB,Y*4Ft8w~c A^8 +uTH՚Nu=/jLG0vUgE~ iӑS;跫mQ`#0 pRݾL tM.toQ^gp!\oH} ,za=~,>̀GA HB$8 GA+g-.ra8uvbF@=h,<ϴ+ꨀ7uR ' 1Y 7 bBd$p,7z(h=.< [`R7 89':V ŪStY V1$ĩ+EB##CU  @=VZ/eHR'u8OD4e{k}nGÞئ$Lvc kG7SFJl9xU\΍Mw*N(yiѸ𞹻*ۃ Fxvq ʠ.Y}VsDfԯ${z07/5A4V&#y ;V8,MTaw75@dizZ1VRؑLXd7Y|ӟh0M}d Dn`4((_!`A/H| ׼N!1&`ɓޚG ^ם ?9Y lƒ" ZKyd5?Y$q<ŶƗ㦊+gKY(}_ܿ!SGL^C)h`6S<2#-'x>Rfr&X6KV뾸+$RL|Z?eR3*UJ JvR}VCM ۹~Cײ-4.n]䨶f?W`^?͏tg24tрI>\*Xu2e8 CŎZ~َAJj4TuߒKc8nZ UIGķ4KCsfGG:^O _z#Roi!*Xm) ӷɞkb|"-+,ԠpJNyN)BNW|$sL6考>i0,#ίVWMpv7%P- uk7KRsNgqmlNUlZ`o:(DL5YKڴ@f:*Ɨs(./+`[Km9:\Ldmd^ՍpTgl6 `bghjݐH̬sdN4Lg\̱/'nJ11hXJ(,:r*̀@-ug&;o$VW[P@-âfOKj~O%wKX{V]mkպx,v]V3 D}\{~w Tp;2}^i8^/Urzy]T5;X[|xש}cC10+c J׺,vYcڌa"k&0 $'+,1^)1!]c9]@FijU+#0p9v S)0'IC8&`Vab*e x6f%EHZ;MBzMqGNWl邊"ZA}nI2Yu 3Jtd kXꗹ d +d)'3qW'7WtrCk/,҆Vz/*4)S,<{:rTr#f: *.²%DdZ͚!%Az!]߷5Ƀ 7dXN!Y9$H緧S8I`!ּ<\>?˚ܿHe $|0(Uzowh6. C~E0zd](|pD2ؽW}+F:%n*'jAf =ԫگJYI4%AI/+ލLtyL}8NszPؿokV"ڸ I!$U L\SIQ$!F39-+APY)d3s5UXWJ=^$ygvd[RiPu72l?CD|ߩLԣβal=SL=hy4YN9\%ŒX3hH1r-G[Hк Qe+3KgW~pϢ夵D*:0*P+oQn|_ !|Lvd_pD}[uF_ 0]77 E^;5.pTrW(`9}"yP !\3&'[ޢ4>^A?0vOu]OuE >jpD7Kӈٺb~61 P0q[ YC,a%-1m/ ;yv/~xw4Ԭ7 f,YjNh٫. i]oôZXHSn}Қ_&jaYv4zj4yz1`1y%1wG:1T^.&q\uݮ1_Lda2QNи2S"'Hi.;77w<'BRW$qz+J-[9chfuCR}!qR1w8#]gzɬ qZ'!)9 ix;fCAL־70'NO 4A|mO\IѺ;Ԍ)%( U|Ĕܝo>&:#TLP ^7JN|Dq=]ԛ$Eh.cmo,e9b-6JGam9]7SdBj H]`l^3fs!FB87b fx)̍ m-SGMkU#'B%E^y($T^ZS3)H@? N}*=syH$mq5C!5@Neũ'{C'cC@#O6v;+)GeZP]"\Α2%ҔJ 'H.b`&gED?~j*|Ba]bd F3м=eH / 9K?#pI owRF@9=ʿ)h=a@2?Q!ȤhSLt$h ~ UxN4=iQ:{NoĦ 4;0R5,Ԍ0 Uqyިm=qcCznK AiñUY1(էFռt<:>p49x{d9Btm2%A?t! hY2ҧMOkiןOwmUy7á;~5 qSj^U(tqNПZ)}HMηm}|ƝñSfMM859cX%x0 }-ޑxI[}@w O"Kp**s~awW6 FVWe햮aq@ԩ{FaZ;A~]sQ Xeo(.P OWɑ1mV[ QTAgw6u-FoK/ҫ{@ሼ= F kgզ2BG +KYM!hvPO8'Y _BVLlLB(ʫ_AȘ?ڭ!9Tv%(%` # ^2UJ↼)ٮlpUF܁`n t`*J]u44afW``+?>|lW"j饨Q9n\_Z ^c|t#_Pr?޵:͟66 `|%J "үI`D{+*_,-/q]m t$v.U_B_&+h컽&GLZlvogwhuJfLlP'd=JVhs2 q.g1p˲Jbɦ>q/,3G <oMy,fA.0+iLUueUgB6G:֣J@E Ҳ`NC=\9Қj@EV]YzTpown浽gla`2 t:!DibԔh럯~?KeBchecksums.yaml.gz0000444000000000000000000000045014442217575014616 0ustar00wheelwheel00000000000000}de;r@ D=^`Μs}H(GCH@Oz?^~y{-yxrLN5"1vNy}>O|2QSL cqD\vY 9-3ٟ>i>tMo8[x͉]'?Ղ)Mtr*M/ r)s᥮ZT2+]uHJ'tXc[ErGF Զ3P)/ui7jWJvgH92got 7ʊI%ii 6"(u!m`Q-KTїIX< | Թd>/Թ kB}O▍;h(1|Ac>[[Aiӛ2,(YK܆_@M7W-tO\P=8's\7KJw~Ϥc*VQ8L-%J5\tQM(%lkk/6`R+odbK_ ~DCɡn2 dAZD\޲΀ @F"7ږL7=_xΈy-E;EA܍e$hQL\mLGFx H N~K9RjBoܳWah7k}_4 o!tezj]~=rf:P4CcJHEV23V^%ڮXIRGaԝ% 5܅Vpg<-jIhz1A0:,ہqvz=}qr~yg/Nސx0#c# (L* 8κ!PowzN ˾ru;5QLƉ H A=PC_"Q0TR9q"t-9P]zpYl 0AmD,9zkMs`]#(ϕ>)ª{Yabyon BvH6*Mt4/<.Jʸ8 bYW)?W4YA$KqPk}K{ybz񀻍^n4/i0ͳq IN9 )x IЏqڏ, [qbAM;>& ¢Xө(d2"!gzTo*|ӈAhiЍ4N9diAoCzӺc3E)}.q9 7g3fyZ7IqwaQT402%cª`8cSwu?E *^F\L{`((0i0ze;8qhn'rt~\;FmZ3z"'P kpq`%cmLZEW-vh~Ơ8 #8/hRnL Qd|W@;S ?6s w"$ZQOI /C5/GqjN L+bsWf2o5Phf: :b'׷潍[[b [ӸwoSscsg-fn? Bh:%"H sb XRB!!J_Bb' NE*loYPBFGN{#).-]3cLaFtREB~Aּl͏闾)H*.4fx/r6FEiQ WQx{lL"^qMo4![ 4YT sy[Lݽ>Ɂ$*7$|UYƽ/\I<XvRgR8i4 .&1I_?6p=%d<.!ቆ9VܒNܭekyIgMOUƐ3H$ј&ڮK\b%̼3?8 N~ =g?iԃ8M(0^I {S|y. qe$s/wώXaqɣwE@ql㑪jTF1˦\ǔ1A(]y猤nz ]I4r<L7:qą%o$\՝K֔Ią+aȀl#*t%=m0v\J>2Q4%ȣ4sTcW[7U RUq@qͣ|x3o9}Ui!=A1iwЄYts[*h`[S°ku;;{zp}TIe'L8qӺwXvavMoֈ;t&.I*؂ AAEX E8KfxWlo\y8/$!@J(-cLu+;!1;MRbd1qJiJ ˡ8oO008R΢϶…YB^\=C<ƣ*㢗'Xb4'8g%8 ĀƑXVzqVSA?b=m1ű.,L [ .aʿ/@$Yb9 UD7YQfbCҼ]`?ʯOTmW }m~HYܙF׆̽exMnI_,ý8f#;x-Q+aU$:- ^Ʉw1UsjnőR= xQ& ~ B"s2bGY(PG4b'^Np(cl"VJVȢ%T mKI9}/XGc{Q<W"ey` +w@F~," lHB>*k1 tx,FpXS:}G Nj1%E|a]WL$>ʲ Xd 0LuL&!Fhi3paE<0],!X#hM$ӗg,wtu}KpN,Q 棲AlhD|OҎʅ-ig~$?UegWKyYș{=&7.ft=o0,'bxRxwjtCx|.xLbԒO :ZEna"}! k65߇y[Gʁ[DnS)zQ od)2Xtli;H'#hyIbEZ1h ҫ!돯Y8&.lBYomMlg}D˜ HZ ̓'?` $Sg҉=Q"1PIlTtPHI9"Ɣ+`.D `}Dgv[3`,`[B0QgbjIR={z|k,\ ,M}dezW_r! ܜOl޿;ODBT+bMa_+lId{[$asi6:7‹0Bl)l~<΂U:0f$>yBCX\tʖGY5&$t |$5iD.%^aqg t#[fw2H*5GAWe/LiY#LXbyh$VK-Z/8G-vt%sR hwZl n!'➅ޯbڔ*. kK0K 0EJD")vN em >ó*Nǎl3b8/$;y>s(M+2'迋g'h6h4#A?KwQ/g׌A+g oEE WAkQSgt1D慅yW@x4КfA+Z@FaP?KKJߵE5`R,:gu$h_! =:YP8tcNGQ0;U.1t( kB~ŀkSbJ{C]I~|.r~fzԆl.3? ~AzD1c\O9H%[WEQKj,fmV"ά,8, f!dؼ8׍tܹK)/<,$PB'3O<#lدKb+,{rg`e8q$p d|9x&ƶp@憷Q5&9$Zd}Zqk.ʪkhL,7 0u;7U3B4ClZT~ :!n ;L (&`,!R*}%p$hO̦$@>a1&_Gbj4O)C¼i H}moU $Z m!߽uƒG vS&ZilSq/lo7ANbUdq4\xd!h\FgHeK]P 7edMEyM@(9?>Jg=1\1;"!?40YS0xOg4}osIUL(1aS$<%$&x/PE֒˥7V{TV2'RNe~fVB*B"r! y)v)ԽVְjXhAL<"t-lNHh& AoGaV4(mg[! J&iɥc(C ȦļodH=O_H>.,\fS'k6A!a<4y3'(Qޮd,R &ߚJxHin%0ӺxM5 1C~4qkIZ֑`u_5̳q523([r6Y$dY S ĦE8bY[|+6m7P0gP9kSZTx1M막=uBwz&! ph<E6=l¬L&[-JܢA[xrݺ[xzu=޺o]Oq=F5]u)޺o].[?zkd5FV{j=Y- {++ML#VhS"C 1|^a) }鈤\`4J0B55/e2 wPк.9!N#bG h;#je?/fDK2 I/ -ъ#SVA싦R?,0s$})Da'$ / q{%dg9!> Dyn?ncBnjk Vm9Zci|y*^ Pŵi}߀O%C/ƙtIC?lo,r/{/B٘j"mĐDsΝ km\񥨰rѼvIw: 5ʪI<. 4~Y?V.py#0*6 i(?nVjBY:HI.1@Fؖ$y[ask~7v7تh,0N<Σ}%>Ro]*JU4H_a}Uڗv"zw贩{Lθ5jgskRmy mox/\__*+1 'T=ӆBw( Wt}W-:FߥXN )wb־'b 6Sh;$vOndVܝe^,E2zI}'q>FKXocAKQ)wDQlۺH Z]Y Yd%l_'ع|~"km]>2swvnGWqvyqp4`Cd!mH ~~=c[jJ5a&f1jZfspOp=0‚䞈͚{r{x~KusI"< G""R\Z^. p !>Fy i 5 yrabQRZ+U79Jʓ[S#ܗ+wI%\:,+!gI -fvw?|Ǖ?bIˎ` ' .s2U+mkI4poQz뭛/P҇_H~ל=*b-GL ;Om6aFc)` 0K#eqKo o/AmYW ;juF.|f-h#<·cmuT$1#1=ʺXCQ&GAA'FT*v:ĒZ8WMEB+i20qluK-A9y"c4J)2U΅oKD8cU֬==m?J4dgU-o]ZBQ,ZӅpI3{F͗yqs.L>4Yog!0U8iV=5\ ooH/@t2Մ -jp3Ɗl\_rm}smu܁Q?S4LpĆ^_mUc!4+1;=tl5x|k G) ^ /kFUGF9pInAzAp?; ^;xqvpzrz`af3JO^$4k-6.6>.} &4f4x}YLb"r^l(x/6fD3nm-kbQ'f7 > xNKpNOľG[ @gUpDstㅅh{+ꮜX)ϒIhRuQu'd?s^ɋ?91L9a -QÛx5_7{ì'8"RPY |#j59KPZ i<$F<:]l}di7ӎ cMsږ1I{)ΘKaF N@4apBq6A>+/gѸdc*,z}H97a\=,KyGM"r>s,8@vg&x:P8#=7R6gt4u$g6Y-BqI.~ǐ6mRSZI" >0֟jAni8i:cubj)Z< +Ftųgx4!AA->]NhHC-ۃPwT]ú?]6[IDM?AW/Lso rgl;A87E};?ߩܸì^|Nz$ѐqGgj;>2EwϷWAH}9тeh"%~ .44]rIOS3i%ąդ$r'/ltm{q2m),KV \l̷`CY51R'c*! nN 6΁(;x^gȢܹTwѵaWĎ(۱_٫~IӲ\‹eaBJu_n d2XnH!I7A08=V-eKϰ rZ2hklMM`%q 0DuSFFǖWMzmqR5hORD3I $s(D> ;3Bve6e0\qa`ڞ|׋8f1 Ç/V k ~Kce{^hR#פj &޴.w_ZQ.۸PI SKO4WN?ީHoQڦ˥Er%r?P>ЄX;e/n^cC#y+C1'H)%5I%16%K_PD2,k0PSF Ǖe6&,b$w*M>neuADF(B_CwAhgD05&J3 Dt"EdWz"rjsЍN J_l$er⼢aϑi,fS qoi1W@!SZǖomviq0Xc@m-7'x߹m O*syE)͔G&H<݇}'nH&Ʋ2wvz/ 5^K7e0q*Ijeu5"J;',Vq_B7M#vy@i-`tlCjPwYzRª1 ϴM7oGlbzq;툻@(*A8"q RȼBt_/%R^QP&nrOc\_7@?OTnGMйn ;$3ŚC^3Dd 3|NSI«(%24=w&v9`-O˃{f!T`2tꅳ*^y5ġTFfγ2B9Uo RFÿ zfmsz[zٓ[EVQU~~~*jڭv*jڍVt E}2!3!ix$\?ؗ-_~ ث&Ji˟:<DK$qU=f"5%\]B.e66{=m!  {I%W]iͯkCWqFdϬ64D8 57|«& K{7Ƃ9$N7Gl Wvc/$:'_&=h3m@|5͸1}FAKz3gNM5_DE}lU ŧ>ꁝΣUjb*9X7!]?rק蠺xTQ7ʢ͆w#LL 2ʾ(#!J+HU1s]9sMRbI&"-dT~a\*4g!)C4fzɮ pFڦy`?*^!Ի@v9wAG<)6CC]ʵM m6EqX`WJ`L,F6'm&Z. z%o7 `zX.8ֹnD^~LE&~pƋGHlqSgn_+~A*C^ Z M1Id5N}ݰ!$-(xpqb@Lp9*i c{ Uwu™Oo/ pG1 N0ڪ6]Ǥ +r[shsO!s%>ɕbZ`A"AaY a.mAr#J9rņ 4eW0-T)xM?.0Eg[bDbc:bXtхKQu6@w0Bg/h)JѲm-\ikυϲ Rvs^N7Iq0J-a.Ք9 X ʐq^8J]=%ӶI3gä ׬@OMr*)ED||?^OngL\t [RjNY(' AqMI]G1,3aʨE$Cӎ|_>!,) (K~QJR|~wRdՋZ|X>UO7\Tjlg0majۿćK"c&>h}d<4qev=WWRƈ$ALEaE"u=D|7Alo*BTJ:W鈱Kg-hLsB*D5wν萞wKqӌZdYga>gbRH6 j⟪>k 刨WӷL|Aֱ93idk2:8R%&ԴZua4!NV /'O㳠8 ("g<(v+I;?cի5ǐ]%@R%r.\M8 ߕ⊐3OƼ3ZRPB/̻ V9Ć6ozcۂPOSS+_x6D8^W-aW;RHϭTUMoYzRoH,I0kTFhb.|zBi/ PVdpe0Qq)Kﲌ*7h q2 _}3y-ʬ5ktqpဦ8|UWɑJ9/CfHncPT *Y`ٖ 'k4s3%TC]nLUpwUrgВog lAi+:qs!ᛇ"yJ8usw$6h 6FR]-9`b<,%&/ 81LD K25Wn;̬!3eh2v׶ckTiP zt{m,VԾu5+'H$v v1҅p33ʯ4{mHhG9jMC7~G>1hf(DdiG 5:I2#4T .(59ҔJDvh:.bţaɻJ, դ#3Up j=6Oc?Xg?QdZ-BBf{ɂ6ό5=_"}2Q\#2{leG:%}vBu'(2uPL|Y2ayQQOZ"HXniJF>1X-2"(s–XT2vMe/[Jaӏ8}F)E34FMN:"D.dpN.t(^.֍IfϮ)I9c T+t{AJ{9kQ9,ufmnl )iA.qt`SC憷iX2HΘ "FDvr5jh)oJqhQQΕr n*kA`z rA7kJF(˒7uh͐+|y1O{2?G6C$D)(l,^ҩ2NJQf~m 0ﶝa-GMy yx9 8OvmBL|4K9#D/*NjK|U_KNWkk-+,WłK%'btXnB&FCSYʶ܇TrbBamC/ 2$n+૩Bjhy"4#D ל+بN*ƦTϤ@*Z¦iZ mРи%Tݥ3Y;hV~hs&/zA(ˤs8:ҡ|2gN3q>PiNyF-uuE\}n IC5f+xl&SamK*P{PR:E͂f>7ǵ0Mm߱"I8 -p׏LU#wz,˺?зt?2}` LMΰPHwDC*c3m|ڑU{dȭDK {bXH7lg#GuAd4e5)-+kS j{{˙` S1B 9L(Dc劋U-I?7 gG* z1Sՙďjo]譑\p`X=g5H:t4.,R/τC'N>n@"|icuz؃n-/[Nb"'F4dS>TBtqjb_UQBT,m  u- vM繰|Ə DAP[ɔ'ad`W L`LT`X>K"g߷ "Mgj"D]#!a89o }'i4"1q5 %:< sk-gUjHk^?}8Q4n(/74⠶!) ^1,j$`|_Ƌ`@^L.ɔ2Qq~d4DMST\$7TWVy#SBu4Nq+ <]O̢~^ۦc/q.o]=O +VàhwD+L5Z7I/4,R' >$ai$M` $QբDUq7qWI7۔JdFK/4o!6 7^yW46OC8<#*i< Z_DKY?*s2ezf0 ;sa!:XUu9v4F)p\sp0ݎ-AhFTBK3)`_gvcDa9_m3B^l) &4?T.oW-N /0t˜'jURxqFchJe/bNg],C1bJ=ͰͱQ; n-1I,\3 UbH窫ata^5JBn`Mmu"* V4+s`#bw,z1M1{ q wvq8k2͇+ 8\4.-d"i<{UdV@%J 9ʉX`R5\.:e{GcNa#jJD\go,&_[vCDC: v.Ci ui#&TѹP0MČc>j`ڦ$\jc'mji =P}D.p3ִ9ϙ Cr&3d?Ɯݫ/I؂Usy1DxX9aQ") RОQ= td=8!O[ $$u@vlԚhkj)0\mEmq`Nי#IKiһb-TQ/XK~^r*l62in| sq`k*3WSVR)H[ٯ?fCpn{ p6Ԩ,/\z+v9WIԼ 0 ڹ:y.2'j6LeӬ$Cy*CZ51ʫKCYI/ " $ kIj/Slf8։+ƫiQvU\ΖH0sd0U"Kw=,`i7F0V)ě$!40ZDc.B1B 7GXհ(fB z_*K]SJf0moA2rj4&Y2⼄p^0}תX!q!f)Tmۖ'Z ߺՈ]U#,wwUe%.le(ZZX'czpk'F|F]iCEqRRؙ}23ҥqct HԜaeK,v5B] }+d.©.r"Dٚgtk"*[nɍڹ؛_ǂe[eH#.z`̌, v3.A&;|l:V- 9"Sbw8q*0i{0"{ @(45v 9\)RYb N6Nd;z]}8e}ϒ4DS*nf`,Bڌ, wrP q m킢D{l-"l86j'.=pP"DB297dqwh0Ey8mV\EU8toD:m k%5MM==Kar;w{`B>^+Pj Rbew0e.`x*5 | F[B gL*bSpR^Vf.@*uqw桻.{i ?(e,~qGb$Jq<[W5tD~ ZbXrSۅV_㏷wj >KK5ؚ6̪LXm b"4d}~3T%qH5oEȘk'NHr=1*##LL'RZxiZ&߯I0or첍G 4!WL>;?*I5cd.dZ(紵YM86nc`}]KUrMW3+ 0($ŭիWF31^ۅNڄg0t&jmK*!d')$ eub ~." =q2]2.ٝ<w4H+Δk C"98)Wu2Q9ΙS3"&Jǩ7 ܡ ҘƾYtl"hjռV|5uK a:ĒQ'зӡu0CcFiBJmwsϧr9:Kw$K-MrP'Zx('ԥS9V ">0UHVPW@+Ze O, wazcbb-,]ZȘ~b/=hfΦͅ$?Rֳeg:"(ҤZ U,<,o_WA-W1)&]bdi51K4U j`Npιԋ-L=*Mjn"?45fWPyҩ<kVm}h~D\{`g^*Vh%$$fV]631ѷJJ{[px8W6ڀ#7VZ9@)5-Ex+FRYN%ibqDB05Hf:)-?;Gjsoú͍{?T䧥\x>M~YyIq5 _b-ʓf MOL0fTMghRpSPgUM@eTJ{``so<7m L:v`٨G |-q# hxI orq[jv6IB@6&Ԁ7kkOc-x&ڝ Hu)fwz'?ͽ3^?=~q{?%~qӃ48|vrtx?:zI{~|ѢAϏLC{N=?<><1Ӡ{G{ɋӓ~ǧ4!JS?ӽ#j/OOÇýG2mvluLxLWD?oЙ<:~~~Ji՗g` q<@FQG# /msz O[ۛs$[[<N?@K?1MfWJ%kkCU p=9Ckn{BPG;Qг?}LA4ke]%E^%,ߐfF&QAZ_Wio~ !qYɚ kTݷ=@3]_,:6w:ٻ+ >O\EN;*]񕈥G$$ӌ#zڿ?LF[K[{ƍgK i$NHgG&,4 bzcd.gvx !t4n%мC4 D Nm B` EO%) +bwVK9nX:r%-9">3e I'Os=\^Ā u{B2^1IEm a^΋$%!BI961䪖+E#2]z̴q㵫TǶgO 0"Ul> &]M"}i={0c#U1ɲb!j ^8dyfCBz Өj D 8EĶyܱȢ5iE7Ng9*~L}ULjx?!'ƷdݦċIirY_/K){9b\HA`  ĉ NXY5a>ݚD%CgS#]4sMaMoÉ<3L>a-o7h t"?amo֝vh0pvvd.CǽG>NGFa'X0>!z>a/1wl 5FH׎uswCډ47OA>qA \f:V^ϧ{Jq!_X-8Dg qq>yTIPOg|Nq-J=Lh鶭1ަPJ&(IVaissq{ʠȑ&Ü1F6?(G.TKEa\sbjh+E" ȑèu<OfzR`DQlEKKc`i&oZ I\8L6t |unF5@keahoHH,N q~AWkݯ_/G%pMhb5aиJkJ! '"6>aek[[vvl~1/͸G;wq|])$ "+--:NCp)8zB5j4$a (B766FW8esJz8uc|ί9GwnϝZx yG|Ѹ5hm̑۠E$[!# ^w'rQBu&,a"yu8$Vj~\@k5pj wqxo*%ePU }\& ٭8" }wEV3ׇ - x٨ ;6ƭJCydҔ!M^_}$x-V#ˮMŐNۄ.g?I}PY/ HP#ћ3_J))g2D.%Y$LH{lP# G]"5Gb{R j8C*D5k EN Z9\+]A[YO{ӋBdk#6[ WyܙmgoM׷--~fb ]ITk\M' }R6VOOQn`|ORBF_v:y\[`[j9K,мwVj3 w:kjaS+RttMו܄;[o?kU"dWQ$O }^\BӚwEhܩ lT7 PP>1+ϯyAGKG ϥK;JњlŮƍƄg&/KC Sv_DŅo(|Mzl}5xDtma`/j>||⇃ӳz"ʇBʤ nH[hg^u%C5D30F|;}C(Is[ 4iaNhMQze4EBB;c mxffYAaQzD]M{9pHϭYmqBDIËw94c^oAusͫkflk$7DM}l䒆1DNx x@!By4#\dZξi,G(X'lMϪ- r-xl+3?YH ^短1ܼ~ss+6L7Aܞ/IJX`>{>7T.uWi<=J&OkcnC 0j }d1qHt jtՄ~6hR(w/tm'yOّ ]p'z|<Gx%3PA֚;;ȏ"N_]-{7 O=kOp0Ph|ls3\oH_فCy?0G [6j`#R82#+ Cb dNڼa<=]0~*/oZ EU9q {+s?rmϸ*eb5?gVҚ&ӌ+ Z[[9%.\+KYyG.)ͥx1 go"lf("YxIX$\*qGH)+? Gy6=~,,Nusu{.A$CQn+^߭[_UٸYg:lV}^6+pV/ԪrQ _iq Y a"]㷰:( n_$썳alT ͽaƩKևF"Yv`x)J\%%XXcܬ\mGϿoo%'X_#^-/flϣ[ [k,KK#/۷FŨAt*  ?SكV^!}}->Y7vvnb V%1If5ϹLLHGS" A𣫦hYT8v%w00 xȌ9,d5zCb[S!($APvP) .p׾׾>7hq(k\[sC742fw2;VQГ6IKoCoBPm@/)IOHaiפekt hlHG.Ivt lnR8?0iA77G RTK".tFYhzV]\/Etid vp3 xLI Or,Uy5\PԤ0P+ ,ޓlHBhMŘ)- `e.؄U~?ؖYѾğ\/lKzsWfotv $R/ucJg"ݥ4m0 .L|Hד]J~&w=26w1P'蠂dG `$ 2A2^('qiƽQG2X;)Ħg|5 JM9Ӵ]$y|~wzb}_F&v`$3 RיCh-*ܵeẑ>'zKsE밭{L7H#͗_T SgUu DYq$pTw)a(ZA1 Σn<@=s@m9O>W=35v)hB"GrWaӲTiJ73OtMj<r%-&4$T7VӟWCyf:$ -F%QdnL56!C=aZLuՕ61K" LK4S$_^* Ez2 hDZxgk<^D/}41PW#~od|oS~1wO9S[ˀ ѩ݇ik32{`QH3Ls~#k)v_QQbaTv%/w"UzeޘWx#axFRNLk{]*|Cek/>*&FڋH$b9M&haE! j78 Zŀ\!gZVXdo J3sMr͢ʧ~#2S*tJw8taEtܻf[ U.Q Vk*| n]s <ӏ!&4)ky=L(AXٟuJ?PCa,g؝4V޷N kT 9ÿGKl ܚl#8酪z/oƃwayh(̚1kv:T!}y֕*"AoIfˮ,ѱ:'IU>%$eV?;]P$ؿ6"{#)zbu$0[x~W;Vƕ;NFo CAW@G ]G1ʔ]w?8 n[UЕ~ R}&|8:8RhQ}&4QW83+jivˣUi_-E?gɞ?& | L^o zhM`K qhytQHxp[F;WO] tW5>|@om@J #-DKqh% V_oLMҘsT0=c{6 7.oV=ɋIO=}OTj{E'T|`u4Mw՗?H?/gǿ?y%cj/M|Wz1aTK,?|wz7w]d(&Ǩ1@aPSI$LŽbO|GE<79byG? 'OP!79NgiWw$u'8}NI\SJ~\ȡ %T{&Ew avWka3hyq/45m0;U4+1/]a4珎!E(94|-e<"y՜EXV[.Њ.937Y4-ʈL "D~}5JgG$5Q3h"fq2t݌[,>iVZvZ'c3xN52]4IE8B1z4*3?3h]Qh4(LX'wItq6bRkIPl`xqT# ߕfkXñ[2jQ;уz+;U .ܖ} `ÏU]k~{՛}9qDɻakB=2nsTKl>Fܣ;j9xQf*g԰[^ `4mm:J7~ЅU'y~ihh/|n 3M;iGVz5r-qVCzXEiegPG}O"WO`TA{h@{ ZuW֖\ ~ykR$ʼ<~7|}8zO}ϴæ (Mm|fϞzOlz0)P~|ow[^G۽^vIgK7ؗL>&z#~|>gpb?ől h6g 6OΣpT`A=]?kOzȟ| "~fB{||%dߦҹ~dn6$F'<Qs 9`Np͠BK<9BqE 2=-pe5^O=se'dԿEzv6hӵ$>_ h+p.0Ϣb0#痻n5 ˹b*{M6a;T]yn9pQ|#о[)hʀTV4U! hKg97ZOH\1kt $b,(Ʊ{O r/d~LT~fx<\g{(O RwےBҙo'DX'^H2 >e`ey~#Ҟ}K?5<]f8wLᘎbپۻNt}aJ)d/k= %?=O۸kW{Fx_ U0Op.e֮p6ʹca[|oaz? c/ܽճ!ټoܼk &viv+q_C3C-PIeo<}y"O}g+G&-YU617үw]i |]t;Zkpe\SBCt6=Hx^ _ vy&{06}![}8,+mNsT}Y'oMzY+3vE Aeyl / , 39 `:b5W?x"RTX!qOOxac;nVgkHB#F#R3XfO-HRŁ ,E~j^q&XMŚAE8X-VE&[@cۙy)I9BGkH92s8ǰ\8%-J ol5ŝCHXCe{ _FN19_ӥYJ/eSVE0V {PXw>g '~P8P__^NVtfk s70~j`[+Ձ7AMe 4,ןنKeO9 %P=V)#ZjO yPR0zTwdbDz_diRޯ”_σ,>)nTqBwuaJS(kx@ٔVYH[Wt(qS[Gn/sU}`ckiLŦd{y]vT'A W(9qԚD|3g'?i76iCh0+?y>~ ).3.^)%ڼZ]1O4'i ~|btro]m\s͋;;&ұyƉGGmꓤ%0ovGQ 2&94$@xy'#$F"q>/fTNPV|&~4Hݱ7K+ D 䜇S>NS "#E<9ֺZo_Zwb*lF{8'^'ةW2շNld7cwͧ'%1i[#.<{V+[^r=ݚX[!R:iH&)UgeS9jsASm>p;;U{㝭a4n9x=jyM?sǁ02:I Y.f1g*="RS}u]T憃N% X2ET!5G>^_O/xY"W9}8Fg|OѤN~Wb&F<)"j 9W6"uܾ;:Ias 偒_nД;U0j T~`BKQ{V})jT. i baS\p St ؁Â툹S5$v`WLEIS` iqX_7+xxH෣1o}{ۯǿ`gzÎzx7^SP%)C/8:W[^?cnw'-D-x<"c^aUhw^̦—,`+SN`jdgp}x`A-5#+k$Mb "tc: P03-3%78λ>囮\5{Nz8lđc0 GttE"}۝gDZYZ0r>MY2%ᇍihVU])O f0o6fvJNp/O,hG+ c2n>ؒܛL (E<1U5Im7;$sQ&4#\=@ׁt:M):Ծ~GpEr"i{iN:eGZ>,g]rI$"ǖЙ Xdd3Ohnƅu3kC+'SXkQhw1mgD[I>tYx\Q ?cZ줝+"c*3녌WuSWK4布$w$_DYEdb59w.g}ä,OLIDLK{nBiΆ2AqB|񹙥V%.Q*J7S)AY+&v_(pߦ҇$,m4!VF5ލٸ\rJS:dJ&MFnv t^ j^zi̞&.(󥾉fn~]\#`ʩaM>l4 4r*MivkT0dkĄ ÚVytvQ1TO!C Fq"Ú,{>\+斖GҀLMQ!uN'ޕ[Q >/PQ] TIe{] `c;2<5S͒8`@ ]L*蠞f{"+xF!%-5~ f9 U*l9~ypVBb[.‹  yIՏQ!wP??_R VHmq|ljnk; T 4.?#=OKO@ab/IyG PͤP.07)hѥpO@#)A^9~dhKl&ɋoGV~KIkD x ʹމ$u9H3P1OH@ EKI:}S.#N}Taˋ㈌h%7dH }Pߣ0ŊvMr,c CLELr"RÕ:pX"XtIC I&02`K]FHaҎ@Rbԩ679b8_S\4ɕYE ;N|βQ=cWDl9j%m„S:3ٖw< ²ɢ7}乀,͹L@"H3Ydќ8m[QŃ6xxy($=5C;]n=xwّt=*ahd-SN]'1+ ׅ2)2q`_0Ù$F& ʍaԽcToNll{OR@H% hwM-ފ(Bf645[ !-['o7T?].ږ4"71Zgav2/l C,3(Ydm7qjd $(T590ɽK^B@ay O3%'F&9G&<=Q0iH2ON(]9f #.sH*LKk3A%=?Ȧ@G`HtDt8lh7]]4+%M!M+I 1"PSA P*߅a'[]p&nA yD 3MhhoRq3&ZX-S vy48EW]m$,Sn߄%-ό`lQZZ+SL.1x΍Ȍ%#Y:ٟΔmNx=8\y/$uШң3$"xJE Jwx*Uո_1A) 98`L $ <[mbS($PZp6yn).R%V AA~ctAߕ4  BNT&Au-j5_)*_юݙ wpNDQE m* (2mY߆16ǏWQ94!N2zIfq_>DԆ|4]E3l(w=,*Ͽˌ;TyoCFwČ5|x҃<2WŲ8zy>Z ]={FK/"(8{dNxN:Zm;:^zVwkǣlWi0NqɎh>#Dp B!6JEjW<3-GfB9tXAΖV^gqJִ??"T@5 --k+S$Ό(nTWynf6{3ТTLfiu?\ yŸ(dYH[g\3 y0ng'J bZ`Y`$݋\@Ž0sGd<_IEa~ iIL12Z9SVd>D)4NA[<"aC^#̡d{<#}l .pv0Kؘ`!* 2 m.B)6t>:WK} 2~ͫD3[G췮nc]4%a `"BdFLkdw -9(ZvP';Shfhv;eoO~Nϓ,.!ʴP>8FYq)m1BXWX{ i呸5$(*iAIV{#H7 y@_%LD&F6iZF12ѣtX~sy qMSDW8P-f9 g2g fD#`Tjè*fuIh/t9zFʺYRG!?xyZ7˱GUej*]5HaVMmW0Yc׵Ė0<\qO2օLO1g+ڒ;<޼*cǮlhw}Hz9hѥe3u#.΃x)؏zuJк!EU#Azz7QfnBp5&i5A²-{_贱ZAͰhOn|(< OB}4^|OfbՂdX{8{/hM kCqrNAziTɒGB Y;4 PAa3䷪O ٜԖY: )ZKie$)/ʛ(nuF9{H0^*@<Ї 47L5hJ4萅x^򴞋ZGK!ִ27̒8*<\l#g QߐǢYyCam&L$\flݚ Ȩlބ0@j\Xu]2~?TtD](LĆyS1RR!9wTbmsy4H -E켲yhC̓c䵭]u.EA! >d,8.d4 Ӻ I\#քmڳc_\\]x6=h,Q2mM^N)3b;k y&2 E ́j.=h'i;KvEO pHNVeb82"̨I7 {-qdN&C^(V:u჻ǚ=OQ&8WWqCf Ex @E؊Ei`ʕYDot'xGC4fŗiQӞ`;J"fl(Dn]yEWdE%چ´FۺLn[H_HI*ԺA"(%u͌9g-S,C3nT0;71jӡi ^(h}'3|rq@#ǣbC olHT#Ϙ[TcIĊ=E8,&M v$xh І#Z!1#rb M_u\-.ahP8!w1l\FF7YV4d<-lm7% N2. c?ZW: =+i66m2YhbAH=鋟N=PXy&/`#JېY8<˖,8뮻Ldkp׊Y`a,al>v:䓇6468эl#pf *!JCz ;6H˶+ra~6&"P;95RӅ ᬓae |-qdU[4ͤabi}6xq!iAFyXE6Z - =zZ29(N@LW=!IјM*irVxGv?ksʾcDi%sI&`0knk6SVj)AjT({91\R !K R ~c:Zc]mC) l"Tog[9 tAqpKJYI72CL+/@41;,7k+o |H-gcGsP{ct!HK7>HQ s<\q/eJԷ8R/Ft*' oo,bߜ Ka!܀zK6GUIh۪T5K3X4mQas{VZ6@jRE;'_!E Q6TMҞU5mRy eЁJ 4 C#F@Sm(˱c"((qs"_@F%F[S͞A6ZgԇȞ4* CܓZzb#r$J3I{(A> Y_^fj3&in] A"3s.= Nw 1`v9Zpc[+;_kvD)WRke*E{~VU`f!?( Q|dE0~b rVmosQ"Nl^HZ |.( 7f/1ufc `_ݩ{=K `lq֦Xbqa"`R}i Ȝ u(`vaI;?̒먍MÃr1o74]rKs/vɶ)kYckQc@/h u9fqNQLt)p3]!0t(@s N@+ِ}۰0uyݬ#\Le BdYeE@yQxE.,vՓ 4M{#2Y]2A؂ 3<S+"AEzA 9kġ7r/d3sUVVb۞heo! bx|Yt&L)j*EqnjDcCÿp_/!gc$Yf BL1.4͚H‹r[D:!?زB {(ɴؠOA޼k)O@r"vglZZ0PASVFcl 7 ME ݳR jx.pUbбx]z+T@)雜 YA)-5оRavmL3m7IYfCF?I3= = q(GlS0%?w,j~|=qGff"\ 9'k8{/()c(qЖF&a|1@*&$G\9IB3>12_.µP=Frgc h;Eu):r q69xc"4T'DBiGiMAqIv&~L :ecps˾ߌȹb 8@ S}CVNɘT.BV}\[ڄP! ( ?Ij<4W|F߱Q Ĵǚ'ܬlնڻx,8XP2ct\ Cy)\<-QX%Dٌnq&=k7q + ':H_DY09Z#nxCJ cEgx.9է*$m%:$qv䜃 l1m!ЇcLО/ Kг9E//g.[lg}u}8\PIĒWt$F Q:.! Û "L #FjK$|o`50sdѬu8m!4iҌh08eD="cc3UqdDZnZ67FNw3=qsFiS= P E 鷄~>ڽF($OX K>0EJZQ~IFMQKX`ף !*ۉFh&1zH?E؊ #$Ak|+wd4AH4B"KsDaH6;%D}a"`dhpYF!Gxb7]"zcx#eP!s!v1$I ` [J Rhұf!7 d rNυ8eliLmOˢKKEgiC>4M>lNij+#X픭^tP91n H'tr2| /+18h5;ݑϝQ@'g=aL]DoT7BjesXӝ-jh٢@_E.13Q8 kxB =[Z?PW1VnT :DԖx$4v?`WcNl9:6m߉kcV'5ܰNT1K[)@M waz)UY+um 9%Zj#"z~WB4W0̸m!.R( =`;HD9 2s`NWcbwSRqg}6D;t׊΂F* c<1<>\*ж@C٘JoϘJK#.jƆQ,ە௳rnǐYUU nlK0ϑENSeyt#Am0PҟfCАb8XݯJ.X0J„_QeÆLΜ`%jS-LhBjeW?|蛊_.ޡ8BnwnqHeV>~Mrzwkgs8'6@p |cvgD+"j#ԅi&y:-.Dѳ 45kƂ'Aƍ<D殢ÜhprwC-ه1j 9GDPPy5¤8GL<9ˌj薱$%z*e Fާ;6a)fu6 mX>!sV4:$h)b@8qp~( m-qc%R/Ovw:jׇ#upz;{ovvWϡ}{ P{58~ [wv@S/vjK:<~u^9|}p4v`8~vI`Rmp^>t[ m{okUGl~@!dՏ/܂m`c=<6=t<<.pb55Nzym>9&`kZ;©/tqȗ,sj|Sѣo?d™ ,Q9$a=Q,oIW3  \T -B |nD$w,w,Q=#ا̷/Qc߅w44sޤbfy(~CcTYY&C+ƋpVQVDN՗yO֬Zݽ1Mz zEaϐb -5yC]Xj#\ IS;\:hc n2gC eJCXƯM)Z!~E]5G/h8 CrnfuOmPj~ϋtirX|"9WdSX|e3|(HWbF# *<~ 7g i:[ J %\Ov TnRg/N5 #NЁK{wҠҞֆsц9W딨F#NV1r';sbf6*ISWm7^,$(ǕXxZB,fH}fyZrP?SGcDz9P䬷"g}6cх]7at'_K9 ֛ ^)1Rw]nz1|INdaVc)pWm{" TlKr!Z?s~-2&0| 2,ՂP.g-gq SlTwK >^we=q"ݭ(%z=D:iE%qf)g x|$(5nyE:GG:?007LQu):P f,ԐfrAh|ZOJ6p{nȉZ;ͱimL3\c(bׇB505$)pi!F H&K$ӉI@b\m`s,be4$C LF6? d2rn8NQ7nf̗:ѧ[E9L[R ^SM_6>t9Zz6ez}<3"ֵ:k0Q/^))p}# DIzS滞Z2Md28(U{j VD Q0ah 5lp‹aSHWTG3)*\uGbJ&K}qLXw(z[M]FN*[5|2226u.L{#|o7v<"7㙸DH|njG,lX7g {/-%  .;J'-5nLfVܦZSIbrcoCAl8`tjДqV ?rrU%rVP- gxJp6y-@Ε|S3ٚdhVUIݏx_o$*0KCv(_yYJ=MQI]w%tetcuL{-XYz;ظ+47PJ@/f2Y}í6QxzàI?s.6M8~nyx«@36;!6N)\\60"Z}Y?IpDFiMV߅Ës\d{Tm_Fc-)I1 V0\͝u݄CGL꬞Q4x!E[iOQ}%w" uMbp{h`oǭ(uT3w4Ȼ zcnњr^ g]wduPр.+9u~*p)AuVq,&qֆdRL[gXH \}r":+NJ33!-@P xMgݩc%X\|%`P4dbU {DQ4 ŏԩ+g?{ @ eˍWAE7{Bј>iZ" ) 0Y/4Sz斨B_֒JOQ܇rΑHaRnrOx3L+F&Uz513{YWkڇçIt@nh↶:nnWhLߟi^ ?7[a$b#sD'.='Ɨg=OgSACyv.ПƫZK̉\ >cMd[sTh6ݨ ~ZNaՆ)^j桑2D]F$ĄW+i~*pxq9s}OW(jI:awij0G >*CK?42|:0`)="?Q3Xƍ~ZCs5*r^sG$s:wF9e\}yiDNKa=ɞtՉ*M<]ݭ }g{t86_#(0bt>kHy:FӮ9 I˂+R+MEKNeHFByr:A"_+R$xCevem6+&_6$jYe0hFv0Iƺ]tx*ڟ1heyz"ЈX 4\.EŴ땩~&D` q@4[׸Mdv+;4ON^okpN=GO1\ M8SRa&T|[cT2\IvŬ|8Τ6:4@ >ӏq% $G#[yMXGz2,"Ί-YΠ~DžS&/X޶z wx*~wAe _yX: 6EPF[2{0rw׏t3?7kHcUlVINd1F,R_~4 =Rg@{ަ7bE ,O@%Wq*uR`m=rիPNJ <.ʝ ~կ`F [ojGafr 1 rELŵh+ݰM0~uծY<ȷ!wşdDP2T_2?`=\F@U9M+Sf@r){=dI Q?!q:ki2D]{+ ~4nxϸ Mo#l/7c8Ԅjk2pZb{AnaT~rՠ?J2Zk؏Rb&-XeUR\ߕ3yJ~CR6#%V'ׅ;V^!.ͅ:Grx4xuu|p;L:yW#J\pony+zh8wV_\c/l ԰"8׵_ m+r`ׯp,3e-H8\6(CiCH8Qn116@ [;Q;!JJ XG6 h)Xqk* kYt}X a v&Hy)#G , 5m$ \bF~KP6Nyu- gmeu/R:vtJg[^%ޖa>}tX7&1oD%;'ZĘ3Hd W.FU$w$TTxw$lf_M(Ļmוs7Id #*j(̜$Vƒb66-jlt_#Udo^;Rf}6L9\7B;Wڇ@*Ij(G=h`õ^NWꊍR;yW>\ ^0&k:qhҵ~~ NtN5Zk7[n=]!|~߉ql­̣"EB]0 4+y0+,DB\[yk0rdf3Ftl#n|U =]SjRQ}Ipϒp ww?St%q ٞquHk8̺ *4&"޼ntb%&#JRbz5EK1% >{X,w ižȧ&MD($"N 73/Iwj(S ޮtZ2RF#T)J\_LWJR8x"$L% sioa&XѪXԠ ' 8:>`,Mp(dc7$ [^ЪYQ)[rtP"JذZ(=/Q: ޫ0&Nۈ8AQEB)_l Q#ͯfDCze* dIՓ{'UFΣ4::S]nj6Bb=9v˗< ߪsuvj'A~I~@Nr-+W Sz ն;z$53rS$*u OcfY~[7EɅ̕_WO 4H,5U lt~j%&ͤZr^БX6kDɫ`jέ3 [O b.mw6+w+۷86'wkr7h~H#]vò@oFmvohIf(mJfD\6,#`R͐p]pm҄_7$%r]\U;3ΤT'ĥ-`( Uw3?zX߀kG|-P;b?1/9.ٌ b"/%%qx}%ܒ3 3\, bb &s=prIPT[Pq<-4{4jƘ HD80FDإze4V₈&Y|,u7fh}siM4 Ii4҅[,<1LF{|՛{sՃrlyuT+6,Gw-f6V'tR5ީL8LjMjV´#L9&iC[V+_ksdXn+Atej0hjA~O-`D2\-3y}e)gAdS>H@)w(Ԝ f[}^xD*܍ah⺮/YzO)mX_)l-;*nޓ^oӍvQl`(ʘ?7 䢀'_brGbK˼>ǼRW3iE[A֌aCboEZp bBMv~ B'ݢkxK\FVm{@.Nw~JoJf7(h(μ7ǵ6kn7[fI_P7\ӇS{ o]_9TعۨZTP:OGtD8., 8;?|b[ڦY55Cz|{vL3'v8D+dmGo^S~րx:Qs9Ve9~R5)E?s35irfԽz5< dV4_E]rO" ij`Ϙ&}HX8Y3q4 [70I j/PAn~l S#꿝l%vQݬ&JTU?}VAQv]Y4𿸦M r6o=Ǐ|GK2uAY‡?WE/P`kpCB $5* ?8izŸN6X.%=ȗ g>» HHjdC Cj`hYͰc2. sճ(II42(fC5<5!)x5-;5$a,ƿo>-80{R|Y&ȳM,2tK|gh:V'p?LxЎA1D̒|-pt+h–!M0J'~gi6оNzT+!+͏WHJ)4 (4*s`>TORJtWa0q,cgցt Eó4A[Mm*VMOJ!c~ZY^յE4bـ8L02PسJ;.OL/k"UC%U>k4TڏqAQ[*iث۷ Cy7U_N1{߻׻OG0 ojO"ba@LLIb m>VjɘEWF'2gE(RQ y{0#6`:#)H{{߈-wSީ/m,IwI&l@ER8JxRHRϜ2MvWE yc$ER\'*z}\KǼ)ap..[Lh!}C+KxȆϰ؂<[] B^浓fmV\YV,Œ`{N~-7_?8dNcK}Ţ|ߡ t^`ߗؖ烯}Cy`w92Q7va]: 3=LreّZIEh#QKFY#zg.gި@er*D̿a̘v؀S.,Ќf)FĎ:n[e#e'OwEkow~m< ZFcWVN _m88|:JםpCi2C&ҿw][MrQ^)8 vqLJ ;'͵|\*9֙ñhE0%.sH ԪՁ^kxY&Uo ]|Yew(Ξt2Ez]c`oVˇry3v0#Pj.a[Dm Fi>vhC^9;s/v $sFA{rvʙ0IUpӭ"|YoiJbkq%j>qzmJ3/X锠:Agn=lk=7;x )\Hۊmm'C[ih8uKҬ#֭p&&ͶhfuC w̳^> ]vsCkJcX4v_$leA6 0=U7katm,M)GG.e_A_?  K?wǖu̩1xUn+G!yɆW2v|oBӞ||̉~_];!xў:<(kn{Zv}(|4Xjmx38WwQaQwQHQG(Ae\GwKd_.(MPڢ1iM5٘4`Ys@HhqrR.M\y'Vp]kr ;0jkVCgu0 i]py#{Ԗ<d]GX&Чhډ~J|LzWn/ġlԝJ*WzymBͦ"(+Ŕ8 ި*Z<76ƹ*!VՆGx;^k8 uZgV>(QSQS./;\S;'@ lꔬagځx1Yfޯ&6(](29"JޫiyVk2¼brʉ1B_Q>CNL@B5瑜:1h#\iߐ7d%tiޛhXNd)7^9=u@j [kION&2mfR 27t/DqѾ~YM\f%]_sx`Uѷz@Sl?D_' {)i6I+Զ.T4-N%<ݑn*+ZEdLt&~?!@|0$vJE_W|r$?b= ACiuܣw aH>1%BMZ"ҺPDVn:} m&lվ͜c;aDtuD`{E"35J*V6T>R!%6يk#w'5dVCq2,-.40cc A$z0^wq5-i~cRŤ:}/eۙՄ6}k򐯊aC`9*-]Ax Y FZe0)"K'c)=~ң'B{w岛[s:ȥg%7l&ty ."i8LBְV9 [Tj|> M&'/r̥` O"ʆ%A2s(M b ;"7JHvW /_R`d (E+p^ujYX@!&3{$aK)HC xSr:캡8ԽTw9\.uw ؏,)6 Wy%W_ro*IeK+]S9,a`VھLPEA8I[׍DQDwWZA!#ptfz;JqfKM@snI,A6Q2ƞ(Nzv9$S_&<=P7]rH? a 1\ 9ϐ,S25A`Iʼ Xp_Ў]w]LpJ޻qd*:x@46vߣ1$dyH-豤֨%?unU[Ln]ٝS>Uu\g{3>~ć l<ɨ dD>C[bm# n0w a)Ok _X5]0Cs4$"U)fp&sMa#(&L +Ԣ 0!A9Q{,/I7qg>Ӏ]əK'k"3/e{*؟unŚ_, kh.݊}m#ZQ߮!pC].XWoD!lFb)¶͎qh\RCg.!6*i?_{zx[JuOed' ۾q?Ygg:n]+h *-B'(]i־@闐ku'sAr63uг:csҙ$صXZsW5eVȱxMm0C> ؟O0=NbO4mizBW}d[1 M]F{ͷ>͞ޛ<4:'Z1+w (?Mx0R[D7UU^cڦ-jGʹ5?́>vƞ( dVm6&3Z3SV#{5Kx `XI0 5{;A|b^l; ӃQT4'`D`cki4iދ3jfY6HԨ6`a쬭dYΈG3 |! 0V 9K2/jзjyW}2;*#4bA) ň[[o%m_mW=5^LT6p99 e$l5[%ڃ?͔k"/}OI>ќOlOlw% =3f|jX J)h=9NSS,Y9 d [BG ]Zbo3RmLLpx*Q+0qH)9-q>V;24䳻iOec4HQ C(g}f/rx&a;B^}Z[`}lhn2e`RbpMsM#YWi,'z;M`U'c_HGMYm /j(yuxnkVNnx`X3D9ÞWᏯZś07lx2Yk]cnzMl}~0nlg4ay~jUu PL;Y6A[#(U]y룵g?wtu%W?;Z$4UzW<ߺf"Uw7+/Š?WdqhY_];{;@{CJG7b|qcwp{9Ak"<W!TX| mdxL:n4Ywgv僶NxUӸY[:N%r-NJ^ߏ?cO N6m\ڸiq ]E7QHԭi8GKY8# Cw&\v-C'"8Oi0:MaD4%{qyW3): L 3sg# ċ,~26[|pEz֖.[$͹x4NкrH|O9Q]zEU&}sH=7@-|>>BjY)?:B7@@TBp 7%rD)h&AvfC#,ZqoH kvDͦ ( 'iSHLN!D|ė!GB6B^2[l%dRIۢ!]HN o8G c!k1ptՀھGB \ˉAMQPR$}]itT#~Y1  `Jl<|:6#E}M0u0%jզR@ z!өd.Cs>&7s{;zC/MO9Hʁl94K?Ifa> |{^8ؠl2А :Sفf@JD};`u]r6fKt-&wzI'F~+86fTW~D ۤa0)8ASp:vAn⫶2 frP4dUQLG =;Bt:N`_QZ 4i w6%3BM਍ 9 _{/^vq6MLM6JLgNy[Q}z\պe7X(.cBŷ(C@dAk]9>\SJ7\6~RY{m\u=Uw>#6mbzb8zDNI5p\bBk7G>ទfZ[OI-w1^=;<8<4|i r1fv"dO<%lĜg{~BE628'ƸX^rOr4WQЛ?&O(_B2lj`(/x$h (+5-zuU޽ʓĤcpӺO7|p%:厣A❦Rԏhf#%,#8;Ìbw-ی 9=9p:MziQDy {Y?C-QT0ɝ 6=kCzoc'O{mFY⤠Y#iuwpŹ. ?NqC*p;3{fi=\*I0++r0Óv0ItlϹoM1Vrw30s9Jpx`I!xVDXT7kL 6 csR\' QO^Iؕʭ bm:6OћV)$+@#֘87wmk5-`doЊ.lIR|m?y< [nƽro@v 4T8tP8-iŒ)߆KD!p~Wo{/g$^Qpɹdxozh鴘 ץ&9ˤiѫsj­Zԉ$:–l+\x4Gx(C0bR@wHJ ǘK17߯u{$G˶J+][ !WӐwCe~^ӼeqI|֒/`ZuGœT?%a wB ۗw<n <-m _Lj B ϪouA;集#F!aƵ@:9^U*;ZUR|Y[TO? P +LBڴ0>Į:D^Ώ׭XXPB1Ord\xeXpCark"MIA)́1Uc֌aZEw)r;#&.Kw0mM; 3u'4wfCuxMCxxhk^T&W S!f'2Mfeg]|_T諘(9v_B9ȏ`ɯɯ3.D|S,0ibu B .X^FMe h:ܐfÿ֭E[J[ 5^/Y]g!8,&t\0UL h`Ҙt֛#fkŕ~&.r*d@( Nli5vA8^*j%¬qj'B (<|"^P*K+WGE`)te\[F).d L} @8gz,XRFXV* l\K0s}3gIK RkF8*tM찷XQt+OO@j8N+Imec] CjV<_ hS#*;vH_pen܈Ը;K$JDOW]"@8sU&2Wq_KoB,c?=a>y_՞ケ6^B!'6k!:uHnFH.d>{;|j|9m]MLųu 4" J4pJZu Xw1w:߼}e{f ڛĜA dW{}hvn123H*ayYSN3߫ht5vgX`=SltupyxxzMfZ0)?&/rsuFm& ܕkо/$(jh%İ&x4g#|Q W_J|>QY!=hXreL,d;7 ϵ)t'rfNi8-`G6fgH O] Éd* KZ6=o{?P3?0! Iy6Ϻ<5RL1wS24$f@fJy*xw ( (dKկ H,}WDPH2} Ok獓X#ʄ:\"H R*〫_}6sϟ]ϿB>]@ {⣅Raf. pMwoJJo2ਓŦJ#Ҵij !zgwaݡ)al7^ft"y3;.o i+f.eYr1R f޴sq\dS5jVSz5wdk  ƯHmgX}Ӱ!/]Pؘ6 OD-}BYE~W& َ,6ˍ/TJK1tǏ~_xwN1U?0 9!˹ę `@CQ бS.·O [f HmVj %O)\}71 Xi4qt^{ͫocG罹.$\~GzMww܏8 2Y/j)IFxnk73v p)^KK²|Ȩ))QF%l%䰝iٰӁܥԳ >~5\h7Cb]-<&0I^ 4  m^4_~?Xc=a b{%(X$ gI+&~bյ^myx+.:~fABh *m8\ykd(#u:69 e !!;1pl [xfOFMTbs=7/[=Mj+rc)p:dl}Un uQjWo*1MW+ ZϭK58B+f)K0a|CR9BN 0(_nG)qu+1OLy\3a4~^oooG&mlEI1:%Ilzp Ѧ8}Ctu!ѳe6~\FX4=>3EH0,5.L+(8)XR%l 8p-'8`8L}W.e1˜oÊN kZtfI#~%S,|Bz_f~Ak 5 h/hP Rȣ/jt)_M7MuW_<ߎm'I˼~ x踟%DS1*+\[_m$6Ri5\i{f+t[EQXHj1TGD$NhօqfDZ`A4ʆ5~M0b~=yfZg3E6{(e'm%H}Ժ#i<i-$"Q+taEwmN1L|-r߿no%@8yvq9sC(C,adGBR[9(D)lpM[ꮘU#Kh˩qh>zO6ؗZ A`#uH'!qzté'& Q3F8rutW1+ 4(+K2=>A΋?4)]0~S hWwo'||sCScSA#3\aM-gE\!"N} C ,NkP?lanڃv4)F'|[FƸBFH7KU-_,nqg_9J8]=:f6N ebJVXꎽ=]-.FwÄXiAz0fbbpZ||7O2xmdg ndahQ~tw9{1 IBYh]C8/eF.=]rlyu%3rTL'Dg\K"hf4\b3p&EKK͇DkCUAz 1ӁX Vp` Jڈn (%auSIhx4(F"}lcv`~r XB4:RwäC|4g$0(1 4o$ڻ==uI)LQalog/!|X=X^5Ce6+1- RSRJ*}[]D_3k!jfa(HC:/#aRK,JFxP{ܫ9 Հq χӿ+@[ː1Ii; u%|,3ۥG\l>m ~WWd8y:U{ l&pRҙ$)}&4 aI甾طmʺ#EY.Y1-Fmt<)1ڜI#A)<'FGtXgTE'BÀ.:֊C jLG.+ājb8eV.Tt]Ki:utVsD]\n+c8U*}[Ō:Wr•M&|f)ws g 4ǜOFa&%.Nn :0en1D XHG\9B-z8j MyAi#;#8+GjyVC-1֙;k=V% .cwۍE]kq.Y\CW}7 $;e%Cx6`vqR&YQ (~IYe[="V&A?>~a /OPhcmlD߼5%ju\ _dX7mq6z1OsƇc+4C0xvNVh17|[_%=d0l 5~:Gť~(y =w2N̥TWڪ̙En4 HC'㎹Km֫\|ּLǬ6컼+c379rf}OUߖ%Y$0MǴm{{H?d!TSid4ͧ&o Mi~Л?_=z|w|Rp34*>MlEP0@@x_|KCxs7~h(7`#yp%AKuhCuZaÖmlKգwgR5%CEq>q86[|!Eƺiqȑicj/Y\)7xzvIF W8Wm3>ׯQ~RɎ"[А^SS7q}u?;V˃#$hUis~3ljm˂@a5ڑ(W]O/upN۰Xfdބ4$ͬ oU俯b^R4bMpyRޗm W=F` %Ba5EyL= X*")lfIsnviCyLa}OQ(C686Ii;ܫ#I2n .Ldi@0ڣ:[Y12",j;WCn~Lj2'^ٛB6‚QP OS& )Mlߛc$cxtbM)$e}sF$[t(&Oݓn_Ǧ_[7;f])XY^LEe¼6jԎV0&ĩ'$Bb,@V6c8q6):G_aLb:?g?X~&0zl 0JGcNDj=DBEr&06ДXaEV'OW\bMל_#)lU2Cqn<՚D#ςxq/m%EfIWk5koخVmJ7N07Q" !]\j1O$,0-e>o;:g0O9|'[.*8 ~- -fBtKD=u"n7O`"b<,RQKn3.ɺNTrɺ?mJgQF 2Jtu#2s-”173փ;CJ=4' dhRbR$T!uhsm)1FV98x%)Zl62 \mT _djjE@O9 D}=N$ ԊƎÑ$f3½F@ Bkh3B)r wxBe/"tPt/ek٘^xZyar{':/mȑ^62cTi ZG]+8"1ԘXM'm\avdd\FbY2sxE C9<4##aʷ#*4W:TPI8 SA賛%&tVtwXP0~R5`MD}@ 6E`jޚmcx3'Xg pO+޼~뙁"sKggܨM̉p^jg0]}6#.|9u AM΁.0U >J^~P O뱟Ip1H1qVܷk{Uњە)s X ?6סþ5u{6j)uOP *;J !eܖ:ެ* zaX̀RӎlU/hv@7Bͥ߆l3;ʝ_߷y?UV0Tn?GW"e/(X>7Skd^#W1fm ;dѾP ؍%\KїI@\Cb+jMG|[3m`9WVs6+nh/xyXˠwl&k%O!S(/ƽi1.?00.brFFreX6$ ݼatZ8D7ӴAjR !1[PSygDݤ J*V0plHk&‚jG'EbX7f͹nWѤvk lzUtnwa8Gk=%=ƬˉOM1dm(\97@0YȈ[ޕ=.EBXBO.(=rnN톔-W?ߢ[ >KsA0'2a_Qh<\/&hy_S#y'q}Z&;-8Z^|զ X,|r)3 u烳a\`D_ 8|I#@z\S,`J0(ϥ mëdP'c>.EMo7B[/ޓL2i+P|Q5i]h6BJ_^#;{o.Gw'پo+X>2)I>mZS$T4qX9+Sk n5Wžy6) ~?qw3X~H eTS{+ã!󎫭x@Dp~t者2t zI]MU6YRIJY%yo2Wn/&ozh-&sng(ʨ+14Ҵ@ja٭pFFyt҇{~9bo#'Esq:yLZ G7ME8['QEdJOzVUJ71),)zj`!ߌa CBg)aMc l?$XhLMa|lʕPnenXܞUħܴ/5EKRcir(t-ٰfF vf,D sQ~ukʒ5}]&bkjA5ӝs;͙Utt잍C+p޷OPX碾@4'o?ml2סz%׼~ E#R,!{'NLɫRN)7L%;Bӂ9VEX%֏/=F(7UdFJHDELJXW#L"ìT?67;}>g]1fcWh#6}Khb['tK!D׶{Ab%1qe%=~(DT,?+5@s=5T 9>52"u*QV?i\\Q@Ǥj+AtueO{h9k8ZA5+/UbSՇU׽ p׆ۜuk,(DѬ ߭tu*bR ~nGz ]ZD$^S3,?sBk|jƁ]rUMy_`tFIX*]r1y<7{_ }_o=BuzLUUeP::vLƂ0\!1(>o@0nI <[zD54 0dPT0\f㕍W9Ov{'`ZD9SB^;Rsq/D喋>3| 9hK0+Y+9@QHa0Ď͉ )?p/'l-JnKIϒᜃ2fI#h"&0$O߷{ R8\gì;ëcX_)mM&dVCXlD1L,Ȝdꓝ`Qz`]$YLEq~{5|iqt)|kk±ro\BT:b. Ld$tN~Z#Eo=1 S^K5[vB,#oau9 Q'> =h/:]@9!e 8 hf [$3{hRգjee~u ܶgE EZ;o@/mǶ&dZ+}fǛWFM𵏬)6ȂdVp B/U~vq2oEj2O+%./'mJN2I왩w,8},navKm˿g"Jń9b(ʯMo؀ P Ow鯋63Ql` O.Aax{fC43>&܄`xwrdGϽ/ڍM[*Tj)p#TPZ<4LGSp֎$zRtڞ,{1V!-~C#ЧpgQ>f" ³K4xkAzN?#v{}xj&W_ѕKp u(̒HrnX~AUg {IB:&r]u)\uJ1/  yp^3Di0`NV5o'{Wu7)pNSK38pZr&y{)8"pI !,-%Wi5?%nT!D WaO KK'g*5Z5.j唞i ⚡Ʃt$$L 53%fd a9\z1I#p0PG:_b;U&5}YnY6PTdz\g:yJ8!-g;ahIU?H ;zqC'(Q^-oUy]qdv av$WOo!4/]û?zX0lT q\̀$VEGcpsbq蠮[]=M# A7%~Wm[u#S(5rdr귗,ZkMڠiVLӴ<ω.duKBsy5GhTYBcbg>Xёm^>ng2A BaL43L3gz ZE{:4R$Cq$Y]gS+s{a6>&ƃzbˋiyzitC8>8ATl兲bqL*!jh昇uLhC{dQ05 Y}#jwwA63\! .6GwדYB-6C$1?Ю3u˕ՠdK"6E?"S1wg?dU͋3#/~2oooK}<~zQ+c1.g4/"VˇyCa& {̥u4?rVLk%h. aw؞9:rj8 O5ך\M[5 7m=ex@|=rtA%,Ʋb .`DTlB!E94<t vPRo||gx#&|!<~:KWtȇGc|h$tF<ɼOUZCaF!:[f Ǝ(4oF^>m~ g:^h4|(I#tSZ5Kn8r؀wa<ʢPlͻBSmYمUgdjK80 p]3xd Ww~$Ц :5aϐ`H\JZ?uI?aQ|59gm\Vųo+.bj6FJMmk[Ǜ8v! t:/?C0ɆYc6luq\ifc*J* п>*MMߨ)V#c>=HG%)[;QTjyw3XfpOKmTm#ݶ^;j/FB3 q500·-Be.(8`ҾI#dPЗރ {iP$K I^vg.KXhRL[esi:6̭RWǚiԃjH-H{VuȆ).C.G&rIN `oପT1)| 0嘟A'=Rev#Tyf'F1#?|BQK(R*Ve ^?8:whq&~-KsQ _GQP)]PZ"Z)CN!É Z5&(s]+tuA\TCm݇vf疲O[Wߺ,ޖkY۹ rJ?kEWe+QZR>8v@"fl 2|)A޴0cΞdDb.N8y 븊 m6ttB/NDvBl^faw?5kkOi\} Fݗ܃7@Vcvd3Qy[4gJ yb4ũ^j,-RiR=<22įąk`++Nڤ.]7LmcOl_hK7+ WYSI/7a 3qZt :YC-1!'T{)umhug3/"36$Jx^:6EC'ӢΏb, {%k)SH KjI)R>'gi|H:*ԪZ^Sc/Űg_^Y9r@._>_wߟAQ-P2J)vVÜ\@PnT+ gCɷ0cllͬ#US6=.LI)ԡW;RY@84 ;<T 6IDz`}*dP7204"iIAc - N}FYZ^DgYs}1=$Yrք+Ņrf(@)nlP0i9iLN{L1)wK W(^#+ .hPU 0]3ȀTuo# y7>5]0wV*e7Lq6qT ۼ'PAMIpI`?6boŶ B>sVi=,ۄ!:yo H D%.HZ;ךê t=j nJ\m(gE j6Ecvg dȭqń8]M_Qcצ._8N;!D{l_FuJJ͉liH蘦et IծP fST*J[#tf]3Jg++FX|#Zz b o7 BY<2Ss@2y!y|{(mG1ȠG)CTCSa {^jG;&/`saR+Z.$hixn\>'#5hCx2*j<4`'旊`.h'9-/+hrZg 8~3qG "nyU)x V1Z-lKY>,w텠)╌"@2=Ņcagq(>)ǐt'pgۿDGSt k\Z ݞ 0D@ zpvV|l# c}Q|No}YzMYYKksT}6my7PE6[a*C@@"oB e~l\2<џ׭0V?Xoq':LQX]U8nq]քVR&wW-g V ªUlV$4w^3c/-W tVٓC=puy*l *tp9z3xuhV0zдgS7;au([N+]0CKcՔ քӁWw{5]n ^:_E1 y0Fzjkzy6wˣHd=8 o{$g55lr~}!@x]bݽw>z*mjhf fEj~#ceYs챂ۃ@Uٻ4.?] V =w Y 6PC`9S aK eRؕkXA=>7ղI9j*>qMώeA4흃g. 7!$CgSuILIGXJ]e{M Kad]wLcuo r15pO9غy 暆+Es`X{.gs: 5+fPx(INE 0 $)g\drAAv z2j(Spk), 0=o!=Q üO{|8gD (xOheݢELY|1]0aTlRٵ SA]Oè)LJٔTzo]]TnfW/Ԣ/)hrI?PBaI?*c$K(8[QڱMĚG8>N߫]Hs0|٦/Z l*x0‚">>Fsٓa֬C06g'8A$O ra&QnE_3/ս=q˂ϳ4` 5+,. ku/x 1%Һsv/fA{8qVt>̷sݷ=5fvSo|{ mGO*.pKv6D ;B"RgѠ|ㄿ])ᬿu]s5(3s=|W1J/$O7tJ)0—ς#ec -y%pƤlA*m=Lx#]W`mmp'U[@^ol~M8ófց1IozW.`.]jDY 8=AUIz, U3Ӈ-RhQh/<...VHn@LM9K4:=5-ۗJP`U8me0:d#4 ")m3 q$64xٔ$0<_qF h2-c(5%0Ş'aPm:OD9J٭%y~VL?, D[$qH,DIPE_ $|^dt0P(P'uKϹ uW'`(z BeR'۵ p/kθ/ԸDTXbsH" ۋϛ;*l3OT;$=3B:t?v9"ˆ]m^SX!GOPa]̚(?#P:#""lٛ!0 0@yԂ.4-u3JH.zƕ|{ZxgOTquԭNU5l_?/. p;0dvH匘vt5j3)dLjA-wtjHl.- re=A9 W3'ĔMly,Z8Q1nhfJ#fnG_MC#; 5^{/|P-j'm ~rT!la`@L/$ $ e|Rl3x4N%=O9%AH3BfIG.Gߗf&B'2P1K1#lSāBH|沤E D Ι;~I*9 F8̇tQ2Qa2-p682؋CV{:M81_kfeeo^KAWRѰܠ'?I,hp 8ֽOM0+^Wnkm^h$E$a1§d)(c/kl)]狮'2dMK5;qZRРQ7O`Owotᳳft;J'HhpVuJ^KA=H&[Akvu8;Ɔ@j+yf ڟa1f\ƻ=9 *#)g뗔YD/jU=hchecksums.yaml.gz0000444000000000000000000000044713515210364014611 0ustar00wheelwheel000000000000005]e+@ b/TY[+5={òs͂kv9ꯧ"--Gm\>jG)<Yr +lmY6bZ %ER#)ްd;_b7˗$Al;ݝ!*6=d>$*ph4RAsBlVr@vq]FF#VOU :L־0%loxJc-R9ڄ'zX.=!ƣ/m~'C:!4|Ai,מ(u ܃iA2? EX>g "Pj}TeB T".zN/Nf+7 5zp9Ot:Y|#X⾐@s'gS֨pQCA(QW% (|ZQӛi ^%թP`A7K+M& Ǚ9h=Z /E+U^L|`{fraIu JbvKks*eJN q]DIЮQK]ACQH- b@DТILmFψ31 VROjM=sqF8<=ò<eq:)g/z]KD1uob+8@K*]Zt}A,K øx6+_Ɩ|Q|Vd8+s1Cyd48 Mc#PH 9zlI{3G~?ť-85fޑ٤.@{W8:6; 9vS(6i{U8T0 * /\:2XW=3bP)߿( dQ52k:i~kד/KD0ߊGދsқQNO(swjs"tޑ0(G1RL(f4&8wq}]1G QG oPՊZWlSLJEؖmVu-}j*VmJeUUEjAdp'̇ 0$@>A3f&7j׃O˲O_Ykkm sG7thN_nΨ7V063u;> 4})fOOO@;Y7v-hvcg^aPmY}6P{x]Q<Y8Mޘ9447*]xzef7m¿ u_n4 s??lJަ^Դ jln]|{>!H ;C"yI i]P|#^`l{雃B:E ^ X0!زhrrӲƾi8ΐ=P𯆼9ku j+,y/uVo~]|镡4m" GAgsD‹qҩ57޸;n:B0t@̀ IM76Ɔ^'zӀɳX[(< A6 }Js /( !% We{>Fʧk^{"Ni U*Ur$.\JAn}R/Ŧ#ZfΞ;|C3wF.u ]~D-3ï/>:a>j=^{ npS57l{n[mjZkf5 +xsɳ |2NH5^>51H|Lب)tfo6Av:Xк4~y_;P5փs ^&2 Es6=! ] M vfAnɃ7c[JӣZv+x}dڃb(0-~3-/{Czp d) >^ Mx– h.uE]Zm ^մ,kKmFˤm+US< k7<<:Q5@JpXqŽ(cSDh\7HWxTE#x4qHPS; <*)덝A =^GAo6[mòM%ފv5Wa:%p-X-BIhooDowj[a #3 d<8N`s(M'3tF0;skՐTܪцo-uEݺE-aeنNVnM2m ^s1SbHbI#Lycz JXSj%?H6چMj[#>c͜i?$W%(QX32am QzLBZvEB>W1?Npp (Sl 9;;zako9~pYSP@Szw޸LS ~;o[~<3/aҦ! 3ös#{G6Iq4K7-$``uAK_83^(6tiB JU& ͇%3ު#7Mm'<+| &wE+KTvrHNw3FF#e~9^c~+|;W 3.@}?\ȥP/^KިF\@<;8Z}w- -2jڂMnKQVkf6f]5zڮoZk)ԙ:z{q yi+>7Yח|PFccou)U~D}9W& kx{ rӿ;PUZ+ ]NfWtykUo^_h];9 }|dS4c )QegP$o@4=IJAt2L$hfqo* I&cCo +m6Fԃ^6o9z>J5〭nx.2l:K=0O`Ncj4Ԕo,;^onM7;⯅uE5;\+ p:p2(YW0TaX͚uVӷkmoo=j[m7۱3$6P5ϿDgn#bxD]W3z4{FomaziV4mZ7un5Qov}ҷz=ozC}:-6nMh6vIvSvEcJT\Î%0(sl$r}ߵzc+_R I U q(:5Qt=.*4Ȝ.X57T.".@/4ݭZ{C֮̏rE>\nqM+gJ86vp_W#}왜5cT[)x_{a8Rd98|i[&r;]ojN[o[f gS~nRբ+Ffl  Ee 7ǩkZ3{jV BxJESfh4m-\]VX͙kt-;/ǀ9m (j: 2~u{L~>a'Zm1*p"}EKj25X!bC]"M1QtdS/І#Ȝ8$CP^*xYf-jKEm;Y52={9J9Bmz9vÞPvs2vV~E`U^)/;l[WR7;A"1kj4@z*0<臱RE7 7u"Y "QAR*)$h XYRxom 30)hDpflW"̛áSN'm&?gS(HEwT;!_=.pBiyL+[bugpLa %[;Vv}1P*j> yn*7^5M_1M9z}h銬6I5r`1c%nG5&,v@MF\mz}7Pn]I!qEf',`E]8`)0\Ng)GSQmu#Da qZuv,Q6m]3z72Hy4`XјwIZȧ`bSCHn/#[c{:.:t\^QD¦y \&mlv< .'{`Y7F2U~h,mGG3h5V40~t}#C11e%ў:<]MPM`.t 붛"-d4e:%Ӛ2ܼ[[%3HGlq؈w8wDxyz/s(7M@ܸ} Cќ6$rl.VͩkQ4N>c~mxJ`iW"t580,a(t/s>w> `K2#T޵^5fQN pa7A5}1]*6E)OR%wK,}c7ք^zG>4E62OuSFP'_MDbLg4Cx 8 5q_pCG@\h#5 e7 S99\8^mƹ{-ȣ٩:"zhtTDZmm"JX3V-R|5z1@t qnJ'Zt[3&&m\1l ĸ h f2Bz `΁-pmnotc K "A'l3ae n`s%-0iLn<CK*?LQyeDI}ѷ孵:rU7| K*'gB¨ ;r{Ԁ O4ۋ̼EioZve-Y nvַڴٷhWHG*>. 89Vy bAV 5JZmX.bvYE)#!EBaPIJ#-^Q .+Cpr"lQgh!"_1 ɑh ҼUFU-m[mmYԌ ۴gr_AkԴ V =lm@FkB@.wzJ+.s+~se1- 6X.vA5-}˶MatnچlB f[S^CwaiIZà8(C8GMM%U EnԱM Oay6u8l+~r=Ec-9Ag`7E(/Wb+8㧪#g @J ‰ MHzcͪD5>=c{;_,=g ezclNq7кWOzmp^W9ah`mnDS2>1҈&*-fƸD3n]*60`MX#8Sx]!IƑ/}aE۩vjMNM&ZZoq;"NhL.&B3^͌Ks DžMG~(&G^{t\'tQv K2,csD#2;W6Ws֜tb;m 3S@-ac6g[30}TNo vrB-+o_HC"GR:7.zhP:$n|.pU1hKdt2z-NMτsbἘ\A+G'5z@dZ@n-a-ʔ%3zOלgpEц-1~@K!f9s3|֦9F _"`S6}{<*/W3DhqMflSj-cN>7$*PY tJ U_ĢkӉ2A/epFA? ݑwu>!2BA} ^f5'߼э8UcHP(?!/5 G*! T_70mG*iP7Ȥ< sc x)“Y =k֘}̴P<5PL ;sެ`‚|=HDƉы6 BKٴX bpQ-at"B,`7Bd)|X0BD ^@.tm`B ll=-n;L+̞wE\^CC`mU 8x(LC{g`(> L{v1y}t礸{ UoN8=8~Ov~&ZG{zry<{ ݇m P4/;d'O_\%`C7/w7G煃ÃW{' ]9aK߳?p<|Wx &*yju,&F{ =;?<(L*$^#@?:P5x+jX(cy:jG[>Τު737?;9wH"ʹϩFsM?9L +qYU/)z;cc@SQoXϰ.vQY6 w"/O,(r% dϊY @D'U9 l)IS`J>]tQ6 o T&(A7쓓3Y#g9'MvlkEuaDR*"9m93Hƾţ2 3C\9ZYuj=t'caqș+C9\ C:Ĩ c_;4.Xj2O ^6!{0aroHvbn48Uc̱hJͯr_`x%cOy=x3@h\tTtXjV 5+ G&SKAfdnjcWse~~ MÖ]~B*BJ1DŽ)>sY$4sc`pr~2}b49? ׼fs`tL]u_$CaR,U&pr4*kX (g,!$rv̦/eX&̟X&K*BJ"'LB[7ŞX$ud^"ojh{˲E*h_4OXfҒ,tܫ"1L e"+&LL'uNo!f:o=O=q€pd Oqn8glcCHv}ϋ-bgc"E=AI~Xؠ),"~E90:5Fr\[1́L&$"㙏i]Z{M{g6h4 ; gGo|,%(SM@?"D9XQ%F/hОr±tͭ`ے֩2c*F<`sN#Қ*rB,sƻ(~ ֣N!G}Ԃ 6sۚ)FzP\Y<|=dK6v).W\3=CCuԳJg@y!c&Bݞ|v 47F o6\z-fU uh}$}5 sHJy/Qy2`4<Y Fc`I s/8lEĠ# Zfdɱd)9?7D2Uwh=|iYZMOV'u@3\'ã _R'] }ķ_m!)bbA>_]n矖Ml>7j>eч#3H6*_$;_OYfg5 ggPf+3%oB|:j+ɹ?S]gxDI'ds^Ldؘ\y(_/P ,R|]\  瞣Yfh29@+siYl W셀Y`e@9D9ZBI4 aDt)Q]dvNën5 j1a L$ZDaw6ŷRqHNhIYT"xI9X]COHX\#2_mBV`4^ÚK ieO(Uz_]7^F&W(oT뾆GLa):bU<x FGa;P5|*p ڴ(CT<4asrpY9?o4z:wGy~8Oe1 GBF\_8s&&*eN)h+;ͽЅ1(nB'}G /3OSvC{(Wq2xD>j& ' W{'?>?捔Jt=?xD6^RJ DoU K/)n22 C|L&B>qMqPkp*ywl3Z^[;:g37q* ltaEC[ixaxJ_u_>=AtaTZ=f'z`tN c&-;1sz>;,@^Q d)wtQ9lQӴ?[Y݆t}ZOIl. x8DOg%@(ɺhe:/~ŋEDТ6/!5Go\XEc W'ro ]163͊0J;/)ػ\RX 3+2k?T;4[YTľc:`V(2{7;,قJQQӶ6oԮ]( yʢa}Csd[f.mİ{/_hC[ͧiRрG+5v5 Y#yxGX~~JO^P#:F]Dn  /?ɨez}^ywl9Ce=ATG>GvF_{v6S&.= ƃ,V5/jRSc sv Uu|XǴ䜪t]pf}NH]5!G|#zƒnptjs]C%%`ak]Ok+3bHR'7E>~A(*ۯ۝{1-g,p2ٿY6zseS_Ƌ*l"'# ee7rYi"h5 Y$;&! 6E"QczX9l3\)n'{<"c<x+Ϩ57b3D: !_軋$g)#=<3r֦'$XM M\Q1ecB+$ZK%I)CLbRoijȜ5Bο6s`3}Xk0O}*WoR?/fZ*֬-)SX5$E~*A 9 ʸ*M7 VQ*);Fƽ?!~pԔPkOK,T9-@4bt]M剀,CaA݋33C7R_z=yq=۳:siaO)J DI@E>DRd48Uҍ'.8#z~NirOMN˩Ut2 !0=AuJqˎ߫0 8bjNã?Z-~>}{܉oZ縡r7,I1BC¬ߋ *M"qH2D] eO>⧄EN*Ujz'Ʀc+ mϼ=UÀxZ3Kv]Y,И 2 ~r [Թ!ehLSuG&>:nZ șw#"Gi/!&bmdV|bذzY*X-87W):E*G:&V.~TVsuɂ*V=ܢ6Źͦ!D 0H~*$- Y<@J:TRJ[TmO[ٖTe}k%OwUZZ8UkVoLu:I:Z#FШvlٽkE}d+wRh.C^ qↀ89Uf~ufPX{XE;$'=9(a]& wz^`)%'8 : dXO _$`ttb$\BL 7g[FuD޿W֙2n:(e#ʘ^m6~MK:"nIG(8b$Ew80]t$'9"sH}ATrS?5 ͬG}%}m/̣m2)M,qEy!a ڀ 4W.Y#Q)o.(灻=C+MKuH|jy\segZ \{;2L;:FvN0.`CǞPBf/xA <?J^Az?qAN~8;s]XI2Zx$R'N:DP]#9@Ur  MSQsD`%@#Wbh=O>kI4E9]G%޸f(H+9;]ӆ̘nHQIT}eITcY*ŅN6[\t(#C4ti/qͧ%|59ޔeN@,>&:x)#Ԅw`DMn (z9l)2%@0HBU/T:K=fSd!<3`bя0}X|q[)(2"AC1$*)fOo\(:c*QK=Fl\. 䘾)[u!=ildi6;VD(`2jB"_s_u AHReɩ]/弘̢9oF IXlo OU:ě Dg%YMHll^oFƭy͛UUeNEy=9rA .A-e96䤌iוoLO' zZU[ bN؎Rs\\5'WmUɣ 7yj[Eny5'`JsU~ZQnI">w(?fghIF$XiIFf؅?x!ͫNWO  ȓ|L/e$rAY8x X$M6Of?xff&Kj?uK|SA廘wV?MOa{gZZ3ZM},yr ;vR)uiXR)TϿ 翶0ד5^\w.b.,t0]LHnOnT=$P>ȻT%ɗHP̘,em]dB~f("xy5O]NR,oV^ ~e*@!!$S?+ cHR!Vpʰbe:6s?|_Ӭ o8Rn3Wo]. Jv/{/z0h0 őZSKKOwYﮇ&Ky\(t(I,Y‚?cHdM'edbR5mFUy開 ou9S9D갮 xGU }S|BI MQ0DĻ &~J( (AP޹!QJ^~pageg\F<bFY۟OLa4Wפ?xk螞 ]һ!.:oIoÿo*pAמ @/=B} /` v}{NsowFQ3Pm%7>nO$2IH E:W"͘Q.3]nURYi/[tVddykbBv.BsRzUy. A.s'vc=ͯZWsbV=S2{פ5X1ڼq=6]:Qnl=_vKIW e2t5*__5y=KK),8ouG0iL[4?/WWow)$^OhVRv"_gi뿞@? !>d3@ЦDIԆEAVrvC)UPUf!$CSg=#j?g";`mXJW)˘2O3 /v`VB񤚔]ZUzjEۥg)6PTQL&aJ4 X'"gto(Z+پy =uCF«yUQ+Ri0;vC+į2z;jj:n8CPd~95*ZLNLc+DE [Nۓ:ΌcQTT~Ӯ#9U}oM%:_<?Samr١v,S9 b'7Z2cǃS2'͛h4(}VIqO %v,Jz㐜{ao;:<[B&|{i`9k=OO 9ʥTynw^z=YLÑN}k"g`4Ug9%~ X(Z"Bo"OљCwiZ 'Pd荺x`@10H/+YhqK'6}x|ec 0+x@ZI4Tdf՗Np~c]7\zt"+ru˂۝Ks.ԥv7"c+uw3鎡y.:rf[ :Mq!H%cvpC&f1E?R4cpYEZe)q kټ p ) qwrh8J⌾ii\O0̠ (k1\״#OZĕ1oA/߸=w^O7[+; _,ӛZdnjole_\ž1lRx<ˋfc#k+Kq$jF, '>+Q5u7V. ∦$ ovr--b07G8 ErC sӴ`3_n1UgMW)xZOwZqC5y֗]DhQ:6^*fjgr%Nbx7A2v;6$&+ְT 2vM&CtTpjVȜR`Q1 -B?"^yX0עeL2e*d%[2M~w6LB7tlX ERXJBߋk*{]zz=J񀈱 L` $rdeN>?L2-9^\ՁES ͐iosĴRSeݩzXrQeU /;ݜrxFV5TO_D]\Ju]xJLu"78xAvriU/,?u "u4mjt`B oa.}XYG8%D i|9$ >]阫9{Ó zSNk|ho|;b}"-zN\²_D6/:[sDXItkǚ\SK"0n'x8%[MLIieB& ;9|p]KZs8` % ,k6Mk[Jq(Zn( ZfmHXO|0:{:qv|f-vԩ<ӎ:uۥ 1?u"9ĆEU=da?͑i?C!oP+@6p9TPÀBK]B@e>U Q%7J`ܲj( Ű P*AN"%&R)|e^jo7S_o@mZ @ʿ;N1o`?7q1k[ɱ|+I$u |wL 5QOu>_checksums.yaml.gz0000444000000000000000000000045413406211174014606 0ustar00wheelwheel00000000000000|\e+@ D[s'o N7  #AWrSUy^߾y># K/KDO!z: IN"Sd}O91dݮ][5h9E;wOA}\d50mˮq"FP !)Xc25Pɢ5虤}ߤwtmC$SI:Nj)evNi exz]F%2a'ʊ!æe]PK% ]cache/ruby-lsapi-5.5.gemnu[metadata.gz0000444000000000000000000000105514453723714013451 0ustar00wheelwheel00000000000000̧dTMo0W^u)BDV q&@.U/=DfY_/Ldރk ;"L l"Fu$8qjN|2PAh A20焎uf\ *|ZqZUVeY'/e-X-hI0ҡ ̀#Ewt<'޼>pi `_s ;v$@);S͸x H:Fwk"ĉڵF8^]^t1Ps:e1& )N-tpqct6a=('ڎ$Eފ@Bͭ%v֤p!L6.:`VEl 6$Am#*Ƈbkާl, nRAK3qHζN @('oNh+^+WRWsu^kרܓ~f}pxL~_'2 Cadata.tar.gz0000444000000000000000000013513714453723714013400 0ustar00wheelwheel00000000000000̧d{_Ȳ(=fM3+C|6X\-NlK!oU/2Ya&`jZ/?1w_lG~}Cʵww?iǟH3?Tn`ZRnYٹ!?iCEN >eAqD&qBZw6vNOk[V#?IuIdvrEFq4 gtZ]:'|DAOI$gijÛ4#d ȝO,Ҁw5 )q8'"QooDA0RIpDI6Gh$RN Y ( `1P#8z#X4C(< Ik!N8XpN8r7&cP2")94̋&7lYKHtpqlt CKݰ. $^6I6yOS!}epY-`Nk7Y6sww= C?`t=g;b>l.㏋\H ld ޷.bRe(`1y߀I6X/÷ӣ~?q0HQea$2֜(GN I=0I3mR.u& 2ثf:46dYL'M:f8,:EW5et$A%Z0Q!\[@C w ֚rnneTem.^ &]Ӂ!'"yO0&w'rpQ.DX?pBlzlr.`9]V. Z2 H\pIUE9+ذy;> 0F$ 'c@oTQ@1cf9 >|0)|}3L&HyLP7nbDlh֜hf U8 `@"s6@Q7Jq0i8QUƷq||;\l(oY"@'N|Lk]e~ʋc "S  3ݷ\EYdipLQIc 'd ez?*eR䢀s11h|t -72pp-uu~ݿVʆV>>QBe"TJK_gL'"g :G(8S}I`T s6.8`üY0dr%yLq ʂ[@2r<Qҋ%&D[8èF;h._H*QrԒ5JujgێK99h)edq4"GV0}T6~TT\sbDL7WfP)*ֿANDst.u kj"Z%r$4S2}v\TGq0Qœ0kn$aF 6/Y:7 5hrcZ؊J' \0'KB!@P?EtL3:a *DjE `s`Oڛ{ǎ<^M&,ո1G1U8n?WpNUF7òo2JL&oj 䅜qI4R03le5LlϷEyDT#E.hϨ~9 #?M2^r¯FXmr|O hU4( r!Cy^%~rόk04A M[nMAחWoMz;Nws; ٧ ǟQ ՃȪލ T`}گ+V&aZ/)d{(ר(=zp;^(Z^_>g|dg&;U KjZ~x \Xl }nHS"Џ! 2?O?0$* yA `-'}O䀬ZsQRϔuAV?),i5OB(v8iopI#?B Vv?45{&M1 KLO}Hg0Wmܭ{s?L/&qw!5>Ӝ>y/ a/ 8 twZ_r3~D}Ma󁺘meNnzycFFnN!-ܿ|;A7zJid@6a:[ `wi]^{{&fhVu߰[޾ڭo5 u:{ݭVfN3Z,~1i?v? =ƒF:{{tbH/ G5#-P,j!É!=JYb4xb%C/LW-f:Eq#5>'3J~8C7"РB $.p9Fœ9G ~ZLx eV*p M FޣjccJCq̒)x!S|vN4B 2ND䷈q^Նo{28?w |;7.9<;y;$oO`"#H={o.Am3k4szOz.N{ ;g^w$ˣIrv>Plxޤ1y77qoxmkr{>_uvzG:H?wφdszvY]$oysņh'z{:z{؃@.aBI::'еeQ2 . KNϏ(Ͻ`(.f3ІP AҬw6CP@0PaQ^]CHJ&mHOJ`;Š= ఖuON{'ݳ.#_zn7=, >yICXGat It~!ڼ0 ل-'vmcV}N" {jARF*Fװí^}s@aVa 7.R _75&Y;\#kT'hYj$}uCܒ6ؾ?$9e%|=0Rgzv5Ng'÷yOmW|}{>];':[{w+"dt s"w콃jFgxV~vn%8Q\4O9,SJ!HA$N _rj==ap~w"+XQo7-ӢrmiA~F@JOgd_RȬs43F`~nW̃2TZRoz'jRC:S`B~|y/_DO9q%zlk\ ^$굡r~EPo'3t޸i5Jzv`V~*yz*i!7`va>)~0JOqMV~~4J5sA粛t)PLI^xQAsSwȋ_>yIPPwxiahZ9 yAZ؛~g#?Q<%j{@4PE\ \4%ٮA48*X󷨗ÿς6BC&'<YQiozPSPvl<^'Zٶf9dgQ|̛6x۹#P<NHjE2sl1c챾磀ذ,J@=y8rq8 '=6s4镻h[ Y 6)yq0JCr`FiCZ%D @;!-pF)ѭ]]͌?Kmѭ#u!J3Ȟ9Im>b lLxwf";]ܙ?_u:] K=bi$7kT1XӺg^iCT6Et6"crj?nut>0 $ )(dQ2;gYx ڻoΏ~+yAȏv7ßN\~4<0Z힆5?ov( RJx#;SAd^KK܂|eٌEy65NyOAxu&hp:b at.w}[TR7uHˊiv}.;P G^xaAT<u A7ĕÓ_XH&_,֚WjִJJP!gk͵9~?;tiL%%Q!wvNarVB`P}Qpsodc+d שWٺhưmǻ t4*NM-ߨN[JHOռ<Xbē__ntm?,-og7z6SJaJzt0eϚ8+9iD/M&UZ`8o=o}ez%mz9&k™Ͷw7Z&`wIߢ7"H|FVh02GXMHtsߢś7tGNCl}@ d(fBşPh\mꉬ49#AE1d"ӢWuwLQiI< `ɽE >#z>0o$oB]y՘7ƺO`KRNQ,DyiГW{غ~6~G $jRk kbeoF؞>u+&f(WFoœ4ð:>ےW0FCh+dL,Ж-aQc6224[akX; C]9H)A#4vжf.?-;1mL#0rv#n€ix wk#_X^֊-%5C)bˤZԼS{:yӔ"qCG">UIsLs0Xސ\v{":2pƠZ;F0gJ3?h,n3d{*lSh@Ӄy(FUoiff9f;0I,9l4EwGLhRn'vJy u84A,,: 9 0bhPDYu tW] ժ$QXD9Yc^c?h::t K&舂*ȝI>c+lh<۫4րCtOY5I~E>>Ŕ 4-UP;YoAǷR;ÃEt G$-i99X|͸rBh#BjNԗy˼Aqa۩A\J8ٷnQUGնAqQ ӛ?g-TDVAyCb]T^)TW/Z/GNƌb6X ņMe5cݢ n#LG˗:y(DTܢuOmlds=!FSHbY uYxsD,GBkqi5 De=y(3ЫSh\nwN:jmpCVaQMצ*}B^lK eJ-!R|9\*q9E>iIN+ɀSes-yMkٲ*FgI@=R܎h'l1V 3ªKJEnК֙^ &Y-?, vB e㢥g*=gG `Gf'OĴ[bMkJR0#OZt_{^e S\pQpi (ܮA+a%|v{%k@. Ye ,b*1/+(䳬RI8_h<3 Qu;,}T"I%]mT8襩Q8tX2Pnځ8 [FĄ{b = E,F" .*gj$U!"[Ԯ&Koݢdk6{T`A7O [h"nʝ&r{{9c>^^M(N|/&粅 ' E\_Y(_5TA yTats$*}}i).U6f 51?eMnO!kgCtu.yWmgn@2ok=ccN\4UsLUF#(l-jaRVg[TE}Ye3[;ǮGven\ۂhjln6:ukcp_$cG˄Цʦ}Ʀ^G8Fa|#u0)G"̕KALp 9{4,ܒ귪I/Ǒ"mW3b- /hC|\RI~o֚Ț\ϗ+XFa~d%`H Z8"kHg5n<^Hb.LO+_VsoLh}%_btӂU(ԃ{-R UZ؊뵬4"y/oeM0Wq*ks!]pkW4=a3ŀ~(9,-Lzys,`V&őpm+m Sn۝nn9pxXEMU*?-jhZ9_^WhQ[:[>a> r+veIiiP=Ļ@&H [쟵TSbvU3h)J%è$$RWѕ ocή8eP=\czwaB%p[;ʻx={ڵ^oQ.{FӟQozGvlL+Ra{<vgkOx}%l6nS|}<9=9ռXS;6dIe֌->*_=+LK hD>BU=(},  ]MA>?֩MҧskJ!&S P*w)( [,yu^ROSzj&,0,<ۨX*4Ө@EGQ5W9YQ5^^K_ q㚭XLf iwJ!ѪJ}[/ e)?kc[&h XTcu%q?@g !uϐ4au*lnZ{H^tmxk7oqjMl&4+}T]B>TC=OOj1i%nvQ %r$Y P bX/ox7Ðᇪ mEmQ p8M~ Ya>MkpA*oFp1Y s@;Y;U.2PL]|f;P+ 4ݖaҮnJG7]c}}b}rQHzyGƭw~rSEpcvXʧgN}ZM"LI9sH 6;ip؃NF\Gژ>b L;Ic8}Vc^a[z"FE?M{+ AO=e0^JBPou&D"/jjmLÓO C(M@=H4lj{jVBwP6~WȃO#SD%4h()@J6} H,rߨ$A4 @˦8)D,F[x1 BUsP.F1-ᳩ-q1 U7f4h'݁] Pk,2gxT= _@E% vvUc 64"CnXĪ/1/KY֚|÷W]p[Tņ̫)y1kQ $mBf^GS,ӵp| 9`\٘:h1$MѦmʁv h;YG\ YtYZ3--ax<~~cn@)Boܶ`ܭbM4Ňi%[՜=j2P:qK!3_cS=>AM[)erϏ;6J;aHCRw9:W[˓컱^ WeK"/rP6ڤξFk9)9(i=vPgFV A#b`@<4a XLd%fbf"N2zW7Z9^1+'yrM,4/.C-لydDJxa$+،Gr+ TZ;6[ Z%CjYA-!lfw[;2>ۗEHCX&Z6Eiџ G$7fNou܁ĿñD}A +4NJŴ^[`>0 )7j_7˲s"/;sPܗӬd}V6 ®TfPLޢaV\U{J,xFn_o/8x) C?#F)ۀ ,J@tǕr] [Tv TTKUPvMgoʀm1+Y^vv/wHiNjY8.)-AI#K ˄2؏qPӧMt'3ݣn7gsSw 9* ߹^KuM=8Coz#zS@{ r;]F{ɲQ\ro7,Fd( $Nˌ$mQ@s*[C2YD1J? 5=/R @Fx 54e=a(x Ƌnk[ 9}שj-ßEnr4QQ%( <3nP= Ncߌ(yM䣇!J%ׄvGY㗾ZBZi4gk"7W\zn2+ww OBbq{Q^L(nliaTb.7&Sh]d_)zOϖն cXO^O]&1ȡG 2R ^4 Ώ* PֹH(3ug^ g{Үbmnsx6PRht ެXqsjqAN| S)mx|q?<;*{xܮ=z}P[{巘(QsQk'hUu} ګbt}s٥DE\uV4VFόy Lz.6K\+v:Z~@-9!O<=QkC-asZ v:xTgY~q,}b': kϖ7@F_6lJy B(i=Vwnb뵪{ :isN7+gMc6)3eTG?2n2ϸgḞW8i_4AŲ&e/(_-3QGÊW3`h-2HgC>o ƤuA/S|S9TIE=n{~S/uQyŞu6reb_ Pkdd67t= $q<3?]L>ûy|&S[Lv"?xc3y?`*=g3e^I /~euNJHnO\]ؒH6WΌ)\+s rlꬅ"t򠽍u VxeOuH T,T &g=P>hqSÆɡpŀBkH*Db+,cW\jEdt3WjDt#,oOxt{ RI ש7Ŵ벐Hj9 OPkGjI]S/EqYYqlވB֔b1#.z,Qh/}\T,v#vȑU'ʡBKIS2)xٖ*,T2UEJmk*uEew1sh㽝\BꏰNՋx|㠂֌a=3X%O YvsXx"V—[_~*RPNjűli3IKQpSh IUa+dKHVr?;܄#ųjl _-SSń#EN٭6%K‹ GaG9SQj; / 0QS׳Eʡ_H/Ud¡1̭aH2(7Xc̫i5uɿ2[NΫӪ#-K3W1vC\B{nv<Z5z%Q鎚k>)"[smOW\exuB.s-?_d˼5vmH],e׸}A"ὈL̢!7!Ab뼲%owfJ,&1۟1,`NQ'qn r`aHWglm3QlTBNo$) _T5ʵ'uDX159^aJU@ w˄KFھ9X4)*l`}D}N'$CwTR(H +l/?Ss=Rwi~#cɵm政!yMfAvYؙ[i/igGeFzڲO?کr`~iWC=Fޫ >l;Ԕ$/L괝{B1+> סMD| b؊F g\'/5]-ԝ(&wHW 冿eX>P"bt8 hjhҥxmV¾ F7Z?@Oo=ae |Ht=jUdk|ys<ޕU4t^eQܹC\cjk}Se7Z-~<+Qk5޺co\˜-a>" ~8}(Mx½vӠCF~-M|srtG7`x1IG(H@_gÏ5rn=mqx.}0.4y_Β*->r,ӑK $@}0 }ci+QbZuA[.@Wϱ|tpuke2@ RVᅷ$/:ՕF#֠+*kUOO:]G TQ6]OQ,]1m^Gp^xb~<6tVrnwͳ:`Tvc뀵LT"ڕ̫<1HyrVb &QStO]:"n8!J?f$]D5?1}&D"=q?N]{857cQ^*i>r)m:ɠK*JjC\ZVױ8˞ FGK+[lYߘD٧ۦQ&{Ξ=t']ۡT==ÔQf1gj_UVJ[<#]7:RuZO`)pc:ycc_U櫎7TLа4SFө5ٹi4rhZ)E"ՂVe5i鋜q* fRUIxY7FC"^, OZ%Òw_`YV0Gkt0yd?2u}uKÔHM2UQ,0cj+1$ԤW-RIҀks[pm .cH]:#5Z᪮!,Hb{_9UtʗM #2{l< rI_XN'+x !v?U!Ay,YUغh-*]Vh!8SBmRg KXǙV˭t6VD*5T1vǖK̴E[sQnJސ.Tv _Yv̯-YUaBOa+vH)78.6.:'k`&6ԋrQX^0Hd%uAPe8ldx kt!ءƳV/H@Sci`V;LTzBυ]퍕B FZX;LLù`q0sbhł$, rh-/ ֌.(s*@& Yl<8=F RհKPEo坝uO;]` RS9-=8 ' KA7 ۀV ;ԇcjpP]Άx2+|bBi%,F1}?Zo)qbZ&k|{@4t0LK1ͪi@T fAY^B Yhp\k-w}ހop"&Jֻ79@vTZVH!aq2 ,(">3([Q_h}P"QNڕoqG28r3[Us 2:|Ή? `v{dWU:]X`NJ8@ް0eXh,Jx_vNry6wG+Py>S{/As=s)/Z_;_ݣwBb,CEz>H@w^=im.llXu}NY2g, $+!%3%`]~.PI@1B{F9)d5 NtaYo\-07:.҂[J_ qlAi/sehjߥqOUK{'eպ e-]i?Y*ozG&i_W{ixuF> э.U]긵#yG6rqxo0_3%ұvh9NɳLt&Q+ɕ4qC hjؖۖκ2w!ITԶÚ %B2[V+4V:lӆyV;uOy+46o[}mlE?ˋ-AI\/dn(c)7d6u~ɞAkv~og΅9;?l8xݨI5BMO;S M2H ։~C')B 2aN4++53wVIōgn׵F΄Y?5/f^!%њCԻWԣ7) R޿f:.Ѩ["mkmkY34zNI1쯲3Vxvk5.ek}P-/@gGqH^\i^M,"ο[&v&$>$!]EH&}7J*.,`G\8FPi -A 14R3 β~bG.#OD1i4OufEv] z|+z >,20$3MFZhX rw.:÷_,d' #`xBW2k%@s NzfLtࢁtC0CrVj< t, ؾ8O3[J0"տQNz T3}u8e#y]l|Q'I/5n*ԭ}˜ҡdhIc1LўGZE @ƪE>in-}|1?n%xOIDJe*3ZVXyiib1m$3韋 .f^͊Q_T_}g%L0r^5NQYN;OɛieI]bH@5ԆdjVȭ?eE&8P8 =Py ,;0678BpyvOo'yl!-B (#ߞ51, Vya>(ڥ[ cPӣr7wS"KYL 9*Z`JN& *ipSL;6Z2lI!j-*PVy*0.||=#]$^= 7 ӭUz;]S9JU鯛Dh[NTl+x4F 5B&tqn U0 .R .r"Mގ;+n V G y<Rojt~j#: {f|=|ZP42Sej/n\G?:Kʲ95:q;z*y ڳB+7xuvޢʯrpZǝز'i%tȗY& ¾%`3HZ[$-dExc> ehs.v#VݾC#?L{ԭӈAViDv֦9fhLN=c MY -4M0"sv~: b4J~G~ljQfq+R ҆R^Q.h!x_e斲qJsr^I(Y"{)Tl8o-qI4,%P{sz~SST]y]h9]`ƣ5 S8@w ˍ燵¢3I{+ѯdDFhד& F\F q_58.%>Aٽ(Fڜus8 bӾOMh]AtKZѢuc@zW[経>μR}/BHGU)waG)@6 a R8oLSz,&p2=%TѮ*@_Օ 6[WUjV4YDp8], H*_q8FĈ:ŋD&L6pc4Spӌ[;+v.Z *Rrjl`8M!(oj.T^>eeCn;Q( ϸ#;7/ Xl(|\c<յ5WM-^kF(Uܬ䂿g.qկrgPp.ˊN9F߱Z%ͬ~2.E~K]qzښ9Ww2sCIw֨K' ߤHv|p W{2B^h3$o;ݽX_QuHmǴqG:W3;Stūe!mlݓMo7i۠n𥛌=[AhUJWTͫ+n[څѩʻt1 7j4dq\t nTc{VM^ zjV*67]43ג*/9;_vNtKtJN3Ju6XoD9֝Ca"NJY]+5B}]Eŝ~ŝ^̩ ie|R7}o|Aa/uw֎e~]vH `;]\r?\H2 ݾ_݂y[|g Mxqt[Lyʹck 5q"Cfi䎃>-E(G{Ra}|*ea@|o5{c \ l5V̟l; NqH BPًewk -aM.)@Adk>Gg.ĿB,L$B#5Wqȧ nٮM̞R<7l*am:XKlnm8Kˁ"HgdNxtK>vUiÀJUY ׏̈Z{$U]k) KvlI,KU"e{-AunP)F%^[<|Wp4{\C<6][b(>LÂv.4[miRb-%^dtHU|CMqYoIbKD'Y~}|ETK7}F&+NBwfdyӊ%w? CFhSdQB,T%}Q5yOVT#PT"G^,*(nH-[_VV\UGT,.TtM^"+,"Z+ cųSsTA- /^)x3u݂.+گr_2(2WnRGBʊ 7 65HJ4 4YJye¬p8<(::_1 0[ʕnk nzmnq{+>ܯV^[?ab-N˖S8'l(,mt6^|JϝqD/viÚLkU ]݄=%PRi&i7vdKBސ8bV ;쎉aѹ2DhC֟Bo,4%Qo{hƇ;g%@Med2_ISM.:^Te)G~;=?YS2>sk!̟] L/Cp;Aٰ1Uwb0^`8X;|*4j١#˸)yBzaٗȣev~>y2O5dB/M ]3s-vmrhaPNJ̿\?u(j97Z!U f4`cnw۲6Ѭ/ngpz *;̀SpR~gHrhJxQ:;*7|qҿ9l!A5#s؉ a]wUPn0A X`/{K>gK{t7X5XQrV8sџ-LDw}syΎϗUxXV5bv(|UԹ+( >De!u ৗ?<2rh_7#w+<F3n=}\>0Ky{Fj>P^>sW$!2J 첻[lsYL+>=d>aǀQn`6im:J,}Dz^6ɻI8-)FQ0x^*|TYkDySלe4;g0Z̮@ 1Kf'%G055I=->Rv5PT2jCTSԟ$ QZ;, q K޷7q$S42FFOl #@'fm,?Վ i ߪL4$wƚ~UWWWWW׃N 8zj pd@(ᜎͭ(IjЮuӞ2Mg!2ta#UE?xqǨJ`ޔrDX" Exց LbE9pr^۸pʛve4};4grbRK>YJɨB/a)AX4+D!GPak cԪ2 ~p'ă(W> C=opa <$Qmg?ye Tm~+1i[tQ~` 1aH @=CxL1 x5*Vṕ1Jt T]׀<]?~HOxHgV\mX9 J(V#8BŔޑqIlx=jZL|Oӭ qd{|(%iiݛSd}h, W-oiwO^;\.Z0x>#;%-6٦g4Cy`܂\w4Q7oԫ|F:oԭuz J)6 ިݭ~)m6V6-YnlֳMi[@zYeohhm6;6!˔joөeSMPΣnoqj$:Z%lg kNqZ*u6;uVvzr^­ZPܪY^MlZՍjg}G6I[YEUlRbGUGؔ"z[~4%IJFmcs=ۜH;~-8'vodZPls#u׷۽Ls۬vMIMw,S$vaN) &կ{MI^Hҳ0$F]Kf؜vk}NE5G{"~$SU|V;U(;Zy c#Ӥ@^MJ7[FgqNbvj9 Z Q4|]4)AH;j}T8)%#v/ۤղMJ}}g;g$~P[A5ۤ,^m62Io#j~IIԳMJ[lwݫw:&%|?s 1}u?CWX;,i=dvøŔ{$R$NʆI#.Yսaq,Xgax5A|{QUџoU/j !o׷kPY__G3 \_pAetpy5c^"iV=v6 kݫq8 /A`s!VY˝A4:sgbzΧ݀ZUgQSk%M 4?fd~k,IQ5jɺ"l]δV )8d)qBYwOX$"h  sq/ i2$ 0ޜpXrҒH.ԝa=hbv#`\ ,7hC{%E/ Μq00Ꮤs1tD45·Z!iݰN@YY"k™#Z`@5 7M.4S9)ۘS^r3vvioOO~nh`߳;9z8=c/q],?8y*88~x{8;c'Q:O[Y5޽;>iȺNJ4h;y4N_σͣf=:Ʊ^ۃV){Y^4o/0:?냣#{_9EϏ8MEqqQ)wq؄? Z`JGü%Aw72V`NN^?7g{䌐Qʽ8h` Κqqzmyr\0@ܓc*H=v8 ܗ/I:@[f59ƫaKO_g",U +4iXX|Mџh!Y%;xsaϚLe9|Bq/3MُۯjqҞ iɼv dLa}QV*-Wyh֣Oo7Q29L \ܴ?yОۃM~ n?cM+2?? '>oEUb:{~8 AԹ:rԔ#kȧΩX#]tIq/ %IfP&t0T~6-XK4Q,ѐ݋* eqCzVUixó&I(q׬?qn⯽% **oL2k#\hz N~ɦll',\[V7h?!ߡj$R ڀ7TQd fPl"la_#JBލ?De:u`-tU<ޜ6\P5L\4ށlMbZ/PENb5K홃 quN:0)x7v N&$Z*Ζn(9wQ⥝Kw0g><*8mG r+\˞TUl߯2̚YB<ުp{EVӢS_𳻔[Ag>oO*1/e&#Btݨ. \ObաwQSGMfNNdêHV=k Oj]Q{ycpږtI\'?c u.ހA."4kkbȑt$]N4r7!.g&fz =2DʆBl( uJ.ޅ^D'N?@4LfE.ghRgWGjYwW;:b_ԸgMz]Ch]/Rĝ,zΔG:q#p\jLl*f)7a,K@'S\u `ѐć8p8ݸd 9q`B/9e H7A;CfwƺiʢwquK_Lč@P~gl :9҆^`i5C]AҘ܁Boo?ҕsTo 2rn| }냗&$.|Rjej$;0Hpzy'PĻܞ uIn9d c]p[D:z2< }wrCd I]6q¦乞?ov /1yr~ x,Y߂%ޔ!o33tzqxÐ}/2"$ۄ77 lM8EHL7NM[aHLĤ/蠎!.kɗ,6)<j+ǢuxxY4`BeKIiD BhHZò-IԪT, לx){҂ewל^{ߔ;j9)ޝS%^TMQH ?cGeƖ Pɘ?mOE}pz/Ӊhzd{l]ϑm} m 4Jma[nj5~n7[g-Qq]5sj8i5~98=>6j4NOONfZfJup5]Xآg7o9<[Z\X%0"ڒZ@<:o/8x4<5QxI?ӥ\.6~uΙYvsn{ځ3o0%+JȽܷXX*JL睛r1XYߌllo3 +ύӳqE13GcV۩g!vdzi{\ ?c44}NK`rP(8 %`>Nb&ƒK&͆ͱ߯A| `/Ys4c@|a5OʼnK|~s?'ě& Ǽ0Yj4+6XTVN5.N0!Q,8,Cgcp:`9 f}&{@~?*y\xKK_^cиZ2GaWRDns|"khd ΂(8MPL\\bҺDJz̀Cں螧hvKD]\.QeTUvT7RmHkJv:`WtM(H)\ezqcŐLp_b8(C0(a8̣P|t¬Q]DKizOŶo*n=vθ'wg) ڢ.%;PJEHAD+%jTEEHV09n z9'\xv>ŦX8(VoU%ŠEtԄ4IsP>/my>U)l5ouU{=nee+ja/K4aHݯ%]L]/N0ZfԠwՕg9Yd<× ԓIzѷF0 F`˰}*Q /&,|koS+̞`u}ז@aEĄP&;a]Ad '#Yߝ6\Mfu0ػXB<0}jnw:#'FMטDF%s6v[Mzx/V\%/3h"C▎*xI0`Pö!/WIvw6P9ȢN2IQ.9Ҟd;Nj^@E;FN|#n+@HOCzX?c˳gaOؓDwN ÕD(~FLS;%J&i3Ci0݀J&lhI{I,`9-bw%\z55TBj0Zy9=y }fARt@ԚH$(_a-Av/Jey+rMc5#Hgeۍsl6 ]і.D~"kt;ߘίAXI;c FQkp4"~Gb 3IZ#YvRܚ.jBf<4UʩolBFISa6zVt| Y5Ht(d,KϖWlf몫JE\Y^P7Ua=CI E|I(y ..'ǗCyP6^nЂ XKȥj2oAt/M~:I~9jC DT޿mp=o&#xί ċ}knTε 3 2]]Lyn`ݞuC'@_s8&7I˩l5qG3Ȕf]T^z.f c߇qy=LvhcI5M2d';d@.ivw%VW|.LLIzw ]mof F?Yww/05lPtƸvd$ScL^L$8&.={Aʊ m.Gݔb(RփcOnKo=ϠX9gIqT=8mo% ƅN]vn6D=PN@+ՐX쓃Kch^R^v_T9TEgji+Pڭ Karpf7 X9KI0l> yWDŽsPM>@sE{O#%1 Q<pƢf=c6@Y/"[iNQgҔhdtc'2*9Z>FmB_o,.!0ÖF?pFfTf04)& ʇ&aaIw $qxrדpW:^9٧#1V@y^J~Op_݂-_@ FBgW>:G#JGzT~A>a~vq8j9 6B'K ;vڲoh{ a|^"n[!ܚHNPo(E,U0±S2C8>1 Rj6^_NF q%VMYXA{iʟ1Q.Y1# 3iT#!Y6Ҥ _®_w+3/At9p]gmB\È[d?eĩ~}߳OYZc%6xM̌+`mmd;7b2 {/wO11uIbE椝ہ*gnyO,x~֚L!zɁ>%Љ0Wf/oq:qpr2ް+XOKlǦN 'r'5I& a*M1y9a2AtѮX#Cw,JqUiKhOU/a*8iE7)Ȅ}^ܤG.]*K=omX};t헺ցcaDۈ4 ޑq=&A)W$,;ܔ;0=AJO\٬}V$vƑf_trHhkOg?F35=Խ.╞mmK۾*Ț(&d6!:_j_M2"( 9k?>0&ަm4pqg/me[bj~}rƕ69l/(]}[E!uS $s i'C@w}۽?«c(0G8H",kT噭ڲ`x f`=9i-rڣJ\KzE3{l*ҝ˜$,B#}3bYȃФ:qxDZMT fF+y>9ʉ@y[O`l JsY0DuO;>C%53.0p#% MgtoC8RfeVڪϴ }o`'Lm2Lఁ28[_5+r:.ExG=;|A{ցsG{ZQ$xPdPdf#'T@HMOs,%c4 ,$SAlGNg;:~yZu}rW=՗ml6ҞŹW=O@Ϻz|,نV+K3G3&Kkl-Ȝ]Ǫ 7292|U藦fhwZhVK\F2njjvD++fBr-_2vy*NSv7dA1^Ȱ)uA ~*-CMwӻ!UjD2=2 S,sfU3KC6LiѾn5YPB,%6FH<#Y$ę4סJV+9b1/ܥz_ 5(gK\5;|dZݯ1J#SjH ߎH#FƥэNB FeZœV@[^̪LoA27ʹDJ."ÅQ+6d3. $>ٱ0b'Lp![͖Sj!VU4(k.Ac,^mj_..dkSWQ -h},o[ϟj}}V{ADq>D&v˂ϳ`L7(+~󱀊]fW8=/A|/e>p4Qs>N9M^蝑>sDN=붭{5 Xs-/6q;GX *dfnr}}]NԮ89e7X8`;::p =/ޠ.&|Gg]Agʹc' Uҙ/~T/86 GGwS'JoM N 02x ΡP\XϳOd8(T58E =La S@:\#fno_r2a\Vp;rpxuzYEo;w?oV*a xN?÷ro0ţkF|\\V 5h%.BOӃ`쳛p^| -"&W%^caEDp>C[81؅a`*W+ZSRi0B~:PE:k0^O!+ot? F#&~*se.>K"wjW]$9MVV}s% =vð@R9$_xx(Rܽ{#=O;~xL{9?$=b_2s2f0"K7Q ̊neuJ ;E e2|70{sKM n2tRHyDWYX:RDHü(M\B-l, Ha^,1Ѱd`Z3tCF8y ';IfE\cq=G/^,I wO>; "28p(~~R^}ZPYr6w=ԐkNќ"`BlxO=Q*+/̀wQdl*] pBeaQ'۬=}5uɷ2E /KOu1jխj=vW?V@?\^͘-:Le g{f2 /Xٵ? P}8g]A-+ 7\ Mcaf$mwۣ;S*!{yѠ I-T\as9qUh#A9;'Et+tO`Fy 5@7I7$'OM8X$X)ypCEU8O':iz(W*+>x r$= Us(~<fm%@ me?z|قxRKxSx=4(ĺJ>0VFF@8ny_+|fb Ջz08ʟzx@ M<|V]PzJ+`yH)'oDrhS;޴ï|ɟpwK)Gˎ+*v$jpF g/~\>P\Hoc4: P1/m'Tc%1H +"~>`+ dSn*n$~O7p)<&XRw$b x( FƒC|:\c~k')`ClnzGpJ([_xs~ߖ*!]^r Q1~4]$NrHͧc($|٩w:g4హ.XG "h/sC8/ºq+NğOI(~ĐtZ??Ei@`-:7D(@FE%I GR<+ ^@Zii р(\zBA?Z"l1PEyl0Ve,Qbx\Bܖ X8/!_ȕD'צwjԋ,ɲuX0CEǤD"!e*4@p!l+gtg(os2j(61? JU[Rd X?bOR1>UJrHU)6QTQa *?7ZTVJͧb.C UP!}?%7cp$/|;H!)j:=+{r4x+_Ny8 fFyTⶮF&n'1dIVkw$ݟ8mLJ}tӐ1TJ<4ޅ#Oc>D'u႑2lHu1>}b _bGKF$ԛ܄H|pR5FJ^rTHH"(=*^L.3V=lx+ x2fH$p{A8l8MU!:L^pṊ"ENU&Tg^m4MK*A:r*+3%)D+2?8:*,u/qkxAVv4w"X`9>9n|;<1Vڊ:q g3|+QV>VQr^5:qaBEW*X4몥V_ZɾTP ڜ) k>%/ 0;.gҙT-*NE#$XJ֑DEr?LxyP`k\ rl%($7V!J#D*vA%}p•{lӰ0ǘL$ ZHN:}w0AELI@`J7^F?gPSo6c/4=\)R͜#ݢsf9b!,剽:D^l2 alZd(sxp^O |]5c}2i^֛;KpH)9O,Ĩox .]~jްp=!S,ť9=VZz-Ia@|=nFL,Qu<Pϴ Gh6mY΍<,+޲kLV qI| DV?schp"I'z$p 0ɤ 刅 ,$MgtRrSؿl&D}Um1~׶yST˒_hzҵiZ%>hI^ӃڣfհXVSwT=7G SMbV;tڋ[cL;un,zŴ)oݦYr3@ذ;љVJ'wS!reYYAtEv b0A;k՜ODŽ]j:$J1(9+7ΥG/x5'[cZ>"e"(2lGyh`n>Cv Jf3C-3O  RMNgNMyQBF/p#7p4/e/js"S()#B'Kt8E䋗=L^D")hOe 4[y%汁 .ú_ 6*:b4+Dl}uX GP8>WO]7\.v*Dz%WXNjPr!rJ,FoTD%R.evFQn/t*XmIHݠ-%WI{qwX 9C3ǐXG7#̦m; J]ȵ Z-|bKK}g;ȓPQ.̾,/R'|TcMNr6c+_-XCIDaTsl!? {nH0g;[b#{~GLζfq8M4r31cTHgt2(%Fv~Ef3x[i 0Wl.)BD˼/RҧĚ6BD`Q@sQ x3V^2&fO? YMEk|2|"x"Oz/_G n" }_hM`BC`K*RFQGœb z[DWLoY pҮ18XmO㰅=Vf2;S7+GƬZK lȹ[v3~d5 tVVFp=TS,.x~毥₩a 1X5nhS[b"lOg̼pQh ƌ۫Vt}Ѐ&*|JȲq3/h dh枳z.&Ab*w㒑Amt wRm9 %S۴o3|CM )Vbݎ? ;BXC9۬ಃDYl>E3Ϫatl`$ +AXb]I%m^o "Ⲯ-dn~{0)^- 1Mh_piԤ:g`k3(񻺬$ˋ.}csf fy/8/\tO#,YmX WU$EN]=.qkQ=G2︔B(7%Lc*n"S6icڠ2RΆJ-fr N[X=-t~taDP3p /6GEִmbo$5`,I:6QMDfUBː6t0ԣu<3VM)qnd$/?Ǣtޕ"g{%/""*+ST\YqX pA Q+{OwW-nay rk ّa &e2?HixUe ETnR=z'%j6_VB#k-#W0Pg˚T>sxݥ:P__2[4aD<ζ߉2.Цs`V\@T=c8q@uiD*_T -MkVt)so $q܀"$WS.jNEF1ޑW-JV+7@rmc/ .Y\));D,D]X('gcp HFzaDЗ*F )i M+IO{M .ug:Bf2@ဋVݠ7zb\};~ك2KjJz ᓳpG&P2(fdZ|a':џ䳷OZP%,FDg&xtkRN{DTr}HAJOCkhtP _*⻛B^t>dhT?mZ9FŠ,I=4H= 32~( qz C+zI+ƖP+ݯLC<=;NX~W0F pc _  p P60 .]@"S]H4nJ.Ų{λZڕAڋ)Cl?zO`SѶ&MDLr-y-v5<Eur# a/y':(邑x zEZV 80Z0Sg~ui]O3*޿^h}rHS7R,Jo&^9yLbi1}"elgzEKNmGDʜ0F?yBV#k#e' ūŴTڨ _Ap̣AR)L<#}i+{5PQm [$K, !Gd9NK/Pn{Z&~e> -i@kakc#}KOT!( *lCM.ž%LPZUO(}9d–z7]8y~EO044pdTʡ41: #;Jvw|0Fۂ@ ˯ryhdw&¤D vOɻ\n B{.$R4O C>t 1JaD{0i _!e3etMݏl~>lu?Ekr UpF iG'p^2.) (h`*+HJ Vjу_aVA@>*|)Q.dtJK2O6WA#NK?TI|?@#E TO%<C-f_Y-Z<* fbEJL*9ayT9^l!*u/ =D`?oWG'맍WeCYF ><Vća(ZpI?Lnd++|XzQAy{Հ{unM>׃!Љ';Z֋)*m/z"yK7Ga|)8n\~/ K; d$NCci)A9nźe2c9\"篕wNy2tGEyl{o w0|R]NܻhFD?~,,q%ԩ/ *S|[+=(U&\U䪲O| NJX(? E+ ] {P.+qb.ؒTa').7CGy#2$+h?񌵼Uջ16!!TY\we9`2A^+Cȧn\yL8#J3PXb(\80%\ukW| NDM*~ W=?WZ+f+,ӚFbnA/td${6Y䐪o&+N[?'zUW&亗Mo2Df`Cq~=?Pf,1nOˠPT×>v#G\гj)˪Mq7h{J RSK汀/߽JE$CmI3&h%{w$ ("M Zw[)vp&Udxm9O bINwKCEgoHu>ѓWd6Y,k_׿|f Dchecksums.yaml.gz0000444000000000000000000000045114453723714014616 0ustar00wheelwheel00000000000000̧deQ=v1s3]{~&o>R&-HB?ozY|yFnI+F+DNbjUPᬵXÆa`~^J+vSĺA]d&zUυgh F/WXAA&e s 2 B޻)ڙv^4!f1'8d;~QvY4L926pM@&oSdSOu57K Ӏt {ԹT^39lZ PK% ]bM$ppcache/xmlrpc-0.3.0.gemnu[metadata.gz0000444000000000000000000000132013051241117013425 0ustar00wheelwheel00000000000000OBXVo0~_aY7 )Ul҆nB"ǹ&fvh9'i ei;>Ή?sm3HL߀I+)Pٚ@FF;pYz|cq-pnIyDu>e>;}|sϔRAe|i#,Wu\aLLVBѪ?B YLQ2x?N h. :wCΧk%7ubbƇ;۪xǜ$Q'&t{lRZh۬\5hTs=lC/3NSm data.tar.gz0000444000000000000000000005723313051241120013353 0ustar00wheelwheel00000000000000OBX{H03\0M2ݓȶ`K^I&d!g7Iv,sۃ7Z]]">O,/Y[_[{5][x{k76B{6+|fyf0ˋ(/(w `0KFh\(6VGxtP`sOjMӬg16Ej2\uq`OT6\5^C ɷ`a(5p~:&j6Ed_)#Y־_哧l勢U㰛 Η nO;8 o7_9\ U_HeQ 3`WwEUXIZjkzD83}40LT Pa2ZM35IG>!TQEMrpH==zRr A&E]ra@yM\ qzk($Eػ:×Kx , N7tJ 4= Kl:+`n8!vU,}^EX+u4!JA y-8 *Ixcyē(І3!!Q;v28̴֮4: 1U0qz}8K89' 'l8P7΍ a7W=K'!kQWLql05U0ma/d?gp%&L(&p V.q2F Q_r vd3IJ0 q@4L͘ dzd$Dy:sE; y'(Lc6Xgl7QW+, !s߁*5p⧳h'QD AlR ހ=%DIb8u֖$Lf)J8ml`!ad;{`7Ch% U*g fb]aV@'”,P<;nJ=ڞHpD/7mVY\QǎY ϮLYfw(N1tHs=*#]ag||%5|?PaO Ϧ"d:0)C8 0Yϲt& ]hy,`]y)+my D1Bd] a-Gꍁ9o,:Sq:z;{ 9|g{Ts~73o?ׇ7/<4pspwU/>?x5U_?9}ЅNt5nUWw_ϝ/A#~{Qovw߾ܑ1y{5?[A;yj/~;fYpk|_<|h9y:asa1O[$a62~0ߟ?Ғ /'}ZFciI>. u(Њˈ(У"c&Q/ ԏ_-BL k8>~|F8$e IdIJ4N d:vX@DD!ɨx&r)-@E5p9:qA2$ä1У;o>|G2OO;TyzC`${נ"Є,JH 44o:8HkH<#B w13ȑ*Fcg4" %$shNY"˹%H?٭g栠*|0".~#Fu~J)G3~$6p4޽!  ER;c 'k3XAMOglOˍܶl^oItj s +QIhq<j8WsE06x>)*?@Y|vb`2]uө r3Xq:E4%8<|AG]yȚ?ưEd&4OxF$T /rԶb'5Pq ލT2M}FY3fGGȉ&;)Kzjf}-"Tlp ‚Y"'JfA~GA6%dNoAɦ}_ zV,#̹Cz~ ? P8qƖOۼwj,Sx:;Wrr,(qIICl : {lA=Q6=dPpYGR4("9 WY~=(=U>4vkwyp&RU$ ; ~z iu5O'EHT4G>{%HK'x]iXBP=BbWxgU?wgugQ@@2C%XbgB x'qc|W.he,fC" XcE}nFRHQTy*># u%5Tk? fCH &y2qViCm3U(Єo1pg@ʋ?V`tBDTM)pxhA?4s^[cya<1C;IF|e޿$16eD_AὯ_{>98Fȸ9'!#BZ"EA$J5 >L  c"<l[@AD߂Y4L!rFD(}T"wStv+1Y8N{^<[S.\RwL4M似3`KwT~@5PƱ'3&y h|ɣM"p҄_Sz>2!b;n&=_w :M(%$RaK\n [1S#=DJGN4,ۏT5eiSMaLV~|D@GLe)Y5HShbmQ'>6~;$eep1p⾫G6GDW{Xfaw+ t:u *M"PfGW*xi "Zjf.s2>R׍>QSL3SO{* >Ǝ<6'$d3֌걒wd?@a|@Z4HMәHsm-F!XNkƬ 2k5ct8<Y;Wh >ʺEh@GoU!yEQYfK!9"B[ҥ:%Cޞ;GKiq 5^]5TKayZ.{=P G/Rn0ꀃwܙ ͰqB2USaUQ(ET,s"Mwy/kBl ğ4 CPc9vd름E> ,&. (r<8fE%jA (ETߴ`Ӥ6w e!72[nA+(,Z>CT<3#8F97J0Eh+VwFcXF(AZ'%#0[ i - #]%ʾ =>H/; dAhY?7DO:~/bFnyS`6CQEBh5Txj˝~52 8a[&ԭwl] GQV<'p0Ȋ~:3V3mfŸE⤰B MVM4J+ NZatpyXs<ؕįYKbR Z,X2Zc:8߼-V1 3־d+ EA#*í(W8Yʣ/sC$LٟX4 Dru+9DSGj49σly.尭/9 zW,Qxo?vѻ/i]k,"tԓ Ro{G`͵^$GU$$677l}]حoУ7z/#8l^ae1HGeH}B G0C 3P.JLVrW5 P hYm^1RMr &*ui$Q֟xqˍQ? Wbp@١|.9Qn"ݩ.Sd@62BH:FIv0CPS\>nHMF-O*"άM!C ɢaK:'P 3` 6vJS4d17l/Y΁]f M-?rclJ% 7s zxe>5yM LQ֟yxB)} `;w5%8YcY6,A?V􌓵Sw{ɗLьO!OB>Kn4q[w8tMcͿ~5>wYFߖc%kY*D^ XYšTϊx79`m+9̲@df9\TtrAE!  SIzb8/RKZ!KZDգS6FlHon4\ˏ7EI4cGeF+`c^4'Vcs%t:HeMt jB  sKP>(ށh]uVMQGjLFrc,?wE_~ Ì Fn,+e=3@-rᭀIuy] TĿG{{h(mم>}Mp#2_M7(.ALn<V t.Ҽh|>p]ՙEGRi ,ɳJ~D@Hr8i"ډVŒfX,P m02ijt$+Y|}wC6N"%e_!@A1N4ŤT0Š9Q$[K5v|36<˦U_!m c}^>Ӈ@蠀b]J0tض>զ.GdEX)ce5mmP5?}v 2#oZ g1Njϯ 0,?н5 :C*UHyӼ{'UcMnMb_ 042P 1X BqSā" {7(~̰\mSbf$jӈ0"|wn@/]zx\My} 24̚2vY3>$-lm)E ct :LtH*Cw6"v:>Z2!)XKUlǣԇh' yB\ "H3([„oi  T"1:Iv 7AVن8}PHA IW#!Ch/gw. Q '~% ce*eB{ϫa<[o@f^2(P^@Fi[#%Fw8ȇ D4,T 5Fܐ=~',9 (~pam"@1EP}XgԆx԰b#2f;ȧh5{ͶW tX33ڤakuc-0,jRc- XH6>t 5a:l\HiJyf,)v\@(WPLV+c~]=WQ$\+esL]^!D^ ']hsg٠k H>.N!(L)sLi,#`Wj=pJ @L Yr F dON(H@ *H9= J*Ze'GLs UМi97MG#rQ/¢Y=܌z#f*x<&R!DȶX8<`!LǢ`\G-h໬k3K+\C'ekFH| ԗ<n_yAbf{kvr޶ör~1ID ,j4 KEGFF3)M[y7d.6łvcr!nlftF_nV6тP:#_;:˔+=0;;"_=(8ݲertk 1>s{bWnS+MOJBnw{-l7e1i|!*Qiߙ (nNW&E(7l>5yx,E]GE\kP)\Meߏ2pw!zzVWSwC-![Tц%jM $]:v9Y˼EVV Qҷq&~Y_ m6\zN_ws!TA39{:=FTfB:~7#{'pEى X%]<\ҝg "60NՎLA`*Wek-ݠ]k9=Z$O 89O=6ϩPOw/"jemUxPP $21ro|A?L8Կ,SF¯\UH( ߆D&ڷd3 3pfPy_`Zy5"~ixxyH wsnGzs=C8up'qaWZNs\G}/.Uc:5Kȑ  ;!/ ~0v]k 6|$> 4zF)1qsm؏K9k2J괿@.}4\{ݴd~,M[`-bʕe.tqpyjJKâ Пa{SS>],j?rkvo跅. Ko+tlHGjy㰸^&)ǎS?&Km޾24#q[xלi9>jq6UOL()n*E]-1pWmVXC 3;NmZrYsak{]r;^@pB:mP.͙fmCúVH`'u)6Ph{?oO:&u¾ bJuhtIl`O&hm= pMt9''*>2kVK4<`n`3s{ %Ոa/)u,Qx0VLimA'fO;-Q}yt48!x;>/uJƥqIŚk)M<< MxS&>j GbƜVU)ز q5aWtF5.:h8^Ze\M!ɠ@oRł):bhP'OKo>\/[5$+X\z[ݜ+na#Ml'i2}ۗY%X;ØF̝~͢uNzzsx5]iHhtHiq. e) };LI2beX%gpէIY*̻RD*I47&\GӲROVGk bZ[0nj[0>z{̩M6W@߫_tӦft{} aH8E<eQ✑s.).RN/> [By .;-;|\GZ ?Gk}]2׉A9gXì\x#Ct5lãzY߬$tZkEm6t@p5ujw)iշd枓2p- 5֪)GXqS:%h6-wZ^?_lQq#*r^Wd.-]%,kj/ EԺsAy(_6 aZl<z{ޕz;TZ}7Aݗ+!A*qEyoDJPvծ3N-q+:_+[X oU[NϢ^MSDUA zxO0xl =Ni8.Wr.k"u=@#t.nAuua W$|0>hz_2ʚl(ɪM&'FU'ʿvVkm/igVyj7ԟq6Qe&kv)A]sISvR ֗%|5yUhLH]E=Ѓ^uA ;Ἡ.W)=5K3פCǤY92)p49㸿e$q"N\*Y.8yJ #M)7au&;Ɖ3o_e8Z&xθe[b9У0^VL "BUy6G)ma9h}ZrOx=lu4񳓵SV[$I%L9^'Yo/wT8>$w>Mhƍ&]4?BTp]$b"UL_NsPz-<"7MNpobm,)|RZ65x)hVJk{mɎO?\Y/vYөQ4-EEw+9-sTBmKi-;E0MEԘ3AΡ灮v.~NhQG  <(b$]KOA]%hxm&V Jj-Z@I2z<ht6;B}6trN A|.+UNic+7%"h[.v k̓SX:k\}Jݑk~ JsL\Y7Nޚ[6H8B:oοv~%/Ù?avY:Z*^sǾ>Y%l\|&`s[O=fH;eyz"wk#{Z{uY9ms)~ͪP`f+ ߇jO*-qH0{TG}`RrF;Yn1|m JNXX+ [- QOk+ņB-@V}b$z–uQ(Y]ˬ-E{eSݢ5dYX^!O3J h8ԜRz҅J@ytzǛ]:m˽4o2K"p91 t{}rs=t_\ Qd!o@HdE]#CE֭v9 +:q>m3ˋOR <#=\F ##LʃC`4R"O>nԟ\xITb˻mZA) 4›CAoFywC!PPb7 N$ȿxn25ϟ9Gh+ ,0C7 HnY(ip=g'7?l&p" 0,*0aڤDHcx\vcp$L[L[Ac[\)-*7$Lt׭kf>RR176(&n"TQĮjkc7['cs$0#U P>6r6lK&P<F^I7x!./bscfo}X\-Z c3a:z:m}'JV.ŽY(=2A,Я"sZlKd~fso%#׫dߏKanHTCV ALVXqZh^-e?})@+E-{ |rA{{/^_ؕR͈F7<$vNSٿ^܁Ww+_c^ }~nC ?ŕjm{ՆL9AY|~}x(ƽZ#A?a#YV>ZdM|WPQBk%)32؞t+_شSVc1_׉,3v3A7N KNΊg%(Ђoі1uș&v5hWe0gM ^ rCV#O'2Sst,IT !(K)Mҕ]5yӕ]HLuiKx ip`s6DM7"tn{#=+/ Mqyn8d"sdmǭ7(|Πa8$?`[6"xz#Kyn^mL?YӪ3^R笨1%JPNwUOb湱I}κvp5H2g@~$37†'}B\՜ZR-QpT\IybTҲi4]Kd½W3+9XTJ,GΩf9WIM䡜 TJË2¯m\L$+fs[i,) $V Owv6mWl=%Ŭ(oS*7RYHR7\-hrdfO*+r-OL(V*~~eS.2֝$XrcW-Bӵx Ev+rKk-Ľ*^݊n)oZnn2&St4I6@W߬.OnbJYK(}?sybfuƌ~^wܾ JzxKS`K&7!{PCTE_`\ b<!VԼcҭ]ow)mxWeRaY˭-ܕJ+ Ana^l(:,pk\>HI৻;/"A󉹹{$]W=6JBURvm".//s}༰!-NOEbr̈́7/"g~RMX xuc{R}=. vtz(@Ap/!(wNMeEJ^br+ZhPwuJ0KO+=rxPd.gun;>!g_ /Bn}85@2EwUp݂;sEdчxU5=e0nexiCxrIP])?gb6̺W}b "hĬgyog7)A?a>G1#"snBs }P…q<dXn7a‚k0.厎~;21ۋgY0傾"t Ϫ]:ݔLhX6/@N,S~%ƫEw$zG^@,yԶ&s2{|V-}o \U!pDkv̻2jn(}(~o/7e7U}}Ɣ/N 0Y| Yc EB30PW(`|*4qo_N0Ouc51"_!jS$#I:f1ox1ZN{*G:䎹*mD1 sבxuNL/64'q+ӪjQEK Y  ^rЂp+|&8t՜6)awɔ4'K3A!H?X KNU5p HZj;޷$ q`{{\hwC%l,bq agmyiD+Vkˁ6RS(ciEY?[fWzwMmjMaCWBkp"ck͐/Mqy54R5IMY@ZbD)|qAf Raùhefo' l::2-ՌO}gvu;K'Gz= ¡\ElW[MWlѱ4WgoGD}m/B;iH(dӚ?C$u u`.Oɽ_ qV9aQd&>c9 qGw?h#* f}mJo&'7HWTosH:q֖:}QjܝԴ6&B+){p%K]ϻ`O'i|JF|v+U\\3 v6X4oVEWzg[@_+jA>I:WDZ^2Ku9謠\ . 0%K):;`UřbVdGwU[o p`76! ƨ Ip^f~lrbð$>Һ,:<=#^uh8ܶʆfRN *9'sD8mB86ZDTD8kѰ $ļ'h/sGTGK푘RS63}{P'*`")TM:To˚|DN]9vh_;ݵ̚Iٶ,KѮU$]jh{j(#ڱie,N̮~RcN,ȵzs额3fC89(#y["BW VLku E2,`ʐfUY0@n| Ԝ5g$eKusA7W6h_KHu6LvebKuƟ:-sK(x䘬%jL6j* ur"nۧ]d8>:l!)]/b<ucC#(ŭ矁X+%?O2BR(#]t1 1Gh6 VH^*Q2M$sRITu b<>A p(|T *N.Ioek?ٛ Eծd0Zs'&gX[ѹ7VN_V׶yS4ʴ[ؠ@͢niVͼO|3Bz˴`}JhLBD[AMp_76DcYQP/V}rBjB",(wwe[$fn2[zt+W)MwdS<_T U06i]sG$(g4砞sÉ3(]G/f&&JT0Jʯ0*\LM^BqWv\~D&ލ7]Um 1 Ko U1U &.&0/LtlooFVԋ>|G(9/0Nw__:n5M> G <С&U1 QN}Ǜ6gi[[Ggla]JwG@v~x y)\j9K N& k I OV ~ =yݰ!!]0xg+1R UQ"m-OYŃBH+1 +C؞g+߉xH%:bZ"Bfx\oI`თoㅀ[[+WGEݺ(&GF޺=rd".#fzk~A:_}3}J/GzWG-tdsr sD6'+D>!d/ vF"ď)+xэl:㚋z yOLよN'(Oyb@0kVe`NFQ-Q ]&TuQĉNYAvSu7䡅HaLg-gQǿ[n|ͬ̚sLfUٿg.eLa~2@HyIsIL)K S$M4+8GGf `z4/:] f:xʢT}y#\)Y /+P6ēyQK[NiñꄳQ,茢J(?<ŋOx6Xp+ܐ'4UA%`q,)I"YHmܶ n~RIc4NϷbhr3u4'e4@Z$ z/8dF|GUq22)JPqCGNIGN(.ޞTi( Lq.B[ ;Ωl:qWĘAnQS?M/j9o_o8EiU5"C24c92`#ؠ$t4@'"<kr!a RV鎒q"Zziq @7r KLMMH" q7H3=q#Ņ$ZX{Hyx/GPFA}PKmxTq^KU?'qaܒ~U3ng|u˵$2wA&J^ǡx5tN|7L15-q!G'ix7R8yS?;sI|O ;TG6h9J"$pu-üj@' dC3 A%m{oK)&ىr;1$9znNǼ:iڧw?ۏdfԿ Օo6( pf3ȧ gf[cǟ]%5YNb e>Iͣ?|G(|1,I9ݺKfֶr>?Oۍq6IHĹ->򷻉+@^l馽]tUtJĤV0_8ɹN7DcG?d@@e9sC}Dem]/,/헆. KCLTWj]AZE+7mN/,0jRnpk4Z[bf_^{~˖Ѷ/g"ҹ%쪻4Q/!!S`0a*V)엺?l Σ R_?keJaY<{lq}<1`^-wU˽~g.fI~-(b|re|o.Xf[n4G ̍>ea"AL}9Uo @ѳ~i88 g@;is^Y 3!@*MxxҼ_yf@uoQ\$pъv- H~C.m抩fPhuW(U)xhW$;VWb67YECbUiu0,l8_+IS?E#L: (vm[E(g+(2=D"3H\A/Ђ,RPio`&bc=\&} nqI^sdG_* ѶY5GtJא)MW9lܼM,|ݪ perVHAchecksums.yaml.gz0000444000000000000000000000041713051241120014573 0ustar00wheelwheel00000000000000OBXe=nA D{BP@r]zrS1Ttq;üqos?~~I5Y p؇ive[*38h콶.fP=kѫU"pY‰0ÃL,-^h-L K#p4 .&q =V܋P/G.ɀ~HSVK'^Ǚp vӠ:xĝxbpA -* >^DfYΑo7PK% ]#cache/test-unit-3.2.9.gemnu[metadata.gz0000444000000000000000000000277613400437376013461 0ustar00wheelwheel00000000000000>\YmD_KA&+ RW BK]/]'KNTjy}33-|lH%Tu )y "1 Fbd/ r =]ξ꒙\jAܘYSH%-kků3eWSQ?-W("jA3JA8-U~=ʘA/Kz\\,eP@><3F{-נb5v*f,o[=:.,|}dsËh4PV^j J`9+5g6Q6|f+*@)R0+mLe12q8,]%n:*^oȧq?#\ot0KT+yk>" )ƍs,f+@ZT|+-RdK^WHWHaiEdN`c~6U+Y3kRVn,7u]"\=+C&'\+}q>i\wږF&2J 9Y㥫V>M_߈L%iGh*3`5,UXe2s4O8?]K|zy~|\]>޾x*sϘF0|Ĺ/86LC rMuc*y2?\J:y4oR)((%$S(XOOIMFAi TPhzDkxtpj]a`9"un&xM2X\d\޸3˜ӵbJҬ’`βÖvm41ۛX2P8A#~y. ђ%xS}3M0AQB҉-:6.ËJC?a2 |064c;dłvfK2]Dкɥ5''K(s/&T ]@#a1@$4ӎx'}imNlР x]C8Ci+d5[bWS/杒yMa<)]+/%촴**LqCsd6 2ɿIg3 RD.uuuN7CL 's͹)Yˉ^}~data.tar.gz0000444000000000000000000036752113400437400013365 0ustar00wheelwheel00000000000000>\Y{י0۩ t .hi$ܚx@VT!ؼ $iId:{796;[[77~|lllNm)"`)7Q4ZCW7SDy,Pqd7E4P,T0ToI˛(VeWiq1n u6 *A3+{!JI֚l 7Ijw<j (p4FJ$sSIZ}X0x(nl!3e4],3N`VVNj% ;¼P'za:5~55ƽa"|~իt'p,)}Gzc5hwa< {Gy<*zGIT,c_.EIƀn嘰 e8.1,2|?Nrh;-ޚ*s?~i& x]$ q@.ƘI([2dާI8M 'es݃eVNfuffz+)yϨ0:s߁* iӹUL{@hA.tLLmk2 (H^3 B [ z`]I ״k8BP+=H>W̢pwFӪt1|k9kka[O¬N)Y@e $hhKy:G@8muE%Hp쪁<>ʅi>6ixiW[b&H-y'0ti햺@xxR]F's,n´f؇1\Ml(?p1 0:bok]6~~Uz=Z`~ժUCL"~ wzPս5}EB:הu >d @zgv\󼀧z_duFh77y7P@)hx#rRo;]Ey 8TgK'AIF 31,OjNAO]sWA Fy| R9QD @|3U =;ubr "I`ϓXHPv#cS]!@DY4~57 eyUm Q1&Ҕ^ZHiiauڍP 1Jrb1J*A’VQd桩~ 8M ( 9CA֚Rں{%+ / HSBn@4Nh.(Q,5OIOy+gP=R֠Nl'9dm iUP'&L`jI9fa,Grv< qgOU|FCFxuoXcW$*y_,&wjk/R|@uΏ^ND,[O0z \E2 UEZ0Z7:GAH`hV'&e܋G ‘A6 7F8j p(P+-!@g+nOX.`'yG&Xhl=䛄_.:.8wk,7NwV wi<`CRnjwXב1 q&dŃ4G'1Lfn; P%Dp >dPV j)T 1<"\OcQ1 t-b<#-/ώI#;9~u<+{kWg/Wɫ{-֒k&M42R"a7`@[, IGip*XF,Jz^`aF`׷`wK# ,x\=fBB[|w  :cะF ]1%GG $RE#%#k)k@8Zշ@&*  NHفa܅O&xс&H`EOUބx)qZ RFbzvt BaUeH^%_ XO uy ONdER{3-x͗Yn<K{S%1=YƐZvf)P)'Ġ+Mio)A|~HZ+ĝw3Ėuy^NP2H@b>Gpp\Ľ1u/{`Q0W8Y>ݤ ="GW~!oc*vk ÚI{<%Y,/ȍ'aKad; }"QÙH2Qj$A6D*A9؏"qvi_iQ[k0>Jxw$1] ßw gП]q `Jᨬ$ cb_I2(d< GH1eLvh+2=|߬_#P+dt^4w1EreCKT k!!pN|sb%k f<{@73.&))4*-؍ʜ'~peqÃh'1]Q͒ ':P _Xd:h-e Dt⑖e3q k9={(4#ӺaHX u0h ?0&tw+4F,Ht8u| TeBr LԮcLCpFZpFG˹3!:Y4lt["규3gBQp>h(AXQItX|\^8=98ЙgF5@@l sOQy4$^SsGRA&)&E`퍫f#D Nd"1YV`/J2-V qE4"h\q:!l Y:%n:>/߰1a!:HNkw9)**X'Ȃ f(;|6^]1s0h *烣pP R&Gq䋞8xKJS“+U1/5i}}5<(&] _cFp,?HN(EY$?c/rQCַQS74—ط$:~.D lGs:BS A2#o{"*5?UF*@qCV$ Va! [CɡƴBɚWrpMpgD#YƠ/eDB^/c@i_sLzȒމI &)!)QaXDruizY&eF'S ;( @3?Tgd1{bcA\L-ҟ&wP$7}Ɉ:">yJd11>Rf?!<L#:(mtN@)5p4FG>bQ̒AH$(Kd|b% 'dB|$^Tn,hܧX{{/f Usռ5;>oiZJ.N:t(E')EK7Z:&?Y({[യ#||rCsoN 5vLVlF,>Ǡ L9\&LCf)_x<r o<, ;ǽcA#m8vmd</ "@Qx6)L,%;9)dkA*ZK4EDR{Qf#EjL!ggN40ݔwGXiX%8аs|:BLL xS1zA :ݺ3:T\dSj1_ByKลu4s;HT >@8&nfힽ٧Wήu¨Ygxϋ uvtpq|0x:~ Ͻ s~wgoh@ =;xB=9|F0;ɴdzI:W/7jH2_0z/au^x~p4`0=kG=:AvwJ`߇@?W_]| O4CuힽWg!pc&8`qgS 8F `9Oz zDus{AXbg %瀖 Au747Y2T;UtHe!n Wl) \Q.̈́E.tz)'pd!HwT\[ "ِdh .$Wܰ"-5IIU$̒KAB1 %,p4+2t 䘣bǿ0`kl%kW';/MB\gY&0ML|ʦ[H/:hU?zmVn؊v?YKgp8 j>n4yQ$30Q1 U ]u;])2]I .^x /dtu /Q\_RV6e+` 79&Aa BL# jY(Gl";8ֆ:$DPf&w2= (N#s (7 HwhyѨhʿ3oA퐴CH߻_QӖU`h \+F+chҺۗtBZr3FH0Gk0o d]/S8f #^;sN9BG'Evi}(0d+% 8JJX4ΛMue`S&@rMdÇH4%k:YD-([S9#$NiLVXg} $9dd!?$pgM\R37KїB]ƚ0rD܊ܔXmi@&& :Tg@y61Fߪ5?@v6w:o~OtAtEZmɢ^V"hxԋ6zJP+ׂ^KHƂ!Lo5<=d]7$JKiL3W>>lXhlިZkVI'U-VV9t7\?:m\|2Hx}1C pt?u+Vp%lL(`QX/FdRN0 Hh2(T`GY!硻$^{'&Sse0}# kfkkfN]ͬ/ jf}p,\W4Fyh_SԳ # 6XG+t&i[JK-+~v!-g0SEKqh!yq?SH f"<5AʂSQ_ ,)z_Iܹbq:{mLE|_ Md/X)e0 tc]h1gfq 9cq&4 G)+W*73 tǹ9nCMer1Gt0 w#p%DO''@LR` n1Cr ê1ErL'BBbE`T`a?Pw#5Jţ6Vi-(fS =`h736q X!8nn ) +څ ѥYFHZXGJ1c``.fܹ1XS HdD懥 DlJ'~]80Wx/P$$+h#p>zV8r%,`MOJQjVc?Kg_"]% 顤ii#iu`VEȝ2'L]Hp"T8J"ο KWT [yfZDRHߦC}C0G۲=;=^?]SVc+2',2l}мLEJ$:#JB 0 e77؀3m<04FLީ/TsQD"\2ҍGhx-ꤋ G0z3.Hd}jAhhE({if 0tL8#up: Ģ^s ; t!U=;jFJleh(|cI2'|Vr̘#*r ̾奚3$ vzTi [ɁLsTf酉5AIQ$@$衊BtaIMOmnՀ}y]d.XN"DR'P >'+6sE7#QWWQUG$ϢgNp: (}2c0)*( rՔbetW3Rq!G J+Y$P6k2 +d qYedղdu)"l]u.lTg'V\Yk?EbPK[(]oְL^uAX2,*IE *duY'IS@\ڤHӭ"Cn.dSzWՔޭ;}M :=!Gw>aT=ͭzrzݑZjduԫ߫,߫]9ޕ%r/ʖ{ >܋Ӯ2r/K0܋}5+9eǁSA}bc]oOO\r,IE$ ZGPYd-]Б7cgGaA-r?NrڟT'9xju=:Ɂk+!Wjٵ[y/-\aH-|Zފ!_4%Zj=_V0͈@%~:0窅q%TNTR*N9 ,yr$g$!XeEЭKIai Ã,,eDיhjhHS)tv@.(m\,c"I*k`Zpd6/:X & ~ GCݯ[tYߊ.狄V̢2P0c`\XtY.VI=[ EgE(lCK9 }srm3FjENjIU]ɞ#JӚB-]UjO^ 4' b↩£F !(L%QU?&E4 ΰXfJRHm}RK3FrWb-ԧJE^!f:;pAxvXa䄩OzT{NWY{Qx|`25ʎ|B=Z#k[%U@\ ]-WV t_GhCV>~ڹ-Q8%1SΘ+8ؠ^UCC6|P:(*Qft$Vm>A2sc{\8M@Xp}./PiN]!)Nԇ939 f!2u |:1۶tCHVƶ`(O!֌t P% Hl2]"I.mж46HF[*7y2ƹ$-'dJ /)F[?7\۝B?j F9m[X6p>9)l._D1u<!5#;$*Wc`ˁwpe2AGs%)GLa?Ks8 ϭVA Duy-euTU>/pt{p{& R\rt++Hm*S'Vmz ȂMYxV y4oNӺ4 Y+k\;ߦ `fuH)%z#MQ9 4y,m:h JۘJZZ@f9ap`QBF"Eı(9b ה7kDPB3ƳGB\غв=T..1;Ul!?dИq܌.qi/3.% wxI&/>*d սpsqf=a(0n k0dM F:T[[+?,2mV@"^-X#/,%&%n6΂`fÖ(p*auɧD3xRؠGl'EwbX:ơ3hK8dT}$dࢾ'>Mpжgruhy۶ڸ\H|Ҡ\ePUbSo$eKDZuޡδG!l#zn"^|q: 83}u"J)s r %o&i35Z c.}W( 3q1Iօ#5|h"Pt.Hp\?1̤IԦ +dpP(:8>תYeX{ѺRuf8e~c*%rkݘ1FUs<g @C e - Plh 0ri*WuO5=IYW|hZff5\ÉU@9Sd)A`רƐ|:"&ɚ޺7nXlӫ?ѽ5RWc_W#_Wc_WL+.A߆pPquk!]:t 2: M!7=Tݵ.9 ` :" ~?G~qu# +)zI7^)MoMlzOGQjHj8^$NUofo6ko~Vtx&]Y\P+N=W\W{y{+3}%+Ε?W\kzz-^[7\?I=5-ԣZsZƩZS[˶S [h浌 ~ږq~˸Ãglɖq麦[i8ԧv q@Ǹcz\ǸczLǸ`Q8TǸ9ڎq( :tS;|fǸ@t L8 e:n8qŽqjq8wS ;wSs;qzQs;ƩpmǸTMǸ3:yws[yUc?e}ı2cړB"qQa-Nl\( FOԍbW6Z%!W*ms*=PxoM׷5dzZ9Q-K:ڢnj-l!ǵ]t{QZ=Hbj-թm3j=W^uTXuKkd!L:g{u2 [(_U ,= fC.pR6I{u q}^l<',, #gzuzWڙ[_mS1Eu)PۺnKzaOXG;Qoۛ2Ŗs=nH <(d@ܥ X~SV>n%5=1yMG1PGRh= M]94z'xD(!b)i}'Numnf[w7[]yw˾ݭ =X=0V[[ ݬygەzk.HiT[LŒeilO`Šm)9éuL3epyzFQQ)3'u gHLj)4/tc:^`ƪ\w!`|&!5QDf;KIxɱ'&>dxcJ %@:oӑ/b3Jl?/P:1(?΄W p~xo*hV'ǴaZ.̹"iVfN?<[c&Cbl,5sQ0$aIPrE""qÃ] {#љ,}Gx{r@e\J0W@{շgw'h>'ںWC#R7`weadApFEzD+mbk_xp' Gޯ9ty>_ɹIx8YN22CI("E\u.G:_XCd()xjf_ %Z.KUʩV5ghx7`j @ҷiAA:$0Qpf#Z0lLtP AϾDz`Xn?~%j]/#3tIۼr$Uӄ Dpo9Tbg6wb?3(7A`8 Hҿا^bCS71q[fI EJLCf 30KpQD.hoz6\I\_[$)_j < b26zgѠX$5`c``_sdx7pr"˹x5_\_BNI1VK t*8EW qae t o:4lyb'.Fbn")Fpķ%3VZF煴 G1М$ro`1QM-":XIG} Xa'vdyN^xZV \GU c3u#+j^cyUC"q792uzuSG&. ]c g#N5Oɵ+ #qv?\F. zSW%@.#t=MP FӽHt0]hht;]|,/}i_G ~x&9&46ϱ|y#ɝ:{kgg>c\`Gm)p֩GzTw;a 臦GB*QDRimWxku,`KhOK3%{|^](퇅-+ e.:\7`bUsEc=Ng< R[u zrRP㔘 jVޝHkh*V~f)CŊaٜ1U#T"P~m*qUgVy_{>F/" 0jj`@SQ%T4#f+es@'pV^G6e.u޵[&\ǥFIK40)Mu55.6J(ml ,2:Sɑ0HkN:ø"$j]>X1r8Q}Vߜr=`>l.#]kYpa&?Ms<j)*ljiܱ:95^%X$xuJe$Dw mg"ᬯЃ() 6L }a㠻"k l7orƿ8@xelXAoS㘫=03(h9:oZvgc[/l$ XESE QkXfVgu`+^>~LN)?ao0Ѯ= BY@LűCt OWQbrCA7QQ'RpLۓ ۓGaív '?I'?y ^R)`P+.^7¤W>*8yu"Av+Xf鄅v [4%\YiI"n ^GWqCLz[ܸd=+󽃃+\0#J.IZފkGΟH2Ps?^$!^Ο_ux&M:\  m VfbFt93kZ-]//>UaCg/~ɫ}҇$7o[~%7CP%*) >K6i װѿ1ZY=GdW|)͢W]V}>ic>Z:C t<Pua,_;7Lo_ŁVf1~K?% / m)~_yTz 1*}bAe;$޳JF'1N#Zj>#`V- {L,*$ хs~Ipԅ>E#~`?U+zXkX}=z8$¡#pկн ' a>Eux}uyڽx*1sX}_Nf)iO*wZS|g*O5 RSڂYq}1yj}IsinZ=N !Gp豵=[DD4]X:0 PqA`CRDA$ W_1~/ a A;}0/5UTf\TiSV|} 0s[Z:;xF/^]D`thew: \"G}hd=ބexܰf "LYvwx0b%CU \&x3#Gǜwɖ߰-a^ =6PҏQDE9%X8+~X70zdq۹QNK$!mEDq+CI fEabp^H֋tpCK6W|bn̂s,ן[okSE+:MެXȝ{~(p(W |*ם]c]şg]S/vU a] ov{Ɂ R`pv-!J͟'萲l[z w1䥡6TeiFl`SƏ`&yp䘾󓯸l^ǥv9߱%}'q\j1*g8( =F]Q2J٤/"c9/.7K4!vlyX*YJzPbߐ%W_PP = hOpǏ´BAXw*{fXąz/6VTsVʪ1Ϫ g= (`0B`lc,#`;x~rA5+i||֢:^F)73X5ۑhaF2uѾdkYH_>Ӯv:? WLLm,(5u0"gGX{R`*pPJhZ1om 륣.i|CQfdѻ.1$n =~{o/Gv׬|׽wrxrF9_a`QtW<99lslx뾡;"cv*c>q#M٩{䗤*v?}1Ԧ2'PC*#|Eau?BF@gGљ3Fg1s1}:s1s-ll7ۛ\w îزH@3槩<'DaJ^4 NaXA2yyPSYϳ!."MSU"aEz\WI{هOâCϳh^QGsjoT*'U*BW3 HWOBNf)hϥ!9B(j^1GiLֶ(AD#CU4[-y1љWqNw {x,轀|}t:ƶ38K8yX3'-,$z0ΈmB{qQW=0ulT-IU+Aq}yyOeYy~KJO;¬*SpԽ@Q=wgB=z^I9p({ąP"}rUot0 K%;V?ΎiAuv.bI]Ό W* \2_(W/3.GM5DCCz`nǿy^8skssOsjPމ!Lrwv]!?ν.l~Ba `pP' +75Pu6K8Kݨ yд "Hj7WWʳiy RC{-SxUӦNu/ va5YF>X8qE:NoG0d7A_?_хðKX$Z"0kq9J88F6k%hj?QuG`NşM/S-۶ǏWwv*+s;dT|cP2UsMj/N:/I0ߙ'Itљa#N0. | 0ҟt 1֕hBm*QZn|ll~VMO*Jjogx !jL Et->BV[`:>J3 >l]cdL>Zlq'`ˈ-;r刅oq4P +aWJ4su; $|-DG n|9}R5Qk禄1oJy}%G%f%Jmշf+$: G::ZU btHXˉBGXDH`">Ow)$ 1*)s*#yO`9T} FXQ 01P6XZ(U '(\3f{:eפ)(2n{a%CH$YPeA807NO Ki?(Vf{Qe)UO$g̀.sis)d82S«?ܨmKwVug)@lnl~ro"׈' 4ѮS @5mq2H‘G PC^{c{o7&!VP}yVv{޸\elFRyCet)1]17m[Jqz@/DjYz.,06YKd净=ZZӞ҃/D 8 wˆT$fe@M/8LDuFYg4(xsN4 fN7ױx~Š Wh se*WRkNyiAgb[9D;4o 1/y˦ɞFc?37ܹsW\!Y\11MCr 3ISe(*JMY6*>07fWx~=p5weIt/Hu蒖GΎ*(xe?xܤcZҾ`(L\mxIvմf|J0KkDߔꡰVs %&qÓB4rn& f夸Vf3PXMajI]: ?TX7foWt9`Gsތ%o,7}>ݛ׼^ mBM?2bLr‰M̝yk-+4vy ѮQVe?D܋eVPqeI|ofF=EJ{~_ee1\)܆g?ڽ߰4Ҝ>wb h:d;eeNnMb?/djΏG8yL!5P+݋ R-{L^qxOhdc[%+jNN(Xj̄mzJlȰG迋(C?C gL#qcPϪZ}I#mT=m3dRv?&j[g䙮qg* m)W R` ^4kvU ̨{Maa?)䩜QГhFg}N]+pTJLM"ê'dZه \U'_AD%N}*TF*Z1Pm|5\ iy`v;>z>giQ=6\Χ}[; D;UgHmª6,_IJFq` ?N{% P>s88 ^,9^.]~SLm+j\͚/t;^DR=$׉сYʃس{]jHPP qazCݛ.kF`8\:G.c9=TYyܗ5k%˽X'%;^,6.0{ [$@[s/^؄^P췑:lq-]\Nm:1b%ztfpπ04 ef(qlHz8_8 h?pB dgg$2JnQ܋&J>oq< ?x56m+#H$РoGO/n)It:ԑ&ބz>X0,]G^W q.'-K>'g%%_qowڏ.ғ,3-ϱl ǫr3 {16[mU:'vb0nK66Xp&#4Fj+ . J#M /Iokc&mB+}ڛ8ap֓p=71H.YWidߍhq _ Pum;S)Z# ێ H,( W]qnVNqikKE:>d/D@k:8z5"{Kͥkٜk┍10J32-ˎ͜bfؤ|Qin[3PZ^N1yZ[q֭x&jw8,b=XH($Jve mb8\z6FXRFT!hǣ4 !R,"gCR'vͮdDǁ#]g@K8up=Aәq'P hlˠYD4zoPڟd˖e2#.ο-xͪ5&^hɍN G4Z]&XjRm&S;` i2ctiO^T(,`{SO{yc)sb]P^Rblκ*Xh-$И0A9lx`魪D)<;vS_!%Kk ]5 r> (]& ͤVا([*ql6MBZGȠt:/2(x:i:F:Kg)ec0+28TIU|Q䠙c6qI*? smOt#$n `O0 2(ɔIKJU+0 d%4ϫhA4&LbMŀ.!ʢW$@ΜAޭ'l=lAQ֢G*ja mhڂ-_Th5d:.@ecd0I7 ~Q04M9gǝX; rrؔX'E!ʡĆ;[mX@ tzAϲ^(Z8Nx k j/E=A`^NȞ'QGc2]6>SxH n$q[5qD$L` GVk!kbo|H69mPǫQ 'gpT_k0R`H6IaR@iM-J2>\V5CT#_kBE@77V= W F[Y`h3 4pcuW#ks!^mCx$^˸S1J:Ky{Kܨ^Afp.KhQX#2F^h}oa/pĊ](eCpe ms@~%5LгCU^$y-:cfS =q _Þ^p/O@7iԿ]W7%|g_\2A ؘm[AOeNufؾBB$Q>f=dRAgyQ Uv(w(M\W)cav|XWl1?=:/1RoՌ@A٭x,VeNWa/bc+c25}3ZV 3b6+G榑$[e~M au J8+p]Ib<6ޒ$9f,7^ gRt_\]Q~-L+V>b귱=\pLxwO;bV켺׏+3>ncsLtva˄0gӈ ,10UxNN랽b[9 unW☕tLEJRJAϋhW^}Sj 9/RXM"kܩ'` S< QpYN}uz1Ĺm?v92(tgbaNez whJ:EphޔmSw ߨa (SweoUt {U{7i]z˺H}?1`3Lvި\m1nt=SK2ڱzQYx=yֱ]鱯Su?kᄛjY5ٕ [6fz w̏Pm\ KG_v*]f`M3p("04Po|nS<5.ك5"p`:VaԱR(#E=O}\m@3d.,,L`Xg&hΌg! Z޷D!o7h X9Gd f4-m=߮!QS GnP-%ú^qԨ=4Rߦv6.Em0I Y",2c8Ms u,M')pڼb"(<acrk@W;W'D#1ÂvTT]mgs[i܃GrUg\Ի.{`]#~bk lؾ@+ٺt'ZX=,uKT/VmnjL2PPxl?r튁O2DcYs NS :\U5Gt׍Kh~ldJSv­S}Va%p#Ot7|!qn؍-E#xr|!aNq؅> p x5PlwwD0ِ->>3dh$Zi԰ꛖmV]^5Md!${Q)$r0N Q.hW"5,4֞ٺJ' @gI& uf>_6&p43.n|'JGڃ :PiJ' .j&-N3/ޫZ5T|3M6`feyv@jH *]/’ X[-}&hpdRS-}۩@]҄!,Cx>aL(& 98qx(T\/k#Dw胵þ07 }#0`k3cC .u;|V!YF p ̋f>W`}d.-f%; ;j_piSGo DlLF2MWxCp!ȘJ|CiP2TB˫@y Đs ( DdTK⠼Ny2Ϧ_P ˅k2#6ɗ>fq sKA[ ۟+ e >1] fV>*Bq`F'H2JNq\H!P0@A!EwUAlfwW/VbE)E#zAڄ@&obճC}h(6 lܩ~瓸U&, nødY* uLw,0D{`rZhXF֜Tm`P92A #*3mI'z;'!ÍL튨EI:iuq):sK0z>bҰY VH=4ݍ+t0k3}ӝh/lbP#$ⴎc3a2i$&Qh7j=zx_R|D- p y@%Ճei"8KK968'mB%rz.3__%tK4̆+2+]#]n\Y o\Ӌ 1 4SN95S}I;A!5i,{OSuCu\+:WHDf@:Wl۫|Txý{GcAO`[1J V4,_ ffrqBλ*#` P8?~̙ЌL'>Rw~}K?w"){MP%uIkrpV7yD+B[zȯ@OѤ3}%z>@ˊ50!sb0v\v,)sBUv'[9杳FeU#oQ)m߫- l%qq!5WV@vbe`P`dY]a*a@be Y "(TweNPJ)ԿYEIvT\KIfd=i Jy,]C-iB'5sdWbq3Ȣ{̴P==^euX49ɢ7;zdz[ CPO>ml@c<}A"J%% 8P_N|ƽöAu)#'Vm"7X8|%D8DqI]KL]; Cpe~Ěۮu :^@E`!粂\M5496^½ϲ^ƃ m,XXxt>Kr`N_duFɣ+mHA{+ px0_;N@Y2tXJCNr=Z(lܔ2 N'p$Y <\J=#L^"e<@7@G߷_h0]eb_~JӐA fԱ^j`v(ve8eHK6zYA2;n)Ll?Mtfr[h~epk=3-B sb0tk< {jrIZܸSY%6q,?RE@w2u2w*;JFk9|!VIşQZ=FcW.i_utj`w?YۓTFnl1w㫟8 "1$M7ӢG (9 d=- $z(*W8) YVL.&1~6{g.{Kg>4 ^Nhx:h  ^m{o_|R1:UxVW?;=0FћO~6z7vZ% -ZcE[éCh;b: %tD kQrJ ֌>.X+mF^=X 0&I|efC&迶{k{ dA-s!bcI= l*@iFɋX[決`"S<iz[j(E2V(VN8r2VD@ | !ʱM/ٌ M u!.2n# ueP shbsdCpAHd5 :U҉$)xCfNUT=nF,~&M·jDyTώW5bO!x7 NҤv!=AF$N f9A+BYA1<@("]#)p3\9P (Hb_A>A&yD7d##?H P xPD@3Ul==L?;K`:S:_ E&WE^zlyc$C\?11mXd4/Q2]$ݏ~+$‡`eVܒS' F]v ڋ纨6cN~MHYJrǔ*?g-#vDs: b; 0c1M] b)QK`iX€*!eOK>`$&U:U}Lzp0|8r {,{oshEh%<9{31VBԕ{XyW k # {& X'fExL `%J @"@{)zG/1*0D>0|~[q_h)\Gbpj&TOG,N(tZ8`qdz6pLcйN t,(,B NA@L|]$\Ap)'%(7'L!0 zDdɠAg!s9Q64Of@m'ւ*5<%6݀d]{ 6AvyOIe<brqc6ōLkPyFSTGR ("n b;R -\:Uc4pE;e`)2IL&2UI `DZO(J=CJN1K> 8cP|uJ ` <sa#2_c~K:#c$$wbNӜB`Ob`(+.V;*:`+ ZrcVfgqT31yc `%4 %1=SN(3!)[p ʝ|ⴻ)/6m1gQ 3WZ8XMMKQ(\p:%4Q的{ "]XPN "8O`#;&X!; Gc$ G1ܾۇ W x)l\գ)P!!d"$LB"2\!A ,Gީ  @bԝSS(NRTF΀Y't\Y;=n8=6eHD .tQw sqt'DhL[漬0GeלIep%J̤&Do"Jq>TX %uVY؉i_4hj7G6숗IC7~sARBxF%j :9ACD'9@hLަQ-/JѬQ'Lo<$dllDICF!{ӳ)0{y?'wUeeg2^WB D6AǗz\Q&I* AXHc(+toM%PAH=*I'jx):yM 1M$@,)\Re}V9\t Iל| D4ZD_>dva׌Qǵ@RhAI;1TYd3Is[=UȮ 60@44+>3' Q뀢٢Hs } 谛`?ϑ&]Tԝˣg/1^ᱳ^t7"@,=YA,SF 30,%Ca!PH4PPz 3mx&OEqeFHχYSW_}5 N_he0qGLӂW"{Oy}r_w^\~-450O'ׯ_l2l/1!_AtpVǜM߱9X$BW=62|)) юqdӊ|lojPg$hrw$.=6mB&XRzYXqGU m#5"BіDU:%3{h$2JI7M<|X딎> IwA2 \( tl ?e9`H|aVD-ؒU ;Ȝ&G ltDQ Xn 61Fg,H]qV5~MTZh u S`)QNL۴l~ΓJZF(x^GaWC*!: q5rpYХpV&Y0M5tLDZ;4ܭx{ỈhkKրRNtp{MN}eR&(5(ek{ 9O40)%clx>$iIVLSurEe?'{yɁ֋ 3v}?zn>22`@mnl|ۍj7QSIsg<2Q]ux˂u6p2F1 ]0aS[i2 N֩#Y?k»Kөfg'd z /Yt ?/u*IJF ]AM[xZ9έSs{#_Olq&_٨g@ 8D 77aƥlbKlڜX(}}>U/^ia;VwwZt\(8Z=Ё?*OBiUobF{6ZY<n ° D{dWQm;,ħ4.:~L9,Z?G:=lѢM[7vܛLTep/Uhk ADKnGfbJ[ߑMu3وMwwF7sI.scEJ5J9ŷl?~JƆ ?L7C5C֛a?Y_o4<皑eBa[՘;rNsy Jm 8MZ.TPQ9C:<֥ o|ͯ0#<&Z,<)0dv9@^P,5߀hiwk+ k b⋳)Dl)HC9əQܸ*};kk.R~1Հ(#< K%q)dThh7L'\} \tJ#l曷cp sԥ4Aʃ'Ťbͼ_Xx0(:K}4=9 3YӘkL =m!Eao LZ8`gιT;09Ots[<х XWsjN>|0'KG f#+#{I&$٥ⓠè2F흓bLΦjXػerX-ܲh{Krn@pG%3dF Q?Ew3hNI5`ٟ {>[\ 0m襗q-stӎյ_tK =,]"{IRShљ֡bk]6t$@iń?y G}2|s~\FF`0[oT>]z񼹴 2 aKی|#@B I%xjDvG"B}.8  \7xU4x92 %))!CA 2Ӏ4饱EJ4*.Ţ՝ZgP2Et(ƕOC5Vj.egwYo*!q*bI0NXKoikxY_j 4 ys8p6eJsk~c*-xXU͑L5Yl si+n#țk5Ԣ< |zd=1zo^} 4;Px7OwfJ7og-@jreH} Xĉ82ĠT g'lK`\`Yn?;Bc,̩n1o1!~N}rAwc_?q{]la߲`&JEx،%C(L)kĬᄇ Ziލ7۰?6gzI;WuQ7=?+1C)WMאK}-p)#*-q v< =/h\N{}GI1m]=ȾKs(>zR+\ڸ k1YWI5|ҕm.lZZc"NbyC}a,,%Sʥ&@YbAE)$<.Z0)a2Zk5Ĺ sΔ!Gd/vlRn8P%q7nDvBE{;mۚ$]A12,ؓn:Lu'@A]ObqKMἱj^f)@(V& ګ=I8gjش t.)׼K?aJb xlO)=\辯 Q8~(V|pnbn8ԎnUQu GoP Q`E9wu}ۥ%I$գ3T2 -7<*[tӕ*Z&܅(Kb89\lֆRDuR&^-lc~9EO !}2~d_/ {=L }+˗茳Z| Ov$@60j!]psyîn i,xBgSsj3S)%ZFwOn"*A@rRġ7Q2١"ߋC1>ͤ31v[zA!{LZKqv:)~-a9,t;eZМ4}a݆nG3Y56A%b;:™,у0J07,!&-$ǿfu~s"x8.GYtoOW0mlx>7@ Y+%%q'm{)m>h(f\u`B%'Rc 3n3@@[ɰf ۝w~yzÓ/P1;ҰXbil5/~^- P!}Q=S)yǭYMNMWsLdyVU%=9+pT(5|Tc#{tҝ@.%@|U9[?s3Gjքo8wraLU<@q]o?Zn,}jnD-ثҥiwH]`}gT1Kh3[r֚c# -}w~◗Oے]2PE8+ - 2׹=0O7}>`(=1¢{ =S&zKU̓ow>8k%}9ylxn`ZYBWw=+~co#}cNkmeD /n:1yF3ιuƸÆYPGɎwBCAh=6nEgӚ9O)Uq+2cr?i&T`dKeZD{ejI̕2M2YMQp..|ɬ-, R%vhf:L&RRs4a'EDumyKtDP,|ptM's9{o{a)l#9}/iڿh"+EOs5ĻfS _7p|5jA'DN-o8eN<*WWLLLRk$upxœeLvuhw?<f & 1_ơ.vZkQ|mEݻMxC~kJDſM_C:~ĩ/DJ~hC*1yfCЯFNġLqbM5ZQ=0.?d',F!8l)nAZivOuɉ)?$n b|4Z%n`mf:<FFmIfa2A{$@K;^]4*3A >^'~]|]*z<_c*(A5"G\P&?䩬1% (j*0\a!D+˅.9\Kwt a:сoZI*rk PPv1ԺGwʘw9MAzVY:;cؓǰ3+6A-/+!ApVm_޳NEP7ޮw7އ ifZ2/__Ϻmaz0=vg,ˊ, ߕ %D^<;TpeY^gޣ }>T2A6\Up#,,]lb2}vl2_DuMԭb9yM6{įc["T mbr-Y]r|^ˎ RɆ#m(F) ߾a`}LC>q[5m pD0g>R( O|} x%f~Xj-vދh'o|M b>x5M!0;rC_Pp(P zd-ȮF0 8I ' Af ֵX%-N\aNk,uf 831J3c5 ^"+{:x|qCAI 567[.93eFNU}[3+D; &2wFf1,R[lNIn-_ɕ#n`_F~3 VˠfTte Hn1S*Tʆ@J+ȆnIZI `ZO 9c}YxjD'B5Y2q[=ojYhϛ[جm AxoWe7ًξ!̳}ء[Ԑg_~#7 |.A rԌD:uoyk9=J[]_5^Wf'PŅS'XƁhjOj40%]D%^Y@tken?{sF5̧295BgN@eTv2Nb,ӓPeMj}O\_EFWA@2ul-|WeünIFVU/Em{}RJVEat` ֶdPk\`+3alkEDŽQn>meOdgƩxYX8A(AבFn@6#:g4Dc܆Ȁ4~@^M}[0# jUt[M DJ**8_}@YrrlPG ]/ŌJ"m*l} i;e1^Zj *J[۴!/0ׁl0mS@S&Jr=:@Uq'c24E-7R> H$GP"]=_]ffUP>{ /9^e%E _|[~e) RuS.׊w*\~ ɢѮ%xȥVOn`g 6BboR^UϚ)Ma|!6/ ~Uz*ún=gd!(ϥǭ&;?Ut\}!!$t 6JZx;I3RƩfuЛ3;H'S]׃`wKYrrZk vP> <#F/q+7z  㙺sbz3bc'ﮡ~%7:c+Kd>]Feʲͦ4eӿyH PlBQ0o~D@UPfP(PB7+Trf׋kwEE#.!U<`AKcbn6.!q6 wHD(a<}J6&;OjcU[WBYg 3HFPl>t NcH'>ySY0(@~HI61HljEi*߇;D 7PeP iNE^BUI6h)b<SD9 D!a*hSF, .kfThbh;l:yyaAgYc2eCʩndODs9l%fY ݪB'-фJ|n+D)nտM!>~:~G/:\,ʇC20Z̃Y?4~`_}/-VJ1@a,tfGPӂe*!O&z2vS־FQ1 $}L%F:ug;N`6tYe)fMCh', "zVMJnۗ{aQ6*[j%׽r&j4(룔G}&a͟"EE-ܢ^#I7ws2 /MjnǑq8^! ^;d@9L< {FmL^(I,Ċ1 G0 B8KhT(|/gϟw?vC"~ox0V;D^Q*2VI9,X K'y׃~Wݒ"oaB+ 41,hY4//6xWWΌmf?:Nw4|z\Mu2ؼ|`ꤿ h0yf {Y ]dVҴ+5A'luOG-Aq`ȸ}|7vΕK1[m [o[w +!~7\?_Ja$0٠Ywuy;W\H2OEj^ #l&#[WPMx4m-tI=G+E:Q {([EfaGTjtrTߛ7F(͛hTW#nFDka ǶYѡ_E D(m Rj R) :#$Ƽ E* cg;7iՋir0?ݴ[9>❼-h]hBCoB^3g@_c`]oݘ1 O8HL &@›ݖo݅tbʾX&bgvEal?RJq7Plc'.j,n;pwv<9oҍKK0$L4Pz 6&φ8:N;U^1x~m^<7;ae}W<%bjc9wǑnM)0@/]>='dz-3C7w:mX|ӑ=퐑߹֢b k1wpr b̧k$`NlȻ˞3ecvG}`%e1xR5-8j5۸+ dfh]?VXZKe(YL:No7&-g <is3b%Ş/EG_G,āz-f{I 9mX`x,CUYX1Clz:Lz!wl'a-ӓ>$,^bݥEué-^lUUIc{5Slgi!T*œZ*՛VMpzkЯ®N7l rNe9{HuRKUu$$^ѳNg~4)ƑH.2렕h)){B+ ѝ"i<:ӁHlg4HCAytR”՚VhM>+B},w :f`q!sp [_BkXrIe]K3 ɹ(ś-B2p,-A^zm,yfdt9'ian{ֹ͒]eSlg|XdYM&5qL`Xr#꜆0,Imy{G_Xדb` ^5=tl 9:OxjZr_^Es}7{*@^{Je[' "25DZ&`idNƸ@J`feȎdVP/G^80='}KEqL8a)\\50ƺQ&&+ȐPJ? Td<*p O2s#{ɧ Z5-ܲzq{f/hNcB1Z Pgkɽݴ 0M ӑx( zf&tM|t" ð'-l *:T[#ͫaa[c<R]u~]"#b7BlPnR,O8eOܒ4(oNТ|@9@ SiUbk+gY~kr/:oYiZɻ# eK Dz~Yb hξPHǠ[.[/Q5 Ζ9ʗta2^8xj$K4$+gk EyXV*Բތ]*Z;/^`FOiB-2!J_rW l_ܗ?M5=;ÓA lWrq0ϒZhftr|y[_pBB( ;ΈcIKj;83QJ7E ׭ڝzr+>J'LZ>QRct%N.`x){up ϧl9N@oi?däIS!]?Sx|ǿ$=h _#6hY;2(g:̆(&Vgzf +}}I 7?2ն^bHmJklɷ_C>1.%<\߳iԋ4(:IGM3A[?[ib5Ag;m~%~tѺa#pN缳fzDq<sP)0q0Rk9lJj7G9J~L^7y 69I>B,8c\51>!?brM1z GF*~o0|9gQ! ;_ԤO A %3z]Bd(*}u .-LPdPx r~:G3xZom7u(`ໜ)^, >;1e7Mz;Xe\MHB +Vٴk^_b]+ز~ٛnwvN$d+ǡwg!N.ߥK `]# Ndž{5MnU>m5-xX^7mIm]TAJi]3G^St!ZEI猠"f9)<6hZծ]#5zZ;\BK 2UAgI f[peR%X. X.sSY0VJ6 +)H<%nܬ鹬aSZ\JI{ԴMeiAނɒ4 ɔ(cK['?Kk3f~VpZ'Dz׃3H'SGU~Ւ62[Hl8 #4 {^WhZ3&}"[lC.Iðۧ8vmխ]xv-kGݷegU+ZJ[([`#s'6J,I88ˌd H֜ L7(ꨗ~qó{j7oZ].5Ba(>A;^-62ByxB+`»9y#s0tv`Sy}ҲUs3scSqTG.2=V-L#(jɥUqW q{W" 5 H$mlo\aH%+}bgy%.`bgW<$6U+bF ; &F,жsNHDFNG1^>f?~M{Ch(0,^SRq5%e~iWw qsۋP 2I]H>) O0)sphd >+iܻr!n{F&[J55mܖ : K\|{CZ;iq|5Dи&-喳H7#^JGMNz#"F2SkM!/ WuKHq߭%/&\>mF D'~16oraPߐUVm7Ow=I's/f*Le{jj4ҿi-ֻłIJͭTַ_Txx]@K@P=+_! 0;eCD_91cΆ7lfC :@ ; AK 5bfLX4GJLI5dGARG6}ޢ͛,2LfWe0".c㈃Iu(׭[#ǽp??|-@/4{\ѷO_Vstiiaᷲ @rm9v} ]wUM!?'YW~UqJ6: 4WݱHf< ( n尵g^1 b V%n:<ΜFouPsM qK~U*IkA7fNp.w~N5\ȶ*ysYB! N F 7:$~:%,tZ,qa?]]hZ'n]V!*ʔrO, Lʒii@n 9Rïj,)dI{bz 6%e$VaeZ%+SG`ywK|%# b  "صUUMVaeXa?ؚ>>˘*[,B>NQ_"-0Ǔ?gJ\)L3>R:}Hf-kH7bca=0x{ASE!]hv3h k qv qF_c wHMoiSoRnN[qv2Ϩ yAvCz;IW:_lD>ߟ\[fa{f{Ib /T5FR#^~wj8b=kf*KԖX.òglr$|{ݮ:~펧.dB(7!>X`N>AI  > b2JYsV}Ш/u$Qa7mJ06H}_`,HU 01sLn 1Ö Sӟ1:-=ddOw6+*HAj"rb }v-# ٘}CEt( i]`+P$LWGyKWRJ2^ :Rtgp Tuʯk+z=\^Mn} n g!yɡ0RTCv.^8߽ qyRW.0PՆ~~4 NxU+Ž1š[_[.K0KB+덯f߸?e[U 9gǃl2i-,FO8=9F{hCrEϽ@h{0)H>@{XP5 gT28on@Z*.put(uQ fǽQ[!i$zwyK$6M̠_5[++ K6=Mho:ɦ6_w=.nϦ[AW P=)#Ls*CyAl$/N'yfz]g=̥'$>٫nW~y ?1Bwt] df Rf~rxQA](..+6(@-gNwCxa' )~=Bx5QŐ}Nܜhz7yhT;'+ УD0a8E I-ĭI|jP>&n3H8--I UTtSyc售R 5FL#LOj"W%lO=0fQ#m3p;]^0oznc{zob>*W8a|=q\{kߥl],d '&4 9hڃ׾CX 𨢮dA. "Ox!5wB|OF5śn4jbocV-ަ ȰJgD5<XL*~ej~;樥B)$ )ԐiK6r.?AZ `;M~cCMNa֍{?+%a&E=S?#%e&e˖NRNT%s™B|o?cĩ.0$coc}AM|9 |"\s$pJpK{0\R5^#8jK-t.r)3tX/#y4ʸS"8VOb@ hUZ޻Ÿ׿ZHX-c;tlnOy,*JM|~K*Ng6yfڪ*AA0'?[YPYcKݫSF ·vð}\kvWO-tr_~ki-~nۣGVvrwz;d]  fv 5-b [\Q *)tɜB)H0 sJl γ_ch19rz+*5piU.cxAtU$;ģ$%KB;`&'WEpW+nD+:d|&N/J(>γR)3!WdQoKt`ܨmPw зֲ0)n)\@bO2ţ:1>fU78GXҠ jq) PFzXhIp ueQOE-ky ]JN4O%D+f >kd)S3{E@Ϡ*up{J.M#,`XڕX"!,n$63icG㲟Xz~H$cȺ3CgZŬYaE:.I wei+sؾB O BZV>k~d)zD!S79Le̚W,c8KvP:RI,c+[!]J* +pEhqiQ̻B7[?pad%p<lWcힶyke\!̊ش]Hy:oT2F^㙧|uk^sh mKOV`!3a2?SRۯi:19tΖ'9RSq} :HG+rc< QCwO]zqǎ.3HvSP}B$WS.V31}4=@l|,9Ox>??c@_-_]t@w{ΰS/4 7h^q NP|p#@tMCI;0LWpmNNySQ1~΋ l?7}w ?x>X!GaZGXW *SlllSYX޳zud' Z]UxE~:ˢj@N>PsZ| (ݴZIxUf jƝ- Tj ~f!rՍg2 .s5,:A=[5-8 02xzW+`?wNxNQhN2*o1%)+݁IrbmMo q8r͜( mOw1*Ѓ[O)ڋǟhWբCuo@&/oک'o6Z[p:P2Wp-H^]sx9V PCC{ WW' 0yWGJض46ͽ>+/4cX8߾z늓cr1NhrʺA,ҟL(3~<]a!Pv/Ksc ])494|b~LA?%g rL|~MG*ne'\=in ZYLyI`E\PѠ7 Vn\ PEbWxQ$ΧgUg|؛E +e w r(| ZUM?i-ݠEof%X9b]f8% :nɇJk|͡{㿂f>km]VJb?bVoe4q7= hJxX3K!z!b$cDqY\[D- ]ɨϐRLO%%q/1Wr2rGbhЖ]׎`+QS`je1un`?u~P J-x]3aЀ 2C8Q[̉u\F\apG&_8[!M=k)$7 `;]C5nƿ򺺀2GW!P`>?fyLclԓ7yøHAW=^{T+a 0y@{=6LAHLN4j7n)ձ‰}?z'n]x'rW2I΅ pO#+$?~+y/4e--^u&Xnh*2%2IOKQG)Wmi6 o/u[ƼaDջLSS Px@F HSX5BA$mN8EE[RelͰeRAͅ+FM:㙨H>kPL'ܱ_mt.*7Yg.߲=F0/] ĶRCnVqe?gK7L)iYġ2.gVǘZ]''ld'<9o߀1K<]6IWb?+5: Pz0t n٧ [VtekYSXU;h[+gdE@]v^|@|d?I4zXKg_dXF:zYc 4?G, RTͬwMl 뱓d+(ڢ@YGoc/sa߾3a=ư˾ĸ,>$2v)3];.`ߢiz[d(Wt4C 2+&̽1iPٖ CT+|WJ)sgn}Kn1ZG;hҍunD]z^d(Z+* 78$EiZK U2+ӿaiۖ ᪀j_gK=yd3N;B>7 \ByBI|Yy\}[Gsg׈L[Cc{, w[NUŖYxI71̒oV$ y$閄. %%aV$T];y>Az~)֏{E g*[QL7v}WBOr~l67k?|X`ic&`lXZ^Z4EA-j6WQ$=]VB`ˆD{Qdix3ٌ=_It2@]VM82jηhpFG`C[g7lccow'GT~tW{h٨NE k }7Aa_10| X]Ru A?\jB:!]C#G|7CHa7-zg`>/ ڸQ Ajԣt|2 (0q1Կ{gPCXk3 7I8v; 2߅]CArZbw&z_́,pWfYl'wxk$oNtY LwлS NwU*GΘ^.3 oS߰-GF1O:6GyVepg/b;JT5}xXk6qbx%-Szk4g }3񫭇RqN%r^؝ Aj\P (ܵ֟6qsN E_]_'OyI`鐼d^w ]!-n+hEpE33x@֥0Y0HxF@]|BYJNP<EZfy{obۈIdBb*${P[_Y|aI tkImq[vb /a*wG!ўbJ0xbTY˵GXlY^:0˦%YLc+Vʋ?AlVy : 5YZp'IמVUu@ջ@taӭi+Uꃮ⁉s'44/x'Ǽ#JHWWL~6,w+ E|gYC%EŚ.H(nIJx(2N.d*0g|4ķӛdk8#Xq }J vLog#ע]:5|& FilT^ςmeM'ZJr{"Z6+XxeC`ߜ]w27'T0-jcLY o n!Ļk7fɈW7-֬Aa MA0<ۚ :G]vڨJ8|oOL!5jXKFܥ~oi'tIa钺'GslOɨ?҉5` %ő,p#%CoN4mǴP8?(T֠S`Amz&J,K=ܑZ铵ܦL,y]A @x^izgsr J_ܗkDdz2+.Wy٤|0$o:x(eOgfSO?XݫFn”Q{DGZk3:+/>qୣ }=gZju^AG5ލn_yo>>Bnyჭ=| >}>[Mwa?6*nʇ&/qH"6WG2+L*@Cr?\T~I}z>3`> 4!>lz*dNY=&ၧ|D-y =_e|O M> V![٤M>T=Kz~}nxnk|mSy}|Fz?ӳgTyZZ? Ihoڛ&d=I$j> |hPTA<أ=_}ǹMzsk[EϿK_ȩ"-FW*Ģ$յ#/Ok$I{Oyu/bwu}:QwS _z^gW/TxsZʭu Q5jyEkkq |Hχ[:/uD\X}={Ȟ*'K?GN0C-C&={lq/ܢ­Mz~I/=7 8ϛ [qIk||2--?n-rmΟ[F[W%}|I虏s/ SA7=nz*#"`-"[ʇMkE|W Suή "Gj @gjyZ$IhouQKψ67ο~!q]=U4/i-NZ?!g Ķ6nho~c+=[6=*8FϞ7^RW-zާg8oSK>UF-B^8ʇ!u=}$&ɴMiIjV gĸ[yyӣ(H-on=&Gs/r|H;g|xD2? ߬x*f8HeUs`7vddߝiXHM/SLDl"e-z2׍Y{tz`ck:3zzQ/h4Z:PzB^=UA8MraL@dknk]VdOf /Vk>8N?ܷkCR͸ pCc3',?ֆh5` HtvCmEr>:ZϑbY/e#)˝+)Lr~e|H~% 5D S^r /d> =4.9]Vg(UFιP.q`_~ /!@] #JP: SBf]Zʟyxj;cjOfc/ 3 nM>m\(NG!k愺5naZB5bý= zqԶuU!=dtphBB಩ɴNCD%xﱻ캨bww2+;:h󋹹_ *j! Ih1>N J& pѺnhjG'o =֒;eDu{n<~7F/UQ2kJ#x]mN?<cwWŝad_K5{J{] ).n˫*Ԕ [T F QshAzwHlTvaJ0efND>be7X4< ɘC ?֣fK6m_New YV|M4 7v}"-BRD]l ߛ^2 #1+{f(Ť r5Mbkh ;rE9UYĨqdVZ_ ;fImYJNcyF 'X̋&QGgSJSYc ,nWW (VҘu;f5)ۇzmZ~絙9bIU1X_K~5O]OxAeT@iƤ/my CCwGdv*zҜDᱥJg370 }99u~|'I<1Wpp:'t(@BsNW1fun|./SmS:᫬0q,B'wo+4c&PS/1zpt6Oo7k%T b-vq `ٷA0G9: 9ZEa,zDܐikO1%yb@S&+F'.?pȐ4)|!bM[m B$taiX0zV?1X(oez`¶{8>wG-r[OfGͧ֌d }"UVYnkOaal:`6vՊڃՔ<|̀*:VS%ǗCJ9iomkShΎL(Ì~釱6$f D{<VNW<>vtHUV0 ~RX3HkRP0MjXcޞA<'86FS-YȔdUa p>YG[sô#\0b ǃ'lAڏ?% ٛ.i.$EY:5=g2<1ϔ'R2ga=%Wq|gɂ%YaAOΕ)Fr6dbcF8HtvC5V 0m6܉'3AR+]N1UA3@i: sB̄ײַK#X}&ۘrCJ\|4NJŤCWC*2 2ϱh'F"vHX^cѺ"W]jL}VD8Q{uU=*qLa4KgGq&&ʫ)qoձ8A:8Ny°\1_@:,$r4lEQ.nKBWxgӄ5)fD*k=LGz:sUYVlPp"Ya8K^e#1r]Gk:eq0ozoؓ-Łǎ7]ᾊ(Kz\UAd+l"Q[dRGB_`S#[Fi2XHVNY㢔VWnW3kuuIO7&F$O' Y%z^QO~-8ynw[?ߝ}sP {}e+Uٚť^&}_C'Ÿ?:Y~<.|YNnY|u9Pr FGЪ x†kRѫjmYz*%?d{(E4Kmkjs8#`n64 ^9>Pe,ױҝ2.ޥOinw\& 6:Qv40Q(2h;=DDN\/t:RWm!(ckll,9}c"i7C-2ɴ.3ɊSl=P7H㙍~w^KȌyY8(rN)xXOL#QD;45żwᰆgw\ƃQ6@hd|?ŏn2jԛ6֚MaJe,D:!J[O#__}5._Rzf)XM,SX]q9&۫GBDX"v"O_qvϪU?qĽ[ru yE̠џZH'{񷹭Qݔ6JC?CӮG5hQmwҟt:'7WgkcN i,7ϨLk`fsShN%%{gyfa{7I<F@PSi|et-KU,D46Ta#؈nh|<v_e5#2MGqm?.oPz{;^5>$%ӲMlnzA 6)=pN@ ?RFb2?%h18=1)Q.FV@ iˊcm)ON̟RNmz5f#8hb!c0SxV0KCdؙϓxJ3HD ^N#8zZms8rA7n;ȳA@z(RyH$=gd|9^MPO]O^Zӊ 7ZwWoUVMgB#љBN7ŷ_;0$u=X|7@8aiWm5?G·ZхI^/^RVGo HzN`"PgYM9x2ݳ%O(K^n߯]],5H2;Ҳͽ-=1DX%a!+]f I :Ec6KY:  MٛN79 hd>";pR6a[hIA0e a¥favujA(߇(:FLz80u0btQX٣t.Kc6gjA~*i@W>e휚m6yRGǥx&L@ IeNq(MDx)sY`ek(=BO> :M5EBMBn>XSFeVo3Tyy/PhVA&ZmGs~ 7Z[wlFsq<{Q܂ظ#Ike"ws)J.G̺1&8j=kO̶ڑjI_IE*WʞMq swп[UL9N\4nn\G*u!,arrեKSUݺ.Q3%!|#.R]r^(q2z+燣׿ͳ |X2f}=V{:d>K|w0̮=H^QU$u{;Wts~[12(y2Q5N&x;1ƕfHPWHkeH Όq|s(ZcUaް?ֹ֮ nWkʤ xpXL=#MK4K{NCɟt[8/NSp6ovP` M]6k,T 뮟Pg;Uj%FnbGHrW29 @>|e gةzz=m0SN5ƨ;ݷ' 4mΟRs8&vuG."KN4lp42i^cؖxRkj95YlAbg5_p'|5B+%7v^"EN#$r,`|)$2d[Fs爳ŽOst[?' 1]0kQf7vgԿ:sOl,KĽZH6_qսaB@#k f(y/`reơ|,f,1EaKӏ 2>d9$m`jlf`%!)=B4v =^'8n=尧b3FLG^.ٱWCASaeq#䏃z-yZ·Tpg @'iQ)jO wBmjp[d (jfBߩbt0,g'óh|&uZ{P86&?zHf@8J}F g, 4M{saN3s' HkS|+n3N $:S@U0ći5^#aFaNv` tz*?d\+{0i`f ʨRc)TW6-ך48LmcuIC݀dvO\!8~;늞@W.i.H{*S _{|G_<-֞X{QS:܀v U(|ȅJœxM/WGI;wB϶'Qb0Z8] XebJ?+{S|9Et;]`CY꾨e~,@kn2+@lc]RԵ$P ѺbbZK!aQ'b&sH2]kl+4jU5ݡb5;޹VX`xEח 50a(+UZ9Vg]Z ݼIY AI-"[!dx[3GF)U1"-L դ@} CqpEai͓HI!OT!tZg]ͥE}y ^#IXun`BhcvP#H# F]\9/;v_G/ HY"G? !JB^[ͪ:$Xnր$od]ڍuE(UDKH9'k򌆟X0NFGot>qU뢒TwYySЅs,ֲn]=D5u&FR :Z^7N3`3hgH"_*50p^*'痼@8hiݸdZQ»Ѳ/tyD0ɌMT X"io]3ş#{ doNB~ b K&np(nkce FZ@jUh~Ԍ9_UO& BV6םPWR/C*g]rԂeHyɝd^MvD m}Ե`6Z,kʅ^t\C5 xcj%ܘGr>&1DقToe, " -%', uQo0^ΛR]1`Nt!5!uv\r =ȗc`lF4}5WI=޿D&{~g%:{jp/ /b~~[lٔ{E{wC7U(XI:-OM7ڑ3Uwۑ{Z6=8m)BQ:2`Z  ]6:ػ{!9rnjT7!bhҒE`}==Y tG0v ?'ʊ@3PG+@KΫ Ծ'Bxz/υLhUO=zܟ^8d!g@4Ǐm}HFj%ÈN#VEtha-8j\J&2h9#^86C,2LZg4՘7f"lnY i!K_]56ƢB [f] Ӓ5ӭ}WKjtQ+SB6Kp)˥2j(:b?buW m~]㿭n57לo͵>;?8;Kwa㯐!?l?l N_K?D2{3}L 7ww 50pWMg(?q6~4#f|Ué2pddrq Ud4 ]\ׯN1^vJ?j^HN;nOlaf=>ϜPE=TL\qJ' fnzl9f;B8E`S,bnE-c Bn֬:.;r](!5.;עe#r"#KOR'2;-J䲉H),["HNd 1H ɪB0FJED2tNY>FK7M$W!菽Eh.20.brm,n^Zi,@v-ًR10b^vRfttƒ;!IhDjΗw^֛0 vhq9DY:\2x-V'|Jyd βkQ kҾ0.k&)7@cjljɭtgv 0ƚ h{W8'1_8󡤞Q&+Nx2${8dژ\)P |xڭA>^q+@*^>ocF;ݯv?מDc:~uC7l]؊p)4ό5Y)qk07Kny*2X81 bCS&CǰK5XuJ8Z/j#8c.k>Nn-ͶrCݹ9 .jxħtKZaZa>tr3eYTݯEg+-6Q2N9t9囮@pbXZ^Z^%x&z>zW+F ~>CdNϧqe욭nAHp<.SV Bh^ǰӫLx=ۯx1F@h28gXB#@Rf m /Av])yR`!lxIz:d!{NX.@d4yGuF{o{oNtOKہCg7 qXǯO9<9ؐEޟj}ޞ6$>"K3W`q3p]^:^b>'7 ! w=Ng c}.Ʒzd#6'3V8JQ 4A{j\]i6O,{lʼQ}efI&ʵo*ͽ!3E5//<ߏ}^gwHr R tMa8p2aGb)xvs;שdL]\d k 7ݺVk2M/{_޾y7MM.޾?ewS0nI{Z[_'뉭#F#W|zTΫÿ겗mIoR15*N5 +u: 'pV܍j[&|*S4vYoIUJ|aᇫ11ۈ#Nc64g>1X+lf 5~yRa7q{ /WVV:t˺ ꬞Sg$X3G`1PKƶD' <Ɛ+l4H*d4^~X*f^:"YҨ$cl]'Cb( ӏ̠}-I0ZW'oj|ꊩ]Laq V0C8rD,V9ogi zZkMU#s%뼏U3PFZqpgdalF)(l3}^ts nW[[vͭ,2ɂj,)B9 Í;>_hon}$ ~Vׯx|]]ÙqߊG9ߞe`ZzzïYNOu|1Xy2c{ NBXݲ쿭ڏ:6.imX}4pw؋MRspڅ^8w;IO?(f'Q:MEVd<#2#QPw[Ja-.,^Un+* iAWKNJx0f't & [DoS&B$\n>v[5{No4w"sϷUA{: 0c2R[iɚr]xory:"!I1N@ :blr5SA/3%b<{{Wz\@G\V%B֚ zO4?M2E*;*Q^JCXwV`f% #מk$xzT4.i<@%3FNSuidd1pN1- TzP-& i?aTpkl37aψifo-VeIS hyv[6 Mo#ղnBhgguxЌe7:G4LӏYs?72x2AKBfl9xwٸg$_FaԲ|6T,P L.Xr^.  )* 7o;1Bdfb x&ɱA"P@}PߨGDFVuOI?/ѝY-o^C L6Jxr ef5.`@D'([fdqha3OG\̍hBKSCʸf8,6@[ ?RkOޟ#XDvU7'YK8}O}M0l[)_eW9{szѨ{;~aXLklpSAvJ^w1gXe:@Ysp@n4lYqO/2w^TvV}=0)KxZ:H}VNՆ`fT1BԾȷ=<,c iS$XeܳZgu͸ͻ' g܇ۤ xY?AG eu]Ív^m>P Vˣ'FjSFG:D.18PsͥbtiN`k9;J I¢>|wڝf VfLZMR͈t׊PH@a$$V^>8b r Vo/ˁ-_?騾f`{|hE4v=4  kh8|un*+`:/ͦu:ܳŗTnA*xm5/\P}-9,Pq)?`8X{*A)]4Ss-΃u=O y5\?P84 &+CtF:lwɈWa`hfqLCҖ#p '̽pƀ20=|oѻ8 zr@hA| +9h0|oA|1*1cCumkЬQ8@$p4hibEx ΩLNA)&oa+{y!T%ٵs,]dU>el{HU-kMTD`I@E(cZ[9l^ X.NMOsOL<1lAjl?+aXj+(κW O{+qbqtaf89~ >"@F-Vοl; >?^&lבNƽ\t6h4{.ɓVd*5W=&lWWR/Yn vNFn ay9vq->xOa#+bzNO &uN=0,E *O+g {>l["1]baBKf~@.A:6Q'pBL9[YA@*;a+^sG ]8Gk&m?tmR şgFYfQrZHZ)~cJ`a)6&8YJTLTlrCuGmqy :vO 'BەZ-=K%Q4h%3Gp(1!{cE0wd|~W5iܜ]-"20$FOA mBg}~[8 ؆>~ꬕNձS}9,/zt SΑ 4.wkL+4b8byhYn>`Zμ̈́Gn+в]6$Q(zCoBܚ\%_z=>R&\rW4dUx8m[Xevxyy)TJ9a2rA&RT_DUOvAK@Sɻ(ڊ<]6ݗfLD_p삪\š# J3xkL{F$GqQ; :Ln#In^˗e0&ԸBW@ 1a<4Vb2cm<$ % 0#$+ |6ف7Nӛ'x d GPo@y10>`^4j|4/"=.80]0VbddAdW_xfڡCOac]O5o";y5ϗxjv9Ml\$ g.@RQ<,KS8di\ԋoڰ`Cff"\pvf e[48ZEӧe4ӓx(㮊A<_C<\,}.[,3{cȺpv^ܳ:n]@UbY~q6RLl}{4[:. @ݒA?qߏ=7 'cmb6GˊT #"?ExGoR|M ̘I< _fLNyō љ*]KE Ozw򦞲(j|OA)y_nGK9qysQw |Dw(zKIyO!ePn}/٦lN 8oĹ T+Ld^Vt]MMӿizjžAudUo!݃'Ʃby.1h/pALՙ&!%M]zu!PdzGt'/MUlޮbNZi||&a~]ԝj+Uu=Xb*` gٽu, j5Qlbs4cdt?Z "x3 F̩7!/႙S +%=F<>엘;=K41Pno eqCAef )2X108,]4 l2Ё%N½;XI)0$TKfuIgF \Dɐ|L!ed (Kư>"&Z#IbHByռ/~uTh7Ze(nIT8Tnjnj%ڰ7xP0ᦓެõL{jᶫkZ?]Č ^ueW%#v>Z/E'--HhA:pDDlHtGɶކo{#-i.o#"wADެF9*]34|nw7a31^duY_x[(qL'qTU>[$0K>H}*_~U{kvۥKs$H2c,s.T7KE9{/!aeB[[SW B2m rçc;TDfuB3⮖h8հz-7ԮұVuFx<;SM,pXIчbg0+˹͸ pZ-w`8~$)6^as&L jyrA` bA%W*;bWNY0@pAv|gc޿zN>XY&kh̩"t k8Vޝ`ѿSם)DAOGSTcu۰?_)ߏi>>9a5j XFZ'ǯߜ(z8xߢm#woߟ9,ʼy+rM{/ߞ+tŤ2> ʟ[[kk_qS(@8ոAܨ* ң*q?Xa܎)mc]9qBR{$qF2"!]FX/R_D$,F͓Ӄ6wh'/:Oaa6o6Oi0r_}=G׬1iU%.}1m=(}2cs}WhUË|n@$FA+ˮ<$ǫm˿ڻ6P?v Bx{N YzL1+.uэvL,$q.T3DSņOna=՘nvo,`مXܣ|tb8lwŭAkϱwhѺ7O#R ^&Xt _h4Wյ W쉕@PX^Ǎ^k)JveĄ N,|g%uP5H@@3uɬ K{5dUL$j`qN!WwKB: }@`}S=_oHT+Z kQ%ST`"y‘(oN- kQȤ6l%}9sqn82\rRS-Cl`xıW\GsJy(] bēw9Yk>qe⒬ߩ7K&uvR;T~=ȁctEF4VּbY_8Ir΋ Aq<}B/}u2FG:کV>+U$&\D͘:(Z%jr[\1Pm[HT __9}oϓO4𹞷'8,~Mf˭VM2e^Y%Ύg<$gS. ]-STF%mPb։d]B~@#8f=U .a %W_714,!}ZpCդJOl% yliv|%_$ nܝV bO lan4O)R4XS4bь9 u͙,oi5ia:&u&rCL&_c>vZvΘi&+w!=oߌ%!TĄJwS+x؎ݠ #c7`SUs5t!v~91aE5:_ ,׀ 5|KWyAM:&fF8ltydJ.KdZy8/fyY3k51%$ʶdDf@ M m,r7D8!{r}oBZR Ol]V [ 8YNFLi8L3tTfi+Myb*i>mG׏=/\^avU obt]:tdp_0 os#% 2:O<vRg&g_xge=-¡щDҐ%,I D3[^DP\7'?qdS#=l*,B;}ܯ&CK FkV3= Zo-zlXjMBQ[0. ˕a1jdOr2t t%u?9'I>uk ƢOݖ:B^B>4 > z$ޤN.u7N3/š HrqȖک]%`& wwC**_I}[{t3Zl ݪSޑ`B8 -t$)ΘoWnp ]gMbôFg0 #AHs0\iVs\e}\ ]k^{|gTO+"GV"M5y w2Y2ȣIN4C(]_DIԞOf=9\yL%GrN挢GsI粁ơ?iQ1n YL0L$nh*fZ\6ҏ\K!vB,6\cl[31hE*V٭2d,l-~iMȟ.`B $k3"hRrckޱ>ͮv+6b b;e5"+1d;fMjJֆAq#&S3<d(7>qt%C G9&լI`D<2м;zyqӘ9&ՓJ01a^wT3D:.I:qDO>ׅ*yJޙak.~Vݾqqe\'U4L7<8BYܭpE4MDfԯ܈7޴8{je8GIՕl&~ vLJ-l"nЩ, %kjɷG}zjW v3;_&mVr5)m( y w l -[PZ%7̍-I(/|[ĊLGb`*oD~"mir&xֻ6.imH4 ywNBzE]|A05򯹵]9'ur88,V~Dc2alOĥtCp)/& b|Z'M;~txuw!f0!2mzuTcK{#}7s1qjo~k{q} A+z=I]M0' m~5ePѓK fʁKn < @kXy욙ei85 /]i;a1Խ 6UĬQPŮu³Nk0Rv=YY45E]6˻ygb6[fDK9oQi >6uZó>眡?[ R̦. GK%/LqR_e-nD,M?C'܊VVYܞ b(ܪI]:&Qezf{ςdpibe qO&؈Ek1MLLJ>rD{#Q!soL\8}'/MR q,>i#Z&EQFdAG4c;H᦯48 ~!1K6S@MIR")ӫh[8>&SYrTfg`/uci=9 ?#R|2ߊ+ytΆkNOˉg^3»#Ȗ;kjx%(EسO/]):K&XVY62l9%ylEJT#Nm4sMB#4|2ɟ8}c ՅȐ*>2 Al|K-m֎R8&ٖT<>$M*IatI$K}f%r2ǟ%ᘿ9} Le3 )p! Xe*O&fG5TɵDZa4ɾ(5u8`&1آH$;> y Tj->ӐWo鷁?xR=%8I@TCpM&% JuY(ΜB#s9RjJx,OY MN?,KTAw{ 鉛ȶ,$w>#Ha/L K&s nڂJS<1=J Ls>q8yLY'&Sv4 aXiSiTwg9+W~m߽grjJ| Y->B`2:Z slqxI@wyd:'wxJ1PIJLܺАHQދ؛RyPu=oDnȹߓk'ZnM|s@7Ei>ATJk92ߪs),ߟs=ۿ=/e9wv97\bA^pSF_ e2Pg,(|ʊV+x]&'<}ō2 ʠ+iҨUfT-fl8?>XZ# Qְ!Dt MUl< Rs2\Jz_KRr5cjQtٮguS*C۴hVԮƒpxJ4z@hhxoLѾ &Lxy$N8BeQ^MEVT@#۞ZFe; qYU2-0EȾ*[mMei9f@;da{ʃm 7knV-FOh  5cڃYd Xi(\aqwp_0ӚL Q $7K$,1ea ϙBl)q }m+,(!*y1NS1M|+l)L&!AJ]r_-=PzdԺ\-Ց*SQBƳIGm2d8V#.Q$z]o`͹vnd)^ YS,n5}"V T/iUɝj0;Vd3eٸ]M'-RUeVTnvj7A2#hpF*2366}p?Sqz} lNW1`4s|=W45j|Sa̰'r){R&d߼|}Qw߾;&zMdչMы?B]Z+m*6:IHŲ [o~U) jlwa+rS& ҦKLr8-Y>7,F}ZR]1Se/Y0x÷DģdJ$HWoG9t+΍ys+bUq*8 }N~;\ @X>i˼`rmznj3,"Ш_ˈI}R'1$gz̔KQ"t#[l4joJqej(6*ʛ|ADGN)B޹?ea<%ir*6A $=L ަsS[\%+i6jg25 !]GTMsw(&~;>PoY38yb7Dr=ۧ?J{VDdozHr Q?)jL$[zIǔ1e=K]--M?a62w|oQFbX`w+A8uy`ϤBl]R) c%Ϗ|7dhҗ_|ũ=uڬ,Q!Z*%,V}Hq ҫlu'GH'بom<ecZR<{WF@n[ͭ]`OÏ% *fAKc}NPLT `}5_lUJb{G Ű<%hNՇ{f3ZDo#|7Ch+uHwedzǿ>cU@l61$8Wުxbبlҍჳr7y 쒘"e͆0."ÈbTܕVoأn PY] NXeQb h Q˛c)vR3m>R }( őF5:+?+$&>@N%9Das B-ihLu-xyiWOڱv_7Ypi9OP| Y3(E]9rA֊(@f =UӀw4mӀc,JkМ|xŗAL@N&ִYxpi|]Gn0m DVfndNuUu:46TM}4 ̝:5at bj,B>7 J4g^ Ķr)~%r:,b: N )l ?<$#ٹHϛ~#UTͣH_mM.>n/io&@P j39["TNmn[*dz<}ibBr[{+[6rҭ vJ;f8nrH$7X31*wQ)UybM+g !M;yz&;\f IZh}2DnZwGY?3ftŴiYڨȒa*q])Պ#as4ih oǮt2Rh488 +Ѣ!@(=oiXK©KsKxgb9OH'J}>>_y{崶 s0,,8״/ŲfffSe.{Qmh% }sZ O\aFe8A]{+/8:LH? @+w,-nV7 +KUo8%JvVܴVSmcG|Ĕ"eW^t  ɀ\wo;E4IR0.6mn\/5xS1-G7j:aY))\A]'Q/֗\H7 "mRy:076,RƂZ@Ј p9&s=w^\b摗exqCLT@7<:C,qcy7d?Y͠XRd6|7òc1O>mU;d=8TWɣ<*Γ4XNcrG[嘂ڸַ7+kX^GOn#j6hVwarUֽpu݃. (y4<*qA{3 Ɲ(qM.y:sC{%X&͏ ϒ$W/]խsx)`"?pT2BVe˲Yk}#Rn.sxP/o^sV4+z^?Jf\Qm3r},t=Nm- Jg%3$~Ȏ Rw wpFJDCf œ(xsj1]"zU\)i C63,b&KDқO`*#$׮dc2dcmXKM""hkZ bތ7`_[r>A(Ђ Фd.JhNTw6klVm9L$ƴ[.3%Kh67~KByrN/uʎ zzBj_}ESN]}Xuio>ې)(ӉB%u?Mzcf[AX7ZV'r$̐%l@[_"n=19 nmx_nad6d3{&Pa05}@e砬Puu4aC~X%v-;LD13X}GL%s.g4n_Mh1 1SxvƇ[-Z;A6 g()JL4]>nn@ńWKL -ލb/K, k!XYgjahYשּׂMGd0ƃTHrFmtxp`q)KG*,NҲ40ʴ'Z`0 xvpK#zPdjL*ߜVFƐ\éb[ZUk<(NIߐ)I7Y*yz|vKy5(̦(m@ 8CkidEԔz %}u1(}Kfi8tT}w~ TgPjWq 2AkīЪ!_]ՆA9KXW'މ^>@(Oiim*HqRgyp(4 u;+I&^r.M=X2Av-7b+%1752ϴeNd;7$91̫&lvY{T $b&&Q-.RB} vI)"T遞H͊Q0fOԡA=V`JX:BߪӮ^lU2D*&; BS=X:څPmztJ[[Yܢ <$I1iE,^W&Ƣ6 %2 b& XL(U1AZX60V^v_e YNd6Np:XFG8ENyRVwR;N؉*!Y-'4O)5Z3RWV^dT'qk*[7plW>6|f:)C'\1͋UJwrThu@x:;zDeZDͧGNW1!?OЯS67|jLhBg<#z{ .&ppl1{d=YYy{nE]ws_J*YbMb*yFkD8o3rrł`6uI6VeMPE,INrzm8vOQQ@ %ie %le le le lWV]LkMLMuHfFf oi﷙B z3&8 gb g}z*{! A)RUY}o{h\;;Rt3q0s?!)zC?YYA[7beB{)UҦ!+gQWLR*al 6;>sJ 3kb񞅮gŖ:OD0'J͓$H3p֛,ZmV&zFLe)l9yb~-S)n%%1ḆO\mZl؋KC2Xңpj{[ qeQKkUQZ+n%+J='=$jS\ Vn"|V_M-eg#7K2frD7 u/>dBOFNӹX3y6sR[/@d҆*P7 @!o:AJȽ*kSuctQ#WW;3\$݆,xٽA\qnS'7J)扞UMCV+5V:yi<4$T|[4>pU^˯~<8o|A}or/o;7c /΂i Ng;UU0f[?DmÏ0G76GQL_/?37L{d٫C vȟN.I8 ?PݬnTQpZڨ֚ W9dzQr6`lm77|>{h=}tƳuǿ\2?;>qYh Džh4Nr+*fbQZz' ?[Jq=܋aO!A(..yVJRcc)xOwٛ&W2|ixzՉқ"XkPFq S^t1֚KKoA`1UΦѻJ)rRD uqbppJ'ox >(pQx#YTƑl,MY +72RgCʯn:uZ'v2:N[w4S0Ŷ~*hni23|*\/нqP9I6B0W'V. S"a2 ZDrE4ضeھӰM i(xc[:q /& D>5Z[HB%Kq4,unTΙ8Iܳ͸*_;lp+bTj4xj W\`[ 1!X<Ռ/xi^{Ⲵ'N.p˦+iTc$si=kJH֢p=m.-PGbr(E䣁9WɾD d捑1y-|guaao(7eJf1/MYpkaћZ@VeB #Ho zd׵0zt5NsZ&Ee`CբO2$\'0Eg2yMnXř(o߁OXjyq>q4-'b[Y ^?}2 'ծk>[<8ʝk+jIhN|,S+7警Hyr%fAL I? Oz4FZg0T4`ԩA7 $Nbfr/_֞|[Y*&yRYHLɹuLDu./*\Gs<= ުY L-zڴi2~&6$sfCkkz\qCS@^ Fs3֢ת?瑌qП' )>Bp͇UڋzZoVa]2a MjvtPBX#㺄WngQҩQgBDk~ÒY?5K"+7ϚSYg@fX͞,.5M~C 0|օ^D7ێBD$ Jhw[@erG|.f@qwT؇3x;PBj9p0Iȹ|2 S N5r4rkw4̹/Lʌ^nBbE#jQ|B{8 $'螎 wǹ[IJYeG*vr\}thʲʻfTGØˁp"eKà89sbtGױ]vmٓTqkU;zx:=GF;w7JεALIr + ͸6:Mgԡj@v BsG#?u|G͍T-#(MVd;'GC慅!+c)F[mO__Ҿ:& ]B5^dh,y>CsjyҡF0D.#qrj% PynC-Ng*3\3{CT,b 0_ jJ()|+T!]`_H_s+ӪUTy|lYsj}h\>ж O?D#v ;nGT x91l8w%Vn űN.eJؔݪr C+%:xrN(|c:?C]VJlRb;,4 <[;38 ?(+u0xYEͿ oh0_鞦ybfiW>1O˛f}}!Xh wI*׉U ]G2' _`F.U(d8ٟ?6Q|z,̡fnh#>ʉEͩkrmiΛp:Up\+X }BD9dCJku۽5J^<8 _@H E~d62@Rx:CW馞䒚z$2TuOjY6RD ^;fL;gH'$F⌖eH@ަdPswM&8HqbcȢ4ЦZ%Tdi\!+貛[b-)J] 2,6O`M4lAp+s 3n&W`& ˈ|&Z;,L 06KlNFx9q$gmiV#(OPvw1iFٺY &/ Im-AcҤ^?lXdehe jvDCpL>[_w5Ўq1'41,QͲɝ!4 B2c=BK*ބ,<+ar+a+$,lb;SV|snA^9Lr'bpy{q`'ҭ^ ܖ|Qt15]&yv`M(S7kk" T֋tYtsBVdT[dy~ K>\jg촮(a6!vt\$<@k53h_iZMB ͅN\Wsf3W/.f"63kJom(^=mu,3^n̈}הzXK KC|J@@&L""̭ek ^*L!#C] Xr(+V2)a Ε.m`xNI "6^0!a9&TNT*0;* mєx8Yuen3 ;EW!H CBr? 0_z6b ˬLK4qpq0f>&m`5\=-Q> -q!+;kpL|,|0*>H*`akġjZh,Vkx!҆8%QI]@Y<3\)ei Dd/UYH2;E0Y= a!z8$z!*G/h)XLvQBxjѠƲZ[Qm)Iv}vO Tlj6X`NH%`@ %ݶM"bZ1v[rzH6ykg] h q0M`ZbGk%.b>04V6I{7+cm}WɆ tXRs۵[Y{d9{S u2c )KPk)feK✔G ,hEx7dKP$$Ȫ:d1杴dj\$fnj~ sȪ竞9&1tRx=61o9}pe|픽3Ȟw:~]q'u9!/o{rHAZKZo$pBC^x2q<+~tQ?ôt(j??:^xTMݧS & pp,hiB` H*$=ni8 ۴I.?ccHg+O+S6q;!+#q83V<2{>wLB3`m="jBpq9>myxZARZ_cu/ e4w 8I C87o+rowqԇ(kςoH%TD ˖]Nޓ?4a|bQD%)3Ǒ#m?~"_ >#Vm7:pc?`iX>S̈́5s3a[8 $*u'v$©#6~>c6:nJzUf\sM7!DᖒhM"OOiִ+7*Ti>jg=h.]p:X1p"BYZY#ՊHKuk7y B"}^,P,4Nn 3gR t} k6bS|Wd-+di-[L6nk&϶: Oӭ(9OC@ aಎe Nri+0PW"|*  %oȉD yZ6Et? p10*{G4>j1sH~~)ͧPVi'V\ZܭHoIUrnQOd^kŵ,3uE͹^D{h*Jձ{4t<2|JAAlv֕Ftªeb]^gb)fV~LUi ٰd_ʥ5Nglp겑C[қHk ra5f8s)N͗ 2W^-0zMNuoc7*Ėuo`* ׯatf6 "yt9 A6;vQ'?Ugs) ]XBaIL٣H y3}R =ݏC!LyHe-F YF }4U Aۺ$r͌*A@DwFFzp$wbZB=Bhsvoq cäyձ+ He|!1i<OHTU:F**˱8]kLKn$ac X?j1+Jz@(]xxIGMP*n|0F0RBqٙ=?X} !$Ӑt{7 _Щ d:r ޻殛 MAl2ٟAԵXʕRb|F3Wzy vl 4Somohk'Y^8V3Wds䡶R1E>/Jō8HC&/1gꘗ6yT*^^1>UڵPPj& "~@cb)X.?4ʂYN"@wS t]U\af@W43QYm5!NV+c |FLnjqFDi,n\^uƽ{kXb*%A/k3n-%nIv41TJ*-"8q׫05HSpF D ]:ݧw . Q ;c:Htg`'ֻ28%Ugv1J\5&qsi6ח$]4w b-#۰!ZTfgɮ7.[q}9.I !Ik|JP}ZBhe%PrTv,:.ZDhMu],r_AЏڝL|7! ;odVx&ZP,M8Uݸ*c [㦠)M\]~HrBZm,Ie,1p_. a! MFe0]0kok}t2ig+='sLf_zF=#UOAǘc?wu `M~4=GJmb{`Dmw yZ2NU.Bx)1,Qqw\2jܤN9 L;^bUaR#0*vAJn;AXGQAtaJQ=0oƑXx#e~La }YHx2La<g".>Wbo$%jZU,k":ͭGE=8FktʰD8uqqy74iD#iLV417zqx1z0RuxpaB*CFFա9+M\ ]sW.qDNL<6SB7:?v 1fd ; ҳ@ЕB }ʔinYn8SȌBEgA RR,U~# :Fdʼn(kܶx`nM+'")0QUwQkJp*Q >;H^״gѧ\DÄe{|gC~3BaG5n튞v!O=v?c1#Ca##C"L`P|MSHU+PIx'?wYTVg`Xߑ_8kS<>&xj6$zO@ 4g9vS7waS}J%10LrhD ҕ M8k L3ԕf$T? FS[u"?4sI/2Y%~J0# EkAg3ZC,BB[!@OG:# )?R$w:fʹit))JJUpoOଊeDFQeWVMxރ b $U *.$H3h%<^U)]>h }kihGnz^a'gOߺ'݅am4ۺ}eТ~≩,/IٟG?P:kqkN:~$ͥ>CtՒfNJe*b\01.wu3\5@>0騩vñ8n '}tMBl#M\#6Ǔr|ۀojSwbx<d6m%qz_uUf'M 0'` rg_N}e$9XZ-Њ`h7ﮉ>'>/z_!#6$?m#3>N:Wp-q}[5op/"`j lH8зCRW8gCҟaEEbnŏ$*mbʓ4 KS`ۑ/Ґ JLe/DlQpx 9z}gKyZ[~LTЦ:D{A6?^nHtsaiAڂS 4IZLe Zٜ{=7uUҽkbV?$SQħjiIR$ܺoaqĭ2‹1&m7j%צټ]Cm<# צhr_ OښaOan0Dټ‚/ ']?ٕR-44E_ٰw$u/wTO6L: [qSgDGmW-W iηְ?Zt'; & gGJ?: htڢ*@zi^n-Ak|GhM{ВmX 4D[) N+>{m'MA=I+NHmNM@s3fkFZ:%ESѾh@TǴaF=\Hf#lD˦jD:6ȿfZSa:eRۜ2ie.i洛a2ʯ3ZG vxކŅ&^띔 4ER=ן=J>~!h\;Ccx{>M߼J:u>iϠAeP\Ϧ J)?a Jᰁ84@ʊoABߓOh3XuV547Il!3s&80h6gt̕"ZF\Icmii%׊3ѫVlawDo׌mk(gb+6i;`Fwu0 KSE'Y*Dh-̬ɩ^"=}loHsd(%g,ϖ)fC ]_Qԕ.@6<34,)۲4Mvg)kBUoc;tUe[r,"6]o)e/Lbm4&;ņ=& bgCie qB-7#s7-6s᡺a ~oIʝw.:sQ)*T@S`ATVE:vM#  ׌w\5\նߍBBVs P ݌olj ݈mN>l8Mgtmgy:|o1pN3 8*@&P?XOc Ҭ5!uogmm PMv^Ie\7`tF,q0A)ucìuX`ԂT߁emѕW. ]Uqjxgs !0:yjHIo/5 _C69H y~r s)bI~gs6 Tzo[ueY{]\Y|:8ٺo.G5HD`FA#hH5g)j(u><5L ,| "¤,N 0A܃mcjAFiHL$Re jӈ-\e(vTBjt4Fkڪ; v4<΋qe6rNjMjg1t׳gY 2033gw-{i4J0Jr9+ݞ&]YR59>ѥTaBYixnWGng(?8zz%}4zd=htTIŅ?r +7*ԍꎳfxMYaͰkxYnCPM_\Z!IK X{.:3eiB (4WFV!Ⱥ;yC[&aKHs`* vJ*ePS1d#LE{xt#l|})%Lcسl3E2+AETe ĞUƒ2#UklAV,+tskBڹ+HcФ1~s ?gXKeڴoll񿶛_3&z'* 1YBedTRAw.G 160Azyu$Ca;}bBO.';၀)< `\_f<gD"ݫ+"ڴ sp7\6pWRlb[ Tbd8|ꫯbP}ӁL=22Ibov']VԉTyDkZ%c;mgޖH<8֓MSs6Z#,&WUK+Y_^U#_WفݯѵcwE'n>fO(X-1\00> e!LK7 / ;YNQt۴+H,OrD$6"҂YTIo14p+}Hr#I!L2C9ɨǘT& !ΣݚmE Ѭo_w6Yqgs2[z`h:J+z!v 8kWP9,:Uw0 ګ&nֻ&&~J%Z!M!A/]έK=G?AËDŽUji1MF>iXq\8(h c@5NF\ hy Mu ^1G}զNoBzUmS*p&`6X#Uj6nĉuC|jy@h KonhxqW߰S$'b+}>S!-ɸmbj:\sZRɧflWȧB9\TcȺ=AjR20OL[R-ek P=+SjRӠ?]ʊ ClG?_A7hvl͜fAI}w8쎥iEe't&Nf}?.-6;2!ݎo?|)Zv2{q$( BP}D9Gb'?ciJYT>T&hm~6gk.5ilrFy>M˸|sOmÉdMGRKZS0} 5Sh-ֳ>U->GR@$-܈pq|(e}˼> U> 0VR˜Δǰu/V `]#8Gpv/tTSﳋp<γ=`ϚR]Eɲ4'|40Ib)&ɦpVXۂgxZR9a87h&D y@ߦ1̠'%s8XQ5=O*ӂ"<ϬCHRK %8p0 ^I@<;x$5\UJx$3W]2T#G%)N8 +NR.T{2!$KθSǭjg6(C2npo/6-|IxnJ۪(|w&mneI&73-<EuB+fܬj-m ڵik][{dž \obGXI ĄTĝ:!?, RT7ebē4cO3Sp .VLWjJ]=FKg'}'yfodNE%/ޘN<Ļ)XZdL$-<8NKJc}YmzSGGWR-KWH- K@TRqV@ǮM</W1 ˯R|j@\G$|gaRx|ӧ=on;!E\$Ku%SRh|y>4LECb 9SLHtںLޯ_`YkڱDf 'ؤ L91SsYR ͖`cO@Fd%M6A!#.zr^u^;4:HKRj(6bFcWE"辅jbd^MjҬW%B(JWX>,e֍:ЯܤZmoQyTѤCmܨʵ5B%?vc>v+>&]hR0Wޛ#.ωbAkyd7O8ZV7zQ{"_ ]}bhe yޚs}5~.(+Qx:PUu/EPZ-k߲#jD*ŒpQ$$8+XWęF)Ixi3xO:VƴبF\Rr+rGҺN. K lss2@e%/㺀nX|LgC2%N@QJhI6J )%sXȪ"MgȋiBSt68P??<ȧ6kWLÅ$ke ;9>6 ZcGiy]^e%WtN; jCgXMm_![jNR @ EMj;獿! W;FIQ&1LӌYXH8!EHlF(%4= .V83> 3}]6x5C.6W!R6d?JF ᳥~χf8m tlD"v90 ʙFgUэj3͌;fp'oi`!i:)T &1hcU`TJmb ®=aԜp8sqv t6kxX'{5?6eDG߸D#}ۤ#"J\5 %A#D"IWe,k l9X.bt^RKG0LH"Бv^MWL>%d՗ ?3^W# Vaq"UyZy$WK)O:ز `?f 6 f^q0@Zc(.L][p@! %4iԬfK?bXf*yIyq#iG{[?Uţa8Lo'aSePi^0TRu J+<Γs:*ݪ4/zʟy5Nʷj~}a^ : EO<OQq ?Ebr٧.#t1pU_ s `cx "0_h` cd Q\¾ A6e$i,3#Py[n|f(:"8X1b@UF`Y"* B*B/Q@p&kS.=4%-`x1GB(^Vl Hu2m7`lƈYm {D 7 3zpbd`[nS (PT+fGЅ%-Pܖ*,KkQaRD(ajƪwF{,bb-K̬3_r?W/=uX] wbO{ѧ ѫlMv3 ëY2h[3fexg eGs _S՚H%{FMR#k>C:|F` M0R2E mժ$B_lO|@C)EW4_G'5=5OrCR#$U9c еq0 &>d|:oBhCI]+,ŵBOWT> ;:j45aAȝE+4Q mΠ+(,͎Ouȥp)C/iduPr25CAШa$cw15%$躀 -eguWW, ,j+5F5fZ@7iHݧ;9+UmGhj/I|}W)C9wGeբy~ms22S{Y~W~г(|ɪh>i&Ƙ8ÆZ}BE`ˠ u PA/v³XXZL?̿> t<91A~jf\ %OgJ%=Uޖw=+H4czREO/ܿERxpdgg ժCEp 0bK l0>3%+j(1֏9^_H~$/(Sz.)dV,orQ>PQt$k_!Gò^8Ԡbq*q}z+w#jw* _z" OR?ba ݅k[ $@V"i?g_44+40·?áëWo^C  C- LV <"(ړ!la[) 72cop 7uWF詸JRXwx75;;nozk3# s~W2[9-0b)A2;b6"vW\7$?e0;}A7Kc )Bg5dA㎍N(Gd-IrѝzQKEյ hλbc8re+tXa J+nMu㮠kM952,vr7V~;`%ẕT>όYa /"mPyLX Ъm4G $$0Zgj8hoFey͡HB]h*u(ͯzu`5g bXKTf Y!Bfbiax*$ mzQ7)ߙAtH\Jv;Cc%K"1Uwu6)$6A#  lI_V0@wI]YN%:gij„UuhNv]\!] "JVIEf R|bn^ runtaMj"2i`ͬ@uU9Mrm(ZAcI# ;ՁN3 )X~'Sc^y"fn <,KKsʦtSrH׍3Lm>RkEmq[ @6֠4kDU3n9-L$Eop[Sr5f}Rs{LԈ3k>soBˀ̓U2+ՈDg z]ˤaQ^.G\ =@[=CVC)턟0uJΙ5٨vm(5|;]"Zu 3(:)ŪCQ9|{ݱ޺.) 2Ozn[P͝cS'd;*}5 Y^CSbv~= "Xj~- 7poS!= 3oN_L$CﻤLj .rqctn,i_h*nӂ \ oΓ&~&TMVU2ju16bt~3W4 pB)\rD:"δu|5Wu߬xM* N9 #wI6R%%2TRՆ۵jVmת Uf6gKE]rʗei*!L 5ŬmrfT8Q @ cL 5}]2<WFrϴZ4k /6⸵2u:Ty}M)*9mSIVB^'¸#o:7}Qo^4 ^Qٯ`| ҋPCs WmlvOr,3 wb973mTZqN)h{]/.l<\/Sp%(/՘ugx@8k~u"~yoHE*")ѐ k߃? ?=_2A(Wo{ܼuO+KkSa؊j dt4J =s¢&[+K&Yjl$onXO#W j?_-؛Zk К45y;in8vjGgNAUcYʷX;ϣuvvl5|h`/_8ɵ G½o5"͌p:H`} eϛbj?Sl[ L?2U!|cd@:^̨0SؔkƌiA┄WK[K[+8(ʠYI݆O5 ! QJ;/OjLA@USed,IE.BQTO/?goߏZ}s9"Eզ{"˦7%Bҽ`FnRZ^h 5;el9*Eb&j?ph8nM8]󻫍ews7B|k#[44iP+HXE4UmB$/M(h>;>aKȸjeQZ i;Dd-흠7ƭ_ō{5k vMjM]xYg;A48IAp *s13j/;ڙیHUc:ϩ?Vq)buZat#N;6 iy7SA,Z̝N ΫA[s,i<:`= ľ݉1(3"N|R9vK~} ;鲍q0?Ø|xx==o+BT>Qڹs<[ (M8'YYv2OKXL`/?CElh q)#hYcnur hgٯ҄0%Wwwvs!_(~<+.T?bc;; U_ ^|z}#A RLsnT%a;#Yyـhq&` M>{^4Ζ e% )1"FA /Pxb3dHLXwߓ.M78xv<GjקcߞzS(EĔ MFW!2~5b~y}HXE&XeqIYܘ}[8QesrFH8鄄Ůݰ<0fE` ` ]zGbGA]^I} :]ױ1PND.,!UH B pU⏁'RC]3ۍ7-gy!?5 mT s޺繡91#yNƼފ![N)Q-BU2o5F>ʠBZ:[{&g"qJh[FZ `4RsEvw6DޝMkMț42`JB32hZSAj59T|#|n YnuN\tq^6SU`m2b .Fԝ;)߄9 fE|\j u_z_ǁiBuG-B:D(GU4dEY‹L*OyΥ$/4Y";D)Q'231`Щǐ,..IW'pN+*#¹򩂕ŌHعg)5;}Ne/ ]!K0f%"aR^,UEd(Ĵ@"]$Nvu?lU)hmyr}ow7;k[QɯpvI,R]luf˕Bڭ0tv}#[@o-"dѩ #'6VdY<̓O5_e/?#×oM!x(""Q>V5v oF+zq),I< ^@`=HMVjqJ9Enk @J;]ܻf̒|? F1>*1tcr=OH٥C,TkJe4ɢ]?=f]0ܺzɢK5G[F>w7+fʊk%\#PjֱB~YR,-IޢV&r*g|lu$\g5R|Q Q<1J3 d3H dc_.x}<[B\.Q+Uxxia,A>Wv?U Y3 r8y+%V&IbKlO$-p0-Tʲ8*%ǨX=՛첁 u_ }n@Ut8ӔDҸR<>\e;V0 "O%٢RRqz;ndy\?u}_=L2rI'F=R5TB> 6{vGZ,LfTH]!zL y(  TŇ'|lC_b3MJ=t#2hBI"D:=B~6)(퐥}2#(ܲ!,?sIyVخ * f˷uCZ0:S ('1/IɺE>T@mRT E~ EpEqPD H{ )KB#د`Q {"\Lwؠ(^P[{^[R FB=UqoTgh.䱣hjǘ>YkDӔ0#N*^tv8v'jwXj]dG kwP+m_s=3Wt:TuP <' 'Cmǟ?oNU(˩gmsbx?M2dFDWՉ9>V46|VAyMwj}R&循f <-:b=1Wd5,/_ۻ=CuߞZtD>͐?Qz[q[IuEFЬ-8U*2T~҄tmu>ko:ηQoK? K״veP*;ךL{D($Z+e+M:iv+ii%Yٍ%p&Uy?qlh|Jp=ƪ x:J=[`|[uwQm_!`CN͍^m +ꈸݭ5=F7Ƌ:%k/ڢZjݗD mQż7*Y8z=Od>X+s ޶zvg<,bonOE~"Šz9\Ւ^P&uW#[1UbZݠJ%K =l&EoW;`#YpS3ƞa鰕_]#_o^|ş`Q&{Yx0^L3~0.#?=ץcsm[ .S=q#816H̠NYԣEB ZvTgdW62!}#!)V]mO}$4XL(%d'~#rr{K8CX & hЀF;t> 1FIxĊ "AK6oH*8-~MCxQ3X94FBN_!ƦGP%(氻t$(O/e_2X1&lżF"^lIXPKP'юPL` {`.X.Nn@(KhFw)(!2z4dj~}@L|LZP癍4ܽS K슡$%u;Pq80u}p)&H 3cg3^$I͠ˆ>h[=HX JDǁ%O@"?HGb.aSX*sm '}A€fA@(Fی.y:ڃY^lbOwR L.tD2IO2<1,I{C=eiLB md@00#t' 5.gT(% kÁ`G(\D"̋'pkeG +\Bɕ@ODy(B-{aaXW2b^/GYdEĻઘr3GhRb-Hl:E6>8,KPléB@+tBU!"ȀUsXu>j dܕGz`FmWPL;"oy h\)%4wȊe&% VRf,-L'D-F2b+LsʁsSAaA'(E__I\TJ-IAa\P1ϢA~P/i e%6<(_Rfے‚˜7 XH@#3"5XOWRqAб%Q,Bq_!xmx1w6k/VfnUhR8o'j kmetadata.gz.sig0000444000000000000000000000040013232740241014207 0ustar00wheelwheel00000000000000R1l>NEg춉W}E 3rۙ^  r_QM88~R Rz91>8'~'FLk^qnLaq 5y%'}IDۤy *c9^/Nād{oɺjYgc+:48Y:kQF\Mfe﫲usH >x"FY ZKlټ/ZegQcb/BΪ 'g?P׭p0&8IS kX|AX$/)Ah=';5z%q?֯׏+|9 ]zro= y/峨hfEɋQ^az_]Q ~{:S{:y7Aih$ {hMcfl~/} 9MQF 9Qv.~ d[jgn x?]Wgv_dzMo7滷]65oҊfy7aΉ.Z ǝ ŋqi{~4jNЛ|9ky\1Q`> 4k7|:Yӥ [?$oy,L3a0G()ˈ8S7S 'E+x҅N'z]`Cw7!ÌZ觃ͬ\{yKI-8!!A:1I%{Qս50fY/O<'ʍ!nEFtZ4(-M{C|e|;Yױz'pJԧiǫ,iȪM{dx01[n6akzmQm|ޓyMf0ǢQ1N9"oe2*Ll2Ѷg݋ޝ]b>^X pXV>6.A/<\hd2GG-Z^"&%L1ϓt5,_NI o#&å~1~j5DpYЧʃbul3xG^ [y9sn5Ѣ0\tEL+ƅa&$$W->JȊ.bFO>'~oJ继io79O')U)VG>ö@@~-T|)H-;0lN)M2M")A* A`VKUI 4e32my \$ y0faSQ!ǤOYY?n=k9|4E|i>&NOb}2/Eu'_fdeCshK:c9u/X|(I44"]/x?Y.am/<47)D><$ OmI Fff I E i`31C P-VA8"4 hЕSS\Ii) ʬ`hdu|۲Y% y4|@?u6hx? f &,4@SOhzċǽȈ[dtgJđ[zyb5m4vA[K MYqz֠wZ`D '2Xi'u}V(fIqF7?N z'dd)^O0YOSZ.#t*v cV >1D׵|M~LnBG!Oj֊&̧-CAj?W⸌zi9 jf=&N1 0U%,GcF5}1| Pw Zv2hŜ Ǩͻ pö.FmEh%7F֟E:KDoaCw\2f,î\p(kZ1),i|FbWOwOz8ɢp[(g֡vJ+:'`Z(,~Ɛs}p^Lq ]Y^PT~k>b'{q4dʪD[N@|Fuޚ;ޞ} wư+*apF"1iPf8>%a6Y{Evanf?yMOrƯV!퐞5Oq3=MX؞0d/ԑ8b0"ESuLv> BKC[O#@3zT&pĆHFb|®So7- w\wӣ" Enc7.b1VM`-z$<԰bRvHk:I74}sL*T. _{xvE\|"V%FL/hjDIȓxX]Z1jN<4 R$SbvG/\ѿp!ot&BN?q ,\P(*JhVv,Y"҇y5}?lL|[-'跻t7WZnmoĝ{\ڢ9|mI8hmzcc)v8IJݖIr7yMɋD)-,i070I#?7QCaE;jJ7jo V:Ҭ!`JŸb(؈lR{"VQmYD=ؓT=ֺ/ <ȶyA>۠Tc+pz] hb o)IQb.r1\?ـ' 2"l69U0507m2 ]vB\0}+D~Jl1ʰtqAߐlEX*q ҨO?7^3zaL@CX2fH XG29iMt Qob]@ABQ˫7/-?84B! 5$UU>%Z$[`}*fHH:ұC|$30=r,mNLJ`LGLn\ g4xi^?pa=k?[O8`w'DԎn8^xNpiՆ} K%d{,El`S,D%f ҏV et{ih[pe|1K2Ud?*ۆ 90&ΓLYJ1 3}rm66D8#ugsյ# ~)d>ܤ/嘽n}07v`#G)x|tRBk`wj~LvA LbG Gp8E8]V h,4FƀrwU$R=* b^@Do}IHBg7&-Xxm=*~|iwP(:L =~iu䨢t3IJFa("hQ@:ʘr@>[$;JL T*SЀ%[oǛo84qޕqJSb:I(`bnNHW9,Lb$cQ%twӅD8j^lb(89͞ Pj2U6)<|A: g> =7Ku{ 7,S\HL>Sn=3pLf7p!` 9bյIro@61KN`3a s솝֡/X% vM y%V&5dL-+WrzxnMy2Y,וZs*0hu%ſDgV ]d̓Ꚙ#:}r;2P c 31K<[RzTlAQ^% ֋[OwIYZԈR$mHdOy ]37 'I(\ZObM`%[O`%+q:MY*w?E%¶Na' zš0q!E(4DrU]=$bb"EMY:*s5œiq?"34{g.l"(!椮u6YI.I6~˦\ ajf}^$}DG/- E%&kd E- r(?˪xjlX Yp1MԳ쀓d~f{oU}A`=Xѿ̱Q&p7,GtJ^Q Oi3@rGQOIڭQi s@3ڇ~`-̙ 4gj_I#1H5-l>Vv7f@578~&nyv8m勤χQTO+kE^ՠI7 vn‚ F!KKau B&o2"0خOoYEC]h"UywSӠoOc#cщu4LD%N'!_=nmD `ۻ%.j5Hb9 iF5p&YE?KE㦅*G/ȼ('SDƗPni|ڰ6|qn{Z6MuH/Z!f%<NXe#RE"rArXlz1or/ff,cP-vq@-[{* D+oʗ&$nl +D}=& UOxiJ]1[%ϰvCķYb+'"!&Pu+ICI8ҀVECH4Zi1~`f[L[ڳ@f=-꽒]zVTzI^֡4 oÏz?iճ&͔ b7zbԟ sXLh-Ɓ?]<!q(~O>ɩВ1uTz7#R؎Fh6w#$e%'kگR‘D9WX{vWiˆX2mUiр_߅R ilmI弉b> :OCj%DQh4Ohi4B?˄6Z]B0.;6(jmvkhv±KSG&[%nu+x"8-q,_N IeQ[!E J́KygH0Ύ|_.7JˊIPط[b15"7~GU( K,K.pRUOIY 5_qv_$keLNxͣ:ݺEHCv`9MiZ!鼈Ȼ`֩\ -J0oph譹.SP$@G"s0׹Ţ5hzj LJN"_$YM/|RpO]H4FѠ2>C2T"./Bx~ķHtB/ҠĔ$ÛGPn'@GfA]av֨5# :-뗕VpŮd@_^{]PG"a*sʦdt;&Ex6~Jc̤] `3V$*Yx[=+'Q49!I+NǛ$qtkd{.ۈѬu[W;Lr0SE .Gc) ,ק9|b81˞逰pp)~s;K,<BB9 =XLru Vy.[Oᅲ&m*l0/hMŸaN$`sLB, U7们.#K`IHbHu_b]R\5 bVl ǰ$&дpJ:70LtJ  U p!Cxn8FjO{"ta-./0Ã@3 +4#P#>Į^aA&qdEQӀ79Oˉ4IROUahxmFR"J9Kzlx`PsʄOhM# 9?mSn6LϼI@r²= Q6 =uָO'?NquqhǓAt%>WC>1>$lF_\om7=Rſt>}fBBNeǽ9 |W P+yc)gݓ?^>LUq:XY $;n"<&`RU|ВUr I x"h|ì_ZWݘSnb؀'9%R̓$$Mn6L͖bxHJIӏá2c!@oC[\;ZgXu eK(V=XRI|#9x%y}ߠA?-WJ%7O'~bM,Ά8r-#3~+2ⲄTS3 LD[[lnЮǑFzފɢ"y$^m `iL[Xu(% DϚ.VZ~!vMbab]4()eDt%ް[JV6|ɁsxĨ֎nJ8Y[6s~{B NrڿWreKBJ7*if0r(16Z$µ@<#M l&#T%vh:GI2ʄ̴@YO VkC쒯]z!E;?lz{F XKC<=UGZװxJ7»>@?y|Qo 57.DdKf?;i%(̓1ŘSF+F&H`n%FK:p('xᙰ`SzZQlX-s /yH8lIY\<>٭4FF B8#F>pmIh7Av4QFhh6׊*@+.˯ EBr I]SUMhJ8n> eǓI޺*e u_QYpg-61T@CS:15IQYd%qQ+hH FNTh/F e0fuЧ_?~<{`R~MKW,KC89l882s{`i>rG+T ]Oɵɵ6PGG`FmcL~ D%꣢@1o.  UDѣPma8O@,M`/US|Hݳ>x|. ok6Y&t4c7L: z]"QۺjI` Cwb !4^ojǙҬrΓXlzP~BR^~kݾ+ɯ, [G9~Hmڃx)]K*8ɪV|']uɽ~(bz㠀Hr)_MLu::}wzuwD: $E#Ԉw@U.<v,r6oh$awYnz^јE )q8]~[+ݵ Q}a,B_I쵩%L+%Qm=zU8fPl)ao DYf= Ql n,xzf7ʿ0aeNtE:{=/pKmsvX9T 8ol;2-] gI\z#SRR[`  ͹@ TB=h'Jv9.ţ{+E|eCh-)i~ltK ˊHVd4M&@^[e 8|vIc+M?R 0rתDiĝrę,&)CNzV>K12y:E \$,؃ͼO!gAifVNCPU'&60/d__z8,A"eyT|x-.jsr~ gNJĕX\_m{酁81K7e@E0v'a+dgxbAT8a E.C@+7]čd.>g a `=a|9U4:sDoxRH$:5^<,xs{]wN$fd5 p7{N#I_ƯV'X3i6JQ޷:zE#CFL@LFVv$E<[Dbm2DUc~z)&[d/?˫;0t&fa=PXObIe=gӃ`oS' GLQ´_B;)Qa9|s[@AtffXȓN4XU-gTV >KNCT'm>ey l}+\0Q˘ncoo;Q0k7Yg1Z dSsɌE1e#XXAɺ~ǏV΀sۛm+xqeg`ϑ@*ny4ٛ|w q_RG {YhaƖ"Hlm1-剗#)龓pՏtB41/`uXڍү+)3ÜEF0LTun+:8d5(BNy$)8ngLˆ(Rx:K :=ydanXa7,-.aBw0h)Y g%] ;LYkW8ϷD 3M4H ՑѰ7"A0 )2d{l{= ݐ+twUKaOy5!B~B/[߶<7O,eT*eʭVlmeAr>جj+UB8_HTh:b) "ZKg\/ Dtn@C$Oi~1"9h3(>nRyBy&Ĕ8kg"vNy}'d ^λ!c*2xAR*u ŽMKzz4Op"hʻ:1 a{ޗbu >߻ Ez&)RDWJEzq{րVz] P5Ox~yzKkEsYìUXѼGkbIZvGɣhEf_/,vPaߧވKgX! !v%&~ !ThDL:]*:l|:2jr((-I8.uwט*hjj2A Bqbʰhp(Fqn,U_,5  { 0flXՠΧg>|ǟ kӥyr^\Y3G /Bx>'rCYJˎ6P;38j=+[6ۘ7xFLZB$J(71K2ZT67.F9ֺVNR5T$TlX,nI[]4U}pX ;{Pet$%P} w~k3, IQJG`%4-½9@p =cgh)^m /%Vgr7 D qwroX"bG²f$hNNɇ9˱W .P.xuԓ2b8YO"Y%$p>g3tQS8,o}0Kd!sjPp"B$uPMU8ehur1ejy? {S2Da=z2SPK٠NL?"$>O5 N[[YJWVܡBĶL-oKTxJa8bHb DE6s|d)XL:e?;b^1PKeUurDׇ6P:&] c#t*IRa1^1:]D<4%)Ӝ+/ 4 YpmnxAH֢eLuܘ:/fW^gy¶# &BɚA NJrG xrCҥjՅ|;nW"wr'`迟Og /XW:cPJke/A7)}!?].*)5-{S:-0Nutkc9Ԑ\Zָ5E5Vz lPXľfMu8]st6,kjYoqY*ćP952<!RXJVjУ%(ĐҤM"8SQPѲ3(@M m +!8j󜶄(W`TtK.*3$b )2gbl72MH֜=8^Y%`0*jRx\Xi,$YeR,":ЀR-S=j+BZ믮Esrx-oaCA+[`["G<.U\NP;ψt Knjƻe5y&}=̅a9p*I7ÙuGL玕X|«x$*|VP~zL1]RH{y`ܕ"M Rm\ɻgcWL:ńaqOGNDYXGX&h=^NXw9 ngg l{Fs._?]Ϋ^.xYzq<+ 7echROŘ{nNH4LE\dY`?ȥPZ 7a0&CS2OrbWl -U-Lۙ$|aSTme05=~{\Y`pR5UrV3pkrU`I)_T飈CpdŽΠe8KEYdd2<%e y ? 1M~Y'| ެ3}eyuV]KpF{)NA!byAV">DY*ڈգ!lɛ0U*ǡX @8K]QF hʒڗ\Lw=j]] 舋F|Ja>o<*y^Ց1IQ&gYSYw)#, DZ5{WiN7U;BL`O;t8@{p[C%* $xj;xʱWۈ~uNgԫ奚hDw Iy$TRY|p$lnȪ%#Vʋ˓-`g. G:W9ہjX5ppF5H m|wSGRfZmAj7VV>OzsVzƘ׋1v+t;%Ҿ>{_SIR *KR3 Tbq&vFYx5H -9xB**{%CvR6 Z9g%` KqX+#>?MXsoiY\4EЛ Ye$h0+Ơ'0{D0 Cd4-NyUq rdT?H!gv&tbl%D{$rcY\*63BAZ9p7.jNy3zbMy^8+ƃpA|$ oR|)hw_oW=dWAsDPH8&w\jɸ"4[niazgL١Mϙ ޏw_<9<  D7"R㢘G{{#W{67ƞ`xؼrC-wf#>׵){gG5;4 I|gIb;hÐ7'W/O/[M"ӷ&NĔf 'aC׈x7o+̶F_Ֆ.h6[Xe5Կ%E(خHmNUGM?N!1ftp+!KhkF;gqh$xܲ /F"z]tfOWװKCh#fOʛdYG!D Eݎ1ZY܏H%@)KpDVD,Si ,G[2f36\PC'AǞ)%))} )zF)mBvZ-f [DSژaZW+'׎xWєʬSx_ ?#hBjVN62)Y{륋`%0Z8\A+ړB̂ R PSPWM,;LF3خ4JS"'57+'wa4dmQET6rB%@BwkCoJZc@7K5MS7m.@Ѣ!B,A'mG+{P Z \|"J,kOqĄ=B/M W1F#J Ρ!w1UPIBON51  g $rt+'J}':s>e?lRءMQy8vrE\77q9n[ә;ΆPDqlǃpJ0o[h_ID1ny; lL m yfZf'J6"$g4TAV\4)+,9v8b>0: ߴP8D'ן.O.._}8xEڗ5@ DM>W6]2 -@6m !WG"kKoo|Z6sCvo=(^cky$.&lLL+AMO3%Oj1&SLDP%b*8xa-'ySatXr3pғ+!0h#f#IK8!A ;4]@FKx;wgW ww@ҍRH8.M;nTzle/a[OލLۧ;W`)dͪ6BIhKPSIS[12ַm , T:gswS<ףE40Aܽ!rYRE e]ںcY#+V5IuY:sŦq~ _EMsזR @"Vn <]᛼ Ҡ\kk[\Uy$KoQbWЦ2YxOwLaUެFj]e&IW-F7Űtpo7XUR1ip|WPkSlM+ȦaM[p wz.A:s> k"Dd@4{}q9>XI-8NW'goGnE萏⦖:m6Eic+E.v9k0'2Z# Z~u=\C(W[bj7C(NYb2= m&I5lnWB`›qҗPKz:moO=y†[xIKO4fCHnĉh+f=4g#\!D>D%MQQ@O d-~CLS5fl2䧘hM=,. -G[k4N%qiPmVMGF\~B"LU5}LY g:45ASw$QU8} bo\XZq,F9YqV.;KB ݟ%Dڼ؋|*V@gn< ^nT#83\5$ 9V.|M5F YJZM{Y)ѲxZ k$(HIwYC,s%+̪[X-Vb{*$r=c{#@R{=|H8*#L+0 V+fL|0{4}'W YB\N^+[ԦiLZZC! [[#@xcWʃJZd2G3l)y7vp_jb^/xY}1S\ڡbVI]`1'>,ԎLv9_,K|&Wyh 0bb靉=R2I{5VL׍Ƽtwlډ+skA9hy)O\z ;,]%c `f+A96*IkcP k!#Hf6W m 8f\Ծ&{?]f2G@H-6\)G{t*r9P~g#tkA8{HBXJgtNKiQ,U1]R8&W]C#oj&l UԶsAB^}<^|1W5O'qH4{RMtO= &?A=*P(-ڨDR ڭNiM 9<|zv>{[SGy1?Jn+wo\ɼVf{(ex1hHR :m-9OkR%j1ARKhb#uA;8m`TbCu CW''o߽DFVpL %[ 1 "a:w F&qŏ>+AYIK3^n1iC'g v˞AkNTL=WˍHJ=J#X75g;Sg1YwB4dcY^H( ̓-[ >qUjש!pN?9o h3vx'P9+ 9TX lЭM6=#?l9XyrX&p_XA࡮|"}FpDxd4&9X-Sg %kӃ6STܘEdŊ<|qæaUkUA RA-4:^_5*W#ۢKG܈G p4|vU']|%B1O-]_b+tV9]chtDXbYOmOGx{}%("j>X4/=g<4g~΄J||\>e< UnȒ;10ոH )zM1sM"t`FXVӻ2O`c |t{o?xTLtF2)ݓ{# p[o@˸$!$xע%AA?-=ԅn[X |SD>з|)T_d,AT(*}4  fb*pmkD= H ]S{F &qXr?|e9s+EߡYb>b)ؔ dEܤvJDSRY:[L~'wsm fP_goUx{bs&fd9YW"g\H[Xy,~oMluA; z2"uwyU|Y=z0wGm\QyL8Y@Lw`?N}≱Io#Cp J5 iXm((7)vW_*nATDoЛA FY:꣖fh`9dh 0JN-:N?]j>i661'|Zn%ԼS¶oopMWɂw'\/[aRK* GT<اN3xFXM7n5-E`)혨pB$`ɊQA,F Un)_Xm!$CArnDFȡ έĒ *:|~|%r-WKIYAS(AͬZɯ]e:1`Da/=nK+káD,lᖳ0#Dl^0KkʗDkn48iy5h9"u@+7M/4OŰl\>i/s_8ˑIS}5E$-aI#}[h78oK}6f4VV(H11 $3GV4U=8qwaj݃;H"i,ei~5oQ;1?CDiK7N>9W`˻xgoơ@AlkSS;'1QKknE$MG~C+F$ܜZy[G/wj M&?ço>C'H^nY >^}w8Σys|j Cé5Ak5A(ױŬ+JTNp9`ӅЇN4B7=juOHYtGOZ0ٲp+!‹ xW H[R~O\&,\?|ïoY! M*똸ɖmD)"۝IuLI]d\jqT^0Vx5A2FDj%t^^,&ћAX޻4SHd+@J\lj3̰֎Scl#dQz&P7LbqH~ =A9_Lif#4 -l~NIhHSXQXr*LM4$SW5U0q;^H]-mwk1 &1| #}zӸ:1`2DRDvOzWKoJ ݽ"YaPP8O'C^ @\jԖE?w uyb~ 1IZZrEPmZ׮qh|ͽS^ {,90u|6bƢu}aӔ}^z&cQ hݯO5/u៺HS_:<5˽KQy7跲lV";Q9u7Ue;)gEmzL*29 HM`'s%r niT)V*@ǛϩY5O]% E^Z_LYfg `D-dmgrgy7?Ky [{ose8l@!,5Mbҍʽ^ESKԻ/Yܧw^xnCȘ&:H+0=^c\S9p6d$1a- e2e.m[bb^;D.*+A.Y'ܵКr.vKy)^{A M`+W ׇGyG^YdX.HN#.K,C:}[4@5ݻ>$*pJ#%`fQi62PmVM{Wd`{LvKW7TT;)(0pPCz;YZSѾ"ZMϮ\h*,yǯOp|}|<=;>..Oߜ<.|7C"4epn/RgfMhA cn#809 & 7$1K;)mǯ嵷vs9BCyЭe.- As͂EwfOST6NiodRaߩΘz6u7JszLgsv^>0n A1\p@.EН w_ǵmVhp[7W0ʪGk#r-n92 VV+$!^5۾Tj(EK$OK+'B`R`j'J/Sp珒_|0z'aS?D_Ktz. 5_lWT>d` '.u")&ya˫K_xVَ|>Y'Zoto(MF"Z/SԅY5,aYMk-AL'z=RFb$_Rgf6Ixu_4BYcί?*+PЂ>Jpw:+iny@cߴ4X53գ>SȺme{iFR)/X:m2ls&V1ڏ2AKi7Tp&K u ,f&I’B[rDF+M-ΣRq4#Y7Jƒ+(O\_۷%n=SY/|ವ?.͇ FBÕsZ!cD3?%2D [eMRQYDf)9VL^Ss4e|`֠+IF"c{ljh{=`/-ux,W`KqQƾɣ;TX^ mG#2qrJ1$,Nٲr|0g,~_FX .Gc9/]x?ToB:;K@Mr^Cz?T-iNnO9 /\Ԝڋ^)BO{Eo-^º;K,[4^^J;&aea {n"*C?l1}Z59W[=;su.*2nf9hrf\8K1X~c,81; |Y@]рBCfi\Ef֠ ^<?hgҹ)t!^ F-Q ,gGK˜kZDNT._\(D ]K4a88eha-a,j.MK;xAޓfoѼ!bmɿ~:C&.p+rI0(jR8è F/$&u#J=.CRrVFL$"IZpJdSìl[6 fzr q!| z#__ d>\U{s[umC`18CK15H[i_E&<t%;8&L.@i&e0˚ܯuMlZoi'~ӛӳw &jFtM{okO._?_~8=>CoǗŧˋ 5{vzzkU;=ς?{ O4K.O߽ޟxsB:p"]}W{c#xs uN\c:oߟG;iϰ&Ϯ/FھI#8<‚<汜97BH+Xjfw,>]99@m]eZjz}lSI?AaS36k5+-8HyFTҧ˟p'kqMW - l3t" DhfQJ`V ߜ=f)T$E=^Nl^{ݺ J_: gl87iΈ fڵ-.t2RL'l1/KxU׾ .`{(_'͛l=ïI<_X`%)]O$ vb ^O5}w3"2g Jm{Tjya~D u# sgfYHЯkYC>Lb%)}ko)Tr6LiK)_ز|Zm$3ǃ-Cں-=/Kslp|v3?x_~&}3Z2>^^` #( : ?xxJR7LΝB/Dϟ+cb$|` 0!)_/TMMM?3|G{x?|[;xIE{yq vpB} GO’]C:]HUUq5!-S CJQW`׾(."Rjg²yU;t[*;wNPTy_{k7~Bc_ ,bEZ)GY>өV"BZ9Ro/OL{|ߌBpesxJIz}%%78[m:8c|"2gtQ"go`hʳT3q.kfVas#s=Qmws6!ôrGw_q\hIU [?#j3ԀqZ {ÃG#E:}$ާN5!)3vtg/ jel}k VGoW92om]zC١I4[er0K*fY1A9˫V>E}nD}Vkk@:[kkퟵ_#?^^Vαz ?x=;^8>RJC2_ FBm6R~ xS:`Nyew}S?I_7LJO+pǏev鬘ny}NOl&yIznj,)> .O|/LffWb JlPd:ڧk gȇ\Ll]/(|ַoPm'BkGg œרMLMEc6ϓܹM#M5v֖%P0EHOkr A1_: nl;*zIְSvCSm=b)mԎ+"C.Vi*zB~k8p~u`t2b앓/N@_)] S"HS$ӅK#D:%zwYfa1/Ȟ+B/3[蛲R#btRJdzr Rh}_,80 ;Ǵ~f7^Dd g#UV |቏Jq^7SgJ87.FGX- 3K)^"--3Ū,+w֎ٙ9F}#jH]p2ycO}jm t3PNb'(ٕaeG`*'2v[='T"(eIgџӱL:U&ט\bU3 x`tcʢS+ c]*HN]\ǍRp\t!5h7G<꬧Yrs|ѫF59[Sl`ڬeܱDɵ>W^m#{imK^N"EZڜ 4u|i\6PSDhQ_T`IlIR˳-;iyLڈQl>f}~$.uhK}+ mc&ۇfh +bjb@*k1i" 23^8jd]-lrxͺnC*(HZgJ@=w5xыz\֍s Jd\)',V܈m}7 LK7*k\T@KKU?csc'fyro7 ])2) &r:Asn"~2"Ir8 BP%ebǹS-P*H]lgz"A?Imh&vj ʵRpjV#]SJU<ɨOl׬n|{"{EҮJxzVξnY6=g?>J1t#,ypovCՁ\8AA♒O0C-%G'p9cwv`F#i9Dm9 YQqۤig#S9Tq{gF9~CN5zϞ42i2ՃGK jk0Uk6bLEqx A;nB"׍څJȧCM9q B-t:v8AJW 0" u}9ƒ?,i>+Oy6'Vk{ڦȆ"Xȣ`?)N'cMfF?];>tVC6E@-u8=%$FWyreټVQ[!kp֎iA,mr0~JB7X ֣\ȝLe$ʨWYI3J5Is[u>Ft0_I,XdttbRPՎjbQ5IY4YLwA\165J716_Ýs"QhD>Ȭseg;0hƜ\c6YĤbQC9(H`(?6#R ('$@YS#UmMU06ݡ,)hV&ΦB.7 *o*O}Wܕ;kN"lY>ݑ ;!j_Ʃ*GRaYԣ:(.Sa1({%*.@x$^}XL2f7$P"O{iGS+ImEbbSJ IрH4XRRj>(meDLsUlc-0K8en]_^O96iJ(ڜ#Eni1{z%:Ma@lyܣieϬ91m]T r&FgGI7^ߎR%\۱hބ(ʤRҪ}%7ZS})F -AbG?x>/w1uoVin4 ƲΈ4!glʇc>!8N_Gnhnr*8mMeFMj2dnkBC1UmW:FOE朱 {Ҳubǜ}p.'<QSg@=["Eyt/h$.[iV1 qM Jwy>K(mT?{^9$Rƅ 5r0q0N:Ur{FXQHטN eYn7y[3Ʋе~>+jm>FI,o$|LJiW8#ǧ,.n̄곉J3Hpӹ& F.U*1jlrcGҡ^dht )M,tE~ո>ʒnV$d[JT 3y[6gz4:nI\>Sӵ9iJ*Ω`&giK_aF-NiS4A6gϓ YR,ƽ w˩?{Krbjס| ԑ~e`~A a2w5||I:JzVTX״¯PN Ҳӥ'߰Xsc8bk0U>1wԢ<sBooҰQt7mIz,؉wI`\gX6Re Y7Z.yݲʕڨj:bO/8"5~ oǷvA{jHO6l_2*ë# n6deroQ 1P:5u&>eH'iOvtfzȓ 44[3^<\km0LϯE 9[+=?x~GdКP`T`4΃;.UjA,շѝ;q[#9^QqeG~ɳg#4Y1Acʿ+:JS*ªDWk/IMØCtVAqil )lG`8tɘSٺKVE^Xj8bzEo~$ %0H ob9)c ZVI!*cǺ4kM/{`*OJ6M__[|SK[s/ hTnru&/ ^%^:7Z78hJynJ?sb{`byXmWWT շP}W#J*BG5(H5hEZs_g՚89J QJ17>kf%[QuE_57jД(q ]lr9^ҳ̱3kj~F My7O_Y!?I w]Qr:L?mݧUΏQXj(\fH4^?y%(.w~E Qy*P}_]5 F# P#0aPH8bZZl.Sbߋ:WߞHQ+tD=m˽m<]I솭lN$c0ґrzÔs;PGK]-̾vsP{c6;t@Y.휟e0Gх/@GwSU.n_aSji*юRŕb |yalr`+Y8&2ԡĐP]!nZҌsX N:&K6~nu~~śϟ=VEpFY{Z73QEQv>In:ClBry #/يK`lM>{xw`+/{_Jَ~ytk;t٩(0> .S[#FRWhĭQq'd Kд Ldja;z& KaG;9ZG[V` & Qqo.%+(q>qIVY]0HAH` H G)܉p5zZ M\ԱnJ.WiMvx.Tr9H@UPz ku:Ot_F8mkW8ga[VĠ*[R=RQ[Lb1VGzUOWziKQi75_f)"Ɋe#2 Mgz s+ͶbF䋈 &SQ-.Hjh0 3xa"Ddb,mw" b@>S unQ=? L&QŔl>CciC3Vq}=8Qt&:z 4G+& wPnnnǡ2JY!Nqwhk_"cdsoYw-kb6>݂b+&?EAfeb "[RD5":nGoev[u">N!oҭ\7&p IUǧs`pd="$d*/o`eF=T?K/'y*9^TH>39_ضR^bD([)b;gtkC)]};FjGi^'ۃOw9py3oǿQ5O2?nk O糳58)AW=nع66VaI~ò"8jnW[G$B%Ql#F8WV13Y6M1d.ZTDV)%v5v2Y壨ч231>wv4}B?13~0} #8L#su iEZwN :1Ձ3SLꆦ\R}>9}u90CtA! {F&ZTѥ{9Ɔ}Q YcP cH-[(ɃhA)s˙>6< jlY 5 ɰ۫8Q)bftH 4#f1s␸'lPN;)f+lFR@_RF\H\3xaQO0=' [vHqRUFѲ$a>Ίtj<~sC;Z1 >6?P* @GR'Yz"3BO Z䀌$a ęp3hX \Y3ŻNU bn*aenhdBfq-_Ge> 1o~_6$?84+CyyLocWlYI V|Tz-Q@#8GwUK̴Nhٖ՗64 n*5?rK^*hs4W>aěl%>bkÑ $2f&es*06?@/@ 6{*kP:@g ${o{W)8i UNC;7sf[FR)j&ͪ/2fUw߮[at#3OtW .8uksi;UXsc"')(TɫDѽuL%l': xX>W[`C׼KaqYb+t0-HSB9JRqZ1Py ]9Q4G8" EaB)TEiVSսn!M:qg *%l:>m 6P9K;v1!0ŒT"%1_c'˅żDey) BT c9K3;Աtpl8n[ ԲYbdf p%udլiMLt'/YԽPueDH".RHu\%C1 Dz7ƺIӀe Q Rp0 KGnidzm_{d: T۶c0/LîC=R#)#5buPJpLuKewb_ 9Y -ϨIY[e)S5 l%bV 0dN;ܯŤ(X5tJZv*38RrI4O`!!:PJxe w؟8q<35u1t&it?>U= 98vjZIŗU;2 ňB:ZvDV\uTƬ:r鈱.$MKY/=D=~eiR]B-<\̸b7$mi1Ǩ3) *Xɛe EtؕimWPK3'9Ym*O'.zol񎝇G$f+c~Ed4{rkz:Ǜ%å.N̅2S}Cg̯$J7jkEh4{ U3Rc-5.c5W2tcms!گ:QKC7W($P`/-Dfۑƅa2~Jl-h4 ; *T`F]hb0VKCFړsOkwP{s5}o=ZJxx6vj.[0޶Pn};󱌘G;;j]ˀ  #󣴯ISSumQcp iFv 7yp|n$-^it?&]_>ƜXk-袼;["5 dhs&ӾJ<L/ҸD{ ܸ_+jKG]n_4NIa[QS.v lL*"$wgpHƓ*Q_~ 3Th%TϹw6Jn,{_?9TŸڮ1tY #NHeDԂN8LRDvjzHo2(os`_) {~@A$B$)'TC#i*Vdg|DuN [ZjuTEQyJLf+wK³O1&J54#MolQrb)VةXΣF{ͨucx׌Ʒ'޴u% l]rĀdxR*06<槭:iD;4xݕi˅_+XRK9@qEUGݻ(5d(k em ŗ@[T1Ů3<0h5wTǿf<sG#ɒЊU)%6Bsxbu vx!jUǦJ**:,Fc6# c:o]i91ϲӳ<ߔKͧSNildr3T|H&ig&Hx~CRcNw|R2դq֖U;QFvYSԋ?KU[H ,$Nyf&BSr j<9 +.a5Qb"^27FHdDlzim01'xon+9ٻl$Χ;$W}3䛕Dkhm\,taנ왝:| QEt`à)Y>V_`mnʼ=}!ǭx!M~ʺD.wdU79$=yԦ=Ik{pKvA˳$4>(O}ŧwRZ-._bw?Yd m~듐p8ث@P>J\Z`0/ltNJRU@e Kir<^ S- Amc?\<111+Ϥ+2sʧٌVR++20yP/Hb[ԍ6b2-jsb5]Cݻ{ފ{~]kuů'^"Sr ft2UҦ#ҡNUC>`2*tؚ Y w t0M29*A2()Z'l*mթn#^˵F8[ BM& ߢ`7[xHSSF#r*|-39P@a^3?׃[}|8wc-=z2‰Az9Nɧ/gc2 lzYoTJe2UKh\slw\Ws]V6z#sm{f9xe=0&: ghBv?drǏrV}f1)gbs[h~P $ʡ^KsD]萖ͺ2)m,oh|l/"r{"sT  to1Tk@1$E_)Y|7o٬e%`.T5 8i7N㝛J{ nrqNߍ(P{0ԆU.-v֢:_'lnXhOЅD藍Y87ͺhk- 2Zs-Z̶ٗuY`n=ole5j_y>2U\৭Fץ|9L-',%msc kbw{ ]27E̪.?Yϸ4v7KBw \|šW;utW@eiznyrbw|u\?4}5 gs9{W[_?>қѳٝB(rvd\3j}9Lќ}` (;?5' 6=vʀpQrrimP~:Ak9Mqy䋤44zvbA?]ƦITrbG\즘7VFRGDo3Iqa09@)em|ץ2E0vnuNL"hטM(Z@RmbG)VN6Kei\IѦߴBk# 76, M;q B#7.f!7X{FiَPљ87thRbй35pyiJq##bcdK`r^kNBUM@VW=tƊaK1kV5KFZZ[UkR5Td[6. 8Ѷ*\+zfH=4՘EVLB(YTLWRLZ{RK'@ֲ9δ|6g#Z1jN3h4' (b%8\ƪ1z# Д.TSdՠ ہZR(Yذ[<\Mph=^⪨9M|p2а!sGjtj+8 UśFks*]e]ܥ&+ysu7wk90ofo^5`7U\}ryȮě}5<\k ޼g7vC׼]j$?PEWO+Xsjt)oZ5lÛ*9oNU)ܭd7?sVk0o#@~oGYZԸ֞U\WhՠЫ{ᗹDKDȪA ]caNsuT66.l] JdB#[lX $hCr.9N 7HpR#}N Q5+(DQodcϾ[ao,d[nKBN֊]QAw#J)xGr8D1n~S? $DXCdwuʤuxx<^*d_洟RIOWdQ_8%ftgMٝji7UūXn,,=Wz$x} a]еuʰ(&1佡;98٩"[|LEtr7sޔ*Knuc)?wqm;LfW>]2@<WBD1EXccǠ,[D{ݡe(هdIpxPuY{J]7?`cΉʦz܊P;Ģ*p7RWZl7B:I>$>0\9-Jg,V&j%;rZ]kbQo@+# u '酏IT! I]…$(Pق~hf14H/ʘɭq-߃9ȗ|GӍU7=pdsnN xfւRZCd2jm}S}$ Ƕ> cIRV'٠v* D7ιl09ClUBTI4{>bZt>TgRB)GUN$ ˧d"+i&7bI8y3^- $fl¶f dټ5Ak8;QZ0TW|NBf 3nՑԓ^d$ tap(ƛ_i'=0YwP;퐚0zF1G،dVZ|Eo2:iJ+ϛ 'n}ߡF^TM0+!0rf)aBk` G`Fè*h]2HPޒ F4Oo8Z|BۜD~Q%MӅiY`}k, k>ܓsoRq R,DyWr|h#+YJ-Ch^yvM=^a-)Gr7/MV )*U%LrfhgT#O{)R( ;!kt"4M;;ڤ(Aа$}*uYL6(LO**}8ɇ-.kc#4.4F91В.ސ1;&QrHIq.j6qG;ĸuJDިQ$46hrd܌T Twb;cz2MwΧ}U5i ;T d҇۵QOKWq8[h 1Mqh+aP"; A1~ftd3 gq6hu.]w"8_|3 `^_NaP]K1{Z;ֺ~ٸY!~\ a;|8sEF`aG1YhXѲ&ce*Ig,^ՠU[u3OÌ7oUr ;֬|NOQ[{rtjL0e(,WOgPW2ILi/vc<3>@r=b=3xܛ IX(G/(wf7z{"'Ko{#O 8h F,an?5ׇb%K:qOPO6=m}ş?o~z#]^H\JO gl(< Y}gz&Uj#6o+N.7yU,B\NIH7nSy(1=VJ"x,͘zbaЦЛzܪL(Cݰ fOPHs@D ]?Č h0Ʊ?lʙջKœ'5S΁YgupPDgN+OV1TB 7#81$<!eSXd29\,] K C(IdrN] 8;g@R/[~ڻ;vKH9MT}{WĘvPC?C@Kwa諆kc]xHJ*# vl&!**+.-xJ7\^e!]MOpQHʽ~<u1?m.Rj rE4SouJCz@I0|C"3^fCT9>.&Rޢ-hާbt/\A~9#lC2}.'^_)A?W_?NP c>ˑ6uTjc0&&bl;Taň4P%&whyIqPܑH#?7N鳟:ӳ )ugAy,׆9.+Wl[Fl t=,P0pl~uKC.`:t氢V+nhԡ)WX֤2-⒕fvp%߱f䌈|pZ'zԖqeh}7{3UmԒaq: 3>j6.fT6jGDp7Z:e}-̡e B+ѥtIL|"T;$lbs w5J(c9po,pb*pwIy/$YۢeI>5`'|0^4 ,Q-$7ӯs^d1L?4HK#_uw2T|1@1/a:0hds,1ĨMQkDt~~OExO)fmĽm2϶m1[ mm6Mmx[ܾδOL}1?=ŪLhو"XбwQ3ҟQm o&3"POA Ɍ>WhQr|gtnE\|m71  3˥^XP:{cI5աI}WU e֬$&'s(&0OX~xHG2a=?3;8.ISNKL#hJR7&?P(PӍ#R8-H4R=Q/"p/@Fr>"~bGI)s+7)M L"W`OxztyB =JIx;|支ܴm* )C4<czv❈ג4Q0,'ꍢP'D)v&t#.ӵb`:dQ` 9H+b3 ""Gl#.IJl!Ȉ|\eȔN|)1i\D7c)Qo֦093 ̺>Ŝ'@5MՉ$Vyh GeYjK@h^ksI\De`J>weIY6OQV\T[FV]KA`WjaE.鰉/bC%a;[V^cVMNf0清GTdI 1-`m 6~vS!.l@Y'[\~i6շVÅX qt'_p*hm&>XU dWA:OM]H@-PԚGB!fl&툌89Z $ѱLqZQ"q`L3^e.9+KDnX~‰i80D%A' l oQ>i MXxb%;0̝gژs#k5.?<@*$ztAY;>xF/q>^yQp$ǒxMZ}K#kQ3wpx Ү.xM5ŷw; R7Ka"+RwªT#MQO1Fp9YC}zm :gP).*{@9[EוN;׳!0QKL>x=1@n[u@[* Nrra;`|Qє'V)/qPu$-PS ;dQVs8ƐŜ-l8(%Wf>`8K'*Ǵ)hWy&tN$ԓ9I}<>/VwP,&_{AYaCO17p]i(e!jMmɢnY)\Dkc]c鉲3pkBIĮ)y< F-+^z>C䤄.~+ ωi__5ɽۦcIV'g; ( 2~q1i|}踟=$+Q$ꍓ>hP?[7,wIT Y:z/d$US2A]JbG.)e fZYbq2PXƯ@ Of6(x~sm ȃlK3:'yA3)`JJ0%c'TQI;AZR\i-z{8:XXFU4 JKWbZ?6 "cU vh2$(z0P<UZ]"Gtѓ7<{ud ,}?we/?*-Xn(\3'kdCG!,,&r1: gbªrt?5ԪB4Z|ߕV{>'W;04GxANX"ݍe5ж_~W/~/ )օ0ɽHoqtN|+lxnU"IsmqV^[p6v2z?BJѷ"]Yo9iɅdO$D=tZh(A[L?A!j=j lԄ~*#}?<%z-XТ_* KSQd];kj F~Eb%MOQ0M*O= f!04Z.B<IWohUaInMOӢ*}P%!H2$q ܱ"MVx;jA[_pRr݊ 괩,kptЫ Fx"1q8fXct l WG& )VxbFih!j{IFWaxJ1[}#u2PIfs{񬲛puOYך}0g|c4hΩ,UU@𾋣_ \yCXB9G p#]æZ}J5\i-82@l:l.]Dc/pP>mJmR? VIP3NbYQ ֝ :5h)釜gjY̤Х4;lDi/0W+Ianك~?YmQ G<qpr ûSIhԄF:(v)i {G\b٭冭!$nz j;n2-I,C1knY j.8KBjT]$xwWh8~9q5Uwc6U{ߢwۡAmm-zHa{qxi=愺ڽ[U[A>psulxxۓVF[;hXm uRkjH#l y;kKPz+B;@W\f(oR={5&_EQ#Eݴ{֠ݣ]Y {{^3`"LV7Kߐgu g>QXW^W_N5g_&Q~"NMYp€Ie1@`r?VJO8.^Fѣ߬Xl}׌5Q# c=ĺjF{ y} qL+;wm`%N+)Pa`E78Xd,Y`jB  YMVvyV[ %)WgX7f=;Rh]y܊qA}u?01VR qP2 1j[]6fhF48ϊ7V VGy#=n ~}Ï,y?FZR%s ͪW~7>4jލ[_Vc&Sg>[ў;4\C*GxH7ٗX */ 3  rDo=fUw4ohvd-h "D*@*{X4 HA"]5 w5ޓލ_e9k#<߽W;TST 1~Z:'y;rl[{ˇazt5_-B3Z½ɐ%oZnsd嫯+F?A/$ލo @ac7&4%LK5Yu¾}G4#QzJǧx>{c9Xp "[zyLv\}OFZ9V1V\+1hӃ.b=yT;h1յwْ=w_~u_-̷ļun}!>!W{7ڣ767 2%DW'x\9^xQlyL@;5Der Za<׌8P34[c);t8Kʏ07G c)He#P( 3Lب_@ NZau($-2)op~k߻?r{Ag4 `Ih{)$h8n6>P) a!|;lXI݅ `&qn Ԧˎ MneYPgn`.6>t0TJhMDY6BMBk@{{@o؅#YS1ܱy'bO֐UBlDN[j)PKEC6.L,9 z鬨umAI^,][s>͡W>Ds0b>IZ.jZn(0ᶠ%Z!d\^ЌNY gz .$}͆Mv06!-m>&!!jDEu 0_1ixO)|Z:܌t4-,L$$XOZ{st1%ҚNɊHF>5  [VL\,U%uሆtk}a10?Ԑ G=`*ӥsN@#cy=U߫ @wxX(R#0f~IA|]p:[q+xl(Ш|LId:pJԢW{~t(">֟4WKjb;rE {WI &pLii? o<5aqb)0Ȑh:QdF]" %X#|90nyM) f1rݾg_(C)n%zh9ʽʺ< ץwH:4NFFQRWqY0)%KZvppͻ׺6>-A7c9h&SChcDQޮ%L+An&v'vsiQ qe?+gALP :0B,/Ya #dC_Q{m[utUT9]i,ĘH+w8mZl -/Y\1LӉwZTm? Oyp6㭞M'sUӺ3ݲp]t)7R~j[߬ќv72jaE2HUUHA4#l6UPhLabECΰ ZW뭄Md͓hƧn_HS[vkvwơ|"g۫*_S[իjO [Gw#}MPk5nB8TJ:X`Q= MVuFB#aa lC+^nhRtx!PJ !idV^{.\M5$I-:Q.`l";*G fTRT)Z]CN R瞄 WČzIOz/yKiMݧj1KM̳泭E*cVَB<[a=XQJ:$uVHyzf tga )zL>1&8W m3$iqH++VA3mxv549ew:t:/~xі\c;T%܌^\^B5l`,9LO&&Kq9FNtSG[?r? UreumHXb`uq"gSa>Qg=j⤳l>' ~cS5ۻnrbRi5(3,M<ᧀP{c>[;z_KTOkt[R=!>+Ѣ+E_D_TB({n%S];?wՐ:u e \ _~i E5e@TUK@ FV%3]YZ`|g%mfw*֬wP1 ,uXMV?ߴ2VRduE@X5 "EGnE9f'YβZYe3'ufU*Ah%Ôa}jVIsu_9R%c`K\0&mQlbZf5Ռ[ wʕ JC!:fY^@kH !r" T³ Bk zZ-=s^٫Ww |6Fp|>ti\f395ͳ+v%LXZ3Pt¹y0@aJB`rFWdYg/ £hbg;ǝNdaSQ2cC3)@t`Y֯!1,[_c\up@wU}}jKWZ)dW.:bn)r}`k?`%Inz D+:+ZI-\q%7Z왬8>Sz,kȺ@.7"ev:]Xw*peYq[v @voCha"B Dwc]\ kPO1-߇R;t ~ ":n9a`v (C'2ʯ}~ )uZr]3)# юy!(p fTq)@wf"h܍nj^P;\RXP nR\vmx:dݗ1Mڐow?Zϫ6B=E"&t`@n$8y\'ZI;=e(3=m~DD՛NW2aR* ײ3Xq&\0ռץ E@R +@U-,Йǽ$ѣtfǐF0֦|(4c+k5 idWszFD_t(OWFk7pn ܵUk`yl:_2@U+R͒K;;2F\а}4Qβp{ˀ3UU\\_0]/Ky h{$|/nǸY r|({~7NϬ-} pFxrKcΌS΀hT(x=Gg0mqS9 N>v#rSȆE\mw9Ώ)]WDgo(tX넳L/KKhRL>iY,$;nGF 'MF nwm!ڜ,& >U_/w/AnNĠ=7r>j )ao-qo\BO< ѕO 10[^c"|hL0Bz?ɹLͼLʿp[OC M"i(VpY7]Y4_3T|R< u_NZ&~nкtB6` n@&^N.S=K)AD.b]F ԭ2wUE;oGkAD%pn>gx9`_atL Bw"ϲn˘pMRP^S߇,c>R?ǟM@^-g7ֹ`r} 5c'vv[R(un:^v?Zx"-PkvJb~9f[W~؅TOwذrg$u3:K)H{=;z|b<PG bgx~c{;p]sz81?1w/f@a /c:INjJ:U>ʱ֨F9{;Cż[ߩoooͦI/ߍΈrKtSxM605;yި>^>~oo-~qqqׇBΫ3O!d0d{8<~py3џeJ%Yi _"勭kăީl vb 8?eqY[7Mv#I~)JM H`>ƂD}#,!if=!r IƢō{{q/p_qq gʬAَ5lI@wUVVfVVVUVq-,1IH 2.,=0oS98n]h{5.1n"PG%f9inݚuq>/6Ǔ4iT=hݏumǙʴ\xe& YE;<2Wn]^\Ƶ}X4Ԩ7Ci+/Bt,3 :Rd%*{S|q5A$w߾wgD7&#Fk=w5+TluS# ksKȪר"]-"KKf gh}Y$nN(jv٭˃d4x4$d"[]v#VEnb$N_~>w^2"/޴R`ӕrܩrnU֠J(f &N#̙S=ZQVϏZc[.7[T3SL2e۔"nfm`{=KOڵV{>s-N-Slα5GZڠEnڂxsjﴡz5$ tdKN!NW" Bjk: 9$mq9:P!>@hAx]I>`o8ZYy9V=3e4)hi:\+"p*z+z7i=z8}mn3/1"0@݁xRo['m@ާLh 0 S:9ʴ͌PNqz|res LV"+#- T4="՜,`r)=trm*O_Xv fsgԲ3a;/̣Yg_튰H`q11,8ƛ|e/`"V3Pd DDrOeڐ;bɖ=SkM{i~.Ю N洄/QS"RčK_F/S)4bA%nEq,U%.H|@SB/݁(+Ad5MYʃB5rA:et.u4̭Q O `)pB~?^ΌqͯDgϡRqNjuxVÐk˓WGf U•:sޙi8k}>@3m;TnIr#\6 ~bp_}53: ֮I\%5vۓ!݌ ;t: d$;Y09mw_TFHlJ˓`M&3},Aυtk5G{C)~Ok/Lz8qpPѬJ2*˨Br 2P/"賬7ZhnV47!i 8NK`!PD?PְxvO=;U\F~hya̤PEX&a!X}`HXlq_|+W-39,&93ZeٲE·Ꝟb]56DZ_WF!9D8z[atQ!.WL6*Q9Mj^k5 ,,FYݓ^9t!L6v9UٴQii00)楌yY=Ut*d"@s/?ـN 61MB#.Po/O7?_ۿ_'۷o2¾gzՇ5FzcmMkwȻ *drE vZv՗qWrl9ĕKTEa{.2^><.d^/T ]Z\UwjGxtGV5}cA ޜeI8ZQx7_pሧy̍p|0΁m*wwUܐp6ixy2eWF2Ar+~JuxgŎn+zyvq.Jgo6 8(6 68$(2rO3WhrI$B7 O GWWW 1"啕 {Kx|3wJȌMS5 *`$mΡ+1B84VJW)x޽?߿[OoB;iS8czA|Z*\N` CBr[ ("*FWZbǃoxF%)CO5?w߿Hd~˒g԰|M9LrWWE"aw]1$Jrk\ 'IylH.:&su {_D:|Eik0p84c>"(i& ~6.F s=Nx< xr\V7Rҵ]&`fhkmۃo/_:x8G; ݺ?P|6xuWw˕B/Q#<_&>Tu #8Pئ殊6ݦ\ oiF" #B0|`µޡ83: 뷧&QþJ YZL@ t;Q2?Z={GmEܨ㣇>ʔ(k9T9l R[yj 5aVخ!X&|#WHAp&iե5giճݢ z@b TۖlؔpL\tuM;0Ivr}5c. ]myk:/.}92QT\W.⼿+X':Oj d1dZ/|yp˃mφВvY V.'prMW`[`-$a|&UCO{{Τ#=a^K(y(8n>NNdQ8נ +,.('yt\PKS\lװ2z Etb22ꉣo(*b&%1(povCf2Yy&TXo=ÅsY+kuX~):n5ٱ8KRYI >r~E{F&ҳN:zQbkb)hR$#H]#i8l`\ptngC˨x~z?xQZ3= 2\$u܄d7`P$I.u.ׂ4˄Zx J:WVPAãkvU. lX/Tv,mA1r{8t3c`F=%޶%VJ0>$ x*{2+Ef!SYܕl7&QFP[%|8T=NSV/S=wp&zi:?%cp)t^ xX\V+M׳*CgVw5kuwC**Q0^[nzU 5Lبs®7ɂktv]*ٽUs`x|2km 7mٹpZI Ps0QX֡P%>^r'Ϗsm#Чֆ/Z*l#\|9sMOp KM] Gdd9z ' .Q 'KVl]b 1Vz2; k.$f)[ࡕD$pQSskP0LĖ2\WxKCuՔt 樜 sěۤ $De)@5B ,h{fdC/Я,:@YVf]C HɪNw+k6_gWV ,cO[Y*F5&lTkٶnG{[{q^]C^7dz73'eqvWbO8Uy?Kuď:ӡys͇)]cݘξ6I&pY-JΊ *[o9f9J ojmA5-0*qy#_'y>+IsMX '%ZD\n*Ls>w;hH'Y%4چsN°]<_E\%>~"#B0c _ zu:픲L$Hj9(4!5ꉴJRH0O'[>0(t pFTY̦')C \*؋~mJ8" s\;3LLB\#@Cz'jlH@3.2ȧhnlѓw[O݋]w휄Y9aN!j ,s4"#N)kOx=Nui +ceoi3WEάFx"&FьH.{WΎ2>wޥB X@vznӧ_zH92 ;;_r岄/ yP.LQ<8$;,j7H(!=Sa2E2S>8S9FUَ_/RREEgrW5ԶeˆRx>ǎ Y^@/]U H{aGǂnXTŽ'A2 \F;+8Y}xig£:"[ {8U1@by%+{SR:$Z>@kl餳h.dTTY_<ݘRWQ4c}E2 ܶ,ֲyZ"4jQOKFZ3c|P!kWJdr4mTTuWy%"aP4[>j[Z&y"Qx^(*\[9Q4Ky:OOAq݋r*xQR J-%WN RJFԔf]^[ծT;d^ޯxjMR<=~K?݄k3Y_CڂVZܲ,-N)"aƤx엏G Vln,Z[dSJ;L~NzQnnmM[*}A;r) 1\kw:7oӇ:>׋E;REZYehO (ـu6Oi$8ݗҐ_b۷5 ͪDJh74ZO95;6|u3>}!Svʿ@Z.r6qOZiFOi=,4AF##]tdڞ貐dGLK8o^+xAtK1Hm*pp +P劂!H ] `rHjdwM x9uo U>}@QX2@N-:}OEDŽ8 -z /+5Ԃ}&za"p 9@\]2 _Dc\6h[ݐNi)0蝟,|=*_߫AJ&t8o-)V[:rYjw X OreJp|e=MR2acLg#M!.X)U K’]X- NU1Ɋ 2Zr@Em.L#7%(W-|Gd^ŭA<]čD;.YH"F=4[a7Rw (U9.r^-ZjZw\WjUD۵}"q~Q&ӫڷѴc;o2ReI /jUp7\Mu/%>ADxpQ5P&m _35{]u^*f[{z+KeԾgkT!`9Ē&P]~׌nmfЩ7 v)$8^_+i*9Ƣ֨E +4P.^"}ZEE rm 6r/̥OGJD1˦piKO[9w;v[s?C<:{؆B?_>jU,xqqݦK$O1hg/D$\"f>+D5F9y9؟I>"jz)p쎃eЉ'7X^.[|[l]fW,H=iS.zz;aww\n-+QY=xyvX-%w:OA6`|C>}x(/jE/f)WG&5,,Ͽ-NCe/JËb 6cj䝗4 Pӌ~/a)P5&nߖL`.2 XxrG DuN[YVV #_, H) 8H}d]m ўcx*AOcIvEI4vE\GuẉizƼw0(O6,|$Dwdv)B9 FUO\!/LIT4Ry|s~h)K--8,<ŴYj>rLȋvx]& F{fiQ?銅Qy TcFV ERfL4?,I'"K4z&"4BltW[ུ.^5*swKد˻0 ScukP`K 6fv.lI7՗8av^/yr7 9D>NuzKK_&;}]ly}#8|oF9l An@gq٭~w^v)NP;jz#F\Ov5{checksums.yaml.gz0000444000000000000000000000045013232740241014601 0ustar00wheelwheel00000000000000kZe;R0 D"#ɒlsLEä8)۽n7}\_}|^)%2T(tB\>checksums.yaml.gz.sig0000444000000000000000000000040013232740241015355 0ustar00wheelwheel00000000000000N9ޤ Y #p%ud}eֻP_9ǝ.3@9ZAO& Nu6ę)[𜪒u?W"I$vx/c';V ГqV#Nr(X)ηK˂V J?xa+|ͧ'oh#'iJm`rRx/-DzoylxV5 ҳ2n#ԜyYhzڡZ]PK% ]5cache/ruby-lsapi-5.6.gemnu[metadata.gz0000444000000000000000000000105614554465252013454 0ustar00wheelwheel00000000000000jeTn0+L/{n HTTBHpi+@(rI2vVgd$3~32Yns[wf-*fGP6x9"Fy$Ӽ8^W+629S% @ᷠzc!x(a 1`5]P^"U52b]ϳ4[yQ_X#sxp m#EwL<'޼>pe̢ `߀s ZPr4}3GD Jd=,,*%=ʓ95pu8YƪG˷S;fz$眦<+a̳IBlGoBw?EGmv݁&qH27GH2> DVn2N GQγ?M@fq`2 Gaeο'YLiFYLQ@sf8ܓxIxA c) $N01+B:$?aO! m4 yOp5%oooc װ E<%j?(v7~Fn; (n$fH[? i@⑦(XODk#8"$gp?#E4u PCQZoq=~P,Oa!~ݤ'N,c8'a{9QGcuU| EQ6E{x Mpά%Wk$]}B:~8M8L~6qV%nXisMry/{{$gl1#AC36C)t8O{m&|o5 c| ǐ 䊧 R^ ]?d`MJV$O;2);%Xi{>Z ((n^q.N>YOmN0~,6ER^O%\`Lq) QWE˫A3@A V:>|Ԇ Ph<'>2J,0u,ٹ۞YΡY0ųt1Is~ wf.$Nx62n@[v1)E0 μo$Q{F8@WըՌ0YOkO qΤ{Mqu6DD)q:YVvVPTP, &3 M}+IÚ2: - !Ώ`;zkM\9F7 7ڲBW~26/ D;9A8xX T"f8qka66LӮ[+V-P $.LX*lwZΆJYBp1 ~7(DuޘAI FIVx^quuj>X>>͂p&Tdx$ < &AxWO71[EUihu4kN4PmA 0 r9|BN|( 84*u8M>g.6J7,B'cՌ52T?ƀs1KQd)T[.Ţ\,2e4 Ť12uʇe2=ŸE2)rQӘUf[>:dv::zE eC+ZYKr2D*p%г&@3#g>$0upy9Y0a,RGE2*xt?a**91u"&G+3MI`r ['9:` {߆55N- Fl)m;N.E*ƣ8mިI^UkЈ570F?#ՆR,AFWV491r-lE}jBK.t%DB!C (:Dc"Q"09iZͽc^o&jᘣG*gO‰cad8* aY7H\mNlTB8H$mq2 |H X|YtY6"<""`gTZ&/`Q9A #69>|'FYS I퐡< ?gƵP U-ZZV +eշ~t';9vSvh(HFAdUFS*0j>AW{+IAv[vd[z2=}OkTcz vG ku\}[/^[g/v /_e3~{Hi l*vk5n-o<.,6a>ZkAC)ǐlּ >c'Ur@PbRuQ)gʺUg[f :tW[/E_Q{f'![{;^촷[~O~A+Nsͦ؄%N'Z3j{6ֽ&}_oϐwiN^<I:; -~/9}3~D}Ma󁺘meNnzycFFnN!-ܿ|;A7zJid@6a:[ `wi]^{{&fhVu߰[޾ڭo=k?;tD[hg:%Yb ~0~^Q'z"!#uL5Đ6_@"TkGz[n?YՂ{C9Cz6j {i@_*EKG f < 2_[ufU,DGjpM}FOfF#3Mp1nDA%5I\8qr9sxډ+ & 1ZYYژOw} BCT׾NЎ>Iv/%m)}I@s2JiG~9|{+a΀W!7kvNoz]ۮ| wNuķ~WEPm;OEJ{];?vՌJqV<h: sYh~C`/I$ܓv?@(j{{I'Dii+wGsѶFlR`qz4&qӆJwLCZ1R[2'cu#e: t[GwCf>=s|o@/٘xX7FYyDayʯ1c%Z@4G$H&%]ѥsms4]Z$Ό&;kyuA._O>{zm9][;꾹`jQc-jԛҒrUcgK=wj %j(usoJ9dͽqpf:gJ!яMJ`e7McFJDȃ%~Fdz[K^0pF]-{>Ek9rʟz#PhݠAl~+3:*Jz!ဣmY(!18sJ+@wã,0 #B/^ivhZu=qKjNdlϼ0ERg򐏞C {:(š8!»Nh*g 6Ez7ԉG+L1d|(L`8o(+'= N&MX5di\yzr ȝP"($91jE`(Z>FEţ(:)wZ"A YםCNDꮢWsW ÅEbڃ.r!).4kIv[W/.{doG#ƻ׃ywwu~4PY#>m4yxj7cF]/@ !K,D_RiAtݰR0?ӋĿ"f3. \8 [λHMQs0M)tG vhfbY?ՙ2Eq l,H9&~Brڛ1ӘJJC9ߣB32°冭.u)nM 2.s{{V2RSu aێw5hHUj}~JrLl3mg3>oO0 Mz.a_EoE"˅H`d)$xGnE޾Nŝ/FAzPPsdν0p&z_)׬<:Lut g '5c-puwTѫ?l&am|&$8. (E7o-ΏsبQ̄Lŋ?ϡѸN?P %"Yi 9zs"Fԋc(/MDE(eXx?{}F|`HF>f1ou͟&(]X&'u>mH^դ@ ތ=1|ꢽVL0P 14?&9iau| %>a2 .-Vɘ& ,Y(-[@l ddi`;;†!ְ%#fw/wf rS F>Myim C̀]~[ 3BwcJ)ژF.Va{ Fcs:G(jKm,][VKjއR<İIC%y *{u4z)_+E E|6ET`P!{xMDtdADѱv`6a;Q_gf~QYX". g&DT:Ѐ=8Qn 7h: 5rwut)(N  MU;??Y|VL1>yWiC O<k=廋||)d9iZv~;ov7=4H6[5r) s"qFPS"///ޭyJ-7SEW&#p[ oݢګpm<7>/Z( 6v婼R_0^tۏly@󢩒F!{NwER% i(Nl\AŬNᬓs_9=?IŰLЛ& ;P$zs ",8V4iqJt~Nb՘W0O`jVy`~Gka| h\z>CS58`t \@)$uJL:kYc}=L}mY jƺEGP45/uDAQ`ȩEkP9X٘.i[0z'w1C7gIJaꞳ&/gg?X)RX:>.B' 9 r}P" _M.7de N苖 lc [4I"QkB!0T1"IT<S\)l͸@kb 5ˎHE ݞ*B,·^]n  eL)?,{Ɯ޹h昪l-㍜GP[Ժ?+`#/ Ru'f.7?7v*]Fݸ:l4u IԩOh /NMѕM@M':3pGt`SpD+s\iX%oU3^_#Eڮf$oU)[@^tFvb55$)J/W6=4Js%(#q(ETאZϜ5Rwk +ܖyL:\* E=D/W6\1ԭ|ܙ%A'Kh!*,*-P*-ZʫkYieE_˚aJLUC׮h{0-Â5Bg e1,PrY[(V0YM#1VF8Rݶ;܌s)OTT4 ~#[rT,1( u"}./|V( ˒83zw9*LBiw;Q&y)?k 2ݧ(d fѪSo3]KQ+IIZ+$Ɯ]quz¸.KvwC1{&LEk ކ\ ?w٘=VIx 캳νe!y&ÚW` LE.? Q X:sH=GS%.$#HF qШOkxKުӔb mP{Y kHSOӻ1Zf>}2EKNm/ xrzsyE 0v 8m$:4ˬ[|WG?UzVr0Zc5Њq/j}z(PY @& @|~+S^O^(BLTRPsYAX>g46=#L2vY%a 9T-$XT3EUyQ)8UhQ 4sM5zk?w s|qkD"6'm&<{-5[A@2bBUnC'^(])^ˈS~=9$ MLJ~Q9ABꆟ!KEËi"$U|٨,j&9Gg&il>־oԚȋa1MhW ,};X^7 {bJ9ݦ-,3ϳ48KHb^$ ?>o!yIUo8~=ۢp5x#$}oURߌ|ct:w8#v]fe0ǙZLvJa3V i-'I[Oä]ݔn=ƒ䢐 +[m&.;PX7y.ԛⱠ?nKOϜʵ2 Eљ:1y"sjT,m0wO1 }riwp$Ǽ¨ѷ2Do0~'4V$0z~Ka"敄AL@zE^j9+J\י8+)4'''Gy;%oN{^wxs4KN1/饐=at0;kB9}Pr5ÛW)z)h6? d!&4ʗmF,ΧKhm PXS#O1lA5)@)Y\QIh0LA>+~MM1pRpX΋cY*I]fbZgS[^_g9dg' c'r11oi8N@Xe&O{3K.(4AHq6m0iFE0M6Iͥ1U_b;^ ʳ&g5Do 4!13ඨ /4M ߙWS;bt,dIUۄwͼYk0"8:@r1u,bH8M۔вuw^nJ;貴fZd='[^gy ܀R޸m/[[Śh ҒK9G;-8 {hՊdt ՗NCfǦz|xY;Rwlw suX'wco ïʖ!D^2lI%}r`SrP/ zEG[&tGT>y#_d7~Nty2D@e~IUzDԋd6~1>^ §3}^&Jglu^0h/(f=]Yg[$W6z]F͑x8Xu#ܓhdh01^]1`\i:pVdY4vq*oy{z]aWv`l)7a]cJ0 &@.a֖K_}\\=p$7G^(R7*xM$/J?)K l`nF0tSĥ5U)ˮFNl4Y+$*7qYǔHcJ_~(uՄR5( hѐUBT1rXòH[2+Mn$a+4P֭(%!Kr u0O0UaޙPȵQu%Ӣ#)(oj1JÓźO`t]ʒWW]{鏹w| g~iW,N:"g>7;{UJ؞^۷Bl;b wV \HDPADvIm̦-ΜzhZ9G{ۯlb]_/P죏bLUg fY\#d ^=Ze IAWJDv &iSoҴ~ 5iՊoe%Ϊ1.oȨP%*Jk%oyЧvk^F;iǒF|Giu|l χc ZWi-%i.r?]'n}aARnRnesq,E6HC͟_w.v}|/YɌn+Vm]v͠EIìxrXR7ܾ> 1 _ qR:~f[mG5LSY=N*>+$^>&vZZ힛<0]bV+tө_ {ӜT/pr]$R1ZL",G e7/9!z秧O੭OgGMMnEPy]ayDoAw%d\ s1`uCd5;5*LfB &ò`v#IKQzO2G9e侺1 bj9_~2SAl)gV^Bw%/A\S+C:B8H˻]ԅ'Ԯ~낋Dny}lLfUdk3ʨQFg$4t$yik!2``,6w~=P?ШH#G>Ǥ6X{C;+Na%6,B2X&+YN2T,u_1ӌZ`f3c=(֕>ri%۴;hzv&֛@:]-h[tdbdenٍ<ڤE$`c](yۊ{«&䋚6ЧX]YP  >;P

wrѻ]enY62P?Hf%띜5ԗ9H,$GufU /dc~/jz^DjhbQ{Pf{:>׶DA>(rSZ*\?h){J8QxfݠK z4"iQj! ?G ,C$(@K Υ+xҩ:>ԪpದH.7 g+< ]a P]:縹- mnx$]v\zm,_iu0$[;[a_U9 f'tI-|O!U]{h Q5zkR^q~QyUPLղEIE]֝4^^Ab\-ǖg. /]~"JP9tJ}9%7@Yպ+ #D)S,aVW ~yvT\տd]{~|e/jMo1-Q禣N /WR)BcKh*xә'/:AcͥU\lЗιVt"L!F[JcsBSx,tm{^׸Z,炵Hi"guRβ&QYF>O&uRמ-o\ρ4l.. m54$UP{*rkUAt,lF,o豍;V.lϺ"t;lR,g˨~*_%Oq_eܢeqo9bpҾh/<-e?M^4Q([f"MZg qZb eD5 φ|jA1I:^$s"%f{j;$F!858_,"2[ =;dlʌ("ƣ>ln6zFAIiyf~ɻP}w  L6 D~gPJ9~&uyUh{"afh4b_"뜔_λ%lhSnV>Y E,A{!0ƭ ܟbG2X0NOKYMRP==zɡ|Z;јקt?! iC7WXא(TtZŨV4X@6o->g >FX ߞ0<1@T^]583Sovi<_7Xe!rby%/r) Ԓ>l1^@ &L:Î Cbi,?~uvWo 9P;Q\QGܺőO|XLtcD? c_YhNpÀ?^xgH;*بHR k#kN˹re>c jr"⫀r S<0ny6]D0Db}#:}sE)hRT<"|: EΉ%NnqH祥TQ28W*y|mχpsS/ŔRYUeoI\Fv~>"_դu*PaQSS$ܨ*OY% -r?#xrO\#3,".Ղ֒GZ'tm{0$ҍd_U5b&xBO ~F}q3gf X.uKj֌|[VJ |s&.%AxP-5nڷ2f$X@P6 f]G{~,o$G#"?t9-zB w@']\'v>?lЌ0W\)4̟b=µ9oԕo$r{g}t՗u'\`ج9'p__cPI_twu}!^~FyM{(Gk);C@/"=ͼk튳ls3^ΎeП~SfFӮ*{đ2W;Am}v)7qI^tRi;\8`c6W:/|1[AC%wdC_A7~5O^jZ;Q*/4M 4ʰ<B}YEjQ:|Q)k>z(\`]:i﫝%'Uz[&}Xҧ#JI^އ a@2X3/8V6vuŌ?µꂶ]N ~cB!'e@xko oI^諝u+FAWTց7 /t.ҏ4XAy8=q?m6/vQXcz<($8ym-%g'u^klD,+kWycpzɭL7[?OAM褟\tDZqBFmHkcE{M3E{\+P^pjnƢd-YYaUV){|R tA)*rU|y(pcq="!2W|ٲ1uOMM=8M9={F|hOK5CK{^Q{)jbԾB竤09mxFto4 u &bRt(47yWo:uL1>ai'S?k#sh&F1ѴRNDoE$](jR98UOE/%n$TE|%Xj0򟴦KLJ%x`Z#i`d!$~e/)OgeҫlɣY`"DWemcIIoZd]!B#6C !N]ƐtGj0R xlq:_A򥻾fQ*x5>I\g|n1lMZ 5o)կгK6QUf}U]C*Y>&S9r/ɛ0Gpe:~+P$amy@咾OV+bC'~2BӃX_峪yZ Y\ZoYoJo ^r}6ooo$+.@pWBR9M\UL!Wr"/ܲ[թPѰwcv[GX>,[V _uՄ>WR։ĔE |cJ&_1,HA;OAV( 3jțQR9z%9E1T+StV4^TEYו@. hFid:lsg](r4&bZ&cToZ1bq<hy`){B#|Uk46XW_??{>Y<֐ݶ۫04ޖgaYc)~[@p P'cdYA48 d,^g5[x纩`a.wB &*}fhG!u$7czcA'8tAĺr4$TA70/{t};es[l=yO̹)(юk) =Iv:~i'xA1(MS{3LG87zV-e3(6#" 0 ګWkXIAۖDvb7&kr@>B_ MShZ(:g5J#"?QOv*ӛ8֬ Ḝ_`P^&C0t&9̛:Pd"~A7Oܹ q_Mst "bPApG+,m&~)58Q8[5f.ѯ^8BHh{VV8:]1,!jiB5b#C ٥q9eQpY<1мj)L,_Q 9hoX)/YI|ux[T^ќCp⧜ڤ8:% 3ͭ[rmhTjc-riN}xX9oG5 ZFk+&Ki00>7 Dj8AP8 [Z" `c*T?| A='jH~ߙsH7<%th8 ~cv8Bq௙7 h ekL*?FaO+`]I:z/ǨʢO OTtélYNmeP?y-*[ʞj:ohh̨ծ.b ]R, xZҬ.%M*9^EFQ$d.6g|܂?!]&+&/_[ $ÄV:LSX)&uop]m]tN!L m0 2" *`ZKJ#+R7YPLpv^w7+".CCgVyua5^J2ƠO`d#v""J 1+3=ޱv"s`D4E/cъIXXG7A t!Z ^@^]qF{Xa0̡B$;;?v~sv9Y, s~13);[~{*#EqN*ow* pOe8V"9JńJYi!b~i1hRŴe!Lܩki a:͙cUWӸis~ d4/Zv/m5\DLw\os쨴;V+9C,ê㼹eYPD|B_gQ@WXa&P9 DΝ+(dhqZ{TgzR,y~$" g A`P2AFו`[P"@Q23d0|eu64ǝ~;3zggaȮ"6tp5'aaʾXR ,󿜝휝|lvWHv|Χd_zǃY{T$W 10R^ƿ wP9'ѿG.j 5Y2}k{ӳ ڂ] ZsـٰNdYrf7HW1 BJ>)=gJѻ]b hrlSЩk_ò8Z\{anu\64' z)N㲅قV^&ԾKG;X㊟RlcO5ʪu Z$-sMZuUNM^ )Wbe}d/]\YNpqkGRm\_=`fKcVps(gkk.M* Vԓ+i---uuev9B4= #mi5Jd 8Wi.u٦ ;2_8vrCVil0Lh~Zk+Vo^4sCP^SZo4l(=m//ްw sv~qQjxKwzZe$c,NRdÜ9i,WVjg5~kӍ +o_ +#k~j_PFcCJ5G,w=GoS *u\~Q@E2ZufhҝvLc_e3fgj\װZ^PΎٽ4$YD/Mr;L I|06kIC$/,2M08oT ]YdqPӰZ9bh2f#g3(@g0eO4;Ď\`G hclc]3<89ch@̊ V+|"Ye`H~_)hg 뛌 ӭrW]toYNzF>lqe֚KlpY>͂PE)y&OaVׇ{ eCc嘭4(x^Y|}q6gVaDfp>4 ʜuGVpOO6RE_j(bU[a[N渓">o2BHJ1Md67L 7z{34 c!3 p'&j̀Q-NW6t KV3tnIETT7.pGTzxDՏ)t>} 6 b,Hf?!OC]̄zکJ`™.bHk v7ӌ˒h&j 8."[ʠŋLïqL?Iq^{,]{GoDd11"sUhÝMT5d!(rVw6leؒ CZUVVg*UZa\Z{F);yI{8ot%}]vps._72жsV"<-ph: JjADžL.a jmU5(\zK\)DowW8.uTAy$05F=xGu)hu#{L| 1=i d~K^p1ܸtuJ>e!sjLGcukvvQ_U,gVo4Z{Eq_e @!l;qeOJ* 1q/ˑL<e}Krgۑh[GfsS}q JG~Cc[`^҈RM-Gs(ј>{Ƹ,aC[h`։E#+t-h0vբV>ܥ Bɩ\3Bf-ew&l'ҙQD.mS :3YGe/jq[ hX9K֡𧦨.7K r"6p;q5GNk[\q:@ suk510E]g&W_\gЮ'M41܅9Hkq\K1.|{Q9p̳'`Ŧ}, WѺ薴EǺ*kK}C} 3y>8_>@S\ԏ e m9,S2mp0vVXL6dzJ]+8T6`+i<\m6o'>լiCkA%!>q8oYP9JUn4qVu(M:m*i*'vV,]BnTR7Ղ q 8BP8\z驼|ʆ3vP~X,q].GFwn^rAܹsQڹykkZdQ.3Ye_ <\_D]ݗWr nUcI3xKYTe\5MsdiNQuOI *`webHtEgIrw{[ 1B:ۜiW㔩t]gvW;Bغ' ao T;[ӶA9K7z ۃZ%jW.?FMWWWTj9K׵ oS/ӣw cn*ht^gry9A[-(jԬTmnVhHg%U,_rv-&EZCfF l |sc)=9>|;E//mWPk:+ 8}+ <+;*;*S/y7nxgZVoy&ڊ _:xfI4XIؠBy6o/*wK&|r(V{Њ-V=YQSlӢq }E!^{-9՚]󻭃ؽ2X'NTX^B"Ng̃iPe^s?bm`Mywr1Ji<ŋR==LoՀ>{ˀ!ɧ;O]$n\X wK 81 fN뾇2&T\=6%hBsÜsڹ?k cgݳЃF|u !1v`v@/BINM)j:YLBwꉵD{N#_#,.!*aIZ/?WC=?f?;^;>|x7^-,5@%A5/, {5JһMn33ɖ!qĦ&*xjQZPo*7z2vxݤ*5MzIRr}Po/wsesXzѭ?-!XhTKΙS2Ќw@K`;dRU\GGu|R= wz~e}_?)`[B?G@^:Gw ac`\~pwDUj-iԲCGnm84mq1R ۅ>#1/G|;?-kSej"^f8?4p[ 0vjyH7axފqЁ2znYyP&^2MΪ4LkA"0ԣZuwTnast3زC jtG4.x޻4ϡ$`6% ^m%}"Nܛo/wk-6嬚qr;"RP!?{[ޙR)p/"-j=vQ4?xݺH[ZC%!nI9l"[MD8hj ]je.&M/K 0˦r?vOkxiZ> 4/Z1GeD ˃X W%X~%ճk#B~hKEPV[49*(䙘O*om!ad!`0BblۄF Y Gc=aqfsAPb4φΏ2Nx}QsW&Q|0>ICiuO/xbY?dnؿoF.ۏWx4 g,z/|fayx9c$ M9AS 0*MAvhO1'hA(l$kl 2 ?&;v$F1QZ?βtjU( ey`g 8G$ܳM7ȡ$d3wHٛF@ІX~ʂm/ǷaҳY~6SAjG=I{do@}k(p61^ߋ4"%`5!_TRi ֕#'dxlӛ#q`f,Y|iTeׁYWƥJKhR!$kEX KZeaΖLyc <^>BLsi7e`/4}}|vs"qI0CzeHmew%|k1W}zz!x3}dB?3m u,.X0lw7[0Iq[R`8U&*ע9riv a]b1N.!Kh`jjL{Z|8(kAdӏ-XE? HF%w=!CϬ(۰"sP' Q2vGp؋)#㒂;\uN{8[6'i@ɰ>G#V3QJMҒ7o7X˯Zb+~.w\䗵;a}GTo{7wJl[lFMh6Nw;h5A:oTߨW=Vs1Auި[AX5RlJQs[LSmݭmJ[^تgҶhZ6hNN/*=mv:mDC)=fS6Gv':IluUkz=K=ٮ=Z8-A $UŸ@(8|kNZ?ߪ_ͿY߬CMꟁy4U [Vɿj0LW3u Vkj ߣ,`g VнrD N9w02jZʹiD3{=!F| ;`O9%J\eN|=X4@l`Lʒp^.,FQ0LkPrLCVb/~'E-B@hЀ1bݡY)[!Ck %'-BуH*F{aw>Rp6W])jMH:LKDC+Z#| @"F %qH<(8u&ɟ YQ؟]#Q rc$"AA83"9EM/z8:g;qSdy$_4O-rgoMpр/>Щtp^0[\}wx =?k5[Z qsqǎNY܋ ]~I8k޶'EX_+4}A=9Ʃ4NNc}OD`eV#;n:jj6{y(R5ϰBŇ1єqil5_?7lQ)ȄPvZG!>cܔO쯦 ('pk@ex[в|7>?f=vU0($0 9υM??Z=f3ִ"C`l}KYT%L?׍J!؈y)7OMI*X<| ᜊ1A+Y* d:hr|OcJg߂ŽD͢ н0Z67Z]>|`U7v '=n.IU,*ì%>Z  W;Zd5-z1 8չ?Ktd/)\fb<"Ԟ @Wߍҩ0$VzyuE~w)N{F@!tgq1v"^J[΢Ly7bg0 &`Ȧ[`rƲ$i tb vkp^3$|,XxvH&#]Xq/=GE( #w>xkBrXG.ŮYf8LұkOϡwE]L;YC8E'w'7TKIp܀Jܕa'lھLn'{1Zp2u-^M6ix0HMgw:O; z/I bJMxS~&l@ڄZt3yߴ *ĄKLBbX|bbsR{,ZL HEa[ &T&F$ "5, вDJKRQmq͉nqȣ5N4o3#C&6(wE@R,q)8jdGRt!㳗)-^_{wM=ޝ2h98]9eJd1kQ8vTYf[ol U>i_ʫH`IMB~{9p{KvI=Gok0 KɫQQyu| b^j7UjP0GQKz(!V㗃cc#Fkl8 ;N0^$頱=%sZRhG])UcYw3\5i6h~b_c8{ɚ EL|*N,e^99]%0Y<ɢVq^q*pJ|ppqڀi W*Lfie|]: ŭY@M%06k dJzE*QZ!wyH-VR/v/EAqb /[r:u#śC6ŒY<*cV,`(&ZV5Ixh˓~WqNey+R1Wp@-']Q ֞`\Ra YR_~5~(Ø/{2+V LIcJ'.|O($0tXx7[^Vd"Z EX{a7]}=ߎ_a#;66WZS7'&f~u`~܋A}K Ҥۓ)Nz.&3W^,si!=?5Wd [kL" C9Upw&wotT}M+DZSjwSLKG$L0bǸZ*9<%٣<Bj5K\t]@4)R+M )rJpxgp61%|%Ĉjwgho3 Ti0p!E#I6# nZĬ=?vH< 4Tpc?<{=O)12\ILgtV8V_fNX1fnoPmBTW@*F i$`\x䉕=]4`6 GSq+wd0<45, 8j+U˭i&dMocOSiT.d0|OhΧFX34ᏏKKƲzLܸf֨_Xĕ%)h ~cY3"2臃yr|Y،w~.%(.x]*&1W\j6ED< jicZ0 "D7^nCт3XKȥdF: ִtPbEGl$1AٔZ8Kc"JkWVu~i#@q[&2kY+#t9"&d4]`ޫ%$q# )If1.j@6:FuCUV9~5lP%xMg]]v-MS?|}u( i*ǭ6$W%L tn:m'/57tL%>j2oAtlDM~:I~9jC DT޿mp=ofLxί ċ}knTε 35 2]1Lyn`%uC썢ȱ'@_s8&7թl!qG3Ȕf]T^z.f c߇qy=LvhыI5M2d';d@.ivw%VW|.LLIzw ]mV:mq~&S.Զ关50- 8"$3ʾny\0$!$<MJԽtܘ-O1X{bf0"ߡ 9f6焆̡$+Sk0l4@:c)Ԟx*dY>oݶF?Yww/05lPtƸvd$ScL^L$8&.={Aʊ .Gݔb&(TփcOnKo=ϠX9gIqT=8mo% ƅN]vn6D=PN@+#iXKch^R^v_T/9TEgji+Pڭ ^Karpf7 X9KI0 l> yWDŽs/RM>@sE{t#%1 QpƢf=c6@Y/ӡiNQgҔhdƝc'2*9Z>FmB_o,.!0ÖFguFȰTf04)& ʇ&aaIw Lwq))xړpW:^9٧#1V@y^J~㴥p_݂-_@kgW>z+G#ʙzT~AGCa~vq8j9 6B'K ;vڲoh{ a|^"n[!z^)Ӣ!jf0T+{, vQfnk0pL'5{8O"ڧ+fQ>}y\US%>>|y^g"uF%ihˠ &AI< k/hPYW(x$-ȹJ)e$׸O98bӘP2et A@&ųK7f 5~2vĖ 9 U `976Luv{\M^<ĩ&ʅ~c\I% ch'}œ$bnC0 IK|HJn# M6:{Kw0mDHָӠ`«kFǝbneY %t'u iolԌ>;H/i:Q$D53LךߍC^JQ6ƶ%pm_dMg2=! L52@$ϲGj]Ţc: [VH6+c=Wo.D>GӢiѓƒz0YtJOXZ}BݴNѸ[zYP=nȊ 9iH#A0i#;!˯ltIBl:2M3^>""6Ioxf涀vyI _1&rK&kKjޜZho6Qa62-1O5_b~R9ydl ޮi": )h]9POF ;ޟXU~_1^wW~fi|[$s5umYd0<΅ 0xyO)_2h\.bx)hPq9ՠMXEvHKFip?Ybz$؟*K'5i~gS|ПEM"C_FbR 2Æ%t~J ΃'%R$`,-jo޾l5UHՋ4>oWL5mL}BΞф*my;o%61%D OFϋ0,)#/!Iz ƃY\1[_.ʼL=p3=M"ל)E6*KRҞ$ui8oϏ?=ΩFFe+ZDM(2^YZ m 0SfӃßڧ''e\N{tPi‘xby^5{a8MEӑB]AGEh$o2 y^QT 鴩qлd_pܶ92il|Go3/]˷n{O]Sq6`0vWYW?47"PՊ~eiFhdub-cݰ|2zXY&GҔ NU+-\jH昑Sܗ[.hbLHˑCn7OcNƣ,@5 ~5_.Ӽ^peI4Xz6JRWFҡv^F~!TxbӬ~fi՞~C3Ԇi6 ?6׭/J,&ɚ$+78:^j%G,T bT:eliˡF|pL>Fir`djC)iԸ4>iUHLb"CkxJh Y5?B2HF9W@\CEWp9JRplƥa"݁D>;iP .dkBSrR-* oU22{4V^n*RKf,ex'}ҎʔVp/#ֈ`nDDkGfy+OzLԮWkZkBh-K gzCGKd c̮0Q6_^|h>.~>N9^ >s8䧨<붭{5 Xs-/6>q;GX *dmfnr}}]NԮ89eCc;:Wp =Х/ޠ#|Gg]Agʹc c@ҙ/~T/}]We\r| ݔês()-Vl5N U Ng{8e|SX6v”9u [1sܯ̣ievam\1[= zRmBm>WAew9l! glR xx61ˊ!-wz<:Ú}v 51OapEd<#K )̪((ghfݻ?0Ll\UjV~ZwU"wV0ͳ55(JUF`92w2ד{/T"iZ5P% #ð@R9_xx(Rܽ{#to=O;~xL{9?$=b_c0s2f鞰ϠK7Q ̊ne2auJ ;E ?nb2|70)winX7$Qa"{,,eY"Z`^&.L6|$0F_[t/hX20V- ˙lr!#<V䂝$C8W9{/$h5 t ]UZVa?LP)>-~zPxX|pGAj5eMrV0I6dX'F(G-f@xһiy2 ]C.~Wn8q~Crа˓mY:[]w"c]cVڬWb81~:1[du&{4d#d^N l; kpκ O)[V@o.b0b0;zĎ09씽 ry4¥;`R U/`\N\wPW?I;O>?Yoٻ_<oPDn8>A{/pScLPR &P9Ǘ-'5ໄ7a3KBn A`5+lhXa)h#B*n8'h-&Xh^G$IS je.q]Qr jH$ m4|feN ͯ906F{Pq Ҷy5@=V\*İ-S ظN6?ZF1)З~ *ou(+F! jd,Y9ėl5v}rb!fF yը-?X]Y)^Q~2 =!e+_m<,̣+je$ (@btdJm[İ‹YI(7Wx\GZ( ܈sd 3W5Gƞe;n@|@=-?8(| .͊r0ryOZ7_G0U MWٯX0ITc}3{[Gݹ8\vjrfEùEW=o%qg>C %Ʌ'+N9u:rNA~ۘaȴ}1XI t"|JG#[})Z$ZkԹQ B6**IR>Q'.8DMw/>  )SQgra[e?@y1K;4G9]U"[)"<~tUCJz4g # ,WPc~֢EPm>sW 6 Co.e]90sL,=Edg&}-D: LCp^!Kyǫ|8Xr\'Ys)A^x ~MSt 9|S̖03 _+jNdd7,W@ E[8])h[ \Tk|M7A*#vETaY+ePCڣ%ck7B1֗pdn~(U˅kӦG<л r*eՠ 5.-OX IJk %~FR|5XT7]A[?zݵKNdI4 hq'Hp 2qǸÂ˹Pt%$7=_”P 3"5(B 3( +%JQ H>Ji)ne#GW4Q!ˇ xȴqyxw Ff?J]||YF\w lG`Fh!dąg0H13ōΣu66qK<퍁'sHHBZsigRr;:Vr硁.y|'*?s g}ш~fG1((VS*c>(X2&ެ &D@ F"1pTrR?IGyxt1 `8[V%O/2ɘ| ?á|7AT40^za;1s9)V Pz|8LG84-ݚZʩ FY訰 ݗGh^LŮF~_؅{qx=l !T^#R7)`?^][ڼvj/ݐ7Kf^?%s ]왰L$iD'w,OFKYtTVѻ9>+һ9jtao*Nd1B?1EOHgb†RST@:ib!+YG>IK:0}wOz|Rd_A9q1~0tXES($A_ W_Mcv38,tj!9EuXBr1'i)xADL!y@ 78OڌhrHMD7srϙq[䈅q &'Xyɰ&teBiua+ yUZ?=(h'z >O@&w5c|׌'ˤyBZo,#)ʦh> K!̻v y]@: ^bOORL [k'Ib}n%f1 D`XGRC+6>ӂ`’Eڴe97Khxˮ1X J&*%5N=Z1D~cZr#䒋H'dciГYTt<$&#T쓀6%K)!LRcRU>JVŜ_ۢEOQ/K~9z%QK׾O[+k%yMj*UbU[hãNrRX-LI^7GZPi/jl]S0EL"[oq/d3p@lɫvKg)DCybúv=W(j* Dd_8pnmפvn@le )8z8E '7*LQ<^<&PH7M:9y4D 2@\8 Ípސ=ҘVqGΉN⣏p '/1yTa,^0yuh>\{)1"Xlm畨4 ~A/ҬY23FaYICUBa{_)>Qvp}<~إ4 "\c9g;բ"j&cj6>m~ŽϦZ.CɅP)Q9rBHF0[ê`y%!a:vgW\%aǝ}`1 }CRc`i݌0Qm4+u!ׂja*n\Kctf--k!j|1 OBEVJ0'@:HQɎ 4f^&='QU+Қr%AȋUt-bm:[lӘ^ LFM#IOE.Ien)V=E9c{'+hAfW+8W+ Q'sGHL [sN7&b]W $'Gy$KO8yٌI:|x`A;VClͧNO$! BP͵Xbo X,2kɺE#wl$g E129vq4@ʑ ǎQ!pɘ/'[Eiμm)V _?>-(?9.JdKLkKڀ޺w_ |FFF'_ ^W4ZyYTlz(r,dV(&671Ɗ92uO|2&hV~G-1D|5 aS,QHHDm s(,~m5_Nj2wg1yKXbU$V7_6ZyB.6T#9d܋"mLE98F<1i?PX3vvxxNܴG}^~~hz,,[3!n٩#8$G4"Z[=PRO nE+,ĐbzָIZnY⊉w k@VhD> 1G53n8oJ*R[iAšDE~*5#1μ1 'GÛCe+{깘hk'tVE&KFgBN>1YhH{1T4OQoӾib 5Xi@@5H̸pBYJ~NUX/okxQRk)upqs2_hɤY"ݺcZ 'Im6Ux-ơ#nc5Ax0̌J $X Ƙ0McJ="bPGŚ0Ǽz FE3iȞJ7bl?2Qj0@t~ d8(b(H MbIT:4oe1S3Hݎdc%\Vv9Vt|rޯ5GALɼRr RKx`2AML-jj"K!:*Uȁ8V oaiKsضЩMi>vBYCn*W-[ӶQ0&URllڿրU$VG5])T -C FFx֞S< |X59( FhtƹLVvyW(nRgŠOQ'NseŹb q;Kk5\Gׯd=]Br%|ʙi6dGm3 J"|zP W-)Q9>&Kn(t8~[ `XG\C9N.kRt(C}u|8lј1O;ۊ'88^[Cb$AUXrQQץJS z|œRM4%CYѥ̽-ĥs>^M -.:Q*F?_H{G^$+YCzcq8ȵ5 z>XgqERpuY"b`fu5#y&w_B_5ܦܦ56$JL<7)PCۏЊI"P|' }.Zw|yqEe2\.Mh+-OʇBˠhw ieC8f:cDn=`{%t4"ZDa1 hRIX{}.Iɏk F]AZ`)ᛖ7-Gikx=I%ᾀ)c$dC) &5[Xy%5!,b'P^bŒ7m\bGG:ptY0JBJ%po3+-34A2 kJyLBpѕ44op4LsMW85_mc 2E½4SwɁhLӎ%tDr^h`;R+%E&ŸKtCZ` %y {^+פmY+;a⌛2WфL+p 5 n7`"&2UE@It0?@ni*F WcEԒ$6+1'O[,-fOL]?8bH0`Zp ԩ(֖HF2(U'ԼPjdm㻌dUxᡘJ6>R5C+14Ny4T>]g/6:meoRtѺtj7 m!UqyIB$,'i -bOү W77G%m(r [#lml`?*AAVmɥ7䡕 J˛!q T7 寻/ޜ[R^6 z8r=s[үh 9{yJ9&YgadG>/&(|[01[8 }e"(,0qmDhB\נ;~V7l6SLz}[@91W1z2@"LDȶu(},5myY4|(hćÊ"?U+.ǠÀɍ ~ ȉKOB;"գEQ;b-ظLӶsj4cRdJkl+bU @*e 3&Slj=F=`a+_64#dȝl]}ì2M+Cp؍ yO/eiv?l=g{fѥ;;X%}aZs:A/Q(G:\k3ݱ2-ZLJ,*4ڹ~wLmKzQrj:?= Lf@g_x?D(約V~ůrGc= S'data.tar.gz0000444000000000000000000002564213313665447013401 0ustar00wheelwheel00000000000000'k/[}}Ʋp}[|N\I¯kp{#<:$Iئg34mǴ1Bڝݝ]S;o~fcsŋo6'zMc{󝝗P~{{7lY*(yO. {}ko|bϸ1sG,~zzۅo]NwƮ_/|o]فvz*o:cl N[gQ댝t=8ju޷ CSǺZGG:u6?j s>! :iهm9[ g)=:^=99p}SKL:ﶫkQ8z!^u{^Rxw30plACb1 |99@*]!S-dA8v+hŠ=``Ou޶+ubhև9=XKm|VX kAeanG7;&mїhڨߗ (Ma' ]θq[ b"} fM@t1z١;GJvP79{XfpvM]ldh=.j0tyb+05Ө0AEfC(>a:@ .\_YcbI[JUt\[4qh&:֜K{YޫIa }- uʅU'+U4}~d`;ڼOKwBawcGfpU 3>gkf}j DH3U(.p I'l-˱10ҳD@<*A5sgl9=F0x猒UDk T {@yJmxL`aAĂ̝Us.Ljs_af>: kgn.B@j:Ş7R)` B'}\hG(E4Qm?7XAa ,AR6 8 `6nN{jM>Ru9 9E/ ڝ-Z$Gx}j$Vq몪BW\WUM/wK;"m~J_Ezz b  Pb o14`3wX66bqlhќ[lOjlʦs6Mpb`OD-~uXïO ?V~HƋ|ZzhcPFIj+>B K 7bqYumcwG;S|v^sߴaaw^wwY32;q?pe…o7+98.`G|zX|Q3!X r{t}aG \[S`c:I z0x/uKF$ 4m eHt]a׬>w߻UEU֨ANWmg1GWlIP93N}c.AHjVre|TA?"2A0®]2( @Ђ[gs,i|5((D; EKGE v5@ܩGqX|!zFΈb QHm\/aX-N|C^rzz(˅]t..ka𩾢F7j9=P -8,}Yl}}M$~TBѲ68TXκ쐏.cqw 7bfX-z-aGюM 懜achn$ Qf,)EEArUƍ!*cWN Y'dƵW -Ek8ɴX赬yMx p]j'E'HPD r4Wf!@DSLJu9v]ꎡsj X-PF0Q2 d( VD>5e`V +1f\ƆA;9 PّEHzY\g(*~VN gVb1:*T 3)̙l:Dܮjs3f:QN._.HEn_) n1|&୍l $D`]?wM@u;t˗O¬cE\ZeP,D0Lr|P,5cDkPAB6,ܛ{Ul2XWepP`zhK5"6GIͅڈf_]X7n5p"%8/`?{VfBFY"p |j5EnBex19+ {ůf/vhHeElW"i0P#PݥZ7mߏ*]%=A9^# 0/~@v`9—{JBK>)qϱvoc«qvݕأ5#+r'^AQ ]D.`vκԻ"Ht} k/Tʴ̦݌x%Z>2Ϫl\ u@` jD\W f/yxEƕRqejXG0|ˆ_r,ވ"3Ip1K|-FݩnSmߘa=31&K(Zʓh;u0Ww4P||VfƓo0Ε)2 ^)RA_,HQ~3NiXl码=>_}SCƋ?bequ:o+}t>lW70.GiG~TNW_z7v3Y >jWiv0W]hOBlIxPoB B r-I9=}fYY=~4)|gk&!#pq{2̷J4VL*Ɩ6WO9IJSZE.8ʔPԃo) Aނ,Y0ۢ!؅ a|=5nlܚ!潚 p1ÞQxv\CIQ,7,3ӳ5w=eo;Ya(WfFh]r+@H8BD#)-:rh@4Ie@uA8zI/ m)bRU1;@Ɍ !eД03l-W;s'[Utj |F)]*F,&Jy O+Yef]es/8\U;%_94@S-bzisgrl |xd{je\1R9H4ےKG֙y:x6;Y(-0AAsr=e*tjflp<=BhE,VSf 6ߋP 0 FLt̬Tx/RH z&HGoFetaL";gdu4A[rn=Ʌeku?pO@SRNdww@ӧO/dMHd$\l {~zzNA۽w'&NPKd|5MKY$p'eX3JI90MXMkf[A6M6*xOHJĤP"Tc? ee@3zj;㐋KyC3I ?c;tcrf}-H'$ي5\* o|,J'KpD*p[fzbgj"R8mЃ.k ۝̫] #Y51r$ 5*ɲ ː>;:WcDžĽTdGڼ+2]R܎$It Q]н!#87k;"i U IAR 7DHo&o\l&d ]u/ss_,ddDuUnWنYBFk_OIukCC|L}[MqbL|+\Pv3kjIWU*dƎ1nFl+3cT^ž^0&VE_"i"}7al%m h 5 L*ft&ɩ#+ +®O! ցw'Ɇ q `K7m#5ָPga6åǥ֘DHulP剚B *j%Re _6eث_A˒J'ƪQ.mpSIW{BWԈ̑M7 ́6RMh]emى:#@8˾-6| `WX)_JqevJ7@;Q w pR&T%sхXo+Ha]ܱ~Ltg9]WE`3LTZ6@J~s+ ad/ېTzT"]]E%N |B$ʇb y`uwF.@3>o=)HTP8)$2}R23U1sc'MǤ<@ՍW /Gt,I0]@68Z  T#)%5A:@z=>آ3,,EUF_X.} i}$iȈT IŕdnzjanDyH2 qvTj}7d_,`X-R1Ո_V1ȮHzެRZNݽMYHK]bkD|JI$pcj~Ӛ[LwY)܍<l?w'Z;w⹂"` :ez%|QG y ,.࢏.<1r㗜`嶒|('. qWpkS:\Km@Я2lVhFBS-1`dfP`L\wS +Jr};Lх]b:5#c yNtZ| q\'"CHI<{`X64?߷WfĭXTHw֓٫D$<,kWU0D&9d8fP;$립8NIYIJmbSx&-ݸ]8FWͨ^=]4Hݥm  z: 5< R]U"jɝ )ZLL2us:$,#WT# xwl厗ehJ-L$K%,%|);5^2>*_Y՚ P~(۹r/IP{\9oHmĤ>OYUĭecahrfP=8ㇼXH.yקB4 3Y o1=S|K]M[y,CNdYNq9%ᡨZvK&cժ${tǟ'[=Qmy9;`>vN`)[T5/ Q ֽLgKps 1NuRxαK[YvGjl:&;uA}khԷtVm _mu:њOh,%%M7>4j$,uN%z"̚!*+DU*Bؚ~cߐ+fZajȤi>s*۷T]]{6j3>7^۳ A7(CQ[B !mtu`3WtWϼm }(/ߋx?b[  _tF-$o#aMR[Z{2ng=애LɲXIf Y`M!k0BTPn 'fq7A^Xv J*Lx*HpfO癬) 5+`2HeGrIЖPMy[c1J6"/&N.nFŒ_\徜)+LfdtH~:jSneȕN^:ZFbem;Q*zϪL-Fa#F\zd=L ;y̝A7E+.֎_pf6r1E<,lo1$U:ie%r!_KJUNfh&g\^fb>$+nd-\k'o{޺W"O# -Lmkr%/6eAoђ+;XȮ"XY& ,J 2A%8p.+23:Zp=:d׈cG z#b}T_ z1UE pZ6~^TJn/J=/UdAFUsT drA(yUAWr2%3)0f*w2)<۸?&c fnI2[U{,jHfb9Je/&Sxp^e$yDҀyUeU@?BxʗU$_! ":,=/S2IObm1xVkړ;;Pcd!V%*~%ȏwwieH\ G BcrwS,CtDb:@D<93ON\ͿeLJq}*ww'+߶IM}˻`b[?}6Ն d}g ˣ1.U*l *j_|CKIl83T3p3:_-БM˟hM4&Z!3.hFJ(!fQ!cUնBo *aMZ+o*^YLa2pTYdK 7UJ\U\= sG3_s96%_KBMK_M|>DY/>qYLMHmR=P2 k\w%߫ %ڎI3'Lm}X2saAoPڊz~LKu K20t'O_{.~+6!y%0`ͧ|{D <_g>]Wof%zejiB²KkE3wF_+V(VtvS>+HFd$͕>yrƽU*Jon{/Hmj3{6o&؏& ]쨋>~UGUMKčGvר$RdOk[BׄHXenre\OQ}{&>x=.Πb9֕=aNbU}lP u0 cH*@lM[$46)Y4j`ad 2DA Q4`Xi UXS&hm`=2<\ݜ%*-uɣH.4yrN{Yv& $vʐ } 5ז bNEhC`TVQ8/y6Oag[l%4a1V|bbϕv[32DRnP@Ǯ 9M"ô&L< }#`L vap|nVSqAmcF nDbL.*&LJwg#%G7MwĝZ|G쯂{e1Jcf2`g|&֭oC:5u?ԽVFd<Y/\ R5h) bt;Ny"{Q[Nt0iBcCܮ$|QJBِq/B@liYv*Az rM@X7NSeވTthZ$FL2R^`7hOe| TT NqP\mi@ե:~8a\bv\UnUb>_]`ě^5hzՔ\YL#ei 0ZH4>%Ȕw/r;sSwCF.>͕')coƺ;[O* &sv"Q}v_w@Q4+Vp {ҋT8 Hҋּϛ.nbRhR N豀& h­ٔY 0@- [,j_bH",wι' )܋!/ka7bI&ߝ{0צH%_`{0%]RYddL.bxY8cMO3j%AHW6嬉Ͷk+pJx>N% L0ƶz7b÷,,_eŏ7ER,ҵL^OV1'H~i&GP3O6k}*;checksums.yaml.gz0000444000000000000000000000045313313665447014622 0ustar00wheelwheel00000000000000'k/[e=@F9dtff枀626B}^o_|//?~?*k~^߄nV9g`mt9}>'z.T^j`F[ v-2w,iVqHy֔*#[|$uxguH:iZݪ8\sfl) MkFFY$Œذzl9ߦ܂tm\` [`O LcDܡipq[ S_Sy1M;2I>`ՃM PK% ]F*BBcache/net-telnet-0.2.0.gemnu[metadata.gz0000444000000000000000000000120613326057144013442 0ustar00wheelwheel00000000000000d^X[VKo0W',H ]JP.B&~Y5Bw>i)RJ|x$ }າOmD߀y B.AZC אS! E<kf~M (cSVN4! u>' :pDOd|è.p D hDDLϒ0>YTЂ C9==.LD ׭|kFEMɋAMφo1%(ۮB(M >f쿍γvck3x>I;!r=q{_V'pꮕN8 WlM4|(]`\3ƶZ΃0x6_+={5>8t~;yͧ%>S'wEoKl$ĪXoԷUo7l:qa Bos؍bkIwCǸwodziO$˓8Gkk,xTZgѭ,Gb]ύ ߍWcw Ա+z/ugz|Ys֓"S‹ ߆xC1 ]WD(vBW Ɖdāx1s_-?uͿ~1p|C/CĮbõ `b~ C8D0?J뫃Dxyvp$*mPIO՚ ~$4-Ѭ Ddػ//}'f8]^pIwfnT,ܘ x0&(@ ::!Κ4zk0VyhRm!3tD[T%?}eˠ/w.-6\(LК^?@D=S#F b8u`3OsppNX w,O]Sz -3JV#yX9v16;a\ O)2ׇ}  2wZ d{\#rm|-C/]Y 궬Hj:ECǦ0 O#8Ux池GhJf,Mcؚ836H~b t:<=Y`]v +m=vݐ!gGӡzSPuSg<1_$xwG{tăv;q]TT\ī%Xj=0ٛv{VK`/b ̺Qr^| 7A/e 2x h'xx"w=(HsJh<R=tGN2xrF-?gɄ #e"{߽T_"\MGl\h4eNBã6BebGQ$2h kl3z}/Lhhd%FB+7;X' 7v)^)Ts\XshЅfDf7jA# "\Z¢/-LTj $Ad&ˑ!Ma j! -g( ʯgJnHE& #w X51 mIcvpr,KڝEI@D0OPbޮ},eݮ\O& AݚZxoW bia |MY2ruUQ||>L g`6%9n{i?q' j # goj86/xM8%Z)Z> BI;(YqP["JHmTe"VDgDDh~jjs,i0GSvĿ c { 0{D@&dVs0~sߣLj?`@/gNbv$ 1ÑJ)K N$gd"ftO4P2: ?]'ה/M@dv0[gLƨyM)'O2q1) ӿg1_,XRYGƊP`IүYU6z]T#`QyO@AY*PwU{_-mLЏTO~Ge^]Uأص͏>INQWE_8q lG'oe;OɂWfCT.g(0K%dԡQ܃}׏ċ=~Þ8@/9hR H|WS"X;[[ V3WZkE@P s2seP?ȻA{N_w|M~#3kQDnǦB΅8h&j`&F5Y쨡ͽQպWnx縪b]ΌDdA(oĝ ;8``ZpaT Q SRDw:%Vp97SrL V0)8vy-qj(CFII4R>UKJhect4e[GR%,`j( &q*E>m9r ՜C%rAİˑUZ)LX#om>>#FeS{w|A:>N$3]0IaˍIT[D 3:j2_Ps32aÉcw6'd'^QY X .bGv4!QkuR]q`Ve,xL{PTf f!&N3a $8-B{|KpF;5&$ԄC7~jp|Of  o&]ZBKoq*EXLBV L$! uV f.Bd-JPgιdqu+Ty 稇EKIOߝj%G ZN*c.զNwePbQMQə"}pMbppCw1q 1Q)41@$>潩6cR}fdkn !~[͒SPzs8TY}O1N9Hi?2?.Yz.*Yzb=TL;:u)26Q4h\8bcWհd<=܏6JrK(JZmksoMtcbCذ (/g`xWhM8`[o2`6-0jKkx+ lHZg)[POh辽7";mbC6(Zo` Z3 GF\L]BZV(FS .[Gh%LscvklDچz`Ci ǂVO]pG|qyu{uk~2pA sa5yF԰,4X;e6a3vAS3k begcf7Hn@[Qf־XW Ȝh19:tRw,Jx5YxX>I8£6 kW+1֤/ʲg*pn7nUI_^WfG{_WI_PSa$iI %וjƙ@=גq@8Qw?5%0ۜ< iy|Nb $EvnD [)nhnOɌ0Xd@XR?BbP]cUߜ#0wyӖF %)%ŠI)(cr5iUM[CXvCsʐ}RcofI E u74א!%e4Ů_H(y:Mzg'vJlhe"Flã4R`4-{[5:7݃ȰrY/:ohtN̂coK$S~"8+G;cGM W^y Nmu٧sG7V:j>?gSXs@m3Jv^.;3f{rd/]AVHl}O>2-CzY:CxJ?1 ^6')¿ L0z]Onqz%dTVTdˆt;x {RFPn%,flӭtsV.kxCGnjr _EularݴHAXF+ * /[On )P$[7G󌡢4,嫁]2p1@c.|1qoPWm*m| |%W@tMuA_o( B5V021)y(eUޕcT+\6 p9`q2uBa5Ͽ\:^Dn?fDc9LvS,Vm2*mP$+EuxEEȶHB"pb&]+/,&ګ 3X0Hy(ݭ8UA"zUc\C?m:oxp ޱ*cV']gKO@?W"]\uF VFt4\8En)ZLB3iTW P>ZUpTMp1xp"JQlDǶBmXn-婂BNfE,=ř uDMUa)Lh<ұ<4*$aJ)?,x([ J|]+u, sˋ8r<mEHuѨ)]h{\UvsKVj*\i ,LA oՀBy+YǮ&`b5sR` U FH\3%ˈmvn%2>`Z} ' ]&W̋IWI_XwsU[lHEoa,kAEyR.yp1 B0d]P[)|^ֻVs(vjomEШ[4<^Hh|'4| 샰SuH6n *\739Raj]m/W+ǂyպxR1Kl#t[镙4^P\{`a=BPL 0'>٫U tZ7z. `H¾bmege9ݭ4WO1ca1jG1ٱ90 Vw+ kJiF?,7uwc(+F?G{C@P[6Jhngnߤzk"& :53}4gހ瀪fNey㢰ʞX{.*bU,S]j7/d&+jtg7ihrr8Js5b/͝UV_`jJA7lշnvo_rMR5SyZjzfrમf~M>`x#qju.^ FW,C&hd1;A--\e2$)]*;rz!l2fLѕm"z^ *{)LK|}Z rn`E%G5;lZ3cY1T@{sIZJ:\ eF.exŃ͡|sRq13pe[xQ @gKzhIURE4Up7iFcᕬtXb}E_d 8FxQOSS:fHH*'K׾KC=˟\ׇ仩|QY{0*AXOIp;B.;q T58SE t8Z#:PԵwoɁê' V]^ݚ ҂~/e[vbǑ{;82V.ŃtZ{fQUTtY*b]W1GHjt&2MZ"-z!2U@-eA _T5*ць zD~~}od4R)LK"r ʄ:~MXJ9&e %UE7q͍V,p}fD̛:!' 1u\t3dߺ):;xͬ?]Jlzܾ|1ְEKO?/}V/xƱE#A[ML޷z `y!3;ϕ󳥏. st|^ⷬ@s*e_XK^~>'|\~o]]񃔧.up=G# &< bl# xXQs۳kT/A? ݘK"1.,*:Rv _ P9芛re6`:7Ӌ؞E\ Va B^o{[@8^I8wO??~R94pA4.LµK|<{բ=00#Cow&1+XyQRv$7qZ'7cdݑ~@zDATS7 tU`2/ j1HWc)՘T.]NrEz鲻0k:kY do'oOVKLJ(G~5.NS{1:bhZڷsEKs\/yA<c]T\pG+xe8OƤȮUvi? bk qta:,F^ of2rRi<&w Jɻ8m}{TX1Sݦ.mJ./QN3UO^alpšۭ䪙gTp]g,:YXVc!_{z`nU`KޢEUIc@2\FwU'=Q lZѢBy%/*+KD% WB9ŘC_bβ F ddt^M^@Eᴷ'ByY$%AEժQ jq:7Q+GP5\U7`rATNJC=y51xT{q\4u 5;=[c:aeP =Rn q>FUn;::f1gX!yCuEj3W=“wET_ӢRSNjOƽ?_Pu֯~i{&NZNM5 pTM|Lg#݌*Ͱ}4 w3%-Bk8F⃍9_I)EU>"Yxg#wHV֯d&ѬUr&m:x9M7'2L=V9ՔN)X^Fȗ0V._a'}%u(%}PO+Yw(PKh c9raMB/0l2v!L'TdRuũZaҾ]Ix៯2z*OK"{6isx]dESeZD-_('HLB1dd6|L(#w$1t"7NdKZuu$ށTiٗtM1EHB}tRLTL0ϰB LķJ-.P9voSX:8H,n1>!!/w6X*8Ok)Qd<]3Phb<,wU䯼ҹפ. C~~T9q*qn+b,j%SY^NqЕD"8aQXA+*.0 9lUjM>04ywL!Em. )+E. _4gPBO ?W?k|Zlы#{\T R/aofC^0&:kealb%m YS"#`#Q>bYz?Vs$5|uk~ h9*k5YR),R ~Q9Ccf9XB,hN]om3*Ɗ,j1wm&%wM'ep6|LիѫUzkU'XcBמ؋<}aeou>PvRKe^ШލGL\&e+y"J.e$*QȈd r&U䥄u^z}>fOU?FLxz;2TV|Ǔ5*aXdߥM/]q\߯+4@~|>'jjUT$Rc,ŲYf2)If}LJ($7\(5j!»!r-LjLT̞n(Ī GeàK4Vn4>/B!=굨u&awU-Z|.)t2ţcE4o4^J`/ o}LޞU 8Fhlon>k'oibvs{h| $@2wzGg'X{yk/ `zdRS_^m }^D0߮No H5 _'#|*u^|[@Aq73w~(Zᛓݵ1xI>fkZ #䰾!h@iʿ \.ݛQ|}:Ť*߄Y7 \z-AT]\z}pZoHAB НjdGr'}D Lk|>D:\*F:нrv( 凴 C.*(^~T'Uy<}>;?checksums.yaml.gz0000444000000000000000000000044613326057144014615 0ustar00wheelwheel00000000000000d^X[e;R0 D"#[_I1)zoou/g?/+󚦾ID4H]"OF0D("sj/MO3_ϼ˶NLh<5Q(ʔ$W X*),0 1h* Jh@KJ"qD0rR`@9:^Dziձz:5?qjcdpfY5bv#r]iNCD@Ktá:jdx!ҪYG-|Ql*\wPK% ]>K{{&doc/rackup-2.1.0/ri/Rack/cdesc-Rack.rinu[U:RDoc::NormalModule[iI" Rack:ET@0o:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/handler.rb;T:0@omit_headings_from_table_of_contents_below0o;;[; I"lib/rack/server.rb;T; 0; 0; 0[[U:RDoc::Constant[iI" Handler;TI"Rack::Handler;T: public0o;;[; @ ; 0@ @cRDoc::NormalModule0U; [iI" Server;TI"Rack::Server;T; 0o;;[; @; 0@@@0[[[I" class;T[[; [[:protected[[: private[[I" instance;T[[; [[; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[ @ @I""lib/rackup/handler/webrick.rb;TI"lib/rackup/lobster.rb;TI"lib/rackup/server.rb;T@cRDoc::TopLevelPK% ]>Aܶ3doc/rackup-2.1.0/ri/Rackup/Lobster/cdesc-Lobster.rinu[U:RDoc::NormalClass[iI" Lobster:ETI"Rackup::Lobster;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"*Paste has a Pony, Rack has a Lobster!;T: @fileI"lib/rackup/lobster.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[U:RDoc::Constant[iI"LobsterString;TI"#Rackup::Lobster::LobsterString;T: public0o;;[; @; 0@@cRDoc::NormalClass0U; [iI"LambdaLobster;TI"#Rackup::Lobster::LambdaLobster;T; 0o;;[; @; 0@@@0[[I" Rack;To;;[; @; 0I"lib/rackup/lobster.rb;T[[I" class;T[[; [[:protected[[: private[[I" instance;T[[; [[I" call;T@&[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rackup;TcRDoc::NormalModulePK% ]g,doc/rackup-2.1.0/ri/Rackup/Lobster/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rackup::Lobster#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/lobster.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Lobster;TcRDoc::NormalClass00PK% ]kC8doc/rackup-2.1.0/ri/Rackup/Server/make_profile_name-i.rinu[U:RDoc::AnyMethod[iI"make_profile_name:ETI"%Rackup::Server#make_profile_name;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below00I" filename;T[I"(filename);T@ FI" Server;TcRDoc::NormalClass00PK% ]K0doc/rackup-2.1.0/ri/Rackup/Server/write_pid-i.rinu[U:RDoc::AnyMethod[iI"write_pid:ETI"Rackup::Server#write_pid;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ] ,doc/rackup-2.1.0/ri/Rackup/Server/start-c.rinu[U:RDoc::AnyMethod[iI" start:ETI"Rackup::Server::start;TT: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I"MStart a new rack server (like running rackup). This will parse ARGV and ;TI"Jprovide standard ARGV rackup options, defaulting to load 'config.ru'.;To:RDoc::Markup::BlankLineo; ; [I"NProviding an options hash will prevent ARGV parsing and will not include ;TI"any default options.;T@o; ; [I"JThis method can be used to very easily launch a CGI application, for ;TI" example:;T@o:RDoc::Markup::Verbatim; [ I"Rack::Server.start( ;TI" :app => lambda do |e| ;TI"A [200, {'content-type' => 'text/html'}, ['hello world']] ;TI" end, ;TI" :server => 'cgi' ;TI") ;T: @format0o; ; [I"MFurther options available here are documented on Rack::Server#initialize;T: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"(options = nil);T@#FI" Server;TcRDoc::NormalClass00PK% ]ln1doc/rackup-2.1.0/ri/Rackup/Server/middleware-c.rinu[U:RDoc::AnyMethod[iI"middleware:ETI"Rackup::Server::middleware;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ]a14doc/rackup-2.1.0/ri/Rackup/Server/exit_with_pid-i.rinu[U:RDoc::AnyMethod[iI"exit_with_pid:ETI"!Rackup::Server#exit_with_pid;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I" (pid);T@ FI" Server;TcRDoc::NormalClass00PK% ]?4doc/rackup-2.1.0/ri/Rackup/Server/daemonize_app-i.rinu[U:RDoc::AnyMethod[iI"daemonize_app:ETI"!Rackup::Server#daemonize_app;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ]@ *doc/rackup-2.1.0/ri/Rackup/Server/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rackup::Server::new;TT: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I"Options may include:;To:RDoc::Markup::List: @type: BULLET: @items[o:RDoc::Markup::ListItem: @label0; [o; ; [I" :app;To:RDoc::Markup::Verbatim; [I"@a rack application to run (overrides :config and :builder) ;T: @format0o;;0; [o; ; [I" :builder;To;; [I"/a string to evaluate a Rack::Builder from ;T;0o;;0; [o; ; [I" :config;To;; [I"4a rackup configuration file path to load (.ru) ;T;0o;;0; [o; ; [I":environment;To;; [ I"=this selects the middleware that will be wrapped around ;TI"6your application. Default options available are: ;TI"= - development: CommonLogger, ShowExceptions, and Lint ;TI"" - deployment: CommonLogger ;TI"# - none: no extra middleware ;TI"Jnote: when the server is a cgi server, CommonLogger is not included. ;T;0o;;0; [o; ; [I" :server;To;; [I"@choose a specific Rackup::Handler, e.g. cgi, fcgi, webrick ;T;0o;;0; [o; ; [I":daemonize;To;; [I"Eif truthy, the server will daemonize itself (fork, detach, etc) ;TI":if :noclose, the server will not close STDOUT/STDERR ;T;0o;;0; [o; ; [I" :pid;To;; [I".path to write a pid file after daemonize ;T;0o;;0; [o; ; [I" :Host;To;; [I"Fthe host address to bind to (used by supporting Rackup::Handler) ;T;0o;;0; [o; ; [I" :Port;To;; [I">the port to bind to (used by supporting Rackup::Handler) ;T;0o;;0; [o; ; [I":AccessLog;To;; [I"@webrick access log options (or supporting Rackup::Handler) ;T;0o;;0; [o; ; [I" :debug;To;; [I"*turn on debug output ($DEBUG = true) ;T;0o;;0; [o; ; [I" :warn;To;; [I"#turn on warnings ($-w = true) ;T;0o;;0; [o; ; [I" :include;To;; [I"#add given paths to $LOAD_PATH ;T;0o;;0; [o; ; [I" :require;To;; [I"!require the given libraries ;T;0o; ; [I"AAdditional options for profiling app initialization include:;To; ; ; ;[o;;0; [o; ; [I":heapfile;To;; [I">location for ObjectSpace.dump_all to write the output to ;T;0o;;0; [o; ; [I":profile_file;To;; [I"Qlocation for CPU/Memory (StackProf) profile output (defaults to a tempfile) ;T;0o;;0; [o; ; [I":profile_mode;To;; [I"-StackProf profile mode (cpu|wall|object);T;0: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"(options = nil);T@FI" Server;TcRDoc::NormalClass00PK% ](L.doc/rackup-2.1.0/ri/Rackup/Server/options-i.rinu[U:RDoc::Attr[iI" options:ETI"Rackup::Server#options;TI"W;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rackup::Server;TcRDoc::NormalClass0PK% ]-2doc/rackup-2.1.0/ri/Rackup/Server/wrapped_app-i.rinu[U:RDoc::AnyMethod[iI"wrapped_app:ETI"Rackup::Server#wrapped_app;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ]1doc/rackup-2.1.0/ri/Rackup/Server/middleware-i.rinu[U:RDoc::AnyMethod[iI"middleware:ETI"Rackup::Server#middleware;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ] 9((Hdoc/rackup-2.1.0/ri/Rackup/Server/default_middleware_by_environment-c.rinu[U:RDoc::AnyMethod[iI"&default_middleware_by_environment:ETI"6Rackup::Server::default_middleware_by_environment;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ]X1doc/rackup-2.1.0/ri/Rackup/Server/cdesc-Server.rinu[U:RDoc::NormalClass[iI" Server:ETI"Rackup::Server;TI" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I" options;TI"W;T: publicFI"lib/rackup/server.rb;T[[[[I" class;T[[; [ [I"&default_middleware_by_environment;T@[I"logging_middleware;T@[I"middleware;T@[I"new;T@[I" start;T@[:protected[[: private[[I" instance;T[[; [ [I"app;T@[I"default_options;T@[I"middleware;T@[I" options;T@[I" server;T@[I" start;T@[; [[; [[I"build_app;T@[I"&build_app_and_options_from_config;T@[I"build_app_from_string;T@[I"check_pid!;T@[I"daemonize_app;T@[I"exit_with_pid;T@[I"handle_profiling;T@[I"make_profile_name;T@[I"opt_parser;T@[I"parse_options;T@[I"wrapped_app;T@[I"write_pid;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rackup;TcRDoc::NormalModulePK% ]';doc/rackup-2.1.0/ri/Rackup/Server/Options/handler_opts-i.rinu[U:RDoc::AnyMethod[iI"handler_opts:ETI")Rackup::Server::Options#handler_opts;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"(options);T@ FI" Options;TcRDoc::NormalClass00PK% ]^t:doc/rackup-2.1.0/ri/Rackup/Server/Options/cdesc-Options.rinu[U:RDoc::NormalClass[iI" Options:ETI"Rackup::Server::Options;TI" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[I"handler_opts;TI"lib/rackup/server.rb;T[I" parse!;T@#[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rackup::Server;TcRDoc::NormalClassPK% ]Lؽ7doc/rackup-2.1.0/ri/Rackup/Server/Options/parse%21-i.rinu[U:RDoc::AnyMethod[iI" parse!:ETI"#Rackup::Server::Options#parse!;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I" (args);T@ FI" Options;TcRDoc::NormalClass00PK% ]},,7doc/rackup-2.1.0/ri/Rackup/Server/handle_profiling-i.rinu[U:RDoc::AnyMethod[iI"handle_profiling:ETI"$Rackup::Server#handle_profiling;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below00I";T[I"'(heapfile, profile_mode, filename);T@ FI" Server;TcRDoc::NormalClass00PK% ]Kt((Hdoc/rackup-2.1.0/ri/Rackup/Server/build_app_and_options_from_config-i.rinu[U:RDoc::AnyMethod[iI"&build_app_and_options_from_config:ETI"5Rackup::Server#build_app_and_options_from_config;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ]|O3doc/rackup-2.1.0/ri/Rackup/Server/check_pid%21-i.rinu[U:RDoc::AnyMethod[iI"check_pid!:ETI"Rackup::Server#check_pid!;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ]<*doc/rackup-2.1.0/ri/Rackup/Server/app-i.rinu[U:RDoc::AnyMethod[iI"app:ETI"Rackup::Server#app;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ]/Ld  9doc/rackup-2.1.0/ri/Rackup/Server/logging_middleware-c.rinu[U:RDoc::AnyMethod[iI"logging_middleware:ETI"'Rackup::Server::logging_middleware;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ]6<doc/rackup-2.1.0/ri/Rackup/Server/build_app_from_string-i.rinu[U:RDoc::AnyMethod[iI"build_app_from_string:ETI")Rackup::Server#build_app_from_string;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ]6doc/rackup-2.1.0/ri/Rackup/Server/default_options-i.rinu[U:RDoc::AnyMethod[iI"default_options:ETI"#Rackup::Server#default_options;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ]fz-doc/rackup-2.1.0/ri/Rackup/Server/server-i.rinu[U:RDoc::AnyMethod[iI" server:ETI"Rackup::Server#server;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ]%,doc/rackup-2.1.0/ri/Rackup/Server/start-i.rinu[U:RDoc::AnyMethod[iI" start:ETI"Rackup::Server#start;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I" (&block);T@ FI" Server;TcRDoc::NormalClass00PK% ]8D/'0doc/rackup-2.1.0/ri/Rackup/Server/build_app-i.rinu[U:RDoc::AnyMethod[iI"build_app:ETI"Rackup::Server#build_app;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I" (app);T@ FI" Server;TcRDoc::NormalClass00PK% ]g|4doc/rackup-2.1.0/ri/Rackup/Server/parse_options-i.rinu[U:RDoc::AnyMethod[iI"parse_options:ETI"!Rackup::Server#parse_options;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I" (args);T@ FI" Server;TcRDoc::NormalClass00PK% ]d1doc/rackup-2.1.0/ri/Rackup/Server/opt_parser-i.rinu[U:RDoc::AnyMethod[iI"opt_parser:ETI"Rackup::Server#opt_parser;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/server.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Server;TcRDoc::NormalClass00PK% ]7doc/rackup-2.1.0/ri/Rackup/Handler/require_handler-c.rinu[U:RDoc::AnyMethod[iI"require_handler:ETI"%Rackup::Handler::require_handler;TT: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I"LTransforms server-name constants to their canonical form as filenames, ;TI"Gthen tries to require them but silences the LoadError if not found;To:RDoc::Markup::BlankLineo; ; [I"Naming convention:;T@o:RDoc::Markup::Verbatim; [ I"Foo # => 'foo' ;TI"FooBar # => 'foo_bar.rb' ;TI"FooBAR # => 'foobar.rb' ;TI"FOObar # => 'foobar.rb' ;TI"FOOBAR # => 'foobar.rb' ;TI"$FooBarBaz # => 'foo_bar_baz.rb';T: @format0: @fileI"lib/rackup/handler.rb;T:0@omit_headings_from_table_of_contents_below000[I"(prefix, const_name);T@FI" Handler;TcRDoc::NormalModule00PK% ],R.doc/rackup-2.1.0/ri/Rackup/Handler/%5b%5d-c.rinu[U:RDoc::AnyMethod[iI"[]:ETI"Rackup::Handler::[];TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/handler.rb;T:0@omit_headings_from_table_of_contents_below000[I" (name);T@ FI" Handler;TcRDoc::NormalModule00PK% ]Br +doc/rackup-2.1.0/ri/Rackup/Handler/get-c.rinu[U:RDoc::AnyMethod[iI"get:ETI"Rackup::Handler::get;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/handler.rb;T:0@omit_headings_from_table_of_contents_below000[I" (name);T@ FI" Handler;TcRDoc::NormalModule00PK% ]  3doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI""Rackup::Handler::WEBrick::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI""lib/rackup/handler/webrick.rb;T:0@omit_headings_from_table_of_contents_below000[I"(server, app);T@ TI" WEBrick;TcRDoc::NormalClass00PK% ][|==;doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/cdesc-WEBrick.rinu[U:RDoc::NormalClass[iI" WEBrick:ETI"Rackup::Handler::WEBrick;TI"*WEBrick::HTTPServlet::AbstractServlet;To:RDoc::Markup::Document: @parts[o;;[: @fileI""lib/rackup/handler/webrick.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[ [I"new;TI""lib/rackup/handler/webrick.rb;T[I"run;T@[I" shutdown;T@[I"valid_options;T@[:protected[[: private[[I" instance;T[[; [[I" service;T@[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rackup::Handler;TcRDoc::NormalModulePK% ],  8doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/shutdown-c.rinu[U:RDoc::AnyMethod[iI" shutdown:ETI"'Rackup::Handler::WEBrick::shutdown;TT: publico:RDoc::Markup::Document: @parts[: @fileI""lib/rackup/handler/webrick.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" WEBrick;TcRDoc::NormalClass00PK% ] U7doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/service-i.rinu[U:RDoc::AnyMethod[iI" service:ETI"%Rackup::Handler::WEBrick#service;TF: publico:RDoc::Markup::Document: @parts[: @fileI""lib/rackup/handler/webrick.rb;T:0@omit_headings_from_table_of_contents_below000[I"(req, res);T@ FI" WEBrick;TcRDoc::NormalClass00PK% ]h3doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/run-c.rinu[U:RDoc::AnyMethod[iI"run:ETI""Rackup::Handler::WEBrick::run;TT: publico:RDoc::Markup::Document: @parts[: @fileI""lib/rackup/handler/webrick.rb;T:0@omit_headings_from_table_of_contents_below00I" server;T[I"(app, **options);T@ FI" WEBrick;TcRDoc::NormalClass00PK% ]Yh=doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/valid_options-c.rinu[U:RDoc::AnyMethod[iI"valid_options:ETI",Rackup::Handler::WEBrick::valid_options;TT: publico:RDoc::Markup::Document: @parts[: @fileI""lib/rackup/handler/webrick.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" WEBrick;TcRDoc::NormalClass00PK% ]`I  9doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/Input/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI")Rackup::Handler::WEBrick::Input::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI""lib/rackup/handler/webrick.rb;T:0@omit_headings_from_table_of_contents_below000[I"(request);T@ FI" Input;TcRDoc::NormalClass00PK% ]g\\?doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/Input/read_next-i.rinu[U:RDoc::AnyMethod[iI"read_next:ETI".Rackup::Handler::WEBrick::Input#read_next;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"*Read one chunk from the request body.;T: @fileI""lib/rackup/handler/webrick.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Input;TcRDoc::NormalClass00PK% ]h;doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/Input/close-i.rinu[U:RDoc::AnyMethod[iI" close:ETI"*Rackup::Handler::WEBrick::Input#close;TF: publico:RDoc::Markup::Document: @parts[: @fileI""lib/rackup/handler/webrick.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Input;TcRDoc::NormalClass00PK% ]RR?doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/Input/cdesc-Input.rinu[U:RDoc::NormalClass[iI" Input:ETI"$Rackup::Handler::WEBrick::Input;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"EThis handles mapping the WEBrick request to a Rack input stream.;T: @fileI""lib/rackup/handler/webrick.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[I"Stream::Reader;To;;[; @; 0I""lib/rackup/handler/webrick.rb;T[[I" class;T[[: public[[I"new;T@[:protected[[: private[[I" instance;T[[; [[I" close;T@[; [[;[[I"read_next;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rackup::Handler::WEBrick;TcRDoc::NormalClassPK% ]E'##,doc/rackup-2.1.0/ri/Rackup/Handler/pick-c.rinu[U:RDoc::AnyMethod[iI" pick:ETI"Rackup::Handler::pick;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"KSelect first available Rack handler given an `Array` of server names. ;TI"0Raises `LoadError` if no handler was found.;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim; [I" > pick ['puma', 'webrick'] ;TI" => Rackup::Handler::WEBrick;T: @format0: @fileI"lib/rackup/handler.rb;T:0@omit_headings_from_table_of_contents_below000[I"(server_names);T@FI" Handler;TcRDoc::NormalModule00PK% ]':eJJ0doc/rackup-2.1.0/ri/Rackup/Handler/register-c.rinu[U:RDoc::AnyMethod[iI" register:ETI"Rackup::Handler::register;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"$Register a named handler class.;T: @fileI"lib/rackup/handler.rb;T:0@omit_headings_from_table_of_contents_below000[I"(name, klass);T@FI" Handler;TcRDoc::NormalModule00PK% ]8S/doc/rackup-2.1.0/ri/Rackup/Handler/default-c.rinu[U:RDoc::AnyMethod[iI" default:ETI"Rackup::Handler::default;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/handler.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Handler;TcRDoc::NormalModule00PK% ]Smf3doc/rackup-2.1.0/ri/Rackup/Handler/cdesc-Handler.rinu[U:RDoc::NormalModule[iI" Handler:ETI"Rackup::Handler;T0o:RDoc::Markup::Document: @parts[o;;[ o:RDoc::Markup::Paragraph;[I".*Handlers* connect web servers with Rack.;To:RDoc::Markup::BlankLineo; ;[I"2Rackup includes Handlers for WEBrick and CGI.;T@o; ;[I"NHandlers usually are activated by calling MyHandler.run(myapp). ;TI"EA second optional hash can be passed to include server-specific ;TI"configuration.;T: @fileI"lib/rackup/handler.rb;T:0@omit_headings_from_table_of_contents_below0o;;[; I"lib/rackup/handler/cgi.rb;T; 0o;;[; I""lib/rackup/handler/webrick.rb;T; 0; 0; 0[[U:RDoc::Constant[iI"RACK_HANDLER;TI""Rackup::Handler::RACK_HANDLER;T: public0o;;[; @; 0@@cRDoc::NormalModule0U; [iI"RACKUP_HANDLER;TI"$Rackup::Handler::RACKUP_HANDLER;T;0o;;[; @; 0@@@(0U; [iI"SERVER_NAMES;TI""Rackup::Handler::SERVER_NAMES;T: private0o;;[; @; 0@@@(0[[[I" class;T[[;[ [I"[];TI"lib/rackup/handler.rb;T[I" default;T@>[I"get;T@>[I" pick;T@>[I" register;T@>[I"require_handler;T@>[:protected[[;[[I" instance;T[[;[[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@@@I" Rackup;T@(PK% ]6UY5doc/rackup-2.1.0/ri/Rackup/Handler/CGI/send_body-c.rinu[U:RDoc::AnyMethod[iI"send_body:ETI"$Rackup::Handler::CGI::send_body;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/handler/cgi.rb;T:0@omit_headings_from_table_of_contents_below000[I" (body);T@ FI"CGI;TcRDoc::NormalClass00PK% ]8doc/rackup-2.1.0/ri/Rackup/Handler/CGI/send_headers-c.rinu[U:RDoc::AnyMethod[iI"send_headers:ETI"'Rackup::Handler::CGI::send_headers;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/handler/cgi.rb;T:0@omit_headings_from_table_of_contents_below000[I"(status, headers);T@ FI"CGI;TcRDoc::NormalClass00PK% ]u|3doc/rackup-2.1.0/ri/Rackup/Handler/CGI/cdesc-CGI.rinu[U:RDoc::NormalClass[iI"CGI:ETI"Rackup::Handler::CGI;TI" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rackup/handler/cgi.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[I" Rack;To;;[; @; 0I"lib/rackup/handler/cgi.rb;T[[I" class;T[[: public[ [I"run;T@[I"send_body;T@[I"send_headers;T@[I" serve;T@[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rackup::Handler;TcRDoc::NormalModulePK% ]7/doc/rackup-2.1.0/ri/Rackup/Handler/CGI/run-c.rinu[U:RDoc::AnyMethod[iI"run:ETI"Rackup::Handler::CGI::run;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/handler/cgi.rb;T:0@omit_headings_from_table_of_contents_below000[I"(app, **options);T@ FI"CGI;TcRDoc::NormalClass00PK% ]ؙ'1doc/rackup-2.1.0/ri/Rackup/Handler/CGI/serve-c.rinu[U:RDoc::AnyMethod[iI" serve:ETI" Rackup::Handler::CGI::serve;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/handler/cgi.rb;T:0@omit_headings_from_table_of_contents_below000[I" (app);T@ FI"CGI;TcRDoc::NormalClass00PK% ]\E]]*doc/rackup-2.1.0/ri/Rackup/cdesc-Rackup.rinu[U:RDoc::NormalModule[iI" Rackup:ET@0o:RDoc::Markup::Document: @parts[ o;;[o:RDoc::Markup::Paragraph;[I"%Released under the MIT License. ;TI".Copyright, 2022-2023, by Samuel Williams.;T: @fileI"lib/rackup/handler.rb;T:0@omit_headings_from_table_of_contents_below0o;;[o; ;[I"%Released under the MIT License. ;TI".Copyright, 2022-2023, by Samuel Williams.;T; I"lib/rackup/handler/cgi.rb;T; 0o;;[; I""lib/rackup/handler/webrick.rb;T; 0o;;[; I"lib/rackup/lobster.rb;T; 0o;;[; I"lib/rackup/server.rb;T; 0o;;[o; ;[I"%Released under the MIT License. ;TI".Copyright, 2019-2022, by Samuel Williams.;T; I"lib/rackup/stream.rb;T; 0o;;[o; ;[I"%Released under the MIT License. ;TI".Copyright, 2022-2023, by Samuel Williams.;T; I"lib/rackup/version.rb;T; 0; 0; 0[[U:RDoc::Constant[iI" VERSION;TI"Rackup::VERSION;T: public0o;;[; @.; 0@.@cRDoc::NormalModule0[[[I" class;T[[; [[:protected[[: private[[I" instance;T[[; [[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[ @@@@@ @'@.@.cRDoc::TopLevelPK% ] D,doc/rackup-2.1.0/ri/Rackup/Stream/flush-i.rinu[U:RDoc::AnyMethod[iI" flush:ETI"Rackup::Stream#flush;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Stream;TcRDoc::NormalClass00PK% ]$|*doc/rackup-2.1.0/ri/Rackup/Stream/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rackup::Stream::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I")(input = nil, output = Buffered.new);T@ FI" Stream;TcRDoc::NormalClass00PK% ]UU2doc/rackup-2.1.0/ri/Rackup/Stream/close_write-i.rinu[U:RDoc::AnyMethod[iI"close_write:ETI"Rackup::Stream#close_write;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"9close must never be called on the input stream. huh?;T: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Stream;TcRDoc::NormalClass00PK% ]>|fEE/doc/rackup-2.1.0/ri/Rackup/Stream/empty%3f-i.rinu[U:RDoc::AnyMethod[iI" empty?:ETI"Rackup::Stream#empty?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"3Whether there are any output chunks remaining?;T: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Stream;TcRDoc::NormalClass00PK% ]S5doc/rackup-2.1.0/ri/Rackup/Stream/write_nonblock-i.rinu[U:RDoc::AnyMethod[iI"write_nonblock:ETI""Rackup::Stream#write_nonblock;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I" (buffer);T@ FI" Stream;TcRDoc::NormalClass00PK% ]ޙ0doc/rackup-2.1.0/ri/Rackup/Stream/read_next-i.rinu[U:RDoc::AnyMethod[iI"read_next:ETI"Rackup::Stream#read_next;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Stream;TcRDoc::NormalClass00PK% ]BB,doc/rackup-2.1.0/ri/Rackup/Stream/close-i.rinu[U:RDoc::AnyMethod[iI" close:ETI"Rackup::Stream#close;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"'Close the input and output bodies.;T: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I"(error = nil);T@FI" Stream;TcRDoc::NormalClass00PK% ],doc/rackup-2.1.0/ri/Rackup/Stream/write-i.rinu[U:RDoc::AnyMethod[iI" write:ETI"Rackup::Stream#write;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I" (buffer);T@ FI" Stream;TcRDoc::NormalClass00PK% ]P`1doc/rackup-2.1.0/ri/Rackup/Stream/cdesc-Stream.rinu[U:RDoc::NormalClass[iI" Stream:ETI"Rackup::Stream;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I" The input stream is an IO-like object which contains the raw HTTP POST data. When applicable, its external encoding must be “ASCII-8BIT” and it must be opened in binary mode, for Ruby 1.9 compatibility. The input stream must respond to gets, each, read and rewind.;T: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I" input;TI"R;T: publicFI"lib/rackup/stream.rb;T[ I" output;T@; F@[[[I" Reader;To;;[; @; 0@[[I" class;T[[; [[I"new;T@[:protected[[: private[[I" instance;T[[; [[I"<<;T@[I" close;T@[I"close_read;T@[I"close_write;T@[I" closed?;T@[I" empty?;T@[I" flush;T@[I" write;T@[I"write_nonblock;T@[; [[;[[I"read_next;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rackup;TcRDoc::NormalModulePK% ]L1doc/rackup-2.1.0/ri/Rackup/Stream/close_read-i.rinu[U:RDoc::AnyMethod[iI"close_read:ETI"Rackup::Stream#close_read;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Stream;TcRDoc::NormalClass00PK% ]ۯ6;doc/rackup-2.1.0/ri/Rackup/Stream/Reader/read_nonblock-i.rinu[U:RDoc::AnyMethod[iI"read_nonblock:ETI")Rackup::Stream::Reader#read_nonblock;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I"(length, buffer = nil);T@ FI" Reader;TcRDoc::NormalModule00PK% ]8doc/rackup-2.1.0/ri/Rackup/Stream/Reader/cdesc-Reader.rinu[U:RDoc::NormalModule[iI" Reader:ETI"Rackup::Stream::Reader;T0o:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"gThis provides a read-only interface for data, which is surprisingly tricky to implement correctly.;T: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [ [I" each;TI"lib/rackup/stream.rb;T[I" gets;T@%[I" read;T@%[I"read_nonblock;T@%[I"read_partial;T@%[; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rackup::Stream;TcRDoc::NormalClassPK% ]i:doc/rackup-2.1.0/ri/Rackup/Stream/Reader/read_partial-i.rinu[U:RDoc::AnyMethod[iI"read_partial:ETI"(Rackup::Stream::Reader#read_partial;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"lRead at most `length` bytes from the stream. Will avoid reading from the underlying stream if possible.;T: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I"(length = nil);T@FI" Reader;TcRDoc::NormalModule00PK% ]5j))2doc/rackup-2.1.0/ri/Rackup/Stream/Reader/read-i.rinu[U:RDoc::AnyMethod[iI" read:ETI" Rackup::Stream::Reader#read;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"Gread behaves like IO#read. Its signature is read([length, [buffer]]). If given, length must be a non-negative Integer (>= 0) or nil, and buffer must be a String and may not be nil. If length is given and not nil, then this method reads at most length bytes from the input stream. If length is not given or nil, then this method reads all data until EOF. When EOF is reached, this method returns nil if length is given and not nil, or “” if length is not given or is nil. If buffer is given, then the read data will be placed into buffer instead of a newly created String object. ;TI"8@param length [Integer] the amount of data to read ;TI"C@param buffer [String] the buffer which will receive the data ;TI")@return a buffer containing the data;T: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I"!(length = nil, buffer = nil);T@FI" Reader;TcRDoc::NormalModule00PK% ]D|2doc/rackup-2.1.0/ri/Rackup/Stream/Reader/gets-i.rinu[U:RDoc::AnyMethod[iI" gets:ETI" Rackup::Stream::Reader#gets;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Reader;TcRDoc::NormalModule00PK% ]h2doc/rackup-2.1.0/ri/Rackup/Stream/Reader/each-i.rinu[U:RDoc::AnyMethod[iI" each:ETI" Rackup::Stream::Reader#each;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below00I" chunk;T[I"();T@ FI" Reader;TcRDoc::NormalModule00PK% ]fy-doc/rackup-2.1.0/ri/Rackup/Stream/output-i.rinu[U:RDoc::Attr[iI" output:ETI"Rackup::Stream#output;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rackup::Stream;TcRDoc::NormalClass0PK% ]$BMM,doc/rackup-2.1.0/ri/Rackup/Stream/input-i.rinu[U:RDoc::Attr[iI" input:ETI"Rackup::Stream#input;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rackup::Stream;TcRDoc::NormalClass0PK% ]<<0doc/rackup-2.1.0/ri/Rackup/Stream/closed%3f-i.rinu[U:RDoc::AnyMethod[iI" closed?:ETI"Rackup::Stream#closed?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"(Whether the stream has been closed.;T: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Stream;TcRDoc::NormalClass00PK% ]Z4-doc/rackup-2.1.0/ri/Rackup/Stream/%3c%3c-i.rinu[U:RDoc::AnyMethod[iI"<<:ETI"Rackup::Stream#<<;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rackup/stream.rb;T:0@omit_headings_from_table_of_contents_below000[I" (buffer);T@ FI" Stream;TcRDoc::NormalClass00PK% ] gdoc/rackup-2.1.0/ri/cache.rinu[{:ancestors{ I"Rackup::Handler::CGI:ET[I" Object;TI" Rack;TI"Rackup::Handler::WEBrick;T[I"*WEBrick::HTTPServlet::AbstractServlet;TI"$Rackup::Handler::WEBrick::Input;T[I" Object;TI"Rackup::Stream::Reader;TI"Rackup::Lobster;T[I" Object;T@ I"Rackup::Server;T[I" Object;TI"Rackup::Server::Options;T[I" Object;TI"Rackup::Stream;T[I" Object;T@:attributes{@[I"attr_writer options;T@[I"attr_reader input;TI"attr_reader output;T:class_methods{ @[ I"run;TI"send_body;TI"send_headers;TI" serve;T@ [ I"new;TI"run;TI" shutdown;TI"valid_options;T@[@+@[ I"&default_middleware_by_environment;TI"logging_middleware;TI"middleware;T@+I" start;T@[@+I"Rackup::Handler;T[ I"[];TI" default;TI"get;TI" pick;TI" register;TI"require_handler;T:c_class_variables{: c_singleton_class_variables{: encodingIu: Encoding UTF-8;F:instance_methods{ @ [I" service;T@[I" close;TI"read_next;T@[I" call;T@[I"app;TI"build_app;TI"&build_app_and_options_from_config;TI"build_app_from_string;TI"check_pid!;TI"daemonize_app;TI"default_options;TI"exit_with_pid;TI"handle_profiling;TI"make_profile_name;TI"middleware;TI"opt_parser;TI" options;TI"parse_options;TI" server;TI" start;TI"wrapped_app;TI"write_pid;T@[I"handler_opts;TI" parse!;T@[I"<<;TI" close;TI"close_read;TI"close_write;TI" closed?;TI" empty?;TI" flush;TI" input;TI" output;TI"read_next;TI" write;TI"write_nonblock;T@[ I" each;TI" gets;TI" read;TI"read_nonblock;TI"read_partial;T: main0: modules[@ I" Rackup;T@6@@ @@@@@@: pages[: titleI"rackup-2.1.0 Documentation;TPK% ]GQ--:doc/rack-3.0.8/ri/Rack/Utils/delete_set_cookie_header-i.rinu[U:RDoc::AnyMethod[iI"delete_set_cookie_header:ETI")Rack::Utils#delete_set_cookie_header;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"KGenerate an encoded string based on the given +key+ and +value+ using ;TI"Mset_cookie_header for the purpose of causing the specified cookie to be ;TI"Gdeleted. The +value+ may be an instance of +Hash+ and can include ;TI"Oattributes as outlined by set_cookie_header. The encoded cookie will have ;TI"Ja +max_age+ of 0 seconds, an +expires+ date in the past and an empty ;TI"O+value+. When used with the +set-cookie+ header, it will cause the client ;TI"%to *remove* any matching cookie.;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim; [I"(delete_set_cookie_header("myname") ;TI"E# => "myname=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT";T: @format0: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0I"Adelete_set_cookie_header(key, value = {}) -> encoded string ;T0[I"(key, value = {});T@FI" Utils;TcRDoc::NormalModule00PK% ],*6doc/rack-3.0.8/ri/Rack/Utils/param_depth_limit%3d-c.rinu[U:RDoc::AnyMethod[iI"param_depth_limit=:ETI"$Rack::Utils::param_depth_limit=;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(v);T@ FI" Utils;TcRDoc::NormalModule00PK% ]Ķ%6doc/rack-3.0.8/ri/Rack/Utils/multipart_file_limit-c.rinu[U:RDoc::Attr[iI"multipart_file_limit:ETI"&Rack::Utils::multipart_file_limit;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0T@ I"Rack::Utils;TcRDoc::NormalModule0PK% ]SF,doc/rack-3.0.8/ri/Rack/Utils/clock_time-i.rinu[U:RDoc::AnyMethod[iI"clock_time:ETI"Rack::Utils#clock_time;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Utils;TcRDoc::NormalModule00PK% ]uU55(doc/rack-3.0.8/ri/Rack/Utils/escape-i.rinu[U:RDoc::AnyMethod[iI" escape:ETI"Rack::Utils#escape;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"(URI escapes. (CGI style space to +);T: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(s);T@FI" Utils;TcRDoc::NormalModule00PK% ]U*doc/rack-3.0.8/ri/Rack/Utils/q_values-i.rinu[U:RDoc::AnyMethod[iI" q_values:ETI"Rack::Utils#q_values;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(q_value_header);T@ FI" Utils;TcRDoc::NormalModule00PK% ]#-doc/rack-3.0.8/ri/Rack/Utils/build_query-i.rinu[U:RDoc::AnyMethod[iI"build_query:ETI"Rack::Utils#build_query;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I" (params);T@ FI" Utils;TcRDoc::NormalModule00PK% ]+?-doc/rack-3.0.8/ri/Rack/Utils/status_code-i.rinu[U:RDoc::AnyMethod[iI"status_code:ETI"Rack::Utils#status_code;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I" (status);T@ FI" Utils;TcRDoc::NormalModule00PK% ]ڌ!!9doc/rack-3.0.8/ri/Rack/Utils/delete_cookie_header%21-i.rinu[U:RDoc::AnyMethod[iI"delete_cookie_header!:ETI"&Rack::Utils#delete_cookie_header!;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(headers, key, value = {});T@ FI" Utils;TcRDoc::NormalModule00PK% ]]  +doc/rack-3.0.8/ri/Rack/Utils/cdesc-Utils.rinu[U:RDoc::NormalModule[iI" Utils:ETI"Rack::Utils;T0o:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"GRack::Utils contains a grab-bag of useful methods for writing web ;TI";applications adopted from all kinds of Ruby libraries.;T: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[ [ I"default_query_parser;TI"RW;T: publicTI"lib/rack/utils.rb;T[ I"multipart_file_limit;T@; T@[ I"multipart_part_limit;T@; T@[ I"multipart_part_limit=;T@; T@[ I"multipart_total_part_limit;T@; T@[U:RDoc::Constant[iI"ParameterTypeError;TI"$Rack::Utils::ParameterTypeError;T; 0o;;[; @; 0@@cRDoc::NormalModule0U; [iI"InvalidParameterError;TI"'Rack::Utils::InvalidParameterError;T; 0o;;[; @; 0@@@&0U; [iI"ParamsTooDeepError;TI"$Rack::Utils::ParamsTooDeepError;T; 0o;;[; @; 0@@@&0U; [iI"DEFAULT_SEP;TI"Rack::Utils::DEFAULT_SEP;T; 0o;;[; @; 0@@@&0U; [iI"COMMON_SEP;TI"Rack::Utils::COMMON_SEP;T; 0o;;[; @; 0@@@&0U; [iI"KeySpaceConstrainedParams;TI"+Rack::Utils::KeySpaceConstrainedParams;T; 0o;;[; @; 0@@@&0U; [iI"ESCAPE_HTML;TI"Rack::Utils::ESCAPE_HTML;T; 0o;;[; @; 0@@@&0U; [iI"ESCAPE_HTML_PATTERN;TI"%Rack::Utils::ESCAPE_HTML_PATTERN;T; 0o;;[; @; 0@@@&0U; [iI"HTTP_STATUS_CODES;TI"#Rack::Utils::HTTP_STATUS_CODES;T; 0o;;[o; ;[I"AEvery standard HTTP code mapped to the appropriate message. ;TI"Generated with:;To:RDoc::Markup::Verbatim;[I"\curl -s https://www.iana.org/assignments/http-status-codes/http-status-codes-1.csv | \ ;TI"Q ruby -ne 'm = /^(\d{3}),(?!Unassigned|\(Unused\))([^,]+)/.match($_) and \ ;TI": puts "#{m[1]} => \x27#{m[2].strip}\x27,"';T: @format0; @; 0@@@&0U; [iI"STATUS_WITH_NO_ENTITY_BODY;TI",Rack::Utils::STATUS_WITH_NO_ENTITY_BODY;T; 0o;;[o; ;[I"IResponses with HTTP status codes that should not have an entity body;T; @; 0@@@&0U; [iI"SYMBOL_TO_STATUS_CODE;TI"'Rack::Utils::SYMBOL_TO_STATUS_CODE;T; 0o;;[; @; 0@@@&0U; [iI"PATH_SEPS;TI"Rack::Utils::PATH_SEPS;T; 0o;;[; @; 0@@@&0U; [iI"NULL_BYTE;TI"Rack::Utils::NULL_BYTE;T; 0o;;[; @; 0@@@&0[[[I" class;T[[; [ [I"forwarded_values;T@[I"key_space_limit;T@[I"key_space_limit=;T@[I"param_depth_limit;T@[I"param_depth_limit=;T@[:protected[[: private[[I" instance;T[[; [#[I"add_cookie_to_header;T@[I" add_remove_cookie_to_header;T@[I"best_q_match;T@[I"build_nested_query;T@[I"build_query;T@[I"byte_ranges;T@[I"clean_path_info;T@[I"clock_time;T@[I"delete_cookie_header!;T@[I"delete_set_cookie_header;T@[I"delete_set_cookie_header!;T@[I" escape;T@[I"escape_html;T@[I"escape_path;T@[I"get_byte_ranges;T@[I"make_delete_cookie_header;T@[I"parse_cookies;T@[I"parse_cookies_header;T@[I"parse_nested_query;T@[I"parse_query;T@[I" q_values;T@[I" rfc2822;T@[I"secure_compare;T@[I"select_best_encoding;T@[I"set_cookie_header;T@[I"set_cookie_header!;T@[I"status_code;T@[I" unescape;T@[I"unescape_path;T@[I"valid_path?;T@[;[[;[[@~@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;T@&PK% ]vy  -doc/rack-3.0.8/ri/Rack/Utils/parse_query-i.rinu[U:RDoc::AnyMethod[iI"parse_query:ETI"Rack::Utils#parse_query;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(qs, d = nil, &unescaper);T@ FI" Utils;TcRDoc::NormalModule00PK% ]p8 6doc/rack-3.0.8/ri/Rack/Utils/add_cookie_to_header-i.rinu[U:RDoc::AnyMethod[iI"add_cookie_to_header:ETI"%Rack::Utils#add_cookie_to_header;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(header, key, value);T@ FI" Utils;TcRDoc::NormalModule00PK% ]4doc/rack-3.0.8/ri/Rack/Utils/parse_nested_query-i.rinu[U:RDoc::AnyMethod[iI"parse_nested_query:ETI"#Rack::Utils#parse_nested_query;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(qs, d = nil);T@ FI" Utils;TcRDoc::NormalModule00PK% ]i6doc/rack-3.0.8/ri/Rack/Utils/multipart_part_limit-c.rinu[U:RDoc::Attr[iI"multipart_part_limit:ETI"&Rack::Utils::multipart_part_limit;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0T@ I"Rack::Utils;TcRDoc::NormalModule0PK% ]#fBee0doc/rack-3.0.8/ri/Rack/Utils/secure_compare-i.rinu[U:RDoc::AnyMethod[iI"secure_compare:ETI"Rack::Utils#secure_compare;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"%Constant time string comparison.;To:RDoc::Markup::BlankLineo; ; [ I"JNOTE: the values compared should be of fixed length, such as strings ;TI"Gthat have already been processed by HMAC. This should not be used ;TI"Lon variable length plaintext strings because it could leak length info ;TI"via timing attacks.;T: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I" (a, b);T@FI" Utils;TcRDoc::NormalModule00PK% ]à##;doc/rack-3.0.8/ri/Rack/Utils/make_delete_cookie_header-i.rinu[U:RDoc::AnyMethod[iI"make_delete_cookie_header:ETI"*Rack::Utils#make_delete_cookie_header;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(header, key, value);T@ FI" Utils;TcRDoc::NormalModule00PK% ][h4doc/rack-3.0.8/ri/Rack/Utils/build_nested_query-i.rinu[U:RDoc::AnyMethod[iI"build_nested_query:ETI"#Rack::Utils#build_nested_query;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(value, prefix = nil);T@ FI" Utils;TcRDoc::NormalModule00PK% ]!)doc/rack-3.0.8/ri/Rack/Utils/rfc2822-i.rinu[U:RDoc::AnyMethod[iI" rfc2822:ETI"Rack::Utils#rfc2822;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I" (time);T@ FI" Utils;TcRDoc::NormalModule00PK% ] VE*doc/rack-3.0.8/ri/Rack/Utils/unescape-i.rinu[U:RDoc::AnyMethod[iI" unescape:ETI"Rack::Utils#unescape;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"LUnescapes a URI escaped string with +encoding+. +encoding+ will be the ;TI"Etarget encoding of the string returned, and it defaults to UTF-8;T: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"$(s, encoding = Encoding::UTF_8);T@FI" Utils;TcRDoc::NormalModule00PK% ]2doc/rack-3.0.8/ri/Rack/Utils/forwarded_values-i.rinu[U:RDoc::AnyMethod[iI"forwarded_values:ETI"!Rack::Utils#forwarded_values;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(forwarded_header);T@ FI" Utils;TcRDoc::NormalModule00PK% ]Ljj/doc/rack-3.0.8/ri/Rack/Utils/parse_cookies-i.rinu[U:RDoc::AnyMethod[iI"parse_cookies:ETI"Rack::Utils#parse_cookies;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"?Parse cookies from the provided request environment using ;TI"Kparse_cookies_header. Returns a map of cookie +key+ to cookie +value+.;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim; [I"8parse_cookies({'HTTP_COOKIE' => 'myname=myvalue'}) ;TI"!# => {'myname' => 'myvalue'};T: @format0: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0I" parse_cookies(env) -> hash ;T0[I" (env);T@FI" Utils;TcRDoc::NormalModule00PK% ]w+3doc/rack-3.0.8/ri/Rack/Utils/set_cookie_header-i.rinu[U:RDoc::AnyMethod[iI"set_cookie_header:ETI""Rack::Utils#set_cookie_header;TF: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I"NGenerate an encoded string using the provided +key+ and +value+ suitable ;TI"Mfor the +set-cookie+ header according to RFC6265. The +value+ may be an ;TI"+instance of either +String+ or +Hash+.;To:RDoc::Markup::BlankLineo; ; [ I"PIf the cookie +value+ is an instance of +Hash+, it considers the following ;TI"Mcookie attribute keys: +domain+, +max_age+, +expires+ (must be instance ;TI"Jof +Time+), +secure+, +http_only+, +same_site+ and +value+. For more ;TI"?details about the interpretation of these fields, consult ;TI"V[RFC6265 Section 5.2](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2).;T@o; ; [I"OAn extra cookie attribute +escape_key+ can be provided to control whether ;TI"Mor not the cookie key is URL encoded. If explicitly set to +false+, the ;TI"Ncookie key name will not be url encoded (escaped). The default is +true+.;T@o:RDoc::Markup::Verbatim; [ I",set_cookie_header("myname", "myvalue") ;TI"# => "myname=myvalue" ;TI" ;TI"Bset_cookie_header("myname", {value: "myvalue", max_age: 10}) ;TI"&# => "myname=myvalue; max-age=10";T: @format0: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0I"5set_cookie_header(key, value) -> encoded string ;T0[I"(key, value);T@$FI" Utils;TcRDoc::NormalModule00PK% ]ܡ6doc/rack-3.0.8/ri/Rack/Utils/parse_cookies_header-i.rinu[U:RDoc::AnyMethod[iI"parse_cookies_header:ETI"%Rack::Utils#parse_cookies_header;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"NParse cookies from the provided header +value+ according to RFC6265. The ;TI"Jsyntax for cookie headers only supports semicolons. Returns a map of ;TI"$cookie +key+ to cookie +value+.;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim; [I"7parse_cookies_header('myname=myvalue; max-age=0') ;TI"/# => {"myname"=>"myvalue", "max-age"=>"0"};T: @format0: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0I")parse_cookies_header(value) -> hash ;T0[I" (value);T@FI" Utils;TcRDoc::NormalModule00PK% ]75doc/rack-3.0.8/ri/Rack/Utils/Context/cdesc-Context.rinu[U:RDoc::NormalClass[iI" Context:ETI"Rack::Utils::Context;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[ I"KContext allows the use of a compatible middleware at different points ;TI"Fin a request handling stack. A compatible middleware must define ;TI"N#context which should take the arguments env and app. The first of which ;TI"Mwould be the request environment. The second of which would be the rack ;TI"8application that the request would be forwarded to.;T: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I"app;TI"R;T: publicFI"lib/rack/utils.rb;T[ I"for;T@; F@[[[[I" class;T[[; [[I"new;T@[:protected[[: private[[I" instance;T[[; [[I" call;T@[I" context;T@[I"recontext;T@[; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Utils;TcRDoc::NormalModulePK% ]>^1doc/rack-3.0.8/ri/Rack/Utils/Context/context-i.rinu[U:RDoc::AnyMethod[iI" context:ETI"!Rack::Utils::Context#context;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(env, app = @app);T@ FI" Context;TcRDoc::NormalClass00PK% ]M^-doc/rack-3.0.8/ri/Rack/Utils/Context/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Utils::Context::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(app_f, app_r);T@ FI" Context;TcRDoc::NormalClass00PK% ]y3doc/rack-3.0.8/ri/Rack/Utils/Context/recontext-i.rinu[U:RDoc::AnyMethod[iI"recontext:ETI"#Rack::Utils::Context#recontext;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I" (app);T@ FI" Context;TcRDoc::NormalClass00PK% ],9).doc/rack-3.0.8/ri/Rack/Utils/Context/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Utils::Context#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Context;TcRDoc::NormalClass00PK% ]=K-doc/rack-3.0.8/ri/Rack/Utils/Context/for-i.rinu[U:RDoc::Attr[iI"for:ETI"Rack::Utils::Context#for;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Utils::Context;TcRDoc::NormalClass0PK% ]_^-doc/rack-3.0.8/ri/Rack/Utils/Context/app-i.rinu[U:RDoc::Attr[iI"app:ETI"Rack::Utils::Context#app;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Utils::Context;TcRDoc::NormalClass0PK% ]V1doc/rack-3.0.8/ri/Rack/Utils/clean_path_info-i.rinu[U:RDoc::AnyMethod[iI"clean_path_info:ETI" Rack::Utils#clean_path_info;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(path_info);T@ FI" Utils;TcRDoc::NormalModule00PK% ] 4doc/rack-3.0.8/ri/Rack/Utils/key_space_limit%3d-c.rinu[U:RDoc::AnyMethod[iI"key_space_limit=:ETI""Rack::Utils::key_space_limit=;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(v);T@ FI" Utils;TcRDoc::NormalModule00PK% ]WH6doc/rack-3.0.8/ri/Rack/Utils/set_cookie_header%21-i.rinu[U:RDoc::AnyMethod[iI"set_cookie_header!:ETI"#Rack::Utils#set_cookie_header!;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"NAppend a cookie in the specified headers with the given cookie +key+ and ;TI"%+value+ using set_cookie_header.;To:RDoc::Markup::BlankLineo; ; [I"NIf the headers already contains a +set-cookie+ key, it will be converted ;TI"3to an +Array+ if not already, and appended to.;T: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0I"=set_cookie_header!(headers, key, value) -> header value ;T0[I"(headers, key, value);T@FI" Utils;TcRDoc::NormalModule00PK% ] /doc/rack-3.0.8/ri/Rack/Utils/unescape_path-i.rinu[U:RDoc::AnyMethod[iI"unescape_path:ETI"Rack::Utils#unescape_path;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"NUnescapes the **path** component of a URI. See Rack::Utils.unescape for ;TI"4unescaping query parameters or form components.;T: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(s);T@FI" Utils;TcRDoc::NormalModule00PK% ]&1doc/rack-3.0.8/ri/Rack/Utils/key_space_limit-c.rinu[U:RDoc::AnyMethod[iI"key_space_limit:ETI"!Rack::Utils::key_space_limit;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Utils;TcRDoc::NormalModule00PK% ]j,,=doc/rack-3.0.8/ri/Rack/Utils/add_remove_cookie_to_header-i.rinu[U:RDoc::AnyMethod[iI" add_remove_cookie_to_header:ETI",Rack::Utils#add_remove_cookie_to_header;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(header, key, value = {});T@ FI" Utils;TcRDoc::NormalModule00PK% ]Ə++6doc/rack-3.0.8/ri/Rack/Utils/select_best_encoding-i.rinu[U:RDoc::AnyMethod[iI"select_best_encoding:ETI"%Rack::Utils#select_best_encoding;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"+(available_encodings, accept_encoding);T@ FI" Utils;TcRDoc::NormalModule00PK% ]J?9doc/rack-3.0.8/ri/Rack/Utils/multipart_part_limit%3d-c.rinu[U:RDoc::Attr[iI"multipart_part_limit=:ETI"'Rack::Utils::multipart_part_limit=;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0T@ I"Rack::Utils;TcRDoc::NormalModule0PK% ]&2.doc/rack-3.0.8/ri/Rack/Utils/best_q_match-i.rinu[U:RDoc::AnyMethod[iI"best_q_match:ETI"Rack::Utils#best_q_match;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"=Return best accept value to use, based on the algorithm ;TI"9in RFC 2616 Section 14. If there are multiple best ;TI"@matches (same specificity and quality), the value returned ;TI"is arbitrary.;T: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"&(q_value_header, available_mimes);T@FI" Utils;TcRDoc::NormalModule00PK% ]B^cc-doc/rack-3.0.8/ri/Rack/Utils/escape_html-i.rinu[U:RDoc::AnyMethod[iI"escape_html:ETI"Rack::Utils#escape_html;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"GEscape ampersands, brackets and quotes to their HTML/XML entities.;T: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I" (string);T@FI" Utils;TcRDoc::NormalModule00PK% ]-doc/rack-3.0.8/ri/Rack/Utils/byte_ranges-i.rinu[U:RDoc::AnyMethod[iI"byte_ranges:ETI"Rack::Utils#byte_ranges;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"MParses the "Range:" header, if present, into an array of Range objects. ;TI"DReturns nil if the header is missing or syntactically invalid. ;TI"BReturns an empty array if none of the ranges are satisfiable.;T: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(env, size);T@FI" Utils;TcRDoc::NormalModule00PK% ]  1doc/rack-3.0.8/ri/Rack/Utils/get_byte_ranges-i.rinu[U:RDoc::AnyMethod[iI"get_byte_ranges:ETI" Rack::Utils#get_byte_ranges;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(http_range, size);T@ FI" Utils;TcRDoc::NormalModule00PK% ]w;doc/rack-3.0.8/ri/Rack/Utils/HeaderHash/cdesc-HeaderHash.rinu[U:RDoc::NormalClass[iI"HeaderHash:ETI"Rack::Utils::HeaderHash;TI" Hash;To:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[I"lib/rack/utils.rb;TI"Rack::Utils;TcRDoc::NormalModulePK% ]\]]=doc/rack-3.0.8/ri/Rack/Utils/delete_set_cookie_header%21-i.rinu[U:RDoc::AnyMethod[iI"delete_set_cookie_header!:ETI"*Rack::Utils#delete_set_cookie_header!;TF: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I"JSet an expired cookie in the specified headers with the given cookie ;TI"C+key+ and +value+ using delete_set_cookie_header. This causes ;TI";the client to immediately delete the specified cookie.;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim; [I"0delete_set_cookie_header!(nil, "mycookie") ;TI"H# => "mycookie=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT" ;T: @format0o; ; [I" ["mycookie=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT"] ;TI" header ;TI"I# => ["mycookie=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT"];T; 0: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0I"Hdelete_set_cookie_header!(header, key, value = {}) -> header value ;T0[I"(header, key, value = {});T@FI" Utils;TcRDoc::NormalModule00PK% ]=t<doc/rack-3.0.8/ri/Rack/Utils/multipart_total_part_limit-c.rinu[U:RDoc::Attr[iI"multipart_total_part_limit:ETI",Rack::Utils::multipart_total_part_limit;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0T@ I"Rack::Utils;TcRDoc::NormalModule0PK% ]R/doc/rack-3.0.8/ri/Rack/Utils/valid_path%3f-i.rinu[U:RDoc::AnyMethod[iI"valid_path?:ETI"Rack::Utils#valid_path?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I" (path);T@ FI" Utils;TcRDoc::NormalModule00PK% ]VL 3doc/rack-3.0.8/ri/Rack/Utils/param_depth_limit-c.rinu[U:RDoc::AnyMethod[iI"param_depth_limit:ETI"#Rack::Utils::param_depth_limit;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Utils;TcRDoc::NormalModule00PK% ]M2doc/rack-3.0.8/ri/Rack/Utils/forwarded_values-c.rinu[U:RDoc::AnyMethod[iI"forwarded_values:ETI""Rack::Utils::forwarded_values;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(forwarded_header);T@ FI" Utils;TcRDoc::NormalModule00PK% ]yF6doc/rack-3.0.8/ri/Rack/Utils/default_query_parser-c.rinu[U:RDoc::Attr[iI"default_query_parser:ETI"&Rack::Utils::default_query_parser;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below0T@ I"Rack::Utils;TcRDoc::NormalModule0PK% ]}}-doc/rack-3.0.8/ri/Rack/Utils/escape_path-i.rinu[U:RDoc::AnyMethod[iI"escape_path:ETI"Rack::Utils#escape_path;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"MLike URI escaping, but with %20 instead of +. Strictly speaking this is ;TI"true URI escaping.;T: @fileI"lib/rack/utils.rb;T:0@omit_headings_from_table_of_contents_below000[I"(s);T@FI" Utils;TcRDoc::NormalModule00PK% ]K|3doc/rack-3.0.8/ri/Rack/Recursive/cdesc-Recursive.rinu[U:RDoc::NormalClass[iI"Recursive:ETI"Rack::Recursive;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[ I"BRack::Recursive allows applications called down the chain to ;TI"4include data from other applications (by using ;TI"=rack['rack.recursive.include'][...] or raise a ;TI"+ForwardRequest to redirect internally.;T: @fileI"lib/rack/recursive.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/recursive.rb;T[:protected[[: private[[I" instance;T[[; [[I" _call;T@ [I" call;T@ [I" include;T@ [; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]N-doc/rack-3.0.8/ri/Rack/Recursive/include-i.rinu[U:RDoc::AnyMethod[iI" include:ETI"Rack::Recursive#include;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/recursive.rb;T:0@omit_headings_from_table_of_contents_below000[I"(env, path);T@ FI"Recursive;TcRDoc::NormalClass00PK% ]~q21)doc/rack-3.0.8/ri/Rack/Recursive/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Recursive::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/recursive.rb;T:0@omit_headings_from_table_of_contents_below000[I" (app);T@ FI"Recursive;TcRDoc::NormalClass00PK% ]s*doc/rack-3.0.8/ri/Rack/Recursive/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Recursive#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/recursive.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI"Recursive;TcRDoc::NormalClass00PK% ]O+doc/rack-3.0.8/ri/Rack/Recursive/_call-i.rinu[U:RDoc::AnyMethod[iI" _call:ETI"Rack::Recursive#_call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/recursive.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI"Recursive;TcRDoc::NormalClass00PK% ]O **9doc/rack-3.0.8/ri/Rack/QueryParser/_normalize_params-i.rinu[U:RDoc::AnyMethod[iI"_normalize_params:ETI"(Rack::QueryParser#_normalize_params;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"(params, name, v, depth);T@ FI"QueryParser;TcRDoc::NormalClass00PK% ]!FF+doc/rack-3.0.8/ri/Rack/QueryParser/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::QueryParser::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"U(params_class, _key_space_limit=(not_deprecated = true; nil), param_depth_limit);T@ FI"QueryParser;TcRDoc::NormalClass00PK% ]o,/AA3doc/rack-3.0.8/ri/Rack/QueryParser/parse_query-i.rinu[U:RDoc::AnyMethod[iI"parse_query:ETI""Rack::QueryParser#parse_query;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"9Stolen from Mongrel, with some small modifications: ;TI"PParses a query string by breaking it up at the '&'. You can also use this ;TI"Nto parse cookies by changing the characters used in the second parameter ;TI"(which defaults to '&').;T: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"&(qs, separator = nil, &unescaper);T@FI"QueryParser;TcRDoc::NormalClass00PK% ]\E_;doc/rack-3.0.8/ri/Rack/QueryParser/params_hash_type%3f-i.rinu[U:RDoc::AnyMethod[iI"params_hash_type?:ETI"(Rack::QueryParser#params_hash_type?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I" (obj);T@ FI"QueryParser;TcRDoc::NormalClass00PK% ]XZ5doc/rack-3.0.8/ri/Rack/QueryParser/Params/key%3f-i.rinu[U:RDoc::AnyMethod[iI" key?:ETI"#Rack::QueryParser::Params#key?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ FI" Params;TcRDoc::NormalClass00PK% ]#P2doc/rack-3.0.8/ri/Rack/QueryParser/Params/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"#Rack::QueryParser::Params::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Params;TcRDoc::NormalClass00PK% ] ===doc/rack-3.0.8/ri/Rack/QueryParser/Params/to_params_hash-i.rinu[U:RDoc::AnyMethod[iI"to_params_hash:ETI"-Rack::QueryParser::Params#to_params_hash;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Params;TcRDoc::NormalClass0[I"Rack::QueryParser::Params;TFI" to_h;TPK% ]9doc/rack-3.0.8/ri/Rack/QueryParser/Params/cdesc-Params.rinu[U:RDoc::NormalClass[iI" Params:ETI"Rack::QueryParser::Params;TI" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/query_parser.rb;T[:protected[[: private[[I" instance;T[[; [ [I"[];T@[I"[]=;T@[I" key?;T@[I" to_h;T@[I"to_params_hash;T@[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::QueryParser;TcRDoc::NormalClassPK% ]95doc/rack-3.0.8/ri/Rack/QueryParser/Params/%5b%5d-i.rinu[U:RDoc::AnyMethod[iI"[]:ETI"!Rack::QueryParser::Params#[];TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ FI" Params;TcRDoc::NormalClass00PK% ]۷#8doc/rack-3.0.8/ri/Rack/QueryParser/Params/%5b%5d%3d-i.rinu[U:RDoc::AnyMethod[iI"[]=:ETI""Rack::QueryParser::Params#[]=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"(key, value);T@ FI" Params;TcRDoc::NormalClass00PK% ]"3doc/rack-3.0.8/ri/Rack/QueryParser/Params/to_h-i.rinu[U:RDoc::AnyMethod[iI" to_h:ETI"#Rack::QueryParser::Params#to_h;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"JRecursively unwraps nested `Params` objects and constructs an object ;TI"Hof the same shape, but using the objects' internal representations ;TI"L(Ruby hashes) in place of the objects. The result is a hash consisting ;TI"purely of Ruby primitives.;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim; [I"Mutation warning! ;TI" ;TI"H1. This method mutates the internal representation of the `Params` ;TI"5 objects in order to save object allocations. ;TI" ;TI"C2. The value you get back is a reference to the internal hash ;TI"$ representation, not a copy. ;TI" ;TI"I3. Because the `Params` object's internal representation is mutable ;TI"H through the `#[]=` method, it is not thread safe. The result of ;TI"I getting the hash representation while another thread is adding a ;TI"' key to it is non-deterministic.;T: @format0: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[[I"to_params_hash;To;; [;@ ;0I"();T@ FI" Params;TcRDoc::NormalClass00PK% ]|:doc/rack-3.0.8/ri/Rack/QueryParser/parse_nested_query-i.rinu[U:RDoc::AnyMethod[iI"parse_nested_query:ETI")Rack::QueryParser#parse_nested_query;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"Pparse_nested_query expands a query string into structural types. Supported ;TI"Ntypes are Arrays, Hashes and basic value types. It is possible to supply ;TI"Hquery strings with parameters of conflicting types, in this case a ;TI"PParameterTypeError is raised. Users are encouraged to return a 400 in this ;TI" case.;T: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"(qs, separator = nil);T@FI"QueryParser;TcRDoc::NormalClass00PK% ]LE   7doc/rack-3.0.8/ri/Rack/QueryParser/new_depth_limit-i.rinu[U:RDoc::AnyMethod[iI"new_depth_limit:ETI"&Rack::QueryParser#new_depth_limit;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"(param_depth_limit);T@ FI"QueryParser;TcRDoc::NormalClass00PK% ]N?"$$0doc/rack-3.0.8/ri/Rack/QueryParser/unescape-i.rinu[U:RDoc::AnyMethod[iI" unescape:ETI"Rack::QueryParser#unescape;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I")(string, encoding = Encoding::UTF_8);T@ FI"QueryParser;TcRDoc::NormalClass00PK% ]C  9doc/rack-3.0.8/ri/Rack/QueryParser/param_depth_limit-i.rinu[U:RDoc::Attr[iI"param_depth_limit:ETI"(Rack::QueryParser#param_depth_limit;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::QueryParser;TcRDoc::NormalClass0PK% ]tSSQdoc/rack-3.0.8/ri/Rack/QueryParser/ParamsTooDeepError/cdesc-ParamsTooDeepError.rinu[U:RDoc::NormalClass[iI"ParamsTooDeepError:ETI"*Rack::QueryParser::ParamsTooDeepError;TI"RangeError;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"PParamsTooDeepError is the error that is raised when params are recursively ;TI"%nested over the specified limit.;T: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::QueryParser;TcRDoc::NormalClassPK% ])7doc/rack-3.0.8/ri/Rack/QueryParser/cdesc-QueryParser.rinu[U:RDoc::NormalClass[iI"QueryParser:ETI"Rack::QueryParser;TI" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I"param_depth_limit;TI"R;T: publicFI"lib/rack/query_parser.rb;T[U:RDoc::Constant[iI"DEFAULT_SEP;TI"#Rack::QueryParser::DEFAULT_SEP;T; 0o;;[; @; 0@@cRDoc::NormalClass0U; [iI"COMMON_SEP;TI""Rack::QueryParser::COMMON_SEP;T; 0o;;[; @; 0@@@0[[[I" class;T[[; [[I"make_default;T@[I"new;T@[:protected[[: private[[I" instance;T[[; [ [I"make_params;T@[I"new_depth_limit;T@[I"normalize_params;T@[I"parse_nested_query;T@[I"parse_query;T@[; [[;[ [I"_normalize_params;T@[I"params_hash_has_key?;T@[I"params_hash_type?;T@[I" unescape;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]CZJJ4doc/rack-3.0.8/ri/Rack/QueryParser/make_default-c.rinu[U:RDoc::AnyMethod[iI"make_default:ETI"$Rack::QueryParser::make_default;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"G(_key_space_limit=(not_deprecated = true; nil), param_depth_limit);T@ FI"QueryParser;TcRDoc::NormalClass00PK% ]l18doc/rack-3.0.8/ri/Rack/QueryParser/normalize_params-i.rinu[U:RDoc::AnyMethod[iI"normalize_params:ETI"'Rack::QueryParser#normalize_params;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"Onormalize_params recursively expands parameters into structural types. If ;TI"Nthe structural types represented by two different parameter names are in ;TI"Qconflict, a ParameterTypeError is raised. The depth argument is deprecated ;TI"Oand should no longer be used, it is kept for backwards compatibility with ;TI"earlier versions of rack.;T: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I""(params, name, v, _depth=nil);T@FI"QueryParser;TcRDoc::NormalClass00PK% ] ssQdoc/rack-3.0.8/ri/Rack/QueryParser/ParameterTypeError/cdesc-ParameterTypeError.rinu[U:RDoc::NormalClass[iI"ParameterTypeError:ETI"*Rack::QueryParser::ParameterTypeError;TI"TypeError;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"MParameterTypeError is the error that is raised when incoming structural ;TI"Iparameters (parsed by parse_nested_query) contain conflicting types.;T: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::QueryParser;TcRDoc::NormalClassPK% ]5Wdoc/rack-3.0.8/ri/Rack/QueryParser/InvalidParameterError/cdesc-InvalidParameterError.rinu[U:RDoc::NormalClass[iI"InvalidParameterError:ETI"-Rack::QueryParser::InvalidParameterError;TI"ArgumentError;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"PInvalidParameterError is the error that is raised when incoming structural ;TI"Nparameters (parsed by parse_nested_query) contain invalid format or byte ;TI"sequence.;T: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::QueryParser;TcRDoc::NormalClassPK% ]-##>doc/rack-3.0.8/ri/Rack/QueryParser/params_hash_has_key%3f-i.rinu[U:RDoc::AnyMethod[iI"params_hash_has_key?:ETI"+Rack::QueryParser#params_hash_has_key?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"(hash, key);T@ FI"QueryParser;TcRDoc::NormalClass00PK% ]}ё3doc/rack-3.0.8/ri/Rack/QueryParser/make_params-i.rinu[U:RDoc::AnyMethod[iI"make_params:ETI""Rack::QueryParser#make_params;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/query_parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"QueryParser;TcRDoc::NormalClass00PK% ]-doc/rack-3.0.8/ri/Rack/ContentLength/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::ContentLength::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/content_length.rb;T:0@omit_headings_from_table_of_contents_below000[I" (app);T@ FI"ContentLength;TcRDoc::NormalClass00PK% ].doc/rack-3.0.8/ri/Rack/ContentLength/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::ContentLength#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/content_length.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI"ContentLength;TcRDoc::NormalClass00PK% ]ڝZ<;doc/rack-3.0.8/ri/Rack/ContentLength/cdesc-ContentLength.rinu[U:RDoc::NormalClass[iI"ContentLength:ETI"Rack::ContentLength;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[ I"ESets the content-length header on responses that do not specify ;TI"Ca content-length or transfer-encoding header. Note that this ;TI"@does not fix responses that have an invalid content-length ;TI"header specified.;T: @fileI"lib/rack/content_length.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[I"Rack::Utils;To;;[; @; 0I"lib/rack/content_length.rb;T[[I" class;T[[: public[[I"new;T@[:protected[[: private[[I" instance;T[[; [[I" call;T@[; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]-gw?doc/rack-3.0.8/ri/Rack/CommonLogger/extract_content_length-i.rinu[U:RDoc::AnyMethod[iI"extract_content_length:ETI".Rack::CommonLogger#extract_content_length;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"AAttempt to determine the content length for the response to ;TI"#include it in the logged data.;T: @fileI"lib/rack/common_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(headers);T@FI"CommonLogger;TcRDoc::NormalClass00PK% ]TjXROO,doc/rack-3.0.8/ri/Rack/CommonLogger/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::CommonLogger::new;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"K+logger+ can be any object that supports the +write+ or +<<+ methods, ;TI"Kwhich includes the standard library Logger. These methods are called ;TI"5with a single string argument, the log message. ;TI"QIf +logger+ is nil, CommonLogger will fall back env['rack.errors'].;T: @fileI"lib/rack/common_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(app, logger = nil);T@FI"CommonLogger;TcRDoc::NormalClass00PK% ]dG@@9doc/rack-3.0.8/ri/Rack/CommonLogger/cdesc-CommonLogger.rinu[U:RDoc::NormalClass[iI"CommonLogger:ETI"Rack::CommonLogger;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[ I"GRack::CommonLogger forwards every request to the given +app+, and ;TI"logs a line in the ;TI"S{Apache common log format}[http://httpd.apache.org/docs/1.3/logs.html#common] ;TI"to the configured logger.;T: @fileI"lib/rack/common_logger.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[U:RDoc::Constant[iI" FORMAT;TI"Rack::CommonLogger::FORMAT;T: public0o;;[ o; ;[I"ICommon Log Format: http://httpd.apache.org/docs/1.3/logs.html#common;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim;[I"Jlilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 - ;TI" ;TI",%{%s - %s [%s] "%s %s%s %s" %d %s\n} % ;T: @format0o; ;[I"GThe actual format is slightly different than the above due to the ;TI"Fseparation of SCRIPT_NAME and PATH_INFO, and because the elapsed ;TI",time in seconds is included at the end.;T; @; 0@@cRDoc::NormalClass0[[[I" class;T[[; [[I"new;TI"lib/rack/common_logger.rb;T[:protected[[: private[[I" instance;T[[; [[I" call;T@5[;[[;[[I"extract_content_length;T@5[I"log;T@5[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]--doc/rack-3.0.8/ri/Rack/CommonLogger/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::CommonLogger#call;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"ELog all requests in common_log format after a response has been ;TI"Freturned. Note that if the app raises an exception, the request ;TI"Gwill not be logged, so if exception handling middleware are used, ;TI"Ithey should be loaded after this middleware. Additionally, because ;TI"Ithe logging happens after the request body has been fully sent, any ;TI"Dexceptions raised during the sending of the response body will ;TI"(cause the request not to be logged.;T: @fileI"lib/rack/common_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@FI"CommonLogger;TcRDoc::NormalClass00PK% ]&-qq,doc/rack-3.0.8/ri/Rack/CommonLogger/log-i.rinu[U:RDoc::AnyMethod[iI"log:ETI"Rack::CommonLogger#log;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I".Log the request to the configured logger.;T: @fileI"lib/rack/common_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I".(env, status, response_headers, began_at);T@FI"CommonLogger;TcRDoc::NormalClass00PK% ]o  3doc/rack-3.0.8/ri/Rack/ShowExceptions/template-i.rinu[U:RDoc::AnyMethod[iI" template:ETI""Rack::ShowExceptions#template;TF: publico:RDoc::Markup::Document: @parts[: @fileI" lib/rack/show_exceptions.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"ShowExceptions;TcRDoc::NormalClass00PK% ]ˍ.doc/rack-3.0.8/ri/Rack/ShowExceptions/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::ShowExceptions::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI" lib/rack/show_exceptions.rb;T:0@omit_headings_from_table_of_contents_below000[I" (app);T@ FI"ShowExceptions;TcRDoc::NormalClass00PK% ]9Q9doc/rack-3.0.8/ri/Rack/ShowExceptions/dump_exception-i.rinu[U:RDoc::AnyMethod[iI"dump_exception:ETI"(Rack::ShowExceptions#dump_exception;TF: publico:RDoc::Markup::Document: @parts[: @fileI" lib/rack/show_exceptions.rb;T:0@omit_headings_from_table_of_contents_below000[I"(exception);T@ FI"ShowExceptions;TcRDoc::NormalClass00PK% ]';/doc/rack-3.0.8/ri/Rack/ShowExceptions/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::ShowExceptions#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI" lib/rack/show_exceptions.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI"ShowExceptions;TcRDoc::NormalClass00PK% ]OA:doc/rack-3.0.8/ri/Rack/ShowExceptions/accepts_html%3f-i.rinu[U:RDoc::AnyMethod[iI"accepts_html?:ETI"'Rack::ShowExceptions#accepts_html?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI" lib/rack/show_exceptions.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI"ShowExceptions;TcRDoc::NormalClass00PK% ]!!?doc/rack-3.0.8/ri/Rack/ShowExceptions/prefers_plaintext%3f-i.rinu[U:RDoc::AnyMethod[iI"prefers_plaintext?:ETI",Rack::ShowExceptions#prefers_plaintext?;TF: publico:RDoc::Markup::Document: @parts[: @fileI" lib/rack/show_exceptions.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI"ShowExceptions;TcRDoc::NormalClass00PK% ]_i1doc/rack-3.0.8/ri/Rack/ShowExceptions/pretty-i.rinu[U:RDoc::AnyMethod[iI" pretty:ETI" Rack::ShowExceptions#pretty;TF: publico:RDoc::Markup::Document: @parts[: @fileI" lib/rack/show_exceptions.rb;T:0@omit_headings_from_table_of_contents_below000[I"(env, exception);T@ FI"ShowExceptions;TcRDoc::NormalClass00PK% ]Ĉ`OO=doc/rack-3.0.8/ri/Rack/ShowExceptions/cdesc-ShowExceptions.rinu[U:RDoc::NormalClass[iI"ShowExceptions:ETI"Rack::ShowExceptions;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[ I"HRack::ShowExceptions catches all exceptions raised from the app it ;TI"Awraps. It shows a useful backtrace with the sourcefile and ;TI"Cclickable context, the whole Rack environment and the request ;TI" data.;To:RDoc::Markup::BlankLineo; ;[I"EBe careful when you use this on public-facing sites as it could ;TI"-reveal information helpful to attackers.;T: @fileI" lib/rack/show_exceptions.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[U:RDoc::Constant[iI" CONTEXT;TI""Rack::ShowExceptions::CONTEXT;T: public0o;;[; @; 0@@cRDoc::NormalClass0[[[I" class;T[[;[[I"new;TI" lib/rack/show_exceptions.rb;T[:protected[[: private[[I" instance;T[[;[ [I" call;T@,[I"dump_exception;T@,[I"prefers_plaintext?;T@,[I" pretty;T@,[I" template;T@,[;[[;[[I"accepts_html?;T@,[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]HH=doc/rack-3.0.8/ri/Rack/ConditionalGet/cdesc-ConditionalGet.rinu[U:RDoc::NormalClass[iI"ConditionalGet:ETI"Rack::ConditionalGet;TI" Object;To:RDoc::Markup::Document: @parts[o;;[ o:RDoc::Markup::Paragraph;[ I"EMiddleware that enables conditional GET using if-none-match and ;TI"Iif-modified-since. The application should set either or both of the ;TI"Hlast-modified or etag response headers according to RFC 2616. When ;TI"Jeither of the conditions is met, the response body is set to be zero ;TI"?length and the response status is set to 304 Not Modified.;To:RDoc::Markup::BlankLineo; ;[I"LApplications that defer response body generation until the body's each ;TI"Mmessage is received will avoid response body generation completely when ;TI"a conditional GET matches.;T@o; ;[I"9Adapted from Michael Klishin's Merb implementation: ;TI"jhttps://github.com/wycats/merb/blob/master/merb-core/lib/merb-core/rack/middleware/conditional_get.rb;T: @fileI" lib/rack/conditional_get.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[I"new;TI" lib/rack/conditional_get.rb;T[:protected[[: private[[I" instance;T[[; [[I" call;T@+[;[[;[ [I"etag_matches?;T@+[I" fresh?;T@+[I"modified_since?;T@+[I"to_rfc2822;T@+[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]dq$.doc/rack-3.0.8/ri/Rack/ConditionalGet/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::ConditionalGet::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI" lib/rack/conditional_get.rb;T:0@omit_headings_from_table_of_contents_below000[I" (app);T@ FI"ConditionalGet;TcRDoc::NormalClass00PK% ]9/doc/rack-3.0.8/ri/Rack/ConditionalGet/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::ConditionalGet#call;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"P:doc/rack-3.0.8/ri/Rack/ConditionalGet/etag_matches%3f-i.rinu[U:RDoc::AnyMethod[iI"etag_matches?:ETI"'Rack::ConditionalGet#etag_matches?;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"PWhether the etag response header matches the if-none-match request header. ;TI".If so, the request has not been modified.;T: @fileI" lib/rack/conditional_get.rb;T:0@omit_headings_from_table_of_contents_below000[I"(none_match, headers);T@FI"ConditionalGet;TcRDoc::NormalClass00PK% ]xӉ3doc/rack-3.0.8/ri/Rack/ConditionalGet/fresh%3f-i.rinu[U:RDoc::AnyMethod[iI" fresh?:ETI" Rack::ConditionalGet#fresh?;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"AReturn whether the response has not been modified since the ;TI"last request.;T: @fileI" lib/rack/conditional_get.rb;T:0@omit_headings_from_table_of_contents_below000[I"(env, headers);T@FI"ConditionalGet;TcRDoc::NormalClass00PK% ]w5doc/rack-3.0.8/ri/Rack/ConditionalGet/to_rfc2822-i.rinu[U:RDoc::AnyMethod[iI"to_rfc2822:ETI"$Rack::ConditionalGet#to_rfc2822;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"KReturn a Time object for the given string (which should be in RFC2822 ;TI"4format), or nil if the string cannot be parsed.;T: @fileI" lib/rack/conditional_get.rb;T:0@omit_headings_from_table_of_contents_below000[I" (since);T@FI"ConditionalGet;TcRDoc::NormalClass00PK% ]CI<doc/rack-3.0.8/ri/Rack/ConditionalGet/modified_since%3f-i.rinu[U:RDoc::AnyMethod[iI"modified_since?:ETI")Rack::ConditionalGet#modified_since?;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"MWhether the last-modified response header matches the if-modified-since ;TI"?request header. If so, the request has not been modified.;T: @fileI" lib/rack/conditional_get.rb;T:0@omit_headings_from_table_of_contents_below000[I"(modified_since, headers);T@FI"ConditionalGet;TcRDoc::NormalClass00PK% ].5**$doc/rack-3.0.8/ri/Rack/cdesc-Rack.rinu[U:RDoc::NormalModule[iI" Rack:ET@0o:RDoc::Markup::Document: @parts[8o;;[: @fileI"lib/rack.rb;T:0@omit_headings_from_table_of_contents_below0o;;[; I"&lib/rack/auth/abstract/handler.rb;T; 0o;;[; I"&lib/rack/auth/abstract/request.rb;T; 0o;;[; I"lib/rack/auth/basic.rb;T; 0o;;[; I"lib/rack/auth/digest.rb;T; 0o;;[; I"lib/rack/body_proxy.rb;T; 0o;;[; I"lib/rack/builder.rb;T; 0o;;[; I"lib/rack/cascade.rb;T; 0o;;[; I"lib/rack/chunked.rb;T; 0o;;[; I"lib/rack/common_logger.rb;T; 0o;;[; I" lib/rack/conditional_get.rb;T; 0o;;[; I"lib/rack/config.rb;T; 0o;;[; I"lib/rack/constants.rb;T; 0o;;[; I"lib/rack/content_length.rb;T; 0o;;[; I"lib/rack/content_type.rb;T; 0o;;[; I"lib/rack/deflater.rb;T; 0o;;[; I"lib/rack/directory.rb;T; 0o;;[; I"lib/rack/etag.rb;T; 0o;;[; I"lib/rack/events.rb;T; 0o;;[; I"lib/rack/file.rb;T; 0o;;[; I"lib/rack/files.rb;T; 0o;;[; I"lib/rack/head.rb;T; 0o;;[; I"lib/rack/headers.rb;T; 0o;;[; I"lib/rack/lint.rb;T; 0o;;[; I"lib/rack/lock.rb;T; 0o;;[; I"lib/rack/logger.rb;T; 0o;;[; I"lib/rack/media_type.rb;T; 0o;;[; I" lib/rack/method_override.rb;T; 0o;;[; I"lib/rack/mime.rb;T; 0o;;[; I"lib/rack/mock_request.rb;T; 0o;;[; I"lib/rack/mock_response.rb;T; 0o;;[; I"lib/rack/multipart.rb;T; 0o;;[; I"$lib/rack/multipart/generator.rb;T; 0o;;[; I"!lib/rack/multipart/parser.rb;T; 0o;;[; I"(lib/rack/multipart/uploaded_file.rb;T; 0o;;[; I"lib/rack/null_logger.rb;T; 0o;;[; I"lib/rack/query_parser.rb;T; 0o;;[; I"lib/rack/recursive.rb;T; 0o;;[; I"lib/rack/reloader.rb;T; 0o;;[; I"lib/rack/request.rb;T; 0o;;[; I"lib/rack/response.rb;T; 0o;;[; I"!lib/rack/rewindable_input.rb;T; 0o;;[; I"lib/rack/runtime.rb;T; 0o;;[; I"lib/rack/sendfile.rb;T; 0o;;[; I" lib/rack/show_exceptions.rb;T; 0o;;[; I"lib/rack/show_status.rb;T; 0o;;[; I"lib/rack/static.rb;T; 0o;;[; I" lib/rack/tempfile_reaper.rb;T; 0o;;[; I"lib/rack/urlmap.rb;T; 0o;;[; I"lib/rack/utils.rb;T; 0o;;[o:RDoc::Markup::Paragraph;[I"DThe Rack main module, serving as a namespace for all core Rack ;TI"modules and classes.;To:RDoc::Markup::BlankLineo; ;[I"QAll modules meant for use in your application are autoloaded here, ;TI"Iso it should be enough just to require 'rack' in your code.;T; I"lib/rack/version.rb;T; 0; 0; 0[[>U:RDoc::Constant[iI"HTTP_HOST;TI"Rack::HTTP_HOST;T: public0o;;[o; ;[I"Request env keys;T; @0; 0@0@cRDoc::NormalModule0U; [iI"HTTP_PORT;TI"Rack::HTTP_PORT;T;0o;;[; @0; 0@0@@0U; [iI" HTTPS;TI"Rack::HTTPS;T;0o;;[; @0; 0@0@@0U; [iI"PATH_INFO;TI"Rack::PATH_INFO;T;0o;;[; @0; 0@0@@0U; [iI"REQUEST_METHOD;TI"Rack::REQUEST_METHOD;T;0o;;[; @0; 0@0@@0U; [iI"REQUEST_PATH;TI"Rack::REQUEST_PATH;T;0o;;[; @0; 0@0@@0U; [iI"SCRIPT_NAME;TI"Rack::SCRIPT_NAME;T;0o;;[; @0; 0@0@@0U; [iI"QUERY_STRING;TI"Rack::QUERY_STRING;T;0o;;[; @0; 0@0@@0U; [iI"SERVER_PROTOCOL;TI"Rack::SERVER_PROTOCOL;T;0o;;[; @0; 0@0@@0U; [iI"SERVER_NAME;TI"Rack::SERVER_NAME;T;0o;;[; @0; 0@0@@0U; [iI"SERVER_PORT;TI"Rack::SERVER_PORT;T;0o;;[; @0; 0@0@@0U; [iI"HTTP_COOKIE;TI"Rack::HTTP_COOKIE;T;0o;;[; @0; 0@0@@0U; [iI"CACHE_CONTROL;TI"Rack::CACHE_CONTROL;T;0o;;[o; ;[I"Response Header Keys;T; @0; 0@0@@0U; [iI"CONTENT_LENGTH;TI"Rack::CONTENT_LENGTH;T;0o;;[; @0; 0@0@@0U; [iI"CONTENT_TYPE;TI"Rack::CONTENT_TYPE;T;0o;;[; @0; 0@0@@0U; [iI" ETAG;TI"Rack::ETAG;T;0o;;[; @0; 0@0@@0U; [iI" EXPIRES;TI"Rack::EXPIRES;T;0o;;[; @0; 0@0@@0U; [iI"SET_COOKIE;TI"Rack::SET_COOKIE;T;0o;;[; @0; 0@0@@0U; [iI"TRANSFER_ENCODING;TI"Rack::TRANSFER_ENCODING;T;0o;;[; @0; 0@0@@0U; [iI"GET;TI"Rack::GET;T;0o;;[o; ;[I"HTTP method verbs;T; @0; 0@0@@0U; [iI" POST;TI"Rack::POST;T;0o;;[; @0; 0@0@@0U; [iI"PUT;TI"Rack::PUT;T;0o;;[; @0; 0@0@@0U; [iI" PATCH;TI"Rack::PATCH;T;0o;;[; @0; 0@0@@0U; [iI" DELETE;TI"Rack::DELETE;T;0o;;[; @0; 0@0@@0U; [iI" HEAD;TI"Rack::HEAD;T;0o;;[; @0; 0@0@@0U; [iI" OPTIONS;TI"Rack::OPTIONS;T;0o;;[; @0; 0@0@@0U; [iI" LINK;TI"Rack::LINK;T;0o;;[; @0; 0@0@@0U; [iI" UNLINK;TI"Rack::UNLINK;T;0o;;[; @0; 0@0@@0U; [iI" TRACE;TI"Rack::TRACE;T;0o;;[; @0; 0@0@@0U; [iI"RACK_VERSION;TI"Rack::RACK_VERSION;T;0o;;[o; ;[I"Rack environment variables;T; @0; 0@0@@0U; [iI"RACK_TEMPFILES;TI"Rack::RACK_TEMPFILES;T;0o;;[; @0; 0@0@@0U; [iI"RACK_ERRORS;TI"Rack::RACK_ERRORS;T;0o;;[; @0; 0@0@@0U; [iI"RACK_LOGGER;TI"Rack::RACK_LOGGER;T;0o;;[; @0; 0@0@@0U; [iI"RACK_INPUT;TI"Rack::RACK_INPUT;T;0o;;[; @0; 0@0@@0U; [iI"RACK_SESSION;TI"Rack::RACK_SESSION;T;0o;;[; @0; 0@0@@0U; [iI"RACK_SESSION_OPTIONS;TI"Rack::RACK_SESSION_OPTIONS;T;0o;;[; @0; 0@0@@0U; [iI"RACK_SHOWSTATUS_DETAIL;TI"!Rack::RACK_SHOWSTATUS_DETAIL;T;0o;;[; @0; 0@0@@0U; [iI"RACK_URL_SCHEME;TI"Rack::RACK_URL_SCHEME;T;0o;;[; @0; 0@0@@0U; [iI"RACK_HIJACK;TI"Rack::RACK_HIJACK;T;0o;;[; @0; 0@0@@0U; [iI"RACK_IS_HIJACK;TI"Rack::RACK_IS_HIJACK;T;0o;;[; @0; 0@0@@0U; [iI"RACK_RECURSIVE_INCLUDE;TI"!Rack::RACK_RECURSIVE_INCLUDE;T;0o;;[; @0; 0@0@@0U; [iI"RACK_MULTIPART_BUFFER_SIZE;TI"%Rack::RACK_MULTIPART_BUFFER_SIZE;T;0o;;[; @0; 0@0@@0U; [iI"$RACK_MULTIPART_TEMPFILE_FACTORY;TI"*Rack::RACK_MULTIPART_TEMPFILE_FACTORY;T;0o;;[; @0; 0@0@@0U; [iI"RACK_RESPONSE_FINISHED;TI"!Rack::RACK_RESPONSE_FINISHED;T;0o;;[; @0; 0@0@@0U; [iI"RACK_REQUEST_FORM_INPUT;TI""Rack::RACK_REQUEST_FORM_INPUT;T;0o;;[; @0; 0@0@@0U; [iI"RACK_REQUEST_FORM_HASH;TI"!Rack::RACK_REQUEST_FORM_HASH;T;0o;;[; @0; 0@0@@0U; [iI"RACK_REQUEST_FORM_VARS;TI"!Rack::RACK_REQUEST_FORM_VARS;T;0o;;[; @0; 0@0@@0U; [iI"RACK_REQUEST_FORM_ERROR;TI""Rack::RACK_REQUEST_FORM_ERROR;T;0o;;[; @0; 0@0@@0U; [iI"RACK_REQUEST_COOKIE_HASH;TI"#Rack::RACK_REQUEST_COOKIE_HASH;T;0o;;[; @0; 0@0@@0U; [iI"RACK_REQUEST_COOKIE_STRING;TI"%Rack::RACK_REQUEST_COOKIE_STRING;T;0o;;[; @0; 0@0@@0U; [iI"RACK_REQUEST_QUERY_HASH;TI""Rack::RACK_REQUEST_QUERY_HASH;T;0o;;[; @0; 0@0@@0U; [iI"RACK_REQUEST_QUERY_STRING;TI"$Rack::RACK_REQUEST_QUERY_STRING;T;0o;;[; @0; 0@0@@0U; [iI"(RACK_METHODOVERRIDE_ORIGINAL_METHOD;TI".Rack::RACK_METHODOVERRIDE_ORIGINAL_METHOD;T;0o;;[; @0; 0@0@@0U; [iI" File;TI"Rack::File;T;I"Rack::Files;To;;[; @E; 0@E@@0U; [iI" VERSION;TI"Rack::VERSION;T;0o;;[o; ;[I"2The Rack protocol version number implemented.;T; @; 0@@@0U; [iI"VERSION_STRING;TI"Rack::VERSION_STRING;T;0o;;[; @; 0@@@0U; [iI" RELEASE;TI"Rack::RELEASE;T;0o;;[; @; 0@@@0[[[I" class;T[[;[[I" release;TI"lib/rack/version.rb;T[I" version;T@[:protected[[: private[[I" instance;T[[;[[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[8@ @@@@@@@!@$@'@*@-@0@3@6@9@<@?@B@E@H@K@N@Q@T@W@Z@]@`@c@f@i@l@o@r@u@x@{@~@|@@@@@@@@@@@@cRDoc::TopLevelPK% ]nvm0doc/rack-3.0.8/ri/Rack/NullLogger/formatter-i.rinu[U:RDoc::AnyMethod[iI"formatter:ETI"Rack::NullLogger#formatter;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ],84doc/rack-3.0.8/ri/Rack/NullLogger/sev_threshold-i.rinu[U:RDoc::AnyMethod[iI"sev_threshold:ETI"#Rack::NullLogger#sev_threshold;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]~/doc/rack-3.0.8/ri/Rack/NullLogger/fatal%3f-i.rinu[U:RDoc::AnyMethod[iI" fatal?:ETI"Rack::NullLogger#fatal?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ] 7  +doc/rack-3.0.8/ri/Rack/NullLogger/warn-i.rinu[U:RDoc::AnyMethod[iI" warn:ETI"Rack::NullLogger#warn;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(progname = nil, &block);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]ٸ5u-doc/rack-3.0.8/ri/Rack/NullLogger/reopen-i.rinu[U:RDoc::AnyMethod[iI" reopen:ETI"Rack::NullLogger#reopen;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(logdev = nil);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]P*doc/rack-3.0.8/ri/Rack/NullLogger/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::NullLogger::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I" (app);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]V..doc/rack-3.0.8/ri/Rack/NullLogger/warn%21-i.rinu[U:RDoc::AnyMethod[iI" warn!:ETI"Rack::NullLogger#warn!;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]l/doc/rack-3.0.8/ri/Rack/NullLogger/fatal%21-i.rinu[U:RDoc::AnyMethod[iI" fatal!:ETI"Rack::NullLogger#fatal!;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]j.doc/rack-3.0.8/ri/Rack/NullLogger/warn%3f-i.rinu[U:RDoc::AnyMethod[iI" warn?:ETI"Rack::NullLogger#warn?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]e/doc/rack-3.0.8/ri/Rack/NullLogger/debug%21-i.rinu[U:RDoc::AnyMethod[iI" debug!:ETI"Rack::NullLogger#debug!;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]).+doc/rack-3.0.8/ri/Rack/NullLogger/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::NullLogger#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]6,doc/rack-3.0.8/ri/Rack/NullLogger/close-i.rinu[U:RDoc::AnyMethod[iI" close:ETI"Rack::NullLogger#close;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]5!C/doc/rack-3.0.8/ri/Rack/NullLogger/error%3f-i.rinu[U:RDoc::AnyMethod[iI" error?:ETI"Rack::NullLogger#error?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]><9doc/rack-3.0.8/ri/Rack/NullLogger/datetime_format%3d-i.rinu[U:RDoc::AnyMethod[iI"datetime_format=:ETI"&Rack::NullLogger#datetime_format=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(datetime_format);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ](r,doc/rack-3.0.8/ri/Rack/NullLogger/error-i.rinu[U:RDoc::AnyMethod[iI" error:ETI"Rack::NullLogger#error;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(progname = nil, &block);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]p.doc/rack-3.0.8/ri/Rack/NullLogger/unknown-i.rinu[U:RDoc::AnyMethod[iI" unknown:ETI"Rack::NullLogger#unknown;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(progname = nil, &block);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]o/doc/rack-3.0.8/ri/Rack/NullLogger/debug%3f-i.rinu[U:RDoc::AnyMethod[iI" debug?:ETI"Rack::NullLogger#debug?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]z!2doc/rack-3.0.8/ri/Rack/NullLogger/progname%3d-i.rinu[U:RDoc::AnyMethod[iI"progname=:ETI"Rack::NullLogger#progname=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(progname);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]q##*doc/rack-3.0.8/ri/Rack/NullLogger/add-i.rinu[U:RDoc::AnyMethod[iI"add:ETI"Rack::NullLogger#add;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"6(severity, message = nil, progname = nil, &block);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ] j5doc/rack-3.0.8/ri/Rack/NullLogger/cdesc-NullLogger.rinu[U:RDoc::NormalClass[iI"NullLogger:ETI"Rack::NullLogger;TI" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/null_logger.rb;T[:protected[[: private[[I" instance;T[[; [%[I"<<;T@[I"add;T@[I" call;T@[I" close;T@[I"datetime_format;T@[I"datetime_format=;T@[I" debug;T@[I" debug!;T@[I" debug?;T@[I" error;T@[I" error!;T@[I" error?;T@[I" fatal;T@[I" fatal!;T@[I" fatal?;T@[I"formatter;T@[I"formatter=;T@[I" info;T@[I" info!;T@[I" info?;T@[I" level;T@[I" level=;T@[I"log;T@[I" progname;T@[I"progname=;T@[I" reopen;T@[I"sev_threshold;T@[I"sev_threshold=;T@[I" unknown;T@[I" warn;T@[I" warn!;T@[I" warn?;T@[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]eZ7doc/rack-3.0.8/ri/Rack/NullLogger/sev_threshold%3d-i.rinu[U:RDoc::AnyMethod[iI"sev_threshold=:ETI"$Rack::NullLogger#sev_threshold=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(sev_threshold);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]=U  +doc/rack-3.0.8/ri/Rack/NullLogger/info-i.rinu[U:RDoc::AnyMethod[iI" info:ETI"Rack::NullLogger#info;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(progname = nil, &block);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]  3doc/rack-3.0.8/ri/Rack/NullLogger/formatter%3d-i.rinu[U:RDoc::AnyMethod[iI"formatter=:ETI" Rack::NullLogger#formatter=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(formatter);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]BO,doc/rack-3.0.8/ri/Rack/NullLogger/level-i.rinu[U:RDoc::AnyMethod[iI" level:ETI"Rack::NullLogger#level;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]Wh.doc/rack-3.0.8/ri/Rack/NullLogger/info%21-i.rinu[U:RDoc::AnyMethod[iI" info!:ETI"Rack::NullLogger#info!;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]M TP.doc/rack-3.0.8/ri/Rack/NullLogger/info%3f-i.rinu[U:RDoc::AnyMethod[iI" info?:ETI"Rack::NullLogger#info?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]  6doc/rack-3.0.8/ri/Rack/NullLogger/datetime_format-i.rinu[U:RDoc::AnyMethod[iI"datetime_format:ETI"%Rack::NullLogger#datetime_format;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]\##*doc/rack-3.0.8/ri/Rack/NullLogger/log-i.rinu[U:RDoc::AnyMethod[iI"log:ETI"Rack::NullLogger#log;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"6(severity, message = nil, progname = nil, &block);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]E]+/doc/rack-3.0.8/ri/Rack/NullLogger/error%21-i.rinu[U:RDoc::AnyMethod[iI" error!:ETI"Rack::NullLogger#error!;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]d-doc/rack-3.0.8/ri/Rack/NullLogger/%3c%3c-i.rinu[U:RDoc::AnyMethod[iI"<<:ETI"Rack::NullLogger#<<;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I" (msg);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]$/doc/rack-3.0.8/ri/Rack/NullLogger/level%3d-i.rinu[U:RDoc::AnyMethod[iI" level=:ETI"Rack::NullLogger#level=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I" (level);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]bKg,doc/rack-3.0.8/ri/Rack/NullLogger/fatal-i.rinu[U:RDoc::AnyMethod[iI" fatal:ETI"Rack::NullLogger#fatal;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(progname = nil, &block);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]6,doc/rack-3.0.8/ri/Rack/NullLogger/debug-i.rinu[U:RDoc::AnyMethod[iI" debug:ETI"Rack::NullLogger#debug;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"(progname = nil, &block);T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]q/doc/rack-3.0.8/ri/Rack/NullLogger/progname-i.rinu[U:RDoc::AnyMethod[iI" progname:ETI"Rack::NullLogger#progname;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/null_logger.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"NullLogger;TcRDoc::NormalClass00PK% ]z>0doc/rack-3.0.8/ri/Rack/Request/delete_param-i.rinu[U:RDoc::AnyMethod[iI"delete_param:ETI"Rack::Request#delete_param;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"(k);T@ TI" Request;TcRDoc::NormalClass00PK% ]Q#'doc/rack-3.0.8/ri/Rack/Request/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Request::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Request;TcRDoc::NormalClass00PK% ]mii3doc/rack-3.0.8/ri/Rack/Request/Env/each_header-i.rinu[U:RDoc::AnyMethod[iI"each_header:ETI"#Rack::Request::Env#each_header;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"FLoops through each key / value pair in the request specific data.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (&block);T@FI"Env;TcRDoc::NormalModule00PK% ]sbB2doc/rack-3.0.8/ri/Rack/Request/Env/add_header-i.rinu[U:RDoc::AnyMethod[iI"add_header:ETI""Rack::Request::Env#add_header;TF: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I"0Add a header that may have multiple values.;To:RDoc::Markup::BlankLineo; ; [I" Example:;To:RDoc::Markup::Verbatim; [ I".request.add_header 'Accept', 'image/png' ;TI"(request.add_header 'Accept', '* ' ;TI" ;TI"@assert_equal 'image/png, *', request.get_header('Accept') ;T: @format0o; ; [I"Ahttp://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key, v);T@FI"Env;TcRDoc::NormalModule00PK% ])g||5doc/rack-3.0.8/ri/Rack/Request/Env/has_header%3f-i.rinu[U:RDoc::AnyMethod[iI"has_header?:ETI"#Rack::Request::Env#has_header?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"GPredicate method to test to see if `name` has been set as request ;TI"specific data;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (name);T@FI"Env;TcRDoc::NormalModule00PK% ]34UU5doc/rack-3.0.8/ri/Rack/Request/Env/delete_header-i.rinu[U:RDoc::AnyMethod[iI"delete_header:ETI"%Rack::Request::Env#delete_header;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"0Delete a request specific value for `name`.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (name);T@FI"Env;TcRDoc::NormalModule00PK% ])hL+doc/rack-3.0.8/ri/Rack/Request/Env/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Request::Env::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ TI"Env;TcRDoc::NormalModule00PK% ]ątt/doc/rack-3.0.8/ri/Rack/Request/Env/cdesc-Env.rinu[U:RDoc::NormalModule[iI"Env:ETI"Rack::Request::Env;T0o:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I"env;TI"R;T: publicFI"lib/rack/request.rb;T[[[[I" class;T[[; [[I"new;T@[:protected[[: private[[I" instance;T[[; [ [I"add_header;T@[I"delete_header;T@[I"each_header;T@[I"fetch_header;T@[I"get_header;T@[I"has_header?;T@[I"initialize_copy;T@[I"set_header;T@[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@ I"Rack::Request;TcRDoc::NormalClassPK% ]ӏ4doc/rack-3.0.8/ri/Rack/Request/Env/fetch_header-i.rinu[U:RDoc::AnyMethod[iI"fetch_header:ETI"$Rack::Request::Env#fetch_header;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"NIf a block is given, it yields to the block if the value hasn't been set ;TI"on the request.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"(name, &block);T@FI"Env;TcRDoc::NormalModule00PK% ]UU2doc/rack-3.0.8/ri/Rack/Request/Env/set_header-i.rinu[U:RDoc::AnyMethod[iI"set_header:ETI""Rack::Request::Env#set_header;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"3Set a request specific value for `name` to `v`;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"(name, v);T@FI"Env;TcRDoc::NormalModule00PK% ]t˰  7doc/rack-3.0.8/ri/Rack/Request/Env/initialize_copy-i.rinu[U:RDoc::AnyMethod[iI"initialize_copy:ETI"'Rack::Request::Env#initialize_copy;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (other);T@ FI"Env;TcRDoc::NormalModule00PK% ]S44+doc/rack-3.0.8/ri/Rack/Request/Env/env-i.rinu[U:RDoc::Attr[iI"env:ETI"Rack::Request::Env#env;TI"R;T: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"$The environment of the request.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below0F@I"Rack::Request::Env;TcRDoc::NormalModule0PK% ] @LL2doc/rack-3.0.8/ri/Rack/Request/Env/get_header-i.rinu[U:RDoc::AnyMethod[iI"get_header:ETI""Rack::Request::Env#get_header;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"-Get a request specific value for `name`.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (name);T@FI"Env;TcRDoc::NormalModule00PK% ]Ƹ*doc/rack-3.0.8/ri/Rack/Request/params-i.rinu[U:RDoc::AnyMethod[iI" params:ETI"Rack::Request#params;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ TI" Request;TcRDoc::NormalClass00PK% ]q>doc/rack-3.0.8/ri/Rack/Request/x_forwarded_proto_priority-c.rinu[U:RDoc::Attr[iI"x_forwarded_proto_priority:ETI".Rack::Request::x_forwarded_proto_priority;TI"RW;T: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"FThe priority when checking either the X-Forwarded-Proto ;TI"Gor X-Forwarded-Scheme header for the forwarded protocol. ;TI";The default is [:proto, :scheme], to try the ;TI"2X-Forwarded-Proto header before the ;TI">X-Forwarded-Scheme header. Rack 2 had behavior ;TI"Fsimilar to [:scheme, :proto]. You can remove either or ;TI"Cboth of the entries in array to ignore that respective header.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below0T@I"Rack::Request;TcRDoc::NormalClass0PK% ]""5doc/rack-3.0.8/ri/Rack/Request/Helpers/authority-i.rinu[U:RDoc::AnyMethod[iI"authority:ETI"%Rack::Request::Helpers#authority;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"BThe authority of the incoming request as defined by RFC3976. ;TI"4https://tools.ietf.org/html/rfc3986#section-3.2;To:RDoc::Markup::BlankLineo; ; [I"+In HTTP/1, this is the `host` header. ;TI"7In HTTP/2, this is the `:authority` pseudo-header.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]4ee8doc/rack-3.0.8/ri/Rack/Request/Helpers/delete_param-i.rinu[U:RDoc::AnyMethod[iI"delete_param:ETI"(Rack::Request::Helpers#delete_param;TF: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I"oDestructively delete a parameter, whether it's in GET or POST. Returns the value of the deleted parameter.;To:RDoc::Markup::BlankLineo; ; [I"nIf the parameter is in both GET and POST, the POST value takes precedence since that's how #params works.;T@o; ; [I"/env['rack.input'] is not touched.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"(k);T@FI" Helpers;TcRDoc::NormalModule00PK% ]5#>>5doc/rack-3.0.8/ri/Rack/Request/Helpers/values_at-i.rinu[U:RDoc::AnyMethod[iI"values_at:ETI"%Rack::Request::Helpers#values_at;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"like Hash#values_at;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (*keys);T@FI" Helpers;TcRDoc::NormalModule00PK% ](܃>doc/rack-3.0.8/ri/Rack/Request/Helpers/get_http_forwarded-i.rinu[U:RDoc::AnyMethod[iI"get_http_forwarded:ETI".Rack::Request::Helpers#get_http_forwarded;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"KGet an array of values set in the RFC 7239 `Forwarded` request header.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (token);T@FI" Helpers;TcRDoc::NormalModule00PK% ]!X8doc/rack-3.0.8/ri/Rack/Request/Helpers/query_parser-i.rinu[U:RDoc::AnyMethod[iI"query_parser:ETI"(Rack::Request::Helpers#query_parser;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]#~8doc/rack-3.0.8/ri/Rack/Request/Helpers/form_data%3f-i.rinu[U:RDoc::AnyMethod[iI"form_data?:ETI"&Rack::Request::Helpers#form_data?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"GDetermine whether the request body contains form-data by checking ;TI":the request content-type for one of the media-types: ;TI"G"application/x-www-form-urlencoded" or "multipart/form-data". The ;TI"?list of form-data media types can be modified through the ;TI"#+FORM_DATA_MEDIA_TYPES+ array.;To:RDoc::Markup::BlankLineo; ; [I"AA request body is also assumed to contain form-data when no ;TI"Dcontent-type header is provided and the request_method is POST.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]j2doc/rack-3.0.8/ri/Rack/Request/Helpers/scheme-i.rinu[U:RDoc::AnyMethod[iI" scheme:ETI""Rack::Request::Helpers#scheme;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]ļ>doc/rack-3.0.8/ri/Rack/Request/Helpers/forwarded_priority-i.rinu[U:RDoc::AnyMethod[iI"forwarded_priority:ETI".Rack::Request::Helpers#forwarded_priority;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]y:doc/rack-3.0.8/ri/Rack/Request/Helpers/allowed_scheme-i.rinu[U:RDoc::AnyMethod[iI"allowed_scheme:ETI"*Rack::Request::Helpers#allowed_scheme;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (header);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]7doc/rack-3.0.8/ri/Rack/Request/Helpers/cdesc-Helpers.rinu[U:RDoc::NormalModule[iI" Helpers:ETI"Rack::Request::Helpers;T0o:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[U:RDoc::Constant[iI"FORM_DATA_MEDIA_TYPES;TI"2Rack::Request::Helpers::FORM_DATA_MEDIA_TYPES;T: public0o;;[o:RDoc::Markup::Paragraph;[I"EThe set of form-data media-types. Requests that do not indicate ;TI"Fone of the media types present in this list will not be eligible ;TI"#for form-data / param parsing.;T; @ ; 0@ @cRDoc::NormalModule0U; [iI"PARSEABLE_DATA_MEDIA_TYPES;TI"7Rack::Request::Helpers::PARSEABLE_DATA_MEDIA_TYPES;T; 0o;;[o; ;[I";The set of media-types. Requests that do not indicate ;TI"Fone of the media types present in this list will not be eligible ;TI"Bfor param parsing like soap attachments or generic multiparts;T; @ ; 0@ @@0U; [iI"DEFAULT_PORTS;TI"*Rack::Request::Helpers::DEFAULT_PORTS;T; 0o;;[o; ;[I"FDefault ports depending on scheme. Used to decide whether or not ;TI",to include the port in a generated URI.;T; @ ; 0@ @@0U; [iI"HTTP_X_FORWARDED_FOR;TI"1Rack::Request::Helpers::HTTP_X_FORWARDED_FOR;T; 0o;;[o; ;[I" 'utf-8' };T: @format0: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]ygg4doc/rack-3.0.8/ri/Rack/Request/Helpers/trace%3f-i.rinu[U:RDoc::AnyMethod[iI" trace?:ETI""Rack::Request::Helpers#trace?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"LChecks the HTTP request method (or verb) to see if it was of type TRACE;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]T2doc/rack-3.0.8/ri/Rack/Request/Helpers/ssl%3f-i.rinu[U:RDoc::AnyMethod[iI" ssl?:ETI" Rack::Request::Helpers#ssl?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]w52doc/rack-3.0.8/ri/Rack/Request/Helpers/logger-i.rinu[U:RDoc::AnyMethod[iI" logger:ETI""Rack::Request::Helpers#logger;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]*e6doc/rack-3.0.8/ri/Rack/Request/Helpers/media_type-i.rinu[U:RDoc::AnyMethod[iI"media_type:ETI"&Rack::Request::Helpers#media_type;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"FThe media type (type/subtype) portion of the CONTENT_TYPE header ;TI"Cwithout any media type parameters. e.g., when CONTENT_TYPE is ;TI"@"text/plain;charset=utf-8", the media-type is "text/plain".;To:RDoc::Markup::BlankLineo; ; [I"BFor more information on the use of media types in HTTP, see: ;TI"Ahttp://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]˭-  <doc/rack-3.0.8/ri/Rack/Request/Helpers/trusted_proxy%3f-i.rinu[U:RDoc::AnyMethod[iI"trusted_proxy?:ETI"*Rack::Request::Helpers#trusted_proxy?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (ip);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]v0doc/rack-3.0.8/ri/Rack/Request/Helpers/port-i.rinu[U:RDoc::AnyMethod[iI" port:ETI" Rack::Request::Helpers#port;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]G`%%Ddoc/rack-3.0.8/ri/Rack/Request/Helpers/parse_http_accept_header-i.rinu[U:RDoc::AnyMethod[iI"parse_http_accept_header:ETI"4Rack::Request::Helpers#parse_http_accept_header;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (header);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]  ;doc/rack-3.0.8/ri/Rack/Request/Helpers/accept_language-i.rinu[U:RDoc::AnyMethod[iI"accept_language:ETI"+Rack::Request::Helpers#accept_language;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]eh7doc/rack-3.0.8/ri/Rack/Request/Helpers/server_port-i.rinu[U:RDoc::AnyMethod[iI"server_port:ETI"'Rack::Request::Helpers#server_port;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ] >l2doc/rack-3.0.8/ri/Rack/Request/Helpers/params-i.rinu[U:RDoc::AnyMethod[iI" params:ETI""Rack::Request::Helpers#params;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"$The union of GET and POST data.;To:RDoc::Markup::BlankLineo; ; [I"Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]aa2doc/rack-3.0.8/ri/Rack/Request/Helpers/put%3f-i.rinu[U:RDoc::AnyMethod[iI" put?:ETI" Rack::Request::Helpers#put?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"JChecks the HTTP request method (or verb) to see if it was of type PUT;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]ovx.doc/rack-3.0.8/ri/Rack/Request/Helpers/ip-i.rinu[U:RDoc::AnyMethod[iI"ip:ETI"Rack::Request::Helpers#ip;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ].u  :doc/rack-3.0.8/ri/Rack/Request/Helpers/content_length-i.rinu[U:RDoc::AnyMethod[iI"content_length:ETI"*Rack::Request::Helpers#content_length;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]x#z=doc/rack-3.0.8/ri/Rack/Request/Helpers/parseable_data%3f-i.rinu[U:RDoc::AnyMethod[iI"parseable_data?:ETI"+Rack::Request::Helpers#parseable_data?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"BDetermine whether the request body contains data by checking ;TI"Ethe request media_type against registered parse-data media-types;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ].7DD2doc/rack-3.0.8/ri/Rack/Request/Helpers/%5b%5d-i.rinu[U:RDoc::AnyMethod[iI"[]:ETI"Rack::Request::Helpers#[];TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I".shortcut for request.params[key];T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@FI" Helpers;TcRDoc::NormalModule00PK% ]75  :doc/rack-3.0.8/ri/Rack/Request/Helpers/request_method-i.rinu[U:RDoc::AnyMethod[iI"request_method:ETI"*Rack::Request::Helpers#request_method;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]F  ;doc/rack-3.0.8/ri/Rack/Request/Helpers/accept_encoding-i.rinu[U:RDoc::AnyMethod[iI"accept_encoding:ETI"+Rack::Request::Helpers#accept_encoding;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]R<5doc/rack-3.0.8/ri/Rack/Request/Helpers/path_info-i.rinu[U:RDoc::AnyMethod[iI"path_info:ETI"%Rack::Request::Helpers#path_info;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]F..;doc/rack-3.0.8/ri/Rack/Request/Helpers/content_charset-i.rinu[U:RDoc::AnyMethod[iI"content_charset:ETI"+Rack::Request::Helpers#content_charset;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"EThe character set of the request body if a "charset" media type ;TI"Eparameter was given, or nil if no "charset" was specified. Note ;TI"Dthat, per RFC2616, text/* media types that specify no explicit ;TI"-charset are to be considered ISO-8859-1.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]>J6  ;doc/rack-3.0.8/ri/Rack/Request/Helpers/parse_multipart-i.rinu[U:RDoc::AnyMethod[iI"parse_multipart:ETI"+Rack::Request::Helpers#parse_multipart;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]]tGG:doc/rack-3.0.8/ri/Rack/Request/Helpers/host_authority-i.rinu[U:RDoc::AnyMethod[iI"host_authority:ETI"*Rack::Request::Helpers#host_authority;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"The `HTTP_HOST` header.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]*fd?WW0doc/rack-3.0.8/ri/Rack/Request/Helpers/host-i.rinu[U:RDoc::AnyMethod[iI" host:ETI" Rack::Request::Helpers#host;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"@Returns a formatted host, suitable for being used in a URI.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]|_E0doc/rack-3.0.8/ri/Rack/Request/Helpers/path-i.rinu[U:RDoc::AnyMethod[iI" path:ETI" Rack::Request::Helpers#path;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]ppy#jj5doc/rack-3.0.8/ri/Rack/Request/Helpers/unlink%3f-i.rinu[U:RDoc::AnyMethod[iI" unlink?:ETI"#Rack::Request::Helpers#unlink?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"MChecks the HTTP request method (or verb) to see if it was of type UNLINK;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]ɰ6doc/rack-3.0.8/ri/Rack/Request/Helpers/user_agent-i.rinu[U:RDoc::AnyMethod[iI"user_agent:ETI"&Rack::Request::Helpers#user_agent;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]y8doc/rack-3.0.8/ri/Rack/Request/Helpers/content_type-i.rinu[U:RDoc::AnyMethod[iI"content_type:ETI"(Rack::Request::Helpers#content_type;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]?s1H4doc/rack-3.0.8/ri/Rack/Request/Helpers/base_url-i.rinu[U:RDoc::AnyMethod[iI" base_url:ETI"$Rack::Request::Helpers#base_url;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]  8doc/rack-3.0.8/ri/Rack/Request/Helpers/split_header-i.rinu[U:RDoc::AnyMethod[iI"split_header:ETI"(Rack::Request::Helpers#split_header;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (value);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]k<doc/rack-3.0.8/ri/Rack/Request/Helpers/forwarded_scheme-i.rinu[U:RDoc::AnyMethod[iI"forwarded_scheme:ETI",Rack::Request::Helpers#forwarded_scheme;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]#dd3doc/rack-3.0.8/ri/Rack/Request/Helpers/post%3f-i.rinu[U:RDoc::AnyMethod[iI" post?:ETI"!Rack::Request::Helpers#post?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"KChecks the HTTP request method (or verb) to see if it was of type POST;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]~e$$:doc/rack-3.0.8/ri/Rack/Request/Helpers/host_with_port-i.rinu[U:RDoc::AnyMethod[iI"host_with_port:ETI"*Rack::Request::Helpers#host_with_port;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"!(authority = self.authority);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]дdd3doc/rack-3.0.8/ri/Rack/Request/Helpers/link%3f-i.rinu[U:RDoc::AnyMethod[iI" link?:ETI"!Rack::Request::Helpers#link?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"KChecks the HTTP request method (or verb) to see if it was of type LINK;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]ls5doc/rack-3.0.8/ri/Rack/Request/Helpers/%5b%5d%3d-i.rinu[U:RDoc::AnyMethod[iI"[]=:ETI"Rack::Request::Helpers#[]=;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"6shortcut for request.params[key] = value;To:RDoc::Markup::BlankLineo; ; [I"Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"(key, value);T@FI" Helpers;TcRDoc::NormalModule00PK% ]4ώ7doc/rack-3.0.8/ri/Rack/Request/Helpers/server_name-i.rinu[U:RDoc::AnyMethod[iI"server_name:ETI"'Rack::Request::Helpers#server_name;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]Id0doc/rack-3.0.8/ri/Rack/Request/Helpers/body-i.rinu[U:RDoc::AnyMethod[iI" body:ETI" Rack::Request::Helpers#body;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]ى;doc/rack-3.0.8/ri/Rack/Request/Helpers/split_authority-i.rinu[U:RDoc::AnyMethod[iI"split_authority:ETI"+Rack::Request::Helpers#split_authority;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"(authority);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]&jj5doc/rack-3.0.8/ri/Rack/Request/Helpers/delete%3f-i.rinu[U:RDoc::AnyMethod[iI" delete?:ETI"#Rack::Request::Helpers#delete?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"MChecks the HTTP request method (or verb) to see if it was of type DELETE;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]A9doc/rack-3.0.8/ri/Rack/Request/Helpers/forwarded_for-i.rinu[U:RDoc::AnyMethod[iI"forwarded_for:ETI")Rack::Request::Helpers#forwarded_for;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]my`8doc/rack-3.0.8/ri/Rack/Request/Helpers/query_string-i.rinu[U:RDoc::AnyMethod[iI"query_string:ETI"(Rack::Request::Helpers#query_string;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]+  ;doc/rack-3.0.8/ri/Rack/Request/Helpers/default_session-i.rinu[U:RDoc::AnyMethod[iI"default_session:ETI"+Rack::Request::Helpers#default_session;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]"HH/doc/rack-3.0.8/ri/Rack/Request/Helpers/GET-i.rinu[U:RDoc::AnyMethod[iI"GET:ETI"Rack::Request::Helpers#GET;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"3Returns the data received in the query string.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]91  :doc/rack-3.0.8/ri/Rack/Request/Helpers/forwarded_port-i.rinu[U:RDoc::AnyMethod[iI"forwarded_port:ETI"*Rack::Request::Helpers#forwarded_port;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]V Paa2doc/rack-3.0.8/ri/Rack/Request/Helpers/get%3f-i.rinu[U:RDoc::AnyMethod[iI" get?:ETI" Rack::Request::Helpers#get?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"JChecks the HTTP request method (or verb) to see if it was of type GET;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]єoo8doc/rack-3.0.8/ri/Rack/Request/Helpers/update_param-i.rinu[U:RDoc::AnyMethod[iI"update_param:ETI"(Rack::Request::Helpers#update_param;TF: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I"TDestructively update a parameter, whether it's in GET and/or POST. Returns nil.;To:RDoc::Markup::BlankLineo; ; [I"The parameter is updated wherever it was previous defined, so GET, POST, or both. If it wasn't previously defined, it's inserted into GET.;T@o; ; [I"/env['rack.input'] is not touched.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (k, v);T@FI" Helpers;TcRDoc::NormalModule00PK% ];W11Gdoc/rack-3.0.8/ri/Rack/Request/Helpers/reject_trusted_ip_addresses-i.rinu[U:RDoc::AnyMethod[iI" reject_trusted_ip_addresses:ETI"7Rack::Request::Helpers#reject_trusted_ip_addresses;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"(ip_addresses);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]nZ[[3doc/rack-3.0.8/ri/Rack/Request/Helpers/referer-i.rinu[U:RDoc::AnyMethod[iI" referer:ETI"#Rack::Request::Helpers#referer;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"the referer of the client;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[[I" referrer;To;; [; @; 0I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]kW7doc/rack-3.0.8/ri/Rack/Request/Helpers/script_name-i.rinu[U:RDoc::AnyMethod[iI"script_name:ETI"'Rack::Request::Helpers#script_name;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]A[[/doc/rack-3.0.8/ri/Rack/Request/Helpers/url-i.rinu[U:RDoc::AnyMethod[iI"url:ETI"Rack::Request::Helpers#url;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"FTries to return a remake of the original request URL as a string.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]n0doc/rack-3.0.8/ri/Rack/Request/Helpers/POST-i.rinu[U:RDoc::AnyMethod[iI" POST:ETI" Rack::Request::Helpers#POST;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"3Returns the data received in the request body.;To:RDoc::Markup::BlankLineo; ; [I"DThis method support both application/x-www-form-urlencoded and ;TI"multipart/form-data.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]):doc/rack-3.0.8/ri/Rack/Request/Helpers/script_name%3d-i.rinu[U:RDoc::AnyMethod[iI"script_name=:ETI"(Rack::Request::Helpers#script_name=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"(s);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]dd3doc/rack-3.0.8/ri/Rack/Request/Helpers/head%3f-i.rinu[U:RDoc::AnyMethod[iI" head?:ETI"!Rack::Request::Helpers#head?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"KChecks the HTTP request method (or verb) to see if it was of type HEAD;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ];2doc/rack-3.0.8/ri/Rack/Request/Helpers/xhr%3f-i.rinu[U:RDoc::AnyMethod[iI" xhr?:ETI" Rack::Request::Helpers#xhr?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]$-++4doc/rack-3.0.8/ri/Rack/Request/Helpers/referrer-i.rinu[U:RDoc::AnyMethod[iI" referrer:ETI"$Rack::Request::Helpers#referrer;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule0[I"Rack::Request::Helpers;TFI" referer;TPK% ]tX8doc/rack-3.0.8/ri/Rack/Request/Helpers/path_info%3d-i.rinu[U:RDoc::AnyMethod[iI"path_info=:ETI"&Rack::Request::Helpers#path_info=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"(s);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]X|  ;doc/rack-3.0.8/ri/Rack/Request/Helpers/session_options-i.rinu[U:RDoc::AnyMethod[iI"session_options:ETI"+Rack::Request::Helpers#session_options;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]pJ6doc/rack-3.0.8/ri/Rack/Request/forwarded_priority-c.rinu[U:RDoc::Attr[iI"forwarded_priority:ETI"&Rack::Request::forwarded_priority;TI"RW;T: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"?The priority when checking forwarded headers. The default ;TI"Dis [:forwarded, :x_forwarded], which means, check the ;TI";+Forwarded+ header first, followed by the appropriate ;TI"DX-Forwarded-* header. You can revert the priority by ;TI":reversing the priority, or remove checking of either ;TI"9or both headers by removing elements from the array.;To:RDoc::Markup::BlankLineo; ; [ I";This should be set as appropriate in your environment ;TI"?based on what reverse proxies are in use. If you are not ;TI"=using reverse proxies, you should probably use an empty ;TI" array.;T: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below0T@I"Rack::Request;TcRDoc::NormalClass0PK% ]e|P0doc/rack-3.0.8/ri/Rack/Request/update_param-i.rinu[U:RDoc::AnyMethod[iI"update_param:ETI"Rack::Request#update_param;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (k, v);T@ TI" Request;TcRDoc::NormalClass00PK% ]@]rr/doc/rack-3.0.8/ri/Rack/Request/cdesc-Request.rinu[U:RDoc::NormalClass[iI" Request:ETI"Rack::Request;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"=Rack::Request provides a convenient interface to a Rack ;TI"Henvironment. It is stateless, the environment +env+ passed to the ;TI"+constructor will be directly modified.;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim;[I""req = Rack::Request.new(env) ;TI"req.post? ;TI"req.params["data"];T: @format0: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below0; 0;0[[ I"forwarded_priority;TI"RW;T: publicTI"lib/rack/request.rb;T[ I"ip_filter;T@;T@[ I"x_forwarded_proto_priority;T@;T@[U:RDoc::Constant[iI"ALLOWED_SCHEMES;TI"#Rack::Request::ALLOWED_SCHEMES;T;0o;;[; @;0@@cRDoc::NormalClass0[[I"Env;To;;[; @;0@[I" Helpers;To;;[; @;0@[[I" class;T[[;[[I"new;T@[:protected[[: private[[I" instance;T[[;[[I"delete_param;T@[I" params;T@[I"update_param;T@[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0;0[@I" Rack;TcRDoc::NormalModulePK% ]È*-doc/rack-3.0.8/ri/Rack/Request/ip_filter-c.rinu[U:RDoc::Attr[iI"ip_filter:ETI"Rack::Request::ip_filter;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/request.rb;T:0@omit_headings_from_table_of_contents_below0T@ I"Rack::Request;TcRDoc::NormalClass0PK% ]/doc/rack-3.0.8/ri/Rack/MockRequest/env_for-c.rinu[U:RDoc::AnyMethod[iI" env_for:ETI"Rack::MockRequest::env_for;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I">Return the Rack environment used for a request to +uri+. ;TI"IAll options that are strings are added to the returned environment. ;TI" Options:;To:RDoc::Markup::List: @type: NOTE: @items[ o:RDoc::Markup::ListItem: @label[I" :fatal ;T; [o; ; [I"DWhether to raise an exception if request outputs to rack.errors;To;;[I" :input ;T; [o; ; [I"The rack.input to set;To;;[I":http_version ;T; [o; ; [I"The SERVER_PROTOCOL to set;To;;[I" :method ;T; [o; ; [I"#The HTTP request method to use;To;;[I" :params ;T; [o; ; [I"The params to use;To;;[I":script_name ;T; [o; ; [I"The SCRIPT_NAME to set;T: @fileI"lib/rack/mock_request.rb;T:0@omit_headings_from_table_of_contents_below000[I"(uri = "", opts = {});T@You can pass a hash with additional configuration to the ;TI"get/post/put/patch/delete.;To:RDoc::Markup::List: @type: NOTE: @items[o:RDoc::Markup::ListItem: @label[I":input;T;[o; ;[I"2A String or IO-like to be used as rack.input.;To;;[I":fatal;T;[o; ;[I";Raise a FatalWarning if the app writes to rack.errors.;To;;[I":lint;T;[o; ;[I"3If true, wrap the application in a Rack::Lint.;T: @fileI"lib/rack/mock_request.rb;T:0@omit_headings_from_table_of_contents_below0;0;0[[U:RDoc::Constant[iI"DEFAULT_ENV;TI"#Rack::MockRequest::DEFAULT_ENV;T: public0o;;[;@3;0@3@cRDoc::NormalClass0[[[I" class;T[[;[[I" env_for;TI"lib/rack/mock_request.rb;T[I"new;T@F[I"parse_uri_rfc2396;T@F[:protected[[: private[[I" instance;T[[;[ [I" delete;T@F[I"get;T@F[I" head;T@F[I" options;T@F[I" patch;T@F[I" post;T@F[I"put;T@F[I" request;T@F[;[[;[[[U:RDoc::Context::Section[i0o;;[;0;0[@3I" Rack;TcRDoc::NormalModulePK% ]ƓØ9doc/rack-3.0.8/ri/Rack/MockRequest/parse_uri_rfc2396-c.rinu[U:RDoc::AnyMethod[iI"parse_uri_rfc2396:ETI")Rack::MockRequest::parse_uri_rfc2396;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"8For historical reasons, we're pinning to RFC 2396. ;TI"&URI::Parser = URI::RFC2396_Parser;T: @fileI"lib/rack/mock_request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (uri);T@FI"MockRequest;TcRDoc::NormalClass00PK% ]hҲff+doc/rack-3.0.8/ri/Rack/MockRequest/put-i.rinu[U:RDoc::AnyMethod[iI"put:ETI"Rack::MockRequest#put;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"@Make a PUT request and return a MockResponse. See #request.;T: @fileI"lib/rack/mock_request.rb;T:0@omit_headings_from_table_of_contents_below000[I"(uri, opts = {});T@FI"MockRequest;TcRDoc::NormalClass00PK% ]_K+doc/rack-3.0.8/ri/Rack/Response/length-i.rinu[U:RDoc::Attr[iI" length:ETI"Rack::Response#length;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Response;TcRDoc::NormalClass0PK% ]/32doc/rack-3.0.8/ri/Rack/Response/has_header%3f-i.rinu[U:RDoc::AnyMethod[iI"has_header?:ETI"Rack::Response#has_header?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ FI" Response;TcRDoc::NormalClass00PK% ]0?2doc/rack-3.0.8/ri/Rack/Response/delete_header-i.rinu[U:RDoc::AnyMethod[iI"delete_header:ETI"!Rack::Response#delete_header;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ FI" Response;TcRDoc::NormalClass00PK% ]h)doc/rack-3.0.8/ri/Rack/Response/to_a-i.rinu[U:RDoc::AnyMethod[iI" to_a:ETI"Rack::Response#to_a;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (&block);T@ FI" Response;TcRDoc::NormalClass0[I"Rack::Response;TFI" finish;TPK% ] +doc/rack-3.0.8/ri/Rack/Response/%5b%5d-c.rinu[U:RDoc::AnyMethod[iI"[]:ETI"Rack::Response::[];TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"(status, headers, body);T@ FI" Response;TcRDoc::NormalClass00PK% ]M::(doc/rack-3.0.8/ri/Rack/Response/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Response::new;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"HInitialize the response object with the specified +body+, +status+ ;TI"and +headers+.;To:RDoc::Markup::BlankLineo; ; [I"NIf the +body+ is +nil+, construct an empty response object with internal ;TI"buffering.;T@o; ; [I"NIf the +body+ responds to +to_str+, assume it's a string-like object and ;TI"Nconstruct a buffered response object containing using that string as the ;TI"$initial contents of the buffer.;T@o; ; [I"NOtherwise it is expected +body+ conforms to the normal requirements of a ;TI"JRack response body, typically implementing one of +each+ (enumerable ;TI"&body) or +call+ (streaming body).;T@o; ; [I"LThe +status+ defaults to +200+ which is the "OK" HTTP status code. You ;TI"-can provide any other valid status code.;T@o; ; [I"OThe +headers+ must be a +Hash+ of key-value header pairs which conform to ;TI"Mthe Rack specification for response headers. The key must be a +String+ ;TI"Iinstance and the value can be either a +String+ or +Array+ instance.;T: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below00I" self;T[I"-(body = nil, status = 200, headers = {});T@'FI" Response;TcRDoc::NormalClass00PK% ]>Cw-doc/rack-3.0.8/ri/Rack/Response/empty%3f-i.rinu[U:RDoc::AnyMethod[iI" empty?:ETI"Rack::Response#empty?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Response;TcRDoc::NormalClass00PK% ]  -doc/rack-3.0.8/ri/Rack/Response/redirect-i.rinu[U:RDoc::AnyMethod[iI" redirect:ETI"Rack::Response#redirect;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"(target, status = 302);T@ FI" Response;TcRDoc::NormalClass00PK% ]ӎ1doc/rack-3.0.8/ri/Rack/Response/cdesc-Response.rinu[U:RDoc::NormalClass[iI" Response:ETI"Rack::Response;TI" Object;To:RDoc::Markup::Document: @parts[o;;[ o:RDoc::Markup::Paragraph;[I"ERack::Response provides a convenient interface to create a Rack ;TI"response.;To:RDoc::Markup::BlankLineo; ;[I"CIt allows setting of headers and cookies, and provides useful ;TI";defaults (an OK response with empty headers and body).;T@o; ;[ I"GYou can use Response#write to iteratively generate your response, ;TI"Ebut note that this is buffered by Rack::Response until you call ;TI"H+finish+. +finish+ however can take a block inside which calls to ;TI"4+write+ are synchronous with the Rack response.;T@o; ;[I"DYour application's +call+ should end returning Response#finish.;T: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[ [ I" body;TI"RW;T: publicFI"lib/rack/response.rb;T[ I" headers;TI"R;T; F@%[ I" length;T@$; F@%[ I" status;T@$; F@%[U:RDoc::Constant[iI" CHUNKED;TI"Rack::Response::CHUNKED;T; 0o;;[; @ ; 0@ @cRDoc::NormalClass0U;[iI"STATUS_WITH_NO_ENTITY_BODY;TI"/Rack::Response::STATUS_WITH_NO_ENTITY_BODY;T; 0o;;[; @ ; 0@ @@40[[I" Helpers;To;;[; @ ; 0@%[[I" class;T[[; [[I"[];T@%[I"new;T@%[:protected[[: private[[I" instance;T[[; [[I"[];T@%[I"[]=;T@%[I" chunked?;T@%[I" close;T@%[I"delete_header;T@%[I" each;T@%[I" empty?;T@%[I" finish;T@%[I"get_header;T@%[I"has_header?;T@%[I" header;T@%[I"no_entity_body?;T@%[I" redirect;T@%[I"set_header;T@%[I" to_a;T@%[I" write;T@%[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@ I" Rack;TcRDoc::NormalModulePK% ]V}U*doc/rack-3.0.8/ri/Rack/Response/close-i.rinu[U:RDoc::AnyMethod[iI" close:ETI"Rack::Response#close;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Response;TcRDoc::NormalClass00PK% ]gA+doc/rack-3.0.8/ri/Rack/Response/%5b%5d-i.rinu[U:RDoc::AnyMethod[iI"[]:ETI"Rack::Response#[];TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ FI" Response;TcRDoc::NormalClass0[I"Rack::Response;TFI"get_header;TPK% ]n˭h*doc/rack-3.0.8/ri/Rack/Response/write-i.rinu[U:RDoc::AnyMethod[iI" write:ETI"Rack::Response#write;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I".Append to body and update content-length.;To:RDoc::Markup::BlankLineo; ; [I"5NOTE: Do not mix #write and direct #body access!;T: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (chunk);T@FI" Response;TcRDoc::NormalClass00PK% ]RP+doc/rack-3.0.8/ri/Rack/Response/status-i.rinu[U:RDoc::Attr[iI" status:ETI"Rack::Response#status;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Response;TcRDoc::NormalClass0PK% ]"+doc/rack-3.0.8/ri/Rack/Response/finish-i.rinu[U:RDoc::AnyMethod[iI" finish:ETI"Rack::Response#finish;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"MGenerate a response array consistent with the requirements of the SPEC. ;TI"E@return [Array] a 3-tuple suitable of `[status, headers, body]` ;TI"Nwhich is suitable to be returned from the middleware `#call(env)` method.;T: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[[I" to_a;To;; [; @; 0I" (&block);T@FI" Response;TcRDoc::NormalClass00PK% ]#F  8doc/rack-3.0.8/ri/Rack/Response/Helpers/location%3d-i.rinu[U:RDoc::AnyMethod[iI"location=:ETI"&Rack::Response::Helpers#location=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"(location);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]AQ?doc/rack-3.0.8/ri/Rack/Response/Helpers/request_timeout%3f-i.rinu[U:RDoc::AnyMethod[iI"request_timeout?:ETI"-Rack::Response::Helpers#request_timeout?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]U7doc/rack-3.0.8/ri/Rack/Response/Helpers/invalid%3f-i.rinu[U:RDoc::AnyMethod[iI" invalid?:ETI"%Rack::Response::Helpers#invalid?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]T>l:doc/rack-3.0.8/ri/Rack/Response/Helpers/no_content%3f-i.rinu[U:RDoc::AnyMethod[iI"no_content?:ETI"(Rack::Response::Helpers#no_content?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]5%<doc/rack-3.0.8/ri/Rack/Response/Helpers/do_not_cache%21-i.rinu[U:RDoc::AnyMethod[iI"do_not_cache!:ETI"*Rack::Response::Helpers#do_not_cache!;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"ZSpecifies that the content shouldn't be cached. Overrides `cache!` if already called.;T: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]Nz7doc/rack-3.0.8/ri/Rack/Response/Helpers/add_header-i.rinu[U:RDoc::AnyMethod[iI"add_header:ETI"'Rack::Response::Helpers#add_header;TF: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I"0Add a header that may have multiple values.;To:RDoc::Markup::BlankLineo; ; [I" Example:;To:RDoc::Markup::Verbatim; [ I"3response.add_header 'vary', 'accept-encoding' ;TI"*response.add_header 'vary', 'cookie' ;TI" ;TI"Hassert_equal 'accept-encoding,cookie', response.get_header('vary') ;T: @format0o; ; [I"Ahttp://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2;T: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"(key, value);T@FI" Helpers;TcRDoc::NormalModule00PK% ]ty:doc/rack-3.0.8/ri/Rack/Response/Helpers/delete_cookie-i.rinu[U:RDoc::AnyMethod[iI"delete_cookie:ETI"*Rack::Response::Helpers#delete_cookie;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"(key, value = {});T@ FI" Helpers;TcRDoc::NormalModule00PK% ]kgAdoc/rack-3.0.8/ri/Rack/Response/Helpers/set_cookie_header%3d-i.rinu[U:RDoc::AnyMethod[iI"set_cookie_header=:ETI"/Rack::Response::Helpers#set_cookie_header=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (value);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]1d>  =doc/rack-3.0.8/ri/Rack/Response/Helpers/unprocessable%3f-i.rinu[U:RDoc::AnyMethod[iI"unprocessable?:ETI"+Rack::Response::Helpers#unprocessable?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]4[__8doc/rack-3.0.8/ri/Rack/Response/Helpers/cdesc-Helpers.rinu[U:RDoc::NormalModule[iI" Helpers:ETI"Rack::Response::Helpers;T0o:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [-[I"accepted?;TI"lib/rack/response.rb;T[I"add_header;T@"[I"bad_request?;T@"[I" cache!;T@"[I"cache_control;T@"[I"cache_control=;T@"[I"client_error?;T@"[I"content_length;T@"[I"content_type;T@"[I"content_type=;T@"[I" created?;T@"[I"delete_cookie;T@"[I"do_not_cache!;T@"[I" etag;T@"[I" etag=;T@"[I"forbidden?;T@"[I" include?;T@"[I"informational?;T@"[I" invalid?;T@"[I" location;T@"[I"location=;T@"[I"media_type;T@"[I"media_type_params;T@"[I"method_not_allowed?;T@"[I"moved_permanently?;T@"[I"no_content?;T@"[I"not_acceptable?;T@"[I"not_found?;T@"[I"ok?;T@"[I"precondition_failed?;T@"[I"redirect?;T@"[I"redirection?;T@"[I"request_timeout?;T@"[I"server_error?;T@"[I"set_cookie;T@"[I"set_cookie_header;T@"[I"set_cookie_header=;T@"[I"successful?;T@"[I"unauthorized?;T@"[I"unprocessable?;T@"[; [[I" append;T@"[I"buffered_body!;T@"[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@ I"Rack::Response;TcRDoc::NormalClassPK% ]z>doc/rack-3.0.8/ri/Rack/Response/Helpers/not_acceptable%3f-i.rinu[U:RDoc::AnyMethod[iI"not_acceptable?:ETI",Rack::Response::Helpers#not_acceptable?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]̋$=doc/rack-3.0.8/ri/Rack/Response/Helpers/buffered_body%21-i.rinu[U:RDoc::AnyMethod[iI"buffered_body!:ETI"+Rack::Response::Helpers#buffered_body!;TF:protectedo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ][Qm3doc/rack-3.0.8/ri/Rack/Response/Helpers/append-i.rinu[U:RDoc::AnyMethod[iI" append:ETI"#Rack::Response::Helpers#append;TF:protectedo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (chunk);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]pC8doc/rack-3.0.8/ri/Rack/Response/Helpers/accepted%3f-i.rinu[U:RDoc::AnyMethod[iI"accepted?:ETI"&Rack::Response::Helpers#accepted?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]W>doc/rack-3.0.8/ri/Rack/Response/Helpers/media_type_params-i.rinu[U:RDoc::AnyMethod[iI"media_type_params:ETI".Rack::Response::Helpers#media_type_params;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]a7doc/rack-3.0.8/ri/Rack/Response/Helpers/include%3f-i.rinu[U:RDoc::AnyMethod[iI" include?:ETI"%Rack::Response::Helpers#include?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (header);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]&Oz7doc/rack-3.0.8/ri/Rack/Response/Helpers/media_type-i.rinu[U:RDoc::AnyMethod[iI"media_type:ETI"'Rack::Response::Helpers#media_type;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]2^1doc/rack-3.0.8/ri/Rack/Response/Helpers/etag-i.rinu[U:RDoc::AnyMethod[iI" etag:ETI"!Rack::Response::Helpers#etag;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]E :doc/rack-3.0.8/ri/Rack/Response/Helpers/successful%3f-i.rinu[U:RDoc::AnyMethod[iI"successful?:ETI"(Rack::Response::Helpers#successful?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]Lz>doc/rack-3.0.8/ri/Rack/Response/Helpers/set_cookie_header-i.rinu[U:RDoc::AnyMethod[iI"set_cookie_header:ETI".Rack::Response::Helpers#set_cookie_header;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]%{Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/precondition_failed%3f-i.rinu[U:RDoc::AnyMethod[iI"precondition_failed?:ETI"1Rack::Response::Helpers#precondition_failed?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]  ;doc/rack-3.0.8/ri/Rack/Response/Helpers/content_length-i.rinu[U:RDoc::AnyMethod[iI"content_length:ETI"+Rack::Response::Helpers#content_length;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]Jc  <doc/rack-3.0.8/ri/Rack/Response/Helpers/server_error%3f-i.rinu[U:RDoc::AnyMethod[iI"server_error?:ETI"*Rack::Response::Helpers#server_error?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ];doc/rack-3.0.8/ri/Rack/Response/Helpers/redirection%3f-i.rinu[U:RDoc::AnyMethod[iI"redirection?:ETI")Rack::Response::Helpers#redirection?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ];doc/rack-3.0.8/ri/Rack/Response/Helpers/bad_request%3f-i.rinu[U:RDoc::AnyMethod[iI"bad_request?:ETI")Rack::Response::Helpers#bad_request?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]z5doc/rack-3.0.8/ri/Rack/Response/Helpers/location-i.rinu[U:RDoc::AnyMethod[iI" location:ETI"%Rack::Response::Helpers#location;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]5Bdoc/rack-3.0.8/ri/Rack/Response/Helpers/method_not_allowed%3f-i.rinu[U:RDoc::AnyMethod[iI"method_not_allowed?:ETI"0Rack::Response::Helpers#method_not_allowed?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]6My7doc/rack-3.0.8/ri/Rack/Response/Helpers/created%3f-i.rinu[U:RDoc::AnyMethod[iI" created?:ETI"%Rack::Response::Helpers#created?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]Q9doc/rack-3.0.8/ri/Rack/Response/Helpers/not_found%3f-i.rinu[U:RDoc::AnyMethod[iI"not_found?:ETI"'Rack::Response::Helpers#not_found?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]'C555doc/rack-3.0.8/ri/Rack/Response/Helpers/cache%21-i.rinu[U:RDoc::AnyMethod[iI" cache!:ETI"#Rack::Response::Helpers#cache!;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"0Specify that the content should be cached. ;TI"N@param duration [Integer] The number of seconds until the cache expires. ;TI"r@option directive [String] The cache control directive, one of "public", "private", "no-cache" or "no-store".;T: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"+(duration = 3600, directive: "public");T@FI" Helpers;TcRDoc::NormalModule00PK% ]M SS9doc/rack-3.0.8/ri/Rack/Response/Helpers/content_type-i.rinu[U:RDoc::AnyMethod[iI"content_type:ETI")Rack::Response::Helpers#content_type;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"*Get the content type of the response.;T: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Helpers;TcRDoc::NormalModule00PK% ]3(  <doc/rack-3.0.8/ri/Rack/Response/Helpers/unauthorized%3f-i.rinu[U:RDoc::AnyMethod[iI"unauthorized?:ETI"*Rack::Response::Helpers#unauthorized?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]H*a2doc/rack-3.0.8/ri/Rack/Response/Helpers/ok%3f-i.rinu[U:RDoc::AnyMethod[iI"ok?:ETI" Rack::Response::Helpers#ok?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]|w  =doc/rack-3.0.8/ri/Rack/Response/Helpers/informational%3f-i.rinu[U:RDoc::AnyMethod[iI"informational?:ETI"+Rack::Response::Helpers#informational?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]74doc/rack-3.0.8/ri/Rack/Response/Helpers/etag%3d-i.rinu[U:RDoc::AnyMethod[iI" etag=:ETI""Rack::Response::Helpers#etag=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (value);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]t3aa<doc/rack-3.0.8/ri/Rack/Response/Helpers/content_type%3d-i.rinu[U:RDoc::AnyMethod[iI"content_type=:ETI"*Rack::Response::Helpers#content_type=;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"*Set the content type of the response.;T: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"(content_type);T@FI" Helpers;TcRDoc::NormalModule00PK% ]7doc/rack-3.0.8/ri/Rack/Response/Helpers/set_cookie-i.rinu[U:RDoc::AnyMethod[iI"set_cookie:ETI"'Rack::Response::Helpers#set_cookie;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"(key, value);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]hZAdoc/rack-3.0.8/ri/Rack/Response/Helpers/moved_permanently%3f-i.rinu[U:RDoc::AnyMethod[iI"moved_permanently?:ETI"/Rack::Response::Helpers#moved_permanently?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]b_bJ9doc/rack-3.0.8/ri/Rack/Response/Helpers/forbidden%3f-i.rinu[U:RDoc::AnyMethod[iI"forbidden?:ETI"'Rack::Response::Helpers#forbidden?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]`,8  :doc/rack-3.0.8/ri/Rack/Response/Helpers/cache_control-i.rinu[U:RDoc::AnyMethod[iI"cache_control:ETI"*Rack::Response::Helpers#cache_control;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]=V8doc/rack-3.0.8/ri/Rack/Response/Helpers/redirect%3f-i.rinu[U:RDoc::AnyMethod[iI"redirect?:ETI"&Rack::Response::Helpers#redirect?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]g  <doc/rack-3.0.8/ri/Rack/Response/Helpers/client_error%3f-i.rinu[U:RDoc::AnyMethod[iI"client_error?:ETI"*Rack::Response::Helpers#client_error?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Helpers;TcRDoc::NormalModule00PK% ]/=doc/rack-3.0.8/ri/Rack/Response/Helpers/cache_control%3d-i.rinu[U:RDoc::AnyMethod[iI"cache_control=:ETI"+Rack::Response::Helpers#cache_control=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (value);T@ FI" Helpers;TcRDoc::NormalModule00PK% ]Aw  /doc/rack-3.0.8/ri/Rack/Response/set_header-i.rinu[U:RDoc::AnyMethod[iI"set_header:ETI"Rack::Response#set_header;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[[I"[]=;To;; [; @ ; 0I"(key, value);T@ FI" Response;TcRDoc::NormalClass00PK% ]'|.doc/rack-3.0.8/ri/Rack/Response/%5b%5d%3d-i.rinu[U:RDoc::AnyMethod[iI"[]=:ETI"Rack::Response#[]=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"(key, value);T@ FI" Response;TcRDoc::NormalClass0[I"Rack::Response;TFI"set_header;TPK% ]Fl4)doc/rack-3.0.8/ri/Rack/Response/body-i.rinu[U:RDoc::Attr[iI" body:ETI"Rack::Response#body;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Response;TcRDoc::NormalClass0PK% ].,doc/rack-3.0.8/ri/Rack/Response/headers-i.rinu[U:RDoc::Attr[iI" headers:ETI"Rack::Response#headers;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Response;TcRDoc::NormalClass0PK% ][w/doc/rack-3.0.8/ri/Rack/Response/chunked%3f-i.rinu[U:RDoc::AnyMethod[iI" chunked?:ETI"Rack::Response#chunked?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Response;TcRDoc::NormalClass00PK% ] ʋ)doc/rack-3.0.8/ri/Rack/Response/each-i.rinu[U:RDoc::AnyMethod[iI" each:ETI"Rack::Response#each;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"(&callback);T@ FI" Response;TcRDoc::NormalClass00PK% ](6doc/rack-3.0.8/ri/Rack/Response/Raw/has_header%3f-i.rinu[U:RDoc::AnyMethod[iI"has_header?:ETI"$Rack::Response::Raw#has_header?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ FI"Raw;TcRDoc::NormalClass00PK% ]*u6doc/rack-3.0.8/ri/Rack/Response/Raw/delete_header-i.rinu[U:RDoc::AnyMethod[iI"delete_header:ETI"&Rack::Response::Raw#delete_header;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ FI"Raw;TcRDoc::NormalClass00PK% ]z? ,doc/rack-3.0.8/ri/Rack/Response/Raw/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Response::Raw::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"(status, headers);T@ FI"Raw;TcRDoc::NormalClass00PK% ]}/doc/rack-3.0.8/ri/Rack/Response/Raw/status-i.rinu[U:RDoc::Attr[iI" status:ETI"Rack::Response::Raw#status;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Response::Raw;TcRDoc::NormalClass0PK% ]ձ=ii0doc/rack-3.0.8/ri/Rack/Response/Raw/cdesc-Raw.rinu[U:RDoc::NormalClass[iI"Raw:ETI"Rack::Response::Raw;TI" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I" headers;TI"R;T: publicFI"lib/rack/response.rb;T[ I" status;TI"RW;T; F@[[[I" Helpers;To;;[; @; 0@[[I" class;T[[; [[I"new;T@[:protected[[: private[[I" instance;T[[; [ [I"delete_header;T@[I"get_header;T@[I"has_header?;T@[I"set_header;T@[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Response;TcRDoc::NormalClassPK% ]pT3doc/rack-3.0.8/ri/Rack/Response/Raw/set_header-i.rinu[U:RDoc::AnyMethod[iI"set_header:ETI"#Rack::Response::Raw#set_header;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"(key, value);T@ FI"Raw;TcRDoc::NormalClass00PK% ]0doc/rack-3.0.8/ri/Rack/Response/Raw/headers-i.rinu[U:RDoc::Attr[iI" headers:ETI" Rack::Response::Raw#headers;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Response::Raw;TcRDoc::NormalClass0PK% ]*3doc/rack-3.0.8/ri/Rack/Response/Raw/get_header-i.rinu[U:RDoc::AnyMethod[iI"get_header:ETI"#Rack::Response::Raw#get_header;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ FI"Raw;TcRDoc::NormalClass00PK% ]g99+doc/rack-3.0.8/ri/Rack/Response/header-i.rinu[U:RDoc::AnyMethod[iI" header:ETI"Rack::Response#header;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"%Deprecated, use headers instead.;T: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Response;TcRDoc::NormalClass00PK% ]c6doc/rack-3.0.8/ri/Rack/Response/no_entity_body%3f-i.rinu[U:RDoc::AnyMethod[iI"no_entity_body?:ETI"#Rack::Response#no_entity_body?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Response;TcRDoc::NormalClass00PK% ][/doc/rack-3.0.8/ri/Rack/Response/get_header-i.rinu[U:RDoc::AnyMethod[iI"get_header:ETI"Rack::Response#get_header;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/response.rb;T:0@omit_headings_from_table_of_contents_below000[[I"[];To;; [; @ ; 0I" (key);T@ FI" Response;TcRDoc::NormalClass00PK% ]KK*doc/rack-3.0.8/ri/Rack/Mime/mime_type-c.rinu[U:RDoc::AnyMethod[iI"mime_type:ETI"Rack::Mime::mime_type;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"GReturns String with mime type if found, otherwise use +fallback+. ;TI"A+ext+ should be filename extension in the '.ext' format that;To:RDoc::Markup::Verbatim; [I"!File.extname(file) returns. ;T: @format0o; ; [I"!+fallback+ may be any object;To:RDoc::Markup::BlankLineo; ; [I".Also see the documentation for MIME_TYPES;T@o; ; [I" Usage:;To; ; [I""Rack::Mime.mime_type('.foo') ;T; 0o; ; [I"This is a shortcut for:;To; ; [I"ERack::Mime::MIME_TYPES.fetch('.foo', 'application/octet-stream');T; 0: @fileI"lib/rack/mime.rb;T:0@omit_headings_from_table_of_contents_below000[I"1(ext, fallback = 'application/octet-stream');T@%FI" Mime;TcRDoc::NormalModule00PK% ]/}})doc/rack-3.0.8/ri/Rack/Mime/match%3f-c.rinu[U:RDoc::AnyMethod[iI" match?:ETI"Rack::Mime::match?;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"NReturns true if the given value is a mime match for the given mime match ;TI"$specification, false otherwise.;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim; [I"6Rack::Mime.match?('text/html', 'text/*') => true ;TI"2Rack::Mime.match?('text/plain', '*') => true ;TI"@Rack::Mime.match?('text/html', 'application/json') => false;T: @format0: @fileI"lib/rack/mime.rb;T:0@omit_headings_from_table_of_contents_below000[I"(value, matcher);T@FI" Mime;TcRDoc::NormalModule00PK% ]HKK*doc/rack-3.0.8/ri/Rack/Mime/mime_type-i.rinu[U:RDoc::AnyMethod[iI"mime_type:ETI"Rack::Mime#mime_type;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"GReturns String with mime type if found, otherwise use +fallback+. ;TI"A+ext+ should be filename extension in the '.ext' format that;To:RDoc::Markup::Verbatim; [I"!File.extname(file) returns. ;T: @format0o; ; [I"!+fallback+ may be any object;To:RDoc::Markup::BlankLineo; ; [I".Also see the documentation for MIME_TYPES;T@o; ; [I" Usage:;To; ; [I""Rack::Mime.mime_type('.foo') ;T; 0o; ; [I"This is a shortcut for:;To; ; [I"ERack::Mime::MIME_TYPES.fetch('.foo', 'application/octet-stream');T; 0: @fileI"lib/rack/mime.rb;T:0@omit_headings_from_table_of_contents_below000[I"1(ext, fallback = 'application/octet-stream');T@%FI" Mime;TcRDoc::NormalModule00PK% ]5 }})doc/rack-3.0.8/ri/Rack/Mime/match%3f-i.rinu[U:RDoc::AnyMethod[iI" match?:ETI"Rack::Mime#match?;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"NReturns true if the given value is a mime match for the given mime match ;TI"$specification, false otherwise.;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim; [I"6Rack::Mime.match?('text/html', 'text/*') => true ;TI"2Rack::Mime.match?('text/plain', '*') => true ;TI"@Rack::Mime.match?('text/html', 'application/json') => false;T: @format0: @fileI"lib/rack/mime.rb;T:0@omit_headings_from_table_of_contents_below000[I"(value, matcher);T@FI" Mime;TcRDoc::NormalModule00PK% ])doc/rack-3.0.8/ri/Rack/Mime/cdesc-Mime.rinu[U:RDoc::NormalModule[iI" Mime:ETI"Rack::Mime;T0o:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/mime.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[U:RDoc::Constant[iI"MIME_TYPES;TI"Rack::Mime::MIME_TYPES;T: public0o;;[ o:RDoc::Markup::Paragraph;[I">List of most common mime-types, selected various sources ;TI"Baccording to their usefulness in a webserving scope for Ruby ;TI" users.;To:RDoc::Markup::BlankLineo; ;[I"DTo amend this list with your local mime.types list you can use:;T@o:RDoc::Markup::Verbatim;[I"!require 'webrick/httputils' ;TI"Blist = WEBrick::HTTPUtils.load_mime_types('/etc/mime.types') ;TI")Rack::Mime::MIME_TYPES.merge!(list) ;T: @format0o; ;[I"PN.B. On Ubuntu the mime.types file does not include the leading period, so ;TI"Dusers may need to modify the data before merging into the hash.;T; @ ; 0@ @cRDoc::NormalModule0[[[I" class;T[[; [[I" match?;TI"lib/rack/mime.rb;T[I"mime_type;T@2[:protected[[: private[[I" instance;T[[; [[;[[;[[@1@2[@4@2[[U:RDoc::Context::Section[i0o;;[; 0; 0[@ I" Rack;T@(PK% ]C/7doc/rack-3.0.8/ri/Rack/Auth/Basic/Request/username-i.rinu[U:RDoc::AnyMethod[iI" username:ETI"(Rack::Auth::Basic::Request#username;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/basic.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Request;TcRDoc::NormalClass00PK% ]C7doc/rack-3.0.8/ri/Rack/Auth/Basic/Request/basic%3f-i.rinu[U:RDoc::AnyMethod[iI" basic?:ETI"&Rack::Auth::Basic::Request#basic?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/basic.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Request;TcRDoc::NormalClass00PK% ])*K  :doc/rack-3.0.8/ri/Rack/Auth/Basic/Request/credentials-i.rinu[U:RDoc::AnyMethod[iI"credentials:ETI"+Rack::Auth::Basic::Request#credentials;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/basic.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Request;TcRDoc::NormalClass00PK% ]\I  :doc/rack-3.0.8/ri/Rack/Auth/Basic/Request/cdesc-Request.rinu[U:RDoc::NormalClass[iI" Request:ETI"Rack::Auth::Basic::Request;TI" Rack::Auth::AbstractRequest;To:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/auth/basic.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[I" basic?;TI"lib/rack/auth/basic.rb;T[I"credentials;T@#[I" username;T@#[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Auth::Basic;TcRDoc::NormalClassPK% ]-X+doc/rack-3.0.8/ri/Rack/Auth/Basic/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Auth::Basic#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/basic.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Basic;TcRDoc::NormalClass00PK% ]5R]0doc/rack-3.0.8/ri/Rack/Auth/Basic/challenge-i.rinu[U:RDoc::AnyMethod[iI"challenge:ETI" Rack::Auth::Basic#challenge;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/basic.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Basic;TcRDoc::NormalClass00PK% ]s0doc/rack-3.0.8/ri/Rack/Auth/Basic/cdesc-Basic.rinu[U:RDoc::NormalClass[iI" Basic:ETI"Rack::Auth::Basic;TI" Rack::Auth::AbstractHandler;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"MRack::Auth::Basic implements HTTP Basic Authentication, as per RFC 2617.;To:RDoc::Markup::BlankLineo; ;[I"DInitialize with the Rack application that you want protecting, ;TI"Gand a block that checks if a username and password pair are valid.;T: @fileI"lib/rack/auth/basic.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[I" call;TI"lib/rack/auth/basic.rb;T[;[[;[[I"challenge;T@+[I" valid?;T@+[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Auth;TcRDoc::NormalModulePK% ]S>j/doc/rack-3.0.8/ri/Rack/Auth/Basic/valid%3f-i.rinu[U:RDoc::AnyMethod[iI" valid?:ETI"Rack::Auth::Basic#valid?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/basic.rb;T:0@omit_headings_from_table_of_contents_below000[I" (auth);T@ FI" Basic;TcRDoc::NormalClass00PK% ]Q=doc/rack-3.0.8/ri/Rack/Auth/Digest/Request/respond_to%3f-i.rinu[U:RDoc::AnyMethod[iI"respond_to?:ETI",Rack::Auth::Digest::Request#respond_to?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (sym, *);T@ TI" Request;TcRDoc::NormalClass00PK% ]q5doc/rack-3.0.8/ri/Rack/Auth/Digest/Request/nonce-i.rinu[U:RDoc::AnyMethod[iI" nonce:ETI"&Rack::Auth::Digest::Request#nonce;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Request;TcRDoc::NormalClass00PK% ]W6doc/rack-3.0.8/ri/Rack/Auth/Digest/Request/params-i.rinu[U:RDoc::AnyMethod[iI" params:ETI"'Rack::Auth::Digest::Request#params;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Request;TcRDoc::NormalClass00PK% ].6doc/rack-3.0.8/ri/Rack/Auth/Digest/Request/method-i.rinu[U:RDoc::AnyMethod[iI" method:ETI"'Rack::Auth::Digest::Request#method;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Request;TcRDoc::NormalClass00PK% ]&t]9doc/rack-3.0.8/ri/Rack/Auth/Digest/Request/digest%3f-i.rinu[U:RDoc::AnyMethod[iI" digest?:ETI"(Rack::Auth::Digest::Request#digest?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Request;TcRDoc::NormalClass00PK% ]♏4^^;doc/rack-3.0.8/ri/Rack/Auth/Digest/Request/cdesc-Request.rinu[U:RDoc::NormalClass[iI" Request:ETI" Rack::Auth::Digest::Request;TI" Rack::Auth::AbstractRequest;To:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [ [I"correct_uri?;TI"lib/rack/auth/digest.rb;T[I" digest?;T@#[I" method;T@#[I"method_missing;T@#[I" nonce;T@#[I" params;T@#[I"respond_to?;T@#[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Auth::Digest;TcRDoc::NormalModulePK% ].?>doc/rack-3.0.8/ri/Rack/Auth/Digest/Request/correct_uri%3f-i.rinu[U:RDoc::AnyMethod[iI"correct_uri?:ETI"-Rack::Auth::Digest::Request#correct_uri?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Request;TcRDoc::NormalClass00PK% ]H(>doc/rack-3.0.8/ri/Rack/Auth/Digest/Request/method_missing-i.rinu[U:RDoc::AnyMethod[iI"method_missing:ETI"/Rack::Auth::Digest::Request#method_missing;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"(sym, *args);T@ TI" Request;TcRDoc::NormalClass00PK% ]Wa6doc/rack-3.0.8/ri/Rack/Auth/Digest/Params/dequote-c.rinu[U:RDoc::AnyMethod[iI" dequote:ETI"(Rack::Auth::Digest::Params::dequote;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (str);T@ FI" Params;TcRDoc::NormalClass00PK% ]7=x2doc/rack-3.0.8/ri/Rack/Auth/Digest/Params/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"$Rack::Auth::Digest::Params::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below00I" self;T[I"();T@ TI" Params;TcRDoc::NormalClass00PK% ]C~4doc/rack-3.0.8/ri/Rack/Auth/Digest/Params/parse-c.rinu[U:RDoc::AnyMethod[iI" parse:ETI"&Rack::Auth::Digest::Params::parse;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (str);T@ FI" Params;TcRDoc::NormalClass00PK% ]X\9doc/rack-3.0.8/ri/Rack/Auth/Digest/Params/cdesc-Params.rinu[U:RDoc::NormalClass[iI" Params:ETI"Rack::Auth::Digest::Params;TI" Hash;To:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[U:RDoc::Constant[iI" UNQUOTED;TI")Rack::Auth::Digest::Params::UNQUOTED;T: public0o;;[; @; 0@@cRDoc::NormalClass0[[[I" class;T[[; [ [I" dequote;TI"lib/rack/auth/digest.rb;T[I"new;T@![I" parse;T@![I"split_header_value;T@![:protected[[: private[[I" instance;T[[; [ [I"[];T@![I"[]=;T@![I" quote;T@![I" to_s;T@![; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Auth::Digest;TcRDoc::NormalModulePK% ]DAdoc/rack-3.0.8/ri/Rack/Auth/Digest/Params/split_header_value-c.rinu[U:RDoc::AnyMethod[iI"split_header_value:ETI"3Rack::Auth::Digest::Params::split_header_value;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (str);T@ FI" Params;TcRDoc::NormalClass00PK% ]/7:5doc/rack-3.0.8/ri/Rack/Auth/Digest/Params/%5b%5d-i.rinu[U:RDoc::AnyMethod[iI"[]:ETI""Rack::Auth::Digest::Params#[];TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"(k);T@ TI" Params;TcRDoc::NormalClass00PK% ]Rj3doc/rack-3.0.8/ri/Rack/Auth/Digest/Params/to_s-i.rinu[U:RDoc::AnyMethod[iI" to_s:ETI"$Rack::Auth::Digest::Params#to_s;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Params;TcRDoc::NormalClass00PK% ]8doc/rack-3.0.8/ri/Rack/Auth/Digest/Params/%5b%5d%3d-i.rinu[U:RDoc::AnyMethod[iI"[]=:ETI"#Rack::Auth::Digest::Params#[]=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (k, v);T@ TI" Params;TcRDoc::NormalClass00PK% ]kC4doc/rack-3.0.8/ri/Rack/Auth/Digest/Params/quote-i.rinu[U:RDoc::AnyMethod[iI" quote:ETI"%Rack::Auth::Digest::Params#quote;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (str);T@ FI" Params;TcRDoc::NormalClass00PK% ]A8doc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/time_limit-c.rinu[U:RDoc::Attr[iI"time_limit:ETI"*Rack::Auth::Digest::Nonce::time_limit;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below0T@ I"Rack::Auth::Digest::Nonce;TcRDoc::NormalClass0PK% ]_Q?!!1doc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"#Rack::Auth::Digest::Nonce::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"/(timestamp = Time.now, given_digest = nil);T@ FI" Nonce;TcRDoc::NormalClass00PK% ]4T3doc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/parse-c.rinu[U:RDoc::AnyMethod[iI" parse:ETI"%Rack::Auth::Digest::Nonce::parse;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (string);T@ FI" Nonce;TcRDoc::NormalClass00PK% ]'2doc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/to_s-i.rinu[U:RDoc::AnyMethod[iI" to_s:ETI"#Rack::Auth::Digest::Nonce#to_s;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Nonce;TcRDoc::NormalClass00PK% ]#$v6doc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/stale%3f-i.rinu[U:RDoc::AnyMethod[iI" stale?:ETI"%Rack::Auth::Digest::Nonce#stale?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Nonce;TcRDoc::NormalClass00PK% ]4doc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/digest-i.rinu[U:RDoc::AnyMethod[iI" digest:ETI"%Rack::Auth::Digest::Nonce#digest;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Nonce;TcRDoc::NormalClass00PK% ]iPt7doc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/cdesc-Nonce.rinu[U:RDoc::NormalClass[iI" Nonce:ETI"Rack::Auth::Digest::Nonce;TI" Object;To:RDoc::Markup::Document: @parts[o;;[ o:RDoc::Markup::Paragraph;[I"FRack::Auth::Digest::Nonce is the default nonce generator for the ;TI"4Rack::Auth::Digest::MD5 authentication handler.;To:RDoc::Markup::BlankLineo; ;[I"5+private_key+ needs to set to a constant string.;T@o; ;[I"K+time_limit+ can be optionally set to an integer (number of seconds), ;TI"3to limit the validity of the generated nonces.;T: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I"private_key;TI"RW;T: publicTI"lib/rack/auth/digest.rb;T[ I"time_limit;T@; T@[[[[I" class;T[[; [[I"new;T@[I" parse;T@[:protected[[: private[[I" instance;T[[; [ [I" digest;T@[I" fresh?;T@[I" stale?;T@[I" to_s;T@[I" valid?;T@[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Auth::Digest;TcRDoc::NormalModulePK% ],6doc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/fresh%3f-i.rinu[U:RDoc::AnyMethod[iI" fresh?:ETI"%Rack::Auth::Digest::Nonce#fresh?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Nonce;TcRDoc::NormalClass00PK% ]N80:9doc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/private_key-c.rinu[U:RDoc::Attr[iI"private_key:ETI"+Rack::Auth::Digest::Nonce::private_key;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below0T@ I"Rack::Auth::Digest::Nonce;TcRDoc::NormalClass0PK% ],}L6doc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/valid%3f-i.rinu[U:RDoc::AnyMethod[iI" valid?:ETI"%Rack::Auth::Digest::Nonce#valid?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Nonce;TcRDoc::NormalClass00PK% ]K2doc/rack-3.0.8/ri/Rack/Auth/Digest/cdesc-Digest.rinu[U:RDoc::NormalModule[iI" Digest:ETI"Rack::Auth::Digest;T0o:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@ I"Rack::Auth;TcRDoc::NormalModulePK% ]As<doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/passwords_hashed-i.rinu[U:RDoc::Attr[iI"passwords_hashed:ETI"-Rack::Auth::Digest::MD5#passwords_hashed;TI"W;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Auth::Digest::MD5;TcRDoc::NormalClass0PK% ]-doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/H-i.rinu[U:RDoc::AnyMethod[iI"H:ETI"Rack::Auth::Digest::MD5#H;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (data);T@ FI"MD5;TcRDoc::NormalClass0[I"Rack::Auth::Digest::MD5;TFI"md5;TPK% ]C  :doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/valid_nonce%3f-i.rinu[U:RDoc::AnyMethod[iI"valid_nonce?:ETI")Rack::Auth::Digest::MD5#valid_nonce?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (auth);T@ FI"MD5;TcRDoc::NormalClass00PK% ]M i.doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/A1-i.rinu[U:RDoc::AnyMethod[iI"A1:ETI"Rack::Auth::Digest::MD5#A1;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"(auth, password);T@ FI"MD5;TcRDoc::NormalClass00PK% ]{0.doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/KD-i.rinu[U:RDoc::AnyMethod[iI"KD:ETI"Rack::Auth::Digest::MD5#KD;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"(secret, data);T@ FI"MD5;TcRDoc::NormalClass00PK% ]Zu##/doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"!Rack::Auth::Digest::MD5::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"5(app, realm = nil, opaque = nil, &authenticator);T@ TI"MD5;TcRDoc::NormalClass00PK% ]RL?doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/passwords_hashed%3f-i.rinu[U:RDoc::AnyMethod[iI"passwords_hashed?:ETI".Rack::Auth::Digest::MD5#passwords_hashed?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"MD5;TcRDoc::NormalClass00PK% ]R60doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"!Rack::Auth::Digest::MD5#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI"MD5;TcRDoc::NormalClass00PK% ]BNGT2doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/params-i.rinu[U:RDoc::AnyMethod[iI" params:ETI"#Rack::Auth::Digest::MD5#params;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"(hash = {});T@ FI"MD5;TcRDoc::NormalClass00PK% ]nH  5doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/challenge-i.rinu[U:RDoc::AnyMethod[iI"challenge:ETI"&Rack::Auth::Digest::MD5#challenge;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"(hash = {});T@ FI"MD5;TcRDoc::NormalClass00PK% ]/  ;doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/valid_digest%3f-i.rinu[U:RDoc::AnyMethod[iI"valid_digest?:ETI"*Rack::Auth::Digest::MD5#valid_digest?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (auth);T@ FI"MD5;TcRDoc::NormalClass00PK% ]  2doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/digest-i.rinu[U:RDoc::AnyMethod[iI" digest:ETI"#Rack::Auth::Digest::MD5#digest;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I"(auth, password);T@ FI"MD5;TcRDoc::NormalClass00PK% ]׏02doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/opaque-i.rinu[U:RDoc::Attr[iI" opaque:ETI"#Rack::Auth::Digest::MD5#opaque;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Auth::Digest::MD5;TcRDoc::NormalClass0PK% ]{993doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/cdesc-MD5.rinu[U:RDoc::NormalClass[iI"MD5:ETI"Rack::Auth::Digest::MD5;TI" Rack::Auth::AbstractHandler;To:RDoc::Markup::Document: @parts[o;;[ o:RDoc::Markup::Paragraph;[I"ERack::Auth::Digest::MD5 implements the MD5 algorithm version of ;TI"1HTTP Digest Authentication, as per RFC 2617.;To:RDoc::Markup::BlankLineo; ;[I"FInitialize with the [Rack] application that you want protecting, ;TI"Iand a block that looks up a plaintext password for a given username.;T@o; ;[I"F+opaque+ needs to be set to a constant base64/hexadecimal string.;T: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I" opaque;TI"RW;T: publicFI"lib/rack/auth/digest.rb;T[ I"passwords_hashed;TI"W;T; F@[U:RDoc::Constant[iI"QOP;TI"!Rack::Auth::Digest::MD5::QOP;T; 0o;;[; @; 0@@cRDoc::NormalClass0[[[I" class;T[[; [[I"new;T@[:protected[[: private[[I" instance;T[[; [[I" call;T@[I"passwords_hashed?;T@[;[[;[[I"A1;T@[I"A2;T@[I"H;T@[I"KD;T@[I"challenge;T@[I" digest;T@[I"md5;T@[I" params;T@[I" valid?;T@[I"valid_digest?;T@[I"valid_nonce?;T@[I"valid_opaque?;T@[I"valid_qop?;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Auth::Digest;TcRDoc::NormalModulePK% ]8u.doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/A2-i.rinu[U:RDoc::AnyMethod[iI"A2:ETI"Rack::Auth::Digest::MD5#A2;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (auth);T@ FI"MD5;TcRDoc::NormalClass00PK% ]/doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/md5-i.rinu[U:RDoc::AnyMethod[iI"md5:ETI" Rack::Auth::Digest::MD5#md5;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[[I"H;To;; [; @ ; 0I" (data);T@ FI"MD5;TcRDoc::NormalClass00PK% ]wZ8doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/valid_qop%3f-i.rinu[U:RDoc::AnyMethod[iI"valid_qop?:ETI"'Rack::Auth::Digest::MD5#valid_qop?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (auth);T@ FI"MD5;TcRDoc::NormalClass00PK% ]ns4doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/valid%3f-i.rinu[U:RDoc::AnyMethod[iI" valid?:ETI"#Rack::Auth::Digest::MD5#valid?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (auth);T@ FI"MD5;TcRDoc::NormalClass00PK% ]sr  ;doc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/valid_opaque%3f-i.rinu[U:RDoc::AnyMethod[iI"valid_opaque?:ETI"*Rack::Auth::Digest::MD5#valid_opaque?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/auth/digest.rb;T:0@omit_headings_from_table_of_contents_below000[I" (auth);T@ FI"MD5;TcRDoc::NormalClass00PK% ]3//4doc/rack-3.0.8/ri/Rack/Auth/AbstractHandler/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"%Rack::Auth::AbstractHandler::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"&lib/rack/auth/abstract/handler.rb;T:0@omit_headings_from_table_of_contents_below000[I"'(app, realm = nil, &authenticator);T@ FI"AbstractHandler;TcRDoc::NormalClass00PK% ]Rk6doc/rack-3.0.8/ri/Rack/Auth/AbstractHandler/realm-i.rinu[U:RDoc::Attr[iI" realm:ETI"&Rack::Auth::AbstractHandler#realm;TI"RW;T: publico:RDoc::Markup::Document: @parts[: @fileI"&lib/rack/auth/abstract/handler.rb;T:0@omit_headings_from_table_of_contents_below0F@ I" Rack::Auth::AbstractHandler;TcRDoc::NormalClass0PK% ])aP<doc/rack-3.0.8/ri/Rack/Auth/AbstractHandler/bad_request-i.rinu[U:RDoc::AnyMethod[iI"bad_request:ETI",Rack::Auth::AbstractHandler#bad_request;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"&lib/rack/auth/abstract/handler.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"AbstractHandler;TcRDoc::NormalClass00PK% ] ===doc/rack-3.0.8/ri/Rack/Auth/AbstractHandler/unauthorized-i.rinu[U:RDoc::AnyMethod[iI"unauthorized:ETI"-Rack::Auth::AbstractHandler#unauthorized;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"&lib/rack/auth/abstract/handler.rb;T:0@omit_headings_from_table_of_contents_below000[I"#(www_authenticate = challenge);T@ FI"AbstractHandler;TcRDoc::NormalClass00PK% ]wuDdoc/rack-3.0.8/ri/Rack/Auth/AbstractHandler/cdesc-AbstractHandler.rinu[U:RDoc::NormalClass[iI"AbstractHandler:ETI" Rack::Auth::AbstractHandler;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"PRack::Auth::AbstractHandler implements common authentication functionality.;To:RDoc::Markup::BlankLineo; ;[I",+realm+ should be set for all handlers.;T: @fileI"&lib/rack/auth/abstract/handler.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I" realm;TI"RW;T: publicFI"&lib/rack/auth/abstract/handler.rb;T[[[[I" class;T[[; [[I"new;T@[:protected[[: private[[I" instance;T[[; [[;[[;[[I"bad_request;T@[I"unauthorized;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Auth;TcRDoc::NormalModulePK% ],6doc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/parts-i.rinu[U:RDoc::AnyMethod[iI" parts:ETI"&Rack::Auth::AbstractRequest#parts;TF: publico:RDoc::Markup::Document: @parts[: @fileI"&lib/rack/auth/abstract/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"AbstractRequest;TcRDoc::NormalClass00PK% ]=7doc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/scheme-i.rinu[U:RDoc::AnyMethod[iI" scheme:ETI"'Rack::Auth::AbstractRequest#scheme;TF: publico:RDoc::Markup::Document: @parts[: @fileI"&lib/rack/auth/abstract/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"AbstractRequest;TcRDoc::NormalClass00PK% ]|L++Bdoc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/authorization_key-i.rinu[U:RDoc::AnyMethod[iI"authorization_key:ETI"2Rack::Auth::AbstractRequest#authorization_key;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"&lib/rack/auth/abstract/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"AbstractRequest;TcRDoc::NormalClass00PK% ]u14doc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"%Rack::Auth::AbstractRequest::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"&lib/rack/auth/abstract/request.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI"AbstractRequest;TcRDoc::NormalClass00PK% ]7doc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/params-i.rinu[U:RDoc::AnyMethod[iI" params:ETI"'Rack::Auth::AbstractRequest#params;TF: publico:RDoc::Markup::Document: @parts[: @fileI"&lib/rack/auth/abstract/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"AbstractRequest;TcRDoc::NormalClass00PK% ]jDdoc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/cdesc-AbstractRequest.rinu[U:RDoc::NormalClass[iI"AbstractRequest:ETI" Rack::Auth::AbstractRequest;TI" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"&lib/rack/auth/abstract/request.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[U:RDoc::Constant[iI"AUTHORIZATION_KEYS;TI"4Rack::Auth::AbstractRequest::AUTHORIZATION_KEYS;T: public0o;;[; @; 0@@cRDoc::NormalClass0[[[I" class;T[[; [[I"new;TI"&lib/rack/auth/abstract/request.rb;T[:protected[[: private[[I" instance;T[[; [ [I" params;T@![I" parts;T@![I"provided?;T@![I" request;T@![I" scheme;T@![I" valid?;T@![; [[;[[I"authorization_key;T@![[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Auth;TcRDoc::NormalModulePK% ]X8doc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/request-i.rinu[U:RDoc::AnyMethod[iI" request:ETI"(Rack::Auth::AbstractRequest#request;TF: publico:RDoc::Markup::Document: @parts[: @fileI"&lib/rack/auth/abstract/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"AbstractRequest;TcRDoc::NormalClass00PK% ]d_<doc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/provided%3f-i.rinu[U:RDoc::AnyMethod[iI"provided?:ETI"*Rack::Auth::AbstractRequest#provided?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"&lib/rack/auth/abstract/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"AbstractRequest;TcRDoc::NormalClass00PK% ]0/9doc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/valid%3f-i.rinu[U:RDoc::AnyMethod[iI" valid?:ETI"'Rack::Auth::AbstractRequest#valid?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"&lib/rack/auth/abstract/request.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"AbstractRequest;TcRDoc::NormalClass00PK% ]cH311)doc/rack-3.0.8/ri/Rack/Auth/cdesc-Auth.rinu[U:RDoc::NormalModule[iI" Auth:ETI"Rack::Auth;T0o:RDoc::Markup::Document: @parts[ o;;[: @fileI"lib/rack.rb;T:0@omit_headings_from_table_of_contents_below0o;;[; I"&lib/rack/auth/abstract/handler.rb;T; 0o;;[; I"&lib/rack/auth/abstract/request.rb;T; 0o;;[; I"lib/rack/auth/basic.rb;T; 0o;;[; I"lib/rack/auth/digest.rb;T; 0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[ @ @@@@I" Rack;TcRDoc::NormalModulePK% ]_ ph$doc/rack-3.0.8/ri/Rack/Lock/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Lock::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/lock.rb;T:0@omit_headings_from_table_of_contents_below000[I"(app, mutex = Mutex.new);T@ FI" Lock;TcRDoc::NormalClass00PK% ]HU%doc/rack-3.0.8/ri/Rack/Lock/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Lock#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/lock.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Lock;TcRDoc::NormalClass00PK% ]DE'doc/rack-3.0.8/ri/Rack/Lock/unlock-i.rinu[U:RDoc::AnyMethod[iI" unlock:ETI"Rack::Lock#unlock;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/lock.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Lock;TcRDoc::NormalClass00PK% ].v:ZZ)doc/rack-3.0.8/ri/Rack/Lock/cdesc-Lock.rinu[U:RDoc::NormalClass[iI" Lock:ETI"Rack::Lock;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"JRack::Lock locks every request inside a mutex, so that every request ;TI"0will effectively be executed synchronously.;T: @fileI"lib/rack/lock.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/lock.rb;T[:protected[[: private[[I" instance;T[[; [[I" call;T@[; [[;[[I" unlock;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]f88)doc/rack-3.0.8/ri/Rack/Head/cdesc-Head.rinu[U:RDoc::NormalClass[iI" Head:ETI"Rack::Head;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"GRack::Head returns an empty body for all HEAD requests. It leaves ;TI""all other requests unchanged.;T: @fileI"lib/rack/head.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/head.rb;T[:protected[[: private[[I" instance;T[[; [[I" call;T@[; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]wt$doc/rack-3.0.8/ri/Rack/Head/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Head::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/head.rb;T:0@omit_headings_from_table_of_contents_below000[I" (app);T@ FI" Head;TcRDoc::NormalClass00PK% ]%doc/rack-3.0.8/ri/Rack/Head/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Head#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/head.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Head;TcRDoc::NormalClass00PK% ]^,-doc/rack-3.0.8/ri/Rack/Static/route_file-i.rinu[U:RDoc::AnyMethod[iI"route_file:ETI"Rack::Static#route_file;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/static.rb;T:0@omit_headings_from_table_of_contents_below000[I" (path);T@ FI" Static;TcRDoc::NormalClass00PK% ]f4doc/rack-3.0.8/ri/Rack/Static/add_index_root%3f-i.rinu[U:RDoc::AnyMethod[iI"add_index_root?:ETI"!Rack::Static#add_index_root?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/static.rb;T:0@omit_headings_from_table_of_contents_below000[I" (path);T@ FI" Static;TcRDoc::NormalClass00PK% ]m $&doc/rack-3.0.8/ri/Rack/Static/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Static::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/static.rb;T:0@omit_headings_from_table_of_contents_below000[I"(app, options = {});T@ FI" Static;TcRDoc::NormalClass00PK% ]U,doc/rack-3.0.8/ri/Rack/Static/can_serve-i.rinu[U:RDoc::AnyMethod[iI"can_serve:ETI"Rack::Static#can_serve;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/static.rb;T:0@omit_headings_from_table_of_contents_below000[I" (path);T@ FI" Static;TcRDoc::NormalClass00PK% ];'doc/rack-3.0.8/ri/Rack/Static/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Static#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/static.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Static;TcRDoc::NormalClass00PK% ]CDD-doc/rack-3.0.8/ri/Rack/Static/cdesc-Static.rinu[U:RDoc::NormalClass[iI" Static:ETI"Rack::Static;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[ I"FThe Rack::Static middleware intercepts requests for static files ;TI"O(javascript files, images, stylesheets, etc) based on the url prefixes or ;TI"Oroute mappings passed in the options, and serves them using a Rack::Files ;TI"Oobject. This allows a Rack stack to serve both static and dynamic content.;To:RDoc::Markup::BlankLineo; ;[I"Examples:;T@o; ;[I"NServe all requests beginning with /media from the "media" folder located ;TI"+in the current directory (ie media/*):;T@o:RDoc::Markup::Verbatim;[I"+use Rack::Static, :urls => ["/media"] ;T: @format0o; ;[I"LSame as previous, but instead of returning 404 for missing files under ;TI"&/media, call the next middleware:;T@o; ;[I"=use Rack::Static, :urls => ["/media"], :cascade => true ;T; 0o; ;[I"PServe all requests beginning with /css or /images from the folder "public" ;TI"Din the current directory (ie public/css/* and public/images/*):;T@o; ;[I"Guse Rack::Static, :urls => ["/css", "/images"], :root => "public" ;T; 0o; ;[I"OServe all requests to / with "index.html" from the folder "public" in the ;TI".current directory (ie public/index.html):;T@o; ;[I"Iuse Rack::Static, :urls => {"/" => 'index.html'}, :root => 'public' ;T; 0o; ;[I"IServe all requests normally from the folder "public" in the current ;TI";directory but uses index.html as default route for "/";T@o; ;[I"Cuse Rack::Static, :urls => [""], :root => 'public', :index => ;TI"'index.html' ;T; 0o; ;[I"0Set custom HTTP Headers for based on rules:;T@o; ;[4I"- use Rack::Static, :root => 'public', ;TI" :header_rules => [ ;TI"J [rule, {header_field => content, header_field => content}], ;TI"0 [rule, {header_field => content}] ;TI" ] ;TI" ;TI" Rules for selecting files: ;TI" ;TI"1) All files ;TI" Provide the :all symbol ;TI"# :all => Matches every file ;TI" ;TI"2) Folders ;TI", Provide the folder path as a string ;TI"N '/folder' or '/folder/subfolder' => Matches files in a certain folder ;TI" ;TI"3) File Extensions ;TI"0 Provide the file extensions as an array ;TI"K ['css', 'js'] or %w(css js) => Matches files ending in .css or .js ;TI" ;TI"%4) Regular Expressions / Regexp ;TI"% Provide a regular expression ;TI"B %r{\.(?:css|js)\z} => Matches files ending in .css or .js ;TI"H /\.(?:eot|ttf|otf|woff2|woff|svg)\z/ => Matches files ending in ;TI"S the most common web font formats (.eot, .ttf, .otf, .woff2, .woff, .svg) ;TI"N Note: This Regexp is available as a shortcut, using the :fonts rule ;TI" ;TI"5) Font Shortcut ;TI"" Provide the :fonts symbol ;TI"_ :fonts => Uses the Regexp rule stated right above to match all common web font endings ;TI" ;TI"Rule Ordering: ;TI"> Rules are applied in the order that they are provided. ;TI"5 List rather general rules above special ones. ;TI" ;TI" 'public', ;TI" :header_rules => [ ;TI"K # Cache all static files in public caches (e.g. Rack::Cache) ;TI"+ # as well as in the browser ;TI"G [:all, {'cache-control' => 'public, max-age=31536000'}], ;TI" ;TI"K # Provide web fonts with cross-origin access-control-headers ;TI"\ # Firefox requires this when serving assets using a Content Delivery Network ;TI"? [:fonts, {'access-control-allow-origin' => '*'}] ;TI" ];T; 0: @fileI"lib/rack/static.rb;T:0@omit_headings_from_table_of_contents_below0; 0;0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/static.rb;T[:protected[[: private[[I" instance;T[[;[ [I"add_index_root?;T@|[I"applicable_rules;T@|[I" call;T@|[I"can_serve;T@|[I"overwrite_file_path;T@|[I"route_file;T@|[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0;0[@pI" Rack;TcRDoc::NormalModulePK% ]rQ  6doc/rack-3.0.8/ri/Rack/Static/overwrite_file_path-i.rinu[U:RDoc::AnyMethod[iI"overwrite_file_path:ETI"%Rack::Static#overwrite_file_path;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/static.rb;T:0@omit_headings_from_table_of_contents_below000[I" (path);T@ FI" Static;TcRDoc::NormalClass00PK% ]+TT3doc/rack-3.0.8/ri/Rack/Static/applicable_rules-i.rinu[U:RDoc::AnyMethod[iI"applicable_rules:ETI""Rack::Static#applicable_rules;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I".Convert HTTP header rules to HTTP headers;T: @fileI"lib/rack/static.rb;T:0@omit_headings_from_table_of_contents_below000[I" (path);T@FI" Static;TcRDoc::NormalClass00PK% ] 4-doc/rack-3.0.8/ri/Rack/Config/cdesc-Config.rinu[U:RDoc::NormalClass[iI" Config:ETI"Rack::Config;TI" Object;To:RDoc::Markup::Document: @parts[o;;[ o:RDoc::Markup::Paragraph;[I"HRack::Config modifies the environment using the block given during ;TI"initialization.;To:RDoc::Markup::BlankLineo; ;[I" Example:;To:RDoc::Markup::Verbatim;[I"use Rack::Config do |env| ;TI"$ env['my-key'] = 'some-value' ;TI"end;T: @format0: @fileI"lib/rack/config.rb;T:0@omit_headings_from_table_of_contents_below0; 0;0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/config.rb;T[:protected[[: private[[I" instance;T[[;[[I" call;T@'[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0;0[@I" Rack;TcRDoc::NormalModulePK% ]^&doc/rack-3.0.8/ri/Rack/Config/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Config::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/config.rb;T:0@omit_headings_from_table_of_contents_below000[I"(app, &block);T@ FI" Config;TcRDoc::NormalClass00PK% ].'doc/rack-3.0.8/ri/Rack/Config/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Config#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/config.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Config;TcRDoc::NormalClass00PK% ]_UC%doc/rack-3.0.8/ri/Rack/File/fail-i.rinu[U:RDoc::AnyMethod[iI" fail:ETI"Rack::Files#fail;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I"!(status, body, headers = {});T@ FI" Files;TcRDoc::NormalClass00PK% ]_y$doc/rack-3.0.8/ri/Rack/File/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Files::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I"6(root, headers = {}, default_mime = 'text/plain');T@ FI" Files;TcRDoc::NormalClass00PK% ]Kcڄ)doc/rack-3.0.8/ri/Rack/File/filesize-i.rinu[U:RDoc::AnyMethod[iI" filesize:ETI"Rack::Files#filesize;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I" (path);T@ FI" Files;TcRDoc::NormalClass00PK% ]_)doc/rack-3.0.8/ri/Rack/File/cdesc-File.rinu[U:RDoc::NormalClass[iI" File:ETI"Rack::File;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[ I"QRack::Files serves files below the +root+ directory given, according to the ;TI"$path info of the Rack request. ;TI"Me.g. when Rack::Files.new("/etc") is used, you can access 'passwd' file ;TI"$as http://localhost:9292/passwd;To:RDoc::Markup::BlankLineo; ;[I"IHandlers can detect if bodies are a Rack::Files, and use mechanisms ;TI"!like sendfile on the +path+.;T: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I" root;TI"R;T: publicFI"lib/rack/files.rb;T[U:RDoc::Constant[iI"ALLOWED_VERBS;TI"Rack::Files::ALLOWED_VERBS;T; 0o;;[; @; 0@I" Files;TcRDoc::NormalClass0U;[iI"ALLOW_HEADER;TI"Rack::Files::ALLOW_HEADER;T; 0o;;[; @; 0@@&@'0U;[iI"MULTIPART_BOUNDARY;TI"$Rack::Files::MULTIPART_BOUNDARY;T; 0o;;[; @; 0@@&@'0[[[I" class;T[[; [[I"new;T@[:protected[[: private[[I" instance;T[[; [[I" call;T@[I"get;T@[I" serving;T@[;[[;[[I" fail;T@[I" filesize;T@[I"mime_type;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"lib/rack/utils.rb;TI" Rack;TcRDoc::NormalModulePK% ]t%doc/rack-3.0.8/ri/Rack/File/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Files#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Files;TcRDoc::NormalClass00PK% ]i$doc/rack-3.0.8/ri/Rack/File/get-i.rinu[U:RDoc::AnyMethod[iI"get:ETI"Rack::Files#get;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Files;TcRDoc::NormalClass00PK% ]+S(doc/rack-3.0.8/ri/Rack/File/serving-i.rinu[U:RDoc::AnyMethod[iI" serving:ETI"Rack::Files#serving;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I"(request, path);T@ FI" Files;TcRDoc::NormalClass00PK% ]ldd*doc/rack-3.0.8/ri/Rack/File/mime_type-i.rinu[U:RDoc::AnyMethod[iI"mime_type:ETI"Rack::Files#mime_type;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"@The MIME type for the contents of the file located at @path;T: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I"(path, default_mime);T@FI" Files;TcRDoc::NormalClass00PK% ]Ҿ%doc/rack-3.0.8/ri/Rack/File/root-i.rinu[U:RDoc::Attr[iI" root:ETI"Rack::Files#root;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Files;TcRDoc::NormalClass0PK% ]xҵ$doc/rack-3.0.8/ri/Rack/Lint/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Lint::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/lint.rb;T:0@omit_headings_from_table_of_contents_below000[I" (app);T@ FI" Lint;TcRDoc::NormalClass00PK% ]U**)doc/rack-3.0.8/ri/Rack/Lint/cdesc-Lint.rinu[U:RDoc::NormalClass[iI" Lint:ETI"Rack::Lint;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"@Rack::Lint validates your application and the requests and ;TI"*responses according to the Rack spec.;T: @fileI"lib/rack/lint.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/lint.rb;T[:protected[[: private[[I" instance;T[[; [[; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]OHdoc/rack-3.0.8/ri/Rack/Lint/Wrapper/StreamWrapper/cdesc-StreamWrapper.rinu[U:RDoc::NormalClass[iI"StreamWrapper:ETI"'Rack::Lint::Wrapper::StreamWrapper;TI" Object;To:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[I"lib/rack/lint.rb;TI"Rack::Lint::Wrapper;TcRDoc::NormalClassPK% ]PR$||4doc/rack-3.0.8/ri/Rack/Lint/Wrapper/cdesc-Wrapper.rinu[U:RDoc::NormalClass[iI" Wrapper:ETI"Rack::Lint::Wrapper;TI" Object;To:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[I"lib/rack/lint.rb;TI"Rack::Lint;TcRDoc::NormalClassPK% ]UۘFdoc/rack-3.0.8/ri/Rack/Lint/Wrapper/ErrorWrapper/cdesc-ErrorWrapper.rinu[U:RDoc::NormalClass[iI"ErrorWrapper:ETI"&Rack::Lint::Wrapper::ErrorWrapper;TI" Object;To:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[I"lib/rack/lint.rb;TI"Rack::Lint::Wrapper;TcRDoc::NormalClassPK% ] GFdoc/rack-3.0.8/ri/Rack/Lint/Wrapper/InputWrapper/cdesc-InputWrapper.rinu[U:RDoc::NormalClass[iI"InputWrapper:ETI"&Rack::Lint::Wrapper::InputWrapper;TI" Object;To:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[I"lib/rack/lint.rb;TI"Rack::Lint::Wrapper;TcRDoc::NormalClassPK% ]3/Y8doc/rack-3.0.8/ri/Rack/Lint/LintError/cdesc-LintError.rinu[U:RDoc::NormalClass[iI"LintError:ETI"Rack::Lint::LintError;TI"RuntimeError;To:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[I"lib/rack/lint.rb;TI"Rack::Lint;TcRDoc::NormalClassPK% ] 6,doc/rack-3.0.8/ri/Rack/ETag/digest_body-i.rinu[U:RDoc::AnyMethod[iI"digest_body:ETI"Rack::ETag#digest_body;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/etag.rb;T:0@omit_headings_from_table_of_contents_below000[I" (body);T@ FI" ETag;TcRDoc::NormalClass00PK% ]s$$$doc/rack-3.0.8/ri/Rack/ETag/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::ETag::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/etag.rb;T:0@omit_headings_from_table_of_contents_below000[I"I(app, no_cache_control = nil, cache_control = DEFAULT_CACHE_CONTROL);T@ FI" ETag;TcRDoc::NormalClass00PK% ]Ծ//doc/rack-3.0.8/ri/Rack/ETag/etag_status%3f-i.rinu[U:RDoc::AnyMethod[iI"etag_status?:ETI"Rack::ETag#etag_status?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/etag.rb;T:0@omit_headings_from_table_of_contents_below000[I" (status);T@ FI" ETag;TcRDoc::NormalClass00PK% ]lG%doc/rack-3.0.8/ri/Rack/ETag/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::ETag#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/etag.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" ETag;TcRDoc::NormalClass00PK% ]lH0doc/rack-3.0.8/ri/Rack/ETag/skip_caching%3f-i.rinu[U:RDoc::AnyMethod[iI"skip_caching?:ETI"Rack::ETag#skip_caching?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/etag.rb;T:0@omit_headings_from_table_of_contents_below000[I"(headers);T@ FI" ETag;TcRDoc::NormalClass00PK% ]02o)doc/rack-3.0.8/ri/Rack/ETag/cdesc-ETag.rinu[U:RDoc::NormalClass[iI" ETag:ETI"Rack::ETag;TI" Object;To:RDoc::Markup::Document: @parts[o;;[ o:RDoc::Markup::Paragraph;[I"=Automatically sets the etag header on all String bodies.;To:RDoc::Markup::BlankLineo; ;[I"PThe etag header is skipped if etag or last-modified headers are sent or if ;TI"La sendfile body (body.responds_to :to_path) is given (since such cases ;TI"(should be handled by apache/nginx).;T@o; ;[I"OOn initialization, you can pass two parameters: a cache-control directive ;TI"Lused when etag is absent and a directive when it is present. The first ;TI"Xdefaults to nil, while the second defaults to "max-age=0, private, must-revalidate";T: @fileI"lib/rack/etag.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[U:RDoc::Constant[iI"ETAG_STRING;TI"Rack::ETag::ETAG_STRING;T: public0o;;[; @; 0@@cRDoc::NormalClass0U; [iI"DEFAULT_CACHE_CONTROL;TI"&Rack::ETag::DEFAULT_CACHE_CONTROL;T;0o;;[; @; 0@@@%0[[[I" class;T[[;[[I"new;TI"lib/rack/etag.rb;T[:protected[[: private[[I" instance;T[[;[[I" call;T@5[;[[;[[I"digest_body;T@5[I"etag_status?;T@5[I"skip_caching?;T@5[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ] -doc/rack-3.0.8/ri/Rack/Events/cdesc-Events.rinu[U:RDoc::NormalClass[iI" Events:ETI"Rack::Events;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Verbatim;[I"GThis middleware provides hooks to certain places in the request / ;T: @format0o:RDoc::Markup::Paragraph;[I"Oresponse lifecycle. This is so that middleware that don't need to filter ;TI"Othe response data can safely leave it alone and not have to send messages ;TI"'down the traditional "rack stack".;To:RDoc::Markup::BlankLineo; ;[I"The events are:;T@o:RDoc::Markup::List: @type: BULLET: @items[ o:RDoc::Markup::ListItem: @label0;[ o; ;[I" on_start(request, response);T@o; ;[ I"EThis event is sent at the start of the request, before the next ;TI"Nmiddleware in the chain is called. This method is called with a request ;TI"Nobject, and a response object. Right now, the response object is always ;TI"Fnil, but in the future it may actually be a real response object.;T@o;;0;[ o; ;[I"!on_commit(request, response);T@o; ;[ I"MThe response has been committed. The application has returned, but the ;TI"Mresponse has not been sent to the webserver yet. This method is always ;TI"Icalled with a request object and the response object. The response ;TI"Oobject is constructed from the rack triple that the application returned. ;TI"DChanges may still be made to the response object at this point.;T@o;;0;[ o; ;[I"on_send(request, response);T@o; ;[ I"OThe webserver has started iterating over the response body and presumably ;TI"Ohas started sending data over the wire. This method is always called with ;TI"Ga request object and the response object. The response object is ;TI"Nconstructed from the rack triple that the application returned. Changes ;TI"LSHOULD NOT be made to the response object as the webserver has already ;TI"Mstarted sending data. Any mutations will likely result in an exception.;T@o;;0;[ o; ;[I"!on_finish(request, response);T@o; ;[ I"MThe webserver has closed the response, and all data has been written to ;TI"Jthe response socket. The request and response object should both be ;TI"Mread-only at this point. The body MAY NOT be available on the response ;TI"6object as it may have been flushed to the socket.;T@o;;0;[ o; ;[I"'on_error(request, response, error);T@o; ;[I"KAn exception has occurred in the application or an `on_commit` event. ;TI"KThis method will get the request, the response (if available) and the ;TI"exception that was raised.;T@o; ;[I" ## Order;T@o; ;[ I"P`on_start` is called on the handlers in the order that they were passed to ;TI"Nthe constructor. `on_commit`, on_send`, `on_finish`, and `on_error` are ;TI"Mcalled in the reverse order. `on_finish` handlers are called inside an ;TI"K`ensure` block, so they are guaranteed to be called even if something ;TI"Mraises an exception. If something raises an exception in a `on_finish` ;TI"(method, then nothing is guaranteed.;T: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below0;0;0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/events.rb;T[:protected[[: private[[I" instance;T[[;[[I" call;T@l[;[[;[ [I"make_request;T@l[I"make_response;T@l[I"on_commit;T@l[I" on_error;T@l[I"on_finish;T@l[I" on_start;T@l[[U:RDoc::Context::Section[i0o;;[;0;0[@`I" Rack;TcRDoc::NormalModulePK% ]!r\/doc/rack-3.0.8/ri/Rack/Events/make_request-i.rinu[U:RDoc::AnyMethod[iI"make_request:ETI"Rack::Events#make_request;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Events;TcRDoc::NormalClass00PK% ]伞Hdoc/rack-3.0.8/ri/Rack/Events/EventedBodyProxy/cdesc-EventedBodyProxy.rinu[U:RDoc::NormalClass[iI"EventedBodyProxy:ETI"#Rack::Events::EventedBodyProxy;TI"Rack::BodyProxy;To:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[I"lib/rack/events.rb;TI"Rack::Events;TcRDoc::NormalClassPK% ] g3doc/rack-3.0.8/ri/Rack/Events/Abstract/on_send-i.rinu[U:RDoc::AnyMethod[iI" on_send:ETI"#Rack::Events::Abstract#on_send;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I"(req, res);T@ FI" Abstract;TcRDoc::NormalModule00PK% ]87L_5doc/rack-3.0.8/ri/Rack/Events/Abstract/on_commit-i.rinu[U:RDoc::AnyMethod[iI"on_commit:ETI"%Rack::Events::Abstract#on_commit;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I"(req, res);T@ FI" Abstract;TcRDoc::NormalModule00PK% ]Ud5doc/rack-3.0.8/ri/Rack/Events/Abstract/on_finish-i.rinu[U:RDoc::AnyMethod[iI"on_finish:ETI"%Rack::Events::Abstract#on_finish;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I"(req, res);T@ FI" Abstract;TcRDoc::NormalModule00PK% ]"Pv8doc/rack-3.0.8/ri/Rack/Events/Abstract/cdesc-Abstract.rinu[U:RDoc::NormalModule[iI" Abstract:ETI"Rack::Events::Abstract;T0o:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [ [I"on_commit;TI"lib/rack/events.rb;T[I" on_error;T@"[I"on_finish;T@"[I" on_send;T@"[I" on_start;T@"[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@ I"Rack::Events;TcRDoc::NormalClassPK% ]j  4doc/rack-3.0.8/ri/Rack/Events/Abstract/on_error-i.rinu[U:RDoc::AnyMethod[iI" on_error:ETI"$Rack::Events::Abstract#on_error;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I"(req, res, e);T@ FI" Abstract;TcRDoc::NormalModule00PK% ]x4doc/rack-3.0.8/ri/Rack/Events/Abstract/on_start-i.rinu[U:RDoc::AnyMethod[iI" on_start:ETI"$Rack::Events::Abstract#on_start;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I"(req, res);T@ FI" Abstract;TcRDoc::NormalModule00PK% ]B\ 0doc/rack-3.0.8/ri/Rack/Events/make_response-i.rinu[U:RDoc::AnyMethod[iI"make_response:ETI"Rack::Events#make_response;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I"(status, headers, body);T@ FI" Events;TcRDoc::NormalClass00PK% ]ֹ&doc/rack-3.0.8/ri/Rack/Events/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Events::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I"(app, handlers);T@ FI" Events;TcRDoc::NormalClass00PK% ]g'doc/rack-3.0.8/ri/Rack/Events/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Events#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Events;TcRDoc::NormalClass00PK% ]K,,doc/rack-3.0.8/ri/Rack/Events/on_commit-i.rinu[U:RDoc::AnyMethod[iI"on_commit:ETI"Rack::Events#on_commit;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I"(request, response);T@ FI" Events;TcRDoc::NormalClass00PK% ]h~Hdoc/rack-3.0.8/ri/Rack/Events/BufferedResponse/cdesc-BufferedResponse.rinu[U:RDoc::NormalClass[iI"BufferedResponse:ETI"#Rack::Events::BufferedResponse;TI"Rack::Response::Raw;To:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[I"lib/rack/events.rb;TI"Rack::Events;TcRDoc::NormalClassPK% ]V,doc/rack-3.0.8/ri/Rack/Events/on_finish-i.rinu[U:RDoc::AnyMethod[iI"on_finish:ETI"Rack::Events#on_finish;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I"(request, response);T@ FI" Events;TcRDoc::NormalClass00PK% ]u+doc/rack-3.0.8/ri/Rack/Events/on_error-i.rinu[U:RDoc::AnyMethod[iI" on_error:ETI"Rack::Events#on_error;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I"(request, response, e);T@ FI" Events;TcRDoc::NormalClass00PK% ]| j++doc/rack-3.0.8/ri/Rack/Events/on_start-i.rinu[U:RDoc::AnyMethod[iI" on_start:ETI"Rack::Events#on_start;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/events.rb;T:0@omit_headings_from_table_of_contents_below000[I"(request, response);T@ FI" Events;TcRDoc::NormalClass00PK% ]}'doc/rack-3.0.8/ri/Rack/Builder/app-c.rinu[U:RDoc::AnyMethod[iI"app:ETI"Rack::Builder::app;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"ICreate a new Rack::Builder instance and return the Rack application ;TI"generated from it.;T: @fileI"lib/rack/builder.rb;T:0@omit_headings_from_table_of_contents_below000[I" (default_app = nil, &block);T@FI" Builder;TcRDoc::NormalClass00PK% ]T66/doc/rack-3.0.8/ri/Rack/Builder/cdesc-Builder.rinu[U:RDoc::NormalClass[iI" Builder:ETI"Rack::Builder;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[ I"ORack::Builder provides a domain-specific language (DSL) to construct Rack ;TI"Iapplications. It is primarily used to parse +config.ru+ files which ;TI"Minstantiate several middleware and a final application which are hosted ;TI"%by a Rack-compatible web server.;To:RDoc::Markup::BlankLineo; ;[I" Example:;T@o:RDoc::Markup::Verbatim;[ I" app = Rack::Builder.new do ;TI" use Rack::CommonLogger ;TI" map "/ok" do ;TI"N run lambda { |env| [200, {'content-type' => 'text/plain'}, ['OK']] } ;TI" end ;TI" end ;TI" ;TI" run app ;T: @format0o; ;[I"Or;T@o; ;[ I" app = Rack::Builder.app do ;TI" use Rack::CommonLogger ;TI"L run lambda { |env| [200, {'content-type' => 'text/plain'}, ['OK']] } ;TI" end ;TI" ;TI" run app ;T; 0o; ;[I"M+use+ adds middleware to the stack, +run+ dispatches to an application. ;TI"GYou can use +map+ to construct a Rack::URLMap in a convenient way.;T: @fileI"lib/rack/builder.rb;T:0@omit_headings_from_table_of_contents_below0; 0;0[[U:RDoc::Constant[iI"UTF_8_BOM;TI"Rack::Builder::UTF_8_BOM;T: public0o;;[o; ;[I"ihttps://stackoverflow.com/questions/2223882/whats-the-difference-between-utf-8-and-utf-8-without-bom;T; @1;0@1@cRDoc::NormalClass0[[[I" class;T[[;[ [I"app;TI"lib/rack/builder.rb;T[I"load_file;T@G[I"new;T@G[I"new_from_string;T@G[I"parse_file;T@G[:protected[[: private[[I" instance;T[[;[ [I" call;T@G[I"freeze_app;T@G[I"map;T@G[I"run;T@G[I" to_app;T@G[I"use;T@G[I" warmup;T@G[;[[;[[I"generate_map;T@G[[U:RDoc::Context::Section[i0o;;[; 0;0[@1I" Rack;TcRDoc::NormalModulePK% ]໡0doc/rack-3.0.8/ri/Rack/Builder/generate_map-i.rinu[U:RDoc::AnyMethod[iI"generate_map:ETI"Rack::Builder#generate_map;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"MGenerate a URLMap instance by generating new Rack applications for each ;TI" map block in this instance.;T: @fileI"lib/rack/builder.rb;T:0@omit_headings_from_table_of_contents_below000[I"(default_app, mapping);T@FI" Builder;TcRDoc::NormalClass00PK% ](xbZ'doc/rack-3.0.8/ri/Rack/Builder/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Builder::new;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"KInitialize a new Rack::Builder instance. +default_app+ specifies the ;TI"Cdefault application if +run+ is not called later. If a block ;TI">is given, it is evaluated in the context of the instance.;T: @fileI"lib/rack/builder.rb;T:0@omit_headings_from_table_of_contents_below000[I" (default_app = nil, &block);T@FI" Builder;TcRDoc::NormalClass00PK% ]S'doc/rack-3.0.8/ri/Rack/Builder/use-i.rinu[U:RDoc::AnyMethod[iI"use:ETI"Rack::Builder#use;TF: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I",Specifies middleware to use in a stack.;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim; [I"class Middleware ;TI" def initialize(app) ;TI" @app = app ;TI" end ;TI" ;TI" def call(env) ;TI"8 env["rack.some_header"] = "setting an example" ;TI" @app.call(env) ;TI" end ;TI" end ;TI" ;TI"use Middleware ;TI"Lrun lambda { |env| [200, { "content-type" => "text/plain" }, ["OK"]] } ;T: @format0o; ; [I"_All requests through to this application will first be processed by the middleware class. ;TI"\The +call+ method in this example sets an additional environment key which then can be ;TI"/referenced in the application if required.;T: @fileI"lib/rack/builder.rb;T:0@omit_headings_from_table_of_contents_below000[I" (middleware, *args, &block);T@#FI" Builder;TcRDoc::NormalClass00PK% ]'doc/rack-3.0.8/ri/Rack/Builder/run-i.rinu[U:RDoc::AnyMethod[iI"run:ETI"Rack::Builder#run;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"LTakes a block or argument that is an object that responds to #call and ;TI"returns a Rack response.;To:RDoc::Markup::BlankLineo; ; [I"You can use a block:;T@o:RDoc::Markup::Verbatim; [I"run do |env| ;TI"C [200, { "content-type" => "text/plain" }, ["Hello World!"]] ;TI" end ;T: @format0o; ; [I"#You can also provide a lambda:;T@o; ; [I"Lrun lambda { |env| [200, { "content-type" => "text/plain" }, ["OK"]] } ;T; 0o; ; [I"+You can also provide a class instance:;T@o; ; [ I"class Heartbeat ;TI" def call(env) ;TI": [200, { "content-type" => "text/plain" }, ["OK"]] ;TI" end ;TI" end ;TI" ;TI"run Heartbeat.new;T; 0: @fileI"lib/rack/builder.rb;T:0@omit_headings_from_table_of_contents_below000[I"(app = nil, &block);T@*FI" Builder;TcRDoc::NormalClass00PK% ]h>*doc/rack-3.0.8/ri/Rack/Builder/warmup-i.rinu[U:RDoc::AnyMethod[iI" warmup:ETI"Rack::Builder#warmup;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"[Takes a lambda or block that is used to warm-up the application. This block is called ;TI"7before the Rack application is returned by to_app.;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim; [ I"warmup do |app| ;TI"+ client = Rack::MockRequest.new(app) ;TI" client.get('/') ;TI" end ;TI" ;TI"use SomeMiddleware ;TI"run MyApp;T: @format0: @fileI"lib/rack/builder.rb;T:0@omit_headings_from_table_of_contents_below000[I"(prc = nil, &block);T@FI" Builder;TcRDoc::NormalClass00PK% ])k(doc/rack-3.0.8/ri/Rack/Builder/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Builder#call;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"MCall the Rack application generated by this builder instance. Note that ;TI"Jthis rebuilds the Rack application and runs the warmup code (if any) ;TI"Severy time it is called, so it should not be used if performance is important.;T: @fileI"lib/rack/builder.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@FI" Builder;TcRDoc::NormalClass00PK% ]X9//.doc/rack-3.0.8/ri/Rack/Builder/parse_file-c.rinu[U:RDoc::AnyMethod[iI"parse_file:ETI"Rack::Builder::parse_file;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I";Parse the given config file to get a Rack application.;To:RDoc::Markup::BlankLineo; ; [I":If the config file ends in +.ru+, it is treated as a ;TI"8rackup file and the contents will be treated as if ;TI",specified inside a Rack::Builder block.;T@o; ; [I"5If the config file does not end in +.ru+, it is ;TI"9required and Rack will use the basename of the file ;TI"Ato guess which constant will be the Rack application to run.;T@o; ; [I"Examples:;T@o:RDoc::Markup::Verbatim; [I"+Rack::Builder.parse_file('config.ru') ;TI"6# Rack application built using Rack::Builder.new ;TI" ;TI"(Rack::Builder.parse_file('app.rb') ;TI"8# requires app.rb, which can be anywhere in Ruby's ;TI"8# load path. After requiring, assumes App constant ;TI"!# contains Rack application ;TI" ;TI"-Rack::Builder.parse_file('./my_app.rb') ;TI"4# requires ./my_app.rb, which should be in the ;TI"6# process's current directory. After requiring, ;TI"7# assumes MyApp constant contains Rack application;T: @format0: @fileI"lib/rack/builder.rb;T:0@omit_headings_from_table_of_contents_below000[I" (path);T@*FI" Builder;TcRDoc::NormalClass00PK% ]ϑMM*doc/rack-3.0.8/ri/Rack/Builder/to_app-i.rinu[U:RDoc::AnyMethod[iI" to_app:ETI"Rack::Builder#to_app;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I" 'text/plain'}, ["Hello World"]] ;TI" end ;TI" end ;TI" ;TI"class Heartbeat ;TI" def call(env) ;TI"; [200, { "content-type" => "text/plain" }, ["OK"]] ;TI" end ;TI" end ;TI" ;TI" app = Rack::Builder.app do ;TI" map '/heartbeat' do ;TI" run Heartbeat.new ;TI" end ;TI" run App.new ;TI" end ;TI" ;TI" run app ;T: @format0o; ; [I"kThe +use+ method can also be used inside the block to specify middleware to run under a specific path:;T@o; ; [ I" app = Rack::Builder.app do ;TI" map '/heartbeat' do ;TI" use Middleware ;TI" run Heartbeat.new ;TI" end ;TI" run App.new ;TI" end ;T; 0o; ; [I"mThis example includes a piece of middleware which will run before +/heartbeat+ requests hit +Heartbeat+.;T@o; ; [I"hNote that providing a +path+ of +/+ will ignore any default application given in a +run+ statement ;TI"outside the block.;T: @fileI"lib/rack/builder.rb;T:0@omit_headings_from_table_of_contents_below000[I"(path, &block);T@:FI" Builder;TcRDoc::NormalClass00PK% ]n?x-doc/rack-3.0.8/ri/Rack/Builder/load_file-c.rinu[U:RDoc::AnyMethod[iI"load_file:ETI"Rack::Builder::load_file;TT: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I"8Load the given file as a rackup file, treating the ;TI";contents as if specified inside a Rack::Builder block.;To:RDoc::Markup::BlankLineo; ; [I":Ignores content in the file after +__END__+, so that ;TI"8use of +__END__+ will not result in a syntax error.;T@o; ; [I"Example config.ru file:;T@o:RDoc::Markup::Verbatim; [ I"$ cat config.ru ;TI" ;TI"use Rack::ContentLength ;TI"require './app.rb' ;TI" run App;T: @format0: @fileI"lib/rack/builder.rb;T:0@omit_headings_from_table_of_contents_below000[I" (path);T@FI" Builder;TcRDoc::NormalClass00PK% ]%7;;7doc/rack-3.0.8/ri/Rack/ContentType/cdesc-ContentType.rinu[U:RDoc::NormalClass[iI"ContentType:ETI"Rack::ContentType;TI" Object;To:RDoc::Markup::Document: @parts[o;;[ o:RDoc::Markup::Paragraph;[I"DSets the content-type header on responses which don't have one.;To:RDoc::Markup::BlankLineo; ;[I"Builder Usage:;To:RDoc::Markup::Verbatim;[I")use Rack::ContentType, "text/plain" ;T: @format0o; ;[I"CWhen no content type argument is provided, "text/html" is the ;TI" default.;T: @fileI"lib/rack/content_type.rb;T:0@omit_headings_from_table_of_contents_below0; 0;0[[[[I"Rack::Utils;To;;[; @;0I"lib/rack/content_type.rb;T[[I" class;T[[: public[[I"new;T@$[:protected[[: private[[I" instance;T[[;[[I" call;T@$[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0;0[@I" Rack;TcRDoc::NormalModulePK% ]ה+doc/rack-3.0.8/ri/Rack/ContentType/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::ContentType::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/content_type.rb;T:0@omit_headings_from_table_of_contents_below000[I"&(app, content_type = "text/html");T@ FI"ContentType;TcRDoc::NormalClass00PK% ]_W,doc/rack-3.0.8/ri/Rack/ContentType/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::ContentType#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/content_type.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI"ContentType;TcRDoc::NormalClass00PK% ]0doc/rack-3.0.8/ri/Rack/Headers/downcase_key-i.rinu[U:RDoc::AnyMethod[iI"downcase_key:ETI"Rack::Headers#downcase_key;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ FI" Headers;TcRDoc::NormalClass00PK% ] -doc/rack-3.0.8/ri/Rack/Headers/values_at-i.rinu[U:RDoc::AnyMethod[iI"values_at:ETI"Rack::Headers#values_at;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (*keys);T@ FI" Headers;TcRDoc::NormalClass00PK% ]j>RR.doc/rack-3.0.8/ri/Rack/Headers/has_key%3f-i.rinu[U:RDoc::AnyMethod[iI" has_key?:ETI"Rack::Headers#has_key?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[[I" include?;To;; [; @ ; 0[I" key?;To;; [; @ ; 0[I" member?;To;; [; @ ; 0I" (key);T@ TI" Headers;TcRDoc::NormalClass00PK% ]V'doc/rack-3.0.8/ri/Rack/Headers/dig-i.rinu[U:RDoc::AnyMethod[iI"dig:ETI"Rack::Headers#dig;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I"(key, *a);T@ TI" Headers;TcRDoc::NormalClass00PK% ]zAA+doc/rack-3.0.8/ri/Rack/Headers/replace-i.rinu[U:RDoc::AnyMethod[iI" replace:ETI"Rack::Headers#replace;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (hash);T@ FI" Headers;TcRDoc::NormalClass00PK% ]ç"q*doc/rack-3.0.8/ri/Rack/Headers/key%3f-i.rinu[U:RDoc::AnyMethod[iI" key?:ETI"Rack::Headers#key?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ FI" Headers;TcRDoc::NormalClass0[I"Rack::Headers;TFI" has_key?;TPK% ]We)doc/rack-3.0.8/ri/Rack/Headers/merge-i.rinu[U:RDoc::AnyMethod[iI" merge:ETI"Rack::Headers#merge;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I"(hash, &block);T@ FI" Headers;TcRDoc::NormalClass00PK% ]&*doc/rack-3.0.8/ri/Rack/Headers/%5b%5d-c.rinu[U:RDoc::AnyMethod[iI"[]:ETI"Rack::Headers::[];TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (*items);T@ FI" Headers;TcRDoc::NormalClass00PK% ]P  7doc/rack-3.0.8/ri/Rack/Headers/compare_by_identity-i.rinu[U:RDoc::AnyMethod[iI"compare_by_identity:ETI"&Rack::Headers#compare_by_identity;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Headers;TcRDoc::NormalClass00PK% ]2k)doc/rack-3.0.8/ri/Rack/Headers/fetch-i.rinu[U:RDoc::AnyMethod[iI" fetch:ETI"Rack::Headers#fetch;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I"(key, *default, &block);T@ TI" Headers;TcRDoc::NormalClass00PK% ]+doc/rack-3.0.8/ri/Rack/Headers/to_proc-i.rinu[U:RDoc::AnyMethod[iI" to_proc:ETI"Rack::Headers#to_proc;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Headers;TcRDoc::NormalClass00PK% ]B*doc/rack-3.0.8/ri/Rack/Headers/update-i.rinu[U:RDoc::AnyMethod[iI" update:ETI"Rack::Headers#update;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[[I" merge!;To;; [; @ ; 0I"(hash, &block);T@ FI" Headers;TcRDoc::NormalClass00PK% ].doc/rack-3.0.8/ri/Rack/Headers/include%3f-i.rinu[U:RDoc::AnyMethod[iI" include?:ETI"Rack::Headers#include?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ FI" Headers;TcRDoc::NormalClass0[I"Rack::Headers;TFI" has_key?;TPK% ]d!{,doc/rack-3.0.8/ri/Rack/Headers/merge%21-i.rinu[U:RDoc::AnyMethod[iI" merge!:ETI"Rack::Headers#merge!;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I"(hash, &block);T@ FI" Headers;TcRDoc::NormalClass0[I"Rack::Headers;TFI" update;TPK% ]x8*doc/rack-3.0.8/ri/Rack/Headers/select-i.rinu[U:RDoc::AnyMethod[iI" select:ETI"Rack::Headers#select;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (&block);T@ FI" Headers;TcRDoc::NormalClass00PK% ]Tk*doc/rack-3.0.8/ri/Rack/Headers/%5b%5d-i.rinu[U:RDoc::AnyMethod[iI"[]:ETI"Rack::Headers#[];TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ TI" Headers;TcRDoc::NormalClass00PK% ]V9%*doc/rack-3.0.8/ri/Rack/Headers/invert-i.rinu[U:RDoc::AnyMethod[iI" invert:ETI"Rack::Headers#invert;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Headers;TcRDoc::NormalClass00PK% ]5doc/rack-3.0.8/ri/Rack/Headers/transform_keys%21-i.rinu[U:RDoc::AnyMethod[iI"transform_keys!:ETI""Rack::Headers#transform_keys!;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below00I" k] = v;T[I"();T@ FI" Headers;TcRDoc::NormalClass00PK% ]cdC@*doc/rack-3.0.8/ri/Rack/Headers/delete-i.rinu[U:RDoc::AnyMethod[iI" delete:ETI"Rack::Headers#delete;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ TI" Headers;TcRDoc::NormalClass00PK% ]8/doc/rack-3.0.8/ri/Rack/Headers/cdesc-Headers.rinu[U:RDoc::NormalClass[iI" Headers:ETI"Rack::Headers;TI" Hash;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[ I"NRack::Headers is a Hash subclass that downcases all keys. It's designed ;TI"Jto be used by rack applications that don't implement the Rack 3 SPEC ;TI"K(by using non-lowercase response header keys), automatically handling ;TI"the downcasing of keys.;T: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[I"[];TI"lib/rack/headers.rb;T[:protected[[: private[[I" instance;T[[; [ [I"[];T@ [I"[]=;T@ [I" assoc;T@ [I"compare_by_identity;T@ [I" delete;T@ [I"dig;T@ [I" except;T@ [I" fetch;T@ [I"fetch_values;T@ [I" has_key?;T@ [I" include?;T@ [I" invert;T@ [I" key?;T@ [I" member?;T@ [I" merge;T@ [I" merge!;T@ [I" reject;T@ [I" replace;T@ [I" select;T@ [I" slice;T@ [I" store;T@ [I" to_proc;T@ [I"transform_keys;T@ [I"transform_keys!;T@ [I"transform_values;T@ [I" update;T@ [I"values_at;T@ [; [[;[[I"downcase_key;T@ [[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]I2doc/rack-3.0.8/ri/Rack/Headers/transform_keys-i.rinu[U:RDoc::AnyMethod[iI"transform_keys:ETI"!Rack::Headers#transform_keys;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (&block);T@ FI" Headers;TcRDoc::NormalClass00PK% ]4=)doc/rack-3.0.8/ri/Rack/Headers/store-i.rinu[U:RDoc::AnyMethod[iI" store:ETI"Rack::Headers#store;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I"(key, value);T@ FI" Headers;TcRDoc::NormalClass0[I"Rack::Headers;TFI"[]=;TPK% ]-doc/rack-3.0.8/ri/Rack/Headers/%5b%5d%3d-i.rinu[U:RDoc::AnyMethod[iI"[]=:ETI"Rack::Headers#[]=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[[I" store;To;; [; @ ; 0I"(key, value);T@ TI" Headers;TcRDoc::NormalClass00PK% ]ėi*doc/rack-3.0.8/ri/Rack/Headers/reject-i.rinu[U:RDoc::AnyMethod[iI" reject:ETI"Rack::Headers#reject;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (&block);T@ FI" Headers;TcRDoc::NormalClass00PK% ]s*doc/rack-3.0.8/ri/Rack/Headers/except-i.rinu[U:RDoc::AnyMethod[iI" except:ETI"Rack::Headers#except;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I" :nocov:;T: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (*a);T@TI" Headers;TcRDoc::NormalClass00PK% ]Vȃ-doc/rack-3.0.8/ri/Rack/Headers/member%3f-i.rinu[U:RDoc::AnyMethod[iI" member?:ETI"Rack::Headers#member?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ FI" Headers;TcRDoc::NormalClass0[I"Rack::Headers;TFI" has_key?;TPK% ]|[  4doc/rack-3.0.8/ri/Rack/Headers/transform_values-i.rinu[U:RDoc::AnyMethod[iI"transform_values:ETI"#Rack::Headers#transform_values;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (&block);T@ FI" Headers;TcRDoc::NormalClass00PK% ]85)doc/rack-3.0.8/ri/Rack/Headers/assoc-i.rinu[U:RDoc::AnyMethod[iI" assoc:ETI"Rack::Headers#assoc;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (key);T@ TI" Headers;TcRDoc::NormalClass00PK% ]i)doc/rack-3.0.8/ri/Rack/Headers/slice-i.rinu[U:RDoc::AnyMethod[iI" slice:ETI"Rack::Headers#slice;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I" :nocov:;T: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (*a);T@FI" Headers;TcRDoc::NormalClass00PK% ]'0doc/rack-3.0.8/ri/Rack/Headers/fetch_values-i.rinu[U:RDoc::AnyMethod[iI"fetch_values:ETI"Rack::Headers#fetch_values;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/headers.rb;T:0@omit_headings_from_table_of_contents_below000[I" (*a);T@ TI" Headers;TcRDoc::NormalClass00PK% ]| Î;doc/rack-3.0.8/ri/Rack/BodyProxy/respond_to_missing%3f-i.rinu[U:RDoc::AnyMethod[iI"respond_to_missing?:ETI"(Rack::BodyProxy#respond_to_missing?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"http:// or https://.;To:RDoc::Markup::BlankLineo; ;[ I"FURLMap modifies the SCRIPT_NAME and PATH_INFO such that the part ;TI"Frelevant for dispatch is in the SCRIPT_NAME, and the rest in the ;TI"?PATH_INFO. This should be taken care of when you need to ;TI"2reconstruct the URL in order to create links.;T@o; ;[I"FURLMap dispatches in such a way that the longest paths are tried ;TI")first, since they are most specific.;T: @fileI"lib/rack/urlmap.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/urlmap.rb;T[:protected[[: private[[I" instance;T[[; [[I" call;T@*[I" remap;T@*[;[[;[[I" casecmp?;T@*[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]0-doc/rack-3.0.8/ri/Rack/URLMap/casecmp%3f-i.rinu[U:RDoc::AnyMethod[iI" casecmp?:ETI"Rack::URLMap#casecmp?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/urlmap.rb;T:0@omit_headings_from_table_of_contents_below000[I" (v1, v2);T@ FI" URLMap;TcRDoc::NormalClass00PK% ]ƦN'doc/rack-3.0.8/ri/Rack/Cascade/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Cascade::new;TT: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Paragraph; [I"CSet the apps to send requests to, and what statuses result in ;TI"cascading. Arguments:;To:RDoc::Markup::BlankLineo; ; [I"/apps: An enumerable of rack applications. ;TI"Ocascade_for: The statuses to use cascading for. If a response is received;To:RDoc::Markup::Verbatim; [I"(from an app, the next app is tried.;T: @format0: @fileI"lib/rack/cascade.rb;T:0@omit_headings_from_table_of_contents_below000[I"%(apps, cascade_for = [404, 405]);T@FI" Cascade;TcRDoc::NormalClass00PK% ]gD TT.doc/rack-3.0.8/ri/Rack/Cascade/include%3f-i.rinu[U:RDoc::AnyMethod[iI" include?:ETI"Rack::Cascade#include?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"''>doc/rack-3.0.8/ri/Rack/Files/BaseIterator/each_range_part-i.rinu[U:RDoc::AnyMethod[iI"each_range_part:ETI".Rack::Files::BaseIterator#each_range_part;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below00I" part;T[I"(file, range);T@ FI"BaseIterator;TcRDoc::NormalClass00PK% ]I7doc/rack-3.0.8/ri/Rack/Files/BaseIterator/bytesize-i.rinu[U:RDoc::AnyMethod[iI" bytesize:ETI"'Rack::Files::BaseIterator#bytesize;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"BaseIterator;TcRDoc::NormalClass00PK% ]w~l?doc/rack-3.0.8/ri/Rack/Files/BaseIterator/cdesc-BaseIterator.rinu[U:RDoc::NormalClass[iI"BaseIterator:ETI"Rack::Files::BaseIterator;TI" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I" options;TI"R;T: publicFI"lib/rack/files.rb;T[ I" path;T@; F@[ I" ranges;T@; F@[[[[I" class;T[[; [[I"new;T@[:protected[[: private[[I" instance;T[[; [[I" bytesize;T@[I" close;T@[I" each;T@[; [[; [[I"each_range_part;T@[I"multipart?;T@[I"multipart_heading;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Files;TcRDoc::NormalClassPK% ]`+d;doc/rack-3.0.8/ri/Rack/Files/BaseIterator/multipart%3f-i.rinu[U:RDoc::AnyMethod[iI"multipart?:ETI")Rack::Files::BaseIterator#multipart?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"BaseIterator;TcRDoc::NormalClass00PK% ]'Z2doc/rack-3.0.8/ri/Rack/Files/BaseIterator/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"#Rack::Files::BaseIterator::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I"(path, ranges, options);T@ FI"BaseIterator;TcRDoc::NormalClass00PK% ]θ+6doc/rack-3.0.8/ri/Rack/Files/BaseIterator/options-i.rinu[U:RDoc::Attr[iI" options:ETI"&Rack::Files::BaseIterator#options;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Files::BaseIterator;TcRDoc::NormalClass0PK% ]uꅨ4doc/rack-3.0.8/ri/Rack/Files/BaseIterator/close-i.rinu[U:RDoc::AnyMethod[iI" close:ETI"$Rack::Files::BaseIterator#close;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"BaseIterator;TcRDoc::NormalClass00PK% ]΍@doc/rack-3.0.8/ri/Rack/Files/BaseIterator/multipart_heading-i.rinu[U:RDoc::AnyMethod[iI"multipart_heading:ETI"0Rack::Files::BaseIterator#multipart_heading;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I" (range);T@ FI"BaseIterator;TcRDoc::NormalClass00PK% ]NО-3doc/rack-3.0.8/ri/Rack/Files/BaseIterator/path-i.rinu[U:RDoc::Attr[iI" path:ETI"#Rack::Files::BaseIterator#path;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Files::BaseIterator;TcRDoc::NormalClass0PK% ]+3doc/rack-3.0.8/ri/Rack/Files/BaseIterator/each-i.rinu[U:RDoc::AnyMethod[iI" each:ETI"#Rack::Files::BaseIterator#each;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below00I"multipart_heading(range);T[I"();T@ FI"BaseIterator;TcRDoc::NormalClass00PK% ]^ 5doc/rack-3.0.8/ri/Rack/Files/BaseIterator/ranges-i.rinu[U:RDoc::Attr[iI" ranges:ETI"%Rack::Files::BaseIterator#ranges;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Files::BaseIterator;TcRDoc::NormalClass0PK% ]_y%doc/rack-3.0.8/ri/Rack/Files/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Files::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I"6(root, headers = {}, default_mime = 'text/plain');T@ FI" Files;TcRDoc::NormalClass00PK% ]Kcڄ*doc/rack-3.0.8/ri/Rack/Files/filesize-i.rinu[U:RDoc::AnyMethod[iI" filesize:ETI"Rack::Files#filesize;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I" (path);T@ FI" Files;TcRDoc::NormalClass00PK% ]t&doc/rack-3.0.8/ri/Rack/Files/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Files#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Files;TcRDoc::NormalClass00PK% ]i%doc/rack-3.0.8/ri/Rack/Files/get-i.rinu[U:RDoc::AnyMethod[iI"get:ETI"Rack::Files#get;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Files;TcRDoc::NormalClass00PK% ]t$+doc/rack-3.0.8/ri/Rack/Files/cdesc-Files.rinu[U:RDoc::NormalClass[iI" Files:ETI"Rack::Files;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[ I"QRack::Files serves files below the +root+ directory given, according to the ;TI"$path info of the Rack request. ;TI"Me.g. when Rack::Files.new("/etc") is used, you can access 'passwd' file ;TI"$as http://localhost:9292/passwd;To:RDoc::Markup::BlankLineo; ;[I"IHandlers can detect if bodies are a Rack::Files, and use mechanisms ;TI"!like sendfile on the +path+.;T: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I" root;TI"R;T: publicFI"lib/rack/files.rb;T[U:RDoc::Constant[iI"ALLOWED_VERBS;TI"Rack::Files::ALLOWED_VERBS;T; 0o;;[; @; 0@@cRDoc::NormalClass0U;[iI"ALLOW_HEADER;TI"Rack::Files::ALLOW_HEADER;T; 0o;;[; @; 0@@@&0U;[iI"MULTIPART_BOUNDARY;TI"$Rack::Files::MULTIPART_BOUNDARY;T; 0o;;[; @; 0@@@&0[[[I" class;T[[; [[I"new;T@[:protected[[: private[[I" instance;T[[; [[I" call;T@[I"get;T@[I" serving;T@[;[[;[[I" fail;T@[I" filesize;T@[I"mime_type;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"lib/rack/utils.rb;TI" Rack;TcRDoc::NormalModulePK% ]+S)doc/rack-3.0.8/ri/Rack/Files/serving-i.rinu[U:RDoc::AnyMethod[iI" serving:ETI"Rack::Files#serving;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I"(request, path);T@ FI" Files;TcRDoc::NormalClass00PK% ]ldd+doc/rack-3.0.8/ri/Rack/Files/mime_type-i.rinu[U:RDoc::AnyMethod[iI"mime_type:ETI"Rack::Files#mime_type;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"@The MIME type for the contents of the file located at @path;T: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below000[I"(path, default_mime);T@FI" Files;TcRDoc::NormalClass00PK% ]Ҿ&doc/rack-3.0.8/ri/Rack/Files/root-i.rinu[U:RDoc::Attr[iI" root:ETI"Rack::Files#root;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Files;TcRDoc::NormalClass0PK% ]ih7doc/rack-3.0.8/ri/Rack/Files/Iterator/cdesc-Iterator.rinu[U:RDoc::NormalClass[iI" Iterator:ETI"Rack::Files::Iterator;TI"Rack::Files::BaseIterator;To:RDoc::Markup::Document: @parts[o;;[: @fileI"lib/rack/files.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Files;TcRDoc::NormalClassPK% ]*doc/rack-3.0.8/ri/Rack/ShowStatus/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::ShowStatus::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/show_status.rb;T:0@omit_headings_from_table_of_contents_below000[I" (app);T@ FI"ShowStatus;TcRDoc::NormalClass00PK% ]S+doc/rack-3.0.8/ri/Rack/ShowStatus/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::ShowStatus#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/show_status.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI"ShowStatus;TcRDoc::NormalClass00PK% ]CS,DD5doc/rack-3.0.8/ri/Rack/ShowStatus/cdesc-ShowStatus.rinu[U:RDoc::NormalClass[iI"ShowStatus:ETI"Rack::ShowStatus;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"DRack::ShowStatus catches all empty responses and replaces them ;TI"&with a site explaining the error.;To:RDoc::Markup::BlankLineo; ;[I"HAdditional details can be put into rack.showstatus.detail ;TI"Gand will be shown as HTML. If such details exist, the error page ;TI"9is always rendered, even if the reply was not empty.;T: @fileI"lib/rack/show_status.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/show_status.rb;T[:protected[[: private[[I" instance;T[[; [[I" call;T@$[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]/doc/rack-3.0.8/ri/Rack/MockResponse/%3d%7e-i.rinu[U:RDoc::AnyMethod[iI"=~:ETI"Rack::MockResponse#=~;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/mock_response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (other);T@ FI"MockResponse;TcRDoc::NormalClass00PK% ]?i77Cdoc/rack-3.0.8/ri/Rack/MockResponse/identify_cookie_attributes-i.rinu[U:RDoc::AnyMethod[iI"identify_cookie_attributes:ETI"2Rack::MockResponse#identify_cookie_attributes;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/mock_response.rb;T:0@omit_headings_from_table_of_contents_below000[I"(cookie_filling);T@ FI"MockResponse;TcRDoc::NormalClass00PK% ])c</doc/rack-3.0.8/ri/Rack/MockResponse/cookie-i.rinu[U:RDoc::AnyMethod[iI" cookie:ETI"Rack::MockResponse#cookie;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/mock_response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (name);T@ FI"MockResponse;TcRDoc::NormalClass00PK% ]ʒ''Bdoc/rack-3.0.8/ri/Rack/MockResponse/parse_cookies_from_header-i.rinu[U:RDoc::AnyMethod[iI"parse_cookies_from_header:ETI"1Rack::MockResponse#parse_cookies_from_header;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/mock_response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"MockResponse;TcRDoc::NormalClass00PK% ]ܦN))0doc/rack-3.0.8/ri/Rack/MockResponse/cookies-i.rinu[U:RDoc::Attr[iI" cookies:ETI"Rack::MockResponse#cookies;TI"R;T: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I" Headers;T: @fileI"lib/rack/mock_response.rb;T:0@omit_headings_from_table_of_contents_below0F@I"Rack::MockResponse;TcRDoc::NormalClass0PK% ]O,doc/rack-3.0.8/ri/Rack/MockResponse/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::MockResponse::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/mock_response.rb;T:0@omit_headings_from_table_of_contents_below000[I"*(status, headers, body, errors = nil);T@ TI"MockResponse;TcRDoc::NormalClass00PK% ]'&1doc/rack-3.0.8/ri/Rack/MockResponse/empty%3f-i.rinu[U:RDoc::AnyMethod[iI" empty?:ETI"Rack::MockResponse#empty?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/mock_response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"MockResponse;TcRDoc::NormalClass00PK% ];.doc/rack-3.0.8/ri/Rack/MockResponse/match-i.rinu[U:RDoc::AnyMethod[iI" match:ETI"Rack::MockResponse#match;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/mock_response.rb;T:0@omit_headings_from_table_of_contents_below000[I" (other);T@ FI"MockResponse;TcRDoc::NormalClass00PK% ]ʆ-doc/rack-3.0.8/ri/Rack/MockResponse/body-i.rinu[U:RDoc::AnyMethod[iI" body:ETI"Rack::MockResponse#body;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/mock_response.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"MockResponse;TcRDoc::NormalClass00PK% ];6zz9doc/rack-3.0.8/ri/Rack/MockResponse/cdesc-MockResponse.rinu[U:RDoc::NormalClass[iI"MockResponse:ETI"Rack::MockResponse;TI"Rack::Response;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"GRack::MockResponse provides useful helpers for testing your apps. ;TI"EUsually, you don't create the MockResponse on your own, but use ;TI"MockRequest.;T: @fileI"lib/rack/mock_response.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I" cookies;TI"R;T: publicFI"lib/rack/mock_response.rb;T[ I" errors;TI"RW;T; F@[ I"original_headers;T@; F@[[[[I" class;T[[; [[I"new;T@[:protected[[: private[[I" instance;T[[; [ [I"=~;T@[I" body;T@[I" cookie;T@[I" empty?;T@[I" match;T@[; [[;[[I"identify_cookie_attributes;T@[I"parse_cookies_from_header;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ];;9doc/rack-3.0.8/ri/Rack/MockResponse/original_headers-i.rinu[U:RDoc::Attr[iI"original_headers:ETI"(Rack::MockResponse#original_headers;TI"R;T: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I" Headers;T: @fileI"lib/rack/mock_response.rb;T:0@omit_headings_from_table_of_contents_below0F@I"Rack::MockResponse;TcRDoc::NormalClass0PK% ]߱''/doc/rack-3.0.8/ri/Rack/MockResponse/errors-i.rinu[U:RDoc::Attr[iI" errors:ETI"Rack::MockResponse#errors;TI"RW;T: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I" Errors;T: @fileI"lib/rack/mock_response.rb;T:0@omit_headings_from_table_of_contents_below0F@I"Rack::MockResponse;TcRDoc::NormalClass0PK% ]a3doc/rack-3.0.8/ri/Rack/MediaType/cdesc-MediaType.rinu[U:RDoc::NormalClass[iI"MediaType:ETI"Rack::MediaType;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"ORack::MediaType parse media type and parameters out of content_type string;T: @fileI"lib/rack/media_type.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[U:RDoc::Constant[iI"SPLIT_PATTERN;TI"#Rack::MediaType::SPLIT_PATTERN;T: public0o;;[; @; 0@@cRDoc::NormalClass0[[[I" class;T[[; [[I" params;TI"lib/rack/media_type.rb;T[I" type;T@$[:protected[[: private[[I"strip_doublequotes;T@$[I" instance;T[[; [[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ] yy,doc/rack-3.0.8/ri/Rack/MediaType/params-c.rinu[U:RDoc::AnyMethod[iI" params:ETI"Rack::MediaType::params;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I"FThe media type parameters provided in CONTENT_TYPE as a Hash, or ;TI"Dan empty Hash if no CONTENT_TYPE or media-type parameters were ;TI"Kprovided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8", ;TI"2this method responds with the following Hash:;To:RDoc::Markup::Verbatim; [I"{ 'charset' => 'utf-8' };T: @format0: @fileI"lib/rack/media_type.rb;T:0@omit_headings_from_table_of_contents_below000[I"(content_type);T@FI"MediaType;TcRDoc::NormalClass00PK% ]ѧӭ8doc/rack-3.0.8/ri/Rack/MediaType/strip_doublequotes-c.rinu[U:RDoc::AnyMethod[iI"strip_doublequotes:ETI"(Rack::MediaType::strip_doublequotes;TT: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/media_type.rb;T:0@omit_headings_from_table_of_contents_below000[I" (str);T@ FI"MediaType;TcRDoc::NormalClass00PK% ]i-l*doc/rack-3.0.8/ri/Rack/MediaType/type-c.rinu[U:RDoc::AnyMethod[iI" type:ETI"Rack::MediaType::type;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"FThe media type (type/subtype) portion of the CONTENT_TYPE header ;TI"Cwithout any media type parameters. e.g., when CONTENT_TYPE is ;TI"@"text/plain;charset=utf-8", the media-type is "text/plain".;To:RDoc::Markup::BlankLineo; ; [I"BFor more information on the use of media types in HTTP, see: ;TI"Ahttp://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7;T: @fileI"lib/rack/media_type.rb;T:0@omit_headings_from_table_of_contents_below000[I"(content_type);T@FI"MediaType;TcRDoc::NormalClass00PK% ]}.doc/rack-3.0.8/ri/Rack/ForwardRequest/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::ForwardRequest::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/recursive.rb;T:0@omit_headings_from_table_of_contents_below000[I"(url, env = {});T@ TI"ForwardRequest;TcRDoc::NormalClass00PK% ]'.doc/rack-3.0.8/ri/Rack/ForwardRequest/url-i.rinu[U:RDoc::Attr[iI"url:ETI"Rack::ForwardRequest#url;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/recursive.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::ForwardRequest;TcRDoc::NormalClass0PK% ]2=doc/rack-3.0.8/ri/Rack/ForwardRequest/cdesc-ForwardRequest.rinu[U:RDoc::NormalClass[iI"ForwardRequest:ETI"Rack::ForwardRequest;TI"Exception;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"GRack::ForwardRequest gets caught by Rack::Recursive and redirects ;TI"-the current request to the app at +url+.;To:RDoc::Markup::BlankLineo:RDoc::Markup::Verbatim;[I"+raise ForwardRequest.new("/not-found");T: @format0: @fileI"lib/rack/recursive.rb;T:0@omit_headings_from_table_of_contents_below0; 0;0[[ I"env;TI"R;T: publicFI"lib/rack/recursive.rb;T[ I"url;T@;F@[[[[I" class;T[[;[[I"new;T@[:protected[[: private[[I" instance;T[[;[[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0;0[@I" Rack;TcRDoc::NormalModulePK% ]L.doc/rack-3.0.8/ri/Rack/ForwardRequest/env-i.rinu[U:RDoc::Attr[iI"env:ETI"Rack::ForwardRequest#env;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/recursive.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::ForwardRequest;TcRDoc::NormalClass0PK% ]n/doc/rack-3.0.8/ri/Rack/Directory/list_path-i.rinu[U:RDoc::AnyMethod[iI"list_path:ETI"Rack::Directory#list_path;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"DRack response to use for files and directories under the root. ;TI"LUnreadable and non-file, non-directory entries will get a 404 response.;T: @fileI"lib/rack/directory.rb;T:0@omit_headings_from_table_of_contents_below000[I"((env, path, path_info, script_name);T@FI"Directory;TcRDoc::NormalClass00PK% ]\$7doc/rack-3.0.8/ri/Rack/Directory/check_bad_request-i.rinu[U:RDoc::AnyMethod[iI"check_bad_request:ETI"&Rack::Directory#check_bad_request;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"SRack response to use for requests with invalid paths, or nil if path is valid.;T: @fileI"lib/rack/directory.rb;T:0@omit_headings_from_table_of_contents_below000[I"(path_info);T@FI"Directory;TcRDoc::NormalClass00PK% ]7___)doc/rack-3.0.8/ri/Rack/Directory/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Directory::new;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I">Set the root directory and application for serving files.;T: @fileI"lib/rack/directory.rb;T:0@omit_headings_from_table_of_contents_below000[I"(root, app = nil);T@FI"Directory;TcRDoc::NormalClass00PK% ]RR5doc/rack-3.0.8/ri/Rack/Directory/filesize_format-i.rinu[U:RDoc::AnyMethod[iI"filesize_format:ETI"$Rack::Directory#filesize_format;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"&Provide human readable file sizes;T: @fileI"lib/rack/directory.rb;T:0@omit_headings_from_table_of_contents_below000[I" (int);T@FI"Directory;TcRDoc::NormalClass00PK% ]/Q*doc/rack-3.0.8/ri/Rack/Directory/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Directory#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/directory.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI"Directory;TcRDoc::NormalClass00PK% ]{{)doc/rack-3.0.8/ri/Rack/Directory/get-i.rinu[U:RDoc::AnyMethod[iI"get:ETI"Rack::Directory#get;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I">Internals of request handling. Similar to call but does ;TI"'not remove body for HEAD requests.;T: @fileI"lib/rack/directory.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@FI"Directory;TcRDoc::NormalClass00PK% ]LL5doc/rack-3.0.8/ri/Rack/Directory/check_forbidden-i.rinu[U:RDoc::AnyMethod[iI"check_forbidden:ETI"$Rack::Directory#check_forbidden;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"fRack response to use for requests with paths outside the root, or nil if path is inside the root.;T: @fileI"lib/rack/directory.rb;T:0@omit_headings_from_table_of_contents_below000[I"(path_info);T@FI"Directory;TcRDoc::NormalClass00PK% ]x3doc/rack-3.0.8/ri/Rack/Directory/cdesc-Directory.rinu[U:RDoc::NormalClass[iI"Directory:ETI"Rack::Directory;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[ I"MRack::Directory serves entries below the +root+ given, according to the ;TI"Qpath info of the Rack request. If a directory is found, the file's contents ;TI"Pwill be presented in an html based index. If a file is found, the env will ;TI"&be passed to the specified +app+.;To:RDoc::Markup::BlankLineo; ;[I"NIf +app+ is not specified, a Rack::Files of the same +root+ will be used.;T: @fileI"lib/rack/directory.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I" root;TI"R;T: publicFI"lib/rack/directory.rb;T[ U:RDoc::Constant[iI" DIR_FILE;TI"Rack::Directory::DIR_FILE;T; 0o;;[; @; 0@@cRDoc::NormalClass0U;[iI"DIR_PAGE_HEADER;TI"%Rack::Directory::DIR_PAGE_HEADER;T; 0o;;[; @; 0@@@%0U;[iI"DIR_PAGE_FOOTER;TI"%Rack::Directory::DIR_PAGE_FOOTER;T; 0o;;[; @; 0@@@%0U;[iI"FILESIZE_FORMAT;TI"%Rack::Directory::FILESIZE_FORMAT;T; 0o;;[o; ;[I"Stolen from Ramaze;T; @; 0@@@%0[[[I" class;T[[; [[I"new;T@[:protected[[: private[[I" instance;T[[; [[I" call;T@[I"check_bad_request;T@[I"check_forbidden;T@[I"entity_not_found;T@[I"filesize_format;T@[I"get;T@[I"list_directory;T@[I"list_path;T@[I" stat;T@[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I" Rack;TcRDoc::NormalModulePK% ]ºɀEdoc/rack-3.0.8/ri/Rack/Directory/DirectoryBody/cdesc-DirectoryBody.rinu[U:RDoc::NormalClass[iI"DirectoryBody:ETI"#Rack::Directory::DirectoryBody;TI"%Struct.new(:root, :path, :files);To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"HBody class for directory entries, showing an index page with links ;TI"to each file.;T: @fileI"lib/rack/directory.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[I" each;TI"lib/rack/directory.rb;T[; [[;[[I"DIR_FILE_escape;T@'[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Directory;TcRDoc::NormalClassPK% ]Y8jwxxCdoc/rack-3.0.8/ri/Rack/Directory/DirectoryBody/DIR_FILE_escape-i.rinu[U:RDoc::AnyMethod[iI"DIR_FILE_escape:ETI"3Rack::Directory::DirectoryBody#DIR_FILE_escape;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"6Escape each element in the array of html strings.;T: @fileI"lib/rack/directory.rb;T:0@omit_headings_from_table_of_contents_below000[I" (htmls);T@FI"DirectoryBody;TcRDoc::NormalClass00PK% ].558doc/rack-3.0.8/ri/Rack/Directory/DirectoryBody/each-i.rinu[U:RDoc::AnyMethod[iI" each:ETI"(Rack::Directory::DirectoryBody#each;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/directory.rb;T:0@omit_headings_from_table_of_contents_below00I"/DIR_PAGE_HEADER % [ show_path, show_path ];T[I"();T@ FI"DirectoryBody;TcRDoc::NormalClass00PK% ]*Ѧbb*doc/rack-3.0.8/ri/Rack/Directory/stat-i.rinu[U:RDoc::AnyMethod[iI" stat:ETI"Rack::Directory#stat;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"KFile::Stat for the given path, but return nil for missing/bad entries.;T: @fileI"lib/rack/directory.rb;T:0@omit_headings_from_table_of_contents_below000[I" (path);T@FI"Directory;TcRDoc::NormalClass00PK% ]">В*doc/rack-3.0.8/ri/Rack/Directory/root-i.rinu[U:RDoc::Attr[iI" root:ETI"Rack::Directory#root;TI"R;T: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"GThe root of the directory hierarchy. Only requests for files and ;TI"use Rack::Deflater, :if => lambda { |*, body| sum=0; body.each { |i| sum += i.length }; sum > 512 }). ;TI"wHowever, be aware that calling `body.each` inside the block will break cases where `body.each` is not idempotent, ;TI")such as when it is an +IO+ instance.;To;;[I":include ;T; [o; ; [I"ea list of content types that should be compressed. By default, all content types are compressed.;To;;[I" :sync ;T; [o; ; [I"ldetermines if the stream is going to be flushed after every chunk. Flushing after every chunk reduces ;TI"^latency for time-sensitive streaming applications, but hurts compression and throughput. ;TI"Defaults to +true+.;T: @fileI"lib/rack/deflater.rb;T:0@omit_headings_from_table_of_contents_below000[I"(app, options = {});T@+FI" Deflater;TcRDoc::NormalClass00PK% ]N!)doc/rack-3.0.8/ri/Rack/Deflater/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Deflater#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/deflater.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Deflater;TcRDoc::NormalClass00PK% ]*l 1doc/rack-3.0.8/ri/Rack/Deflater/cdesc-Deflater.rinu[U:RDoc::NormalClass[iI" Deflater:ETI"Rack::Deflater;TI" Object;To:RDoc::Markup::Document: @parts[o;;[ o:RDoc::Markup::Paragraph;[I"AThis middleware enables content encoding of http responses, ;TI")usually for purposes of compression.;To:RDoc::Markup::BlankLineo; ;[I"#Currently supported encodings:;T@o:RDoc::Markup::List: @type: BULLET: @items[o:RDoc::Markup::ListItem: @label0;[o; ;[I" gzip;To;;0;[o; ;[I"!identity (no transformation);T@o; ;[ I"FThis middleware automatically detects when encoding is supported ;TI"?and allowed. For example no encoding is made when a cache ;TI"Fdirective of 'no-transform' is present, when the response status ;TI"Ecode is one that doesn't allow an entity body, or when the body ;TI"is empty.;T@o; ;[I"INote that despite the name, Deflater does not support the +deflate+ ;TI"encoding.;T: @fileI"lib/rack/deflater.rb;T:0@omit_headings_from_table_of_contents_below0;0;0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/deflater.rb;T[:protected[[: private[[I" instance;T[[;[[I" call;T@9[;[[;[[I"should_deflate?;T@9[[U:RDoc::Context::Section[i0o;;[;0;0[@-I" Rack;TcRDoc::NormalModulePK% ]5' 3doc/rack-3.0.8/ri/Rack/Deflater/GzipStream/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"$Rack::Deflater::GzipStream::new;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I",Initialize the gzip stream. Arguments:;To:RDoc::Markup::List: @type: NOTE: @items[o:RDoc::Markup::ListItem: @label[I" body ;T; [o; ; [I"(Response body to compress with gzip;To;;[I" mtime ;T; [o; ; [I"8The modification time of the body, used to set the ;TI"*modification time in the gzip header.;To;;[I" sync ;T; [o; ; [I"=Whether to flush each gzip chunk as soon as it is ready.;T: @fileI"lib/rack/deflater.rb;T:0@omit_headings_from_table_of_contents_below000[I"(body, mtime, sync);T@&FI"GzipStream;TcRDoc::NormalClass00PK% ]$׷II5doc/rack-3.0.8/ri/Rack/Deflater/GzipStream/close-i.rinu[U:RDoc::AnyMethod[iI" close:ETI"%Rack::Deflater::GzipStream#close;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I")Close the original body if possible.;T: @fileI"lib/rack/deflater.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI"GzipStream;TcRDoc::NormalClass00PK% ]u>doc/rack-3.0.8/ri/Rack/Deflater/GzipStream/cdesc-GzipStream.rinu[U:RDoc::NormalClass[iI"GzipStream:ETI"Rack::Deflater::GzipStream;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"0Body class used for gzip encoded responses.;T: @fileI"lib/rack/deflater.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[U:RDoc::Constant[iI"BUFFER_LENGTH;TI".Rack::Deflater::GzipStream::BUFFER_LENGTH;T: public0o;;[; @; 0@@cRDoc::NormalClass0[[[I" class;T[[; [[I"new;TI"lib/rack/deflater.rb;T[:protected[[: private[[I" instance;T[[; [[I" close;T@$[I" each;T@$[I" write;T@$[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Deflater;T@PK% ] |1+^^5doc/rack-3.0.8/ri/Rack/Deflater/GzipStream/write-i.rinu[U:RDoc::AnyMethod[iI" write:ETI"%Rack::Deflater::GzipStream#write;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I":Call the block passed to #each with the gzipped data.;T: @fileI"lib/rack/deflater.rb;T:0@omit_headings_from_table_of_contents_below000[I" (data);T@FI"GzipStream;TcRDoc::NormalClass00PK% ]x{)ZZ4doc/rack-3.0.8/ri/Rack/Deflater/GzipStream/each-i.rinu[U:RDoc::AnyMethod[iI" each:ETI"$Rack::Deflater::GzipStream#each;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"6Yield gzip compressed strings to the given block.;T: @fileI"lib/rack/deflater.rb;T:0@omit_headings_from_table_of_contents_below000[I" (&block);T@FI"GzipStream;TcRDoc::NormalClass00PK% ]z_ll6doc/rack-3.0.8/ri/Rack/Deflater/should_deflate%3f-i.rinu[U:RDoc::AnyMethod[iI"should_deflate?:ETI"#Rack::Deflater#should_deflate?;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"+Whether the body should be compressed.;T: @fileI"lib/rack/deflater.rb;T:0@omit_headings_from_table_of_contents_below000[I"!(env, status, headers, body);T@FI" Deflater;TcRDoc::NormalClass00PK% ]~S/doc/rack-3.0.8/ri/Rack/Chunked/cdesc-Chunked.rinu[U:RDoc::NormalClass[iI" Chunked:ETI"Rack::Chunked;TI" Object;To:RDoc::Markup::Document: @parts[o;;[ o:RDoc::Markup::Paragraph;[I"JMiddleware that applies chunked transfer encoding to response bodies ;TI"@when the response does not include a content-length header.;To:RDoc::Markup::BlankLineo; ;[I"LThis supports the trailer response header to allow the use of trailing ;TI"Qheaders in the chunked encoding. However, using this requires you manually ;TI"Ispecify a response body that supports a +trailers+ method. Example:;T@o:RDoc::Markup::Verbatim;[I":[200, { 'trailer' => 'expires'}, ["Hello", "World"]] ;TI"# error raised ;TI" ;TI"body = ["Hello", "World"] ;TI"def body.trailers ;TI"& { 'expires' => Time.now.to_s } ;TI" end ;TI",[200, { 'trailer' => 'expires'}, body] ;TI"# No exception raised;T: @format0: @fileI"lib/rack/chunked.rb;T:0@omit_headings_from_table_of_contents_below0; 0;0[[[[I"Rack::Utils;To;;[; @#;0I"lib/rack/chunked.rb;T[[I" class;T[[: public[[I"new;T@+[:protected[[: private[[I" instance;T[[;[[I" call;T@+[I"chunkable_version?;T@+[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0;0[@#I" Rack;TcRDoc::NormalModulePK% ]Ĩ'doc/rack-3.0.8/ri/Rack/Chunked/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Chunked::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/chunked.rb;T:0@omit_headings_from_table_of_contents_below000[I" (app);T@ FI" Chunked;TcRDoc::NormalClass00PK% ]{(doc/rack-3.0.8/ri/Rack/Chunked/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Chunked#call;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"AIf the rack app returns a response that should have a body, ;TI"Dbut does not have content-length or transfer-encoding headers, ;TI":modify the response to use chunked transfer-encoding.;T: @fileI"lib/rack/chunked.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@FI" Chunked;TcRDoc::NormalClass00PK% ]ͯ{>>,doc/rack-3.0.8/ri/Rack/Chunked/Body/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Chunked::Body::new;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"+Store the response body to be chunked.;T: @fileI"lib/rack/chunked.rb;T:0@omit_headings_from_table_of_contents_below000[I" (body);T@FI" Body;TcRDoc::NormalClass00PK% ]nPP.doc/rack-3.0.8/ri/Rack/Chunked/Body/close-i.rinu[U:RDoc::AnyMethod[iI" close:ETI"Rack::Chunked::Body#close;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I">Close the response body if the response body supports it.;T: @fileI"lib/rack/chunked.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Body;TcRDoc::NormalClass00PK% ]8-doc/rack-3.0.8/ri/Rack/Chunked/Body/each-i.rinu[U:RDoc::AnyMethod[iI" each:ETI"Rack::Chunked::Body#each;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I":For each element yielded by the response body, yield ;TI"%the element in chunked encoding.;T: @fileI"lib/rack/chunked.rb;T:0@omit_headings_from_table_of_contents_below00I"[size, term, b, term].join;T[I" (&block);T@FI" Body;TcRDoc::NormalClass00PK% ]?1doc/rack-3.0.8/ri/Rack/Chunked/Body/cdesc-Body.rinu[U:RDoc::NormalClass[iI" Body:ETI"Rack::Chunked::Body;TI" Object;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"1A body wrapper that emits chunked responses.;T: @fileI"lib/rack/chunked.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[U:RDoc::Constant[iI" TERM;TI"Rack::Chunked::Body::TERM;T: public0o;;[; @; 0@@cRDoc::NormalClass0U; [iI" TAIL;TI"Rack::Chunked::Body::TAIL;T; 0o;;[; @; 0@@@0[[[I" class;T[[; [[I"new;TI"lib/rack/chunked.rb;T[:protected[[: private[[I" instance;T[[; [[I" close;T@*[I" each;T@*[;[[;[[I"yield_trailers;T@*[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Chunked;T@PK% ]9dd7doc/rack-3.0.8/ri/Rack/Chunked/Body/yield_trailers-i.rinu[U:RDoc::AnyMethod[iI"yield_trailers:ETI"'Rack::Chunked::Body#yield_trailers;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"?Do nothing as this class does not support trailer headers.;T: @fileI"lib/rack/chunked.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Body;TcRDoc::NormalClass00PK% ]K/Tii?doc/rack-3.0.8/ri/Rack/Chunked/TrailerBody/cdesc-TrailerBody.rinu[U:RDoc::NormalClass[iI"TrailerBody:ETI"Rack::Chunked::TrailerBody;TI"Rack::Chunked::Body;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[ I"CA body wrapper that emits chunked responses and also supports ;TI"Gsending Trailer headers. Note that the response body provided to ;TI"Binitialize must have a +trailers+ method that returns a hash ;TI"Dof trailer headers, and the rack response itself should have a ;TI"CTrailer header listing the headers that the +trailers+ method ;TI"will return.;T: @fileI"lib/rack/chunked.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[;[[I"yield_trailers;TI"lib/rack/chunked.rb;T[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Chunked;TcRDoc::NormalClassPK% ]tt>doc/rack-3.0.8/ri/Rack/Chunked/TrailerBody/yield_trailers-i.rinu[U:RDoc::AnyMethod[iI"yield_trailers:ETI".Rack::Chunked::TrailerBody#yield_trailers;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"+Yield strings for each trailer header.;T: @fileI"lib/rack/chunked.rb;T:0@omit_headings_from_table_of_contents_below00I""#{k}: #{v}\r\n";T[I"();T@FI"TrailerBody;TcRDoc::NormalClass00PK% ]Xctt8doc/rack-3.0.8/ri/Rack/Chunked/chunkable_version%3f-i.rinu[U:RDoc::AnyMethod[iI"chunkable_version?:ETI"%Rack::Chunked#chunkable_version?;TF: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"HWhether the HTTP version supports chunked encoding (HTTP 1.1 does).;T: @fileI"lib/rack/chunked.rb;T:0@omit_headings_from_table_of_contents_below000[I" (ver);T@FI" Chunked;TcRDoc::NormalClass00PK% ]>K$;;#doc/rack-3.0.8/ri/Rack/version-c.rinu[U:RDoc::AnyMethod[iI" version:ETI"Rack::version;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"2The Rack protocol version number implemented.;T: @fileI"lib/rack/version.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Rack;TcRDoc::NormalModule00PK% ]% (doc/rack-3.0.8/ri/Rack/Sendfile/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"Rack::Sendfile::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/sendfile.rb;T:0@omit_headings_from_table_of_contents_below000[I"*(app, variation = nil, mappings = []);T@ FI" Sendfile;TcRDoc::NormalClass00PK% ]6J771doc/rack-3.0.8/ri/Rack/Sendfile/cdesc-Sendfile.rinu[U:RDoc::NormalClass[iI" Sendfile:ETI"Rack::Sendfile;TI" Object;To:RDoc::Markup::Document: @parts[o;;[)S:RDoc::Markup::Heading: leveli: textI" Sendfile;To:RDoc::Markup::BlankLineo:RDoc::Markup::Paragraph;[ I"FThe Sendfile middleware intercepts responses whose body is being ;TI"Jserved from a file and replaces it with a server specific x-sendfile ;TI"Nheader. The web server is then responsible for writing the file contents ;TI"Mto the client. This can dramatically reduce the amount of work required ;TI"Pby the Ruby backend and takes advantage of the web server's optimized file ;TI"delivery code.;T@o; ;[ I"KIn order to take advantage of this middleware, the response body must ;TI"Jrespond to +to_path+ and the request must include an x-sendfile-type ;TI"Mheader. Rack::Files and other components implement +to_path+ so there's ;TI"Mrarely anything you need to do in your application. The x-sendfile-type ;TI"Nheader is typically set in your web servers configuration. The following ;TI"!sections attempt to document;T@S; ; i; I" Nginx;T@o; ;[I"ONginx supports the x-accel-redirect header. This is similar to x-sendfile ;TI"Jbut requires parts of the filesystem to be mapped into a private URL ;TI"hierarchy.;T@o; ;[I"LThe following example shows the Nginx configuration required to create ;TI"Ma private "/files/" area, enable x-accel-redirect, and pass the special ;TI"@x-sendfile-type and x-accel-mapping headers to the backend:;T@o:RDoc::Markup::Verbatim;[I"location ~ /files/(.*) { ;TI" internal; ;TI" alias /var/www/$1; ;TI"} ;TI" ;TI"location / { ;TI" proxy_redirect off; ;TI" ;TI"5 proxy_set_header Host $host; ;TI"< proxy_set_header X-Real-IP $remote_addr; ;TI"J proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; ;TI" ;TI"@ proxy_set_header x-sendfile-type x-accel-redirect; ;TI"A proxy_set_header x-accel-mapping /var/www/=/files/; ;TI" ;TI"2 proxy_pass http://127.0.0.1:8080/; ;TI"} ;T: @format0o; ;[ I"NNote that the x-sendfile-type header must be set exactly as shown above. ;TI"PThe x-accel-mapping header should specify the location on the file system, ;TI"Nfollowed by an equals sign (=), followed name of the private URL pattern ;TI"Kthat it maps to. The middleware performs a simple substitution on the ;TI"resulting path.;T@o; ;[I"SSee Also: https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile;T@S; ; i; I" lighttpd;T@o; ;[I"MLighttpd has supported some variation of the x-sendfile header for some ;TI"Ntime, although only recent version support x-sendfile in a reverse proxy ;TI"configuration.;T@o;;[I"&$HTTP["host"] == "example.com" { ;TI"% proxy-core.protocol = "http" ;TI", proxy-core.balancer = "round-robin" ;TI" proxy-core.backends = ( ;TI" "127.0.0.1:8000", ;TI" "127.0.0.1:8001", ;TI" ... ;TI" ) ;TI" ;TI"/ proxy-core.allow-x-sendfile = "enable" ;TI"' proxy-core.rewrite-request = ( ;TI"6 "x-sendfile-type" => (".*" => "x-sendfile") ;TI" ) ;TI" } ;T;0o; ;[I"JSee Also: http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModProxyCore;T@S; ; i; I" Apache;T@o; ;[I"Fx-sendfile is supported under Apache 2.x using a separate module:;T@o; ;[I"%https://tn123.org/mod_xsendfile/;T@o; ;[I"HOnce the module is compiled and installed, you can enable it using ;TI" XSendFile config directive:;T@o;;[I"2RequestHeader Set x-sendfile-type x-sendfile ;TI"/ProxyPassReverse / http://localhost:8001/ ;TI"XSendFile on ;T;0S; ; i; I"Mapping parameter;T@o; ;[ I"CThe third parameter allows for an overriding extension of the ;TI"Rx-accel-mapping header. Mappings should be provided in tuples of internal to ;TI"Oexternal. The internal values may contain regular expression syntax, they ;TI",will be matched with case indifference.;T: @fileI"lib/rack/sendfile.rb;T:0@omit_headings_from_table_of_contents_below0;0;0[[[[[I" class;T[[: public[[I"new;TI"lib/rack/sendfile.rb;T[:protected[[: private[[I" instance;T[[;[[I" call;T@[;[[;[[I"map_accel_path;T@[I"variation;T@[[U:RDoc::Context::Section[i0o;;[;0;0[@}I" Rack;TcRDoc::NormalModulePK% ]JC.doc/rack-3.0.8/ri/Rack/Sendfile/variation-i.rinu[U:RDoc::AnyMethod[iI"variation:ETI"Rack::Sendfile#variation;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/sendfile.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Sendfile;TcRDoc::NormalClass00PK% ]~)doc/rack-3.0.8/ri/Rack/Sendfile/call-i.rinu[U:RDoc::AnyMethod[iI" call:ETI"Rack::Sendfile#call;TF: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/sendfile.rb;T:0@omit_headings_from_table_of_contents_below000[I" (env);T@ FI" Sendfile;TcRDoc::NormalClass00PK% ]^  3doc/rack-3.0.8/ri/Rack/Sendfile/map_accel_path-i.rinu[U:RDoc::AnyMethod[iI"map_accel_path:ETI""Rack::Sendfile#map_accel_path;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"lib/rack/sendfile.rb;T:0@omit_headings_from_table_of_contents_below000[I"(env, path);T@ FI" Sendfile;TcRDoc::NormalClass00PK% ]q x99#doc/rack-3.0.8/ri/Rack/release-c.rinu[U:RDoc::AnyMethod[iI" release:ETI"Rack::release;TT: publico:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [I"0Return the Rack release as a dotted string.;T: @fileI"lib/rack/version.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Rack;TcRDoc::NormalModule00PK% ]!A@@7doc/rack-3.0.8/ri/Rack/Multipart/extract_multipart-c.rinu[U:RDoc::AnyMethod[iI"extract_multipart:ETI"'Rack::Multipart::extract_multipart;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/multipart.rb;T:0@omit_headings_from_table_of_contents_below000[I"9(request, params = Rack::Utils.default_query_parser);T@ FI"Multipart;TcRDoc::NormalModule00PK% ]3 3 3doc/rack-3.0.8/ri/Rack/Multipart/cdesc-Multipart.rinu[U:RDoc::NormalModule[iI"Multipart:ETI"Rack::Multipart;T0o:RDoc::Markup::Document: @parts[ o;;[o:RDoc::Markup::Paragraph;[I"5A multipart form data parser, adapted from IOWA.;To:RDoc::Markup::BlankLineo; ;[I".Ȼ=doc/rack-3.0.8/ri/Rack/Multipart/Parser/handle_mime_head-i.rinu[U:RDoc::AnyMethod[iI"handle_mime_head:ETI"-Rack::Multipart::Parser#handle_mime_head;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Parser;TcRDoc::NormalClass00PK% ]~z6doc/rack-3.0.8/ri/Rack/Multipart/Parser/read_data-i.rinu[U:RDoc::AnyMethod[iI"read_data:ETI"&Rack::Multipart::Parser#read_data;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"(io, outbuf);T@ FI" Parser;TcRDoc::NormalClass00PK% ]Q7}}7doc/rack-3.0.8/ri/Rack/Multipart/Parser/cdesc-Parser.rinu[U:RDoc::NormalClass[iI" Parser:ETI"Rack::Multipart::Parser;TI" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[ I" state;TI"R;T: publicFI"!lib/rack/multipart/parser.rb;T[ U:RDoc::Constant[iI" BUFSIZE;TI"%Rack::Multipart::Parser::BUFSIZE;T; 0o;;[; @; 0@@cRDoc::NormalClass0U; [iI"TEXT_PLAIN;TI"(Rack::Multipart::Parser::TEXT_PLAIN;T; 0o;;[; @; 0@@@0U; [iI"TEMPFILE_FACTORY;TI".Rack::Multipart::Parser::TEMPFILE_FACTORY;T; 0o;;[; @; 0@@@0U; [iI"MultipartInfo;TI"+Rack::Multipart::Parser::MultipartInfo;T; 0o;;[; @; 0@@@0U; [iI" EMPTY;TI"#Rack::Multipart::Parser::EMPTY;T; 0o;;[; @; 0@@@0U; [iI" CHARSET;TI"%Rack::Multipart::Parser::CHARSET;T; 0o;;[; @; 0@@@0[[[I" class;T[[; [[I"new;T@[I" parse;T@[I"parse_boundary;T@[:protected[[: private[[I" instance;T[[; [[I" parse;T@[I" result;T@[; [[;[[I"consume_boundary;T@[I" dequote;T@[I"get_filename;T@[I"handle_consume_token;T@[I"handle_empty_content!;T@[I"handle_fast_forward;T@[I"handle_mime_body;T@[I"handle_mime_head;T@[I"read_data;T@[I"tag_multipart_encoding;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Multipart;TcRDoc::NormalModulePK% ])R3doc/rack-3.0.8/ri/Rack/Multipart/Parser/result-i.rinu[U:RDoc::AnyMethod[iI" result:ETI"#Rack::Multipart::Parser#result;TF: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Parser;TcRDoc::NormalClass00PK% ]ɷDdoc/rack-3.0.8/ri/Rack/Multipart/Parser/BoundedIO/cdesc-BoundedIO.rinu[U:RDoc::NormalClass[iI"BoundedIO:ETI"'Rack::Multipart::Parser::BoundedIO;TI" Object;To:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[I"!lib/rack/multipart/parser.rb;TI"Rack::Multipart::Parser;TcRDoc::NormalClassPK% ]XmEECdoc/rack-3.0.8/ri/Rack/Multipart/Parser/tag_multipart_encoding-i.rinu[U:RDoc::AnyMethod[iI"tag_multipart_encoding:ETI"3Rack::Multipart::Parser#tag_multipart_encoding;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I")(filename, content_type, name, body);T@ FI" Parser;TcRDoc::NormalClass00PK% ]i4doc/rack-3.0.8/ri/Rack/Multipart/Parser/dequote-i.rinu[U:RDoc::AnyMethod[iI" dequote:ETI"$Rack::Multipart::Parser#dequote;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I" (str);T@ FI" Parser;TcRDoc::NormalClass00PK% ]+ =doc/rack-3.0.8/ri/Rack/Multipart/Parser/handle_mime_body-i.rinu[U:RDoc::AnyMethod[iI"handle_mime_body:ETI"-Rack::Multipart::Parser#handle_mime_body;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" Parser;TcRDoc::NormalClass00PK% ]q22=doc/rack-3.0.8/ri/Rack/Multipart/Parser/consume_boundary-i.rinu[U:RDoc::AnyMethod[iI"consume_boundary:ETI"-Rack::Multipart::Parser#consume_boundary;TF: privateo:RDoc::Markup::Document: @parts[o:RDoc::Markup::Paragraph; [ I">Scan until the we find the start or end of the boundary. ;TI"CIf we find it, return the appropriate symbol for the start or ;TI"Dend of the boundary. If we don't find the start or end of the ;TI"/boundary, clear the buffer and return nil.;T: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@FI" Parser;TcRDoc::NormalClass00PK% ]g**Edoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/on_mime_finish-i.rinu[U:RDoc::AnyMethod[iI"on_mime_finish:ETI"6Rack::Multipart::Parser::Collector#on_mime_finish;TF: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"(mime_index);T@ FI"Collector;TcRDoc::NormalClass00PK% ]3 :doc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI",Rack::Multipart::Parser::Collector::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"(tempfile);T@ FI"Collector;TcRDoc::NormalClass00PK% ]1f+//Cdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/on_mime_body-i.rinu[U:RDoc::AnyMethod[iI"on_mime_body:ETI"4Rack::Multipart::Parser::Collector#on_mime_body;TF: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"(mime_index, content);T@ FI"Collector;TcRDoc::NormalClass00PK% ]Dp''Hdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/MimePart/get_data-i.rinu[U:RDoc::AnyMethod[iI" get_data:ETI":Rack::Multipart::Parser::Collector::MimePart#get_data;TF: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below00I" data;T[I"();T@ FI" MimePart;TcRDoc::NormalClass00PK% ]/Ĉ00Ldoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/MimePart/cdesc-MimePart.rinu[U:RDoc::NormalClass[iI" MimePart:ETI"1Rack::Multipart::Parser::Collector::MimePart;TI">Struct.new(:body, :head, :filename, :content_type, :name);To:RDoc::Markup::Document: @parts[o;;[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[I" get_data;TI"!lib/rack/multipart/parser.rb;T[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"'Rack::Multipart::Parser::Collector;TcRDoc::NormalClassPK% ]4t,zzDdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/cdesc-Collector.rinu[U:RDoc::NormalClass[iI"Collector:ETI"'Rack::Multipart::Parser::Collector;TI" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[I"Enumerable;To;;[; @; 0I"!lib/rack/multipart/parser.rb;T[[I" class;T[[: public[[I"new;T@[:protected[[: private[[I" instance;T[[; [ [I" each;T@[I"on_mime_body;T@[I"on_mime_finish;T@[I"on_mime_head;T@[; [[; [[I"check_part_limits;T@[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Multipart::Parser;TcRDoc::NormalClassPK% ]:JJCdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/on_mime_head-i.rinu[U:RDoc::AnyMethod[iI"on_mime_head:ETI"4Rack::Multipart::Parser::Collector#on_mime_head;TF: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"5(mime_index, head, filename, content_type, name);T@ FI"Collector;TcRDoc::NormalClass00PK% ]c44Pdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/BufferPart/cdesc-BufferPart.rinu[U:RDoc::NormalClass[iI"BufferPart:ETI"3Rack::Multipart::Parser::Collector::BufferPart;TI"1Rack::Multipart::Parser::Collector::MimePart;To:RDoc::Markup::Document: @parts[o;;[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[I" close;TI"!lib/rack/multipart/parser.rb;T[I" file?;T@#[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"'Rack::Multipart::Parser::Collector;TcRDoc::NormalClassPK% ]NRIdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/BufferPart/file%3f-i.rinu[U:RDoc::AnyMethod[iI" file?:ETI"9Rack::Multipart::Parser::Collector::BufferPart#file?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"BufferPart;TcRDoc::NormalClass00PK% ]'Gdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/BufferPart/close-i.rinu[U:RDoc::AnyMethod[iI" close:ETI"9Rack::Multipart::Parser::Collector::BufferPart#close;TF: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"BufferPart;TcRDoc::NormalClass00PK% ]''Hdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/check_part_limits-i.rinu[U:RDoc::AnyMethod[iI"check_part_limits:ETI"9Rack::Multipart::Parser::Collector#check_part_limits;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"Collector;TcRDoc::NormalClass00PK% ] Kdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/TempfilePart/file%3f-i.rinu[U:RDoc::AnyMethod[iI" file?:ETI";Rack::Multipart::Parser::Collector::TempfilePart#file?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"TempfilePart;TcRDoc::NormalClass00PK% ]#FVIdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/TempfilePart/close-i.rinu[U:RDoc::AnyMethod[iI" close:ETI";Rack::Multipart::Parser::Collector::TempfilePart#close;TF: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"TempfilePart;TcRDoc::NormalClass00PK% ]88Tdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/TempfilePart/cdesc-TempfilePart.rinu[U:RDoc::NormalClass[iI"TempfilePart:ETI"5Rack::Multipart::Parser::Collector::TempfilePart;TI"1Rack::Multipart::Parser::Collector::MimePart;To:RDoc::Markup::Document: @parts[o;;[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[I" close;TI"!lib/rack/multipart/parser.rb;T[I" file?;T@#[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"'Rack::Multipart::Parser::Collector;TcRDoc::NormalClassPK% ];doc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/each-i.rinu[U:RDoc::AnyMethod[iI" each:ETI",Rack::Multipart::Parser::Collector#each;TF: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below00I" part;T[I"();T@ FI"Collector;TcRDoc::NormalClass00PK% ],42doc/rack-3.0.8/ri/Rack/Multipart/Parser/state-i.rinu[U:RDoc::Attr[iI" state:ETI""Rack::Multipart::Parser#state;TI"R;T: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below0F@ I"Rack::Multipart::Parser;TcRDoc::NormalClass0PK% ] \g79doc/rack-3.0.8/ri/Rack/Multipart/Parser/get_filename-i.rinu[U:RDoc::AnyMethod[iI"get_filename:ETI")Rack::Multipart::Parser#get_filename;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I" (head);T@ FI" Parser;TcRDoc::NormalClass00PK% ]{b2doc/rack-3.0.8/ri/Rack/Multipart/Parser/parse-i.rinu[U:RDoc::AnyMethod[iI" parse:ETI""Rack::Multipart::Parser#parse;TF: publico:RDoc::Markup::Document: @parts[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below000[I" (io);T@ FI" Parser;TcRDoc::NormalClass00PK% ]"DD5doc/rack-3.0.8/ri/Rack/Multipart/Error/cdesc-Error.rinu[U:RDoc::NormalClass[iI" Error:ETI"Rack::Multipart::Error;TI"StandardError;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"CBase class for multipart exceptions that do not subclass from ;TI"9other exception classes for backwards compatibility.;T: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Multipart;TcRDoc::NormalModulePK% ]󘾲--Mdoc/rack-3.0.8/ri/Rack/Multipart/EmptyContentError/cdesc-EmptyContentError.rinu[U:RDoc::NormalClass[iI"EmptyContentError:ETI"'Rack::Multipart::EmptyContentError;TI" EOFError;To:RDoc::Markup::Document: @parts[o;;[o:RDoc::Markup::Paragraph;[I"=Use specific error class when parsing multipart request ;TI"that ends early.;T: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Multipart;TcRDoc::NormalModulePK% ]WTs#885doc/rack-3.0.8/ri/Rack/Multipart/parse_multipart-c.rinu[U:RDoc::AnyMethod[iI"parse_multipart:ETI"%Rack::Multipart::parse_multipart;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/multipart.rb;T:0@omit_headings_from_table_of_contents_below000[I"5(env, params = Rack::Utils.default_query_parser);T@ FI"Multipart;TcRDoc::NormalModule00PK% ]Ydoc/rack-3.0.8/ri/Rack/Multipart/MultipartPartLimitError/cdesc-MultipartPartLimitError.rinu[U:RDoc::NormalClass[iI"MultipartPartLimitError:ETI"-Rack::Multipart::MultipartPartLimitError;TI"Errno::EMFILE;To:RDoc::Markup::Document: @parts[o;;[: @fileI"!lib/rack/multipart/parser.rb;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@I"Rack::Multipart;TcRDoc::NormalModulePK% ]@95doc/rack-3.0.8/ri/Rack/Multipart/build_multipart-c.rinu[U:RDoc::AnyMethod[iI"build_multipart:ETI"%Rack::Multipart::build_multipart;TT: publico:RDoc::Markup::Document: @parts[: @fileI"lib/rack/multipart.rb;T:0@omit_headings_from_table_of_contents_below000[I"(params, first = true);T@ FI"Multipart;TcRDoc::NormalModule00PK% ]],,Adoc/rack-3.0.8/ri/Rack/Multipart/Generator/content_for_other-i.rinu[U:RDoc::AnyMethod[iI"content_for_other:ETI"1Rack::Multipart::Generator#content_for_other;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"$lib/rack/multipart/generator.rb;T:0@omit_headings_from_table_of_contents_below000[I"(file, name);T@ FI"Generator;TcRDoc::NormalClass00PK% ]-hu<doc/rack-3.0.8/ri/Rack/Multipart/Generator/multipart%3f-i.rinu[U:RDoc::AnyMethod[iI"multipart?:ETI"*Rack::Multipart::Generator#multipart?;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"$lib/rack/multipart/generator.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"Generator;TcRDoc::NormalClass00PK% ]%66Ddoc/rack-3.0.8/ri/Rack/Multipart/Generator/content_for_tempfile-i.rinu[U:RDoc::AnyMethod[iI"content_for_tempfile:ETI"4Rack::Multipart::Generator#content_for_tempfile;TF: privateo:RDoc::Markup::Document: @parts[: @fileI"$lib/rack/multipart/generator.rb;T:0@omit_headings_from_table_of_contents_below000[I"(io, file, name);T@ FI"Generator;TcRDoc::NormalClass00PK% ]n 3doc/rack-3.0.8/ri/Rack/Multipart/Generator/new-c.rinu[U:RDoc::AnyMethod[iI"new:ETI"$Rack::Multipart::Generator::new;TT: publico:RDoc::Markup::Document: @parts[: @fileI"$lib/rack/multipart/generator.rb;T:0@omit_headings_from_table_of_contents_below000[I"(params, first = true);T@ FI"Generator;TcRDoc::NormalClass00PK% ]#;4doc/rack-3.0.8/ri/Rack/Multipart/Generator/dump-i.rinu[U:RDoc::AnyMethod[iI" dump:ETI"$Rack::Multipart::Generator#dump;TF: publico:RDoc::Markup::Document: @parts[: @fileI"$lib/rack/multipart/generator.rb;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI"Generator;TcRDoc::NormalClass00PK% ](D= have nil values. ({#2059}[https://github.com/rack/rack/pull/2059], {@jeremyevans}[https://github.com/jeremyevans]);TS; ; i; I"[3.0.6.1] - 2023-03-13;To; ;;;[o;;0;[o; ;[I"3[CVE-2023-27539] Avoid ReDoS in header parsing;TS; ; i; I"[3.0.6] - 2023-03-13;To; ;;;[o;;0;[o; ;[I"Add QueryParser#missing_value for handling missing values + tests. ({#2052}[https://github.com/rack/rack/pull/2052], {@ioquatix}[https://github.com/ioquatix]);TS; ; i; I"[3.0.5] - 2023-03-13;To; ;;;[o;;0;[o; ;[I"Split form/query parsing into two steps. ({#2038}[https://github.com/rack/rack/pull/2038], {@matthewd}[https://github.com/matthewd]);TS; ; i; I"[3.0.4.1] - 2023-03-02;To; ;;;[o;;0;[o; ;[I"O[CVE-2023-27530] Introduce multipart_total_part_limit to limit total parts;TS; ; i; I"[3.0.4.1] - 2023-01-17;To; ;;;[o;;0;[o; ;[I"A[CVE-2022-44571] Fix ReDoS vulnerability in multipart parser;To;;0;[o; ;[I">[CVE-2022-44570] Fix ReDoS in Rack::Utils.get_byte_ranges;To;;0;[o; ;[I"J[CVE-2022-44572] Forbid control characters in attributes (also ReDoS);TS; ; i; I"[3.0.4] - 2023-01-17;To; ;;;[o;;0;[o; ;[I"Rack::Request#POST should consistently raise errors. Cache errors that occur when invoking Rack::Request#POST so they can be raised again later. ({#2010}[https://github.com/rack/rack/pull/2010], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Fix Rack::Lint error message for HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH. ({#2007}[https://github.com/rack/rack/pull/2007], {@byroot}[https://github.com/byroot]);To;;0;[o; ;[I"Extend Rack::MethodOverride to handle QueryParser::ParamsTooDeepError error. ({#2006}[https://github.com/rack/rack/pull/2006], {@byroot}[https://github.com/byroot]);TS; ; i; I"[3.0.3] - 2022-12-27;TS; ; i; I" Fixed;To; ;;;[o;;0;[o; ;[I"Rack::URLMap uses non-deprecated form of Regexp.new. ({#1998}[https://github.com/rack/rack/pull/1998], {@weizheheng}[https://github.com/weizheheng]);TS; ; i; I"[3.0.2] - 2022-12-05;TS; ; i; I" Fixed;To; ;;;[o;;0;[o; ;[I"hUtils.build_nested_query URL-encodes nested field names including the square brackets.;To;;0;[o; ;[I"Allow Rack::Response to pass through streaming bodies. ({#1993}[https://github.com/rack/rack/pull/1993], {@ioquatix}[https://github.com/ioquatix]);TS; ; i; I"[3.0.1] - 2022-11-18;TS; ; i; I" Fixed;To; ;;;[o;;0;[o; ;[I"qMethodOverride does not look for an override if a request does not include form/parseable data.;To;;0;[o; ;[I"Rack::Lint::Wrapper correctly handles respond_to? with to_ary, each, call and to_path, forwarding to the body. ({#1981}[https://github.com/rack/rack/pull/1981], {@ioquatix}[https://github.com/ioquatix]);TS; ; i; I"[3.0.0] - 2022-09-06;To; ;;;[o;;0;[o; ;[I"No changes;TS; ; i; I"[3.0.0.rc1] - 2022-09-04;TS; ; i; I"SPEC Changes;To; ;;;[o;;0;[o; ;[I"ZStream argument must implement << https://github.com/rack/rack/pull/1959;To;;0;[o; ;[I"gclose may be called on rack.input https://github.com/rack/rack/pull/1956;To;;0;[o; ;[I"rack.response_finished may be used for executing code after the response has been finished https://github.com/rack/rack/pull/1952;TS; ; i; I"[3.0.0.beta1] - 2022-08-08;TS; ; i; I" Security;To; ;;;[o;;0;[o; ;[I"Do not use semicolon as GET parameter separator. ({#1733}[https://github.com/rack/rack/pull/1733], {@jeremyevans}[https://github.com/jeremyevans]);TS; ; i; I"SPEC Changes;To; ;;;[o;;0;[o; ;[I"+Response array must now be non-frozen.;To;;0;[o; ;[I"VResponse status must now be an integer greater than or equal to 100.;To;;0;[o; ;[I"@Response headers must now be an unfrozen hash.;To;;0;[o; ;[I"EResponse header keys can no longer include uppercase characters.;To;;0;[o; ;[I"Response header values can be an Array to handle multiple values (and no longer supports \n encoded headers).;To;;0;[o; ;[I"Response body can now respond to #call (streaming body) instead of #each (enumerable body), for the equivalent of response hijacking in previous versions.;To;;0;[o; ;[I"Middleware must no longer call #each on the body, but they can call #to_ary on the body if it responds to #to_ary.;To;;0;[o; ;[I"Drack.input is no longer required to be rewindable.;To;;0;[o; ;[I"rack.multithread/rack.multiprocess/rack.run_once/rack.version are no longer required environment keys.;To;;0;[o; ;[I"tSERVER_PROTOCOL is now a required environment key, matching the HTTP protocol used in the request.;To;;0;[o; ;[I"zrack.hijack? (partial hijack) and rack.hijack (full hijack) are now independently optional.;To;;0;[o; ;[I"=rack.hijack_io has been removed completely.;To;;0;[o; ;[I"rack.response_finished is an optional environment key which contains an array of callable objects that must accept #call(env, status, headers, error) and are invoked after the response is finished (either successfully or unsuccessfully).;To;;0;[o; ;[I"~It is okay to call #close on rack.input to indicate that you no longer need or care about the input.;To;;0;[o; ;[I"tThe stream argument supplied to the streaming body and hijack must support #<< for writing output.;TS; ; i; I" Removed;To; ;;;[ o;;0;[o; ;[I""Remove rack.multithread/rack.multiprocess/rack.run_once. These variables generally come too late to be useful. ({#1720}[https://github.com/rack/rack/pull/1720], {@ioquatix}[https://github.com/ioquatix], {@jeremyevans}[https://github.com/jeremyevans]));To;;0;[o; ;[I"hRemove deprecated Rack::Request::SCHEME_WHITELIST. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Remove internal cookie deletion using pattern matching, there are very few practical cases where it would be useful and browsers handle it correctly without us doing anything special. ({#1844}[https://github.com/rack/rack/pull/1844], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Remove rack.version as it comes too late to be useful. ({#1938}[https://github.com/rack/rack/pull/1938], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Extract rackup command, Rack::Server, Rack::Handler and related code into a separate gem. ({#1937}[https://github.com/rack/rack/pull/1937], {@ioquatix}[https://github.com/ioquatix]);TS; ; i; I" Added;To; ;;;[o;;0;[o; ;[I"yRack::Headers added to support lower-case header keys. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Rack::Utils#set_cookie_header now supports escape_key: false to avoid key escaping. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"]Rack::RewindableInput supports size. ({@ahorek}[https://github.com/ahorek]);To;;0;[o; ;[I"Rack::RewindableInput::Middleware added for making rack.input rewindable. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"The RFC 7239 Forwarded header is now supported and considered by default when looking for information on forwarding, falling back to the X-Forwarded-* headers. Rack::Request.forwarded_priority accessor has been added for configuring the priority of which header to check. ({#1423}[https://github.com/rack/rack/issues/1423], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Allow response headers to contain array of values. ({#1598}[https://github.com/rack/rack/issues/1598], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Support callable body for explicit streaming support and clarify streaming response body behaviour. ({#1745}[https://github.com/rack/rack/pull/1745], {@ioquatix}[https://github.com/ioquatix], {#1748}[https://github.com/rack/rack/pull/1748], {@wjordan}[https://github.com/wjordan]);To;;0;[o; ;[I"Allow Rack::Builder#run to take a block instead of an argument. ({#1942}[https://github.com/rack/rack/pull/1942], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Add rack.response_finished to Rack::Lint. ({#1802}[https://github.com/rack/rack/pull/1802], {@BlakeWilliams}[https://github.com/BlakeWilliams], {#1952}[https://github.com/rack/rack/pull/1952], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"The stream argument must implement #<<. ({#1959}[https://github.com/rack/rack/pull/1959], {@ioquatix}[https://github.com/ioquatix]);TS; ; i; I" Changed;To; ;;;[o;;0;[o; ;[I"BREAKING CHANGE: Require status to be an Integer. ({#1662}[https://github.com/rack/rack/pull/1662], {@olleolleolle}[https://github.com/olleolleolle]);To;;0;[o; ;[I"BREAKING CHANGE: Query parsing now treats parameters without = as having the empty string value instead of nil value, to conform to the URL spec. ({#1696}[https://github.com/rack/rack/issues/1696], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Relax validations around Rack::Request#host and Rack::Request#hostname. ({#1606}[https://github.com/rack/rack/issues/1606], {@pvande}[https://github.com/pvande]);To;;0;[o; ;[I"Removed antiquated handlers: FCGI, LSWS, SCGI, Thin. ({#1658}[https://github.com/rack/rack/pull/1658], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Removed options from Rack::Builder.parse_file and Rack::Builder.load_file. ({#1663}[https://github.com/rack/rack/pull/1663], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Rack::HTTP_VERSION has been removed and the HTTP_VERSION env setting is no longer set in the CGI and Webrick handlers. ({#970}[https://github.com/rack/rack/issues/970], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Rack::Request#[] and #[]= now warn even in non-verbose mode. ({#1277}[https://github.com/rack/rack/issues/1277], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Decrease default allowed parameter recursion level from 100 to 32. ({#1640}[https://github.com/rack/rack/issues/1640], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Attempting to parse a multipart response with an empty body now raises Rack::Multipart::EmptyContentError. ({#1603}[https://github.com/rack/rack/issues/1603], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Rack::Utils.secure_compare uses OpenSSL's faster implementation if available. ({#1711}[https://github.com/rack/rack/pull/1711], {@bdewater}[https://github.com/bdewater]);To;;0;[o; ;[I"Rack::Request#POST now caches an empty hash if input content type is not parseable. ({#749}[https://github.com/rack/rack/pull/749], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"BREAKING CHANGE: Updated trusted_proxy? to match full 127.0.0.0/8 network. ({#1781}[https://github.com/rack/rack/pull/1781], {@snbloch}[https://github.com/snbloch]);To;;0;[o; ;[I"Explicitly deprecate Rack::File which was an alias for Rack::Files. ({#1811}[https://github.com/rack/rack/pull/1720], {@ioquatix}[https://github.com/ioquatix]).;To;;0;[o; ;[I"Moved Rack::Session into {separate gem}[https://github.com/rack/rack-session]. ({#1805}[https://github.com/rack/rack/pull/1805], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"rackup -D option to daemonizes no longer changes the working directory to the root. ({#1813}[https://github.com/rack/rack/pull/1813], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"~The x-forwarded-proto header is now considered before the x-forwarded-scheme header for determining the forwarded protocol. Rack::Request.x_forwarded_proto_priority accessor has been added for configuring the priority of which header to check. ({#1809}[https://github.com/rack/rack/issues/1809], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"vRack::Request.forwarded_authority (and methods that call it, such as host) now returns the last authority in the forwarded header, instead of the first, as earlier forwarded authorities can be forged by clients. This restores the Rack 2.1 behavior. ({#1829}[https://github.com/rack/rack/issues/1809], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"$Use lower case cookie attributes when creating cookies, and fold cookie attributes to lower case when reading cookies (specifically impacting secure and httponly attributes). ({#1849}[https://github.com/rack/rack/pull/1849], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"LThe response array must now be mutable (non-frozen) so middleware can modify it without allocating a new Array,therefore reducing object allocations. ({#1887}[https://github.com/rack/rack/pull/1887], {#1927}[https://github.com/rack/rack/pull/1927], {@amatsuda}[https://github.com/amatsuda], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"rack.hijack? (partial hijack) and rack.hijack (full hijack) are now independently optional. rack.hijack_io is no longer required/specified. ({#1939}[https://github.com/rack/rack/pull/1939], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Allow calling close on rack.input. ({#1956}[https://github.com/rack/rack/pull/1956], {@ioquatix}[https://github.com/ioquatix]);TS; ; i; I" Fixed;To; ;;;[ o;;0;[o; ;[I"Make Rack::MockResponse handle non-hash headers. ({#1629}[https://github.com/rack/rack/issues/1629], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"TempfileReaper now deletes temp files if application raises an exception. ({#1679}[https://github.com/rack/rack/issues/1679], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Handle cookies with values that end in '=' ({#1645}[https://github.com/rack/rack/pull/1645], {@lukaso}[https://github.com/lukaso]);To;;0;[o; ;[I"wMake Rack::NullLogger respond to #fatal! {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Fix multipart filename generation for filenames that contain spaces. Encode spaces as "%20" instead of "+" which will be decoded properly by the multipart parser. ({#1736}[https://github.com/rack/rack/pull/1645], {@muirdm}[https://github.com/muirdm]);To;;0;[o; ;[I"?Rack::Request#scheme returns ws or wss when one of the X-Forwarded-Scheme / X-Forwarded-Proto headers is set to ws or wss, respectively. ({#1730}[https://github.com/rack/rack/issues/1730], {@erwanst}[https://github.com/erwanst]);TS; ; i; I"[2.2.4] - 2022-06-30;To; ;;;[o;;0;[o; ;[I"Better support for lower case headers in Rack::ETag middleware. ({#1919}[https://github.com/rack/rack/pull/1919], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Use custom exception on params too deep error. ({#1838}[https://github.com/rack/rack/pull/1838], {@simi}[https://github.com/simi]);TS; ; i; I"[2.2.3.1] - 2022-05-27;To; ;;;[o;;0;[o; ;[I"?[CVE-2022-30123] Fix shell escaping issue in Common Logger;To;;0;[o; ;[I"A[CVE-2022-30122] Restrict parsing of broken MIME attachments;TS; ; i; I"[2.2.3] - 2020-06-15;TS; ; i; I" Security;To; ;;;[o;;0;[o; ;[I"![{CVE-2020-8184}[https://nvd.nist.gov/vuln/detail/CVE-2020-8184]] Do not allow percent-encoded cookie name to override existing cookie names. BREAKING CHANGE: Accessing cookie names that require URL encoding with decoded name no longer works. ({@fletchto99}[https://github.com/fletchto99]);TS; ; i; I"[2.2.2] - 2020-02-11;TS; ; i; I" Fixed;To; ;;;[ o;;0;[o; ;[I"Fix incorrect Rack::Request#host value. ({#1591}[https://github.com/rack/rack/pull/1591], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Revert Rack::Handler::Thin implementation. ({#1583}[https://github.com/rack/rack/pull/1583], {@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Double assignment is still needed to prevent an "unused variable" warning. ({#1589}[https://github.com/rack/rack/pull/1589], {@kamipo}[https://github.com/kamipo]);To;;0;[o; ;[I"Fix to handle same_site option for session pool. ({#1587}[https://github.com/rack/rack/pull/1587], {@kamipo}[https://github.com/kamipo]);TS; ; i; I"[2.2.1] - 2020-02-09;TS; ; i; I" Fixed;To; ;;;[o;;0;[o; ;[I"Rework Rack::Request#ip to handle empty forwarded_for. ({#1577}[https://github.com/rack/rack/pull/1577], {@ioquatix}[https://github.com/ioquatix]);TS; ; i; I"[2.2.0] - 2020-02-08;TS; ; i; I"SPEC Changes;To; ;;;[ o;;0;[o; ;[I"rack.session request environment entry must respond to to_hash and return unfrozen Hash. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"[Request environment cannot be frozen. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"CGI values in the request environment with non-ASCII characters must use ASCII-8BIT encoding. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Improve SPEC/lint relating to SERVER_NAME, SERVER_PORT and HTTP_HOST. ({#1561}[https://github.com/rack/rack/pull/1561], {@ioquatix}[https://github.com/ioquatix]);TS; ; i; I" Added;To; ;;;[o;;0;[o; ;[I"rackup supports multiple -r options and will require all arguments. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Server supports an array of paths to require for the :require option. ({@khotta}[https://github.com/khotta]);To;;0;[o; ;[I"gFiles supports multipart range requests. ({@fatkodima}[https://github.com/fatkodima]);To;;0;[o; ;[I"Multipart::UploadedFile supports an IO-like object instead of using the filesystem, using :filename and :io options. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Multipart::UploadedFile supports keyword arguments :path, :content_type, and :binary in addition to positional arguments. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Static supports a :cascade option for calling the app if there is no matching file. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"fSession::Abstract::SessionHash#dig. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Response.[] and MockResponse.[] for creating instances using status, headers, and body. ({@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Convenient cache and content type methods for Rack::Response. ({#1555}[https://github.com/rack/rack/pull/1555], {@ioquatix}[https://github.com/ioquatix]);TS; ; i; I" Changed;To; ;;;[o;;0;[o; ;[I"mRequest#params no longer rescues EOFError. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Directory uses a streaming approach, significantly improving time to first byte for large directories. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Directory no longer includes a Parent directory link in the root directory index. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"QueryParser#parse_nested_query uses original backtrace when reraising exception with new class. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"ConditionalGet follows RFC 7232 precedence if both If-None-Match and If-Modified-Since headers are provided. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"|.ru files supports the frozen-string-literal magic comment. ({@eregon}[https://github.com/eregon]);To;;0;[o; ;[I"Rely on autoload to load constants instead of requiring internal files, make sure to require 'rack' and not just 'rack/...'. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I" BREAKING CHANGE: Etag will continue sending ETag even if the response should not be cached. Streaming no longer works without a workaround, see {#1619}[https://github.com/rack/rack/issues/1619#issuecomment-848460528]. ({@henm}[https://github.com/henm]);To;;0;[o; ;[I"Request#host_with_port no longer includes a colon for a missing or empty port. ({@AlexWayfer}[https://github.com/AlexWayfer]);To;;0;[o; ;[I"yAll handlers uses keywords arguments instead of an options hash argument. ({@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Files handling of range requests no longer return a body that supports to_path, to ensure range requests are handled correctly. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Multipart::Generator only includes Content-Length for files with paths, and Content-Disposition filename if the UploadedFile instance has one. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Request#ssl? is true for the wss scheme (secure websockets). ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Rack::HeaderHash is memoized by default. ({#1549}[https://github.com/rack/rack/pull/1549], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Rack::Directory allow directory traversal inside root directory. ({#1417}[https://github.com/rack/rack/pull/1417], {@ThomasSevestre}[https://github.com/ThomasSevestre]);To;;0;[o; ;[I"Sort encodings by server preference. ({#1184}[https://github.com/rack/rack/pull/1184], {@ioquatix}[https://github.com/ioquatix], {@wjordan}[https://github.com/wjordan]);To;;0;[o; ;[I"}Rework host/hostname/authority implementation in Rack::Request. #host and #host_with_port have been changed to correctly return IPv6 addresses formatted with square brackets, as defined by {RFC3986}[https://tools.ietf.org/html/rfc3986#section-3.2.2]. ({#1561}[https://github.com/rack/rack/pull/1561], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Rack::Builder parsing options on first #\ line is deprecated. ({#1574}[https://github.com/rack/rack/pull/1574], {@ioquatix}[https://github.com/ioquatix]);TS; ; i; I" Removed;To; ;;;[ o;;0;[o; ;[I"}Directory#path as it was not used and always returned nil. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"BodyProxy#each as it was only needed to work around a bug in Ruby <1.9.3. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"URLMap::INFINITY and URLMap::NEGATIVE_INFINITY, in favor of Float::INFINITY. ({@ch1c0t}[https://github.com/ch1c0t]);To;;0;[o; ;[I"Deprecation of Rack::File. It will be deprecated again in rack 2.2 or 3.0. ({@rafaelfranca}[https://github.com/rafaelfranca]);To;;0;[o; ;[I"\Support for Ruby 2.2 as it is well past EOL. ({@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Remove Rack::Files#response_body as the implementation was broken. ({#1153}[https://github.com/rack/rack/pull/1153], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Remove SERVER_ADDR which was never part of the original SPEC. ({#1573}[https://github.com/rack/rack/pull/1573], {@ioquatix}[https://github.com/ioquatix]);TS; ; i; I" Fixed;To; ;;;[o;;0;[o; ;[I"Directory correctly handles root paths containing glob metacharacters. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Cascade uses a new response object for each call if initialized with no apps. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"BodyProxy correctly delegates keyword arguments to the body object on Ruby 2.7+. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"BodyProxy#method correctly handles methods delegated to the body object. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Request#host and Request#host_with_port handle IPv6 addresses correctly. ({@AlexWayfer}[https://github.com/AlexWayfer]);To;;0;[o; ;[I"Lint checks when response hijacking that rack.hijack is called with a valid object. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Response#write correctly updates Content-Length if initialized with a body. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"qCommonLogger includes SCRIPT_NAME when logging. ({@Erol}[https://github.com/Erol]);To;;0;[o; ;[I"Utils.parse_nested_query correctly handles empty queries, using an empty instance of the params class instead of a hash. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"`Directory correctly escapes paths in links. ({@yous}[https://github.com/yous]);To;;0;[o; ;[I"Request#delete_cookie and related Utils methods handle :domain and :path options in same call. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Request#delete_cookie and related Utils methods do an exact match on :domain and :path options. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Static no longer adds headers when a gzipped file request has a 304 response. ({@chooh}[https://github.com/chooh]);To;;0;[o; ;[I"ContentLength sets Content-Length response header even for bodies not responding to to_ary. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"Thin handler supports options passed directly to Thin::Controllers::Controller. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"yWEBrick handler no longer ignores :BindAddress option. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"lShowExceptions handles invalid POST data. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"~Basic authentication requires a password, even if the password is empty. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"{Lint checks response is array with 3 elements, per SPEC. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"bSupport for using :SSLEnable option when using WEBrick handler. (Gregor Melhorn);To;;0;[o; ;[I"fClose response body after buffering it when buffering. ({@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"iOnly accept ; as delimiter when parsing cookies. ({@mrageh}[https://github.com/mrageh]);To;;0;[o; ;[I"qUtils::HeaderHash#clear clears the name mapping as well. ({@raxoft}[https://github.com/raxoft]);To;;0;[o; ;[I"Support for passing nil Rack::Files.new, which notably fixes Rails' current ActiveStorage::FileServer implementation. ({@ioquatix}[https://github.com/ioquatix]);TS; ; i; I"Documentation;To; ;;;[o;;0;[o; ;[I">CHANGELOG updates. ({@aupajo}[https://github.com/aupajo]);To;;0;[o; ;[I"RAdded {CONTRIBUTING}[CONTRIBUTING.md]. ({@dblock}[https://github.com/dblock]);TS; ; i; I"[2.0.9] - 2020-02-08;To; ;;;[o;;0;[o; ;[I"oHandle case where session id key is requested but missing ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"vRestore support for code relying on SessionId#to_s. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"hAdd support for SameSite=None cookie value. ({@hennikul}[https://github.com/hennikul]);TS; ; i; I"[2.1.2] - 2020-01-27;To; ;;;[ o;;0;[o; ;[I"rFix multipart parser for some files to prevent denial of service ({@aiomaster}[https://github.com/aiomaster]);To;;0;[o; ;[I"eFix Rack::Builder#use with keyword arguments ({@kamipo}[https://github.com/kamipo]);To;;0;[o; ;[I"mSkip deflating in Rack::Deflater if Content-Length is 0 ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"jRemove SessionHash#transform_keys, no longer needed ({@pavel}[https://github.com/pavel]);To;;0;[o; ;[I"hAdd to_hash to wrap Hash and Session classes ({@oleh-demyanyuk}[https://github.com/oleh-demyanyuk]);To;;0;[o; ;[I"oHandle case where session id key is requested but missing ({@jeremyevans}[https://github.com/jeremyevans]);TS; ; i; I"[2.1.1] - 2020-01-12;To; ;;;[o;;0;[o; ;[I"Remove Rack::Chunked from Rack::Server default middleware. ({#1475}[https://github.com/rack/rack/pull/1475], {@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"vRestore support for code relying on SessionId#to_s. ({@jeremyevans}[https://github.com/jeremyevans]);TS; ; i; I"[2.1.0] - 2020-01-10;TS; ; i; I" Added;To; ;;;[o;;0;[o; ;[I"hAdd support for SameSite=None cookie value. ({@hennikul}[https://github.com/hennikul]);To;;0;[o; ;[I"JAdd trailer headers. ({@eileencodes}[https://github.com/eileencodes]);To;;0;[o; ;[I"KAdd MIME Types for video streaming. ({@styd}[https://github.com/styd]);To;;0;[o; ;[I"KAdd MIME Type for WASM. ({@buildrtech}[https://github.com/buildrtech]);To;;0;[o; ;[I"\Add Early Hints(103) to status codes. ({@egtra}[https://github.com/egtra]);To;;0;[o; ;[I"^Add Too Early(425) to status codes. ({@y-yagi}[(https://github.com/y-yagi)]);To;;0;[o; ;[I"mAdd Bandwidth Limit Exceeded(509) to status codes. ({@CJKinni}[https://github.com/CJKinni]);To;;0;[o; ;[I"cAdd method for custom ip_filter. ({@svcastaneda}[https://github.com/svcastaneda]);To;;0;[o; ;[I"pAdd boot-time profiling capabilities to rackup. ({@tenderlove}[https://github.com/tenderlove]);To;;0;[o; ;[I"qAdd multi mapping support for X-Accel-Mappings header. ({@yoshuki}[https://github.com/yoshuki]);To;;0;[o; ;[I"TAdd sync: false option to Rack::Deflater. (Eric Wong);To;;0;[o; ;[I"Add Builder#freeze_app to freeze application and all middleware instances. ({@jeremyevans}[https://github.com/jeremyevans]);To;;0;[o; ;[I"tAdd API to extract cookies from Rack::MockResponse. ({@petercline}[https://github.com/petercline]);TS; ; i; I" Changed;To; ;;;[o;;0;[o; ;[I"[Don't propagate nil values from middleware. ({@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"sLazily initialize the response body and only buffer it if required. ({@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"oFix deflater zlib buffer errors on empty body part. ({@felixbuenemann}[https://github.com/felixbuenemann]);To;;0;[o; ;[I"hSet X-Accel-Redirect to percent-encoded path. ({@diskkid}[https://github.com/diskkid]);To;;0;[o; ;[I"eRemove unnecessary buffer growing when parsing multipart. ({@tainoe}[https://github.com/tainoe]);To;;0;[o; ;[I"xExpand the root path in Rack::Static upon initialization. ({@rosenfeld}[https://github.com/rosenfeld]);To;;0;[o; ;[I"aMake ShowExceptions work with binary data. ({@axyjo}[https://github.com/axyjo]);To;;0;[o; ;[I"`Use buffer string when parsing multipart requests. ({@janko-m}[https://github.com/janko-m]);To;;0;[o; ;[I"hSupport optional UTF-8 Byte Order Mark (BOM) in config.ru. ({@mikegee}[https://github.com/mikegee]);To;;0;[o; ;[I"kHandle X-Forwarded-For with optional port. ({@dpritchett}[https://github.com/dpritchett]);To;;0;[o; ;[I"wUse Time#httpdate format for Expires, as proposed by RFC 7231. ({@nanaya}[https://github.com/nanaya]);To;;0;[o; ;[I"Make Utils.status_code raise an error when the status symbol is invalid instead of 500. ({@adambutler}[https://github.com/adambutler]);To;;0;[o; ;[I"\Rename Request::SCHEME_WHITELIST to Request::ALLOWED_SCHEMES.;To;;0;[o; ;[I"Make Multipart::Parser.get_filename accept files with + in their name. ({@lucaskanashiro}[https://github.com/lucaskanashiro]);To;;0;[o; ;[I"\Add Falcon to the default handler fallbacks. ({@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"Update codebase to avoid string mutations in preparation for frozen_string_literals. ({@pat}[https://github.com/pat]);To;;0;[o; ;[I"Change MockRequest#env_for to rely on the input optionally responding to #size instead of #length. ({@janko}[https://github.com/janko]);To;;0;[o; ;[I"Rename Rack::File -> Rack::Files and add deprecation notice. ({@postmodern}[https://github.com/postmodern]);To;;0;[o; ;[I"gPrefer Base64 “strict encoding” for Base64 cookies. ({@ioquatix}[https://github.com/ioquatix]);TS; ; i; I" Removed;To; ;;;[o;;0;[o; ;[I"mBREAKING CHANGE: Remove to_ary from Response ({@tenderlove}[https://github.com/tenderlove]);To;;0;[o; ;[I"Deprecate Rack::Session::Memcache in favor of Rack::Session::Dalli from dalli gem ({@fatkodima}[https://github.com/fatkodima]);TS; ; i; I" Fixed;To; ;;;[o;;0;[o; ;[I"WEliminate warnings for Ruby 2.7. ({@osamtimizer}[https://github.com/osamtimizer]]);TS; ; i; I"Documentation;To; ;;;[ o;;0;[o; ;[I"Update broken example in Session::Abstract::ID documentation. ({tonytonyjan}[https://github.com/tonytonyjan]);To;;0;[o; ;[I"jAdd Padrino to the list of frameworks implementing Rack. ({@wikimatze}[https://github.com/wikimatze]);To;;0;[o; ;[I"xRemove Mongrel from the suggested server options in the help output. ({@tricknotes}[https://github.com/tricknotes]);To;;0;[o; ;[I"Replace HISTORY.md and NEWS.md with CHANGELOG.md. ({@twitnithegirl}[https://github.com/twitnithegirl]);To;;0;[o; ;[I"\CHANGELOG updates. ({@drenmi}[https://github.com/Drenmi], {@p8}[https://github.com/p8]);TS; ; i; I"[2.0.8] - 2019-12-08;TS; ; i; I" Security;To; ;;;[o;;0;[o; ;[I"'[{CVE-2019-16782}[https://nvd.nist.gov/vuln/detail/CVE-2019-16782]] Prevent timing attacks targeted at session ID lookup. BREAKING CHANGE: Session ID is now a SessionId instance instead of a String. ({@tenderlove}[https://github.com/tenderlove], {@rafaelfranca}[https://github.com/rafaelfranca]);TS; ; i; I"[1.6.12] - 2019-12-08;TS; ; i; I" Security;To; ;;;[o;;0;[o; ;[I"'[{CVE-2019-16782}[https://nvd.nist.gov/vuln/detail/CVE-2019-16782]] Prevent timing attacks targeted at session ID lookup. BREAKING CHANGE: Session ID is now a SessionId instance instead of a String. ({@tenderlove}[https://github.com/tenderlove], {@rafaelfranca}[https://github.com/rafaelfranca]);TS; ; i; I"[2.0.7] - 2019-04-02;TS; ; i; I" Fixed;To; ;;;[o;;0;[o; ;[I"Remove calls to #eof? on Rack input in Multipart::Parser, as this breaks the specification. ({@matthewd}[https://github.com/matthewd]);To;;0;[o; ;[I"mPreserve forwarded IP addresses for trusted proxy chains. ({@SamSaffron}[https://github.com/SamSaffron]);TS; ; i; I"[2.0.6] - 2018-11-05;TS; ; i; I" Fixed;To; ;;;[o;;0;[o; ;[I"[{CVE-2018-16470}[https://nvd.nist.gov/vuln/detail/CVE-2018-16470]] Reduce buffer size of Multipart::Parser to avoid pathological parsing. ({@tenderlove}[https://github.com/tenderlove]);To;;0;[o; ;[I"Fix a call to a non-existing method #accepts_html in the ShowExceptions middleware. ({@tomelm}[https://github.com/tomelm]);To;;0;[o; ;[I"[{CVE-2018-16471}[https://nvd.nist.gov/vuln/detail/CVE-2018-16471]] Whitelist HTTP and HTTPS schemes in Request#scheme to prevent a possible XSS attack. ({@PatrickTulskie}[https://github.com/PatrickTulskie]);TS; ; i; I"[2.0.5] - 2018-04-23;TS; ; i; I" Fixed;To; ;;;[o;;0;[o; ;[I"Record errors originating from invalid UTF8 in MethodOverride middleware instead of breaking. ({@mclark}[https://github.com/mclark]);TS; ; i; I"[2.0.4] - 2018-01-31;TS; ; i; I" Changed;To; ;;;[ o;;0;[o; ;[I"{Ensure the Lock middleware passes the original env object. ({@lugray}[https://github.com/lugray]);To;;0;[o; ;[I"}Improve performance of Multipart::Parser when uploading large files. ({@tompng}[https://github.com/tompng]);To;;0;[o; ;[I"|Increase buffer size in Multipart::Parser for better performance. ({@jkowens}[https://github.com/jkowens]);To;;0;[o; ;[I"}Reduce memory usage of Multipart::Parser when uploading large files. ({@tompng}[https://github.com/tompng]);To;;0;[o; ;[I"uReplace ConcurrentRuby dependency with native Queue. ({@devmchakan}[https://github.com/devmchakan]);TS; ; i; I" Fixed;To; ;;;[o;;0;[o; ;[I"yRequire the correct digest algorithm in the ETag middleware. ({@matthewd}[https://github.com/matthewd]);TS; ; i; I"Documentation;To; ;;;[o;;0;[o; ;[I"YUpdate homepage links to use SSL. ({@hugoabonizio}[https://github.com/hugoabonizio]);TS; ; i; I"[2.0.3] - 2017-05-15;TS; ; i; I" Changed;To; ;;;[o;;0;[o; ;[I"mEnsure env values are ASCII 8-bit encoded. ({@eileencodes}[https://github.com/eileencodes]);TS; ; i; I" Fixed;To; ;;;[o;;0;[o; ;[I"Prevent exceptions when a class with mixins inherits from Session::Abstract::ID. ({@jnraine}[https://github.com/jnraine]);TS; ; i; I"[2.0.2] - 2017-05-08;TS; ; i; I" Added;To; ;;;[o;;0;[o; ;[I"Allow Session::Abstract::SessionHash#fetch to accept a block with a default value. ({@yannvanhalewyn}[https://github.com/yannvanhalewyn]);To;;0;[o; ;[I"~Add Builder#freeze_app to freeze application and all middleware. ({@jeremyevans}[https://github.com/jeremyevans]);TS; ; i; I" Changed;To; ;;;[ o;;0;[o; ;[I"dFreeze default session options to avoid accidental mutation. ({@kirs}[https://github.com/kirs]);To;;0;[o; ;[I"_Detect partial hijack without hash headers. ({@devmchakan}[https://github.com/devmchakan]);To;;0;[o; ;[I"^Update tests to use MiniTest 6 matchers. ({@tonytonyjan}[https://github.com/tonytonyjan]);To;;0;[o; ;[I"Allow 205 Reset Content responses to set a Content-Length, as RFC 7231 proposes setting this to 0. ({@devmchakan}[https://github.com/devmchakan]);TS; ; i; I" Fixed;To; ;;;[ o;;0;[o; ;[I"nHandle NULL bytes in multipart filenames. ({@casperisfine}[https://github.com/casperisfine]);To;;0;[o; ;[I"]Remove warnings due to miscapitalized global. ({@ioquatix}[https://github.com/ioquatix]);To;;0;[o; ;[I"{Prevent exceptions caused by a race condition on multi-threaded servers. ({@sophiedeziel}[https://github.com/sophiedeziel]);To;;0;[o; ;[I"tAdd RDoc as an explicit dependency for doc group. ({@tonytonyjan}[https://github.com/tonytonyjan]);To;;0;[o; ;[I"Record errors originating from Multipart::Parser in the MethodOverride middleware instead of letting them bubble up. ({@carlzulauf}[https://github.com/carlzulauf]);To;;0;[o; ;[I"Remove remaining use of removed Utils#bytesize method from the File middleware. ({@brauliomartinezlm}[https://github.com/brauliomartinezlm]);TS; ; i; I" Removed;To; ;;;[o;;0;[o; ;[I"|Remove deflate encoding support to reduce caching overhead. ({@devmchakan}[https://github.com/devmchakan]);TS; ; i; I"Documentation;To; ;;;[o;;0;[o; ;[I"oUpdate broken example in Deflater documentation. ({@mwpastore}[https://github.com/mwpastore]);TS; ; i; I"[2.0.1] - 2016-06-30;TS; ; i; I" Changed;To; ;;;[o;;0;[o; ;[I"TRemove JSON as an explicit dependency. ({@mperham}[https://github.com/mperham]);TS; ; i; I"History/News Archive;To; ;[I"[Items below this line are from the previously maintained HISTORY.md and NEWS.md files.;TS; ; i; I"[2.0.0.rc1] 2016-05-06;To; ;;;[o;;0;[o; ;[I"gRack::Session::Abstract::ID is deprecated. Please change to use Rack::Session::Abstract::Persisted;TS; ; i; I"[2.0.0.alpha] 2015-12-04;To; ;;;[o;;0;[o; ;[I"First-party "SameSite" cookies. Browsers omit SameSite cookies from third-party requests, closing the door on many CSRF attacks.;To;;0;[o; ;[I"Pass same_site: true (or :strict) to enable: response.set_cookie 'foo', value: 'bar', same_site: true or same_site: :lax to use Lax enforcement: response.set_cookie 'foo', value: 'bar', same_site: :lax;To;;0;[o; ;[I"Based on version 7 of the Same-site Cookies internet draft: https://tools.ietf.org/html/draft-west-first-party-cookies-07;To;;0;[o; ;[I"`Thanks to Ben Toews (@mastahyeti) and Bob Long (@bobjflong) for updating to drafts 5 and 7.;To;;0;[o; ;[I"Add Rack::Events middleware for adding event based middleware: middleware that does not care about the response body, but only cares about doing work at particular points in the request / response lifecycle.;To;;0;[o; ;[I"Add Rack::Request#authority to calculate the authority under which the response is being made (this will be handy for h2 pushes).;To;;0;[o; ;[I"Add Rack::Response::Helpers#cache_control and cache_control=. Use this for setting cache control headers on your response objects.;To;;0;[o; ;[I"|Add Rack::Response::Helpers#etag and etag=. Use this for setting etag values on the response.;To;;0;[o; ;[I" Introduce Rack::Response::Helpers#add_header to add a value to a multi-valued response header. Implemented in terms of other Response#*_header methods, so it's available to any response-like class that includes the Helpers module.;To;;0;[o; ;[I"8Add Rack::Request#add_header to match.;To;;0;[o; ;[I"Rack::Session::Abstract::ID IS DEPRECATED. Please switch to Rack::Session::Abstract::Persisted. Rack::Session::Abstract::Persisted uses a request object rather than the env hash.;To;;0;[o; ;[I"Pull ENV access inside the request object in to a module. This will help with legacy Request objects that are ENV based but don't want to inherit from Rack::Request;To;;0;[o; ;[I"`Move most methods on the Rack::Request to a module Rack::Request::Helpers and use public API to get values from the request object. This enables users to mix Rack::Request::Helpers in to their own objects so they can implement (get|set|fetch|each)_header as they see fit (for example a proxy object).;To;;0;[o; ;[I"Files and directories with + in the name are served correctly. Rather than unescaping paths like a form, we unescape with a URI parser using Rack::Utils.unescape_path. Fixes #265;To;;0;[o; ;[I"UTempfiles are automatically closed in the case that there were too many posted.;To;;0;[o; ;[I"Added methods for manipulating response headers that don't assume they're stored as a Hash. Response-like classes may include the Rack::Response::Helpers module if they define these methods:;To; ;;;[o;;0;[o; ;[I"Rack::Response#has_header?;To; ;;;[o;;0;[o; ;[I"Rack::Response#get_header;To;;0;[o; ;[I"Rack::Response#set_header;To;;0;[o; ;[I"!Rack::Response#delete_header;To;;0;[o; ;[I"Introduce Util.get_byte_ranges that will parse the value of the HTTP_RANGE string passed to it without depending on the env hash. byte_ranges is deprecated in favor of this method.;To;;0;[o; ;[I"Change Session internals to use Request objects for looking up session information. This allows us to only allocate one request object when dealing with session objects (rather than doing it every time we need to manipulate cookies, etc).;To;;0;[o; ;[I"iAdd Rack::Request#initialize_copy so that the env is duped when the request gets duped.;To;;0;[o; ;[I"pAdded methods for manipulating request specific data. This includes data set as CGI parameters, and just any arbitrary data the user wants to associate with a particular request. New methods: - Rack::Request#has_header? - Rack::Request#get_header - Rack::Request#fetch_header - Rack::Request#each_header - Rack::Request#set_header - Rack::Request#delete_header;To;;0;[o; ;[I"lib/rack/utils.rb: add a method for constructing "delete" cookie headers. This allows us to construct cookie headers without depending on the side effects of mutating a hash.;To;;0;[o; ;[I"GPrevent extremely deep parameters from being parsed. CVE-2015-3225;TS; ; i; I"[1.6.1] 2015-05-06;To; ;;;[o;;0;[o; ;[I":Fix CVE-2014-9490, denial of service attack in OkJson;To;;0;[o; ;[I"9Use a monotonic time for Rack::Runtime, if available;To;;0;[o; ;[I"{RACK_MULTIPART_LIMIT changed to RACK_MULTIPART_PART_LIMIT (RACK_MULTIPART_LIMIT is deprecated and will be removed in 1.7.0);TS; ; i; I"[1.5.3] 2015-05-06;To; ;;;[o;;0;[o; ;[I":Fix CVE-2014-9490, denial of service attack in OkJson;To;;0;[o; ;[I"%Backport bug fixes to 1.5 series;TS; ; i; I"[1.6.0] 2014-01-18;To; ;;;[o;;0;[o; ;[I""Response#unauthorized? helper;To;;0;[o; ;[I"WDeflater now accepts an options hash to control compression on a per-request level;To;;0;[o; ;[I"-Builder#warmup method for app preloading;To;;0;[o; ;[I"CRequest#accept_language method to extract HTTP_ACCEPT_LANGUAGE;To;;0;[o; ;[I"2Add quiet mode of rack server, rackup --quiet;To;;0;[o; ;[I")Update HTTP Status Codes to RFC 7231;To;;0;[o; ;[I"=Less strict header name validation according to RFC 2616;To;;0;[o; ;[I"ESPEC updated to specify headers conform to RFC7230 specification;To;;0;[o; ;[I"'Etag correctly marks etags as weak;To;;0;[o; ;[I"ARequest#port supports multiple x-http-forwarded-proto values;To;;0;[o; ;[I"\Utils#multipart_part_limit configures the maximum number of parts a request can contain;To;;0;[o; ;[I"7Default host to localhost when in development mode;To;;0;[o; ;[I"2Various bugfixes and performance improvements;TS; ; i; I"[1.5.2] 2013-02-07;To; ;;;[ o;;0;[o; ;[I"CFix CVE-2013-0263, timing attack against Rack::Session::Cookie;To;;0;[o; ;[I"Struct.new(:body, :head, :filename, :content_type, :name);TI"3Rack::Multipart::Parser::Collector::BufferPart;T[@I"5Rack::Multipart::Parser::Collector::TempfilePart;T[@I""Rack::Multipart::UploadedFile;T[I" Object;TI"Rack::NullLogger;T[I" Object;TI"Rack::QueryParser;T[I" Object;TI"*Rack::QueryParser::ParameterTypeError;T[I"TypeError;TI"-Rack::QueryParser::InvalidParameterError;T[I"ArgumentError;TI"*Rack::QueryParser::ParamsTooDeepError;T[I"RangeError;TI"Rack::QueryParser::Params;T[I" Object;TI"Rack::ForwardRequest;T[I"Exception;TI"Rack::Recursive;T[I" Object;TI"Rack::Reloader;T[I" Object;TI"Rack::Request;T[I" Object;TI"Rack::Request::Env;TI"Rack::Request::Helpers;T@[I" Object;TI"Rack::Response::Helpers;T@R[I" Object;T@I"Rack::RewindableInput;T[I" Object;TI"&Rack::RewindableInput::Middleware;T[I" Object;TI"Rack::Runtime;T[I" Object;TI"Rack::Sendfile;T[I" Object;TI"Rack::ShowExceptions;T[I" Object;TI"Rack::ShowStatus;T[I" Object;TI"Rack::Static;T[I" Object;TI"Rack::TempfileReaper;T[I" Object;TI"Rack::URLMap;T[I" Object;TI"Rack::Utils::Context;T[I" Object;TI"Rack::Utils::HeaderHash;T[I" Hash;T:attributes{@[I"attr_accessor realm;T@[I"attr_accessor private_key;TI"attr_accessor time_limit;T@[I"attr_accessor opaque;TI"!attr_writer passwords_hashed;T@![I"attr_reader apps;T@B[I"attr_reader root;T@S[I"attr_reader root;T@V[I"attr_reader root;T@X[I"attr_reader options;TI"attr_reader path;TI"attr_reader ranges;T@[I"attr_accessor errors;TI"attr_reader cookies;TI"!attr_reader original_headers;T@[I"attr_reader state;T@[I"attr_accessor content_type;TI""attr_reader original_filename;T@[I""attr_reader param_depth_limit;T@[I"attr_reader env;TI"attr_reader url;T@[I"%attr_accessor forwarded_priority;TI"attr_accessor ip_filter;TI"-attr_accessor x_forwarded_proto_priority;T@[ I"attr_accessor body;TI"attr_accessor length;TI"attr_accessor status;TI"attr_reader headers;T@R[I"attr_accessor status;TI"attr_reader headers;T@[I"attr_reader app;TI"attr_reader for;T@[I"attr_reader env;T@'[ I"'attr_accessor default_query_parser;TI"'attr_accessor multipart_file_limit;TI"'attr_accessor multipart_part_limit;TI"(attr_accessor multipart_part_limit=;TI"-attr_accessor multipart_total_part_limit;T:class_methods{A@[I"new;T@ [@-@[ @-I" parse;TI"private_key;TI"time_limit;T@[ I" dequote;T@-I" parse;TI"split_header_value;T@[@-@[@-@[ I"app;TI"load_file;T@-I"new_from_string;TI"parse_file;T@![@-@$[@-@([@-@-[@-@0[@-@3[@-@6[@-@9[@-@<[@-@?[@-@B[@-@H[@-@K[@-@S[@-@V[@-@X[@-@][@-@`[I"[];T@c[@-@u[@-@x[@-@{[I" params;TI"strip_doublequotes;TI" type;T@~[@-@|[I" env_for;T@-I"parse_uri_rfc2396;T@[@-@[@-@[@-I" parse;TI"parse_boundary;T@[@-@[@-@[@-@[I"make_default;T@-@[@-@[@-@[@-@[@-@[ I"forwarded_priority;TI"ip_filter;T@-I"x_forwarded_proto_priority;T@[I"[];T@-@R[@-@[@-@[@-@[@-@[@-@[@-@[@-@[@-@[@-@[@-@[@-I" Rack;T[I" release;TI" version;TI"Rack::Mime;T[I" match?;TI"mime_type;TI"Rack::Multipart;T[I"build_multipart;TI"extract_multipart;TI"parse_multipart;T@[@-@'[I"default_query_parser;TI"forwarded_values;TI"key_space_limit;TI"key_space_limit=;TI"multipart_file_limit;TI"multipart_part_limit;TI"multipart_part_limit=;TI"multipart_total_part_limit;TI"param_depth_limit;TI"param_depth_limit=;T:c_class_variables{: c_singleton_class_variables{: encodingIu: Encoding UTF-8;F:instance_methods{J@[I"bad_request;TI" realm;TI"unauthorized;T@ [ I"authorization_key;TI" params;TI" parts;TI"provided?;TI" request;TI" scheme;TI" valid?;T@ [I" call;TI"challenge;TI" valid?;T@[I" basic?;TI"credentials;TI" username;T@[ I" digest;TI" fresh?;TI" stale?;TI" to_s;TI" valid?;T@[ I"[];TI"[]=;TI" quote;TI" to_s;T@[ I"correct_uri?;TI" digest?;TI" method;TI"method_missing;TI" nonce;TI" params;TI"respond_to?;T@[I"A1;TI"A2;TI"H;TI"KD;TI" call;TI"challenge;TI" digest;TI"md5;TI" opaque;TI" params;TI"passwords_hashed;TI"passwords_hashed?;TI" valid?;TI"valid_digest?;TI"valid_nonce?;TI"valid_opaque?;TI"valid_qop?;T@[ I" close;TI" closed?;TI"method_missing;TI"respond_to_missing?;T@[ I" call;TI"freeze_app;TI"generate_map;TI"map;TI"run;TI" to_app;TI"use;TI" warmup;T@![ I"<<;TI"add;TI" apps;TI" call;TI" include?;T@$[I" call;TI"chunkable_version?;T@([I" close;TI" each;TI"yield_trailers;T@+[I"yield_trailers;T@-[I" call;TI"extract_content_length;TI"log;T@0[ I" call;TI"etag_matches?;TI" fresh?;TI"modified_since?;TI"to_rfc2822;T@3[I" call;T@6[I" call;T@9[I" call;T@<[I" call;TI"should_deflate?;T@?[I" close;TI" each;TI" write;T@B[I" call;TI"check_bad_request;TI"check_forbidden;TI"entity_not_found;TI"filesize_format;TI"get;TI"list_directory;TI"list_path;TI" root;TI" stat;T@E[I"DIR_FILE_escape;TI" each;T@H[ I" call;TI"digest_body;TI"etag_status?;TI"skip_caching?;T@K[ I" call;TI"make_request;TI"make_response;TI"on_commit;TI" on_error;TI"on_finish;TI" on_start;T@S[ I" call;TI" fail;TI" filesize;TI"get;TI"mime_type;TI" root;TI" serving;T@V[ @!@"@#@$@%@&@'@X[I" bytesize;TI" close;TI" each;TI"each_range_part;TI"multipart?;TI"multipart_heading;TI" options;TI" path;TI" ranges;T@][I" call;T@`[!I"[];TI"[]=;TI" assoc;TI"compare_by_identity;TI" delete;TI"dig;TI"downcase_key;TI" except;TI" fetch;TI"fetch_values;TI" has_key?;TI" include?;TI" invert;TI" key?;TI" member?;TI" merge;TI" merge!;TI" reject;TI" replace;TI" select;TI" slice;TI" store;TI" to_proc;TI"transform_keys;TI"transform_keys!;TI"transform_values;TI" update;TI"values_at;T@u[I" call;TI" unlock;T@x[I" call;T@~[ I"allowed_methods;TI" call;TI"method_override;TI"method_override_param;T@|[ I" delete;TI"get;TI" head;TI" options;TI" patch;TI" post;TI"put;TI" request;T@[ I" flush;TI" puts;TI" string;TI" write;T@[I"=~;TI" body;TI" cookie;TI" cookies;TI" empty?;TI" errors;TI"identify_cookie_attributes;TI" match;TI"original_headers;TI"parse_cookies_from_header;T@[ I"content_for_other;TI"content_for_tempfile;TI" dump;TI"flattened_params;TI"multipart?;T@[I"consume_boundary;TI" dequote;TI"get_filename;TI"handle_consume_token;TI"handle_empty_content!;TI"handle_fast_forward;TI"handle_mime_body;TI"handle_mime_head;TI" parse;TI"read_data;TI" result;TI" state;TI"tag_multipart_encoding;T@[ I"check_part_limits;TI" each;TI"on_mime_body;TI"on_mime_finish;TI"on_mime_head;T@[I" get_data;T@[I" close;TI" file?;T@[I" close;TI" file?;T@[ I"content_type;TI"local_path;TI"original_filename;TI" path;TI"respond_to?;T@[%I"<<;TI"add;TI" call;TI" close;TI"datetime_format;TI"datetime_format=;TI" debug;TI" debug!;TI" debug?;TI" error;TI" error!;TI" error?;TI" fatal;TI" fatal!;TI" fatal?;TI"formatter;TI"formatter=;TI" info;TI" info!;TI" info?;TI" level;TI" level=;TI"log;TI" progname;TI"progname=;TI" reopen;TI"sev_threshold;TI"sev_threshold=;TI" unknown;TI" warn;TI" warn!;TI" warn?;T@[I"_normalize_params;TI"make_params;TI"new_depth_limit;TI"normalize_params;TI"param_depth_limit;TI"params_hash_has_key?;TI"params_hash_type?;TI"parse_nested_query;TI"parse_query;TI" unescape;T@[ I"[];TI"[]=;TI" key?;TI" to_h;TI"to_params_hash;T@[I"env;TI"url;T@[I" _call;TI" call;TI" include;T@[I" call;TI" reload!;TI"safe_load;T@[I"delete_param;TI" params;TI"update_param;T@[I"[];TI"[]=;TI" body;TI" chunked?;TI" close;TI"delete_header;TI" each;TI" empty?;TI" finish;TI"get_header;TI"has_header?;TI" header;TI" headers;TI" length;TI"no_entity_body?;TI" redirect;TI"set_header;TI" status;TI" to_a;TI" write;T@R[ I"delete_header;TI"get_header;TI"has_header?;TI" headers;TI"set_header;TI" status;T@[ I" close;TI" each;TI"$filesystem_has_posix_semantics?;TI" gets;TI"make_rewindable;TI" read;TI" rewind;TI" size;T@[I" call;T@[I" call;T@[I" call;TI"map_accel_path;TI"variation;T@[ I"accepts_html?;TI" call;TI"dump_exception;TI"prefers_plaintext?;TI" pretty;TI" template;T@[I" call;T@[ I"add_index_root?;TI"applicable_rules;TI" call;TI"can_serve;TI"overwrite_file_path;TI"route_file;T@[I" call;T@[I" call;TI" casecmp?;TI" remap;T@[ I"app;TI" call;TI" context;TI"for;TI"recontext;TI"Rack::Events::Abstract;T[ I"on_commit;TI" on_error;TI"on_finish;TI" on_send;TI" on_start;T@[@@I"Rack::Reloader::Stat;T[I"figure_path;TI" rotation;TI"safe_stat;T@[I"add_header;TI"delete_header;TI"each_header;TI"env;TI"fetch_header;TI"get_header;TI"has_header?;TI"initialize_copy;TI"set_header;T@[QI"GET;TI" POST;TI"[];TI"[]=;TI"accept_encoding;TI"accept_language;TI"allowed_scheme;TI"authority;TI" base_url;TI" body;TI"content_charset;TI"content_length;TI"content_type;TI" cookies;TI"default_session;TI" delete?;TI"delete_param;TI"form_data?;TI"forwarded_authority;TI"forwarded_for;TI"forwarded_port;TI"forwarded_priority;TI"forwarded_scheme;TI" fullpath;TI" get?;TI"get_http_forwarded;TI" head?;TI" host;TI"host_authority;TI"host_with_port;TI" hostname;TI"ip;TI" link?;TI" logger;TI"media_type;TI"media_type_params;TI" options?;TI" params;TI"parse_http_accept_header;TI"parse_multipart;TI"parse_query;TI"parseable_data?;TI" patch?;TI" path;TI"path_info;TI"path_info=;TI" port;TI" post?;TI" put?;TI"query_parser;TI"query_string;TI" referer;TI" referrer;TI" reject_trusted_ip_addresses;TI"request_method;TI" scheme;TI"script_name;TI"script_name=;TI"server_authority;TI"server_name;TI"server_port;TI" session;TI"session_options;TI"split_authority;TI"split_header;TI" ssl?;TI" trace?;TI"trusted_proxy?;TI" unlink?;TI"update_param;TI"url;TI"user_agent;TI"values_at;TI"wrap_ipv6;TI"x_forwarded_proto_priority;TI" xhr?;T@[/I"accepted?;TI"add_header;TI" append;TI"bad_request?;TI"buffered_body!;TI" cache!;TI"cache_control;TI"cache_control=;TI"client_error?;TI"content_length;TI"content_type;TI"content_type=;TI" created?;TI"delete_cookie;TI"do_not_cache!;TI" etag;TI" etag=;TI"forbidden?;TI" include?;TI"informational?;TI" invalid?;TI" location;TI"location=;TI"media_type;TI"media_type_params;TI"method_not_allowed?;TI"moved_permanently?;TI"no_content?;TI"not_acceptable?;TI"not_found?;TI"ok?;TI"precondition_failed?;TI"redirect?;TI"redirection?;TI"request_timeout?;TI"server_error?;TI"set_cookie;TI"set_cookie_header;TI"set_cookie_header=;TI"successful?;TI"unauthorized?;TI"unprocessable?;T@'[$I"add_cookie_to_header;TI" add_remove_cookie_to_header;TI"best_q_match;TI"build_nested_query;TI"build_query;TI"byte_ranges;TI"clean_path_info;TI"clock_time;TI"delete_cookie_header!;TI"delete_set_cookie_header;TI"delete_set_cookie_header!;TI" escape;TI"escape_html;TI"escape_path;T@I"get_byte_ranges;TI"make_delete_cookie_header;TI"parse_cookies;TI"parse_cookies_header;TI"parse_nested_query;TI"parse_query;TI" q_values;TI" rfc2822;TI"secure_compare;TI"select_best_encoding;TI"set_cookie_header;TI"set_cookie_header!;TI"status_code;TI" unescape;TI"unescape_path;TI"valid_path?;T: main0: modules[bI" Rack;TI"Rack::Auth;T@@ @ @I"Rack::Auth::Digest;T@@@@@@@!@$@(@+@-@0@3@6@9@<@?@B@E@H@K@'@P@N@V@S@X@[@@]@`@c@f@i@o@l@r@u@x@{@~@@|@@@@@@@@@@@@@@@@@@@@@@@@@/@@@@@@R@@@@@@@@@@'@@: pages[I"CHANGELOG.md;TI"CONTRIBUTING.md;TI"README.md;T: titleI"rack-3.0.8 Documentation;TPK% ]0Oj;j;#doc/rack-3.0.8/ri/page-README_md.rinu[U:RDoc::TopLevel[ iI"README.md:ETcRDoc::Parser::Markdowno:RDoc::Markup::Document: @parts[OS:RDoc::Markup::Heading: leveli: textI"!rdoc-image:contrib/logo.webp;To:RDoc::Markup::BlockQuote;[o:RDoc::Markup::Paragraph;[I"NOTE: Rack v3.0.0 was recently released. Please check the {Upgrade Guide}[UPGRADE-GUIDE.md] for more details about migrating your existing servers, middlewares and applications. For detailed information on specific changes, check the {Change Log}[CHANGELOG.md].;To; ;[I"Rack provides a minimal, modular, and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the bridge between web servers, web frameworks, and web application into a single method call.;To; ;[I"~The exact details of this are described in the {Rack Specification}[SPEC.rdoc], which all Rack applications should conform to.;TS; ; i; I"Installation;To; ;[I"Add the rack gem to your application bundle, or follow the instructions provided by a {supported web framework}[#supported-web-frameworks]:;To:RDoc::Markup::Verbatim;[I"# Install it generally: $ gem install rack --pre # or, add it to your current application gemfile: $ bundle add rack --version 3.0.0 ;T: @format: basho; ;[I"vIf you need features from Rack::Session or bin/rackup please add those gems separately.;To;;[I"'$ gem install rack-session rackup ;T;;S; ; i; I" Usage;To; ;[I"MCreate a file called config.ru with the following contents:;To;;[I"3run do |env| [200, {}, ["Hello World"]] end ;T;: rubyo; ;[I"]Run this using the rackup gem or another {supported web server}[#supported-web-servers].;To;;[I"L$ gem install rackup $ rackup $ curl http://localhost:9292 Hello World ;T;;S; ; i; I"Supported web servers;To; ;[I"=Rack is supported by a wide range of servers, including:;To:RDoc::Markup::List: @type: BULLET: @items[o:RDoc::Markup::ListItem: @label0;[o; ;[I",{Agoo}[https://github.com/ohler55/agoo];To;;0;[o; ;[I"L{Falcon}[https://github.com/socketry/falcon] (Rack 3 Compatible);To;;0;[o; ;[I"2{Iodine}[https://github.com/boazsegev/iodine];To;;0;[o; ;[I"*{NGINX Unit}[https://unit.nginx.org/];To;;0;[o; ;[I"i{Phusion Passenger}[https://www.phusionpassenger.com/] (which is mod_rack for Apache and for nginx);To;;0;[o; ;[I"{Puma}[https://puma.io/];To;;0;[o; ;[I"0{Thin}[https://github.com/macournoyer/thin];To;;0;[o; ;[I"){Unicorn}[https://yhbt.net/unicorn/];To;;0;[o; ;[I":{uWSGI}[https://uwsgi-docs.readthedocs.io/en/latest/];To;;0;[o; ;[I">{Lamby}[https://lamby.custominktech.com] (for AWS Lambda);To; ;[I"You will need to consult the server documentation to find out what features and limitations they may have. In general, any valid Rack app will run the same on all these servers, without changing anything.;TS; ; i; I" Rackup;To; ;[I"Rack provides a separate gem, {rackup}[https://github.com/rack/rackup] which is a generic interface for running a Rack application on supported servers, which include WEBRick, Puma, Falcon and others.;TS; ; i; I"Supported web frameworks;To; ;[I"RThese frameworks and many others support the {Rack Specification}[SPEC.rdoc]:;To;;;;[ o;;0;[o; ;[I"2{Camping}[https://github.com/camping/camping];To;;0;[o; ;[I"${Hanami}[https://hanamirb.org/];To;;0;[o; ;[I"&{Padrino}[https://padrinorb.com/];To;;0;[o; ;[I"K{Roda}[https://github.com/jeremyevans/roda] (Rack 3 Compatible);To;;0;[o; ;[I".{Ruby on Rails}[https://rubyonrails.org/];To;;0;[o; ;[I"&{Sinatra}[https://sinatrarb.com/];To;;0;[o; ;[I"L{Utopia}[https://github.com/socketry/utopia] (Rack 3 Compatible);To;;0;[o; ;[I".{WABuR}[https://github.com/ohler55/wabur];TS; ; i; I"0Older (possibly unsupported) web frameworks;To;;;;[o;;0;[o; ;[I"!{Ramaze}[http://ramaze.net/];To;;0;[o; ;[I"1{Rum}[https://github.com/leahneukirchen/rum];TS; ; i; I"+Available middleware shipped with Rack;To; ;[I"Between the server and the framework, Rack can be customized to your applications needs using middleware. Rack itself ships with the following middleware:;To;;;;[o;;0;[o; ;[I"HRack::CommonLogger for creating Apache-style logfiles.;To;;0;[o; ;[I"Rack::ConditionalGet for returning {Not Modified}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304] responses when the response has not changed.;To;;0;[o; ;[I"[Rack::Config for modifying the environment before processing the request.;To;;0;[o; ;[I"kRack::ContentLength for setting a content-length header based on body size.;To;;0;[o; ;[I"iRack::ContentType for setting a default content-type header for responses.;To;;0;[o; ;[I"ERack::Deflater for compressing responses with gzip.;To;;0;[o; ;[I"aRack::ETag for setting etag header on bodies that can be buffered.;To;;0;[o; ;[I"rRack::Events for providing easy hooks when a request is received and when the response is sent.;To;;0;[o; ;[I"7Rack::Files for serving static files.;To;;0;[o; ;[I"KRack::Head for returning an empty body for HEAD requests.;To;;0;[o; ;[I"]Rack::Lint for checking conformance to the {Rack Specification}[SPEC.rdoc].;To;;0;[o; ;[I"DRack::Lock for serializing requests using a mutex.;To;;0;[o; ;[I"MRack::Logger for setting a logger to handle logging errors.;To;;0;[o; ;[I"hRack::MethodOverride for modifying the request method based on a submitted parameter.;To;;0;[o; ;[I"|Rack::Recursive for including data from other paths in the application, and for performing internal redirects.;To;;0;[o; ;[I"PRack::Reloader for reloading files if they have been modified.;To;;0;[o; ;[I"lRack::Runtime for including a response header with the time taken to process the request.;To;;0;[o; ;[I"yRack::Sendfile for working with web servers that can use optimized file serving for file system paths.;To;;0;[o; ;[I"Rack::ShowException for catching unhandled exceptions and presenting them in a nice and helpful way with clickable backtrace.;To;;0;[o; ;[I"`Rack::ShowStatus for using nice error pages for empty client error responses.;To;;0;[o; ;[I"MRack::Static for more configurable serving of static files.;To;;0;[o; ;[I"^Rack::TempfileReaper for removing temporary files creating during a request.;To; ;[I"All these components use the same interface, which is described in detail in the {Rack Specification}[SPEC.rdoc]. These optional components can be used in any way you wish.;TS; ; i; I"Convenience interfaces;To; ;[I"If you want to develop outside of existing frameworks, implement your own ones, or develop middleware, Rack provides many helpers to create Rack applications quickly and without doing the same web stuff all over:;To;;;;[o;;0;[o; ;[I"aRack::Request which also provides query string parsing and multipart handling.;To;;0;[o; ;[I"`Rack::Response for convenient generation of HTTP replies and cookie handling.;To;;0;[o; ;[I"Rack::MockRequest and Rack::MockResponse for efficient and quick testing of Rack application without real HTTP round-trips.;To;;0;[o; ;[I"Rack::Cascade for trying additional Rack applications if an application returns a not found or method not supported response.;To;;0;[o; ;[I"eRack::Directory for serving files under a given directory, with directory indexes.;To;;0;[o; ;[I"CRack::MediaType for parsing content-type headers.;To;;0;[o; ;[I"RRack::Mime for determining content-type based on file extension.;To;;0;[o; ;[I"lRack::RewindableInput for making any IO object rewindable, using a temporary file buffer.;To;;0;[o; ;[I"YRack::URLMap to route to multiple applications inside the same process.;TS; ; i; I"Configuration;To; ;[I"eRack exposes several configuration parameters to control various features of the implementation.;TS; ; i; I"#param_depth_limit;To;;[I"2Rack::Utils.param_depth_limit = 32 # default ;T;;o; ;[I"wThe maximum amount of nesting allowed in parameters. For example, if set to 3, this query string would be allowed:;To;;[I"?a[b][c]=d ;T;0o; ;[I"0but this query string would not be allowed:;To;;[I"?a[b][c][d]=e ;T;0o; ;[I"SLimiting the depth prevents a possible stack overflow when parsing parameters.;TS; ; i; I"&multipart_file_limit;To;;[I"6Rack::Utils.multipart_file_limit = 128 # default ;T;;o; ;[I"The maximum number of parts with a filename a request can contain. Accepting too many parts can lead to the server running out of file handles.;To; ;[I"{The default is 128, which means that a single request can't upload more than 128 files at once. Set to 0 for no limit.;To; ;[I"YCan also be set via the RACK_MULTIPART_FILE_LIMIT environment variable.;To; ;[I"}(This is also aliased as multipart_part_limit and RACK_MULTIPART_PART_LIMIT for compatibility);TS; ; i; I",multipart_total_part_limit;To; ;[I"wThe maximum total number of parts a request can contain of any type, including both file and non-file form fields.;To; ;[I"_The default is 4096, which means that a single request can't contain more than 4096 parts.;To; ;[I"Set to 0 for no limit.;To; ;[I"_Can also be set via the RACK_MULTIPART_TOTAL_PART_LIMIT environment variable.;TS; ; i; I"Changelog;To; ;[I"&See {CHANGELOG.md}[CHANGELOG.md].;TS; ; i; I"Contributing;To; ;[I"jSee {CONTRIBUTING.md}[CONTRIBUTING.md] for specific details about how to make a contribution to Rack.;To; ;[I"gPlease post bugs, suggestions and patches to {GitHub Issues}[https://github.com/rack/rack/issues].;To; ;[I"UPlease check our {Security Policy}[https://github.com/rack/rack/security/policy] for responsible disclosure and security bug reporting process. Due to wide usage of the library, it is strongly preferred that we manage timing in order to provide viable patches at the time of disclosure. Your assistance in this matter is greatly appreciated.;TS; ; i; I" See Also;TS; ; i; I"rack-contrib;To; ;[I"The plethora of useful middleware created the need for a project that collects fresh Rack middleware. rack-contrib includes a variety of add-on components for Rack and it is easy to contribute new modules.;To;;;;[o;;0;[o; ;[I")https://github.com/rack/rack-contrib;TS; ; i; I"rack-session;To; ;[I"5Provides convenient session management for Rack.;To;;;;[o;;0;[o; ;[I")https://github.com/rack/rack-session;TS; ; i; I" Thanks;To; ;[I"&The Rack Core Team, consisting of;To;;;;[ o;;0;[o; ;[I"@Aaron Patterson {tenderlove}[https://github.com/tenderlove];To;;0;[o; ;[I"Scytrin dai Kinthra {scytrin}[https://github.com/scytrin];To;;0;[o; ;[I"HLeah Neukirchen {leahneukirchen}[https://github.com/leahneukirchen];To;;0;[o; ;[I"3James Tucker {raggi}[https://github.com/raggi];To;;0;[o; ;[I".Josh Peek {josh}[https://github.com/josh];To;;0;[o; ;[I":José Valim {josevalim}[https://github.com/josevalim];To;;0;[o; ;[I"Rack::Deflater.;To;;0;[o; ;[I"4Tim Fletcher, for the HTTP authentication code.;To;;0;[o; ;[I"PLuc Heinrich for the Cookie sessions, the static file handler and bugfixes.;To;;0;[o; ;[I"0Armin Ronacher, for the logo and racktools.;To;;0;[o; ;[I"Alex Beregszaszi, Alexander Kahn, Anil Wadghule, Aredridel, Ben Alpert, Dan Kubb, Daniel Roethlisberger, Matt Todd, Tom Robinson, Phil Hagelberg, S. Brent Faulkner, Bosko Milekic, Daniel Rodríguez Troitiño, Genki Takiuchi, Geoffrey Grosenbach, Julien Sanchez, Kamal Fariz Mahyuddin, Masayoshi Takahashi, Patrick Aljordm, Mig, Kazuhiro Nishiyama, Jon Bardin, Konstantin Haase, Larry Siden, Matias Korhonen, Sam Ruby, Simon Chiang, Tim Connor, Timur Batyrshin, and Zach Brock for bug fixing and other improvements.;To;;0;[o; ;[I"]Eric Wong, Hongli Lai, Jeremy Kemper for their continuous support and API improvements.;To;;0;[o; ;[I"8Yehuda Katz and Carl Lerche for refactoring rackup.;To;;0;[o; ;[I"7Brian Candler, for Rack::ContentType.;To;;0;[o; ;[I"0Graham Batty, for improved handler loading.;To;;0;[o; ;[I"9Stephen Bannasch, for bug reports and documentation.;To;;0;[o; ;[I"OGary Wright, for proposing a better Rack::Response interface.;To;;0;[o; ;[I"KJonathan Buch, for improvements regarding Rack::Response.;To;;0;[o; ;[I"BArmin Röhrl, for tracking down bugs in the Cookie generator.;To;;0;[o; ;[I"JAlexander Kellett for testing the Gem and reviewing the announcement.;To;;0;[o; ;[I"GMarcus Rückert, for help with configuring and debugging lighttpd.;To;;0;[o; ;[I"]The WSGI team for the well-done and documented work they've done and Rack builds up on.;To;;0;[o; ;[I"BAll bug reporters and patch contributors not mentioned above.;TS; ; i; I" License;To; ;[I";Rack is released under the {MIT License}[MIT-LICENSE].;T: @file@:0@omit_headings_from_table_of_contents_below0PK% ]|,,0doc/ruby-lsapi-5.5/ri/ext/lsapi/page-Makefile.rinu[U:RDoc::TopLevel[ iI"ext/lsapi/Makefile:ETcRDoc::Parser::Simpleo:RDoc::Markup::Document: @parts[$o:RDoc::Markup::Paragraph;[I"SHELL = /bin/sh;To:RDoc::Markup::BlankLineo; ;[ I"9# V=0 quiet, V=1 verbose. other values don't work. ;TI" V = 0 ;TI"Q1 = $(V:1=) ;TI"Q = $(Q1:0=@) ;TI"ECHO1 = $(V:1=@ :) ;TI"ECHO = $(ECHO1:0=@ echo) ;TI"NULLCMD = :;T@o; ;[I"5#### Start of system configuration section. ####;T@o; ;[7I"srcdir = . ;TI"1topdir = /opt/alt/ruby26/include/ruby-2.6.0 ;TI"hdrdir = $(topdir) ;TI"Carch_hdrdir = /opt/alt/ruby26/include/ruby-2.6.0/x86_64-linux ;TI"PATH_SEPARATOR = : ;TI":VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby ;TI"(prefix = $(DESTDIR)/opt/alt/ruby26 ;TI"7rubysitearchprefix = $(rubylibprefix)/$(sitearch) ;TI"/rubyarchprefix = $(rubylibprefix)/$(arch) ;TI"1rubylibprefix = $(libdir)/$(RUBY_BASE_NAME) ;TI"-exec_prefix = $(DESTDIR)/opt/alt/ruby26 ;TI"4vendorarchhdrdir = $(vendorhdrdir)/$(sitearch) ;TI"0sitearchhdrdir = $(sitehdrdir)/$(sitearch) ;TI",rubyarchhdrdir = $(rubyhdrdir)/$(arch) ;TI".vendorhdrdir = $(rubyhdrdir)/vendor_ruby ;TI"*sitehdrdir = $(rubyhdrdir)/site_ruby ;TI"5rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME) ;TI"1vendorarchdir = $(vendorlibdir)/$(sitearch) ;TI"1vendorlibdir = $(vendordir)/$(ruby_version) ;TI".vendordir = $(rubylibprefix)/vendor_ruby ;TI";T@o; ;[I"3#### End of system configuration section. ####;T@o; ;[ I"preload = ;TI"libpath = . $(libdir) ;TI"5LIBPATH = -L. -L$(libdir) -Wl,-rpath,$(libdir) ;TI"DEFFILE = ;T@o; ;[I"CLEANFILES = mkmf.log ;TI"DISTCLEANFILES = ;TI"DISTCLEANDIRS = ;T@o; ;[I"extout = ;TI"extout_prefix = ;TI"target_prefix = ;TI"LOCAL_LIBS = ;TI",LIBS = $(LIBRUBYARG_SHARED) -lm -lc ;TI"%ORIG_SRCS = lsapilib.c lsruby.c ;TI"SRCS = $(ORIG_SRCS) ;TI" OBJS = lsapilib.o lsruby.o ;TI"6HDRS = $(srcdir)/lsapidef.h $(srcdir)/lsapilib.h ;TI"LOCAL_HDRS = ;TI"TARGET = lsapi ;TI"TARGET_NAME = lsapi ;TI"(TARGET_ENTRY = Init_$(TARGET_NAME) ;TI"DLLIB = $(TARGET).so ;TI"EXTSTATIC = ;TI"STATIC_LIB = ;T@o; ;[I"TIMESTAMP_DIR = . ;TI"BINDIR = $(bindir) ;TI"0RUBYCOMMONDIR = $(sitedir)$(target_prefix) ;TI"3RUBYLIBDIR = $(sitelibdir)$(target_prefix) ;TI"4RUBYARCHDIR = $(sitearchdir)$(target_prefix) ;TI"8HDRDIR = $(rubyhdrdir)/ruby$(target_prefix) ;TI"@ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix) ;TI"TARGET_SO_DIR = ;TI".TARGET_SO = $(TARGET_SO_DIR)$(DLLIB) ;TI"#CLEANLIBS = $(TARGET_SO) ;TI"CLEANOBJS = *.o *.bak;T@o; ;[ I"all: $(DLLIB) ;TI"static: $(STATIC_LIB) ;TI"6.PHONY: all install static install-so install-rb ;TI"1.PHONY: clean clean-so clean-static clean-rb;T@o:RDoc::Markup::List: @type: NOTE: @items[o:RDoc::Markup::ListItem: @label[ I"clean-static;TI"clean-rb-default;TI" clean-rb;TI" clean-so;T;[o; ;[I";clean: clean-so clean-static clean-rb-default clean-rb;To:RDoc::Markup::Verbatim;[I"@-$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time ;T: @format0o; ; ; ;[o;;[ I"distclean-rb-default;TI"distclean-rb;TI"distclean-so;TI"distclean-static;T;[/o; ;[I"Udistclean: clean distclean-so distclean-static distclean-rb-default distclean-rb;To;;[I"?-$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log ;TI"8-$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) ;TI":-$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true ;T;0o; ;[I"realclean: distclean ;TI"#install: install-so install-rb;T@o; ;[I"$doc/ruby-lsapi-5.5/ri/page-README.rinu[U:RDoc::TopLevel[ iI" README:ETcRDoc::Parser::Simpleo:RDoc::Markup::Document: @parts[Mo:RDoc::Markup::Paragraph;[I"%lsapi - LSAPI extension for Ruby;TS:RDoc::Markup::Heading: leveli%: textI";To:RDoc::Markup::BlankLineo; ;[I" INSTALL;TS:RDoc::Markup::Rule: weighti @o:RDoc::Markup::Verbatim;[I"$ ruby setup.rb config ;TI"$ ruby setup.rb setup ;TI"# ruby setup.rb install ;T: @format0o; ;[I" USAGE;TS;;i@o; ;[ I"General CGI scripts ;TI"^^^^^^^^^^^^^^^^^^^ ;TI"SThe most efficient way to use LSAPI interface is to modify your CGI scripts. ;TI" ;TI" ... ;TI" ;TI" end ;T;0o; ;[I"LThere is no need to change the way that how CGI environment variables ;TI"(are being accessed in your scripts.;T@o; ;[I"7You can find some examples under examples/ folder.;T@o; ;[ I"Ruby Script Runner ;TI"^^^^^^^^^^^^^^^^^^ ;TI"OIf you don't want to change your existing Ruby CGI code, you can use our ;TI"FRuby script runner under scripts/ folder. You need to configure ;TI"Ilsruby_runner.rb as a LSAPI application, then add a script handler ;TI"for "rb" suffix.;T@@o; ;[I"Rails dispatcher ;TI"^^^^^^^^^^^^^^^^;T@o; ;[I"RWith Ruby LSAPI, we proudly provide a optimum platform for Rails application ;TI"Ndeployment. Ruby LSAPI has the following advantages over other solutions.;T@o;;[ I"M* Easy configuration, deploy a Rails application only take a few clicks ;TI") with our Rails easy configuration ;TI"M* Fast startup, the expensive Rails framework initialization only takes ;TI"= place once when multiple processes need to be started ;TI"J* Resource efficience, ruby processes can be started on demand, idle ;TI" process will be stop. ;T;0o; ;[I"DTo use LSAPI with Ruby on Rails, please check out our toturial ;TI"7http://www.litespeedtech.com/support/wiki/doku.php;T@o; ;[I"MThere are a few environment variables that can be tweaked to tune ruby ;TI"LSAPI process.;T@o:RDoc::Markup::List: @type: BULLET: @items[o:RDoc::Markup::ListItem: @label0;[o; ;[I"/LSAPI_CHILDREN (default: 0);T@o; ;[ I"MLSAPI_CHILDREN controls the maximum number of children processes can be ;TI"Ostarted by the first ruby process started by web server. When set to <=1, ;TI"Pthe first ruby process will handle request by itself, without starting any ;TI"Rchild process. When LSAPI_CHILDREN is >1, the LSAPI application is stared in ;TI"O"Self Managed Mode", which will start children processes based on demand. ;TI"JWith Rails easy configuration, LSAPI_CHILDREN is set to the value of ;TI"C"Max Connections" by web server, no need to set it explicitly.;T@o; ;[I"OUsually, there is no need to set value of LSAPI_CHILDREN over 100 in most ;TI"server environment.;T@o;;;;[o;;0;[o; ;[I"/LSAPI_AVOID_FORK (default: 0);T@o; ;[ I"NLSAPI_AVOID_FORK specifies the policy of the internal process manager in ;TI"P"Self Managed Mode". When set to 0, the internal process manager will stop ;TI"Kand start children process on demand to save system resource. This is ;TI"Lpreferred in a shared hosting environment. When set to 1, the internal ;TI"Pprocess manager will try to avoid freqently stopping and starting children ;TI"Hprocess. This might be preferred in a dedicate hosting environment.;T@o;;;;[o;;0;[o; ;[I"HLSAPI_EXTRA_CHILDREN (default: 1/3 of LSAPI_CHILDREN or 0);T@o; ;[ I"RLSAPI_EXTRA_CHILDREN controls the maximum number of extra children processes ;TI"Hcan be started when some or all existing children processes are in ;TI"Qmalfunctioning state. Total number of children processes will be reduced to ;TI"@LSAPI_CHILDREN level as soon as service is back to normal. ;TI"DWhen LSAPI_AVOID_FORK is set to 0, the default value is 1/3 of ;TI"OLSAPI_CHIDLREN, When LSAPI_AVOID_FORK is set to 1, the default value is 0.;T@o;;;;[o;;0;[o; ;[I"9LSAPI_MAX_REQS (default value: 10000);T@o; ;[I"HLSAPI_MAX_REQS specifies the maximum number of requests each child ;TI"Kprocess will handle before it exits automatically. This parameter can ;TI"Phelp reducing memory usage when there are memory leaks in the application. ;T@o;;;;[o;;0;[o; ;[I"?LSAPI_MAX_IDLE (default value: 300 seconds);T@o; ;[I"HIn Self Managed Mode, LSAPI_MAX_IDLE controls how long a idle child;T@o; ;[I"Hprocess will wait for a new request before exit. This option help ;TI"8releasing system resources taken by idle processes.;T@o;;;;[o;;0;[o; ;[I"LSAPI_MAX_IDLE_CHILDREN;To;;[I">(default value: 1/3 of LSAPI_CHILDREN or LSAPI_CHILDREN) ;T;0o; ;[ I"JIn Self Managed Mode, LSAI_MAX_IDLE_CHILDREN controls how many idle ;TI"Gchildren processes are allowed. Excessive idle children processes ;TI"+will be killed by the parent process. ;TI"DWhen LSAPI_AVOID_FORK is set to 0, the default value is 1/3 of ;TI"JLSAPI_CHIDLREN, When LSAPI_AVOID_FORK is set to 1, the default value ;TI"is LSAPI_CHILDREN.;T@o;;;;[o;;0;[o; ;[I"?LSAPI_MAX_PROCESS_TIME (default value: 300 seconds);T@o; ;[ I"HIn Self Managed Mode, LSAPI_MAX_PROCESS_TIME controls the maximum ;TI"Kprocessing time allowed when processing a request. If a child process ;TI"Jcan not finish processing of a request in the given time period, it ;TI"Mwill be killed by the parent process. This option can help getting rid ;TI"&of dead or runaway child process.;T@o;;;;[o;;0;[o; ;[I")) (Japanese);To;;0;[o; ;[I"@(()) (English);T@o; ;[I"Copyright;TS;;i @o; ;[I"4Copyright (C) 2006 Lite Speed Technologies Inc.;T: @file@:0@omit_headings_from_table_of_contents_below0PK% ]yW֌[[2doc/ruby-lsapi-5.5/ri/Kernel/eval_string_wrap-i.rinu[U:RDoc::AnyMethod[iI"eval_string_wrap:ETI"Kernel#eval_string_wrap;TF: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Verbatim; [ I"2 static int chdir_file( const char * pFile ) ;TI" { ;TI"+ char * p = strrchr( pFile, '/' ); ;TI" int ret; ;TI" if ( !p ) ;TI" return -1; ;TI" p = 0; ;T: @format0o:RDoc::Markup::Paragraph; [I"ret = chdir( pFile );;To; ; [I"p = '/'; ;T; 0o; ; [I"return ret; ;TI"};T: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (p1);T@FI" Kernel;TcRDoc::NormalModule00PK% ]Qzz,doc/ruby-lsapi-5.5/ri/Kernel/cdesc-Kernel.rinu[U:RDoc::NormalModule[iI" Kernel:ET@0o:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[I"eval_string_wrap;TI"ext/lsapi/lsruby.c;T[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[I"ext/lsapi/lsruby.c;T@*cRDoc::TopLevelPK% ]m"0doc/ruby-lsapi-5.5/ri/LSAPI/postfork_parent-c.rinu[U:RDoc::AnyMethod[iI"postfork_parent:ETI"LSAPI::postfork_parent;TT: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]7$doc/ruby-lsapi-5.5/ri/LSAPI/eof-i.rinu[U:RDoc::AnyMethod[iI"eof:ETI"LSAPI#eof;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]] )doc/ruby-lsapi-5.5/ri/LSAPI/readline-i.rinu[U:RDoc::AnyMethod[iI" readline:ETI"LSAPI#readline;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]A&doc/ruby-lsapi-5.5/ri/LSAPI/flush-i.rinu[U:RDoc::AnyMethod[iI" flush:ETI"LSAPI#flush;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]+&doc/ruby-lsapi-5.5/ri/LSAPI/print-i.rinu[U:RDoc::AnyMethod[iI" print:ETI"LSAPI#print;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (*args);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]+B'doc/ruby-lsapi-5.5/ri/LSAPI/reopen-i.rinu[U:RDoc::AnyMethod[iI" reopen:ETI"LSAPI#reopen;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (*args);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]3`(doc/ruby-lsapi-5.5/ri/LSAPI/sync%3d-i.rinu[U:RDoc::AnyMethod[iI" sync=:ETI"LSAPI#sync=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (p1);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]nA%doc/ruby-lsapi-5.5/ri/LSAPI/puts-i.rinu[U:RDoc::AnyMethod[iI" puts:ETI"LSAPI#puts;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (*args);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]3II*doc/ruby-lsapi-5.5/ri/LSAPI/cdesc-LSAPI.rinu[U:RDoc::NormalClass[iI" LSAPI:ET@I" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[ [I" accept;TI"ext/lsapi/lsruby.c;T[I"accept_new_connection;T@[I"postfork_child;T@[I"postfork_parent;T@[:protected[[: private[[I" instance;T[[; [[I"<<;T@[I" binmode;T@[I" close;T@[I" each;T@[I"eof;T@[I" eof?;T@[I" flush;T@[I" getc;T@[I" gets;T@[I" isatty;T@[I" print;T@[I" printf;T@[I" process;T@[I" putc;T@[I" puts;T@[I" read;T@[I" readline;T@[I" reopen;T@[I" rewind;T@[I" sync;T@[I" sync=;T@[I" tty?;T@[I" write;T@[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@ @ cRDoc::TopLevelPK% ]|'doc/ruby-lsapi-5.5/ri/LSAPI/eof%3f-i.rinu[U:RDoc::AnyMethod[iI" eof?:ETI"LSAPI#eof?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]Î'doc/ruby-lsapi-5.5/ri/LSAPI/isatty-i.rinu[U:RDoc::AnyMethod[iI" isatty:ETI"LSAPI#isatty;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]Q%doc/ruby-lsapi-5.5/ri/LSAPI/putc-i.rinu[U:RDoc::AnyMethod[iI" putc:ETI"LSAPI#putc;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (p1);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]&doc/ruby-lsapi-5.5/ri/LSAPI/close-i.rinu[U:RDoc::AnyMethod[iI" close:ETI"LSAPI#close;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]dU&'doc/ruby-lsapi-5.5/ri/LSAPI/printf-i.rinu[U:RDoc::AnyMethod[iI" printf:ETI"LSAPI#printf;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (*args);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]*'doc/ruby-lsapi-5.5/ri/LSAPI/tty%3f-i.rinu[U:RDoc::AnyMethod[iI" tty?:ETI"LSAPI#tty?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]^%doc/ruby-lsapi-5.5/ri/LSAPI/sync-i.rinu[U:RDoc::AnyMethod[iI" sync:ETI"LSAPI#sync;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]{&doc/ruby-lsapi-5.5/ri/LSAPI/write-i.rinu[U:RDoc::AnyMethod[iI" write:ETI"LSAPI#write;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (p1);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]b6doc/ruby-lsapi-5.5/ri/LSAPI/accept_new_connection-c.rinu[U:RDoc::AnyMethod[iI"accept_new_connection:ETI"!LSAPI::accept_new_connection;TT: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]_$%doc/ruby-lsapi-5.5/ri/LSAPI/read-i.rinu[U:RDoc::AnyMethod[iI" read:ETI"LSAPI#read;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (*args);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ] T=%doc/ruby-lsapi-5.5/ri/LSAPI/gets-i.rinu[U:RDoc::AnyMethod[iI" gets:ETI"LSAPI#gets;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]V(doc/ruby-lsapi-5.5/ri/LSAPI/binmode-i.rinu[U:RDoc::AnyMethod[iI" binmode:ETI"LSAPI#binmode;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]z{'doc/ruby-lsapi-5.5/ri/LSAPI/rewind-i.rinu[U:RDoc::AnyMethod[iI" rewind:ETI"LSAPI#rewind;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]O (doc/ruby-lsapi-5.5/ri/LSAPI/process-i.rinu[U:RDoc::AnyMethod[iI" process:ETI"LSAPI#process;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]m/doc/ruby-lsapi-5.5/ri/LSAPI/postfork_child-c.rinu[U:RDoc::AnyMethod[iI"postfork_child:ETI"LSAPI::postfork_child;TT: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]%doc/ruby-lsapi-5.5/ri/LSAPI/each-i.rinu[U:RDoc::AnyMethod[iI" each:ETI"LSAPI#each;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]~%doc/ruby-lsapi-5.5/ri/LSAPI/getc-i.rinu[U:RDoc::AnyMethod[iI" getc:ETI"LSAPI#getc;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]'doc/ruby-lsapi-5.5/ri/LSAPI/%3c%3c-i.rinu[U:RDoc::AnyMethod[iI"<<:ETI" LSAPI#<<;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (p1);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]v>z'doc/ruby-lsapi-5.5/ri/LSAPI/accept-c.rinu[U:RDoc::AnyMethod[iI" accept:ETI"LSAPI::accept;TT: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]edoc/ruby-lsapi-5.5/ri/cache.rinu[{:ancestors{I" LSAPI:ET[I" Object;T@ [I"BasicObject;T:attributes{:class_methods{I" LSAPI;T[ I" accept;TI"accept_new_connection;TI"postfork_child;TI"postfork_parent;T:c_class_variables{ I"ext/lsapi/lsapidef.h;T{I"ext/lsapi/lsapilib.c;T{I"ext/lsapi/lsapilib.h;T{I"ext/lsapi/lsruby.c;T{I" cLSAPI;TI" LSAPI;TI"rb_cObject;T@ I"rb_mKernel;TI" Kernel;T: c_singleton_class_variables{ I"ext/lsapi/lsapidef.h;T{I"ext/lsapi/lsapilib.c;T{I"ext/lsapi/lsapilib.h;T{I"ext/lsapi/lsruby.c;T{: encodingIu: Encoding UTF-8;F:instance_methods{I" LSAPI;T[I"<<;TI" binmode;TI" close;TI" each;TI"eof;TI" eof?;TI" flush;TI" getc;TI" gets;TI" isatty;TI" print;TI" printf;TI" process;TI" putc;TI" puts;TI" read;TI" readline;TI" reopen;TI" rewind;TI" sync;TI" sync=;TI" tty?;TI" write;T@![I"eval_string_wrap;T: main0: modules[@!@@ : pages[I" README;TI"ext/lsapi/Makefile;T: titleI"!ruby-lsapi-5.5 Documentation;TPK% ]GB N,doc/ruby-lsapi-5.5/ri/Object/cdesc-Object.rinu[U:RDoc::NormalClass[iI" Object:ET@I"BasicObject;To:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[U:RDoc::Constant[iI" STDERR;TI"Object::STDERR;T: public0o;;[; I"ext/lsapi/lsruby.c;T; 0@@cRDoc::NormalClass0U; [iI"ENV;TI"Object::ENV;T; 0o;;[o:RDoc::Markup::Paragraph;[I"Nredefine ENV using a hash table, should be faster than char **environment;To:RDoc::Markup::BlankLine; @; 0@@@0[[[I" class;T[[; [[:protected[[: private[[I" instance;T[[; [[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@@cRDoc::TopLevelPK% ]ճ,,0doc/ruby-lsapi-5.6/ri/ext/lsapi/page-Makefile.rinu[U:RDoc::TopLevel[ iI"ext/lsapi/Makefile:ETcRDoc::Parser::Simpleo:RDoc::Markup::Document: @parts[$o:RDoc::Markup::Paragraph;[I"SHELL = /bin/sh;To:RDoc::Markup::BlankLineo; ;[ I"9# V=0 quiet, V=1 verbose. other values don't work. ;TI" V = 0 ;TI"Q1 = $(V:1=) ;TI"Q = $(Q1:0=@) ;TI"ECHO1 = $(V:1=@ :) ;TI"ECHO = $(ECHO1:0=@ echo) ;TI"NULLCMD = :;T@o; ;[I"5#### Start of system configuration section. ####;T@o; ;[8I"srcdir = . ;TI"1topdir = /opt/alt/ruby26/include/ruby-2.6.0 ;TI"hdrdir = $(topdir) ;TI"Carch_hdrdir = /opt/alt/ruby26/include/ruby-2.6.0/x86_64-linux ;TI"PATH_SEPARATOR = : ;TI":VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby ;TI"(prefix = $(DESTDIR)/opt/alt/ruby26 ;TI"7rubysitearchprefix = $(rubylibprefix)/$(sitearch) ;TI"/rubyarchprefix = $(rubylibprefix)/$(arch) ;TI"1rubylibprefix = $(libdir)/$(RUBY_BASE_NAME) ;TI"-exec_prefix = $(DESTDIR)/opt/alt/ruby26 ;TI"4vendorarchhdrdir = $(vendorhdrdir)/$(sitearch) ;TI"0sitearchhdrdir = $(sitehdrdir)/$(sitearch) ;TI",rubyarchhdrdir = $(rubyhdrdir)/$(arch) ;TI".vendorhdrdir = $(rubyhdrdir)/vendor_ruby ;TI"*sitehdrdir = $(rubyhdrdir)/site_ruby ;TI"5rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME) ;TI"1vendorarchdir = $(vendorlibdir)/$(sitearch) ;TI"1vendorlibdir = $(vendordir)/$(ruby_version) ;TI".vendordir = $(rubylibprefix)/vendor_ruby ;TI"=sitearchdir = $(DESTDIR)./.gem.20240125-3712957-1hs47jp ;TI";T@o; ;[I"3#### End of system configuration section. ####;T@o; ;[ I"preload = ;TI"libpath = . $(libdir) ;TI"5LIBPATH = -L. -L$(libdir) -Wl,-rpath,$(libdir) ;TI"DEFFILE = ;T@o; ;[I"CLEANFILES = mkmf.log ;TI"DISTCLEANFILES = ;TI"DISTCLEANDIRS = ;T@o; ;[I"extout = ;TI"extout_prefix = ;TI"target_prefix = ;TI"LOCAL_LIBS = ;TI",LIBS = $(LIBRUBYARG_SHARED) -lm -lc ;TI"%ORIG_SRCS = lsapilib.c lsruby.c ;TI"SRCS = $(ORIG_SRCS) ;TI" OBJS = lsapilib.o lsruby.o ;TI"6HDRS = $(srcdir)/lsapidef.h $(srcdir)/lsapilib.h ;TI"LOCAL_HDRS = ;TI"TARGET = lsapi ;TI"TARGET_NAME = lsapi ;TI"(TARGET_ENTRY = Init_$(TARGET_NAME) ;TI"DLLIB = $(TARGET).so ;TI"EXTSTATIC = ;TI"STATIC_LIB = ;T@o; ;[I"TIMESTAMP_DIR = . ;TI"BINDIR = $(bindir) ;TI"0RUBYCOMMONDIR = $(sitedir)$(target_prefix) ;TI"3RUBYLIBDIR = $(sitelibdir)$(target_prefix) ;TI"4RUBYARCHDIR = $(sitearchdir)$(target_prefix) ;TI"8HDRDIR = $(rubyhdrdir)/ruby$(target_prefix) ;TI"@ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix) ;TI"TARGET_SO_DIR = ;TI".TARGET_SO = $(TARGET_SO_DIR)$(DLLIB) ;TI"#CLEANLIBS = $(TARGET_SO) ;TI"CLEANOBJS = *.o *.bak;T@o; ;[ I"all: $(DLLIB) ;TI"static: $(STATIC_LIB) ;TI"6.PHONY: all install static install-so install-rb ;TI"1.PHONY: clean clean-so clean-static clean-rb;T@o:RDoc::Markup::List: @type: NOTE: @items[o:RDoc::Markup::ListItem: @label[ I"clean-static;TI"clean-rb-default;TI" clean-rb;TI" clean-so;T;[o; ;[I";clean: clean-so clean-static clean-rb-default clean-rb;To:RDoc::Markup::Verbatim;[I"@-$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time ;T: @format0o; ; ; ;[o;;[ I"distclean-rb-default;TI"distclean-rb;TI"distclean-so;TI"distclean-static;T;[/o; ;[I"Udistclean: clean distclean-so distclean-static distclean-rb-default distclean-rb;To;;[I"?-$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log ;TI"8-$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) ;TI":-$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true ;T;0o; ;[I"realclean: distclean ;TI"#install: install-so install-rb;T@o; ;[I"$doc/ruby-lsapi-5.6/ri/page-README.rinu[U:RDoc::TopLevel[ iI" README:ETcRDoc::Parser::Simpleo:RDoc::Markup::Document: @parts[Mo:RDoc::Markup::Paragraph;[I"%lsapi - LSAPI extension for Ruby;TS:RDoc::Markup::Heading: leveli%: textI";To:RDoc::Markup::BlankLineo; ;[I" INSTALL;TS:RDoc::Markup::Rule: weighti @o:RDoc::Markup::Verbatim;[I"$ ruby setup.rb config ;TI"$ ruby setup.rb setup ;TI"# ruby setup.rb install ;T: @format0o; ;[I" USAGE;TS;;i@o; ;[ I"General CGI scripts ;TI"^^^^^^^^^^^^^^^^^^^ ;TI"SThe most efficient way to use LSAPI interface is to modify your CGI scripts. ;TI" ;TI" ... ;TI" ;TI" end ;T;0o; ;[I"LThere is no need to change the way that how CGI environment variables ;TI"(are being accessed in your scripts.;T@o; ;[I"7You can find some examples under examples/ folder.;T@o; ;[ I"Ruby Script Runner ;TI"^^^^^^^^^^^^^^^^^^ ;TI"OIf you don't want to change your existing Ruby CGI code, you can use our ;TI"FRuby script runner under scripts/ folder. You need to configure ;TI"Ilsruby_runner.rb as a LSAPI application, then add a script handler ;TI"for "rb" suffix.;T@@o; ;[I"Rails dispatcher ;TI"^^^^^^^^^^^^^^^^;T@o; ;[I"RWith Ruby LSAPI, we proudly provide a optimum platform for Rails application ;TI"Ndeployment. Ruby LSAPI has the following advantages over other solutions.;T@o;;[ I"M* Easy configuration, deploy a Rails application only take a few clicks ;TI") with our Rails easy configuration ;TI"M* Fast startup, the expensive Rails framework initialization only takes ;TI"= place once when multiple processes need to be started ;TI"J* Resource efficience, ruby processes can be started on demand, idle ;TI" process will be stop. ;T;0o; ;[I"DTo use LSAPI with Ruby on Rails, please check out our toturial ;TI"7http://www.litespeedtech.com/support/wiki/doku.php;T@o; ;[I"MThere are a few environment variables that can be tweaked to tune ruby ;TI"LSAPI process.;T@o:RDoc::Markup::List: @type: BULLET: @items[o:RDoc::Markup::ListItem: @label0;[o; ;[I"/LSAPI_CHILDREN (default: 0);T@o; ;[ I"MLSAPI_CHILDREN controls the maximum number of children processes can be ;TI"Ostarted by the first ruby process started by web server. When set to <=1, ;TI"Pthe first ruby process will handle request by itself, without starting any ;TI"Rchild process. When LSAPI_CHILDREN is >1, the LSAPI application is stared in ;TI"O"Self Managed Mode", which will start children processes based on demand. ;TI"JWith Rails easy configuration, LSAPI_CHILDREN is set to the value of ;TI"C"Max Connections" by web server, no need to set it explicitly.;T@o; ;[I"OUsually, there is no need to set value of LSAPI_CHILDREN over 100 in most ;TI"server environment.;T@o;;;;[o;;0;[o; ;[I"/LSAPI_AVOID_FORK (default: 0);T@o; ;[ I"NLSAPI_AVOID_FORK specifies the policy of the internal process manager in ;TI"P"Self Managed Mode". When set to 0, the internal process manager will stop ;TI"Kand start children process on demand to save system resource. This is ;TI"Lpreferred in a shared hosting environment. When set to 1, the internal ;TI"Pprocess manager will try to avoid freqently stopping and starting children ;TI"Hprocess. This might be preferred in a dedicate hosting environment.;T@o;;;;[o;;0;[o; ;[I"HLSAPI_EXTRA_CHILDREN (default: 1/3 of LSAPI_CHILDREN or 0);T@o; ;[ I"RLSAPI_EXTRA_CHILDREN controls the maximum number of extra children processes ;TI"Hcan be started when some or all existing children processes are in ;TI"Qmalfunctioning state. Total number of children processes will be reduced to ;TI"@LSAPI_CHILDREN level as soon as service is back to normal. ;TI"DWhen LSAPI_AVOID_FORK is set to 0, the default value is 1/3 of ;TI"OLSAPI_CHIDLREN, When LSAPI_AVOID_FORK is set to 1, the default value is 0.;T@o;;;;[o;;0;[o; ;[I"9LSAPI_MAX_REQS (default value: 10000);T@o; ;[I"HLSAPI_MAX_REQS specifies the maximum number of requests each child ;TI"Kprocess will handle before it exits automatically. This parameter can ;TI"Phelp reducing memory usage when there are memory leaks in the application. ;T@o;;;;[o;;0;[o; ;[I"?LSAPI_MAX_IDLE (default value: 300 seconds);T@o; ;[I"HIn Self Managed Mode, LSAPI_MAX_IDLE controls how long a idle child;T@o; ;[I"Hprocess will wait for a new request before exit. This option help ;TI"8releasing system resources taken by idle processes.;T@o;;;;[o;;0;[o; ;[I"LSAPI_MAX_IDLE_CHILDREN;To;;[I">(default value: 1/3 of LSAPI_CHILDREN or LSAPI_CHILDREN) ;T;0o; ;[ I"JIn Self Managed Mode, LSAI_MAX_IDLE_CHILDREN controls how many idle ;TI"Gchildren processes are allowed. Excessive idle children processes ;TI"+will be killed by the parent process. ;TI"DWhen LSAPI_AVOID_FORK is set to 0, the default value is 1/3 of ;TI"JLSAPI_CHIDLREN, When LSAPI_AVOID_FORK is set to 1, the default value ;TI"is LSAPI_CHILDREN.;T@o;;;;[o;;0;[o; ;[I"?LSAPI_MAX_PROCESS_TIME (default value: 300 seconds);T@o; ;[ I"HIn Self Managed Mode, LSAPI_MAX_PROCESS_TIME controls the maximum ;TI"Kprocessing time allowed when processing a request. If a child process ;TI"Jcan not finish processing of a request in the given time period, it ;TI"Mwill be killed by the parent process. This option can help getting rid ;TI"&of dead or runaway child process.;T@o;;;;[o;;0;[o; ;[I")) (Japanese);To;;0;[o; ;[I"@(()) (English);T@o; ;[I"Copyright;TS;;i @o; ;[I"4Copyright (C) 2006 Lite Speed Technologies Inc.;T: @file@:0@omit_headings_from_table_of_contents_below0PK% ]yW֌[[2doc/ruby-lsapi-5.6/ri/Kernel/eval_string_wrap-i.rinu[U:RDoc::AnyMethod[iI"eval_string_wrap:ETI"Kernel#eval_string_wrap;TF: publico:RDoc::Markup::Document: @parts[ o:RDoc::Markup::Verbatim; [ I"2 static int chdir_file( const char * pFile ) ;TI" { ;TI"+ char * p = strrchr( pFile, '/' ); ;TI" int ret; ;TI" if ( !p ) ;TI" return -1; ;TI" p = 0; ;T: @format0o:RDoc::Markup::Paragraph; [I"ret = chdir( pFile );;To; ; [I"p = '/'; ;T; 0o; ; [I"return ret; ;TI"};T: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (p1);T@FI" Kernel;TcRDoc::NormalModule00PK% ]Qzz,doc/ruby-lsapi-5.6/ri/Kernel/cdesc-Kernel.rinu[U:RDoc::NormalModule[iI" Kernel:ET@0o:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[[[[I" class;T[[: public[[:protected[[: private[[I" instance;T[[; [[I"eval_string_wrap;TI"ext/lsapi/lsruby.c;T[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[I"ext/lsapi/lsruby.c;T@*cRDoc::TopLevelPK% ]m"0doc/ruby-lsapi-5.6/ri/LSAPI/postfork_parent-c.rinu[U:RDoc::AnyMethod[iI"postfork_parent:ETI"LSAPI::postfork_parent;TT: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]7$doc/ruby-lsapi-5.6/ri/LSAPI/eof-i.rinu[U:RDoc::AnyMethod[iI"eof:ETI"LSAPI#eof;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]] )doc/ruby-lsapi-5.6/ri/LSAPI/readline-i.rinu[U:RDoc::AnyMethod[iI" readline:ETI"LSAPI#readline;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]A&doc/ruby-lsapi-5.6/ri/LSAPI/flush-i.rinu[U:RDoc::AnyMethod[iI" flush:ETI"LSAPI#flush;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]+&doc/ruby-lsapi-5.6/ri/LSAPI/print-i.rinu[U:RDoc::AnyMethod[iI" print:ETI"LSAPI#print;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (*args);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]+B'doc/ruby-lsapi-5.6/ri/LSAPI/reopen-i.rinu[U:RDoc::AnyMethod[iI" reopen:ETI"LSAPI#reopen;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (*args);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]3`(doc/ruby-lsapi-5.6/ri/LSAPI/sync%3d-i.rinu[U:RDoc::AnyMethod[iI" sync=:ETI"LSAPI#sync=;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (p1);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]nA%doc/ruby-lsapi-5.6/ri/LSAPI/puts-i.rinu[U:RDoc::AnyMethod[iI" puts:ETI"LSAPI#puts;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (*args);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]3II*doc/ruby-lsapi-5.6/ri/LSAPI/cdesc-LSAPI.rinu[U:RDoc::NormalClass[iI" LSAPI:ET@I" Object;To:RDoc::Markup::Document: @parts[o;;[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below0; 0; 0[[[[[I" class;T[[: public[ [I" accept;TI"ext/lsapi/lsruby.c;T[I"accept_new_connection;T@[I"postfork_child;T@[I"postfork_parent;T@[:protected[[: private[[I" instance;T[[; [[I"<<;T@[I" binmode;T@[I" close;T@[I" each;T@[I"eof;T@[I" eof?;T@[I" flush;T@[I" getc;T@[I" gets;T@[I" isatty;T@[I" print;T@[I" printf;T@[I" process;T@[I" putc;T@[I" puts;T@[I" read;T@[I" readline;T@[I" reopen;T@[I" rewind;T@[I" sync;T@[I" sync=;T@[I" tty?;T@[I" write;T@[; [[; [[[U:RDoc::Context::Section[i0o;;[; 0; 0[@ @ cRDoc::TopLevelPK% ]|'doc/ruby-lsapi-5.6/ri/LSAPI/eof%3f-i.rinu[U:RDoc::AnyMethod[iI" eof?:ETI"LSAPI#eof?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]Î'doc/ruby-lsapi-5.6/ri/LSAPI/isatty-i.rinu[U:RDoc::AnyMethod[iI" isatty:ETI"LSAPI#isatty;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]Q%doc/ruby-lsapi-5.6/ri/LSAPI/putc-i.rinu[U:RDoc::AnyMethod[iI" putc:ETI"LSAPI#putc;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (p1);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]&doc/ruby-lsapi-5.6/ri/LSAPI/close-i.rinu[U:RDoc::AnyMethod[iI" close:ETI"LSAPI#close;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]dU&'doc/ruby-lsapi-5.6/ri/LSAPI/printf-i.rinu[U:RDoc::AnyMethod[iI" printf:ETI"LSAPI#printf;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (*args);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]*'doc/ruby-lsapi-5.6/ri/LSAPI/tty%3f-i.rinu[U:RDoc::AnyMethod[iI" tty?:ETI"LSAPI#tty?;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]^%doc/ruby-lsapi-5.6/ri/LSAPI/sync-i.rinu[U:RDoc::AnyMethod[iI" sync:ETI"LSAPI#sync;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]{&doc/ruby-lsapi-5.6/ri/LSAPI/write-i.rinu[U:RDoc::AnyMethod[iI" write:ETI"LSAPI#write;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (p1);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]b6doc/ruby-lsapi-5.6/ri/LSAPI/accept_new_connection-c.rinu[U:RDoc::AnyMethod[iI"accept_new_connection:ETI"!LSAPI::accept_new_connection;TT: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]_$%doc/ruby-lsapi-5.6/ri/LSAPI/read-i.rinu[U:RDoc::AnyMethod[iI" read:ETI"LSAPI#read;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (*args);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ] T=%doc/ruby-lsapi-5.6/ri/LSAPI/gets-i.rinu[U:RDoc::AnyMethod[iI" gets:ETI"LSAPI#gets;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]V(doc/ruby-lsapi-5.6/ri/LSAPI/binmode-i.rinu[U:RDoc::AnyMethod[iI" binmode:ETI"LSAPI#binmode;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]z{'doc/ruby-lsapi-5.6/ri/LSAPI/rewind-i.rinu[U:RDoc::AnyMethod[iI" rewind:ETI"LSAPI#rewind;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]O (doc/ruby-lsapi-5.6/ri/LSAPI/process-i.rinu[U:RDoc::AnyMethod[iI" process:ETI"LSAPI#process;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]m/doc/ruby-lsapi-5.6/ri/LSAPI/postfork_child-c.rinu[U:RDoc::AnyMethod[iI"postfork_child:ETI"LSAPI::postfork_child;TT: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]%doc/ruby-lsapi-5.6/ri/LSAPI/each-i.rinu[U:RDoc::AnyMethod[iI" each:ETI"LSAPI#each;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]~%doc/ruby-lsapi-5.6/ri/LSAPI/getc-i.rinu[U:RDoc::AnyMethod[iI" getc:ETI"LSAPI#getc;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]'doc/ruby-lsapi-5.6/ri/LSAPI/%3c%3c-i.rinu[U:RDoc::AnyMethod[iI"<<:ETI" LSAPI#<<;TF: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I" (p1);T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]v>z'doc/ruby-lsapi-5.6/ri/LSAPI/accept-c.rinu[U:RDoc::AnyMethod[iI" accept:ETI"LSAPI::accept;TT: publico:RDoc::Markup::Document: @parts[: @fileI"ext/lsapi/lsruby.c;T:0@omit_headings_from_table_of_contents_below000[I"();T@ FI" LSAPI;TcRDoc::NormalClass00PK% ]5doc/ruby-lsapi-5.6/ri/cache.rinu[{:ancestors{I" LSAPI:ET[I" Object;T@ [I"BasicObject;T:attributes{:class_methods{I" LSAPI;T[ I" accept;TI"accept_new_connection;TI"postfork_child;TI"postfork_parent;T:c_class_variables{ I"ext/lsapi/lsapidef.h;T{I"ext/lsapi/lsapilib.c;T{I"ext/lsapi/lsapilib.h;T{I"ext/lsapi/lsruby.c;T{I" cLSAPI;TI" LSAPI;TI"rb_cObject;T@ I"rb_mKernel;TI" Kernel;T: c_singleton_class_variables{ I"ext/lsapi/lsapidef.h;T{I"ext/lsapi/lsapilib.c;T{I"ext/lsapi/lsapilib.h;T{I"ext/lsapi/lsruby.c;T{: encodingIu: Encoding UTF-8;F:instance_methods{I" LSAPI;T[I"<<;TI" binmode;TI" close;TI" each;TI"eof;TI" eof?;TI" flush;TI" getc;TI" gets;TI" isatty;TI" print;TI" printf;TI" process;TI" putc;TI" puts;TI" read;TI" readline;TI" reopen;TI" rewind;TI" sync;TI" sync=;TI" tty?;TI" write;T@![I"eval_string_wrap;T: main0: modules[@!@@ : pages[I" README;TI"ext/lsapi/Makefile;T: titleI"!ruby-lsapi-5.6 Documentation;TPK% ]GB N,doc/ruby-lsapi-5.6/ri/Object/cdesc-Object.rinu[U:RDoc::NormalClass[iI" Object:ET@I"BasicObject;To:RDoc::Markup::Document: @parts[: @file0:0@omit_headings_from_table_of_contents_below0[[U:RDoc::Constant[iI" STDERR;TI"Object::STDERR;T: public0o;;[; I"ext/lsapi/lsruby.c;T; 0@@cRDoc::NormalClass0U; [iI"ENV;TI"Object::ENV;T; 0o;;[o:RDoc::Markup::Paragraph;[I"Nredefine ENV using a hash table, should be faster than char **environment;To:RDoc::Markup::BlankLine; @; 0@@@0[[[I" class;T[[; [[:protected[[: private[[I" instance;T[[; [[;[[;[[[U:RDoc::Context::Section[i0o;;[; 0; 0[@@cRDoc::TopLevelPK% ]Gm__9extensions/x86_64-linux/2.6.0/ruby-lsapi-5.5/gem_make.outnu[current directory: /builddir/build/BUILD/opt/alt/ruby26/lib64/ruby/gems/2.6.0/gems/ruby-lsapi-5.5/ext/lsapi /opt/alt/ruby26/bin/ruby -I /opt/alt/ruby26/lib64/ruby/2.6.0 -r ./siteconf20230713-3059785-1ocv8su.rb extconf.rb current directory: /builddir/build/BUILD/opt/alt/ruby26/lib64/ruby/gems/2.6.0/gems/ruby-lsapi-5.5/ext/lsapi make "DESTDIR=" clean current directory: /builddir/build/BUILD/opt/alt/ruby26/lib64/ruby/gems/2.6.0/gems/ruby-lsapi-5.5/ext/lsapi make "DESTDIR=" current directory: /builddir/build/BUILD/opt/alt/ruby26/lib64/ruby/gems/2.6.0/gems/ruby-lsapi-5.5/ext/lsapi make "DESTDIR=" install PK% ]8M>5extensions/x86_64-linux/2.6.0/ruby-lsapi-5.5/mkmf.lognu[have_library: checking for -lsocket... -------------------- no "gcc -o conftest -I/opt/alt/ruby26/include/ruby-2.6.0/x86_64-linux -I/opt/alt/ruby26/include/ruby-2.6.0/ruby/backward -I/opt/alt/ruby26/include/ruby-2.6.0 -I. -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection conftest.c -L. -L/opt/alt/ruby26/lib64 -Wl,-rpath,/opt/alt/ruby26/lib64 -L. -Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -fstack-protector-strong -rdynamic -Wl,-export-dynamic -m64 -Wl,-rpath,/opt/alt/ruby26/lib64 -L/opt/alt/ruby26/lib64 -lruby -lm -lc" checked program was: /* begin */ 1: #include "ruby.h" 2: 3: int main(int argc, char **argv) 4: { 5: return 0; 6: } /* end */ "gcc -o conftest -I/opt/alt/ruby26/include/ruby-2.6.0/x86_64-linux -I/opt/alt/ruby26/include/ruby-2.6.0/ruby/backward -I/opt/alt/ruby26/include/ruby-2.6.0 -I. -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection conftest.c -L. -L/opt/alt/ruby26/lib64 -Wl,-rpath,/opt/alt/ruby26/lib64 -L. -Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -fstack-protector-strong -rdynamic -Wl,-export-dynamic -m64 -Wl,-rpath,/opt/alt/ruby26/lib64 -L/opt/alt/ruby26/lib64 -lruby -lsocket -lm -lc" /usr/bin/ld: cannot find -lsocket collect2: error: ld returned 1 exit status checked program was: /* begin */ 1: #include "ruby.h" 2: 3: /*top*/ 4: extern int t(void); 5: int main(int argc, char **argv) 6: { 7: if (argc > 1000000) { 8: int (* volatile tp)(void)=(int (*)(void))&t; 9: printf("%d", (*tp)()); 10: } 11: 12: return 0; 13: } 14: 15: int t(void) { ; return 0; } /* end */ -------------------- PK% ]?extensions/x86_64-linux/2.6.0/ruby-lsapi-5.5/gem.build_completenu[PK% ]Dk--5extensions/x86_64-linux/2.6.0/ruby-lsapi-5.5/lsapi.sonuȯELF>U@&@8 @ !!0 !!888$$hhh Stdhhh PtdPPPQtdRtd!!P P GNU5<-s흏2bC H‚3@(L`qCSlP*fRn}'3qѮl>&Sɶ ܮʼnSO`[is|&߱RD/y7řkՊ eY&09=By:%/=ejOzJ6'l#mNULCB1{!\$O#W23S=apbU06aD7jp#7ĴDIΊ=\4yݾCEкQuo rSѮIo|q%h6 󝵛 ' =qX[ u  f   d ysOq    T [M f A k &K ! , 2TRT" s G +L  } >W  9 - kH  .E   $7x9 vo | Z A 9J 4, 2> F"`| E]   r G p `}F 0rD @I  `K 5 0vi~  z@! b П. P! ] Z\ g o  v 1 r Y ` Pq@  @ sl zj V } - Ps]   `o @rY po  5 o x$ Pl! u U U E v rS o7 @oT (   0  }F rJ @pT ! P~I   Е  P!b g  @g "! l p6 o p [ !__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizecompareValueLocationset_skip_writesigactionsigemptyset__stack_chk_failreallocfcntlacceptsetsockoptmmapmemsetsetsidread__errno_locationclosewritevkillgetppid__ctype_b_locstrncpystrchrstrcasecmpstrtolgetaddrinfomemcpyfreeaddrinfoinet_addrLSAPI_Log__vfprintf_chk__snprintf_chkgetuid__fprintf_chkgettimeofdaylocaltime_rwaitpidforksystemexitlsapi_perrorstrerrorLSAPI_is_suEXEC_DaemonLSAPI_StopLSAPI_IsRunningLSAPI_Register_Pgrp_Timer_CallbackLSAPI_InitRequestmallocgetpeernamedup2LSAPI_Initgeteuidsignalg_reqdlopendlsymLSAPI_Is_Listen_rLSAPI_Is_ListenLSAPI_Reset_rLSAPI_Release_rfreeLSAPI_GetHeader_rLSAPI_ReqBodyGetChar_rLSAPI_ReqBodyGetLine_rmemchrmemmoveLSAPI_ReadReqBody_rFlush_RespBuf_rLSAPI_GetEnv_rstrcmp__ctype_toupper_locLSAPI_ForeachOrgHeader_rqsortLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rLSAPI_ForeachSpecialEnv_rLSAPI_FinalizeRespHeaders_rLSAPI_Flush_rLSAPI_Write_Stderr_rgetpidgetcwdmemccpy__realpath_chkLSAPI_Finish_rLSAPI_End_Response_rLSAPI_Write_rLSAPI_sendfile_rsendfileLSAPI_AppendRespHeader2_rstrlenLSAPI_AppendRespHeader_rLSAPI_CreateListenSock2socketbindlistenunlinkLSAPI_ParseSockAddrLSAPI_CreateListenSockLSAPI_Init_Prefork_ServercallocsetpgidsysconfLSAPI_Set_Server_fdLSAPI_reset_server_stateis_enough_free_memLSAPI_Postfork_ChildLSAPI_Postfork_ParenttimeLSAPI_Accept_Before_Fork__fdelt_chkusleepsched_yieldLSAPI_Set_Max_ReqsLSAPI_Set_Max_IdleLSAPI_Set_Max_ChildrenLSAPI_Set_Extra_ChildrenLSAPI_Set_Max_Process_TimeLSAPI_Set_Max_Idle_ChildrenLSAPI_Set_Server_Max_Idle_SecsLSAPI_Set_Slow_Req_MsecsLSAPI_Get_Slow_Req_MsecsLSAPI_No_Check_ppidLSAPI_Get_ppidLSAPI_Init_Env_Parametersgetenvgetpwnamdlerrorsetrlimit__fxstatsetreuidLSAPI_ErrResponse_rlsapi_MD5Initlsapi_MD5Updatelsapi_MD5FinalgetpwuidsetgidsetgroupssetuidstrtollprctlinitgroupsLSAPI_Accept_rLSAPI_Prefork_Accept_rsigaddsetsigprocmaskLSAPI_Set_Restored_Parent_PidLSAPI_Inc_Req_Processedselectrb_tainted_str_newrb_hash_asetrb_funcallvrb_intern2rb_gc_markmunmaprb_check_typerb_obj_as_stringrb_f_sprintfs_fn_add_envrb_safe_levelrb_string_value_ptrrb_eval_string_wraprb_string_valuerb_check_safe_objrb_ruby_verbose_ptrrb_define_global_construby_strdupmkstempftruncaterb_str_buf_newrb_str_catrb_num2intrb_fix2intrb_eSecurityErrorrb_raisememmemrb_yieldrb_gc_writebarrier_unprotectrb_io_putsrb_ary_detransientrb_str_new_staticrb_exec_recursiverb_default_rsrb_output_fsrb_output_rsrb_lastline_getInit_lsapichdirrb_stderrrb_cObjectrb_const_getrb_global_variablerb_define_global_functionrb_define_classrb_define_singleton_methodrb_define_methodrb_data_object_zallocrb_stdoutrb_stdinrb_hash_new__memcpy_chklibruby.so.2.6libm.so.6libc.so.6__environ_edata__bss_start_endGLIBC_2.14GLIBC_2.15GLIBC_2.4GLIBC_2.3.4GLIBC_2.2.5GLIBC_2.3/opt/alt/ruby26/lib64@ l w ii  ti  ui  ii  !U!pU!!!!!!!!!! !(!0! 8!@!*H!8P!CX!P`!_h!fp!nx!s!z!!!!!!!!!!!!!!!2!G !\(!o0!8!@!H!P!X!`!h!p!x!!!!2!@!Y!i!t!!!!!!!X!!!!H!P!X!`!h!p!x!!!$!5!!?!K!M!U!Y!Y!Z!!!q!!! ! ! ! ! ! ! !( !0 !8 !@ !H ! P ! X ! ` ! h ! p !x ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !( ! 0 !8 !"@ !#H !%P !&X !` !'h !(p !)x ! !* !+ ! !, ! ! ! !- !. !/ !0 ! ! ! ! !1 !2 !3 ! !4 !( !0 !68 !7@ !8H !9P !:X !;` !<h !>p !@x !A !B !C ! !D !E !F !G !H !I ! !J ! !L !N !O !P !Q !R ! !S !T( !0 !V8 !@ !WH !XP ![X !\` !]h !^p !_x !` !a ! !b !c ! !d !e !f !g !h !i !j !k !l !m !!n!o!p! !(!r0!s8!t@!uH!vP!X!w`!xh!yp!{x!|!}!~!!!!!!!!!!!!!!!!!! !(!0!8!@!HH! HtH5J %K hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhA% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݾ D%վ D%; D%ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݽ D%ս D%ͽ D%Ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݼ D%ռ D%ͼ D%ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݻ D%ջ D%ͻ D%Ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݺ D%պ D%ͺ D%ź D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E DH= H H9tH6 Ht H= H5 H)HHH?HHtH HtfD=e u+UH=b Ht H=. d= ]wff. ÐHGH+FHcAVIH@AUATL$USHtQHHtIHIL9r 0HI9v'KHSMsH;Յ[]A\A]A^[D]A\A]A^øff.f= D2 ÐO AWDD_AVAUATUSD6^nAxj׋G3G D!3G V\$ЋW^$DD1\$!3WAʋN Fp $E‰L$A1A1DD^ !D1G;νD\$DEDVDT$A!A1EE|A 1AD!E1DD*ƇGD1D!A1A1DDN DL$E F0D!DnA1D1DGFEDf Dd$D^(A!A1EEؘiA 1AD!1DDDʋ^0D1D!A1DE [D 1!D1DDN,A1DL$G\EA!Df8A1ED"kA 1AD!1DDN4EqDD1!1DE CyD 1!D1DDV<1G!I!1DDD$ Eb%1!1DDD$E@@1!1DDD$ EQZ^&1!1DE6Ƕ1!1DD]/։ 1!1DESD1!1DE ؉ 1!1DDD$E01!1DDD$ E!1!1DE7É1!1DDD$ E 1!1DDD$A0ZEAA1A!A1AA㩉A AD1!1t$DD1!A ogD1 1D!FL*1DD$Ή1AA!B9A1DD$A AD1D$qDD11‹D$ 0"amD1G 81Ɖ11DDD$ ED꾤11DDD$AKAA1A5`KA1AЉApA 1AD1D1D1A ~(D 1G'111DDD$ A0AA1A1AЋT$A2A1D1֋T$ 9ىDD11D11C|A A1A1AD$A0eVĉA1D1AD")Dt$ D D1A *CDG# 1  1DD9Ή 1DDY[e\$  1DE Dt$ щ1DE3}D\$  1DDD$E] 1DEO~oA AD 1DE ,DT$ A1ADE6CDt$ AN 1A~SADEAA A1A5:ADA AD 1Љ3*\$D D1DFӆ[ ]A\A]A^ 1։ 1DƉA4A_ OW GOW ATI1USHdH%(H$1HHH<$t)H$dH3%(uL{8IHC0L)H9>Lt$L+{(LA@LLfIM)MK H@σLSLCpNIHDI0HI@HKpM~HC(MxIH E1I@HC8HL1HMLIHHKpH9eHMthILM)MUI9t H)tDL+t$HL[]A\A]A^A_DM@@M)(+IHt$HLHk8f.HAVLAUIATIUSHu\H߉[AD${LǃLSHu0{L[L]A\A]A^K[H]A\A]A^Hff.AWAVAUATUSHHHHD$ 0xIHIHLc\CHcT t u(HDLcLH t tLÅ~6HcAT t u#H@Å~ALH t tE<AG=I|$PHHTI9T$Hs7HI+t$@L2%))I|$PLHHcAMt$PHLIFID$PA:I|$P}MD$PII@ID$PAIc$0fET8HЃA$0D$ H[]A\A]A^A_D$ ff.H HB=0AUATUSHcHfDA< t< uH؅uH[]A\A]IHPHHDI9D$Hs3HI+t$@L2%))tQI|$PHHAPI\$PHCID$PIc$0fET8HЃA$0H1[]A\A]øSDAUATAUHSH?dH%(HD$1D$ff t1fHL$dH3 %(H[]A\A]ÐA1ҾÃtʼnǺ1HL$Aߺ踿u#DH'uDo̾߻D HJDeOAkDH}An衾}NSHtff.USHdH%(H$1HHu/HH$dH3%(uHĘ[]Ŀ@1H= tAUATA'USH݋ 'DNuD H@AHH^ HHtH- t YƉlj JUDk HM DcEuSH8dH%(H$(1=HtH H=H H=_>HE1 H讹H=Y>Ht 1H膹 H=E>ijHHt 1H]IAąWE1H=">萳Ht 1H, H=>jHtHǺ 1_H==CH H==$HtHǺ 1IԶH==H1 H舸OH==òHtHǺ 1_H==蜲HtHǺ 18!H==uHtHǺ 1H==NHtHǺ 1蓲H=r='HtMH=p=Ht 1H護ۀ _H=X=Ht 1H D   EH=$=H=r u Pe 5[ H=&=cH 1H% …t% HQv HHHHD L*=L =L#=C HLt@HֹL€D t%HtAHHt9HLuHfDHJHHJHuHHu1ۉH$(dH3%(H8[]A\A]fD& H覲D9舭HHiHǺ11˵ÃHT$ƿD$(?H5/ رHgH Htxc@dx@D  E9D E)ZfH=}8贬 HK]  u t 'j X '> )fՅtbH H-DHH5?1 cAHc螲L%~ HH~ a蓮Åt=~ 0~ u ~ 5~ `HH5@?uHH5>1u HH5>Fff.AVIAUEATIUHSHt4Hu!(fDHH蔭HLgH]HuMtEL [1]A\A]A^ÐIcLLH#EgHGHHܺvT2HGAWAVAAUIATUHoSH1HGO@ƉWDW?t;AĉDHH|@D)A9rhAGt4LLDHL9A?vWEfAIIIH޺@HH@ HLL9uA?DLHH[]A\A]A^A_ܱIATLfUHSFH?LHz?)ƒw=t19rLHfCAD$AD$ ID$071)"HCHLHCP?o H{1HMHHCPH)KXH[]A\ff.fAWAVAUATUSHdH%(H$1Ht^ IAfMcg IoA_@LH3HuM88u =Yw uٽH$dH3 %( HĨ[]A\A]A^A_f~AAuIALJf8LS|xr@tPHf@HPXN MgA;G ZA9~uEo)HHcIHLD"Hu$'85Dv uAMgA9ID$,HD$HcIIDhAh(A9}A /HcIH4@HUHAIIh$A9}A HcIH4@HHAIIHl$p(ILHIILp$hMIc@o9gIcP[9SIcpG9?IcH39+IHHHHIHT$IIc@ H)IHHIHHHIHIIcHIHHHD$I9E1DL4t9dfH H IGAG IPH f@ f@ HHP P H HPPHHPPHHPPHHPPf@f@f@HH#PP H H'P#P$H$H+P'P(f@f@!f@%H(P+f@)I1 fDIHcȋL4t#fBIHT4 rfB@2JHHuMIcP IHHH9pH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@pHH9wMApIbIc@ IH0zu ALJt`!u u Au 1LHc迩IHIGAo IuID%t D-t B(AA1IcH4IILI 9HqH=W. IJDB(9xHqH=2. XIJB($AD$IKAzHL$;MbfoOt Lt$ LAoL$AT$Ml$)$踪 LL(HL$LHLLH$ID$H$I3L$H1H D$$Dl$EDDl$H=s IHIDEs MH=$s t"LDLŃP|$臨Et$A9uHt$莤D=Ń5r $A?D5r t 0AH5*L*HtHHr f)r #AH5:e 1;H@H5+1YLH 1HIH531H531D%q q DD$$H=q IHtZEW7E1111H=3H5*1耨E|$迦M2;|$藦E1H5*LuI}觧Ń1H5*LKfD=p -p p ED$AIFH5*1覧HH)H51H1聧1H5!*L 1H5C2LA#LH 3H H=NQ HL~H-> H 4> H=H HP HzH HJH*HQ H]> HH> HH=P LH5}H = H="H HP HH HJH*H踀yH(yHHP 1aH5P H=}H3H=r}yH(H[]A\A]@HPHH=L }HwHL H.XXXXXXH(Ht+H=uH=O 1HxH5,H=O 1HJfDmHzHfKHzHt -GF OkHyHu-*F 2HHAnonymous mmap() failedlocalhost%02d:%02d:%02d [%s] [UID:%d][%d] %.*syesnosystem()%s, errno: %d (%s) /dev/nulllibpthread.sopthread_atforkHTTP_[UID:%d][%d] %s:%s: %s LSAPI: jail() failure./etc/Can't set signalsaccept() failedLSAPI_STDERR_LOGPHP_LSAPI_MAX_REQUESTSLSAPI_MAX_REQSLSAPI_KEEP_LISTENLSAPI_AVOID_FORKLSAPI_ACCEPT_NOTIFYLSAPI_SLOW_REQ_MSECSLSAPI_ALLOW_CORE_DUMPLSAPI_MAX_IDLEPHP_LSAPI_CHILDRENLSAPI_EXTRA_CHILDRENLSAPI_MAX_IDLE_CHILDRENLSAPI_PGRP_MAX_IDLELSAPI_MAX_PROCESS_TIMELSAPI_PPID_NO_CHECKLSAPI_MAX_BUSY_WORKERLSAPI_DUMP_DEBUG_INFOnobodyLSAPI_DEFAULT_UIDLSAPI_DEFAULT_GIDLSAPI_SECRETLSAPI_LVE_ENABLEliblve.so.0lve_is_availablelve_instance_initlve_destroylve_enterlve_leavejailPHP_LSAPI_PHPRC=packetLen < 0 packetLen > %d Bad request header - ERROR#1 ParseRequest error SUEXEC_AUTHSUEXEC_UGIDLSAPI: setgid()LSAPI: initgroups()LSAPI: setgroups()LSAPI: setuid()Bad request header - ERROR#2 lsapi_accept() errorPragma: no-cacheRetry-After: 60Content-Type: text/htmlDEBUGNOTICEWARNERRORCRITFATALAcceptAccept-CharsetAccept-EncodingAccept-LanguageAuthorizationConnectionContent-TypeContent-LengthCookieCookie2HostPragmaRefererUser-AgentCache-ControlIf-Modified-SinceIf-MatchIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveX-Forwarded-ForViaTransfer-EncodingHTTP_ACCEPTHTTP_ACCEPT_CHARSETHTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_AUTHORIZATIONHTTP_CONNECTIONCONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_COOKIE2HTTP_HOSTHTTP_PRAGMAHTTP_REFERERHTTP_USER_AGENTHTTP_CACHE_CONTROLHTTP_IF_MODIFIED_SINCEHTTP_IF_MATCHHTTP_IF_NONE_MATCHHTTP_IF_RANGEHTTP_IF_UNMODIFIED_SINCEHTTP_KEEP_ALIVEHTTP_RANGEHTTP_X_FORWARDED_FORHTTP_VIAHTTP_TRANSFER_ENCODING%04d-%02d-%02d %02d:%02d:%02d.%06d Child process with pid: %d was killed by signal: %d, core dumped: %s Possible runaway process, UID: %d, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld gdb --batch -ex "attach %d" -ex "set height 0" -ex "bt" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2Force killing runaway process PID: %d with SIGKILL Killing runaway process PID: %d with SIGTERM Children tracking is wrong: Cur Children: %d, count: %d, idle: %d, dying: %d LSAPI: LVE jail(%d) result: %d, error: %s ! Invalid custom stderr log pathFailed to open custom stderr logCan't set signal handler for SIGCHILDReached max children process limit: %d, extra: %d, current: %d, busy: %d, please increase LSAPI_CHILDREN. LSAPI: failed to open secret file: %s! LSAPI: failed to check state of file: %s! LSAPI: file permission check failure: %s LSAPI: failed to read secret from secret file: %s LSAPI: Unable to initialize LVERequest header does match total size, total: %d, real: %ld LSAPI: missing SUEXEC_UGID env, use default user! LSAPI: SUEXEC_AUTH authentication failed, use default user! LSAPI: lve_enter() failure, reached resource limit.prctl: Failed to set dumpable, core dump may not be available!sigprocmask(SIG_BLOCK) to block SIGCHLDsigprocmask( SIG_SETMASK ) to restore SIGMASK in childfork() failed, please increase process limitsigprocmask( SIG_SETMASK ) to restore SIGMASKCache-Control: private, no-cache, no-store, must-revalidate, max-age=0PID 508 Resource Limit Is Reached

Resource Limit Is Reached

The website is temporarily unable to service your request as it exceeded resource limit. Please try again later.
          replacesrandQUERY_STRINGREQUEST_URIPATH_INFOREQUEST_PATHSCRIPT_NAMESTDERRreopenftruncate() failed. File mapping failed. Memory calloc error[...]nilLSAPI_MAX_BODYBUF_LENGTHLSAPI_TEMPFILEXXXXXXRACK_ROOTchdir()to_hashCGI/1.2eval_string_wrapLSAPIacceptaccept_new_connectionpostfork_childpostfork_parentprocessputcwriteprintprintfputs<<flushgetcgetsreadrewindeacheofeof?closebinmodeisattytty?syncsync=RACK_ENVInsecure: operation on untainted IOGATEWAY_Irewindable_input.rbNTERFACE/tmp/lsapi.XXXXX;z@Ze pp8pLp`pt q0q@qx00ydyxyPzz|$|t}~<Pd$@ppH p  0 @ Ќ 0 D PX t ` Џ 8 PL p P d `x p ph ` (pt@ @pp0<PPdx`Я,@T h@|`й4Ptp@ L $@8pL`tp00\Pxp@,`x`@ pHzRx $@V FJ w?:*3$"D` \0lp,l(l L$lsEIB E(A0z (A BBBI A (D BBBA Tl Pl@LlYGJB B(A0A80F(B DBb0ThsBFC G  AABK sk( tGADJ n AAA 4DtUAGK R CAG L JCG ltAG] AJ $tt C KFLHuBBE A(H0H (D BBBD  (D BBBA PtvvFB A(D0D (A BBBB L(A BBBA$vaAAD XAAHwBBB B(A0A8D@N 8C0A(B BBBH $`wOAf Q C E H@wYBBB A(D0J 0A(A BBBF xzFEA C(G   (A ABBD M I c A  E M A k E E E E H V HHT|FBB B(A0A8D`` 8A0A(B BBBD l}+BBB B(A0D8JYHPC Mi 8A0A(B BBBE LTMDd~6BBB B(A0A8DP 8A0A(B BBBG  8J0H(G DBBK $l`7EFF IIOx | 4xFAA G>  AABG EO D  A @ ThY|JED$S p]Ph H XAHlFBB B(A0A8LP 8A0A(B BBBH <Є FBB A(A0 (D BBBI \i`pFBB B(A0A8DP~ 8A0A(B BBBA k 8A0A(B BBBH L$FBB A(A0H Q D 0A(A BBBH L$FBB B(A0A8G 8A0A(B BBBF thFF$lnCXJLDlFBB B(A0A8DA 8A0A(B BBBA `( dBBB B(A0A8G I K I L N N w 8A0A(B BBBI 0 BMD GL  AABA < |=BAA G L@I@U  AABG $ |TWEHG ( ag H SHL pFBB B(A0A8DPS 8D0A(B BBBF T bIE D(C0P (F BBBM Q(H BBBAH lFBB B(A0A8DP 8A0A(B BBBA T< CBA A(G0` (A ABBD  (C ABBA J8 Ȗ-FBD D(D@T (A ABBB  ( ȗlECGF AAI L !cBG A(D0 (A ABBE XD0` t Z D10 ppFAA G@7  AABF  @LsL КFBB B(A0A8G 8A0A(B BBBG < P d x    Ȟ Ԟ  О  ̞Ȟ <Ğ FBA K(G (A ABBG <XFEE D(D0M (C BBBB ԧ(HFBH E(A0E8I@ 8A0A(B BBBE (FED ABH$8 BBB B(A0A8G 8A0A(B BBBJ Dp̴FBB A(A0G 0A(A BBBF L4 FBB B(A0A8G  8A0A(B BBBA 4 H\+p(BFGA kFB4zD O E  HU gHQ G <ayd(THEDL ] CAJ ELEY HW HW-Hd(EAD  DAJ ,aED y AE HP FBB E(D0C8GPm 8F0A(B BBBG ,ZAD J ABL 4PoAD  AAK pP \FBD C(G0 (D ABBE j (D ABBE | (G DBBA HdhFBB B(A0A8G@ 8D0A(B BBBD 7^UVvd1",a^E7Y:LP*%p 'P-Eҁ<whoIs2@:ra0l h|w/OR8 #iXtIsBe1q~]|IP9t¨Cv؈s+@r|HS6aRawoto %1ɯ`1/bcRۆP;[0jdZE7TB^:kW/#Iƒ~fpBDURnew·]9 x4M xovyC arD^U;t6#&YCçFZ#`ٔSÕ/7Elqb#SIS,Ko>_]Vp1}=50CoFլ8XgEe+6%(4oOc/$md٤Ũ;xuXx+5E^uCĵ,I)PZ5#ǯ>v>} /`sw[m^"a"Iz09بa~d5*_Mt++!T´TN;GO>jiVnƈw%ZsyX:70ER54$nEWraR{ D'c#DqDMX/3%oRQZWb^· O |a=LQuU)JUsjC q2εxR.8mHP Hq1b A $z")nT\?Iށ-#f ]p2:U]d,D.I 1000000) { 8: int (* volatile tp)(void)=(int (*)(void))&t; 9: printf("%d", (*tp)()); 10: } 11: 12: return 0; 13: } 14: 15: int t(void) { ; return 0; } /* end */ -------------------- PK% ]?extensions/x86_64-linux/2.6.0/ruby-lsapi-5.6/gem.build_completenu[PK% ]Sxs@--5extensions/x86_64-linux/2.6.0/ruby-lsapi-5.6/lsapi.sonuȯELF>U@&@8 @ !!0 !!888$$hhh Stdhhh PtdPPPQtdRtd!!P P GNUIրmQ1v"C H‚3@(L`qCSlP*fRn}'3qѮl>&Sɶ ܮʼnSO`[is|&߱RD/y7řkՊ eY&09=By:%/=ejOzJ6'l#mNULCB1{!\$O#W23S=apbU06aD7jp#7ĴDIΊ=\4yݾCEкQuo rSѮIo|q%h6 󝵛 ' =qX[ u  f   d ysOq    T [M f A k &K ! , 2TRT" s G +L  } >W  9 - kH  .E   $7x9 vo | Z A 9J 4, 2> F"`| E]   r G p `}F 0rD @I  `K 5 0vi~  z@! b П. P! ] Z\ g o  v 1 r Y ` Pq@  @ sl zj V } - Ps]   `o @rY po  5 o x$ Pl! u U U E v rS o7 @oT (   0  }F rJ @pT ! P~I   Е  P!b g  @g "! l p6 o p [ !__gmon_start___ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizecompareValueLocationset_skip_writesigactionsigemptyset__stack_chk_failreallocfcntlacceptsetsockoptmmapmemsetsetsidread__errno_locationclosewritevkillgetppid__ctype_b_locstrncpystrchrstrcasecmpstrtolgetaddrinfomemcpyfreeaddrinfoinet_addrLSAPI_Log__vfprintf_chk__snprintf_chkgetuid__fprintf_chkgettimeofdaylocaltime_rwaitpidforksystemexitlsapi_perrorstrerrorLSAPI_is_suEXEC_DaemonLSAPI_StopLSAPI_IsRunningLSAPI_Register_Pgrp_Timer_CallbackLSAPI_InitRequestmallocgetpeernamedup2LSAPI_Initgeteuidsignalg_reqdlopendlsymLSAPI_Is_Listen_rLSAPI_Is_ListenLSAPI_Reset_rLSAPI_Release_rfreeLSAPI_GetHeader_rLSAPI_ReqBodyGetChar_rLSAPI_ReqBodyGetLine_rmemchrmemmoveLSAPI_ReadReqBody_rFlush_RespBuf_rLSAPI_GetEnv_rstrcmp__ctype_toupper_locLSAPI_ForeachOrgHeader_rqsortLSAPI_ForeachHeader_rLSAPI_ForeachEnv_rLSAPI_ForeachSpecialEnv_rLSAPI_FinalizeRespHeaders_rLSAPI_Flush_rLSAPI_Write_Stderr_rgetpidgetcwdmemccpy__realpath_chkLSAPI_Finish_rLSAPI_End_Response_rLSAPI_Write_rLSAPI_sendfile_rsendfileLSAPI_AppendRespHeader2_rstrlenLSAPI_AppendRespHeader_rLSAPI_CreateListenSock2socketbindlistenunlinkLSAPI_ParseSockAddrLSAPI_CreateListenSockLSAPI_Init_Prefork_ServercallocsetpgidsysconfLSAPI_Set_Server_fdLSAPI_reset_server_stateis_enough_free_memLSAPI_Postfork_ChildLSAPI_Postfork_ParenttimeLSAPI_Accept_Before_Fork__fdelt_chkusleepsched_yieldLSAPI_Set_Max_ReqsLSAPI_Set_Max_IdleLSAPI_Set_Max_ChildrenLSAPI_Set_Extra_ChildrenLSAPI_Set_Max_Process_TimeLSAPI_Set_Max_Idle_ChildrenLSAPI_Set_Server_Max_Idle_SecsLSAPI_Set_Slow_Req_MsecsLSAPI_Get_Slow_Req_MsecsLSAPI_No_Check_ppidLSAPI_Get_ppidLSAPI_Init_Env_Parametersgetenvgetpwnamdlerrorsetrlimit__fxstatsetreuidLSAPI_ErrResponse_rlsapi_MD5Initlsapi_MD5Updatelsapi_MD5FinalgetpwuidsetgidsetgroupssetuidstrtollprctlinitgroupsLSAPI_Accept_rLSAPI_Prefork_Accept_rsigaddsetsigprocmaskLSAPI_Set_Restored_Parent_PidLSAPI_Inc_Req_Processedselectrb_tainted_str_newrb_hash_asetrb_funcallvrb_intern2rb_gc_markmunmaprb_check_typerb_obj_as_stringrb_f_sprintfs_fn_add_envrb_safe_levelrb_string_value_ptrrb_eval_string_wraprb_string_valuerb_check_safe_objrb_ruby_verbose_ptrrb_define_global_construby_strdupmkstempftruncaterb_str_buf_newrb_str_catrb_num2intrb_fix2intrb_eSecurityErrorrb_raisememmemrb_yieldrb_gc_writebarrier_unprotectrb_io_putsrb_ary_detransientrb_str_new_staticrb_exec_recursiverb_default_rsrb_output_fsrb_output_rsrb_lastline_getInit_lsapichdirrb_stderrrb_cObjectrb_const_getrb_global_variablerb_define_global_functionrb_define_classrb_define_singleton_methodrb_define_methodrb_data_object_zallocrb_stdoutrb_stdinrb_hash_new__memcpy_chklibruby.so.2.6libm.so.6libc.so.6__environ_edata__bss_start_endGLIBC_2.14GLIBC_2.15GLIBC_2.4GLIBC_2.3.4GLIBC_2.2.5GLIBC_2.3/opt/alt/ruby26/lib64@ l w ii  ti  ui  ii  !U!pU!!!!!!!!!! !(!0! 8!@!*H!8P!CX!P`!_h!fp!nx!s!z!!!!!!!!!!!!!!!2!G !\(!o0!8!@!H!P!X!`!h!p!x!!!!2!@!Y!i!t!!!!!!!X!!!!H!P!X!`!h!p!x!!!$!5!!?!K!M!U!Y!Y!Z!!!q!!! ! ! ! ! ! ! !( !0 !8 !@ !H ! P ! X ! ` ! h ! p !x ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !( ! 0 !8 !"@ !#H !%P !&X !` !'h !(p !)x ! !* !+ ! !, ! ! ! !- !. !/ !0 ! ! ! ! !1 !2 !3 ! !4 !( !0 !68 !7@ !8H !9P !:X !;` !<h !>p !@x !A !B !C ! !D !E !F !G !H !I ! !J ! !L !N !O !P !Q !R ! !S !T( !0 !V8 !@ !WH !XP ![X !\` !]h !^p !_x !` !a ! !b !c ! !d !e !f !g !h !i !j !k !l !m !!n!o!p! !(!r0!s8!t@!uH!vP!X!w`!xh!yp!{x!|!}!~!!!!!!!!!!!!!!!!!! !(!0!8!@!HH! HtH5J %K hhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhhahiQhjAhk1hl!hmhnhohphqhrhshthuhvhwqhxahyQhzAh{1h|!h}h~hhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhAh1h!hhhhhhhhhhhqhahQhA% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݾ D%վ D%; D%ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݽ D%ս D%ͽ D%Ž D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݼ D%ռ D%ͼ D%ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݻ D%ջ D%ͻ D%Ż D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E D%= D%5 D%- D%% D% D% D% D% D% D% D% D% D%ݺ D%պ D%ͺ D%ź D% D% D% D% D% D% D% D% D%} D%u D%m D%e D%] D%U D%M D%E DH= H H9tH6 Ht H= H5 H)HHH?HHtH HtfD=e u+UH=b Ht H=. d= ]wff. ÐHGH+FHcAVIH@AUATL$USHtQHHtIHIL9r 0HI9v'KHSMsH;Յ[]A\A]A^[D]A\A]A^øff.f= D2 ÐO AWDD_AVAUATUSD6^nAxj׋G3G D!3G V\$ЋW^$DD1\$!3WAʋN Fp $E‰L$A1A1DD^ !D1G;νD\$DEDVDT$A!A1EE|A 1AD!E1DD*ƇGD1D!A1A1DDN DL$E F0D!DnA1D1DGFEDf Dd$D^(A!A1EEؘiA 1AD!1DDDʋ^0D1D!A1DE [D 1!D1DDN,A1DL$G\EA!Df8A1ED"kA 1AD!1DDN4EqDD1!1DE CyD 1!D1DDV<1G!I!1DDD$ Eb%1!1DDD$E@@1!1DDD$ EQZ^&1!1DE6Ƕ1!1DD]/։ 1!1DESD1!1DE ؉ 1!1DDD$E01!1DDD$ E!1!1DE7É1!1DDD$ E 1!1DDD$A0ZEAA1A!A1AA㩉A AD1!1t$DD1!A ogD1 1D!FL*1DD$Ή1AA!B9A1DD$A AD1D$qDD11‹D$ 0"amD1G 81Ɖ11DDD$ ED꾤11DDD$AKAA1A5`KA1AЉApA 1AD1D1D1A ~(D 1G'111DDD$ A0AA1A1AЋT$A2A1D1֋T$ 9ىDD11D11C|A A1A1AD$A0eVĉA1D1AD")Dt$ D D1A *CDG# 1  1DD9Ή 1DDY[e\$  1DE Dt$ щ1DE3}D\$  1DDD$E] 1DEO~oA AD 1DE ,DT$ A1ADE6CDt$ AN 1A~SADEAA A1A5:ADA AD 1Љ3*\$D D1DFӆ[ ]A\A]A^ 1։ 1DƉA4A_ OW GOW ATI1USHdH%(H$1HHH<$t)H$dH3%(uL{8IHC0L)H9>Lt$L+{(LA@LLfIM)MK H@σLSLCpNIHDI0HI@HKpM~HC(MxIH E1I@HC8HL1HMLIHHKpH9eHMthILM)MUI9t H)tDL+t$HL[]A\A]A^A_DM@@M)(+IHt$HLHk8f.HAVLAUIATIUSHu\H߉[AD${LǃLSHu0{L[L]A\A]A^K[H]A\A]A^Hff.AWAVAUATUSHHHHD$ 0xIHIHLc\CHcT t u(HDLcLH t tLÅ~6HcAT t u#H@Å~ALH t tE<AG=I|$PHHTI9T$Hs7HI+t$@L2%))I|$PLHHcAMt$PHLIFID$PA:I|$P}MD$PII@ID$PAIc$0fET8HЃA$0D$ H[]A\A]A^A_D$ ff.H HB=0AUATUSHcHfDA< t< uH؅uH[]A\A]IHPHHDI9D$Hs3HI+t$@L2%))tQI|$PHHAPI\$PHCID$PIc$0fET8HЃA$0H1[]A\A]øSDAUATAUHSH?dH%(HD$1D$ff t1fHL$dH3 %(H[]A\A]ÐA1ҾÃtʼnǺ1HL$Aߺ踿u#DH'uDo̾߻D HJDeOAkDH}An衾}NSHtff.USHdH%(H$1HHu/HH$dH3%(uHĘ[]Ŀ@1H= tAUATA'USH݋ 'DNuD H@AHH^ HHtH- t YƉlj JUDk HM DcEuSH8dH%(H$(1=HtH H=H H=_>HE1 H讹H=Y>Ht 1H膹 H=E>ijHHt 1H]IAąWE1H=">萳Ht 1H, H=>jHtHǺ 1_H==CH H==$HtHǺ 1IԶH==H1 H舸OH==òHtHǺ 1_H==蜲HtHǺ 18!H==uHtHǺ 1H==NHtHǺ 1蓲H=r='HtMH=p=Ht 1H護ۀ _H=X=Ht 1H D   EH=$=H=r u Pe 5[ H=&=cH 1H% …t% HQv HHHHD L*=L =L#=C HLt@HֹL€D t%HtAHHt9HLuHfDHJHHJHuHHu1ۉH$(dH3%(H8[]A\A]fD& H覲D9舭HHiHǺ11˵ÃHT$ƿD$(?H5/ رHgH Htxc@dx@D  E9D E)ZfH=}8贬 HK]  u t 'j X '> )fՅtbH H-DHH5?1 cAHc螲L%~ HH~ a蓮Åt=~ 0~ u ~ 5~ `HH5@?uHH5>1u HH5>Fff.AVIAUEATIUHSHt4Hu!(fDHH蔭HLgH]HuMtEL [1]A\A]A^ÐIcLLH#EgHGHHܺvT2HGAWAVAAUIATUHoSH1HGO@ƉWDW?t;AĉDHH|@D)A9rhAGt4LLDHL9A?vWEfAIIIH޺@HH@ HLL9uA?DLHH[]A\A]A^A_ܱIATLfUHSFH?LHz?)ƒw=t19rLHfCAD$AD$ ID$071)"HCHLHCP?o H{1HMHHCPH)KXH[]A\ff.fAWAVAUATUSHdH%(H$1Ht^ IAfMcg IoA_@LH3HuM88u =Yw uٽH$dH3 %( HĨ[]A\A]A^A_f~AAuIALJf8LS|xr@tPHf@HPXN MgA;G ZA9~uEo)HHcIHLD"Hu$'85Dv uAMgA9ID$,HD$HcIIDhAh(A9}A /HcIH4@HUHAIIh$A9}A HcIH4@HHAIIHl$p(ILHIILp$hMIc@o9gIcP[9SIcpG9?IcH39+IHHHHIHT$IIc@ H)IHHIHHHIHIIcHIHHHD$I9E1DL4t9dfH H IGAG IPH f@ f@ HHP P H HPPHHPPHHPPHHPPf@f@f@HH#PP H H'P#P$H$H+P'P(f@f@!f@%H(P+f@)I1 fDIHcȋL4t#fBIHT4 rfB@2JHHuMIcP IHHH9pH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@ppHH@pHH9wMApIbIc@ IH0zu ALJt`!u u Au 1LHc迩IHIGAo IuID%t D-t B(AA1IcH4IILI 9HqH=W. IJDB(9xHqH=2. XIJB($AD$IKAzHL$;MbfoOt Lt$ LAoL$AT$Ml$)$踪 LL(HL$LHLLH$ID$H$I3L$H1H D$$Dl$EDDl$H=s IHIDEs MH=$s t"LDLŃP|$臨Et$A9uHt$莤D=Ń5r $A?D5r t 0AH5*L*HtHHr f)r #AH5:e 1;H@H5+1YLH 1HIH531H531D%q q DD$$H=q IHtZEW7E1111H=3H5*1耨E|$迦M2;|$藦E1H5*LuI}觧Ń1H5*LKfD=p -p p ED$AIFH5*1覧HH)H51H1聧1H5!*L 1H5C2LA#LH 3H H=NQ HL~H-> H 4> H=H HP HzH HJH*HQ H]> HH> HH=P LH5}H = H="H HP HH HJH*H踀yH(yHHP 1aH5P H=}H3H=r}yH(H[]A\A]@HPHH=L }HwHL H.XXXXXXH(Ht+H=uH=O 1HxH5,H=O 1HJfDmHzHfKHzHt -GF OkHyHu-*F 2HHAnonymous mmap() failedlocalhost%02d:%02d:%02d [%s] [UID:%d][%d] %.*syesnosystem()%s, errno: %d (%s) /dev/nulllibpthread.sopthread_atforkHTTP_[UID:%d][%d] %s:%s: %s LSAPI: jail() failure./etc/Can't set signalsaccept() failedLSAPI_STDERR_LOGPHP_LSAPI_MAX_REQUESTSLSAPI_MAX_REQSLSAPI_KEEP_LISTENLSAPI_AVOID_FORKLSAPI_ACCEPT_NOTIFYLSAPI_SLOW_REQ_MSECSLSAPI_ALLOW_CORE_DUMPLSAPI_MAX_IDLEPHP_LSAPI_CHILDRENLSAPI_EXTRA_CHILDRENLSAPI_MAX_IDLE_CHILDRENLSAPI_PGRP_MAX_IDLELSAPI_MAX_PROCESS_TIMELSAPI_PPID_NO_CHECKLSAPI_MAX_BUSY_WORKERLSAPI_DUMP_DEBUG_INFOnobodyLSAPI_DEFAULT_UIDLSAPI_DEFAULT_GIDLSAPI_SECRETLSAPI_LVE_ENABLEliblve.so.0lve_is_availablelve_instance_initlve_destroylve_enterlve_leavejailPHP_LSAPI_PHPRC=packetLen < 0 packetLen > %d Bad request header - ERROR#1 ParseRequest error SUEXEC_AUTHSUEXEC_UGIDLSAPI: setgid()LSAPI: initgroups()LSAPI: setgroups()LSAPI: setuid()Bad request header - ERROR#2 lsapi_accept() errorPragma: no-cacheRetry-After: 60Content-Type: text/htmlDEBUGNOTICEWARNERRORCRITFATALAcceptAccept-CharsetAccept-EncodingAccept-LanguageAuthorizationConnectionContent-TypeContent-LengthCookieCookie2HostPragmaRefererUser-AgentCache-ControlIf-Modified-SinceIf-MatchIf-None-MatchIf-RangeIf-Unmodified-SinceKeep-AliveX-Forwarded-ForViaTransfer-EncodingHTTP_ACCEPTHTTP_ACCEPT_CHARSETHTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_AUTHORIZATIONHTTP_CONNECTIONCONTENT_TYPECONTENT_LENGTHHTTP_COOKIEHTTP_COOKIE2HTTP_HOSTHTTP_PRAGMAHTTP_REFERERHTTP_USER_AGENTHTTP_CACHE_CONTROLHTTP_IF_MODIFIED_SINCEHTTP_IF_MATCHHTTP_IF_NONE_MATCHHTTP_IF_RANGEHTTP_IF_UNMODIFIED_SINCEHTTP_KEEP_ALIVEHTTP_RANGEHTTP_X_FORWARDED_FORHTTP_VIAHTTP_TRANSFER_ENCODING%04d-%02d-%02d %02d:%02d:%02d.%06d Child process with pid: %d was killed by signal: %d, core dumped: %s Possible runaway process, UID: %d, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld gdb --batch -ex "attach %d" -ex "set height 0" -ex "bt" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2Force killing runaway process PID: %d with SIGKILL Killing runaway process PID: %d with SIGTERM Children tracking is wrong: Cur Children: %d, count: %d, idle: %d, dying: %d LSAPI: LVE jail(%d) result: %d, error: %s ! Invalid custom stderr log pathFailed to open custom stderr logCan't set signal handler for SIGCHILDReached max children process limit: %d, extra: %d, current: %d, busy: %d, please increase LSAPI_CHILDREN. LSAPI: failed to open secret file: %s! LSAPI: failed to check state of file: %s! LSAPI: file permission check failure: %s LSAPI: failed to read secret from secret file: %s LSAPI: Unable to initialize LVERequest header does match total size, total: %d, real: %ld LSAPI: missing SUEXEC_UGID env, use default user! LSAPI: SUEXEC_AUTH authentication failed, use default user! LSAPI: lve_enter() failure, reached resource limit.prctl: Failed to set dumpable, core dump may not be available!sigprocmask(SIG_BLOCK) to block SIGCHLDsigprocmask( SIG_SETMASK ) to restore SIGMASK in childfork() failed, please increase process limitsigprocmask( SIG_SETMASK ) to restore SIGMASKCache-Control: private, no-cache, no-store, must-revalidate, max-age=0PID 508 Resource Limit Is Reached

Resource Limit Is Reached

The website is temporarily unable to service your request as it exceeded resource limit. Please try again later.
          replacesrandQUERY_STRINGREQUEST_URIPATH_INFOREQUEST_PATHSCRIPT_NAMESTDERRreopenftruncate() failed. File mapping failed. Memory calloc error[...]nilLSAPI_MAX_BODYBUF_LENGTHLSAPI_TEMPFILEXXXXXXRACK_ROOTchdir()to_hashCGI/1.2eval_string_wrapLSAPIacceptaccept_new_connectionpostfork_childpostfork_parentprocessputcwriteprintprintfputs<<flushgetcgetsreadrewindeacheofeof?closebinmodeisattytty?syncsync=RACK_ENVInsecure: operation on untainted IOGATEWAY_Irewindable_input.rbNTERFACE/tmp/lsapi.XXXXX;z@Ze pp8pLp`pt q0q@qx00ydyxyPzz|$|t}~<Pd$@ppH p  0 @ Ќ 0 D PX t ` Џ 8 PL p P d `x p ph ` (pt@ @pp0<PPdx`Я,@T h@|`й4Ptp@ L $@8pL`tp00\Pxp@,`x`@ pHzRx $@V FJ w?:*3$"D` \0lp,l(l L$lsEIB E(A0z (A BBBI A (D BBBA Tl Pl@LlYGJB B(A0A80F(B DBb0ThsBFC G  AABK sk( tGADJ n AAA 4DtUAGK R CAG L JCG ltAG] AJ $tt C KFLHuBBE A(H0H (D BBBD  (D BBBA PtvvFB A(D0D (A BBBB L(A BBBA$vaAAD XAAHwBBB B(A0A8D@N 8C0A(B BBBH $`wOAf Q C E H@wYBBB A(D0J 0A(A BBBF xzFEA C(G   (A ABBD M I c A  E M A k E E E E H V HHT|FBB B(A0A8D`` 8A0A(B BBBD l}+BBB B(A0D8JYHPC Mi 8A0A(B BBBE LTMDd~6BBB B(A0A8DP 8A0A(B BBBG  8J0H(G DBBK $l`7EFF IIOx | 4xFAA G>  AABG EO D  A @ ThY|JED$S p]Ph H XAHlFBB B(A0A8LP 8A0A(B BBBH <Є FBB A(A0 (D BBBI \i`pFBB B(A0A8DP~ 8A0A(B BBBA k 8A0A(B BBBH L$FBB A(A0H Q D 0A(A BBBH L$FBB B(A0A8G 8A0A(B BBBF thFF$lnCXJLDlFBB B(A0A8DA 8A0A(B BBBA `( dBBB B(A0A8G I K I L N N w 8A0A(B BBBI 0 BMD GL  AABA < |=BAA G L@I@U  AABG $ |TWEHG ( ag H SHL pFBB B(A0A8DPS 8D0A(B BBBF T bIE D(C0P (F BBBM Q(H BBBAH lFBB B(A0A8DP 8A0A(B BBBA T< CBA A(G0` (A ABBD  (C ABBA J8 Ȗ-FBD D(D@T (A ABBB  ( ȗlECGF AAI L !cBG A(D0 (A ABBE XD0` t Z D10 ppFAA G@7  AABF  @LsL КFBB B(A0A8G 8A0A(B BBBG < P d x    Ȟ Ԟ  О  ̞Ȟ <Ğ FBA K(G (A ABBG <XFEE D(D0M (C BBBB ԧ(HFBH E(A0E8I@ 8A0A(B BBBE (FED ABH$8 BBB B(A0A8G 8A0A(B BBBJ Dp̴FBB A(A0G 0A(A BBBF L4 FBB B(A0A8G  8A0A(B BBBA 4 H\+p(BFGA kFB4zD O E  HU gHQ G <ayd(THEDL ] CAJ ELEY HW HW-Hd(EAD  DAJ ,aED y AE HP FBB E(D0C8GPm 8F0A(B BBBG ,ZAD J ABL 4PoAD  AAK pP \FBD C(G0 (D ABBE j (D ABBE | (G DBBA HdhFBB B(A0A8G@ 8D0A(B BBBD 7ٯqR_pwKJZnz9:ShX=05RCEth7qX,/[Y*wҽ:-Ry# Գ&-ozaR+I=3OP69ZLoXhGKqgD3i⺟ZjlAQ42((#U]`ikU4Sޞ^$ ߏ]FJYL_9nΙ#/.|L$S 3ɭɓ#&p6p>VnB?T֭mEn%Uc[z&Xy/=/??kF~CRPsTU-v_〝k{$*=]T6:"\1l1|eZ{DzuNZKb4/۞㜡 Rk:JI/ x^ʱٸj ;gk=$2zc.y"P,*l~<䭟 iF-Lм '?kە꠯F318'fCfSƍS^!+iAz޷`0>14X%x箌zldňY,uxA ]|S!'LdZ(1lD8V8y-'w4̕ ~nM^Ef& cǝo+f)"OuKZi!φ{= x~ɦ1NB R.:j |VOmGosF{2\f}$Lؚ6k(R-~ =v=qK{8}L^Wǁ9nq+-?ӡ,}_B֓ lkIvZ)'܋)bJᔻF*ja>Bc-@pL5oNÏމ 8nŚ),k|Z3C2M/MKȯ@ $ X:Uo۸Spy]}T:~(yy>1QOJA+>ȀQ.[H5r˙LQB"2V[lJivpg6<^ϟڏYd7ziگPSo/t1TzI!m_:XCVC;ْ 33!/{$K_D4 _{^>F-Mh[kRΫJ’0Uw+p|E%] ;ܕ0gYZ.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.note.gnu.property.init_array.fini_array.data.rel.ro.dynamic.got.data.bss.gnu.build.attributes.gnu_debuglink.gnu_debugdata 88$o``p( (0 8o$$Eop&p&pT&&^Bh/h/hp?p?c?? nPJPJ wUU~}  PP008hh !!! ! !  ! ! "a $`x%(PK% ]k爹%specifications/ruby-lsapi-5.5.gemspecnu[PK% ]2 %specifications/ruby-lsapi-5.6.gemspecnu[PK% ]&"V44# specifications/xmlrpc-0.3.0.gemspecnu[PK% ]Cض#specifications/rackup-2.1.0.gemspecnu[PK% ]R'specifications/net-telnet-0.2.0.gemspecnu[PK% ]8~)specifications/did_you_mean-1.3.0.gemspecnu[PK% ]Vk&$specifications/minitest-5.11.3.gemspecnu[PK% ]Z )7specifications/power_assert-1.1.3.gemspecnu[PK% ]"  ,Aspecifications/default/openssl-2.1.2.gemspecnu[PK% ]!j(JLspecifications/default/shell-0.7.gemspecnu[PK% ]+pRspecifications/default/e2mmap-0.1.0.gemspecnu[PK% ]"+Wspecifications/default/logger-1.3.0.gemspecnu[PK% ]h`Ho o )]specifications/default/json-2.1.0.gemspecnu[PK% ]-)gspecifications/default/gdbm-2.0.0.gemspecnu[PK% ]C6j+nspecifications/default/ipaddr-1.2.2.gemspecnu[PK% ]`P<<+Duspecifications/default/matrix-0.1.0.gemspecnu[PK% ]:9gff*zspecifications/default/fcntl-1.0.0.gemspecnu[PK% ]L L (specifications/default/irb-1.0.0.gemspecnu[PK% ]D8 8 ,?specifications/default/webrick-1.4.4.gemspecnu[PK% ]Q5tt*ӕspecifications/default/prime-0.1.0.gemspecnu[PK% ]@+specifications/default/thwait-0.1.0.gemspecnu[PK% ] : *specifications/default/psych-3.1.0.gemspecnu[PK% ]~b**-Sspecifications/default/bundler-1.17.2.gemspecnu[PK% ]Qli i /Kspecifications/default/bigdecimal-1.4.1.gemspecnu[PK% ]5TA,specifications/default/strscan-1.0.0.gemspecnu[PK% ] ^)Ispecifications/default/date-2.0.3.gemspecnu[PK% ].440specifications/default/forwardable-1.2.0.gemspecnu[PK% ]׷*$specifications/default/cmath-1.0.0.gemspecnu[PK% ]@ 撛,5specifications/default/mutex_m-0.1.0.gemspecnu[PK% ]+,specifications/default/fiddle-1.0.0.gemspecnu[PK% ] o}})fspecifications/default/zlib-1.0.0.gemspecnu[PK% ]KjK+< specifications/default/rdoc-6.1.2.1.gemspecnu[PK% ]s(&specifications/default/csv-3.0.9.gemspecnu[PK% ]dS(.specifications/default/etc-1.0.1.gemspecnu[PK% ]g ,r6specifications/default/rexml-3.1.9.1.gemspecnu[PK% ]'&V  (Aspecifications/default/rss-0.2.7.gemspecnu[PK% ])m-/Lspecifications/default/stringio-0.0.2.gemspecnu[PK% ]Z/WQspecifications/default/io-console-0.4.7.gemspecnu[PK% ]a+Wspecifications/default/tracer-0.1.0.gemspecnu[PK% ]#{(]specifications/default/dbm-1.0.0.gemspecnu[PK% ]Z,cspecifications/default/ostruct-0.1.0.gemspecnu[PK% ]!u]*whspecifications/default/scanf-1.0.0.gemspecnu[PK% ]oi5)nspecifications/default/sync-0.5.0.gemspecnu[PK% ]Cj)tspecifications/default/sdbm-1.0.0.gemspecnu[PK% ]&8.zspecifications/default/fileutils-1.1.0.gemspecnu[PK% ]+D D &%specifications/test-unit-3.2.9.gemspecnu[PK% ]pc` !specifications/rack-3.0.8.gemspecnu[PK% ]7 7 "specifications/rake-12.3.3.gemspecnu[PK% ]%Bqq+gems/power_assert-1.1.3/LEGALnu[PK% ]Vgems/power_assert-1.1.3/Gemfilenu[PK% ]X gems/power_assert-1.1.3/Rakefilenu[PK% ]*Dvgems/power_assert-1.1.3/BSDLnu[PK% ]|m# # #gems/power_assert-1.1.3/README.rdocnu[PK% ] b gems/power_assert-1.1.3/COPYINGnu[PK% ]rD[ , gems/power_assert-1.1.3/power_assert.gemspecnu[PK% ]t/;JJ!gems/power_assert-1.1.3/bin/setupnu[PK% ]9\#gems/power_assert-1.1.3/bin/consolenu[PK% ]~553gems/power_assert-1.1.3/lib/power_assert/context.rbnu[PK% ]’2/gems/power_assert-1.1.3/lib/power_assert/parser.rbnu[PK% ]wY++3 gems/power_assert-1.1.3/lib/power_assert/version.rbnu[PK% ]!4 gems/power_assert-1.1.3/lib/power_assert/colorize.rbnu[PK% ]{%}}WW9B gems/power_assert-1.1.3/lib/power_assert/configuration.rbnu[PK% ]Wa]Dgems/power_assert-1.1.3/lib/power_assert/enable_tracepoint_events.rbnu[PK% ]\>5tgems/power_assert-1.1.3/lib/power_assert/inspector.rbnu[PK% ]O3e: +|gems/power_assert-1.1.3/lib/power_assert.rbnu[PK% ]YE[h*gems/rdoc-6.1.2.1/exe/rdocnuȯPK% ]ֳso.gems/rdoc-6.1.2.1/exe/rinuȯPK% ]z o/gems/rackup-2.1.0/license.mdnu[PK% ]<d^<gems/rackup-2.1.0/readme.mdnu[PK% ]ǻii?gems/rackup-2.1.0/bin/rackupnuȯPK% ]e eeS@gems/rackup-2.1.0/security.mdnu[PK% ]/:44&Agems/rackup-2.1.0/lib/rackup/server.rbnu[PK% ]'2vgems/rackup-2.1.0/lib/rackup/lobster.rbnu[PK% ]F; ; 'Ngems/rackup-2.1.0/lib/rackup/handler.rbnu[PK% ]cϛ'gems/rackup-2.1.0/lib/rackup/version.rbnu[PK% ]|/ˋgems/rackup-2.1.0/lib/rackup/handler/webrick.rbnu[PK% ]HH+$gems/rackup-2.1.0/lib/rackup/handler/cgi.rbnu[PK% ]lo| &Ǣgems/rackup-2.1.0/lib/rackup/stream.rbnu[PK% ]9$$gems/rackup-2.1.0/lib/rackup.rbnu[PK% ]G TTgems/rack-3.0.8/MIT-LICENSEnu[PK% ]==gems/rack-3.0.8/SPEC.rdocnu[PK% ]t2gems/rack-3.0.8/CHANGELOG.mdnu[PK% ]tz,,Bgems/rack-3.0.8/README.mdnu[PK% ]_* * gems/rack-3.0.8/CONTRIBUTING.mdnu[PK% ]um gems/rack-3.0.8/lib/rack.rbnu[PK% ]:}= = "gems/rack-3.0.8/lib/rack/urlmap.rbnu[PK% ]М} :gems/rack-3.0.8/lib/rack/file.rbnu[PK% ];`ff#1gems/rack-3.0.8/lib/rack/runtime.rbnu[PK% ]4 4 #gems/rack-3.0.8/lib/rack/chunked.rbnu[PK% ]HSGbGb#q"gems/rack-3.0.8/lib/rack/request.rbnu[PK% ]ʆ66+ gems/rack-3.0.8/lib/rack/show_exceptions.rbnu[PK% ][J$Vgems/rack-3.0.8/lib/rack/deflater.rbnu[PK% ]>== gems/rack-3.0.8/lib/rack/lock.rbnu[PK% ]/{{(=gems/rack-3.0.8/lib/rack/mock_request.rbnu[PK% ]gG&gems/rack-3.0.8/lib/rack/media_type.rbnu[PK% ]/gems/rack-3.0.8/lib/rack/auth/digest/request.rbnu[PK% ]+{gems/rack-3.0.8/lib/rack/auth/digest/md5.rbnu[PK% ]-gems/rack-3.0.8/lib/rack/auth/digest/nonce.rbnu[PK% ].mgems/rack-3.0.8/lib/rack/auth/digest/params.rbnu[PK% ],UU1gems/rack-3.0.8/lib/rack/auth/abstract/request.rbnu[PK% ]lGRR1gems/rack-3.0.8/lib/rack/auth/abstract/handler.rbnu[PK% ]&Qgems/rack-3.0.8/lib/rack/auth/basic.rbnu[PK% ]  'Xgems/rack-3.0.8/lib/rack/auth/digest.rbnu[PK% ]>Sf?"?"#gems/rack-3.0.8/lib/rack/builder.rbnu[PK% ]O~%K:gems/rack-3.0.8/lib/rack/recursive.rbnu[PK% ]ӎ cTcT!Agems/rack-3.0.8/lib/rack/utils.rbnu[PK% ]&44,rgems/rack-3.0.8/lib/rack/multipart/parser.rbnu[PK% ]l /gems/rack-3.0.8/lib/rack/multipart/generator.rbnu[PK% ]N$$3gems/rack-3.0.8/lib/rack/multipart/uploaded_file.rbnu[PK% ] Cx x )Cgems/rack-3.0.8/lib/rack/common_logger.rbnu[PK% ]YYd  +gems/rack-3.0.8/lib/rack/tempfile_reaper.rbnu[PK% ]Kbx  $ygems/rack-3.0.8/lib/rack/reloader.rbnu[PK% ]&{!{!(gems/rack-3.0.8/lib/rack/query_parser.rbnu[PK% ]U``"%gems/rack-3.0.8/lib/rack/multipart.rbnu[PK% ]|Х!gems/rack-3.0.8/lib/rack/files.rbnu[PK% ]44"5gems/rack-3.0.8/lib/rack/events.rbnu[PK% ]A%2Igems/rack-3.0.8/lib/rack/directory.rbnu[PK% ]iZ&&*agems/rack-3.0.8/lib/rack/content_length.rbnu[PK% ]ɸHO#egems/rack-3.0.8/lib/rack/version.rbnu[PK% ]R  )0igems/rack-3.0.8/lib/rack/mock_response.rbnu[PK% ]Y488$vgems/rack-3.0.8/lib/rack/sendfile.rbnu[PK% ]dP"0gems/rack-3.0.8/lib/rack/logger.rbnu[PK% ]M}Y??  gems/rack-3.0.8/lib/rack/mock.rbnu[PK% ]K?33&gems/rack-3.0.8/lib/rack/body_proxy.rbnu[PK% ]ю "8gems/rack-3.0.8/lib/rack/static.rbnu[PK% ]VMVww gems/rack-3.0.8/lib/rack/etag.rbnu[PK% ];~ ~ ,Pgems/rack-3.0.8/lib/rack/rewindable_input.rbnu[PK% ]$**$*gems/rack-3.0.8/lib/rack/response.rbnu[PK% ]3+cgems/rack-3.0.8/lib/rack/method_override.rbnu[PK% ]@j %gems/rack-3.0.8/lib/rack/constants.rbnu[PK% ]Oi #gems/rack-3.0.8/lib/rack/headers.rbnu[PK% ]ѝo    gems/rack-3.0.8/lib/rack/head.rbnu[PK% ]՝[[ C gems/rack-3.0.8/lib/rack/lint.rbnuȯPK% ]|| +gems/rack-3.0.8/lib/rack/conditional_get.rbnu[PK% ]N4q(>gems/rack-3.0.8/lib/rack/content_type.rbnu[PK% ]dNN'Mgems/rack-3.0.8/lib/rack/show_status.rbnu[PK% ]?6/ gems/rack-3.0.8/lib/rack/mime.rbnu[PK% ]i\">gems/rack-3.0.8/lib/rack/config.rbnu[PK% ]Y  #?gems/rack-3.0.8/lib/rack/cascade.rbnu[PK% ]_l'CIgems/rack-3.0.8/lib/rack/null_logger.rbnu[PK% ]/WNgems/ruby-lsapi-5.5/ext/lsapi/.sitearchdir.timenu[PK% ]Y//(Ngems/ruby-lsapi-5.5/ext/lsapi/lsapilib.hnu[PK% ]7Zw( gems/ruby-lsapi-5.5/ext/lsapi/extconf.rbnu[PK% ].ZZ&_gems/ruby-lsapi-5.5/ext/lsapi/lsruby.cnu[PK% ]W q,,(bgems/ruby-lsapi-5.5/ext/lsapi/lsapidef.hnu[PK% ]T(((gems/ruby-lsapi-5.5/ext/lsapi/lsapilib.onu[PK% ]p K#K#&.gems/ruby-lsapi-5.5/ext/lsapi/Makefilenu[PK% ] 3O8aa(:gems/ruby-lsapi-5.5/ext/lsapi/lsapilib.cnu[PK% ]Dk--& gems/ruby-lsapi-5.5/ext/lsapi/lsapi.sonuȯPK% ]‹AWXX&:gems/ruby-lsapi-5.5/ext/lsapi/lsruby.onu[PK% ]lΉ!tgems/ruby-lsapi-5.5/lsapi.gemspecnu[PK% ]^wͱNgems/ruby-lsapi-5.5/READMEnu[PK% ]GF(I3gems/ruby-lsapi-5.5/rails/dispatch.lsapinuȯPK% ]H@MM,5gems/ruby-lsapi-5.5/scripts/lsruby_runner.rbnuȯPK% ]##BBB:gems/ruby-lsapi-5.5/setup.rbnu[PK% ]&E  )gems/ruby-lsapi-5.5/examples/testlsapi.rbnuȯPK% ]+.4gems/ruby-lsapi-5.5/examples/lsapi_with_cgi.rbnuȯPK% ]&\-- gems/ruby-lsapi-5.5/lib/lsapi.sonuȯPK% ];kk!gems/minitest-5.11.3/Manifest.txtnu[PK% ]q8) ) ugems/minitest-5.11.3/Rakefilenu[PK% ]9(  =gems/minitest-5.11.3/test/minitest/test_minitest_benchmark.rbnu[PK% ]`#*ii<gems/minitest-5.11.3/test/minitest/test_minitest_reporter.rbnu[PK% ]HB"ee8)gems/minitest-5.11.3/test/minitest/test_minitest_test.rbnu[PK% ]B1YJYJ8ygems/minitest-5.11.3/test/minitest/test_minitest_mock.rbnu[PK% ]xc2:2gems/minitest-5.11.3/test/minitest/metametameta.rbnu[PK% ] dd8U;gems/minitest-5.11.3/test/minitest/test_minitest_spec.rbnu[PK% ]smm qgems/minitest-5.11.3/README.rdocnu[PK% ]R`4Y4Y$ gems/minitest-5.11.3/lib/minitest.rbnu[PK% ]lrR^CC*Xggems/minitest-5.11.3/lib/minitest/pride.rbnu[PK% ]<II/ggems/minitest-5.11.3/lib/minitest/assertions.rbnu[PK% ]+**)۱gems/minitest-5.11.3/lib/minitest/test.rbnu[PK% ]Us//.^gems/minitest-5.11.3/lib/minitest/benchmark.rbnu[PK% ]y)gems/minitest-5.11.3/lib/minitest/unit.rbnu[PK% ]/w[NN)gems/minitest-5.11.3/lib/minitest/mock.rbnu[PK% ]_cGG-gems/minitest-5.11.3/lib/minitest/parallel.rbnu[PK% ]oz)K gems/minitest-5.11.3/lib/minitest/hell.rbnu[PK% ]9M M 1o!gems/minitest-5.11.3/lib/minitest/pride_plugin.rbnu[PK% ]1.gems/minitest-5.11.3/lib/minitest/expectations.rbnu[PK% ]I,Egems/minitest-5.11.3/lib/minitest/autorun.rbnu[PK% ]>!!)Fgems/minitest-5.11.3/lib/minitest/spec.rbnu[PK% ]Lj)p(hgems/minitest-5.11.3/lib/hoe/minitest.rbnu[PK% ]koOO!kgems/minitest-5.11.3/History.rdocnu[PK% ]5~~( gems/minitest-5.11.3/design_rationale.rbnu[PK% ]W^gems/rake-12.3.3/MIT-LICENSEnu[PK% ]''gems/rake-12.3.3/Gemfilenu[PK% ]I4gems/rake-12.3.3/exe/rakenuȯPK% ]VQOgems/rake-12.3.3/Rakefilenu[PK% ]n\?$%!gems/rake-12.3.3/azure-pipelines.ymlnu[PK% ]q"gems/rake-12.3.3/README.rdocnu[PK% ]toc7gems/rake-12.3.3/rake.gemspecnu[PK% ]?qFF,Hgems/rake-12.3.3/doc/command_line_usage.rdocnu[PK% ]@u,u,`gems/rake-12.3.3/doc/jamis.rbnu[PK% ]Oq AA Rgems/rake-12.3.3/doc/example/a.cnu[PK% ]۸ &gems/rake-12.3.3/doc/example/Rakefile1nu[PK% ]AA אgems/rake-12.3.3/doc/example/b.cnu[PK% ]";WW&hgems/rake-12.3.3/doc/example/Rakefile2nu[PK% ]_bgg#gems/rake-12.3.3/doc/example/main.cnu[PK% ]PP"ϔgems/rake-12.3.3/doc/rakefile.rdocnu[PK% ]) $gems/rake-12.3.3/doc/proto_rake.rdocnu[PK% ]gems/rake-12.3.3/doc/rake.1nu[PK% ]v3HH"gems/rake-12.3.3/doc/rational.rdocnu[PK% ]'S{"gems/rake-12.3.3/doc/glossary.rdocnu[PK% ]Xgems/rake-12.3.3/bin/rdocnu[PK% ]Y2"gems/rake-12.3.3/bin/rakenu[PK% ]|u%%gems/rake-12.3.3/bin/rubocopnu[PK% ]t/;JJ(gems/rake-12.3.3/bin/setupnu[PK% ]r WUU)gems/rake-12.3.3/bin/consolenu[PK% ]>h  +*gems/rake-12.3.3/bin/bundlenu[PK% ]R  (5gems/rake-12.3.3/lib/rake/linked_list.rbnu[PK% ]2bb-@gems/rake-12.3.3/lib/rake/loaders/makefile.rbnu[PK% ]u%Fgems/rake-12.3.3/lib/rake/ext/core.rbnu[PK% ]yOurr'Igems/rake-12.3.3/lib/rake/ext/string.rbnu[PK% ].*C}}"tagems/rake-12.3.3/lib/rake/phony.rbnu[PK% ]?{Hrr'Ccgems/rake-12.3.3/lib/rake/early_time.rbnu[PK% ]n#0 egems/rake-12.3.3/lib/rake/task_argument_error.rbnu[PK% ]ݢ"fgems/rake-12.3.3/lib/rake/clean.rbnu[PK% ]d11&ongems/rake-12.3.3/lib/rake/file_list.rbnu[PK% ]F- +gems/rake-12.3.3/lib/rake/dsl_definition.rbnu[PK% ]&ݶgems/rake-12.3.3/lib/rake/cloneable.rbnu[PK% ]X"Vgg/gems/test-unit-3.2.9/LGPLnu[PK% ]vm n/gems/test-unit-3.2.9/COPYINGnu[PK% ]oc)~/gems/test-unit-3.2.9/sample/test_adder.rbnu[PK% ]c: $b/gems/test-unit-3.2.9/sample/adder.rbnu[PK% ]d@./gems/test-unit-3.2.9/sample/test_subtracter.rbnu[PK% ]/jj(/gems/test-unit-3.2.9/sample/test_user.rbnu[PK% ]Z)/gems/test-unit-3.2.9/sample/subtracter.rbnu[PK% ]$yӱ'/gems/test-unit-3.2.9/doc/text/how-to.mdnu[PK% ]Maa%0gems/test-unit-3.2.9/doc/text/news.mdnu[PK% ]p00gems/test-unit-3.2.9/doc/text/getting-started.mdnu[PK% ]2)5:0gems/test-unit-3.2.9/lib/test/unit/code-snippet-fetcher.rbnu[PK% ]y3 3 5E0gems/test-unit-3.2.9/lib/test/unit/util/observable.rbnu[PK% ]b1ݶ0gems/test-unit-3.2.9/lib/test/unit/util/output.rbnu[PK% ]S<>#0gems/test-unit-3.2.9/lib/test/unit/util/method-owner-finder.rbnu[PK% ]>\MM6i0gems/test-unit-3.2.9/lib/test/unit/util/procwrapper.rbnu[PK% ]00:0gems/test-unit-3.2.9/lib/test/unit/util/backtracefilter.rbnu[PK% ]9'ee*0gems/test-unit-3.2.9/lib/test/unit/diff.rbnu[PK% ]*6r +/1gems/test-unit-3.2.9/lib/test/unit/color.rbnu[PK% ]jx /;1gems/test-unit-3.2.9/lib/test/unit/data-sets.rbnu[PK% ]Z((06H1gems/test-unit-3.2.9/lib/test/unit/assertions.rbnu[PK% ] 0p2gems/test-unit-3.2.9/lib/test/unit/testresult.rbnu[PK% ]"ss-}2gems/test-unit-3.2.9/lib/test/unit/pending.rbnu[PK% ]AV.2gems/test-unit-3.2.9/lib/test/unit/omission.rbnu[PK% ]soo+2gems/test-unit-3.2.9/lib/test/unit/error.rbnu[PK% ] /44/2gems/test-unit-3.2.9/lib/test/unit/testsuite.rbnu[PK% ]E/R2gems/test-unit-3.2.9/lib/test/unit/attribute.rbnu[PK% ].2gems/test-unit-3.2.9/lib/test/unit/priority.rbnu[PK% ] \'____.2gems/test-unit-3.2.9/lib/test/unit/testcase.rbnu[PK% ]<KO3gems/test-unit-3.2.9/lib/test/unit/assertion-failed-error.rbnu[PK% ]=@Z Z 2R3gems/test-unit-3.2.9/lib/test/unit/notification.rbnu[PK% ] ::-_`3gems/test-unit-3.2.9/lib/test/unit/version.rbnu[PK% ]tH(A(A0`3gems/test-unit-3.2.9/lib/test/unit/autorunner.rbnu[PK% ]n$$-~3gems/test-unit-3.2.9/lib/test/unit/fixture.rbnu[PK% ]l 43gems/test-unit-3.2.9/lib/test/unit/runner/console.rbnu[PK% ]qo0#3gems/test-unit-3.2.9/lib/test/unit/runner/xml.rbnu[PK% ]l2+3gems/test-unit-3.2.9/lib/test/unit/runner/emacs.rbnu[PK% ] 11*G3gems/test-unit-3.2.9/lib/test/unit/data.rbnu[PK% ]z|{{84gems/test-unit-3.2.9/lib/test/unit/auto-runner-loader.rbnu[PK% ]xpp:u 4gems/test-unit-3.2.9/lib/test/unit/collector/descendant.rbnu[PK% ]W"DD3O 4gems/test-unit-3.2.9/lib/test/unit/collector/xml.rbnu[PK% ] z4)4gems/test-unit-3.2.9/lib/test/unit/collector/load.rbnu[PK% ]Q$ 3yA4gems/test-unit-3.2.9/lib/test/unit/collector/dir.rbnu[PK% ]>;N4gems/test-unit-3.2.9/lib/test/unit/collector/objectspace.rbnu[PK% ]], =&R4gems/test-unit-3.2.9/lib/test/unit/fault-location-detector.rbnu[PK% ]j V 7u]4gems/test-unit-3.2.9/lib/test/unit/exception-handler.rbnu[PK% ]"zz2h4gems/test-unit-3.2.9/lib/test/unit/color-scheme.rbnu[PK% ]= = 84gems/test-unit-3.2.9/lib/test/unit/test-suite-creator.rbnu[PK% ]H~XX-&4gems/test-unit-3.2.9/lib/test/unit/failure.rbnu[PK% ]xZZ9ۦ4gems/test-unit-3.2.9/lib/test/unit/ui/emacs/testrunner.rbnu[PK% ]u$$<4gems/test-unit-3.2.9/lib/test/unit/ui/testrunnerutilities.rbnu[PK% ]d7.4gems/test-unit-3.2.9/lib/test/unit/ui/xml/testrunner.rbnu[PK% ]l~<4gems/test-unit-3.2.9/lib/test/unit/ui/console/outputlevel.rbnu[PK% ]!=(__;4gems/test-unit-3.2.9/lib/test/unit/ui/console/testrunner.rbnu[PK% ]޸34/5gems/test-unit-3.2.9/lib/test/unit/ui/testrunner.rbnu[PK% ]N N ;<45gems/test-unit-3.2.9/lib/test/unit/ui/testrunnermediator.rbnu[PK% ]KE::/A5gems/test-unit-3.2.9/lib/test/unit/collector.rbnu[PK% ]Vݯ7I5gems/test-unit-3.2.9/lib/test/unit/attribute-matcher.rbnu[PK% ]kO?O?%K5gems/test-unit-3.2.9/lib/test/unit.rbnu[PK% ] O%H5gems/test-unit-3.2.9/lib/test-unit.rbnu[PK% ]Y44#L5gems/did_you_mean-1.3.0/LICENSE.txtnu[PK% ]PDD$Ӕ5gems/did_you_mean-1.3.0/CHANGELOG.mdnu[PK% ]yCy 5gems/did_you_mean-1.3.0/Gemfilenu[PK% ]Ɛ 5gems/did_you_mean-1.3.0/Rakefilenu[PK% ]+Jx##-5gems/did_you_mean-1.3.0/test/fixtures/book.rbnu[PK% ]o||?c5gems/did_you_mean-1.3.0/test/edit_distance/jaro_winkler_test.rbnu[PK% ]}؝MN5gems/did_you_mean-1.3.0/test/experimental/initializer_name_correction_test.rbnu[PK% ]無qqEh5gems/did_you_mean-1.3.0/test/experimental/method_name_checker_test.rbnu[PK% ] BN5gems/did_you_mean-1.3.0/test/core_ext/name_error_extension_test.rbnu[PK% ]D}7ii+5gems/did_you_mean-1.3.0/test/test_helper.rbnu[PK% ]41Bp5gems/did_you_mean-1.3.0/test/spell_checking/key_name_check_test.rbnu[PK% ]LyD E}5gems/did_you_mean-1.3.0/test/spell_checking/method_name_check_test.rbnu[PK% ](*; G6gems/did_you_mean-1.3.0/test/spell_checking/variable_name_check_test.rbnu[PK% ]g00D6gems/did_you_mean-1.3.0/test/spell_checking/class_name_check_test.rbnu[PK% ]NX;;Lq6gems/did_you_mean-1.3.0/test/spell_checking/uncorrectable_name_check_test.rbnu[PK% ]S9 2(6gems/did_you_mean-1.3.0/test/spell_checker_test.rbnu[PK% ]ٮ͇6X)6gems/did_you_mean-1.3.0/test/verbose_formatter_test.rbnu[PK% ]EwΝ!+6gems/did_you_mean-1.3.0/README.mdnu[PK% ]ON,=6gems/did_you_mean-1.3.0/did_you_mean.gemspecnu[PK% ]8XX6M6gems/did_you_mean-1.3.0/benchmark/levenshtein/speed.rbnu[PK% ]ol=O6gems/did_you_mean-1.3.0/benchmark/levenshtein/memory_usage.rbnu[PK% ]&&n($$7P6gems/did_you_mean-1.3.0/benchmark/jaro_winkler/speed.rbnu[PK% ]2>R6gems/did_you_mean-1.3.0/benchmark/jaro_winkler/memory_usage.rbnu[PK% ]ӯK1S6gems/did_you_mean-1.3.0/benchmark/memory_usage.rbnu[PK% ]rr2U6gems/did_you_mean-1.3.0/doc/changelog_generator.rbnu[PK% ]ݪ,Y6gems/did_you_mean-1.3.0/doc/CHANGELOG.md.erbnu[PK% ]m2_ +Z6gems/did_you_mean-1.3.0/lib/did_you_mean.rbnu[PK% ]aɣ))8i6gems/did_you_mean-1.3.0/lib/did_you_mean/jaro_winkler.rbnu[PK% ] Mp6gems/did_you_mean-1.3.0/lib/did_you_mean/experimental/ivar_name_correction.rbnu[PK% ]wT0y6gems/did_you_mean-1.3.0/lib/did_you_mean/experimental/initializer_name_correction.rbnu[PK% ]Z-**3{6gems/did_you_mean-1.3.0/lib/did_you_mean/version.rbnu[PK% ]#yy8|6gems/did_you_mean-1.3.0/lib/did_you_mean/experimental.rbnu[PK% ]?Naa7|6gems/did_you_mean-1.3.0/lib/did_you_mean/levenshtein.rbnu[PK% ]<?6gems/did_you_mean-1.3.0/lib/did_you_mean/core_ext/name_error.rbnu[PK% ] 36gems/did_you_mean-1.3.0/lib/did_you_mean/verbose.rbnu[PK% ]m,,96gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checker.rbnu[PK% ]k=8N6gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/method_name_checker.rbnu[PK% ](F66L6gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/key_error_checker.rbnu[PK% ] hhGƓ6gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/null_checker.rbnu[PK% ] ]]N6gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/name_error_checkers.rbnu[PK% ]*w,d6gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rbnu[PK% ]`a؟6gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rbnu[PK% ]FC6gems/did_you_mean-1.3.0/lib/did_you_mean/formatters/plain_formatter.rbnu[PK% ] ӰH6gems/did_you_mean-1.3.0/lib/did_you_mean/formatters/verbose_formatter.rbnu[PK% ] !ˮ6gems/net-telnet-0.2.0/LICENSE.txtnu[PK% ]V__6gems/net-telnet-0.2.0/Gemfilenu[PK% ]nn(6gems/net-telnet-0.2.0/net-telnet.gemspecnu[PK% ]77V6gems/net-telnet-0.2.0/Rakefilenu[PK% ]ɷ׽F F L6gems/net-telnet-0.2.0/README.mdnu[PK% ]Gss6gems/net-telnet-0.2.0/bin/setupnu[PK% ]V?OO!6gems/net-telnet-0.2.0/bin/consolenu[PK% ]]8HH'C6gems/net-telnet-0.2.0/lib/net/telnet.rbnu[PK% ]>7C::/L7gems/net-telnet-0.2.0/lib/net/telnet/version.rbnu[PK% ][J¼'{M7gems/net-telnet-0.2.0/lib/net-telnet.rbnu[PK% ]D\\M7gems/bundler-1.17.2/exe/bundlernuȯPK% ]'u"N7gems/bundler-1.17.2/exe/bundlenuȯPK% ]I>>R7cache/rackup-2.1.0.gemnu[PK% ]"א7cache/rack-3.0.8.gemnu[PK% ]w|TT99cache/rake-12.3.3.gemnu[PK% ]1ZZ`:cache/did_you_mean-1.3.0.gemnu[PK% ]:cache/ruby-lsapi-5.5.gemnu[PK% ]bM$pp;cache/xmlrpc-0.3.0.gemnu[PK% ]#:$<cache/test-unit-3.2.9.gemnu[PK% ] '66&>cache/minitest-5.11.3.gemnu[PK% ]5\?cache/ruby-lsapi-5.6.gemnu[PK% ]y<<)@cache/power_assert-1.1.3.gemnu[PK% ]F*BB`e@cache/net-telnet-0.2.0.gemnu[PK% ]>K{{&@doc/rackup-2.1.0/ri/Rack/cdesc-Rack.rinu[PK% ]>Aܶ3{@doc/rackup-2.1.0/ri/Rackup/Lobster/cdesc-Lobster.rinu[PK% ]g,ʭ@doc/rackup-2.1.0/ri/Rackup/Lobster/call-i.rinu[PK% ]kC8@doc/rackup-2.1.0/ri/Rackup/Server/make_profile_name-i.rinu[PK% ]K0@doc/rackup-2.1.0/ri/Rackup/Server/write_pid-i.rinu[PK% ] ,@doc/rackup-2.1.0/ri/Rackup/Server/start-c.rinu[PK% ]ln1,@doc/rackup-2.1.0/ri/Rackup/Server/middleware-c.rinu[PK% ]a14@doc/rackup-2.1.0/ri/Rackup/Server/exit_with_pid-i.rinu[PK% ]?4@doc/rackup-2.1.0/ri/Rackup/Server/daemonize_app-i.rinu[PK% ]@ *R@doc/rackup-2.1.0/ri/Rackup/Server/new-c.rinu[PK% ](L.@doc/rackup-2.1.0/ri/Rackup/Server/options-i.rinu[PK% ]-2@doc/rackup-2.1.0/ri/Rackup/Server/wrapped_app-i.rinu[PK% ]1S@doc/rackup-2.1.0/ri/Rackup/Server/middleware-i.rinu[PK% ] 9((H@doc/rackup-2.1.0/ri/Rackup/Server/default_middleware_by_environment-c.rinu[PK% ]X1M@doc/rackup-2.1.0/ri/Rackup/Server/cdesc-Server.rinu[PK% ]';@doc/rackup-2.1.0/ri/Rackup/Server/Options/handler_opts-i.rinu[PK% ]^t:@doc/rackup-2.1.0/ri/Rackup/Server/Options/cdesc-Options.rinu[PK% ]Lؽ7D@doc/rackup-2.1.0/ri/Rackup/Server/Options/parse%21-i.rinu[PK% ]},,7@doc/rackup-2.1.0/ri/Rackup/Server/handle_profiling-i.rinu[PK% ]Kt((H=@doc/rackup-2.1.0/ri/Rackup/Server/build_app_and_options_from_config-i.rinu[PK% ]|O3@doc/rackup-2.1.0/ri/Rackup/Server/check_pid%21-i.rinu[PK% ]<*:@doc/rackup-2.1.0/ri/Rackup/Server/app-i.rinu[PK% ]/Ld  9@doc/rackup-2.1.0/ri/Rackup/Server/logging_middleware-c.rinu[PK% ]6<@doc/rackup-2.1.0/ri/Rackup/Server/build_app_from_string-i.rinu[PK% ]6n@doc/rackup-2.1.0/ri/Rackup/Server/default_options-i.rinu[PK% ]fz-@doc/rackup-2.1.0/ri/Rackup/Server/server-i.rinu[PK% ]%,%@doc/rackup-2.1.0/ri/Rackup/Server/start-i.rinu[PK% ]8D/'0v@doc/rackup-2.1.0/ri/Rackup/Server/build_app-i.rinu[PK% ]g|4@doc/rackup-2.1.0/ri/Rackup/Server/parse_options-i.rinu[PK% ]d19@doc/rackup-2.1.0/ri/Rackup/Server/opt_parser-i.rinu[PK% ]7@doc/rackup-2.1.0/ri/Rackup/Handler/require_handler-c.rinu[PK% ],R.@doc/rackup-2.1.0/ri/Rackup/Handler/%5b%5d-c.rinu[PK% ]Br +:@doc/rackup-2.1.0/ri/Rackup/Handler/get-c.rinu[PK% ]  3@doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/new-c.rinu[PK% ][|==;@doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/cdesc-WEBrick.rinu[PK% ],  8@doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/shutdown-c.rinu[PK% ] U7@doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/service-i.rinu[PK% ]h3@doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/run-c.rinu[PK% ]Yh=@doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/valid_options-c.rinu[PK% ]`I  9@doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/Input/new-c.rinu[PK% ]g\\?@doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/Input/read_next-i.rinu[PK% ]h;@doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/Input/close-i.rinu[PK% ]RR?8@doc/rackup-2.1.0/ri/Rackup/Handler/WEBrick/Input/cdesc-Input.rinu[PK% ]E'##,9@doc/rackup-2.1.0/ri/Rackup/Handler/pick-c.rinu[PK% ]':eJJ0@doc/rackup-2.1.0/ri/Rackup/Handler/register-c.rinu[PK% ]8S/bAdoc/rackup-2.1.0/ri/Rackup/Handler/default-c.rinu[PK% ]Smf3Adoc/rackup-2.1.0/ri/Rackup/Handler/cdesc-Handler.rinu[PK% ]6UY5Adoc/rackup-2.1.0/ri/Rackup/Handler/CGI/send_body-c.rinu[PK% ]8[Adoc/rackup-2.1.0/ri/Rackup/Handler/CGI/send_headers-c.rinu[PK% ]u|3 Adoc/rackup-2.1.0/ri/Rackup/Handler/CGI/cdesc-CGI.rinu[PK% ]7/W Adoc/rackup-2.1.0/ri/Rackup/Handler/CGI/run-c.rinu[PK% ]ؙ'1 Adoc/rackup-2.1.0/ri/Rackup/Handler/CGI/serve-c.rinu[PK% ]\E]]*Adoc/rackup-2.1.0/ri/Rackup/cdesc-Rackup.rinu[PK% ] D,Adoc/rackup-2.1.0/ri/Rackup/Stream/flush-i.rinu[PK% ]$|*Adoc/rackup-2.1.0/ri/Rackup/Stream/new-c.rinu[PK% ]UU2~Adoc/rackup-2.1.0/ri/Rackup/Stream/close_write-i.rinu[PK% ]>|fEE/5Adoc/rackup-2.1.0/ri/Rackup/Stream/empty%3f-i.rinu[PK% ]S5Adoc/rackup-2.1.0/ri/Rackup/Stream/write_nonblock-i.rinu[PK% ]ޙ0EAdoc/rackup-2.1.0/ri/Rackup/Stream/read_next-i.rinu[PK% ]BB,Adoc/rackup-2.1.0/ri/Rackup/Stream/close-i.rinu[PK% ],;Adoc/rackup-2.1.0/ri/Rackup/Stream/write-i.rinu[PK% ]P`1Adoc/rackup-2.1.0/ri/Rackup/Stream/cdesc-Stream.rinu[PK% ]L1#Adoc/rackup-2.1.0/ri/Rackup/Stream/close_read-i.rinu[PK% ]ۯ6;1%Adoc/rackup-2.1.0/ri/Rackup/Stream/Reader/read_nonblock-i.rinu[PK% ]8&Adoc/rackup-2.1.0/ri/Rackup/Stream/Reader/cdesc-Reader.rinu[PK% ]i:)Adoc/rackup-2.1.0/ri/Rackup/Stream/Reader/read_partial-i.rinu[PK% ]5j))2+Adoc/rackup-2.1.0/ri/Rackup/Stream/Reader/read-i.rinu[PK% ]D|2;0Adoc/rackup-2.1.0/ri/Rackup/Stream/Reader/gets-i.rinu[PK% ]h21Adoc/rackup-2.1.0/ri/Rackup/Stream/Reader/each-i.rinu[PK% ]fy-2Adoc/rackup-2.1.0/ri/Rackup/Stream/output-i.rinu[PK% ]$BMM,@4Adoc/rackup-2.1.0/ri/Rackup/Stream/input-i.rinu[PK% ]<<05Adoc/rackup-2.1.0/ri/Rackup/Stream/closed%3f-i.rinu[PK% ]Z4-#7Adoc/rackup-2.1.0/ri/Rackup/Stream/%3c%3c-i.rinu[PK% ] go8Adoc/rackup-2.1.0/ri/cache.rinu[PK% ]GQ--:?Adoc/rack-3.0.8/ri/Rack/Utils/delete_set_cookie_header-i.rinu[PK% ],*6"DAdoc/rack-3.0.8/ri/Rack/Utils/param_depth_limit%3d-c.rinu[PK% ]Ķ%6EAdoc/rack-3.0.8/ri/Rack/Utils/multipart_file_limit-c.rinu[PK% ]SF,FAdoc/rack-3.0.8/ri/Rack/Utils/clock_time-i.rinu[PK% ]uU55(EHAdoc/rack-3.0.8/ri/Rack/Utils/escape-i.rinu[PK% ]U*IAdoc/rack-3.0.8/ri/Rack/Utils/q_values-i.rinu[PK% ]#-)KAdoc/rack-3.0.8/ri/Rack/Utils/build_query-i.rinu[PK% ]+?-LAdoc/rack-3.0.8/ri/Rack/Utils/status_code-i.rinu[PK% ]ڌ!!9MAdoc/rack-3.0.8/ri/Rack/Utils/delete_cookie_header%21-i.rinu[PK% ]]  +cOAdoc/rack-3.0.8/ri/Rack/Utils/cdesc-Utils.rinu[PK% ]vy  -\Adoc/rack-3.0.8/ri/Rack/Utils/parse_query-i.rinu[PK% ]p8 67^Adoc/rack-3.0.8/ri/Rack/Utils/add_cookie_to_header-i.rinu[PK% ]4_Adoc/rack-3.0.8/ri/Rack/Utils/parse_nested_query-i.rinu[PK% ]i6(aAdoc/rack-3.0.8/ri/Rack/Utils/multipart_part_limit-c.rinu[PK% ]#fBee0bAdoc/rack-3.0.8/ri/Rack/Utils/secure_compare-i.rinu[PK% ]à##;VeAdoc/rack-3.0.8/ri/Rack/Utils/make_delete_cookie_header-i.rinu[PK% ][h4fAdoc/rack-3.0.8/ri/Rack/Utils/build_nested_query-i.rinu[PK% ]!)^hAdoc/rack-3.0.8/ri/Rack/Utils/rfc2822-i.rinu[PK% ] VE*iAdoc/rack-3.0.8/ri/Rack/Utils/unescape-i.rinu[PK% ]2kAdoc/rack-3.0.8/ri/Rack/Utils/forwarded_values-i.rinu[PK% ]Ljj/4mAdoc/rack-3.0.8/ri/Rack/Utils/parse_cookies-i.rinu[PK% ]w+3oAdoc/rack-3.0.8/ri/Rack/Utils/set_cookie_header-i.rinu[PK% ]ܡ6vAdoc/rack-3.0.8/ri/Rack/Utils/parse_cookies_header-i.rinu[PK% ]75ByAdoc/rack-3.0.8/ri/Rack/Utils/Context/cdesc-Context.rinu[PK% ]>^1H}Adoc/rack-3.0.8/ri/Rack/Utils/Context/context-i.rinu[PK% ]M^-~Adoc/rack-3.0.8/ri/Rack/Utils/Context/new-c.rinu[PK% ]y3Adoc/rack-3.0.8/ri/Rack/Utils/Context/recontext-i.rinu[PK% ],9).iAdoc/rack-3.0.8/ri/Rack/Utils/Context/call-i.rinu[PK% ]=K-Adoc/rack-3.0.8/ri/Rack/Utils/Context/for-i.rinu[PK% ]_^-Adoc/rack-3.0.8/ri/Rack/Utils/Context/app-i.rinu[PK% ]V1UAdoc/rack-3.0.8/ri/Rack/Utils/clean_path_info-i.rinu[PK% ] 4Adoc/rack-3.0.8/ri/Rack/Utils/key_space_limit%3d-c.rinu[PK% ]WH6!Adoc/rack-3.0.8/ri/Rack/Utils/set_cookie_header%21-i.rinu[PK% ] /Adoc/rack-3.0.8/ri/Rack/Utils/unescape_path-i.rinu[PK% ]&1Adoc/rack-3.0.8/ri/Rack/Utils/key_space_limit-c.rinu[PK% ]j,,=vAdoc/rack-3.0.8/ri/Rack/Utils/add_remove_cookie_to_header-i.rinu[PK% ]Ə++6Adoc/rack-3.0.8/ri/Rack/Utils/select_best_encoding-i.rinu[PK% ]J?9Adoc/rack-3.0.8/ri/Rack/Utils/multipart_part_limit%3d-c.rinu[PK% ]&2.Adoc/rack-3.0.8/ri/Rack/Utils/best_q_match-i.rinu[PK% ]B^cc-qAdoc/rack-3.0.8/ri/Rack/Utils/escape_html-i.rinu[PK% ]-1Adoc/rack-3.0.8/ri/Rack/Utils/byte_ranges-i.rinu[PK% ]  1Adoc/rack-3.0.8/ri/Rack/Utils/get_byte_ranges-i.rinu[PK% ]w;Adoc/rack-3.0.8/ri/Rack/Utils/HeaderHash/cdesc-HeaderHash.rinu[PK% ]\]]=Adoc/rack-3.0.8/ri/Rack/Utils/delete_set_cookie_header%21-i.rinu[PK% ]=t<Adoc/rack-3.0.8/ri/Rack/Utils/multipart_total_part_limit-c.rinu[PK% ]R/&Adoc/rack-3.0.8/ri/Rack/Utils/valid_path%3f-i.rinu[PK% ]VL 3~Adoc/rack-3.0.8/ri/Rack/Utils/param_depth_limit-c.rinu[PK% ]M2Adoc/rack-3.0.8/ri/Rack/Utils/forwarded_values-c.rinu[PK% ]yF6UAdoc/rack-3.0.8/ri/Rack/Utils/default_query_parser-c.rinu[PK% ]}}-Adoc/rack-3.0.8/ri/Rack/Utils/escape_path-i.rinu[PK% ]K|3Adoc/rack-3.0.8/ri/Rack/Recursive/cdesc-Recursive.rinu[PK% ]N-Adoc/rack-3.0.8/ri/Rack/Recursive/include-i.rinu[PK% ]~q21)@Adoc/rack-3.0.8/ri/Rack/Recursive/new-c.rinu[PK% ]s*Adoc/rack-3.0.8/ri/Rack/Recursive/call-i.rinu[PK% ]O+ܱAdoc/rack-3.0.8/ri/Rack/Recursive/_call-i.rinu[PK% ]O **9.Adoc/rack-3.0.8/ri/Rack/QueryParser/_normalize_params-i.rinu[PK% ]!FF+Adoc/rack-3.0.8/ri/Rack/QueryParser/new-c.rinu[PK% ]o,/AA3bAdoc/rack-3.0.8/ri/Rack/QueryParser/parse_query-i.rinu[PK% ]\E_;Adoc/rack-3.0.8/ri/Rack/QueryParser/params_hash_type%3f-i.rinu[PK% ]XZ5Adoc/rack-3.0.8/ri/Rack/QueryParser/Params/key%3f-i.rinu[PK% ]#P2Adoc/rack-3.0.8/ri/Rack/QueryParser/Params/new-c.rinu[PK% ] ===IAdoc/rack-3.0.8/ri/Rack/QueryParser/Params/to_params_hash-i.rinu[PK% ]9Adoc/rack-3.0.8/ri/Rack/QueryParser/Params/cdesc-Params.rinu[PK% ]95xAdoc/rack-3.0.8/ri/Rack/QueryParser/Params/%5b%5d-i.rinu[PK% ]۷#8Adoc/rack-3.0.8/ri/Rack/QueryParser/Params/%5b%5d%3d-i.rinu[PK% ]"3DAdoc/rack-3.0.8/ri/Rack/QueryParser/Params/to_h-i.rinu[PK% ]|:VAdoc/rack-3.0.8/ri/Rack/QueryParser/parse_nested_query-i.rinu[PK% ]LE   7QAdoc/rack-3.0.8/ri/Rack/QueryParser/new_depth_limit-i.rinu[PK% ]N?"$$0Adoc/rack-3.0.8/ri/Rack/QueryParser/unescape-i.rinu[PK% ]C  9\Adoc/rack-3.0.8/ri/Rack/QueryParser/param_depth_limit-i.rinu[PK% ]tSSQAdoc/rack-3.0.8/ri/Rack/QueryParser/ParamsTooDeepError/cdesc-ParamsTooDeepError.rinu[PK% ])7Adoc/rack-3.0.8/ri/Rack/QueryParser/cdesc-QueryParser.rinu[PK% ]CZJJ4Adoc/rack-3.0.8/ri/Rack/QueryParser/make_default-c.rinu[PK% ]l18gAdoc/rack-3.0.8/ri/Rack/QueryParser/normalize_params-i.rinu[PK% ] ssQAdoc/rack-3.0.8/ri/Rack/QueryParser/ParameterTypeError/cdesc-ParameterTypeError.rinu[PK% ]5WsAdoc/rack-3.0.8/ri/Rack/QueryParser/InvalidParameterError/cdesc-InvalidParameterError.rinu[PK% ]-##>Adoc/rack-3.0.8/ri/Rack/QueryParser/params_hash_has_key%3f-i.rinu[PK% ]}ё3 Adoc/rack-3.0.8/ri/Rack/QueryParser/make_params-i.rinu[PK% ]-Adoc/rack-3.0.8/ri/Rack/ContentLength/new-c.rinu[PK% ].Adoc/rack-3.0.8/ri/Rack/ContentLength/call-i.rinu[PK% ]ڝZ<;HAdoc/rack-3.0.8/ri/Rack/ContentLength/cdesc-ContentLength.rinu[PK% ]-gw?Adoc/rack-3.0.8/ri/Rack/CommonLogger/extract_content_length-i.rinu[PK% ]TjXROO,Adoc/rack-3.0.8/ri/Rack/CommonLogger/new-c.rinu[PK% ]dG@@9xAdoc/rack-3.0.8/ri/Rack/CommonLogger/cdesc-CommonLogger.rinu[PK% ]--!Adoc/rack-3.0.8/ri/Rack/CommonLogger/call-i.rinu[PK% ]&-qq,zAdoc/rack-3.0.8/ri/Rack/CommonLogger/log-i.rinu[PK% ]o  3GAdoc/rack-3.0.8/ri/Rack/ShowExceptions/template-i.rinu[PK% ]ˍ.Adoc/rack-3.0.8/ri/Rack/ShowExceptions/new-c.rinu[PK% ]9Q9Adoc/rack-3.0.8/ri/Rack/ShowExceptions/dump_exception-i.rinu[PK% ]';/Adoc/rack-3.0.8/ri/Rack/ShowExceptions/call-i.rinu[PK% ]OA:Bdoc/rack-3.0.8/ri/Rack/ShowExceptions/accepts_html%3f-i.rinu[PK% ]!!?Bdoc/rack-3.0.8/ri/Rack/ShowExceptions/prefers_plaintext%3f-i.rinu[PK% ]_i1Bdoc/rack-3.0.8/ri/Rack/ShowExceptions/pretty-i.rinu[PK% ]Ĉ`OO=Bdoc/rack-3.0.8/ri/Rack/ShowExceptions/cdesc-ShowExceptions.rinu[PK% ]HH=E Bdoc/rack-3.0.8/ri/Rack/ConditionalGet/cdesc-ConditionalGet.rinu[PK% ]dq$.Bdoc/rack-3.0.8/ri/Rack/ConditionalGet/new-c.rinu[PK% ]9/\Bdoc/rack-3.0.8/ri/Rack/ConditionalGet/call-i.rinu[PK% ]>P:DBdoc/rack-3.0.8/ri/Rack/ConditionalGet/etag_matches%3f-i.rinu[PK% ]xӉ3wBdoc/rack-3.0.8/ri/Rack/ConditionalGet/fresh%3f-i.rinu[PK% ]w5cBdoc/rack-3.0.8/ri/Rack/ConditionalGet/to_rfc2822-i.rinu[PK% ]CI<~Bdoc/rack-3.0.8/ri/Rack/ConditionalGet/modified_since%3f-i.rinu[PK% ].5**$Bdoc/rack-3.0.8/ri/Rack/cdesc-Rack.rinu[PK% ]nvm0G:Bdoc/rack-3.0.8/ri/Rack/NullLogger/formatter-i.rinu[PK% ],84;Bdoc/rack-3.0.8/ri/Rack/NullLogger/sev_threshold-i.rinu[PK% ]~/=Bdoc/rack-3.0.8/ri/Rack/NullLogger/fatal%3f-i.rinu[PK% ] 7  +l>Bdoc/rack-3.0.8/ri/Rack/NullLogger/warn-i.rinu[PK% ]ٸ5u-?Bdoc/rack-3.0.8/ri/Rack/NullLogger/reopen-i.rinu[PK% ]P*6ABdoc/rack-3.0.8/ri/Rack/NullLogger/new-c.rinu[PK% ]V..BBdoc/rack-3.0.8/ri/Rack/NullLogger/warn%21-i.rinu[PK% ]l/CBdoc/rack-3.0.8/ri/Rack/NullLogger/fatal%21-i.rinu[PK% ]j.7EBdoc/rack-3.0.8/ri/Rack/NullLogger/warn%3f-i.rinu[PK% ]e/FBdoc/rack-3.0.8/ri/Rack/NullLogger/debug%21-i.rinu[PK% ]).+GBdoc/rack-3.0.8/ri/Rack/NullLogger/call-i.rinu[PK% ]6,:IBdoc/rack-3.0.8/ri/Rack/NullLogger/close-i.rinu[PK% ]5!C/JBdoc/rack-3.0.8/ri/Rack/NullLogger/error%3f-i.rinu[PK% ]><9KBdoc/rack-3.0.8/ri/Rack/NullLogger/datetime_format%3d-i.rinu[PK% ](r,mMBdoc/rack-3.0.8/ri/Rack/NullLogger/error-i.rinu[PK% ]p.NBdoc/rack-3.0.8/ri/Rack/NullLogger/unknown-i.rinu[PK% ]o/GPBdoc/rack-3.0.8/ri/Rack/NullLogger/debug%3f-i.rinu[PK% ]z!2QBdoc/rack-3.0.8/ri/Rack/NullLogger/progname%3d-i.rinu[PK% ]q##* SBdoc/rack-3.0.8/ri/Rack/NullLogger/add-i.rinu[PK% ] j5TBdoc/rack-3.0.8/ri/Rack/NullLogger/cdesc-NullLogger.rinu[PK% ]eZ7XBdoc/rack-3.0.8/ri/Rack/NullLogger/sev_threshold%3d-i.rinu[PK% ]=U  +WZBdoc/rack-3.0.8/ri/Rack/NullLogger/info-i.rinu[PK% ]  3[Bdoc/rack-3.0.8/ri/Rack/NullLogger/formatter%3d-i.rinu[PK% ]BO,,]Bdoc/rack-3.0.8/ri/Rack/NullLogger/level-i.rinu[PK% ]Wh.^Bdoc/rack-3.0.8/ri/Rack/NullLogger/info%21-i.rinu[PK% ]M TP._Bdoc/rack-3.0.8/ri/Rack/NullLogger/info%3f-i.rinu[PK% ]  6,aBdoc/rack-3.0.8/ri/Rack/NullLogger/datetime_format-i.rinu[PK% ]\##*bBdoc/rack-3.0.8/ri/Rack/NullLogger/log-i.rinu[PK% ]E]+/dBdoc/rack-3.0.8/ri/Rack/NullLogger/error%21-i.rinu[PK% ]d-teBdoc/rack-3.0.8/ri/Rack/NullLogger/%3c%3c-i.rinu[PK% ]$/fBdoc/rack-3.0.8/ri/Rack/NullLogger/level%3d-i.rinu[PK% ]bKg,$hBdoc/rack-3.0.8/ri/Rack/NullLogger/fatal-i.rinu[PK% ]6,iBdoc/rack-3.0.8/ri/Rack/NullLogger/debug-i.rinu[PK% ]q/jBdoc/rack-3.0.8/ri/Rack/NullLogger/progname-i.rinu[PK% ]z>0UlBdoc/rack-3.0.8/ri/Rack/Request/delete_param-i.rinu[PK% ]Q#'mBdoc/rack-3.0.8/ri/Rack/Request/new-c.rinu[PK% ]mii3nBdoc/rack-3.0.8/ri/Rack/Request/Env/each_header-i.rinu[PK% ]sbB2pBdoc/rack-3.0.8/ri/Rack/Request/Env/add_header-i.rinu[PK% ])g||5sBdoc/rack-3.0.8/ri/Rack/Request/Env/has_header%3f-i.rinu[PK% ]34UU5uBdoc/rack-3.0.8/ri/Rack/Request/Env/delete_header-i.rinu[PK% ])hL+ZwBdoc/rack-3.0.8/ri/Rack/Request/Env/new-c.rinu[PK% ]ątt/xBdoc/rack-3.0.8/ri/Rack/Request/Env/cdesc-Env.rinu[PK% ]ӏ4x{Bdoc/rack-3.0.8/ri/Rack/Request/Env/fetch_header-i.rinu[PK% ]UU2k}Bdoc/rack-3.0.8/ri/Rack/Request/Env/set_header-i.rinu[PK% ]t˰  7"Bdoc/rack-3.0.8/ri/Rack/Request/Env/initialize_copy-i.rinu[PK% ]S44+Bdoc/rack-3.0.8/ri/Rack/Request/Env/env-i.rinu[PK% ] @LL2!Bdoc/rack-3.0.8/ri/Rack/Request/Env/get_header-i.rinu[PK% ]Ƹ*σBdoc/rack-3.0.8/ri/Rack/Request/params-i.rinu[PK% ]q>Bdoc/rack-3.0.8/ri/Rack/Request/x_forwarded_proto_priority-c.rinu[PK% ]""5Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/authority-i.rinu[PK% ]4ee8Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/delete_param-i.rinu[PK% ]5#>>5ݍBdoc/rack-3.0.8/ri/Rack/Request/Helpers/values_at-i.rinu[PK% ](܃>Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/get_http_forwarded-i.rinu[PK% ]!X8rBdoc/rack-3.0.8/ri/Rack/Request/Helpers/query_parser-i.rinu[PK% ]#~8Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/form_data%3f-i.rinu[PK% ]j2JBdoc/rack-3.0.8/ri/Rack/Request/Helpers/scheme-i.rinu[PK% ]ļ>Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/forwarded_priority-i.rinu[PK% ]y:'Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/allowed_scheme-i.rinu[PK% ]7Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/cdesc-Helpers.rinu[PK% ]1`gg5!Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/wrap_ipv6-i.rinu[PK% ][3Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/session-i.rinu[PK% ]X$ĵ##FLBdoc/rack-3.0.8/ri/Rack/Request/Helpers/x_forwarded_proto_priority-i.rinu[PK% ]^F\mm6Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/options%3f-i.rinu[PK% ]7x3Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/cookies-i.rinu[PK% ]"J?Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/forwarded_authority-i.rinu[PK% ]Ah<Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/server_authority-i.rinu[PK% ]:^!(4Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/fullpath-i.rinu[PK% ]qx4Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/hostname-i.rinu[PK% ]|gg4iBdoc/rack-3.0.8/ri/Rack/Request/Helpers/patch%3f-i.rinu[PK% ]i74Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/parse_query-i.rinu[PK% ]X=Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/media_type_params-i.rinu[PK% ]ygg4Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/trace%3f-i.rinu[PK% ]T2hBdoc/rack-3.0.8/ri/Rack/Request/Helpers/ssl%3f-i.rinu[PK% ]w52Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/logger-i.rinu[PK% ]*e6Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/media_type-i.rinu[PK% ]˭-  <Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/trusted_proxy%3f-i.rinu[PK% ]v0Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/port-i.rinu[PK% ]G`%%DBdoc/rack-3.0.8/ri/Rack/Request/Helpers/parse_http_accept_header-i.rinu[PK% ]  ;Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/accept_language-i.rinu[PK% ]eh7Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/server_port-i.rinu[PK% ] >l2eBdoc/rack-3.0.8/ri/Rack/Request/Helpers/params-i.rinu[PK% ]aa2Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/put%3f-i.rinu[PK% ]ovx.zBdoc/rack-3.0.8/ri/Rack/Request/Helpers/ip-i.rinu[PK% ].u  :Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/content_length-i.rinu[PK% ]x#z=>Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/parseable_data%3f-i.rinu[PK% ].7DD2aBdoc/rack-3.0.8/ri/Rack/Request/Helpers/%5b%5d-i.rinu[PK% ]75  :Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/request_method-i.rinu[PK% ]F  ;{Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/accept_encoding-i.rinu[PK% ]R<5Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/path_info-i.rinu[PK% ]F..;WBdoc/rack-3.0.8/ri/Rack/Request/Helpers/content_charset-i.rinu[PK% ]>J6  ;Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/parse_multipart-i.rinu[PK% ]]tGG:hBdoc/rack-3.0.8/ri/Rack/Request/Helpers/host_authority-i.rinu[PK% ]*fd?WW0Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/host-i.rinu[PK% ]|_E0Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/path-i.rinu[PK% ]ppy#jj5&Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/unlink%3f-i.rinu[PK% ]ɰ6Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/user_agent-i.rinu[PK% ]y8]Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/content_type-i.rinu[PK% ]?s1H4Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/base_url-i.rinu[PK% ]  8-Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/split_header-i.rinu[PK% ]k<Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/forwarded_scheme-i.rinu[PK% ]#dd3Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/post%3f-i.rinu[PK% ]~e$$:Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/host_with_port-i.rinu[PK% ]дdd3qBdoc/rack-3.0.8/ri/Rack/Request/Helpers/link%3f-i.rinu[PK% ]ls58Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/%5b%5d%3d-i.rinu[PK% ]4ώ7Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/server_name-i.rinu[PK% ]Id0Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/body-i.rinu[PK% ]ى;dBdoc/rack-3.0.8/ri/Rack/Request/Helpers/split_authority-i.rinu[PK% ]&jj5Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/delete%3f-i.rinu[PK% ]A9Bdoc/rack-3.0.8/ri/Rack/Request/Helpers/forwarded_for-i.rinu[PK% ]my`8%Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/query_string-i.rinu[PK% ]+  ;Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/default_session-i.rinu[PK% ]"HH/ Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/GET-i.rinu[PK% ]91  :Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/forwarded_port-i.rinu[PK% ]V Paa2&Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/get%3f-i.rinu[PK% ]єoo8Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/update_param-i.rinu[PK% ];W11G Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/reject_trusted_ip_addresses-i.rinu[PK% ]nZ[[3h Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/referer-i.rinu[PK% ]kW7&Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/script_name-i.rinu[PK% ]A[[/Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/url-i.rinu[PK% ]n0KCdoc/rack-3.0.8/ri/Rack/Request/Helpers/POST-i.rinu[PK% ]):yCdoc/rack-3.0.8/ri/Rack/Request/Helpers/script_name%3d-i.rinu[PK% ]dd3Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/head%3f-i.rinu[PK% ];2Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/xhr%3f-i.rinu[PK% ]$-++4 Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/referrer-i.rinu[PK% ]tX8Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/path_info%3d-i.rinu[PK% ]X|  ;Cdoc/rack-3.0.8/ri/Rack/Request/Helpers/session_options-i.rinu[PK% ]pJ6zCdoc/rack-3.0.8/ri/Rack/Request/forwarded_priority-c.rinu[PK% ]e|P0q Cdoc/rack-3.0.8/ri/Rack/Request/update_param-i.rinu[PK% ]@]rr/!Cdoc/rack-3.0.8/ri/Rack/Request/cdesc-Request.rinu[PK% ]È*-&Cdoc/rack-3.0.8/ri/Rack/Request/ip_filter-c.rinu[PK% ]/'Cdoc/rack-3.0.8/ri/Rack/MockRequest/env_for-c.rinu[PK% ]Fii,,Cdoc/rack-3.0.8/ri/Rack/MockRequest/head-i.rinu[PK% ]v+-Cdoc/rack-3.0.8/ri/Rack/MockRequest/new-c.rinu[PK% ]Fxii,8/Cdoc/rack-3.0.8/ri/Rack/MockRequest/post-i.rinu[PK% ]#өss/0Cdoc/rack-3.0.8/ri/Rack/MockRequest/options-i.rinu[PK% ]i|ff+2Cdoc/rack-3.0.8/ri/Rack/MockRequest/get-i.rinu[PK% ]!?oo.4Cdoc/rack-3.0.8/ri/Rack/MockRequest/delete-i.rinu[PK% ]sE]6Cdoc/rack-3.0.8/ri/Rack/MockRequest/FatalWarning/cdesc-FatalWarning.rinu[PK% ]bR98Cdoc/rack-3.0.8/ri/Rack/MockRequest/FatalWarner/flush-i.rinu[PK% ];<  89Cdoc/rack-3.0.8/ri/Rack/MockRequest/FatalWarner/puts-i.rinu[PK% ]mh  :i;Cdoc/rack-3.0.8/ri/Rack/MockRequest/FatalWarner/string-i.rinu[PK% ];CCw-[Cdoc/rack-3.0.8/ri/Rack/Response/empty%3f-i.rinu[PK% ]  -\Cdoc/rack-3.0.8/ri/Rack/Response/redirect-i.rinu[PK% ]ӎ1:^Cdoc/rack-3.0.8/ri/Rack/Response/cdesc-Response.rinu[PK% ]V}U*`eCdoc/rack-3.0.8/ri/Rack/Response/close-i.rinu[PK% ]gA+fCdoc/rack-3.0.8/ri/Rack/Response/%5b%5d-i.rinu[PK% ]n˭h*hCdoc/rack-3.0.8/ri/Rack/Response/write-i.rinu[PK% ]RP+jCdoc/rack-3.0.8/ri/Rack/Response/status-i.rinu[PK% ]"+^kCdoc/rack-3.0.8/ri/Rack/Response/finish-i.rinu[PK% ]#F  8mCdoc/rack-3.0.8/ri/Rack/Response/Helpers/location%3d-i.rinu[PK% ]AQ?EoCdoc/rack-3.0.8/ri/Rack/Response/Helpers/request_timeout%3f-i.rinu[PK% ]U7pCdoc/rack-3.0.8/ri/Rack/Response/Helpers/invalid%3f-i.rinu[PK% ]T>l:+rCdoc/rack-3.0.8/ri/Rack/Response/Helpers/no_content%3f-i.rinu[PK% ]5%<sCdoc/rack-3.0.8/ri/Rack/Response/Helpers/do_not_cache%21-i.rinu[PK% ]Nz7uCdoc/rack-3.0.8/ri/Rack/Response/Helpers/add_header-i.rinu[PK% ]ty:xCdoc/rack-3.0.8/ri/Rack/Response/Helpers/delete_cookie-i.rinu[PK% ]kgA-zCdoc/rack-3.0.8/ri/Rack/Response/Helpers/set_cookie_header%3d-i.rinu[PK% ]1d>  ={Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/unprocessable%3f-i.rinu[PK% ]4[__80}Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/cdesc-Helpers.rinu[PK% ]z>Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/not_acceptable%3f-i.rinu[PK% ]̋$=sCdoc/rack-3.0.8/ri/Rack/Response/Helpers/buffered_body%21-i.rinu[PK% ][Qm3Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/append-i.rinu[PK% ]pC8VCdoc/rack-3.0.8/ri/Rack/Response/Helpers/accepted%3f-i.rinu[PK% ]W>Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/media_type_params-i.rinu[PK% ]a7@Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/include%3f-i.rinu[PK% ]&Oz7Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/media_type-i.rinu[PK% ]2^1Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/etag-i.rinu[PK% ]E :qCdoc/rack-3.0.8/ri/Rack/Response/Helpers/successful%3f-i.rinu[PK% ]Lz>Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/set_cookie_header-i.rinu[PK% ]%{CaCdoc/rack-3.0.8/ri/Rack/Response/Helpers/precondition_failed%3f-i.rinu[PK% ]  ;Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/content_length-i.rinu[PK% ]Jc  <cCdoc/rack-3.0.8/ri/Rack/Response/Helpers/server_error%3f-i.rinu[PK% ];ٕCdoc/rack-3.0.8/ri/Rack/Response/Helpers/redirection%3f-i.rinu[PK% ];LCdoc/rack-3.0.8/ri/Rack/Response/Helpers/bad_request%3f-i.rinu[PK% ]z5Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/location-i.rinu[PK% ]5B$Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/method_not_allowed%3f-i.rinu[PK% ]6My7Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/created%3f-i.rinu[PK% ]Q9Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/not_found%3f-i.rinu[PK% ]'C555Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/cache%21-i.rinu[PK% ]M SS9Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/content_type-i.rinu[PK% ]3(  <֢Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/unauthorized%3f-i.rinu[PK% ]H*a2LCdoc/rack-3.0.8/ri/Rack/Response/Helpers/ok%3f-i.rinu[PK% ]|w  =Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/informational%3f-i.rinu[PK% ]74Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/etag%3d-i.rinu[PK% ]t3aa<Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/content_type%3d-i.rinu[PK% ]7MCdoc/rack-3.0.8/ri/Rack/Response/Helpers/set_cookie-i.rinu[PK% ]hZA«Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/moved_permanently%3f-i.rinu[PK% ]b_bJ9GCdoc/rack-3.0.8/ri/Rack/Response/Helpers/forbidden%3f-i.rinu[PK% ]`,8  :Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/cache_control-i.rinu[PK% ]=V8(Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/redirect%3f-i.rinu[PK% ]g  <Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/client_error%3f-i.rinu[PK% ]/=Cdoc/rack-3.0.8/ri/Rack/Response/Helpers/cache_control%3d-i.rinu[PK% ]Aw  /Cdoc/rack-3.0.8/ri/Rack/Response/set_header-i.rinu[PK% ]'|.Cdoc/rack-3.0.8/ri/Rack/Response/%5b%5d%3d-i.rinu[PK% ]Fl4)Cdoc/rack-3.0.8/ri/Rack/Response/body-i.rinu[PK% ].,ŸCdoc/rack-3.0.8/ri/Rack/Response/headers-i.rinu[PK% ][w/Cdoc/rack-3.0.8/ri/Rack/Response/chunked%3f-i.rinu[PK% ] ʋ)fCdoc/rack-3.0.8/ri/Rack/Response/each-i.rinu[PK% ](6Cdoc/rack-3.0.8/ri/Rack/Response/Raw/has_header%3f-i.rinu[PK% ]*u6Cdoc/rack-3.0.8/ri/Rack/Response/Raw/delete_header-i.rinu[PK% ]z? ,Cdoc/rack-3.0.8/ri/Rack/Response/Raw/new-c.rinu[PK% ]}/Cdoc/rack-3.0.8/ri/Rack/Response/Raw/status-i.rinu[PK% ]ձ=ii07Cdoc/rack-3.0.8/ri/Rack/Response/Raw/cdesc-Raw.rinu[PK% ]pT3Cdoc/rack-3.0.8/ri/Rack/Response/Raw/set_header-i.rinu[PK% ]0hCdoc/rack-3.0.8/ri/Rack/Response/Raw/headers-i.rinu[PK% ]*3Cdoc/rack-3.0.8/ri/Rack/Response/Raw/get_header-i.rinu[PK% ]g99+"Cdoc/rack-3.0.8/ri/Rack/Response/header-i.rinu[PK% ]c6Cdoc/rack-3.0.8/ri/Rack/Response/no_entity_body%3f-i.rinu[PK% ][/!Cdoc/rack-3.0.8/ri/Rack/Response/get_header-i.rinu[PK% ]KK*Cdoc/rack-3.0.8/ri/Rack/Mime/mime_type-c.rinu[PK% ]/}})=Cdoc/rack-3.0.8/ri/Rack/Mime/match%3f-c.rinu[PK% ]HKK*Cdoc/rack-3.0.8/ri/Rack/Mime/mime_type-i.rinu[PK% ]5 }})Cdoc/rack-3.0.8/ri/Rack/Mime/match%3f-i.rinu[PK% ])Cdoc/rack-3.0.8/ri/Rack/Mime/cdesc-Mime.rinu[PK% ]C/7mCdoc/rack-3.0.8/ri/Rack/Auth/Basic/Request/username-i.rinu[PK% ]C7Cdoc/rack-3.0.8/ri/Rack/Auth/Basic/Request/basic%3f-i.rinu[PK% ])*K  :?Cdoc/rack-3.0.8/ri/Rack/Auth/Basic/Request/credentials-i.rinu[PK% ]\I  :Cdoc/rack-3.0.8/ri/Rack/Auth/Basic/Request/cdesc-Request.rinu[PK% ]-X+&Cdoc/rack-3.0.8/ri/Rack/Auth/Basic/call-i.rinu[PK% ]5R]0uCdoc/rack-3.0.8/ri/Rack/Auth/Basic/challenge-i.rinu[PK% ]s0Cdoc/rack-3.0.8/ri/Rack/Auth/Basic/cdesc-Basic.rinu[PK% ]S>j/CCdoc/rack-3.0.8/ri/Rack/Auth/Basic/valid%3f-i.rinu[PK% ]Q=Cdoc/rack-3.0.8/ri/Rack/Auth/Digest/Request/respond_to%3f-i.rinu[PK% ]q5Cdoc/rack-3.0.8/ri/Rack/Auth/Digest/Request/nonce-i.rinu[PK% ]W6Cdoc/rack-3.0.8/ri/Rack/Auth/Digest/Request/params-i.rinu[PK% ].6Cdoc/rack-3.0.8/ri/Rack/Auth/Digest/Request/method-i.rinu[PK% ]&t]9PCdoc/rack-3.0.8/ri/Rack/Auth/Digest/Request/digest%3f-i.rinu[PK% ]♏4^^;Cdoc/rack-3.0.8/ri/Rack/Auth/Digest/Request/cdesc-Request.rinu[PK% ].?>Cdoc/rack-3.0.8/ri/Rack/Auth/Digest/Request/correct_uri%3f-i.rinu[PK% ]H(>Cdoc/rack-3.0.8/ri/Rack/Auth/Digest/Request/method_missing-i.rinu[PK% ]Wa6Cdoc/rack-3.0.8/ri/Rack/Auth/Digest/Params/dequote-c.rinu[PK% ]7=x2Cdoc/rack-3.0.8/ri/Rack/Auth/Digest/Params/new-c.rinu[PK% ]C~4_Cdoc/rack-3.0.8/ri/Rack/Auth/Digest/Params/parse-c.rinu[PK% ]X\9Cdoc/rack-3.0.8/ri/Rack/Auth/Digest/Params/cdesc-Params.rinu[PK% ]DADdoc/rack-3.0.8/ri/Rack/Auth/Digest/Params/split_header_value-c.rinu[PK% ]/7:5vDdoc/rack-3.0.8/ri/Rack/Auth/Digest/Params/%5b%5d-i.rinu[PK% ]Rj3Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Params/to_s-i.rinu[PK% ]83Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Params/%5b%5d%3d-i.rinu[PK% ]kC4Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Params/quote-i.rinu[PK% ]A8Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/time_limit-c.rinu[PK% ]_Q?!!1v Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/new-c.rinu[PK% ]4T3 Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/parse-c.rinu[PK% ]'2^ Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/to_s-i.rinu[PK% ]#$v6Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/stale%3f-i.rinu[PK% ]4Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/digest-i.rinu[PK% ]iPt7Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/cdesc-Nonce.rinu[PK% ],6Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/fresh%3f-i.rinu[PK% ]N80:96Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/private_key-c.rinu[PK% ],}L6Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/Nonce/valid%3f-i.rinu[PK% ]K2Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/cdesc-Digest.rinu[PK% ]As<Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/passwords_hashed-i.rinu[PK% ]-Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/H-i.rinu[PK% ]C  :Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/valid_nonce%3f-i.rinu[PK% ]M i.p Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/A1-i.rinu[PK% ]{0.!Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/KD-i.rinu[PK% ]Zu##/,#Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/new-c.rinu[PK% ]RL?$Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/passwords_hashed%3f-i.rinu[PK% ]R60-&Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/call-i.rinu[PK% ]BNGT2'Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/params-i.rinu[PK% ]nH  5(Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/challenge-i.rinu[PK% ]/  ;[*Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/valid_digest%3f-i.rinu[PK% ]  2+Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/digest-i.rinu[PK% ]׏02>-Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/opaque-i.rinu[PK% ]{993.Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/cdesc-MD5.rinu[PK% ]8u.?4Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/A2-i.rinu[PK% ]/5Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/md5-i.rinu[PK% ]wZ87Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/valid_qop%3f-i.rinu[PK% ]ns4t8Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/valid%3f-i.rinu[PK% ]sr  ;9Ddoc/rack-3.0.8/ri/Rack/Auth/Digest/MD5/valid_opaque%3f-i.rinu[PK% ]3//4O;Ddoc/rack-3.0.8/ri/Rack/Auth/AbstractHandler/new-c.rinu[PK% ]Rk6Ddoc/rack-3.0.8/ri/Rack/Auth/AbstractHandler/bad_request-i.rinu[PK% ] ===?Ddoc/rack-3.0.8/ri/Rack/Auth/AbstractHandler/unauthorized-i.rinu[PK% ]wuDADdoc/rack-3.0.8/ri/Rack/Auth/AbstractHandler/cdesc-AbstractHandler.rinu[PK% ],6DDdoc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/parts-i.rinu[PK% ]=7hFDdoc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/scheme-i.rinu[PK% ]|L++BGDdoc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/authorization_key-i.rinu[PK% ]u14IDdoc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/new-c.rinu[PK% ]7JDdoc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/params-i.rinu[PK% ]jDqLDdoc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/cdesc-AbstractRequest.rinu[PK% ]X8ODdoc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/request-i.rinu[PK% ]d_<WQDdoc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/provided%3f-i.rinu[PK% ]0/9RDdoc/rack-3.0.8/ri/Rack/Auth/AbstractRequest/valid%3f-i.rinu[PK% ]cH311)ZTDdoc/rack-3.0.8/ri/Rack/Auth/cdesc-Auth.rinu[PK% ]_ ph$VDdoc/rack-3.0.8/ri/Rack/Lock/new-c.rinu[PK% ]HU%0XDdoc/rack-3.0.8/ri/Rack/Lock/call-i.rinu[PK% ]DE'kYDdoc/rack-3.0.8/ri/Rack/Lock/unlock-i.rinu[PK% ].v:ZZ)ZDdoc/rack-3.0.8/ri/Rack/Lock/cdesc-Lock.rinu[PK% ]f88)]]Ddoc/rack-3.0.8/ri/Rack/Head/cdesc-Head.rinu[PK% ]wt$_Ddoc/rack-3.0.8/ri/Rack/Head/new-c.rinu[PK% ]%'aDdoc/rack-3.0.8/ri/Rack/Head/call-i.rinu[PK% ]^,-bbDdoc/rack-3.0.8/ri/Rack/Static/route_file-i.rinu[PK% ]f4cDdoc/rack-3.0.8/ri/Rack/Static/add_index_root%3f-i.rinu[PK% ]m $&eDdoc/rack-3.0.8/ri/Rack/Static/new-c.rinu[PK% ]U,nfDdoc/rack-3.0.8/ri/Rack/Static/can_serve-i.rinu[PK% ];'gDdoc/rack-3.0.8/ri/Rack/Static/call-i.rinu[PK% ]CDD-iDdoc/rack-3.0.8/ri/Rack/Static/cdesc-Static.rinu[PK% ]rQ  6yDdoc/rack-3.0.8/ri/Rack/Static/overwrite_file_path-i.rinu[PK% ]+TT3{Ddoc/rack-3.0.8/ri/Rack/Static/applicable_rules-i.rinu[PK% ] 4-|Ddoc/rack-3.0.8/ri/Rack/Config/cdesc-Config.rinu[PK% ]^&Ddoc/rack-3.0.8/ri/Rack/Config/new-c.rinu[PK% ].'QDdoc/rack-3.0.8/ri/Rack/Config/call-i.rinu[PK% ]_UC%Ddoc/rack-3.0.8/ri/Rack/File/fail-i.rinu[PK% ]_y$Ddoc/rack-3.0.8/ri/Rack/File/new-c.rinu[PK% ]Kcڄ)RDdoc/rack-3.0.8/ri/Rack/File/filesize-i.rinu[PK% ]_)Ddoc/rack-3.0.8/ri/Rack/File/cdesc-File.rinu[PK% ]t%Ddoc/rack-3.0.8/ri/Rack/File/call-i.rinu[PK% ]i$9Ddoc/rack-3.0.8/ri/Rack/File/get-i.rinu[PK% ]+S(tDdoc/rack-3.0.8/ri/Rack/File/serving-i.rinu[PK% ]ldd*ŏDdoc/rack-3.0.8/ri/Rack/File/mime_type-i.rinu[PK% ]Ҿ%Ddoc/rack-3.0.8/ri/Rack/File/root-i.rinu[PK% ]xҵ$Ddoc/rack-3.0.8/ri/Rack/Lint/new-c.rinu[PK% ]U**)Ddoc/rack-3.0.8/ri/Rack/Lint/cdesc-Lint.rinu[PK% ]OHtDdoc/rack-3.0.8/ri/Rack/Lint/Wrapper/StreamWrapper/cdesc-StreamWrapper.rinu[PK% ]PR$||4Ddoc/rack-3.0.8/ri/Rack/Lint/Wrapper/cdesc-Wrapper.rinu[PK% ]UۘFfDdoc/rack-3.0.8/ri/Rack/Lint/Wrapper/ErrorWrapper/cdesc-ErrorWrapper.rinu[PK% ] GFtDdoc/rack-3.0.8/ri/Rack/Lint/Wrapper/InputWrapper/cdesc-InputWrapper.rinu[PK% ]3/Y8Ddoc/rack-3.0.8/ri/Rack/Lint/LintError/cdesc-LintError.rinu[PK% ] 6,pDdoc/rack-3.0.8/ri/Rack/ETag/digest_body-i.rinu[PK% ]s$$$¡Ddoc/rack-3.0.8/ri/Rack/ETag/new-c.rinu[PK% ]Ծ//:Ddoc/rack-3.0.8/ri/Rack/ETag/etag_status%3f-i.rinu[PK% ]lG%Ddoc/rack-3.0.8/ri/Rack/ETag/call-i.rinu[PK% ]lH0ΥDdoc/rack-3.0.8/ri/Rack/ETag/skip_caching%3f-i.rinu[PK% ]02o)+Ddoc/rack-3.0.8/ri/Rack/ETag/cdesc-ETag.rinu[PK% ] -Ddoc/rack-3.0.8/ri/Rack/Events/cdesc-Events.rinu[PK% ]!r\/Ddoc/rack-3.0.8/ri/Rack/Events/make_request-i.rinu[PK% ]伞HDdoc/rack-3.0.8/ri/Rack/Events/EventedBodyProxy/cdesc-EventedBodyProxy.rinu[PK% ] g3Ddoc/rack-3.0.8/ri/Rack/Events/Abstract/on_send-i.rinu[PK% ]87L_5fDdoc/rack-3.0.8/ri/Rack/Events/Abstract/on_commit-i.rinu[PK% ]Ud5Ddoc/rack-3.0.8/ri/Rack/Events/Abstract/on_finish-i.rinu[PK% ]"Pv8@Ddoc/rack-3.0.8/ri/Rack/Events/Abstract/cdesc-Abstract.rinu[PK% ]j  4Ddoc/rack-3.0.8/ri/Rack/Events/Abstract/on_error-i.rinu[PK% ]x4Ddoc/rack-3.0.8/ri/Rack/Events/Abstract/on_start-i.rinu[PK% ]B\ 0~Ddoc/rack-3.0.8/ri/Rack/Events/make_response-i.rinu[PK% ]ֹ&Ddoc/rack-3.0.8/ri/Rack/Events/new-c.rinu[PK% ]g':Ddoc/rack-3.0.8/ri/Rack/Events/call-i.rinu[PK% ]K,,}Ddoc/rack-3.0.8/ri/Rack/Events/on_commit-i.rinu[PK% ]h~HDdoc/rack-3.0.8/ri/Rack/Events/BufferedResponse/cdesc-BufferedResponse.rinu[PK% ]V,Ddoc/rack-3.0.8/ri/Rack/Events/on_finish-i.rinu[PK% ]u+XDdoc/rack-3.0.8/ri/Rack/Events/on_error-i.rinu[PK% ]| j++Ddoc/rack-3.0.8/ri/Rack/Events/on_start-i.rinu[PK% ]}'Ddoc/rack-3.0.8/ri/Rack/Builder/app-c.rinu[PK% ]T66/Ddoc/rack-3.0.8/ri/Rack/Builder/cdesc-Builder.rinu[PK% ]໡0Ddoc/rack-3.0.8/ri/Rack/Builder/generate_map-i.rinu[PK% ](xbZ'Ddoc/rack-3.0.8/ri/Rack/Builder/new-c.rinu[PK% ]S'Ddoc/rack-3.0.8/ri/Rack/Builder/use-i.rinu[PK% ]'Ddoc/rack-3.0.8/ri/Rack/Builder/run-i.rinu[PK% ]h>*Ddoc/rack-3.0.8/ri/Rack/Builder/warmup-i.rinu[PK% ])k( Ddoc/rack-3.0.8/ri/Rack/Builder/call-i.rinu[PK% ]X9//.aDdoc/rack-3.0.8/ri/Rack/Builder/parse_file-c.rinu[PK% ]ϑMM*Ddoc/rack-3.0.8/ri/Rack/Builder/to_app-i.rinu[PK% ]3Ddoc/rack-3.0.8/ri/Rack/Builder/new_from_string-c.rinu[PK% ]%LD.Ddoc/rack-3.0.8/ri/Rack/Builder/freeze_app-i.rinu[PK% ]\66'Ddoc/rack-3.0.8/ri/Rack/Builder/map-i.rinu[PK% ]n?x-.Edoc/rack-3.0.8/ri/Rack/Builder/load_file-c.rinu[PK% ]%7;;7mEdoc/rack-3.0.8/ri/Rack/ContentType/cdesc-ContentType.rinu[PK% ]ה+Edoc/rack-3.0.8/ri/Rack/ContentType/new-c.rinu[PK% ]_W,Edoc/rack-3.0.8/ri/Rack/ContentType/call-i.rinu[PK% ]0 Edoc/rack-3.0.8/ri/Rack/Headers/downcase_key-i.rinu[PK% ] -9 Edoc/rack-3.0.8/ri/Rack/Headers/values_at-i.rinu[PK% ]j>RR. Edoc/rack-3.0.8/ri/Rack/Headers/has_key%3f-i.rinu[PK% ]V'AEdoc/rack-3.0.8/ri/Rack/Headers/dig-i.rinu[PK% ]zAA+Edoc/rack-3.0.8/ri/Rack/Headers/replace-i.rinu[PK% ]ç"q*Edoc/rack-3.0.8/ri/Rack/Headers/key%3f-i.rinu[PK% ]We)HEdoc/rack-3.0.8/ri/Rack/Headers/merge-i.rinu[PK% ]&*Edoc/rack-3.0.8/ri/Rack/Headers/%5b%5d-c.rinu[PK% ]P  7Edoc/rack-3.0.8/ri/Rack/Headers/compare_by_identity-i.rinu[PK% ]2k)UEdoc/rack-3.0.8/ri/Rack/Headers/fetch-i.rinu[PK% ]+Edoc/rack-3.0.8/ri/Rack/Headers/to_proc-i.rinu[PK% ]B*Edoc/rack-3.0.8/ri/Rack/Headers/update-i.rinu[PK% ].rEdoc/rack-3.0.8/ri/Rack/Headers/include%3f-i.rinu[PK% ]d!{,Edoc/rack-3.0.8/ri/Rack/Headers/merge%21-i.rinu[PK% ]x8*gEdoc/rack-3.0.8/ri/Rack/Headers/select-i.rinu[PK% ]Tk*Edoc/rack-3.0.8/ri/Rack/Headers/%5b%5d-i.rinu[PK% ]V9%*Edoc/rack-3.0.8/ri/Rack/Headers/invert-i.rinu[PK% ]5F!Edoc/rack-3.0.8/ri/Rack/Headers/transform_keys%21-i.rinu[PK% ]cdC@*"Edoc/rack-3.0.8/ri/Rack/Headers/delete-i.rinu[PK% ]8/$Edoc/rack-3.0.8/ri/Rack/Headers/cdesc-Headers.rinu[PK% ]I2:)Edoc/rack-3.0.8/ri/Rack/Headers/transform_keys-i.rinu[PK% ]4=)*Edoc/rack-3.0.8/ri/Rack/Headers/store-i.rinu[PK% ]-,Edoc/rack-3.0.8/ri/Rack/Headers/%5b%5d%3d-i.rinu[PK% ]ėi*-Edoc/rack-3.0.8/ri/Rack/Headers/reject-i.rinu[PK% ]s*.Edoc/rack-3.0.8/ri/Rack/Headers/except-i.rinu[PK% ]Vȃ-J0Edoc/rack-3.0.8/ri/Rack/Headers/member%3f-i.rinu[PK% ]|[  41Edoc/rack-3.0.8/ri/Rack/Headers/transform_values-i.rinu[PK% ]85)/3Edoc/rack-3.0.8/ri/Rack/Headers/assoc-i.rinu[PK% ]i)y4Edoc/rack-3.0.8/ri/Rack/Headers/slice-i.rinu[PK% ]'05Edoc/rack-3.0.8/ri/Rack/Headers/fetch_values-i.rinu[PK% ]| Î;M7Edoc/rack-3.0.8/ri/Rack/BodyProxy/respond_to_missing%3f-i.rinu[PK% ]gJ;3F9Edoc/rack-3.0.8/ri/Rack/BodyProxy/cdesc-BodyProxy.rinu[PK% ]sI/)tEdoc/rack-3.0.8/ri/Rack/BodyProxy/close-i.rinu[PK% ]a/5@Edoc/rack-3.0.8/ri/Rack/BodyProxy/closed%3f-i.rinu[PK% ]att4&BEdoc/rack-3.0.8/ri/Rack/BodyProxy/method_missing-i.rinu[PK% ]g  2CEdoc/rack-3.0.8/ri/Rack/Reloader/Stat/rotation-i.rinu[PK% ].K2lEEdoc/rack-3.0.8/ri/Rack/Reloader/Stat/cdesc-Stat.rinu[PK% ]ߞ5GEdoc/rack-3.0.8/ri/Rack/Reloader/Stat/figure_path-i.rinu[PK% ]N43IEdoc/rack-3.0.8/ri/Rack/Reloader/Stat/safe_stat-i.rinu[PK% ]NIJ(HKEdoc/rack-3.0.8/ri/Rack/Reloader/new-c.rinu[PK% ])LEdoc/rack-3.0.8/ri/Rack/Reloader/call-i.rinu[PK% ]{{.MEdoc/rack-3.0.8/ri/Rack/Reloader/safe_load-i.rinu[PK% ]̊.OEdoc/rack-3.0.8/ri/Rack/Reloader/reload%21-i.rinu[PK% ]mUU17QEdoc/rack-3.0.8/ri/Rack/Reloader/cdesc-Reloader.rinu[PK% ]~.K<<MUEdoc/rack-3.0.8/ri/Rack/RewindableInput/filesystem_has_posix_semantics%3f-i.rinu[PK% ];/WEdoc/rack-3.0.8/ri/Rack/RewindableInput/new-c.rinu[PK% ]GTWZ? YEdoc/rack-3.0.8/ri/Rack/RewindableInput/cdesc-RewindableInput.rinu[PK% ]ڻ;w]Edoc/rack-3.0.8/ri/Rack/RewindableInput/make_rewindable-i.rinu[PK% ]p0a E^Edoc/rack-3.0.8/ri/Rack/RewindableInput/Middleware/cdesc-Middleware.rinu[PK% ].E:?bEdoc/rack-3.0.8/ri/Rack/RewindableInput/Middleware/new-c.rinu[PK% ]x;cEdoc/rack-3.0.8/ri/Rack/RewindableInput/Middleware/call-i.rinu[PK% ]'z01eEdoc/rack-3.0.8/ri/Rack/RewindableInput/size-i.rinu[PK% ]2^APP1fEdoc/rack-3.0.8/ri/Rack/RewindableInput/close-i.rinu[PK% ]WA  0GiEdoc/rack-3.0.8/ri/Rack/RewindableInput/read-i.rinu[PK% ]Bd+R0jEdoc/rack-3.0.8/ri/Rack/RewindableInput/gets-i.rinu[PK% ]J`  2lEdoc/rack-3.0.8/ri/Rack/RewindableInput/rewind-i.rinu[PK% ]=t  0mEdoc/rack-3.0.8/ri/Rack/RewindableInput/each-i.rinu[PK% ]J.nEdoc/rack-3.0.8/ri/Rack/TempfileReaper/new-c.rinu[PK% ]䱦=NpEdoc/rack-3.0.8/ri/Rack/TempfileReaper/cdesc-TempfileReaper.rinu[PK% ]GX/sEdoc/rack-3.0.8/ri/Rack/TempfileReaper/call-i.rinu[PK% ]A''uEdoc/rack-3.0.8/ri/Rack/Runtime/new-c.rinu[PK% ]/xvEdoc/rack-3.0.8/ri/Rack/Runtime/cdesc-Runtime.rinu[PK% ]C(yEdoc/rack-3.0.8/ri/Rack/Runtime/call-i.rinu[PK% ]9\:!{Edoc/rack-3.0.8/ri/Rack/MethodOverride/allowed_methods-i.rinu[PK% ]l.|Edoc/rack-3.0.8/ri/Rack/MethodOverride/new-c.rinu[PK% ] !fL/~Edoc/rack-3.0.8/ri/Rack/MethodOverride/call-i.rinu[PK% ]Ns:jEdoc/rack-3.0.8/ri/Rack/MethodOverride/method_override-i.rinu[PK% ]:<((@Edoc/rack-3.0.8/ri/Rack/MethodOverride/method_override_param-i.rinu[PK% ]R=Edoc/rack-3.0.8/ri/Rack/MethodOverride/cdesc-MethodOverride.rinu[PK% ]:  -Edoc/rack-3.0.8/ri/Rack/Logger/cdesc-Logger.rinu[PK% ]1l&TEdoc/rack-3.0.8/ri/Rack/Logger/new-c.rinu[PK% ]/'e'Edoc/rack-3.0.8/ri/Rack/Logger/call-i.rinu[PK% ]6+k&Edoc/rack-3.0.8/ri/Rack/URLMap/new-c.rinu[PK% ]B(6Edoc/rack-3.0.8/ri/Rack/URLMap/remap-i.rinu[PK% ]!q'|Edoc/rack-3.0.8/ri/Rack/URLMap/call-i.rinu[PK% ]Dvjj-Edoc/rack-3.0.8/ri/Rack/URLMap/cdesc-URLMap.rinu[PK% ]0-Edoc/rack-3.0.8/ri/Rack/URLMap/casecmp%3f-i.rinu[PK% ]ƦN'ەEdoc/rack-3.0.8/ri/Rack/Cascade/new-c.rinu[PK% ]gD TT.Edoc/rack-3.0.8/ri/Rack/Cascade/include%3f-i.rinu[PK% ]a|(eEdoc/rack-3.0.8/ri/Rack/Cascade/call-i.rinu[PK% ]/Edoc/rack-3.0.8/ri/Rack/Cascade/cdesc-Cascade.rinu[PK% ],55(Edoc/rack-3.0.8/ri/Rack/Cascade/apps-i.rinu[PK% ]s9'9Edoc/rack-3.0.8/ri/Rack/Cascade/add-i.rinu[PK% ]*-8  *Edoc/rack-3.0.8/ri/Rack/Cascade/%3c%3c-i.rinu[PK% ]_UC&tEdoc/rack-3.0.8/ri/Rack/Files/fail-i.rinu[PK% ]d>''>˦Edoc/rack-3.0.8/ri/Rack/Files/BaseIterator/each_range_part-i.rinu[PK% ]I7`Edoc/rack-3.0.8/ri/Rack/Files/BaseIterator/bytesize-i.rinu[PK% ]w~l?ʩEdoc/rack-3.0.8/ri/Rack/Files/BaseIterator/cdesc-BaseIterator.rinu[PK% ]`+d;Edoc/rack-3.0.8/ri/Rack/Files/BaseIterator/multipart%3f-i.rinu[PK% ]'Z2,Edoc/rack-3.0.8/ri/Rack/Files/BaseIterator/new-c.rinu[PK% ]θ+6Edoc/rack-3.0.8/ri/Rack/Files/BaseIterator/options-i.rinu[PK% ]uꅨ4Edoc/rack-3.0.8/ri/Rack/Files/BaseIterator/close-i.rinu[PK% ]΍@fEdoc/rack-3.0.8/ri/Rack/Files/BaseIterator/multipart_heading-i.rinu[PK% ]NО-3Edoc/rack-3.0.8/ri/Rack/Files/BaseIterator/path-i.rinu[PK% ]+3PEdoc/rack-3.0.8/ri/Rack/Files/BaseIterator/each-i.rinu[PK% ]^ 5̶Edoc/rack-3.0.8/ri/Rack/Files/BaseIterator/ranges-i.rinu[PK% ]_y%1Edoc/rack-3.0.8/ri/Rack/Files/new-c.rinu[PK% ]Kcڄ*Edoc/rack-3.0.8/ri/Rack/Files/filesize-i.rinu[PK% ]t&Edoc/rack-3.0.8/ri/Rack/Files/call-i.rinu[PK% ]i%&Edoc/rack-3.0.8/ri/Rack/Files/get-i.rinu[PK% ]t$+bEdoc/rack-3.0.8/ri/Rack/Files/cdesc-Files.rinu[PK% ]+S)Edoc/rack-3.0.8/ri/Rack/Files/serving-i.rinu[PK% ]ldd+ Edoc/rack-3.0.8/ri/Rack/Files/mime_type-i.rinu[PK% ]Ҿ&Edoc/rack-3.0.8/ri/Rack/Files/root-i.rinu[PK% ]ih7Edoc/rack-3.0.8/ri/Rack/Files/Iterator/cdesc-Iterator.rinu[PK% ]* Edoc/rack-3.0.8/ri/Rack/ShowStatus/new-c.rinu[PK% ]S+\Edoc/rack-3.0.8/ri/Rack/ShowStatus/call-i.rinu[PK% ]CS,DD5Edoc/rack-3.0.8/ri/Rack/ShowStatus/cdesc-ShowStatus.rinu[PK% ]/YEdoc/rack-3.0.8/ri/Rack/MockResponse/%3d%7e-i.rinu[PK% ]?i77CEdoc/rack-3.0.8/ri/Rack/MockResponse/identify_cookie_attributes-i.rinu[PK% ])c</_Edoc/rack-3.0.8/ri/Rack/MockResponse/cookie-i.rinu[PK% ]ʒ''BEdoc/rack-3.0.8/ri/Rack/MockResponse/parse_cookies_from_header-i.rinu[PK% ]ܦN))0[Edoc/rack-3.0.8/ri/Rack/MockResponse/cookies-i.rinu[PK% ]O,Edoc/rack-3.0.8/ri/Rack/MockResponse/new-c.rinu[PK% ]'&1^Edoc/rack-3.0.8/ri/Rack/MockResponse/empty%3f-i.rinu[PK% ];.Edoc/rack-3.0.8/ri/Rack/MockResponse/match-i.rinu[PK% ]ʆ- Edoc/rack-3.0.8/ri/Rack/MockResponse/body-i.rinu[PK% ];6zz9yEdoc/rack-3.0.8/ri/Rack/MockResponse/cdesc-MockResponse.rinu[PK% ];;9\Edoc/rack-3.0.8/ri/Rack/MockResponse/original_headers-i.rinu[PK% ]߱''/Edoc/rack-3.0.8/ri/Rack/MockResponse/errors-i.rinu[PK% ]a3Edoc/rack-3.0.8/ri/Rack/MediaType/cdesc-MediaType.rinu[PK% ] yy,Edoc/rack-3.0.8/ri/Rack/MediaType/params-c.rinu[PK% ]ѧӭ8Edoc/rack-3.0.8/ri/Rack/MediaType/strip_doublequotes-c.rinu[PK% ]i-l*Edoc/rack-3.0.8/ri/Rack/MediaType/type-c.rinu[PK% ]}.Edoc/rack-3.0.8/ri/Rack/ForwardRequest/new-c.rinu[PK% ]'.\Edoc/rack-3.0.8/ri/Rack/ForwardRequest/url-i.rinu[PK% ]2=Edoc/rack-3.0.8/ri/Rack/ForwardRequest/cdesc-ForwardRequest.rinu[PK% ]L. Edoc/rack-3.0.8/ri/Rack/ForwardRequest/env-i.rinu[PK% ]n/^Edoc/rack-3.0.8/ri/Rack/Directory/list_path-i.rinu[PK% ]\$7Edoc/rack-3.0.8/ri/Rack/Directory/check_bad_request-i.rinu[PK% ]7___)}Edoc/rack-3.0.8/ri/Rack/Directory/new-c.rinu[PK% ]RR55Edoc/rack-3.0.8/ri/Rack/Directory/filesize_format-i.rinu[PK% ]/Q*Edoc/rack-3.0.8/ri/Rack/Directory/call-i.rinu[PK% ]{{);Edoc/rack-3.0.8/ri/Rack/Directory/get-i.rinu[PK% ]LL5Fdoc/rack-3.0.8/ri/Rack/Directory/check_forbidden-i.rinu[PK% ]x3 Fdoc/rack-3.0.8/ri/Rack/Directory/cdesc-Directory.rinu[PK% ]ºɀERFdoc/rack-3.0.8/ri/Rack/Directory/DirectoryBody/cdesc-DirectoryBody.rinu[PK% ]Y8jwxxCG Fdoc/rack-3.0.8/ri/Rack/Directory/DirectoryBody/DIR_FILE_escape-i.rinu[PK% ].5582 Fdoc/rack-3.0.8/ri/Rack/Directory/DirectoryBody/each-i.rinu[PK% ]*Ѧbb*Fdoc/rack-3.0.8/ri/Rack/Directory/stat-i.rinu[PK% ]">В*Fdoc/rack-3.0.8/ri/Rack/Directory/root-i.rinu[PK% ]f6wFdoc/rack-3.0.8/ri/Rack/Directory/entity_not_found-i.rinu[PK% ]Mx||4^Fdoc/rack-3.0.8/ri/Rack/Directory/list_directory-i.rinu[PK% ]OZ(>Fdoc/rack-3.0.8/ri/Rack/Deflater/new-c.rinu[PK% ]N!)kFdoc/rack-3.0.8/ri/Rack/Deflater/call-i.rinu[PK% ]*l 1Fdoc/rack-3.0.8/ri/Rack/Deflater/cdesc-Deflater.rinu[PK% ]5' 3!Fdoc/rack-3.0.8/ri/Rack/Deflater/GzipStream/new-c.rinu[PK% ]$׷II50%Fdoc/rack-3.0.8/ri/Rack/Deflater/GzipStream/close-i.rinu[PK% ]u>&Fdoc/rack-3.0.8/ri/Rack/Deflater/GzipStream/cdesc-GzipStream.rinu[PK% ] |1+^^5*Fdoc/rack-3.0.8/ri/Rack/Deflater/GzipStream/write-i.rinu[PK% ]x{)ZZ4+Fdoc/rack-3.0.8/ri/Rack/Deflater/GzipStream/each-i.rinu[PK% ]z_ll6-Fdoc/rack-3.0.8/ri/Rack/Deflater/should_deflate%3f-i.rinu[PK% ]~S/U/Fdoc/rack-3.0.8/ri/Rack/Chunked/cdesc-Chunked.rinu[PK% ]Ĩ'4Fdoc/rack-3.0.8/ri/Rack/Chunked/new-c.rinu[PK% ]{(5Fdoc/rack-3.0.8/ri/Rack/Chunked/call-i.rinu[PK% ]ͯ{>>,8Fdoc/rack-3.0.8/ri/Rack/Chunked/Body/new-c.rinu[PK% ]nPP.9Fdoc/rack-3.0.8/ri/Rack/Chunked/Body/close-i.rinu[PK% ]8-];Fdoc/rack-3.0.8/ri/Rack/Chunked/Body/each-i.rinu[PK% ]?1Q=Fdoc/rack-3.0.8/ri/Rack/Chunked/Body/cdesc-Body.rinu[PK% ]9dd7@Fdoc/rack-3.0.8/ri/Rack/Chunked/Body/yield_trailers-i.rinu[PK% ]K/Tii?_BFdoc/rack-3.0.8/ri/Rack/Chunked/TrailerBody/cdesc-TrailerBody.rinu[PK% ]tt>7FFdoc/rack-3.0.8/ri/Rack/Chunked/TrailerBody/yield_trailers-i.rinu[PK% ]Xctt8HFdoc/rack-3.0.8/ri/Rack/Chunked/chunkable_version%3f-i.rinu[PK% ]>K$;;#IFdoc/rack-3.0.8/ri/Rack/version-c.rinu[PK% ]% (KFdoc/rack-3.0.8/ri/Rack/Sendfile/new-c.rinu[PK% ]6J771LFdoc/rack-3.0.8/ri/Rack/Sendfile/cdesc-Sendfile.rinu[PK% ]JC.^Fdoc/rack-3.0.8/ri/Rack/Sendfile/variation-i.rinu[PK% ]~)_Fdoc/rack-3.0.8/ri/Rack/Sendfile/call-i.rinu[PK% ]^  3*aFdoc/rack-3.0.8/ri/Rack/Sendfile/map_accel_path-i.rinu[PK% ]q x99#bFdoc/rack-3.0.8/ri/Rack/release-c.rinu[PK% ]!A@@7&dFdoc/rack-3.0.8/ri/Rack/Multipart/extract_multipart-c.rinu[PK% ]3 3 3eFdoc/rack-3.0.8/ri/Rack/Multipart/cdesc-Multipart.rinu[PK% ]`$$@crFdoc/rack-3.0.8/ri/Rack/Multipart/UploadedFile/respond_to%3f-i.rinu[PK% ]F;NN=sFdoc/rack-3.0.8/ri/Rack/Multipart/UploadedFile/local_path-i.rinu[PK% ]qNI6uFdoc/rack-3.0.8/ri/Rack/Multipart/UploadedFile/new-c.rinu[PK% ]=)mmCwFdoc/rack-3.0.8/ri/Rack/Multipart/UploadedFile/cdesc-UploadedFile.rinu[PK% ]Rcs337}zFdoc/rack-3.0.8/ri/Rack/Multipart/UploadedFile/path-i.rinu[PK% ]{7]D|Fdoc/rack-3.0.8/ri/Rack/Multipart/UploadedFile/original_filename-i.rinu[PK% ]p tt?~Fdoc/rack-3.0.8/ri/Rack/Multipart/UploadedFile/content_type-i.rinu[PK% ]_;Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/parse_boundary-c.rinu[PK% ]hBee@Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/handle_fast_forward-i.rinu[PK% ]gų((DaFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/handle_empty_content%21-i.rinu[PK% ]qAFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/handle_consume_token-i.rinu[PK% ]E*&&0Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/new-c.rinu[PK% ]g+3772Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/parse-c.rinu[PK% ]>.Ȼ=Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/handle_mime_head-i.rinu[PK% ]~z60Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/read_data-i.rinu[PK% ]Q7}}7Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/cdesc-Parser.rinu[PK% ])R3Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/result-i.rinu[PK% ]ɷDFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/BoundedIO/cdesc-BoundedIO.rinu[PK% ]XmEEC Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/tag_multipart_encoding-i.rinu[PK% ]i4ęFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/dequote-i.rinu[PK% ]+ =0Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/handle_mime_body-i.rinu[PK% ]q22=Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/consume_boundary-i.rinu[PK% ]g**ESFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/on_mime_finish-i.rinu[PK% ]3 :Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/new-c.rinu[PK% ]1f+//CoFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/on_mime_body-i.rinu[PK% ]Dp''HFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/MimePart/get_data-i.rinu[PK% ]/Ĉ00LFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/MimePart/cdesc-MimePart.rinu[PK% ]4t,zzD\Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/cdesc-Collector.rinu[PK% ]:JJCJFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/on_mime_head-i.rinu[PK% ]c44PFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/BufferPart/cdesc-BufferPart.rinu[PK% ]NRIFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/BufferPart/file%3f-i.rinu[PK% ]'GOFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/BufferPart/close-i.rinu[PK% ]''HFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/check_part_limits-i.rinu[PK% ] KFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/TempfilePart/file%3f-i.rinu[PK% ]#FVIFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/TempfilePart/close-i.rinu[PK% ]88TFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/TempfilePart/cdesc-TempfilePart.rinu[PK% ];nFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/Collector/each-i.rinu[PK% ],42Fdoc/rack-3.0.8/ri/Rack/Multipart/Parser/state-i.rinu[PK% ] \g79VFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/get_filename-i.rinu[PK% ]{b2ҾFdoc/rack-3.0.8/ri/Rack/Multipart/Parser/parse-i.rinu[PK% ]"DD56Fdoc/rack-3.0.8/ri/Rack/Multipart/Error/cdesc-Error.rinu[PK% ]󘾲--MFdoc/rack-3.0.8/ri/Rack/Multipart/EmptyContentError/cdesc-EmptyContentError.rinu[PK% ]WTs#885Fdoc/rack-3.0.8/ri/Rack/Multipart/parse_multipart-c.rinu[PK% ]Y&Fdoc/rack-3.0.8/ri/Rack/Multipart/MultipartPartLimitError/cdesc-MultipartPartLimitError.rinu[PK% ]@95xFdoc/rack-3.0.8/ri/Rack/Multipart/build_multipart-c.rinu[PK% ]],,AFdoc/rack-3.0.8/ri/Rack/Multipart/Generator/content_for_other-i.rinu[PK% ]-hu<Fdoc/rack-3.0.8/ri/Rack/Multipart/Generator/multipart%3f-i.rinu[PK% ]%66DFdoc/rack-3.0.8/ri/Rack/Multipart/Generator/content_for_tempfile-i.rinu[PK% ]n 3Fdoc/rack-3.0.8/ri/Rack/Multipart/Generator/new-c.rinu[PK% ]#;4?Fdoc/rack-3.0.8/ri/Rack/Multipart/Generator/dump-i.rinu[PK% ](D$Hdoc/ruby-lsapi-5.5/ri/page-README.rinu[PK% ]yW֌[[2JHdoc/ruby-lsapi-5.5/ri/Kernel/eval_string_wrap-i.rinu[PK% ]Qzz,Hdoc/ruby-lsapi-5.5/ri/Kernel/cdesc-Kernel.rinu[PK% ]m"0Hdoc/ruby-lsapi-5.5/ri/LSAPI/postfork_parent-c.rinu[PK% ]7$5Hdoc/ruby-lsapi-5.5/ri/LSAPI/eof-i.rinu[PK% ]] )hHdoc/ruby-lsapi-5.5/ri/LSAPI/readline-i.rinu[PK% ]A&Hdoc/ruby-lsapi-5.5/ri/LSAPI/flush-i.rinu[PK% ]+&Hdoc/ruby-lsapi-5.5/ri/LSAPI/print-i.rinu[PK% ]+B'!Hdoc/ruby-lsapi-5.5/ri/LSAPI/reopen-i.rinu[PK% ]3`(bHdoc/ruby-lsapi-5.5/ri/LSAPI/sync%3d-i.rinu[PK% ]nA%Hdoc/ruby-lsapi-5.5/ri/LSAPI/puts-i.rinu[PK% ]3II*Hdoc/ruby-lsapi-5.5/ri/LSAPI/cdesc-LSAPI.rinu[PK% ]|'}Hdoc/ruby-lsapi-5.5/ri/LSAPI/eof%3f-i.rinu[PK% ]Î'Hdoc/ruby-lsapi-5.5/ri/LSAPI/isatty-i.rinu[PK% ]Q%Hdoc/ruby-lsapi-5.5/ri/LSAPI/putc-i.rinu[PK% ]&)Hdoc/ruby-lsapi-5.5/ri/LSAPI/close-i.rinu[PK% ]dU&'bHdoc/ruby-lsapi-5.5/ri/LSAPI/printf-i.rinu[PK% ]*'Hdoc/ruby-lsapi-5.5/ri/LSAPI/tty%3f-i.rinu[PK% ]^%Hdoc/ruby-lsapi-5.5/ri/LSAPI/sync-i.rinu[PK% ]{&Hdoc/ruby-lsapi-5.5/ri/LSAPI/write-i.rinu[PK% ]b6LHdoc/ruby-lsapi-5.5/ri/LSAPI/accept_new_connection-c.rinu[PK% ]_$%Hdoc/ruby-lsapi-5.5/ri/LSAPI/read-i.rinu[PK% ] T=%Hdoc/ruby-lsapi-5.5/ri/LSAPI/gets-i.rinu[PK% ]V('Hdoc/ruby-lsapi-5.5/ri/LSAPI/binmode-i.rinu[PK% ]z{'fHdoc/ruby-lsapi-5.5/ri/LSAPI/rewind-i.rinu[PK% ]O (Hdoc/ruby-lsapi-5.5/ri/LSAPI/process-i.rinu[PK% ]m/Hdoc/ruby-lsapi-5.5/ri/LSAPI/postfork_child-c.rinu[PK% ]%6Hdoc/ruby-lsapi-5.5/ri/LSAPI/each-i.rinu[PK% ]~%lHdoc/ruby-lsapi-5.5/ri/LSAPI/getc-i.rinu[PK% ]'Hdoc/ruby-lsapi-5.5/ri/LSAPI/%3c%3c-i.rinu[PK% ]v>z'Hdoc/ruby-lsapi-5.5/ri/LSAPI/accept-c.rinu[PK% ]eHdoc/ruby-lsapi-5.5/ri/cache.rinu[PK% ]GB N,hHdoc/ruby-lsapi-5.5/ri/Object/cdesc-Object.rinu[PK% ]ճ,,0CHdoc/ruby-lsapi-5.6/ri/ext/lsapi/page-Makefile.rinu[PK% ]:gy>$V Idoc/ruby-lsapi-5.6/ri/page-README.rinu[PK% ]yW֌[[2z'eIdoc/ruby-lsapi-5.6/ri/LSAPI/accept-c.rinu[PK% ]5OfIdoc/ruby-lsapi-5.6/ri/cache.rinu[PK% ]GB N,jIdoc/ruby-lsapi-5.6/ri/Object/cdesc-Object.rinu[PK% ]Gm__9}mIextensions/x86_64-linux/2.6.0/ruby-lsapi-5.5/gem_make.outnu[PK% ]8M>5EpIextensions/x86_64-linux/2.6.0/ruby-lsapi-5.5/mkmf.lognu[PK% ]?FyIextensions/x86_64-linux/2.6.0/ruby-lsapi-5.5/gem.build_completenu[PK% ]Dk--5yIextensions/x86_64-linux/2.6.0/ruby-lsapi-5.5/lsapi.sonuȯPK% ]&E^^9Jextensions/x86_64-linux/2.6.0/ruby-lsapi-5.6/gem_make.outnu[PK% ]8M>5ɪJextensions/x86_64-linux/2.6.0/ruby-lsapi-5.6/mkmf.lognu[PK% ]?ʳJextensions/x86_64-linux/2.6.0/ruby-lsapi-5.6/gem.build_completenu[PK% ]Sxs@--59Jextensions/x86_64-linux/2.6.0/ruby-lsapi-5.6/lsapi.sonuȯPK  k;~K