user_agent.rb 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. # Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
  2. require 'net/http'
  3. require 'net/https'
  4. require 'net/ftp'
  5. require 'tempfile'
  6. class UserAgent
  7. =begin
  8. http/https/ftp calls
  9. result = UserAgent.request( 'ftp://host/some_dir/some_file.bin' )
  10. result = UserAgent.request( 'http://host/some_dir/some_file.bin' )
  11. result = UserAgent.request( 'https://host/some_dir/some_file.bin' )
  12. result = UserAgent.request( 'http://host/some_dir/some_file.bin', { :method => 'post', :data => { :param1 => 123 } } )
  13. returns
  14. result # result object
  15. =end
  16. def self.request(url, options = {})
  17. uri = URI.parse(url)
  18. case uri.scheme.downcase
  19. when /ftp/
  20. ftp(uri, options)
  21. when /http|https/
  22. http(uri, options, 10)
  23. end
  24. end
  25. private
  26. def self.http(uri, options, count)
  27. http = Net::HTTP.new(uri.host, uri.port)
  28. if uri.scheme =~ /https/i
  29. http.use_ssl = true
  30. http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  31. end
  32. if !options[:method] || options[:method] =~ /^get$/i
  33. request = Net::HTTP::Get.new(uri.request_uri)
  34. # http basic auth (if needed)
  35. if options[:user] && options[:user] != '' && options[:password] && options[:password] != ''
  36. request.basic_auth user, password
  37. end
  38. begin
  39. response = http.request(request)
  40. rescue Exception => e
  41. return Result.new(
  42. :error => e.inspect,
  43. :success => false,
  44. :code => 0,
  45. )
  46. end
  47. elsif options[:method] =~ /^post$/i
  48. request = Net::HTTP::Post.new(uri.request_uri)
  49. # http basic auth (if needed)
  50. if options[:user] && options[:user] != '' && options[:password] && options[:password] != ''
  51. request.basic_auth user, password
  52. end
  53. begin
  54. request.set_form_data( options[:data] )
  55. response = http.request(request)
  56. rescue Exception => e
  57. return Result.new(
  58. :error => e.inspect,
  59. :success => false,
  60. :code => 0,
  61. )
  62. end
  63. end
  64. if !response
  65. return Result.new(
  66. :error => "Can't connect to #{uri.to_s}, got no response!",
  67. :success => false,
  68. :code => 0,
  69. )
  70. end
  71. case response
  72. when Net::HTTPNotFound
  73. return Result.new(
  74. :error => "No such file #{uri.to_s}, 404!",
  75. :success => false,
  76. :code => response.code,
  77. )
  78. when Net::HTTPClientError
  79. return Result.new(
  80. :error => "Client Error: #{response.inspect}!",
  81. :success => false,
  82. :code => response.code,
  83. )
  84. when Net::HTTPRedirection
  85. raise "Too many redirections for the original URL, halting." if count <= 0
  86. url = response["location"]
  87. uri = URI.parse(url)
  88. return http(uri, options, count - 1)
  89. when Net::HTTPOK
  90. return Result.new(
  91. :body => response.body,
  92. :success => true,
  93. :code => response.code,
  94. )
  95. end
  96. raise "Unknown method '#{option[:method]}'"
  97. end
  98. def self.ftp(uri,options)
  99. host = uri.host
  100. filename = File.basename(uri.path)
  101. remote_dir = File.dirname(uri.path)
  102. temp_file = Tempfile.new("download-#{filename}")
  103. temp_file.binmode
  104. begin
  105. Net::FTP.open(host) do |ftp|
  106. ftp.passive = true
  107. if options[:user] && options[:password]
  108. ftp.login( options[:user], options[:password] )
  109. else
  110. ftp.login
  111. end
  112. ftp.chdir(remote_dir) unless remote_dir == '.'
  113. begin
  114. ftp.getbinaryfile( filename, temp_file )
  115. rescue => e
  116. return Result.new(
  117. :error => e.inspect,
  118. :success => false,
  119. :code => 550,
  120. )
  121. end
  122. end
  123. rescue => e
  124. return Result.new(
  125. :error => e.inspect,
  126. :success => false,
  127. )
  128. end
  129. contents = temp_file.read
  130. temp_file.close
  131. Result.new(
  132. :body => contents,
  133. :success => true,
  134. :code => 200,
  135. )
  136. end
  137. class Result
  138. def initialize(options)
  139. @success = options[:success]
  140. @body = options[:body]
  141. @code = options[:code]
  142. @error = options[:error]
  143. end
  144. def error
  145. @error
  146. end
  147. def success?
  148. @success
  149. end
  150. def body
  151. @body
  152. end
  153. def code
  154. @code
  155. end
  156. end
  157. end