logical-insight 0.4.0
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/History.txt +45 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.md +123 -0
- data/Rakefile +24 -0
- data/Thorfile +113 -0
- data/lib/insight.rb +17 -0
- data/lib/insight/app.rb +189 -0
- data/lib/insight/database.rb +186 -0
- data/lib/insight/enable-button.rb +43 -0
- data/lib/insight/filtered_backtrace.rb +45 -0
- data/lib/insight/instrumentation.rb +9 -0
- data/lib/insight/instrumentation/backstage.rb +10 -0
- data/lib/insight/instrumentation/client.rb +20 -0
- data/lib/insight/instrumentation/instrument.rb +109 -0
- data/lib/insight/instrumentation/package-definition.rb +58 -0
- data/lib/insight/instrumentation/probe-definition.rb +20 -0
- data/lib/insight/instrumentation/probe.rb +199 -0
- data/lib/insight/instrumentation/setup.rb +32 -0
- data/lib/insight/logger.rb +55 -0
- data/lib/insight/options.rb +102 -0
- data/lib/insight/panel.rb +119 -0
- data/lib/insight/panel_app.rb +31 -0
- data/lib/insight/panels-content.rb +22 -0
- data/lib/insight/panels-header.rb +18 -0
- data/lib/insight/panels/active_record_panel.rb +46 -0
- data/lib/insight/panels/cache_panel.rb +69 -0
- data/lib/insight/panels/cache_panel/panel_app.rb +46 -0
- data/lib/insight/panels/cache_panel/stats.rb +98 -0
- data/lib/insight/panels/log_panel.rb +54 -0
- data/lib/insight/panels/memory_panel.rb +32 -0
- data/lib/insight/panels/rails_info_panel.rb +19 -0
- data/lib/insight/panels/redis_panel.rb +42 -0
- data/lib/insight/panels/redis_panel/redis_extension.rb +23 -0
- data/lib/insight/panels/redis_panel/stats.rb +50 -0
- data/lib/insight/panels/request_variables_panel.rb +70 -0
- data/lib/insight/panels/speedtracer_panel.rb +89 -0
- data/lib/insight/panels/speedtracer_panel/trace-app.rb +52 -0
- data/lib/insight/panels/speedtracer_panel/tracer.rb +212 -0
- data/lib/insight/panels/sql_panel.rb +53 -0
- data/lib/insight/panels/sql_panel/panel_app.rb +37 -0
- data/lib/insight/panels/sql_panel/query.rb +94 -0
- data/lib/insight/panels/templates_panel.rb +58 -0
- data/lib/insight/panels/templates_panel/rendering.rb +81 -0
- data/lib/insight/panels/timer_panel.rb +40 -0
- data/lib/insight/params_signature.rb +61 -0
- data/lib/insight/public/__insight__/bookmarklet.html +10 -0
- data/lib/insight/public/__insight__/bookmarklet.js +223 -0
- data/lib/insight/public/__insight__/insight.css +235 -0
- data/lib/insight/public/__insight__/insight.js +123 -0
- data/lib/insight/public/__insight__/jquery-1.3.2.js +4376 -0
- data/lib/insight/public/__insight__/jquery.tablesorter.min.js +1 -0
- data/lib/insight/public/__insight__/spinner.gif +0 -0
- data/lib/insight/rack_static_bug_avoider.rb +16 -0
- data/lib/insight/redirect_interceptor.rb +25 -0
- data/lib/insight/render.rb +72 -0
- data/lib/insight/request-recorder.rb +23 -0
- data/lib/insight/toolbar.rb +63 -0
- data/lib/insight/views/enable-button.html.erb +1 -0
- data/lib/insight/views/error.html.erb +17 -0
- data/lib/insight/views/headers_fragment.html.erb +20 -0
- data/lib/insight/views/panels/active_record.html.erb +17 -0
- data/lib/insight/views/panels/cache.html.erb +93 -0
- data/lib/insight/views/panels/execute_sql.html.erb +32 -0
- data/lib/insight/views/panels/explain_sql.html.erb +32 -0
- data/lib/insight/views/panels/log.html.erb +21 -0
- data/lib/insight/views/panels/profile_sql.html.erb +32 -0
- data/lib/insight/views/panels/rails_info.html.erb +19 -0
- data/lib/insight/views/panels/redis.html.erb +46 -0
- data/lib/insight/views/panels/request_variables.html.erb +25 -0
- data/lib/insight/views/panels/speedtracer/serverevent.html.erb +10 -0
- data/lib/insight/views/panels/speedtracer/servertrace.html.erb +12 -0
- data/lib/insight/views/panels/speedtracer/traces.html.erb +18 -0
- data/lib/insight/views/panels/sql.html.erb +43 -0
- data/lib/insight/views/panels/templates.html.erb +6 -0
- data/lib/insight/views/panels/timer.html.erb +19 -0
- data/lib/insight/views/panels/view_cache.html.erb +19 -0
- data/lib/insight/views/redirect.html.erb +16 -0
- data/lib/insight/views/request_fragment.html.erb +25 -0
- data/lib/insight/views/toolbar.html.erb +29 -0
- data/lib/logical-insight.rb +1 -0
- data/spec/custom_matchers.rb +31 -0
- data/spec/fixtures/config.ru +8 -0
- data/spec/fixtures/dummy_panel.rb +2 -0
- data/spec/fixtures/sample_app.rb +72 -0
- data/spec/insight/panels/active_record_panel_spec.rb +42 -0
- data/spec/insight/panels/cache_panel_spec.rb +176 -0
- data/spec/insight/panels/log_panel_spec.rb +44 -0
- data/spec/insight/panels/memory_panel_spec.rb +19 -0
- data/spec/insight/panels/mongo_panel_spec_pending.rb +50 -0
- data/spec/insight/panels/rails_info_panel_spec.rb +27 -0
- data/spec/insight/panels/redis_panel_spec.rb +66 -0
- data/spec/insight/panels/sql_panel_spec.rb +145 -0
- data/spec/insight/panels/templates_panel_spec.rb +84 -0
- data/spec/insight/panels/timer_panel_spec.rb +36 -0
- data/spec/insight_spec.rb +141 -0
- data/spec/instrumentation_spec.rb +188 -0
- data/spec/rcov.opts +1 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +93 -0
- metadata +187 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require "digest"
|
|
2
|
+
|
|
3
|
+
module Insight
|
|
4
|
+
|
|
5
|
+
class SQLPanel < Panel
|
|
6
|
+
|
|
7
|
+
require "insight/panels/sql_panel/panel_app"
|
|
8
|
+
require "insight/panels/sql_panel/query"
|
|
9
|
+
|
|
10
|
+
def initialize(app)
|
|
11
|
+
super
|
|
12
|
+
probe(self) do
|
|
13
|
+
%w{ PostgreSQLAdapter MysqlAdapter SQLiteAdapter
|
|
14
|
+
Mysql2Adapter OracleEnhancedAdapter }.each do |adapter|
|
|
15
|
+
instrument "ActiveRecord::ConnectionAdapters::#{adapter}" do
|
|
16
|
+
instance_probe :execute
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
table_setup("sql_queries")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.panel_mappings
|
|
24
|
+
{ "sql" => PanelApp.new }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def after_detect(method_call, timing, arguments, results)
|
|
28
|
+
store(@env, QueryResult.new(arguments.first, timing.duration, method_call.backtrace, results))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def total_time(queries)
|
|
32
|
+
(queries.inject(0) do |memo, query|
|
|
33
|
+
memo + query.time
|
|
34
|
+
end)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def name
|
|
38
|
+
"sql"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def heading_for_request(number)
|
|
42
|
+
queries = retrieve(number)
|
|
43
|
+
"#{queries.size} Queries (%.2fms)" % total_time(queries)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def content_for_request(number)
|
|
47
|
+
queries = retrieve(number)
|
|
48
|
+
render_template "panels/sql", :queries => queries
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'insight/panels/sql_panel/query'
|
|
2
|
+
|
|
3
|
+
module Insight
|
|
4
|
+
class SQLPanel
|
|
5
|
+
|
|
6
|
+
class PanelApp < ::Insight::PanelApp
|
|
7
|
+
|
|
8
|
+
def dispatch
|
|
9
|
+
case request.path_info
|
|
10
|
+
when "/explain" then explain_sql
|
|
11
|
+
when "/profile" then profile_sql
|
|
12
|
+
when "/execute" then execute_sql
|
|
13
|
+
else not_found
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def explain_sql
|
|
18
|
+
validate_params
|
|
19
|
+
query = ExplainResult.new(params["query"], params["time"].to_f)
|
|
20
|
+
render_template "panels/explain_sql", :query => query
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def profile_sql
|
|
24
|
+
validate_params
|
|
25
|
+
query = ProfileResult.new(params["query"], params["time"].to_f)
|
|
26
|
+
render_template "panels/profile_sql", :query => query
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def execute_sql
|
|
30
|
+
validate_params
|
|
31
|
+
query = QueryResult.new(params["query"], params["time"].to_f)
|
|
32
|
+
render_template "panels/execute_sql", :query => query
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
module Insight
|
|
2
|
+
class SQLPanel
|
|
3
|
+
|
|
4
|
+
class QueryResult
|
|
5
|
+
include Insight::FilteredBacktrace
|
|
6
|
+
|
|
7
|
+
attr_reader :sql
|
|
8
|
+
attr_reader :time
|
|
9
|
+
|
|
10
|
+
def initialize(sql, time, backtrace = [], result=nil)
|
|
11
|
+
@sql = sql
|
|
12
|
+
@time = time
|
|
13
|
+
@backtrace = backtrace
|
|
14
|
+
@result = result
|
|
15
|
+
@results = nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def result
|
|
19
|
+
@results ||= execute
|
|
20
|
+
return @results
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def column_names
|
|
24
|
+
if result.respond_to?(:fields)
|
|
25
|
+
return result.fields
|
|
26
|
+
else
|
|
27
|
+
return result.fetch_fields.map{|col| col.name}
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def rows
|
|
32
|
+
if result.respond_to?(:values)
|
|
33
|
+
result.values
|
|
34
|
+
else
|
|
35
|
+
result.map do |row|
|
|
36
|
+
row
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def human_time
|
|
42
|
+
"%.2fms" % (@time)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def inspectable?
|
|
46
|
+
sql.strip =~ /^SELECT /i
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
#Downside is: we re-execute the SQL...
|
|
50
|
+
def self.execute(sql)
|
|
51
|
+
ActiveRecord::Base.connection.execute(sql)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def execute
|
|
55
|
+
self.class.execute(@sql)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def valid_hash?(secret_key, possible_hash)
|
|
59
|
+
hash = Digest::SHA1.hexdigest [secret_key, @sql].join(":")
|
|
60
|
+
possible_hash == hash
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class ExplainResult < QueryResult
|
|
65
|
+
def execute
|
|
66
|
+
self.class.execute "EXPLAIN #{@sql}"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class ProfileResult < QueryResult
|
|
71
|
+
def with_profiling
|
|
72
|
+
result = nil
|
|
73
|
+
begin
|
|
74
|
+
self.class.execute("SET PROFILING=1")
|
|
75
|
+
result = yield
|
|
76
|
+
ensure
|
|
77
|
+
self.class.execute("SET PROFILING=0")
|
|
78
|
+
end
|
|
79
|
+
return result
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def execute
|
|
83
|
+
with_profiling do
|
|
84
|
+
super
|
|
85
|
+
self.class.execute <<-SQL
|
|
86
|
+
SELECT *
|
|
87
|
+
FROM information_schema.profiling
|
|
88
|
+
WHERE query_id = (SELECT query_id FROM information_schema.profiling ORDER BY query_id DESC LIMIT 1)
|
|
89
|
+
SQL
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module Insight
|
|
2
|
+
|
|
3
|
+
class TemplatesPanel < Panel
|
|
4
|
+
require "insight/panels/templates_panel/rendering"
|
|
5
|
+
|
|
6
|
+
def initialize(app)
|
|
7
|
+
super
|
|
8
|
+
|
|
9
|
+
probe(self) do
|
|
10
|
+
instrument "ActionView::Template" do
|
|
11
|
+
instance_probe :render
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
table_setup("templates")
|
|
16
|
+
|
|
17
|
+
@current = nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def request_start(env, start)
|
|
22
|
+
@current = Rendering.new("root")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def request_finish(env, status, headers, body, timing)
|
|
26
|
+
store(env, @current)
|
|
27
|
+
@current = nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def before_detect(method_call, args)
|
|
31
|
+
template_name = method_call.object.virtual_path
|
|
32
|
+
|
|
33
|
+
rendering = Rendering.new(template_name)
|
|
34
|
+
@current.add(rendering)
|
|
35
|
+
@current = rendering
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def after_detect(method_call, timing, args, result)
|
|
39
|
+
@current.timing = timing
|
|
40
|
+
@current = @current.parent
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def name
|
|
44
|
+
"templates"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def heading_for_request(number)
|
|
48
|
+
"Templates: %.2fms" % (retrieve(number).inject(0.0){|memo, rendering| memo + rendering.duration})
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def content_for_request(number)
|
|
52
|
+
result = render_template "panels/templates", :root_rendering => retrieve(number).first
|
|
53
|
+
return result
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module Insight
|
|
2
|
+
class TemplatesPanel
|
|
3
|
+
|
|
4
|
+
class Rendering
|
|
5
|
+
attr_accessor :name
|
|
6
|
+
attr_accessor :parent
|
|
7
|
+
attr_accessor :timing
|
|
8
|
+
attr_reader :children
|
|
9
|
+
|
|
10
|
+
def initialize(name, timing = nil)
|
|
11
|
+
@name = name
|
|
12
|
+
@timing = timing
|
|
13
|
+
@children = []
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def start_time
|
|
17
|
+
@timing.start
|
|
18
|
+
end
|
|
19
|
+
alias_method :time, :start_time
|
|
20
|
+
|
|
21
|
+
def end_time
|
|
22
|
+
@timing.end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def add(rendering)
|
|
26
|
+
@children << rendering
|
|
27
|
+
rendering.parent = self
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def delete(rendering)
|
|
31
|
+
@children.delete(rendering)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def duration
|
|
35
|
+
if @timing
|
|
36
|
+
@timing.duration
|
|
37
|
+
else
|
|
38
|
+
child_duration
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def exclusive_duration
|
|
43
|
+
duration - child_duration
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def child_duration
|
|
47
|
+
children.inject(0.0) { |memo, c| memo + c.duration }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def duration_summary
|
|
51
|
+
if children.any?
|
|
52
|
+
"%.2fms, %.2f exclusive" % [duration, exclusive_duration]
|
|
53
|
+
else
|
|
54
|
+
"%.2fms" % (duration)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
def html
|
|
58
|
+
<<-HTML
|
|
59
|
+
<li>
|
|
60
|
+
<p>#{name} (#{duration_summary})</p>
|
|
61
|
+
|
|
62
|
+
#{children_html}
|
|
63
|
+
</li>
|
|
64
|
+
HTML
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def children_html
|
|
68
|
+
return "" unless children.any?
|
|
69
|
+
|
|
70
|
+
<<-HTML
|
|
71
|
+
<ul>#{joined_children_html}</ul>
|
|
72
|
+
HTML
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def joined_children_html
|
|
76
|
+
children.map { |c| c.html }.join
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'benchmark'
|
|
2
|
+
|
|
3
|
+
module Insight
|
|
4
|
+
class TimerPanel < Panel
|
|
5
|
+
def initialize(app)
|
|
6
|
+
super
|
|
7
|
+
table_setup("timer")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def name
|
|
11
|
+
"timer"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call(env)
|
|
15
|
+
status, headers, body = nil
|
|
16
|
+
@times = Benchmark.measure do
|
|
17
|
+
status, headers, body = @app.call(env)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
store(env, [
|
|
21
|
+
["User CPU time", "%.2fms" % (@times.utime * 1_000)],
|
|
22
|
+
["System CPU time", "%.2fms" % (@times.stime * 1_000)],
|
|
23
|
+
["Total CPU time", "%.2fms" % (@times.total * 1_000)],
|
|
24
|
+
["Elapsed time", "%.2fms" % (@times.real * 1_000)]
|
|
25
|
+
])
|
|
26
|
+
|
|
27
|
+
return [status, headers, body]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def heading_for_request(number)
|
|
31
|
+
measurements = retreive(number).first
|
|
32
|
+
|
|
33
|
+
measurements.last.last
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def content_for_request(number)
|
|
37
|
+
render_template "panels/timer", :measurements => retrieve(number).first
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require "digest"
|
|
2
|
+
|
|
3
|
+
module Insight
|
|
4
|
+
|
|
5
|
+
class ParamsSignature
|
|
6
|
+
extend ERB::Util
|
|
7
|
+
|
|
8
|
+
def self.sign(request, hash)
|
|
9
|
+
parts = []
|
|
10
|
+
|
|
11
|
+
hash.keys.sort.each do |key|
|
|
12
|
+
parts << "#{key}=#{u(hash[key])}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
signature = new(request).signature(hash)
|
|
16
|
+
parts << "hash=#{u(signature)}"
|
|
17
|
+
|
|
18
|
+
parts.join("&")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
attr_reader :request
|
|
22
|
+
|
|
23
|
+
def initialize(request)
|
|
24
|
+
@request = request
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def secret_key
|
|
28
|
+
@request.env['insight.secret_key']
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def secret_key_blank?
|
|
32
|
+
secret_key.nil? || secret_key == ""
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def validate!
|
|
36
|
+
if secret_key_blank?
|
|
37
|
+
raise SecurityError.new("Missing secret key")
|
|
38
|
+
elsif request.params["hash"] != signature(request.params)
|
|
39
|
+
raise SecurityError.new("Invalid query hash.")
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def signature(params)
|
|
44
|
+
Digest::SHA1.hexdigest(signature_base(params))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def signature_base(params)
|
|
48
|
+
signature = []
|
|
49
|
+
signature << secret_key
|
|
50
|
+
|
|
51
|
+
params.keys.sort.each do |key|
|
|
52
|
+
next if key == "hash"
|
|
53
|
+
signature << params[key].to_s
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
signature.join(":")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
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='/__insight__/bookmarklet.js'; document.getElementsByTagName('head')[0].appendChild(script);})()">
|
|
7
|
+
Toggle Insight
|
|
8
|
+
</a>
|
|
9
|
+
</body>
|
|
10
|
+
</html>
|
|
@@ -0,0 +1,223 @@
|
|
|
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.insightEnable = function() {
|
|
203
|
+
var password = prompt("Insight password:", "");
|
|
204
|
+
if (password != null) {
|
|
205
|
+
document.createCookie('insight_password', document.SHA1('insight:'+password));
|
|
206
|
+
document.createCookie('insight_enabled', "1");
|
|
207
|
+
window.location.reload();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
document.insightDisable = function() {
|
|
212
|
+
document.eraseCookie('insight_password');
|
|
213
|
+
document.eraseCookie('insight_enabled');
|
|
214
|
+
window.location.reload();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
document.insightBookmarklet = function() {
|
|
218
|
+
if (document.readCookie('insight_password')) {
|
|
219
|
+
document.insightDisable()
|
|
220
|
+
} else {
|
|
221
|
+
document.insightEnable()
|
|
222
|
+
}
|
|
223
|
+
}
|