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.
- data.tar.gz.asc +12 -0
- data/NEWS +12 -0
- data/bin/passenger-install-nginx-module +3 -4
- data/doc/Architectural overview.html +90 -49
- data/doc/Security of user switching support.html +66 -35
- data/doc/Users guide Apache.html +506 -329
- data/doc/Users guide Apache.idmap.txt +55 -52
- data/doc/Users guide Nginx.html +380 -241
- data/doc/Users guide Nginx.idmap.txt +52 -52
- data/doc/Users guide Standalone.html +48 -24
- data/ext/common/Constants.h +1 -1
- data/ext/libev/configure +3545 -4964
- data/lib/phusion_passenger.rb +2 -2
- data/lib/phusion_passenger/abstract_request_handler.rb +7 -1
- data/lib/phusion_passenger/dependencies.rb +12 -20
- data/lib/phusion_passenger/platform_info.rb +17 -25
- data/lib/phusion_passenger/platform_info/apache.rb +1 -10
- data/lib/phusion_passenger/platform_info/ruby.rb +97 -37
- data/lib/phusion_passenger/rack/request_handler.rb +20 -1
- data/lib/phusion_passenger/standalone/command.rb +5 -4
- data/lib/phusion_passenger/standalone/runtime_installer.rb +4 -5
- metadata +69 -86
- metadata.gz.asc +12 -0
- data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
data.tar.gz.asc
ADDED
@@ -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 = "
|
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.
|
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 & 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 & 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(
|
798
|
+
asciidoc.install();
|
799
799
|
/*]]>*/
|
800
|
-
</script
|
800
|
+
</script>
|
801
|
+
<style type="text/css">
|
801
802
|
body {
|
802
|
-
margin: 1em
|
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=""
|
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 & 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 & architecture</h1>
|
1068
|
+
<h1>Phusion Passenger design & 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"
|
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
|
-
|
1067
|
-
|
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
|
-
<
|
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
|
-
<
|
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"
|
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
|
-
<
|
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
|
-
<
|
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"
|
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"
|
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
|
-
<
|
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
|
-
<
|
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
|
-
<
|
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
|
-
<
|
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"
|
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
|
-
<
|
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
|
-
<
|
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"
|
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
|
-
<
|
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
|
-
<
|
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
|
-
<
|
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"
|
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
|
-
|
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(
|
798
|
+
asciidoc.install();
|
799
799
|
/*]]>*/
|
800
|
-
</script
|
800
|
+
</script>
|
801
|
+
<style type="text/css">
|
801
802
|
body {
|
802
|
-
margin: 1em
|
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=""
|
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
|
-
|
1054
|
-
|
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
|
-
<
|
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
|
-
<
|
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
|
-
<
|
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
|
-
<
|
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
|
-
<
|
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
|
-
<
|
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
|
-
<
|
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
|
-
<
|
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
|
-
<
|
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
|
-
<
|
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
|
-
|
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>
|