knjrbfw 0.0.21 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.21
1
+ 0.0.22
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{knjrbfw}
8
- s.version = "0.0.21"
8
+ s.version = "0.0.22"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kasper Johansen"]
12
- s.date = %q{2012-03-04}
12
+ s.date = %q{2012-03-16}
13
13
  s.description = %q{Including stuff for HTTP, SSH and much more.}
14
14
  s.email = %q{k@spernj.org}
15
15
  s.extra_rdoc_files = [
@@ -79,10 +79,24 @@ module Knj::ArrayExt
79
79
  end
80
80
  end
81
81
 
82
- adds.each do |key, value|
83
- hash_given[key] = value
82
+ hash_given.merge!(adds)
83
+
84
+ return hash_given
85
+ end
86
+
87
+ #Converts all keys in the given hash to strings.
88
+ def self.hash_str(hash_given)
89
+ adds = {}
90
+
91
+ hash_given.each do |key, val|
92
+ if !key.is_a?(String)
93
+ adds[key.to_s] = val
94
+ hash_given.delete(key)
95
+ end
84
96
  end
85
97
 
98
+ hash_given.merge!(adds)
99
+
86
100
  return hash_given
87
101
  end
88
102
 
@@ -201,7 +215,7 @@ module Knj::ArrayExt
201
215
  Knj::Php.foreach(hash) do |key, val|
202
216
  if val.is_a?(String)
203
217
  begin
204
- hash[key] = Knj::Php.utf8_encode(encoding)
218
+ hash[key] = Knj::Php.utf8_encode(val)
205
219
  rescue Encoding::UndefinedConversionError => e
206
220
  if args["ignore_encoding_errors"]
207
221
  next
@@ -4,15 +4,37 @@ class Knj::Cmd_parser
4
4
 
5
5
  str.lines.each do |line|
6
6
  next if line.match(/^total ([\d\.,]+)(M|k|G|)$/)
7
- match = line.match(/^(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)\s+(\d+)\s+(.+)\s+([^\W].+?)\s+([\d\.,]+)(M|k|G|K|)\s+((\d+)-(\d+)-(\d+)|(([A-z]{3})\s+(\d+)))\s+(\d+):(\d+)\s+(.+)$/)
7
+ match = line.match(/^(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)\s+(\d+)\s+(.+)\s+([^\W].+?)\s+([\d\.,]+)(M|k|G|K|)\s+((\d+)-(\d+)-(\d+)|(([A-z]{3})\s+(\d+)))\s+((\d+):(\d+)|(\d{4}))\s+(.+)$/)
8
8
  raise "Could not match: '#{line}'." if !match
9
9
 
10
+ year = nil
11
+
12
+ if match[17].to_i > 0
13
+ year = match[17].to_i
14
+ elsif match[26].to_i > 0
15
+ year = match[26].to_i
16
+ end
17
+
18
+ hour = match[24].to_i
19
+ min = match[25].to_i
20
+
10
21
  if match[17] and match[18] and match[19]
11
- time = Time.local(match[17].to_i, match[18].to_i, match[19].to_i, match[23].to_i, match[24].to_i)
22
+ month = match[18].to_i
23
+ date = match[19].to_i
12
24
  elsif match[20] and match[21] and match[22]
13
- time = Time.local(Time.now.year, match[21], match[22].to_i, match[23].to_i, match[24].to_i)
25
+ month = Knj::Datet.month_str_to_no(match[21])
26
+ date = match[22].to_i
27
+ end
28
+
29
+ if !year
30
+ if month > Time.now.month
31
+ year = Time.now.year - 1
32
+ else
33
+ year = Time.now.year
34
+ end
14
35
  end
15
36
 
37
+ time = Time.local(year, month, date, hour, min)
16
38
  bytes = match[14].gsub(",", ".").to_f
17
39
 
18
40
  size_match = match[15]
@@ -50,7 +72,7 @@ class Knj::Cmd_parser
50
72
  :grp => match[13],
51
73
  :size => bytes.to_i,
52
74
  :time => time,
53
- :file => match[25]
75
+ :file => match[27]
54
76
  }
55
77
  end
56
78
 
@@ -1,5 +1,8 @@
1
1
  class Knj::Csv
2
2
  def self.arr_to_csv(arr, del, encl)
3
+ raise "No delimiter given." if !del
4
+ raise "No enclosure given." if !encl
5
+
3
6
  str = ""
4
7
  first = true
5
8
  arr.each do |val|
@@ -11,6 +11,11 @@ class Knj::Datarow
11
11
  return @depending_data
12
12
  end
13
13
 
14
+ def self.autodelete_data
15
+ @autodelete_data = [] if !@autodelete_data
16
+ return @autodelete_data
17
+ end
18
+
14
19
  #This helps various parts of the framework determine if this is a datarow class without requiring it.
15
20
  def is_knj?
16
21
  return true
@@ -33,7 +38,14 @@ class Knj::Datarow
33
38
  methodname = val[:method]
34
39
 
35
40
  if val[:depends]
36
- depending_data << {
41
+ self.depending_data << {
42
+ :colname => colname,
43
+ :classname => classname
44
+ }
45
+ end
46
+
47
+ if val[:autodelete]
48
+ self.autodelete_data << {
37
49
  :colname => colname,
38
50
  :classname => classname
39
51
  }
@@ -106,7 +118,7 @@ class Knj::Datarow
106
118
 
107
119
  if val[:required]
108
120
  colname = "#{classname.to_s.downcase}_id".to_sym if !colname
109
- required_data << {
121
+ self.required_data << {
110
122
  :col => colname,
111
123
  :class => classname
112
124
  }
@@ -378,6 +390,7 @@ class Knj::Datarow
378
390
  sql = "SELECT #{table_str}.*"
379
391
  end
380
392
 
393
+ qargs = nil
381
394
  ret = self.list_helper(d)
382
395
 
383
396
  sql << " FROM #{table_str}"
@@ -389,6 +402,8 @@ class Knj::Datarow
389
402
  case key
390
403
  when "return_sql"
391
404
  #ignore
405
+ when :cloned_ubuf
406
+ qargs = {:cloned_ubuf => true}
392
407
  else
393
408
  raise "Invalid key: '#{key}' for '#{self.name}'. Valid keys are: '#{@columns_sqlhelper_args[:cols].keys.sort}'."
394
409
  end
@@ -418,7 +433,7 @@ class Knj::Datarow
418
433
 
419
434
  if select_col_as_array
420
435
  ids = [] if !block
421
- d.db.q(sql) do |data|
436
+ d.db.q(sql, qargs) do |data|
422
437
  if block
423
438
  block.call(data[:id])
424
439
  else
@@ -437,7 +452,7 @@ class Knj::Datarow
437
452
  return 0
438
453
  end
439
454
 
440
- return d.ob.list_bysql(self.classname, sql, &block)
455
+ return d.ob.list_bysql(self.classname, sql, qargs, &block)
441
456
  end
442
457
 
443
458
  def self.list_helper(d)
@@ -129,7 +129,7 @@ class Knj::Datet
129
129
  #Is a year a leap year in the Gregorian calendar? Copied from Date-class.
130
130
  def self.gregorian_leap?(y)
131
131
  if Date.respond_to?("gregorian_leap?")
132
- return Date.gregorian_leap?
132
+ return Date.gregorian_leap?(y)
133
133
  elsif y % 4 == 0 && y % 100 != 0
134
134
  return true
135
135
  elsif y % 400 == 0
@@ -30,11 +30,11 @@ class Knj::Gettext_threadded
30
30
 
31
31
  cont = nil
32
32
  File.open(pofn, {:encoding => @args[:encoding]}) do |fp|
33
- cont = fp.read
33
+ cont = fp.read.encode("utf-8")
34
34
  end
35
35
 
36
36
  cont.scan(/msgid\s+\"(.+)\"\nmsgstr\s+\"(.+)\"\n\n/) do |match|
37
- @langs[file][match[0]] = match[1]
37
+ @langs[file][match[0]] = match[1].to_s.encode("utf-8")
38
38
  end
39
39
  end
40
40
  end
@@ -2,58 +2,97 @@ class Knj::Google_sitemap
2
2
  attr_reader :doc
3
3
 
4
4
  def initialize(args = {})
5
+ raise "No block given." if !block_given?
6
+
5
7
  @args = args
6
8
 
7
9
  #used for Time.iso8601.
8
10
  require "time"
9
11
 
10
- @doc = REXML::Document.new
11
- @doc << REXML::XMLDecl.new("1.0", "UTF-8")
12
+ #REXML is known to leak memory - use subprocess.
13
+ @subproc = Knj::Process_meta.new("id" => "google_sitemap", "debug_err" => true)
12
14
 
13
- @urlset = @doc.add_element("urlset")
14
- @urlset.add_attributes("xmlns" => "http://www.sitemaps.org/schemas/sitemap/0.9")
15
+ begin
16
+ @subproc.static("Object", "require", "rexml/rexml")
17
+ @subproc.static("Object", "require", "rexml/document")
18
+
19
+ @doc = @subproc.new("REXML::Document")
20
+
21
+ xmldecl = @subproc.new("REXML::XMLDecl", "1.0", "UTF-8")
22
+ @doc._pm_send_noret("<<", xmldecl)
23
+
24
+ urlset = @subproc.proxy_from_call(@doc, "add_element", "urlset")
25
+ urlset._pm_send_noret("add_attributes", {"xmlns" => "http://www.sitemaps.org/schemas/sitemap/0.9"})
26
+
27
+ @root = @subproc.proxy_from_call(@doc, "root")
28
+ yield(self)
29
+ ensure
30
+ @doc = nil
31
+ @root = nil
32
+ @subproc.destroy
33
+ @subproc = nil
34
+ end
15
35
  end
16
36
 
17
37
  def add_url(url_value, lastmod_value, cf_value = nil, priority_value = nil)
18
- el = REXML::Element.new("url")
19
-
20
- loc = el.add_element("loc")
21
- loc.text = url_value
22
-
23
38
  if !lastmod_value or lastmod_value.to_i == 0
24
39
  raise sprintf("Invalid date: %1$s, url: %2$s", lastmod_value.to_s, url_value)
25
40
  end
26
41
 
27
- lm = el.add_element("lastmod")
42
+ el = @subproc.new("REXML::Element", "url")
43
+
44
+ loc = @subproc.proxy_from_call(el, "add_element", "loc")
45
+ loc._pm_send_noret("text=", url_value)
46
+
47
+ lm = @subproc.proxy_from_call(el, "add_element", "lastmod")
28
48
  if @args.key?(:date_min) and @args[:date_min] > lastmod_value
29
49
  lastmod_value = @args[:date_min]
30
50
  end
31
51
 
32
- lm.text = lastmod_value.iso8601
52
+ lm._pm_send_noret("text=", lastmod_value.iso8601)
33
53
 
34
54
  if cf_value
35
- cf = el.add_element("changefreq")
36
- cf.text = cf_value
55
+ cf = @subproc.proxy_from_call(el, "add_element", "changefreq")
56
+ cf._pm_send_noret("text=", cf_value)
37
57
  end
38
58
 
39
59
  if priority_value
40
- priority = el.add_element("priority")
41
- priority.text = priority_value
60
+ priority = @subproc.proxy_from_call("el", "add_element", "priority")
61
+ priority._pm_send_noret("text=", priority_value)
42
62
  end
43
63
 
44
- @doc.root << el
64
+ @root._pm_send_noret("<<", el)
45
65
  end
46
66
 
67
+ #This will return a non-human-readable XML-string.
47
68
  def to_xml
48
69
  return @doc.to_s
49
70
  end
50
71
 
72
+ #This will return a non-human-readable XML-string.
51
73
  def to_s
52
74
  return @doc.to_s
53
75
  end
54
76
 
77
+ #This will print the result.
55
78
  def write
56
- writer = REXML::Formatters::Pretty.new(5)
57
- writer.write(@doc, $stdout)
79
+ #Require and spawn StringIO in the subprocess.
80
+ @subproc.static("Object", "require", "stringio")
81
+ string_io = @subproc.spawn_object("StringIO")
82
+
83
+ #We want a human-readable print.
84
+ writer = @subproc.spawn_object("REXML::Formatters::Pretty", 5)
85
+ writer._pm_send_noret("write", @doc, string_io)
86
+
87
+ #Prepare printing by rewinding StringIO to read from beginning.
88
+ string_io._pm_send_noret("rewind")
89
+
90
+ #Buffer results from subprocess in order to speed up printing.
91
+ string_io._process_meta_block_buffer_use = true
92
+
93
+ #Print out the result in bits to avoid raping the memory (subprocess is already raped - no question there...).
94
+ string_io._pm_send_noret("each", 4096) do |str|
95
+ print str
96
+ end
58
97
  end
59
98
  end
@@ -33,6 +33,14 @@ class Knj::Http2
33
33
 
34
34
  raise "No host was given." if !@args[:host]
35
35
  self.reconnect
36
+
37
+ if block_given?
38
+ begin
39
+ yield(self)
40
+ ensure
41
+ self.destroy
42
+ end
43
+ end
36
44
  end
37
45
 
38
46
  def socket_working?
@@ -49,6 +57,25 @@ class Knj::Http2
49
57
  return true
50
58
  end
51
59
 
60
+ def destroy
61
+ @args = nil
62
+ @cookies = nil
63
+ @debug = nil
64
+ @mutex = nil
65
+ @uagent = nil
66
+ @keepalive_timeout = nil
67
+ @request_last = nil
68
+
69
+ @sock.close if @sock and !@sock.closed?
70
+ @sock = nil
71
+
72
+ @sock_plain.close if @sock_plain and !@sock_plain.closed?
73
+ @sock_plain = nil
74
+
75
+ @sock_ssl.close if @sock_ssl and !@sock_ssl.closed?
76
+ @sock_ssl = nil
77
+ end
78
+
52
79
  #Reconnects to the host.
53
80
  def reconnect
54
81
  print "Http2: Reconnect.\n" if @debug
@@ -106,19 +133,25 @@ class Knj::Http2
106
133
  end
107
134
 
108
135
  def get(addr, args = {})
109
- @mutex.synchronize do
110
- header_str = "GET /#{addr} HTTP/1.1#{@nl}"
111
- header_str << self.header_str(self.default_headers(args), args)
112
- header_str << "#{@nl}"
113
-
114
- print "Http2: Writing headers.\n" if @debug
115
- self.write(header_str)
116
-
117
- print "Http2: Reading response.\n" if @debug
118
- resp = self.read_response(args)
136
+ begin
137
+ @mutex.synchronize do
138
+ header_str = "GET /#{addr} HTTP/1.1#{@nl}"
139
+ header_str << self.header_str(self.default_headers(args), args)
140
+ header_str << "#{@nl}"
141
+
142
+ print "Http2: Writing headers.\n" if @debug
143
+ self.write(header_str)
144
+
145
+ print "Http2: Reading response.\n" if @debug
146
+ resp = self.read_response(args)
147
+
148
+ print "Http2: Done with get request.\n" if @debug
149
+ return resp
150
+ end
151
+ rescue Knj::Errors::Retry => e
152
+ print "Redirecting to: #{e.message}\n"
119
153
 
120
- print "Http2: Done with get request.\n" if @debug
121
- return resp
154
+ return self.get(e.message, args)
122
155
  end
123
156
  end
124
157
 
@@ -159,59 +192,67 @@ class Knj::Http2
159
192
  end
160
193
 
161
194
  def post(addr, pdata = {}, args = {})
162
- @mutex.synchronize do
163
- praw = ""
164
- pdata.each do |key, val|
165
- praw << "&" if praw != ""
166
- praw << "#{Knj::Web.urlenc(key)}=#{Knj::Web.urlenc(val)}"
195
+ begin
196
+ @mutex.synchronize do
197
+ praw = ""
198
+ pdata.each do |key, val|
199
+ praw << "&" if praw != ""
200
+ praw << "#{Knj::Web.urlenc(key)}=#{Knj::Web.urlenc(val)}"
201
+ end
202
+
203
+ header_str = "POST /#{addr} HTTP/1.1#{@nl}"
204
+ header_str << self.header_str(self.default_headers(args).merge("Content-Length" => praw.length), args)
205
+ header_str << "#{@nl}"
206
+ header_str << praw
207
+
208
+ self.write(header_str)
209
+ return self.read_response(args)
167
210
  end
168
-
169
- header_str = "POST /#{addr} HTTP/1.1#{@nl}"
170
- header_str << self.header_str(self.default_headers(args).merge("Content-Length" => praw.length), args)
171
- header_str << "#{@nl}"
172
- header_str << praw
173
-
174
- self.write(header_str)
175
- return self.read_response(args)
211
+ rescue Knj::Errors::Retry => e
212
+ return self.get(e.message, args)
176
213
  end
177
214
  end
178
215
 
179
216
  def post_multipart(addr, pdata, args = {})
180
- @mutex.synchronize do
181
- boundary = Digest::MD5.hexdigest(Time.now.to_f.to_s)
182
-
183
- praw = ""
184
- pdata.each do |key, val|
185
- praw << "--#{boundary}#{@nl}"
217
+ begin
218
+ @mutex.synchronize do
219
+ boundary = Digest::MD5.hexdigest(Time.now.to_f.to_s)
186
220
 
187
- if val.class.name == "Tempfile" and val.respond_to?("original_filename")
188
- praw << "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{val.original_filename}\";#{@nl}"
189
- else
190
- praw << "Content-Disposition: form-data; name=\"#{key}\";#{@nl}"
221
+ praw = ""
222
+ pdata.each do |key, val|
223
+ praw << "--#{boundary}#{@nl}"
224
+
225
+ if val.class.name == "Tempfile" and val.respond_to?("original_filename")
226
+ praw << "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{val.original_filename}\";#{@nl}"
227
+ else
228
+ praw << "Content-Disposition: form-data; name=\"#{key}\";#{@nl}"
229
+ end
230
+
231
+ praw << "Content-Type: text/plain#{@nl}"
232
+ praw << "Content-Length: #{val.length}#{@nl}"
233
+ praw << @nl
234
+
235
+ if val.is_a?(StringIO)
236
+ praw << val.read
237
+ else
238
+ praw << val.to_s
239
+ end
240
+
241
+ praw << @nl
191
242
  end
192
243
 
193
- praw << "Content-Type: text/plain#{@nl}"
194
- praw << "Content-Length: #{val.length}#{@nl}"
195
- praw << @nl
244
+ header_str = "POST /#{addr} HTTP/1.1#{@nl}"
245
+ header_str << "Content-Type: multipart/form-data; boundary=#{boundary}#{@nl}"
246
+ header_str << self.header_str(self.default_headers(args).merge("Content-Length" => praw.length), args)
247
+ header_str << "#{@nl}"
248
+ header_str << praw
249
+ header_str << "--#{boundary}--"
196
250
 
197
- if val.is_a?(StringIO)
198
- praw << val.read
199
- else
200
- praw << val.to_s
201
- end
202
-
203
- praw << @nl
251
+ self.write(header_str)
252
+ return self.read_response(args)
204
253
  end
205
-
206
- header_str = "POST /#{addr} HTTP/1.1#{@nl}"
207
- header_str << "Content-Type: multipart/form-data; boundary=#{boundary}#{@nl}"
208
- header_str << self.header_str(self.default_headers(args).merge("Content-Length" => praw.length), args)
209
- header_str << "#{@nl}"
210
- header_str << praw
211
- header_str << "--#{boundary}--"
212
-
213
- self.write(header_str)
214
- return self.read_response(args)
254
+ rescue Knj::Errors::Retry => e
255
+ return self.get(e.message, args)
215
256
  end
216
257
  end
217
258
 
@@ -313,13 +354,15 @@ class Knj::Http2
313
354
  args[:port] = uri.port if uri.port
314
355
 
315
356
  if !args[:host] or args[:host] == @args[:host]
316
- return self.get(resp.header("location"))
357
+ raise Knj::Errors::Retry, resp.header("location")
317
358
  else
318
359
  http = Knj::Http2.new(args)
319
360
  return http.get(uri.path)
320
361
  end
321
362
  elsif resp.args[:code].to_s == "500"
322
363
  raise "500 - Internal server error."
364
+ elsif resp.args[:code].to_s == "403"
365
+ raise Knj::Errors::NoAccess
323
366
  else
324
367
  return resp
325
368
  end
@@ -428,6 +471,7 @@ class Knj::Http2::Response
428
471
  return @args[:headers][key].first.to_s
429
472
  end
430
473
 
474
+ #Returns true if a header of the given string exists.
431
475
  def header?(key)
432
476
  return true if @args[:headers].key?(key) and @args[:headers][key].first.to_s.length > 0
433
477
  return false