module PluginTool SERVER_INFO = 'server.yaml' SERVER_CERTIFICATE = 'server.crt' REQUIRED_SERVER_INFO_KEYS = [:hostname, :key] def self.load_server_info @@server = YAML::load(File.open(SERVER_INFO) { |f| f.read }) REQUIRED_SERVER_INFO_KEYS.each do |key| return "#{SERVER_INFO} does not contain :#{key}" unless @@server.has_key? key end if File.file?(SERVER_CERTIFICATE) # Use provided server.crt if it exists @@server_ca = SERVER_CERTIFICATE puts "NOTICE: Using alternative CAs for SSL from #{SERVER_CERTIFICATE}" else # Use build in certificate bundle @@server_ca = "#{File.dirname(__FILE__)}/CertificateBundle.pem" end puts "Application: https://#{@@server[:hostname]}/" nil end def self.make_http_connection http = Net::HTTP.new(@@server[:hostname], 443) ssl_ca = OpenSSL::X509::Store.new unless ssl_ca.respond_to? :add_file puts puts "jruby-openssl gem is not installed or bouncy castle crypto not available on CLASSPATH." puts "See installation instructions." puts exit 1 end ssl_ca.add_file(@@server_ca) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_PEER http.cert_store = ssl_ca http.start http end @@http = nil def self.get_http @@http ||= make_http_connection end def self.finish_with_connection if @@http != nil @@http.finish @@http = nil end end def self.setup_request(req) req['User-Agent'] = 'plugin-tool' req['X-ONEIS-Key'] = @@server[:key] end def self.get(path) http = get_http request = Net::HTTP::Get.new(path) setup_request(request) http.request(request).body end def self.get_yaml(path) report_errors_from_server(YAML::load(get(path))) end def self.post(path, params = nil, files = nil) http = get_http request = Net::HTTP::Post.new(path) setup_request(request) if files == nil request.set_form_data(params) if params != nil else boundary = "----------XnJLe9ZIbbGUYtzPQJ16u1" request["Content-Type"] = "multipart/form-data; boundary=#{boundary}" body = '' if params != nil params.each do |key,value| body << <<-EOF --#{boundary}\r Content-Disposition: form-data; name="#{key}"\r \r #{value}\r EOF end end files.each do |key,info| pathname, data = info body << <<-EOF --#{boundary}\r Content-Disposition: form-data; name="#{key}"; filename="#{pathname}"\r Content-Type: application/octet-stream\r Content-Length: #{data.length}\r \r #{data}\r EOF end body << "--#{boundary}--\r" request.body = body end http.request(request).body end def self.post_yaml(path, params = nil, files = nil) report_errors_from_server(YAML::load(post(path, params, files))) end def self.report_errors_from_server(r) unless r.kind_of? Hash r = { :result => 'error', :protocol_error => true, :message => "Unknown error. Either the server is not enabled for development, or the credentials in #{SERVER_INFO} are not valid." } end if r[:result] != 'success' && r.has_key?(:message) puts "\n\n**************************************************************" puts " ERROR REPORTED BY SERVER" puts "**************************************************************\n\n" puts r[:message] puts "\n**************************************************************\n\n" beep end r end # Delayed apply support @@delayed_apply_queue = [] def self.push_delayed_apply(name) @@delayed_apply_queue.push(name) end def self.do_delayed_apply return if @@delayed_apply_queue.empty? puts "Updating server..." self.post_yaml("/api/development_plugin_loader/delayed_apply", {"plugins" => @@delayed_apply_queue.join(',')}) self.finish_with_connection puts "Updated." @@delayed_apply_queue = [] end end