knjappserver 0.0.20 → 0.0.21

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.20
1
+ 0.0.21
data/knjappserver.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{knjappserver}
8
- s.version = "0.0.20"
8
+ s.version = "0.0.21"
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-16}
12
+ s.date = %q{2012-04-26}
13
13
  s.description = %q{Which supports a lot of undocumented stuff.}
14
14
  s.email = %q{k@spernj.org}
15
15
  s.executables = ["check_running.rb", "knjappserver_start.rb"]
@@ -42,6 +42,7 @@ Gem::Specification.new do |s|
42
42
  "lib/include/class_httpsession_contentgroup.rb",
43
43
  "lib/include/class_httpsession_http_request.rb",
44
44
  "lib/include/class_httpsession_http_response.rb",
45
+ "lib/include/class_httpsession_page_environment.rb",
45
46
  "lib/include/class_httpsession_post_multipart.rb",
46
47
  "lib/include/class_knjappserver.rb",
47
48
  "lib/include/class_knjappserver_cleaner.rb",
@@ -1,12 +1,13 @@
1
1
  class Knjappserver::Httpsession
2
2
  attr_accessor :data, :alert_sent
3
- attr_reader :session, :session_id, :session_hash, :kas, :active, :out, :eruby, :browser, :debug, :resp, :page_path, :cgroup, :meta, :httpsession_var, :handler, :working
3
+ attr_reader :get, :session, :session_id, :session_hash, :kas, :active, :out, :eruby, :browser, :debug, :resp, :page_path, :post, :cgroup, :meta, :httpsession_var, :handler, :working
4
4
 
5
5
  dir = File.dirname(__FILE__)
6
6
 
7
7
  autoload :Contentgroup, "#{dir}/class_httpsession_contentgroup.rb"
8
8
  autoload :Http_request, "#{dir}/class_httpsession_http_request.rb"
9
9
  autoload :Http_response, "#{dir}/class_httpsession_http_response.rb"
10
+ autoload :Page_environment, "#{dir}/class_httpsession_page_environment.rb"
10
11
  autoload :Post_multipart, "#{dir}/class_httpsession_post_multipart.rb"
11
12
 
12
13
  def initialize(httpserver, socket)
@@ -17,11 +18,15 @@ class Knjappserver::Httpsession
17
18
  @types = @kas.types
18
19
  @config = @kas.config
19
20
  @active = true
20
- @eruby = Knj::Eruby.new(:cache_hash => @kas.eruby_cache)
21
21
  @debug = @kas.debug
22
22
  @handlers_cache = @config[:handlers_cache]
23
23
  @httpsession_var = {}
24
24
 
25
+ @eruby = Knj::Eruby.new(
26
+ :cache_hash => @kas.eruby_cache,
27
+ :binding_callback => self.method("create_binding")
28
+ )
29
+
25
30
  #Set socket stuff.
26
31
  if RUBY_PLATFORM == "java" or RUBY_ENGINE == "rbx"
27
32
  if @kas.config[:peeraddr_static]
@@ -135,6 +140,12 @@ class Knjappserver::Httpsession
135
140
  end
136
141
  end
137
142
 
143
+ #Creates a new Knjappserver::Binding-object and returns the binding for that object.
144
+ def create_binding
145
+ binding_obj = Knjappserver::Httpsession::Page_environment.new(:httpsession => self, :kas => @kas)
146
+ return binding_obj.get_binding
147
+ end
148
+
138
149
  #Is called when content is added and begings to write the output if it goes above the limit.
139
150
  def add_size(size)
140
151
  @written_size += size
@@ -204,7 +215,7 @@ class Knjappserver::Httpsession
204
215
 
205
216
  def serve
206
217
  STDOUT.print "Generating meta, cookie, get, post and headers.\n" if @debug
207
- @meta = @handler.meta.merge!(@socket_meta)
218
+ @meta = @handler.meta.merge(@socket_meta)
208
219
  @cookie = @handler.cookie
209
220
  @get = @handler.get
210
221
  @post = @handler.post
@@ -292,49 +303,56 @@ class Knjappserver::Httpsession
292
303
  :httpsession => self
293
304
  }) if @kas.events
294
305
 
295
- if @handlers_cache.key?(@ext)
296
- STDOUT.print "Calling handler.\n" if @debug
297
- @handlers_cache[@ext].call(self)
298
- else
299
- #check if we should use a handler for this request.
300
- @config[:handlers].each do |handler_info|
301
- if handler_info.key?(:file_ext) and handler_info[:file_ext] == @ext
302
- return handler_info[:callback].call(self)
303
- elsif handler_info.key?(:path) and handler_info[:mount] and @meta["SCRIPT_NAME"].slice(0, handler_info[:path].length) == handler_info[:path]
304
- @page_path = "#{handler_info[:mount]}#{@meta["SCRIPT_NAME"].slice(handler_info[:path].length, @meta["SCRIPT_NAME"].length)}"
305
- break
306
- end
307
- end
308
-
309
- if !File.exists?(@page_path)
310
- @resp.status = 404
311
- @resp.header("Content-Type", "text/html")
312
- @cgroup.write("File you are looking for was not found: '#{@meta["REQUEST_URI"]}'.")
313
- else
314
- if @headers["cache-control"] and @headers["cache-control"][0]
315
- cache_control = {}
316
- @headers["cache-control"][0].scan(/(.+)=(.+)/) do |match|
317
- cache_control[match[1]] = match[2]
306
+ begin
307
+ Timeout.timeout(@kas.config[:timeout]) do
308
+ if @handlers_cache.key?(@ext)
309
+ STDOUT.print "Calling handler.\n" if @debug
310
+ @handlers_cache[@ext].call(self)
311
+ else
312
+ #check if we should use a handler for this request.
313
+ @config[:handlers].each do |handler_info|
314
+ if handler_info.key?(:file_ext) and handler_info[:file_ext] == @ext
315
+ return handler_info[:callback].call(self)
316
+ elsif handler_info.key?(:path) and handler_info[:mount] and @meta["SCRIPT_NAME"].slice(0, handler_info[:path].length) == handler_info[:path]
317
+ @page_path = "#{handler_info[:mount]}#{@meta["SCRIPT_NAME"].slice(handler_info[:path].length, @meta["SCRIPT_NAME"].length)}"
318
+ break
319
+ end
318
320
  end
319
- end
320
-
321
- cache_dont = true if cache_control and cache_control.key?("max-age") and cache_control["max-age"].to_i <= 0
322
- lastmod = File.mtime(@page_path)
323
-
324
- @resp.header("Last-Modified", lastmod.httpdate)
325
- @resp.header("Expires", (Time.now + 86400).httpdate) #next day.
326
-
327
- if !cache_dont and @headers["if-modified-since"] and @headers["if-modified-since"][0]
328
- request_mod = Knj::Datet.parse(@headers["if-modified-since"][0]).time
329
321
 
330
- if request_mod == lastmod
331
- @resp.status = 304
332
- return nil
322
+ if !File.exists?(@page_path)
323
+ @resp.status = 404
324
+ @resp.header("Content-Type", "text/html")
325
+ @cgroup.write("File you are looking for was not found: '#{@meta["REQUEST_URI"]}'.")
326
+ else
327
+ if @headers["cache-control"] and @headers["cache-control"][0]
328
+ cache_control = {}
329
+ @headers["cache-control"][0].scan(/(.+)=(.+)/) do |match|
330
+ cache_control[match[1]] = match[2]
331
+ end
332
+ end
333
+
334
+ cache_dont = true if cache_control and cache_control.key?("max-age") and cache_control["max-age"].to_i <= 0
335
+ lastmod = File.mtime(@page_path)
336
+
337
+ @resp.header("Last-Modified", lastmod.httpdate)
338
+ @resp.header("Expires", (Time.now + 86400).httpdate) #next day.
339
+
340
+ if !cache_dont and @headers["if-modified-since"] and @headers["if-modified-since"][0]
341
+ request_mod = Knj::Datet.parse(@headers["if-modified-since"].first).time
342
+
343
+ if request_mod == lastmod
344
+ @resp.status = 304
345
+ return nil
346
+ end
347
+ end
348
+
349
+ @cgroup.new_io(:type => :file, :path => @page_path)
333
350
  end
334
351
  end
335
-
336
- @cgroup.new_io(File.new(@page_path))
337
352
  end
353
+ rescue Timeout::Error
354
+ @resp.status = 500
355
+ print "The request timed out."
338
356
  end
339
357
 
340
358
  @cgroup.mark_done
@@ -121,24 +121,22 @@ class Knjappserver::Httpsession::Contentgroup
121
121
  if data.is_a?(Knjappserver::Httpsession::Contentgroup)
122
122
  data.write_to_socket
123
123
  elsif data.key?(:str)
124
- if data[:str].is_a?(File)
125
- file = data[:str]
126
-
127
- loop do
128
- begin
129
- buf = file.sysread(16384)
130
- rescue EOFError
131
- break
132
- end
133
-
134
- if @chunked
135
- @socket.write("#{buf.length.to_s(16)}#{NL}#{buf}#{NL}")
136
- else
137
- @socket.write(buf)
124
+ if data[:str].is_a?(Hash) and data[:str][:type] == :file
125
+ File.open(data[:str][:path], "r") do |file|
126
+ loop do
127
+ begin
128
+ buf = file.sysread(16384)
129
+ rescue EOFError
130
+ break
131
+ end
132
+
133
+ if @chunked
134
+ @socket.write("#{buf.length.to_s(16)}#{NL}#{buf}#{NL}")
135
+ else
136
+ @socket.write(buf)
137
+ end
138
138
  end
139
139
  end
140
-
141
- file.close
142
140
  else
143
141
  loop do
144
142
  break if data[:done] and data[:str].size <= 0
@@ -1,4 +1,3 @@
1
- require "uri"
2
1
  require "knj/web"
3
2
 
4
3
  #If we are running on JRuby or Rubinius this will seriously speed things up if we are behind a proxy.
@@ -18,40 +17,56 @@ class Knjappserver::Httpsession::Http_request
18
17
  end
19
18
 
20
19
  #Reads content from the socket until the end of headers. Also does various error-checks.
21
- def read_socket
20
+ def read_socket(socket, cont)
22
21
  loop do
23
- raise Errno::ECONNRESET, "Socket closed." if @socket.closed?
24
- read = @socket.gets
22
+ raise Errno::ECONNRESET, "Socket closed." if socket.closed?
23
+ read = socket.gets
25
24
  raise Errno::ECONNRESET, "Socket returned non-string: '#{read.class.name}'." if !read.is_a?(String)
26
- @cont << read
27
- break if @cont[-4..-1] == "\r\n\r\n" or @cont[-2..-1] == "\n\n"
25
+ cont << read
26
+ break if cont[-4..-1] == "\r\n\r\n" or cont[-2..-1] == "\n\n"
28
27
  end
29
28
  end
30
29
 
30
+ def reset
31
+ @modified_since = nil
32
+ @get = nil
33
+ @post = nil
34
+ @cookie = nil
35
+ @meta = nil
36
+ @page_path = nil
37
+ @headers = nil
38
+ @http_version = nil
39
+ @read = nil
40
+ @clength = nil
41
+ @speec = nil
42
+ @percent = nil
43
+ @secs_left = nil
44
+ end
45
+
31
46
  #Generates data on object from the given socket.
32
47
  def socket_parse(socket)
33
- @modified_since = nil
34
- @cont = ""
35
- @socket = socket
36
- self.read_socket
48
+ self.reset
49
+ cont = ""
50
+ self.read_socket(socket, cont)
37
51
 
38
52
  #Parse URI (page_path and get).
39
- match = @cont.match(/^(GET|POST|HEAD)\s+(.+)\s+HTTP\/1\.(\d+)\s*/)
40
- raise "Could not parse request: '#{@cont.split("\n").first}'." if !match
53
+ match = cont.match(/^(GET|POST|HEAD)\s+(.+)\s+HTTP\/1\.(\d+)\s*/)
54
+ raise "Could not parse request: '#{cont.split("\n").first}'." if !match
41
55
 
42
56
  @http_version = "1.#{match[3]}"
43
57
 
44
58
  method = match[1]
45
- @cont = @cont.gsub(match[0], "")
46
- uri = URI.parse(match[2])
59
+ cont = cont.gsub(match[0], "")
60
+
61
+ uri = Knj::Web.parse_uri(match[2])
47
62
 
48
- page_filepath = Knj::Web.urldec(uri.path)
63
+ page_filepath = Knj::Web.urldec(uri[:path])
49
64
  if page_filepath.length <= 0 or page_filepath == "/" or File.directory?("#{@kas.config[:doc_root]}/#{page_filepath}")
50
65
  page_filepath = "#{page_filepath}/#{@kas.config[:default_page]}"
51
66
  end
52
67
 
53
68
  @page_path = "#{@kas.config[:doc_root]}/#{page_filepath}"
54
- @get = Knj::Web.parse_urlquery(uri.query.to_s, {:urldecode => true, :force_utf8 => true})
69
+ @get = Knj::Web.parse_urlquery(uri[:query], {:urldecode => true, :force_utf8 => true})
55
70
 
56
71
  if @get["_kas_httpsession_id"]
57
72
  @kas.httpsessions_ids[@get["_kas_httpsession_id"]] = @args[:httpsession]
@@ -63,12 +78,12 @@ class Knjappserver::Httpsession::Http_request
63
78
  @cookie = {}
64
79
  @meta = {
65
80
  "REQUEST_METHOD" => method,
66
- "QUERY_STRING" => uri.query,
81
+ "QUERY_STRING" => uri[:query],
67
82
  "REQUEST_URI" => match[2],
68
- "SCRIPT_NAME" => uri.path
83
+ "SCRIPT_NAME" => uri[:path]
69
84
  }
70
85
 
71
- @cont.scan(/^(\S+):\s*(.+)\r\n/) do |header_match|
86
+ cont.scan(/^(\S+):\s*(.+)\r\n/) do |header_match|
72
87
  key = header_match[0].downcase
73
88
  val = header_match[1]
74
89
 
@@ -141,8 +156,8 @@ class Knjappserver::Httpsession::Http_request
141
156
  read_size = @clength - @read
142
157
  read_size = 4096 if read_size > 4096
143
158
 
144
- raise Errno::ECONNRESET, "Socket closed." if @socket.closed?
145
- read = @socket.read(read_size)
159
+ raise Errno::ECONNRESET, "Socket closed." if socket.closed?
160
+ read = socket.read(read_size)
146
161
  raise Errno::ECONNRESET, "Socket returned non-string: '#{read.class.name}'." if !read.is_a?(String)
147
162
  post_data << read
148
163
  @read += read.length
@@ -59,6 +59,9 @@ class Knjappserver::Httpsession::Http_response
59
59
  end
60
60
 
61
61
  def header(key, val)
62
+ lines = val.to_s.count("\n") + 1
63
+ raise "Value contains more lines than 1 (#{lines})." if lines > 1
64
+
62
65
  if !@headers_sent
63
66
  @headers[key.to_s.downcase] = [key, val]
64
67
  else
@@ -0,0 +1,66 @@
1
+ #This class handels all the magic-methods in a different way - by defining them as methods on the binding for the .rhtml-pages.
2
+ class Knjappserver::Httpsession::Page_environment
3
+ def initialize(args = {})
4
+ @args = args
5
+ end
6
+
7
+ def get_binding
8
+ return binding
9
+ end
10
+
11
+ def _buf
12
+ return $stdout
13
+ end
14
+
15
+ def _cookie
16
+ return @args[:httpsession].cookie
17
+ end
18
+
19
+ def _db
20
+ return @args[:kas].db_handler
21
+ end
22
+
23
+ def _get
24
+ return @args[:httpsession].get
25
+ end
26
+
27
+ def _kas
28
+ return @args[:kas]
29
+ end
30
+
31
+ alias _requestdata _kas
32
+
33
+ def _kas_vars
34
+ return @args[:kas].vars
35
+ end
36
+
37
+ def _httpsession
38
+ return @args[:httpsession]
39
+ end
40
+
41
+ def _httpsession_var
42
+ return @args[:httpsession].httpsession_var
43
+ end
44
+
45
+ def _post
46
+ return @args[:httpsession].post
47
+ end
48
+
49
+ def _meta
50
+ return @args[:httpsession].meta
51
+ end
52
+
53
+ alias _server _meta
54
+
55
+ def _session
56
+ return @args[:httpsession].session.sess_data
57
+ end
58
+
59
+ def _session_hash
60
+ return @args[:httpsession].session_hash
61
+ end
62
+
63
+ def _session_obj
64
+ return @args[:httpsession].session
65
+ end
66
+ end
@@ -5,6 +5,7 @@ class Knjappserver
5
5
  appsrv_dir = File.dirname(__FILE__)
6
6
  autoload :ERBHandler, "#{appsrv_dir}/class_erbhandler"
7
7
  autoload :Log, "#{appsrv_dir}/class_log.rb"
8
+ autoload :Log_link, "#{appsrv_dir}/class_log_link.rb"
8
9
 
9
10
  def initialize(config)
10
11
  raise "No arguments given." if !config.is_a?(Hash)
@@ -67,8 +68,6 @@ class Knjappserver
67
68
  @path_knjappserver = File.dirname(__FILE__)
68
69
  if @config[:knjrbfw_path]
69
70
  @path_knjrbfw = @config[:knjrbfw_path]
70
- elsif $knjappserver_config and $knjappserver_config["knjrbfw"]
71
- @path_knjrbfw = $knjappserver_config["knjrbfw"]
72
71
  else
73
72
  @path_knjrbfw = ""
74
73
  end
@@ -232,8 +231,7 @@ class Knjappserver
232
231
 
233
232
  #Save the PID to the run-file.
234
233
  print "Setting run-file.\n" if @debug
235
- require "tmpdir"
236
- tmpdir = "#{Dir.tmpdir}/knjappserver"
234
+ tmpdir = "#{Knj::Os.tmpdir}/knjappserver"
237
235
  tmppath = "#{tmpdir}/run_#{@config[:title]}"
238
236
 
239
237
  if !File.exists?(tmpdir)
@@ -372,8 +370,8 @@ class Knjappserver
372
370
  STDOUT.print "Threadpool startet.\n" if @debug
373
371
  @httpserv.start
374
372
  STDOUT.print "Appserver startet.\n" if @debug
375
- rescue Interrupt
376
- STDOUT.print "Got interrupt - stopping appserver.\n" if @debug
373
+ rescue Interrupt => e
374
+ STDOUT.print "Got interrupt - trying to stop appserver.\n" if @debug
377
375
  self.stop
378
376
  end
379
377
  end
@@ -392,12 +390,10 @@ class Knjappserver
392
390
  self.sessions_flush
393
391
  }
394
392
 
395
- #If we cant get a paused-execution in 10 secs - we just force the stop.
393
+ #If we cant get a paused-execution in 5 secs - we just force the stop.
396
394
  begin
397
- Timeout.timeout(10) do
398
- self.paused_exec do
399
- proc_stop.call
400
- end
395
+ Timeout.timeout(5) do
396
+ self.paused_exec(&proc_stop)
401
397
  end
402
398
  rescue Timeout::Error, SystemExit, Interrupt
403
399
  STDOUT.print "Forcing stop-appserver - couldnt get timing window.\n" if @debug
@@ -423,12 +419,15 @@ class Knjappserver
423
419
 
424
420
  #Will stop handeling any more HTTP-requests, run the proc given and return handeling HTTP-requests.
425
421
  def paused_exec
422
+ raise "No block given." if !block_given?
426
423
  self.pause
427
424
 
428
425
  begin
429
426
  sleep 0.2 while @httpserv and @httpserv.working_count and @httpserv.working_count > 0
430
427
  @paused_mutex.synchronize do
431
- yield
428
+ Timeout.timeout(15) do
429
+ yield
430
+ end
432
431
  end
433
432
  ensure
434
433
  self.unpause
@@ -8,7 +8,7 @@ class Knjappserver
8
8
 
9
9
  #This should not be runned via _kas.timeout because timeout wont run when @should_restart is true! - knj
10
10
  Thread.new do
11
- begin
11
+ begin
12
12
  loop do
13
13
  sleep time
14
14
 
@@ -91,51 +91,43 @@ class Knjappserver
91
91
  end
92
92
 
93
93
  #This flushes (writes) all session-data to the server and deletes old unused sessions from the database.
94
- self.timeout(:time => @config[:cleaner_timeout]) do
95
- self.clean
96
- end
94
+ self.timeout(:time => @config[:cleaner_timeout], &self.method("clean"))
97
95
  end
98
96
 
99
97
  #This method can be used to clean the appserver. Dont call this from a HTTP-request.
100
98
  def clean
101
- self.paused_exec do
102
- STDOUT.print "Cleaning sessions on appserver.\n" if @config[:debug]
103
-
104
- #Clean up various inactive sessions.
105
- session_not_ids = []
106
- time_check = Time.now.to_i - 300
107
- newsessions = {}
108
- @sessions.each do |session_hash, session_data|
109
- session_data[:dbobj].flush
110
-
111
- if session_data[:time_lastused].to_i > time_check
112
- newsessions[session_hash] = session_data
113
- session_not_ids << session_data[:dbobj].id
114
- end
115
- end
116
-
117
- @sessions = newsessions
99
+ STDOUT.print "Cleaning sessions on appserver.\n" if @config[:debug]
100
+
101
+ #Clean up various inactive sessions.
102
+ session_not_ids = []
103
+ time_check = Time.now.to_i - 300
104
+ newsessions = {}
105
+ @sessions.each do |session_hash, session_data|
106
+ session_data[:dbobj].flush
118
107
 
119
- STDOUT.print "Delete sessions...\n" if @config[:debug]
120
- @ob.list(:Session, {"id_not" => session_not_ids, "date_lastused_below" => (Time.now - 5356800)}) do |session|
121
- idhash = session[:idhash]
122
- STDOUT.print "Deleting session: '#{session.id}'.\n" if @config[:debug]
123
- @ob.delete(session)
124
- @sessions.delete(idhash)
108
+ if session_data[:time_lastused].to_i > time_check
109
+ newsessions[session_hash] = session_data
110
+ session_not_ids << session_data[:dbobj].id
125
111
  end
126
-
127
-
128
- #Clean database weak references from the tables-module.
129
- @db.clean
130
-
131
- #Clean the object-handler.
132
- @ob.clean_all
133
-
134
- #Run garbage-collector.
135
- GC.start
136
-
137
- #Call various user-connected methods.
138
- @events.call(:on_clean) if @events
139
112
  end
113
+
114
+ @sessions = newsessions
115
+
116
+ STDOUT.print "Delete sessions...\n" if @config[:debug]
117
+ @ob.list(:Session, {"id_not" => session_not_ids, "date_lastused_below" => (Time.now - 5356800)}) do |session|
118
+ idhash = session[:idhash]
119
+ STDOUT.print "Deleting session: '#{session.id}'.\n" if @config[:debug]
120
+ @ob.delete(session)
121
+ @sessions.delete(idhash)
122
+ end
123
+
124
+ #Clean database weak references from the tables-module.
125
+ @db.clean
126
+
127
+ #Clean the object-handler.
128
+ @ob.clean_all
129
+
130
+ #Call various user-connected methods.
131
+ @events.call(:on_clean) if @events
140
132
  end
141
133
  end
@@ -93,10 +93,10 @@ class Knjappserver
93
93
  end
94
94
 
95
95
  html = "An error occurred.<br /><br />"
96
- html << "<b>#{e.class.name.html}: #{e.message.html}</b><br /><br />"
96
+ html << "<b>#{Knj::Web.html(e.class.name)}: #{Knj::Web.html(e.message)}</b><br /><br />"
97
97
 
98
98
  e.backtrace.each do |line|
99
- html << line.html + "<br />"
99
+ html << "#{Knj::Web.html(line)}<br />"
100
100
  end
101
101
 
102
102
  html << "<br /><b>Post:</b><br /><pre>#{Knj::Php.print_r(_post, true)}</pre>" if _post
@@ -112,7 +112,27 @@ class Knjappserver
112
112
  end
113
113
  end
114
114
 
115
+ #Converts fileuploads into strings so logging wont be crazy big.
116
+ def log_hash_safe(hash)
117
+ hash_obj = {}
118
+ hash.each do |key, val|
119
+ if val.is_a?(Knjappserver::Httpsession::Post_multipart::File_upload)
120
+ hash_obj[key] = "<Fileupload>"
121
+ elsif val.is_a?(Hash)
122
+ hash_obj[key] = self.log_hash_safe(val)
123
+ else
124
+ hash_obj[key] = val
125
+ end
126
+ end
127
+
128
+ return hash_obj
129
+ end
130
+
131
+ #Handles the hashes that should be logged.
115
132
  def log_hash_ins(hash_obj)
133
+ #Sort out fileuploads - it would simply bee too big to log this.
134
+ hash_obj = self.log_hash_safe(hash_obj)
135
+
116
136
  inserts_links = []
117
137
  ret = {}
118
138
  [:keys, :values].each do |type|
@@ -269,6 +289,18 @@ class Knjappserver
269
289
  end
270
290
  end
271
291
 
292
+ #Deletes all logs for an object.
293
+ def logs_delete(obj)
294
+ @ob.list(:Log_link, {"object_class" => obj.class.name, "object_id" => obj.id}) do |log_link|
295
+ log = log_link.log
296
+ @ob.delete(log_link)
297
+
298
+ if log
299
+ @ob.delete(log) if log.links("count" => true) <= 0
300
+ end
301
+ end
302
+ end
303
+
272
304
  #Returns the HTML for a table with logs from a given object.
273
305
  def logs_table(obj, args = {})
274
306
  links = @ob.list(:Log_link, {"object_class" => obj.class.name, "object_id" => obj.id, "limit" => 500, "orderby" => [["id", "desc"]]})
@@ -48,7 +48,7 @@ class Knjappserver
48
48
  begin
49
49
  #Use subprocessing to avoid the mail-framework (activesupport and so on, also possible memory leaks in those large frameworks).
50
50
  require "knj/process_meta"
51
- subproc = Knj::Process_meta.new("debug" => @debug, "debug_err" => true)
51
+ subproc = Knj::Process_meta.new("debug" => @debug, "debug_err" => true, "id" => "knjappserver_mailing")
52
52
  subproc.static("Object", "require", "rubygems")
53
53
  subproc.static("Object", "require", "mail")
54
54
  subproc.static("Object", "require", "#{@config[:knjrbfw_path]}knjrbfw")
@@ -49,7 +49,14 @@ class Knjappserver::Threadding_timeout
49
49
 
50
50
  begin
51
51
  @running = true
52
- @args[:block].call(*@args[:args])
52
+
53
+ if @args.key?(:timeout)
54
+ Timeout.timeout(@args[:timeout]) do
55
+ @args[:block].call(*@args[:args])
56
+ end
57
+ else
58
+ @args[:block].call(*@args[:args])
59
+ end
53
60
  ensure
54
61
  @running = false
55
62
  @kas.ob.db.free_thread if @kas.ob.db.opts[:threadsafe]
@@ -1,13 +1,6 @@
1
1
  class Knjappserver
2
2
  def trans(obj, key, args = {})
3
- if !args.key?(:locale)
4
- if _session[:locale]
5
- args[:locale] = _session[:locale]
6
- elsif _httpsession.data[:locale]
7
- args[:locale] = _httpsession.data[:locale]
8
- end
9
- end
10
-
3
+ args[:locale] = self.trans_locale if !args[:locale]
11
4
  trans_val = @translations.get(obj, key, args).to_s
12
5
 
13
6
  if trans_val.length <= 0
@@ -17,12 +10,24 @@ class Knjappserver
17
10
  return trans_val
18
11
  end
19
12
 
20
- def trans_set(obj, values, args = {})
21
- if !args[:locale]
22
- args[:locale] = _session[:locale] if _session[:locale]
23
- args[:locale] = _httpsession.data[:locale] if _httpsession.data[:locale] and !args[:locale]
13
+ def trans_locale(args = {})
14
+ if args.is_a?(Hash) and args[:locale]
15
+ return args[:locale]
16
+ elsif _session and _session[:locale]
17
+ return _session[:locale]
18
+ elsif _httpsession and _httpsession.data[:locale]
19
+ return _httpsession.data[:locale]
20
+ elsif Thread.current[:locale]
21
+ return Thread.current[:locale]
22
+ elsif @config[:locale_default]
23
+ return @config[:locale_default]
24
24
  end
25
25
 
26
+ raise "Could not figure out locale."
27
+ end
28
+
29
+ def trans_set(obj, values, args = {})
30
+ args[:locale] = self.trans_locale if !args[:locale]
26
31
  @translations.set(obj, values, args)
27
32
  end
28
33
 
@@ -25,6 +25,13 @@ class Knjappserver::Log < Knj::Datarow
25
25
  case key
26
26
  when "object_lookup"
27
27
  sql << " AND Log_link.id IS NOT NULL"
28
+ when "tag"
29
+ data_val = d.ob.get_by(:Log_data_value, {"value" => val})
30
+ if !data_val
31
+ sql << " AND false"
32
+ else
33
+ sql << " AND Log.tag_data_id = '#{d.db.esc(data_val.id)}'"
34
+ end
28
35
  else
29
36
  raise "Invalid key: #{key}."
30
37
  end
@@ -4,9 +4,15 @@ class Knjappserver::Log_link < Knj::Datarow
4
4
  ]
5
5
 
6
6
  def self.list(d, &block)
7
- sql = "SELECT * FROM #{table} WHERE 1=1"
7
+ if d.args["count"]
8
+ sql = "SELECT COUNT(id) AS count FROM #{table} WHERE 1=1"
9
+ count = true
10
+ d.args.delete("count")
11
+ else
12
+ sql = "SELECT * FROM #{table} WHERE 1=1"
13
+ end
8
14
 
9
- ret = list_helper(d)
15
+ ret = self.list_helper(d)
10
16
  d.args.each do |key, val|
11
17
  case key
12
18
  when "object_class"
@@ -19,6 +25,9 @@ class Knjappserver::Log_link < Knj::Datarow
19
25
  end
20
26
 
21
27
  sql << ret[:sql_where]
28
+
29
+ return d.db.query(sql).fetch[:count].to_i if count
30
+
22
31
  sql << ret[:sql_order]
23
32
  sql << ret[:sql_limit]
24
33
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knjappserver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.20
4
+ version: 0.0.21
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-16 00:00:00.000000000 +01:00
12
+ date: 2012-04-26 00:00:00.000000000 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: knjrbfw
17
- requirement: &12366780 !ruby/object:Gem::Requirement
17
+ requirement: &10828140 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *12366780
25
+ version_requirements: *10828140
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: erubis
28
- requirement: &12365600 !ruby/object:Gem::Requirement
28
+ requirement: &10827060 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *12365600
36
+ version_requirements: *10827060
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: mail
39
- requirement: &12365060 !ruby/object:Gem::Requirement
39
+ requirement: &10826360 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :runtime
46
46
  prerelease: false
47
- version_requirements: *12365060
47
+ version_requirements: *10826360
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: rspec
50
- requirement: &12364340 !ruby/object:Gem::Requirement
50
+ requirement: &10825400 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ~>
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: 2.3.0
56
56
  type: :development
57
57
  prerelease: false
58
- version_requirements: *12364340
58
+ version_requirements: *10825400
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: bundler
61
- requirement: &12363160 !ruby/object:Gem::Requirement
61
+ requirement: &10824260 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ~>
@@ -66,10 +66,10 @@ dependencies:
66
66
  version: 1.0.0
67
67
  type: :development
68
68
  prerelease: false
69
- version_requirements: *12363160
69
+ version_requirements: *10824260
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: jeweler
72
- requirement: &12362140 !ruby/object:Gem::Requirement
72
+ requirement: &10822320 !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
75
  - - ~>
@@ -77,10 +77,10 @@ dependencies:
77
77
  version: 1.6.3
78
78
  type: :development
79
79
  prerelease: false
80
- version_requirements: *12362140
80
+ version_requirements: *10822320
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: rcov
83
- requirement: &12352800 !ruby/object:Gem::Requirement
83
+ requirement: &10821260 !ruby/object:Gem::Requirement
84
84
  none: false
85
85
  requirements:
86
86
  - - ! '>='
@@ -88,10 +88,10 @@ dependencies:
88
88
  version: '0'
89
89
  type: :development
90
90
  prerelease: false
91
- version_requirements: *12352800
91
+ version_requirements: *10821260
92
92
  - !ruby/object:Gem::Dependency
93
93
  name: sqlite3
94
- requirement: &12352260 !ruby/object:Gem::Requirement
94
+ requirement: &10820300 !ruby/object:Gem::Requirement
95
95
  none: false
96
96
  requirements:
97
97
  - - ! '>='
@@ -99,10 +99,10 @@ dependencies:
99
99
  version: '0'
100
100
  type: :development
101
101
  prerelease: false
102
- version_requirements: *12352260
102
+ version_requirements: *10820300
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: json
105
- requirement: &12351520 !ruby/object:Gem::Requirement
105
+ requirement: &10819440 !ruby/object:Gem::Requirement
106
106
  none: false
107
107
  requirements:
108
108
  - - ! '>='
@@ -110,7 +110,7 @@ dependencies:
110
110
  version: '0'
111
111
  type: :development
112
112
  prerelease: false
113
- version_requirements: *12351520
113
+ version_requirements: *10819440
114
114
  description: Which supports a lot of undocumented stuff.
115
115
  email: k@spernj.org
116
116
  executables:
@@ -145,6 +145,7 @@ files:
145
145
  - lib/include/class_httpsession_contentgroup.rb
146
146
  - lib/include/class_httpsession_http_request.rb
147
147
  - lib/include/class_httpsession_http_response.rb
148
+ - lib/include/class_httpsession_page_environment.rb
148
149
  - lib/include/class_httpsession_post_multipart.rb
149
150
  - lib/include/class_knjappserver.rb
150
151
  - lib/include/class_knjappserver_cleaner.rb
@@ -207,7 +208,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
207
208
  version: '0'
208
209
  segments:
209
210
  - 0
210
- hash: 894779464839235539
211
+ hash: -1162266061337157012
211
212
  required_rubygems_version: !ruby/object:Gem::Requirement
212
213
  none: false
213
214
  requirements: