httpclient-fixcerts 2.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +98 -0
  3. data/bin/httpclient +77 -0
  4. data/bin/jsonclient +85 -0
  5. data/lib/hexdump.rb +50 -0
  6. data/lib/http-access2/cookie.rb +1 -0
  7. data/lib/http-access2/http.rb +1 -0
  8. data/lib/http-access2.rb +55 -0
  9. data/lib/httpclient/auth.rb +924 -0
  10. data/lib/httpclient/cacert.pem +3952 -0
  11. data/lib/httpclient/cacert1024.pem +3866 -0
  12. data/lib/httpclient/connection.rb +88 -0
  13. data/lib/httpclient/cookie.rb +220 -0
  14. data/lib/httpclient/http.rb +1082 -0
  15. data/lib/httpclient/include_client.rb +85 -0
  16. data/lib/httpclient/jruby_ssl_socket.rb +594 -0
  17. data/lib/httpclient/session.rb +960 -0
  18. data/lib/httpclient/ssl_config.rb +433 -0
  19. data/lib/httpclient/ssl_socket.rb +150 -0
  20. data/lib/httpclient/timeout.rb +140 -0
  21. data/lib/httpclient/util.rb +222 -0
  22. data/lib/httpclient/version.rb +3 -0
  23. data/lib/httpclient/webagent-cookie.rb +459 -0
  24. data/lib/httpclient.rb +1332 -0
  25. data/lib/jsonclient.rb +66 -0
  26. data/lib/oauthclient.rb +111 -0
  27. data/sample/async.rb +8 -0
  28. data/sample/auth.rb +11 -0
  29. data/sample/cookie.rb +18 -0
  30. data/sample/dav.rb +103 -0
  31. data/sample/howto.rb +49 -0
  32. data/sample/jsonclient.rb +67 -0
  33. data/sample/oauth_buzz.rb +57 -0
  34. data/sample/oauth_friendfeed.rb +59 -0
  35. data/sample/oauth_twitter.rb +61 -0
  36. data/sample/ssl/0cert.pem +22 -0
  37. data/sample/ssl/0key.pem +30 -0
  38. data/sample/ssl/1000cert.pem +19 -0
  39. data/sample/ssl/1000key.pem +18 -0
  40. data/sample/ssl/htdocs/index.html +10 -0
  41. data/sample/ssl/ssl_client.rb +22 -0
  42. data/sample/ssl/webrick_httpsd.rb +29 -0
  43. data/sample/stream.rb +21 -0
  44. data/sample/thread.rb +27 -0
  45. data/sample/wcat.rb +21 -0
  46. data/test/ca-chain.pem +44 -0
  47. data/test/ca.cert +23 -0
  48. data/test/client-pass.key +18 -0
  49. data/test/client.cert +19 -0
  50. data/test/client.key +15 -0
  51. data/test/helper.rb +131 -0
  52. data/test/htdigest +1 -0
  53. data/test/htpasswd +2 -0
  54. data/test/jruby_ssl_socket/test_pemutils.rb +32 -0
  55. data/test/runner.rb +2 -0
  56. data/test/server.cert +19 -0
  57. data/test/server.key +15 -0
  58. data/test/sslsvr.rb +65 -0
  59. data/test/subca.cert +21 -0
  60. data/test/test_auth.rb +492 -0
  61. data/test/test_cookie.rb +309 -0
  62. data/test/test_hexdump.rb +14 -0
  63. data/test/test_http-access2.rb +508 -0
  64. data/test/test_httpclient.rb +2145 -0
  65. data/test/test_include_client.rb +52 -0
  66. data/test/test_jsonclient.rb +98 -0
  67. data/test/test_ssl.rb +562 -0
  68. data/test/test_webagent-cookie.rb +465 -0
  69. metadata +124 -0
@@ -0,0 +1,459 @@
1
+ # cookie.rb is redistributed file which is originally included in Webagent
2
+ # version 0.6.2 by TAKAHASHI `Maki' Masayoshi. And it contains some bug fixes.
3
+ # You can download the entire package of Webagent from
4
+ # http://www.rubycolor.org/arc/.
5
+
6
+
7
+ # Cookie class
8
+ #
9
+ # I refered to w3m's source to make these classes. Some comments
10
+ # are quoted from it. I'm thanksful for author(s) of it.
11
+ #
12
+ # w3m homepage: http://ei5nazha.yz.yamagata-u.ac.jp/~aito/w3m/eng/
13
+
14
+ require 'time'
15
+ require 'monitor'
16
+ require 'httpclient/util'
17
+
18
+ class WebAgent
19
+
20
+ module CookieUtils
21
+
22
+ def head_match?(str1, str2)
23
+ str1 == str2[0, str1.length]
24
+ end
25
+
26
+ def tail_match?(str1, str2)
27
+ if str1.length > 0
28
+ str1 == str2[-str1.length..-1].to_s
29
+ else
30
+ true
31
+ end
32
+ end
33
+
34
+ def domain_match(host, domain)
35
+ return false if domain.nil?
36
+ domainname = domain.sub(/\.\z/, '').downcase
37
+ hostname = host.sub(/\.\z/, '').downcase
38
+ case domain
39
+ when /\d+\.\d+\.\d+\.\d+/
40
+ return (hostname == domainname)
41
+ when '.'
42
+ return true
43
+ when /^\./
44
+ # allows; host == rubyforge.org, domain == .rubyforge.org
45
+ return tail_match?(domainname, '.' + hostname)
46
+ else
47
+ return (hostname == domainname)
48
+ end
49
+ end
50
+ end
51
+
52
+ class Cookie
53
+ include CookieUtils
54
+
55
+ attr_accessor :name, :value
56
+ attr_accessor :domain, :path
57
+ attr_accessor :expires ## for Netscape Cookie
58
+ attr_accessor :url
59
+ attr_writer :use, :secure, :http_only, :discard, :domain_orig, :path_orig, :override
60
+
61
+ USE = 1
62
+ SECURE = 2
63
+ DOMAIN = 4
64
+ PATH = 8
65
+ DISCARD = 16
66
+ OVERRIDE = 32
67
+ OVERRIDE_OK = 32
68
+ HTTP_ONLY = 64
69
+
70
+ def self.parse(str, url)
71
+ cookie = new
72
+ cookie.parse(str, url)
73
+ cookie
74
+ end
75
+
76
+ def initialize
77
+ @name = @value = @domain = @path = nil
78
+ @expires = nil
79
+ @url = nil
80
+ @use = @secure = @http_only = @discard = @domain_orig = @path_orig = @override = nil
81
+ end
82
+
83
+ def discard?
84
+ @discard
85
+ end
86
+
87
+ def use?
88
+ @use
89
+ end
90
+
91
+ def secure?
92
+ @secure
93
+ end
94
+
95
+ def http_only?
96
+ @http_only
97
+ end
98
+
99
+ def domain_orig?
100
+ @domain_orig
101
+ end
102
+
103
+ def path_orig?
104
+ @path_orig
105
+ end
106
+
107
+ def override?
108
+ @override
109
+ end
110
+
111
+ def flag
112
+ flg = 0
113
+ flg += USE if @use
114
+ flg += SECURE if @secure
115
+ flg += HTTP_ONLY if @http_only
116
+ flg += DOMAIN if @domain_orig
117
+ flg += PATH if @path_orig
118
+ flg += DISCARD if @discard
119
+ flg += OVERRIDE if @override
120
+ flg
121
+ end
122
+
123
+ def set_flag(flag)
124
+ flag = flag.to_i
125
+ @use = true if flag & USE > 0
126
+ @secure = true if flag & SECURE > 0
127
+ @http_only = true if flag & HTTP_ONLY > 0
128
+ @domain_orig = true if flag & DOMAIN > 0
129
+ @path_orig = true if flag & PATH > 0
130
+ @discard = true if flag & DISCARD > 0
131
+ @override = true if flag & OVERRIDE > 0
132
+ end
133
+
134
+ def match?(url)
135
+ domainname = url.host
136
+ if (!domainname ||
137
+ !domain_match(domainname, @domain) ||
138
+ (@path && !head_match?(@path, url.path.empty? ? '/' : url.path)) ||
139
+ (@secure && (url.scheme != 'https')) )
140
+ return false
141
+ else
142
+ return true
143
+ end
144
+ end
145
+
146
+ def join_quotedstr(array, sep)
147
+ ret = Array.new
148
+ old_elem = nil
149
+ array.each{|elem|
150
+ if (elem.scan(/"/).length % 2) == 0
151
+ if old_elem
152
+ old_elem << sep << elem
153
+ else
154
+ ret << elem
155
+ old_elem = nil
156
+ end
157
+ else
158
+ if old_elem
159
+ old_elem << sep << elem
160
+ ret << old_elem
161
+ old_elem = nil
162
+ else
163
+ old_elem = elem.dup
164
+ end
165
+ end
166
+ }
167
+ ret
168
+ end
169
+
170
+ def parse(str, url)
171
+ @url = url
172
+ # TODO: should not depend on join_quotedstr. scan with escape like CSV.
173
+ cookie_elem = str.split(/;/)
174
+ cookie_elem = join_quotedstr(cookie_elem, ';')
175
+ cookie_elem -= [""] # del empty elements, a cookie might included ";;"
176
+ first_elem = cookie_elem.shift
177
+ if first_elem !~ /([^=]*)(\=(.*))?/
178
+ return
179
+ ## raise ArgumentError 'invalid cookie value'
180
+ end
181
+ @name = $1.strip
182
+ @value = normalize_cookie_value($3)
183
+ cookie_elem.each{|pair|
184
+ key, value = pair.split(/=/, 2) ## value may nil
185
+ key.strip!
186
+ value = normalize_cookie_value(value)
187
+ case key.downcase
188
+ when 'domain'
189
+ @domain = value
190
+ when 'expires'
191
+ @expires = nil
192
+ begin
193
+ @expires = Time.parse(value).gmtime if value
194
+ rescue ArgumentError
195
+ end
196
+ when 'path'
197
+ @path = value
198
+ when 'secure'
199
+ @secure = true ## value may nil, but must 'true'.
200
+ when 'httponly'
201
+ @http_only = true ## value may nil, but must 'true'.
202
+ else
203
+ warn("Unknown key: #{key} = #{value}")
204
+ end
205
+ }
206
+ end
207
+
208
+ private
209
+
210
+ def normalize_cookie_value(value)
211
+ if value
212
+ value = value.strip.sub(/\A"(.*)"\z/) { $1 }
213
+ value = nil if value.empty?
214
+ end
215
+ value
216
+ end
217
+ end
218
+
219
+ ##
220
+ # An Array class that already includes the MonitorMixin module.
221
+ #
222
+ class SynchronizedArray < Array
223
+ include MonitorMixin
224
+ end
225
+
226
+ class CookieManager
227
+ include CookieUtils
228
+
229
+ ### errors
230
+ class Error < StandardError; end
231
+ class ErrorOverrideOK < Error; end
232
+ class SpecialError < Error; end
233
+
234
+ attr_reader :cookies
235
+ attr_accessor :cookies_file
236
+ attr_accessor :accept_domains, :reject_domains
237
+
238
+ def initialize(file=nil)
239
+ @cookies = SynchronizedArray.new
240
+ @cookies_file = file
241
+ @is_saved = true
242
+ @reject_domains = Array.new
243
+ @accept_domains = Array.new
244
+ @netscape_rule = false
245
+ end
246
+
247
+ def cookies=(cookies)
248
+ if cookies.is_a?(SynchronizedArray)
249
+ @cookies = cookies
250
+ else
251
+ @cookies = SynchronizedArray.new(cookies)
252
+ end
253
+ end
254
+
255
+ def save_all_cookies(force = nil, save_unused = true, save_discarded = true)
256
+ @cookies.synchronize do
257
+ check_expired_cookies
258
+ if @is_saved and !force
259
+ return
260
+ end
261
+ File.open(@cookies_file, 'w') do |f|
262
+ @cookies.each do |cookie|
263
+ if (cookie.use? or save_unused) and
264
+ (!cookie.discard? or save_discarded)
265
+ f.print(cookie.url.to_s,"\t",
266
+ cookie.name,"\t",
267
+ cookie.value,"\t",
268
+ cookie.expires.to_i,"\t",
269
+ cookie.domain,"\t",
270
+ cookie.path,"\t",
271
+ cookie.flag,"\n")
272
+ end
273
+ end
274
+ end
275
+ end
276
+ @is_saved = true
277
+ end
278
+
279
+ def save_cookies(force = nil)
280
+ save_all_cookies(force, false, false)
281
+ end
282
+
283
+ def check_expired_cookies
284
+ @cookies.reject!{|cookie|
285
+ is_expired = (cookie.expires && (cookie.expires < Time.now.gmtime))
286
+ if is_expired && !cookie.discard?
287
+ @is_saved = false
288
+ end
289
+ is_expired
290
+ }
291
+ end
292
+
293
+ def parse(str, url)
294
+ cookie = WebAgent::Cookie.new
295
+ cookie.parse(str, url)
296
+ add(cookie)
297
+ end
298
+
299
+ def find(url)
300
+ return nil if @cookies.empty?
301
+
302
+ cookie_list = Array.new
303
+ @cookies.each{|cookie|
304
+ is_expired = (cookie.expires && (cookie.expires < Time.now.gmtime))
305
+ if cookie.use? && !is_expired && cookie.match?(url)
306
+ if cookie_list.select{|c1| c1.name == cookie.name}.empty?
307
+ cookie_list << cookie
308
+ end
309
+ end
310
+ }
311
+ return make_cookie_str(cookie_list)
312
+ end
313
+ alias cookie_value find
314
+
315
+ def add(given)
316
+ check_domain(given.domain, given.url.host, given.override?)
317
+
318
+ domain = given.domain || given.url.host
319
+ path = given.path || given.url.path.sub(%r|/[^/]*\z|, '')
320
+
321
+ cookie = nil
322
+ @cookies.synchronize do
323
+ check_expired_cookies
324
+ cookie = @cookies.find { |c|
325
+ c.domain == domain && c.path == path && c.name == given.name
326
+ }
327
+ if !cookie
328
+ cookie = WebAgent::Cookie.new
329
+ cookie.use = true
330
+ @cookies << cookie
331
+ end
332
+ end
333
+
334
+ cookie.domain = domain
335
+ cookie.path = path
336
+ cookie.url = given.url
337
+ cookie.name = given.name
338
+ cookie.value = given.value
339
+ cookie.expires = given.expires
340
+ cookie.secure = given.secure?
341
+ cookie.http_only = given.http_only?
342
+ cookie.domain_orig = given.domain
343
+ cookie.path_orig = given.path
344
+
345
+ if cookie.discard? || cookie.expires.nil?
346
+ cookie.discard = true
347
+ else
348
+ cookie.discard = false
349
+ @is_saved = false
350
+ end
351
+ end
352
+
353
+ def load_cookies
354
+ return if !File.readable?(@cookies_file)
355
+ @cookies.synchronize do
356
+ @cookies.clear
357
+ File.open(@cookies_file,'r'){|f|
358
+ while line = f.gets
359
+ cookie = WebAgent::Cookie.new
360
+ @cookies << cookie
361
+ col = line.chomp.split(/\t/)
362
+ cookie.url = HTTPClient::Util.urify(col[0])
363
+ cookie.name = col[1]
364
+ cookie.value = col[2]
365
+ if col[3].empty? or col[3] == '0'
366
+ cookie.expires = nil
367
+ else
368
+ cookie.expires = Time.at(col[3].to_i).gmtime
369
+ end
370
+ cookie.domain = col[4]
371
+ cookie.path = col[5]
372
+ cookie.set_flag(col[6])
373
+ end
374
+ }
375
+ end
376
+ end
377
+
378
+ # Who use it?
379
+ def check_cookie_accept_domain(domain)
380
+ unless domain
381
+ return false
382
+ end
383
+ @accept_domains.each{|dom|
384
+ if domain_match(domain, dom)
385
+ return true
386
+ end
387
+ }
388
+ @reject_domains.each{|dom|
389
+ if domain_match(domain, dom)
390
+ return false
391
+ end
392
+ }
393
+ return true
394
+ end
395
+
396
+ private
397
+
398
+ def make_cookie_str(cookie_list)
399
+ if cookie_list.empty?
400
+ return nil
401
+ end
402
+
403
+ ret = ''
404
+ c = cookie_list.shift
405
+ ret += "#{c.name}=#{c.value}"
406
+ cookie_list.each{|cookie|
407
+ ret += "; #{cookie.name}=#{cookie.value}"
408
+ }
409
+ return ret
410
+ end
411
+
412
+ # for conformance to http://wp.netscape.com/newsref/std/cookie_spec.html
413
+ attr_accessor :netscape_rule
414
+ SPECIAL_DOMAIN = [".com",".edu",".gov",".mil",".net",".org",".int"]
415
+
416
+ def check_domain(domain, hostname, override)
417
+ return unless domain
418
+
419
+ # [DRAFT 12] s. 4.2.2 (does not apply in the case that
420
+ # host name is the same as domain attribute for version 0
421
+ # cookie)
422
+ # I think that this rule has almost the same effect as the
423
+ # tail match of [NETSCAPE].
424
+ if domain !~ /^\./ && hostname != domain
425
+ domain = '.'+domain
426
+ end
427
+ # [NETSCAPE] rule
428
+ if @netscape_rule
429
+ n = domain.scan(/\./).length
430
+ if n < 2
431
+ cookie_error(SpecialError.new, override)
432
+ elsif n == 2
433
+ ## [NETSCAPE] rule
434
+ ok = SPECIAL_DOMAIN.select{|sdomain|
435
+ sdomain == domain[-(sdomain.length)..-1]
436
+ }
437
+ if ok.empty?
438
+ cookie_error(SpecialError.new, override)
439
+ end
440
+ end
441
+ end
442
+ # this implementation does not check RFC2109 4.3.2 case 2;
443
+ # the portion of host not in domain does not contain a dot.
444
+ # according to nsCookieService.cpp in Firefox 3.0.4, Firefox 3.0.4
445
+ # and IE does not check, too.
446
+ end
447
+
448
+ # not tested well; used only netscape_rule = true.
449
+ def cookie_error(err, override)
450
+ if !err.kind_of?(ErrorOverrideOK) || !override
451
+ raise err
452
+ end
453
+ end
454
+ end
455
+ end
456
+
457
+ class HTTPClient
458
+ CookieManager = WebAgent::CookieManager
459
+ end unless defined?(HTTPClient::CookieManager)