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.
Files changed (100) hide show
  1. data/History.txt +45 -0
  2. data/MIT-LICENSE.txt +19 -0
  3. data/README.md +123 -0
  4. data/Rakefile +24 -0
  5. data/Thorfile +113 -0
  6. data/lib/insight.rb +17 -0
  7. data/lib/insight/app.rb +189 -0
  8. data/lib/insight/database.rb +186 -0
  9. data/lib/insight/enable-button.rb +43 -0
  10. data/lib/insight/filtered_backtrace.rb +45 -0
  11. data/lib/insight/instrumentation.rb +9 -0
  12. data/lib/insight/instrumentation/backstage.rb +10 -0
  13. data/lib/insight/instrumentation/client.rb +20 -0
  14. data/lib/insight/instrumentation/instrument.rb +109 -0
  15. data/lib/insight/instrumentation/package-definition.rb +58 -0
  16. data/lib/insight/instrumentation/probe-definition.rb +20 -0
  17. data/lib/insight/instrumentation/probe.rb +199 -0
  18. data/lib/insight/instrumentation/setup.rb +32 -0
  19. data/lib/insight/logger.rb +55 -0
  20. data/lib/insight/options.rb +102 -0
  21. data/lib/insight/panel.rb +119 -0
  22. data/lib/insight/panel_app.rb +31 -0
  23. data/lib/insight/panels-content.rb +22 -0
  24. data/lib/insight/panels-header.rb +18 -0
  25. data/lib/insight/panels/active_record_panel.rb +46 -0
  26. data/lib/insight/panels/cache_panel.rb +69 -0
  27. data/lib/insight/panels/cache_panel/panel_app.rb +46 -0
  28. data/lib/insight/panels/cache_panel/stats.rb +98 -0
  29. data/lib/insight/panels/log_panel.rb +54 -0
  30. data/lib/insight/panels/memory_panel.rb +32 -0
  31. data/lib/insight/panels/rails_info_panel.rb +19 -0
  32. data/lib/insight/panels/redis_panel.rb +42 -0
  33. data/lib/insight/panels/redis_panel/redis_extension.rb +23 -0
  34. data/lib/insight/panels/redis_panel/stats.rb +50 -0
  35. data/lib/insight/panels/request_variables_panel.rb +70 -0
  36. data/lib/insight/panels/speedtracer_panel.rb +89 -0
  37. data/lib/insight/panels/speedtracer_panel/trace-app.rb +52 -0
  38. data/lib/insight/panels/speedtracer_panel/tracer.rb +212 -0
  39. data/lib/insight/panels/sql_panel.rb +53 -0
  40. data/lib/insight/panels/sql_panel/panel_app.rb +37 -0
  41. data/lib/insight/panels/sql_panel/query.rb +94 -0
  42. data/lib/insight/panels/templates_panel.rb +58 -0
  43. data/lib/insight/panels/templates_panel/rendering.rb +81 -0
  44. data/lib/insight/panels/timer_panel.rb +40 -0
  45. data/lib/insight/params_signature.rb +61 -0
  46. data/lib/insight/public/__insight__/bookmarklet.html +10 -0
  47. data/lib/insight/public/__insight__/bookmarklet.js +223 -0
  48. data/lib/insight/public/__insight__/insight.css +235 -0
  49. data/lib/insight/public/__insight__/insight.js +123 -0
  50. data/lib/insight/public/__insight__/jquery-1.3.2.js +4376 -0
  51. data/lib/insight/public/__insight__/jquery.tablesorter.min.js +1 -0
  52. data/lib/insight/public/__insight__/spinner.gif +0 -0
  53. data/lib/insight/rack_static_bug_avoider.rb +16 -0
  54. data/lib/insight/redirect_interceptor.rb +25 -0
  55. data/lib/insight/render.rb +72 -0
  56. data/lib/insight/request-recorder.rb +23 -0
  57. data/lib/insight/toolbar.rb +63 -0
  58. data/lib/insight/views/enable-button.html.erb +1 -0
  59. data/lib/insight/views/error.html.erb +17 -0
  60. data/lib/insight/views/headers_fragment.html.erb +20 -0
  61. data/lib/insight/views/panels/active_record.html.erb +17 -0
  62. data/lib/insight/views/panels/cache.html.erb +93 -0
  63. data/lib/insight/views/panels/execute_sql.html.erb +32 -0
  64. data/lib/insight/views/panels/explain_sql.html.erb +32 -0
  65. data/lib/insight/views/panels/log.html.erb +21 -0
  66. data/lib/insight/views/panels/profile_sql.html.erb +32 -0
  67. data/lib/insight/views/panels/rails_info.html.erb +19 -0
  68. data/lib/insight/views/panels/redis.html.erb +46 -0
  69. data/lib/insight/views/panels/request_variables.html.erb +25 -0
  70. data/lib/insight/views/panels/speedtracer/serverevent.html.erb +10 -0
  71. data/lib/insight/views/panels/speedtracer/servertrace.html.erb +12 -0
  72. data/lib/insight/views/panels/speedtracer/traces.html.erb +18 -0
  73. data/lib/insight/views/panels/sql.html.erb +43 -0
  74. data/lib/insight/views/panels/templates.html.erb +6 -0
  75. data/lib/insight/views/panels/timer.html.erb +19 -0
  76. data/lib/insight/views/panels/view_cache.html.erb +19 -0
  77. data/lib/insight/views/redirect.html.erb +16 -0
  78. data/lib/insight/views/request_fragment.html.erb +25 -0
  79. data/lib/insight/views/toolbar.html.erb +29 -0
  80. data/lib/logical-insight.rb +1 -0
  81. data/spec/custom_matchers.rb +31 -0
  82. data/spec/fixtures/config.ru +8 -0
  83. data/spec/fixtures/dummy_panel.rb +2 -0
  84. data/spec/fixtures/sample_app.rb +72 -0
  85. data/spec/insight/panels/active_record_panel_spec.rb +42 -0
  86. data/spec/insight/panels/cache_panel_spec.rb +176 -0
  87. data/spec/insight/panels/log_panel_spec.rb +44 -0
  88. data/spec/insight/panels/memory_panel_spec.rb +19 -0
  89. data/spec/insight/panels/mongo_panel_spec_pending.rb +50 -0
  90. data/spec/insight/panels/rails_info_panel_spec.rb +27 -0
  91. data/spec/insight/panels/redis_panel_spec.rb +66 -0
  92. data/spec/insight/panels/sql_panel_spec.rb +145 -0
  93. data/spec/insight/panels/templates_panel_spec.rb +84 -0
  94. data/spec/insight/panels/timer_panel_spec.rb +36 -0
  95. data/spec/insight_spec.rb +141 -0
  96. data/spec/instrumentation_spec.rb +188 -0
  97. data/spec/rcov.opts +1 -0
  98. data/spec/spec.opts +1 -0
  99. data/spec/spec_helper.rb +93 -0
  100. 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("&amp;")
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
+ }