rack-bug 0.2.1
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/.gitignore +3 -0
- data/History.txt +0 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.rdoc +29 -0
- data/Rakefile +36 -0
- data/VERSION +1 -0
- data/lib/rack/bug.rb +43 -0
- data/lib/rack/bug/options.rb +89 -0
- data/lib/rack/bug/panel.rb +50 -0
- data/lib/rack/bug/panel_app.rb +33 -0
- data/lib/rack/bug/panels/active_record_panel.rb +45 -0
- data/lib/rack/bug/panels/active_record_panel/activerecord_extensions.rb +18 -0
- data/lib/rack/bug/panels/cache_panel.rb +50 -0
- data/lib/rack/bug/panels/cache_panel/memcache_extension.rb +129 -0
- data/lib/rack/bug/panels/cache_panel/panel_app.rb +48 -0
- data/lib/rack/bug/panels/cache_panel/stats.rb +97 -0
- data/lib/rack/bug/panels/log_panel.rb +39 -0
- data/lib/rack/bug/panels/log_panel/rails_extension.rb +11 -0
- data/lib/rack/bug/panels/memory_panel.rb +27 -0
- data/lib/rack/bug/panels/rails_info_panel.rb +23 -0
- data/lib/rack/bug/panels/redis_panel.rb +44 -0
- data/lib/rack/bug/panels/redis_panel/redis_extension.rb +14 -0
- data/lib/rack/bug/panels/redis_panel/stats.rb +48 -0
- data/lib/rack/bug/panels/request_variables_panel.rb +25 -0
- data/lib/rack/bug/panels/sql_panel.rb +55 -0
- data/lib/rack/bug/panels/sql_panel/panel_app.rb +37 -0
- data/lib/rack/bug/panels/sql_panel/query.rb +73 -0
- data/lib/rack/bug/panels/sql_panel/sql_extension.rb +11 -0
- data/lib/rack/bug/panels/templates_panel.rb +44 -0
- data/lib/rack/bug/panels/templates_panel/actionview_extension.rb +12 -0
- data/lib/rack/bug/panels/templates_panel/rendering.rb +67 -0
- data/lib/rack/bug/panels/templates_panel/trace.rb +34 -0
- data/lib/rack/bug/panels/timer_panel.rb +40 -0
- data/lib/rack/bug/params_signature.rb +65 -0
- data/lib/rack/bug/public/__rack_bug__/bookmarklet.html +10 -0
- data/lib/rack/bug/public/__rack_bug__/bookmarklet.js +215 -0
- data/lib/rack/bug/public/__rack_bug__/bug.css +211 -0
- data/lib/rack/bug/public/__rack_bug__/bug.js +84 -0
- data/lib/rack/bug/public/__rack_bug__/jquery-1.3.2.js +4376 -0
- data/lib/rack/bug/public/__rack_bug__/jquery.tablesorter.min.js +1 -0
- data/lib/rack/bug/public/__rack_bug__/spinner.gif +0 -0
- data/lib/rack/bug/render.rb +66 -0
- data/lib/rack/bug/toolbar.rb +137 -0
- data/lib/rack/bug/views/error.html.erb +16 -0
- data/lib/rack/bug/views/panels/active_record.html.erb +17 -0
- data/lib/rack/bug/views/panels/cache.html.erb +93 -0
- data/lib/rack/bug/views/panels/execute_sql.html.erb +32 -0
- data/lib/rack/bug/views/panels/explain_sql.html.erb +32 -0
- data/lib/rack/bug/views/panels/log.html.erb +23 -0
- data/lib/rack/bug/views/panels/profile_sql.html.erb +32 -0
- data/lib/rack/bug/views/panels/rails_info.html.erb +19 -0
- data/lib/rack/bug/views/panels/redis.html.erb +32 -0
- data/lib/rack/bug/views/panels/request_variables.html.erb +107 -0
- data/lib/rack/bug/views/panels/sql.html.erb +43 -0
- data/lib/rack/bug/views/panels/templates.html.erb +7 -0
- data/lib/rack/bug/views/panels/timer.html.erb +19 -0
- data/lib/rack/bug/views/panels/view_cache.html.erb +19 -0
- data/lib/rack/bug/views/redirect.html.erb +16 -0
- data/lib/rack/bug/views/toolbar.html.erb +42 -0
- data/rack-bug.gemspec +126 -0
- data/spec/fixtures/config.ru +8 -0
- data/spec/fixtures/dummy_panel.rb +2 -0
- data/spec/fixtures/sample_app.rb +29 -0
- data/spec/rack/bug/panels/active_record_panel_spec.rb +30 -0
- data/spec/rack/bug/panels/cache_panel_spec.rb +159 -0
- data/spec/rack/bug/panels/log_panel_spec.rb +25 -0
- data/spec/rack/bug/panels/memory_panel_spec.rb +21 -0
- data/spec/rack/bug/panels/rails_info_panel_spec.rb +25 -0
- data/spec/rack/bug/panels/redis_panel_spec.rb +57 -0
- data/spec/rack/bug/panels/sql_panel_spec.rb +136 -0
- data/spec/rack/bug/panels/templates_panel_spec.rb +71 -0
- data/spec/rack/bug/panels/timer_panel_spec.rb +38 -0
- data/spec/rack/toolbar_spec.rb +100 -0
- data/spec/rcov.opts +1 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +70 -0
- metadata +143 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
module Rack
|
2
|
+
module Bug
|
3
|
+
class SQLPanel
|
4
|
+
|
5
|
+
class Query
|
6
|
+
attr_reader :sql
|
7
|
+
attr_reader :time
|
8
|
+
attr_reader :backtrace
|
9
|
+
|
10
|
+
def initialize(sql, time, backtrace = [])
|
11
|
+
@sql = sql
|
12
|
+
@time = time
|
13
|
+
@backtrace = backtrace
|
14
|
+
end
|
15
|
+
|
16
|
+
def human_time
|
17
|
+
"%.2fms" % (@time * 1_000)
|
18
|
+
end
|
19
|
+
|
20
|
+
def inspectable?
|
21
|
+
sql.strip =~ /^SELECT /i
|
22
|
+
end
|
23
|
+
|
24
|
+
def with_profiling
|
25
|
+
self.class.execute("SET PROFILING=1")
|
26
|
+
result = yield
|
27
|
+
self.class.execute("SET PROFILING=0")
|
28
|
+
return result
|
29
|
+
end
|
30
|
+
|
31
|
+
def explain
|
32
|
+
self.class.execute "EXPLAIN #{@sql}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def profile
|
36
|
+
with_profiling do
|
37
|
+
execute
|
38
|
+
self.class.execute <<-SQL
|
39
|
+
SELECT *
|
40
|
+
FROM information_schema.profiling
|
41
|
+
WHERE query_id = (SELECT query_id FROM information_schema.profiling ORDER BY query_id DESC LIMIT 1)
|
42
|
+
SQL
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def execute
|
47
|
+
self.class.execute(@sql)
|
48
|
+
end
|
49
|
+
|
50
|
+
def valid_hash?(secret_key, possible_hash)
|
51
|
+
hash = Digest::SHA1.hexdigest [secret_key, @sql].join(":")
|
52
|
+
possible_hash == hash
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.execute(sql)
|
56
|
+
ActiveRecord::Base.connection.execute(sql)
|
57
|
+
end
|
58
|
+
|
59
|
+
def has_backtrace?
|
60
|
+
filtered_backtrace.any?
|
61
|
+
end
|
62
|
+
|
63
|
+
def filtered_backtrace
|
64
|
+
@filtered_backtrace ||= @backtrace.map { |l| l.to_s.strip }.select do |line|
|
65
|
+
line.starts_with?(Rails.root) &&
|
66
|
+
!line.starts_with?(Rails.root.join("vendor"))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
if defined?(ActiveRecord) && defined?(ActiveRecord::ConnectionAdapters)
|
2
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
|
3
|
+
def log_with_rack_bug(sql, name, &block)
|
4
|
+
Rack::Bug::SQLPanel.record(sql, Kernel.caller) do
|
5
|
+
log_without_rack_bug(sql, name, &block)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method_chain :log, :rack_bug
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Rack
|
2
|
+
module Bug
|
3
|
+
|
4
|
+
class TemplatesPanel < Panel
|
5
|
+
require "rack/bug/panels/templates_panel/actionview_extension"
|
6
|
+
|
7
|
+
autoload :Trace, "rack/bug/panels/templates_panel/trace"
|
8
|
+
autoload :Rendering, "rack/bug/panels/templates_panel/rendering"
|
9
|
+
|
10
|
+
def self.record(template, &block)
|
11
|
+
return block.call unless Rack::Bug.enabled?
|
12
|
+
|
13
|
+
template_trace.start(template)
|
14
|
+
result = block.call
|
15
|
+
template_trace.finished(template)
|
16
|
+
return result
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.reset
|
20
|
+
Thread.current["rack.bug.template_trace"] = Trace.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.template_trace
|
24
|
+
Thread.current["rack.bug.template_trace"] ||= Trace.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def name
|
28
|
+
"templates"
|
29
|
+
end
|
30
|
+
|
31
|
+
def heading
|
32
|
+
"Templates: %.2fms" % (self.class.template_trace.total_time * 1_000)
|
33
|
+
end
|
34
|
+
|
35
|
+
def content
|
36
|
+
result = render_template "panels/templates", :template_trace => self.class.template_trace
|
37
|
+
self.class.reset
|
38
|
+
return result
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
if defined?(ActionView) && defined?(ActionView::Template)
|
2
|
+
ActionView::Template.class_eval do
|
3
|
+
|
4
|
+
def render_template_with_rack_bug(*args, &block)
|
5
|
+
Rack::Bug::TemplatesPanel.record(path_without_format_and_extension) do
|
6
|
+
render_template_without_rack_bug(*args, &block)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
alias_method_chain :render_template, :rack_bug
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Rack
|
2
|
+
module Bug
|
3
|
+
class TemplatesPanel
|
4
|
+
|
5
|
+
class Rendering
|
6
|
+
attr_accessor :name
|
7
|
+
attr_accessor :start_time
|
8
|
+
attr_accessor :end_time
|
9
|
+
attr_accessor :parent
|
10
|
+
attr_reader :children
|
11
|
+
|
12
|
+
|
13
|
+
def initialize(name)
|
14
|
+
@name = name
|
15
|
+
@children = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def add(rendering)
|
19
|
+
@children << rendering
|
20
|
+
rendering.parent = self
|
21
|
+
end
|
22
|
+
|
23
|
+
def time
|
24
|
+
@end_time - @start_time
|
25
|
+
end
|
26
|
+
|
27
|
+
def exclusive_time
|
28
|
+
time - child_time
|
29
|
+
end
|
30
|
+
|
31
|
+
def child_time
|
32
|
+
children.inject(0.0) { |memo, c| memo + c.time }
|
33
|
+
end
|
34
|
+
|
35
|
+
def time_summary
|
36
|
+
if children.any?
|
37
|
+
"%.2fms, %.2f exclusive" % [time * 1_000, exclusive_time * 1_000]
|
38
|
+
else
|
39
|
+
"%.2fms" % (time * 1_000)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
def html
|
43
|
+
<<-HTML
|
44
|
+
<li>
|
45
|
+
<p>#{name} (#{time_summary})</p>
|
46
|
+
|
47
|
+
#{children_html}
|
48
|
+
</li>
|
49
|
+
HTML
|
50
|
+
end
|
51
|
+
|
52
|
+
def children_html
|
53
|
+
return "" unless children.any?
|
54
|
+
|
55
|
+
<<-HTML
|
56
|
+
<ul>#{joined_children_html}</ul>
|
57
|
+
HTML
|
58
|
+
end
|
59
|
+
|
60
|
+
def joined_children_html
|
61
|
+
children.map { |c| c.html }.join
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Rack
|
2
|
+
module Bug
|
3
|
+
class TemplatesPanel
|
4
|
+
|
5
|
+
class Trace
|
6
|
+
|
7
|
+
def start(template_name)
|
8
|
+
rendering = Rendering.new(template_name)
|
9
|
+
rendering.start_time = Time.now
|
10
|
+
@current.add(rendering)
|
11
|
+
@current = rendering
|
12
|
+
end
|
13
|
+
|
14
|
+
def finished(template_name)
|
15
|
+
@current.end_time = Time.now
|
16
|
+
@current = @current.parent
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@current = root
|
21
|
+
end
|
22
|
+
|
23
|
+
def total_time
|
24
|
+
root.child_time
|
25
|
+
end
|
26
|
+
|
27
|
+
def root
|
28
|
+
@root ||= Rendering.new("root")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "benchmark"
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module Bug
|
5
|
+
|
6
|
+
class TimerPanel < Panel
|
7
|
+
|
8
|
+
def name
|
9
|
+
"timer"
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
status, headers, body = nil
|
14
|
+
@times = Benchmark.measure do
|
15
|
+
status, headers, body = @app.call(env)
|
16
|
+
end
|
17
|
+
|
18
|
+
@measurements = [
|
19
|
+
["User CPU time", "%.2fms" % (@times.utime * 1_000)],
|
20
|
+
["System CPU time", "%.2fms" % (@times.stime * 1_000)],
|
21
|
+
["Total CPU time", "%.2fms" % (@times.total * 1_000)],
|
22
|
+
["Elapsed time", "%.2fms" % (@times.real * 1_000)]
|
23
|
+
]
|
24
|
+
|
25
|
+
env["rack-bug.panels"] << self
|
26
|
+
return [status, headers, body]
|
27
|
+
end
|
28
|
+
|
29
|
+
def heading
|
30
|
+
"%.2fms" % (@times.real * 1_000)
|
31
|
+
end
|
32
|
+
|
33
|
+
def content
|
34
|
+
render_template "panels/timer", :measurements => @measurements
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "digest"
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module Bug
|
5
|
+
|
6
|
+
class ParamsSignature
|
7
|
+
extend ERB::Util
|
8
|
+
|
9
|
+
def self.sign(request, hash)
|
10
|
+
parts = []
|
11
|
+
|
12
|
+
hash.keys.sort.each do |key|
|
13
|
+
parts << "#{key}=#{u(hash[key])}"
|
14
|
+
end
|
15
|
+
|
16
|
+
signature = new(request).signature(hash)
|
17
|
+
parts << "hash=#{u(signature)}"
|
18
|
+
|
19
|
+
parts.join("&")
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :request
|
23
|
+
|
24
|
+
def initialize(request)
|
25
|
+
@request = request
|
26
|
+
end
|
27
|
+
|
28
|
+
def secret_key
|
29
|
+
@request.env['rack-bug.secret_key']
|
30
|
+
end
|
31
|
+
|
32
|
+
def secret_key_blank?
|
33
|
+
secret_key.nil? || secret_key == ""
|
34
|
+
end
|
35
|
+
|
36
|
+
def validate!
|
37
|
+
if secret_key_blank?
|
38
|
+
raise SecurityError.new("Missing secret key")
|
39
|
+
end
|
40
|
+
|
41
|
+
if secret_key_blank? || request.params["hash"] != signature(request.params)
|
42
|
+
raise SecurityError.new("Invalid query hash.")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def signature(params)
|
47
|
+
Digest::SHA1.hexdigest(signature_base(params))
|
48
|
+
end
|
49
|
+
|
50
|
+
def signature_base(params)
|
51
|
+
signature = []
|
52
|
+
signature << secret_key
|
53
|
+
|
54
|
+
params.keys.sort.each do |key|
|
55
|
+
next if key == "hash"
|
56
|
+
signature << params[key].to_s
|
57
|
+
end
|
58
|
+
|
59
|
+
signature.join(":")
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
</head>
|
4
|
+
<body>
|
5
|
+
<br/><br/><br/>
|
6
|
+
<a href="javascript: (function(){var script=document.createElement('script'); script.src='/__rack_bug__/bookmarklet.js'; document.getElementsByTagName('head')[0].appendChild(script);})()">
|
7
|
+
Toggle Rack::Bug
|
8
|
+
</a>
|
9
|
+
</body>
|
10
|
+
</html>
|
@@ -0,0 +1,215 @@
|
|
1
|
+
/**
|
2
|
+
*
|
3
|
+
* Secure Hash Algorithm (SHA1)
|
4
|
+
* http://www.webtoolkit.info/
|
5
|
+
*
|
6
|
+
**/
|
7
|
+
|
8
|
+
document.SHA1 = function(msg) {
|
9
|
+
function rotate_left(n,s) {
|
10
|
+
var t4 = ( n<<s ) | (n>>>(32-s));
|
11
|
+
return t4;
|
12
|
+
};
|
13
|
+
|
14
|
+
function lsb_hex(val) {
|
15
|
+
var str="";
|
16
|
+
var i;
|
17
|
+
var vh;
|
18
|
+
var vl;
|
19
|
+
|
20
|
+
for( i=0; i<=6; i+=2 ) {
|
21
|
+
vh = (val>>>(i*4+4))&0x0f;
|
22
|
+
vl = (val>>>(i*4))&0x0f;
|
23
|
+
str += vh.toString(16) + vl.toString(16);
|
24
|
+
}
|
25
|
+
return str;
|
26
|
+
};
|
27
|
+
|
28
|
+
function cvt_hex(val) {
|
29
|
+
var str="";
|
30
|
+
var i;
|
31
|
+
var v;
|
32
|
+
|
33
|
+
for( i=7; i>=0; i-- ) {
|
34
|
+
v = (val>>>(i*4))&0x0f;
|
35
|
+
str += v.toString(16);
|
36
|
+
}
|
37
|
+
return str;
|
38
|
+
};
|
39
|
+
|
40
|
+
|
41
|
+
function Utf8Encode(string) {
|
42
|
+
string = string.replace(/\r\n/g,"\n");
|
43
|
+
var utftext = "";
|
44
|
+
|
45
|
+
for (var n = 0; n < string.length; n++) {
|
46
|
+
|
47
|
+
var c = string.charCodeAt(n);
|
48
|
+
|
49
|
+
if (c < 128) {
|
50
|
+
utftext += String.fromCharCode(c);
|
51
|
+
}
|
52
|
+
else if((c > 127) && (c < 2048)) {
|
53
|
+
utftext += String.fromCharCode((c >> 6) | 192);
|
54
|
+
utftext += String.fromCharCode((c & 63) | 128);
|
55
|
+
}
|
56
|
+
else {
|
57
|
+
utftext += String.fromCharCode((c >> 12) | 224);
|
58
|
+
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
59
|
+
utftext += String.fromCharCode((c & 63) | 128);
|
60
|
+
}
|
61
|
+
|
62
|
+
}
|
63
|
+
|
64
|
+
return utftext;
|
65
|
+
};
|
66
|
+
|
67
|
+
var blockstart;
|
68
|
+
var i, j;
|
69
|
+
var W = new Array(80);
|
70
|
+
var H0 = 0x67452301;
|
71
|
+
var H1 = 0xEFCDAB89;
|
72
|
+
var H2 = 0x98BADCFE;
|
73
|
+
var H3 = 0x10325476;
|
74
|
+
var H4 = 0xC3D2E1F0;
|
75
|
+
var A, B, C, D, E;
|
76
|
+
var temp;
|
77
|
+
|
78
|
+
msg = Utf8Encode(msg);
|
79
|
+
|
80
|
+
var msg_len = msg.length;
|
81
|
+
|
82
|
+
var word_array = new Array();
|
83
|
+
for( i=0; i<msg_len-3; i+=4 ) {
|
84
|
+
j = msg.charCodeAt(i)<<24 | msg.charCodeAt(i+1)<<16 |
|
85
|
+
msg.charCodeAt(i+2)<<8 | msg.charCodeAt(i+3);
|
86
|
+
word_array.push( j );
|
87
|
+
}
|
88
|
+
|
89
|
+
switch( msg_len % 4 ) {
|
90
|
+
case 0:
|
91
|
+
i = 0x080000000;
|
92
|
+
break;
|
93
|
+
case 1:
|
94
|
+
i = msg.charCodeAt(msg_len-1)<<24 | 0x0800000;
|
95
|
+
break;
|
96
|
+
|
97
|
+
case 2:
|
98
|
+
i = msg.charCodeAt(msg_len-2)<<24 | msg.charCodeAt(msg_len-1)<<16 | 0x08000;
|
99
|
+
break;
|
100
|
+
|
101
|
+
case 3:
|
102
|
+
i = msg.charCodeAt(msg_len-3)<<24 | msg.charCodeAt(msg_len-2)<<16 | msg.charCodeAt(msg_len-1)<<8 | 0x80;
|
103
|
+
break;
|
104
|
+
}
|
105
|
+
|
106
|
+
word_array.push( i );
|
107
|
+
|
108
|
+
while( (word_array.length % 16) != 14 ) word_array.push( 0 );
|
109
|
+
|
110
|
+
word_array.push( msg_len>>>29 );
|
111
|
+
word_array.push( (msg_len<<3)&0x0ffffffff );
|
112
|
+
|
113
|
+
|
114
|
+
for ( blockstart=0; blockstart<word_array.length; blockstart+=16 ) {
|
115
|
+
|
116
|
+
for( i=0; i<16; i++ ) W[i] = word_array[blockstart+i];
|
117
|
+
for( i=16; i<=79; i++ ) W[i] = rotate_left(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
|
118
|
+
|
119
|
+
A = H0;
|
120
|
+
B = H1;
|
121
|
+
C = H2;
|
122
|
+
D = H3;
|
123
|
+
E = H4;
|
124
|
+
|
125
|
+
for( i= 0; i<=19; i++ ) {
|
126
|
+
temp = (rotate_left(A,5) + ((B&C) | (~B&D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
|
127
|
+
E = D;
|
128
|
+
D = C;
|
129
|
+
C = rotate_left(B,30);
|
130
|
+
B = A;
|
131
|
+
A = temp;
|
132
|
+
}
|
133
|
+
|
134
|
+
for( i=20; i<=39; i++ ) {
|
135
|
+
temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
|
136
|
+
E = D;
|
137
|
+
D = C;
|
138
|
+
C = rotate_left(B,30);
|
139
|
+
B = A;
|
140
|
+
A = temp;
|
141
|
+
}
|
142
|
+
|
143
|
+
for( i=40; i<=59; i++ ) {
|
144
|
+
temp = (rotate_left(A,5) + ((B&C) | (B&D) | (C&D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
|
145
|
+
E = D;
|
146
|
+
D = C;
|
147
|
+
C = rotate_left(B,30);
|
148
|
+
B = A;
|
149
|
+
A = temp;
|
150
|
+
}
|
151
|
+
|
152
|
+
for( i=60; i<=79; i++ ) {
|
153
|
+
temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
|
154
|
+
E = D;
|
155
|
+
D = C;
|
156
|
+
C = rotate_left(B,30);
|
157
|
+
B = A;
|
158
|
+
A = temp;
|
159
|
+
}
|
160
|
+
|
161
|
+
H0 = (H0 + A) & 0x0ffffffff;
|
162
|
+
H1 = (H1 + B) & 0x0ffffffff;
|
163
|
+
H2 = (H2 + C) & 0x0ffffffff;
|
164
|
+
H3 = (H3 + D) & 0x0ffffffff;
|
165
|
+
H4 = (H4 + E) & 0x0ffffffff;
|
166
|
+
|
167
|
+
}
|
168
|
+
|
169
|
+
var temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);
|
170
|
+
|
171
|
+
return temp.toLowerCase();
|
172
|
+
}
|
173
|
+
|
174
|
+
document.createCookie = function(name,value,days) {
|
175
|
+
if (days) {
|
176
|
+
var date = new Date();
|
177
|
+
date.setTime(date.getTime()+(days*24*60*60*1000));
|
178
|
+
var expires = "; expires="+date.toGMTString();
|
179
|
+
}
|
180
|
+
else
|
181
|
+
var expires = "";
|
182
|
+
document.cookie = name+"="+value+expires+"; path=/";
|
183
|
+
}
|
184
|
+
|
185
|
+
document.readCookie = function(name) {
|
186
|
+
var nameEQ = name + "=";
|
187
|
+
var ca = document.cookie.split(';');
|
188
|
+
for(var i=0;i < ca.length;i++) {
|
189
|
+
var c = ca[i];
|
190
|
+
while (c.charAt(0)==' ')
|
191
|
+
c = c.substring(1,c.length);
|
192
|
+
if (c.indexOf(nameEQ) == 0)
|
193
|
+
return c.substring(nameEQ.length,c.length);
|
194
|
+
}
|
195
|
+
return null;
|
196
|
+
}
|
197
|
+
|
198
|
+
document.eraseCookie = function(name) {
|
199
|
+
document.createCookie(name,"",-1);
|
200
|
+
}
|
201
|
+
|
202
|
+
document.rackBugBookmarklet = function() {
|
203
|
+
if (document.readCookie('rack_bug_password')) {
|
204
|
+
document.eraseCookie('rack_bug_password');
|
205
|
+
document.eraseCookie('rack_bug_enabled');
|
206
|
+
alert('Rack::Bug Disabled');
|
207
|
+
} else {
|
208
|
+
var password = prompt("Rack::Bug password:", "")
|
209
|
+
document.createCookie('rack_bug_password', document.SHA1('rack_bug:'+password));
|
210
|
+
document.createCookie('rack_bug_enabled', "1");
|
211
|
+
alert('Rack::Bug Enabled');
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
document.rackBugBookmarklet();
|