require'bundler/vendored_persistent'require'cgi'require'securerandom'moduleBundler# Handles all the fetching with the rubygems serverclassFetcherautoload:Downloader,'bundler/fetcher/downloader'autoload:Dependency,'bundler/fetcher/dependency'autoload:Index,'bundler/fetcher/index'# This error is raised when it looks like the network is downclassNetworkDownError<HTTPError;end# This error is raised if the API returns a 413 (only printed in verbose)classFallbackError<HTTPError;end# This is the error raised if OpenSSL fails the cert verificationclassCertificateFailureError<HTTPErrordefinitialize(remote_uri)super"Could not verify the SSL certificate for #{remote_uri}.\nThere"\" is a chance you are experiencing a man-in-the-middle attack, but"\" most likely your system doesn't have the CA certificates needed"\" for verification. For information about OpenSSL certificates, see"\" bit.ly/ruby-ssl. To connect without using SSL, edit your Gemfile"\" sources and change 'https' to 'http'."endend# This is the error raised when a source is HTTPS and OpenSSL didn't loadclassSSLError<HTTPErrordefinitialize(msg=nil)supermsg||"Could not load OpenSSL.\n"\"You must recompile Ruby with OpenSSL support or change the sources in your "\"Gemfile from 'https' to 'http'. Instructions for compiling with OpenSSL "\"using RVM are available at rvm.io/packages/openssl."endend# This error is raised if HTTP authentication is required, but not provided.classAuthenticationRequiredError<HTTPErrordefinitialize(remote_uri)super"Authentication is required for #{remote_uri}.\n"\"Please supply credentials for this source. You can do this by running:\n"\" bundle config #{remote_uri} username:password"endend# This error is raised if HTTP authentication is provided, but incorrect.classBadAuthenticationError<HTTPErrordefinitialize(remote_uri)super"Bad username or password for #{remote_uri}.\n"\"Please double-check your credentials and correct them."endend# Exceptions classes that should bypass retry attempts. If your password didn't work the# first time, it's not going to the third time.AUTH_ERRORS=[AuthenticationRequiredError,BadAuthenticationError]class<<selfattr_accessor:disable_endpoint,:api_timeout,:redirect_limit,:max_retriesendself.redirect_limit=Bundler.settings[:redirect]# How many redirects to allow in one requestself.api_timeout=Bundler.settings[:timeout]# How long to wait for each API callself.max_retries=Bundler.settings[:retry]# How many retries for the API calldefinitialize(remote)@remote=remoteSocket.do_not_reverse_lookup=trueconnection# create persistent connectionenddefuri@remote.anonymized_uriend# fetch a gem specificationdeffetch_spec(spec)spec=spec-[nil,'ruby','']spec_file_name="#{spec.join'-'}.gemspec"uri=URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")ifuri.scheme=='file'Bundler.load_marshalGem.inflate(Gem.read_binary(uri.path))elsifcached_spec_path=gemspec_cached_path(spec_file_name)Bundler.load_gemspec(cached_spec_path)elseBundler.load_marshalGem.inflate(downloader.fetchuri)endrescueMarshalErrorraiseHTTPError,"Gemspec #{spec} contained invalid data.\n"\"Your network or your gem server is probably having issues right now."end# return the specs in the bundler format as an indexdefspecs(gem_names,source)old=Bundler.rubygems.sourcesindex=Bundler::Index.newspecs={}fetchers.dup.eachdo|f|unlessf.api_fetcher?&&!gem_namesbreakifspecs=f.specs(gem_names)endfetchers.delete(f)end@use_api=falseiffetchers.none?(&:api_fetcher?)specs[remote_uri].eachdo|name,version,platform,dependencies|nextifname=='bundler'spec=nilifdependenciesspec=EndpointSpecification.new(name,version,platform,dependencies)elsespec=RemoteSpecification.new(name,version,platform,self)endspec.source=sourcespec.remote=@remoteindex<<specendindexrescueCertificateFailureErrorBundler.ui.info""ifgem_names&&use_api# newline after dotsraiseensureBundler.rubygems.sources=oldenddefuse_apireturn@use_apiifdefined?(@use_api)ifremote_uri.scheme=="file"||Bundler::Fetcher.disable_endpoint@use_api=falseelsefetchers.reject!{|f|f.api_fetcher?&&!f.api_available?}@use_api=fetchers.any?(&:api_fetcher?)endenddefuser_agent@user_agent||=beginruby=Bundler.ruby_versionagent="bundler/#{Bundler::VERSION}"agent<<" rubygems/#{Gem::VERSION}"agent<<" ruby/#{ruby.version}"agent<<" (#{ruby.host})"agent<<" command/#{ARGV.first}"ifruby.engine!="ruby"# engine_version raises on unknown enginesengine_version=ruby.engine_versionrescue"???"agent<<" #{ruby.engine}/#{engine_version}"endagent<<" options/#{Bundler.settings.all.join(",")}"# add a random ID so we can consolidate runs server-sideagent<<" "<<SecureRandom.hex(8)# add any user agent strings set in the configextra_ua=Bundler.settings[:user_agent]agent<<" "<<extra_uaifextra_uaagentendenddeffetchers@fetchers||=FETCHERS.map{|f|f.new(downloader,remote_uri,fetch_uri,uri)}enddefinspect"#<#{self.class}:0x#{object_id} uri=#{uri}>"endprivateFETCHERS=[Dependency,Index]defconnection@connection||=beginneeds_ssl=remote_uri.scheme=="https"||Bundler.settings[:ssl_verify_mode]||Bundler.settings[:ssl_client_cert]raiseSSLErrorifneeds_ssl&&!defined?(OpenSSL::SSL)con=Net::HTTP::Persistent.new'bundler',:ENVifremote_uri.scheme=="https"con.verify_mode=(Bundler.settings[:ssl_verify_mode]||OpenSSL::SSL::VERIFY_PEER)con.cert_store=bundler_cert_storeendifBundler.settings[:ssl_client_cert]pem=File.read(Bundler.settings[:ssl_client_cert])con.cert=OpenSSL::X509::Certificate.new(pem)con.key=OpenSSL::PKey::RSA.new(pem)endcon.read_timeout=Fetcher.api_timeoutcon.override_headers["User-Agent"]=user_agentconendend# cached gem specification path, if one existsdefgemspec_cached_pathspec_file_namepaths=Bundler.rubygems.spec_cache_dirs.map{|dir|File.join(dir,spec_file_name)}paths=paths.select{|path|File.file?path}paths.firstendHTTP_ERRORS=[Timeout::Error,EOFError,SocketError,Errno::ENETDOWN,Errno::EINVAL,Errno::ECONNRESET,Errno::ETIMEDOUT,Errno::EAGAIN,Net::HTTPBadResponse,Net::HTTPHeaderSyntaxError,Net::ProtocolError,Net::HTTP::Persistent::Error]defbundler_cert_storestore=OpenSSL::X509::Store.newifBundler.settings[:ssl_ca_cert]ifFile.directory?Bundler.settings[:ssl_ca_cert]store.add_pathBundler.settings[:ssl_ca_cert]elsestore.add_fileBundler.settings[:ssl_ca_cert]endelsestore.set_default_pathscerts=File.expand_path("../ssl_certs/*.pem",__FILE__)Dir.glob(certs).each{|c|store.add_filec}endstoreendprivatedeffetch_uri@fetch_uri||=beginifremote_uri.host=="rubygems.org"uri=remote_uri.dupuri.host="bundler.rubygems.org"urielseremote_uriendendenddefremote_uri@remote.urienddefdownloader@downloader||=Downloader.new(connection,self.class.redirect_limit)endendend