passenger 3.0.19 → 3.0.21

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

@@ -0,0 +1,12 @@
1
+ -----BEGIN PGP SIGNATURE-----
2
+ Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
3
+ Comment: GPGTools - http://gpgtools.org
4
+
5
+ iQEcBAABAgAGBQJRpfApAAoJECrHRaUKISqMopkIAKS0mOJ09YCFd9yaUgHIqcDH
6
+ rrbZ7G+vkQ0W/CFeT6l+taM2ZARn9m97pAQrl/0p2dD7fzK6dah5+2MObRBhgcKw
7
+ RrtbRUHQ46Xz+0Y5yMuTvMh9tIwwsbbd+9kjc2IkH9CuZWBMmRCI61c9HozoFN/b
8
+ /OGkKDx7Mh0iNzPhq9VG4e/h4Kktq5I2EsuXxIo47bi6W2N2VDh1ZzdHtgO6LEpr
9
+ edUc9qFOYdRkkdUiLxTp3Yt4X4Qs1D4bI1N8g56QbOGY3ULbYssji6sxR1MNswz6
10
+ Jt9H35NUcap1yRpEwYcX7KSkI2WkF6H31OOKYNTDdXd13FJk/mODIoHbbANaiAg=
11
+ =U73p
12
+ -----END PGP SIGNATURE-----
data/NEWS CHANGED
@@ -1,3 +1,15 @@
1
+ Release 3.0.21
2
+ --------------
3
+
4
+ * Rebootstrapped the libev configure to fix compilation problems on Solaris 11.
5
+ * Fixed support for RVM mixed mode installations. Fixes issue #828.
6
+ * Fixed encoding problems in Phusion Passenger Standalone.
7
+ * Changed preferred Nginx version to 1.2.9.
8
+ * Catch exceptions raised by Rack application objects.
9
+ * Fix for CVE-2013-2119. Details can be found in the announcement for version 4.0.5.
10
+ * Version 3.0.20 was pulled because its fixes were incomplete.
11
+
12
+
1
13
  Release 3.0.19
2
14
  --------------
3
15
 
@@ -27,6 +27,7 @@ $LOAD_PATH.unshift("#{passenger_root}/lib")
27
27
  require 'phusion_passenger'
28
28
  require 'optparse'
29
29
  require 'fileutils'
30
+ require 'tmpdir'
30
31
  require 'phusion_passenger/platform_info/ruby'
31
32
  require 'phusion_passenger/dependencies'
32
33
  require 'phusion_passenger/abstract_installer'
@@ -108,14 +109,12 @@ class Installer < PhusionPassenger::AbstractInstaller
108
109
  def before_install
109
110
  super
110
111
  myself = `whoami`.strip
111
- @working_dir = "/tmp/#{myself}-passenger-#{Process.pid}"
112
- FileUtils.rm_rf(@working_dir)
113
- FileUtils.mkdir_p(@working_dir)
112
+ @working_dir = Dir.mktmpdir("passenger.")
114
113
  end
115
114
 
116
115
  def after_install
117
116
  super
118
- FileUtils.rm_rf(@working_dir)
117
+ FileUtils.remove_entry_secure(@working_dir) if @working_dir
119
118
  end
120
119
 
121
120
  private
@@ -1,9 +1,9 @@
1
1
  <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5
- <meta name="generator" content="AsciiDoc 8.6.7">
6
- <title>Phusion Passenger design &amp; architecture</title>
2
+ <html lang="en">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5
+ <meta name="generator" content="AsciiDoc 8.6.7">
6
+ <title>Phusion Passenger design &amp; architecture</title>
7
7
  <style type="text/css">
8
8
  /* Shared CSS for AsciiDoc xhtml11 and html5 backends */
9
9
 
@@ -603,7 +603,7 @@ div.exampleblock > div.content, div.sidebarblock > div.content, div.listingblock
603
603
  div.verseblock { border-left-width: 0; margin-left: 3em; }
604
604
  div.quoteblock { border-left-width: 3px; margin-left: 0; margin-right: 0;}
605
605
  div.admonitionblock td.content { border-left: 3px solid #E8E8E8; }
606
- </style>
606
+ </style>
607
607
  <script type="text/javascript">
608
608
  /*<![CDATA[*/
609
609
  var asciidoc = { // Namespace.
@@ -795,11 +795,14 @@ install: function(toclevels) {
795
795
  }
796
796
 
797
797
  }
798
- asciidoc.install(3);
798
+ asciidoc.install();
799
799
  /*]]>*/
800
- </script><style type="text/css">
800
+ </script>
801
+ <style type="text/css">
801
802
  body {
802
- margin: 1em 10% 1em 10%;
803
+ margin: 1em auto 1em auto;
804
+ padding: 0 1em 0 1em;
805
+ max-width: 800px;
803
806
  }
804
807
 
805
808
  a.image {
@@ -878,6 +881,10 @@ a.image {
878
881
  margin: 2em;
879
882
  }
880
883
 
884
+ pre {
885
+ overflow: auto;
886
+ }
887
+
881
888
  @media print {
882
889
  body {
883
890
  font-size: 18pt;
@@ -1038,22 +1045,33 @@ a.image {
1038
1045
  border-bottom-right-radius: 0;
1039
1046
  }
1040
1047
 
1048
+ /* http://nicolasgallagher.com/jump-links-and-viewport-positioning/ */
1049
+ .anchor_helper {
1050
+ position: relative;
1051
+ display: block;
1052
+ top: -50px;
1053
+ width: 1px;
1054
+ height: 1px;
1055
+ }
1056
+
1041
1057
  </style>
1042
- </head>
1058
+ </head>
1043
1059
  <body class="article">
1044
1060
  <div id="topbar" style="display: none">
1045
1061
  <div class="title">
1046
- <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAAEV95QVAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sGCRMSACDxkZwAAAAidEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVAgb24gYSBNYWOHqHdDAAAAZUlEQVQY032PSxbAIAjEIlfygL6ePF3UUvpzNjgSYWwqAMEhUQnANnsC7TQPeJpsVWzMuh2sog4vDTUbqP081zECrW4dtdaQGSIKlWluPyjK+VXxAz5XfcKufCzA130AfQHWB30HZxlPaP080xsAAAAASUVORK5CYII=" width="11" height="10" alt=""><a href="javascript:void(Mizuho.smoothlyScrollToToc())">Phusion Passenger design &amp; architecture</a>
1062
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAAEV95QVAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sGCRMSACDxkZwAAAAidEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVAgb24gYSBNYWOHqHdDAAAAZUlEQVQY032PSxbAIAjEIlfygL6ePF3UUvpzNjgSYWwqAMEhUQnANnsC7TQPeJpsVWzMuh2sog4vDTUbqP081zECrW4dtdaQGSIKlWluPyjK+VXxAz5XfcKufCzA130AfQHWB30HZxlPaP080xsAAAAASUVORK5CYII=" width="11" height="10" alt="">
1063
+ <a href="javascript:void(Mizuho.smoothlyScrollToToc())">Phusion Passenger design &amp; architecture</a>
1047
1064
  </div>
1048
1065
  <a href="javascript:void(0)" id="current_section"></a>
1049
1066
  </div>
1050
1067
  <div id="header">
1051
- <h1>Phusion Passenger design &amp; architecture</h1>
1068
+ <h1>Phusion Passenger design &amp; architecture</h1>
1052
1069
  <div id="preamble">
1053
1070
  <div class="sectionbody">
1054
1071
  <div class="paragraph"><p><span class="image">
1055
1072
  <a class="image" href="http://www.phusion.nl/">
1056
- <img src="images/phusion_banner.png" alt="images/phusion_banner.png"></a>
1073
+ <img src="images/phusion_banner.png" alt="images/phusion_banner.png">
1074
+ </a>
1057
1075
  </span></p></div>
1058
1076
  <div class="paragraph"><p>Last updated: June 5, 2012.</p></div>
1059
1077
  <div class="paragraph"><p>This document describes Phusion Passenger’s design and architure in a global way.
@@ -1061,19 +1079,31 @@ Its purpose is to lower the barrier to entry for new contributors,
1061
1079
  to explain some of the design choices we have made and to educate people
1062
1080
  about how Phusion Passenger works.</p></div>
1063
1081
  </div>
1064
- </div>
1082
+ </div>
1065
1083
  <div id="toc">
1066
- <div id="toctitle">Table of Contents</div>
1067
- <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
1068
- </div>
1084
+ <div id="toctitle">Table of Contents</div>
1085
+ <div class="foo toclevel2"><a href="#_introduction_to_related_technologies">1. Introduction to related technologies</a></div>
1086
+ <div class="foo toclevel3"><a href="#web_app_models">1.1. Web application models</a></div>
1087
+ <div class="foo toclevel4"><a href="#_why_reverse_proxy">1.1.1. Why reverse proxy?</a></div>
1088
+ <div class="foo toclevel3"><a href="#_ruby_rack_and_ruby_on_rails">1.2. Ruby Rack and Ruby on Rails</a></div>
1089
+ <div class="foo toclevel3"><a href="#_apache">1.3. Apache</a></div>
1090
+ <div class="foo toclevel3"><a href="#_nginx">1.4. Nginx</a></div>
1091
+ <div class="foo toclevel2"><a href="#_phusion_passenger_architecture">2. Phusion Passenger architecture</a></div>
1092
+ <div class="foo toclevel3"><a href="#_overview">2.1. Overview</a></div>
1093
+ <div class="foo toclevel3"><a href="#_spawning_and_caching_of_code_and_applications">2.2. Spawning and caching of code and applications</a></div>
1094
+ <div class="foo toclevel3"><a href="#spawn_server">2.3. The spawn server</a></div>
1095
+ <div class="foo toclevel4"><a href="#_memory_sharing">2.3.1. Memory sharing</a></div>
1096
+ <div class="foo toclevel3"><a href="#concurrent_requests">2.4. Handling of concurrent requests</a></div>
1097
+ <div class="foo toclevel2"><a href="#_appendix_a_about_this_document">3. Appendix A: About this document</a></div>
1098
+ </div>
1069
1099
  </div>
1070
1100
  <div id="content">
1071
1101
 
1072
1102
  <div class="sect1">
1073
- <h2 id="_introduction_to_related_technologies">1. Introduction to related technologies</h2>
1103
+ <span class="anchor_helper" id="_introduction_to_related_technologies"></span><h2 data-anchor="_introduction_to_related_technologies">1. Introduction to related technologies</h2>
1074
1104
  <div class="sectionbody">
1075
1105
  <div class="sect2">
1076
- <h3 id="web_app_models">1.1. Web application models</h3>
1106
+ <span class="anchor_helper" id="web_app_models"></span><h3 data-anchor="web_app_models">1.1. Web application models</h3>
1077
1107
  <div class="paragraph"><p>Before we describe Phusion Passenger, it is important to understand how typical web
1078
1108
  applications work from the viewpoint of someone who wants to connect the
1079
1109
  application to a web server.</p></div>
@@ -1084,10 +1114,11 @@ to exit. This does not necessarily mean that the web application speaks HTTP
1084
1114
  directly: it just means that the web application accepts some kind of
1085
1115
  representation of an HTTP request.</p></div>
1086
1116
  <div class="paragraph"><p><span class="image">
1087
- <img src="images/typical_isolated_web_application.png" alt="Architecture of a typical web application in isolation"></span></p></div>
1117
+ <img src="images/typical_isolated_web_application.png" alt="Architecture of a typical web application in isolation">
1118
+ </span></p></div>
1088
1119
  <div class="paragraph"><p>Few web applications are accessible directly by HTTP clients. Common models
1089
1120
  are:</p></div>
1090
- <div class="olist arabic"><ol class="arabic">
1121
+ <div class="olist arabic"><ol class="arabic">
1091
1122
  <li>
1092
1123
  <p>
1093
1124
  The web application is contained in an application server. This application
@@ -1101,7 +1132,7 @@ sent to the application server, which in turn sends them to the web server,
1101
1132
  and eventually to the HTTP client.
1102
1133
  </p>
1103
1134
  <div class="paragraph"><p>Typical examples of such a model:</p></div>
1104
- <div class="ulist"><ul>
1135
+ <div class="ulist"><ul>
1105
1136
  <li>
1106
1137
  <p>
1107
1138
  A J2EE application, contained in the Tomcat application server, proxied
@@ -1165,7 +1196,7 @@ processes.</p></div>
1165
1196
  <div class="paragraph"><p>Of course, there are many variations possible. For example, load balancers
1166
1197
  could be used. But that is outside the scope of this document.</p></div>
1167
1198
  <div class="sect3">
1168
- <h4 id="_why_reverse_proxy">1.1.1. Why reverse proxy?</h4>
1199
+ <span class="anchor_helper" id="_why_reverse_proxy"></span><h4 data-anchor="_why_reverse_proxy">1.1.1. Why reverse proxy?</h4>
1169
1200
  <div class="paragraph"><p>As you’ve seen, it is often necessary to put the web application or its
1170
1201
  application server behind a real web server in a reverse proxy setup even
1171
1202
  when the web app/app server already speaks HTTP. This is because implementing
@@ -1205,19 +1236,21 @@ and the web application do what they’re best at: their own core business logic
1205
1236
  </div>
1206
1237
  </div>
1207
1238
  <div class="sect2">
1208
- <h3 id="_ruby_rack_and_ruby_on_rails">1.2. Ruby Rack and Ruby on Rails</h3>
1239
+ <span class="anchor_helper" id="_ruby_rack_and_ruby_on_rails"></span><h3 data-anchor="_ruby_rack_and_ruby_on_rails">1.2. Ruby Rack and Ruby on Rails</h3>
1209
1240
  <div class="paragraph"><p>The de-facto standard interface for Ruby web applications is <a href="http://rack.rubyforge.org/">Rack</a>.
1210
1241
  Rack specifies an programming interface for web application developers to implement.
1211
1242
  This interface covers HTTP request and response handling, and is not dependent on
1212
1243
  any particular application server. The idea is that any Rack-compliant application
1213
1244
  server can implement the Rack specification and work with all Rack-compliant web applications.</p></div>
1214
1245
  <div class="paragraph"><p><span class="image">
1215
- <img src="images/rack.png" alt="images/rack.png"></span></p></div>
1246
+ <img src="images/rack.png" alt="images/rack.png">
1247
+ </span></p></div>
1216
1248
  <div class="paragraph"><p>In the distant past, each Ruby web framework had its own interface, so application
1217
1249
  servers needed to explicitly add support for each web framework. Nowadays application
1218
1250
  servers just support Rack.</p></div>
1219
1251
  <div class="paragraph"><p><span class="image">
1220
- <img src="images/many_web_framework_protocols.png" alt="images/many_web_framework_protocols.png"></span></p></div>
1252
+ <img src="images/many_web_framework_protocols.png" alt="images/many_web_framework_protocols.png">
1253
+ </span></p></div>
1221
1254
  <div class="paragraph"><p>Ruby on Rails has been fully Rack compliant since version 3.0. Rails 2.3 was partially
1222
1255
  Rack-compliant while earlier versions were not Rack-compliant at all. Phusion Passenger
1223
1256
  supports Rack as well as all Rails 1.x and 2.x versions.</p></div>
@@ -1230,7 +1263,7 @@ Enterprise Edition</a>. Also, a lot of the startup time of a Ruby on Rails
1230
1263
  application is spent on bootstrapping the Rails framework.</p></div>
1231
1264
  </div>
1232
1265
  <div class="sect2">
1233
- <h3 id="_apache">1.3. Apache</h3>
1266
+ <span class="anchor_helper" id="_apache"></span><h3 data-anchor="_apache">1.3. Apache</h3>
1234
1267
  <div class="paragraph"><p>The Apache web server has a dynamic module system and a pluggable I/O
1235
1268
  multiprocessing (the ability to
1236
1269
  handle more than 1 concurrent HTTP client at the same time) architecture. An
@@ -1249,7 +1282,7 @@ so-called control process, and then forwarded to one of the worker processes.
1249
1282
  The next section contains a diagram which shows the prefork MPM’s architecture.</p></div>
1250
1283
  </div>
1251
1284
  <div class="sect2">
1252
- <h3 id="_nginx">1.4. Nginx</h3>
1285
+ <span class="anchor_helper" id="_nginx"></span><h3 data-anchor="_nginx">1.4. Nginx</h3>
1253
1286
  <div class="paragraph"><p>Nginx is a lightweight web server that is becoming increasingly popular. It is known
1254
1287
  to be smaller, lighter weight and more scalable than Apache thanks to its evented I/O
1255
1288
  architecture. That said, Nginx is less flexible than Apache. For example it has no
@@ -1258,18 +1291,19 @@ dynamic module system: all modules must be statically compiled into Nginx.</p></
1258
1291
  </div>
1259
1292
  </div>
1260
1293
  <div class="sect1">
1261
- <h2 id="_phusion_passenger_architecture">2. Phusion Passenger architecture</h2>
1294
+ <span class="anchor_helper" id="_phusion_passenger_architecture"></span><h2 data-anchor="_phusion_passenger_architecture">2. Phusion Passenger architecture</h2>
1262
1295
  <div class="sectionbody">
1263
1296
  <div class="sect2">
1264
- <h3 id="_overview">2.1. Overview</h3>
1297
+ <span class="anchor_helper" id="_overview"></span><h3 data-anchor="_overview">2.1. Overview</h3>
1265
1298
  <div class="paragraph"><p>Phusion Passenger’s architecture is a lot like model #2 described in
1266
1299
  <a href="#web_app_models">Web application models</a>. In other words,
1267
1300
  Phusion Passenger extends Apache/Nginx and allows it to act like an
1268
1301
  application server. This is shown in the following diagram:</p></div>
1269
1302
  <div class="paragraph"><p><span class="image">
1270
- <img src="images/passenger_architecture.png" alt="Passenger’s architecture"></span></p></div>
1303
+ <img src="images/passenger_architecture.png" alt="Passenger’s architecture">
1304
+ </span></p></div>
1271
1305
  <div class="paragraph"><p>Phusion Passenger consists of:</p></div>
1272
- <div class="ulist"><ul>
1306
+ <div class="ulist"><ul>
1273
1307
  <li>
1274
1308
  <p>
1275
1309
  an Apache module, <em>mod_passenger</em>. This is written in C++, and can be found in the directory <em>ext/apache2</em>.
@@ -1296,7 +1330,7 @@ is carefully designed and implemented so that the web server shouldn’t crash b
1296
1330
  of Phusion Passenger.</p></div>
1297
1331
  </div>
1298
1332
  <div class="sect2">
1299
- <h3 id="_spawning_and_caching_of_code_and_applications">2.2. Spawning and caching of code and applications</h3>
1333
+ <span class="anchor_helper" id="_spawning_and_caching_of_code_and_applications"></span><h3 data-anchor="_spawning_and_caching_of_code_and_applications">2.2. Spawning and caching of code and applications</h3>
1300
1334
  <div class="paragraph"><p>A very naive implementation of an application server would spawn an application
1301
1335
  process every time an HTTP request is received, just like CGI would.
1302
1336
  However, spawning Ruby applications is typically expensive. It can take a few
@@ -1304,7 +1338,7 @@ seconds on a modern computer, and possibly much longer on a heavily loaded serve
1304
1338
  A less naive implementation would keep spawned application processes alive,
1305
1339
  similar to how Lighttpd’s FastCGI implementation works.
1306
1340
  However, this still has several problems:</p></div>
1307
- <div class="olist arabic"><ol class="arabic">
1341
+ <div class="olist arabic"><ol class="arabic">
1308
1342
  <li>
1309
1343
  <p>
1310
1344
  The first request to a Rails website will be slow, and subsequent requests
@@ -1365,13 +1399,13 @@ spawned applications' handles, and cleaning up applications which have been
1365
1399
  idle for an extended period of time.</p></div>
1366
1400
  </div>
1367
1401
  <div class="sect2">
1368
- <h3 id="spawn_server">2.3. The spawn server</h3>
1402
+ <span class="anchor_helper" id="spawn_server"></span><h3 data-anchor="spawn_server">2.3. The spawn server</h3>
1369
1403
  <div class="paragraph"><p>The spawn server is written in Ruby, and its code can be found in the directory
1370
1404
  <em>lib/passenger</em>. Its main executable is <em>bin/passenger-spawn-server</em>.
1371
1405
  <a href="rdoc/index.html">The spawn server’s RDoc documentation</a> documents the
1372
1406
  implementation in detail.</p></div>
1373
1407
  <div class="paragraph"><p>The spawn server consists of 3 logical layers:</p></div>
1374
- <div class="olist arabic"><ol class="arabic">
1408
+ <div class="olist arabic"><ol class="arabic">
1375
1409
  <li>
1376
1410
  <p>
1377
1411
  <strong>The spawn manager.</strong> This is the topmost layer, and acts like a fascade for
@@ -1401,7 +1435,8 @@ implementation in detail.</p></div>
1401
1435
  </li>
1402
1436
  </ol></div>
1403
1437
  <div class="paragraph"><p><span class="image">
1404
- <img src="images/spawn_server_architecture.png" alt="The spawn server’s architecture"></span></p></div>
1438
+ <img src="images/spawn_server_architecture.png" alt="The spawn server’s architecture">
1439
+ </span></p></div>
1405
1440
  <div class="paragraph"><p>As you can see, we have two layers of code caching: when the spawn server
1406
1441
  receives a request to spawn a new application instance, it will forward the
1407
1442
  request to the correct framework spawner server (and will spawn that framework
@@ -1419,7 +1454,7 @@ application instance’s life time (through the application pool).</p></div>
1419
1454
  single Ruby process can only load a single Ruby on Rails framework and a
1420
1455
  single application.</p></div>
1421
1456
  <div class="sect3">
1422
- <h4 id="_memory_sharing">2.3.1. Memory sharing</h4>
1457
+ <span class="anchor_helper" id="_memory_sharing"></span><h4 data-anchor="_memory_sharing">2.3.1. Memory sharing</h4>
1423
1458
  <div class="paragraph"><p>On most modern Unix operating systems, when a child process is created, it will
1424
1459
  share most of its memory with the parent process. Processes are not supposed to
1425
1460
  be able to access each others' memory, so the operating system makes a copy of
@@ -1433,9 +1468,9 @@ haven’t been written to. This means that all spawned Rails applications will
1433
1468
  application code, with each other. This results in a dramatic reduction in
1434
1469
  memory usage.</p></div>
1435
1470
  <div class="admonitionblock">
1436
- <table><tr>
1471
+ <table><tr>
1437
1472
  <td class="icon">
1438
- <img src="./images/icons/note.png" alt="Note">
1473
+ <img src="./images/icons/note.png" alt="Note">
1439
1474
  </td>
1440
1475
  <td class="content">
1441
1476
  <div class="paragraph"><p>Sharing memory only works if <a href="http://www.rubyenterpriseedition.com/">Ruby
@@ -1445,20 +1480,20 @@ Enterprise Edition website for technical details.</p></div>
1445
1480
  <div class="paragraph"><p>Passenger works fine with standard Ruby. You still get to enjoy reduced Rails
1446
1481
  startup times. You just won’t be able to benefit from memory sharing.</p></div>
1447
1482
  </td>
1448
- </tr></table>
1483
+ </tr></table>
1449
1484
  </div>
1450
1485
  <div class="paragraph"><p>Note that <a href="http://rubini.us/">Rubinius</a>'s garbage collector is already
1451
1486
  copy-on-write friendly.</p></div>
1452
1487
  </div>
1453
1488
  </div>
1454
1489
  <div class="sect2">
1455
- <h3 id="concurrent_requests">2.4. Handling of concurrent requests</h3>
1490
+ <span class="anchor_helper" id="concurrent_requests"></span><h3 data-anchor="concurrent_requests">2.4. Handling of concurrent requests</h3>
1456
1491
  <div class="paragraph"><p>As explained earlier, a single Rails application instance can only handle a
1457
1492
  single request at the same time. This is obviously undesirable. But before we
1458
1493
  dive into the solution, let us take a look how the “competition” solves this
1459
1494
  problem. PHP has similar problems: a single PHP script can also process only
1460
1495
  one HTTP request at a time.</p></div>
1461
- <div class="ulist"><ul>
1496
+ <div class="ulist"><ul>
1462
1497
  <li>
1463
1498
  <p>
1464
1499
  mod_php “solves” this problem by using Apache’s MPM. In other words,
@@ -1489,23 +1524,22 @@ algorithm, which is non-trivial. The algorithm is documented in detail in
1489
1524
  </div>
1490
1525
  </div>
1491
1526
  <div class="sect1">
1492
- <h2 id="_appendix_a_about_this_document">3. Appendix A: About this document</h2>
1527
+ <span class="anchor_helper" id="_appendix_a_about_this_document"></span><h2 data-anchor="_appendix_a_about_this_document">3. Appendix A: About this document</h2>
1493
1528
  <div class="sectionbody">
1494
1529
  <div class="paragraph"><p>The text of this document is licensed under the
1495
1530
  <a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons
1496
1531
  Attribution-Share Alike 3.0 Unported License</a>.</p></div>
1497
1532
  <div class="paragraph"><p><span class="image">
1498
1533
  <a class="image" href="link:http://creativecommons.org/licenses/by-sa/3.0/">
1499
- <img src="images/by_sa.png" alt="images/by_sa.png"></a>
1534
+ <img src="images/by_sa.png" alt="images/by_sa.png">
1535
+ </a>
1500
1536
  </span></p></div>
1501
1537
  </div>
1502
1538
  </div>
1503
1539
  </div>
1504
1540
  <div id="footnotes"><hr></div>
1505
1541
  <div id="footer">
1506
- <div id="footer-text">
1507
- Last updated 2012-10-23 21:45:15 CEST
1508
- </div>
1542
+
1509
1543
  </div>
1510
1544
  <script>/*! jQuery v1.7.1 jquery.com | jquery.org/license */
1511
1545
  (function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
@@ -1842,6 +1876,7 @@ Mizuho.initializeTopBar = $.proxy(function() {
1842
1876
  var isMobileDevice = this.isMobileDevice();
1843
1877
  var timerId;
1844
1878
 
1879
+ // Create the floating table of contents used in the top bar.
1845
1880
  var $floattoc = $('<div id="floattoc"></div>').html($('#toc').html());
1846
1881
  $floattoc.find('#toctitle').remove();
1847
1882
  $floattoc.find('.comments').remove();
@@ -1860,6 +1895,8 @@ Mizuho.initializeTopBar = $.proxy(function() {
1860
1895
  self.internalLinkClicked(this, event);
1861
1896
  });
1862
1897
 
1898
+ // Callback for when the user clicks on the Table of Contents
1899
+ // button on the top bar.
1863
1900
  function showFloatingToc() {
1864
1901
  var scrollUpdateTimerId;
1865
1902
 
@@ -1952,6 +1989,9 @@ Mizuho.initializeTopBar = $.proxy(function() {
1952
1989
  $window.bind('scroll', onScroll);
1953
1990
  }
1954
1991
 
1992
+ // Called whenever the user scrolls. Updates the title of the
1993
+ // Table of Contents button in the top bar to the section that
1994
+ // the user is currently reading.
1955
1995
  function update() {
1956
1996
  if ($title.offset().top + $title.height() < $document.scrollTop()) {
1957
1997
  if (!$topbar.is(':visible')) {
@@ -1995,6 +2035,7 @@ Mizuho.initializeTopBar = $.proxy(function() {
1995
2035
  }, 100);
1996
2036
  }
1997
2037
 
2038
+
1998
2039
  if (isMobileDevice) {
1999
2040
  // Mobile devices don't support position fixed.
2000
2041
  $topbar.css('position', 'absolute');
@@ -2009,5 +2050,5 @@ Mizuho.initializeTopBar = $.proxy(function() {
2009
2050
  $(document).ready(Mizuho.initializeTopBar);
2010
2051
 
2011
2052
  </script>
2012
- </body>
2053
+ </body>
2013
2054
  </html>
@@ -1,9 +1,9 @@
1
1
  <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5
- <meta name="generator" content="AsciiDoc 8.6.7">
6
- <title>Security of user switching support in Passenger</title>
2
+ <html lang="en">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5
+ <meta name="generator" content="AsciiDoc 8.6.7">
6
+ <title>Security of user switching support in Passenger</title>
7
7
  <style type="text/css">
8
8
  /* Shared CSS for AsciiDoc xhtml11 and html5 backends */
9
9
 
@@ -603,7 +603,7 @@ div.exampleblock > div.content, div.sidebarblock > div.content, div.listingblock
603
603
  div.verseblock { border-left-width: 0; margin-left: 3em; }
604
604
  div.quoteblock { border-left-width: 3px; margin-left: 0; margin-right: 0;}
605
605
  div.admonitionblock td.content { border-left: 3px solid #E8E8E8; }
606
- </style>
606
+ </style>
607
607
  <script type="text/javascript">
608
608
  /*<![CDATA[*/
609
609
  var asciidoc = { // Namespace.
@@ -795,11 +795,14 @@ install: function(toclevels) {
795
795
  }
796
796
 
797
797
  }
798
- asciidoc.install(3);
798
+ asciidoc.install();
799
799
  /*]]>*/
800
- </script><style type="text/css">
800
+ </script>
801
+ <style type="text/css">
801
802
  body {
802
- margin: 1em 10% 1em 10%;
803
+ margin: 1em auto 1em auto;
804
+ padding: 0 1em 0 1em;
805
+ max-width: 800px;
803
806
  }
804
807
 
805
808
  a.image {
@@ -878,6 +881,10 @@ a.image {
878
881
  margin: 2em;
879
882
  }
880
883
 
884
+ pre {
885
+ overflow: auto;
886
+ }
887
+
881
888
  @media print {
882
889
  body {
883
890
  font-size: 18pt;
@@ -1038,34 +1045,53 @@ a.image {
1038
1045
  border-bottom-right-radius: 0;
1039
1046
  }
1040
1047
 
1048
+ /* http://nicolasgallagher.com/jump-links-and-viewport-positioning/ */
1049
+ .anchor_helper {
1050
+ position: relative;
1051
+ display: block;
1052
+ top: -50px;
1053
+ width: 1px;
1054
+ height: 1px;
1055
+ }
1056
+
1041
1057
  </style>
1042
- </head>
1058
+ </head>
1043
1059
  <body class="article">
1044
1060
  <div id="topbar" style="display: none">
1045
1061
  <div class="title">
1046
- <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAAEV95QVAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sGCRMSACDxkZwAAAAidEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVAgb24gYSBNYWOHqHdDAAAAZUlEQVQY032PSxbAIAjEIlfygL6ePF3UUvpzNjgSYWwqAMEhUQnANnsC7TQPeJpsVWzMuh2sog4vDTUbqP081zECrW4dtdaQGSIKlWluPyjK+VXxAz5XfcKufCzA130AfQHWB30HZxlPaP080xsAAAAASUVORK5CYII=" width="11" height="10" alt=""><a href="javascript:void(Mizuho.smoothlyScrollToToc())">Security of user switching support in Passenger</a>
1062
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAAEV95QVAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sGCRMSACDxkZwAAAAidEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVAgb24gYSBNYWOHqHdDAAAAZUlEQVQY032PSxbAIAjEIlfygL6ePF3UUvpzNjgSYWwqAMEhUQnANnsC7TQPeJpsVWzMuh2sog4vDTUbqP081zECrW4dtdaQGSIKlWluPyjK+VXxAz5XfcKufCzA130AfQHWB30HZxlPaP080xsAAAAASUVORK5CYII=" width="11" height="10" alt="">
1063
+ <a href="javascript:void(Mizuho.smoothlyScrollToToc())">Security of user switching support in Passenger</a>
1047
1064
  </div>
1048
1065
  <a href="javascript:void(0)" id="current_section"></a>
1049
1066
  </div>
1050
1067
  <div id="header">
1051
1068
  <h1>Security of user switching support in Passenger</h1>
1052
1069
  <div id="toc">
1053
- <div id="toctitle">Table of Contents</div>
1054
- <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
1055
- </div>
1070
+ <div id="toctitle">Table of Contents</div>
1071
+ <div class="foo toclevel2"><a href="#_problem_description">1. Problem description</a></div>
1072
+ <div class="foo toclevel2"><a href="#_analysis_of_possible_solutions">2. Analysis of possible solutions</a></div>
1073
+ <div class="foo toclevel3"><a href="#apache_root">2.1. Apache must already be running as root</a></div>
1074
+ <div class="foo toclevel3"><a href="#_using_apache_8217_s_suexec">2.2. Using Apache’s suEXEC</a></div>
1075
+ <div class="foo toclevel3"><a href="#_using_a_setuid_root_wrapper_application">2.3. Using a setuid root wrapper application</a></div>
1076
+ <div class="foo toclevel3"><a href="#setuid_root">2.4. Using a setuid $X wrapper application</a></div>
1077
+ <div class="foo toclevel3"><a href="#_using_em_su_em">2.5. Using su</a></div>
1078
+ <div class="foo toclevel3"><a href="#_using_em_sudo_em">2.6. Using sudo</a></div>
1079
+ <div class="foo toclevel3"><a href="#_common_security_issues">2.7. Common security issues</a></div>
1080
+ <div class="foo toclevel2"><a href="#_chosen_solution">3. Chosen solution</a></div>
1081
+ </div>
1056
1082
  </div>
1057
1083
  <div id="content">
1058
1084
  <div class="sect1">
1059
- <h2 id="_problem_description">1. Problem description</h2>
1085
+ <span class="anchor_helper" id="_problem_description"></span><h2 data-anchor="_problem_description">1. Problem description</h2>
1060
1086
  <div class="sectionbody">
1061
1087
  <div class="admonitionblock">
1062
- <table><tr>
1088
+ <table><tr>
1063
1089
  <td class="icon">
1064
- <img src="./images/icons/tip.png" alt="Tip">
1090
+ <img src="./images/icons/tip.png" alt="Tip">
1065
1091
  </td>
1066
1092
  <td class="content">It is strongly recommended that you first read our
1067
1093
  <a href="Architectural%20overview.html">Architectural Overview</a>.</td>
1068
- </tr></table>
1094
+ </tr></table>
1069
1095
  </div>
1070
1096
  <div class="paragraph"><p>A straightforward implementation of Passenger will spawn Rails applications in
1071
1097
  the same user context as Apache itself. On server machines which host multiple
@@ -1080,12 +1106,12 @@ Passenger’s security may be peer reviewed.</p></div>
1080
1106
  </div>
1081
1107
  </div>
1082
1108
  <div class="sect1">
1083
- <h2 id="_analysis_of_possible_solutions">2. Analysis of possible solutions</h2>
1109
+ <span class="anchor_helper" id="_analysis_of_possible_solutions"></span><h2 data-anchor="_analysis_of_possible_solutions">2. Analysis of possible solutions</h2>
1084
1110
  <div class="sectionbody">
1085
1111
  <div class="paragraph"><p>It seems that the only way to solve this problem on Unix, is to run each Rails
1086
1112
  application server as its owner’s user and group. Passenger can make use of
1087
1113
  one of the following methods to implement this:</p></div>
1088
- <div class="olist arabic"><ol class="arabic">
1114
+ <div class="olist arabic"><ol class="arabic">
1089
1115
  <li>
1090
1116
  <p>
1091
1117
  Apache (and thus Passenger) must already be running as root.
@@ -1121,7 +1147,7 @@ Using <em>sudo</em>.
1121
1147
  </ol></div>
1122
1148
  <div class="paragraph"><p>Let us take a look at each method in detail.</p></div>
1123
1149
  <div class="sect2">
1124
- <h3 id="apache_root">2.1. Apache must already be running as root</h3>
1150
+ <span class="anchor_helper" id="apache_root"></span><h3 data-anchor="apache_root">2.1. Apache must already be running as root</h3>
1125
1151
  <div class="paragraph"><p>First, let us take a look at the typical Apache setup, in which Apache is bound
1126
1152
  to port 80, and uses the prefork MPM. Binding to any port lower than 1024
1127
1153
  requires root privileges, so Apache is typically run as root. This poses an
@@ -1149,7 +1175,7 @@ this method in automated unit tests will require running the unit test suit as
1149
1175
  root.</p></div>
1150
1176
  </div>
1151
1177
  <div class="sect2">
1152
- <h3 id="_using_apache_8217_s_suexec">2.2. Using Apache’s suEXEC</h3>
1178
+ <span class="anchor_helper" id="_using_apache_8217_s_suexec"></span><h3 data-anchor="_using_apache_8217_s_suexec">2.2. Using Apache’s suEXEC</h3>
1153
1179
  <div class="paragraph"><p>Apache’s <a href="http://httpd.apache.org/docs/2.0/suexec.html">suEXEC</a> allows one to
1154
1180
  run CGI processes as different users. But it seems that suEXEC can only be
1155
1181
  used for CGI, and is not a general-purpose mechanism. The
@@ -1159,7 +1185,7 @@ to use suEXEC, then it is likely that we’ll have to patch suEXEC. The suEXEC
1159
1185
  website strongly discourages patching.</p></div>
1160
1186
  </div>
1161
1187
  <div class="sect2">
1162
- <h3 id="_using_a_setuid_root_wrapper_application">2.3. Using a setuid root wrapper application</h3>
1188
+ <span class="anchor_helper" id="_using_a_setuid_root_wrapper_application"></span><h3 data-anchor="_using_a_setuid_root_wrapper_application">2.3. Using a setuid root wrapper application</h3>
1163
1189
  <div class="paragraph"><p>If we use this method, we must be extremely careful. It must not be possible
1164
1190
  for arbitrary processes to gain root privileges. We want Passenger, and only
1165
1191
  Passenger, to be able to gain root privileges.</p></div>
@@ -1168,7 +1194,7 @@ a password file, which only Apache and the wrapper can read, through
1168
1194
  the use of proper file permissions. The password file must never be world
1169
1195
  readable or writable.</p></div>
1170
1196
  <div class="paragraph"><p>It works as follows:</p></div>
1171
- <div class="olist arabic"><ol class="arabic">
1197
+ <div class="olist arabic"><ol class="arabic">
1172
1198
  <li>
1173
1199
  <p>
1174
1200
  Passenger runs the wrapper.
@@ -1202,7 +1228,7 @@ process’s user is in the whitelist.</p></div>
1202
1228
  run as root, in contrast to the run-Apache-as-root method.</p></div>
1203
1229
  </div>
1204
1230
  <div class="sect2">
1205
- <h3 id="setuid_root">2.4. Using a setuid $X wrapper application</h3>
1231
+ <span class="anchor_helper" id="setuid_root"></span><h3 data-anchor="setuid_root">2.4. Using a setuid $X wrapper application</h3>
1206
1232
  <div class="paragraph"><p>A setuid $X wrapper will work in a fashion similar to the setuid root wrapper,
1207
1233
  i.e. it will use a password file for authorization.</p></div>
1208
1234
  <div class="paragraph"><p>Passenger does not spawn Rails applications itself, but does so via the spawn
@@ -1220,13 +1246,13 @@ methods.</p></div>
1220
1246
  wrapper for each user, and to install it.</p></div>
1221
1247
  </div>
1222
1248
  <div class="sect2">
1223
- <h3 id="_using_em_su_em">2.5. Using <em>su</em>
1249
+ <span class="anchor_helper" id="_using_em_su_em"></span><h3 data-anchor="_using_em_su_em">2.5. Using <em>su</em>
1224
1250
  </h3>
1225
1251
  <div class="paragraph"><p>The standard Unix <em>su</em> tool asks for the root password. It’s a bad idea for
1226
1252
  Apache to know the root password, so using <em>su</em> is not a viable alternative.</p></div>
1227
1253
  </div>
1228
1254
  <div class="sect2">
1229
- <h3 id="_using_em_sudo_em">2.6. Using <em>sudo</em>
1255
+ <span class="anchor_helper" id="_using_em_sudo_em"></span><h3 data-anchor="_using_em_sudo_em">2.6. Using <em>sudo</em>
1230
1256
  </h3>
1231
1257
  <div class="paragraph"><p>It might be possible to use the <em>sudo</em> utility. sudo can be configured in
1232
1258
  such a way that the user Apache runs as can use sudo without having to enter a
@@ -1242,10 +1268,10 @@ or (on Linux) by reading the file <span class="monospaced">/proc/$PID/cmdline</s
1242
1268
  <div class="paragraph"><p>So it seems <em>sudo</em> is not a viable alternative.</p></div>
1243
1269
  </div>
1244
1270
  <div class="sect2">
1245
- <h3 id="_common_security_issues">2.7. Common security issues</h3>
1271
+ <span class="anchor_helper" id="_common_security_issues"></span><h3 data-anchor="_common_security_issues">2.7. Common security issues</h3>
1246
1272
  <div class="paragraph"><p>Whatever method Passenger will use, the following security principles must be
1247
1273
  honored:</p></div>
1248
- <div class="ulist"><ul>
1274
+ <div class="ulist"><ul>
1249
1275
  <li>
1250
1276
  <p>
1251
1277
  Rails applications must never be run as root.
@@ -1254,7 +1280,7 @@ Rails applications must never be run as root.
1254
1280
  </ul></div>
1255
1281
  <div class="paragraph"><p>It might also be worthy to look into suEXEC’s security model for inspiration.</p></div>
1256
1282
  <div class="paragraph"><p>Also, the following questions remain:</p></div>
1257
- <div class="ulist"><ul>
1283
+ <div class="ulist"><ul>
1258
1284
  <li>
1259
1285
  <p>
1260
1286
  Is there a need for a user whitelist/blacklist? That is, is there a need for
@@ -1266,7 +1292,7 @@ Is there a need for a user whitelist/blacklist? That is, is there a need for
1266
1292
  </div>
1267
1293
  </div>
1268
1294
  <div class="sect1">
1269
- <h2 id="_chosen_solution">3. Chosen solution</h2>
1295
+ <span class="anchor_helper" id="_chosen_solution"></span><h2 data-anchor="_chosen_solution">3. Chosen solution</h2>
1270
1296
  <div class="sectionbody">
1271
1297
  <div class="paragraph"><p>Running Apache as root and writing a setuid root wrapper are the main
1272
1298
  contestants. The former is preferred, because it’s easier to implement.</p></div>
@@ -1292,9 +1318,7 @@ feel free to discuss it with us.</p></div>
1292
1318
  </div>
1293
1319
  <div id="footnotes"><hr></div>
1294
1320
  <div id="footer">
1295
- <div id="footer-text">
1296
- Last updated 2010-09-25 20:09:08 CEST
1297
- </div>
1321
+
1298
1322
  </div>
1299
1323
  <script>/*! jQuery v1.7.1 jquery.com | jquery.org/license */
1300
1324
  (function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
@@ -1631,6 +1655,7 @@ Mizuho.initializeTopBar = $.proxy(function() {
1631
1655
  var isMobileDevice = this.isMobileDevice();
1632
1656
  var timerId;
1633
1657
 
1658
+ // Create the floating table of contents used in the top bar.
1634
1659
  var $floattoc = $('<div id="floattoc"></div>').html($('#toc').html());
1635
1660
  $floattoc.find('#toctitle').remove();
1636
1661
  $floattoc.find('.comments').remove();
@@ -1649,6 +1674,8 @@ Mizuho.initializeTopBar = $.proxy(function() {
1649
1674
  self.internalLinkClicked(this, event);
1650
1675
  });
1651
1676
 
1677
+ // Callback for when the user clicks on the Table of Contents
1678
+ // button on the top bar.
1652
1679
  function showFloatingToc() {
1653
1680
  var scrollUpdateTimerId;
1654
1681
 
@@ -1741,6 +1768,9 @@ Mizuho.initializeTopBar = $.proxy(function() {
1741
1768
  $window.bind('scroll', onScroll);
1742
1769
  }
1743
1770
 
1771
+ // Called whenever the user scrolls. Updates the title of the
1772
+ // Table of Contents button in the top bar to the section that
1773
+ // the user is currently reading.
1744
1774
  function update() {
1745
1775
  if ($title.offset().top + $title.height() < $document.scrollTop()) {
1746
1776
  if (!$topbar.is(':visible')) {
@@ -1784,6 +1814,7 @@ Mizuho.initializeTopBar = $.proxy(function() {
1784
1814
  }, 100);
1785
1815
  }
1786
1816
 
1817
+
1787
1818
  if (isMobileDevice) {
1788
1819
  // Mobile devices don't support position fixed.
1789
1820
  $topbar.css('position', 'absolute');
@@ -1798,5 +1829,5 @@ Mizuho.initializeTopBar = $.proxy(function() {
1798
1829
  $(document).ready(Mizuho.initializeTopBar);
1799
1830
 
1800
1831
  </script>
1801
- </body>
1832
+ </body>
1802
1833
  </html>