passenger 5.0.4 → 5.0.5

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.

Files changed (550) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +10 -0
  5. data/CHANGELOG +21 -0
  6. data/build/agents.rb +2 -2
  7. data/build/apache2.rb +6 -5
  8. data/build/common_library.rb +22 -7
  9. data/build/cxx_tests.rb +0 -3
  10. data/build/misc.rb +1 -1
  11. data/dev/parse_file_descriptor_log +119 -0
  12. data/doc/CloudLicensingConfiguration.html +387 -0
  13. data/doc/Design and Architecture.html +2430 -0
  14. data/doc/Packaging.html +488 -0
  15. data/doc/Security of user switching support.html +1833 -0
  16. data/doc/ServerOptimizationGuide.html +659 -0
  17. data/doc/ServerOptimizationGuide.txt.md +8 -0
  18. data/doc/Users guide Apache.html +9116 -0
  19. data/doc/Users guide Apache.idmap.txt +6 -2
  20. data/doc/Users guide Apache.txt +26 -7
  21. data/doc/Users guide Nginx.html +9025 -0
  22. data/doc/Users guide Nginx.idmap.txt +7 -3
  23. data/doc/Users guide Nginx.txt +29 -6
  24. data/doc/Users guide Standalone.html +3983 -0
  25. data/doc/Users guide.html +1748 -0
  26. data/doc/users_guide_snippets/installation.txt +4 -4
  27. data/ext/apache2/Configuration.cpp +16 -5
  28. data/ext/apache2/Configuration.hpp +4 -2
  29. data/ext/apache2/Hooks.cpp +44 -19
  30. data/ext/boost/libs/thread/src/pthread/once.cpp +2 -0
  31. data/ext/boost/libs/thread/src/pthread/once_atomic.cpp +6 -0
  32. data/ext/common/AgentsStarter.h +3 -2
  33. data/ext/common/ApplicationPool2/DirectSpawner.h +14 -4
  34. data/ext/common/ApplicationPool2/DummySpawner.h +12 -7
  35. data/ext/common/ApplicationPool2/Implementation.cpp +1 -1
  36. data/ext/common/ApplicationPool2/Process.h +2 -1
  37. data/ext/common/ApplicationPool2/Session.h +6 -6
  38. data/ext/common/ApplicationPool2/SmartSpawner.h +19 -4
  39. data/ext/common/ApplicationPool2/Socket.h +59 -27
  40. data/ext/common/ApplicationPool2/Spawner.h +2 -2
  41. data/ext/common/BackgroundEventLoop.cpp +6 -1
  42. data/ext/common/Constants.h +1 -1
  43. data/ext/common/EventedClient.h +1 -1
  44. data/ext/common/EventedServer.h +2 -2
  45. data/ext/common/FileDescriptor.h +25 -6
  46. data/ext/common/Logging.cpp +107 -52
  47. data/ext/common/Logging.h +146 -19
  48. data/ext/common/MessageClient.h +2 -2
  49. data/ext/common/MessageServer.h +3 -2
  50. data/ext/common/RandomGenerator.h +8 -7
  51. data/ext/common/SafeLibev.h +5 -1
  52. data/ext/common/ServerKit/AcceptLoadBalancer.h +9 -4
  53. data/ext/common/ServerKit/FdSinkChannel.h +5 -2
  54. data/ext/common/ServerKit/FdSourceChannel.h +5 -2
  55. data/ext/common/ServerKit/FileBufferedChannel.h +2 -0
  56. data/ext/common/ServerKit/FileBufferedFdSinkChannel.h +7 -2
  57. data/ext/common/ServerKit/HttpServer.h +6 -0
  58. data/ext/common/ServerKit/Server.h +40 -3
  59. data/ext/common/StaticString.h +20 -0
  60. data/ext/common/UnionStation/Connection.h +3 -1
  61. data/ext/common/UnionStation/Core.h +6 -4
  62. data/ext/common/Utils.cpp +4 -3
  63. data/ext/common/Utils/DateParsing.h +19 -5
  64. data/ext/common/Utils/FastStringStream.h +183 -0
  65. data/ext/common/Utils/IOUtils.cpp +47 -28
  66. data/ext/common/Utils/IOUtils.h +56 -12
  67. data/ext/common/Utils/MessagePassing.h +3 -3
  68. data/ext/common/Utils/ProcessMetricsCollector.h +2 -2
  69. data/ext/common/Utils/ScopeGuard.h +16 -5
  70. data/ext/common/Utils/SpeedMeter.h +2 -2
  71. data/ext/common/Utils/StrIntUtils.cpp +6 -6
  72. data/ext/common/Utils/StrIntUtils.h +2 -1
  73. data/ext/common/agents/Base.cpp +56 -4
  74. data/ext/common/agents/Base.h +2 -1
  75. data/ext/common/agents/HelperAgent/AdminServer.h +122 -11
  76. data/ext/common/agents/HelperAgent/Main.cpp +16 -5
  77. data/ext/common/agents/HelperAgent/OptionParser.h +7 -1
  78. data/ext/common/agents/HelperAgent/RequestHandler.h +1 -1
  79. data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +10 -1
  80. data/ext/common/agents/HelperAgent/RequestHandler/Request.h +8 -0
  81. data/ext/common/agents/HelperAgent/RequestHandler/TurboCaching.h +4 -3
  82. data/ext/common/agents/LoggingAgent/AdminServer.h +57 -11
  83. data/ext/common/agents/LoggingAgent/LoggingServer.h +3 -3
  84. data/ext/common/agents/LoggingAgent/Main.cpp +11 -3
  85. data/ext/common/agents/Watchdog/AdminServer.h +53 -11
  86. data/ext/common/agents/Watchdog/AgentWatcher.cpp +3 -3
  87. data/ext/common/agents/Watchdog/Main.cpp +13 -6
  88. data/ext/libeio/ecb.h +1 -1
  89. data/ext/libev/ev.c +13 -1
  90. data/ext/libev/ev.h +3 -0
  91. data/ext/nginx/Configuration.c +28 -6
  92. data/ext/nginx/Configuration.h +2 -1
  93. data/ext/nginx/ngx_http_passenger_module.c +5 -4
  94. data/ext/oxt/dynamic_thread_group.hpp +38 -5
  95. data/lib/phusion_passenger.rb +1 -1
  96. data/lib/phusion_passenger/common_library.rb +9 -5
  97. data/lib/phusion_passenger/config/reopen_logs_command.rb +2 -2
  98. data/lib/phusion_passenger/packaging.rb +23 -37
  99. data/passenger.gemspec +21 -21
  100. metadata +4 -453
  101. metadata.gz.asc +7 -7
  102. data/.gitignore +0 -68
  103. data/.travis.yml +0 -16
  104. data/Gemfile +0 -17
  105. data/Gemfile.lock +0 -39
  106. data/Vagrantfile +0 -54
  107. data/debian.template/README.Debian +0 -15
  108. data/debian.template/changelog +0 -316
  109. data/debian.template/compat +0 -1
  110. data/debian.template/control.erb +0 -91
  111. data/debian.template/copyright +0 -385
  112. data/debian.template/libapache2-mod-passenger.install +0 -3
  113. data/debian.template/libapache2-mod-passenger.postinst +0 -36
  114. data/debian.template/libapache2-mod-passenger.prerm +0 -15
  115. data/debian.template/locations.ini.erb +0 -14
  116. data/debian.template/passenger-dev.install.erb +0 -3
  117. data/debian.template/passenger-doc.install.erb +0 -2
  118. data/debian.template/passenger.conf +0 -6
  119. data/debian.template/passenger.docs +0 -4
  120. data/debian.template/passenger.install.erb +0 -14
  121. data/debian.template/passenger.load +0 -3
  122. data/debian.template/passenger.manpages +0 -3
  123. data/debian.template/patches/series +0 -0
  124. data/debian.template/rules.erb +0 -76
  125. data/debian.template/source/format +0 -1
  126. data/ext/common/EventedBufferedInput.h +0 -458
  127. data/packaging/rpm/LICENSE.txt +0 -19
  128. data/packaging/rpm/Makefile +0 -13
  129. data/packaging/rpm/README.md +0 -41
  130. data/packaging/rpm/Vagrantfile +0 -38
  131. data/packaging/rpm/Vagrantfile.centos +0 -30
  132. data/packaging/rpm/build +0 -170
  133. data/packaging/rpm/create_project +0 -41
  134. data/packaging/rpm/git_update +0 -88
  135. data/packaging/rpm/image/Dockerfile +0 -37
  136. data/packaging/rpm/image/Gemfile +0 -3
  137. data/packaging/rpm/image/Gemfile.lock +0 -12
  138. data/packaging/rpm/image/RPM-GPG-KEY-amazon-ga +0 -19
  139. data/packaging/rpm/image/amazon2014-i386.cfg +0 -96
  140. data/packaging/rpm/image/amazon2014-x86_64.cfg +0 -96
  141. data/packaging/rpm/image/site-defaults.cfg +0 -168
  142. data/packaging/rpm/internal/build_tasks.rb +0 -238
  143. data/packaging/rpm/internal/dummygpg +0 -11
  144. data/packaging/rpm/internal/exec_build +0 -42
  145. data/packaging/rpm/internal/get_distro_arch +0 -14
  146. data/packaging/rpm/internal/get_distro_id +0 -10
  147. data/packaging/rpm/internal/git_update +0 -27
  148. data/packaging/rpm/internal/inituidgid +0 -17
  149. data/packaging/rpm/internal/my_init +0 -344
  150. data/packaging/rpm/internal/python27 +0 -3
  151. data/packaging/rpm/internal/repo_update +0 -46
  152. data/packaging/rpm/internal/setuser +0 -26
  153. data/packaging/rpm/internal/tracking_helper +0 -40
  154. data/packaging/rpm/jenkins_release +0 -99
  155. data/packaging/rpm/lib/build_tasks_support.rb +0 -402
  156. data/packaging/rpm/lib/preprocessor.rb +0 -341
  157. data/packaging/rpm/nginx_spec/404.html +0 -119
  158. data/packaging/rpm/nginx_spec/50x.html +0 -119
  159. data/packaging/rpm/nginx_spec/index.html +0 -116
  160. data/packaging/rpm/nginx_spec/nginx-auto-cc-gcc.patch +0 -13
  161. data/packaging/rpm/nginx_spec/nginx-logo.png +0 -0
  162. data/packaging/rpm/nginx_spec/nginx-upgrade +0 -13
  163. data/packaging/rpm/nginx_spec/nginx-upgrade.8 +0 -151
  164. data/packaging/rpm/nginx_spec/nginx.conf +0 -131
  165. data/packaging/rpm/nginx_spec/nginx.init +0 -144
  166. data/packaging/rpm/nginx_spec/nginx.logrotate +0 -13
  167. data/packaging/rpm/nginx_spec/nginx.service +0 -15
  168. data/packaging/rpm/nginx_spec/nginx.spec.template +0 -560
  169. data/packaging/rpm/nginx_spec/nginx.sysconfig +0 -4
  170. data/packaging/rpm/nginx_spec/passenger.conf +0 -9
  171. data/packaging/rpm/nginx_spec/poweredby.png +0 -0
  172. data/packaging/rpm/passenger_spec/apache-passenger.conf.in +0 -26
  173. data/packaging/rpm/passenger_spec/config.json +0 -30
  174. data/packaging/rpm/passenger_spec/passenger.logrotate +0 -7
  175. data/packaging/rpm/passenger_spec/passenger.spec.template +0 -478
  176. data/packaging/rpm/passenger_spec/passenger_dynamic_thread_group.patch +0 -16
  177. data/packaging/rpm/passenger_spec/passenger_tests_default_config_example.patch +0 -44
  178. data/packaging/rpm/passenger_spec/rubygem-passenger-4.0.18-GLIBC_HAVE_LONG_LONG.patch +0 -21
  179. data/packaging/rpm/repo_update +0 -114
  180. data/packaging/rpm/setup-system +0 -61
  181. data/packaging/rpm/shell +0 -10
  182. data/test/.rspec +0 -4
  183. data/test/config.json.example +0 -42
  184. data/test/config.json.rpm-automation +0 -15
  185. data/test/config.json.travis +0 -15
  186. data/test/config.json.vagrant +0 -30
  187. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +0 -124
  188. data/test/cxx/ApplicationPool2/OptionsTest.cpp +0 -30
  189. data/test/cxx/ApplicationPool2/PoolTest.cpp +0 -2062
  190. data/test/cxx/ApplicationPool2/ProcessTest.cpp +0 -130
  191. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +0 -243
  192. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +0 -823
  193. data/test/cxx/BufferedIOTest.cpp +0 -364
  194. data/test/cxx/CachedFileStatTest.cpp +0 -402
  195. data/test/cxx/CxxTestMain.cpp +0 -181
  196. data/test/cxx/DataStructures/LStringTest.cpp +0 -275
  197. data/test/cxx/DataStructures/StringKeyTableTest.cpp +0 -199
  198. data/test/cxx/DateParsingTest.cpp +0 -75
  199. data/test/cxx/DechunkerTest.cpp +0 -250
  200. data/test/cxx/EventedBufferedInputTest.cpp +0 -758
  201. data/test/cxx/EventedClientTest.cpp +0 -523
  202. data/test/cxx/FileChangeCheckerTest.cpp +0 -331
  203. data/test/cxx/FileDescriptorTest.cpp +0 -69
  204. data/test/cxx/FilterSupportTest.cpp +0 -433
  205. data/test/cxx/IOUtilsTest.cpp +0 -861
  206. data/test/cxx/MemoryKit/MbufTest.cpp +0 -213
  207. data/test/cxx/MessageIOTest.cpp +0 -360
  208. data/test/cxx/MessagePassingTest.cpp +0 -81
  209. data/test/cxx/MessageReadersWritersTest.cpp +0 -576
  210. data/test/cxx/MessageServerTest.cpp +0 -393
  211. data/test/cxx/ProcessMetricsCollectorTest.cpp +0 -123
  212. data/test/cxx/RequestHandlerTest.cpp +0 -1463
  213. data/test/cxx/ResponseCacheTest.cpp +0 -322
  214. data/test/cxx/ServerKit/ChannelTest.cpp +0 -1467
  215. data/test/cxx/ServerKit/CookieUtilsTest.cpp +0 -274
  216. data/test/cxx/ServerKit/FileBufferedChannelTest.cpp +0 -992
  217. data/test/cxx/ServerKit/HeaderTableTest.cpp +0 -177
  218. data/test/cxx/ServerKit/HttpServerTest.cpp +0 -1580
  219. data/test/cxx/ServerKit/ServerTest.cpp +0 -408
  220. data/test/cxx/StaticStringTest.cpp +0 -220
  221. data/test/cxx/StringMapTest.cpp +0 -131
  222. data/test/cxx/SystemTimeTest.cpp +0 -37
  223. data/test/cxx/TemplateTest.cpp +0 -118
  224. data/test/cxx/TestSupport.cpp +0 -207
  225. data/test/cxx/TestSupport.h +0 -333
  226. data/test/cxx/UnionStationTest.cpp +0 -741
  227. data/test/cxx/Utils/StrIntUtilsTest.cpp +0 -39
  228. data/test/cxx/UtilsTest.cpp +0 -672
  229. data/test/cxx/VariantMapTest.cpp +0 -191
  230. data/test/gdbinit.example +0 -34
  231. data/test/integration_tests/apache2_tests.rb +0 -585
  232. data/test/integration_tests/downloaded_binaries_tests.rb +0 -185
  233. data/test/integration_tests/native_packaging_spec.rb +0 -368
  234. data/test/integration_tests/nginx_tests.rb +0 -402
  235. data/test/integration_tests/shared/example_webapp_tests.rb +0 -289
  236. data/test/integration_tests/source_packaging_test.rb +0 -201
  237. data/test/integration_tests/spec_helper.rb +0 -22
  238. data/test/integration_tests/standalone_tests.rb +0 -392
  239. data/test/node/line_reader_spec.js +0 -338
  240. data/test/node/spec_helper.js +0 -65
  241. data/test/oxt/backtrace_test.cpp +0 -88
  242. data/test/oxt/counter.hpp +0 -55
  243. data/test/oxt/dynamic_thread_group_test.cpp +0 -131
  244. data/test/oxt/oxt_test_main.cpp +0 -27
  245. data/test/oxt/spin_lock_test.cpp +0 -59
  246. data/test/oxt/syscall_interruption_test.cpp +0 -39
  247. data/test/ruby/debug_logging_spec.rb +0 -145
  248. data/test/ruby/message_channel_spec.rb +0 -196
  249. data/test/ruby/rack/loader_spec.rb +0 -42
  250. data/test/ruby/rack/preloader_spec.rb +0 -48
  251. data/test/ruby/rails3.0/loader_spec.rb +0 -26
  252. data/test/ruby/rails3.0/preloader_spec.rb +0 -32
  253. data/test/ruby/rails3.1/loader_spec.rb +0 -26
  254. data/test/ruby/rails3.1/preloader_spec.rb +0 -32
  255. data/test/ruby/rails3.2/loader_spec.rb +0 -26
  256. data/test/ruby/rails3.2/preloader_spec.rb +0 -32
  257. data/test/ruby/rails4.0/loader_spec.rb +0 -28
  258. data/test/ruby/rails4.0/preloader_spec.rb +0 -34
  259. data/test/ruby/rails4.1/loader_spec.rb +0 -28
  260. data/test/ruby/rails4.1/preloader_spec.rb +0 -34
  261. data/test/ruby/request_handler_spec.rb +0 -747
  262. data/test/ruby/shared/loader_sharedspec.rb +0 -247
  263. data/test/ruby/shared/rails/union_station_extensions_sharedspec.rb +0 -357
  264. data/test/ruby/shared/ruby_loader_sharedspec.rb +0 -55
  265. data/test/ruby/spec_helper.rb +0 -114
  266. data/test/ruby/standalone/runtime_installer_spec.rb +0 -402
  267. data/test/ruby/union_station_spec.rb +0 -288
  268. data/test/ruby/utils/file_system_watcher_spec.rb +0 -229
  269. data/test/ruby/utils/hosts_file_parser.rb +0 -258
  270. data/test/ruby/utils/tee_input_spec.rb +0 -235
  271. data/test/ruby/utils/unseekable_socket_spec.rb +0 -66
  272. data/test/ruby/utils_spec.rb +0 -41
  273. data/test/stub/apache2/httpd.conf.erb +0 -122
  274. data/test/stub/apache2/mime.types +0 -748
  275. data/test/stub/garbage1.dat +0 -0
  276. data/test/stub/garbage2.dat +0 -0
  277. data/test/stub/garbage3.dat +0 -0
  278. data/test/stub/http_request.yml +0 -23
  279. data/test/stub/index.html +0 -1
  280. data/test/stub/nginx/koi-utf +0 -109
  281. data/test/stub/nginx/koi-win +0 -103
  282. data/test/stub/nginx/mime.types +0 -70
  283. data/test/stub/nginx/nginx.conf.erb +0 -70
  284. data/test/stub/nginx/win-utf +0 -126
  285. data/test/stub/node/app.js +0 -133
  286. data/test/stub/node/public/.gitignore +0 -0
  287. data/test/stub/node/tmp/.gitignore +0 -0
  288. data/test/stub/rack/config.ru +0 -95
  289. data/test/stub/rack/library.rb +0 -16
  290. data/test/stub/rack/public/.gitignore +0 -0
  291. data/test/stub/rack/start.rb +0 -52
  292. data/test/stub/rack/tmp/.gitignore +0 -0
  293. data/test/stub/rails3.0/.gitignore +0 -4
  294. data/test/stub/rails3.0/Gemfile +0 -22
  295. data/test/stub/rails3.0/Gemfile.lock +0 -80
  296. data/test/stub/rails3.0/Rakefile +0 -10
  297. data/test/stub/rails3.0/app/controllers/application_controller.rb +0 -4
  298. data/test/stub/rails3.0/app/helpers/application_helper.rb +0 -2
  299. data/test/stub/rails3.0/app/views/layouts/application.html.erb +0 -14
  300. data/test/stub/rails3.0/config.ru +0 -4
  301. data/test/stub/rails3.0/config/application.rb +0 -48
  302. data/test/stub/rails3.0/config/boot.rb +0 -13
  303. data/test/stub/rails3.0/config/database.yml +0 -22
  304. data/test/stub/rails3.0/config/environment.rb +0 -5
  305. data/test/stub/rails3.0/config/environments/development.rb +0 -19
  306. data/test/stub/rails3.0/config/environments/production.rb +0 -48
  307. data/test/stub/rails3.0/config/environments/test.rb +0 -32
  308. data/test/stub/rails3.0/config/initializers/backtrace_silencers.rb +0 -7
  309. data/test/stub/rails3.0/config/initializers/inflections.rb +0 -10
  310. data/test/stub/rails3.0/config/initializers/mime_types.rb +0 -5
  311. data/test/stub/rails3.0/config/initializers/passenger.rb +0 -2
  312. data/test/stub/rails3.0/config/initializers/secret_token.rb +0 -7
  313. data/test/stub/rails3.0/config/initializers/session_store.rb +0 -8
  314. data/test/stub/rails3.0/config/locales/en.yml +0 -5
  315. data/test/stub/rails3.0/config/routes.rb +0 -58
  316. data/test/stub/rails3.0/db/seeds.rb +0 -7
  317. data/test/stub/rails3.0/doc/README_FOR_APP +0 -2
  318. data/test/stub/rails3.0/lib/tasks/.gitkeep +0 -0
  319. data/test/stub/rails3.0/log/.gitignore +0 -0
  320. data/test/stub/rails3.0/public/404.html +0 -26
  321. data/test/stub/rails3.0/public/422.html +0 -26
  322. data/test/stub/rails3.0/public/500.html +0 -26
  323. data/test/stub/rails3.0/public/favicon.ico +0 -0
  324. data/test/stub/rails3.0/public/index.html +0 -279
  325. data/test/stub/rails3.0/public/robots.txt +0 -5
  326. data/test/stub/rails3.0/public/stylesheets/.gitkeep +0 -0
  327. data/test/stub/rails3.0/script/rails +0 -9
  328. data/test/stub/rails3.0/test/performance/browsing_test.rb +0 -9
  329. data/test/stub/rails3.0/test/test_helper.rb +0 -13
  330. data/test/stub/rails3.0/vendor/plugins/.gitkeep +0 -0
  331. data/test/stub/rails3.1/.gitignore +0 -15
  332. data/test/stub/rails3.1/Gemfile +0 -37
  333. data/test/stub/rails3.1/Gemfile.lock +0 -115
  334. data/test/stub/rails3.1/README +0 -261
  335. data/test/stub/rails3.1/Rakefile +0 -7
  336. data/test/stub/rails3.1/app/assets/images/rails.png +0 -0
  337. data/test/stub/rails3.1/app/assets/stylesheets/application.css +0 -7
  338. data/test/stub/rails3.1/app/controllers/application_controller.rb +0 -3
  339. data/test/stub/rails3.1/app/helpers/application_helper.rb +0 -2
  340. data/test/stub/rails3.1/app/mailers/.gitkeep +0 -0
  341. data/test/stub/rails3.1/app/models/.gitkeep +0 -0
  342. data/test/stub/rails3.1/app/views/layouts/application.html.erb +0 -14
  343. data/test/stub/rails3.1/config.ru +0 -4
  344. data/test/stub/rails3.1/config/application.rb +0 -48
  345. data/test/stub/rails3.1/config/boot.rb +0 -6
  346. data/test/stub/rails3.1/config/database.yml +0 -25
  347. data/test/stub/rails3.1/config/environment.rb +0 -5
  348. data/test/stub/rails3.1/config/environments/development.rb +0 -30
  349. data/test/stub/rails3.1/config/environments/production.rb +0 -60
  350. data/test/stub/rails3.1/config/environments/test.rb +0 -39
  351. data/test/stub/rails3.1/config/initializers/backtrace_silencers.rb +0 -7
  352. data/test/stub/rails3.1/config/initializers/inflections.rb +0 -10
  353. data/test/stub/rails3.1/config/initializers/mime_types.rb +0 -5
  354. data/test/stub/rails3.1/config/initializers/passenger.rb +0 -2
  355. data/test/stub/rails3.1/config/initializers/secret_token.rb +0 -7
  356. data/test/stub/rails3.1/config/initializers/session_store.rb +0 -8
  357. data/test/stub/rails3.1/config/initializers/wrap_parameters.rb +0 -14
  358. data/test/stub/rails3.1/config/locales/en.yml +0 -5
  359. data/test/stub/rails3.1/config/routes.rb +0 -58
  360. data/test/stub/rails3.1/db/seeds.rb +0 -7
  361. data/test/stub/rails3.1/doc/README_FOR_APP +0 -2
  362. data/test/stub/rails3.1/lib/assets/.gitkeep +0 -0
  363. data/test/stub/rails3.1/lib/tasks/.gitkeep +0 -0
  364. data/test/stub/rails3.1/log/.gitkeep +0 -0
  365. data/test/stub/rails3.1/public/404.html +0 -26
  366. data/test/stub/rails3.1/public/422.html +0 -26
  367. data/test/stub/rails3.1/public/500.html +0 -26
  368. data/test/stub/rails3.1/public/favicon.ico +0 -0
  369. data/test/stub/rails3.1/public/index.html +0 -241
  370. data/test/stub/rails3.1/public/robots.txt +0 -5
  371. data/test/stub/rails3.1/script/rails +0 -6
  372. data/test/stub/rails3.1/test/fixtures/.gitkeep +0 -0
  373. data/test/stub/rails3.1/test/functional/.gitkeep +0 -0
  374. data/test/stub/rails3.1/test/integration/.gitkeep +0 -0
  375. data/test/stub/rails3.1/test/performance/browsing_test.rb +0 -12
  376. data/test/stub/rails3.1/test/test_helper.rb +0 -13
  377. data/test/stub/rails3.1/test/unit/.gitkeep +0 -0
  378. data/test/stub/rails3.1/vendor/assets/stylesheets/.gitkeep +0 -0
  379. data/test/stub/rails3.1/vendor/plugins/.gitkeep +0 -0
  380. data/test/stub/rails3.2/.gitignore +0 -15
  381. data/test/stub/rails3.2/Gemfile +0 -39
  382. data/test/stub/rails3.2/Gemfile.lock +0 -113
  383. data/test/stub/rails3.2/Rakefile +0 -7
  384. data/test/stub/rails3.2/app/assets/images/rails.png +0 -0
  385. data/test/stub/rails3.2/app/assets/stylesheets/application.css +0 -13
  386. data/test/stub/rails3.2/app/controllers/application_controller.rb +0 -3
  387. data/test/stub/rails3.2/app/helpers/application_helper.rb +0 -2
  388. data/test/stub/rails3.2/app/mailers/.gitkeep +0 -0
  389. data/test/stub/rails3.2/app/models/.gitkeep +0 -0
  390. data/test/stub/rails3.2/app/views/layouts/application.html.erb +0 -14
  391. data/test/stub/rails3.2/config.ru +0 -4
  392. data/test/stub/rails3.2/config/application.rb +0 -62
  393. data/test/stub/rails3.2/config/boot.rb +0 -6
  394. data/test/stub/rails3.2/config/database.yml +0 -25
  395. data/test/stub/rails3.2/config/environment.rb +0 -5
  396. data/test/stub/rails3.2/config/environments/development.rb +0 -37
  397. data/test/stub/rails3.2/config/environments/production.rb +0 -67
  398. data/test/stub/rails3.2/config/environments/test.rb +0 -37
  399. data/test/stub/rails3.2/config/initializers/backtrace_silencers.rb +0 -7
  400. data/test/stub/rails3.2/config/initializers/inflections.rb +0 -15
  401. data/test/stub/rails3.2/config/initializers/mime_types.rb +0 -5
  402. data/test/stub/rails3.2/config/initializers/passenger.rb +0 -2
  403. data/test/stub/rails3.2/config/initializers/secret_token.rb +0 -7
  404. data/test/stub/rails3.2/config/initializers/session_store.rb +0 -8
  405. data/test/stub/rails3.2/config/initializers/wrap_parameters.rb +0 -14
  406. data/test/stub/rails3.2/config/locales/en.yml +0 -5
  407. data/test/stub/rails3.2/config/routes.rb +0 -58
  408. data/test/stub/rails3.2/db/seeds.rb +0 -7
  409. data/test/stub/rails3.2/doc/README_FOR_APP +0 -2
  410. data/test/stub/rails3.2/lib/assets/.gitkeep +0 -0
  411. data/test/stub/rails3.2/lib/tasks/.gitkeep +0 -0
  412. data/test/stub/rails3.2/log/.gitkeep +0 -0
  413. data/test/stub/rails3.2/public/404.html +0 -26
  414. data/test/stub/rails3.2/public/422.html +0 -26
  415. data/test/stub/rails3.2/public/500.html +0 -25
  416. data/test/stub/rails3.2/public/favicon.ico +0 -0
  417. data/test/stub/rails3.2/public/index.html +0 -241
  418. data/test/stub/rails3.2/public/robots.txt +0 -5
  419. data/test/stub/rails3.2/script/rails +0 -6
  420. data/test/stub/rails3.2/test/fixtures/.gitkeep +0 -0
  421. data/test/stub/rails3.2/test/functional/.gitkeep +0 -0
  422. data/test/stub/rails3.2/test/integration/.gitkeep +0 -0
  423. data/test/stub/rails3.2/test/performance/browsing_test.rb +0 -12
  424. data/test/stub/rails3.2/test/test_helper.rb +0 -13
  425. data/test/stub/rails3.2/test/unit/.gitkeep +0 -0
  426. data/test/stub/rails3.2/vendor/assets/stylesheets/.gitkeep +0 -0
  427. data/test/stub/rails3.2/vendor/plugins/.gitkeep +0 -0
  428. data/test/stub/rails4.0/.gitignore +0 -16
  429. data/test/stub/rails4.0/Gemfile +0 -45
  430. data/test/stub/rails4.0/Gemfile.lock +0 -126
  431. data/test/stub/rails4.0/README.rdoc +0 -28
  432. data/test/stub/rails4.0/Rakefile +0 -6
  433. data/test/stub/rails4.0/app/assets/images/.keep +0 -0
  434. data/test/stub/rails4.0/app/assets/javascripts/application.js +0 -16
  435. data/test/stub/rails4.0/app/assets/stylesheets/application.css +0 -13
  436. data/test/stub/rails4.0/app/controllers/application_controller.rb +0 -5
  437. data/test/stub/rails4.0/app/controllers/concerns/.keep +0 -0
  438. data/test/stub/rails4.0/app/helpers/application_helper.rb +0 -2
  439. data/test/stub/rails4.0/app/mailers/.keep +0 -0
  440. data/test/stub/rails4.0/app/models/.keep +0 -0
  441. data/test/stub/rails4.0/app/models/concerns/.keep +0 -0
  442. data/test/stub/rails4.0/app/views/layouts/application.html.erb +0 -14
  443. data/test/stub/rails4.0/bin/bundle +0 -3
  444. data/test/stub/rails4.0/bin/rails +0 -4
  445. data/test/stub/rails4.0/bin/rake +0 -4
  446. data/test/stub/rails4.0/config.ru +0 -4
  447. data/test/stub/rails4.0/config/application.rb +0 -23
  448. data/test/stub/rails4.0/config/boot.rb +0 -4
  449. data/test/stub/rails4.0/config/database.yml +0 -25
  450. data/test/stub/rails4.0/config/environment.rb +0 -5
  451. data/test/stub/rails4.0/config/environments/development.rb +0 -29
  452. data/test/stub/rails4.0/config/environments/production.rb +0 -80
  453. data/test/stub/rails4.0/config/environments/test.rb +0 -36
  454. data/test/stub/rails4.0/config/initializers/backtrace_silencers.rb +0 -7
  455. data/test/stub/rails4.0/config/initializers/filter_parameter_logging.rb +0 -4
  456. data/test/stub/rails4.0/config/initializers/inflections.rb +0 -16
  457. data/test/stub/rails4.0/config/initializers/mime_types.rb +0 -5
  458. data/test/stub/rails4.0/config/initializers/passenger.rb +0 -2
  459. data/test/stub/rails4.0/config/initializers/secret_token.rb +0 -12
  460. data/test/stub/rails4.0/config/initializers/session_store.rb +0 -3
  461. data/test/stub/rails4.0/config/initializers/wrap_parameters.rb +0 -14
  462. data/test/stub/rails4.0/config/locales/en.yml +0 -23
  463. data/test/stub/rails4.0/config/routes.rb +0 -57
  464. data/test/stub/rails4.0/db/seeds.rb +0 -7
  465. data/test/stub/rails4.0/lib/assets/.keep +0 -0
  466. data/test/stub/rails4.0/lib/tasks/.keep +0 -0
  467. data/test/stub/rails4.0/log/.keep +0 -0
  468. data/test/stub/rails4.0/public/404.html +0 -58
  469. data/test/stub/rails4.0/public/422.html +0 -58
  470. data/test/stub/rails4.0/public/500.html +0 -57
  471. data/test/stub/rails4.0/public/favicon.ico +0 -0
  472. data/test/stub/rails4.0/public/robots.txt +0 -5
  473. data/test/stub/rails4.0/test/controllers/.keep +0 -0
  474. data/test/stub/rails4.0/test/fixtures/.keep +0 -0
  475. data/test/stub/rails4.0/test/helpers/.keep +0 -0
  476. data/test/stub/rails4.0/test/integration/.keep +0 -0
  477. data/test/stub/rails4.0/test/mailers/.keep +0 -0
  478. data/test/stub/rails4.0/test/models/.keep +0 -0
  479. data/test/stub/rails4.0/test/test_helper.rb +0 -15
  480. data/test/stub/rails4.0/vendor/assets/javascripts/.keep +0 -0
  481. data/test/stub/rails4.0/vendor/assets/stylesheets/.keep +0 -0
  482. data/test/stub/rails4.1/.gitignore +0 -16
  483. data/test/stub/rails4.1/Gemfile +0 -45
  484. data/test/stub/rails4.1/Gemfile.lock +0 -129
  485. data/test/stub/rails4.1/README.rdoc +0 -28
  486. data/test/stub/rails4.1/Rakefile +0 -6
  487. data/test/stub/rails4.1/app/assets/images/.keep +0 -0
  488. data/test/stub/rails4.1/app/assets/javascripts/application.js +0 -16
  489. data/test/stub/rails4.1/app/assets/stylesheets/application.css +0 -13
  490. data/test/stub/rails4.1/app/controllers/application_controller.rb +0 -5
  491. data/test/stub/rails4.1/app/controllers/concerns/.keep +0 -0
  492. data/test/stub/rails4.1/app/helpers/application_helper.rb +0 -2
  493. data/test/stub/rails4.1/app/mailers/.keep +0 -0
  494. data/test/stub/rails4.1/app/models/.keep +0 -0
  495. data/test/stub/rails4.1/app/models/concerns/.keep +0 -0
  496. data/test/stub/rails4.1/app/views/layouts/application.html.erb +0 -14
  497. data/test/stub/rails4.1/bin/bundle +0 -3
  498. data/test/stub/rails4.1/bin/rails +0 -4
  499. data/test/stub/rails4.1/bin/rake +0 -4
  500. data/test/stub/rails4.1/config.ru +0 -4
  501. data/test/stub/rails4.1/config/application.rb +0 -23
  502. data/test/stub/rails4.1/config/boot.rb +0 -4
  503. data/test/stub/rails4.1/config/database.yml +0 -25
  504. data/test/stub/rails4.1/config/environment.rb +0 -5
  505. data/test/stub/rails4.1/config/environments/development.rb +0 -29
  506. data/test/stub/rails4.1/config/environments/production.rb +0 -80
  507. data/test/stub/rails4.1/config/environments/test.rb +0 -36
  508. data/test/stub/rails4.1/config/initializers/backtrace_silencers.rb +0 -7
  509. data/test/stub/rails4.1/config/initializers/filter_parameter_logging.rb +0 -4
  510. data/test/stub/rails4.1/config/initializers/inflections.rb +0 -16
  511. data/test/stub/rails4.1/config/initializers/mime_types.rb +0 -5
  512. data/test/stub/rails4.1/config/initializers/passenger.rb +0 -5
  513. data/test/stub/rails4.1/config/initializers/secret_token.rb +0 -12
  514. data/test/stub/rails4.1/config/initializers/session_store.rb +0 -3
  515. data/test/stub/rails4.1/config/initializers/wrap_parameters.rb +0 -14
  516. data/test/stub/rails4.1/config/locales/en.yml +0 -23
  517. data/test/stub/rails4.1/config/routes.rb +0 -57
  518. data/test/stub/rails4.1/db/seeds.rb +0 -7
  519. data/test/stub/rails4.1/lib/assets/.keep +0 -0
  520. data/test/stub/rails4.1/lib/tasks/.keep +0 -0
  521. data/test/stub/rails4.1/log/.keep +0 -0
  522. data/test/stub/rails4.1/public/404.html +0 -58
  523. data/test/stub/rails4.1/public/422.html +0 -58
  524. data/test/stub/rails4.1/public/500.html +0 -57
  525. data/test/stub/rails4.1/public/favicon.ico +0 -0
  526. data/test/stub/rails4.1/public/robots.txt +0 -5
  527. data/test/stub/rails4.1/test/controllers/.keep +0 -0
  528. data/test/stub/rails4.1/test/fixtures/.keep +0 -0
  529. data/test/stub/rails4.1/test/helpers/.keep +0 -0
  530. data/test/stub/rails4.1/test/integration/.keep +0 -0
  531. data/test/stub/rails4.1/test/mailers/.keep +0 -0
  532. data/test/stub/rails4.1/test/models/.keep +0 -0
  533. data/test/stub/rails4.1/test/test_helper.rb +0 -15
  534. data/test/stub/rails4.1/vendor/assets/javascripts/.keep +0 -0
  535. data/test/stub/rails4.1/vendor/assets/stylesheets/.keep +0 -0
  536. data/test/stub/start_error.pl +0 -24
  537. data/test/stub/upload_data.txt +0 -494
  538. data/test/stub/wsgi/passenger_wsgi.py +0 -212
  539. data/test/stub/wsgi/public/.gitignore +0 -0
  540. data/test/stub/wsgi/tmp/.gitignore +0 -0
  541. data/test/support/allocate_memory.c +0 -14
  542. data/test/support/apache2_controller.rb +0 -258
  543. data/test/support/multipart.rb +0 -62
  544. data/test/support/nginx_controller.rb +0 -97
  545. data/test/support/placebo-preloader.rb +0 -88
  546. data/test/support/test_helper.rb +0 -455
  547. data/test/support/valgrind.h +0 -2539
  548. data/test/tut/tut.h +0 -1310
  549. data/test/tut/tut_reporter.h +0 -256
  550. data/test/valgrind-osx.supp +0 -7
@@ -0,0 +1,2430 @@
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 and Architecture</title>
7
+ <style type="text/css">
8
+ /* Shared CSS for AsciiDoc xhtml11 and html5 backends */
9
+
10
+ /* Default font. */
11
+ body {
12
+ font-family: Georgia,serif;
13
+ }
14
+
15
+ /* Title font. */
16
+ h1, h2, h3, h4, h5, h6,
17
+ div.title, caption.title,
18
+ thead, p.table.header,
19
+ #toctitle,
20
+ #author, #revnumber, #revdate, #revremark,
21
+ #footer {
22
+ font-family: Arial,Helvetica,sans-serif;
23
+ }
24
+
25
+ body {
26
+ margin: 1em 5% 1em 5%;
27
+ }
28
+
29
+ a {
30
+ color: blue;
31
+ text-decoration: underline;
32
+ }
33
+ a:visited {
34
+ color: fuchsia;
35
+ }
36
+
37
+ em {
38
+ font-style: italic;
39
+ color: navy;
40
+ }
41
+
42
+ strong {
43
+ font-weight: bold;
44
+ color: #083194;
45
+ }
46
+
47
+ h1, h2, h3, h4, h5, h6 {
48
+ color: #527bbd;
49
+ margin-top: 1.2em;
50
+ margin-bottom: 0.5em;
51
+ line-height: 1.3;
52
+ }
53
+
54
+ h1, h2, h3 {
55
+ border-bottom: 2px solid silver;
56
+ }
57
+ h2 {
58
+ padding-top: 0.5em;
59
+ }
60
+ h3 {
61
+ float: left;
62
+ }
63
+ h3 + * {
64
+ clear: left;
65
+ }
66
+ h5 {
67
+ font-size: 1.0em;
68
+ }
69
+
70
+ div.sectionbody {
71
+ margin-left: 0;
72
+ }
73
+
74
+ hr {
75
+ border: 1px solid silver;
76
+ }
77
+
78
+ p {
79
+ margin-top: 0.5em;
80
+ margin-bottom: 0.5em;
81
+ }
82
+
83
+ ul, ol, li > p {
84
+ margin-top: 0;
85
+ }
86
+ ul > li { color: #aaa; }
87
+ ul > li > * { color: black; }
88
+
89
+ pre {
90
+ padding: 0;
91
+ margin: 0;
92
+ overflow: auto;
93
+ }
94
+
95
+ #author {
96
+ color: #527bbd;
97
+ font-weight: bold;
98
+ font-size: 1.1em;
99
+ }
100
+ #email {
101
+ }
102
+ #revnumber, #revdate, #revremark {
103
+ }
104
+
105
+ #footer {
106
+ font-size: small;
107
+ border-top: 2px solid silver;
108
+ padding-top: 0.5em;
109
+ margin-top: 4.0em;
110
+ }
111
+ #footer-text {
112
+ float: left;
113
+ padding-bottom: 0.5em;
114
+ }
115
+ #footer-badges {
116
+ float: right;
117
+ padding-bottom: 0.5em;
118
+ }
119
+
120
+ #preamble {
121
+ margin-top: 1.5em;
122
+ margin-bottom: 1.5em;
123
+ }
124
+ div.imageblock, div.exampleblock, div.verseblock,
125
+ div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
126
+ div.admonitionblock {
127
+ margin-top: 1.0em;
128
+ margin-bottom: 1.5em;
129
+ }
130
+ div.admonitionblock {
131
+ margin-top: 2.0em;
132
+ margin-bottom: 2.0em;
133
+ margin-right: 10%;
134
+ color: #606060;
135
+ }
136
+
137
+ div.content { /* Block element content. */
138
+ padding: 0;
139
+ }
140
+
141
+ /* Block element titles. */
142
+ div.title, caption.title {
143
+ color: #527bbd;
144
+ font-weight: bold;
145
+ text-align: left;
146
+ margin-top: 1.0em;
147
+ margin-bottom: 0.5em;
148
+ }
149
+ div.title + * {
150
+ margin-top: 0;
151
+ }
152
+
153
+ td div.title:first-child {
154
+ margin-top: 0.0em;
155
+ }
156
+ div.content div.title:first-child {
157
+ margin-top: 0.0em;
158
+ }
159
+ div.content + div.title {
160
+ margin-top: 0.0em;
161
+ }
162
+
163
+ div.sidebarblock > div.content {
164
+ background: #ffffee;
165
+ border: 1px solid #dddddd;
166
+ border-left: 4px solid #f0f0f0;
167
+ padding: 0.5em;
168
+ }
169
+
170
+ div.listingblock > div.content {
171
+ border: 1px solid #dddddd;
172
+ border-left: 5px solid #f0f0f0;
173
+ background: #f8f8f8;
174
+ padding: 0.5em;
175
+ }
176
+
177
+ div.quoteblock, div.verseblock {
178
+ padding-left: 1.0em;
179
+ margin-left: 1.0em;
180
+ margin-right: 10%;
181
+ border-left: 5px solid #f0f0f0;
182
+ color: #777777;
183
+ }
184
+
185
+ div.quoteblock > div.attribution {
186
+ padding-top: 0.5em;
187
+ text-align: right;
188
+ }
189
+
190
+ div.verseblock > pre.content {
191
+ font-family: inherit;
192
+ font-size: inherit;
193
+ }
194
+ div.verseblock > div.attribution {
195
+ padding-top: 0.75em;
196
+ text-align: left;
197
+ }
198
+ /* DEPRECATED: Pre version 8.2.7 verse style literal block. */
199
+ div.verseblock + div.attribution {
200
+ text-align: left;
201
+ }
202
+
203
+ div.admonitionblock .icon {
204
+ vertical-align: top;
205
+ font-size: 1.1em;
206
+ font-weight: bold;
207
+ text-decoration: underline;
208
+ color: #527bbd;
209
+ padding-right: 0.5em;
210
+ }
211
+ div.admonitionblock td.content {
212
+ padding-left: 0.5em;
213
+ border-left: 3px solid #dddddd;
214
+ }
215
+
216
+ div.exampleblock > div.content {
217
+ border-left: 3px solid #dddddd;
218
+ padding-left: 0.5em;
219
+ }
220
+
221
+ div.imageblock div.content { padding-left: 0; }
222
+ span.image img { border-style: none; }
223
+ a.image:visited { color: white; }
224
+
225
+ dl {
226
+ margin-top: 0.8em;
227
+ margin-bottom: 0.8em;
228
+ }
229
+ dt {
230
+ margin-top: 0.5em;
231
+ margin-bottom: 0;
232
+ font-style: normal;
233
+ color: navy;
234
+ }
235
+ dd > *:first-child {
236
+ margin-top: 0.1em;
237
+ }
238
+
239
+ ul, ol {
240
+ list-style-position: outside;
241
+ }
242
+ ol.arabic {
243
+ list-style-type: decimal;
244
+ }
245
+ ol.loweralpha {
246
+ list-style-type: lower-alpha;
247
+ }
248
+ ol.upperalpha {
249
+ list-style-type: upper-alpha;
250
+ }
251
+ ol.lowerroman {
252
+ list-style-type: lower-roman;
253
+ }
254
+ ol.upperroman {
255
+ list-style-type: upper-roman;
256
+ }
257
+
258
+ div.compact ul, div.compact ol,
259
+ div.compact p, div.compact p,
260
+ div.compact div, div.compact div {
261
+ margin-top: 0.1em;
262
+ margin-bottom: 0.1em;
263
+ }
264
+
265
+ tfoot {
266
+ font-weight: bold;
267
+ }
268
+ td > div.verse {
269
+ white-space: pre;
270
+ }
271
+
272
+ div.hdlist {
273
+ margin-top: 0.8em;
274
+ margin-bottom: 0.8em;
275
+ }
276
+ div.hdlist tr {
277
+ padding-bottom: 15px;
278
+ }
279
+ dt.hdlist1.strong, td.hdlist1.strong {
280
+ font-weight: bold;
281
+ }
282
+ td.hdlist1 {
283
+ vertical-align: top;
284
+ font-style: normal;
285
+ padding-right: 0.8em;
286
+ color: navy;
287
+ }
288
+ td.hdlist2 {
289
+ vertical-align: top;
290
+ }
291
+ div.hdlist.compact tr {
292
+ margin: 0;
293
+ padding-bottom: 0;
294
+ }
295
+
296
+ .comment {
297
+ background: yellow;
298
+ }
299
+
300
+ .footnote, .footnoteref {
301
+ font-size: 0.8em;
302
+ }
303
+
304
+ span.footnote, span.footnoteref {
305
+ vertical-align: super;
306
+ }
307
+
308
+ #footnotes {
309
+ margin: 20px 0 20px 0;
310
+ padding: 7px 0 0 0;
311
+ }
312
+
313
+ #footnotes div.footnote {
314
+ margin: 0 0 5px 0;
315
+ }
316
+
317
+ #footnotes hr {
318
+ border: none;
319
+ border-top: 1px solid silver;
320
+ height: 1px;
321
+ text-align: left;
322
+ margin-left: 0;
323
+ width: 20%;
324
+ min-width: 100px;
325
+ }
326
+
327
+ div.colist td {
328
+ padding-right: 0.5em;
329
+ padding-bottom: 0.3em;
330
+ vertical-align: top;
331
+ }
332
+ div.colist td img {
333
+ margin-top: 0.3em;
334
+ }
335
+
336
+ @media print {
337
+ #footer-badges { display: none; }
338
+ }
339
+
340
+ #toc {
341
+ margin-bottom: 2.5em;
342
+ }
343
+
344
+ #toctitle {
345
+ color: #527bbd;
346
+ font-size: 1.1em;
347
+ font-weight: bold;
348
+ margin-top: 1.0em;
349
+ margin-bottom: 0.1em;
350
+ }
351
+
352
+ div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
353
+ margin-top: 0;
354
+ margin-bottom: 0;
355
+ }
356
+ div.toclevel2 {
357
+ margin-left: 2em;
358
+ font-size: 0.9em;
359
+ }
360
+ div.toclevel3 {
361
+ margin-left: 4em;
362
+ font-size: 0.9em;
363
+ }
364
+ div.toclevel4 {
365
+ margin-left: 6em;
366
+ font-size: 0.9em;
367
+ }
368
+
369
+ span.aqua { color: aqua; }
370
+ span.black { color: black; }
371
+ span.blue { color: blue; }
372
+ span.fuchsia { color: fuchsia; }
373
+ span.gray { color: gray; }
374
+ span.green { color: green; }
375
+ span.lime { color: lime; }
376
+ span.maroon { color: maroon; }
377
+ span.navy { color: navy; }
378
+ span.olive { color: olive; }
379
+ span.purple { color: purple; }
380
+ span.red { color: red; }
381
+ span.silver { color: silver; }
382
+ span.teal { color: teal; }
383
+ span.white { color: white; }
384
+ span.yellow { color: yellow; }
385
+
386
+ span.aqua-background { background: aqua; }
387
+ span.black-background { background: black; }
388
+ span.blue-background { background: blue; }
389
+ span.fuchsia-background { background: fuchsia; }
390
+ span.gray-background { background: gray; }
391
+ span.green-background { background: green; }
392
+ span.lime-background { background: lime; }
393
+ span.maroon-background { background: maroon; }
394
+ span.navy-background { background: navy; }
395
+ span.olive-background { background: olive; }
396
+ span.purple-background { background: purple; }
397
+ span.red-background { background: red; }
398
+ span.silver-background { background: silver; }
399
+ span.teal-background { background: teal; }
400
+ span.white-background { background: white; }
401
+ span.yellow-background { background: yellow; }
402
+
403
+ span.big { font-size: 2em; }
404
+ span.small { font-size: 0.6em; }
405
+
406
+ span.underline { text-decoration: underline; }
407
+ span.overline { text-decoration: overline; }
408
+ span.line-through { text-decoration: line-through; }
409
+
410
+
411
+ /*
412
+ * xhtml11 specific
413
+ *
414
+ * */
415
+
416
+ tt {
417
+ font-family: monospace;
418
+ font-size: inherit;
419
+ color: navy;
420
+ }
421
+
422
+ div.tableblock {
423
+ margin-top: 1.0em;
424
+ margin-bottom: 1.5em;
425
+ }
426
+ div.tableblock > table {
427
+ border: 3px solid #527bbd;
428
+ }
429
+ thead, p.table.header {
430
+ font-weight: bold;
431
+ color: #527bbd;
432
+ }
433
+ p.table {
434
+ margin-top: 0;
435
+ }
436
+ /* Because the table frame attribute is overriden by CSS in most browsers. */
437
+ div.tableblock > table[frame="void"] {
438
+ border-style: none;
439
+ }
440
+ div.tableblock > table[frame="hsides"] {
441
+ border-left-style: none;
442
+ border-right-style: none;
443
+ }
444
+ div.tableblock > table[frame="vsides"] {
445
+ border-top-style: none;
446
+ border-bottom-style: none;
447
+ }
448
+
449
+
450
+ /*
451
+ * html5 specific
452
+ *
453
+ * */
454
+
455
+ .monospaced {
456
+ font-family: monospace;
457
+ font-size: inherit;
458
+ color: navy;
459
+ }
460
+
461
+ table.tableblock {
462
+ margin-top: 1.0em;
463
+ margin-bottom: 1.5em;
464
+ }
465
+ thead, p.tableblock.header {
466
+ font-weight: bold;
467
+ color: #527bbd;
468
+ }
469
+ p.tableblock {
470
+ margin-top: 0;
471
+ }
472
+ table.tableblock {
473
+ border-width: 3px;
474
+ border-spacing: 0px;
475
+ border-style: solid;
476
+ border-color: #527bbd;
477
+ border-collapse: collapse;
478
+ }
479
+ th.tableblock, td.tableblock {
480
+ border-width: 1px;
481
+ padding: 4px;
482
+ border-style: solid;
483
+ border-color: #527bbd;
484
+ }
485
+
486
+ table.tableblock.frame-topbot {
487
+ border-left-style: hidden;
488
+ border-right-style: hidden;
489
+ }
490
+ table.tableblock.frame-sides {
491
+ border-top-style: hidden;
492
+ border-bottom-style: hidden;
493
+ }
494
+ table.tableblock.frame-none {
495
+ border-style: hidden;
496
+ }
497
+
498
+ th.tableblock.halign-left, td.tableblock.halign-left {
499
+ text-align: left;
500
+ }
501
+ th.tableblock.halign-center, td.tableblock.halign-center {
502
+ text-align: center;
503
+ }
504
+ th.tableblock.halign-right, td.tableblock.halign-right {
505
+ text-align: right;
506
+ }
507
+
508
+ th.tableblock.valign-top, td.tableblock.valign-top {
509
+ vertical-align: top;
510
+ }
511
+ th.tableblock.valign-middle, td.tableblock.valign-middle {
512
+ vertical-align: middle;
513
+ }
514
+ th.tableblock.valign-bottom, td.tableblock.valign-bottom {
515
+ vertical-align: bottom;
516
+ }
517
+
518
+
519
+ /*
520
+ * manpage specific
521
+ *
522
+ * */
523
+
524
+ body.manpage h1 {
525
+ padding-top: 0.5em;
526
+ padding-bottom: 0.5em;
527
+ border-top: 2px solid silver;
528
+ border-bottom: 2px solid silver;
529
+ }
530
+ body.manpage h2 {
531
+ border-style: none;
532
+ }
533
+ body.manpage div.sectionbody {
534
+ margin-left: 3em;
535
+ }
536
+
537
+ @media print {
538
+ body.manpage div#toc { display: none; }
539
+ }
540
+
541
+
542
+ /*
543
+ * Theme specific overrides of the preceding (asciidoc.css) CSS.
544
+ *
545
+ */
546
+ body {
547
+ font-family: Garamond, Georgia, serif;
548
+ font-size: 17px;
549
+ color: #3E4349;
550
+ line-height: 1.3em;
551
+ }
552
+ h1, h2, h3, h4, h5, h6,
553
+ div.title, caption.title,
554
+ thead, p.table.header,
555
+ #toctitle,
556
+ #author, #revnumber, #revdate, #revremark,
557
+ #footer {
558
+ font-family: Garmond, Georgia, serif;
559
+ font-weight: normal;
560
+ border-bottom-width: 0;
561
+ color: #3E4349;
562
+ }
563
+ div.title, caption.title { color: #596673; font-weight: bold; }
564
+ h1 { font-size: 240%; }
565
+ h2 { font-size: 180%; }
566
+ h3 { font-size: 150%; }
567
+ h4 { font-size: 130%; }
568
+ h5 { font-size: 115%; }
569
+ h6 { font-size: 100%; }
570
+ #header h1 { margin-top: 0; }
571
+ #toc {
572
+ color: #444444;
573
+ line-height: 1.5;
574
+ padding-top: 1.5em;
575
+ }
576
+ #toctitle {
577
+ font-size: 20px;
578
+ }
579
+ #toc a {
580
+ border-bottom: 1px dotted #999999;
581
+ color: #444444 !important;
582
+ text-decoration: none !important;
583
+ }
584
+ #toc a:hover {
585
+ border-bottom: 1px solid #6D4100;
586
+ color: #6D4100 !important;
587
+ text-decoration: none !important;
588
+ }
589
+ div.toclevel1 { margin-top: 0.2em; font-size: 16px; }
590
+ div.toclevel2 { margin-top: 0.15em; font-size: 14px; }
591
+ em, dt, td.hdlist1 { color: black; }
592
+ strong { color: #3E4349; }
593
+ a { color: #004B6B; text-decoration: none; border-bottom: 1px dotted #004B6B; }
594
+ a:visited { color: #615FA0; border-bottom: 1px dotted #615FA0; }
595
+ a:hover { color: #6D4100; border-bottom: 1px solid #6D4100; }
596
+ div.tableblock > table, table.tableblock { border: 3px solid #E8E8E8; }
597
+ th.tableblock, td.tableblock { border: 1px solid #E8E8E8; }
598
+ ul > li > * { color: #3E4349; }
599
+ pre, tt, .monospaced { font-family: Consolas,Menlo,'Deja Vu Sans Mono','Bitstream Vera Sans Mono',monospace; }
600
+ tt, .monospaced { font-size: 0.9em; color: black;
601
+ }
602
+ div.exampleblock > div.content, div.sidebarblock > div.content, div.listingblock > div.content { border-width: 0 0 0 3px; border-color: #E8E8E8; }
603
+ div.verseblock { border-left-width: 0; margin-left: 3em; }
604
+ div.quoteblock { border-left-width: 3px; margin-left: 0; margin-right: 0;}
605
+ div.admonitionblock td.content { border-left: 3px solid #E8E8E8; }
606
+ </style>
607
+ <script type="text/javascript">
608
+ /*<![CDATA[*/
609
+ var asciidoc = { // Namespace.
610
+
611
+ /////////////////////////////////////////////////////////////////////
612
+ // Table Of Contents generator
613
+ /////////////////////////////////////////////////////////////////////
614
+
615
+ /* Author: Mihai Bazon, September 2002
616
+ * http://students.infoiasi.ro/~mishoo
617
+ *
618
+ * Table Of Content generator
619
+ * Version: 0.4
620
+ *
621
+ * Feel free to use this script under the terms of the GNU General Public
622
+ * License, as long as you do not remove or alter this notice.
623
+ */
624
+
625
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
626
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
627
+
628
+ // toclevels = 1..4.
629
+ toc: function (toclevels) {
630
+
631
+ function getText(el) {
632
+ var text = "";
633
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
634
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
635
+ text += i.data;
636
+ else if (i.firstChild != null)
637
+ text += getText(i);
638
+ }
639
+ return text;
640
+ }
641
+
642
+ function TocEntry(el, text, toclevel) {
643
+ this.element = el;
644
+ this.text = text;
645
+ this.toclevel = toclevel;
646
+ }
647
+
648
+ function tocEntries(el, toclevels) {
649
+ var result = new Array;
650
+ var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
651
+ // Function that scans the DOM tree for header elements (the DOM2
652
+ // nodeIterator API would be a better technique but not supported by all
653
+ // browsers).
654
+ var iterate = function (el) {
655
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
656
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
657
+ var mo = re.exec(i.tagName);
658
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
659
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
660
+ }
661
+ iterate(i);
662
+ }
663
+ }
664
+ }
665
+ iterate(el);
666
+ return result;
667
+ }
668
+
669
+ var toc = document.getElementById("toc");
670
+ if (!toc) {
671
+ return;
672
+ }
673
+
674
+ // Delete existing TOC entries in case we're reloading the TOC.
675
+ var tocEntriesToRemove = [];
676
+ var i;
677
+ for (i = 0; i < toc.childNodes.length; i++) {
678
+ var entry = toc.childNodes[i];
679
+ if (entry.nodeName.toLowerCase() == 'div'
680
+ && entry.getAttribute("class")
681
+ && entry.getAttribute("class").match(/^toclevel/))
682
+ tocEntriesToRemove.push(entry);
683
+ }
684
+ for (i = 0; i < tocEntriesToRemove.length; i++) {
685
+ toc.removeChild(tocEntriesToRemove[i]);
686
+ }
687
+
688
+ // Rebuild TOC entries.
689
+ var entries = tocEntries(document.getElementById("content"), toclevels);
690
+ for (var i = 0; i < entries.length; ++i) {
691
+ var entry = entries[i];
692
+ if (entry.element.id == "")
693
+ entry.element.id = "_toc_" + i;
694
+ var a = document.createElement("a");
695
+ a.href = "#" + entry.element.id;
696
+ a.appendChild(document.createTextNode(entry.text));
697
+ var div = document.createElement("div");
698
+ div.appendChild(a);
699
+ div.className = "toclevel" + entry.toclevel;
700
+ toc.appendChild(div);
701
+ }
702
+ if (entries.length == 0)
703
+ toc.parentNode.removeChild(toc);
704
+ },
705
+
706
+
707
+ /////////////////////////////////////////////////////////////////////
708
+ // Footnotes generator
709
+ /////////////////////////////////////////////////////////////////////
710
+
711
+ /* Based on footnote generation code from:
712
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
713
+ */
714
+
715
+ footnotes: function () {
716
+ // Delete existing footnote entries in case we're reloading the footnodes.
717
+ var i;
718
+ var noteholder = document.getElementById("footnotes");
719
+ if (!noteholder) {
720
+ return;
721
+ }
722
+ var entriesToRemove = [];
723
+ for (i = 0; i < noteholder.childNodes.length; i++) {
724
+ var entry = noteholder.childNodes[i];
725
+ if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
726
+ entriesToRemove.push(entry);
727
+ }
728
+ for (i = 0; i < entriesToRemove.length; i++) {
729
+ noteholder.removeChild(entriesToRemove[i]);
730
+ }
731
+
732
+ // Rebuild footnote entries.
733
+ var cont = document.getElementById("content");
734
+ var spans = cont.getElementsByTagName("span");
735
+ var refs = {};
736
+ var n = 0;
737
+ for (i=0; i<spans.length; i++) {
738
+ if (spans[i].className == "footnote") {
739
+ n++;
740
+ var note = spans[i].getAttribute("data-note");
741
+ if (!note) {
742
+ // Use [\s\S] in place of . so multi-line matches work.
743
+ // Because JavaScript has no s (dotall) regex flag.
744
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
745
+ spans[i].innerHTML =
746
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
747
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
748
+ spans[i].setAttribute("data-note", note);
749
+ }
750
+ noteholder.innerHTML +=
751
+ "<div class='footnote' id='_footnote_" + n + "'>" +
752
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
753
+ n + "</a>. " + note + "</div>";
754
+ var id =spans[i].getAttribute("id");
755
+ if (id != null) refs["#"+id] = n;
756
+ }
757
+ }
758
+ if (n == 0)
759
+ noteholder.parentNode.removeChild(noteholder);
760
+ else {
761
+ // Process footnoterefs.
762
+ for (i=0; i<spans.length; i++) {
763
+ if (spans[i].className == "footnoteref") {
764
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
765
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
766
+ n = refs[href];
767
+ spans[i].innerHTML =
768
+ "[<a href='#_footnote_" + n +
769
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
770
+ }
771
+ }
772
+ }
773
+ },
774
+
775
+ install: function(toclevels) {
776
+ var timerId;
777
+
778
+ function reinstall() {
779
+ asciidoc.footnotes();
780
+ if (toclevels) {
781
+ asciidoc.toc(toclevels);
782
+ }
783
+ }
784
+
785
+ function reinstallAndRemoveTimer() {
786
+ clearInterval(timerId);
787
+ reinstall();
788
+ }
789
+
790
+ timerId = setInterval(reinstall, 500);
791
+ if (document.addEventListener)
792
+ document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
793
+ else
794
+ window.onload = reinstallAndRemoveTimer;
795
+ }
796
+
797
+ }
798
+ asciidoc.install();
799
+ /*]]>*/
800
+ </script>
801
+ <style type="text/css">
802
+ body {
803
+ margin: 1em auto 1em auto;
804
+ padding: 0 1em 0 1em;
805
+ max-width: 800px;
806
+ }
807
+
808
+ a.image {
809
+ border: none;
810
+ }
811
+
812
+ .comments {
813
+ display: block;
814
+ background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAgCAYAAAB6kdqOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAB0wAAAdMBc2+PegAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAASjSURBVFiFvZdPaBxVHMc/b/7sbNLdxG13s0sbE1jBxELVbVGEgqmQiiBiDxZqKRWhR0Fqe/BSmoNQSNmrt4ISTyV3byWLHorVU5dYtgVpk4DGhXZ1a7rZmXkeMm99eZn9k1b9wY/3Z2f2fX7f3++9mRFSSnQTQgjAAkTkaO2zmtRaCYTSABBqrIEkS6VS9vTp069lMpmClFL4vt8BCsNwWwsQBAHm7+Y4CAKEEEGtVvtlYWHhbqvVagJ/AE90MCGlVDD2xYsXiydPnvza87wXksnk8NDQUFIPQPW7zfXyMAwJw5BGo/FXs9ncvHfv3tKFCxe+aLfbDyKwQEopFZBdLpdfnp2d/Tafz4+5rhsxghAC1d+h/y5gzH69XvdrtdqDs2fPfuT7/jLQkFIGlhBC5HK5oZmZmW8KhUI+kUgIy7KwLAvbtrFte1vfdHVtnKtg9L7yffv2OcViceLSpUufA88DSSGEcABrfn7+zdHR0UnXdWNv1tXqpY6phGVZnRoy/0MIQT6fdw4ePHgUKAK/AU8sQOzfv/+tdDq9x4xKd1MVU51uSvTzVCrlTU9PTwN7AGEBYmRk5FXXdTvk+gI6kJnGQQG6KQQwMjLiTk1NTQIJBQTgmAWst2rhfiBxC3ab00wAbtRugZjb2LzR3O7d2rh7+s2Ztg1IwajChK2DTSlggpuFrHs34H7BOHELqN0Rl5K4P+4GNQioPt8BUqeoqpd+MGYQvQ7DfrCxKVNAcTCws0B7RdrvhO4HtS1lCkYtbKrT7WB8GihdQf2B3FFIPbEH2cY6iAljjk1l4qB2KKSrMwjMblXqpVpfIF2lXjBxULsB06HigDb1lA2ijgm0WyithmS73faJ3iYdgHq9/tOBAwfe9jyvJ4wam1H1O196QT18+HBzeXl5FQgVkLxz5873k5OTzWw2m+oHE6dMHEw3EGBbuh4/fuyvrKysAS1AOkA4Nzf3w5EjR+6m0+mS/tTvBhMH1U2lXgqtra21l5aWvgNWgCYQ2tH/hY1G48epqal3Pc/b4ziOGLQegiCIPVv0ubhDcXV1dfP27dv3y+Xyl0AVqAO+/pKfmpiYeHFubm4+m82+kkgkPNd1nbjI9TaZTNqu61rRQpbrujiOs+O6MAx59OhRuL6+3mq1Wq1KpXJjYWFhMYK5DzSljF7yo7RYwBCQBfKlUml6bGxsMggCLwgC/Ruts4CRPpFMJodnZmbeKBaLLxUKheFMJmPr6a5Wq0+uXLmyWK1WK8DPwBrwO7AhpQxB+y6LoARbhe4Bw0AyGlv0N/Vd56VSqb3nzp378PDhw+/ncrnnCoWCZ1kWvu9z69at9fPnz3+6sbFxE/gVaEkNYhuQBqUvsBtTSnrAKDB25syZ944dO/ZxNpvNjY+PDzebTb9Sqdy8fPnyZ0AN+FOpEwv0rKYFZEdgaSB7/PjxoydOnPgkl8tNAN7169fLi4uLX7G1w/5RadDnz9N4pJbNVupzwHSpVPrg6tWrN65du/broUOHZoEMYHXu+S+BYsA8YC9QHB8ff/3UqVPvREC2uvZfT1kvi9KpNo7LVo1uApsqZf8rkAHWMX2X/Q1tcUY1hl3QyQAAAABJRU5ErkJggg==') top left no-repeat;
815
+ float: left;
816
+ margin-left: -55px;
817
+ width: 36px;
818
+ height: 48px;
819
+ line-height: 0;
820
+ color: black;
821
+ text-decoration: none !important;
822
+ border: none !important;
823
+ }
824
+
825
+ #toc .comments {
826
+ margin-top: 0.25em;
827
+ }
828
+
829
+ .sect1 .comments {
830
+ margin-top: 0.5em;
831
+ }
832
+
833
+ .sect2 .comments {
834
+ margin-top: 1.15em;
835
+ }
836
+
837
+ .sect3 .comments {
838
+ margin-top: -1em;
839
+ }
840
+
841
+ .comments.empty {
842
+ opacity: 0.2;
843
+ }
844
+
845
+ .comments.empty:hover,
846
+ .comments.nonempty {
847
+ opacity: 1;
848
+ }
849
+
850
+ .comments .count {
851
+ display: block;
852
+ font-size: 80%;
853
+ padding-top: 12px;
854
+ text-align: center;
855
+ text-shadow: 1px 1px 2px white;
856
+ }
857
+
858
+ #comments_lightbox_shadow {
859
+ position: fixed;
860
+ top: 0;
861
+ left: 0;
862
+ right: 0;
863
+ bottom: 0;
864
+ background: black;
865
+ opacity: 0.7;
866
+ z-index: 10;
867
+ }
868
+
869
+ #comments_lightbox_contents {
870
+ position: fixed;
871
+ top: 10%;
872
+ left: 20%;
873
+ right: 20%;
874
+ bottom: 10%;
875
+ background: white;
876
+ overflow: auto;
877
+ z-index: 11;
878
+ }
879
+
880
+ #comments_lightbox_contents > .shell {
881
+ margin: 2em;
882
+ }
883
+
884
+ pre {
885
+ overflow: auto;
886
+ }
887
+
888
+ @media print {
889
+ body {
890
+ font-size: 18pt;
891
+ }
892
+
893
+ #header h1 {
894
+ page-break-after: always;
895
+ font-size: 500%;
896
+ vertical-align: middle;
897
+ }
898
+
899
+ #header {
900
+ page-break-after: always;
901
+ }
902
+
903
+ #toctitle {
904
+ font-size: 200%;
905
+ margin-bottom: 1em;
906
+ }
907
+
908
+ div.toclevel1 {
909
+ font-size: 100%;
910
+ }
911
+
912
+ div.toclevel2 {
913
+ font-size: 90%;
914
+ }
915
+
916
+ div.toclevel3 {
917
+ font-size: 80%;
918
+ }
919
+
920
+ #content .comments {
921
+ display: none;
922
+ }
923
+
924
+ @page :left {
925
+ @bottom-left {
926
+ content: counter(page);
927
+ }
928
+ }
929
+ }
930
+
931
+ #topbar {
932
+ position: fixed;
933
+ left: 0;
934
+ top: 0;
935
+ right: 0;
936
+ height: 2.5em;
937
+ padding-left: 10%;
938
+ padding-right: 10%;
939
+ z-index: 1;
940
+ background: #880000;
941
+ overflow: hidden;
942
+ white-space: nowrap;
943
+ box-shadow: 0px 3px 6px #555555;
944
+ -moz-box-shadow: 0px 3px 6px #555555;
945
+ -webkit-box-shadow: 0px 3px 6px #555555;
946
+ -o-box-shadow: 0px 3px 6px #555555;
947
+ }
948
+
949
+ #topbar .title {
950
+ display: inline-block;
951
+ margin: 0.6em 1em 0 0;
952
+ vertical-align: top;
953
+ }
954
+
955
+ #topbar .title img {
956
+ display: none;
957
+ margin-right: 6px;
958
+ vertical-align: middle;
959
+ }
960
+
961
+ #topbar .title a {
962
+ color: #fffafa;
963
+ border: 0;
964
+ }
965
+
966
+ #topbar .title:hover img,
967
+ .mobile #topbar .title img {
968
+ display: inline-block;
969
+ margin-left: -17px;
970
+ }
971
+
972
+ #topbar .title:hover a,
973
+ .mobile #topbar .title a {
974
+ color: #ffffdd;
975
+ }
976
+
977
+ #floattoc {
978
+ position: fixed;
979
+ z-index: 1;
980
+ top: 2em;
981
+ bottom: 20%;
982
+ width: 50%;
983
+ background: #f0f0f0;
984
+ color: black;
985
+ box-shadow: 0px 6px 6px #555555;
986
+ -moz-box-shadow: 0px 6px 6px #555555;
987
+ -webkit-box-shadow: 0px 6px 6px #555555;
988
+ -o-box-shadow: 0px 6px 6px #555555;
989
+ overflow: auto;
990
+ padding: 1em;
991
+ border-radius: 6px;
992
+ -webkit-border-radius: 8px;
993
+ -webkit-border-top-left-radius: 0;
994
+ -webkit-border-top-right-radius: 0;
995
+ -moz-border-radius: 8px;
996
+ -moz-border-radius-topleft: 0;
997
+ -moz-border-top-right-radius: 0;
998
+ -o-border-radius: 8px;
999
+ -o-border-radius-topleft: 0;
1000
+ -o-border-top-right-radius: 0;
1001
+ border-radius: 8px;
1002
+ border-top-left-radius: 0;
1003
+ border-top-right-radius: 0;
1004
+ }
1005
+
1006
+ #floattoc a.current {
1007
+ font-weight: bold;
1008
+ color: black;
1009
+ }
1010
+
1011
+ #current_section {
1012
+ display: inline-block;
1013
+ margin: 0.5em 0 0 0;
1014
+ padding: 0.2em 0.5em 0.2em 0.5em;
1015
+ background: #550000;
1016
+ font-size: 90%;
1017
+ vertical-align: top;
1018
+ color: white;
1019
+ border: none;
1020
+ -webkit-border-radius: 8px;
1021
+ -moz-border-radius: 8px;
1022
+ -o-border-radius: 8px;
1023
+ border-radius: 8px;
1024
+ }
1025
+
1026
+ #current_section:hover {
1027
+ text-decoration: none;
1028
+ border: none;
1029
+ }
1030
+
1031
+ #current_section.pressed {
1032
+ background: #f0f0f0;
1033
+ color: black;
1034
+ -webkit-border-top-left-radius: 8px;
1035
+ -webkit-border-top-right-radius: 8px;
1036
+ -webkit-border-bottom-left-radius: 0;
1037
+ -webkit-border-bottom-right-radius: 0;
1038
+ -moz-border-radius-topleft: 8px;
1039
+ -moz-border-radius-topright: 8px;
1040
+ -moz-border-bottom-left-radius: 0;
1041
+ -moz-border-bottom-right-radius: 0;
1042
+ border-top-left-radius: 8px;
1043
+ border-top-right-radius: 8px;
1044
+ border-bottom-left-radius: 0;
1045
+ border-bottom-right-radius: 0;
1046
+ }
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
+
1057
+ </style>
1058
+ </head>
1059
+ <body class="article">
1060
+ <div id="topbar" style="display: none">
1061
+ <div class="title">
1062
+ <!-- Don't put a space between the img and a. That will break the hover layout. -->
1063
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAAEV95QVAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sGCRMSACDxkZwAAAAidEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVAgb24gYSBNYWOHqHdDAAAAZUlEQVQY032PSxbAIAjEIlfygL6ePF3UUvpzNjgSYWwqAMEhUQnANnsC7TQPeJpsVWzMuh2sog4vDTUbqP081zECrW4dtdaQGSIKlWluPyjK+VXxAz5XfcKufCzA130AfQHWB30HZxlPaP080xsAAAAASUVORK5CYII=" width="11" height="10" alt=""><a href="javascript:void(Mizuho.smoothlyScrollToToc())">Phusion Passenger Design and Architecture</a>
1064
+ </div>
1065
+ <a href="javascript:void(0)" id="current_section"></a>
1066
+ </div>
1067
+ <div id="header">
1068
+ <h1>Phusion Passenger Design and Architecture</h1>
1069
+ <div id="preamble">
1070
+ <div class="sectionbody">
1071
+ <div class="paragraph"><p><span class="image">
1072
+ <a class="image" href="http://www.phusion.nl/">
1073
+ <img src="images/phusion_banner.png" alt="images/phusion_banner.png">
1074
+ </a>
1075
+ </span></p></div>
1076
+ <div class="paragraph"><p>This guide describes <a href="https://www.phusionpassenger.com/">Phusion Passenger</a>'s design and architecture in detail. With this guide, we hope that contributors can quickly find their way around the Phusion Passenger codebase.</p></div>
1077
+ <div class="paragraph"><p>The guide assumes that you’re familiar with using Phusion Passenger and with Nginx or Apache, and that you’ve read the <a href="https://github.com/phusion/passenger/blob/master/CONTRIBUTING.md">Contributors Guide</a> and the <a href="https://github.com/phusion/passenger/blob/master/doc/DeveloperQuickstart.md">Developer QuickStart</a>.</p></div>
1078
+ <div class="paragraph"><p><span class="image">
1079
+ <a class="image" href="http://vimeo.com/phusionnl/review/98027409/03ba678684">
1080
+ <img src="images/code_walkthrough.jpg" alt="images/code_walkthrough.jpg">
1081
+ </a>
1082
+ </span><br>
1083
+ <em>You should also watch the complementary video: <a href="http://vimeo.com/phusionnl/review/98027409/03ba678684">Phusion Passenger Code Walkthrough</a></em></p></div>
1084
+ </div>
1085
+ </div>
1086
+ <div id="toc">
1087
+ <div id="toctitle">Table of Contents</div>
1088
+ <div class="foo toclevel2"><a href="#_introduction">1. Introduction</a></div>
1089
+ <div class="foo toclevel3"><a href="#web_app_models">1.1. Web application models and the role of the application server</a></div>
1090
+ <div class="foo toclevel4"><a href="#_common_models">1.1.1. Common models</a></div>
1091
+ <div class="foo toclevel4"><a href="#_the_rationale_behind_reverse_proxying">1.1.2. The rationale behind reverse proxying</a></div>
1092
+ <div class="foo toclevel3"><a href="#_phusion_passenger_architecture_overview">1.2. Phusion Passenger architecture overview</a></div>
1093
+ <div class="foo toclevel4"><a href="#_web_server_module">1.2.1. Web server module</a></div>
1094
+ <div class="foo toclevel4"><a href="#_helperagent">1.2.2. HelperAgent</a></div>
1095
+ <div class="foo toclevel4"><a href="#_loggingagent">1.2.3. LoggingAgent</a></div>
1096
+ <div class="foo toclevel4"><a href="#_watchdog">1.2.4. Watchdog</a></div>
1097
+ <div class="foo toclevel4"><a href="#_command_line_tools">1.2.5. Command line tools</a></div>
1098
+ <div class="foo toclevel4"><a href="#_passenger_standalone">1.2.6. Passenger Standalone</a></div>
1099
+ <div class="foo toclevel3"><a href="#_build_system_and_source_tree">1.3. Build system and source tree</a></div>
1100
+ <div class="foo toclevel2"><a href="#_initialization">2. Initialization</a></div>
1101
+ <div class="foo toclevel2"><a href="#helper_agent_architecture">3. HelperAgent architecture</a></div>
1102
+ <div class="foo toclevel3"><a href="#_request_handling">3.1. Request handling</a></div>
1103
+ <div class="foo toclevel4"><a href="#_one_client_per_request">3.1.1. One client per request</a></div>
1104
+ <div class="foo toclevel4"><a href="#request_handler_forwarding_to_app">3.1.2. Forwarding to the application</a></div>
1105
+ <div class="foo toclevel4"><a href="#_i_o_model">3.1.3. I/O model</a></div>
1106
+ <div class="foo toclevel3"><a href="#_the_applicationpool_subsystem">3.2. The ApplicationPool subsystem</a></div>
1107
+ <div class="foo toclevel3"><a href="#spawner_subsystem">3.3. The Spawner subsystem</a></div>
1108
+ <div class="foo toclevel2"><a href="#app_spawning_and_loading">4. Application spawning and loading</a></div>
1109
+ <div class="foo toclevel3"><a href="#_preparation_work">4.1. Preparation work</a></div>
1110
+ <div class="foo toclevel4"><a href="#basic_setup_and_forking">4.1.1. Basic setup and forking</a></div>
1111
+ <div class="foo toclevel4"><a href="#_loading_spawnpreparer_possibly_through_bash">4.1.2. Loading SpawnPreparer, possibly through bash</a></div>
1112
+ <div class="foo toclevel4"><a href="#_spawnpreparer_further_sets_up_the_environment">4.1.3. SpawnPreparer further sets up the environment</a></div>
1113
+ <div class="foo toclevel4"><a href="#_executing_the_loader_or_preloader">4.1.4. Executing the loader or preloader</a></div>
1114
+ <div class="foo toclevel3"><a href="#loaders">4.2. Loaders</a></div>
1115
+ <div class="foo toclevel4"><a href="#loader_handshake">4.2.1. Handshake</a></div>
1116
+ <div class="foo toclevel4"><a href="#application_loading">4.2.2. Application loading</a></div>
1117
+ <div class="foo toclevel4"><a href="#loader_setting_up_server">4.2.3. Setting up a server</a></div>
1118
+ <div class="foo toclevel4"><a href="#loader_report_readiness">4.2.4. Reporting readiness</a></div>
1119
+ <div class="foo toclevel4"><a href="#loader_error_reporting">4.2.5. Error reporting</a></div>
1120
+ <div class="foo toclevel4"><a href="#loader_main_loop">4.2.6. Main loop and termination</a></div>
1121
+ <div class="foo toclevel4"><a href="#_stdout_and_stderr_forwarding">4.2.7. Stdout and stderr forwarding</a></div>
1122
+ <div class="foo toclevel3"><a href="#preloaders">4.3. Preloaders</a></div>
1123
+ <div class="foo toclevel3"><a href="#app_types_registry">4.4. The AppTypes registry</a></div>
1124
+ <div class="foo toclevel2"><a href="#instance_state_and_communication">5. Instance state and communication</a></div>
1125
+ <div class="foo toclevel2"><a href="#_about_rack">6. Appendix A: About Rack</a></div>
1126
+ <div class="foo toclevel2"><a href="#_about_apache">7. Appendix B: About Apache</a></div>
1127
+ <div class="foo toclevel2"><a href="#_about_nginx">8. Appendix C: About Nginx</a></div>
1128
+ </div>
1129
+ </div>
1130
+ <div id="content">
1131
+
1132
+ <div class="sect1">
1133
+ <span class="anchor_helper" id="_introduction"></span><h2 data-anchor="_introduction">1. Introduction</h2>
1134
+ <div class="sectionbody">
1135
+ <div class="sect2">
1136
+ <span class="anchor_helper" id="web_app_models"></span><h3 data-anchor="web_app_models">1.1. Web application models and the role of the application server</h3>
1137
+ <div class="paragraph"><p>Before we describe Phusion Passenger, it is important to understand how typical web applications work from the viewpoint of someone who wants to connect a web application to a web server.</p></div>
1138
+ <div class="paragraph"><p>A typical, isolated, web application accepts an HTTP request from some I/O channel, processes it internally, and outputs an HTTP response, which is sent back to the client. This is done in a loop, until the application is commanded to exit. This does not necessarily mean that the web application speaks HTTP directly: it just means that the web application accepts some kind of representation of an HTTP request.</p></div>
1139
+ <div class="paragraph"><p><span class="image">
1140
+ <img src="images/typical_isolated_web_application.png" alt="Architecture of a typical web application in isolation">
1141
+ </span></p></div>
1142
+ <div class="paragraph"><p>Some web applications are directly accessible through the HTTP protocol, while others are not. It depends on the language and framework that the web application is built on. For example, Ruby (Rack/Rails) and Python (WSGI) web applications are typically not directly accessible through the HTTP protocol. On the other hand, Node.js web applications <strong>do</strong> tend to be accessible through the HTTP protocol. The reasons for this are historical, but they’re outside the scope of this guide.</p></div>
1143
+ <div class="sect3">
1144
+ <span class="anchor_helper" id="_common_models"></span><h4 data-anchor="_common_models">1.1.1. Common models</h4>
1145
+ <div class="paragraph"><p>Here are some common models that are in use:</p></div>
1146
+ <div class="olist arabic"><ol class="arabic">
1147
+ <li>
1148
+ <p>
1149
+ The web application is contained in an application server. This application server may or may not be able to contain multiple web applications. The administrator then connects the application server to a web server through some kind of protocol. This protocol may be HTTP, FastCGI, SCGI, AJP or whatever. The web server dispatches (forwards) requests to the application server, which in turn dispatches requests to the correct web application, in a format that the web application understands. Conversely, HTTP responses outputted by the web application are sent to the application server, which in turn sends them to the web server, and eventually to the HTTP client.
1150
+ </p>
1151
+ <div class="paragraph"><p>Typical examples of such a model:</p></div>
1152
+ <div class="ulist"><ul>
1153
+ <li>
1154
+ <p>
1155
+ A J2EE application, contained in the Tomcat application server, reverse proxied behind the Apache web server. Tomcat can contain multiple web applications in a single Tomcat instance.
1156
+ </p>
1157
+ </li>
1158
+ <li>
1159
+ <p>
1160
+ Most Ruby application servers besides Phusion Passenger (Thin, Unicorn, Goliath, etc). These application servers can only contain a single Ruby web application per instance. They load the web application into their own process and are put behind a web server (Apache, Nginx) in a reverse proxy setup.
1161
+ </p>
1162
+ </li>
1163
+ <li>
1164
+ <p>
1165
+ Green Unicorn, the Python (WSGI) application server, behind a reverse proxy setup.
1166
+ </p>
1167
+ </li>
1168
+ <li>
1169
+ <p>
1170
+ PHP web applications spawned by the FastCGI Process Manager (FPM), behind an Nginx reverse proxy setup.
1171
+ </p>
1172
+ </li>
1173
+ </ul></div>
1174
+ </li>
1175
+ <li>
1176
+ <p>
1177
+ The web application is contained directly in a web server. In this case, the web server acts like an application server. Typical examples include:
1178
+ </p>
1179
+ <div class="openblock">
1180
+ <div class="content">
1181
+ <div class="ulist"><ul>
1182
+ <li>
1183
+ <p>
1184
+ PHP web applications running on Apache through mod_php.
1185
+ </p>
1186
+ </li>
1187
+ <li>
1188
+ <p>
1189
+ Python (WSGI) web applications running on Apache through mod_uwsgi or mod_python.
1190
+ </p>
1191
+ </li>
1192
+ </ul></div>
1193
+ </div>
1194
+ </div>
1195
+ <div class="paragraph"><p>Note that this does not necessarily mean that the web application is run inside the same process as the web server: it just means that the web server manages applications. In case of mod_php, PHP runs directly inside the Apache worker processes, but in case of mod_uwsgi the Python processes can be configured to run out-of-process.</p></div>
1196
+ <div class="paragraph"><p>Phusion Passenger for Apache and Phusion Passenger for Nginx implement this model, and run applications outside the web server process.</p></div>
1197
+ </li>
1198
+ <li>
1199
+ <p>
1200
+ The web application <strong>is</strong> a web server, and can accept HTTP requests directly. Examples of this model:
1201
+ </p>
1202
+ <div class="openblock">
1203
+ <div class="content">
1204
+ <div class="ulist"><ul>
1205
+ <li>
1206
+ <p>
1207
+ Almost all Node.js and Meteor JS web applications.
1208
+ </p>
1209
+ </li>
1210
+ <li>
1211
+ <p>
1212
+ The Trac bug tracking software, running in its standalone server.
1213
+ </p>
1214
+ </li>
1215
+ </ul></div>
1216
+ </div>
1217
+ </div>
1218
+ <div class="paragraph"><p>In most setups, the administrator puts them in a reverse proxy configuration, behind a real web server such as Apache or Nginx, instead of letting them accept HTTP requests directly.</p></div>
1219
+ <div class="paragraph"><p>Phusion Passenger Standalone implements this model. However, you can expose Phusion Passenger Standalone directly to the Internet because it uses Nginx internally.</p></div>
1220
+ </li>
1221
+ <li>
1222
+ <p>
1223
+ The web application does not speak HTTP directly, but is connected directly to the web server through some communication adapter. CGI, FastCGI and SCGI are good examples of this.
1224
+ </p>
1225
+ </li>
1226
+ </ol></div>
1227
+ <div class="paragraph"><p>The above models cover how nearly all web applications work, whether they’re based on PHP, Django, J2EE, ASP.NET, Ruby on Rails, or whatever. Note that all of these models provide the same functionality, i.e. no model can do something that a different model can’t. The critical reader will notice that all of these models are identical to the one described in the first diagram, if the combination of web servers, application servers, web applications etc. are considered to be a single entity; a black box if you will.</p></div>
1228
+ <div class="paragraph"><p>It should also be noted that these models do not enforce any particular I/O processing implementation. The web servers, application servers, web applications, etc. could process I/O serially (i.e. one request at a time),
1229
+ could multiplex I/O with a single thread (e.g. by using <span class="monospaced">select(2)</span> or <span class="monospaced">poll(2)</span>) or it could process I/O with multiple threads and/or multiple processes. It depends on the implementation.</p></div>
1230
+ <div class="paragraph"><p>Of course, there are many variations possible. For example, load balancers could be used. But that is outside the scope of this document.</p></div>
1231
+ </div>
1232
+ <div class="sect3">
1233
+ <span class="anchor_helper" id="_the_rationale_behind_reverse_proxying"></span><h4 data-anchor="_the_rationale_behind_reverse_proxying">1.1.2. The rationale behind reverse proxying</h4>
1234
+ <div class="paragraph"><p>As you’ve seen, administrators often put the web application or its application server behind a real web server in a reverse proxy setup, even when the web app/app server already speaks HTTP. This is because implementing HTTP in a proper, secure way involves more than just speaking the protocol. The public Internet is a hostile environment where clients can send any arbitrary data and can exhibit any arbitrary I/O patterns. If you don’t properly implement I/O handling, then you could open yourself either to parser vulnerabilities, or denial-of-service attacks.</p></div>
1235
+ <div class="paragraph"><p>Web servers like Apache and Nginx have already implemented world-class I/O and connection handling code and it would be a waste to reinvent their wheel. In the end, putting the application in a reverse proxying setup often makes the whole system more robust and and more secure. This is the reason why it’s considered good practice.</p></div>
1236
+ <div class="paragraph"><p>A typical problem involves dealing with <strong>slow clients</strong>. These clients may send HTTP requests slowly and read HTTP responses slowly, perhaps taking many seconds to complete their work. A naive single-threaded HTTP server implementation that reads an HTTP requests, processes, and sends the HTTP response in a loop may end up spending so much time waiting for I/O that spends very little time doing actual work. Worse: suppose that the client is malicious, just leaves the socket open and never reads the HTTP response, then the server will spend forever waiting for the client, not being able to handle any more requests. A real-world attack based on this principle is <a href="http://en.wikipedia.org/wiki/Slowloris">Slowloris</a>.</p></div>
1237
+ <div class="listingblock">
1238
+ <div class="title">An example of a naive HTTP server implementation</div>
1239
+ <div class="content monospaced">
1240
+ <pre>while true
1241
+ client = accept_next_client()
1242
+ request = read_http_request(client)
1243
+ response = process_request(request)
1244
+ send_http_response(client, response)
1245
+ end</pre>
1246
+ </div>
1247
+ </div>
1248
+ <div class="paragraph"><p>There are many ways to solve this problem. One could use one thread per client, one could implement I/O timeouts, one could use an evented I/O architecture, one could have a dedicated I/O thread or process buffer requests and responses. The point is, implementing all this properly is non-trivial. Instead of reimplementing these over and over in each application server, it’s better to let a real web server deal with all the details and let the application server and the web application do what they’re best at: their own core business logic.</p></div>
1249
+ </div>
1250
+ </div>
1251
+ <div class="sect2">
1252
+ <span class="anchor_helper" id="_phusion_passenger_architecture_overview"></span><h3 data-anchor="_phusion_passenger_architecture_overview">1.2. Phusion Passenger architecture overview</h3>
1253
+ <div class="paragraph"><p><span class="image">
1254
+ <img src="images/passenger_architecture_overview.png" alt="An overview of Phusion Passenger’s architecture">
1255
+ </span></p></div>
1256
+ <div class="paragraph"><p>Phusion Passenger is not a single, monolithic entity. Instead, it consists of multiple components and processes that work together. Part of the reason why Phusion Passenger is split like this, is because it’s technically necessary (no other way to implement it). But another part of the reason is stability and robustness. Individual components can crash and can be restarted independently from each other. If we were to put everything inside a single process, then a crash will take down all of Phusion Passenger.</p></div>
1257
+ <div class="paragraph"><p>Thus, if the HelperAgent crashes, or if an application process crashes, they can both be restarted without affecting the web server’s stability.</p></div>
1258
+ <div class="sect3">
1259
+ <span class="anchor_helper" id="_web_server_module"></span><h4 data-anchor="_web_server_module">1.2.1. Web server module</h4>
1260
+ <div class="paragraph"><p>When an HTTP client sends a request, it is received by the web server (Nginx or Apache). Both Apache and Nginx can be extended with <strong>modules</strong>. Phusion Passenger provides such a module. The module is loaded into Nginx/Apache. It checks whether the request should be handled by a Phusion Passenger-served web application, and if so, forwards the request to the HelperAgent. The internal wire protocol used during this forwarding, is a modified version of <a href="http://en.wikipedia.org/wiki/SCGI">SCGI</a>.</p></div>
1261
+ <div class="paragraph"><p>The Nginx module and Apache module have an entirely different code base. Their code bases are in <span class="monospaced">ext/nginx</span> and <span class="monospaced">ext/apache2</span>, respectively. Both modules are relatively small because they outsource most logic to the HelperAgent, and because they utilize a common library (<span class="monospaced">ext/common</span>). This allows us to support both Nginx and Apache without having to write a lot of things twice.</p></div>
1262
+ </div>
1263
+ <div class="sect3">
1264
+ <span class="anchor_helper" id="_helperagent"></span><h4 data-anchor="_helperagent">1.2.2. HelperAgent</h4>
1265
+ <div class="paragraph"><p>The <strong>HelperAgent</strong> is Phusion Passenger’s core, where most of the processing is done. The HelperAgent keeps track of which application processes currently exist, and using load balancing rules, determines which process a request should be forwarded to. The HelperAgent also takes care of <strong>application spawning</strong>: if it determines that having more application processes is necessary or beneficial, then it will make that happen. Process spawning is subject to user-configured limits: the HelperAgent will never spawn more processes than a user-configured maximum.</p></div>
1266
+ <div class="paragraph"><p>The HelperAgent also has monitoring and statistics gathering capabilities. It constantly keeps track of applications' memory usage, how many requests they’ve handled, etc. This information can later be queried from administration tools. And if an application process crashes, the HelperAgent restarts it.</p></div>
1267
+ <div class="paragraph"><p>The HelperAgent is by far the largest and most complex part of the system, but it is itself composed of several smaller subsystems. Most of the <a href="#helper_agent_architecture">HelperAgent architecture</a> chapter is devoted to describing the HelperAgent.</p></div>
1268
+ </div>
1269
+ <div class="sect3">
1270
+ <span class="anchor_helper" id="_loggingagent"></span><h4 data-anchor="_loggingagent">1.2.3. LoggingAgent</h4>
1271
+ <div class="paragraph"><p>The HelperAgent cooperates with the <strong>LoggingAgent</strong>. This latter is responsible for sending data to <a href="https://www.unionstationapp.com">Union Station</a>, a monitoring web service. If you didn’t explicitly tell Phusion Passenger to send data to Union Station, then the LoggingAgent sits idle and does not consume resources.</p></div>
1272
+ </div>
1273
+ <div class="sect3">
1274
+ <span class="anchor_helper" id="_watchdog"></span><h4 data-anchor="_watchdog">1.2.4. Watchdog</h4>
1275
+ <div class="paragraph"><p>The HelperAgent and the LoggingAgent contain complex logic, so they could contain bugs which could crash them.
1276
+ So as a safety measure, they are both monitored by the <strong>Watchdog</strong>. If either of them crash, they are restarted by the Watchdog. This setup seeks to ensure that the system stays up, no matter what.</p></div>
1277
+ <div class="paragraph"><p>You might now wonder: what happens if the Watchdog crashes? Shouldn’t the Watchdog be monitored by another Watchdog? We’ve contemplated this possibility, but the Watchdog is very simple, and since 2012 we haven’t seen a single report of the Watchdog crashing, nor have we been able to make it crash since that time. So, for the sake of keeping the codebase as simple as possible, we’ve chosen not to introduce multiple Watchdogs.</p></div>
1278
+ </div>
1279
+ <div class="sect3">
1280
+ <span class="anchor_helper" id="_command_line_tools"></span><h4 data-anchor="_command_line_tools">1.2.5. Command line tools</h4>
1281
+ <div class="paragraph"><p>Finally, there is an array of <strong>command line tools</strong> which support Phusion Passenger. The installers — <span class="monospaced">passenger-install-*-module</span> — are responsible for installing Phusion Passenger. There are administrative tools such as <span class="monospaced">passenger-status</span> and <span class="monospaced">passenger-memory-stats</span>. And many more. Some of these tools may communicate with one of the agents. For example, the <span class="monospaced">passenger-status</span> queries the HelperAgent for information that the HelperAgent has collected. How this communication is done, is described in <a href="#instance_state_and_communication">Instance state and communication</a>.</p></div>
1282
+ </div>
1283
+ <div class="sect3">
1284
+ <span class="anchor_helper" id="_passenger_standalone"></span><h4 data-anchor="_passenger_standalone">1.2.6. Passenger Standalone</h4>
1285
+ <div class="paragraph"><p>You might have noticed that Phusion Passenger Standalone is not part of the diagram. So how does it fit into the architecture? Well, Phusion Passenger Standalone is actually just Phusion Passenger for Nginx. The <span class="monospaced">passenger start</span> command simply sets up a modified and stripped-down Nginx web server (which we call the <span class="monospaced">WebHelper</span>) with the Phusion Passenger Nginx module loaded.</p></div>
1286
+ </div>
1287
+ </div>
1288
+ <div class="sect2">
1289
+ <span class="anchor_helper" id="_build_system_and_source_tree"></span><h3 data-anchor="_build_system_and_source_tree">1.3. Build system and source tree</h3>
1290
+ <div class="paragraph"><p>Phusion Passenger is written mostly in C++ and Ruby. The web server modules, HelperAgent, LoggingAgent and Watchdog are written in C++. Most command line tools are written in Ruby. You can find each component here:</p></div>
1291
+ <div class="ulist"><ul>
1292
+ <li>
1293
+ <p>
1294
+ The web server modules can be found in <span class="monospaced">ext/apache2</span> and <span class="monospaced">ext/nginx</span>.
1295
+ </p>
1296
+ </li>
1297
+ <li>
1298
+ <p>
1299
+ The HelperAgent, LoggingAgent and Watchdog can be found in <span class="monospaced">ext/common/agents</span>.
1300
+ </p>
1301
+ </li>
1302
+ <li>
1303
+ <p>
1304
+ The command line tools can be found in <span class="monospaced">bin</span>, with some parts of their code in <span class="monospaced">lib</span>.
1305
+ </p>
1306
+ </li>
1307
+ </ul></div>
1308
+ <div class="paragraph"><p>More information can be found in the <a href="https://github.com/phusion/passenger/blob/master/CONTRIBUTING.md">Contributors Guide</a>. This guide also teaches you how to compile Phusion Passenger.</p></div>
1309
+ </div>
1310
+ </div>
1311
+ </div>
1312
+ <div class="sect1">
1313
+ <span class="anchor_helper" id="_initialization"></span><h2 data-anchor="_initialization">2. Initialization</h2>
1314
+ <div class="sectionbody">
1315
+ <div class="paragraph"><p><span class="image">
1316
+ <img src="images/startup_sequence.png" alt="Startup sequence">
1317
+ </span></p></div>
1318
+ <div class="paragraph"><p>Phusion Passenger initializes as follows.</p></div>
1319
+ <div class="olist arabic"><ol class="arabic">
1320
+ <li>
1321
+ <p>
1322
+ First, the user begins with starting the web server. This for example be done by running <span class="monospaced">sudo service apache2 start</span> or <span class="monospaced">sudo service nginx start</span>. Or perhaps the web server is configured to be automatically started by the OS, in which case the user doesn’t have to do anything. In case of Phusion Passenger Standalone, the user runs <span class="monospaced">passenger start</span> which in turn starts Nginx.
1323
+ </p>
1324
+ </li>
1325
+ <li>
1326
+ <p>
1327
+ The Phusion Passenger module inside Nginx/Apache proceeds with starting the Watchdog. This is implemented in:
1328
+ </p>
1329
+ <div class="ulist"><ul>
1330
+ <li>
1331
+ <p>
1332
+ <span class="monospaced">ext/nginx/ngx_http_passenger_module.c</span>, function <span class="monospaced">start_watchdog()</span>.
1333
+ </p>
1334
+ </li>
1335
+ <li>
1336
+ <p>
1337
+ <span class="monospaced">ext/apache2/Hooks.cpp</span>, in the constructor for the <span class="monospaced">Hooks</span> class.
1338
+ </p>
1339
+ </li>
1340
+ <li>
1341
+ <p>
1342
+ <span class="monospaced">ext/common/AgentsStarter.h</span> and <span class="monospaced">AgentsStarter.cpp</span>. Most of the logic pertaining starting the Watchdog is in this file.
1343
+ </p>
1344
+ </li>
1345
+ </ul></div>
1346
+ </li>
1347
+ <li>
1348
+ <p>
1349
+ The Watchdog first initializes a <a href="#instance_state_and_communication">"instance directory"</a>, which is a temporary directory containing files that will be used during the life time of this Phusion Passenger instance. For example, the directory contains Unix domain socket files, so that the different Phusion Passenger processes can communicate with each other. The Watchdog is implemented in <span class="monospaced">ext/common/agents/Watchdog/Main.cpp</span>.
1350
+ </p>
1351
+ </li>
1352
+ <li>
1353
+ <p>
1354
+ The Watchdog starts the HelperAgent and the LoggingAgent simultaneously. Each performs its own initialization.
1355
+ </p>
1356
+ </li>
1357
+ <li>
1358
+ <p>
1359
+ When the HelperAgent is done initializing, it will send a message back to the Watchdog saying that it’s done. The LoggingAgent does something similar. When the Watchdog has received both acknowledgment messages, it finishes initialization. If the Watchdog notices that one of the agents have exited without sending an acknowledgment message, then it enters an error state.
1360
+ </p>
1361
+ </li>
1362
+ <li>
1363
+ <p>
1364
+ The Watchdog reports successful startup back to the Phusion Passenger module that’s running inside Nginx/Apache. Or, if initialization didn’t success, the Watchdog reports back an error. The Phusion Passenger module inside Nginx/Apache then logs the error.
1365
+ </p>
1366
+ </li>
1367
+ </ol></div>
1368
+ <div class="paragraph"><p>After initialization, Phusion Passenger is ready to receive and to process requests.</p></div>
1369
+ </div>
1370
+ </div>
1371
+ <div class="sect1">
1372
+ <span class="anchor_helper" id="helper_agent_architecture"></span><h2 data-anchor="helper_agent_architecture">3. HelperAgent architecture</h2>
1373
+ <div class="sectionbody">
1374
+ <div class="paragraph"><p><span class="image">
1375
+ <img src="images/helper_agent_core_architecture.png" alt="HelperAgent architecture">
1376
+ </span></p></div>
1377
+ <div class="paragraph"><p>The HelperAgent consists of two subsystems. One is the <strong>request handling subsystem</strong>. The other is <strong>the ApplicationPool subsystem</strong>, which performs the bulk of process management. The HelperAgent also uses a number of support libraries. The largest third-party support libraries are shown in the diagram. Many more — internal — support libraries are used, but they’re omitted from the diagram. You can find these internal support libraries in the directory <span class="monospaced">ext/common/Utils</span>.</p></div>
1378
+ <div class="sect2">
1379
+ <span class="anchor_helper" id="_request_handling"></span><h3 data-anchor="_request_handling">3.1. Request handling</h3>
1380
+ <div class="paragraph"><p>Recall that requests are first received from the web server. The web server serializes the request into a slightly modified version of <a href="http://en.wikipedia.org/wiki/SCGI">the SCGI format</a>, and sends it to the HelperAgent’s RequestHandler. The RequestHandler performs some work, and eventually sends back a regular HTTP response. The web server parses the RequestHandler response, and sends a response to the original HTTP client.</p></div>
1381
+ <div class="paragraph"><p>The RequestHandler listens on a Unix domain socket file. This Unix domain socket file is called <span class="monospaced">request</span>, and is located in <a href="#instance_state_and_communication">the instance directory</a>.</p></div>
1382
+ <div class="sect3">
1383
+ <span class="anchor_helper" id="_one_client_per_request"></span><h4 data-anchor="_one_client_per_request">3.1.1. One client per request</h4>
1384
+ <div class="paragraph"><p>The web server creates a new connection to the HelperAgent on every request. Thus, from the viewpoint of the RequestHandler, its client is the web server. Every time a client connects (i.e. a new request is forwarded), the RequestHandler creates a new Client object which represents that request. All request-specific state is stored inside the Client. After the RequestHandler is done processing a request, it closes the client socket.</p></div>
1385
+ <div class="paragraph"><p>Note that in the diagram, a Client has a 0..1 association with RequestHandler. That’s because when a Client is disconnected, the pointer to the associated RequestHandler is set to NULL. There might be background operations left which still have a pointer to the Client. As soon as those background operations finish, they check whether the Client has a valid pointer to the RequestHandler. If so, they commit their work; if not, they discard their work. The Client is destroyed when all its associated background operations have finished.</p></div>
1386
+ </div>
1387
+ <div class="sect3">
1388
+ <span class="anchor_helper" id="request_handler_forwarding_to_app"></span><h4 data-anchor="request_handler_forwarding_to_app">3.1.2. Forwarding to the application</h4>
1389
+ <div class="paragraph"><p>The RequestHandler asynchronously asks the ApplicationPool subsystem to select an appropriate application process to handle this request. The ApplicationPool checks whether there is an appropriate process, and if not, tries to spawn one. Maybe spawning is not possible right now because of configured resource limits, and we have to wait. In any case, the ApplicationPool takes care of all the nasty details and book keeping, and eventually replies back to the RequestHandler with either a Session object, or an exception.</p></div>
1390
+ <div class="paragraph"><p>A Session object represents a single request/response cycle with a particular application process. The RequestHandler uses the information in this Session object to establish a connection with that process and forwards the request, using <a href="#loader_setting_up_server">a protocol that the application prefers</a> and that the RequestHandler supports. The process performs work, and replies back with an HTTP response. The RequestHandler parses and postprocesses the response, and sends a response back to the web server.</p></div>
1391
+ <div class="paragraph"><p>If the ApplicationPool replied with an exception, the RequestHandler sends back an error response.</p></div>
1392
+ </div>
1393
+ <div class="sect3">
1394
+ <span class="anchor_helper" id="_i_o_model"></span><h4 data-anchor="_i_o_model">3.1.3. I/O model</h4>
1395
+ <div class="paragraph"><p>The RequestHandler uses the <strong>evented I/O model</strong>. This means that the RequestHandler handles many clients (requests) at the same time, using a single thread, inside a single process. This is possible through the use of I/O event multiplexing mechanisms, which are provided by the OS. Examples of such mechanisms include the <span class="monospaced">select()</span>, <span class="monospaced">poll()</span>, <span class="monospaced">epoll()</span> and <span class="monospaced">kqueue()</span> system calls. But those mechanisms are very low-level and OS-specific, so the RequestHandler uses two libraries which abstract away the differences and provide a higher-level API: <a href="http://software.schmorp.de/pkg/libev.html">libev</a> and <a href="http://software.schmorp.de/pkg/libeio.html">libeio</a>.</p></div>
1396
+ <div class="paragraph"><p>The evented I/O model is also used in Nginx. It is in contrast to the single-threaded multi-process model which handles 1 client per process (used by Apache with the prefork MPM), or the multi-threaded model which handles 1 client per thread (used by Apache with the worker MPM). You can learn more about evented I/O and the different I/O models through these resources:</p></div>
1397
+ <div class="ulist"><ul>
1398
+ <li>
1399
+ <p>
1400
+ <a href="http://www.slideshare.net/marc.seeger/seeger-aysnc-io">Event-Driven I/O: A hands-on introduction</a> — Marc Seeger, 2010
1401
+ </p>
1402
+ </li>
1403
+ <li>
1404
+ <p>
1405
+ <a href="http://stackoverflow.com/questions/5807246/event-driven-io-and-blocking-vs-nonblocking">Event Driven IO And Blocking vs NonBlocking</a> — Stack Overflow
1406
+ </p>
1407
+ </li>
1408
+ <li>
1409
+ <p>
1410
+ <a href="http://stackoverflow.com/questions/3231018/how-does-event-driven-i-o-allow-multiprocessing">How does event driven I/O allow multiprocessing?</a> — Stack Overflow
1411
+ </p>
1412
+ </li>
1413
+ <li>
1414
+ <p>
1415
+ <a href="http://www.kegel.com/c10k.html">The C10K problem</a> — an overview of the different I/O models used in different servers; Dan Kegel
1416
+ </p>
1417
+ </li>
1418
+ </ul></div>
1419
+ </div>
1420
+ </div>
1421
+ <div class="sect2">
1422
+ <span class="anchor_helper" id="_the_applicationpool_subsystem"></span><h3 data-anchor="_the_applicationpool_subsystem">3.2. The ApplicationPool subsystem</h3>
1423
+ <div class="paragraph"><p>The ApplicationPool subsystem is responsible for:</p></div>
1424
+ <div class="ulist"><ul>
1425
+ <li>
1426
+ <p>
1427
+ Keeping track of which application processes exist.
1428
+ </p>
1429
+ </li>
1430
+ <li>
1431
+ <p>
1432
+ Spawning processes.
1433
+ </p>
1434
+ </li>
1435
+ <li>
1436
+ <p>
1437
+ Routing requests to an appropriate process. This also implies that it load balances requests between processes.
1438
+ </p>
1439
+ </li>
1440
+ <li>
1441
+ <p>
1442
+ Monitoring processes (CPU usage, memory usage, etc).
1443
+ </p>
1444
+ </li>
1445
+ <li>
1446
+ <p>
1447
+ Enforcing resource limits. Ensuring that not too many processes are spawned, ensuring that processes that use too much memory are shut down, etc.
1448
+ </p>
1449
+ </li>
1450
+ <li>
1451
+ <p>
1452
+ Restarting processes on demand (e.g. when the timestamp of <span class="monospaced">restart.txt</span> has changed).
1453
+ </p>
1454
+ </li>
1455
+ <li>
1456
+ <p>
1457
+ Restarting processes that have crashed.
1458
+ </p>
1459
+ </li>
1460
+ <li>
1461
+ <p>
1462
+ Queuing requests and limiting concurrency. Each process tells the ApplicationPool how many concurrent requests it can handle. If more concurrent requests come in than the processes says it can handle, then the excess requests are queued within the ApplicationPool subsystem. Similarly, if requests come in while a process is being spawned, then those requests are queued until the process is done spawning.
1463
+ </p>
1464
+ </li>
1465
+ </ul></div>
1466
+ <div class="paragraph"><p>The main interface into the subsystem is the Pool class, with its <span class="monospaced">asyncGet()</span> method. The RequestHandler calls something like <span class="monospaced">pool-&gt;asyncGet(options, callback)</span> inside its <span class="monospaced">checkoutSession()</span> method. <span class="monospaced">asyncGet()</span> replies with a Session, or an exception.</p></div>
1467
+ <div class="paragraph"><p>The Pool class is the core of the subsystem. It contains high-level process management logic but not low-level details, such as the details of spawning processes. The code is further divided into the following classes, each of which contain the core code managing its respective domain:</p></div>
1468
+ <div class="dlist"><dl>
1469
+ <dt class="hdlist1">
1470
+ <strong>SuperGroup</strong>
1471
+ </dt>
1472
+ <dd>
1473
+ <p>
1474
+ A logical collection of different applications. It’s designed to be able to contain one or more Groups, but currently it always contains exactly 1 Group.
1475
+ </p>
1476
+ <div class="paragraph"><p>SuperGroup was originally introduced as a building block for a future feature: polyglot, multi-language applications. The idea was that, as more and more programming languages are introduced and become popular, there would be more and more demand to write applications in multiple languages. This would be done by splitting applications into multiple parts, with each part implemented in a different language. We wanted to introduce a feature that makes it super-easy to make such polyglot applications as a single whole. However, as time went on, we realized that we were mistaken and that most developers actually don’t want to bother with multiple programming languages: they’d rather stick with a single one. So nowadays, SuperGroup is actually obsolete, but it’s still kept in the codebase because it’s not harmful, and removing it is too much work.</p></div>
1477
+ </dd>
1478
+ <dt class="hdlist1">
1479
+ <strong>Group</strong>
1480
+ </dt>
1481
+ <dd>
1482
+ <p>
1483
+ Represents an application. It can contain multiple processes, all belonging to the same application.
1484
+ </p>
1485
+ </dd>
1486
+ <dt class="hdlist1">
1487
+ <strong>Process</strong>
1488
+ </dt>
1489
+ <dd>
1490
+ <p>
1491
+ Represents an OS process; an instance of a certain application. A process may have multiple server sockets on which it listens for requests. The Process class contains various book keeping information, such as the number of sessions that are currently open. It also contains the communication channel with the underlying OS process. Process objects are created through <a href="#spawner_subsystem">the ApplicationPool Spawner sub-subsystem</a>.
1492
+ </p>
1493
+ </dd>
1494
+ <dt class="hdlist1">
1495
+ <strong>Socket</strong>
1496
+ </dt>
1497
+ <dd>
1498
+ <p>
1499
+ Represents a single server socket, on which a process listens for requests. Session objects are created through Socket. Socket maintains book keeping information about how many sessions are currently open for that particular socket.
1500
+ </p>
1501
+ </dd>
1502
+ <dt class="hdlist1">
1503
+ <strong>Session</strong>
1504
+ </dt>
1505
+ <dd>
1506
+ <p>
1507
+ Represents a single request/response cycle with a particular process. Upon creation and destruction, various book keeping information is updated.
1508
+ </p>
1509
+ </dd>
1510
+ <dt class="hdlist1">
1511
+ <strong>Options (not shown in diagram)</strong>
1512
+ </dt>
1513
+ <dd>
1514
+ <p>
1515
+ A configuration object for the <span class="monospaced">Pool::asyncGet()</span> method.
1516
+ </p>
1517
+ </dd>
1518
+ </dl></div>
1519
+ <div class="paragraph"><p>If you look at the diagram, then you see that SuperGroup, Group and Process all have 0..1 associations with their containing classes. An object that has a NULL association with its containing object, is considered invalid and should not be used. The fact that the association can be NULL is a detail of the memory management scheme that we employ.</p></div>
1520
+ </div>
1521
+ <div class="sect2">
1522
+ <span class="anchor_helper" id="spawner_subsystem"></span><h3 data-anchor="spawner_subsystem">3.3. The Spawner subsystem</h3>
1523
+ <div class="paragraph"><p>The Spawner subsystem is a sub-subsystem within ApplicationPool. It is responsible for actually spawning application processes, and then creating Process objects with the correct information in it.</p></div>
1524
+ <div class="paragraph"><p>The <span class="monospaced">Spawner</span> interface encapsulates all low-level process spawning logic. Pool calls Spawner whenever it needs to spawn another application process.</p></div>
1525
+ <div class="paragraph"><p>Recall that Phusion Passenger supports multiple spawn methods. For example, the <span class="monospaced">smart</span> spawn method spawns processes through an intermediate preloader process, and can utilize copy-on-write. This is explained in detail in <a href="Users%20guide%20Nginx.html#spawning_methods_explained">Spawn methods explained</a> in the Phusion Passenger manual. Each spawn method corresponds to a different implementation of the Spawner interface. The following implementations are available:</p></div>
1526
+ <div class="ulist"><ul>
1527
+ <li>
1528
+ <p>
1529
+ DirectSpawner — implements the <span class="monospaced">direct</span> spawn method.
1530
+ </p>
1531
+ </li>
1532
+ <li>
1533
+ <p>
1534
+ SmartSpawner — implements the <span class="monospaced">smart</span> spawn method.
1535
+ </p>
1536
+ </li>
1537
+ <li>
1538
+ <p>
1539
+ DummySpawner (not shown in diagram) — only used in unit tests.
1540
+ </p>
1541
+ </li>
1542
+ </ul></div>
1543
+ <div class="paragraph"><p>The spawn method is user-configurable through the <span class="monospaced">spawnMethod</span> field in the <span class="monospaced">Options</span> object. To avoid convoluting the Pool code with spawner implementation selection logic, we also have a SpawnerFactory class, which the Pool uses.</p></div>
1544
+ <div class="paragraph"><p>The details of the spawning process is described in <a href="#app_spawning_and_loading">Application spawning and loading</a>.</p></div>
1545
+ </div>
1546
+ </div>
1547
+ </div>
1548
+ <div class="sect1">
1549
+ <span class="anchor_helper" id="app_spawning_and_loading"></span><h2 data-anchor="app_spawning_and_loading">4. Application spawning and loading</h2>
1550
+ <div class="sectionbody">
1551
+ <div class="paragraph"><p>Application processes are spawned from the HelperAgent process. Spawning a process involves a lot of <strong>preparation work</strong>, such as setting up communication channels, setting up the current working directory, environment variables, etc. This preparation work is done by <a href="#spawner_subsystem">a Spawner object</a>, together with various support executables.</p></div>
1552
+ <div class="paragraph"><p>When preparation is done, your application’s entry point has to be loaded somehow. That loading is done through a language-specific <strong>loader program</strong>. The loader program communicates with the Spawner through the communication channel that was set up earlier, initializes the language-specific environment, sets up a server, and reports back to the Spawner. This communication is done through a certain <strong>protocol</strong>.</p></div>
1553
+ <div class="sect2">
1554
+ <span class="anchor_helper" id="_preparation_work"></span><h3 data-anchor="_preparation_work">4.1. Preparation work</h3>
1555
+ <div class="paragraph"><p><span class="image">
1556
+ <img src="images/spawning_preparation_work.png" alt="Spawning preparation work">
1557
+ </span></p></div>
1558
+ <div class="sect3">
1559
+ <span class="anchor_helper" id="basic_setup_and_forking"></span><h4 data-anchor="basic_setup_and_forking">4.1.1. Basic setup and forking</h4>
1560
+ <div class="paragraph"><p>Spawning begins when the <span class="monospaced">spawn()</span> method is called on a <a href="#spawner_subsystem">Spawner object</a>. The Spawner determines <a href="Users%20guide%20Nginx.html#user_switching">which user the process should run as</a>, and sets up some communication channels (anonymous Unix domain socket pairs), and forks a process. The parent waits until the child exits, or replies with something over the communication channel.</p></div>
1561
+ <div class="paragraph"><p>The communication channel in question is — from the viewpoint of the (pre)loader — actually just stdin, stdout and stderr! The anonymous Unix domain socket pairs that the Spawner creates, is mapped to the child process’s stdin, stdout and stderr file descriptors. Thus, Spawner sends data to the (pre)loader by writing stuff to its stdin, and the (pre)loader sends data back to the Spawner by writing stuff to stdout or stderr.</p></div>
1562
+ </div>
1563
+ <div class="sect3">
1564
+ <span class="anchor_helper" id="_loading_spawnpreparer_possibly_through_bash"></span><h4 data-anchor="_loading_spawnpreparer_possibly_through_bash">4.1.2. Loading SpawnPreparer, possibly through bash</h4>
1565
+ <div class="paragraph"><p>Because the HelperAgent is heavily multi-threaded, the child process has been forked by the Spawner <a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html">may only perform async-signal-safe operations</a>:</p></div>
1566
+ <div class="quoteblock">
1567
+ <div class="content">"A process shall be created with a single thread. If a multi-threaded process calls fork(), the new process shall contain a replica of the calling thread and its entire address space, possibly including the states of mutexes and other resources. Consequently, to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called. Fork handlers may be established by means of the pthread_atfork() function in order to maintain application invariants across fork() calls."</div>
1568
+ <div class="attribution">
1569
+ <em>fork() man page</em><br>
1570
+ — The Open Group's POSIX specification
1571
+ </div>
1572
+ </div>
1573
+ <div class="paragraph"><p>Don’t worry if you don’t know what this means. The point is, there’s almost nothing the forked process can safely do at that stage. So it outsources most of the remaining preparation work to an external executable, the SpawnPreparer. The SpawnPreparer starts with a clean environment where it can safely execute code.</p></div>
1574
+ <div class="paragraph"><p>To execute the SpawnPreparer, the child process executes one of the following commands:</p></div>
1575
+ <div class="ulist"><ul>
1576
+ <li>
1577
+ <p>
1578
+ If the target user’s shell is bash, and the <span class="monospaced">passenger_load_shell_envvars</span> option is turned on:
1579
+ </p>
1580
+ <div class="paragraph"><p><span class="monospaced">bash -l -c '/path-to/SpawnPreparer /path-to-loader-or-preloader'</span></p></div>
1581
+ <div class="paragraph"><p>This causes bash to load its startup files, e.g. bashrc, profile, etc, after which it executes the SpawnPreparer with the given parameters. The reason why we do this is because a lot of users try to set environment variables in their bashrc, and they expect these environment variables to be picked up by applications spawned by Phusion Passenger. Unfortunately environment variables <a href="Users%20guide%20Nginx.html#about_environment_variables">don’t work that way</a>, but we support it anyway because it is good for usability.</p></div>
1582
+ </li>
1583
+ <li>
1584
+ <p>
1585
+ Otherwise, the SpawnPreparer is executed directly, without bash:
1586
+ </p>
1587
+ <div class="paragraph"><p><span class="monospaced">/path-to/SpawnPreparer /path-to-loader-or-preloader</span></p></div>
1588
+ </li>
1589
+ </ul></div>
1590
+ <div class="paragraph"><p>How <span class="monospaced">path-to-loader-or-preloader</span> is determined, is described in <a href="#app_types_registry">The AppTypes registry</a>.</p></div>
1591
+ </div>
1592
+ <div class="sect3">
1593
+ <span class="anchor_helper" id="_spawnpreparer_further_sets_up_the_environment"></span><h4 data-anchor="_spawnpreparer_further_sets_up_the_environment">4.1.3. SpawnPreparer further sets up the environment</h4>
1594
+ <div class="paragraph"><p>The SpawnPreparer is responsible for setting up certain environment variables, current working directory, and other process environmental conditions. When SpawnPreparer is done, it executes the loader or the preloader.</p></div>
1595
+ </div>
1596
+ <div class="sect3">
1597
+ <span class="anchor_helper" id="_executing_the_loader_or_preloader"></span><h4 data-anchor="_executing_the_loader_or_preloader">4.1.4. Executing the loader or preloader</h4>
1598
+ <div class="paragraph"><p>If <span class="monospaced">passenger_spawn_method</span> is set to <span class="monospaced">smart</span> (the default), and there is a preloader available for the application’s programming language, then this step executes the language-specific <strong>preloader</strong>. If either of the previous conditions are not met (and thus the <span class="monospaced">passenger_spawn_method</span> is automatically forced to <span class="monospaced">direct</span>), then this step executes the language-specific <strong>loader</strong>.</p></div>
1599
+ <div class="paragraph"><p>All (pre)loaders are located in the <span class="monospaced">helper-scripts</span> directory in the source tree. Here are some of the (pre)loaders that are used:</p></div>
1600
+ <table class="tableblock frame-all grid-all" style="
1601
+ width:100%;
1602
+ ">
1603
+ <col style="width:33%;">
1604
+ <col style="width:33%;">
1605
+ <col style="width:33%;">
1606
+ <thead>
1607
+ <tr>
1608
+ <th class="tableblock halign-left valign-top"> Language/Framework </th>
1609
+ <th class="tableblock halign-left valign-top"> Loader </th>
1610
+ <th class="tableblock halign-left valign-top"> Preloader</th>
1611
+ </tr>
1612
+ </thead>
1613
+ <tbody>
1614
+ <tr>
1615
+ <td class="tableblock halign-left valign-top"><p class="tableblock">Ruby Rack and Rails</p></td>
1616
+ <td class="tableblock halign-left valign-top"><p class="tableblock">rack-loader.rb</p></td>
1617
+ <td class="tableblock halign-left valign-top"><p class="tableblock">rack-preloader.rb</p></td>
1618
+ </tr>
1619
+ <tr>
1620
+ <td class="tableblock halign-left valign-top"><p class="tableblock">Python</p></td>
1621
+ <td class="tableblock halign-left valign-top"><p class="tableblock">wsgi-loader.py</p></td>
1622
+ <td class="tableblock halign-left valign-top"><p class="tableblock">-</p></td>
1623
+ </tr>
1624
+ <tr>
1625
+ <td class="tableblock halign-left valign-top"><p class="tableblock">Node.js and bundled Meteor</p></td>
1626
+ <td class="tableblock halign-left valign-top"><p class="tableblock">node-loader.js</p></td>
1627
+ <td class="tableblock halign-left valign-top"><p class="tableblock">-</p></td>
1628
+ </tr>
1629
+ <tr>
1630
+ <td class="tableblock halign-left valign-top"><p class="tableblock">Unbundled Meteor</p></td>
1631
+ <td class="tableblock halign-left valign-top"><p class="tableblock">meteor-loader.rb</p></td>
1632
+ <td class="tableblock halign-left valign-top"><p class="tableblock">-</p></td>
1633
+ </tr>
1634
+ </tbody>
1635
+ </table>
1636
+ <div class="paragraph"><p><a href="#app_types_registry">The AppTypes registry</a> keeps a list of available (pre)loaders, and which languages they belong to.</p></div>
1637
+ <div class="paragraph"><p>What the loader does is described in <a href="#loaders">Loaders</a>. Likewise, preloaders are described in <a href="#preloaders">Preloaders</a>.</p></div>
1638
+ </div>
1639
+ </div>
1640
+ <div class="sect2">
1641
+ <span class="anchor_helper" id="loaders"></span><h3 data-anchor="loaders">4.2. Loaders</h3>
1642
+ <div class="paragraph"><p>A loader initializes in 4 stages:</p></div>
1643
+ <div class="olist arabic"><ol class="arabic">
1644
+ <li>
1645
+ <p>
1646
+ It first goes through a <a href="#loader_handshake">handshake</a>, where it reads the parameters that the Spawner has sent over the communication channel.
1647
+ </p>
1648
+ </li>
1649
+ <li>
1650
+ <p>
1651
+ It <a href="#application_loading">loads the application</a>. The behavior of this stage may be customized by the received parameters.
1652
+ </p>
1653
+ </li>
1654
+ <li>
1655
+ <p>
1656
+ It <a href="#loader_setting_up_server">sets up a server</a>, on which this application process listens for requests.
1657
+ </p>
1658
+ </li>
1659
+ <li>
1660
+ <p>
1661
+ It <a href="#loader_report_readiness">sends a response back</a> to the Spawner, in which it tells Spawner whether initialization was successful, and if so, where the socket is on which this application process listens for requests.
1662
+ </p>
1663
+ </li>
1664
+ </ol></div>
1665
+ <div class="paragraph"><p>Once initialized, the loader enters a main loop, in which it keeps handling requests until a signal has been received that says it should terminate.</p></div>
1666
+ <div class="paragraph"><p>As explained in <a href="#basic_setup_and_forking">Basic setup and forking</a>, the communication channels that the loader uses are just plain old stdin and stdout. Every programming language supports reading and writing from these channels. This also means that you can easily test a loader by simply executing it and entering messages in the terminal.</p></div>
1667
+ <div class="paragraph"><p>But stdout can also be used for printing normal output. How does the Spawner distinguish between control messages, and normal messages that should be displayed? The answer is that control messages must start with `!&gt; ` (including the trailing whitespace), and must end with a newline. The Spawner reads messages line-by-line, processes lines that start with `!&gt; `, and prints lines that don’t start with that marker.</p></div>
1668
+ <div class="sect3">
1669
+ <span class="anchor_helper" id="loader_handshake"></span><h4 data-anchor="loader_handshake">4.2.1. Handshake</h4>
1670
+ <div class="paragraph"><p>The handshaking process begins with a protocol version handshake. The loader printing the line <span class="monospaced">!&gt; I have control 1.0</span>. The Spawner then sends "You have control 1.0", which the loader checks. If the loader observes that the version handshake does not match the expectation, then it aborts with an error.</p></div>
1671
+ <div class="paragraph"><p>The Spawner also sends a list of key-value pairs, which is terminated by an empty newline. Upon receiving the empty newline, the Spawner proceeds with <a href="#application_loading">loading the application</a>.</p></div>
1672
+ <div class="paragraph"><p>Example:</p></div>
1673
+ <div class="listingblock">
1674
+ <div class="content monospaced">
1675
+ <pre>Loader Spawner
1676
+
1677
+ !&gt; I have control 1.0
1678
+ You have control 1.0
1679
+ passenger_root: ...
1680
+ passenger_version: 4.0.45
1681
+ ruby_libdir: /Users/hongli/Projects/passenger/lib
1682
+ generation_dir: /tmp/passenger.1.0.2082/generation-0
1683
+ gupid: 1647ad4-ovJJMiPkAAt
1684
+ connect_password: jXGaSzo8vRX5oGe2uuSv5tJsf1uX7ZgIeEH2x0nfOEa
1685
+ app_root: /Users/hongli/Sites/rack.test
1686
+ startup_file: config.ru
1687
+ process_title: Passenger RackApp
1688
+ log_level: 3
1689
+ environment: development
1690
+ base_uri: /
1691
+ ...
1692
+ (empty newline)</pre>
1693
+ </div>
1694
+ </div>
1695
+ </div>
1696
+ <div class="sect3">
1697
+ <span class="anchor_helper" id="application_loading"></span><h4 data-anchor="application_loading">4.2.2. Application loading</h4>
1698
+ <div class="paragraph"><p>How the application is loaded, depends on the programming language. Here are some examples:</p></div>
1699
+ <div class="ulist"><ul>
1700
+ <li>
1701
+ <p>
1702
+ The Ruby Rack loader does it by <span class="monospaced">load()</span>-ing the startup file, which by default is <span class="monospaced">config.ru</span>.
1703
+ </p>
1704
+ </li>
1705
+ <li>
1706
+ <p>
1707
+ The Python loader does it by calling <span class="monospaced">imp.load_source('passenger_wsgi', 'passenger_wsgi.py')</span>.
1708
+ </p>
1709
+ </li>
1710
+ <li>
1711
+ <p>
1712
+ The Node.js (and bundled Meteor) loader does it by <span class="monospaced">require()</span>-ing the startup file, which by default is <span class="monospaced">app.js</span>.
1713
+ </p>
1714
+ </li>
1715
+ <li>
1716
+ <p>
1717
+ The unbundled Meteor loader does it by executing the <span class="monospaced">meteor run</span> command.
1718
+ </p>
1719
+ </li>
1720
+ </ul></div>
1721
+ <div class="paragraph"><p>If no errors occur, the loader proceeds with <a href="#loader_setting_up_server">setting up a server</a>. Otherwise, it <a href="#loader_error_reporting">reports an error</a>.</p></div>
1722
+ </div>
1723
+ <div class="sect3">
1724
+ <span class="anchor_helper" id="loader_setting_up_server"></span><h4 data-anchor="loader_setting_up_server">4.2.3. Setting up a server</h4>
1725
+ <div class="paragraph"><p>The loader sets up a server on which the application listens for requests. The Spawner doesn’t care how this is done, how this server works, or even what its concurrency is. It only cares about how it can contact the server. So the loader has full freedom in this step.</p></div>
1726
+ <div class="paragraph"><p>As explained in <a href="#request_handler_forwarding_to_app">section <em>Request handling</em> and subsection <em>Forwarding to the application</em></a>, the RequestHandler can talk with the application process in a protocol that the application prefers. The RequestHandler supports two protocols:</p></div>
1727
+ <div class="ulist"><ul>
1728
+ <li>
1729
+ <p>
1730
+ A Phusion Passenger internal protocol which we call the <em>session</em> protocol. This protocol is used by the Ruby loaders and the Python loader. A description of this protocol is outside the scope of this document, but if you’re interested in how it looks like and how it behaves, you can study the source code of the Ruby and Python loaders, as well as <span class="monospaced">ext/common/Utils/MessageIO.h</span>.
1731
+ </p>
1732
+ </li>
1733
+ <li>
1734
+ <p>
1735
+ The HTTP protocol. This protocol is used by the Node.js and Meteor loaders. If you’re writing a new loader then, it’s probably easiest to use this protocol, together with whatever HTTP library is available for the loader’s target language.
1736
+ </p>
1737
+ </li>
1738
+ </ul></div>
1739
+ <div class="paragraph"><p>Typically, the server is setup to listen on a Unix domain socket file, inside the <span class="monospaced">backends</span> subdirectory of the <em>generation directory</em>. The path to the generation directory was passed during handshake. However the server may also listen on a TCP socket.</p></div>
1740
+ <div class="paragraph"><p>Once a server has been setup, the loader can <a href="#load_report_readiness">report readiness</a>.</p></div>
1741
+ </div>
1742
+ <div class="sect3">
1743
+ <span class="anchor_helper" id="loader_report_readiness"></span><h4 data-anchor="loader_report_readiness">4.2.4. Reporting readiness</h4>
1744
+ <div class="paragraph"><p>Once the server is set up, the loader sends back a <span class="monospaced">!&gt; Ready</span> response, followed by information about where the server socket listens on, and what protocol it expects. The response is terminated with a `!&gt; ` line (notice the trailing whitespace, which is required).</p></div>
1745
+ <div class="paragraph"><p>The information about where the server socket listens on, is a 4-tuple:</p></div>
1746
+ <div class="ulist"><ul>
1747
+ <li>
1748
+ <p>
1749
+ The <strong>name</strong>. This must always be <span class="monospaced">main</span>.
1750
+ </p>
1751
+ </li>
1752
+ <li>
1753
+ <p>
1754
+ The <strong>address</strong>. For Unix domain sockets, it has the form <span class="monospaced">unix:/path-to-socket</span>. For TCP socket, it has the form <span class="monospaced">tcp://127.0.0.1:PORT</span>.
1755
+ </p>
1756
+ </li>
1757
+ <li>
1758
+ <p>
1759
+ The <strong>protocol</strong>. This must be either <span class="monospaced">session</span> or <span class="monospaced">http_session</span>.
1760
+ </p>
1761
+ </li>
1762
+ <li>
1763
+ <p>
1764
+ The maximum number of <strong>concurrent connections</strong> the server supports. The ApplicationPool will ensure that the process never receives more concurrent requests than this number. A value of 0 means that the concurrency is unlimited.
1765
+ </p>
1766
+ </li>
1767
+ </ul></div>
1768
+ <div class="paragraph"><p>Here’s an example of what the Node.js loader sends as response:</p></div>
1769
+ <div class="listingblock">
1770
+ <div class="content monospaced">
1771
+ <pre>!&gt; Ready
1772
+ !&gt; socket: main;unix:/path-to-generation-dir/backends/node.1234-5677;session;0")
1773
+ !&gt;</pre>
1774
+ </div>
1775
+ </div>
1776
+ <div class="paragraph"><p>After reporting readiness, the loader can <a href="#loader_main_loop">enter a main loop and wait for termination</a>.</p></div>
1777
+ </div>
1778
+ <div class="sect3">
1779
+ <span class="anchor_helper" id="loader_error_reporting"></span><h4 data-anchor="loader_error_reporting">4.2.5. Error reporting</h4>
1780
+ <div class="paragraph"><p>If something goes wrong in any of the stages, the loader can report an error in two ways:</p></div>
1781
+ <div class="olist arabic"><ol class="arabic">
1782
+ <li>
1783
+ <p>
1784
+ Just write the error message to stdout as you normally do, and abort without printing the <span class="monospaced">!&gt; Ready</span> message. The HelperAgent will read everything that the loader has written to stdout, and use it as the error message. This error message is considered to be plain text.
1785
+ </p>
1786
+ </li>
1787
+ <li>
1788
+ <p>
1789
+ Abort after printing a special <span class="monospaced">!&gt; Error</span> message. The loader can signal that the message is HTML. The RequestHandler will format the error message as HTML.
1790
+ </p>
1791
+ </li>
1792
+ </ol></div>
1793
+ </div>
1794
+ <div class="sect3">
1795
+ <span class="anchor_helper" id="loader_main_loop"></span><h4 data-anchor="loader_main_loop">4.2.6. Main loop and termination</h4>
1796
+ <div class="paragraph"><p>The loader’s main loop’s job is to wait until a single byte has been received on stdin. As long as the byte has not been received, the loader should not exit, and should keep processing requests. When the byte has been received, the following conditions are guaranteed to be true:</p></div>
1797
+ <div class="ulist"><ul>
1798
+ <li>
1799
+ <p>
1800
+ All clients for this particular process have disconnected.
1801
+ </p>
1802
+ </li>
1803
+ <li>
1804
+ <p>
1805
+ No more clients will be routed to this particular process.
1806
+ </p>
1807
+ </li>
1808
+ </ul></div>
1809
+ <div class="paragraph"><p>This guarantee is enforced by the RequestHandler and the ApplicationPool. Thus, the loader doesn’t have to perform any kind of complicated shutdown. It can just exit the process.</p></div>
1810
+ <div class="paragraph"><p>If the server was listening on a Unix domain socket file, then the loader doesn’t even have to remove the file. The ApplicationPool already takes care of that.</p></div>
1811
+ </div>
1812
+ <div class="sect3">
1813
+ <span class="anchor_helper" id="_stdout_and_stderr_forwarding"></span><h4 data-anchor="_stdout_and_stderr_forwarding">4.2.7. Stdout and stderr forwarding</h4>
1814
+ <div class="paragraph"><p>All lines that the loader writes to stdout, and that are not prefixed with `!&gt; `, are forwarded by the HelperAgent to its own stdout. Similarly, everything that the loader writes to stderr, whether prefixed with `!&gt; ` or not, is forwarded by the HelperAgent to its own stdout.</p></div>
1815
+ <div class="paragraph"><p>While the Spawner is still doing its work, it takes care of this forwarding by itself. Once the Spawner is done, it outsources this work to two PipeWatcher objects, each which spawns a background thread for this purpose.</p></div>
1816
+ </div>
1817
+ </div>
1818
+ <div class="sect2">
1819
+ <span class="anchor_helper" id="preloaders"></span><h3 data-anchor="preloaders">4.3. Preloaders</h3>
1820
+ <div class="paragraph"><p>Preloaders are a special kind of loaders, used for reducing spawn time and leveraging copy-on-write. You can learn more about this at <a href="Users%20guide%20Nginx.html#spawning_methods_explained">Spawning methods explained</a>.</p></div>
1821
+ <div class="paragraph"><p>Preloaders look a lot like loaders, but behave slightly differently. They also use stdin, stderr and stdout to communicate with the Spawner. The protocols are very similar.</p></div>
1822
+ <div class="paragraph"><p>A preloader initializes in 4 stages:</p></div>
1823
+ <div class="olist arabic"><ol class="arabic">
1824
+ <li>
1825
+ <p>
1826
+ It first goes through a handshake, which is the same as <a href="#loader_handshake">the loader handshake</a>.
1827
+ </p>
1828
+ </li>
1829
+ <li>
1830
+ <p>
1831
+ It <a href="#application_loading">loads the application</a> just like the loader does.
1832
+ </p>
1833
+ </li>
1834
+ <li>
1835
+ <p>
1836
+ It sets up a server on which it listens for spawn commands.
1837
+ </p>
1838
+ </li>
1839
+ <li>
1840
+ <p>
1841
+ It sends a response back to the Spawner. This is similar to how the loader does it, but instead of telling the Spawner where the application listens for requests, it tells the Spawner where the preloader process listens for spawn commands.
1842
+ </p>
1843
+ </li>
1844
+ </ol></div>
1845
+ <div class="paragraph"><p>Once initialized, the preloader enters a main loop, in which it keeps handling spawn commands until a signal has been received that says it should terminate.</p></div>
1846
+ <div class="paragraph"><p>When a spawn command is received, the preloader forks off a child process (which already has the application loaded) and reports the child process’s PID to the Spawner. It also sets up a communication channel between the Spawner and the child process.</p></div>
1847
+ </div>
1848
+ <div class="sect2">
1849
+ <span class="anchor_helper" id="app_types_registry"></span><h3 data-anchor="app_types_registry">4.4. The AppTypes registry</h3>
1850
+ <div class="paragraph"><p>When the web server receives a request, the Phusion Passenger module inside it autodetects the type of application that the request belongs to. It does that by examening the filesystem and checking which one of the startup files exist. For example, if <span class="monospaced">config.ru</span> exists, then it assumes that it’s a Ruby app. Or if <span class="monospaced">app.js</span> exists, then it assumes that it’s a Node.js app. The Phusion Passenger module forwards the inferred application type to the HelperAgent.</p></div>
1851
+ <div class="paragraph"><p>Given an application type, the associated loader and preloader can be looked up.</p></div>
1852
+ <div class="paragraph"><p>Information about the supported application types, startup files, loaders and preloaders are defined in the following places:</p></div>
1853
+ <div class="ulist"><ul>
1854
+ <li>
1855
+ <p>
1856
+ The constant <span class="monospaced">appTypeDefinitions</span> in the file <span class="monospaced">ext/common/ApplicationPool2/AppTypes.cpp</span> keeps a list of supported languages. It also specifies the default startup file name belonging to each language.
1857
+ </p>
1858
+ </li>
1859
+ <li>
1860
+ <p>
1861
+ The method <span class="monospaced">getStartCommand()</span> in the file <span class="monospaced">ext/common/ApplicationPool2/Options.h</span> defines the loaders that should be used for each language.
1862
+ </p>
1863
+ </li>
1864
+ <li>
1865
+ <p>
1866
+ The method <span class="monospaced">tryCreateSmartSpawner()</span> in the file <span class="monospaced">ext/common/ApplicationPool2/SpawnerFactory.h</span> defines the preloaders that should be used for each language.
1867
+ </p>
1868
+ </li>
1869
+ <li>
1870
+ <p>
1871
+ The method <span class="monospaced">looks_like_app_directory?</span> in the file <span class="monospaced">lib/phusion_passenger/standalone/app_finder.rb</span> keeps a list of supported startup files. This is only used within Passenger Standalone.
1872
+ </p>
1873
+ </li>
1874
+ </ul></div>
1875
+ </div>
1876
+ </div>
1877
+ </div>
1878
+ <div class="sect1">
1879
+ <span class="anchor_helper" id="instance_state_and_communication"></span><h2 data-anchor="instance_state_and_communication">5. Instance state and communication</h2>
1880
+ <div class="sectionbody">
1881
+ <div class="paragraph"><p>Every time you start Phusion Passenger, you’ve created a new <strong>instance</strong>. Every instance consists of multiple processes that work together (Watchdog, HelperAgent, LoggingAgent, application processes). All those processes have to be able to communicate with each other. Those processes must also <strong>not</strong> communicate with the processes belonging to other instances. For example, if you start Apache+Passenger <strong>and</strong> Nginx+Passenger, then we don’t want the HelperAgent that’s started from Apache to use LoggingAgent that’s started from Nginx.</p></div>
1882
+ <div class="paragraph"><p>Clearly, the processes can’t listen on a specific TCP port for communication. Nor can they listen on a fixed Unix domain socket filename.</p></div>
1883
+ <div class="paragraph"><p>That is where the <em>instance directory</em> comes in. Every Phusion Passenger instance has its own, unique temporary directory. That directory is removed when the instance halts. The directory contains Unix domain socket files that the processes listen on. Every Phusion Passenger related process knows where its own instance directory is, and thus, knows how to communicate with other processes belonging to the same instance. The instance directory is implemented in <span class="monospaced">ext/common/InstanceDirectory.h</span>.</p></div>
1884
+ <div class="paragraph"><p>Administration tools such as <span class="monospaced">passenger-status</span> query information using instance directories. First, they check which instance directories exist on the system. If they find only one, then they query the sockets inside that sole instance directory. Otherwise, they abort with an error and ask the user to specifically select the instance to query.</p></div>
1885
+ </div>
1886
+ </div>
1887
+ <div class="sect1">
1888
+ <span class="anchor_helper" id="_about_rack"></span><h2 data-anchor="_about_rack">6. Appendix A: About Rack</h2>
1889
+ <div class="sectionbody">
1890
+ <div class="paragraph"><p>The de-facto standard interface for Ruby web applications is <a href="http://rack.rubyforge.org/">Rack</a>. Rack specifies an programming interface for web application developers to implement. This interface covers HTTP request and response handling, and is not dependent on any particular application server. The idea is that any Rack-compliant application server can implement the Rack specification and work with all Rack-compliant web applications.</p></div>
1891
+ <div class="paragraph"><p><span class="image">
1892
+ <img src="images/rack.png" alt="images/rack.png">
1893
+ </span></p></div>
1894
+ <div class="paragraph"><p>In the distant past, each Ruby web framework had its own interface, so application servers needed to explicitly add support for each web framework. Nowadays application servers just support Rack.</p></div>
1895
+ <div class="paragraph"><p><span class="image">
1896
+ <img src="images/many_web_framework_protocols.png" alt="images/many_web_framework_protocols.png">
1897
+ </span></p></div>
1898
+ <div class="paragraph"><p>Ruby on Rails has been fully Rack compliant since version 3.0. Rails 2.3 was partially Rack-compliant while earlier versions were not Rack-compliant at all. Phusion Passenger supports Rack as well as all Rails 1.x and 2.x versions.</p></div>
1899
+ </div>
1900
+ </div>
1901
+ <div class="sect1">
1902
+ <span class="anchor_helper" id="_about_apache"></span><h2 data-anchor="_about_apache">7. Appendix B: About Apache</h2>
1903
+ <div class="sectionbody">
1904
+ <div class="paragraph"><p>The Apache web server has a dynamic module system and a pluggable I/O multiprocessing (the ability to handle more than 1 concurrent HTTP client at the same time) architecture. An Apache module which implements a particular multiprocessing strategy, is called a Multi-Processing Module (MPM). The single-threaded multi-process <a href="http://httpd.apache.org/docs/2.4/mod/prefork.html">prefork MPM</a> had been the default and the most popular one for a long time, but in recent times the hybrid multi-threaded/multi-process <a href="http://httpd.apache.org/docs/2.4/mod/worker.html">worker MPM</a> is becoming increasingly popular because of its better performance and scalability. Furthermore, Apache 2.4 introduced the <a href="http://httpd.apache.org/docs/2.4/mod/event.html">event MPM</a> which is a hybrid evented/multi-threaded/multi-process MPM and offers even more scalability benefits.</p></div>
1905
+ <div class="paragraph"><p>The prefork MPM remains in wide use today because it’s the only MPM that works well with mod_php.</p></div>
1906
+ <div class="paragraph"><p>The prefork MPM spawns multiple worker child processes. HTTP requests are first accepted by a so-called control process, and then forwarded to one of the worker processes. The next section contains a diagram which shows the prefork MPM’s architecture.</p></div>
1907
+ </div>
1908
+ </div>
1909
+ <div class="sect1">
1910
+ <span class="anchor_helper" id="_about_nginx"></span><h2 data-anchor="_about_nginx">8. Appendix C: About Nginx</h2>
1911
+ <div class="sectionbody">
1912
+ <div class="paragraph"><p>Nginx is a lightweight web server that is becoming increasingly popular. It is known to be smaller, lighter weight and more scalable than Apache thanks to its evented I/O architecture. That said, Nginx is less flexible than Apache. For example it has no dynamic module system: all modules must be statically compiled into Nginx.</p></div>
1913
+ </div>
1914
+ </div>
1915
+ </div>
1916
+ <div id="footnotes"><hr></div>
1917
+ <div id="footer">
1918
+
1919
+ </div>
1920
+ <script>/*! jQuery v1.7.1 jquery.com | jquery.org/license */
1921
+ (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")};
1922
+ f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
1923
+ {for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
1924
+ /**
1925
+ * jQuery hashchange 1.0.0
1926
+ *
1927
+ * (based on jquery.history)
1928
+ *
1929
+ * Copyright (c) 2008 Chris Leishman (chrisleishman.com)
1930
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
1931
+ * and GPL (GPL-LICENSE.txt) licenses.
1932
+ */
1933
+ (function($) {
1934
+
1935
+ $.fn.extend({
1936
+ hashchange: function(callback) { this.bind('hashchange', callback) },
1937
+ openOnClick: function(href) {
1938
+ if (href === undefined || href.length == 0)
1939
+ href = '#';
1940
+ return this.click(function(ev) {
1941
+ if (href && href.charAt(0) == '#') {
1942
+ // execute load in separate call stack
1943
+ window.setTimeout(function() { $.locationHash(href) }, 0);
1944
+ } else {
1945
+ window.location(href);
1946
+ }
1947
+ ev.stopPropagation();
1948
+ return false;
1949
+ });
1950
+ }
1951
+ });
1952
+
1953
+ // IE 8 introduces the hashchange event natively - so nothing more to do
1954
+ if ($.browser.msie && document.documentMode && document.documentMode >= 8) {
1955
+ $.extend({
1956
+ locationHash: function(hash) {
1957
+ if (!hash) hash = '#';
1958
+ else if (hash.charAt(0) != '#') hash = '#' + hash;
1959
+ location.hash = hash;
1960
+ }
1961
+ });
1962
+ return;
1963
+ }
1964
+
1965
+ var curHash;
1966
+ // hidden iframe for IE (earlier than 8)
1967
+ var iframe;
1968
+
1969
+ $.extend({
1970
+ locationHash: function(hash) {
1971
+ if (curHash === undefined) return;
1972
+
1973
+ if (!hash) hash = '#';
1974
+ else if (hash.charAt(0) != '#') hash = '#' + hash;
1975
+
1976
+ location.hash = hash;
1977
+
1978
+ if (curHash == hash) return;
1979
+ curHash = hash;
1980
+
1981
+ if ($.browser.msie) updateIEFrame(hash);
1982
+ $.event.trigger('hashchange');
1983
+ }
1984
+ });
1985
+
1986
+ $(document).ready(function() {
1987
+ curHash = location.hash;
1988
+ if ($.browser.msie) {
1989
+ // stop the callback firing twice during init if no hash present
1990
+ if (curHash == '') curHash = '#';
1991
+ // add hidden iframe for IE
1992
+ iframe = $('<iframe />').hide().get(0);
1993
+ $('body').prepend(iframe);
1994
+ updateIEFrame(location.hash);
1995
+ setInterval(checkHashIE, 100);
1996
+ } else {
1997
+ setInterval(checkHash, 100);
1998
+ }
1999
+ });
2000
+ $(window).unload(function() { iframe = null });
2001
+
2002
+ function checkHash() {
2003
+ var hash = location.hash;
2004
+ if (hash != curHash) {
2005
+ curHash = hash;
2006
+ $.event.trigger('hashchange');
2007
+ }
2008
+ }
2009
+
2010
+ if ($.browser.msie) {
2011
+ // Attach a live handler for any anchor links
2012
+ $('a[href^=#]').live('click', function() {
2013
+ var hash = $(this).attr('href');
2014
+ // Don't intercept the click if there is an existing anchor on the page
2015
+ // that matches this hash
2016
+ if ($(hash).length == 0 && $('a[name='+hash.slice(1)+']').length == 0) {
2017
+ $.locationHash(hash);
2018
+ return false;
2019
+ }
2020
+ });
2021
+ }
2022
+
2023
+ function checkHashIE() {
2024
+ // On IE, check for location.hash of iframe
2025
+ var idoc = iframe.contentDocument || iframe.contentWindow.document;
2026
+ var hash = idoc.location.hash;
2027
+ if (hash == '') hash = '#';
2028
+
2029
+ if (hash != curHash) {
2030
+ if (location.hash != hash) location.hash = hash;
2031
+ curHash = hash;
2032
+ $.event.trigger('hashchange');
2033
+ }
2034
+ }
2035
+
2036
+ function updateIEFrame(hash) {
2037
+ if (hash == '#') hash = '';
2038
+ var idoc = iframe.contentWindow.document;
2039
+ idoc.open();
2040
+ idoc.close();
2041
+ if (idoc.location.hash != hash) idoc.location.hash = hash;
2042
+ }
2043
+
2044
+ })(jQuery);
2045
+ // IE...
2046
+ if (!Date.now) {
2047
+ Date.now = function() {
2048
+ return new Date().getTime();
2049
+ }
2050
+ }
2051
+
2052
+ var Mizuho = {
2053
+ /** Cached DOM elements so that we don't have to re-find them over and over. */
2054
+ $document: undefined,
2055
+ $window: undefined,
2056
+ $mainSections: undefined,
2057
+ $sectionHeaders: undefined,
2058
+
2059
+ /** Constants */
2060
+ MAX_TOC_LEVEL: 3,
2061
+
2062
+ sectionHeadersSelector: undefined,
2063
+ scrollMemory: {},
2064
+ changingHash: false,
2065
+ activeHash: undefined,
2066
+ /** Whether in single-page or multi-page mode. Either 'single' or 'multi'. */
2067
+ mode: 'single',
2068
+ /** Whether smooth scrolling is enabled. It is always enabled except right
2069
+ * after page load: when the page is scrolled to the section as pointed to
2070
+ * by location.hash.
2071
+ */
2072
+ smoothScrolling: true,
2073
+
2074
+ initialize: function() {
2075
+ this.sectionHeadersSelector = '';
2076
+ for (var i = 0; i < this.MAX_TOC_LEVEL; i++) {
2077
+ if (i != 0) {
2078
+ this.sectionHeadersSelector += ', ';
2079
+ }
2080
+ this.sectionHeadersSelector += 'h' + (i + 2);
2081
+ }
2082
+
2083
+ this.$document = $(document);
2084
+ this.$window = $(window);
2085
+ this.$mainSections = $('.sect1');
2086
+ this.$sectionHeaders = $(this.sectionHeadersSelector, '#content');
2087
+ this.$sectionHeaders.sort(function(a, b) {
2088
+ var off_a = $(a).offset();
2089
+ var off_b = $(b).offset();
2090
+ return off_a.top - off_b.top;
2091
+ });
2092
+
2093
+ if (this.isMobileDevice()) {
2094
+ $(document.body).addClass('mobile');
2095
+ }
2096
+ },
2097
+
2098
+
2099
+ /********* Generic utility functions *********/
2100
+
2101
+ isMobileDevice: function() {
2102
+ return navigator.userAgent.match(
2103
+ /(IEMobile|Windows CE|NetFront|PlayStation|PLAYSTATION|like Mac OS X|MIDP|UP\.Browser|Symbian|Nintendo|Android)/
2104
+ );
2105
+ },
2106
+
2107
+ virtualAnimate: function(options) {
2108
+ var options = $.extend({
2109
+ duration: 1000
2110
+ }, options || {});
2111
+ var animation_start = Date.now();
2112
+ var animation_end = Date.now() + options.duration;
2113
+ var interval = animation_end - animation_start;
2114
+ this._virtualAnimate_step(animation_start, animation_end, interval, options);
2115
+ },
2116
+
2117
+ _virtualAnimate_step: function(animation_start, animation_end, interval, options) {
2118
+ var self = this;
2119
+ var now = new Date();
2120
+ var progress = (now - animation_start) / interval;
2121
+ if (progress > 1) {
2122
+ progress = 1;
2123
+ }
2124
+ progress = (1 + Math.sin(-Math.PI / 2 + progress * Math.PI)) / 2;
2125
+ options.step(progress);
2126
+ if (now < animation_end) {
2127
+ setTimeout(function() {
2128
+ self._virtualAnimate_step(animation_start,
2129
+ animation_end, interval, options);
2130
+ }, 15);
2131
+ } else {
2132
+ options.step(1);
2133
+ if (options.finish) {
2134
+ options.finish();
2135
+ }
2136
+ }
2137
+ },
2138
+
2139
+ smoothlyScrollTo: function(top) {
2140
+ if (!this.smoothScrolling) {
2141
+ return this.setScrollTop(top);
2142
+ }
2143
+
2144
+ var self = this;
2145
+ var $document = this.$document;
2146
+ var current = $document.scrollTop();
2147
+ this.virtualAnimate({
2148
+ duration: 300,
2149
+ step: function(x) {
2150
+ $document.scrollTop(Math.floor(
2151
+ top + (1 - x) * (current - top)
2152
+ ));
2153
+ },
2154
+ finish: function() {
2155
+ self.setScrollTop(top);
2156
+ }
2157
+ });
2158
+ },
2159
+
2160
+ smoothlyScrollToToc: function() {
2161
+ this.smoothlyScrollTo($('#toc').position().top);
2162
+ },
2163
+
2164
+ scrollToHeader: function(header) {
2165
+ this.smoothlyScrollTo($(header).offset().top - 50);
2166
+ },
2167
+
2168
+ setScrollTop: function(top, element) {
2169
+ // Browsers don't always scroll properly so work around
2170
+ // this with a few timers.
2171
+ var self = this;
2172
+ element = element || this.$document;
2173
+ element = $(element);
2174
+ element.scrollTop(top);
2175
+ setTimeout(function() {
2176
+ element.scrollTop(top);
2177
+ }, 1);
2178
+ setTimeout(function() {
2179
+ element.scrollTop(top);
2180
+ self.$document.trigger('mizuho:updateTopBar');
2181
+ }, 20);
2182
+ },
2183
+
2184
+
2185
+ /********* Mizuho-specific functions *********/
2186
+
2187
+ /** Returns the currently displayed section's header DOM element. */
2188
+ currentSubsection: function() {
2189
+ var $sectionHeaders = this.$sectionHeaders;
2190
+ var scrollTop = this.$document.scrollTop();
2191
+ var windowHeight = this.$window.height();
2192
+ var offset;
2193
+
2194
+ var low = 0;
2195
+ var high = this.$sectionHeaders.length - 1;
2196
+ var mid = 0;
2197
+
2198
+ while (low <= high) {
2199
+ mid = Math.floor((low + high) / 2);
2200
+ offset = $($sectionHeaders[mid]).offset();
2201
+
2202
+ if (offset.top >= scrollTop) {
2203
+ high = mid - 1;
2204
+ } else {
2205
+ low = mid + 1;
2206
+ }
2207
+ }
2208
+
2209
+ var $found = $($sectionHeaders[low]);
2210
+ if ($found.offset().top > scrollTop + windowHeight) {
2211
+ if (low > 0) {
2212
+ return $sectionHeaders[low - 1];
2213
+ } else {
2214
+ return undefined;
2215
+ }
2216
+ } else {
2217
+ return $sectionHeaders[low];
2218
+ }
2219
+ },
2220
+
2221
+ /** Looks up a section's header DOM element corresponding to a hash name. */
2222
+ lookupHeader: function(hash) {
2223
+ var id = hash.replace(/^#!\//, '#');
2224
+ if (id == '') {
2225
+ return undefined;
2226
+ } else {
2227
+ var header = $(id);
2228
+ if (header.length == 0) {
2229
+ return undefined;
2230
+ } else {
2231
+ return header;
2232
+ }
2233
+ }
2234
+ }
2235
+ };
2236
+
2237
+ for (var key in Mizuho) {
2238
+ if (typeof(Mizuho[key]) == 'function') {
2239
+ Mizuho[key] = $.proxy(Mizuho[key], Mizuho);
2240
+ }
2241
+ }
2242
+ $(document).ready(Mizuho.initialize);
2243
+ //$(document).ready(Mizuho.installHashbangLinks);
2244
+
2245
+ Mizuho.initializeTopBar = $.proxy(function() {
2246
+ var $window = this.$window;
2247
+ var $document = this.$document;
2248
+ var self = this;
2249
+ var $topbar = $('#topbar');
2250
+ var $title = $('#header h1');
2251
+ var $currentSection = $('#current_section');
2252
+ var isMobileDevice = this.isMobileDevice();
2253
+ var timerId;
2254
+
2255
+ // Create the floating table of contents used in the top bar.
2256
+ var $floattoc = $('<div id="floattoc"></div>').html($('#toc').html());
2257
+ $floattoc.find('#toctitle').remove();
2258
+ $floattoc.find('.comments').remove();
2259
+ $floattoc.css('visibility', 'hidden');
2260
+ $floattoc.insertAfter($topbar);
2261
+ var $floattoclinks = $floattoc.find('a');
2262
+ $floattoclinks.each(function() {
2263
+ // Firefox changes '#!' to '#%21' so change that back.
2264
+ var $this = $(this);
2265
+ var href = $this.attr('href');
2266
+ if (href.match(/^#%21/)) {
2267
+ $this.attr('href', href.replace(/^#%21/, '#!'));
2268
+ }
2269
+ });
2270
+ $floattoclinks.click(function(event) {
2271
+ self.internalLinkClicked(this, event);
2272
+ });
2273
+
2274
+ // Callback for when the user clicks on the Table of Contents
2275
+ // button on the top bar.
2276
+ function showFloatingToc() {
2277
+ var scrollUpdateTimerId;
2278
+
2279
+ function reposition() {
2280
+ if (isMobileDevice) {
2281
+ $floattoc.css({
2282
+ top: $currentSection.offset().top +
2283
+ $currentSection.innerHeight() +
2284
+ 'px',
2285
+ height: $window.height() * 0.7 + 'px'
2286
+ });
2287
+ }
2288
+ }
2289
+
2290
+ function highlightCurrentTocEntry() {
2291
+ var currentSubsection = self.currentSubsection();
2292
+ $floattoclinks.removeClass('current');
2293
+ if (currentSubsection) {
2294
+ var currentSubsectionTitle = $(currentSubsection).text();
2295
+ var $link;
2296
+
2297
+ $floattoclinks.each(function() {
2298
+ if ($(this).text() == currentSubsectionTitle) {
2299
+ $link = $(this);
2300
+ return false;
2301
+ }
2302
+ });
2303
+ if ($link) {
2304
+ $link.addClass('current');
2305
+ self.setScrollTop(
2306
+ $floattoc.scrollTop() +
2307
+ $link.position().top -
2308
+ $floattoc.height() * 0.45,
2309
+ $floattoc);
2310
+ return false;
2311
+ }
2312
+ }
2313
+ }
2314
+
2315
+ function hideFloatingToc() {
2316
+ $currentSection.removeClass('pressed');
2317
+ $floattoc.css('visibility', 'hidden');
2318
+ $floattoclinks.unbind('click', hideFloatingToc);
2319
+ $document.unbind('mousedown', onMouseDown);
2320
+ $document.unbind('touchdown', onMouseDown);
2321
+ $document.unbind('mizuho:hideTopBar', hideFloatingToc);
2322
+ $window.unbind('scroll', onScroll);
2323
+ if (scrollUpdateTimerId !== undefined) {
2324
+ clearTimeout(scrollUpdateTimerId);
2325
+ scrollUpdateTimerId = undefined;
2326
+ }
2327
+ }
2328
+
2329
+ function onMouseDown(event) {
2330
+ if (event.target != $floattoc[0]
2331
+ && $(event.target).closest('#floattoc').length == 0) {
2332
+ hideFloatingToc();
2333
+ }
2334
+ }
2335
+
2336
+ function onScroll(event) {
2337
+ if (scrollUpdateTimerId === undefined) {
2338
+ scrollUpdateTimerId = setTimeout(function() {
2339
+ scrollUpdateTimerId = undefined;
2340
+ reposition();
2341
+ highlightCurrentTocEntry();
2342
+ }, 100);
2343
+ }
2344
+ }
2345
+
2346
+ // Layout and display floating TOC.
2347
+ highlightCurrentTocEntry();
2348
+ var origScrollTop = $document.scrollTop();
2349
+ var windowWidth = $window.width();
2350
+ var maxRight = windowWidth - Math.floor(windowWidth * 0.1);
2351
+
2352
+ if ($currentSection.offset().left + $floattoc.outerWidth() > maxRight) {
2353
+ $floattoc.css('left', maxRight - $floattoc.outerWidth());
2354
+ } else {
2355
+ $floattoc.css('left', $currentSection.offset().left + 'px');
2356
+ }
2357
+ reposition();
2358
+ $floattoc.css('visibility', 'visible');
2359
+ $currentSection.addClass('pressed');
2360
+
2361
+ $floattoclinks.bind('click', hideFloatingToc);
2362
+ $document.bind('mousedown', onMouseDown)
2363
+ $document.bind('touchdown', onMouseDown);
2364
+ $document.bind('mizuho:hideTopBar', hideFloatingToc);
2365
+ $window.bind('scroll', onScroll);
2366
+ }
2367
+
2368
+ // Called whenever the user scrolls. Updates the title of the
2369
+ // Table of Contents button in the top bar to the section that
2370
+ // the user is currently reading.
2371
+ function update() {
2372
+ if ($title.offset().top + $title.height() < $document.scrollTop()) {
2373
+ if (!$topbar.is(':visible')) {
2374
+ $topbar.slideDown(250);
2375
+ $document.trigger('mizuho:showTopBar');
2376
+ }
2377
+ } else {
2378
+ if ($topbar.is(':visible')) {
2379
+ $topbar.slideUp();
2380
+ $document.trigger('mizuho:hideTopBar');
2381
+ }
2382
+ }
2383
+
2384
+ if (isMobileDevice) {
2385
+ $topbar.css({
2386
+ top: $document.scrollTop() + 'px',
2387
+ width: $window.width() -
2388
+ parseInt($topbar.css('padding-left')) -
2389
+ parseInt($topbar.css('padding-right')) +
2390
+ 'px'
2391
+ });
2392
+ }
2393
+
2394
+ var header = self.currentSubsection();
2395
+ var name;
2396
+ if (header) {
2397
+ name = $(header).text();
2398
+ } else {
2399
+ name = 'Preamble';
2400
+ }
2401
+ $currentSection.text(name);
2402
+ }
2403
+
2404
+ function scheduleUpdate() {
2405
+ if (timerId !== undefined) {
2406
+ return;
2407
+ }
2408
+ timerId = setTimeout(function() {
2409
+ timerId = undefined;
2410
+ update();
2411
+ }, 100);
2412
+ }
2413
+
2414
+
2415
+ if (isMobileDevice) {
2416
+ // Mobile devices don't support position fixed.
2417
+ $topbar.css('position', 'absolute');
2418
+ $floattoc.css('position', 'absolute');
2419
+ }
2420
+
2421
+ $currentSection.click(showFloatingToc);
2422
+ $window.scroll(scheduleUpdate);
2423
+ $document.bind('mizuho:updateTopBar', update);
2424
+ }, Mizuho);
2425
+
2426
+ $(document).ready(Mizuho.initializeTopBar);
2427
+
2428
+ </script>
2429
+ </body>
2430
+ </html>