knjappserver 0.0.15 → 0.0.16
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/Gemfile +4 -2
- data/Gemfile.lock +24 -10
- data/README.rdoc +298 -1
- data/VERSION +1 -1
- data/bin/check_running.rb +2 -2
- data/knjappserver.gemspec +23 -5
- data/lib/files/database_schema.rb +124 -111
- data/lib/include/class_customio.rb +19 -5
- data/lib/include/class_erbhandler.rb +5 -22
- data/lib/include/class_httpresp.rb +66 -28
- data/lib/include/class_httpserver.rb +27 -14
- data/lib/include/class_httpsession.rb +161 -212
- data/lib/include/class_httpsession_contentgroup.rb +144 -0
- data/lib/include/class_httpsession_knjengine.rb +33 -68
- data/lib/include/class_httpsession_mongrel.rb +1 -1
- data/lib/include/class_httpsession_webrick.rb +1 -1
- data/lib/include/class_knjappserver.rb +105 -130
- data/lib/include/class_knjappserver_cleaner.rb +20 -13
- data/lib/include/class_knjappserver_cmdline.rb +44 -0
- data/lib/include/class_knjappserver_errors.rb +4 -1
- data/lib/include/class_knjappserver_logging.rb +48 -8
- data/lib/include/class_knjappserver_mailing.rb +36 -14
- data/lib/include/class_knjappserver_sessions.rb +78 -0
- data/lib/include/class_knjappserver_threadding.rb +18 -45
- data/lib/include/class_knjappserver_threadding_timeout.rb +78 -0
- data/lib/include/class_knjappserver_translations.rb +30 -0
- data/lib/include/class_knjappserver_web.rb +55 -3
- data/lib/include/class_log.rb +31 -3
- data/lib/include/class_log_access.rb +0 -15
- data/lib/include/class_log_data.rb +0 -15
- data/lib/include/class_log_data_link.rb +1 -14
- data/lib/include/class_log_data_value.rb +5 -17
- data/lib/include/class_session.rb +6 -18
- data/lib/include/magic_methods.rb +12 -14
- data/lib/pages/benchmark.rhtml +0 -0
- data/lib/pages/benchmark_print.rhtml +14 -0
- data/lib/pages/benchmark_simple.rhtml +3 -0
- data/lib/pages/benchmark_threadded_content.rhtml +21 -0
- data/lib/pages/spec.rhtml +26 -0
- data/lib/pages/spec_test_multiple_clients.rhtml +3 -0
- data/lib/pages/spec_threadded_content.rhtml +38 -0
- data/lib/scripts/benchmark.rb +65 -0
- data/spec/knjappserver_spec.rb +87 -43
- metadata +54 -20
| @@ -13,7 +13,8 @@ class Knjappserver | |
| 13 13 |  | 
| 14 14 | 
             
                    if @config.has_key?(:restart_when_used_memory) and !@should_restart
         | 
| 15 15 | 
             
                      mbs_used = (Knj::Php.memory_get_usage / 1024) / 1024
         | 
| 16 | 
            -
                       | 
| 16 | 
            +
                      STDOUT.print "Restart when over #{@config[:restart_when_used_memory]}mb\n" if @config[:debug]
         | 
| 17 | 
            +
                      STDOUT.print "Used: #{mbs_used}mb\n" if @config[:debug]
         | 
| 17 18 |  | 
| 18 19 | 
             
                      if mbs_used.to_i >= @config[:restart_when_used_memory].to_i
         | 
| 19 20 | 
             
                        STDOUT.print "Memory is over #{@config[:restart_when_used_memory]} - restarting.\n"
         | 
| @@ -25,7 +26,7 @@ class Knjappserver | |
| 25 26 | 
             
                      begin
         | 
| 26 27 | 
             
                        @should_restart_runnning = true
         | 
| 27 28 |  | 
| 28 | 
            -
                        #When we begin to restart it should go as fast as possible - so start by flushing out any emails waiting...
         | 
| 29 | 
            +
                        #When we begin to restart it should go as fast as possible - so start by flushing out any emails waiting so it goes faster the last time...
         | 
| 29 30 | 
             
                        STDOUT.print "Flushing mails.\n"
         | 
| 30 31 | 
             
                        self.mail_flush
         | 
| 31 32 |  | 
| @@ -89,19 +90,25 @@ class Knjappserver | |
| 89 90 | 
             
                  STDOUT.print "Cleaning sessions on appserver.\n" if @config[:debug]
         | 
| 90 91 |  | 
| 91 92 | 
             
                  self.paused_exec do
         | 
| 93 | 
            +
                    session_not_ids = []
         | 
| 92 94 | 
             
                    time_check = Time.now.to_i - 300
         | 
| 93 | 
            -
                     | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
                          session_data[:dbobj].flush
         | 
| 97 | 
            -
                          @ob.unset(session_data[:dbobj])
         | 
| 98 | 
            -
                          session_data[:hash].clear
         | 
| 99 | 
            -
                          ip_sessions.delete(session_hash)
         | 
| 100 | 
            -
                          session_data.clear
         | 
| 101 | 
            -
                        end
         | 
| 102 | 
            -
                      end
         | 
| 95 | 
            +
                    newsessions = {}
         | 
| 96 | 
            +
                    @sessions.each do |session_hash, session_data|
         | 
| 97 | 
            +
                      session_data[:dbobj].flush
         | 
| 103 98 |  | 
| 104 | 
            -
                       | 
| 99 | 
            +
                      if session_data[:time_lastused].to_i > time_check
         | 
| 100 | 
            +
                        newsessions[session_hash] = session_data
         | 
| 101 | 
            +
                        session_not_ids << session_data[:dbobj].id
         | 
| 102 | 
            +
                      end
         | 
| 103 | 
            +
                    end
         | 
| 104 | 
            +
                    
         | 
| 105 | 
            +
                    @sessions = newsessions
         | 
| 106 | 
            +
                    
         | 
| 107 | 
            +
                    STDOUT.print "Delete sessions...\n" if @config[:debug]
         | 
| 108 | 
            +
                    @ob.list(:Session, {"id_not" => session_not_ids, "date_lastused_below" => (Time.now - 5356800)}) do |session|
         | 
| 109 | 
            +
                      @ob.delete(session)
         | 
| 110 | 
            +
                      @sessions.delete(session[:idhash])
         | 
| 111 | 
            +
                      STDOUT.print "Deleted session: #{session.id}\n" if @config[:debug]
         | 
| 105 112 | 
             
                    end
         | 
| 106 113 | 
             
                  end
         | 
| 107 114 | 
             
                end
         | 
| @@ -0,0 +1,44 @@ | |
| 1 | 
            +
            class Knjappserver
         | 
| 2 | 
            +
              def initialize_cmdline
         | 
| 3 | 
            +
                @cmds = {}
         | 
| 4 | 
            +
                
         | 
| 5 | 
            +
                Knj::Thread.new do
         | 
| 6 | 
            +
                  line = $stdin.gets
         | 
| 7 | 
            +
                  
         | 
| 8 | 
            +
                  called = 0
         | 
| 9 | 
            +
                  @cmds.each do |key, connects|
         | 
| 10 | 
            +
                    data = {}
         | 
| 11 | 
            +
                    
         | 
| 12 | 
            +
                    if key.is_a?(Regexp)
         | 
| 13 | 
            +
                      if line.match(key)
         | 
| 14 | 
            +
                        connects.each do |conn|
         | 
| 15 | 
            +
                          called += 1
         | 
| 16 | 
            +
                          conn[:block].call(data)
         | 
| 17 | 
            +
                        end
         | 
| 18 | 
            +
                      end
         | 
| 19 | 
            +
                    else
         | 
| 20 | 
            +
                      raise "Unknown class for 'cmd_connect': '#{key.class.name}'."
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                  
         | 
| 24 | 
            +
                  if called == 0
         | 
| 25 | 
            +
                    print "Unknown command: '#{line.strip}'.\n"
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
                
         | 
| 29 | 
            +
                self.cmd_connect(/^\s*restart\s*$/i) do |data|
         | 
| 30 | 
            +
                  print "Restart will begin shortly.\n"
         | 
| 31 | 
            +
                  self.should_restart = true
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
                
         | 
| 34 | 
            +
                self.cmd_connect(/^\s*stop\s*$/i) do |data|
         | 
| 35 | 
            +
                  self.stop
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
              
         | 
| 39 | 
            +
              #Connects a proc to a specific command in the command-line (key should be a regex).
         | 
| 40 | 
            +
              def cmd_connect(cmd, &block)
         | 
| 41 | 
            +
                @cmds[cmd] = [] if !@cmds.key?(cmd)
         | 
| 42 | 
            +
                @cmds[cmd] << {:block => block}
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
            end
         | 
| @@ -18,6 +18,7 @@ class Knjappserver | |
| 18 18 | 
             
            		end
         | 
| 19 19 | 
             
            	end
         | 
| 20 20 |  | 
| 21 | 
            +
            	#Send error-emails based on error-emails-cache (cached so the same error isnt send out every time it occurrs to prevent spamming).
         | 
| 21 22 | 
             
            	def flush_error_emails
         | 
| 22 23 | 
             
            		@error_emails_pending_mutex.synchronize do
         | 
| 23 24 | 
             
            			send_time_older_than = Time.new.to_i - @error_emails_time
         | 
| @@ -65,6 +66,7 @@ class Knjappserver | |
| 65 66 | 
             
            		end
         | 
| 66 67 | 
             
            	end
         | 
| 67 68 |  | 
| 69 | 
            +
            	#Handels a given error. Sends to the admin-emails.
         | 
| 68 70 | 
             
            	def handle_error(e, args = {})
         | 
| 69 71 | 
             
            		@error_emails_pending_mutex.synchronize do
         | 
| 70 72 | 
             
            			if !Thread.current[:knjappserver] or !Thread.current[:knjappserver][:httpsession]
         | 
| @@ -82,7 +84,7 @@ class Knjappserver | |
| 82 84 | 
             
            					@error_emails_pending[backtrace_hash] = {
         | 
| 83 85 | 
             
            						:first_time => Time.new,
         | 
| 84 86 | 
             
            						:messages => [],
         | 
| 85 | 
            -
            						:subject => sprintf("Error @ %s", @config[:title]) + " (#{e.message})"
         | 
| 87 | 
            +
            						:subject => sprintf("Error @ %s", @config[:title]) + " (#{Knj::Strings.shorten(e.message, 100)})"
         | 
| 86 88 | 
             
            					}
         | 
| 87 89 | 
             
            				end
         | 
| 88 90 |  | 
| @@ -107,6 +109,7 @@ class Knjappserver | |
| 107 109 | 
             
            		end
         | 
| 108 110 | 
             
            	end
         | 
| 109 111 |  | 
| 112 | 
            +
            	#Takes a proc and executes it. On error it alerts the error-message with javascript to the server, sends a javascript back and exits.
         | 
| 110 113 | 
             
            	def on_error_go_back(&block)
         | 
| 111 114 | 
             
                begin
         | 
| 112 115 | 
             
                  block.call
         | 
| @@ -12,6 +12,7 @@ class Knjappserver | |
| 12 12 | 
             
            		end
         | 
| 13 13 | 
             
            	end
         | 
| 14 14 |  | 
| 15 | 
            +
            	#Writes all queued access-logs to the database.
         | 
| 15 16 | 
             
            	def flush_access_log
         | 
| 16 17 | 
             
            		@logs_mutex.synchronize do
         | 
| 17 18 | 
             
            			ins_arr = @logs_access_pending
         | 
| @@ -155,8 +156,12 @@ class Knjappserver | |
| 155 156 | 
             
            	end
         | 
| 156 157 |  | 
| 157 158 | 
             
            	def log_data_hash(keys_id, values_id)
         | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 159 | 
            +
                begin
         | 
| 160 | 
            +
                  keys_data_obj = @ob.get(:Log_data, keys_id)
         | 
| 161 | 
            +
                  values_data_obj = @ob.get(:Log_data, values_id)
         | 
| 162 | 
            +
                rescue Knj::Errors::NotFound
         | 
| 163 | 
            +
                  return {}
         | 
| 164 | 
            +
                end
         | 
| 160 165 |  | 
| 161 166 | 
             
            		sql = "
         | 
| 162 167 | 
             
            			SELECT
         | 
| @@ -181,20 +186,20 @@ class Knjappserver | |
| 181 186 | 
             
            		"
         | 
| 182 187 |  | 
| 183 188 | 
             
            		hash = {}
         | 
| 184 | 
            -
            		 | 
| 185 | 
            -
            		while d_hash = q_hash.fetch
         | 
| 189 | 
            +
            		db.q(sql) do |d_hash|
         | 
| 186 190 | 
             
            			hash[d_hash[:key].to_sym] = d_hash[:value]
         | 
| 187 191 | 
             
            		end
         | 
| 188 192 |  | 
| 189 193 | 
             
            		return hash
         | 
| 190 194 | 
             
            	end
         | 
| 191 195 |  | 
| 192 | 
            -
            	 | 
| 196 | 
            +
            	#Writes a custom log to the database.
         | 
| 197 | 
            +
            	def log(msg, objs, args = {})
         | 
| 193 198 | 
             
            		@logs_mutex.synchronize do
         | 
| 194 199 | 
             
            			objs = [objs] if !objs.is_a?(Array)
         | 
| 195 200 | 
             
            			log_value_id = @ob.static(:Log_data_value, :force_id, msg)
         | 
| 196 201 | 
             
            			ins_data = {
         | 
| 197 | 
            -
            				:date_saved => Time. | 
| 202 | 
            +
            				:date_saved => Time.now,
         | 
| 198 203 | 
             
            				:text_value_id => log_value_id
         | 
| 199 204 | 
             
            			}
         | 
| 200 205 |  | 
| @@ -210,6 +215,28 @@ class Knjappserver | |
| 210 215 | 
             
            				ins_data[:post_values_data_id] = post_hash[:values_data_id]
         | 
| 211 216 | 
             
            			end
         | 
| 212 217 |  | 
| 218 | 
            +
            			cookie_hash = log_hash_ins(_cookie) if _cookie
         | 
| 219 | 
            +
            			if cookie_hash
         | 
| 220 | 
            +
                    ins_data[:post_keys_data_id] = cookie_hash[:keys_data_id]
         | 
| 221 | 
            +
                    ins_data[:post_values_data_id] = cookie_hash[:values_data_id]
         | 
| 222 | 
            +
            			end
         | 
| 223 | 
            +
            			
         | 
| 224 | 
            +
            			meta_hash = log_hash_ins(_meta) if _meta
         | 
| 225 | 
            +
                  if cookie_hash
         | 
| 226 | 
            +
                    ins_data[:meta_keys_data_id] = meta_hash[:keys_data_id]
         | 
| 227 | 
            +
                    ins_data[:meta_values_data_id] = meta_hash[:values_data_id]
         | 
| 228 | 
            +
                  end
         | 
| 229 | 
            +
                  
         | 
| 230 | 
            +
                  if args[:tag]
         | 
| 231 | 
            +
                    tag_value_id = @ob.static(:Log_data_value, :force_id, args[:tag])
         | 
| 232 | 
            +
                    ins_data[:tag_data_id] = tag_value_id
         | 
| 233 | 
            +
                  end
         | 
| 234 | 
            +
                  
         | 
| 235 | 
            +
                  if args[:comment]
         | 
| 236 | 
            +
                    comment_value_id = @ob.static(:Log_data_value, :force_id, args[:comment])
         | 
| 237 | 
            +
                    ins_data[:comment_data_id] = comment_value_id
         | 
| 238 | 
            +
                  end
         | 
| 239 | 
            +
            			
         | 
| 213 240 | 
             
            			log_id = @db.insert(:Log, ins_data, {:return_id => true})
         | 
| 214 241 |  | 
| 215 242 | 
             
            			log_links = []
         | 
| @@ -227,6 +254,7 @@ class Knjappserver | |
| 227 254 | 
             
            		end
         | 
| 228 255 | 
             
            	end
         | 
| 229 256 |  | 
| 257 | 
            +
            	#Returns the HTML for a table with logs from a given object.
         | 
| 230 258 | 
             
            	def logs_table(obj, args = {})
         | 
| 231 259 | 
             
            		links = @ob.list(:Log_link, {"object_class" => obj.class.name, "object_id" => obj.id, "limit" => 500, "orderby" => [["id", "desc"]]})
         | 
| 232 260 |  | 
| @@ -235,8 +263,10 @@ class Knjappserver | |
| 235 263 | 
             
            		html += "<tr>"
         | 
| 236 264 | 
             
            		html += "<th>ID</th>"
         | 
| 237 265 | 
             
            		html += "<th>Message</th>"
         | 
| 238 | 
            -
            		html += "<th>Date & time</th>"
         | 
| 266 | 
            +
            		html += "<th style=\"width: 130px;\">Date & time</th>"
         | 
| 267 | 
            +
            		html += "<th>Tag</th>"
         | 
| 239 268 | 
             
            		html += "<th>Objects</th>" if args[:ob_use]
         | 
| 269 | 
            +
            		html += "<th>IP</th>" if args[:show_ip]
         | 
| 240 270 | 
             
            		html += "</tr>"
         | 
| 241 271 | 
             
            		html += "</thead>"
         | 
| 242 272 | 
             
            		html += "<tbody>"
         | 
| @@ -254,7 +284,17 @@ class Knjappserver | |
| 254 284 | 
             
            			html += "<td>#{log.id}</td>"
         | 
| 255 285 | 
             
            			html += "<td>#{first_line.html}</td>"
         | 
| 256 286 | 
             
            			html += "<td>#{log.date_saved_str}</td>"
         | 
| 257 | 
            -
            			html += "<td>#{log. | 
| 287 | 
            +
            			html += "<td>#{log.tag.html}</td>"
         | 
| 288 | 
            +
            			
         | 
| 289 | 
            +
            			if args[:ob_use]
         | 
| 290 | 
            +
                    begin
         | 
| 291 | 
            +
                      html += "<td>#{log.objects_html(args[:ob_use])}</td>"
         | 
| 292 | 
            +
                    rescue => e
         | 
| 293 | 
            +
                      html += "<td>#{e.message.html}</td>"
         | 
| 294 | 
            +
                    end
         | 
| 295 | 
            +
                  end
         | 
| 296 | 
            +
                  
         | 
| 297 | 
            +
            			html += "<td>#{log.ip}</td>" if args[:show_ip]
         | 
| 258 298 | 
             
            			html += "</tr>"
         | 
| 259 299 | 
             
            		end
         | 
| 260 300 |  | 
| @@ -2,6 +2,9 @@ class Knjappserver | |
| 2 2 | 
             
              attr_reader :mails_waiting
         | 
| 3 3 |  | 
| 4 4 | 
             
            	def initialize_mailing
         | 
| 5 | 
            +
                STDOUT.print "Loading mail.\n" if @config[:debug]
         | 
| 6 | 
            +
                require "mail" if !@config.has_key?(:mail_require) or @config[:mail_require]
         | 
| 7 | 
            +
                
         | 
| 5 8 | 
             
            		@mails_waiting = []
         | 
| 6 9 | 
             
            		@mails_mutex = Mutex.new
         | 
| 7 10 | 
             
            		@mails_queue_mutex = Mutex.new
         | 
| @@ -10,6 +13,7 @@ class Knjappserver | |
| 10 13 | 
             
            		end
         | 
| 11 14 | 
             
            	end
         | 
| 12 15 |  | 
| 16 | 
            +
            	#Queue a mail for sending. Possible keys are: :subject, :from, :to, :text and :html.
         | 
| 13 17 | 
             
            	def mail(mail_args)
         | 
| 14 18 | 
             
            		@mails_queue_mutex.synchronize do
         | 
| 15 19 | 
             
            			count_wait = 0
         | 
| @@ -23,11 +27,13 @@ class Knjappserver | |
| 23 27 | 
             
            			end
         | 
| 24 28 |  | 
| 25 29 | 
             
            			mailobj = Knjappserver::Mail.new({:kas => self, :errors => {}, :status => :waiting}.merge(mail_args))
         | 
| 30 | 
            +
            			STDOUT.print "Added mail '#{mailobj.__id__}' to the mail-send-queue.\n" if debug
         | 
| 26 31 | 
             
            			@mails_waiting << mailobj
         | 
| 27 32 | 
             
            			return mailobj
         | 
| 28 33 | 
             
            		end
         | 
| 29 34 | 
             
            	end
         | 
| 30 35 |  | 
| 36 | 
            +
            	#Sends all queued mails to the respective servers, if we are online.
         | 
| 31 37 | 
             
            	def mail_flush
         | 
| 32 38 | 
             
            		@mails_mutex.synchronize do
         | 
| 33 39 | 
             
            			return false if @mails_waiting.length <= 0
         | 
| @@ -55,41 +61,57 @@ class Knjappserver | |
| 55 61 | 
             
            		end
         | 
| 56 62 | 
             
            	end
         | 
| 57 63 |  | 
| 64 | 
            +
            	#This class represents the queued mails.
         | 
| 58 65 | 
             
            	class Mail
         | 
| 59 66 | 
             
            		def initialize(args)
         | 
| 60 67 | 
             
            			@args = args
         | 
| 61 68 |  | 
| 62 69 | 
             
            			raise "No knjappserver-object was given (as :kas)." if !@args[:kas].is_a?(Knjappserver)
         | 
| 63 70 | 
             
            			raise "No :to was given." if !@args[:to]
         | 
| 64 | 
            -
             | 
| 71 | 
            +
                  raise "No content was given (:html or :text)." if !@args[:html] and !@args[:text]
         | 
| 65 72 | 
             
            		end
         | 
| 66 73 |  | 
| 74 | 
            +
            		#Returns a key from the arguments.
         | 
| 67 75 | 
             
            		def [](key)
         | 
| 68 76 | 
             
            			return @args[key]
         | 
| 69 77 | 
             
            		end
         | 
| 70 78 |  | 
| 79 | 
            +
            		#Sends the email to the receiver.
         | 
| 71 80 | 
             
            		def send
         | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 81 | 
            +
                  STDOUT.print "Sending mail '#{__id__}'.\n" if @args[:kas].debug
         | 
| 82 | 
            +
                  
         | 
| 83 | 
            +
                  begin
         | 
| 84 | 
            +
                    mail = Knj::Mailobj.new(@args[:kas].config[:smtp_args])
         | 
| 85 | 
            +
                    mail.to = @args[:to]
         | 
| 86 | 
            +
                    mail.subject = @args[:subject] if @args[:subject]
         | 
| 87 | 
            +
                    mail.html = @args[:html] if @args[:html]
         | 
| 88 | 
            +
                    mail.text = @args[:text] if @args[:text]
         | 
| 89 | 
            +
                    
         | 
| 90 | 
            +
                    if @args[:from]
         | 
| 91 | 
            +
                      mail.from = @args[:from]
         | 
| 92 | 
            +
                    elsif @args[:kas].config[:error_report_from]
         | 
| 93 | 
            +
                      mail.from = @args[:kas].config[:error_report_from]
         | 
| 94 | 
            +
                    else
         | 
| 95 | 
            +
                      raise "Dont know where to take the 'from'-paramter from - none given in appserver config or mail-method-arguments?"
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
                    
         | 
| 84 98 | 
             
            				mail.send
         | 
| 85 99 | 
             
            				@args[:status] = :sent
         | 
| 100 | 
            +
            				STDOUT.print "Sent email #{self.__id__}\n" if @args[:kas].debug
         | 
| 86 101 | 
             
            				return true
         | 
| 87 | 
            -
            			rescue  | 
| 102 | 
            +
            			rescue Exception => e
         | 
| 103 | 
            +
                    if @args[:kas].debug
         | 
| 104 | 
            +
                      STDOUT.print "Could not send email.\n"
         | 
| 105 | 
            +
                      STDOUT.puts e.inspect
         | 
| 106 | 
            +
                      STDOUT.puts e.backtrace
         | 
| 107 | 
            +
                    end
         | 
| 108 | 
            +
                    
         | 
| 88 109 | 
             
            				@args[:errors][e.class.name] = {:count => 0} if !@args[:errors].has_key?(e.class.name)
         | 
| 89 110 | 
             
            				@args[:errors][e.class.name][:count] += 1
         | 
| 90 111 | 
             
            				raise e if @args[:errors][e.class.name][:count] >= 5
         | 
| 91 112 | 
             
            				@args[:status] = :error
         | 
| 92 113 | 
             
            				@args[:error] = e
         | 
| 114 | 
            +
            				
         | 
| 93 115 | 
             
            				return false
         | 
| 94 116 | 
             
            			end
         | 
| 95 117 | 
             
            		end
         | 
| @@ -0,0 +1,78 @@ | |
| 1 | 
            +
            class Knjappserver
         | 
| 2 | 
            +
              def initialize_sessions
         | 
| 3 | 
            +
                @sessions = {}
         | 
| 4 | 
            +
              end
         | 
| 5 | 
            +
              
         | 
| 6 | 
            +
              #Returns or adds session based on idhash and meta-data.
         | 
| 7 | 
            +
              def session_fromid(args)
         | 
| 8 | 
            +
                ip = args[:ip].to_s
         | 
| 9 | 
            +
                idhash = args[:idhash].to_s
         | 
| 10 | 
            +
                ip = "bot" if idhash == "bot"
         | 
| 11 | 
            +
                
         | 
| 12 | 
            +
                if !@sessions.key?(idhash)
         | 
| 13 | 
            +
                  session = @ob.get_by(:Session, {"idhash" => idhash})
         | 
| 14 | 
            +
                  if !session
         | 
| 15 | 
            +
                    session = @ob.add(:Session, {
         | 
| 16 | 
            +
                      :idhash => idhash,
         | 
| 17 | 
            +
                      :user_agent => args[:meta]["HTTP_USER_AGENT"],
         | 
| 18 | 
            +
                      :ip => ip
         | 
| 19 | 
            +
                    })
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                  
         | 
| 22 | 
            +
                  @sessions[idhash] = {
         | 
| 23 | 
            +
                    :dbobj => session,
         | 
| 24 | 
            +
                    :hash => {}
         | 
| 25 | 
            +
                  }
         | 
| 26 | 
            +
                else
         | 
| 27 | 
            +
                  session = @sessions[idhash][:dbobj]
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
                
         | 
| 30 | 
            +
            =begin
         | 
| 31 | 
            +
                if ip != "bot"
         | 
| 32 | 
            +
                  if session[:user_agent] != args[:meta]["HTTP_USER_AGENT"]
         | 
| 33 | 
            +
                    STDOUT.print "Invalid user-agent!\n"
         | 
| 34 | 
            +
                    STDOUT.print Knj::Php.print_r(session, true)
         | 
| 35 | 
            +
                    
         | 
| 36 | 
            +
                    raise Knj::Errors::InvalidData, "Invalid user-agent."
         | 
| 37 | 
            +
                  elsif !session.remember? and ip.to_s != session[:ip].to_s
         | 
| 38 | 
            +
                    STDOUT.print "Invalid IP!\n"
         | 
| 39 | 
            +
                    STDOUT.print Knj::Php.print_r(session, true)
         | 
| 40 | 
            +
                    
         | 
| 41 | 
            +
                    raise Knj::Errors::InvalidData, "Invalid IP."
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
            =end
         | 
| 45 | 
            +
                
         | 
| 46 | 
            +
                @sessions[idhash][:time_lastused] = Time.now
         | 
| 47 | 
            +
                return @sessions[idhash]
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
              
         | 
| 50 | 
            +
              #Generates a new session-ID by the meta data.
         | 
| 51 | 
            +
              def session_generate_id(args)
         | 
| 52 | 
            +
                meta = args[:meta]
         | 
| 53 | 
            +
                return Digest::MD5.hexdigest("#{Time.now.to_f}_#{meta["HTTP_HOST"]}_#{meta["REMOTE_HOST"]}_#{meta["HTTP_X_FORWARDED_SERVER"]}_#{meta["HTTP_X_FORWARDED_FOR"]}_#{meta["HTTP_X_FORWARDED_HOST"]}_#{meta["REMOTE_ADDR"]}_#{meta["HTTP_USER_AGENT"]}")
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
              
         | 
| 56 | 
            +
              #Will make the session rememberable for a year. IP wont be checked any more.
         | 
| 57 | 
            +
              def session_remember
         | 
| 58 | 
            +
                session = _httpsession.session
         | 
| 59 | 
            +
                session[:remember] = 1
         | 
| 60 | 
            +
                
         | 
| 61 | 
            +
                self.cookie(
         | 
| 62 | 
            +
                  "name" => "KnjappserverSession",
         | 
| 63 | 
            +
                  "value" => _httpsession.session_id,
         | 
| 64 | 
            +
                  "path" => "/",
         | 
| 65 | 
            +
                  "expires" => Time.now + 32140800 #add around 12 months
         | 
| 66 | 
            +
                )
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
              
         | 
| 69 | 
            +
              #Writes all session-data to the database (normally it is cached in memory and not updated on change).
         | 
| 70 | 
            +
              def sessions_flush
         | 
| 71 | 
            +
                if @sessions
         | 
| 72 | 
            +
                  @sessions.each do |session_hash, session_data|
         | 
| 73 | 
            +
                    STDOUT.print "Flushing session: #{session_data[:dbobj].id}\n" if @debug
         | 
| 74 | 
            +
                    session_data[:dbobj].flush
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
            end
         | 
| @@ -10,6 +10,13 @@ class Knjappserver | |
| 10 10 | 
             
            		end
         | 
| 11 11 | 
             
            	end
         | 
| 12 12 |  | 
| 13 | 
            +
            	#Inits the thread so it has access to the appserver and various magic methods can be used.
         | 
| 14 | 
            +
            	def thread_init(thread)
         | 
| 15 | 
            +
                thread[:knjappserver] = {} if !thread[:knjappserver]
         | 
| 16 | 
            +
                thread[:knjappserver][:kas] = self
         | 
| 17 | 
            +
            	end
         | 
| 18 | 
            +
            	
         | 
| 19 | 
            +
            	#Spawns a new thread with access to magic methods, _db-method and various other stuff in the appserver.
         | 
| 13 20 | 
             
            	def thread(args = {})
         | 
| 14 21 | 
             
            		raise "No block given." if !block_given?
         | 
| 15 22 | 
             
            		args[:args] = [] if !args[:args]
         | 
| @@ -34,53 +41,19 @@ class Knjappserver | |
| 34 41 | 
             
            		end
         | 
| 35 42 | 
             
            	end
         | 
| 36 43 |  | 
| 37 | 
            -
            	 | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
            						
         | 
| 48 | 
            -
            						while Thread.current[:knjappserver_timeout] > 0
         | 
| 49 | 
            -
            							Thread.current[:knjappserver_timeout] += -1
         | 
| 50 | 
            -
            							break if @should_restart
         | 
| 51 | 
            -
            							sleep 1
         | 
| 52 | 
            -
            						end
         | 
| 53 | 
            -
            					else
         | 
| 54 | 
            -
            						sleep args[:time]
         | 
| 55 | 
            -
            					end
         | 
| 56 | 
            -
            					
         | 
| 57 | 
            -
            					break if @should_restart
         | 
| 58 | 
            -
            					
         | 
| 59 | 
            -
            					@threadpool.run do
         | 
| 60 | 
            -
                        @ob.db.get_and_register_thread if @ob.db.opts[:threadsafe]
         | 
| 61 | 
            -
                        @db_handler.get_and_register_thread if @db_handler.opts[:threadsafe]
         | 
| 62 | 
            -
                        
         | 
| 63 | 
            -
                        Thread.current[:knjappserver] = {
         | 
| 64 | 
            -
                          :kas => self,
         | 
| 65 | 
            -
                          :db => @db_handler
         | 
| 66 | 
            -
                        }
         | 
| 67 | 
            -
            						
         | 
| 68 | 
            -
            						begin
         | 
| 69 | 
            -
            							yield(*args[:args])
         | 
| 70 | 
            -
            						ensure
         | 
| 71 | 
            -
            							@ob.db.free_thread if @ob.db.opts[:threadsafe]
         | 
| 72 | 
            -
            							@db_handler.free_thread if @db_handler.opts[:threadsafe]
         | 
| 73 | 
            -
            						end
         | 
| 74 | 
            -
            					end
         | 
| 75 | 
            -
            				rescue Exception => e
         | 
| 76 | 
            -
            					handle_error(e)
         | 
| 77 | 
            -
            				end
         | 
| 78 | 
            -
            			end
         | 
| 79 | 
            -
            		end
         | 
| 80 | 
            -
            		
         | 
| 81 | 
            -
            		return thread
         | 
| 44 | 
            +
            	#Runs a proc every number of seconds.
         | 
| 45 | 
            +
            	def timeout(args = {}, &block)
         | 
| 46 | 
            +
                to = Knjappserver::Threadding_timeout.new(
         | 
| 47 | 
            +
                  :kas => self,
         | 
| 48 | 
            +
                  :block => block,
         | 
| 49 | 
            +
                  :args => args
         | 
| 50 | 
            +
                )
         | 
| 51 | 
            +
                to.start
         | 
| 52 | 
            +
                
         | 
| 53 | 
            +
                return to
         | 
| 82 54 | 
             
            	end
         | 
| 83 55 |  | 
| 56 | 
            +
            	#Spawns a thread to run the given proc and add the output of that block in the correct order to the HTML.
         | 
| 84 57 | 
             
            	def threadded_content(&block)
         | 
| 85 58 | 
             
                _httpsession.threadded_content(block)
         | 
| 86 59 | 
             
            	end
         |