<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>config/initializers/delete_cache.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -4,11 +4,13 @@ class BruteforceController &lt; ApplicationController
   
   # Start brute force
   def index
+    session[:solved] = nil
     render :action =&gt; 'pending' and return if solved? and !demo_mode
   end
 
   # Get client JavaScript for the HTML client
   def client
+    session[:solved] = nil
     render :action =&gt; 'pending.js' and return if solved? and !demo_mode
     if demo_mode
       @options = default_client_options 1     
@@ -33,19 +35,20 @@ class BruteforceController &lt; ApplicationController
   
   # Hand in a response interval
   def report
-    render :text =&gt; 'Currently we don\'t keep track of reports. Thank you!' and return unless normal_mode
-    render :text =&gt; 'Somebody already found the solution.', :status =&gt; 406 and return if solved? and !demo_mode
+    render :js =&gt; '// Currently we don\'t keep track of reports. Thank you!' and return unless normal_mode
+    render :js =&gt; &quot;// Sorry, but the solution was already handed in by somebody else!\n// Let's refresh your browser (twice, to go sure ;).\nwindow.location.reload();\nwindow.location.reload();&quot; and return if solved? and !demo_mode
     Attack.save_report params[:client], params[:counter]
-    render :text =&gt; 'Thank you for your report!'
+    render :js =&gt; '// Thank you for your report!'
   end
   
   # Hand in a solution
   def solution
-    if params[:password].to_s == session[:settings].secret
-      if solved? and !demo_mode
+    if params[:password].to_s.hashed == session[:settings].sha
+      if solved? and !demo_mode and solved_by? != params[:client].to_s
         render :action =&gt; 'alreadysolved' and return
       else
-        solve! params[:password].to_s unless demo_mode
+        session[:solved] = params[:password].to_s
+        solve!(params[:password].to_s, params[:client].to_s) unless demo_mode
         render :action =&gt; 'congratulations' and return
       end
     end
@@ -60,8 +63,9 @@ class BruteforceController &lt; ApplicationController
     end
     session[:updown] = 'DESC' unless session[:updown].to_s == 'ASC' or session[:updown].to_s == 'DESC'
     @attacks = Attack.find(:all, :order =&gt; order + ' ' + session[:updown], :limit =&gt; 400)
-    @progress = Attack.find(:all, :conditions =&gt; [&quot;response&quot;], :order =&gt; 'xoffset ASC', :limit =&gt; 400)
     @realm = session[:settings].characters.size.to_i ** session[:settings].max.to_i
+    @solution = what_is_the_solution?
+    @client = solved_by?
     render :layout =&gt; 'status'
   end
   
@@ -88,7 +92,7 @@ class BruteforceController &lt; ApplicationController
         session[:settings] = session[:settings].save
         flash[:notice] = 'Settings saved.'
       else
-        flash[:error] = 'Please provide a valid password according to the selected &lt;b&gt;&lt;u&gt;valid characters&lt;/u&gt;&lt;/b&gt; and &lt;b&gt;&lt;u&gt;length&lt;/u&gt;&lt;/b&gt;.'
+        flash[:error] = 'Please provide a valid password according to the &lt;b&gt;&lt;u&gt;valid characters&lt;/u&gt;&lt;/b&gt; and &lt;b&gt;&lt;u&gt;length&lt;/u&gt;&lt;/b&gt;.'
       end
     end
     @realm = session[:settings].characters.size ** session[:settings].max</diff>
      <filename>app/controllers/bruteforce_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,22 @@
 module ApplicationHelper
 
+  def solved_item(left=0, width=0, offset=0, password='')
+    return if left &lt; 1 and width &lt; 1
+    result = ''
+    result += '&lt;div style=&quot;left:' + (left - 20).to_s + 'px; position:absolute; top:13px; color:red; font-size:13px; background-color:white; z-index:10000;&quot;&gt;' + offset.to_delimiter_s + '&lt;/div&gt;'
+    result += '&lt;div style=&quot;left:' + left.to_s + 'px; width:' + width.to_s + 'px; position:absolute; top:31px; height:30px; background-color: red; z-index:10000;&quot;&gt;&lt;/div&gt;'
+    result += '&lt;div style=&quot;left:' + (left - 20).to_s + 'px; position:absolute; top:63px; color:red; font-size:16px; background-color:white; z-index:10000;&quot;&gt;' + password.to_s + '&lt;/div&gt;'
+  end
+
+  def progress_item(left=0, width=0, offset=0)
+    return if left &lt; 1 and width &lt; 1
+    left = left + 31
+    width = width + 2
+    result = ''
+    result += '&lt;div style=&quot;left:' + (left - 10).to_s + 'px; position:absolute; top:19px; font-size:9px; background-color:white;&quot;&gt;' + offset.to_delimiter_s + '&lt;/div&gt;' if left &gt; 45 and left &lt; 950
+    result += '&lt;div style=&quot;left:' + left.to_s + 'px; width:' + width.to_s + 'px; position:absolute; top:31px; height:30px; background-color: yellow;&quot;&gt;&lt;/div&gt;'
+  end
+
   def other_updown
     session[:updown] == 'DESC' ? 'ASC' : 'DESC'
   end</diff>
      <filename>app/helpers/application_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,13 +2,14 @@ require 'yaml'
 
 class Settings
     
-  attr_accessor :secret, :mode, :max, :mix, :assumed, :character_space
+  attr_accessor :secret, :mode, :max, :mix, :assumed, :character_space, :sha
   attr_reader :characters
 
   def initialize
     @mode = 'demo'
     @character_space = 'alpha'
     @secret = 'sha'
+    @sha = @secret.hashed
     @max = 3
     @assumed = 100000
     @mix = 0
@@ -18,13 +19,14 @@ class Settings
   # Loading settings from settings.yml
   def read
     settings = YAML.load_file SETTINGS_FILE
-    [:secret, :mode, :max, :mix, :assumed, :character_space, :characters].each { |attribute| instance_eval &quot;@#{attribute.to_s} = settings.#{attribute.to_s}&quot; }
+    [:secret, :mode, :max, :mix, :assumed, :character_space, :characters, :sha].each { |attribute| instance_eval &quot;@#{attribute.to_s} = settings.#{attribute.to_s}&quot; }
     self
   end
   
   # Save settings object to file
   def save
     @characters = characters_array @mix
+    @sha = @secret.size == 64 ? @secret : @secret.hashed
     File.open(SETTINGS_FILE, 'w') { |file| file.write YAML::dump(self) }
     self
   end
@@ -41,21 +43,22 @@ class Settings
   
   def character_space_short
     case @character_space
-      when 'alpha' then 'a-z'
-      when 'alnum' then 'A-Z a-z 0-9'
-      when 'digit' then '0-9'
-      when 'ascii' then 'A-Z a-z 0-9 ' + SPECIAL_CHARS.join(' ')
+      when 'alpha' then HUMAN_ALPHA
+      when 'alnum' then HUMAN_ALNUM
+      when 'digit' then HUMAN_DIGIT
+      when 'ascii' then HUMAN_ASCII
     end
   end
   
   def valid_secret?
+    return true if @secret.size == 64 # Hashes are allowed as input value
     return false if @secret.empty? or @secret.size != @max
     case @character_space
-      when 'alpha' then !(@secret =~ /[^a-zA-Z]/)
-      when 'alnum' then !(@secret =~ /[^a-zA-Z0-9]/)
-      when 'digit' then !(@secret =~ /[^0-9]/)
-      when 'ascii' then !(@secret =~ Regexp.new('[^a-zA-Z0-9' + Regexp.escape(SPECIAL_CHARS.join) + ']'))
-    end    
+      when 'alpha' then !(@secret =~ REG_ALPHA)
+      when 'alnum' then !(@secret =~ REG_ALNUM)
+      when 'digit' then !(@secret =~ REG_DIGIT)
+      when 'ascii' then !(@secret =~ REG_ASCII)
+    end
   end
   
   # Reset Settings and save to file</diff>
      <filename>app/models/settings.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 &lt;h1 id=&quot;title&quot;&gt;Congratulations!!!&lt;/h1&gt;
 
-You found the password! It's &lt;div id=&quot;solution&quot;&gt;&lt;h2&gt;&lt;%= session[:settings].secret %&gt;&lt;/h2&gt;&lt;/div&gt;
+You found the password! It's &lt;div id=&quot;solution&quot;&gt;&lt;%= session[:settings].secret %&gt;&lt;/div&gt;
 
 Thank you for participating in our project.
 </diff>
      <filename>app/views/bruteforce/congratulations.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,14 @@
 &lt;h1&gt;s h a c k e r&lt;/h1&gt;
-&lt;span id=&quot;setup&quot;&gt;Connecting to server... &lt;/span&gt;&lt;span id=&quot;status_label&quot;&gt;&lt;/span&gt;&lt;span id=&quot;status&quot;&gt;&lt;/span&gt;
+&lt;span id=&quot;setup&quot;&gt;&lt;%= button_to_function &quot;Load  s h a c k e r  &gt;&quot;, &quot;window.location.reload()&quot;, :id =&gt; &quot;override_button&quot; %&gt;&lt;/span&gt;&lt;span id=&quot;status_label&quot;&gt;&lt;/span&gt;&lt;span id=&quot;status&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;%= button_to_function &quot;Start  s h a c k e r  &gt;&quot;, &quot;start_shacker()&quot;, :id =&gt; &quot;start_button&quot; %&gt;&lt;/span&gt;
+
+&lt;%= javascript_tag update_page { |page|
+  page['override_button'].hide
+  page['setup'].update 'Connecting to server... '
+}%&gt;
 
 &lt;%= javascript_tag remote_function(
-  :url =&gt; {:action =&gt; 'client.js', :only_path =&gt; false },
+  :url =&gt; {:action =&gt; 'client.js', :randomizer =&gt; random_string, :only_path =&gt; false },
   404 =&gt; &quot;$('setup').insert('#{escape_javascript &quot;HTTP Error 404.&quot;.to_error}')&quot;,
   :failure =&gt; &quot;$('setup').insert('#{escape_javascript &quot;failure.&lt;br/&gt;&lt;br/&gt;&quot;.to_error}Reason: HTTP Error' + request.status)&quot;,
   :success =&gt; &quot;$('setup').insert('#{escape_javascript &quot;success.&lt;br/&gt;&quot;.to_success}')&quot;
 )%&gt;
-</diff>
      <filename>app/views/bruteforce/index.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -7,10 +7,12 @@
     Currently there are no challenges.&lt;br&gt;
     Please hang on, until one comes up.
   &lt;/h2&gt;
-  (This page reloads automatically, just wait right here :)&lt;br&gt;&lt;br&gt;
+  &lt;span id=&quot;autoreloader&quot;&gt;(This page reloads automatically, just wait right here :)&lt;br&gt;&lt;br&gt;&lt;%= button_to_function &quot;Look for a challenge now!&quot;, 'window.location.reload()' %&gt;&lt;/span&gt;
+  &lt;br&gt;&lt;br&gt;
 &lt;/div&gt;
 
 &lt;%= javascript_tag update_page { |page|
+  #page['autoreloader'].update '(This page reloads automatically, just wait right here :)'
   page['container'].visual_effect(:highlight)
   page['busy'].appear
   page.delay(20) do</diff>
      <filename>app/views/bruteforce/pending.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@
   &lt;% f.inputs do %&gt;
     &lt;%= f.input :mode, :as =&gt; :select, :collection =&gt; MODES, :include_blank =&gt; false, :hint =&gt; 'This influences the scalability of our application on the server\'s side.', :required =&gt; false %&gt;
     &lt;%= f.input :character_space, :label =&gt; 'Chars', :as =&gt; :select, :collection =&gt; CHARACTER_SPACES, :include_blank =&gt; false, :hint =&gt; 'Which characters do we allow for the password?', :required =&gt; false %&gt;
-    &lt;%= f.input :secret, :hint =&gt; &quot;The password to be cracked. Currently allowed characters: &lt;br/&gt;&lt;tt&gt;#{session[:settings].character_space_short}&lt;/tt&gt;&quot;, :required =&gt; false %&gt;
+    &lt;%= f.input :secret, :hint =&gt; &quot;The password to be cracked. Currently allowed characters: &lt;br/&gt;&lt;tt&gt;#{session[:settings].character_space_short}&lt;/tt&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(&lt;b&gt;OR&lt;/b&gt; a SHA-256 hash value) #{&quot;&lt;br/&gt;Now: &lt;tt&gt;#{session[:settings].sha}&lt;/tt&gt;&quot; if session[:settings].secret != session[:settings].sha}&quot;, :required =&gt; false %&gt;
     &lt;%= f.input :max, :label =&gt; 'Length', :as =&gt; :select, :collection =&gt; Settings.maxes, :include_blank =&gt; false, :hint =&gt; &quot;The number of characters in the password that we will specifically assume. &lt;br/&gt;Current realm: #{number_with_delimiter @realm.to_i}&quot;, :required =&gt; false %&gt;
     &lt;%= f.input :assumed, :label =&gt; 'Respond', :hint =&gt; &quot;After how many tried password should the client send a response?&lt;br/&gt;The current password realm indicates that we need #{number_with_delimiter((@realm.to_i / session[:settings].assumed).to_positive_i)} clients.&quot;, :required =&gt; false %&gt;
     &lt;%= f.input :mix, :as =&gt; :select, :collection =&gt; Settings.mixes, :include_blank =&gt; false, :hint =&gt; &quot;Should we use a randomly sorted character space for brute force? This is the current order: &lt;br/&gt;&lt;tt&gt;#{session[:settings].characters.to_a.join(' ')}&lt;/tt&gt;&quot; , :required =&gt; false %&gt;</diff>
      <filename>app/views/bruteforce/settings.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -1,59 +1,77 @@
+&lt;div id=&quot;barlabel&quot;&gt;
+  &lt;div style=&quot;float:left&quot;&gt;1&lt;/div&gt;
+  &lt;div style=&quot;float:right&quot;&gt;&lt;%= @realm.to_delimiter_s %&gt;&lt;/div&gt;
+&lt;/div&gt;
+
+&lt;div id=&quot;bar&quot;&gt;&lt;/div&gt;
+
 &lt;div id=&quot;statistics&quot; style=&quot;clear:both&quot;&gt;
+  &lt;h1&gt;Statistics&lt;/h1&gt;
+
+  &lt;% if @attacks.size &gt; 0 %&gt;
+
+    &lt;div&gt;
+      &lt;div class=&quot;tcol attack id&quot;&gt;&lt;%= link_to 'ID', :sort =&gt; 'id', :updown =&gt; other_updown %&gt;&lt;/div&gt;
+      &lt;div class=&quot;tcol attack position&quot;&gt;&lt;%= link_to 'Pos.', :sort =&gt; 'position', :updown =&gt; other_updown %&gt;&lt;/div&gt;
+      &lt;div class=&quot;tcol attack offset&quot;&gt;&lt;%= link_to 'Offset', :sort =&gt; 'offset', :updown =&gt; other_updown %&gt;&lt;/div&gt;
+      &lt;div class=&quot;tcol attack chunk&quot;&gt;&lt;%= link_to 'Chunk', :sort =&gt; 'chunk', :updown =&gt; other_updown %&gt;&lt;/div&gt;
+      &lt;div class=&quot;tcol attack client&quot;&gt;&lt;%= link_to 'Client', :sort =&gt; 'client', :updown =&gt; other_updown %&gt;&lt;/div&gt;
+      &lt;div class=&quot;tcol attack created_at&quot;&gt;&lt;%= link_to 'Created', :sort =&gt; 'created_at', :updown =&gt; other_updown %&gt;&lt;/div&gt;
+      &lt;div class=&quot;tcol attack updated_at&quot;&gt;&lt;%= link_to 'Updated', :sort =&gt; 'updated_at', :updown =&gt; other_updown %&gt;&lt;/div&gt;
+      &lt;div class=&quot;tcol attack response&quot;&gt;&lt;%= link_to 'Response', :sort =&gt; 'response', :updown =&gt; other_updown %&gt;&lt;/div&gt;
+      &lt;div class=&quot;tcol attack timespan&quot;&gt;Elapsed time&lt;/div&gt;
+      &lt;div class=&quot;tcol attack timespan&quot;&gt;&lt;/div&gt;
+    &lt;/div&gt;
+
+    &lt;% for attack in @attacks do %&gt;
+
+      &lt;% if attack.client == @client %&gt;
+        &lt;% solution_offset = attack.response.nil? ? attack.xoffset.overlap(@realm).to_s + ' + X&amp;nbsp;' : (attack.xoffset + attack.response).overlap(@realm) %&gt;
+        &lt;%= solved_item((((attack.xoffset.to_i + attack.response.to_i).overlap(@realm) * 1000) / @realm).to_i + 31, 5, solution_offset, @solution) %&gt;
+      &lt;% end %&gt;
+        
+      &lt;% if attack.response and attack.response.to_i &lt;= @realm %&gt;
 
-  &lt;div id=&quot;barlabel&quot;&gt;
-    &lt;div style=&quot;float:left&quot;&gt;1&lt;/div&gt;
-    &lt;div style=&quot;float:right&quot;&gt;&lt;%= @realm.to_delimiter_s %&gt;&lt;/div&gt;
-  &lt;/div&gt;
-  &lt;div id=&quot;bar&quot;&gt;
-    &lt;% if @progress.size &gt; 0 %&gt;
-      &lt;% total_progress = 0 %&gt;
-      &lt;% for progress in @progress do %&gt;
-        &lt;% left = ((progress.xoffset.to_i * 10) / @realm).to_i %&gt;
-        &lt;% width = ((progress.response.to_i * 1000) / @realm).to_i %&gt;
-        &lt;%= image_tag 'progress.gif', :style =&gt; &quot;padding-left: #{left - total_progress}px; height: 27px; width: #{width}px; margin-left:40px;&quot; %&gt;
-        &lt;% total_progress += (left + width) %&gt;
+        &lt;%
+          left = ((attack.xoffset.to_i * 1000) / @realm).to_i
+          width = ((attack.response.to_i * 1000) / @realm).to_i
         
+          if (left + width) &lt; 1001
+            first_width = width.overlap 1000
+            second_width = 0
+          else
+            first_width = (1000 - left)
+            second_width = (width - first_width).overlap 1000
+          end
+        %&gt;
+      
+        &lt;%= progress_item left, first_width, attack.xoffset.to_i %&gt;
+        &lt;%= progress_item(1, second_width, attack.xoffset.to_i) unless second_width == 0 %&gt;
+
       &lt;% end %&gt;
-    &lt;% end %&gt;
-  &lt;/div&gt;
-  
-&lt;br&gt;
-&lt;h1&gt;Statistics&lt;/h1&gt;
-
-&lt;% if @attacks.size &gt; 0 %&gt;
-
-  &lt;div&gt;
-    &lt;div class=&quot;tcol attack id&quot;&gt;&lt;%= link_to 'ID', :sort =&gt; 'id', :updown =&gt; other_updown %&gt;&lt;/div&gt;
-    &lt;div class=&quot;tcol attack position&quot;&gt;&lt;%= link_to 'Pos.', :sort =&gt; 'position', :updown =&gt; other_updown %&gt;&lt;/div&gt;
-    &lt;div class=&quot;tcol attack offset&quot;&gt;&lt;%= link_to 'Offset', :sort =&gt; 'offset', :updown =&gt; other_updown %&gt;&lt;/div&gt;
-    &lt;div class=&quot;tcol attack chunk&quot;&gt;&lt;%= link_to 'Chunk', :sort =&gt; 'chunk', :updown =&gt; other_updown %&gt;&lt;/div&gt;
-    &lt;div class=&quot;tcol attack client&quot;&gt;&lt;%= link_to 'Client', :sort =&gt; 'client', :updown =&gt; other_updown %&gt;&lt;/div&gt;
-    &lt;div class=&quot;tcol attack created_at&quot;&gt;&lt;%= link_to 'Created', :sort =&gt; 'created_at', :updown =&gt; other_updown %&gt;&lt;/div&gt;
-    &lt;div class=&quot;tcol attack updated_at&quot;&gt;&lt;%= link_to 'Updated', :sort =&gt; 'updated_at', :updown =&gt; other_updown %&gt;&lt;/div&gt;
-    &lt;div class=&quot;tcol attack response&quot;&gt;&lt;%= link_to 'Response', :sort =&gt; 'response', :updown =&gt; other_updown %&gt;&lt;/div&gt;
-    &lt;div class=&quot;tcol attack timespan&quot;&gt;Elapsed time&lt;/div&gt;
-  &lt;/div&gt;
-
-  &lt;% for attack in @attacks do %&gt;
-
-    &lt;div id=&quot;&lt;%= attack.id %&gt;&quot; style=&quot;clear:both;&quot;&gt;
-      &lt;div class=&quot;attack id&quot;&gt;&lt;%= attack.id %&gt;&lt;/div&gt;
-      &lt;div class=&quot;attack position&quot;&gt;&lt;%= attack.position %&gt;&lt;/div&gt;
-      &lt;div class=&quot;attack offset&quot;&gt;&lt;%= attack.xoffset %&gt;&lt;/div&gt;
-      &lt;div class=&quot;attack chunk&quot;&gt;&lt;tt&gt;&lt;%= attack.chunk %&gt;&lt;/tt&gt;&lt;/div&gt;
-      &lt;div class=&quot;attack client&quot;&gt;&lt;%= attack.client %&gt;&lt;/div&gt;
-      &lt;div class=&quot;attack created_at&quot;&gt;&lt;%= attack.created_at.to_s(:db) %&gt;&lt;/div&gt;
-      &lt;div class=&quot;attack updated_at&quot;&gt;&lt;%= attack.updated_at.to_s(:db) %&gt;&lt;/div&gt;
-      &lt;div class=&quot;attack response&quot;&gt;&lt;%= attack.response %&gt;&lt;/div&gt;
-      &lt;div class=&quot;attack timespan&quot;&gt;&lt;%= attack.timespan.to_s + 's' if attack.timespan &gt; 0 %&gt;&lt;/div&gt;
-    &lt;/div&gt;
+
+      &lt;div id=&quot;&lt;%= attack.id %&gt;&quot; style=&quot;clear:both;&quot;&gt;
+        &lt;div class=&quot;attack id &lt;%= &quot;solution&quot; if attack.client == @client %&gt;&quot;&gt;&lt;%= attack.id %&gt;&lt;/div&gt;
+        &lt;div class=&quot;attack position &lt;%= &quot;solution&quot; if attack.client == @client %&gt;&quot;&gt;&lt;%= attack.position %&gt;&lt;/div&gt;
+        &lt;div class=&quot;attack offset &lt;%= &quot;solution&quot; if attack.client == @client %&gt;&quot;&gt;&lt;%= attack.xoffset %&gt;&lt;/div&gt;
+        &lt;div class=&quot;attack chunk &lt;%= &quot;solution&quot; if attack.client == @client %&gt;&quot;&gt;&lt;tt&gt;&lt;%= attack.chunk %&gt;&lt;/tt&gt;&lt;/div&gt;
+        &lt;div class=&quot;attack client &lt;%= &quot;solution&quot; if attack.client == @client %&gt;&quot;&gt;&lt;%= attack.client %&gt;&lt;/div&gt;
+        &lt;div class=&quot;attack created_at &lt;%= &quot;solution&quot; if attack.client == @client %&gt;&quot;&gt;&lt;%= attack.created_at.to_s(:db) %&gt;&lt;/div&gt;
+        &lt;div class=&quot;attack updated_at &lt;%= &quot;solution&quot; if attack.client == @client %&gt;&quot;&gt;&lt;%= attack.updated_at.to_s(:db) %&gt;&lt;/div&gt;
+        &lt;div class=&quot;attack response &lt;%= &quot;solution&quot; if attack.client == @client %&gt;&quot;&gt;&lt;%= attack.response %&gt;&lt;/div&gt;
+        &lt;div class=&quot;attack timespan &lt;%= &quot;solution&quot; if attack.client == @client %&gt;&quot;&gt;&lt;%= attack.timespan.to_s + 's' if attack.timespan &gt; 0 %&gt;&lt;/div&gt;
+        &lt;% if attack.client == @client %&gt;
+        &lt;div class=&quot;attack timespan solution solutioninrow&quot;&gt;
+          SOLUTION: &lt;%= @solution %&gt;
+        &lt;/div&gt;
+        &lt;% end %&gt;
+      &lt;/div&gt;
   
+    &lt;% end %&gt;
   &lt;% end %&gt;
-&lt;% end %&gt;
 
-&lt;div style=&quot;clear:both&quot;&gt;&lt;/div&gt;
+  &lt;div style=&quot;clear:both&quot;&gt;&lt;/div&gt;
   &lt;%= &quot;&lt;br&gt;Note that only 400 entries are shown.&quot; if @attacks.size &gt; 20 %&gt;
 &lt;/div&gt;
 
-&lt;%#= javascript_tag update_page { |page| page[&quot;statistics&quot;].visual_effect(:highlight) } %&gt;
-&lt;%= javascript_tag update_page { |page| page.delay(10) { page.reload } } %&gt;
\ No newline at end of file
+&lt;%= javascript_tag update_page { |page| page.delay(10) { page.reload } } if unsolved? %&gt;</diff>
      <filename>app/views/bruteforce/statistics.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
 
-&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;en&quot; lang=&quot;en&quot;&gt;
+&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;en&quot; lang=&quot;en&quot; onclick='window.location.reload();'&gt;
 &lt;head&gt;
   &lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html;charset=UTF-8&quot; /&gt;
   &lt;title&gt;s h a c k e r&lt;/title&gt;</diff>
      <filename>app/views/layouts/status.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,7 @@ config.whiny_nils = true
 # Show full error reports and disable caching
 config.action_controller.consider_all_requests_local = true
 config.action_view.debug_rjs                         = false
-config.action_controller.perform_caching             = true
+config.action_controller.perform_caching             = false
 
 # Don't care if the mailer can't send
 config.action_mailer.raise_delivery_errors = false
\ No newline at end of file</diff>
      <filename>config/environments/development.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,25 +1,43 @@
+# File paths
 SETTINGS_FILE = File.join Rails.root, 'config', 'settings.yml'
 SOLUTION_FILE = File.join Rails.root, 'tmp', 'solution.txt'
+CLIENT_FILE = File.join Rails.root, 'tmp', 'client.txt'
 
+# Characters
+ALPHA_DOWN = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
+ALPHA_CAP  = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
+ALPHA = ALPHA_DOWN + ALPHA_CAP
+SPECIAL_CHARS = [&quot;!&quot;, &quot;\&quot;&quot;, &quot;#&quot;, &quot;$&quot;, &quot;%&quot;, &quot;&amp;&quot;, &quot;'&quot;, &quot;(&quot;, &quot;)&quot;, &quot;*&quot;, &quot;+&quot;, &quot;, &quot;, &quot;-&quot;, &quot;.&quot;, &quot;/&quot;, &quot;=&quot;]
+DIGITS    = ['0','1','2','3','4','5','6','7','8','9']
+
+# Character modes
 CHARACTER_SPACES = [['Only alphabetical characters', 'alpha'],
                    ['Alphabetical characters and numbers', 'alnum'],
                    ['Only numbers', 'digit'],
                    ['Numbers, alphabetical and special characters', 'ascii']]
 
+# Regexps for character modes
+REG_ALPHA = /[^a-zA-Z]/
+REG_ALNUM = /[^a-zA-Z0-9]/
+REG_DIGIT = /[^0-9]/
+REG_ASCII = Regexp.new('[^a-zA-Z0-9' + Regexp.escape(SPECIAL_CHARS.join) + ']')
+
+# Same thing only human-readable
+HUMAN_ALPHA = 'a-z A-Z'
+HUMAN_ALNUM = 'A-Z a-z 0-9'
+HUMAN_DIGIT = '0-9'
+HUMAN_ASCII = 'A-Z a-z 0-9 ' + SPECIAL_CHARS.join(' ')
+
+# Application modes
 MODES = [['Normal mode', 'normal'],
         ['Demo mode (no solutions, no database)', 'demo'],
         ['Mass mode (no client response evaluation but highly scalable)', 'mass']]
 
-SPECIAL_CHARS = [&quot;!&quot;, &quot;\&quot;&quot;, &quot;#&quot;, &quot;$&quot;, &quot;%&quot;, &quot;&amp;&quot;, &quot;'&quot;, &quot;(&quot;, &quot;)&quot;, &quot;*&quot;, &quot;+&quot;, &quot;, &quot;, &quot;-&quot;, &quot;.&quot;, &quot;/&quot;, &quot;=&quot;]
-
-ALPHA_DOWN = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
-ALPHA_CAP  = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
-ALPHA = ALPHA_DOWN + ALPHA_CAP
-
-DIGITS    = ['0','1','2','3','4','5','6','7','8','9']
-
+# Javascript list for developers
 JAVASCRIPTS = ['prototype', 'effects', 'lowpro', 'helper', 'sha256', 'algorithm']
 
+# Client modes
 PRESETS = [['client', 'For our own HTML interface'], ['facebook', 'A low-duty version for Facebook profiles']]
 
-solve! # We don't want everything to begin unless via settings
\ No newline at end of file
+solve! # We do not want everything to begin unless via settings
+Attack.reset</diff>
      <filename>config/initializers/settings.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@ ActionController::Routing::Routes.draw do |map|
   map.connect 'facebook.js', :controller =&gt; 'bruteforce', :action =&gt; 'client', :option =&gt; 'facebook'
 
   map.connect 'solution/:client', :controller =&gt; 'bruteforce', :action =&gt; 'solution'
-  map.connect 'statistics/:sort/:updown', :controller =&gt; 'bruteforce', :action =&gt; 'status'
+  map.connect 'statistics/:sort/:updown', :controller =&gt; 'bruteforce', :action =&gt; 'statistics'
 
   map.connect ':action',         :controller =&gt; 'bruteforce'
   map.connect ':action.:format', :controller =&gt; 'bruteforce'</diff>
      <filename>config/routes.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,5 @@
 --- !ruby/object:Settings 
-assumed: 30000
+assumed: 100000
 character_space: alpha
 characters: 
 - a
@@ -56,5 +56,6 @@ characters:
 - Z
 max: 3
 mix: 0
-mode: normal
-secret: baa
+mode: demo
+secret: sha
+sha: d600474b1b8e50d3633c91c0cf1efc454b79c9624a43fd7de441ee71745726ab</diff>
      <filename>config/settings.yml</filename>
    </modified>
    <modified>
      <diff>@@ -5,12 +5,22 @@ class Object
   
   include ActionView::Helpers::NumberHelper
   
-  def solve!(password='')
+  def solve!(password='', client='', offset='')
     File.open(SOLUTION_FILE, 'w') { |f| f.write password.to_s }
+    File.open(CLIENT_FILE, 'w') { |f| f.write client.to_s }
   end
   
   def unsolve!
-    File.delete SOLUTION_FILE if solved?
+    File.delete SOLUTION_FILE if File.exists? SOLUTION_FILE
+    File.delete CLIENT_FILE if File.exists? CLIENT_FILE
+  end
+  
+  def what_is_the_solution?
+    File.new(SOLUTION_FILE).read if File.exists? SOLUTION_FILE
+  end
+  
+  def solved_by?
+    File.new(CLIENT_FILE).read if File.exists? CLIENT_FILE
   end
   
   def solved?</diff>
      <filename>lib/object.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,6 @@ counter = 0;
 
 // You may want to override this if you are creating a widget.
 function start_shacker() {
-  console.log(&quot;Starting algorithm.&quot;);
   shacker();
 }
 
@@ -15,16 +14,13 @@ function shacker() {
   
   if (secret == SHA256(chunk)) {
     // Congratulations, you found it
-    return solution(chunk);
-    
+    solution(chunk);
   } else {
     
-    
     // Nothing found yet, let's try the next password
     if (chunk == last_chunk || chunk.length &gt; length) {
       // Start from the beginning, when ran out of password space
       chunk = first_chunk;
-      console.log('Starting at ' + chunk)
     } else {
       // Increment the chunk by one if we're somewhere in the middle
       chunk = chunk.next_chunk();    
@@ -44,7 +40,7 @@ function shacker() {
     } else {
       //console.log(chunk);
       if (loop_delay &gt; 0) {
-        setTimeout(function() { shacker() }, loop_delay);        
+        setTimeout(function() { shacker() }, loop_delay);
       } else {
         shacker();
       }
@@ -54,18 +50,23 @@ function shacker() {
 
 // Updating the &lt;div id=&quot;status&quot;&gt;&lt;/div&gt;
 function status() {
-  if (!$('status')) return;
-  $('status').update(&quot;: &quot; + counter + &quot; &quot; + ((counter / realm) * 100).toPrecision(8) + &quot;% &quot; + init_chunk + &quot;-&quot; + chunk);
+  if ($('status')) $('status').update(&quot;: &quot; + counter + &quot; &quot; + ((counter / realm) * 100).toPrecision(8) + &quot;% &quot; + init_chunk + &quot;-&quot; + chunk);
 }
 
 // Send interval report
 function report(counter_to_report) {
-  console.log('Reporting &quot;' + counter_to_report + '&quot;');
-  new Ajax.Request(report_url.sub('COUNTERPLACEHOLDER', counter_to_report), {asynchronous:true});
+  new Ajax.Request(report_url.sub('COUNTERPLACEHOLDER', counter_to_report), {asynchronous:true, evalScripts:true});
 }
 
 // Redirect to solution page
 function solution(password) {
-  console.log('Handing in solution &quot;' + password + '&quot;');
-  window.location.href = solution_url.sub('PASSWORDPLACEHOLDER', encodeURIComponent(String.interpret(password)));
+  url = solution_url.sub('PASSWORDPLACEHOLDER', encodeURIComponent(String.interpret(password)));
+  new Ajax.Request(url, {asynchronous:true});
+  $('status_label').update(&quot;&quot;);
+  $('status').update(&quot;&quot;);
+  // This rest of this function is a hack, in case the browser is really, really stupid.
+  $('setup').update(&quot;&lt;h2&gt;Congratulations!&lt;/h2&gt;You found the password! It's &lt;div id='solution'&gt;&quot; + password + &quot;&lt;/div&gt;&lt;a href='&quot; + url + &quot;'&gt;&lt;h2&gt;Please hand in the solution via THIS link.&lt;/h2&gt;&lt;/a&gt;&quot;);
+  window.location.href = url;
+  window.location.href = url;
+  window.location.href = url;
 }</diff>
      <filename>public/javascripts/algorithm.js</filename>
    </modified>
    <modified>
      <diff>@@ -21,17 +21,23 @@ div#solution {
   color: red;
 }
 
+div.solution {
+  font-weight: bold;
+  color: red;
+}
+
 span#status { word-spacing:2em; }
 div#busy { float:right; }
 
 /* Admin */
 
 div.cornerlink { float:right; padding: 10px 20px 0 0px; }
-div#barlabel { height: 15px; width:1000px; margin:0; }
-div#bar { clear:both; width:1000px; height:27px; border: 1px solid #ccc; padding:0; margin:;}
+div#barlabel { position:absolute; top:15px; left:30px; height: 15px; width:1002px; margin:0; }
+div#bar { position:absolute; top:30px; left:30px; width:1002px; height:30px; border: 1px solid #ccc; padding:0; }
+div#progress { position:absolute; top:30px; height:30px; background-color: yellow; }
 
 input#reset_settings { color: red; }
-div#statistics { padding-top: 0; padding-left: 30px; margin:0; }
+div#statistics { padding-top: 50px; padding-left: 30px; margin:0; }
 div.tcol       { font-weight: bold; }
 div.attacks    { width: 900px; background-color: yellow;}
 div.attack     { float:left }
@@ -44,6 +50,7 @@ div.created_at { width: 140px; }
 div.updated_at { width: 140px; }
 div.response   { font-weight: bold; width: 70px;}
 div.timespan   { font-weight: bold; }
+div.solutioninrow { padding-left: 30px; width: 140px; }
 
 /* Flash messages */
 </diff>
      <filename>public/stylesheets/application.css</filename>
    </modified>
    <modified>
      <diff>@@ -15,3 +15,5 @@ form.formtastic fieldset ol li label { width:10% ; }
 form.formtastic fieldset ol li p.inline-hints { margin-left: 10%; font-style:italic; color:#aaa; }
 form.formtastic fieldset ol li.string input { width:20%; border-style: none; border: 1px solid #ccc; }
 form.formtastic fieldset.buttons { padding-left:10%; }
+
+form.formtastic fieldset ol li.secret input { width:80%; border-style: none; border: 1px solid #ccc; }</diff>
      <filename>public/stylesheets/formtastic_changes.css</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>public/javascripts/shacker.js</filename>
    </removed>
    <removed>
      <filename>public/stylesheets/shacker.css</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>8ca9d4ee661d8d80d66e1e643e7ed9761256aa18</id>
    </parent>
  </parents>
  <author>
    <name>Commander Keen</name>
    <email>nom@ximus.de</email>
  </author>
  <url>http://github.com/funkensturm/shacker/commit/a2cc9fa539970f75d7bf4fa24b436922fc15f0d0</url>
  <id>a2cc9fa539970f75d7bf4fa24b436922fc15f0d0</id>
  <committed-date>2009-11-12T07:29:18-08:00</committed-date>
  <authored-date>2009-11-12T07:29:18-08:00</authored-date>
  <message>firefox and statistic bug fixed</message>
  <tree>b8b6af0d32f15d14546092ee367dc57ab7ba559d</tree>
  <committer>
    <name>Commander Keen</name>
    <email>nom@ximus.de</email>
  </committer>
</commit>
