r509-ocsp-responder 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/README.md +77 -0
  2. data/Rakefile +38 -0
  3. data/doc/R509.html +115 -0
  4. data/doc/R509/Ocsp.html +130 -0
  5. data/doc/R509/Ocsp/Helper.html +126 -0
  6. data/doc/R509/Ocsp/Helper/RequestChecker.html +739 -0
  7. data/doc/R509/Ocsp/Helper/ResponseSigner.html +583 -0
  8. data/doc/R509/Ocsp/Responder.html +129 -0
  9. data/doc/R509/Ocsp/Responder/OcspConfig.html +289 -0
  10. data/doc/R509/Ocsp/Responder/Server.html +128 -0
  11. data/doc/R509/Ocsp/Responder/StatusError.html +134 -0
  12. data/doc/R509/Ocsp/Signer.html +584 -0
  13. data/doc/_index.html +197 -0
  14. data/doc/class_list.html +53 -0
  15. data/doc/css/common.css +1 -0
  16. data/doc/css/full_list.css +57 -0
  17. data/doc/css/style.css +328 -0
  18. data/doc/file.README.html +156 -0
  19. data/doc/file_list.html +55 -0
  20. data/doc/frames.html +28 -0
  21. data/doc/index.html +156 -0
  22. data/doc/js/app.js +214 -0
  23. data/doc/js/full_list.js +173 -0
  24. data/doc/js/jquery.js +4 -0
  25. data/doc/method_list.html +164 -0
  26. data/doc/top-level-namespace.html +112 -0
  27. data/lib/r509/ocsp/responder/ocsp-config.rb +35 -0
  28. data/lib/r509/ocsp/responder/server.rb +169 -0
  29. data/lib/r509/ocsp/responder/version.rb +7 -0
  30. data/lib/r509/ocsp/signer.rb +244 -0
  31. data/spec/fixtures.rb +196 -0
  32. data/spec/fixtures/cert1.pem +24 -0
  33. data/spec/fixtures/config_test_various.yaml +46 -0
  34. data/spec/fixtures/ocsptest.r509.local.pem +27 -0
  35. data/spec/fixtures/second_ca.cer +26 -0
  36. data/spec/fixtures/second_ca.key +27 -0
  37. data/spec/fixtures/stca.pem +22 -0
  38. data/spec/fixtures/stca_ocsp_request.der +0 -0
  39. data/spec/fixtures/stca_ocsp_response.der +0 -0
  40. data/spec/fixtures/test_ca.cer +22 -0
  41. data/spec/fixtures/test_ca.key +28 -0
  42. data/spec/fixtures/test_ca_ocsp.cer +26 -0
  43. data/spec/fixtures/test_ca_ocsp.key +27 -0
  44. data/spec/fixtures/test_ca_ocsp_chain.txt +48 -0
  45. data/spec/fixtures/test_ca_request.der +0 -0
  46. data/spec/fixtures/test_ca_response.der +0 -0
  47. data/spec/fixtures/test_ca_subroot.cer +25 -0
  48. data/spec/fixtures/test_ca_subroot.key +27 -0
  49. data/spec/fixtures/test_ca_subroot_ocsp.cer +25 -0
  50. data/spec/fixtures/test_ca_subroot_ocsp.key +27 -0
  51. data/spec/fixtures/test_config.yaml +17 -0
  52. data/spec/server_spec.rb +400 -0
  53. data/spec/signer_spec.rb +275 -0
  54. data/spec/spec_helper.rb +18 -0
  55. metadata +259 -0
@@ -0,0 +1,156 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6
+ <title>
7
+ File: README
8
+
9
+ &mdash; Documentation by YARD 0.8.2.1
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ hasFrames = window.top.frames.main ? true : false;
19
+ relpath = '';
20
+ framesUrl = "frames.html#!" + escape(window.location.href);
21
+ </script>
22
+
23
+
24
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
25
+
26
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
27
+
28
+
29
+ </head>
30
+ <body>
31
+ <div id="header">
32
+ <div id="menu">
33
+
34
+ <a href="_index.html">Index</a> &raquo;
35
+ <span class="title">File: README</span>
36
+
37
+
38
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
39
+ </div>
40
+
41
+ <div id="search">
42
+
43
+ <a class="full_list_link" id="class_list_link"
44
+ href="class_list.html">
45
+ Class List
46
+ </a>
47
+
48
+ <a class="full_list_link" id="method_list_link"
49
+ href="method_list.html">
50
+ Method List
51
+ </a>
52
+
53
+ <a class="full_list_link" id="file_list_link"
54
+ href="file_list.html">
55
+ File List
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <iframe id="search_frame"></iframe>
63
+
64
+ <div id="content"><div id='filecontents'><h1>r509-ocsp-responder <a href="http://travis-ci.org/reaperhulk/r509-ocsp-responder"><img src="https://secure.travis-ci.org/reaperhulk/r509-ocsp-responder.png" alt="Build Status"></a></h1>
65
+
66
+ <p>r509-ocsp-responder is an OCSP responder written using <a href="https://github.com/reaperhulk/r509">r509</a> and Sinatra to conform to RFC <a href="http://www.ietf.org/rfc/rfc2560.txt">2560</a> and <a href="http://www.ietf.org/rfc/rfc5019.txt">5019</a>.</p>
67
+
68
+ <h2>Requirements</h2>
69
+
70
+ <p>r509-ocsp-responder depends on <a href="https://github.com/reaperhulk/r509">r509</a>, <a href="http://redis.io">redis</a>, <a href="https://github.com/sirsean/r509-validity-redis">r509-validity-redis</a> (or another library that implements R509::Validity), <a href="http://sinatrarb.com">sinatra</a>, <a href="https://github.com/sirsean/r509-ocsp-stats">r509-ocsp-stats</a>, and <a href="https://github.com/sirsean/dependo">dependo</a>. These must be installed as gems.</p>
71
+
72
+ <h2>Basic Usage</h2>
73
+
74
+ <ol>
75
+ <li>Build the gem. If you have cloned the repo you can build the gem with <code>rake gem:build</code>. You will need</li>
76
+ <li>Install the gem. <code>rake gem:install</code></li>
77
+ <li>Set up your config.ru and config.yaml. At this time you&#39;ll need to copy the config.ru from the gem install to another dir with your config.yaml. You should also copy (and modify) the config.yaml.example file from the gem. You&#39;ll need to alter the config.ru&#39;s require line from <code>require &#39;./lib/r509/ocsp/responder/server&#39;</code> to <code>require &#39;r509/ocsp/responder/server&#39;</code> if you have it installed as a gem.</li>
78
+ </ol>
79
+
80
+ <p>Once you&#39;ve done that you can set up your rack server. The example below is an example yaml config for thin. You will want to have as many servers as you have cores.</p>
81
+
82
+ <pre class="code yaml"><code>chdir: /var/www/r509-ocsp-responder
83
+ rackup: /var/www/r509-ocsp-responder/config.ru
84
+ socket: /var/run/r509-ocsp-responder.sock
85
+ pid: /var/run/r509-ocsp-responder.pid
86
+ servers: 2
87
+ daemonize: true
88
+ log: /var/log/r509-ocsp-responder.log
89
+ </code></pre>
90
+
91
+ <p>Since this config is just using sockets let&#39;s set up nginx as a reverse proxy for the thin instances. We can also use this as a caching layer if we choose to enable cache_headers.</p>
92
+
93
+ <pre class="code ruby"><code>proxy_cache_path /var/www/cache levels=1:2 keys_zone=ocsp:8m max_size=16m inactive=64m;
94
+ proxy_temp_path /var/www/cache/tmp;
95
+
96
+ upstream thin_ocsp_responder{
97
+ server unix:/var/run/r509-ocsp-responder.0.sock fail_timeout=0;
98
+ server unix:/var/run/r509-ocsp-responder.1.sock fail_timeout=0;
99
+ }
100
+ server {
101
+ listen 80;
102
+ server_name ocsp.r509.org;
103
+
104
+ location / {
105
+ proxy_pass http://thin_ocsp_responder;
106
+ proxy_cache ocsp;
107
+ proxy_cache_use_stale updating;
108
+ }
109
+ }
110
+ </code></pre>
111
+
112
+ <p>Within the location block you may also choose to add these directives:</p>
113
+
114
+ <pre class="code ruby"><code>proxy_cache_methods GET POST;
115
+ proxy_cache_valid 200 302 1m;
116
+ </code></pre>
117
+
118
+ <p>If present, these lines will cause 200 and 302 responses to POST and GET to be cached for 1 minute. This allows you to cache POST requests (Note: Per the HTTP RFC POST requests should not be cached) in addition to the GET requests normally supported by the ruby layer. <strong>NOTE:</strong> The proxy_cache_valid values are lower priority than caching headers sent by the thin instances so if you do not keep the value here in sync with the max_cache_age config (or turn off cache_headers entirely and solely control it through nginx) you will have mismatched cache times. Additionally, this will cache nonced responses, which wastes RAM since they will not be re-used.</p>
119
+
120
+ <p>If you would like to track the cache utilization you can also modify the nginx logging to track cache hits. There are a variety of ways this can be accomplisehd, but one of the simplest is simply to alter your log_format line to add <code>$upstream_cache_status</code>.</p>
121
+
122
+ <h2>Options</h2>
123
+
124
+ <p>This OCSP responder supports several optional flags (in addition to supporting an arbitrary number of responder certificates).</p>
125
+
126
+ <ul>
127
+ <li><p><strong>copy_nonce</strong> - (true/false) Sets whether to copy the nonce from request to response (if present)</p></li>
128
+ <li><p><strong>cache_headers</strong> - (true/false) Sets whether to set HTTP headers for caching GET responses. Coupled with a reverse proxy you can cache responses for a finite period and vastly speed up the response time of your server (at the cost of response freshness). Nonced requests will not be cached. The performance benefit of caching can vary drastically depending on the mix of clients connecting to the OCSP responder.</p></li>
129
+ <li><p><strong>max_cache_age</strong> - (integer) Sets the maximum age in <strong>seconds</strong> a response can be cached. At this time r509-ocsp-responder does not support cache invalidation so it is recommended to set this to a low value to reduce the time you may serve stale responses in the event of a revocation.</p></li>
130
+ </ul>
131
+
132
+ <p>See the config.yaml.example for an example configuration.</p>
133
+
134
+ <h2>Signals</h2>
135
+
136
+ <p>You can send a kill -USR2 signal to any running r509-ocsp-responder process to cause it to reload and print its config to the logs (provided your app server isn&#39;t trapping USR2 first).</p>
137
+
138
+ <h2>Running Tests</h2>
139
+
140
+ <p>You&#39;ll need rspec, rake, and rack-test to run the tests. With these gems in place run <code>rake spec</code></p>
141
+
142
+ <h2>Future Ideas</h2>
143
+
144
+ <ul>
145
+ <li>Devise a mechanism for doing automated OCSP delegate certificate renewal</li>
146
+ </ul>
147
+ </div></div>
148
+
149
+ <div id="footer">
150
+ Generated on Thu Nov 8 14:33:52 2012 by
151
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
152
+ 0.8.2.1 (ruby-1.9.3).
153
+ </div>
154
+
155
+ </body>
156
+ </html>
@@ -0,0 +1,55 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html>
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+
7
+ <link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen" charset="utf-8" />
8
+
9
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
10
+
11
+
12
+
13
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
14
+
15
+ <script type="text/javascript" charset="utf-8" src="js/full_list.js"></script>
16
+
17
+
18
+ <base id="base_target" target="_parent" />
19
+ </head>
20
+ <body>
21
+ <script type="text/javascript" charset="utf-8">
22
+ if (window.top.frames.main) {
23
+ document.getElementById('base_target').target = 'main';
24
+ document.body.className = 'frames';
25
+ }
26
+ </script>
27
+ <div id="content">
28
+ <h1 id="full_list_header">File List</h1>
29
+ <div id="nav">
30
+
31
+ <span><a target="_self" href="class_list.html">
32
+ Classes
33
+ </a></span>
34
+
35
+ <span><a target="_self" href="method_list.html">
36
+ Methods
37
+ </a></span>
38
+
39
+ <span><a target="_self" href="file_list.html">
40
+ Files
41
+ </a></span>
42
+
43
+ </div>
44
+ <div id="search">Search: <input type="text" /></div>
45
+
46
+ <ul id="full_list" class="file">
47
+
48
+
49
+ <li class="r1"><a href="index.html" title="README">README</a></li>
50
+
51
+
52
+ </ul>
53
+ </div>
54
+ </body>
55
+ </html>
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
3
+
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
+ <head>
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
+ <title>Documentation by YARD 0.8.2.1</title>
8
+ </head>
9
+ <script type="text/javascript" charset="utf-8">
10
+ window.onload = function() {
11
+ var match = window.location.hash.match(/^#!(.+)/);
12
+ var name = 'index.html';
13
+ if (match) {
14
+ name = unescape(match[1]);
15
+ }
16
+ document.writeln('<frameset cols="20%,*">' +
17
+ '<frame name="list" src="class_list.html" />' +
18
+ '<frame name="main" src="' + name + '" />' +
19
+ '</frameset>');
20
+ }
21
+ </script>
22
+ <noscript>
23
+ <frameset cols="20%,*">
24
+ <frame name="list" src="class_list.html" />
25
+ <frame name="main" src="index.html" />
26
+ </frameset>
27
+ </noscript>
28
+ </html>
@@ -0,0 +1,156 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6
+ <title>
7
+ File: README
8
+
9
+ &mdash; Documentation by YARD 0.8.2.1
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ hasFrames = window.top.frames.main ? true : false;
19
+ relpath = '';
20
+ framesUrl = "frames.html#!" + escape(window.location.href);
21
+ </script>
22
+
23
+
24
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
25
+
26
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
27
+
28
+
29
+ </head>
30
+ <body>
31
+ <div id="header">
32
+ <div id="menu">
33
+
34
+ <a href="_index.html">Index</a> &raquo;
35
+ <span class="title">File: README</span>
36
+
37
+
38
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
39
+ </div>
40
+
41
+ <div id="search">
42
+
43
+ <a class="full_list_link" id="class_list_link"
44
+ href="class_list.html">
45
+ Class List
46
+ </a>
47
+
48
+ <a class="full_list_link" id="method_list_link"
49
+ href="method_list.html">
50
+ Method List
51
+ </a>
52
+
53
+ <a class="full_list_link" id="file_list_link"
54
+ href="file_list.html">
55
+ File List
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <iframe id="search_frame"></iframe>
63
+
64
+ <div id="content"><div id='filecontents'><h1>r509-ocsp-responder <a href="http://travis-ci.org/reaperhulk/r509-ocsp-responder"><img src="https://secure.travis-ci.org/reaperhulk/r509-ocsp-responder.png" alt="Build Status"></a></h1>
65
+
66
+ <p>r509-ocsp-responder is an OCSP responder written using <a href="https://github.com/reaperhulk/r509">r509</a> and Sinatra to conform to RFC <a href="http://www.ietf.org/rfc/rfc2560.txt">2560</a> and <a href="http://www.ietf.org/rfc/rfc5019.txt">5019</a>.</p>
67
+
68
+ <h2>Requirements</h2>
69
+
70
+ <p>r509-ocsp-responder depends on <a href="https://github.com/reaperhulk/r509">r509</a>, <a href="http://redis.io">redis</a>, <a href="https://github.com/sirsean/r509-validity-redis">r509-validity-redis</a> (or another library that implements R509::Validity), <a href="http://sinatrarb.com">sinatra</a>, <a href="https://github.com/sirsean/r509-ocsp-stats">r509-ocsp-stats</a>, and <a href="https://github.com/sirsean/dependo">dependo</a>. These must be installed as gems.</p>
71
+
72
+ <h2>Basic Usage</h2>
73
+
74
+ <ol>
75
+ <li>Build the gem. If you have cloned the repo you can build the gem with <code>rake gem:build</code>. You will need</li>
76
+ <li>Install the gem. <code>rake gem:install</code></li>
77
+ <li>Set up your config.ru and config.yaml. At this time you&#39;ll need to copy the config.ru from the gem install to another dir with your config.yaml. You should also copy (and modify) the config.yaml.example file from the gem. You&#39;ll need to alter the config.ru&#39;s require line from <code>require &#39;./lib/r509/ocsp/responder/server&#39;</code> to <code>require &#39;r509/ocsp/responder/server&#39;</code> if you have it installed as a gem.</li>
78
+ </ol>
79
+
80
+ <p>Once you&#39;ve done that you can set up your rack server. The example below is an example yaml config for thin. You will want to have as many servers as you have cores.</p>
81
+
82
+ <pre class="code yaml"><code>chdir: /var/www/r509-ocsp-responder
83
+ rackup: /var/www/r509-ocsp-responder/config.ru
84
+ socket: /var/run/r509-ocsp-responder.sock
85
+ pid: /var/run/r509-ocsp-responder.pid
86
+ servers: 2
87
+ daemonize: true
88
+ log: /var/log/r509-ocsp-responder.log
89
+ </code></pre>
90
+
91
+ <p>Since this config is just using sockets let&#39;s set up nginx as a reverse proxy for the thin instances. We can also use this as a caching layer if we choose to enable cache_headers.</p>
92
+
93
+ <pre class="code ruby"><code>proxy_cache_path /var/www/cache levels=1:2 keys_zone=ocsp:8m max_size=16m inactive=64m;
94
+ proxy_temp_path /var/www/cache/tmp;
95
+
96
+ upstream thin_ocsp_responder{
97
+ server unix:/var/run/r509-ocsp-responder.0.sock fail_timeout=0;
98
+ server unix:/var/run/r509-ocsp-responder.1.sock fail_timeout=0;
99
+ }
100
+ server {
101
+ listen 80;
102
+ server_name ocsp.r509.org;
103
+
104
+ location / {
105
+ proxy_pass http://thin_ocsp_responder;
106
+ proxy_cache ocsp;
107
+ proxy_cache_use_stale updating;
108
+ }
109
+ }
110
+ </code></pre>
111
+
112
+ <p>Within the location block you may also choose to add these directives:</p>
113
+
114
+ <pre class="code ruby"><code>proxy_cache_methods GET POST;
115
+ proxy_cache_valid 200 302 1m;
116
+ </code></pre>
117
+
118
+ <p>If present, these lines will cause 200 and 302 responses to POST and GET to be cached for 1 minute. This allows you to cache POST requests (Note: Per the HTTP RFC POST requests should not be cached) in addition to the GET requests normally supported by the ruby layer. <strong>NOTE:</strong> The proxy_cache_valid values are lower priority than caching headers sent by the thin instances so if you do not keep the value here in sync with the max_cache_age config (or turn off cache_headers entirely and solely control it through nginx) you will have mismatched cache times. Additionally, this will cache nonced responses, which wastes RAM since they will not be re-used.</p>
119
+
120
+ <p>If you would like to track the cache utilization you can also modify the nginx logging to track cache hits. There are a variety of ways this can be accomplisehd, but one of the simplest is simply to alter your log_format line to add <code>$upstream_cache_status</code>.</p>
121
+
122
+ <h2>Options</h2>
123
+
124
+ <p>This OCSP responder supports several optional flags (in addition to supporting an arbitrary number of responder certificates).</p>
125
+
126
+ <ul>
127
+ <li><p><strong>copy_nonce</strong> - (true/false) Sets whether to copy the nonce from request to response (if present)</p></li>
128
+ <li><p><strong>cache_headers</strong> - (true/false) Sets whether to set HTTP headers for caching GET responses. Coupled with a reverse proxy you can cache responses for a finite period and vastly speed up the response time of your server (at the cost of response freshness). Nonced requests will not be cached. The performance benefit of caching can vary drastically depending on the mix of clients connecting to the OCSP responder.</p></li>
129
+ <li><p><strong>max_cache_age</strong> - (integer) Sets the maximum age in <strong>seconds</strong> a response can be cached. At this time r509-ocsp-responder does not support cache invalidation so it is recommended to set this to a low value to reduce the time you may serve stale responses in the event of a revocation.</p></li>
130
+ </ul>
131
+
132
+ <p>See the config.yaml.example for an example configuration.</p>
133
+
134
+ <h2>Signals</h2>
135
+
136
+ <p>You can send a kill -USR2 signal to any running r509-ocsp-responder process to cause it to reload and print its config to the logs (provided your app server isn&#39;t trapping USR2 first).</p>
137
+
138
+ <h2>Running Tests</h2>
139
+
140
+ <p>You&#39;ll need rspec, rake, and rack-test to run the tests. With these gems in place run <code>rake spec</code></p>
141
+
142
+ <h2>Future Ideas</h2>
143
+
144
+ <ul>
145
+ <li>Devise a mechanism for doing automated OCSP delegate certificate renewal</li>
146
+ </ul>
147
+ </div></div>
148
+
149
+ <div id="footer">
150
+ Generated on Thu Nov 8 14:33:52 2012 by
151
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
152
+ 0.8.2.1 (ruby-1.9.3).
153
+ </div>
154
+
155
+ </body>
156
+ </html>
@@ -0,0 +1,214 @@
1
+ function createSourceLinks() {
2
+ $('.method_details_list .source_code').
3
+ before("<span class='showSource'>[<a href='#' class='toggleSource'>View source</a>]</span>");
4
+ $('.toggleSource').toggle(function() {
5
+ $(this).parent().nextAll('.source_code').slideDown(100);
6
+ $(this).text("Hide source");
7
+ },
8
+ function() {
9
+ $(this).parent().nextAll('.source_code').slideUp(100);
10
+ $(this).text("View source");
11
+ });
12
+ }
13
+
14
+ function createDefineLinks() {
15
+ var tHeight = 0;
16
+ $('.defines').after(" <a href='#' class='toggleDefines'>more...</a>");
17
+ $('.toggleDefines').toggle(function() {
18
+ tHeight = $(this).parent().prev().height();
19
+ $(this).prev().show();
20
+ $(this).parent().prev().height($(this).parent().height());
21
+ $(this).text("(less)");
22
+ },
23
+ function() {
24
+ $(this).prev().hide();
25
+ $(this).parent().prev().height(tHeight);
26
+ $(this).text("more...");
27
+ });
28
+ }
29
+
30
+ function createFullTreeLinks() {
31
+ var tHeight = 0;
32
+ $('.inheritanceTree').toggle(function() {
33
+ tHeight = $(this).parent().prev().height();
34
+ $(this).parent().toggleClass('showAll');
35
+ $(this).text("(hide)");
36
+ $(this).parent().prev().height($(this).parent().height());
37
+ },
38
+ function() {
39
+ $(this).parent().toggleClass('showAll');
40
+ $(this).parent().prev().height(tHeight);
41
+ $(this).text("show all");
42
+ });
43
+ }
44
+
45
+ function fixBoxInfoHeights() {
46
+ $('dl.box dd.r1, dl.box dd.r2').each(function() {
47
+ $(this).prev().height($(this).height());
48
+ });
49
+ }
50
+
51
+ function searchFrameLinks() {
52
+ $('.full_list_link').click(function() {
53
+ toggleSearchFrame(this, $(this).attr('href'));
54
+ return false;
55
+ });
56
+ }
57
+
58
+ function toggleSearchFrame(id, link) {
59
+ var frame = $('#search_frame');
60
+ $('#search a').removeClass('active').addClass('inactive');
61
+ if (frame.attr('src') == link && frame.css('display') != "none") {
62
+ frame.slideUp(100);
63
+ $('#search a').removeClass('active inactive');
64
+ }
65
+ else {
66
+ $(id).addClass('active').removeClass('inactive');
67
+ frame.attr('src', link).slideDown(100);
68
+ }
69
+ }
70
+
71
+ function linkSummaries() {
72
+ $('.summary_signature').click(function() {
73
+ document.location = $(this).find('a').attr('href');
74
+ });
75
+ }
76
+
77
+ function framesInit() {
78
+ if (hasFrames) {
79
+ document.body.className = 'frames';
80
+ $('#menu .noframes a').attr('href', document.location);
81
+ window.top.document.title = $('html head title').text();
82
+ }
83
+ else {
84
+ $('#menu .noframes a').text('frames').attr('href', framesUrl);
85
+ }
86
+ }
87
+
88
+ function keyboardShortcuts() {
89
+ if (window.top.frames.main) return;
90
+ $(document).keypress(function(evt) {
91
+ if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) return;
92
+ if (typeof evt.target !== "undefined" &&
93
+ (evt.target.nodeName == "INPUT" ||
94
+ evt.target.nodeName == "TEXTAREA")) return;
95
+ switch (evt.charCode) {
96
+ case 67: case 99: $('#class_list_link').click(); break; // 'c'
97
+ case 77: case 109: $('#method_list_link').click(); break; // 'm'
98
+ case 70: case 102: $('#file_list_link').click(); break; // 'f'
99
+ default: break;
100
+ }
101
+ });
102
+ }
103
+
104
+ function summaryToggle() {
105
+ $('.summary_toggle').click(function() {
106
+ if (localStorage) {
107
+ localStorage.summaryCollapsed = $(this).text();
108
+ }
109
+ $('.summary_toggle').each(function() {
110
+ $(this).text($(this).text() == "collapse" ? "expand" : "collapse");
111
+ var next = $(this).parent().parent().nextAll('ul.summary').first();
112
+ if (next.hasClass('compact')) {
113
+ next.toggle();
114
+ next.nextAll('ul.summary').first().toggle();
115
+ }
116
+ else if (next.hasClass('summary')) {
117
+ var list = $('<ul class="summary compact" />');
118
+ list.html(next.html());
119
+ list.find('.summary_desc, .note').remove();
120
+ list.find('a').each(function() {
121
+ $(this).html($(this).find('strong').html());
122
+ $(this).parent().html($(this)[0].outerHTML);
123
+ });
124
+ next.before(list);
125
+ next.toggle();
126
+ }
127
+ });
128
+ return false;
129
+ });
130
+ if (localStorage) {
131
+ if (localStorage.summaryCollapsed == "collapse") {
132
+ $('.summary_toggle').first().click();
133
+ }
134
+ else localStorage.summaryCollapsed = "expand";
135
+ }
136
+ }
137
+
138
+ function fixOutsideWorldLinks() {
139
+ $('a').each(function() {
140
+ if (window.location.host != this.host) this.target = '_parent';
141
+ });
142
+ }
143
+
144
+ function generateTOC() {
145
+ if ($('#filecontents').length === 0) return;
146
+ var _toc = $('<ol class="top"></ol>');
147
+ var show = false;
148
+ var toc = _toc;
149
+ var counter = 0;
150
+ var tags = ['h2', 'h3', 'h4', 'h5', 'h6'];
151
+ var i;
152
+ if ($('#filecontents h1').length > 1) tags.unshift('h1');
153
+ for (i = 0; i < tags.length; i++) { tags[i] = '#filecontents ' + tags[i]; }
154
+ var lastTag = parseInt(tags[0][1], 10);
155
+ $(tags.join(', ')).each(function() {
156
+ if ($(this).parents('.method_details .docstring').length != 0) return;
157
+ if (this.id == "filecontents") return;
158
+ show = true;
159
+ var thisTag = parseInt(this.tagName[1], 10);
160
+ if (this.id.length === 0) {
161
+ var proposedId = $(this).attr('toc-id');
162
+ if (typeof(proposedId) != "undefined") this.id = proposedId;
163
+ else {
164
+ var proposedId = $(this).text().replace(/[^a-z0-9-]/ig, '_');
165
+ if ($('#' + proposedId).length > 0) { proposedId += counter; counter++; }
166
+ this.id = proposedId;
167
+ }
168
+ }
169
+ if (thisTag > lastTag) {
170
+ for (i = 0; i < thisTag - lastTag; i++) {
171
+ var tmp = $('<ol/>'); toc.append(tmp); toc = tmp;
172
+ }
173
+ }
174
+ if (thisTag < lastTag) {
175
+ for (i = 0; i < lastTag - thisTag; i++) toc = toc.parent();
176
+ }
177
+ var title = $(this).attr('toc-title');
178
+ if (typeof(title) == "undefined") title = $(this).text();
179
+ toc.append('<li><a href="#' + this.id + '">' + title + '</a></li>');
180
+ lastTag = thisTag;
181
+ });
182
+ if (!show) return;
183
+ html = '<div id="toc"><p class="title"><a class="hide_toc" href="#"><strong>Table of Contents</strong></a> <small>(<a href="#" class="float_toc">left</a>)</small></p></div>';
184
+ $('#content').prepend(html);
185
+ $('#toc').append(_toc);
186
+ $('#toc .hide_toc').toggle(function() {
187
+ $('#toc .top').slideUp('fast');
188
+ $('#toc').toggleClass('hidden');
189
+ $('#toc .title small').toggle();
190
+ }, function() {
191
+ $('#toc .top').slideDown('fast');
192
+ $('#toc').toggleClass('hidden');
193
+ $('#toc .title small').toggle();
194
+ });
195
+ $('#toc .float_toc').toggle(function() {
196
+ $(this).text('float');
197
+ $('#toc').toggleClass('nofloat');
198
+ }, function() {
199
+ $(this).text('left');
200
+ $('#toc').toggleClass('nofloat');
201
+ });
202
+ }
203
+
204
+ $(framesInit);
205
+ $(createSourceLinks);
206
+ $(createDefineLinks);
207
+ $(createFullTreeLinks);
208
+ $(fixBoxInfoHeights);
209
+ $(searchFrameLinks);
210
+ $(linkSummaries);
211
+ $(keyboardShortcuts);
212
+ $(summaryToggle);
213
+ $(fixOutsideWorldLinks);
214
+ $(generateTOC);