Browse Source

Merge branch 'master' into unicorn

Patrick Falls 12 years ago
parent
commit
53c58b3a13
100 changed files with 14644 additions and 90 deletions
  1. 3 0
      .gitignore
  2. 12 4
      README.md
  3. 1362 0
      cake/app/webroot/apc.php
  4. 1 0
      config/benchmark_profile
  5. 8 0
      config/erlang.list
  6. BIN
      finagle/.cache
  7. 34 0
      finagle/.classpath
  8. 3 0
      finagle/.gitignore
  9. 12 0
      finagle/.project
  10. 0 0
      finagle/__init__.py
  11. 24 0
      finagle/benchmark_config
  12. 15 0
      finagle/build.sbt
  13. 1 0
      finagle/project/build.properties
  14. 1 0
      finagle/sbt
  15. BIN
      finagle/sbt-launch.jar
  16. 29 0
      finagle/setup.py
  17. 133 0
      finagle/src/main/scala/com/falmarri/finagle/Finagle.scala
  18. 14 14
      framework_test.py
  19. 2 0
      go/benchmark_config
  20. 0 0
      go/bin/.gitkeep
  21. 0 25
      go/hello.go
  22. 0 0
      go/pkg/.gitkeep
  23. 6 4
      go/setup.py
  24. 67 0
      go/src/hello/hello.go
  25. 3 1
      http-kit/hello/project.clj
  26. 6 5
      http-kit/hello/src/hello/handler.clj
  27. 5 2
      http-kit/setup.py
  28. 22 12
      installer.py
  29. 27 0
      lift-stateless/README.md
  30. 0 0
      lift-stateless/__init__.py
  31. 13 0
      lift-stateless/benchmark_config
  32. 63 0
      lift-stateless/build.sbt
  33. 44 0
      lift-stateless/project/Deploy.scala
  34. 1 0
      lift-stateless/project/build.properties
  35. 7 0
      lift-stateless/project/build.scala
  36. 5 0
      lift-stateless/project/plugins.sbt
  37. 3 0
      lift-stateless/run
  38. 1 0
      lift-stateless/sbt
  39. BIN
      lift-stateless/sbt-launch.jar
  40. 7 0
      lift-stateless/server.conf
  41. 21 0
      lift-stateless/setup.py
  42. 18 0
      lift-stateless/src/main/resources/WEB-INF/web.xml
  43. 1109 0
      lift-stateless/src/main/resources/bootstrap/css/bootstrap-responsive.css
  44. 8 0
      lift-stateless/src/main/resources/bootstrap/css/bootstrap-responsive.min.css
  45. 6158 0
      lift-stateless/src/main/resources/bootstrap/css/bootstrap.css
  46. 8 0
      lift-stateless/src/main/resources/bootstrap/css/bootstrap.min.css
  47. BIN
      lift-stateless/src/main/resources/bootstrap/img/glyphicons-halflings-white.png
  48. BIN
      lift-stateless/src/main/resources/bootstrap/img/glyphicons-halflings.png
  49. 2268 0
      lift-stateless/src/main/resources/bootstrap/js/bootstrap.js
  50. 5 0
      lift-stateless/src/main/resources/bootstrap/js/bootstrap.min.js
  51. 27 0
      lift-stateless/src/main/resources/index.html
  52. 1 0
      lift-stateless/src/main/resources/jsl/jquery-1.8.3.min.js
  53. 0 0
      lift-stateless/src/main/resources/jsl/underscore-1.4.3.min.js
  54. 2 0
      lift-stateless/src/main/resources/logback.xml
  55. 47 0
      lift-stateless/src/main/resources/templates-hidden/wizard-all.html
  56. 48 0
      lift-stateless/src/main/resources/templates-hidden/wrapper.html
  57. 67 0
      lift-stateless/src/main/scala/Benchmark.scala
  58. 45 0
      lift-stateless/src/main/scala/Boot.scala
  59. 59 0
      lift-stateless/src/main/scala/DB.scala
  60. 38 0
      lift-stateless/src/main/scala/Main.scala
  61. 14 0
      lift-stateless/src/main/scala/Options.scala
  62. 8 1
      nodejs/benchmark_config
  63. 54 22
      nodejs/hello.js
  64. 1 0
      nodejs/package.json
  65. 21 0
      onion/Makefile
  66. 7 0
      onion/README
  67. 0 0
      onion/__init__.py
  68. 18 0
      onion/benchmark_config
  69. 228 0
      onion/hello.c
  70. 20 0
      onion/setup.py
  71. 21 0
      openresty/README.md
  72. 0 0
      openresty/__init__.py
  73. 30 0
      openresty/app.lua
  74. 13 0
      openresty/benchmark_config
  75. 17 0
      openresty/nginx.conf
  76. 16 0
      openresty/setup.py
  77. 9 0
      php-symfony2/.gitignore
  78. 10 0
      php-symfony2/.travis.yml
  79. 19 0
      php-symfony2/LICENSE
  80. 37 0
      php-symfony2/README.md
  81. 0 0
      php-symfony2/__init__.py
  82. 1 0
      php-symfony2/app/.htaccess
  83. 9 0
      php-symfony2/app/AppCache.php
  84. 39 0
      php-symfony2/app/AppKernel.php
  85. 13 0
      php-symfony2/app/Resources/views/base.html.twig
  86. 669 0
      php-symfony2/app/SymfonyRequirements.php
  87. 14 0
      php-symfony2/app/autoload.php
  88. 1137 0
      php-symfony2/app/bootstrap.php.cache
  89. 55 0
      php-symfony2/app/check.php
  90. 65 0
      php-symfony2/app/config/config.yml
  91. 29 0
      php-symfony2/app/config/config_dev.yml
  92. 29 0
      php-symfony2/app/config/config_prod.yml
  93. 16 0
      php-symfony2/app/config/config_test.yml
  94. 14 0
      php-symfony2/app/config/parameters.yml
  95. 3 0
      php-symfony2/app/config/routing.yml
  96. 27 0
      php-symfony2/app/config/routing_dev.yml
  97. 42 0
      php-symfony2/app/config/security.yml
  98. 22 0
      php-symfony2/app/console
  99. 41 0
      php-symfony2/app/phpunit.xml.dist
  100. 13 0
      php-symfony2/benchmark_config

+ 3 - 0
.gitignore

@@ -9,3 +9,6 @@ target/
 *.out
 *.class
 mods/
+/.settings
+/.buildpath
+/.project

+ 12 - 4
README.md

@@ -44,10 +44,14 @@ Next, we're going to setup the servers with all the necessary software:
 
 	./run-tests.py -s server-private-ip -c client-private-ip -i path-to-pem --install-software --list-tests
     source ~/.bash_profile
+    # For your first time through the tests, set the ulimit for open files
+    ulimit -n 4096
     # Most software is installed autormatically by the script, but running the mongo command below from 
     # the install script was causing some errors. For now this needs to be run manually.
-    go get github.com/hoisie/web
-	mongo --host client-private-ip < config/create.js
+    cd installs/jruby-rack && rvm jruby-1.7.3 do jruby -S bundle exec rake clean gem SKIP_SPECS=true"
+    cd target && rvm jruby-1.7.3 do gem install jruby-rack-1.2.0.SNAPSHOT.gem
+    cd ../..
+	  mongo --host client-private-ip < config/create.js
 
 Assuming the above finished without error, we're ready to start the test suite:
 
@@ -92,10 +96,14 @@ Next, we're going to setup the servers with all the necessary software:
 
 	./run-tests.py -s server-ip -c client-ip -i path-to-ssh-key --install-software --list-tests
     source ~/.bash_profile
+    # For your first time through the tests, set the ulimit for open files
+    ulimit -n 4096
     # Most software is installed autormatically by the script, but running the mongo command below from
     # the install script was causing some errors. For now this needs to be run manually.
-    go get github.com/hoisie/web
-	mongo --host client-ip < config/create.js
+    cd installs/jruby-rack && rvm jruby-1.7.3 do jruby -S bundle exec rake clean gem SKIP_SPECS=true"
+    cd target && rvm jruby-1.7.3 do gem install jruby-rack-1.2.0.SNAPSHOT.gem
+    cd ../..
+    mongo --host client-ip < config/create.js
 
 Assuming this finished without error, we're ready to start the test suite:
 

+ 1362 - 0
cake/app/webroot/apc.php

@@ -0,0 +1,1362 @@
+<?php
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2011 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | [email protected] so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Authors: Ralf Becker <[email protected]>                               |
+  |          Rasmus Lerdorf <[email protected]>                             |
+  |          Ilia Alshanetsky <[email protected]>                         |
+  +----------------------------------------------------------------------+
+
+   All other licensing and usage conditions are those of the PHP Group.
+
+ */
+
+$VERSION='$Id: apc.php 325483 2012-05-01 00:34:04Z rasmus $';
+
+////////// READ OPTIONAL CONFIGURATION FILE ////////////
+if (file_exists("apc.conf.php")) include("apc.conf.php");
+////////////////////////////////////////////////////////
+
+////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
+
+defaults('USE_AUTHENTICATION',1);			// Use (internal) authentication - best choice if 
+											// no other authentication is available
+											// If set to 0:
+											//  There will be no further authentication. You 
+											//  will have to handle this by yourself!
+											// If set to 1:
+											//  You need to change ADMIN_PASSWORD to make
+											//  this work!
+defaults('ADMIN_USERNAME','apc'); 			// Admin Username
+defaults('ADMIN_PASSWORD','password');  	// Admin Password - CHANGE THIS TO ENABLE!!!
+
+// (beckerr) I'm using a clear text password here, because I've no good idea how to let 
+//           users generate a md5 or crypt password in a easy way to fill it in above
+
+//defaults('DATE_FORMAT', "d.m.Y H:i:s");	// German
+defaults('DATE_FORMAT', 'Y/m/d H:i:s'); 	// US
+
+defaults('GRAPH_SIZE',200);					// Image size
+
+//defaults('PROXY', 'tcp://127.0.0.1:8080');
+
+////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
+
+
+// "define if not defined"
+function defaults($d,$v) {
+	if (!defined($d)) define($d,$v); // or just @define(...)
+}
+
+// rewrite $PHP_SELF to block XSS attacks
+//
+$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES, 'UTF-8') : '';
+$time = time();
+$host = php_uname('n');
+if($host) { $host = '('.$host.')'; }
+if (isset($_SERVER['SERVER_ADDR'])) {
+  $host .= ' ('.$_SERVER['SERVER_ADDR'].')';
+}
+
+// operation constants
+define('OB_HOST_STATS',1);
+define('OB_SYS_CACHE',2);
+define('OB_USER_CACHE',3);
+define('OB_SYS_CACHE_DIR',4);
+define('OB_VERSION_CHECK',9);
+
+// check validity of input variables
+$vardom=array(
+	'OB'	=> '/^\d+$/',			// operational mode switch
+	'CC'	=> '/^[01]$/',			// clear cache requested
+	'DU'	=> '/^.*$/',			// Delete User Key
+	'SH'	=> '/^[a-z0-9]+$/',		// shared object description
+
+	'IMG'	=> '/^[123]$/',			// image to generate
+	'LO'	=> '/^1$/',				// login requested
+
+	'COUNT'	=> '/^\d+$/',			// number of line displayed in list
+	'SCOPE'	=> '/^[AD]$/',			// list view scope
+	'SORT1'	=> '/^[AHSMCDTZ]$/',	// first sort key
+	'SORT2'	=> '/^[DA]$/',			// second sort key
+	'AGGR'	=> '/^\d+$/',			// aggregation by dir level
+	'SEARCH'	=> '~^[a-zA-Z0-9/_.-]*$~'			// aggregation by dir level
+);
+
+// default cache mode
+$cache_mode='opcode';
+
+// cache scope
+$scope_list=array(
+	'A' => 'cache_list',
+	'D' => 'deleted_list'
+);
+
+// handle POST and GET requests
+if (empty($_REQUEST)) {
+	if (!empty($_GET) && !empty($_POST)) {
+		$_REQUEST = array_merge($_GET, $_POST);
+	} else if (!empty($_GET)) {
+		$_REQUEST = $_GET;
+	} else if (!empty($_POST)) {
+		$_REQUEST = $_POST;
+	} else {
+		$_REQUEST = array();
+	}
+}
+
+// check parameter syntax
+foreach($vardom as $var => $dom) {
+	if (!isset($_REQUEST[$var])) {
+		$MYREQUEST[$var]=NULL;
+	} else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) {
+		$MYREQUEST[$var]=$_REQUEST[$var];
+	} else {
+		$MYREQUEST[$var]=$_REQUEST[$var]=NULL;
+	}
+}
+
+// check parameter sematics
+if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A";
+if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H";
+if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D";
+if (empty($MYREQUEST['OB']))	$MYREQUEST['OB']=OB_HOST_STATS;
+if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;
+if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';
+
+$MY_SELF=
+	"$PHP_SELF".
+	"?SCOPE=".$MYREQUEST['SCOPE'].
+	"&SORT1=".$MYREQUEST['SORT1'].
+	"&SORT2=".$MYREQUEST['SORT2'].
+	"&COUNT=".$MYREQUEST['COUNT'];
+$MY_SELF_WO_SORT=
+	"$PHP_SELF".
+	"?SCOPE=".$MYREQUEST['SCOPE'].
+	"&COUNT=".$MYREQUEST['COUNT'];
+
+// authentication needed?
+//
+if (!USE_AUTHENTICATION) {
+	$AUTHENTICATED=1;
+} else {
+	$AUTHENTICATED=0;
+	if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
+
+		if (!isset($_SERVER['PHP_AUTH_USER']) ||
+			!isset($_SERVER['PHP_AUTH_PW']) ||
+			$_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||
+			$_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
+			Header("WWW-Authenticate: Basic realm=\"APC Login\"");
+			Header("HTTP/1.0 401 Unauthorized");
+
+			echo <<<EOB
+				<html><body>
+				<h1>Rejected!</h1>
+				<big>Wrong Username or Password!</big><br/>&nbsp;<br/>&nbsp;
+				<big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
+				</body></html>
+EOB;
+			exit;
+			
+		} else {
+			$AUTHENTICATED=1;
+		}
+	}
+}
+	
+// select cache mode
+if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
+	$cache_mode='user';
+}
+// clear cache
+if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
+	apc_clear_cache($cache_mode);
+}
+
+if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) {
+	apc_delete($MYREQUEST['DU']);
+}
+
+if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {
+	echo "No cache info available.  APC does not appear to be running.";
+  exit;
+}
+
+$cache_user = apc_cache_info('user', 1);  
+$mem=apc_sma_info();
+if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; }  // Avoid division by 0 errors on a cache clear
+
+// don't cache this page
+//
+header("Cache-Control: no-store, no-cache, must-revalidate");  // HTTP/1.1
+header("Cache-Control: post-check=0, pre-check=0", false);
+header("Pragma: no-cache");                                    // HTTP/1.0
+
+function duration($ts) {
+    global $time;
+    $years = (int)((($time - $ts)/(7*86400))/52.177457);
+    $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
+    $weeks = (int)(($rem)/(7*86400));
+    $days = (int)(($rem)/86400) - $weeks*7;
+    $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
+    $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
+    $str = '';
+    if($years==1) $str .= "$years year, ";
+    if($years>1) $str .= "$years years, ";
+    if($weeks==1) $str .= "$weeks week, ";
+    if($weeks>1) $str .= "$weeks weeks, ";
+    if($days==1) $str .= "$days day,";
+    if($days>1) $str .= "$days days,";
+    if($hours == 1) $str .= " $hours hour and";
+    if($hours>1) $str .= " $hours hours and";
+    if($mins == 1) $str .= " 1 minute";
+    else $str .= " $mins minutes";
+    return $str;
+}
+
+// create graphics
+//
+function graphics_avail() {
+	return extension_loaded('gd');
+}
+if (isset($MYREQUEST['IMG']))
+{
+	if (!graphics_avail()) {
+		exit(0);
+	}
+
+	function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
+		$r=$diameter/2;
+		$w=deg2rad((360+$start+($end-$start)/2)%360);
+
+		
+		if (function_exists("imagefilledarc")) {
+			// exists only if GD 2.0.1 is avaliable
+			imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
+			imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
+			imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
+		} else {
+			imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
+			imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
+			imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
+			imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
+			imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
+			imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
+		}
+		if ($text) {
+			if ($placeindex>0) {
+				imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
+				imagestring($im,4,$diameter, $placeindex*12,$text,$color1);	
+				
+			} else {
+				imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
+			}
+		}
+	} 
+
+	function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
+		$r=$diameter/2;
+		$w=deg2rad((360+$start+($end-$start)/2)%360);
+
+		if ($placeindex>0) {
+			imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
+			imagestring($im,4,$diameter, $placeindex*12,$text,$color1);	
+				
+		} else {
+			imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
+		}
+	} 
+	
+	function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
+		global $col_black;
+		$x1=$x+$w-1;
+		$y1=$y+$h-1;
+
+		imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
+		if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
+		else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
+		imagerectangle($im, $x, $y1, $x1, $y, $color1);
+		if ($text) {
+			if ($placeindex>0) {
+			
+				if ($placeindex<16)
+				{
+					$px=5;
+					$py=$placeindex*12+6;
+					imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
+					imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
+					imagestring($im,2,$px,$py-6,$text,$color1);	
+					
+				} else {
+					if ($placeindex<31) {
+						$px=$x+40*2;
+						$py=($placeindex-15)*12+6;
+					} else {
+						$px=$x+40*2+100*intval(($placeindex-15)/15);
+						$py=($placeindex%15)*12+6;
+					}
+					imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
+					imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
+					imagestring($im,2,$px+2,$py-6,$text,$color1);	
+				}
+			} else {
+				imagestring($im,4,$x+5,$y1-16,$text,$color1);
+			}
+		}
+	}
+
+
+	$size = GRAPH_SIZE; // image size
+	if ($MYREQUEST['IMG']==3)
+		$image = imagecreate(2*$size+150, $size+10);
+	else
+		$image = imagecreate($size+50, $size+10);
+
+	$col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
+	$col_red   = imagecolorallocate($image, 0xD0, 0x60,  0x30);
+	$col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
+	$col_black = imagecolorallocate($image,   0,   0,   0);
+	imagecolortransparent($image,$col_white);
+
+	switch ($MYREQUEST['IMG']) {
+	
+	case 1:
+		$s=$mem['num_seg']*$mem['seg_size'];
+		$a=$mem['avail_mem'];
+		$x=$y=$size/2;
+		$fuzz = 0.000001;
+
+		// This block of code creates the pie chart.  It is a lot more complex than you
+		// would expect because we try to visualize any memory fragmentation as well.
+		$angle_from = 0;
+		$string_placement=array();
+		for($i=0; $i<$mem['num_seg']; $i++) {	
+			$ptr = 0;
+			$free = $mem['block_lists'][$i];
+			uasort($free, 'block_sort');
+			foreach($free as $block) {
+				if($block['offset']!=$ptr) {       // Used block
+					$angle_to = $angle_from+($block['offset']-$ptr)/$s;
+					if(($angle_to+$fuzz)>1) $angle_to = 1;
+					if( ($angle_to*360) - ($angle_from*360) >= 1) {
+						fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
+						if (($angle_to-$angle_from)>0.05) {
+							array_push($string_placement, array($angle_from,$angle_to));
+						}
+					}
+					$angle_from = $angle_to;
+				}
+				$angle_to = $angle_from+($block['size'])/$s;
+				if(($angle_to+$fuzz)>1) $angle_to = 1;
+				if( ($angle_to*360) - ($angle_from*360) >= 1) {
+					fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
+					if (($angle_to-$angle_from)>0.05) {
+						array_push($string_placement, array($angle_from,$angle_to));
+					}
+				}
+				$angle_from = $angle_to;
+				$ptr = $block['offset']+$block['size'];
+			}
+			if ($ptr < $mem['seg_size']) { // memory at the end 
+				$angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
+				if(($angle_to+$fuzz)>1) $angle_to = 1;
+				fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
+				if (($angle_to-$angle_from)>0.05) {
+					array_push($string_placement, array($angle_from,$angle_to));
+				}
+			}
+		}
+		foreach ($string_placement as $angle) {
+			text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));
+		}
+		break;
+		
+	case 2: 
+		$s=$cache['num_hits']+$cache['num_misses'];
+		$a=$cache['num_hits'];
+		
+		fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
+		fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
+		break;
+		
+	case 3:
+		$s=$mem['num_seg']*$mem['seg_size'];
+		$a=$mem['avail_mem'];
+		$x=130;
+		$y=1;
+		$j=1;
+
+		// This block of code creates the bar chart.  It is a lot more complex than you
+		// would expect because we try to visualize any memory fragmentation as well.
+		for($i=0; $i<$mem['num_seg']; $i++) {	
+			$ptr = 0;
+			$free = $mem['block_lists'][$i];
+			uasort($free, 'block_sort');
+			foreach($free as $block) {
+				if($block['offset']!=$ptr) {       // Used block
+					$h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
+					if ($h>0) {
+                                                $j++;
+						if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);
+                                                else fill_box($image,$x,$y,50,$h,$col_black,$col_red);
+                                        }
+					$y+=$h;
+				}
+				$h=(GRAPH_SIZE-5)*($block['size'])/$s;
+				if ($h>0) {
+                                        $j++;
+					if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);
+					else fill_box($image,$x,$y,50,$h,$col_black,$col_green);
+                                }
+				$y+=$h;
+				$ptr = $block['offset']+$block['size'];
+			}
+			if ($ptr < $mem['seg_size']) { // memory at the end 
+				$h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
+				if ($h > 0) {
+					fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
+				}
+			}
+		}
+		break;
+	case 4: 
+		$s=$cache['num_hits']+$cache['num_misses'];
+		$a=$cache['num_hits'];
+	        	
+		fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
+		fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
+		break;
+	
+	}
+	header("Content-type: image/png");
+	imagepng($image);
+	exit;
+}
+
+// pretty printer for byte values
+//
+function bsize($s) {
+	foreach (array('','K','M','G') as $i => $k) {
+		if ($s < 1024) break;
+		$s/=1024;
+	}
+	return sprintf("%5.1f %sBytes",$s,$k);
+}
+
+// sortable table header in "scripts for this host" view
+function sortheader($key,$name,$extra='') {
+	global $MYREQUEST, $MY_SELF_WO_SORT;
+	
+	if ($MYREQUEST['SORT1']==$key) {
+		$MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
+	}
+	return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
+
+}
+
+// create menu entry 
+function menu_entry($ob,$title) {
+	global $MYREQUEST,$MY_SELF;
+	if ($MYREQUEST['OB']!=$ob) {
+		return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>";
+	} else if (empty($MYREQUEST['SH'])) {
+		return "<li><span class=active>$title</span></li>";
+	} else {
+		return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";	
+	}
+}
+
+function put_login_link($s="Login")
+{
+	global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
+	// needs ADMIN_PASSWORD to be changed!
+	//
+	if (!USE_AUTHENTICATION) {
+		return;
+	} else if (ADMIN_PASSWORD=='password')
+	{
+		print <<<EOB
+			<a href="#" onClick="javascript:alert('You need to set a password at the top of apc.php before this will work!');return false";>$s</a>
+EOB;
+	} else if ($AUTHENTICATED) {
+		print <<<EOB
+			'{$_SERVER['PHP_AUTH_USER']}'&nbsp;logged&nbsp;in!
+EOB;
+	} else{
+		print <<<EOB
+			<a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
+EOB;
+	}
+}
+
+function block_sort($array1, $array2)
+{
+	if ($array1['offset'] > $array2['offset']) {
+		return 1;
+	} else {
+		return -1;
+	}
+}
+
+
+?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head><title>APC INFO <?php echo $host ?></title>
+<style><!--
+body { background:white; font-size:100.01%; margin:0; padding:0; }
+body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
+* html body   {font-size:0.8em}
+* html p      {font-size:0.8em}
+* html td     {font-size:0.8em}
+* html th     {font-size:0.8em}
+* html input  {font-size:0.8em}
+* html submit {font-size:0.8em}
+td { vertical-align:top }
+a { color:black; font-weight:none; text-decoration:none; }
+a:hover { text-decoration:underline; }
+div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
+
+
+div.head div.login {
+	position:absolute;
+	right: 1em;
+	top: 1.2em;
+	color:white;
+	width:6em;
+	}
+div.head div.login a {
+	position:absolute;
+	right: 0em;
+	background:rgb(119,123,180);
+	border:solid rgb(102,102,153) 2px;
+	color:white;
+	font-weight:bold;
+	padding:0.1em 0.5em 0.1em 0.5em;
+	text-decoration:none;
+	}
+div.head div.login a:hover {
+	background:rgb(193,193,244);
+	}
+
+h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
+* html h1.apc { margin-bottom:-7px; }
+h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
+h1.apc div.logo span.logo {
+	background:rgb(119,123,180);
+	color:black;
+	border-right: solid black 1px;
+	border-bottom: solid black 1px;
+	font-style:italic;
+	font-size:1em;
+	padding-left:1.2em;
+	padding-right:1.2em;
+	text-align:right;
+	}
+h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
+h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
+h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
+hr.apc {
+	background:white;
+	border-bottom:solid rgb(102,102,153) 1px;
+	border-style:none;
+	border-top:solid rgb(102,102,153) 10px;
+	height:12px;
+	margin:0;
+	margin-top:1px;
+	padding:0;
+}
+
+ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
+ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
+ol.menu a {
+	background:rgb(153,153,204);
+	border:solid rgb(102,102,153) 2px;
+	color:white;
+	font-weight:bold;
+	margin-right:0em;
+	padding:0.1em 0.5em 0.1em 0.5em;
+	text-decoration:none;
+	margin-left: 5px;
+	}
+ol.menu a.child_active {
+	background:rgb(153,153,204);
+	border:solid rgb(102,102,153) 2px;
+	color:white;
+	font-weight:bold;
+	margin-right:0em;
+	padding:0.1em 0.5em 0.1em 0.5em;
+	text-decoration:none;
+	border-left: solid black 5px;
+	margin-left: 0px;
+	}
+ol.menu span.active {
+	background:rgb(153,153,204);
+	border:solid rgb(102,102,153) 2px;
+	color:black;
+	font-weight:bold;
+	margin-right:0em;
+	padding:0.1em 0.5em 0.1em 0.5em;
+	text-decoration:none;
+	border-left: solid black 5px;
+	}
+ol.menu span.inactive {
+	background:rgb(193,193,244);
+	border:solid rgb(182,182,233) 2px;
+	color:white;
+	font-weight:bold;
+	margin-right:0em;
+	padding:0.1em 0.5em 0.1em 0.5em;
+	text-decoration:none;
+	margin-left: 5px;
+	}
+ol.menu a:hover {
+	background:rgb(193,193,244);
+	text-decoration:none;
+	}
+	
+	
+div.info {
+	background:rgb(204,204,204);
+	border:solid rgb(204,204,204) 1px;
+	margin-bottom:1em;
+	}
+div.info h2 {
+	background:rgb(204,204,204);
+	color:black;
+	font-size:1em;
+	margin:0;
+	padding:0.1em 1em 0.1em 1em;
+	}
+div.info table {
+	border:solid rgb(204,204,204) 1px;
+	border-spacing:0;
+	width:100%;
+	}
+div.info table th {
+	background:rgb(204,204,204);
+	color:white;
+	margin:0;
+	padding:0.1em 1em 0.1em 1em;
+	}
+div.info table th a.sortable { color:black; }
+div.info table tr.tr-0 { background:rgb(238,238,238); }
+div.info table tr.tr-1 { background:rgb(221,221,221); }
+div.info table td { padding:0.3em 1em 0.3em 1em; }
+div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
+div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
+div.info table td h3 {
+	color:black;
+	font-size:1.1em;
+	margin-left:-0.3em;
+	}
+
+div.graph { margin-bottom:1em }
+div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
+div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
+div.graph table td.td-0 { background:rgb(238,238,238); }
+div.graph table td.td-1 { background:rgb(221,221,221); }
+div.graph table td { padding:0.2em 1em 0.4em 1em; }
+
+div.div1,div.div2 { margin-bottom:1em; width:35em; }
+div.div3 { position:absolute; left:40em; top:1em; width:580px; }
+//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
+
+div.sorting { margin:1.5em 0em 1.5em 2em }
+.center { text-align:center }
+.aright { position:absolute;right:1em }
+.right { text-align:right }
+.ok { color:rgb(0,200,0); font-weight:bold}
+.failed { color:rgb(200,0,0); font-weight:bold}
+
+span.box {
+	border: black solid 1px;
+	border-right:solid black 2px;
+	border-bottom:solid black 2px;
+	padding:0 0.5em 0 0.5em;
+	margin-right:1em;
+}
+span.green { background:#60F060; padding:0 0.5em 0 0.5em}
+span.red { background:#D06030; padding:0 0.5em 0 0.5em }
+
+div.authneeded {
+	background:rgb(238,238,238);
+	border:solid rgb(204,204,204) 1px;
+	color:rgb(200,0,0);
+	font-size:1.2em;
+	font-weight:bold;
+	padding:2em;
+	text-align:center;
+	}
+	
+input {
+	background:rgb(153,153,204);
+	border:solid rgb(102,102,153) 2px;
+	color:white;
+	font-weight:bold;
+	margin-right:1em;
+	padding:0.1em 0.5em 0.1em 0.5em;
+	}
+//-->
+</style>
+</head>
+<body>
+<div class="head">
+	<h1 class="apc">
+		<div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div>
+		<div class="nameinfo">Opcode Cache</div>
+	</h1>
+	<div class="login">
+	<?php put_login_link(); ?>
+	</div>
+	<hr class="apc">
+</div>
+<?php
+
+
+// Display main Menu
+echo <<<EOB
+	<ol class=menu>
+	<li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
+EOB;
+echo
+	menu_entry(1,'View Host Stats'),
+	menu_entry(2,'System Cache Entries');
+if ($AUTHENTICATED) {
+	echo menu_entry(4,'Per-Directory Entries');
+}
+echo
+	menu_entry(3,'User Cache Entries'),
+	menu_entry(9,'Version Check');
+	
+if ($AUTHENTICATED) {
+	echo <<<EOB
+		<li><a class="aright" href="$MY_SELF&CC=1&OB={$MYREQUEST['OB']}" onClick="javascript:return confirm('Are you sure?');">Clear $cache_mode Cache</a></li>
+EOB;
+}
+echo <<<EOB
+	</ol>
+EOB;
+
+
+// CONTENT
+echo <<<EOB
+	<div class=content>
+EOB;
+
+// MAIN SWITCH STATEMENT 
+
+switch ($MYREQUEST['OB']) {
+
+
+
+
+
+// -----------------------------------------------
+// Host Stats
+// -----------------------------------------------
+case OB_HOST_STATS:
+	$mem_size = $mem['num_seg']*$mem['seg_size'];
+	$mem_avail= $mem['avail_mem'];
+	$mem_used = $mem_size-$mem_avail;
+	$seg_size = bsize($mem['seg_size']);
+	$req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));
+	$hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time']));
+	$miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time']));
+	$insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time']));
+	$req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));
+	$hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time']));
+	$miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time']));
+	$insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time']));
+	$apcversion = phpversion('apc');
+	$phpversion = phpversion();
+	$number_files = $cache['num_entries']; 
+    $size_files = bsize($cache['mem_size']);
+	$number_vars = $cache_user['num_entries'];
+    $size_vars = bsize($cache_user['mem_size']);
+	$i=0;
+	echo <<< EOB
+		<div class="info div1"><h2>General Cache Information</h2>
+		<table cellspacing=0><tbody>
+		<tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>
+		<tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
+EOB;
+
+	if(!empty($_SERVER['SERVER_NAME']))
+		echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
+	if(!empty($_SERVER['SERVER_SOFTWARE']))
+		echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
+
+	echo <<<EOB
+		<tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size 
+    <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)
+    </td></tr>
+EOB;
+	echo   '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';
+	echo   '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';
+	echo   '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';
+	echo <<<EOB
+		</tbody></table>
+		</div>
+
+		<div class="info div1"><h2>File Cache Information</h2>
+		<table cellspacing=0><tbody>
+		<tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>
+		<tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
+		<tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
+		<tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
+		<tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
+		<tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
+		<tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>
+		<tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
+		</tbody></table>
+		</div>
+
+		<div class="info div1"><h2>User Cache Information</h2>
+		<table cellspacing=0><tbody>
+    <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
+		<tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>
+		<tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>
+		<tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
+		<tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
+		<tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
+		<tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
+		<tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>
+
+		</tbody></table>
+		</div>
+
+		<div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
+EOB;
+
+	$j = 0;
+	foreach (ini_get_all('apc') as $k => $v) {
+		echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n";
+		$j = 1 - $j;
+	}
+
+	if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)
+		$mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
+	else
+		$mem_note = "Memory Usage";
+
+	echo <<< EOB
+		</tbody></table>
+		</div>
+
+		<div class="graph div3"><h2>Host Status Diagrams</h2>
+		<table cellspacing=0><tbody>
+EOB;
+	$size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
+	echo <<<EOB
+		<tr>
+		<td class=td-0>$mem_note</td>
+		<td class=td-1>Hits &amp; Misses</td>
+		</tr>
+EOB;
+
+	echo
+		graphics_avail() ? 
+			  '<tr>'.
+			  "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>".
+			  "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n"
+			: "",
+		'<tr>',
+		'<td class=td-0><span class="green box">&nbsp;</span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
+		'<td class=td-1><span class="green box">&nbsp;</span>Hits: ',$cache['num_hits'].sprintf(" (%.1f%%)",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n",
+		'</tr>',
+		'<tr>',
+		'<td class=td-0><span class="red box">&nbsp;</span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
+		'<td class=td-1><span class="red box">&nbsp;</span>Misses: ',$cache['num_misses'].sprintf(" (%.1f%%)",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n";
+	echo <<< EOB
+		</tr>
+		</tbody></table>
+
+		<br/>
+		<h2>Detailed Memory Usage and Fragmentation</h2>
+		<table cellspacing=0><tbody>
+		<tr>
+		<td class=td-0 colspan=2><br/>
+EOB;
+
+	// Fragementation: (freeseg - 1) / total_seg
+	$nseg = $freeseg = $fragsize = $freetotal = 0;
+	for($i=0; $i<$mem['num_seg']; $i++) {
+		$ptr = 0;
+		foreach($mem['block_lists'][$i] as $block) {
+			if ($block['offset'] != $ptr) {
+				++$nseg;
+			}
+			$ptr = $block['offset'] + $block['size'];
+                        /* Only consider blocks <5M for the fragmentation % */
+                        if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
+                        $freetotal+=$block['size'];
+		}
+		$freeseg += count($mem['block_lists'][$i]);
+	}
+	
+	if ($freeseg > 1) {
+		$frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
+	} else {
+		$frag = "0%";
+	}
+
+	if (graphics_avail()) {
+		$size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
+		echo <<<EOB
+			<img alt="" $size src="$PHP_SELF?IMG=3&$time">
+EOB;
+	}
+	echo <<<EOB
+		</br>Fragmentation: $frag
+		</td>
+		</tr>
+EOB;
+        if(isset($mem['adist'])) {
+          foreach($mem['adist'] as $i=>$v) {
+            $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
+            if($i==0) $range = "1";
+            else $range = "$cur - $nxt";
+            echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
+          }
+        }
+        echo <<<EOB
+		</tbody></table>
+		</div>
+EOB;
+		
+	break;
+
+
+// -----------------------------------------------
+// User Cache Entries
+// -----------------------------------------------
+case OB_USER_CACHE:
+	if (!$AUTHENTICATED) {
+    echo '<div class="error">You need to login to see the user values here!<br/>&nbsp;<br/>';
+		put_login_link("Login now!");
+		echo '</div>';
+		break;
+	}
+	$fieldname='info';
+	$fieldheading='User Entry Label';
+	$fieldkey='info';
+
+// -----------------------------------------------
+// System Cache Entries		
+// -----------------------------------------------
+case OB_SYS_CACHE:	
+	if (!isset($fieldname))
+	{
+		$fieldname='filename';
+		$fieldheading='Script Filename';
+		if(ini_get("apc.stat")) $fieldkey='inode';
+		else $fieldkey='filename'; 
+	}
+	if (!empty($MYREQUEST['SH']))
+	{
+		echo <<< EOB
+			<div class="info"><table cellspacing=0><tbody>
+			<tr><th>Attribute</th><th>Value</th></tr>
+EOB;
+
+		$m=0;
+		foreach($scope_list as $j => $list) {
+			foreach($cache[$list] as $i => $entry) {
+				if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;
+				foreach($entry as $k => $value) {
+					if (!$AUTHENTICATED) {
+						// hide all path entries if not logged in
+						$value=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$value);
+					}
+
+					if ($k == "num_hits") {
+						$value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
+					}
+					if ($k == 'deletion_time') {
+						if(!$entry['deletion_time']) $value = "None";
+					}
+					echo
+						"<tr class=tr-$m>",
+						"<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>",
+						"<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : htmlspecialchars($value, ENT_QUOTES, 'UTF-8'),"</td>",
+						"</tr>";
+					$m=1-$m;
+				}
+				if($fieldkey=='info') {
+					echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>";
+					$output = var_export(apc_fetch($entry[$fieldkey]),true);
+					echo htmlspecialchars($output, ENT_QUOTES, 'UTF-8');
+					echo "</pre></td></tr>\n";
+				}
+				break;
+			}
+		}
+
+		echo <<<EOB
+			</tbody></table>
+			</div>
+EOB;
+		break;
+	}
+
+	$cols=6;
+	echo <<<EOB
+		<div class=sorting><form>Scope:
+		<input type=hidden name=OB value={$MYREQUEST['OB']}>
+		<select name=SCOPE>
+EOB;
+	echo 
+		"<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
+		"<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
+		"</select>",
+		", Sorting:<select name=SORT1>",
+		"<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>",
+		"<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>",
+		"<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>",
+		"<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>",
+		"<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>",
+		"<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>",
+		"<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>";
+	if($fieldname=='info') echo
+		"<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>";
+	echo 
+		'</select>',
+		'<select name=SORT2>',
+		'<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
+		'<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
+		'</select>',
+		'<select name=COUNT onChange="form.submit()">',
+		'<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
+		'<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
+		'<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
+		'<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
+		'<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
+		'<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
+		'<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
+		'<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
+		'</select>',
+    '&nbsp; Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
+		'&nbsp;<input type=submit value="GO!">',
+		'</form></div>';
+
+  if (isset($MYREQUEST['SEARCH'])) {
+   // Don't use preg_quote because we want the user to be able to specify a
+   // regular expression subpattern.
+   $MYREQUEST['SEARCH'] = '/'.str_replace('/', '\\/', $MYREQUEST['SEARCH']).'/i';
+   if (preg_match($MYREQUEST['SEARCH'], 'test') === false) {
+     echo '<div class="error">Error: enter a valid regular expression as a search query.</div>';
+     break;
+   }
+  }
+
+  echo
+		'<div class="info"><table cellspacing=0><tbody>',
+		'<tr>',
+		'<th>',sortheader('S',$fieldheading,  "&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('H','Hits',         "&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('Z','Size',         "&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('C','Created at',   "&OB=".$MYREQUEST['OB']),'</th>';
+
+	if($fieldname=='info') {
+		$cols+=2;
+		 echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
+	}
+	echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
+
+	// builds list with alpha numeric sortable keys
+	//
+	$list = array();
+	foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
+		switch($MYREQUEST['SORT1']) {
+			case 'A': $k=sprintf('%015d-',$entry['access_time']); 	break;
+			case 'H': $k=sprintf('%015d-',$entry['num_hits']); 		break;
+			case 'Z': $k=sprintf('%015d-',$entry['mem_size']); 		break;
+			case 'M': $k=sprintf('%015d-',$entry['mtime']);			break;
+			case 'C': $k=sprintf('%015d-',$entry['creation_time']);	break;
+			case 'T': $k=sprintf('%015d-',$entry['ttl']);			break;
+			case 'D': $k=sprintf('%015d-',$entry['deletion_time']);	break;
+			case 'S': $k='';										break;
+		}
+		if (!$AUTHENTICATED) {
+			// hide all path entries if not logged in
+			$list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','*hidden*/',$entry);
+		} else {
+			$list[$k.$entry[$fieldname]]=$entry;
+		}
+	}
+
+	if ($list) {
+		
+		// sort list
+		//
+		switch ($MYREQUEST['SORT2']) {
+			case "A":	krsort($list);	break;
+			case "D":	ksort($list);	break;
+		}
+		
+		// output list
+		$i=0;
+		foreach($list as $k => $entry) {
+      if(!$MYREQUEST['SEARCH'] || preg_match($MYREQUEST['SEARCH'], $entry[$fieldname]) != 0) {  
+        $field_value = htmlentities(strip_tags($entry[$fieldname],''), ENT_QUOTES, 'UTF-8');
+        echo
+          '<tr class=tr-',$i%2,'>',
+          "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$field_value,'</a></td>',
+          '<td class="td-n center">',$entry['num_hits'],'</td>',
+          '<td class="td-n right">',$entry['mem_size'],'</td>',
+          '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>',
+          '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>',
+          '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>';
+
+        if($fieldname=='info') {
+          if($entry['ttl'])
+            echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
+          else
+            echo '<td class="td-n center">None</td>';
+        }
+        if ($entry['deletion_time']) {
+
+          echo '<td class="td-last center">', date(DATE_FORMAT,$entry['deletion_time']), '</td>';
+        } else if ($MYREQUEST['OB'] == OB_USER_CACHE) {
+
+          echo '<td class="td-last center">';
+          echo '[<a href="', $MY_SELF, '&OB=', $MYREQUEST['OB'], '&DU=', urlencode($entry[$fieldkey]), '">Delete Now</a>]';
+          echo '</td>';
+        } else {
+          echo '<td class="td-last center"> &nbsp; </td>';
+        }
+        echo '</tr>';
+        $i++;
+        if ($i == $MYREQUEST['COUNT'])
+          break;
+      }
+		}
+		
+	} else {
+		echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
+	}
+	echo <<< EOB
+		</tbody></table>
+EOB;
+
+	if ($list && $i < count($list)) {
+		echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
+	}
+
+	echo <<< EOB
+		</div>
+EOB;
+	break;
+
+
+// -----------------------------------------------
+// Per-Directory System Cache Entries
+// -----------------------------------------------
+case OB_SYS_CACHE_DIR:	
+	if (!$AUTHENTICATED) {
+		break;
+	}
+
+	echo <<<EOB
+		<div class=sorting><form>Scope:
+		<input type=hidden name=OB value={$MYREQUEST['OB']}>
+		<select name=SCOPE>
+EOB;
+	echo 
+		"<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
+		"<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
+		"</select>",
+		", Sorting:<select name=SORT1>",
+		"<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>",
+		"<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>",
+		"<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>",
+		"<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>",
+		"<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>",
+		"<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>",
+		'</select>',
+		'<select name=SORT2>',
+		'<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
+		'<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
+		'</select>',
+		'<select name=COUNT onChange="form.submit()">',
+		'<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
+		'<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
+		'<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
+		'<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
+		'<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
+		'<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
+		'<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
+		'<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
+		'</select>',
+		", Group By Dir Level:<select name=AGGR>",
+		"<option value='' selected>None</option>";
+		for ($i = 1; $i < 10; $i++)
+			echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>";
+		echo '</select>',
+		'&nbsp;<input type=submit value="GO!">',
+		'</form></div>',
+
+		'<div class="info"><table cellspacing=0><tbody>',
+		'<tr>',
+		'<th>',sortheader('S','Directory Name',	"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('H','Total Hits',	"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('Z','Total Size',	"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('C','Avg. Hits',	"&OB=".$MYREQUEST['OB']),'</th>',
+		'<th>',sortheader('A','Avg. Size',	"&OB=".$MYREQUEST['OB']),'</th>',
+		'</tr>';
+
+	// builds list with alpha numeric sortable keys
+	//
+	$tmp = $list = array();
+	foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {
+		$n = dirname($entry['filename']);
+		if ($MYREQUEST['AGGR'] > 0) {
+			$n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n);
+		}
+		if (!isset($tmp[$n])) {
+			$tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
+		}
+		$tmp[$n]['hits'] += $entry['num_hits'];
+		$tmp[$n]['size'] += $entry['mem_size'];
+		++$tmp[$n]['ents'];
+	}
+
+	foreach ($tmp as $k => $v) {
+		switch($MYREQUEST['SORT1']) {
+			case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;
+			case 'T': $kn=sprintf('%015d-',$v['ents']);		break;
+			case 'H': $kn=sprintf('%015d-',$v['hits']);		break;
+			case 'Z': $kn=sprintf('%015d-',$v['size']);		break;
+			case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;
+			case 'S': $kn = $k;					break;
+		}
+		$list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
+	}
+
+	if ($list) {
+		
+		// sort list
+		//
+		switch ($MYREQUEST['SORT2']) {
+			case "A":	krsort($list);	break;
+			case "D":	ksort($list);	break;
+		}
+		
+		// output list
+		$i = 0;
+		foreach($list as $entry) {
+			echo
+				'<tr class=tr-',$i%2,'>',
+				"<td class=td-0>",$entry[0],'</a></td>',
+				'<td class="td-n center">',$entry[1],'</td>',
+				'<td class="td-n center">',$entry[2],'</td>',
+				'<td class="td-n center">',$entry[3],'</td>',
+				'<td class="td-n center">',round($entry[2] / $entry[1]),'</td>',
+				'<td class="td-n center">',round($entry[3] / $entry[1]),'</td>',
+				'</tr>';
+
+			if (++$i == $MYREQUEST['COUNT']) break;
+		}
+		
+	} else {
+		echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
+	}
+	echo <<< EOB
+		</tbody></table>
+EOB;
+
+	if ($list && $i < count($list)) {
+		echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
+	}
+
+	echo <<< EOB
+		</div>
+EOB;
+	break;
+
+// -----------------------------------------------
+// Version check
+// -----------------------------------------------
+case OB_VERSION_CHECK:
+	echo <<<EOB
+		<div class="info"><h2>APC Version Information</h2>
+		<table cellspacing=0><tbody>
+		<tr>
+		<th></th>
+		</tr>
+EOB;
+  if (defined('PROXY')) {
+    $ctxt = stream_context_create( array( 'http' => array( 'proxy' => PROXY, 'request_fulluri' => True ) ) );
+    $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss", False, $ctxt);
+  } else {
+    $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
+  }
+	if (!$rss) {
+		echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
+	} else {
+		$apcversion = phpversion('apc');
+
+		preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
+		echo '<tr class="tr-0 center"><td>';
+		if (version_compare($apcversion, $match[1], '>=')) {
+			echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>';
+			$i = 3;
+		} else {
+			echo '<div class="failed">You are running an older version of APC ('.$apcversion.'), 
+				newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'">
+				http://pecl.php.net/package/APC/'.$match[1].'</a>
+				</div>';
+			$i = -1;
+		}
+		echo '</td></tr>';
+		echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
+
+		preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
+		next($match[2]); next($match[2]);
+
+		while (list(,$v) = each($match[2])) {
+			list(,$ver) = explode(' ', $v, 2);
+			if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
+				break;
+			} else if (!$i--) {
+				break;
+			}
+			echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v, ENT_QUOTES, 'UTF-8')."</a></b><br><blockquote>";
+			echo nl2br(htmlspecialchars(current($match[2]), ENT_QUOTES, 'UTF-8'))."</blockquote>";
+			next($match[2]);
+		}
+		echo '</td></tr>';
+	}
+	echo <<< EOB
+		</tbody></table>
+		</div>
+EOB;
+	break;
+
+}
+
+echo <<< EOB
+	</div>
+EOB;
+
+?>
+
+<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
+</body>
+</html>

+ 1 - 0
config/benchmark_profile

@@ -3,6 +3,7 @@ export RESIN_HOME=~/FrameworkBenchmarks/installs/resin-4.0.34
 export GRAILS_HOME=~/FrameworkBenchmarks/installs/grails-2.1.1
 export VERTX_HOME=~/FrameworkBenchmarks/installs/vert.x-1.3.1.final
 export GOROOT=~/FrameworkBenchmarks/installs/go
+export GOPATH=~/FrameworkBenchmarks/go:~/FrameworkBenchmarks/webgo:$GOROOT
 export TOMCAT_HOME=~/FrameworkBenchmarks/installs/apache-tomcat-7.0.35
 export NODE_HOME=~/FrameworkBenchmarks/installs/node-v0.10.2-linux-x64
 export PLAY_HOME=~/FrameworkBenchmarks/installs/play-2.1.1

+ 8 - 0
config/erlang.list

@@ -0,0 +1,8 @@
+deb http://binaries.erlang-solutions.com/debian quantal contrib
+deb http://binaries.erlang-solutions.com/debian precise contrib
+deb http://binaries.erlang-solutions.com/debian oneiric contrib
+deb http://binaries.erlang-solutions.com/debian natty contrib
+deb http://binaries.erlang-solutions.com/debian maverick contrib
+deb http://binaries.erlang-solutions.com/debian lucid contrib
+
+deb http://binaries.erlang-solutions.com/debian squeeze contrib

BIN
finagle/.cache


+ 34 - 0
finagle/.classpath

@@ -0,0 +1,34 @@
+<classpath>
+  <classpathentry output="target/scala-2.10/classes" path="src/main/scala" kind="src"></classpathentry>
+  <classpathentry output="target/scala-2.10/classes" path="src/main/java" kind="src"></classpathentry>
+  <classpathentry output="target/scala-2.10/test-classes" path="src/test/scala" kind="src"></classpathentry>
+  <classpathentry output="target/scala-2.10/test-classes" path="src/test/java" kind="src"></classpathentry>
+  <classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/finagle-http_2.10/jars/finagle-http_2.10-6.2.1.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/finagle-core_2.10/jars/finagle-core_2.10-6.2.1.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/io.netty/netty/bundles/netty-3.5.12.Final.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-core_2.10/jars/util-core_2.10-6.2.4.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-collection_2.10/jars/util-collection_2.10-6.2.4.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/commons-collections/commons-collections/jars/commons-collections-3.2.1.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-hashing_2.10/jars/util-hashing_2.10-6.2.4.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-jvm_2.10/jars/util-jvm_2.10-6.2.4.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-logging_2.10/jars/util-logging_2.10-6.2.4.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-app_2.10/jars/util-app_2.10-6.2.4.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-codec_2.10/jars/util-codec_2.10-6.2.4.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/commons-codec/commons-codec/jars/commons-codec-1.5.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/commons-lang/commons-lang/jars/commons-lang-2.6.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.fasterxml.jackson.module/jackson-module-scala_2.10/jars/jackson-module-scala_2.10-2.1.3.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.fasterxml.jackson.core/jackson-core/jars/jackson-core-2.1.2.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.fasterxml.jackson.core/jackson-annotations/jars/jackson-annotations-2.1.2.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.fasterxml.jackson.core/jackson-databind/jars/jackson-databind-2.1.2.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.thoughtworks.paranamer/paranamer/jars/paranamer-2.3.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.google.guava/guava/jars/guava-13.0.1.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.10.0.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/com.typesafe.slick/slick_2.10/jars/slick_2.10-1.0.0.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/org.slf4j/slf4j-api/jars/slf4j-api-1.6.4.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/mysql/mysql-connector-java/jars/mysql-connector-java-5.1.24.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/commons-dbcp/commons-dbcp/jars/commons-dbcp-1.4.jar" kind="lib"></classpathentry>
+  <classpathentry path="/home/dknapp/.ivy2/cache/commons-pool/commons-pool/jars/commons-pool-1.5.4.jar" kind="lib"></classpathentry>
+  <classpathentry path="org.eclipse.jdt.launching.JRE_CONTAINER" kind="con"></classpathentry>
+  <classpathentry path="bin" kind="output"></classpathentry>
+</classpath>

+ 3 - 0
finagle/.gitignore

@@ -0,0 +1,3 @@
+/project/.*
+/project/target
+/target

+ 12 - 0
finagle/.project

@@ -0,0 +1,12 @@
+<projectDescription>
+  <name>finagle</name>
+  <buildSpec>
+    <buildCommand>
+      <name>org.scala-ide.sdt.core.scalabuilder</name>
+    </buildCommand>
+  </buildSpec>
+  <natures>
+    <nature>org.scala-ide.sdt.core.scalanature</nature>
+    <nature>org.eclipse.jdt.core.javanature</nature>
+  </natures>
+</projectDescription>

+ 0 - 0
finagle/__init__.py


+ 24 - 0
finagle/benchmark_config

@@ -0,0 +1,24 @@
+{
+    "framework" : "finagle",
+    "tests" : [{
+        "default" : {
+            "setup_file" : "setup",
+            "json_url" : "/json",
+            "db_url" : "/db",
+            "query_url" : "/db?queries=",
+            "port": 8080,
+            "sort": 44
+            }
+        },
+        {
+        "future-pool" : {
+            "setup_file" : "setup",
+            "db_url" : "/pooling",
+            "query_url" : "/pooling?queries=",
+            "port": 8080,
+            "sort": 46
+            }
+        }
+        ]
+
+}

+ 15 - 0
finagle/build.sbt

@@ -0,0 +1,15 @@
+name := "finagle"
+
+organization := "com.falmarri"
+
+scalaVersion := "2.10.0"
+
+version := "1.0"
+
+libraryDependencies ++= Seq(
+                "com.twitter" % "finagle-http_2.10" % "6.+",
+                "com.fasterxml.jackson.module" % "jackson-module-scala_2.10" % "2.+",
+                "com.typesafe.slick" % "slick_2.10" % "1.0.0",
+                "mysql" % "mysql-connector-java" % "5.1.24",
+                "commons-dbcp" % "commons-dbcp" % "1.+"
+                )

+ 1 - 0
finagle/project/build.properties

@@ -0,0 +1 @@
+sbt.version=0.12.1

+ 1 - 0
finagle/sbt

@@ -0,0 +1 @@
+java  -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=384M -Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy -jar `dirname $0`/sbt-launch.jar "$@"

BIN
finagle/sbt-launch.jar


+ 29 - 0
finagle/setup.py

@@ -0,0 +1,29 @@
+
+import subprocess
+import sys
+import time
+import os
+
+def start(args=None):
+
+
+    
+    subprocess.check_call("./sbt update compile", shell=True, cwd="finagle")
+    subprocess.Popen("./sbt -Ddb.host=" + args.database_host + " run", cwd="finagle", shell=True)
+    time.sleep(5)
+    return 0
+
+
+
+def stop():
+  p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+  out, err = p.communicate()
+  for line in out.splitlines():
+    if 'sbt' in line:
+      try:
+        pid = int(line.split(None, 2)[1])
+        os.kill(pid, 9)
+      except OSError:
+        pass
+  
+  return 0

+ 133 - 0
finagle/src/main/scala/com/falmarri/finagle/Finagle.scala

@@ -0,0 +1,133 @@
+package com.falmarri.finagle
+
+import com.twitter.finagle.http.{ Request, Response, RichHttp, Http }
+import com.twitter.finagle.builder.{ Server, ServerBuilder }
+import java.net.InetSocketAddress
+import com.twitter.finagle.http.service.RoutingService
+import com.twitter.finagle.Service
+import com.twitter.util.Future
+import org.jboss.netty.buffer.ChannelBuffers.copiedBuffer
+import org.jboss.netty.handler.codec.http.DefaultHttpResponse
+import org.jboss.netty.handler.codec.http.HttpResponseStatus
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.module.scala.DefaultScalaModule
+import scala.language.experimental.macros
+import scala.reflect.macros.Context
+import java.io.StringWriter
+import org.jboss.netty.util.CharsetUtil.UTF_8
+import scala.slick.driver.MySQLDriver.simple._
+import scala.util.Random
+import org.apache.commons.dbcp.BasicDataSource
+import javax.sql.DataSource
+import com.twitter.util.FuturePool
+import java.util.concurrent.Executors
+
+case class World(id: Int, randomNumber: Int)
+
+object Worlds extends Table[World]("World") {
+  def id = column[Int]("id", O.PrimaryKey)
+  def randomNumber = column[Int]("randomNumber")
+  def * = id ~ randomNumber <> (World, World.unapply _)
+  
+}
+
+
+object FinagleBenchmark extends App {
+
+//  def serialize[T](value: T): String = macro serializeImpl[T]
+//
+//  def serializeImpl[T](c: Context)(value: c.Expr[T]): c.Expr[String] = {
+//    import java.io.StringWriter
+//    import c.universe._
+//    c.Expr[String](reify {
+//          val writer = new StringWriter()
+//          mapper.writeValue(writer, value.splice)
+//          writer.toString()
+//    }.tree)
+//  }
+  val dataSource: DataSource = {
+    val ds = new BasicDataSource
+    ds.setDriverClassName("com.mysql.jdbc.Driver")
+    ds.setUsername("benchmarkdbuser")
+    ds.setPassword("benchmarkdbpass")
+    ds.setMaxActive(20);
+    ds.setMaxIdle(10);
+    ds.setInitialSize(20);
+    //ds.setValidationQuery("SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS")
+    //new java.io.File("target").mkdirs // ensure that folder for database exists
+    ds.setUrl("jdbc:mysql://" + System.getProperty("db.host", "localhost") + ":3306/hello_world")
+    ds
+  }
+  
+  val database = Database.forDataSource(dataSource)
+  
+  def serialize(value: Any) = {
+    val writer = new StringWriter()
+    mapper.writeValue(writer, value)
+    writer.toString()
+  }
+
+  val mapper = new ObjectMapper()
+  mapper.registerModule(DefaultScalaModule)
+
+  val json = new Service[Request, Response] {
+    def apply(req: Request): Future[Response] ={
+      val resp = Response()
+      resp.setContent(copiedBuffer(serialize(Map("message" -> "Hello, World!")), UTF_8))
+      resp.setContentTypeJson
+      Future.value(resp)
+    }
+
+  }
+  
+  val diskIoFuturePool = FuturePool(Executors.newFixedThreadPool(8))
+ 
+
+  val db = new Service[Request, Response] {
+    def apply(req: Request): Future[Response] = {
+      val n = req.params.getIntOrElse("queries", 1)
+      val resp = Response()
+      database withSession {implicit session: Session =>
+        val rand = new Random()
+        val q = Query(Worlds).where(_.id inSet( for (i <- 0 to n) yield rand.nextInt(10000)))
+        resp.setContent(copiedBuffer(serialize(if (n == 1) q.first else q.list), UTF_8))
+        resp.setContentTypeJson
+        Future.value(resp)
+      }
+    }
+  }
+  
+  val poolingdb = new Service[Request, Response] {
+    def apply(req: Request): Future[Response] = {
+      val n = req.params.getIntOrElse("queries", 1)
+      val query = {
+	      val resp = Response()
+	      database withSession {implicit session: Session =>
+	        val rand = new Random()
+	        val q = Query(Worlds).where(_.id inSet( for (i <- 0 to n) yield rand.nextInt(10000)))
+	        resp.setContent(copiedBuffer(serialize(if (n == 1) q.first else q.list), UTF_8))
+	        resp.setContentTypeJson
+	        resp
+	      	}
+      	}
+      diskIoFuturePool(query)
+    }
+  }
+  
+
+  val service =
+    RoutingService byPath {
+
+      case "/json" => json
+      case "/db" => db
+      case "/pooling" => poolingdb
+
+    }
+
+  val server: Server = ServerBuilder()
+    .codec(RichHttp[Request](Http()))
+    .bindTo(new InetSocketAddress(8080))
+    .name("finagle")
+    .build(service)
+
+}

+ 14 - 14
framework_test.py

@@ -16,29 +16,29 @@ class FrameworkTest:
     echo ""
     echo "---------------------------------------------------------"
     echo " Running Primer {name}"
-    echo " wrk -r 1000 -c 8 -t 8 http://{server_host}:{port}{url}"
+    echo " wrk -d 60 -c 8 -t 8 http://{server_host}:{port}{url}"
     echo "---------------------------------------------------------"
     echo ""
-    wrk -r 1000 -c 8 -t 8 http://{server_host}:{port}{url}
+    wrk -d 5 -c 8 -t 8 http://{server_host}:{port}{url}
     sleep 5
     
     echo ""
     echo "---------------------------------------------------------"
     echo " Running Warmup {name}"
-    echo " wrk -r {runs} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}"
+    echo " wrk -d {duration} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}"
     echo "---------------------------------------------------------"
     echo ""
-    wrk -r {runs} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}
+    wrk -d {duration} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}
     sleep 5
     for c in {interval}
     do
       echo ""
       echo "---------------------------------------------------------"
       echo " Concurrency: $c for {name}"
-      echo " wrk -n {runs} -c $c -t $(($c>{max_threads}?{max_threads}:$c)) http://{server_host}:{port}{url}"
+      echo " wrk -d {duration} -c $c -t $(($c>{max_threads}?{max_threads}:$c)) http://{server_host}:{port}{url}"
       echo "---------------------------------------------------------"
       echo ""
-      wrk -r {runs} -c "$c" -t "$(($c>{max_threads}?{max_threads}:$c))" http://{server_host}:{port}{url}
+      wrk -d {duration} -c "$c" -t "$(($c>{max_threads}?{max_threads}:$c))" http://{server_host}:{port}{url}
       sleep 2
     done
   """
@@ -49,29 +49,29 @@ class FrameworkTest:
     echo ""
     echo "---------------------------------------------------------"
     echo " Running Primer {name}"
-    echo " wrk -r 1000 -c 8 -t 8 http://{server_host}:{port}{url}2"
+    echo " wrk -d 5 -c 8 -t 8 http://{server_host}:{port}{url}2"
     echo "---------------------------------------------------------"
     echo ""
-    wrk -r 1000 -c 8 -t 8 http://{server_host}:{port}{url}2
+    wrk -d 5 -c 8 -t 8 http://{server_host}:{port}{url}2
     sleep 5
     
     echo ""
     echo "---------------------------------------------------------"
     echo " Running Warmup {name}"
-    echo " wrk -r {runs} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}2"
+    echo " wrk -d {duration} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}2"
     echo "---------------------------------------------------------"
     echo ""
-    wrk -r {runs} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}2
+    wrk -d {duration} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}2
     sleep 5
     for c in {interval}
     do
       echo ""
       echo "---------------------------------------------------------"
       echo " Queries: $c for {name}"
-      echo " wrk -r {runs} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}$c"
+      echo " wrk -d {duration} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}$c"
       echo "---------------------------------------------------------"
       echo ""
-      wrk -r {runs} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}"$c"
+      wrk -d {duration} -c {max_concurrency} -t {max_threads} http://{server_host}:{port}{url}"$c"
       sleep 2
     done
   """
@@ -320,7 +320,7 @@ class FrameworkTest:
   ############################################################
   def __generate_concurrency_script(self, url, port):
     return self.concurrency_template.format(max_concurrency=self.benchmarker.max_concurrency, 
-      max_threads=self.benchmarker.max_threads, name=self.name, runs=self.benchmarker.number_of_runs, 
+      max_threads=self.benchmarker.max_threads, name=self.name, duration=self.benchmarker.duration, 
       interval=" ".join("{}".format(item) for item in self.benchmarker.concurrency_levels), 
       server_host=self.benchmarker.server_host, port=port, url=url)
   ############################################################
@@ -335,7 +335,7 @@ class FrameworkTest:
   ############################################################
   def __generate_query_script(self, url, port):
     return self.query_template.format(max_concurrency=self.benchmarker.max_concurrency, 
-      max_threads=self.benchmarker.max_threads, name=self.name, runs=self.benchmarker.number_of_runs, 
+      max_threads=self.benchmarker.max_threads, name=self.name, duration=self.benchmarker.duration, 
       interval=" ".join("{}".format(item) for item in self.benchmarker.query_intervals), 
       server_host=self.benchmarker.server_host, port=port, url=url)
   ############################################################

+ 2 - 0
go/benchmark_config

@@ -4,6 +4,8 @@
     "default": {
       "setup_file": "setup",
       "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
       "port": 8080,
       "sort": 27
     }

+ 0 - 0
go/bin/.gitkeep


+ 0 - 25
go/hello.go

@@ -1,25 +0,0 @@
-package main
-
-import (
-	"encoding/json"
-	"net/http"
-	"runtime"
-	"strconv"
-)
-
-type MessageStruct struct {
-	Message string
-}
-
-func hello(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-Type", "application/javascript")
-	j, _ := json.Marshal(&MessageStruct{"Hello, world"})
-	w.Header().Set("Content-Length", strconv.Itoa(len(j)))
-	w.Write(j)
-}
-
-func main() {
-	runtime.GOMAXPROCS(runtime.NumCPU())
-	http.HandleFunc("/json", hello)
-	http.ListenAndServe(":8080", nil)
-}

+ 0 - 0
go/pkg/.gitkeep


+ 6 - 4
go/setup.py

@@ -1,17 +1,19 @@
 import subprocess
 import sys
 import os
+import setup_util
 
 def start(args):
-  
-  subprocess.Popen("go run hello.go".rsplit(" "), cwd="go")
+  setup_util.replace_text("go/src/hello/hello.go", "tcp\(.*:3306\)", "tcp(" + args.database_host + ":3306)")
+  subprocess.call("go get ./...", shell=True, cwd="go") 
+  subprocess.Popen("go run src/hello/hello.go".rsplit(" "), cwd="go")
   return 0
 def stop():
   
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()
   for line in out.splitlines():
-    if 'a.out' in line:
+    if 'hello' in line:
       pid = int(line.split(None, 2)[1])
       os.kill(pid, 9)
-  return 0
+  return 0

+ 67 - 0
go/src/hello/hello.go

@@ -0,0 +1,67 @@
+package main
+
+import (
+	"encoding/json"
+	"net/http"
+	"runtime"
+	"strconv"
+
+	"database/sql"
+	_ "github.com/go-sql-driver/mysql"
+	"log"
+	"math/rand"
+)
+
+const DB_ROWS = 10000
+
+var db *sql.DB
+var q *sql.Stmt
+
+type MessageStruct struct {
+	Message string
+}
+type World struct {
+	Id           uint16 `json:"id"`
+	RandomNumber uint16 `json:"randomNumber"`
+}
+
+func hello(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/javascript")
+	j, _ := json.Marshal(&MessageStruct{"Hello, world"})
+	w.Header().Set("Content-Length", strconv.Itoa(len(j)))
+	w.Write(j)
+}
+
+func dbh(w http.ResponseWriter, r *http.Request) {
+	qnum := 1
+	qnumString := r.URL.Query().Get("queries")
+	if len(qnumString) != 0 {
+		qnum, _ = strconv.Atoi(qnumString)
+	}
+	ww := make([]World, qnum)
+	for i := 0; i < qnum; i++ {
+		q.QueryRow(rand.Intn(DB_ROWS)+1).Scan(&ww[i].Id, &ww[i].RandomNumber)
+	}
+	w.Header().Set("Content-Type", "application/javascript")
+	j, _ := json.Marshal(ww)
+	w.Header().Set("Content-Length", strconv.Itoa(len(j)))
+	w.Write(j)
+}
+
+func main() {
+	var err error
+	runtime.GOMAXPROCS(runtime.NumCPU())
+
+	db, err = sql.Open("mysql", "benchmarkdbuser:benchmarkdbpass@tcp(localhost:3306)/hello_world?charset=utf8")
+	if err != nil {
+		log.Fatalf("Error opening database: %s", err)
+	}
+	q, err = db.Prepare("SELECT * FROM World where id = ?;")
+	if err != nil {
+		log.Fatalf("Error preparing statement: %s", err)
+	}
+
+	http.HandleFunc("/json", hello)
+	http.HandleFunc("/db", dbh)
+	http.ListenAndServe(":8080", nil)
+}

+ 3 - 1
http-kit/hello/project.clj

@@ -6,8 +6,10 @@
                  [ring/ring-json "0.2.0"]
                  [org.clojure/tools.cli "0.2.1"]
                  [http-kit/dbcp "0.1.0"]
-                 [http-kit "2.0.0-RC4"]
+                 [http-kit "2.0.0"]
                  [log4j "1.2.15" :exclusions [javax.mail/mail javax.jms/jms com.sun.jdmk/jmxtools com.sun.jmx/jmxri]]
                  [mysql/mysql-connector-java "5.1.6"]]
   :main hello.handler
+  :aot [hello.handler]
+  :uberjar-name "http-kit-standalone.jar"
   :profiles {:dev {:dependencies [[ring-mock "0.1.3"]]}})

+ 6 - 5
http-kit/hello/src/hello/handler.clj

@@ -38,20 +38,21 @@
   (route/not-found "Not Found"))
 
 
-(defn start-server [{:keys [port worker db-host]}]
+(defn start-server [{:keys [port db-host]}]
   (db/use-database! (str "jdbc:mysql://" db-host "/hello_world")
                     "benchmarkdbuser"
                     "benchmarkdbpass")
   ;; Format responses as JSON
-  (let [handler (wrap-json-response app-routes)]
-    (run-server handler {:port port :worker worker})))
-
+  (let [handler (wrap-json-response app-routes)
+        cpu (.availableProcessors (Runtime/getRuntime))]
+    ;; double worker threads should increase database access performance
+    (run-server handler {:port port :thread (* 2 cpu)})
+    (println (str "http-kit server listens at :" port))))
 
 (defn -main [& args]
   (let [[options _ banner]
         (cli args
              ["-p" "--port" "Port to listen" :default 8080 :parse-fn to-int]
-             ["--worker" "Http worker thread count" :default 6 :parse-fn to-int]
              ["--db-host" "MySQL database host" :default "localhost"]
              ["--[no-]help" "Print this help"])]
     (when (:help options) (println banner) (System/exit 0))

+ 5 - 2
http-kit/setup.py

@@ -7,8 +7,11 @@ def start(args):
 
   try:
     subprocess.check_call("lein deps", shell=True, cwd="http-kit/hello")
-    # lein run -- --help for more options
-    command = "lein run -- --db-host " + args.database_host
+    # pack all dependencies into a single jar: target/http-kit-standalone.jar
+    subprocess.check_call("lein uberjar", shell=True, cwd="http-kit/hello")
+    # -server is much faster
+    # 'lein run' passes '-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1' which make it starts fast, but runs slow
+    command = "java -server -jar target/http-kit-standalone.jar --db-host " + args.database_host
     subprocess.Popen(command, shell=True, cwd="http-kit/hello")
     return 0
   except subprocess.CalledProcessError:

+ 22 - 12
installer.py

@@ -22,9 +22,10 @@ class Installer:
     #######################################
     self.__run_command("sudo apt-get update", True)
     self.__run_command("sudo apt-get upgrade", True)    
-    self.__run_command("sudo apt-get install build-essential libpcre3 libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev python-software-properties unzip git-core libcurl4-openssl-dev libbz2-dev libmysqlclient-dev mongodb-clients libreadline6-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev libgdbm-dev ncurses-dev automake libffi-dev htop libtool bison libevent-dev libgstreamer-plugins-base0.10-0 libgstreamer0.10-0 liborc-0.4-0 libwxbase2.8-0 libwxgtk2.8-0", True)
+    self.__run_command("sudo apt-get install build-essential libpcre3 libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev python-software-properties unzip git-core libcurl4-openssl-dev libbz2-dev libmysqlclient-dev mongodb-clients libreadline6-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev libgdbm-dev ncurses-dev automake libffi-dev htop libtool bison libevent-dev libgstreamer-plugins-base0.10-0 libgstreamer0.10-0 liborc-0.4-0 libwxbase2.8-0 libwxgtk2.8-0 libgnutls-dev libjson0-dev", True)
 
     self.__run_command("cp ../config/benchmark_profile ../../.bash_profile")
+    self.__run_command("sudo sh -c \"echo '*               soft    nofile          4096' >> /etc/security/limits.conf\"")
 
     #######################################
     # Languages
@@ -33,9 +34,11 @@ class Installer:
     #
     # Erlang
     #
-    self.__run_command("curl -klO https://elearning.erlang-solutions.com/couchdb//rbingen_adapter//package_R16B_precise64_1361901944/esl-erlang_16.b-1~ubuntu~precise_amd64.deb")
-    self.__run_command("sudo /usr/bin/dpkg --install esl-erlang_16.b-1~ubuntu~precise_amd64.deb")
-
+    self.__run_command("sudo cp ../config/erlang.list /etc/apt/sources.list.d/erlang.list")
+    self.__run_command("wget -O - http://binaries.erlang-solutions.com/debian/erlang_solutions.asc | sudo apt-key add -")
+    self.__run_command("sudo apt-get update")
+    self.__run_command("sudo apt-get install esl-erlang", True)
+    
     #
     # Python
     #
@@ -84,7 +87,7 @@ class Installer:
     # go
     #
 
-    self.__run_command("curl http://go.googlecode.com/files/go1.0.3.linux-amd64.tar.gz | tar xvz")
+    self.__run_command("curl http://go.googlecode.com/files/go1.1beta1.linux-amd64.tar.gz | tar xvz")
 
     #
     # php
@@ -92,7 +95,7 @@ class Installer:
 
     self.__run_command("wget --trust-server-names http://www.php.net/get/php-5.4.13.tar.gz/from/us1.php.net/mirror")
     self.__run_command("tar xvf php-5.4.13.tar.gz")
-    self.__run_command("./configure --with-pdo-mysql --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data", cwd="php-5.4.13")
+    self.__run_command("./configure --with-pdo-mysql --with-mysql --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data", cwd="php-5.4.13")
     self.__run_command("make", cwd="php-5.4.13")
     self.__run_command("sudo make install", cwd="php-5.4.13")
     self.__run_command("printf \"\\n\" | sudo pecl install apc-beta", cwd="php-5.4.13")
@@ -100,6 +103,9 @@ class Installer:
     self.__run_command("sudo cp ../config/php-fpm.conf /usr/local/lib/php-fpm.conf")
     self.__run_command("rm php-5.4.13.tar.gz")
 
+    # Composer
+    self.__run_command("curl -sS https://getcomposer.org/installer | php -- --install-dir=bin")
+
     #
     # Haskell
     #
@@ -129,6 +135,14 @@ class Installer:
     self.__run_command("make", cwd="nginx-1.2.7")
     self.__run_command("sudo make install", cwd="nginx-1.2.7")
     
+    #
+    # Openresty (nginx with openresty stuff)
+    #
+    self.__run_command("curl http://openresty.org/download/ngx_openresty-1.2.7.5.tar.gz | tar xvz")
+    self.__run_command("./configure --with-luajit", cwd="ngx_openresty-1.2.7.5")
+    self.__run_command("make", cwd="ngx_openresty-1.2.7.5")
+    self.__run_command("sudo make install", cwd="ngx_openresty-1.2.7.5")
+    
     #
     # Gunicorn
     #
@@ -225,11 +239,6 @@ class Installer:
     ##############################
     self.__run_command("curl http://vertx.io/downloads/vert.x-1.3.1.final.tar.gz | tar xvz")
 
-    ##############################
-    # WebGO
-    ##############################
-    self.__run_command("go/bin/go get github.com/hoisie/web")
-
     ##############################
     # Yesod
     ##############################
@@ -271,6 +280,7 @@ class Installer:
     ##############################
     yes | sudo apt-get update
     yes | sudo apt-get install build-essential git libev-dev libpq-dev libreadline6-dev
+    sudo sh -c "echo '*               soft    nofile          4096' >> /etc/security/limits.conf"
 
     ##############################
     # MySQL
@@ -313,7 +323,7 @@ class Installer:
     # MongoDB
     ##############################
     sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
-    sudo cp config/10gen.list /etc/apt/sources.list.d/10gen.list
+    sudo cp 10gen.list /etc/apt/sources.list.d/10gen.list
     sudo apt-get update 
     yes | sudo apt-get install mongodb-10gen
     

+ 27 - 0
lift-stateless/README.md

@@ -0,0 +1,27 @@
+#Lift Benchmarking Test (stateless)
+
+This is the stateless Lift portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test source](src/main/scala/code/lib/StatelessJson.scala)
+
+### Data-Store/Database Mapping Test
+
+* [Database test snippet](src/main/scala/code/lib/StatelessDb.scala)
+* [Database test model](src/main/scala/code/model/World.scala)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
+* [Lift 2.5.0-RC2](http://http://www.liftweb.net/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost/json
+
+### Data-Store/Database Mapping Test
+
+http://localhost/db/5

+ 0 - 0
lift-stateless/__init__.py


+ 13 - 0
lift-stateless/benchmark_config

@@ -0,0 +1,13 @@
+{
+  "framework": "lift-stateless",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/db/",
+      "port": 8080,
+      "sort": 45
+    }
+  }]
+}

+ 63 - 0
lift-stateless/build.sbt

@@ -0,0 +1,63 @@
+import AssemblyKeys._
+
+organization := "code"
+
+name := "lift-stateless"
+
+version := "0.0.1"
+
+scalaVersion := "2.10.1"
+
+scalacOptions ++= Seq(
+  "-deprecation",
+  "-unchecked", 
+  "-feature", 
+  "-language:postfixOps",
+  "-language:reflectiveCalls",
+  "-language:implicitConversions",
+  "-Xlint")
+
+libraryDependencies ++= Seq(
+  "org.streum" %% "configrity-core" % "1.0.0",
+  "org.rogach" %% "scallop" % "0.8.1",
+  "commons-dbcp" % "commons-dbcp" % "1.4",
+  "mysql" % "mysql-connector-java" % "5.1.21",
+  "com.typesafe.slick" %% "slick" % "1.0.0",
+  "ch.qos.logback" % "logback-classic" % "1.0.9",
+  "org.eintr.loglady" %% "loglady" % "1.1.0",
+  "org.eclipse.jetty" % "jetty-server" % "8.1.9.v20130131",
+  "org.eclipse.jetty" % "jetty-webapp" % "8.1.9.v20130131",
+  "org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" artifacts Artifact("javax.servlet", "jar", "jar"),
+  "net.liftweb" %% "lift-webkit" % "2.5-RC2"
+)
+
+assemblySettings
+
+mainClass in assembly := Some("code.Main")
+
+mergeStrategy in assembly <<= (mergeStrategy in assembly) { old =>
+  {
+    case "index.html" => MergeStrategy.first
+    case "about.html" => MergeStrategy.discard
+    case x => old(x)
+  }
+}
+
+seq(Revolver.settings: _*)
+
+mainClass in Revolver.reStart := Some("code.Main")
+
+buildInfoSettings
+
+sourceGenerators in Compile <+= buildInfo
+
+buildInfoKeys ++= Seq[BuildInfoKey](
+  name,
+  version,
+  scalaVersion,
+  sbtVersion,
+  buildInfoBuildNumber,
+  BuildInfoKey.action("buildTime") { System.currentTimeMillis }
+)
+
+buildInfoPackage := "code"

+ 44 - 0
lift-stateless/project/Deploy.scala

@@ -0,0 +1,44 @@
+import sbt._
+import Keys._
+import sbtassembly.Plugin.AssemblyKeys._
+
+object Deploy {
+  val deployPackTask = TaskKey[Unit]("deploy-pack")
+  val deployPack = deployPackTask <<= (assembly, jarName in assembly, target, baseDirectory) map { (_, jarName, target, base) =>
+    IO.delete(target / "deploy")
+    IO.createDirectory(target / "deploy")
+    IO.copyFile(target / jarName, target / "deploy" / jarName)
+    if (base / "server.conf" exists)
+      IO.copyFile(base / "server.conf", target / "deploy" / "server.conf")
+    IO.write(target / "deploy" / "start.sh",
+      """#!/bin/bash
+        |DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)"
+        |cd $DIR
+        |java -Dfile.encoding=UTF8 -jar %s
+        |""" format (jarName) stripMargin)
+    target / "deploy" / "start.sh" setExecutable true
+  }
+  
+  val deployHost = SettingKey[Option[String]]("deployHost", "default host, on which deployed files will be pushed")
+  val deployDest = SettingKey[Option[String]]("deployDest", "default destination on that host")
+  
+  val deploySsh = InputKey[Unit]("deploy-ssh") <<= inputTask { (argTask: TaskKey[Seq[String]]) =>
+    (argTask, deployPackTask, deployHost, deployDest, jarName in assembly, target) map { (args, _, deployHost, deployDest, jarName, target) => 
+      val (host, dest) = if (args.size < 2) {
+        (for {
+          host <- deployHost
+          dest <- deployDest
+        } yield (host, dest)).getOrElse(sys.error("Destination was not provided on command line - and there was no default"))
+      } else (args(0), args(1))
+      val cmd = "rsync" +: "-avz" +: IO.listFiles(target / "deploy").map(_.toString) :+ (host+":"+dest)
+      println("Copying files: " + cmd.mkString(" "))
+      if (Process(cmd).! == 0) {
+        val startCmd = List("ssh", host, "-x", "cd " + dest + "; (nohup ./start.sh > server.log 2>&1 &)")
+        println("Starting process: " + startCmd.mkString(" "))
+        Process(startCmd).!
+      }
+    }
+  }
+  
+  lazy val deploySettings = Seq(deployPack, deployHost := None, deployDest := None, deploySsh)
+}

+ 1 - 0
lift-stateless/project/build.properties

@@ -0,0 +1 @@
+sbt.version=0.12.2

+ 7 - 0
lift-stateless/project/build.scala

@@ -0,0 +1,7 @@
+import sbt._
+import Keys._
+
+object build extends Build {
+
+  lazy val root = Project("lift-stateless", file(".")) settings (Deploy.deploySettings:_*)
+}

+ 5 - 0
lift-stateless/project/plugins.sbt

@@ -0,0 +1,5 @@
+addSbtPlugin("io.spray" % "sbt-revolver" % "0.6.2")
+
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.8.6")
+
+addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.2.2")

+ 3 - 0
lift-stateless/run

@@ -0,0 +1,3 @@
+cd `dirname $0`/target
+java -server -XX:+CMSClassUnloadingEnabled -Xmx2G -Xss512M -XX:MaxPermSize=512m -jar lift-stateless-assembly-0.0.1.jar &> /dev/null
+cd -

+ 1 - 0
lift-stateless/sbt

@@ -0,0 +1 @@
+java -Xmx1024M -Xss2M -XX:MaxPermSize=512m -XX:+CMSClassUnloadingEnabled -jar `dirname $0`/sbt-launch.jar "$@"

BIN
lift-stateless/sbt-launch.jar


+ 7 - 0
lift-stateless/server.conf

@@ -0,0 +1,7 @@
+# db {
+#   host = "localhost:3306"
+#   name = "hello_world"
+#   user = "benchmarkdbuser"
+#   pass = "benchmarkdbpass"
+# }
+# http.port = 8080

+ 21 - 0
lift-stateless/setup.py

@@ -0,0 +1,21 @@
+
+import subprocess
+import sys
+import setup_util
+import os
+
+def start(args):
+  setup_util.replace_text("lift-stateless/src/main/scala/Main.scala", "> \".*:3306", "> \"" + args.database_host + ":3306")
+
+  subprocess.check_call("./sbt update assembly", shell=True, cwd="lift-stateless")
+  subprocess.Popen("./run", shell=True, cwd="lift-stateless")
+
+  return 0
+def stop():
+  p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+  out, err = p.communicate()
+  for line in out.splitlines():
+    if 'lift-stateless-assembly' in line and 'java' in line:
+      pid = int(line.split(None, 2)[1])
+      os.kill(pid, 9)
+  return 0

+ 18 - 0
lift-stateless/src/main/resources/WEB-INF/web.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+<filter>
+  <filter-name>LiftFilter</filter-name>
+  <display-name>Lift Filter</display-name>
+  <description>The Filter that intercepts lift calls</description>
+  <filter-class>net.liftweb.http.LiftFilter</filter-class>
+</filter>
+
+<filter-mapping>
+  <filter-name>LiftFilter</filter-name>
+  <url-pattern>/*</url-pattern>
+</filter-mapping>
+	
+</web-app>

+ 1109 - 0
lift-stateless/src/main/resources/bootstrap/css/bootstrap-responsive.css

@@ -0,0 +1,1109 @@
+/*!
+ * Bootstrap Responsive v2.3.0
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+
+.clearfix {
+  *zoom: 1;
+}
+
+.clearfix:before,
+.clearfix:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.clearfix:after {
+  clear: both;
+}
+
+.hide-text {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+.input-block-level {
+  display: block;
+  width: 100%;
+  min-height: 30px;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+@-ms-viewport {
+  width: device-width;
+}
+
+.hidden {
+  display: none;
+  visibility: hidden;
+}
+
+.visible-phone {
+  display: none !important;
+}
+
+.visible-tablet {
+  display: none !important;
+}
+
+.hidden-desktop {
+  display: none !important;
+}
+
+.visible-desktop {
+  display: inherit !important;
+}
+
+@media (min-width: 768px) and (max-width: 979px) {
+  .hidden-desktop {
+    display: inherit !important;
+  }
+  .visible-desktop {
+    display: none !important ;
+  }
+  .visible-tablet {
+    display: inherit !important;
+  }
+  .hidden-tablet {
+    display: none !important;
+  }
+}
+
+@media (max-width: 767px) {
+  .hidden-desktop {
+    display: inherit !important;
+  }
+  .visible-desktop {
+    display: none !important;
+  }
+  .visible-phone {
+    display: inherit !important;
+  }
+  .hidden-phone {
+    display: none !important;
+  }
+}
+
+.visible-print {
+  display: none !important;
+}
+
+@media print {
+  .visible-print {
+    display: inherit !important;
+  }
+  .hidden-print {
+    display: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .row {
+    margin-left: -30px;
+    *zoom: 1;
+  }
+  .row:before,
+  .row:after {
+    display: table;
+    line-height: 0;
+    content: "";
+  }
+  .row:after {
+    clear: both;
+  }
+  [class*="span"] {
+    float: left;
+    min-height: 1px;
+    margin-left: 30px;
+  }
+  .container,
+  .navbar-static-top .container,
+  .navbar-fixed-top .container,
+  .navbar-fixed-bottom .container {
+    width: 1170px;
+  }
+  .span12 {
+    width: 1170px;
+  }
+  .span11 {
+    width: 1070px;
+  }
+  .span10 {
+    width: 970px;
+  }
+  .span9 {
+    width: 870px;
+  }
+  .span8 {
+    width: 770px;
+  }
+  .span7 {
+    width: 670px;
+  }
+  .span6 {
+    width: 570px;
+  }
+  .span5 {
+    width: 470px;
+  }
+  .span4 {
+    width: 370px;
+  }
+  .span3 {
+    width: 270px;
+  }
+  .span2 {
+    width: 170px;
+  }
+  .span1 {
+    width: 70px;
+  }
+  .offset12 {
+    margin-left: 1230px;
+  }
+  .offset11 {
+    margin-left: 1130px;
+  }
+  .offset10 {
+    margin-left: 1030px;
+  }
+  .offset9 {
+    margin-left: 930px;
+  }
+  .offset8 {
+    margin-left: 830px;
+  }
+  .offset7 {
+    margin-left: 730px;
+  }
+  .offset6 {
+    margin-left: 630px;
+  }
+  .offset5 {
+    margin-left: 530px;
+  }
+  .offset4 {
+    margin-left: 430px;
+  }
+  .offset3 {
+    margin-left: 330px;
+  }
+  .offset2 {
+    margin-left: 230px;
+  }
+  .offset1 {
+    margin-left: 130px;
+  }
+  .row-fluid {
+    width: 100%;
+    *zoom: 1;
+  }
+  .row-fluid:before,
+  .row-fluid:after {
+    display: table;
+    line-height: 0;
+    content: "";
+  }
+  .row-fluid:after {
+    clear: both;
+  }
+  .row-fluid [class*="span"] {
+    display: block;
+    float: left;
+    width: 100%;
+    min-height: 30px;
+    margin-left: 2.564102564102564%;
+    *margin-left: 2.5109110747408616%;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .row-fluid [class*="span"]:first-child {
+    margin-left: 0;
+  }
+  .row-fluid .controls-row [class*="span"] + [class*="span"] {
+    margin-left: 2.564102564102564%;
+  }
+  .row-fluid .span12 {
+    width: 100%;
+    *width: 99.94680851063829%;
+  }
+  .row-fluid .span11 {
+    width: 91.45299145299145%;
+    *width: 91.39979996362975%;
+  }
+  .row-fluid .span10 {
+    width: 82.90598290598291%;
+    *width: 82.8527914166212%;
+  }
+  .row-fluid .span9 {
+    width: 74.35897435897436%;
+    *width: 74.30578286961266%;
+  }
+  .row-fluid .span8 {
+    width: 65.81196581196582%;
+    *width: 65.75877432260411%;
+  }
+  .row-fluid .span7 {
+    width: 57.26495726495726%;
+    *width: 57.21176577559556%;
+  }
+  .row-fluid .span6 {
+    width: 48.717948717948715%;
+    *width: 48.664757228587014%;
+  }
+  .row-fluid .span5 {
+    width: 40.17094017094017%;
+    *width: 40.11774868157847%;
+  }
+  .row-fluid .span4 {
+    width: 31.623931623931625%;
+    *width: 31.570740134569924%;
+  }
+  .row-fluid .span3 {
+    width: 23.076923076923077%;
+    *width: 23.023731587561375%;
+  }
+  .row-fluid .span2 {
+    width: 14.52991452991453%;
+    *width: 14.476723040552828%;
+  }
+  .row-fluid .span1 {
+    width: 5.982905982905983%;
+    *width: 5.929714493544281%;
+  }
+  .row-fluid .offset12 {
+    margin-left: 105.12820512820512%;
+    *margin-left: 105.02182214948171%;
+  }
+  .row-fluid .offset12:first-child {
+    margin-left: 102.56410256410257%;
+    *margin-left: 102.45771958537915%;
+  }
+  .row-fluid .offset11 {
+    margin-left: 96.58119658119658%;
+    *margin-left: 96.47481360247316%;
+  }
+  .row-fluid .offset11:first-child {
+    margin-left: 94.01709401709402%;
+    *margin-left: 93.91071103837061%;
+  }
+  .row-fluid .offset10 {
+    margin-left: 88.03418803418803%;
+    *margin-left: 87.92780505546462%;
+  }
+  .row-fluid .offset10:first-child {
+    margin-left: 85.47008547008548%;
+    *margin-left: 85.36370249136206%;
+  }
+  .row-fluid .offset9 {
+    margin-left: 79.48717948717949%;
+    *margin-left: 79.38079650845607%;
+  }
+  .row-fluid .offset9:first-child {
+    margin-left: 76.92307692307693%;
+    *margin-left: 76.81669394435352%;
+  }
+  .row-fluid .offset8 {
+    margin-left: 70.94017094017094%;
+    *margin-left: 70.83378796144753%;
+  }
+  .row-fluid .offset8:first-child {
+    margin-left: 68.37606837606839%;
+    *margin-left: 68.26968539734497%;
+  }
+  .row-fluid .offset7 {
+    margin-left: 62.393162393162385%;
+    *margin-left: 62.28677941443899%;
+  }
+  .row-fluid .offset7:first-child {
+    margin-left: 59.82905982905982%;
+    *margin-left: 59.72267685033642%;
+  }
+  .row-fluid .offset6 {
+    margin-left: 53.84615384615384%;
+    *margin-left: 53.739770867430444%;
+  }
+  .row-fluid .offset6:first-child {
+    margin-left: 51.28205128205128%;
+    *margin-left: 51.175668303327875%;
+  }
+  .row-fluid .offset5 {
+    margin-left: 45.299145299145295%;
+    *margin-left: 45.1927623204219%;
+  }
+  .row-fluid .offset5:first-child {
+    margin-left: 42.73504273504273%;
+    *margin-left: 42.62865975631933%;
+  }
+  .row-fluid .offset4 {
+    margin-left: 36.75213675213675%;
+    *margin-left: 36.645753773413354%;
+  }
+  .row-fluid .offset4:first-child {
+    margin-left: 34.18803418803419%;
+    *margin-left: 34.081651209310785%;
+  }
+  .row-fluid .offset3 {
+    margin-left: 28.205128205128204%;
+    *margin-left: 28.0987452264048%;
+  }
+  .row-fluid .offset3:first-child {
+    margin-left: 25.641025641025642%;
+    *margin-left: 25.53464266230224%;
+  }
+  .row-fluid .offset2 {
+    margin-left: 19.65811965811966%;
+    *margin-left: 19.551736679396257%;
+  }
+  .row-fluid .offset2:first-child {
+    margin-left: 17.094017094017094%;
+    *margin-left: 16.98763411529369%;
+  }
+  .row-fluid .offset1 {
+    margin-left: 11.11111111111111%;
+    *margin-left: 11.004728132387708%;
+  }
+  .row-fluid .offset1:first-child {
+    margin-left: 8.547008547008547%;
+    *margin-left: 8.440625568285142%;
+  }
+  input,
+  textarea,
+  .uneditable-input {
+    margin-left: 0;
+  }
+  .controls-row [class*="span"] + [class*="span"] {
+    margin-left: 30px;
+  }
+  input.span12,
+  textarea.span12,
+  .uneditable-input.span12 {
+    width: 1156px;
+  }
+  input.span11,
+  textarea.span11,
+  .uneditable-input.span11 {
+    width: 1056px;
+  }
+  input.span10,
+  textarea.span10,
+  .uneditable-input.span10 {
+    width: 956px;
+  }
+  input.span9,
+  textarea.span9,
+  .uneditable-input.span9 {
+    width: 856px;
+  }
+  input.span8,
+  textarea.span8,
+  .uneditable-input.span8 {
+    width: 756px;
+  }
+  input.span7,
+  textarea.span7,
+  .uneditable-input.span7 {
+    width: 656px;
+  }
+  input.span6,
+  textarea.span6,
+  .uneditable-input.span6 {
+    width: 556px;
+  }
+  input.span5,
+  textarea.span5,
+  .uneditable-input.span5 {
+    width: 456px;
+  }
+  input.span4,
+  textarea.span4,
+  .uneditable-input.span4 {
+    width: 356px;
+  }
+  input.span3,
+  textarea.span3,
+  .uneditable-input.span3 {
+    width: 256px;
+  }
+  input.span2,
+  textarea.span2,
+  .uneditable-input.span2 {
+    width: 156px;
+  }
+  input.span1,
+  textarea.span1,
+  .uneditable-input.span1 {
+    width: 56px;
+  }
+  .thumbnails {
+    margin-left: -30px;
+  }
+  .thumbnails > li {
+    margin-left: 30px;
+  }
+  .row-fluid .thumbnails {
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 768px) and (max-width: 979px) {
+  .row {
+    margin-left: -20px;
+    *zoom: 1;
+  }
+  .row:before,
+  .row:after {
+    display: table;
+    line-height: 0;
+    content: "";
+  }
+  .row:after {
+    clear: both;
+  }
+  [class*="span"] {
+    float: left;
+    min-height: 1px;
+    margin-left: 20px;
+  }
+  .container,
+  .navbar-static-top .container,
+  .navbar-fixed-top .container,
+  .navbar-fixed-bottom .container {
+    width: 724px;
+  }
+  .span12 {
+    width: 724px;
+  }
+  .span11 {
+    width: 662px;
+  }
+  .span10 {
+    width: 600px;
+  }
+  .span9 {
+    width: 538px;
+  }
+  .span8 {
+    width: 476px;
+  }
+  .span7 {
+    width: 414px;
+  }
+  .span6 {
+    width: 352px;
+  }
+  .span5 {
+    width: 290px;
+  }
+  .span4 {
+    width: 228px;
+  }
+  .span3 {
+    width: 166px;
+  }
+  .span2 {
+    width: 104px;
+  }
+  .span1 {
+    width: 42px;
+  }
+  .offset12 {
+    margin-left: 764px;
+  }
+  .offset11 {
+    margin-left: 702px;
+  }
+  .offset10 {
+    margin-left: 640px;
+  }
+  .offset9 {
+    margin-left: 578px;
+  }
+  .offset8 {
+    margin-left: 516px;
+  }
+  .offset7 {
+    margin-left: 454px;
+  }
+  .offset6 {
+    margin-left: 392px;
+  }
+  .offset5 {
+    margin-left: 330px;
+  }
+  .offset4 {
+    margin-left: 268px;
+  }
+  .offset3 {
+    margin-left: 206px;
+  }
+  .offset2 {
+    margin-left: 144px;
+  }
+  .offset1 {
+    margin-left: 82px;
+  }
+  .row-fluid {
+    width: 100%;
+    *zoom: 1;
+  }
+  .row-fluid:before,
+  .row-fluid:after {
+    display: table;
+    line-height: 0;
+    content: "";
+  }
+  .row-fluid:after {
+    clear: both;
+  }
+  .row-fluid [class*="span"] {
+    display: block;
+    float: left;
+    width: 100%;
+    min-height: 30px;
+    margin-left: 2.7624309392265194%;
+    *margin-left: 2.709239449864817%;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .row-fluid [class*="span"]:first-child {
+    margin-left: 0;
+  }
+  .row-fluid .controls-row [class*="span"] + [class*="span"] {
+    margin-left: 2.7624309392265194%;
+  }
+  .row-fluid .span12 {
+    width: 100%;
+    *width: 99.94680851063829%;
+  }
+  .row-fluid .span11 {
+    width: 91.43646408839778%;
+    *width: 91.38327259903608%;
+  }
+  .row-fluid .span10 {
+    width: 82.87292817679558%;
+    *width: 82.81973668743387%;
+  }
+  .row-fluid .span9 {
+    width: 74.30939226519337%;
+    *width: 74.25620077583166%;
+  }
+  .row-fluid .span8 {
+    width: 65.74585635359117%;
+    *width: 65.69266486422946%;
+  }
+  .row-fluid .span7 {
+    width: 57.18232044198895%;
+    *width: 57.12912895262725%;
+  }
+  .row-fluid .span6 {
+    width: 48.61878453038674%;
+    *width: 48.56559304102504%;
+  }
+  .row-fluid .span5 {
+    width: 40.05524861878453%;
+    *width: 40.00205712942283%;
+  }
+  .row-fluid .span4 {
+    width: 31.491712707182323%;
+    *width: 31.43852121782062%;
+  }
+  .row-fluid .span3 {
+    width: 22.92817679558011%;
+    *width: 22.87498530621841%;
+  }
+  .row-fluid .span2 {
+    width: 14.3646408839779%;
+    *width: 14.311449394616199%;
+  }
+  .row-fluid .span1 {
+    width: 5.801104972375691%;
+    *width: 5.747913483013988%;
+  }
+  .row-fluid .offset12 {
+    margin-left: 105.52486187845304%;
+    *margin-left: 105.41847889972962%;
+  }
+  .row-fluid .offset12:first-child {
+    margin-left: 102.76243093922652%;
+    *margin-left: 102.6560479605031%;
+  }
+  .row-fluid .offset11 {
+    margin-left: 96.96132596685082%;
+    *margin-left: 96.8549429881274%;
+  }
+  .row-fluid .offset11:first-child {
+    margin-left: 94.1988950276243%;
+    *margin-left: 94.09251204890089%;
+  }
+  .row-fluid .offset10 {
+    margin-left: 88.39779005524862%;
+    *margin-left: 88.2914070765252%;
+  }
+  .row-fluid .offset10:first-child {
+    margin-left: 85.6353591160221%;
+    *margin-left: 85.52897613729868%;
+  }
+  .row-fluid .offset9 {
+    margin-left: 79.8342541436464%;
+    *margin-left: 79.72787116492299%;
+  }
+  .row-fluid .offset9:first-child {
+    margin-left: 77.07182320441989%;
+    *margin-left: 76.96544022569647%;
+  }
+  .row-fluid .offset8 {
+    margin-left: 71.2707182320442%;
+    *margin-left: 71.16433525332079%;
+  }
+  .row-fluid .offset8:first-child {
+    margin-left: 68.50828729281768%;
+    *margin-left: 68.40190431409427%;
+  }
+  .row-fluid .offset7 {
+    margin-left: 62.70718232044199%;
+    *margin-left: 62.600799341718584%;
+  }
+  .row-fluid .offset7:first-child {
+    margin-left: 59.94475138121547%;
+    *margin-left: 59.838368402492065%;
+  }
+  .row-fluid .offset6 {
+    margin-left: 54.14364640883978%;
+    *margin-left: 54.037263430116376%;
+  }
+  .row-fluid .offset6:first-child {
+    margin-left: 51.38121546961326%;
+    *margin-left: 51.27483249088986%;
+  }
+  .row-fluid .offset5 {
+    margin-left: 45.58011049723757%;
+    *margin-left: 45.47372751851417%;
+  }
+  .row-fluid .offset5:first-child {
+    margin-left: 42.81767955801105%;
+    *margin-left: 42.71129657928765%;
+  }
+  .row-fluid .offset4 {
+    margin-left: 37.01657458563536%;
+    *margin-left: 36.91019160691196%;
+  }
+  .row-fluid .offset4:first-child {
+    margin-left: 34.25414364640884%;
+    *margin-left: 34.14776066768544%;
+  }
+  .row-fluid .offset3 {
+    margin-left: 28.45303867403315%;
+    *margin-left: 28.346655695309746%;
+  }
+  .row-fluid .offset3:first-child {
+    margin-left: 25.69060773480663%;
+    *margin-left: 25.584224756083227%;
+  }
+  .row-fluid .offset2 {
+    margin-left: 19.88950276243094%;
+    *margin-left: 19.783119783707537%;
+  }
+  .row-fluid .offset2:first-child {
+    margin-left: 17.12707182320442%;
+    *margin-left: 17.02068884448102%;
+  }
+  .row-fluid .offset1 {
+    margin-left: 11.32596685082873%;
+    *margin-left: 11.219583872105325%;
+  }
+  .row-fluid .offset1:first-child {
+    margin-left: 8.56353591160221%;
+    *margin-left: 8.457152932878806%;
+  }
+  input,
+  textarea,
+  .uneditable-input {
+    margin-left: 0;
+  }
+  .controls-row [class*="span"] + [class*="span"] {
+    margin-left: 20px;
+  }
+  input.span12,
+  textarea.span12,
+  .uneditable-input.span12 {
+    width: 710px;
+  }
+  input.span11,
+  textarea.span11,
+  .uneditable-input.span11 {
+    width: 648px;
+  }
+  input.span10,
+  textarea.span10,
+  .uneditable-input.span10 {
+    width: 586px;
+  }
+  input.span9,
+  textarea.span9,
+  .uneditable-input.span9 {
+    width: 524px;
+  }
+  input.span8,
+  textarea.span8,
+  .uneditable-input.span8 {
+    width: 462px;
+  }
+  input.span7,
+  textarea.span7,
+  .uneditable-input.span7 {
+    width: 400px;
+  }
+  input.span6,
+  textarea.span6,
+  .uneditable-input.span6 {
+    width: 338px;
+  }
+  input.span5,
+  textarea.span5,
+  .uneditable-input.span5 {
+    width: 276px;
+  }
+  input.span4,
+  textarea.span4,
+  .uneditable-input.span4 {
+    width: 214px;
+  }
+  input.span3,
+  textarea.span3,
+  .uneditable-input.span3 {
+    width: 152px;
+  }
+  input.span2,
+  textarea.span2,
+  .uneditable-input.span2 {
+    width: 90px;
+  }
+  input.span1,
+  textarea.span1,
+  .uneditable-input.span1 {
+    width: 28px;
+  }
+}
+
+@media (max-width: 767px) {
+  body {
+    padding-right: 20px;
+    padding-left: 20px;
+  }
+  .navbar-fixed-top,
+  .navbar-fixed-bottom,
+  .navbar-static-top {
+    margin-right: -20px;
+    margin-left: -20px;
+  }
+  .container-fluid {
+    padding: 0;
+  }
+  .dl-horizontal dt {
+    float: none;
+    width: auto;
+    clear: none;
+    text-align: left;
+  }
+  .dl-horizontal dd {
+    margin-left: 0;
+  }
+  .container {
+    width: auto;
+  }
+  .row-fluid {
+    width: 100%;
+  }
+  .row,
+  .thumbnails {
+    margin-left: 0;
+  }
+  .thumbnails > li {
+    float: none;
+    margin-left: 0;
+  }
+  [class*="span"],
+  .uneditable-input[class*="span"],
+  .row-fluid [class*="span"] {
+    display: block;
+    float: none;
+    width: 100%;
+    margin-left: 0;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .span12,
+  .row-fluid .span12 {
+    width: 100%;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .row-fluid [class*="offset"]:first-child {
+    margin-left: 0;
+  }
+  .input-large,
+  .input-xlarge,
+  .input-xxlarge,
+  input[class*="span"],
+  select[class*="span"],
+  textarea[class*="span"],
+  .uneditable-input {
+    display: block;
+    width: 100%;
+    min-height: 30px;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .input-prepend input,
+  .input-append input,
+  .input-prepend input[class*="span"],
+  .input-append input[class*="span"] {
+    display: inline-block;
+    width: auto;
+  }
+  .controls-row [class*="span"] + [class*="span"] {
+    margin-left: 0;
+  }
+  .modal {
+    position: fixed;
+    top: 20px;
+    right: 20px;
+    left: 20px;
+    width: auto;
+    margin: 0;
+  }
+  .modal.fade {
+    top: -100px;
+  }
+  .modal.fade.in {
+    top: 20px;
+  }
+}
+
+@media (max-width: 480px) {
+  .nav-collapse {
+    -webkit-transform: translate3d(0, 0, 0);
+  }
+  .page-header h1 small {
+    display: block;
+    line-height: 20px;
+  }
+  input[type="checkbox"],
+  input[type="radio"] {
+    border: 1px solid #ccc;
+  }
+  .form-horizontal .control-label {
+    float: none;
+    width: auto;
+    padding-top: 0;
+    text-align: left;
+  }
+  .form-horizontal .controls {
+    margin-left: 0;
+  }
+  .form-horizontal .control-list {
+    padding-top: 0;
+  }
+  .form-horizontal .form-actions {
+    padding-right: 10px;
+    padding-left: 10px;
+  }
+  .media .pull-left,
+  .media .pull-right {
+    display: block;
+    float: none;
+    margin-bottom: 10px;
+  }
+  .media-object {
+    margin-right: 0;
+    margin-left: 0;
+  }
+  .modal {
+    top: 10px;
+    right: 10px;
+    left: 10px;
+  }
+  .modal-header .close {
+    padding: 10px;
+    margin: -10px;
+  }
+  .carousel-caption {
+    position: static;
+  }
+}
+
+@media (max-width: 979px) {
+  body {
+    padding-top: 0;
+  }
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    position: static;
+  }
+  .navbar-fixed-top {
+    margin-bottom: 20px;
+  }
+  .navbar-fixed-bottom {
+    margin-top: 20px;
+  }
+  .navbar-fixed-top .navbar-inner,
+  .navbar-fixed-bottom .navbar-inner {
+    padding: 5px;
+  }
+  .navbar .container {
+    width: auto;
+    padding: 0;
+  }
+  .navbar .brand {
+    padding-right: 10px;
+    padding-left: 10px;
+    margin: 0 0 0 -5px;
+  }
+  .nav-collapse {
+    clear: both;
+  }
+  .nav-collapse .nav {
+    float: none;
+    margin: 0 0 10px;
+  }
+  .nav-collapse .nav > li {
+    float: none;
+  }
+  .nav-collapse .nav > li > a {
+    margin-bottom: 2px;
+  }
+  .nav-collapse .nav > .divider-vertical {
+    display: none;
+  }
+  .nav-collapse .nav .nav-header {
+    color: #777777;
+    text-shadow: none;
+  }
+  .nav-collapse .nav > li > a,
+  .nav-collapse .dropdown-menu a {
+    padding: 9px 15px;
+    font-weight: bold;
+    color: #777777;
+    -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+            border-radius: 3px;
+  }
+  .nav-collapse .btn {
+    padding: 4px 10px 4px;
+    font-weight: normal;
+    -webkit-border-radius: 4px;
+       -moz-border-radius: 4px;
+            border-radius: 4px;
+  }
+  .nav-collapse .dropdown-menu li + li a {
+    margin-bottom: 2px;
+  }
+  .nav-collapse .nav > li > a:hover,
+  .nav-collapse .nav > li > a:focus,
+  .nav-collapse .dropdown-menu a:hover,
+  .nav-collapse .dropdown-menu a:focus {
+    background-color: #f2f2f2;
+  }
+  .navbar-inverse .nav-collapse .nav > li > a,
+  .navbar-inverse .nav-collapse .dropdown-menu a {
+    color: #999999;
+  }
+  .navbar-inverse .nav-collapse .nav > li > a:hover,
+  .navbar-inverse .nav-collapse .nav > li > a:focus,
+  .navbar-inverse .nav-collapse .dropdown-menu a:hover,
+  .navbar-inverse .nav-collapse .dropdown-menu a:focus {
+    background-color: #111111;
+  }
+  .nav-collapse.in .btn-group {
+    padding: 0;
+    margin-top: 5px;
+  }
+  .nav-collapse .dropdown-menu {
+    position: static;
+    top: auto;
+    left: auto;
+    display: none;
+    float: none;
+    max-width: none;
+    padding: 0;
+    margin: 0 15px;
+    background-color: transparent;
+    border: none;
+    -webkit-border-radius: 0;
+       -moz-border-radius: 0;
+            border-radius: 0;
+    -webkit-box-shadow: none;
+       -moz-box-shadow: none;
+            box-shadow: none;
+  }
+  .nav-collapse .open > .dropdown-menu {
+    display: block;
+  }
+  .nav-collapse .dropdown-menu:before,
+  .nav-collapse .dropdown-menu:after {
+    display: none;
+  }
+  .nav-collapse .dropdown-menu .divider {
+    display: none;
+  }
+  .nav-collapse .nav > li > .dropdown-menu:before,
+  .nav-collapse .nav > li > .dropdown-menu:after {
+    display: none;
+  }
+  .nav-collapse .navbar-form,
+  .nav-collapse .navbar-search {
+    float: none;
+    padding: 10px 15px;
+    margin: 10px 0;
+    border-top: 1px solid #f2f2f2;
+    border-bottom: 1px solid #f2f2f2;
+    -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+       -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+            box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+  }
+  .navbar-inverse .nav-collapse .navbar-form,
+  .navbar-inverse .nav-collapse .navbar-search {
+    border-top-color: #111111;
+    border-bottom-color: #111111;
+  }
+  .navbar .nav-collapse .nav.pull-right {
+    float: none;
+    margin-left: 0;
+  }
+  .nav-collapse,
+  .nav-collapse.collapse {
+    height: 0;
+    overflow: hidden;
+  }
+  .navbar .btn-navbar {
+    display: block;
+  }
+  .navbar-static .navbar-inner {
+    padding-right: 10px;
+    padding-left: 10px;
+  }
+}
+
+@media (min-width: 980px) {
+  .nav-collapse.collapse {
+    height: auto !important;
+    overflow: visible !important;
+  }
+}

File diff suppressed because it is too large
+ 8 - 0
lift-stateless/src/main/resources/bootstrap/css/bootstrap-responsive.min.css


+ 6158 - 0
lift-stateless/src/main/resources/bootstrap/css/bootstrap.css

@@ -0,0 +1,6158 @@
+/*!
+ * Bootstrap v2.3.0
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+
+.clearfix {
+  *zoom: 1;
+}
+
+.clearfix:before,
+.clearfix:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.clearfix:after {
+  clear: both;
+}
+
+.hide-text {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+.input-block-level {
+  display: block;
+  width: 100%;
+  min-height: 30px;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+nav,
+section {
+  display: block;
+}
+
+audio,
+canvas,
+video {
+  display: inline-block;
+  *display: inline;
+  *zoom: 1;
+}
+
+audio:not([controls]) {
+  display: none;
+}
+
+html {
+  font-size: 100%;
+  -webkit-text-size-adjust: 100%;
+      -ms-text-size-adjust: 100%;
+}
+
+a:focus {
+  outline: thin dotted #333;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+a:hover,
+a:active {
+  outline: 0;
+}
+
+sub,
+sup {
+  position: relative;
+  font-size: 75%;
+  line-height: 0;
+  vertical-align: baseline;
+}
+
+sup {
+  top: -0.5em;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+img {
+  width: auto\9;
+  height: auto;
+  max-width: 100%;
+  vertical-align: middle;
+  border: 0;
+  -ms-interpolation-mode: bicubic;
+}
+
+#map_canvas img,
+.google-maps img {
+  max-width: none;
+}
+
+button,
+input,
+select,
+textarea {
+  margin: 0;
+  font-size: 100%;
+  vertical-align: middle;
+}
+
+button,
+input {
+  *overflow: visible;
+  line-height: normal;
+}
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+  cursor: pointer;
+  -webkit-appearance: button;
+}
+
+label,
+select,
+button,
+input[type="button"],
+input[type="reset"],
+input[type="submit"],
+input[type="radio"],
+input[type="checkbox"] {
+  cursor: pointer;
+}
+
+input[type="search"] {
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+  -webkit-appearance: textfield;
+}
+
+input[type="search"]::-webkit-search-decoration,
+input[type="search"]::-webkit-search-cancel-button {
+  -webkit-appearance: none;
+}
+
+textarea {
+  overflow: auto;
+  vertical-align: top;
+}
+
+@media print {
+  * {
+    color: #000 !important;
+    text-shadow: none !important;
+    background: transparent !important;
+    box-shadow: none !important;
+  }
+  a,
+  a:visited {
+    text-decoration: underline;
+  }
+  a[href]:after {
+    content: " (" attr(href) ")";
+  }
+  abbr[title]:after {
+    content: " (" attr(title) ")";
+  }
+  .ir a:after,
+  a[href^="javascript:"]:after,
+  a[href^="#"]:after {
+    content: "";
+  }
+  pre,
+  blockquote {
+    border: 1px solid #999;
+    page-break-inside: avoid;
+  }
+  thead {
+    display: table-header-group;
+  }
+  tr,
+  img {
+    page-break-inside: avoid;
+  }
+  img {
+    max-width: 100% !important;
+  }
+  @page  {
+    margin: 0.5cm;
+  }
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2,
+  h3 {
+    page-break-after: avoid;
+  }
+}
+
+body {
+  margin: 0;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 14px;
+  line-height: 20px;
+  color: #333333;
+  background-color: #ffffff;
+}
+
+a {
+  color: #0088cc;
+  text-decoration: none;
+}
+
+a:hover,
+a:focus {
+  color: #005580;
+  text-decoration: underline;
+}
+
+.img-rounded {
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+}
+
+.img-polaroid {
+  padding: 4px;
+  background-color: #fff;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+
+.img-circle {
+  -webkit-border-radius: 500px;
+     -moz-border-radius: 500px;
+          border-radius: 500px;
+}
+
+.row {
+  margin-left: -20px;
+  *zoom: 1;
+}
+
+.row:before,
+.row:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.row:after {
+  clear: both;
+}
+
+[class*="span"] {
+  float: left;
+  min-height: 1px;
+  margin-left: 20px;
+}
+
+.container,
+.navbar-static-top .container,
+.navbar-fixed-top .container,
+.navbar-fixed-bottom .container {
+  width: 940px;
+}
+
+.span12 {
+  width: 940px;
+}
+
+.span11 {
+  width: 860px;
+}
+
+.span10 {
+  width: 780px;
+}
+
+.span9 {
+  width: 700px;
+}
+
+.span8 {
+  width: 620px;
+}
+
+.span7 {
+  width: 540px;
+}
+
+.span6 {
+  width: 460px;
+}
+
+.span5 {
+  width: 380px;
+}
+
+.span4 {
+  width: 300px;
+}
+
+.span3 {
+  width: 220px;
+}
+
+.span2 {
+  width: 140px;
+}
+
+.span1 {
+  width: 60px;
+}
+
+.offset12 {
+  margin-left: 980px;
+}
+
+.offset11 {
+  margin-left: 900px;
+}
+
+.offset10 {
+  margin-left: 820px;
+}
+
+.offset9 {
+  margin-left: 740px;
+}
+
+.offset8 {
+  margin-left: 660px;
+}
+
+.offset7 {
+  margin-left: 580px;
+}
+
+.offset6 {
+  margin-left: 500px;
+}
+
+.offset5 {
+  margin-left: 420px;
+}
+
+.offset4 {
+  margin-left: 340px;
+}
+
+.offset3 {
+  margin-left: 260px;
+}
+
+.offset2 {
+  margin-left: 180px;
+}
+
+.offset1 {
+  margin-left: 100px;
+}
+
+.row-fluid {
+  width: 100%;
+  *zoom: 1;
+}
+
+.row-fluid:before,
+.row-fluid:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.row-fluid:after {
+  clear: both;
+}
+
+.row-fluid [class*="span"] {
+  display: block;
+  float: left;
+  width: 100%;
+  min-height: 30px;
+  margin-left: 2.127659574468085%;
+  *margin-left: 2.074468085106383%;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.row-fluid [class*="span"]:first-child {
+  margin-left: 0;
+}
+
+.row-fluid .controls-row [class*="span"] + [class*="span"] {
+  margin-left: 2.127659574468085%;
+}
+
+.row-fluid .span12 {
+  width: 100%;
+  *width: 99.94680851063829%;
+}
+
+.row-fluid .span11 {
+  width: 91.48936170212765%;
+  *width: 91.43617021276594%;
+}
+
+.row-fluid .span10 {
+  width: 82.97872340425532%;
+  *width: 82.92553191489361%;
+}
+
+.row-fluid .span9 {
+  width: 74.46808510638297%;
+  *width: 74.41489361702126%;
+}
+
+.row-fluid .span8 {
+  width: 65.95744680851064%;
+  *width: 65.90425531914893%;
+}
+
+.row-fluid .span7 {
+  width: 57.44680851063829%;
+  *width: 57.39361702127659%;
+}
+
+.row-fluid .span6 {
+  width: 48.93617021276595%;
+  *width: 48.88297872340425%;
+}
+
+.row-fluid .span5 {
+  width: 40.42553191489362%;
+  *width: 40.37234042553192%;
+}
+
+.row-fluid .span4 {
+  width: 31.914893617021278%;
+  *width: 31.861702127659576%;
+}
+
+.row-fluid .span3 {
+  width: 23.404255319148934%;
+  *width: 23.351063829787233%;
+}
+
+.row-fluid .span2 {
+  width: 14.893617021276595%;
+  *width: 14.840425531914894%;
+}
+
+.row-fluid .span1 {
+  width: 6.382978723404255%;
+  *width: 6.329787234042553%;
+}
+
+.row-fluid .offset12 {
+  margin-left: 104.25531914893617%;
+  *margin-left: 104.14893617021275%;
+}
+
+.row-fluid .offset12:first-child {
+  margin-left: 102.12765957446808%;
+  *margin-left: 102.02127659574467%;
+}
+
+.row-fluid .offset11 {
+  margin-left: 95.74468085106382%;
+  *margin-left: 95.6382978723404%;
+}
+
+.row-fluid .offset11:first-child {
+  margin-left: 93.61702127659574%;
+  *margin-left: 93.51063829787232%;
+}
+
+.row-fluid .offset10 {
+  margin-left: 87.23404255319149%;
+  *margin-left: 87.12765957446807%;
+}
+
+.row-fluid .offset10:first-child {
+  margin-left: 85.1063829787234%;
+  *margin-left: 84.99999999999999%;
+}
+
+.row-fluid .offset9 {
+  margin-left: 78.72340425531914%;
+  *margin-left: 78.61702127659572%;
+}
+
+.row-fluid .offset9:first-child {
+  margin-left: 76.59574468085106%;
+  *margin-left: 76.48936170212764%;
+}
+
+.row-fluid .offset8 {
+  margin-left: 70.2127659574468%;
+  *margin-left: 70.10638297872339%;
+}
+
+.row-fluid .offset8:first-child {
+  margin-left: 68.08510638297872%;
+  *margin-left: 67.9787234042553%;
+}
+
+.row-fluid .offset7 {
+  margin-left: 61.70212765957446%;
+  *margin-left: 61.59574468085106%;
+}
+
+.row-fluid .offset7:first-child {
+  margin-left: 59.574468085106375%;
+  *margin-left: 59.46808510638297%;
+}
+
+.row-fluid .offset6 {
+  margin-left: 53.191489361702125%;
+  *margin-left: 53.085106382978715%;
+}
+
+.row-fluid .offset6:first-child {
+  margin-left: 51.063829787234035%;
+  *margin-left: 50.95744680851063%;
+}
+
+.row-fluid .offset5 {
+  margin-left: 44.68085106382979%;
+  *margin-left: 44.57446808510638%;
+}
+
+.row-fluid .offset5:first-child {
+  margin-left: 42.5531914893617%;
+  *margin-left: 42.4468085106383%;
+}
+
+.row-fluid .offset4 {
+  margin-left: 36.170212765957444%;
+  *margin-left: 36.06382978723405%;
+}
+
+.row-fluid .offset4:first-child {
+  margin-left: 34.04255319148936%;
+  *margin-left: 33.93617021276596%;
+}
+
+.row-fluid .offset3 {
+  margin-left: 27.659574468085104%;
+  *margin-left: 27.5531914893617%;
+}
+
+.row-fluid .offset3:first-child {
+  margin-left: 25.53191489361702%;
+  *margin-left: 25.425531914893618%;
+}
+
+.row-fluid .offset2 {
+  margin-left: 19.148936170212764%;
+  *margin-left: 19.04255319148936%;
+}
+
+.row-fluid .offset2:first-child {
+  margin-left: 17.02127659574468%;
+  *margin-left: 16.914893617021278%;
+}
+
+.row-fluid .offset1 {
+  margin-left: 10.638297872340425%;
+  *margin-left: 10.53191489361702%;
+}
+
+.row-fluid .offset1:first-child {
+  margin-left: 8.51063829787234%;
+  *margin-left: 8.404255319148938%;
+}
+
+[class*="span"].hide,
+.row-fluid [class*="span"].hide {
+  display: none;
+}
+
+[class*="span"].pull-right,
+.row-fluid [class*="span"].pull-right {
+  float: right;
+}
+
+.container {
+  margin-right: auto;
+  margin-left: auto;
+  *zoom: 1;
+}
+
+.container:before,
+.container:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.container:after {
+  clear: both;
+}
+
+.container-fluid {
+  padding-right: 20px;
+  padding-left: 20px;
+  *zoom: 1;
+}
+
+.container-fluid:before,
+.container-fluid:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.container-fluid:after {
+  clear: both;
+}
+
+p {
+  margin: 0 0 10px;
+}
+
+.lead {
+  margin-bottom: 20px;
+  font-size: 21px;
+  font-weight: 200;
+  line-height: 30px;
+}
+
+small {
+  font-size: 85%;
+}
+
+strong {
+  font-weight: bold;
+}
+
+em {
+  font-style: italic;
+}
+
+cite {
+  font-style: normal;
+}
+
+.muted {
+  color: #999999;
+}
+
+a.muted:hover,
+a.muted:focus {
+  color: #808080;
+}
+
+.text-warning {
+  color: #c09853;
+}
+
+a.text-warning:hover,
+a.text-warning:focus {
+  color: #a47e3c;
+}
+
+.text-error {
+  color: #b94a48;
+}
+
+a.text-error:hover,
+a.text-error:focus {
+  color: #953b39;
+}
+
+.text-info {
+  color: #3a87ad;
+}
+
+a.text-info:hover,
+a.text-info:focus {
+  color: #2d6987;
+}
+
+.text-success {
+  color: #468847;
+}
+
+a.text-success:hover,
+a.text-success:focus {
+  color: #356635;
+}
+
+.text-left {
+  text-align: left;
+}
+
+.text-right {
+  text-align: right;
+}
+
+.text-center {
+  text-align: center;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+  margin: 10px 0;
+  font-family: inherit;
+  font-weight: bold;
+  line-height: 20px;
+  color: inherit;
+  text-rendering: optimizelegibility;
+}
+
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small {
+  font-weight: normal;
+  line-height: 1;
+  color: #999999;
+}
+
+h1,
+h2,
+h3 {
+  line-height: 40px;
+}
+
+h1 {
+  font-size: 38.5px;
+}
+
+h2 {
+  font-size: 31.5px;
+}
+
+h3 {
+  font-size: 24.5px;
+}
+
+h4 {
+  font-size: 17.5px;
+}
+
+h5 {
+  font-size: 14px;
+}
+
+h6 {
+  font-size: 11.9px;
+}
+
+h1 small {
+  font-size: 24.5px;
+}
+
+h2 small {
+  font-size: 17.5px;
+}
+
+h3 small {
+  font-size: 14px;
+}
+
+h4 small {
+  font-size: 14px;
+}
+
+.page-header {
+  padding-bottom: 9px;
+  margin: 20px 0 30px;
+  border-bottom: 1px solid #eeeeee;
+}
+
+ul,
+ol {
+  padding: 0;
+  margin: 0 0 10px 25px;
+}
+
+ul ul,
+ul ol,
+ol ol,
+ol ul {
+  margin-bottom: 0;
+}
+
+li {
+  line-height: 20px;
+}
+
+ul.unstyled,
+ol.unstyled {
+  margin-left: 0;
+  list-style: none;
+}
+
+ul.inline,
+ol.inline {
+  margin-left: 0;
+  list-style: none;
+}
+
+ul.inline > li,
+ol.inline > li {
+  display: inline-block;
+  *display: inline;
+  padding-right: 5px;
+  padding-left: 5px;
+  *zoom: 1;
+}
+
+dl {
+  margin-bottom: 20px;
+}
+
+dt,
+dd {
+  line-height: 20px;
+}
+
+dt {
+  font-weight: bold;
+}
+
+dd {
+  margin-left: 10px;
+}
+
+.dl-horizontal {
+  *zoom: 1;
+}
+
+.dl-horizontal:before,
+.dl-horizontal:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.dl-horizontal:after {
+  clear: both;
+}
+
+.dl-horizontal dt {
+  float: left;
+  width: 160px;
+  overflow: hidden;
+  clear: left;
+  text-align: right;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.dl-horizontal dd {
+  margin-left: 180px;
+}
+
+hr {
+  margin: 20px 0;
+  border: 0;
+  border-top: 1px solid #eeeeee;
+  border-bottom: 1px solid #ffffff;
+}
+
+abbr[title],
+abbr[data-original-title] {
+  cursor: help;
+  border-bottom: 1px dotted #999999;
+}
+
+abbr.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+
+blockquote {
+  padding: 0 0 0 15px;
+  margin: 0 0 20px;
+  border-left: 5px solid #eeeeee;
+}
+
+blockquote p {
+  margin-bottom: 0;
+  font-size: 17.5px;
+  font-weight: 300;
+  line-height: 1.25;
+}
+
+blockquote small {
+  display: block;
+  line-height: 20px;
+  color: #999999;
+}
+
+blockquote small:before {
+  content: '\2014 \00A0';
+}
+
+blockquote.pull-right {
+  float: right;
+  padding-right: 15px;
+  padding-left: 0;
+  border-right: 5px solid #eeeeee;
+  border-left: 0;
+}
+
+blockquote.pull-right p,
+blockquote.pull-right small {
+  text-align: right;
+}
+
+blockquote.pull-right small:before {
+  content: '';
+}
+
+blockquote.pull-right small:after {
+  content: '\00A0 \2014';
+}
+
+q:before,
+q:after,
+blockquote:before,
+blockquote:after {
+  content: "";
+}
+
+address {
+  display: block;
+  margin-bottom: 20px;
+  font-style: normal;
+  line-height: 20px;
+}
+
+code,
+pre {
+  padding: 0 3px 2px;
+  font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
+  font-size: 12px;
+  color: #333333;
+  -webkit-border-radius: 3px;
+     -moz-border-radius: 3px;
+          border-radius: 3px;
+}
+
+code {
+  padding: 2px 4px;
+  color: #d14;
+  white-space: nowrap;
+  background-color: #f7f7f9;
+  border: 1px solid #e1e1e8;
+}
+
+pre {
+  display: block;
+  padding: 9.5px;
+  margin: 0 0 10px;
+  font-size: 13px;
+  line-height: 20px;
+  word-break: break-all;
+  word-wrap: break-word;
+  white-space: pre;
+  white-space: pre-wrap;
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+pre.prettyprint {
+  margin-bottom: 20px;
+}
+
+pre code {
+  padding: 0;
+  color: inherit;
+  white-space: pre;
+  white-space: pre-wrap;
+  background-color: transparent;
+  border: 0;
+}
+
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}
+
+form {
+  margin: 0 0 20px;
+}
+
+fieldset {
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+
+legend {
+  display: block;
+  width: 100%;
+  padding: 0;
+  margin-bottom: 20px;
+  font-size: 21px;
+  line-height: 40px;
+  color: #333333;
+  border: 0;
+  border-bottom: 1px solid #e5e5e5;
+}
+
+legend small {
+  font-size: 15px;
+  color: #999999;
+}
+
+label,
+input,
+button,
+select,
+textarea {
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 20px;
+}
+
+input,
+button,
+select,
+textarea {
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+
+label {
+  display: block;
+  margin-bottom: 5px;
+}
+
+select,
+textarea,
+input[type="text"],
+input[type="password"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="date"],
+input[type="month"],
+input[type="time"],
+input[type="week"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="search"],
+input[type="tel"],
+input[type="color"],
+.uneditable-input {
+  display: inline-block;
+  height: 20px;
+  padding: 4px 6px;
+  margin-bottom: 10px;
+  font-size: 14px;
+  line-height: 20px;
+  color: #555555;
+  vertical-align: middle;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+input,
+textarea,
+.uneditable-input {
+  width: 206px;
+}
+
+textarea {
+  height: auto;
+}
+
+textarea,
+input[type="text"],
+input[type="password"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="date"],
+input[type="month"],
+input[type="time"],
+input[type="week"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="search"],
+input[type="tel"],
+input[type="color"],
+.uneditable-input {
+  background-color: #ffffff;
+  border: 1px solid #cccccc;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
+     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
+       -o-transition: border linear 0.2s, box-shadow linear 0.2s;
+          transition: border linear 0.2s, box-shadow linear 0.2s;
+}
+
+textarea:focus,
+input[type="text"]:focus,
+input[type="password"]:focus,
+input[type="datetime"]:focus,
+input[type="datetime-local"]:focus,
+input[type="date"]:focus,
+input[type="month"]:focus,
+input[type="time"]:focus,
+input[type="week"]:focus,
+input[type="number"]:focus,
+input[type="email"]:focus,
+input[type="url"]:focus,
+input[type="search"]:focus,
+input[type="tel"]:focus,
+input[type="color"]:focus,
+.uneditable-input:focus {
+  border-color: rgba(82, 168, 236, 0.8);
+  outline: 0;
+  outline: thin dotted \9;
+  /* IE6-9 */
+
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+}
+
+input[type="radio"],
+input[type="checkbox"] {
+  margin: 4px 0 0;
+  margin-top: 1px \9;
+  *margin-top: 0;
+  line-height: normal;
+}
+
+input[type="file"],
+input[type="image"],
+input[type="submit"],
+input[type="reset"],
+input[type="button"],
+input[type="radio"],
+input[type="checkbox"] {
+  width: auto;
+}
+
+select,
+input[type="file"] {
+  height: 30px;
+  /* In IE7, the height of the select element cannot be changed by height, only font-size */
+
+  *margin-top: 4px;
+  /* For IE7, add top margin to align select with labels */
+
+  line-height: 30px;
+}
+
+select {
+  width: 220px;
+  background-color: #ffffff;
+  border: 1px solid #cccccc;
+}
+
+select[multiple],
+select[size] {
+  height: auto;
+}
+
+select:focus,
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+  outline: thin dotted #333;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+.uneditable-input,
+.uneditable-textarea {
+  color: #999999;
+  cursor: not-allowed;
+  background-color: #fcfcfc;
+  border-color: #cccccc;
+  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
+     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
+          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
+}
+
+.uneditable-input {
+  overflow: hidden;
+  white-space: nowrap;
+}
+
+.uneditable-textarea {
+  width: auto;
+  height: auto;
+}
+
+input:-moz-placeholder,
+textarea:-moz-placeholder {
+  color: #999999;
+}
+
+input:-ms-input-placeholder,
+textarea:-ms-input-placeholder {
+  color: #999999;
+}
+
+input::-webkit-input-placeholder,
+textarea::-webkit-input-placeholder {
+  color: #999999;
+}
+
+.radio,
+.checkbox {
+  min-height: 20px;
+  padding-left: 20px;
+}
+
+.radio input[type="radio"],
+.checkbox input[type="checkbox"] {
+  float: left;
+  margin-left: -20px;
+}
+
+.controls > .radio:first-child,
+.controls > .checkbox:first-child {
+  padding-top: 5px;
+}
+
+.radio.inline,
+.checkbox.inline {
+  display: inline-block;
+  padding-top: 5px;
+  margin-bottom: 0;
+  vertical-align: middle;
+}
+
+.radio.inline + .radio.inline,
+.checkbox.inline + .checkbox.inline {
+  margin-left: 10px;
+}
+
+.input-mini {
+  width: 60px;
+}
+
+.input-small {
+  width: 90px;
+}
+
+.input-medium {
+  width: 150px;
+}
+
+.input-large {
+  width: 210px;
+}
+
+.input-xlarge {
+  width: 270px;
+}
+
+.input-xxlarge {
+  width: 530px;
+}
+
+input[class*="span"],
+select[class*="span"],
+textarea[class*="span"],
+.uneditable-input[class*="span"],
+.row-fluid input[class*="span"],
+.row-fluid select[class*="span"],
+.row-fluid textarea[class*="span"],
+.row-fluid .uneditable-input[class*="span"] {
+  float: none;
+  margin-left: 0;
+}
+
+.input-append input[class*="span"],
+.input-append .uneditable-input[class*="span"],
+.input-prepend input[class*="span"],
+.input-prepend .uneditable-input[class*="span"],
+.row-fluid input[class*="span"],
+.row-fluid select[class*="span"],
+.row-fluid textarea[class*="span"],
+.row-fluid .uneditable-input[class*="span"],
+.row-fluid .input-prepend [class*="span"],
+.row-fluid .input-append [class*="span"] {
+  display: inline-block;
+}
+
+input,
+textarea,
+.uneditable-input {
+  margin-left: 0;
+}
+
+.controls-row [class*="span"] + [class*="span"] {
+  margin-left: 20px;
+}
+
+input.span12,
+textarea.span12,
+.uneditable-input.span12 {
+  width: 926px;
+}
+
+input.span11,
+textarea.span11,
+.uneditable-input.span11 {
+  width: 846px;
+}
+
+input.span10,
+textarea.span10,
+.uneditable-input.span10 {
+  width: 766px;
+}
+
+input.span9,
+textarea.span9,
+.uneditable-input.span9 {
+  width: 686px;
+}
+
+input.span8,
+textarea.span8,
+.uneditable-input.span8 {
+  width: 606px;
+}
+
+input.span7,
+textarea.span7,
+.uneditable-input.span7 {
+  width: 526px;
+}
+
+input.span6,
+textarea.span6,
+.uneditable-input.span6 {
+  width: 446px;
+}
+
+input.span5,
+textarea.span5,
+.uneditable-input.span5 {
+  width: 366px;
+}
+
+input.span4,
+textarea.span4,
+.uneditable-input.span4 {
+  width: 286px;
+}
+
+input.span3,
+textarea.span3,
+.uneditable-input.span3 {
+  width: 206px;
+}
+
+input.span2,
+textarea.span2,
+.uneditable-input.span2 {
+  width: 126px;
+}
+
+input.span1,
+textarea.span1,
+.uneditable-input.span1 {
+  width: 46px;
+}
+
+.controls-row {
+  *zoom: 1;
+}
+
+.controls-row:before,
+.controls-row:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.controls-row:after {
+  clear: both;
+}
+
+.controls-row [class*="span"],
+.row-fluid .controls-row [class*="span"] {
+  float: left;
+}
+
+.controls-row .checkbox[class*="span"],
+.controls-row .radio[class*="span"] {
+  padding-top: 5px;
+}
+
+input[disabled],
+select[disabled],
+textarea[disabled],
+input[readonly],
+select[readonly],
+textarea[readonly] {
+  cursor: not-allowed;
+  background-color: #eeeeee;
+}
+
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"][readonly],
+input[type="checkbox"][readonly] {
+  background-color: transparent;
+}
+
+.control-group.warning .control-label,
+.control-group.warning .help-block,
+.control-group.warning .help-inline {
+  color: #c09853;
+}
+
+.control-group.warning .checkbox,
+.control-group.warning .radio,
+.control-group.warning input,
+.control-group.warning select,
+.control-group.warning textarea {
+  color: #c09853;
+}
+
+.control-group.warning input,
+.control-group.warning select,
+.control-group.warning textarea {
+  border-color: #c09853;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.warning input:focus,
+.control-group.warning select:focus,
+.control-group.warning textarea:focus {
+  border-color: #a47e3c;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+}
+
+.control-group.warning .input-prepend .add-on,
+.control-group.warning .input-append .add-on {
+  color: #c09853;
+  background-color: #fcf8e3;
+  border-color: #c09853;
+}
+
+.control-group.error .control-label,
+.control-group.error .help-block,
+.control-group.error .help-inline {
+  color: #b94a48;
+}
+
+.control-group.error .checkbox,
+.control-group.error .radio,
+.control-group.error input,
+.control-group.error select,
+.control-group.error textarea {
+  color: #b94a48;
+}
+
+.control-group.error input,
+.control-group.error select,
+.control-group.error textarea {
+  border-color: #b94a48;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.error input:focus,
+.control-group.error select:focus,
+.control-group.error textarea:focus {
+  border-color: #953b39;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+}
+
+.control-group.error .input-prepend .add-on,
+.control-group.error .input-append .add-on {
+  color: #b94a48;
+  background-color: #f2dede;
+  border-color: #b94a48;
+}
+
+.control-group.success .control-label,
+.control-group.success .help-block,
+.control-group.success .help-inline {
+  color: #468847;
+}
+
+.control-group.success .checkbox,
+.control-group.success .radio,
+.control-group.success input,
+.control-group.success select,
+.control-group.success textarea {
+  color: #468847;
+}
+
+.control-group.success input,
+.control-group.success select,
+.control-group.success textarea {
+  border-color: #468847;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.success input:focus,
+.control-group.success select:focus,
+.control-group.success textarea:focus {
+  border-color: #356635;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+}
+
+.control-group.success .input-prepend .add-on,
+.control-group.success .input-append .add-on {
+  color: #468847;
+  background-color: #dff0d8;
+  border-color: #468847;
+}
+
+.control-group.info .control-label,
+.control-group.info .help-block,
+.control-group.info .help-inline {
+  color: #3a87ad;
+}
+
+.control-group.info .checkbox,
+.control-group.info .radio,
+.control-group.info input,
+.control-group.info select,
+.control-group.info textarea {
+  color: #3a87ad;
+}
+
+.control-group.info input,
+.control-group.info select,
+.control-group.info textarea {
+  border-color: #3a87ad;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.info input:focus,
+.control-group.info select:focus,
+.control-group.info textarea:focus {
+  border-color: #2d6987;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
+}
+
+.control-group.info .input-prepend .add-on,
+.control-group.info .input-append .add-on {
+  color: #3a87ad;
+  background-color: #d9edf7;
+  border-color: #3a87ad;
+}
+
+input:focus:invalid,
+textarea:focus:invalid,
+select:focus:invalid {
+  color: #b94a48;
+  border-color: #ee5f5b;
+}
+
+input:focus:invalid:focus,
+textarea:focus:invalid:focus,
+select:focus:invalid:focus {
+  border-color: #e9322d;
+  -webkit-box-shadow: 0 0 6px #f8b9b7;
+     -moz-box-shadow: 0 0 6px #f8b9b7;
+          box-shadow: 0 0 6px #f8b9b7;
+}
+
+.form-actions {
+  padding: 19px 20px 20px;
+  margin-top: 20px;
+  margin-bottom: 20px;
+  background-color: #f5f5f5;
+  border-top: 1px solid #e5e5e5;
+  *zoom: 1;
+}
+
+.form-actions:before,
+.form-actions:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.form-actions:after {
+  clear: both;
+}
+
+.help-block,
+.help-inline {
+  color: #595959;
+}
+
+.help-block {
+  display: block;
+  margin-bottom: 10px;
+}
+
+.help-inline {
+  display: inline-block;
+  *display: inline;
+  padding-left: 5px;
+  vertical-align: middle;
+  *zoom: 1;
+}
+
+.input-append,
+.input-prepend {
+  display: inline-block;
+  margin-bottom: 10px;
+  font-size: 0;
+  white-space: nowrap;
+  vertical-align: middle;
+}
+
+.input-append input,
+.input-prepend input,
+.input-append select,
+.input-prepend select,
+.input-append .uneditable-input,
+.input-prepend .uneditable-input,
+.input-append .dropdown-menu,
+.input-prepend .dropdown-menu,
+.input-append .popover,
+.input-prepend .popover {
+  font-size: 14px;
+}
+
+.input-append input,
+.input-prepend input,
+.input-append select,
+.input-prepend select,
+.input-append .uneditable-input,
+.input-prepend .uneditable-input {
+  position: relative;
+  margin-bottom: 0;
+  *margin-left: 0;
+  vertical-align: top;
+  -webkit-border-radius: 0 4px 4px 0;
+     -moz-border-radius: 0 4px 4px 0;
+          border-radius: 0 4px 4px 0;
+}
+
+.input-append input:focus,
+.input-prepend input:focus,
+.input-append select:focus,
+.input-prepend select:focus,
+.input-append .uneditable-input:focus,
+.input-prepend .uneditable-input:focus {
+  z-index: 2;
+}
+
+.input-append .add-on,
+.input-prepend .add-on {
+  display: inline-block;
+  width: auto;
+  height: 20px;
+  min-width: 16px;
+  padding: 4px 5px;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 20px;
+  text-align: center;
+  text-shadow: 0 1px 0 #ffffff;
+  background-color: #eeeeee;
+  border: 1px solid #ccc;
+}
+
+.input-append .add-on,
+.input-prepend .add-on,
+.input-append .btn,
+.input-prepend .btn,
+.input-append .btn-group > .dropdown-toggle,
+.input-prepend .btn-group > .dropdown-toggle {
+  vertical-align: top;
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.input-append .active,
+.input-prepend .active {
+  background-color: #a9dba9;
+  border-color: #46a546;
+}
+
+.input-prepend .add-on,
+.input-prepend .btn {
+  margin-right: -1px;
+}
+
+.input-prepend .add-on:first-child,
+.input-prepend .btn:first-child {
+  -webkit-border-radius: 4px 0 0 4px;
+     -moz-border-radius: 4px 0 0 4px;
+          border-radius: 4px 0 0 4px;
+}
+
+.input-append input,
+.input-append select,
+.input-append .uneditable-input {
+  -webkit-border-radius: 4px 0 0 4px;
+     -moz-border-radius: 4px 0 0 4px;
+          border-radius: 4px 0 0 4px;
+}
+
+.input-append input + .btn-group .btn:last-child,
+.input-append select + .btn-group .btn:last-child,
+.input-append .uneditable-input + .btn-group .btn:last-child {
+  -webkit-border-radius: 0 4px 4px 0;
+     -moz-border-radius: 0 4px 4px 0;
+          border-radius: 0 4px 4px 0;
+}
+
+.input-append .add-on,
+.input-append .btn,
+.input-append .btn-group {
+  margin-left: -1px;
+}
+
+.input-append .add-on:last-child,
+.input-append .btn:last-child,
+.input-append .btn-group:last-child > .dropdown-toggle {
+  -webkit-border-radius: 0 4px 4px 0;
+     -moz-border-radius: 0 4px 4px 0;
+          border-radius: 0 4px 4px 0;
+}
+
+.input-prepend.input-append input,
+.input-prepend.input-append select,
+.input-prepend.input-append .uneditable-input {
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.input-prepend.input-append input + .btn-group .btn,
+.input-prepend.input-append select + .btn-group .btn,
+.input-prepend.input-append .uneditable-input + .btn-group .btn {
+  -webkit-border-radius: 0 4px 4px 0;
+     -moz-border-radius: 0 4px 4px 0;
+          border-radius: 0 4px 4px 0;
+}
+
+.input-prepend.input-append .add-on:first-child,
+.input-prepend.input-append .btn:first-child {
+  margin-right: -1px;
+  -webkit-border-radius: 4px 0 0 4px;
+     -moz-border-radius: 4px 0 0 4px;
+          border-radius: 4px 0 0 4px;
+}
+
+.input-prepend.input-append .add-on:last-child,
+.input-prepend.input-append .btn:last-child {
+  margin-left: -1px;
+  -webkit-border-radius: 0 4px 4px 0;
+     -moz-border-radius: 0 4px 4px 0;
+          border-radius: 0 4px 4px 0;
+}
+
+.input-prepend.input-append .btn-group:first-child {
+  margin-left: 0;
+}
+
+input.search-query {
+  padding-right: 14px;
+  padding-right: 4px \9;
+  padding-left: 14px;
+  padding-left: 4px \9;
+  /* IE7-8 doesn't have border-radius, so don't indent the padding */
+
+  margin-bottom: 0;
+  -webkit-border-radius: 15px;
+     -moz-border-radius: 15px;
+          border-radius: 15px;
+}
+
+/* Allow for input prepend/append in search forms */
+
+.form-search .input-append .search-query,
+.form-search .input-prepend .search-query {
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.form-search .input-append .search-query {
+  -webkit-border-radius: 14px 0 0 14px;
+     -moz-border-radius: 14px 0 0 14px;
+          border-radius: 14px 0 0 14px;
+}
+
+.form-search .input-append .btn {
+  -webkit-border-radius: 0 14px 14px 0;
+     -moz-border-radius: 0 14px 14px 0;
+          border-radius: 0 14px 14px 0;
+}
+
+.form-search .input-prepend .search-query {
+  -webkit-border-radius: 0 14px 14px 0;
+     -moz-border-radius: 0 14px 14px 0;
+          border-radius: 0 14px 14px 0;
+}
+
+.form-search .input-prepend .btn {
+  -webkit-border-radius: 14px 0 0 14px;
+     -moz-border-radius: 14px 0 0 14px;
+          border-radius: 14px 0 0 14px;
+}
+
+.form-search input,
+.form-inline input,
+.form-horizontal input,
+.form-search textarea,
+.form-inline textarea,
+.form-horizontal textarea,
+.form-search select,
+.form-inline select,
+.form-horizontal select,
+.form-search .help-inline,
+.form-inline .help-inline,
+.form-horizontal .help-inline,
+.form-search .uneditable-input,
+.form-inline .uneditable-input,
+.form-horizontal .uneditable-input,
+.form-search .input-prepend,
+.form-inline .input-prepend,
+.form-horizontal .input-prepend,
+.form-search .input-append,
+.form-inline .input-append,
+.form-horizontal .input-append {
+  display: inline-block;
+  *display: inline;
+  margin-bottom: 0;
+  vertical-align: middle;
+  *zoom: 1;
+}
+
+.form-search .hide,
+.form-inline .hide,
+.form-horizontal .hide {
+  display: none;
+}
+
+.form-search label,
+.form-inline label,
+.form-search .btn-group,
+.form-inline .btn-group {
+  display: inline-block;
+}
+
+.form-search .input-append,
+.form-inline .input-append,
+.form-search .input-prepend,
+.form-inline .input-prepend {
+  margin-bottom: 0;
+}
+
+.form-search .radio,
+.form-search .checkbox,
+.form-inline .radio,
+.form-inline .checkbox {
+  padding-left: 0;
+  margin-bottom: 0;
+  vertical-align: middle;
+}
+
+.form-search .radio input[type="radio"],
+.form-search .checkbox input[type="checkbox"],
+.form-inline .radio input[type="radio"],
+.form-inline .checkbox input[type="checkbox"] {
+  float: left;
+  margin-right: 3px;
+  margin-left: 0;
+}
+
+.control-group {
+  margin-bottom: 10px;
+}
+
+legend + .control-group {
+  margin-top: 20px;
+  -webkit-margin-top-collapse: separate;
+}
+
+.form-horizontal .control-group {
+  margin-bottom: 20px;
+  *zoom: 1;
+}
+
+.form-horizontal .control-group:before,
+.form-horizontal .control-group:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.form-horizontal .control-group:after {
+  clear: both;
+}
+
+.form-horizontal .control-label {
+  float: left;
+  width: 160px;
+  padding-top: 5px;
+  text-align: right;
+}
+
+.form-horizontal .controls {
+  *display: inline-block;
+  *padding-left: 20px;
+  margin-left: 180px;
+  *margin-left: 0;
+}
+
+.form-horizontal .controls:first-child {
+  *padding-left: 180px;
+}
+
+.form-horizontal .help-block {
+  margin-bottom: 0;
+}
+
+.form-horizontal input + .help-block,
+.form-horizontal select + .help-block,
+.form-horizontal textarea + .help-block,
+.form-horizontal .uneditable-input + .help-block,
+.form-horizontal .input-prepend + .help-block,
+.form-horizontal .input-append + .help-block {
+  margin-top: 10px;
+}
+
+.form-horizontal .form-actions {
+  padding-left: 180px;
+}
+
+table {
+  max-width: 100%;
+  background-color: transparent;
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+
+.table {
+  width: 100%;
+  margin-bottom: 20px;
+}
+
+.table th,
+.table td {
+  padding: 8px;
+  line-height: 20px;
+  text-align: left;
+  vertical-align: top;
+  border-top: 1px solid #dddddd;
+}
+
+.table th {
+  font-weight: bold;
+}
+
+.table thead th {
+  vertical-align: bottom;
+}
+
+.table caption + thead tr:first-child th,
+.table caption + thead tr:first-child td,
+.table colgroup + thead tr:first-child th,
+.table colgroup + thead tr:first-child td,
+.table thead:first-child tr:first-child th,
+.table thead:first-child tr:first-child td {
+  border-top: 0;
+}
+
+.table tbody + tbody {
+  border-top: 2px solid #dddddd;
+}
+
+.table .table {
+  background-color: #ffffff;
+}
+
+.table-condensed th,
+.table-condensed td {
+  padding: 4px 5px;
+}
+
+.table-bordered {
+  border: 1px solid #dddddd;
+  border-collapse: separate;
+  *border-collapse: collapse;
+  border-left: 0;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+.table-bordered th,
+.table-bordered td {
+  border-left: 1px solid #dddddd;
+}
+
+.table-bordered caption + thead tr:first-child th,
+.table-bordered caption + tbody tr:first-child th,
+.table-bordered caption + tbody tr:first-child td,
+.table-bordered colgroup + thead tr:first-child th,
+.table-bordered colgroup + tbody tr:first-child th,
+.table-bordered colgroup + tbody tr:first-child td,
+.table-bordered thead:first-child tr:first-child th,
+.table-bordered tbody:first-child tr:first-child th,
+.table-bordered tbody:first-child tr:first-child td {
+  border-top: 0;
+}
+
+.table-bordered thead:first-child tr:first-child > th:first-child,
+.table-bordered tbody:first-child tr:first-child > td:first-child,
+.table-bordered tbody:first-child tr:first-child > th:first-child {
+  -webkit-border-top-left-radius: 4px;
+          border-top-left-radius: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+.table-bordered thead:first-child tr:first-child > th:last-child,
+.table-bordered tbody:first-child tr:first-child > td:last-child,
+.table-bordered tbody:first-child tr:first-child > th:last-child {
+  -webkit-border-top-right-radius: 4px;
+          border-top-right-radius: 4px;
+  -moz-border-radius-topright: 4px;
+}
+
+.table-bordered thead:last-child tr:last-child > th:first-child,
+.table-bordered tbody:last-child tr:last-child > td:first-child,
+.table-bordered tbody:last-child tr:last-child > th:first-child,
+.table-bordered tfoot:last-child tr:last-child > td:first-child,
+.table-bordered tfoot:last-child tr:last-child > th:first-child {
+  -webkit-border-bottom-left-radius: 4px;
+          border-bottom-left-radius: 4px;
+  -moz-border-radius-bottomleft: 4px;
+}
+
+.table-bordered thead:last-child tr:last-child > th:last-child,
+.table-bordered tbody:last-child tr:last-child > td:last-child,
+.table-bordered tbody:last-child tr:last-child > th:last-child,
+.table-bordered tfoot:last-child tr:last-child > td:last-child,
+.table-bordered tfoot:last-child tr:last-child > th:last-child {
+  -webkit-border-bottom-right-radius: 4px;
+          border-bottom-right-radius: 4px;
+  -moz-border-radius-bottomright: 4px;
+}
+
+.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {
+  -webkit-border-bottom-left-radius: 0;
+          border-bottom-left-radius: 0;
+  -moz-border-radius-bottomleft: 0;
+}
+
+.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {
+  -webkit-border-bottom-right-radius: 0;
+          border-bottom-right-radius: 0;
+  -moz-border-radius-bottomright: 0;
+}
+
+.table-bordered caption + thead tr:first-child th:first-child,
+.table-bordered caption + tbody tr:first-child td:first-child,
+.table-bordered colgroup + thead tr:first-child th:first-child,
+.table-bordered colgroup + tbody tr:first-child td:first-child {
+  -webkit-border-top-left-radius: 4px;
+          border-top-left-radius: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+.table-bordered caption + thead tr:first-child th:last-child,
+.table-bordered caption + tbody tr:first-child td:last-child,
+.table-bordered colgroup + thead tr:first-child th:last-child,
+.table-bordered colgroup + tbody tr:first-child td:last-child {
+  -webkit-border-top-right-radius: 4px;
+          border-top-right-radius: 4px;
+  -moz-border-radius-topright: 4px;
+}
+
+.table-striped tbody > tr:nth-child(odd) > td,
+.table-striped tbody > tr:nth-child(odd) > th {
+  background-color: #f9f9f9;
+}
+
+.table-hover tbody tr:hover > td,
+.table-hover tbody tr:hover > th {
+  background-color: #f5f5f5;
+}
+
+table td[class*="span"],
+table th[class*="span"],
+.row-fluid table td[class*="span"],
+.row-fluid table th[class*="span"] {
+  display: table-cell;
+  float: none;
+  margin-left: 0;
+}
+
+.table td.span1,
+.table th.span1 {
+  float: none;
+  width: 44px;
+  margin-left: 0;
+}
+
+.table td.span2,
+.table th.span2 {
+  float: none;
+  width: 124px;
+  margin-left: 0;
+}
+
+.table td.span3,
+.table th.span3 {
+  float: none;
+  width: 204px;
+  margin-left: 0;
+}
+
+.table td.span4,
+.table th.span4 {
+  float: none;
+  width: 284px;
+  margin-left: 0;
+}
+
+.table td.span5,
+.table th.span5 {
+  float: none;
+  width: 364px;
+  margin-left: 0;
+}
+
+.table td.span6,
+.table th.span6 {
+  float: none;
+  width: 444px;
+  margin-left: 0;
+}
+
+.table td.span7,
+.table th.span7 {
+  float: none;
+  width: 524px;
+  margin-left: 0;
+}
+
+.table td.span8,
+.table th.span8 {
+  float: none;
+  width: 604px;
+  margin-left: 0;
+}
+
+.table td.span9,
+.table th.span9 {
+  float: none;
+  width: 684px;
+  margin-left: 0;
+}
+
+.table td.span10,
+.table th.span10 {
+  float: none;
+  width: 764px;
+  margin-left: 0;
+}
+
+.table td.span11,
+.table th.span11 {
+  float: none;
+  width: 844px;
+  margin-left: 0;
+}
+
+.table td.span12,
+.table th.span12 {
+  float: none;
+  width: 924px;
+  margin-left: 0;
+}
+
+.table tbody tr.success > td {
+  background-color: #dff0d8;
+}
+
+.table tbody tr.error > td {
+  background-color: #f2dede;
+}
+
+.table tbody tr.warning > td {
+  background-color: #fcf8e3;
+}
+
+.table tbody tr.info > td {
+  background-color: #d9edf7;
+}
+
+.table-hover tbody tr.success:hover > td {
+  background-color: #d0e9c6;
+}
+
+.table-hover tbody tr.error:hover > td {
+  background-color: #ebcccc;
+}
+
+.table-hover tbody tr.warning:hover > td {
+  background-color: #faf2cc;
+}
+
+.table-hover tbody tr.info:hover > td {
+  background-color: #c4e3f3;
+}
+
+[class^="icon-"],
+[class*=" icon-"] {
+  display: inline-block;
+  width: 14px;
+  height: 14px;
+  margin-top: 1px;
+  *margin-right: .3em;
+  line-height: 14px;
+  vertical-align: text-top;
+  background-image: url("../img/glyphicons-halflings.png");
+  background-position: 14px 14px;
+  background-repeat: no-repeat;
+}
+
+/* White icons with optional class, or on hover/focus/active states of certain elements */
+
+.icon-white,
+.nav-pills > .active > a > [class^="icon-"],
+.nav-pills > .active > a > [class*=" icon-"],
+.nav-list > .active > a > [class^="icon-"],
+.nav-list > .active > a > [class*=" icon-"],
+.navbar-inverse .nav > .active > a > [class^="icon-"],
+.navbar-inverse .nav > .active > a > [class*=" icon-"],
+.dropdown-menu > li > a:hover > [class^="icon-"],
+.dropdown-menu > li > a:focus > [class^="icon-"],
+.dropdown-menu > li > a:hover > [class*=" icon-"],
+.dropdown-menu > li > a:focus > [class*=" icon-"],
+.dropdown-menu > .active > a > [class^="icon-"],
+.dropdown-menu > .active > a > [class*=" icon-"],
+.dropdown-submenu:hover > a > [class^="icon-"],
+.dropdown-submenu:focus > a > [class^="icon-"],
+.dropdown-submenu:hover > a > [class*=" icon-"],
+.dropdown-submenu:focus > a > [class*=" icon-"] {
+  background-image: url("../img/glyphicons-halflings-white.png");
+}
+
+.icon-glass {
+  background-position: 0      0;
+}
+
+.icon-music {
+  background-position: -24px 0;
+}
+
+.icon-search {
+  background-position: -48px 0;
+}
+
+.icon-envelope {
+  background-position: -72px 0;
+}
+
+.icon-heart {
+  background-position: -96px 0;
+}
+
+.icon-star {
+  background-position: -120px 0;
+}
+
+.icon-star-empty {
+  background-position: -144px 0;
+}
+
+.icon-user {
+  background-position: -168px 0;
+}
+
+.icon-film {
+  background-position: -192px 0;
+}
+
+.icon-th-large {
+  background-position: -216px 0;
+}
+
+.icon-th {
+  background-position: -240px 0;
+}
+
+.icon-th-list {
+  background-position: -264px 0;
+}
+
+.icon-ok {
+  background-position: -288px 0;
+}
+
+.icon-remove {
+  background-position: -312px 0;
+}
+
+.icon-zoom-in {
+  background-position: -336px 0;
+}
+
+.icon-zoom-out {
+  background-position: -360px 0;
+}
+
+.icon-off {
+  background-position: -384px 0;
+}
+
+.icon-signal {
+  background-position: -408px 0;
+}
+
+.icon-cog {
+  background-position: -432px 0;
+}
+
+.icon-trash {
+  background-position: -456px 0;
+}
+
+.icon-home {
+  background-position: 0 -24px;
+}
+
+.icon-file {
+  background-position: -24px -24px;
+}
+
+.icon-time {
+  background-position: -48px -24px;
+}
+
+.icon-road {
+  background-position: -72px -24px;
+}
+
+.icon-download-alt {
+  background-position: -96px -24px;
+}
+
+.icon-download {
+  background-position: -120px -24px;
+}
+
+.icon-upload {
+  background-position: -144px -24px;
+}
+
+.icon-inbox {
+  background-position: -168px -24px;
+}
+
+.icon-play-circle {
+  background-position: -192px -24px;
+}
+
+.icon-repeat {
+  background-position: -216px -24px;
+}
+
+.icon-refresh {
+  background-position: -240px -24px;
+}
+
+.icon-list-alt {
+  background-position: -264px -24px;
+}
+
+.icon-lock {
+  background-position: -287px -24px;
+}
+
+.icon-flag {
+  background-position: -312px -24px;
+}
+
+.icon-headphones {
+  background-position: -336px -24px;
+}
+
+.icon-volume-off {
+  background-position: -360px -24px;
+}
+
+.icon-volume-down {
+  background-position: -384px -24px;
+}
+
+.icon-volume-up {
+  background-position: -408px -24px;
+}
+
+.icon-qrcode {
+  background-position: -432px -24px;
+}
+
+.icon-barcode {
+  background-position: -456px -24px;
+}
+
+.icon-tag {
+  background-position: 0 -48px;
+}
+
+.icon-tags {
+  background-position: -25px -48px;
+}
+
+.icon-book {
+  background-position: -48px -48px;
+}
+
+.icon-bookmark {
+  background-position: -72px -48px;
+}
+
+.icon-print {
+  background-position: -96px -48px;
+}
+
+.icon-camera {
+  background-position: -120px -48px;
+}
+
+.icon-font {
+  background-position: -144px -48px;
+}
+
+.icon-bold {
+  background-position: -167px -48px;
+}
+
+.icon-italic {
+  background-position: -192px -48px;
+}
+
+.icon-text-height {
+  background-position: -216px -48px;
+}
+
+.icon-text-width {
+  background-position: -240px -48px;
+}
+
+.icon-align-left {
+  background-position: -264px -48px;
+}
+
+.icon-align-center {
+  background-position: -288px -48px;
+}
+
+.icon-align-right {
+  background-position: -312px -48px;
+}
+
+.icon-align-justify {
+  background-position: -336px -48px;
+}
+
+.icon-list {
+  background-position: -360px -48px;
+}
+
+.icon-indent-left {
+  background-position: -384px -48px;
+}
+
+.icon-indent-right {
+  background-position: -408px -48px;
+}
+
+.icon-facetime-video {
+  background-position: -432px -48px;
+}
+
+.icon-picture {
+  background-position: -456px -48px;
+}
+
+.icon-pencil {
+  background-position: 0 -72px;
+}
+
+.icon-map-marker {
+  background-position: -24px -72px;
+}
+
+.icon-adjust {
+  background-position: -48px -72px;
+}
+
+.icon-tint {
+  background-position: -72px -72px;
+}
+
+.icon-edit {
+  background-position: -96px -72px;
+}
+
+.icon-share {
+  background-position: -120px -72px;
+}
+
+.icon-check {
+  background-position: -144px -72px;
+}
+
+.icon-move {
+  background-position: -168px -72px;
+}
+
+.icon-step-backward {
+  background-position: -192px -72px;
+}
+
+.icon-fast-backward {
+  background-position: -216px -72px;
+}
+
+.icon-backward {
+  background-position: -240px -72px;
+}
+
+.icon-play {
+  background-position: -264px -72px;
+}
+
+.icon-pause {
+  background-position: -288px -72px;
+}
+
+.icon-stop {
+  background-position: -312px -72px;
+}
+
+.icon-forward {
+  background-position: -336px -72px;
+}
+
+.icon-fast-forward {
+  background-position: -360px -72px;
+}
+
+.icon-step-forward {
+  background-position: -384px -72px;
+}
+
+.icon-eject {
+  background-position: -408px -72px;
+}
+
+.icon-chevron-left {
+  background-position: -432px -72px;
+}
+
+.icon-chevron-right {
+  background-position: -456px -72px;
+}
+
+.icon-plus-sign {
+  background-position: 0 -96px;
+}
+
+.icon-minus-sign {
+  background-position: -24px -96px;
+}
+
+.icon-remove-sign {
+  background-position: -48px -96px;
+}
+
+.icon-ok-sign {
+  background-position: -72px -96px;
+}
+
+.icon-question-sign {
+  background-position: -96px -96px;
+}
+
+.icon-info-sign {
+  background-position: -120px -96px;
+}
+
+.icon-screenshot {
+  background-position: -144px -96px;
+}
+
+.icon-remove-circle {
+  background-position: -168px -96px;
+}
+
+.icon-ok-circle {
+  background-position: -192px -96px;
+}
+
+.icon-ban-circle {
+  background-position: -216px -96px;
+}
+
+.icon-arrow-left {
+  background-position: -240px -96px;
+}
+
+.icon-arrow-right {
+  background-position: -264px -96px;
+}
+
+.icon-arrow-up {
+  background-position: -289px -96px;
+}
+
+.icon-arrow-down {
+  background-position: -312px -96px;
+}
+
+.icon-share-alt {
+  background-position: -336px -96px;
+}
+
+.icon-resize-full {
+  background-position: -360px -96px;
+}
+
+.icon-resize-small {
+  background-position: -384px -96px;
+}
+
+.icon-plus {
+  background-position: -408px -96px;
+}
+
+.icon-minus {
+  background-position: -433px -96px;
+}
+
+.icon-asterisk {
+  background-position: -456px -96px;
+}
+
+.icon-exclamation-sign {
+  background-position: 0 -120px;
+}
+
+.icon-gift {
+  background-position: -24px -120px;
+}
+
+.icon-leaf {
+  background-position: -48px -120px;
+}
+
+.icon-fire {
+  background-position: -72px -120px;
+}
+
+.icon-eye-open {
+  background-position: -96px -120px;
+}
+
+.icon-eye-close {
+  background-position: -120px -120px;
+}
+
+.icon-warning-sign {
+  background-position: -144px -120px;
+}
+
+.icon-plane {
+  background-position: -168px -120px;
+}
+
+.icon-calendar {
+  background-position: -192px -120px;
+}
+
+.icon-random {
+  width: 16px;
+  background-position: -216px -120px;
+}
+
+.icon-comment {
+  background-position: -240px -120px;
+}
+
+.icon-magnet {
+  background-position: -264px -120px;
+}
+
+.icon-chevron-up {
+  background-position: -288px -120px;
+}
+
+.icon-chevron-down {
+  background-position: -313px -119px;
+}
+
+.icon-retweet {
+  background-position: -336px -120px;
+}
+
+.icon-shopping-cart {
+  background-position: -360px -120px;
+}
+
+.icon-folder-close {
+  width: 16px;
+  background-position: -384px -120px;
+}
+
+.icon-folder-open {
+  width: 16px;
+  background-position: -408px -120px;
+}
+
+.icon-resize-vertical {
+  background-position: -432px -119px;
+}
+
+.icon-resize-horizontal {
+  background-position: -456px -118px;
+}
+
+.icon-hdd {
+  background-position: 0 -144px;
+}
+
+.icon-bullhorn {
+  background-position: -24px -144px;
+}
+
+.icon-bell {
+  background-position: -48px -144px;
+}
+
+.icon-certificate {
+  background-position: -72px -144px;
+}
+
+.icon-thumbs-up {
+  background-position: -96px -144px;
+}
+
+.icon-thumbs-down {
+  background-position: -120px -144px;
+}
+
+.icon-hand-right {
+  background-position: -144px -144px;
+}
+
+.icon-hand-left {
+  background-position: -168px -144px;
+}
+
+.icon-hand-up {
+  background-position: -192px -144px;
+}
+
+.icon-hand-down {
+  background-position: -216px -144px;
+}
+
+.icon-circle-arrow-right {
+  background-position: -240px -144px;
+}
+
+.icon-circle-arrow-left {
+  background-position: -264px -144px;
+}
+
+.icon-circle-arrow-up {
+  background-position: -288px -144px;
+}
+
+.icon-circle-arrow-down {
+  background-position: -312px -144px;
+}
+
+.icon-globe {
+  background-position: -336px -144px;
+}
+
+.icon-wrench {
+  background-position: -360px -144px;
+}
+
+.icon-tasks {
+  background-position: -384px -144px;
+}
+
+.icon-filter {
+  background-position: -408px -144px;
+}
+
+.icon-briefcase {
+  background-position: -432px -144px;
+}
+
+.icon-fullscreen {
+  background-position: -456px -144px;
+}
+
+.dropup,
+.dropdown {
+  position: relative;
+}
+
+.dropdown-toggle {
+  *margin-bottom: -3px;
+}
+
+.dropdown-toggle:active,
+.open .dropdown-toggle {
+  outline: 0;
+}
+
+.caret {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  vertical-align: top;
+  border-top: 4px solid #000000;
+  border-right: 4px solid transparent;
+  border-left: 4px solid transparent;
+  content: "";
+}
+
+.dropdown .caret {
+  margin-top: 8px;
+  margin-left: 2px;
+}
+
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: 1000;
+  display: none;
+  float: left;
+  min-width: 160px;
+  padding: 5px 0;
+  margin: 2px 0 0;
+  list-style: none;
+  background-color: #ffffff;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  *border-right-width: 2px;
+  *border-bottom-width: 2px;
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  -webkit-background-clip: padding-box;
+     -moz-background-clip: padding;
+          background-clip: padding-box;
+}
+
+.dropdown-menu.pull-right {
+  right: 0;
+  left: auto;
+}
+
+.dropdown-menu .divider {
+  *width: 100%;
+  height: 1px;
+  margin: 9px 1px;
+  *margin: -5px 0 5px;
+  overflow: hidden;
+  background-color: #e5e5e5;
+  border-bottom: 1px solid #ffffff;
+}
+
+.dropdown-menu > li > a {
+  display: block;
+  padding: 3px 20px;
+  clear: both;
+  font-weight: normal;
+  line-height: 20px;
+  color: #333333;
+  white-space: nowrap;
+}
+
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus,
+.dropdown-submenu:hover > a,
+.dropdown-submenu:focus > a {
+  color: #ffffff;
+  text-decoration: none;
+  background-color: #0081c2;
+  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
+  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
+  background-image: -o-linear-gradient(top, #0088cc, #0077b3);
+  background-image: linear-gradient(to bottom, #0088cc, #0077b3);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
+}
+
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  color: #ffffff;
+  text-decoration: none;
+  background-color: #0081c2;
+  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
+  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
+  background-image: -o-linear-gradient(top, #0088cc, #0077b3);
+  background-image: linear-gradient(to bottom, #0088cc, #0077b3);
+  background-repeat: repeat-x;
+  outline: 0;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
+}
+
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  color: #999999;
+}
+
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  text-decoration: none;
+  cursor: default;
+  background-color: transparent;
+  background-image: none;
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.open {
+  *z-index: 1000;
+}
+
+.open > .dropdown-menu {
+  display: block;
+}
+
+.pull-right > .dropdown-menu {
+  right: 0;
+  left: auto;
+}
+
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+  border-top: 0;
+  border-bottom: 4px solid #000000;
+  content: "";
+}
+
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+  top: auto;
+  bottom: 100%;
+  margin-bottom: 1px;
+}
+
+.dropdown-submenu {
+  position: relative;
+}
+
+.dropdown-submenu > .dropdown-menu {
+  top: 0;
+  left: 100%;
+  margin-top: -6px;
+  margin-left: -1px;
+  -webkit-border-radius: 0 6px 6px 6px;
+     -moz-border-radius: 0 6px 6px 6px;
+          border-radius: 0 6px 6px 6px;
+}
+
+.dropdown-submenu:hover > .dropdown-menu {
+  display: block;
+}
+
+.dropup .dropdown-submenu > .dropdown-menu {
+  top: auto;
+  bottom: 0;
+  margin-top: 0;
+  margin-bottom: -2px;
+  -webkit-border-radius: 5px 5px 5px 0;
+     -moz-border-radius: 5px 5px 5px 0;
+          border-radius: 5px 5px 5px 0;
+}
+
+.dropdown-submenu > a:after {
+  display: block;
+  float: right;
+  width: 0;
+  height: 0;
+  margin-top: 5px;
+  margin-right: -10px;
+  border-color: transparent;
+  border-left-color: #cccccc;
+  border-style: solid;
+  border-width: 5px 0 5px 5px;
+  content: " ";
+}
+
+.dropdown-submenu:hover > a:after {
+  border-left-color: #ffffff;
+}
+
+.dropdown-submenu.pull-left {
+  float: none;
+}
+
+.dropdown-submenu.pull-left > .dropdown-menu {
+  left: -100%;
+  margin-left: 10px;
+  -webkit-border-radius: 6px 0 6px 6px;
+     -moz-border-radius: 6px 0 6px 6px;
+          border-radius: 6px 0 6px 6px;
+}
+
+.dropdown .dropdown-menu .nav-header {
+  padding-right: 20px;
+  padding-left: 20px;
+}
+
+.typeahead {
+  z-index: 1051;
+  margin-top: 2px;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+.well {
+  min-height: 20px;
+  padding: 19px;
+  margin-bottom: 20px;
+  background-color: #f5f5f5;
+  border: 1px solid #e3e3e3;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+
+.well blockquote {
+  border-color: #ddd;
+  border-color: rgba(0, 0, 0, 0.15);
+}
+
+.well-large {
+  padding: 24px;
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+}
+
+.well-small {
+  padding: 9px;
+  -webkit-border-radius: 3px;
+     -moz-border-radius: 3px;
+          border-radius: 3px;
+}
+
+.fade {
+  opacity: 0;
+  -webkit-transition: opacity 0.15s linear;
+     -moz-transition: opacity 0.15s linear;
+       -o-transition: opacity 0.15s linear;
+          transition: opacity 0.15s linear;
+}
+
+.fade.in {
+  opacity: 1;
+}
+
+.collapse {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  -webkit-transition: height 0.35s ease;
+     -moz-transition: height 0.35s ease;
+       -o-transition: height 0.35s ease;
+          transition: height 0.35s ease;
+}
+
+.collapse.in {
+  height: auto;
+}
+
+.close {
+  float: right;
+  font-size: 20px;
+  font-weight: bold;
+  line-height: 20px;
+  color: #000000;
+  text-shadow: 0 1px 0 #ffffff;
+  opacity: 0.2;
+  filter: alpha(opacity=20);
+}
+
+.close:hover,
+.close:focus {
+  color: #000000;
+  text-decoration: none;
+  cursor: pointer;
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+
+button.close {
+  padding: 0;
+  cursor: pointer;
+  background: transparent;
+  border: 0;
+  -webkit-appearance: none;
+}
+
+.btn {
+  display: inline-block;
+  *display: inline;
+  padding: 4px 12px;
+  margin-bottom: 0;
+  *margin-left: .3em;
+  font-size: 14px;
+  line-height: 20px;
+  color: #333333;
+  text-align: center;
+  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
+  vertical-align: middle;
+  cursor: pointer;
+  background-color: #f5f5f5;
+  *background-color: #e6e6e6;
+  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
+  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
+  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
+  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
+  background-repeat: repeat-x;
+  border: 1px solid #cccccc;
+  *border: 0;
+  border-color: #e6e6e6 #e6e6e6 #bfbfbf;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  border-bottom-color: #b3b3b3;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  *zoom: 1;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn:hover,
+.btn:focus,
+.btn:active,
+.btn.active,
+.btn.disabled,
+.btn[disabled] {
+  color: #333333;
+  background-color: #e6e6e6;
+  *background-color: #d9d9d9;
+}
+
+.btn:active,
+.btn.active {
+  background-color: #cccccc \9;
+}
+
+.btn:first-child {
+  *margin-left: 0;
+}
+
+.btn:hover,
+.btn:focus {
+  color: #333333;
+  text-decoration: none;
+  background-position: 0 -15px;
+  -webkit-transition: background-position 0.1s linear;
+     -moz-transition: background-position 0.1s linear;
+       -o-transition: background-position 0.1s linear;
+          transition: background-position 0.1s linear;
+}
+
+.btn:focus {
+  outline: thin dotted #333;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+.btn.active,
+.btn:active {
+  background-image: none;
+  outline: 0;
+  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn.disabled,
+.btn[disabled] {
+  cursor: default;
+  background-image: none;
+  opacity: 0.65;
+  filter: alpha(opacity=65);
+  -webkit-box-shadow: none;
+     -moz-box-shadow: none;
+          box-shadow: none;
+}
+
+.btn-large {
+  padding: 11px 19px;
+  font-size: 17.5px;
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+}
+
+.btn-large [class^="icon-"],
+.btn-large [class*=" icon-"] {
+  margin-top: 4px;
+}
+
+.btn-small {
+  padding: 2px 10px;
+  font-size: 11.9px;
+  -webkit-border-radius: 3px;
+     -moz-border-radius: 3px;
+          border-radius: 3px;
+}
+
+.btn-small [class^="icon-"],
+.btn-small [class*=" icon-"] {
+  margin-top: 0;
+}
+
+.btn-mini [class^="icon-"],
+.btn-mini [class*=" icon-"] {
+  margin-top: -1px;
+}
+
+.btn-mini {
+  padding: 0 6px;
+  font-size: 10.5px;
+  -webkit-border-radius: 3px;
+     -moz-border-radius: 3px;
+          border-radius: 3px;
+}
+
+.btn-block {
+  display: block;
+  width: 100%;
+  padding-right: 0;
+  padding-left: 0;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.btn-block + .btn-block {
+  margin-top: 5px;
+}
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+
+.btn-primary.active,
+.btn-warning.active,
+.btn-danger.active,
+.btn-success.active,
+.btn-info.active,
+.btn-inverse.active {
+  color: rgba(255, 255, 255, 0.75);
+}
+
+.btn-primary {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #006dcc;
+  *background-color: #0044cc;
+  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+  background-image: linear-gradient(to bottom, #0088cc, #0044cc);
+  background-repeat: repeat-x;
+  border-color: #0044cc #0044cc #002a80;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-primary:hover,
+.btn-primary:focus,
+.btn-primary:active,
+.btn-primary.active,
+.btn-primary.disabled,
+.btn-primary[disabled] {
+  color: #ffffff;
+  background-color: #0044cc;
+  *background-color: #003bb3;
+}
+
+.btn-primary:active,
+.btn-primary.active {
+  background-color: #003399 \9;
+}
+
+.btn-warning {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #faa732;
+  *background-color: #f89406;
+  background-image: -moz-linear-gradient(top, #fbb450, #f89406);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
+  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
+  background-image: -o-linear-gradient(top, #fbb450, #f89406);
+  background-image: linear-gradient(to bottom, #fbb450, #f89406);
+  background-repeat: repeat-x;
+  border-color: #f89406 #f89406 #ad6704;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-warning:hover,
+.btn-warning:focus,
+.btn-warning:active,
+.btn-warning.active,
+.btn-warning.disabled,
+.btn-warning[disabled] {
+  color: #ffffff;
+  background-color: #f89406;
+  *background-color: #df8505;
+}
+
+.btn-warning:active,
+.btn-warning.active {
+  background-color: #c67605 \9;
+}
+
+.btn-danger {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #da4f49;
+  *background-color: #bd362f;
+  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
+  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
+  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
+  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
+  background-repeat: repeat-x;
+  border-color: #bd362f #bd362f #802420;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-danger:hover,
+.btn-danger:focus,
+.btn-danger:active,
+.btn-danger.active,
+.btn-danger.disabled,
+.btn-danger[disabled] {
+  color: #ffffff;
+  background-color: #bd362f;
+  *background-color: #a9302a;
+}
+
+.btn-danger:active,
+.btn-danger.active {
+  background-color: #942a25 \9;
+}
+
+.btn-success {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #5bb75b;
+  *background-color: #51a351;
+  background-image: -moz-linear-gradient(top, #62c462, #51a351);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
+  background-image: -webkit-linear-gradient(top, #62c462, #51a351);
+  background-image: -o-linear-gradient(top, #62c462, #51a351);
+  background-image: linear-gradient(to bottom, #62c462, #51a351);
+  background-repeat: repeat-x;
+  border-color: #51a351 #51a351 #387038;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-success:hover,
+.btn-success:focus,
+.btn-success:active,
+.btn-success.active,
+.btn-success.disabled,
+.btn-success[disabled] {
+  color: #ffffff;
+  background-color: #51a351;
+  *background-color: #499249;
+}
+
+.btn-success:active,
+.btn-success.active {
+  background-color: #408140 \9;
+}
+
+.btn-info {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #49afcd;
+  *background-color: #2f96b4;
+  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));
+  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
+  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
+  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);
+  background-repeat: repeat-x;
+  border-color: #2f96b4 #2f96b4 #1f6377;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-info:hover,
+.btn-info:focus,
+.btn-info:active,
+.btn-info.active,
+.btn-info.disabled,
+.btn-info[disabled] {
+  color: #ffffff;
+  background-color: #2f96b4;
+  *background-color: #2a85a0;
+}
+
+.btn-info:active,
+.btn-info.active {
+  background-color: #24748c \9;
+}
+
+.btn-inverse {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #363636;
+  *background-color: #222222;
+  background-image: -moz-linear-gradient(top, #444444, #222222);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
+  background-image: -webkit-linear-gradient(top, #444444, #222222);
+  background-image: -o-linear-gradient(top, #444444, #222222);
+  background-image: linear-gradient(to bottom, #444444, #222222);
+  background-repeat: repeat-x;
+  border-color: #222222 #222222 #000000;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-inverse:hover,
+.btn-inverse:focus,
+.btn-inverse:active,
+.btn-inverse.active,
+.btn-inverse.disabled,
+.btn-inverse[disabled] {
+  color: #ffffff;
+  background-color: #222222;
+  *background-color: #151515;
+}
+
+.btn-inverse:active,
+.btn-inverse.active {
+  background-color: #080808 \9;
+}
+
+button.btn,
+input[type="submit"].btn {
+  *padding-top: 3px;
+  *padding-bottom: 3px;
+}
+
+button.btn::-moz-focus-inner,
+input[type="submit"].btn::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+
+button.btn.btn-large,
+input[type="submit"].btn.btn-large {
+  *padding-top: 7px;
+  *padding-bottom: 7px;
+}
+
+button.btn.btn-small,
+input[type="submit"].btn.btn-small {
+  *padding-top: 3px;
+  *padding-bottom: 3px;
+}
+
+button.btn.btn-mini,
+input[type="submit"].btn.btn-mini {
+  *padding-top: 1px;
+  *padding-bottom: 1px;
+}
+
+.btn-link,
+.btn-link:active,
+.btn-link[disabled] {
+  background-color: transparent;
+  background-image: none;
+  -webkit-box-shadow: none;
+     -moz-box-shadow: none;
+          box-shadow: none;
+}
+
+.btn-link {
+  color: #0088cc;
+  cursor: pointer;
+  border-color: transparent;
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.btn-link:hover,
+.btn-link:focus {
+  color: #005580;
+  text-decoration: underline;
+  background-color: transparent;
+}
+
+.btn-link[disabled]:hover,
+.btn-link[disabled]:focus {
+  color: #333333;
+  text-decoration: none;
+}
+
+.btn-group {
+  position: relative;
+  display: inline-block;
+  *display: inline;
+  *margin-left: .3em;
+  font-size: 0;
+  white-space: nowrap;
+  vertical-align: middle;
+  *zoom: 1;
+}
+
+.btn-group:first-child {
+  *margin-left: 0;
+}
+
+.btn-group + .btn-group {
+  margin-left: 5px;
+}
+
+.btn-toolbar {
+  margin-top: 10px;
+  margin-bottom: 10px;
+  font-size: 0;
+}
+
+.btn-toolbar > .btn + .btn,
+.btn-toolbar > .btn-group + .btn,
+.btn-toolbar > .btn + .btn-group {
+  margin-left: 5px;
+}
+
+.btn-group > .btn {
+  position: relative;
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.btn-group > .btn + .btn {
+  margin-left: -1px;
+}
+
+.btn-group > .btn,
+.btn-group > .dropdown-menu,
+.btn-group > .popover {
+  font-size: 14px;
+}
+
+.btn-group > .btn-mini {
+  font-size: 10.5px;
+}
+
+.btn-group > .btn-small {
+  font-size: 11.9px;
+}
+
+.btn-group > .btn-large {
+  font-size: 17.5px;
+}
+
+.btn-group > .btn:first-child {
+  margin-left: 0;
+  -webkit-border-bottom-left-radius: 4px;
+          border-bottom-left-radius: 4px;
+  -webkit-border-top-left-radius: 4px;
+          border-top-left-radius: 4px;
+  -moz-border-radius-bottomleft: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+.btn-group > .btn:last-child,
+.btn-group > .dropdown-toggle {
+  -webkit-border-top-right-radius: 4px;
+          border-top-right-radius: 4px;
+  -webkit-border-bottom-right-radius: 4px;
+          border-bottom-right-radius: 4px;
+  -moz-border-radius-topright: 4px;
+  -moz-border-radius-bottomright: 4px;
+}
+
+.btn-group > .btn.large:first-child {
+  margin-left: 0;
+  -webkit-border-bottom-left-radius: 6px;
+          border-bottom-left-radius: 6px;
+  -webkit-border-top-left-radius: 6px;
+          border-top-left-radius: 6px;
+  -moz-border-radius-bottomleft: 6px;
+  -moz-border-radius-topleft: 6px;
+}
+
+.btn-group > .btn.large:last-child,
+.btn-group > .large.dropdown-toggle {
+  -webkit-border-top-right-radius: 6px;
+          border-top-right-radius: 6px;
+  -webkit-border-bottom-right-radius: 6px;
+          border-bottom-right-radius: 6px;
+  -moz-border-radius-topright: 6px;
+  -moz-border-radius-bottomright: 6px;
+}
+
+.btn-group > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group > .btn:active,
+.btn-group > .btn.active {
+  z-index: 2;
+}
+
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+
+.btn-group > .btn + .dropdown-toggle {
+  *padding-top: 5px;
+  padding-right: 8px;
+  *padding-bottom: 5px;
+  padding-left: 8px;
+  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn-group > .btn-mini + .dropdown-toggle {
+  *padding-top: 2px;
+  padding-right: 5px;
+  *padding-bottom: 2px;
+  padding-left: 5px;
+}
+
+.btn-group > .btn-small + .dropdown-toggle {
+  *padding-top: 5px;
+  *padding-bottom: 4px;
+}
+
+.btn-group > .btn-large + .dropdown-toggle {
+  *padding-top: 7px;
+  padding-right: 12px;
+  *padding-bottom: 7px;
+  padding-left: 12px;
+}
+
+.btn-group.open .dropdown-toggle {
+  background-image: none;
+  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn-group.open .btn.dropdown-toggle {
+  background-color: #e6e6e6;
+}
+
+.btn-group.open .btn-primary.dropdown-toggle {
+  background-color: #0044cc;
+}
+
+.btn-group.open .btn-warning.dropdown-toggle {
+  background-color: #f89406;
+}
+
+.btn-group.open .btn-danger.dropdown-toggle {
+  background-color: #bd362f;
+}
+
+.btn-group.open .btn-success.dropdown-toggle {
+  background-color: #51a351;
+}
+
+.btn-group.open .btn-info.dropdown-toggle {
+  background-color: #2f96b4;
+}
+
+.btn-group.open .btn-inverse.dropdown-toggle {
+  background-color: #222222;
+}
+
+.btn .caret {
+  margin-top: 8px;
+  margin-left: 0;
+}
+
+.btn-large .caret {
+  margin-top: 6px;
+}
+
+.btn-large .caret {
+  border-top-width: 5px;
+  border-right-width: 5px;
+  border-left-width: 5px;
+}
+
+.btn-mini .caret,
+.btn-small .caret {
+  margin-top: 8px;
+}
+
+.dropup .btn-large .caret {
+  border-bottom-width: 5px;
+}
+
+.btn-primary .caret,
+.btn-warning .caret,
+.btn-danger .caret,
+.btn-info .caret,
+.btn-success .caret,
+.btn-inverse .caret {
+  border-top-color: #ffffff;
+  border-bottom-color: #ffffff;
+}
+
+.btn-group-vertical {
+  display: inline-block;
+  *display: inline;
+  /* IE7 inline-block hack */
+
+  *zoom: 1;
+}
+
+.btn-group-vertical > .btn {
+  display: block;
+  float: none;
+  max-width: 100%;
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.btn-group-vertical > .btn + .btn {
+  margin-top: -1px;
+  margin-left: 0;
+}
+
+.btn-group-vertical > .btn:first-child {
+  -webkit-border-radius: 4px 4px 0 0;
+     -moz-border-radius: 4px 4px 0 0;
+          border-radius: 4px 4px 0 0;
+}
+
+.btn-group-vertical > .btn:last-child {
+  -webkit-border-radius: 0 0 4px 4px;
+     -moz-border-radius: 0 0 4px 4px;
+          border-radius: 0 0 4px 4px;
+}
+
+.btn-group-vertical > .btn-large:first-child {
+  -webkit-border-radius: 6px 6px 0 0;
+     -moz-border-radius: 6px 6px 0 0;
+          border-radius: 6px 6px 0 0;
+}
+
+.btn-group-vertical > .btn-large:last-child {
+  -webkit-border-radius: 0 0 6px 6px;
+     -moz-border-radius: 0 0 6px 6px;
+          border-radius: 0 0 6px 6px;
+}
+
+.alert {
+  padding: 8px 35px 8px 14px;
+  margin-bottom: 20px;
+  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+  background-color: #fcf8e3;
+  border: 1px solid #fbeed5;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+.alert,
+.alert h4 {
+  color: #c09853;
+}
+
+.alert h4 {
+  margin: 0;
+}
+
+.alert .close {
+  position: relative;
+  top: -2px;
+  right: -21px;
+  line-height: 20px;
+}
+
+.alert-success {
+  color: #468847;
+  background-color: #dff0d8;
+  border-color: #d6e9c6;
+}
+
+.alert-success h4 {
+  color: #468847;
+}
+
+.alert-danger,
+.alert-error {
+  color: #b94a48;
+  background-color: #f2dede;
+  border-color: #eed3d7;
+}
+
+.alert-danger h4,
+.alert-error h4 {
+  color: #b94a48;
+}
+
+.alert-info {
+  color: #3a87ad;
+  background-color: #d9edf7;
+  border-color: #bce8f1;
+}
+
+.alert-info h4 {
+  color: #3a87ad;
+}
+
+.alert-block {
+  padding-top: 14px;
+  padding-bottom: 14px;
+}
+
+.alert-block > p,
+.alert-block > ul {
+  margin-bottom: 0;
+}
+
+.alert-block p + p {
+  margin-top: 5px;
+}
+
+.nav {
+  margin-bottom: 20px;
+  margin-left: 0;
+  list-style: none;
+}
+
+.nav > li > a {
+  display: block;
+}
+
+.nav > li > a:hover,
+.nav > li > a:focus {
+  text-decoration: none;
+  background-color: #eeeeee;
+}
+
+.nav > li > a > img {
+  max-width: none;
+}
+
+.nav > .pull-right {
+  float: right;
+}
+
+.nav-header {
+  display: block;
+  padding: 3px 15px;
+  font-size: 11px;
+  font-weight: bold;
+  line-height: 20px;
+  color: #999999;
+  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+  text-transform: uppercase;
+}
+
+.nav li + .nav-header {
+  margin-top: 9px;
+}
+
+.nav-list {
+  padding-right: 15px;
+  padding-left: 15px;
+  margin-bottom: 0;
+}
+
+.nav-list > li > a,
+.nav-list .nav-header {
+  margin-right: -15px;
+  margin-left: -15px;
+  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+}
+
+.nav-list > li > a {
+  padding: 3px 15px;
+}
+
+.nav-list > .active > a,
+.nav-list > .active > a:hover,
+.nav-list > .active > a:focus {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
+  background-color: #0088cc;
+}
+
+.nav-list [class^="icon-"],
+.nav-list [class*=" icon-"] {
+  margin-right: 2px;
+}
+
+.nav-list .divider {
+  *width: 100%;
+  height: 1px;
+  margin: 9px 1px;
+  *margin: -5px 0 5px;
+  overflow: hidden;
+  background-color: #e5e5e5;
+  border-bottom: 1px solid #ffffff;
+}
+
+.nav-tabs,
+.nav-pills {
+  *zoom: 1;
+}
+
+.nav-tabs:before,
+.nav-pills:before,
+.nav-tabs:after,
+.nav-pills:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.nav-tabs:after,
+.nav-pills:after {
+  clear: both;
+}
+
+.nav-tabs > li,
+.nav-pills > li {
+  float: left;
+}
+
+.nav-tabs > li > a,
+.nav-pills > li > a {
+  padding-right: 12px;
+  padding-left: 12px;
+  margin-right: 2px;
+  line-height: 14px;
+}
+
+.nav-tabs {
+  border-bottom: 1px solid #ddd;
+}
+
+.nav-tabs > li {
+  margin-bottom: -1px;
+}
+
+.nav-tabs > li > a {
+  padding-top: 8px;
+  padding-bottom: 8px;
+  line-height: 20px;
+  border: 1px solid transparent;
+  -webkit-border-radius: 4px 4px 0 0;
+     -moz-border-radius: 4px 4px 0 0;
+          border-radius: 4px 4px 0 0;
+}
+
+.nav-tabs > li > a:hover,
+.nav-tabs > li > a:focus {
+  border-color: #eeeeee #eeeeee #dddddd;
+}
+
+.nav-tabs > .active > a,
+.nav-tabs > .active > a:hover,
+.nav-tabs > .active > a:focus {
+  color: #555555;
+  cursor: default;
+  background-color: #ffffff;
+  border: 1px solid #ddd;
+  border-bottom-color: transparent;
+}
+
+.nav-pills > li > a {
+  padding-top: 8px;
+  padding-bottom: 8px;
+  margin-top: 2px;
+  margin-bottom: 2px;
+  -webkit-border-radius: 5px;
+     -moz-border-radius: 5px;
+          border-radius: 5px;
+}
+
+.nav-pills > .active > a,
+.nav-pills > .active > a:hover,
+.nav-pills > .active > a:focus {
+  color: #ffffff;
+  background-color: #0088cc;
+}
+
+.nav-stacked > li {
+  float: none;
+}
+
+.nav-stacked > li > a {
+  margin-right: 0;
+}
+
+.nav-tabs.nav-stacked {
+  border-bottom: 0;
+}
+
+.nav-tabs.nav-stacked > li > a {
+  border: 1px solid #ddd;
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.nav-tabs.nav-stacked > li:first-child > a {
+  -webkit-border-top-right-radius: 4px;
+          border-top-right-radius: 4px;
+  -webkit-border-top-left-radius: 4px;
+          border-top-left-radius: 4px;
+  -moz-border-radius-topright: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+.nav-tabs.nav-stacked > li:last-child > a {
+  -webkit-border-bottom-right-radius: 4px;
+          border-bottom-right-radius: 4px;
+  -webkit-border-bottom-left-radius: 4px;
+          border-bottom-left-radius: 4px;
+  -moz-border-radius-bottomright: 4px;
+  -moz-border-radius-bottomleft: 4px;
+}
+
+.nav-tabs.nav-stacked > li > a:hover,
+.nav-tabs.nav-stacked > li > a:focus {
+  z-index: 2;
+  border-color: #ddd;
+}
+
+.nav-pills.nav-stacked > li > a {
+  margin-bottom: 3px;
+}
+
+.nav-pills.nav-stacked > li:last-child > a {
+  margin-bottom: 1px;
+}
+
+.nav-tabs .dropdown-menu {
+  -webkit-border-radius: 0 0 6px 6px;
+     -moz-border-radius: 0 0 6px 6px;
+          border-radius: 0 0 6px 6px;
+}
+
+.nav-pills .dropdown-menu {
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+}
+
+.nav .dropdown-toggle .caret {
+  margin-top: 6px;
+  border-top-color: #0088cc;
+  border-bottom-color: #0088cc;
+}
+
+.nav .dropdown-toggle:hover .caret,
+.nav .dropdown-toggle:focus .caret {
+  border-top-color: #005580;
+  border-bottom-color: #005580;
+}
+
+/* move down carets for tabs */
+
+.nav-tabs .dropdown-toggle .caret {
+  margin-top: 8px;
+}
+
+.nav .active .dropdown-toggle .caret {
+  border-top-color: #fff;
+  border-bottom-color: #fff;
+}
+
+.nav-tabs .active .dropdown-toggle .caret {
+  border-top-color: #555555;
+  border-bottom-color: #555555;
+}
+
+.nav > .dropdown.active > a:hover,
+.nav > .dropdown.active > a:focus {
+  cursor: pointer;
+}
+
+.nav-tabs .open .dropdown-toggle,
+.nav-pills .open .dropdown-toggle,
+.nav > li.dropdown.open.active > a:hover,
+.nav > li.dropdown.open.active > a:focus {
+  color: #ffffff;
+  background-color: #999999;
+  border-color: #999999;
+}
+
+.nav li.dropdown.open .caret,
+.nav li.dropdown.open.active .caret,
+.nav li.dropdown.open a:hover .caret,
+.nav li.dropdown.open a:focus .caret {
+  border-top-color: #ffffff;
+  border-bottom-color: #ffffff;
+  opacity: 1;
+  filter: alpha(opacity=100);
+}
+
+.tabs-stacked .open > a:hover,
+.tabs-stacked .open > a:focus {
+  border-color: #999999;
+}
+
+.tabbable {
+  *zoom: 1;
+}
+
+.tabbable:before,
+.tabbable:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.tabbable:after {
+  clear: both;
+}
+
+.tab-content {
+  overflow: auto;
+}
+
+.tabs-below > .nav-tabs,
+.tabs-right > .nav-tabs,
+.tabs-left > .nav-tabs {
+  border-bottom: 0;
+}
+
+.tab-content > .tab-pane,
+.pill-content > .pill-pane {
+  display: none;
+}
+
+.tab-content > .active,
+.pill-content > .active {
+  display: block;
+}
+
+.tabs-below > .nav-tabs {
+  border-top: 1px solid #ddd;
+}
+
+.tabs-below > .nav-tabs > li {
+  margin-top: -1px;
+  margin-bottom: 0;
+}
+
+.tabs-below > .nav-tabs > li > a {
+  -webkit-border-radius: 0 0 4px 4px;
+     -moz-border-radius: 0 0 4px 4px;
+          border-radius: 0 0 4px 4px;
+}
+
+.tabs-below > .nav-tabs > li > a:hover,
+.tabs-below > .nav-tabs > li > a:focus {
+  border-top-color: #ddd;
+  border-bottom-color: transparent;
+}
+
+.tabs-below > .nav-tabs > .active > a,
+.tabs-below > .nav-tabs > .active > a:hover,
+.tabs-below > .nav-tabs > .active > a:focus {
+  border-color: transparent #ddd #ddd #ddd;
+}
+
+.tabs-left > .nav-tabs > li,
+.tabs-right > .nav-tabs > li {
+  float: none;
+}
+
+.tabs-left > .nav-tabs > li > a,
+.tabs-right > .nav-tabs > li > a {
+  min-width: 74px;
+  margin-right: 0;
+  margin-bottom: 3px;
+}
+
+.tabs-left > .nav-tabs {
+  float: left;
+  margin-right: 19px;
+  border-right: 1px solid #ddd;
+}
+
+.tabs-left > .nav-tabs > li > a {
+  margin-right: -1px;
+  -webkit-border-radius: 4px 0 0 4px;
+     -moz-border-radius: 4px 0 0 4px;
+          border-radius: 4px 0 0 4px;
+}
+
+.tabs-left > .nav-tabs > li > a:hover,
+.tabs-left > .nav-tabs > li > a:focus {
+  border-color: #eeeeee #dddddd #eeeeee #eeeeee;
+}
+
+.tabs-left > .nav-tabs .active > a,
+.tabs-left > .nav-tabs .active > a:hover,
+.tabs-left > .nav-tabs .active > a:focus {
+  border-color: #ddd transparent #ddd #ddd;
+  *border-right-color: #ffffff;
+}
+
+.tabs-right > .nav-tabs {
+  float: right;
+  margin-left: 19px;
+  border-left: 1px solid #ddd;
+}
+
+.tabs-right > .nav-tabs > li > a {
+  margin-left: -1px;
+  -webkit-border-radius: 0 4px 4px 0;
+     -moz-border-radius: 0 4px 4px 0;
+          border-radius: 0 4px 4px 0;
+}
+
+.tabs-right > .nav-tabs > li > a:hover,
+.tabs-right > .nav-tabs > li > a:focus {
+  border-color: #eeeeee #eeeeee #eeeeee #dddddd;
+}
+
+.tabs-right > .nav-tabs .active > a,
+.tabs-right > .nav-tabs .active > a:hover,
+.tabs-right > .nav-tabs .active > a:focus {
+  border-color: #ddd #ddd #ddd transparent;
+  *border-left-color: #ffffff;
+}
+
+.nav > .disabled > a {
+  color: #999999;
+}
+
+.nav > .disabled > a:hover,
+.nav > .disabled > a:focus {
+  text-decoration: none;
+  cursor: default;
+  background-color: transparent;
+}
+
+.navbar {
+  *position: relative;
+  *z-index: 2;
+  margin-bottom: 20px;
+  overflow: visible;
+}
+
+.navbar-inner {
+  min-height: 40px;
+  padding-right: 20px;
+  padding-left: 20px;
+  background-color: #fafafa;
+  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));
+  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);
+  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);
+  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);
+  background-repeat: repeat-x;
+  border: 1px solid #d4d4d4;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);
+  *zoom: 1;
+  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+}
+
+.navbar-inner:before,
+.navbar-inner:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.navbar-inner:after {
+  clear: both;
+}
+
+.navbar .container {
+  width: auto;
+}
+
+.nav-collapse.collapse {
+  height: auto;
+  overflow: visible;
+}
+
+.navbar .brand {
+  display: block;
+  float: left;
+  padding: 10px 20px 10px;
+  margin-left: -20px;
+  font-size: 20px;
+  font-weight: 200;
+  color: #777777;
+  text-shadow: 0 1px 0 #ffffff;
+}
+
+.navbar .brand:hover,
+.navbar .brand:focus {
+  text-decoration: none;
+}
+
+.navbar-text {
+  margin-bottom: 0;
+  line-height: 40px;
+  color: #777777;
+}
+
+.navbar-link {
+  color: #777777;
+}
+
+.navbar-link:hover,
+.navbar-link:focus {
+  color: #333333;
+}
+
+.navbar .divider-vertical {
+  height: 40px;
+  margin: 0 9px;
+  border-right: 1px solid #ffffff;
+  border-left: 1px solid #f2f2f2;
+}
+
+.navbar .btn,
+.navbar .btn-group {
+  margin-top: 5px;
+}
+
+.navbar .btn-group .btn,
+.navbar .input-prepend .btn,
+.navbar .input-append .btn,
+.navbar .input-prepend .btn-group,
+.navbar .input-append .btn-group {
+  margin-top: 0;
+}
+
+.navbar-form {
+  margin-bottom: 0;
+  *zoom: 1;
+}
+
+.navbar-form:before,
+.navbar-form:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.navbar-form:after {
+  clear: both;
+}
+
+.navbar-form input,
+.navbar-form select,
+.navbar-form .radio,
+.navbar-form .checkbox {
+  margin-top: 5px;
+}
+
+.navbar-form input,
+.navbar-form select,
+.navbar-form .btn {
+  display: inline-block;
+  margin-bottom: 0;
+}
+
+.navbar-form input[type="image"],
+.navbar-form input[type="checkbox"],
+.navbar-form input[type="radio"] {
+  margin-top: 3px;
+}
+
+.navbar-form .input-append,
+.navbar-form .input-prepend {
+  margin-top: 5px;
+  white-space: nowrap;
+}
+
+.navbar-form .input-append input,
+.navbar-form .input-prepend input {
+  margin-top: 0;
+}
+
+.navbar-search {
+  position: relative;
+  float: left;
+  margin-top: 5px;
+  margin-bottom: 0;
+}
+
+.navbar-search .search-query {
+  padding: 4px 14px;
+  margin-bottom: 0;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 13px;
+  font-weight: normal;
+  line-height: 1;
+  -webkit-border-radius: 15px;
+     -moz-border-radius: 15px;
+          border-radius: 15px;
+}
+
+.navbar-static-top {
+  position: static;
+  margin-bottom: 0;
+}
+
+.navbar-static-top .navbar-inner {
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  position: fixed;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+  margin-bottom: 0;
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-static-top .navbar-inner {
+  border-width: 0 0 1px;
+}
+
+.navbar-fixed-bottom .navbar-inner {
+  border-width: 1px 0 0;
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-fixed-bottom .navbar-inner {
+  padding-right: 0;
+  padding-left: 0;
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.navbar-static-top .container,
+.navbar-fixed-top .container,
+.navbar-fixed-bottom .container {
+  width: 940px;
+}
+
+.navbar-fixed-top {
+  top: 0;
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-static-top .navbar-inner {
+  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+}
+
+.navbar-fixed-bottom {
+  bottom: 0;
+}
+
+.navbar-fixed-bottom .navbar-inner {
+  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
+     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
+          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
+}
+
+.navbar .nav {
+  position: relative;
+  left: 0;
+  display: block;
+  float: left;
+  margin: 0 10px 0 0;
+}
+
+.navbar .nav.pull-right {
+  float: right;
+  margin-right: 0;
+}
+
+.navbar .nav > li {
+  float: left;
+}
+
+.navbar .nav > li > a {
+  float: none;
+  padding: 10px 15px 10px;
+  color: #777777;
+  text-decoration: none;
+  text-shadow: 0 1px 0 #ffffff;
+}
+
+.navbar .nav .dropdown-toggle .caret {
+  margin-top: 8px;
+}
+
+.navbar .nav > li > a:focus,
+.navbar .nav > li > a:hover {
+  color: #333333;
+  text-decoration: none;
+  background-color: transparent;
+}
+
+.navbar .nav > .active > a,
+.navbar .nav > .active > a:hover,
+.navbar .nav > .active > a:focus {
+  color: #555555;
+  text-decoration: none;
+  background-color: #e5e5e5;
+  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
+     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
+          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
+}
+
+.navbar .btn-navbar {
+  display: none;
+  float: right;
+  padding: 7px 10px;
+  margin-right: 5px;
+  margin-left: 5px;
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #ededed;
+  *background-color: #e5e5e5;
+  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));
+  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);
+  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);
+  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);
+  background-repeat: repeat-x;
+  border-color: #e5e5e5 #e5e5e5 #bfbfbf;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
+     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
+}
+
+.navbar .btn-navbar:hover,
+.navbar .btn-navbar:focus,
+.navbar .btn-navbar:active,
+.navbar .btn-navbar.active,
+.navbar .btn-navbar.disabled,
+.navbar .btn-navbar[disabled] {
+  color: #ffffff;
+  background-color: #e5e5e5;
+  *background-color: #d9d9d9;
+}
+
+.navbar .btn-navbar:active,
+.navbar .btn-navbar.active {
+  background-color: #cccccc \9;
+}
+
+.navbar .btn-navbar .icon-bar {
+  display: block;
+  width: 18px;
+  height: 2px;
+  background-color: #f5f5f5;
+  -webkit-border-radius: 1px;
+     -moz-border-radius: 1px;
+          border-radius: 1px;
+  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
+     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
+          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
+}
+
+.btn-navbar .icon-bar + .icon-bar {
+  margin-top: 3px;
+}
+
+.navbar .nav > li > .dropdown-menu:before {
+  position: absolute;
+  top: -7px;
+  left: 9px;
+  display: inline-block;
+  border-right: 7px solid transparent;
+  border-bottom: 7px solid #ccc;
+  border-left: 7px solid transparent;
+  border-bottom-color: rgba(0, 0, 0, 0.2);
+  content: '';
+}
+
+.navbar .nav > li > .dropdown-menu:after {
+  position: absolute;
+  top: -6px;
+  left: 10px;
+  display: inline-block;
+  border-right: 6px solid transparent;
+  border-bottom: 6px solid #ffffff;
+  border-left: 6px solid transparent;
+  content: '';
+}
+
+.navbar-fixed-bottom .nav > li > .dropdown-menu:before {
+  top: auto;
+  bottom: -7px;
+  border-top: 7px solid #ccc;
+  border-bottom: 0;
+  border-top-color: rgba(0, 0, 0, 0.2);
+}
+
+.navbar-fixed-bottom .nav > li > .dropdown-menu:after {
+  top: auto;
+  bottom: -6px;
+  border-top: 6px solid #ffffff;
+  border-bottom: 0;
+}
+
+.navbar .nav li.dropdown > a:hover .caret,
+.navbar .nav li.dropdown > a:focus .caret {
+  border-top-color: #333333;
+  border-bottom-color: #333333;
+}
+
+.navbar .nav li.dropdown.open > .dropdown-toggle,
+.navbar .nav li.dropdown.active > .dropdown-toggle,
+.navbar .nav li.dropdown.open.active > .dropdown-toggle {
+  color: #555555;
+  background-color: #e5e5e5;
+}
+
+.navbar .nav li.dropdown > .dropdown-toggle .caret {
+  border-top-color: #777777;
+  border-bottom-color: #777777;
+}
+
+.navbar .nav li.dropdown.open > .dropdown-toggle .caret,
+.navbar .nav li.dropdown.active > .dropdown-toggle .caret,
+.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {
+  border-top-color: #555555;
+  border-bottom-color: #555555;
+}
+
+.navbar .pull-right > li > .dropdown-menu,
+.navbar .nav > li > .dropdown-menu.pull-right {
+  right: 0;
+  left: auto;
+}
+
+.navbar .pull-right > li > .dropdown-menu:before,
+.navbar .nav > li > .dropdown-menu.pull-right:before {
+  right: 12px;
+  left: auto;
+}
+
+.navbar .pull-right > li > .dropdown-menu:after,
+.navbar .nav > li > .dropdown-menu.pull-right:after {
+  right: 13px;
+  left: auto;
+}
+
+.navbar .pull-right > li > .dropdown-menu .dropdown-menu,
+.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {
+  right: 100%;
+  left: auto;
+  margin-right: -1px;
+  margin-left: 0;
+  -webkit-border-radius: 6px 0 6px 6px;
+     -moz-border-radius: 6px 0 6px 6px;
+          border-radius: 6px 0 6px 6px;
+}
+
+.navbar-inverse .navbar-inner {
+  background-color: #1b1b1b;
+  background-image: -moz-linear-gradient(top, #222222, #111111);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));
+  background-image: -webkit-linear-gradient(top, #222222, #111111);
+  background-image: -o-linear-gradient(top, #222222, #111111);
+  background-image: linear-gradient(to bottom, #222222, #111111);
+  background-repeat: repeat-x;
+  border-color: #252525;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);
+}
+
+.navbar-inverse .brand,
+.navbar-inverse .nav > li > a {
+  color: #999999;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+
+.navbar-inverse .brand:hover,
+.navbar-inverse .nav > li > a:hover,
+.navbar-inverse .brand:focus,
+.navbar-inverse .nav > li > a:focus {
+  color: #ffffff;
+}
+
+.navbar-inverse .brand {
+  color: #999999;
+}
+
+.navbar-inverse .navbar-text {
+  color: #999999;
+}
+
+.navbar-inverse .nav > li > a:focus,
+.navbar-inverse .nav > li > a:hover {
+  color: #ffffff;
+  background-color: transparent;
+}
+
+.navbar-inverse .nav .active > a,
+.navbar-inverse .nav .active > a:hover,
+.navbar-inverse .nav .active > a:focus {
+  color: #ffffff;
+  background-color: #111111;
+}
+
+.navbar-inverse .navbar-link {
+  color: #999999;
+}
+
+.navbar-inverse .navbar-link:hover,
+.navbar-inverse .navbar-link:focus {
+  color: #ffffff;
+}
+
+.navbar-inverse .divider-vertical {
+  border-right-color: #222222;
+  border-left-color: #111111;
+}
+
+.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,
+.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,
+.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {
+  color: #ffffff;
+  background-color: #111111;
+}
+
+.navbar-inverse .nav li.dropdown > a:hover .caret,
+.navbar-inverse .nav li.dropdown > a:focus .caret {
+  border-top-color: #ffffff;
+  border-bottom-color: #ffffff;
+}
+
+.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {
+  border-top-color: #999999;
+  border-bottom-color: #999999;
+}
+
+.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,
+.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,
+.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {
+  border-top-color: #ffffff;
+  border-bottom-color: #ffffff;
+}
+
+.navbar-inverse .navbar-search .search-query {
+  color: #ffffff;
+  background-color: #515151;
+  border-color: #111111;
+  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
+     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
+          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
+  -webkit-transition: none;
+     -moz-transition: none;
+       -o-transition: none;
+          transition: none;
+}
+
+.navbar-inverse .navbar-search .search-query:-moz-placeholder {
+  color: #cccccc;
+}
+
+.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {
+  color: #cccccc;
+}
+
+.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {
+  color: #cccccc;
+}
+
+.navbar-inverse .navbar-search .search-query:focus,
+.navbar-inverse .navbar-search .search-query.focused {
+  padding: 5px 15px;
+  color: #333333;
+  text-shadow: 0 1px 0 #ffffff;
+  background-color: #ffffff;
+  border: 0;
+  outline: 0;
+  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+}
+
+.navbar-inverse .btn-navbar {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #0e0e0e;
+  *background-color: #040404;
+  background-image: -moz-linear-gradient(top, #151515, #040404);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));
+  background-image: -webkit-linear-gradient(top, #151515, #040404);
+  background-image: -o-linear-gradient(top, #151515, #040404);
+  background-image: linear-gradient(to bottom, #151515, #040404);
+  background-repeat: repeat-x;
+  border-color: #040404 #040404 #000000;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.navbar-inverse .btn-navbar:hover,
+.navbar-inverse .btn-navbar:focus,
+.navbar-inverse .btn-navbar:active,
+.navbar-inverse .btn-navbar.active,
+.navbar-inverse .btn-navbar.disabled,
+.navbar-inverse .btn-navbar[disabled] {
+  color: #ffffff;
+  background-color: #040404;
+  *background-color: #000000;
+}
+
+.navbar-inverse .btn-navbar:active,
+.navbar-inverse .btn-navbar.active {
+  background-color: #000000 \9;
+}
+
+.breadcrumb {
+  padding: 8px 15px;
+  margin: 0 0 20px;
+  list-style: none;
+  background-color: #f5f5f5;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+.breadcrumb > li {
+  display: inline-block;
+  *display: inline;
+  text-shadow: 0 1px 0 #ffffff;
+  *zoom: 1;
+}
+
+.breadcrumb > li > .divider {
+  padding: 0 5px;
+  color: #ccc;
+}
+
+.breadcrumb > .active {
+  color: #999999;
+}
+
+.pagination {
+  margin: 20px 0;
+}
+
+.pagination ul {
+  display: inline-block;
+  *display: inline;
+  margin-bottom: 0;
+  margin-left: 0;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  *zoom: 1;
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.pagination ul > li {
+  display: inline;
+}
+
+.pagination ul > li > a,
+.pagination ul > li > span {
+  float: left;
+  padding: 4px 12px;
+  line-height: 20px;
+  text-decoration: none;
+  background-color: #ffffff;
+  border: 1px solid #dddddd;
+  border-left-width: 0;
+}
+
+.pagination ul > li > a:hover,
+.pagination ul > li > a:focus,
+.pagination ul > .active > a,
+.pagination ul > .active > span {
+  background-color: #f5f5f5;
+}
+
+.pagination ul > .active > a,
+.pagination ul > .active > span {
+  color: #999999;
+  cursor: default;
+}
+
+.pagination ul > .disabled > span,
+.pagination ul > .disabled > a,
+.pagination ul > .disabled > a:hover,
+.pagination ul > .disabled > a:focus {
+  color: #999999;
+  cursor: default;
+  background-color: transparent;
+}
+
+.pagination ul > li:first-child > a,
+.pagination ul > li:first-child > span {
+  border-left-width: 1px;
+  -webkit-border-bottom-left-radius: 4px;
+          border-bottom-left-radius: 4px;
+  -webkit-border-top-left-radius: 4px;
+          border-top-left-radius: 4px;
+  -moz-border-radius-bottomleft: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+.pagination ul > li:last-child > a,
+.pagination ul > li:last-child > span {
+  -webkit-border-top-right-radius: 4px;
+          border-top-right-radius: 4px;
+  -webkit-border-bottom-right-radius: 4px;
+          border-bottom-right-radius: 4px;
+  -moz-border-radius-topright: 4px;
+  -moz-border-radius-bottomright: 4px;
+}
+
+.pagination-centered {
+  text-align: center;
+}
+
+.pagination-right {
+  text-align: right;
+}
+
+.pagination-large ul > li > a,
+.pagination-large ul > li > span {
+  padding: 11px 19px;
+  font-size: 17.5px;
+}
+
+.pagination-large ul > li:first-child > a,
+.pagination-large ul > li:first-child > span {
+  -webkit-border-bottom-left-radius: 6px;
+          border-bottom-left-radius: 6px;
+  -webkit-border-top-left-radius: 6px;
+          border-top-left-radius: 6px;
+  -moz-border-radius-bottomleft: 6px;
+  -moz-border-radius-topleft: 6px;
+}
+
+.pagination-large ul > li:last-child > a,
+.pagination-large ul > li:last-child > span {
+  -webkit-border-top-right-radius: 6px;
+          border-top-right-radius: 6px;
+  -webkit-border-bottom-right-radius: 6px;
+          border-bottom-right-radius: 6px;
+  -moz-border-radius-topright: 6px;
+  -moz-border-radius-bottomright: 6px;
+}
+
+.pagination-mini ul > li:first-child > a,
+.pagination-small ul > li:first-child > a,
+.pagination-mini ul > li:first-child > span,
+.pagination-small ul > li:first-child > span {
+  -webkit-border-bottom-left-radius: 3px;
+          border-bottom-left-radius: 3px;
+  -webkit-border-top-left-radius: 3px;
+          border-top-left-radius: 3px;
+  -moz-border-radius-bottomleft: 3px;
+  -moz-border-radius-topleft: 3px;
+}
+
+.pagination-mini ul > li:last-child > a,
+.pagination-small ul > li:last-child > a,
+.pagination-mini ul > li:last-child > span,
+.pagination-small ul > li:last-child > span {
+  -webkit-border-top-right-radius: 3px;
+          border-top-right-radius: 3px;
+  -webkit-border-bottom-right-radius: 3px;
+          border-bottom-right-radius: 3px;
+  -moz-border-radius-topright: 3px;
+  -moz-border-radius-bottomright: 3px;
+}
+
+.pagination-small ul > li > a,
+.pagination-small ul > li > span {
+  padding: 2px 10px;
+  font-size: 11.9px;
+}
+
+.pagination-mini ul > li > a,
+.pagination-mini ul > li > span {
+  padding: 0 6px;
+  font-size: 10.5px;
+}
+
+.pager {
+  margin: 20px 0;
+  text-align: center;
+  list-style: none;
+  *zoom: 1;
+}
+
+.pager:before,
+.pager:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.pager:after {
+  clear: both;
+}
+
+.pager li {
+  display: inline;
+}
+
+.pager li > a,
+.pager li > span {
+  display: inline-block;
+  padding: 5px 14px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  -webkit-border-radius: 15px;
+     -moz-border-radius: 15px;
+          border-radius: 15px;
+}
+
+.pager li > a:hover,
+.pager li > a:focus {
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+
+.pager .next > a,
+.pager .next > span {
+  float: right;
+}
+
+.pager .previous > a,
+.pager .previous > span {
+  float: left;
+}
+
+.pager .disabled > a,
+.pager .disabled > a:hover,
+.pager .disabled > a:focus,
+.pager .disabled > span {
+  color: #999999;
+  cursor: default;
+  background-color: #fff;
+}
+
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1040;
+  background-color: #000000;
+}
+
+.modal-backdrop.fade {
+  opacity: 0;
+}
+
+.modal-backdrop,
+.modal-backdrop.fade.in {
+  opacity: 0.8;
+  filter: alpha(opacity=80);
+}
+
+.modal {
+  position: fixed;
+  top: 10%;
+  left: 50%;
+  z-index: 1050;
+  width: 560px;
+  margin-left: -280px;
+  background-color: #ffffff;
+  border: 1px solid #999;
+  border: 1px solid rgba(0, 0, 0, 0.3);
+  *border: 1px solid #999;
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+  outline: none;
+  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+  -webkit-background-clip: padding-box;
+     -moz-background-clip: padding-box;
+          background-clip: padding-box;
+}
+
+.modal.fade {
+  top: -25%;
+  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;
+     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;
+       -o-transition: opacity 0.3s linear, top 0.3s ease-out;
+          transition: opacity 0.3s linear, top 0.3s ease-out;
+}
+
+.modal.fade.in {
+  top: 10%;
+}
+
+.modal-header {
+  padding: 9px 15px;
+  border-bottom: 1px solid #eee;
+}
+
+.modal-header .close {
+  margin-top: 2px;
+}
+
+.modal-header h3 {
+  margin: 0;
+  line-height: 30px;
+}
+
+.modal-body {
+  position: relative;
+  max-height: 400px;
+  padding: 15px;
+  overflow-y: auto;
+}
+
+.modal-form {
+  margin-bottom: 0;
+}
+
+.modal-footer {
+  padding: 14px 15px 15px;
+  margin-bottom: 0;
+  text-align: right;
+  background-color: #f5f5f5;
+  border-top: 1px solid #ddd;
+  -webkit-border-radius: 0 0 6px 6px;
+     -moz-border-radius: 0 0 6px 6px;
+          border-radius: 0 0 6px 6px;
+  *zoom: 1;
+  -webkit-box-shadow: inset 0 1px 0 #ffffff;
+     -moz-box-shadow: inset 0 1px 0 #ffffff;
+          box-shadow: inset 0 1px 0 #ffffff;
+}
+
+.modal-footer:before,
+.modal-footer:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.modal-footer:after {
+  clear: both;
+}
+
+.modal-footer .btn + .btn {
+  margin-bottom: 0;
+  margin-left: 5px;
+}
+
+.modal-footer .btn-group .btn + .btn {
+  margin-left: -1px;
+}
+
+.modal-footer .btn-block + .btn-block {
+  margin-left: 0;
+}
+
+.tooltip {
+  position: absolute;
+  z-index: 1030;
+  display: block;
+  font-size: 11px;
+  line-height: 1.4;
+  opacity: 0;
+  filter: alpha(opacity=0);
+  visibility: visible;
+}
+
+.tooltip.in {
+  opacity: 0.8;
+  filter: alpha(opacity=80);
+}
+
+.tooltip.top {
+  padding: 5px 0;
+  margin-top: -3px;
+}
+
+.tooltip.right {
+  padding: 0 5px;
+  margin-left: 3px;
+}
+
+.tooltip.bottom {
+  padding: 5px 0;
+  margin-top: 3px;
+}
+
+.tooltip.left {
+  padding: 0 5px;
+  margin-left: -3px;
+}
+
+.tooltip-inner {
+  max-width: 200px;
+  padding: 8px;
+  color: #ffffff;
+  text-align: center;
+  text-decoration: none;
+  background-color: #000000;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+.tooltip-arrow {
+  position: absolute;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.tooltip.top .tooltip-arrow {
+  bottom: 0;
+  left: 50%;
+  margin-left: -5px;
+  border-top-color: #000000;
+  border-width: 5px 5px 0;
+}
+
+.tooltip.right .tooltip-arrow {
+  top: 50%;
+  left: 0;
+  margin-top: -5px;
+  border-right-color: #000000;
+  border-width: 5px 5px 5px 0;
+}
+
+.tooltip.left .tooltip-arrow {
+  top: 50%;
+  right: 0;
+  margin-top: -5px;
+  border-left-color: #000000;
+  border-width: 5px 0 5px 5px;
+}
+
+.tooltip.bottom .tooltip-arrow {
+  top: 0;
+  left: 50%;
+  margin-left: -5px;
+  border-bottom-color: #000000;
+  border-width: 0 5px 5px;
+}
+
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1010;
+  display: none;
+  max-width: 276px;
+  padding: 1px;
+  text-align: left;
+  white-space: normal;
+  background-color: #ffffff;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  -webkit-background-clip: padding-box;
+     -moz-background-clip: padding;
+          background-clip: padding-box;
+}
+
+.popover.top {
+  margin-top: -10px;
+}
+
+.popover.right {
+  margin-left: 10px;
+}
+
+.popover.bottom {
+  margin-top: 10px;
+}
+
+.popover.left {
+  margin-left: -10px;
+}
+
+.popover-title {
+  padding: 8px 14px;
+  margin: 0;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 18px;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+  -webkit-border-radius: 5px 5px 0 0;
+     -moz-border-radius: 5px 5px 0 0;
+          border-radius: 5px 5px 0 0;
+}
+
+.popover-title:empty {
+  display: none;
+}
+
+.popover-content {
+  padding: 9px 14px;
+}
+
+.popover .arrow,
+.popover .arrow:after {
+  position: absolute;
+  display: block;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.popover .arrow {
+  border-width: 11px;
+}
+
+.popover .arrow:after {
+  border-width: 10px;
+  content: "";
+}
+
+.popover.top .arrow {
+  bottom: -11px;
+  left: 50%;
+  margin-left: -11px;
+  border-top-color: #999;
+  border-top-color: rgba(0, 0, 0, 0.25);
+  border-bottom-width: 0;
+}
+
+.popover.top .arrow:after {
+  bottom: 1px;
+  margin-left: -10px;
+  border-top-color: #ffffff;
+  border-bottom-width: 0;
+}
+
+.popover.right .arrow {
+  top: 50%;
+  left: -11px;
+  margin-top: -11px;
+  border-right-color: #999;
+  border-right-color: rgba(0, 0, 0, 0.25);
+  border-left-width: 0;
+}
+
+.popover.right .arrow:after {
+  bottom: -10px;
+  left: 1px;
+  border-right-color: #ffffff;
+  border-left-width: 0;
+}
+
+.popover.bottom .arrow {
+  top: -11px;
+  left: 50%;
+  margin-left: -11px;
+  border-bottom-color: #999;
+  border-bottom-color: rgba(0, 0, 0, 0.25);
+  border-top-width: 0;
+}
+
+.popover.bottom .arrow:after {
+  top: 1px;
+  margin-left: -10px;
+  border-bottom-color: #ffffff;
+  border-top-width: 0;
+}
+
+.popover.left .arrow {
+  top: 50%;
+  right: -11px;
+  margin-top: -11px;
+  border-left-color: #999;
+  border-left-color: rgba(0, 0, 0, 0.25);
+  border-right-width: 0;
+}
+
+.popover.left .arrow:after {
+  right: 1px;
+  bottom: -10px;
+  border-left-color: #ffffff;
+  border-right-width: 0;
+}
+
+.thumbnails {
+  margin-left: -20px;
+  list-style: none;
+  *zoom: 1;
+}
+
+.thumbnails:before,
+.thumbnails:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.thumbnails:after {
+  clear: both;
+}
+
+.row-fluid .thumbnails {
+  margin-left: 0;
+}
+
+.thumbnails > li {
+  float: left;
+  margin-bottom: 20px;
+  margin-left: 20px;
+}
+
+.thumbnail {
+  display: block;
+  padding: 4px;
+  line-height: 20px;
+  border: 1px solid #ddd;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
+     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
+          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
+  -webkit-transition: all 0.2s ease-in-out;
+     -moz-transition: all 0.2s ease-in-out;
+       -o-transition: all 0.2s ease-in-out;
+          transition: all 0.2s ease-in-out;
+}
+
+a.thumbnail:hover,
+a.thumbnail:focus {
+  border-color: #0088cc;
+  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
+     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
+          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
+}
+
+.thumbnail > img {
+  display: block;
+  max-width: 100%;
+  margin-right: auto;
+  margin-left: auto;
+}
+
+.thumbnail .caption {
+  padding: 9px;
+  color: #555555;
+}
+
+.media,
+.media-body {
+  overflow: hidden;
+  *overflow: visible;
+  zoom: 1;
+}
+
+.media,
+.media .media {
+  margin-top: 15px;
+}
+
+.media:first-child {
+  margin-top: 0;
+}
+
+.media-object {
+  display: block;
+}
+
+.media-heading {
+  margin: 0 0 5px;
+}
+
+.media > .pull-left {
+  margin-right: 10px;
+}
+
+.media > .pull-right {
+  margin-left: 10px;
+}
+
+.media-list {
+  margin-left: 0;
+  list-style: none;
+}
+
+.label,
+.badge {
+  display: inline-block;
+  padding: 2px 4px;
+  font-size: 11.844px;
+  font-weight: bold;
+  line-height: 14px;
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  white-space: nowrap;
+  vertical-align: baseline;
+  background-color: #999999;
+}
+
+.label {
+  -webkit-border-radius: 3px;
+     -moz-border-radius: 3px;
+          border-radius: 3px;
+}
+
+.badge {
+  padding-right: 9px;
+  padding-left: 9px;
+  -webkit-border-radius: 9px;
+     -moz-border-radius: 9px;
+          border-radius: 9px;
+}
+
+.label:empty,
+.badge:empty {
+  display: none;
+}
+
+a.label:hover,
+a.label:focus,
+a.badge:hover,
+a.badge:focus {
+  color: #ffffff;
+  text-decoration: none;
+  cursor: pointer;
+}
+
+.label-important,
+.badge-important {
+  background-color: #b94a48;
+}
+
+.label-important[href],
+.badge-important[href] {
+  background-color: #953b39;
+}
+
+.label-warning,
+.badge-warning {
+  background-color: #f89406;
+}
+
+.label-warning[href],
+.badge-warning[href] {
+  background-color: #c67605;
+}
+
+.label-success,
+.badge-success {
+  background-color: #468847;
+}
+
+.label-success[href],
+.badge-success[href] {
+  background-color: #356635;
+}
+
+.label-info,
+.badge-info {
+  background-color: #3a87ad;
+}
+
+.label-info[href],
+.badge-info[href] {
+  background-color: #2d6987;
+}
+
+.label-inverse,
+.badge-inverse {
+  background-color: #333333;
+}
+
+.label-inverse[href],
+.badge-inverse[href] {
+  background-color: #1a1a1a;
+}
+
+.btn .label,
+.btn .badge {
+  position: relative;
+  top: -1px;
+}
+
+.btn-mini .label,
+.btn-mini .badge {
+  top: 0;
+}
+
+@-webkit-keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@-moz-keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@-ms-keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@-o-keyframes progress-bar-stripes {
+  from {
+    background-position: 0 0;
+  }
+  to {
+    background-position: 40px 0;
+  }
+}
+
+@keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+.progress {
+  height: 20px;
+  margin-bottom: 20px;
+  overflow: hidden;
+  background-color: #f7f7f7;
+  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));
+  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);
+  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);
+  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);
+  background-repeat: repeat-x;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);
+  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+
+.progress .bar {
+  float: left;
+  width: 0;
+  height: 100%;
+  font-size: 12px;
+  color: #ffffff;
+  text-align: center;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #0e90d2;
+  background-image: -moz-linear-gradient(top, #149bdf, #0480be);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));
+  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);
+  background-image: -o-linear-gradient(top, #149bdf, #0480be);
+  background-image: linear-gradient(to bottom, #149bdf, #0480be);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);
+  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+  -webkit-transition: width 0.6s ease;
+     -moz-transition: width 0.6s ease;
+       -o-transition: width 0.6s ease;
+          transition: width 0.6s ease;
+}
+
+.progress .bar + .bar {
+  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+}
+
+.progress-striped .bar {
+  background-color: #149bdf;
+  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  -webkit-background-size: 40px 40px;
+     -moz-background-size: 40px 40px;
+       -o-background-size: 40px 40px;
+          background-size: 40px 40px;
+}
+
+.progress.active .bar {
+  -webkit-animation: progress-bar-stripes 2s linear infinite;
+     -moz-animation: progress-bar-stripes 2s linear infinite;
+      -ms-animation: progress-bar-stripes 2s linear infinite;
+       -o-animation: progress-bar-stripes 2s linear infinite;
+          animation: progress-bar-stripes 2s linear infinite;
+}
+
+.progress-danger .bar,
+.progress .bar-danger {
+  background-color: #dd514c;
+  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));
+  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
+  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
+  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);
+}
+
+.progress-danger.progress-striped .bar,
+.progress-striped .bar-danger {
+  background-color: #ee5f5b;
+  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.progress-success .bar,
+.progress .bar-success {
+  background-color: #5eb95e;
+  background-image: -moz-linear-gradient(top, #62c462, #57a957);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));
+  background-image: -webkit-linear-gradient(top, #62c462, #57a957);
+  background-image: -o-linear-gradient(top, #62c462, #57a957);
+  background-image: linear-gradient(to bottom, #62c462, #57a957);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);
+}
+
+.progress-success.progress-striped .bar,
+.progress-striped .bar-success {
+  background-color: #62c462;
+  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.progress-info .bar,
+.progress .bar-info {
+  background-color: #4bb1cf;
+  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));
+  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
+  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
+  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);
+}
+
+.progress-info.progress-striped .bar,
+.progress-striped .bar-info {
+  background-color: #5bc0de;
+  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.progress-warning .bar,
+.progress .bar-warning {
+  background-color: #faa732;
+  background-image: -moz-linear-gradient(top, #fbb450, #f89406);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
+  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
+  background-image: -o-linear-gradient(top, #fbb450, #f89406);
+  background-image: linear-gradient(to bottom, #fbb450, #f89406);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
+}
+
+.progress-warning.progress-striped .bar,
+.progress-striped .bar-warning {
+  background-color: #fbb450;
+  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.accordion {
+  margin-bottom: 20px;
+}
+
+.accordion-group {
+  margin-bottom: 2px;
+  border: 1px solid #e5e5e5;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+.accordion-heading {
+  border-bottom: 0;
+}
+
+.accordion-heading .accordion-toggle {
+  display: block;
+  padding: 8px 15px;
+}
+
+.accordion-toggle {
+  cursor: pointer;
+}
+
+.accordion-inner {
+  padding: 9px 15px;
+  border-top: 1px solid #e5e5e5;
+}
+
+.carousel {
+  position: relative;
+  margin-bottom: 20px;
+  line-height: 1;
+}
+
+.carousel-inner {
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+
+.carousel-inner > .item {
+  position: relative;
+  display: none;
+  -webkit-transition: 0.6s ease-in-out left;
+     -moz-transition: 0.6s ease-in-out left;
+       -o-transition: 0.6s ease-in-out left;
+          transition: 0.6s ease-in-out left;
+}
+
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+  display: block;
+  line-height: 1;
+}
+
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  display: block;
+}
+
+.carousel-inner > .active {
+  left: 0;
+}
+
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+
+.carousel-inner > .next {
+  left: 100%;
+}
+
+.carousel-inner > .prev {
+  left: -100%;
+}
+
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+  left: 0;
+}
+
+.carousel-inner > .active.left {
+  left: -100%;
+}
+
+.carousel-inner > .active.right {
+  left: 100%;
+}
+
+.carousel-control {
+  position: absolute;
+  top: 40%;
+  left: 15px;
+  width: 40px;
+  height: 40px;
+  margin-top: -20px;
+  font-size: 60px;
+  font-weight: 100;
+  line-height: 30px;
+  color: #ffffff;
+  text-align: center;
+  background: #222222;
+  border: 3px solid #ffffff;
+  -webkit-border-radius: 23px;
+     -moz-border-radius: 23px;
+          border-radius: 23px;
+  opacity: 0.5;
+  filter: alpha(opacity=50);
+}
+
+.carousel-control.right {
+  right: 15px;
+  left: auto;
+}
+
+.carousel-control:hover,
+.carousel-control:focus {
+  color: #ffffff;
+  text-decoration: none;
+  opacity: 0.9;
+  filter: alpha(opacity=90);
+}
+
+.carousel-indicators {
+  position: absolute;
+  top: 15px;
+  right: 15px;
+  z-index: 5;
+  margin: 0;
+  list-style: none;
+}
+
+.carousel-indicators li {
+  display: block;
+  float: left;
+  width: 10px;
+  height: 10px;
+  margin-left: 5px;
+  text-indent: -999px;
+  background-color: #ccc;
+  background-color: rgba(255, 255, 255, 0.25);
+  border-radius: 5px;
+}
+
+.carousel-indicators .active {
+  background-color: #fff;
+}
+
+.carousel-caption {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 15px;
+  background: #333333;
+  background: rgba(0, 0, 0, 0.75);
+}
+
+.carousel-caption h4,
+.carousel-caption p {
+  line-height: 20px;
+  color: #ffffff;
+}
+
+.carousel-caption h4 {
+  margin: 0 0 5px;
+}
+
+.carousel-caption p {
+  margin-bottom: 0;
+}
+
+.hero-unit {
+  padding: 60px;
+  margin-bottom: 30px;
+  font-size: 18px;
+  font-weight: 200;
+  line-height: 30px;
+  color: inherit;
+  background-color: #eeeeee;
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+}
+
+.hero-unit h1 {
+  margin-bottom: 0;
+  font-size: 60px;
+  line-height: 1;
+  letter-spacing: -1px;
+  color: inherit;
+}
+
+.hero-unit li {
+  line-height: 30px;
+}
+
+.pull-right {
+  float: right;
+}
+
+.pull-left {
+  float: left;
+}
+
+.hide {
+  display: none;
+}
+
+.show {
+  display: block;
+}
+
+.invisible {
+  visibility: hidden;
+}
+
+.affix {
+  position: fixed;
+}

File diff suppressed because it is too large
+ 8 - 0
lift-stateless/src/main/resources/bootstrap/css/bootstrap.min.css


BIN
lift-stateless/src/main/resources/bootstrap/img/glyphicons-halflings-white.png


BIN
lift-stateless/src/main/resources/bootstrap/img/glyphicons-halflings.png


+ 2268 - 0
lift-stateless/src/main/resources/bootstrap/js/bootstrap.js

@@ -0,0 +1,2268 @@
+/* ===================================================
+ * bootstrap-transition.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
+ * ===================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+  /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
+   * ======================================================= */
+
+  $(function () {
+
+    $.support.transition = (function () {
+
+      var transitionEnd = (function () {
+
+        var el = document.createElement('bootstrap')
+          , transEndEventNames = {
+               'WebkitTransition' : 'webkitTransitionEnd'
+            ,  'MozTransition'    : 'transitionend'
+            ,  'OTransition'      : 'oTransitionEnd otransitionend'
+            ,  'transition'       : 'transitionend'
+            }
+          , name
+
+        for (name in transEndEventNames){
+          if (el.style[name] !== undefined) {
+            return transEndEventNames[name]
+          }
+        }
+
+      }())
+
+      return transitionEnd && {
+        end: transitionEnd
+      }
+
+    })()
+
+  })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-alert.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* ALERT CLASS DEFINITION
+  * ====================== */
+
+  var dismiss = '[data-dismiss="alert"]'
+    , Alert = function (el) {
+        $(el).on('click', dismiss, this.close)
+      }
+
+  Alert.prototype.close = function (e) {
+    var $this = $(this)
+      , selector = $this.attr('data-target')
+      , $parent
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+    }
+
+    $parent = $(selector)
+
+    e && e.preventDefault()
+
+    $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
+
+    $parent.trigger(e = $.Event('close'))
+
+    if (e.isDefaultPrevented()) return
+
+    $parent.removeClass('in')
+
+    function removeElement() {
+      $parent
+        .trigger('closed')
+        .remove()
+    }
+
+    $.support.transition && $parent.hasClass('fade') ?
+      $parent.on($.support.transition.end, removeElement) :
+      removeElement()
+  }
+
+
+ /* ALERT PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.alert
+
+  $.fn.alert = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('alert')
+      if (!data) $this.data('alert', (data = new Alert(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  $.fn.alert.Constructor = Alert
+
+
+ /* ALERT NO CONFLICT
+  * ================= */
+
+  $.fn.alert.noConflict = function () {
+    $.fn.alert = old
+    return this
+  }
+
+
+ /* ALERT DATA-API
+  * ============== */
+
+  $(document).on('click.alert.data-api', dismiss, Alert.prototype.close)
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-button.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* BUTTON PUBLIC CLASS DEFINITION
+  * ============================== */
+
+  var Button = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.button.defaults, options)
+  }
+
+  Button.prototype.setState = function (state) {
+    var d = 'disabled'
+      , $el = this.$element
+      , data = $el.data()
+      , val = $el.is('input') ? 'val' : 'html'
+
+    state = state + 'Text'
+    data.resetText || $el.data('resetText', $el[val]())
+
+    $el[val](data[state] || this.options[state])
+
+    // push to event loop to allow forms to submit
+    setTimeout(function () {
+      state == 'loadingText' ?
+        $el.addClass(d).attr(d, d) :
+        $el.removeClass(d).removeAttr(d)
+    }, 0)
+  }
+
+  Button.prototype.toggle = function () {
+    var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
+
+    $parent && $parent
+      .find('.active')
+      .removeClass('active')
+
+    this.$element.toggleClass('active')
+  }
+
+
+ /* BUTTON PLUGIN DEFINITION
+  * ======================== */
+
+  var old = $.fn.button
+
+  $.fn.button = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('button')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('button', (data = new Button(this, options)))
+      if (option == 'toggle') data.toggle()
+      else if (option) data.setState(option)
+    })
+  }
+
+  $.fn.button.defaults = {
+    loadingText: 'loading...'
+  }
+
+  $.fn.button.Constructor = Button
+
+
+ /* BUTTON NO CONFLICT
+  * ================== */
+
+  $.fn.button.noConflict = function () {
+    $.fn.button = old
+    return this
+  }
+
+
+ /* BUTTON DATA-API
+  * =============== */
+
+  $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
+    var $btn = $(e.target)
+    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+    $btn.button('toggle')
+  })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-carousel.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#carousel
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* CAROUSEL CLASS DEFINITION
+  * ========================= */
+
+  var Carousel = function (element, options) {
+    this.$element = $(element)
+    this.$indicators = this.$element.find('.carousel-indicators')
+    this.options = options
+    this.options.pause == 'hover' && this.$element
+      .on('mouseenter', $.proxy(this.pause, this))
+      .on('mouseleave', $.proxy(this.cycle, this))
+  }
+
+  Carousel.prototype = {
+
+    cycle: function (e) {
+      if (!e) this.paused = false
+      if (this.interval) clearInterval(this.interval);
+      this.options.interval
+        && !this.paused
+        && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+      return this
+    }
+
+  , getActiveIndex: function () {
+      this.$active = this.$element.find('.item.active')
+      this.$items = this.$active.parent().children()
+      return this.$items.index(this.$active)
+    }
+
+  , to: function (pos) {
+      var activeIndex = this.getActiveIndex()
+        , that = this
+
+      if (pos > (this.$items.length - 1) || pos < 0) return
+
+      if (this.sliding) {
+        return this.$element.one('slid', function () {
+          that.to(pos)
+        })
+      }
+
+      if (activeIndex == pos) {
+        return this.pause().cycle()
+      }
+
+      return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
+    }
+
+  , pause: function (e) {
+      if (!e) this.paused = true
+      if (this.$element.find('.next, .prev').length && $.support.transition.end) {
+        this.$element.trigger($.support.transition.end)
+        this.cycle()
+      }
+      clearInterval(this.interval)
+      this.interval = null
+      return this
+    }
+
+  , next: function () {
+      if (this.sliding) return
+      return this.slide('next')
+    }
+
+  , prev: function () {
+      if (this.sliding) return
+      return this.slide('prev')
+    }
+
+  , slide: function (type, next) {
+      var $active = this.$element.find('.item.active')
+        , $next = next || $active[type]()
+        , isCycling = this.interval
+        , direction = type == 'next' ? 'left' : 'right'
+        , fallback  = type == 'next' ? 'first' : 'last'
+        , that = this
+        , e
+
+      this.sliding = true
+
+      isCycling && this.pause()
+
+      $next = $next.length ? $next : this.$element.find('.item')[fallback]()
+
+      e = $.Event('slide', {
+        relatedTarget: $next[0]
+      , direction: direction
+      })
+
+      if ($next.hasClass('active')) return
+
+      if (this.$indicators.length) {
+        this.$indicators.find('.active').removeClass('active')
+        this.$element.one('slid', function () {
+          var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
+          $nextIndicator && $nextIndicator.addClass('active')
+        })
+      }
+
+      if ($.support.transition && this.$element.hasClass('slide')) {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $next.addClass(type)
+        $next[0].offsetWidth // force reflow
+        $active.addClass(direction)
+        $next.addClass(direction)
+        this.$element.one($.support.transition.end, function () {
+          $next.removeClass([type, direction].join(' ')).addClass('active')
+          $active.removeClass(['active', direction].join(' '))
+          that.sliding = false
+          setTimeout(function () { that.$element.trigger('slid') }, 0)
+        })
+      } else {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $active.removeClass('active')
+        $next.addClass('active')
+        this.sliding = false
+        this.$element.trigger('slid')
+      }
+
+      isCycling && this.cycle()
+
+      return this
+    }
+
+  }
+
+
+ /* CAROUSEL PLUGIN DEFINITION
+  * ========================== */
+
+  var old = $.fn.carousel
+
+  $.fn.carousel = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('carousel')
+        , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
+        , action = typeof option == 'string' ? option : options.slide
+      if (!data) $this.data('carousel', (data = new Carousel(this, options)))
+      if (typeof option == 'number') data.to(option)
+      else if (action) data[action]()
+      else if (options.interval) data.pause().cycle()
+    })
+  }
+
+  $.fn.carousel.defaults = {
+    interval: 5000
+  , pause: 'hover'
+  }
+
+  $.fn.carousel.Constructor = Carousel
+
+
+ /* CAROUSEL NO CONFLICT
+  * ==================== */
+
+  $.fn.carousel.noConflict = function () {
+    $.fn.carousel = old
+    return this
+  }
+
+ /* CAROUSEL DATA-API
+  * ================= */
+
+  $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
+    var $this = $(this), href
+      , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+      , options = $.extend({}, $target.data(), $this.data())
+      , slideIndex
+
+    $target.carousel(options)
+
+    if (slideIndex = $this.attr('data-slide-to')) {
+      $target.data('carousel').pause().to(slideIndex).cycle()
+    }
+
+    e.preventDefault()
+  })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-collapse.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#collapse
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* COLLAPSE PUBLIC CLASS DEFINITION
+  * ================================ */
+
+  var Collapse = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.collapse.defaults, options)
+
+    if (this.options.parent) {
+      this.$parent = $(this.options.parent)
+    }
+
+    this.options.toggle && this.toggle()
+  }
+
+  Collapse.prototype = {
+
+    constructor: Collapse
+
+  , dimension: function () {
+      var hasWidth = this.$element.hasClass('width')
+      return hasWidth ? 'width' : 'height'
+    }
+
+  , show: function () {
+      var dimension
+        , scroll
+        , actives
+        , hasData
+
+      if (this.transitioning || this.$element.hasClass('in')) return
+
+      dimension = this.dimension()
+      scroll = $.camelCase(['scroll', dimension].join('-'))
+      actives = this.$parent && this.$parent.find('> .accordion-group > .in')
+
+      if (actives && actives.length) {
+        hasData = actives.data('collapse')
+        if (hasData && hasData.transitioning) return
+        actives.collapse('hide')
+        hasData || actives.data('collapse', null)
+      }
+
+      this.$element[dimension](0)
+      this.transition('addClass', $.Event('show'), 'shown')
+      $.support.transition && this.$element[dimension](this.$element[0][scroll])
+    }
+
+  , hide: function () {
+      var dimension
+      if (this.transitioning || !this.$element.hasClass('in')) return
+      dimension = this.dimension()
+      this.reset(this.$element[dimension]())
+      this.transition('removeClass', $.Event('hide'), 'hidden')
+      this.$element[dimension](0)
+    }
+
+  , reset: function (size) {
+      var dimension = this.dimension()
+
+      this.$element
+        .removeClass('collapse')
+        [dimension](size || 'auto')
+        [0].offsetWidth
+
+      this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
+
+      return this
+    }
+
+  , transition: function (method, startEvent, completeEvent) {
+      var that = this
+        , complete = function () {
+            if (startEvent.type == 'show') that.reset()
+            that.transitioning = 0
+            that.$element.trigger(completeEvent)
+          }
+
+      this.$element.trigger(startEvent)
+
+      if (startEvent.isDefaultPrevented()) return
+
+      this.transitioning = 1
+
+      this.$element[method]('in')
+
+      $.support.transition && this.$element.hasClass('collapse') ?
+        this.$element.one($.support.transition.end, complete) :
+        complete()
+    }
+
+  , toggle: function () {
+      this[this.$element.hasClass('in') ? 'hide' : 'show']()
+    }
+
+  }
+
+
+ /* COLLAPSE PLUGIN DEFINITION
+  * ========================== */
+
+  var old = $.fn.collapse
+
+  $.fn.collapse = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('collapse')
+        , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option)
+      if (!data) $this.data('collapse', (data = new Collapse(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.collapse.defaults = {
+    toggle: true
+  }
+
+  $.fn.collapse.Constructor = Collapse
+
+
+ /* COLLAPSE NO CONFLICT
+  * ==================== */
+
+  $.fn.collapse.noConflict = function () {
+    $.fn.collapse = old
+    return this
+  }
+
+
+ /* COLLAPSE DATA-API
+  * ================= */
+
+  $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
+    var $this = $(this), href
+      , target = $this.attr('data-target')
+        || e.preventDefault()
+        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
+      , option = $(target).data('collapse') ? 'toggle' : $this.data()
+    $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
+    $(target).collapse(option)
+  })
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-dropdown.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* DROPDOWN CLASS DEFINITION
+  * ========================= */
+
+  var toggle = '[data-toggle=dropdown]'
+    , Dropdown = function (element) {
+        var $el = $(element).on('click.dropdown.data-api', this.toggle)
+        $('html').on('click.dropdown.data-api', function () {
+          $el.parent().removeClass('open')
+        })
+      }
+
+  Dropdown.prototype = {
+
+    constructor: Dropdown
+
+  , toggle: function (e) {
+      var $this = $(this)
+        , $parent
+        , isActive
+
+      if ($this.is('.disabled, :disabled')) return
+
+      $parent = getParent($this)
+
+      isActive = $parent.hasClass('open')
+
+      clearMenus()
+
+      if (!isActive) {
+        $parent.toggleClass('open')
+      }
+
+      $this.focus()
+
+      return false
+    }
+
+  , keydown: function (e) {
+      var $this
+        , $items
+        , $active
+        , $parent
+        , isActive
+        , index
+
+      if (!/(38|40|27)/.test(e.keyCode)) return
+
+      $this = $(this)
+
+      e.preventDefault()
+      e.stopPropagation()
+
+      if ($this.is('.disabled, :disabled')) return
+
+      $parent = getParent($this)
+
+      isActive = $parent.hasClass('open')
+
+      if (!isActive || (isActive && e.keyCode == 27)) {
+        if (e.which == 27) $parent.find(toggle).focus()
+        return $this.click()
+      }
+
+      $items = $('[role=menu] li:not(.divider):visible a', $parent)
+
+      if (!$items.length) return
+
+      index = $items.index($items.filter(':focus'))
+
+      if (e.keyCode == 38 && index > 0) index--                                        // up
+      if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
+      if (!~index) index = 0
+
+      $items
+        .eq(index)
+        .focus()
+    }
+
+  }
+
+  function clearMenus() {
+    $(toggle).each(function () {
+      getParent($(this)).removeClass('open')
+    })
+  }
+
+  function getParent($this) {
+    var selector = $this.attr('data-target')
+      , $parent
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+    }
+
+    $parent = selector && $(selector)
+
+    if (!$parent || !$parent.length) $parent = $this.parent()
+
+    return $parent
+  }
+
+
+  /* DROPDOWN PLUGIN DEFINITION
+   * ========================== */
+
+  var old = $.fn.dropdown
+
+  $.fn.dropdown = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('dropdown')
+      if (!data) $this.data('dropdown', (data = new Dropdown(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  $.fn.dropdown.Constructor = Dropdown
+
+
+ /* DROPDOWN NO CONFLICT
+  * ==================== */
+
+  $.fn.dropdown.noConflict = function () {
+    $.fn.dropdown = old
+    return this
+  }
+
+
+  /* APPLY TO STANDARD DROPDOWN ELEMENTS
+   * =================================== */
+
+  $(document)
+    .on('click.dropdown.data-api', clearMenus)
+    .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+    .on('.dropdown-menu', function (e) { e.stopPropagation() })
+    .on('click.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)
+    .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
+
+}(window.jQuery);
+/* =========================================================
+ * bootstrap-modal.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#modals
+ * =========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* MODAL CLASS DEFINITION
+  * ====================== */
+
+  var Modal = function (element, options) {
+    this.options = options
+    this.$element = $(element)
+      .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
+    this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
+  }
+
+  Modal.prototype = {
+
+      constructor: Modal
+
+    , toggle: function () {
+        return this[!this.isShown ? 'show' : 'hide']()
+      }
+
+    , show: function () {
+        var that = this
+          , e = $.Event('show')
+
+        this.$element.trigger(e)
+
+        if (this.isShown || e.isDefaultPrevented()) return
+
+        this.isShown = true
+
+        this.escape()
+
+        this.backdrop(function () {
+          var transition = $.support.transition && that.$element.hasClass('fade')
+
+          if (!that.$element.parent().length) {
+            that.$element.appendTo(document.body) //don't move modals dom position
+          }
+
+          that.$element.show()
+
+          if (transition) {
+            that.$element[0].offsetWidth // force reflow
+          }
+
+          that.$element
+            .addClass('in')
+            .attr('aria-hidden', false)
+
+          that.enforceFocus()
+
+          transition ?
+            that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :
+            that.$element.focus().trigger('shown')
+
+        })
+      }
+
+    , hide: function (e) {
+        e && e.preventDefault()
+
+        var that = this
+
+        e = $.Event('hide')
+
+        this.$element.trigger(e)
+
+        if (!this.isShown || e.isDefaultPrevented()) return
+
+        this.isShown = false
+
+        this.escape()
+
+        $(document).off('focusin.modal')
+
+        this.$element
+          .removeClass('in')
+          .attr('aria-hidden', true)
+
+        $.support.transition && this.$element.hasClass('fade') ?
+          this.hideWithTransition() :
+          this.hideModal()
+      }
+
+    , enforceFocus: function () {
+        var that = this
+        $(document).on('focusin.modal', function (e) {
+          if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
+            that.$element.focus()
+          }
+        })
+      }
+
+    , escape: function () {
+        var that = this
+        if (this.isShown && this.options.keyboard) {
+          this.$element.on('keyup.dismiss.modal', function ( e ) {
+            e.which == 27 && that.hide()
+          })
+        } else if (!this.isShown) {
+          this.$element.off('keyup.dismiss.modal')
+        }
+      }
+
+    , hideWithTransition: function () {
+        var that = this
+          , timeout = setTimeout(function () {
+              that.$element.off($.support.transition.end)
+              that.hideModal()
+            }, 500)
+
+        this.$element.one($.support.transition.end, function () {
+          clearTimeout(timeout)
+          that.hideModal()
+        })
+      }
+
+    , hideModal: function () {
+        var that = this
+        this.$element.hide()
+        this.backdrop(function () {
+          that.removeBackdrop()
+          that.$element.trigger('hidden')
+        })
+      }
+
+    , removeBackdrop: function () {
+        this.$backdrop.remove()
+        this.$backdrop = null
+      }
+
+    , backdrop: function (callback) {
+        var that = this
+          , animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+        if (this.isShown && this.options.backdrop) {
+          var doAnimate = $.support.transition && animate
+
+          this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+            .appendTo(document.body)
+
+          this.$backdrop.click(
+            this.options.backdrop == 'static' ?
+              $.proxy(this.$element[0].focus, this.$element[0])
+            : $.proxy(this.hide, this)
+          )
+
+          if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+          this.$backdrop.addClass('in')
+
+          if (!callback) return
+
+          doAnimate ?
+            this.$backdrop.one($.support.transition.end, callback) :
+            callback()
+
+        } else if (!this.isShown && this.$backdrop) {
+          this.$backdrop.removeClass('in')
+
+          $.support.transition && this.$element.hasClass('fade')?
+            this.$backdrop.one($.support.transition.end, callback) :
+            callback()
+
+        } else if (callback) {
+          callback()
+        }
+      }
+  }
+
+
+ /* MODAL PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.modal
+
+  $.fn.modal = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('modal')
+        , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
+      if (!data) $this.data('modal', (data = new Modal(this, options)))
+      if (typeof option == 'string') data[option]()
+      else if (options.show) data.show()
+    })
+  }
+
+  $.fn.modal.defaults = {
+      backdrop: true
+    , keyboard: true
+    , show: true
+  }
+
+  $.fn.modal.Constructor = Modal
+
+
+ /* MODAL NO CONFLICT
+  * ================= */
+
+  $.fn.modal.noConflict = function () {
+    $.fn.modal = old
+    return this
+  }
+
+
+ /* MODAL DATA-API
+  * ============== */
+
+  $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) {
+    var $this = $(this)
+      , href = $this.attr('href')
+      , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
+      , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
+
+    e.preventDefault()
+
+    $target
+      .modal(option)
+      .one('hide', function () {
+        $this.focus()
+      })
+  })
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-tooltip.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* TOOLTIP PUBLIC CLASS DEFINITION
+  * =============================== */
+
+  var Tooltip = function (element, options) {
+    this.init('tooltip', element, options)
+  }
+
+  Tooltip.prototype = {
+
+    constructor: Tooltip
+
+  , init: function (type, element, options) {
+      var eventIn
+        , eventOut
+        , triggers
+        , trigger
+        , i
+
+      this.type = type
+      this.$element = $(element)
+      this.options = this.getOptions(options)
+      this.enabled = true
+
+      triggers = this.options.trigger.split(' ')
+
+      for (i = triggers.length; i--;) {
+        trigger = triggers[i]
+        if (trigger == 'click') {
+          this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+        } else if (trigger != 'manual') {
+          eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
+          eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
+          this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+          this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+        }
+      }
+
+      this.options.selector ?
+        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+        this.fixTitle()
+    }
+
+  , getOptions: function (options) {
+      options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)
+
+      if (options.delay && typeof options.delay == 'number') {
+        options.delay = {
+          show: options.delay
+        , hide: options.delay
+        }
+      }
+
+      return options
+    }
+
+  , enter: function (e) {
+      var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+      if (!self.options.delay || !self.options.delay.show) return self.show()
+
+      clearTimeout(this.timeout)
+      self.hoverState = 'in'
+      this.timeout = setTimeout(function() {
+        if (self.hoverState == 'in') self.show()
+      }, self.options.delay.show)
+    }
+
+  , leave: function (e) {
+      var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+      if (this.timeout) clearTimeout(this.timeout)
+      if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+      self.hoverState = 'out'
+      this.timeout = setTimeout(function() {
+        if (self.hoverState == 'out') self.hide()
+      }, self.options.delay.hide)
+    }
+
+  , show: function () {
+      var $tip
+        , pos
+        , actualWidth
+        , actualHeight
+        , placement
+        , tp
+        , e = $.Event('show')
+
+      if (this.hasContent() && this.enabled) {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $tip = this.tip()
+        this.setContent()
+
+        if (this.options.animation) {
+          $tip.addClass('fade')
+        }
+
+        placement = typeof this.options.placement == 'function' ?
+          this.options.placement.call(this, $tip[0], this.$element[0]) :
+          this.options.placement
+
+        $tip
+          .detach()
+          .css({ top: 0, left: 0, display: 'block' })
+
+        this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+
+        pos = this.getPosition()
+
+        actualWidth = $tip[0].offsetWidth
+        actualHeight = $tip[0].offsetHeight
+
+        switch (placement) {
+          case 'bottom':
+            tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
+            break
+          case 'top':
+            tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
+            break
+          case 'left':
+            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
+            break
+          case 'right':
+            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
+            break
+        }
+
+        this.applyPlacement(tp, placement)
+        this.$element.trigger('shown')
+      }
+    }
+
+  , applyPlacement: function(offset, placement){
+      var $tip = this.tip()
+        , width = $tip[0].offsetWidth
+        , height = $tip[0].offsetHeight
+        , actualWidth
+        , actualHeight
+        , delta
+        , replace
+
+      $tip
+        .offset(offset)
+        .addClass(placement)
+        .addClass('in')
+
+      actualWidth = $tip[0].offsetWidth
+      actualHeight = $tip[0].offsetHeight
+
+      if (placement == 'top' && actualHeight != height) {
+        offset.top = offset.top + height - actualHeight
+        replace = true
+      }
+
+      if (placement == 'bottom' || placement == 'top') {
+        delta = 0
+
+        if (offset.left < 0){
+          delta = offset.left * -2
+          offset.left = 0
+          $tip.offset(offset)
+          actualWidth = $tip[0].offsetWidth
+          actualHeight = $tip[0].offsetHeight
+        }
+
+        this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
+      } else {
+        this.replaceArrow(actualHeight - height, actualHeight, 'top')
+      }
+
+      if (replace) $tip.offset(offset)
+    }
+
+  , replaceArrow: function(delta, dimension, position){
+      this
+        .arrow()
+        .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
+    }
+
+  , setContent: function () {
+      var $tip = this.tip()
+        , title = this.getTitle()
+
+      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+      $tip.removeClass('fade in top bottom left right')
+    }
+
+  , hide: function () {
+      var that = this
+        , $tip = this.tip()
+        , e = $.Event('hide')
+
+      this.$element.trigger(e)
+      if (e.isDefaultPrevented()) return
+
+      $tip.removeClass('in')
+
+      function removeWithAnimation() {
+        var timeout = setTimeout(function () {
+          $tip.off($.support.transition.end).detach()
+        }, 500)
+
+        $tip.one($.support.transition.end, function () {
+          clearTimeout(timeout)
+          $tip.detach()
+        })
+      }
+
+      $.support.transition && this.$tip.hasClass('fade') ?
+        removeWithAnimation() :
+        $tip.detach()
+
+      this.$element.trigger('hidden')
+
+      return this
+    }
+
+  , fixTitle: function () {
+      var $e = this.$element
+      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
+        $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+      }
+    }
+
+  , hasContent: function () {
+      return this.getTitle()
+    }
+
+  , getPosition: function () {
+      var el = this.$element[0]
+      return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
+        width: el.offsetWidth
+      , height: el.offsetHeight
+      }, this.$element.offset())
+    }
+
+  , getTitle: function () {
+      var title
+        , $e = this.$element
+        , o = this.options
+
+      title = $e.attr('data-original-title')
+        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
+
+      return title
+    }
+
+  , tip: function () {
+      return this.$tip = this.$tip || $(this.options.template)
+    }
+
+  , arrow: function(){
+      return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
+    }
+
+  , validate: function () {
+      if (!this.$element[0].parentNode) {
+        this.hide()
+        this.$element = null
+        this.options = null
+      }
+    }
+
+  , enable: function () {
+      this.enabled = true
+    }
+
+  , disable: function () {
+      this.enabled = false
+    }
+
+  , toggleEnabled: function () {
+      this.enabled = !this.enabled
+    }
+
+  , toggle: function (e) {
+      var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this
+      self.tip().hasClass('in') ? self.hide() : self.show()
+    }
+
+  , destroy: function () {
+      this.hide().$element.off('.' + this.type).removeData(this.type)
+    }
+
+  }
+
+
+ /* TOOLTIP PLUGIN DEFINITION
+  * ========================= */
+
+  var old = $.fn.tooltip
+
+  $.fn.tooltip = function ( option ) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('tooltip')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.tooltip.Constructor = Tooltip
+
+  $.fn.tooltip.defaults = {
+    animation: true
+  , placement: 'top'
+  , selector: false
+  , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
+  , trigger: 'hover focus'
+  , title: ''
+  , delay: 0
+  , html: false
+  , container: false
+  }
+
+
+ /* TOOLTIP NO CONFLICT
+  * =================== */
+
+  $.fn.tooltip.noConflict = function () {
+    $.fn.tooltip = old
+    return this
+  }
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-popover.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* POPOVER PUBLIC CLASS DEFINITION
+  * =============================== */
+
+  var Popover = function (element, options) {
+    this.init('popover', element, options)
+  }
+
+
+  /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
+     ========================================== */
+
+  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
+
+    constructor: Popover
+
+  , setContent: function () {
+      var $tip = this.tip()
+        , title = this.getTitle()
+        , content = this.getContent()
+
+      $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+      $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
+
+      $tip.removeClass('fade top bottom left right in')
+    }
+
+  , hasContent: function () {
+      return this.getTitle() || this.getContent()
+    }
+
+  , getContent: function () {
+      var content
+        , $e = this.$element
+        , o = this.options
+
+      content = (typeof o.content == 'function' ? o.content.call($e[0]) :  o.content)
+        || $e.attr('data-content')
+
+      return content
+    }
+
+  , tip: function () {
+      if (!this.$tip) {
+        this.$tip = $(this.options.template)
+      }
+      return this.$tip
+    }
+
+  , destroy: function () {
+      this.hide().$element.off('.' + this.type).removeData(this.type)
+    }
+
+  })
+
+
+ /* POPOVER PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.popover
+
+  $.fn.popover = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('popover')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('popover', (data = new Popover(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.popover.Constructor = Popover
+
+  $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
+    placement: 'right'
+  , trigger: 'click'
+  , content: ''
+  , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+  })
+
+
+ /* POPOVER NO CONFLICT
+  * =================== */
+
+  $.fn.popover.noConflict = function () {
+    $.fn.popover = old
+    return this
+  }
+
+}(window.jQuery);
+/* =============================================================
+ * bootstrap-scrollspy.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#scrollspy
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* SCROLLSPY CLASS DEFINITION
+  * ========================== */
+
+  function ScrollSpy(element, options) {
+    var process = $.proxy(this.process, this)
+      , $element = $(element).is('body') ? $(window) : $(element)
+      , href
+    this.options = $.extend({}, $.fn.scrollspy.defaults, options)
+    this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
+    this.selector = (this.options.target
+      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+      || '') + ' .nav li > a'
+    this.$body = $('body')
+    this.refresh()
+    this.process()
+  }
+
+  ScrollSpy.prototype = {
+
+      constructor: ScrollSpy
+
+    , refresh: function () {
+        var self = this
+          , $targets
+
+        this.offsets = $([])
+        this.targets = $([])
+
+        $targets = this.$body
+          .find(this.selector)
+          .map(function () {
+            var $el = $(this)
+              , href = $el.data('target') || $el.attr('href')
+              , $href = /^#\w/.test(href) && $(href)
+            return ( $href
+              && $href.length
+              && [[ $href.position().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]] ) || null
+          })
+          .sort(function (a, b) { return a[0] - b[0] })
+          .each(function () {
+            self.offsets.push(this[0])
+            self.targets.push(this[1])
+          })
+      }
+
+    , process: function () {
+        var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+          , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
+          , maxScroll = scrollHeight - this.$scrollElement.height()
+          , offsets = this.offsets
+          , targets = this.targets
+          , activeTarget = this.activeTarget
+          , i
+
+        if (scrollTop >= maxScroll) {
+          return activeTarget != (i = targets.last()[0])
+            && this.activate ( i )
+        }
+
+        for (i = offsets.length; i--;) {
+          activeTarget != targets[i]
+            && scrollTop >= offsets[i]
+            && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+            && this.activate( targets[i] )
+        }
+      }
+
+    , activate: function (target) {
+        var active
+          , selector
+
+        this.activeTarget = target
+
+        $(this.selector)
+          .parent('.active')
+          .removeClass('active')
+
+        selector = this.selector
+          + '[data-target="' + target + '"],'
+          + this.selector + '[href="' + target + '"]'
+
+        active = $(selector)
+          .parent('li')
+          .addClass('active')
+
+        if (active.parent('.dropdown-menu').length)  {
+          active = active.closest('li.dropdown').addClass('active')
+        }
+
+        active.trigger('activate')
+      }
+
+  }
+
+
+ /* SCROLLSPY PLUGIN DEFINITION
+  * =========================== */
+
+  var old = $.fn.scrollspy
+
+  $.fn.scrollspy = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('scrollspy')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.scrollspy.Constructor = ScrollSpy
+
+  $.fn.scrollspy.defaults = {
+    offset: 10
+  }
+
+
+ /* SCROLLSPY NO CONFLICT
+  * ===================== */
+
+  $.fn.scrollspy.noConflict = function () {
+    $.fn.scrollspy = old
+    return this
+  }
+
+
+ /* SCROLLSPY DATA-API
+  * ================== */
+
+  $(window).on('load', function () {
+    $('[data-spy="scroll"]').each(function () {
+      var $spy = $(this)
+      $spy.scrollspy($spy.data())
+    })
+  })
+
+}(window.jQuery);/* ========================================================
+ * bootstrap-tab.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
+ * ========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* TAB CLASS DEFINITION
+  * ==================== */
+
+  var Tab = function (element) {
+    this.element = $(element)
+  }
+
+  Tab.prototype = {
+
+    constructor: Tab
+
+  , show: function () {
+      var $this = this.element
+        , $ul = $this.closest('ul:not(.dropdown-menu)')
+        , selector = $this.attr('data-target')
+        , previous
+        , $target
+        , e
+
+      if (!selector) {
+        selector = $this.attr('href')
+        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+      }
+
+      if ( $this.parent('li').hasClass('active') ) return
+
+      previous = $ul.find('.active:last a')[0]
+
+      e = $.Event('show', {
+        relatedTarget: previous
+      })
+
+      $this.trigger(e)
+
+      if (e.isDefaultPrevented()) return
+
+      $target = $(selector)
+
+      this.activate($this.parent('li'), $ul)
+      this.activate($target, $target.parent(), function () {
+        $this.trigger({
+          type: 'shown'
+        , relatedTarget: previous
+        })
+      })
+    }
+
+  , activate: function ( element, container, callback) {
+      var $active = container.find('> .active')
+        , transition = callback
+            && $.support.transition
+            && $active.hasClass('fade')
+
+      function next() {
+        $active
+          .removeClass('active')
+          .find('> .dropdown-menu > .active')
+          .removeClass('active')
+
+        element.addClass('active')
+
+        if (transition) {
+          element[0].offsetWidth // reflow for transition
+          element.addClass('in')
+        } else {
+          element.removeClass('fade')
+        }
+
+        if ( element.parent('.dropdown-menu') ) {
+          element.closest('li.dropdown').addClass('active')
+        }
+
+        callback && callback()
+      }
+
+      transition ?
+        $active.one($.support.transition.end, next) :
+        next()
+
+      $active.removeClass('in')
+    }
+  }
+
+
+ /* TAB PLUGIN DEFINITION
+  * ===================== */
+
+  var old = $.fn.tab
+
+  $.fn.tab = function ( option ) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('tab')
+      if (!data) $this.data('tab', (data = new Tab(this)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.tab.Constructor = Tab
+
+
+ /* TAB NO CONFLICT
+  * =============== */
+
+  $.fn.tab.noConflict = function () {
+    $.fn.tab = old
+    return this
+  }
+
+
+ /* TAB DATA-API
+  * ============ */
+
+  $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+    e.preventDefault()
+    $(this).tab('show')
+  })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-typeahead.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#typeahead
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function($){
+
+  "use strict"; // jshint ;_;
+
+
+ /* TYPEAHEAD PUBLIC CLASS DEFINITION
+  * ================================= */
+
+  var Typeahead = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.typeahead.defaults, options)
+    this.matcher = this.options.matcher || this.matcher
+    this.sorter = this.options.sorter || this.sorter
+    this.highlighter = this.options.highlighter || this.highlighter
+    this.updater = this.options.updater || this.updater
+    this.source = this.options.source
+    this.$menu = $(this.options.menu)
+    this.shown = false
+    this.listen()
+  }
+
+  Typeahead.prototype = {
+
+    constructor: Typeahead
+
+  , select: function () {
+      var val = this.$menu.find('.active').attr('data-value')
+      this.$element
+        .val(this.updater(val))
+        .change()
+      return this.hide()
+    }
+
+  , updater: function (item) {
+      return item
+    }
+
+  , show: function () {
+      var pos = $.extend({}, this.$element.position(), {
+        height: this.$element[0].offsetHeight
+      })
+
+      this.$menu
+        .insertAfter(this.$element)
+        .css({
+          top: pos.top + pos.height
+        , left: pos.left
+        })
+        .show()
+
+      this.shown = true
+      return this
+    }
+
+  , hide: function () {
+      this.$menu.hide()
+      this.shown = false
+      return this
+    }
+
+  , lookup: function (event) {
+      var items
+
+      this.query = this.$element.val()
+
+      if (!this.query || this.query.length < this.options.minLength) {
+        return this.shown ? this.hide() : this
+      }
+
+      items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
+
+      return items ? this.process(items) : this
+    }
+
+  , process: function (items) {
+      var that = this
+
+      items = $.grep(items, function (item) {
+        return that.matcher(item)
+      })
+
+      items = this.sorter(items)
+
+      if (!items.length) {
+        return this.shown ? this.hide() : this
+      }
+
+      return this.render(items.slice(0, this.options.items)).show()
+    }
+
+  , matcher: function (item) {
+      return ~item.toLowerCase().indexOf(this.query.toLowerCase())
+    }
+
+  , sorter: function (items) {
+      var beginswith = []
+        , caseSensitive = []
+        , caseInsensitive = []
+        , item
+
+      while (item = items.shift()) {
+        if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
+        else if (~item.indexOf(this.query)) caseSensitive.push(item)
+        else caseInsensitive.push(item)
+      }
+
+      return beginswith.concat(caseSensitive, caseInsensitive)
+    }
+
+  , highlighter: function (item) {
+      var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
+      return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
+        return '<strong>' + match + '</strong>'
+      })
+    }
+
+  , render: function (items) {
+      var that = this
+
+      items = $(items).map(function (i, item) {
+        i = $(that.options.item).attr('data-value', item)
+        i.find('a').html(that.highlighter(item))
+        return i[0]
+      })
+
+      items.first().addClass('active')
+      this.$menu.html(items)
+      return this
+    }
+
+  , next: function (event) {
+      var active = this.$menu.find('.active').removeClass('active')
+        , next = active.next()
+
+      if (!next.length) {
+        next = $(this.$menu.find('li')[0])
+      }
+
+      next.addClass('active')
+    }
+
+  , prev: function (event) {
+      var active = this.$menu.find('.active').removeClass('active')
+        , prev = active.prev()
+
+      if (!prev.length) {
+        prev = this.$menu.find('li').last()
+      }
+
+      prev.addClass('active')
+    }
+
+  , listen: function () {
+      this.$element
+        .on('focus',    $.proxy(this.focus, this))
+        .on('blur',     $.proxy(this.blur, this))
+        .on('keypress', $.proxy(this.keypress, this))
+        .on('keyup',    $.proxy(this.keyup, this))
+
+      if (this.eventSupported('keydown')) {
+        this.$element.on('keydown', $.proxy(this.keydown, this))
+      }
+
+      this.$menu
+        .on('click', $.proxy(this.click, this))
+        .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
+        .on('mouseleave', 'li', $.proxy(this.mouseleave, this))
+    }
+
+  , eventSupported: function(eventName) {
+      var isSupported = eventName in this.$element
+      if (!isSupported) {
+        this.$element.setAttribute(eventName, 'return;')
+        isSupported = typeof this.$element[eventName] === 'function'
+      }
+      return isSupported
+    }
+
+  , move: function (e) {
+      if (!this.shown) return
+
+      switch(e.keyCode) {
+        case 9: // tab
+        case 13: // enter
+        case 27: // escape
+          e.preventDefault()
+          break
+
+        case 38: // up arrow
+          e.preventDefault()
+          this.prev()
+          break
+
+        case 40: // down arrow
+          e.preventDefault()
+          this.next()
+          break
+      }
+
+      e.stopPropagation()
+    }
+
+  , keydown: function (e) {
+      this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])
+      this.move(e)
+    }
+
+  , keypress: function (e) {
+      if (this.suppressKeyPressRepeat) return
+      this.move(e)
+    }
+
+  , keyup: function (e) {
+      switch(e.keyCode) {
+        case 40: // down arrow
+        case 38: // up arrow
+        case 16: // shift
+        case 17: // ctrl
+        case 18: // alt
+          break
+
+        case 9: // tab
+        case 13: // enter
+          if (!this.shown) return
+          this.select()
+          break
+
+        case 27: // escape
+          if (!this.shown) return
+          this.hide()
+          break
+
+        default:
+          this.lookup()
+      }
+
+      e.stopPropagation()
+      e.preventDefault()
+  }
+
+  , focus: function (e) {
+      this.focused = true
+    }
+
+  , blur: function (e) {
+      this.focused = false
+      if (!this.mousedover && this.shown) this.hide()
+    }
+
+  , click: function (e) {
+      e.stopPropagation()
+      e.preventDefault()
+      this.select()
+      this.$element.focus()
+    }
+
+  , mouseenter: function (e) {
+      this.mousedover = true
+      this.$menu.find('.active').removeClass('active')
+      $(e.currentTarget).addClass('active')
+    }
+
+  , mouseleave: function (e) {
+      this.mousedover = false
+      if (!this.focused && this.shown) this.hide()
+    }
+
+  }
+
+
+  /* TYPEAHEAD PLUGIN DEFINITION
+   * =========================== */
+
+  var old = $.fn.typeahead
+
+  $.fn.typeahead = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('typeahead')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.typeahead.defaults = {
+    source: []
+  , items: 8
+  , menu: '<ul class="typeahead dropdown-menu"></ul>'
+  , item: '<li><a href="#"></a></li>'
+  , minLength: 1
+  }
+
+  $.fn.typeahead.Constructor = Typeahead
+
+
+ /* TYPEAHEAD NO CONFLICT
+  * =================== */
+
+  $.fn.typeahead.noConflict = function () {
+    $.fn.typeahead = old
+    return this
+  }
+
+
+ /* TYPEAHEAD DATA-API
+  * ================== */
+
+  $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
+    var $this = $(this)
+    if ($this.data('typeahead')) return
+    $this.typeahead($this.data())
+  })
+
+}(window.jQuery);
+/* ==========================================================
+ * bootstrap-affix.js v2.3.0
+ * http://twitter.github.com/bootstrap/javascript.html#affix
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* AFFIX CLASS DEFINITION
+  * ====================== */
+
+  var Affix = function (element, options) {
+    this.options = $.extend({}, $.fn.affix.defaults, options)
+    this.$window = $(window)
+      .on('scroll.affix.data-api', $.proxy(this.checkPosition, this))
+      .on('click.affix.data-api',  $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this))
+    this.$element = $(element)
+    this.checkPosition()
+  }
+
+  Affix.prototype.checkPosition = function () {
+    if (!this.$element.is(':visible')) return
+
+    var scrollHeight = $(document).height()
+      , scrollTop = this.$window.scrollTop()
+      , position = this.$element.offset()
+      , offset = this.options.offset
+      , offsetBottom = offset.bottom
+      , offsetTop = offset.top
+      , reset = 'affix affix-top affix-bottom'
+      , affix
+
+    if (typeof offset != 'object') offsetBottom = offsetTop = offset
+    if (typeof offsetTop == 'function') offsetTop = offset.top()
+    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
+
+    affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?
+      false    : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?
+      'bottom' : offsetTop != null && scrollTop <= offsetTop ?
+      'top'    : false
+
+    if (this.affixed === affix) return
+
+    this.affixed = affix
+    this.unpin = affix == 'bottom' ? position.top - scrollTop : null
+
+    this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))
+  }
+
+
+ /* AFFIX PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.affix
+
+  $.fn.affix = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('affix')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('affix', (data = new Affix(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.affix.Constructor = Affix
+
+  $.fn.affix.defaults = {
+    offset: 0
+  }
+
+
+ /* AFFIX NO CONFLICT
+  * ================= */
+
+  $.fn.affix.noConflict = function () {
+    $.fn.affix = old
+    return this
+  }
+
+
+ /* AFFIX DATA-API
+  * ============== */
+
+  $(window).on('load', function () {
+    $('[data-spy="affix"]').each(function () {
+      var $spy = $(this)
+        , data = $spy.data()
+
+      data.offset = data.offset || {}
+
+      data.offsetBottom && (data.offset.bottom = data.offsetBottom)
+      data.offsetTop && (data.offset.top = data.offsetTop)
+
+      $spy.affix(data)
+    })
+  })
+
+
+}(window.jQuery);

File diff suppressed because it is too large
+ 5 - 0
lift-stateless/src/main/resources/bootstrap/js/bootstrap.min.js


+ 27 - 0
lift-stateless/src/main/resources/index.html

@@ -0,0 +1,27 @@
+<div id="main" class="lift:surround?with=/templates-hidden/wrapper&at=content">
+  <head_merge>
+    <title>Main page</title>
+  </head_merge>
+  <div class="row">
+    <h4>This is the handy template for Lift webapp project</h4>
+    <p class="text-success">Includes:</p>
+    <ul>
+      <li>Jetty 8.1.9</li>
+      <li>Lift 2.5-M4</li>
+      <li>Configrity 1.0.0</li>
+      <li>Scallop 0.8.0</li>
+      <li>Bootstrap 2.3.0</li>
+      <li>JQuery 1.8.3</li>
+      <li>Underscore.js 1.4.3</li>
+      <li>Dojo 1.8.3</li>
+    </ul>
+    <p class="text-success">Usage:</p>
+    <ul>
+      <li>Start server on port 8080: <code>re-start</code></li>
+      <li>Create a runnable jar: <code>assembly</code></li>
+      <li>Create a folder with files, ready for deployment: <code>deploy-pack</code> (the resulting files are located in target/deploy)</li>
+      <li>Deploy the project to server and start it (requires rsync and ssh): <code>deploy-ssh "host" "path"</code></li>
+    </ul>
+  </div>
+</div>
+

File diff suppressed because it is too large
+ 1 - 0
lift-stateless/src/main/resources/jsl/jquery-1.8.3.min.js


File diff suppressed because it is too large
+ 0 - 0
lift-stateless/src/main/resources/jsl/underscore-1.4.3.min.js


+ 2 - 0
lift-stateless/src/main/resources/logback.xml

@@ -0,0 +1,2 @@
+<configuration>
+</configuration>

+ 47 - 0
lift-stateless/src/main/resources/templates-hidden/wizard-all.html

@@ -0,0 +1,47 @@
+<div class="form-horizontal" style="text-align: left; padding-top: 2em;">
+  <wizard:wizard_top> <div> <wizard:bind/> </div> </wizard:wizard_top> 
+  <wizard:wizard_top> <div> <wizard:bind/> </div> </wizard:wizard_top> 
+  <wizard:screen_top> <div> <wizard:bind/> </div> </wizard:screen_top> 
+  <wizard:errors>
+    <div>
+      <ul>
+        <wizard:item>
+          <li><wizard:bind/></li>
+        </wizard:item>
+      </ul>
+    </div>
+  </wizard:errors>
+  <fieldset>
+    <div lift:bind="wizard:fields"> 
+      <div class="control-group" lift:bind="wizard:line">
+        <span class="control-label">
+          <wizard:label>
+            <label wizard:for=""><wizard:bind></wizard:bind></label>
+          </wizard:label>
+        </span>
+        <div class="controls">
+          <wizard:form></wizard:form> 
+          <wizard:help><p class="help-block"><wizard:bind></wizard:bind></p></wizard:help> 
+          <wizard:field_errors>
+            <ul class="form-error">
+              <wizard:error><li><wizard:bind/></li></wizard:error>
+            </ul>
+          </wizard:field_errors>
+        </div>
+      </div>
+    </div>
+    <div class="form-actions" style="margin-bottom: 0;">
+      <span class="form-prev-button"><wizard:prev></wizard:prev></span>
+      <span class="form-next-button"><wizard:next></wizard:next></span>
+      <span class="form-cancel-button"><wizard:cancel></wizard:cancel></span>
+    </div>
+  </fieldset>
+  <wizard:screen_bottom><div><wizard:bind></wizard:bind></div></wizard:screen_bottom> 
+  <wizard:wizard_bottom><div><wizard:bind></wizard:bind></div></wizard:wizard_bottom>
+<script type="text/javascript"> 
+// <![CDATA[
+  $(".form-next-button button").addClass("btn btn-primary");
+  $(".form-cancel-button button").addClass("btn");
+//]]>
+</script>
+</div>

+ 48 - 0
lift-stateless/src/main/resources/templates-hidden/wrapper.html

@@ -0,0 +1,48 @@
+<html>
+  <head>
+    <!-- Let's get some style! -->
+    <link rel="stylesheet" href="/bootstrap/css/bootstrap.css"> 
+
+    <script src="/jsl/jquery-1.8.3.min.js"></script>
+    <script src="/jsl/underscore-1.4.3.min.js"></script>
+    <script src="/bootstrap/js/bootstrap.min.js"></script>
+    <script src="/bootstrap/js/bootstrap-modal.js"></script>
+    <script>
+      var dojoConfig = {
+        async: true,
+        parseOnLoad: false
+      }
+    </script>
+    <script src="//ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojo/dojo.js"></script>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+
+  </head>
+  <body>
+      <div class="navbar navbar-static-top navbar-inverse">
+        <div class="navbar-inner">
+          <div class="container">
+            <a class="brand" href="/">lift-stateless</a>
+            <div class="nav">
+              <ul class="nav">
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Menu <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="#">Item 1</a></li>
+                    <li><a href="#">Item 2</a></li>
+                  </ul>
+                </li>
+                <li>
+                  <a href="#"><i class="icon-wrench icon-white"></i></a>
+                </li>
+              </ul>
+            </div>
+          </div>
+        </div>
+      </div>
+    <div class="container">
+      <div class="row">
+        <div id="content" class="span12"/>
+      </div>
+    </div>
+  </body>
+</html>

+ 67 - 0
lift-stateless/src/main/scala/Benchmark.scala

@@ -0,0 +1,67 @@
+package code.lib
+
+import net.liftweb._
+import net.liftweb.http._
+import net.liftweb.util.Helpers._
+import net.liftweb.common._
+
+import js._
+import json._
+import JsCmds._
+
+import code.db._
+
+import java.util.concurrent.ThreadLocalRandom
+
+import scala.slick.driver.MySQLDriver.simple._
+import Database.threadLocalSession
+
+object JsonBenchmark {
+  def init() =
+    LiftRules.statelessDispatch.append{
+            case r @ Req("json" :: Nil, _, _) => () => sayHello()
+    }
+
+  def sayHello() = Full(JsonResponse(
+    JObject(List(JField("message", JString("Hello World!"))))
+  ))
+}
+
+object DbBenchmark {
+  private val DB_ROWS = 10000
+
+
+  def init() =
+    LiftRules.statelessDispatch.append{
+            case r @ Req("db" :: Nil, _, _) => () => singleQuery()
+            case r @ Req("db" :: queries :: Nil, _ , _) => () => customQuery(queries.toInt)
+    }
+
+  def customQuery(count: Int) : Box[LiftResponse] = {
+    val tlc = ThreadLocalRandom.current()
+    val randoms = for(i <- (1 to count)) yield tlc.nextLong(DB_ROWS)
+    val result = DB.exec {
+      (for {
+        w <- WorldTable
+        if w.id inSetBind randoms
+      } yield w).list
+    }
+
+    Full(JsonResponse(JArray(result.map(_.toJson))))
+  }
+
+  def singleQuery() : Box[LiftResponse] = {
+    val tlc = ThreadLocalRandom.current()
+    val random = tlc.nextLong(DB_ROWS)
+
+    val result = DB.exec {
+      (for {
+        w <- WorldTable if w.id === random
+      } yield w).list
+    }
+
+
+    Full(JsonResponse(result(0).toJson))
+  }
+
+}

+ 45 - 0
lift-stateless/src/main/scala/Boot.scala

@@ -0,0 +1,45 @@
+package bootstrap.liftweb
+
+import net.liftweb._
+import util._
+import Helpers._
+
+import common._
+import http._
+import auth._
+import sitemap._
+import Loc._
+
+import code._
+
+class Boot {
+  def boot() {
+    LiftRules.addToPackages("code")
+    LiftRules.htmlProperties.default.set((r: Req) => new Html5Properties(r.userAgent))
+    LiftRules.early.append(_.setCharacterEncoding("UTF-8"))
+
+
+    LiftRules.setSiteMap(SiteMap())
+
+    lib.JsonBenchmark.init()
+    lib.DbBenchmark.init()
+
+    // wrap the request in db
+/*    S.addAround( new LoanWrapper {
+      def apply[T](f: => T): T = {
+        code.db.DB.exec {
+          f
+        }
+      }
+    })
+*/
+    sys.addShutdownHook {
+      code.Main.server.stop() // jetty server isn't smart enough to stop itself on sigterm
+    }
+    LiftRules.unloadHooks.append({ () =>
+      // lift unload, happens after all remaining requests were served
+      println("Lift server stopped. (x_x)")
+    })
+
+  }
+}

+ 59 - 0
lift-stateless/src/main/scala/DB.scala

@@ -0,0 +1,59 @@
+package code.db
+
+import code.Main
+
+import org.apache.commons.dbcp.BasicDataSource
+import javax.sql.DataSource
+import Main.config
+import scala.slick.driver.MySQLDriver.simple._
+
+import Database.threadLocalSession
+
+
+object DB {
+  val dataSource: DataSource = {
+    val ds = new BasicDataSource
+    ds.setDriverClassName("com.mysql.jdbc.Driver")
+    ds.setUsername("benchmarkdbuser")
+    ds.setPassword("benchmarkdbpass")
+    ds.setMaxActive(20);
+    ds.setMaxIdle(10);
+    ds.setInitialSize(10);
+    ds.setValidationQuery("SELECT 1")
+    ds.setUrl("jdbc:mysql://%s/%s?useUnicode=true&characterEncoding=UTF-8"
+      format (config[String]("db.host"), config[String]("db.name")))
+    ds
+  }
+
+  // test the data source validity
+  dataSource.getConnection().close()
+
+  // perform the migrations
+  val database = Database.forDataSource(dataSource)
+
+  val lastInsertIdFunction = SimpleFunction.nullary[Long]("LAST_INSERT_ID")
+  def lastInsertId = Query(lastInsertIdFunction).firstOption
+
+
+  /** runs the db code inside the transaction */
+  def exec[A](fn: => A) =
+    database withTransaction {
+      fn
+    }
+}
+
+  case class World(id: Option[Long], randomNumber: Long) {
+    import net.liftweb.json._
+
+    def toJson = JObject(List(
+      JField("id", JInt(id.get)),
+      JField("randomNumber", JInt(randomNumber))
+    ))
+  }
+
+   object WorldTable extends Table[World]("World") {
+      def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
+      def randomNumber = column[Long]("randomNumber")
+
+      def * = id.? ~ randomNumber <> (World, World.unapply _)
+  }

+ 38 - 0
lift-stateless/src/main/scala/Main.scala

@@ -0,0 +1,38 @@
+package code
+
+import org.eclipse.jetty.server.Server
+import org.eclipse.jetty.webapp.WebAppContext
+import org.streum.configrity._
+import util.control.Exception._
+import db._
+
+object Main extends App {
+  val opts = new Options(args)
+  val defaults = new Configuration(Map[String, String](
+    "db.host" -> "localhost:3306",
+    "db.name" -> "hello_world",
+    "db.user" -> "benchmarkdbuser",
+    "db.pass" -> "benchmarkdbpass",
+    "http.port" -> "8080"
+  ))
+  val config = defaults ++ allCatch.opt(Configuration.load("server.conf")).getOrElse(Configuration()) ++ Configuration(opts.properties)
+
+  // initialize the db
+  DB
+
+  val server = new Server(config[Int]("http.port"))
+
+  val src = new java.io.File("src")
+  if (src.exists && src.isDirectory) {
+    // dev mode
+    server.setHandler(new WebAppContext("src/main/resources/", "/"))
+  } else {
+    // runnable jar
+    server.setHandler(new WebAppContext(getClass.getClassLoader.getResource("WEB-INF/web.xml").toExternalForm.stripSuffix("WEB-INF/web.xml"), "/"))
+    // setting lift's production mode
+    System.setProperty("run.mode", "production")
+  }
+
+
+  server.start()
+}

+ 14 - 0
lift-stateless/src/main/scala/Options.scala

@@ -0,0 +1,14 @@
+package code
+
+import org.rogach.scallop._
+
+class Options(args: Seq[String]) extends ScallopConf(args) {
+  version("lift-stateless, %s b%s (%3$td.%3$tm.%3$tY %3$tH:%3$tM). Built with Scala %4$s" format (
+    BuildInfo.version,
+    BuildInfo.buildinfoBuildnumber,
+    new java.util.Date(BuildInfo.buildTime),
+    BuildInfo.scalaVersion))
+
+  val properties = props[String]('C')
+
+}

+ 8 - 1
nodejs/benchmark_config

@@ -14,6 +14,13 @@
       "port": 8080,
       "sort": 9
     },
+    "mongodb-raw": {
+      "setup_file": "setup",
+      "db_url": "/mongodbdriver",
+      "query_url": "/mongodbdriver?queries=",
+      "port": 8080,
+      "sort": 47
+    },
     "mysql": {
       "setup_file": "setup",
       "db_url": "/sequelize",
@@ -29,4 +36,4 @@
       "sort": 28
     }
   }]
-}
+}

+ 54 - 22
nodejs/hello.js

@@ -1,7 +1,7 @@
 var cluster = require('cluster')
   , numCPUs = require('os').cpus().length;
 
-if (cluster.isMaster) {
+if(cluster.isMaster) {
   // Fork workers.
   for (var i = 0; i < numCPUs; i++) {
     cluster.fork();
@@ -18,10 +18,11 @@ var http = require('http')
   , url = require('url')
   , async = require('async')
   , mongoose = require('mongoose')
-  , conn = mongoose.connect('mongodb://172.16.234.132/hello_world')
+  , conn = mongoose.connect('mongodb://localhost/hello_world')
+  , MongoClient = require('mongodb').MongoClient
   , mysql = require('mysql')
   , pool  = mysql.createPool({
-      host: '172.16.234.132',
+      host: 'localhost',
       user     : 'benchmarkdbuser',
       password : 'benchmarkdbpass',
       database : 'hello_world',
@@ -29,7 +30,7 @@ var http = require('http')
     })
   , Sequelize = require("sequelize")
   , sequelize = new Sequelize('hello_world', 'benchmarkdbuser', 'benchmarkdbpass', {
-    host: '172.16.234.132',
+    host: 'localhost',
     logging: false,
     define: { timestamps: false },
     maxConcurrentQueries: 100,
@@ -41,6 +42,12 @@ var http = require('http')
     freezeTableName: true
   });
 
+var collection = null;
+
+MongoClient.connect('mongodb://localhost/hello_world?maxPoolSize=5', function(err, db) {
+  collection = db.collection('world');
+});
+
 // define model
 var Schema = mongoose.Schema
   , ObjectId = Schema.ObjectId;
@@ -63,6 +70,14 @@ function mongooseQuery(callback) {
   });
 }
 
+function mongodbDriverQuery(callback) {
+  process.nextTick(function() {
+  collection.find({ id: getRandomNumber()}).toArray(function(err, world) {
+    callback(err, world[0]);
+  });
+  })
+}
+
 function sequelizeQuery(callback) {
   World.find(getRandomNumber()).success(function (world) {
     callback(null, world);
@@ -83,6 +98,23 @@ http.createServer(function (req, res) {
     res.end(JSON.stringify(hello));
     break;
 
+  case '/mongodbdriver':
+    // Database Test
+    var values = url.parse(req.url, true);
+    var queries = values.query.queries || 1;
+    var queryFunctions = new Array(queries);
+
+    for (var i = 0; i < queries; i += 1) {
+      queryFunctions[i] = mongodbDriverQuery;
+    }
+
+    res.writeHead(200, {'Content-Type': 'application/json; charset=UTF-8'});
+
+    async.parallel(queryFunctions, function(err, results) {
+      res.end(JSON.stringify(results));
+    });
+    break;
+
   case '/mongoose':
     // Database Test
     var values = url.parse(req.url, true);
@@ -118,30 +150,30 @@ http.createServer(function (req, res) {
 
   case '/mysql':
     res.writeHead(200, {'Content-Type': 'application/json'});
-    
-    pool.getConnection(function(err, connection) {
-      if (err || !connection) {
-        return res.end('MYSQL CONNECTION ERROR.');
-      } 
 
-      function mysqlQuery(callback) {
-        connection.query("SELECT * FROM World WHERE id = " + getRandomNumber(), function(err, rows) {
+    function mysqlQuery(callback) {
+      pool.getConnection(function(err, connection) {
+        if (err) callback(err);
+        connection.query("SELECT * FROM world WHERE id = " + getRandomNumber(), function(err, rows) {
           callback(null, rows[0]);
+          connection.end();
         });
-      }
+      });
+    }
 
-      var values = url.parse(req.url, true);
-      var queries = values.query.queries || 1;
-      var queryFunctions = new Array(queries);
+    var values = url.parse(req.url, true);
+    var queries = values.query.queries || 1;
+    var queryFunctions = new Array(queries);
 
-      for (var i = 0; i < queries; i += 1) {
-        queryFunctions[i] = mysqlQuery;
+    for (var i = 0; i < queries; i += 1) {
+      queryFunctions[i] = mysqlQuery;
+    }
+    async.parallel(queryFunctions, function(err, results) {
+      if (err) {
+        res.writeHead(500);
+        return res.end('MYSQL CONNECTION ERROR.');
       }
-
-      async.parallel(queryFunctions, function(err, results) {
-        res.end(JSON.stringify(results));
-        connection.end();
-      });
+      res.end(JSON.stringify(results));
     });
     break;
 

+ 1 - 0
nodejs/package.json

@@ -7,6 +7,7 @@
     , "sequelize": "1.6.0-beta4"
     , "async": "0.2.5"
     , "mysql": "2.0.0-alpha7"
+    , "mongodb": "1.2.14"
   }
   , "main": "hello.js"
 }

+ 21 - 0
onion/Makefile

@@ -0,0 +1,21 @@
+all: hello
+
+CFLAGS=-O2 -Ionion/src/
+LDFLAGS=-lonion -ljson -lmysqlclient -lpthread -L/usr/lib64/mysql/ -L.
+
+hello.o: onion hello.c 
+
+hello: hello.o libonion_static.a
+	cc hello.o libonion_static.a -o hello -lpthread -lmysqlclient -ljson -lgnutls -lrt
+
+clean:
+	rm -f *.o hello
+
+	
+libonion_static.a: onion
+	(cd onion && mkdir -p build && cd build && cmake .. && cd src && make -j4)
+	cp onion/build/src/onion/libonion_static.a .
+
+onion:
+	git clone https://github.com/davidmoreno/onion.git
+

+ 7 - 0
onion/README

@@ -0,0 +1,7 @@
+Makefile works for ubuntu. Other distros may need tweak. These extra packages are needed:
+
+libgnutls-dev
+libmysqlclient-dev
+libjson0-dev
+
+Any question or comment to [email protected].

+ 0 - 0
onion/__init__.py


+ 18 - 0
onion/benchmark_config

@@ -0,0 +1,18 @@
+{
+  "framework": "onion",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/",
+      "port": 8080,
+      "sort": 42
+    },
+    "raw": {
+      "setup_file": "setup",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "port": 8080,
+      "sort": 43
+    }
+  }]
+}

+ 228 - 0
onion/hello.c

@@ -0,0 +1,228 @@
+// Compile it with: 
+//   $ gcc -o bench bench.c -lonion -Wall -O2 -lsqlite3
+//   $ export ONION_LOG=noinfo  # To properly test, you may need some control over logging. Here almost disabled. 
+//   $ ./bench
+// It listens to localhost:8080, known addresses: http://localhost:8080/ , http://localhost:8080/db , http://localhost:8080/db20
+// Test it with ab:
+//   $ ab -k -t 10 -c 20 http://localhost:8080/
+// It gave me (Intel(R) Core(TM) i7-2677M CPU @ 1.80GHz):
+//   Requests per second:    58288.10 [#/sec] (mean)
+
+// Done in response of http://www.techempower.com/blog/2013/03/28/framework-benchmarks/
+// Although onion is not a framework.
+
+// Copyright (c) 2013, David Moreno
+// Under BSD license
+
+// All rights reserved. 
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met: 
+// 
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer. 
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution. 
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies, 
+// either expressed or implied, of the FreeBSD Project.
+
+
+
+#include <onion/onion.h>
+#include <onion/handler.h>
+#include <onion/dict.h>
+#include <onion/block.h>
+#include <onion/log.h>
+#include <string.h>
+#include <mysql/mysql.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <json/json.h>
+#include <semaphore.h>
+#include <pthread.h>
+#include <signal.h>
+
+/// Gets the dict and converts it to JSON and writes it into the response. 
+onion_connection_status return_json(onion_dict *json, onion_request *req, onion_response *res){
+	onion_block *bl=onion_dict_to_json(json);
+	size_t size=onion_block_size(bl);
+	onion_response_set_header(res, "Content-Type","application/json");
+	onion_response_set_length(res, size);
+	onion_response_write(res, onion_block_data(bl), size);
+	onion_block_free(bl);
+	return OCS_PROCESSED;
+}
+
+/// Gets the dict and converts it to JSON and writes it into the response. 
+onion_connection_status return_json_libjson(void *_, onion_request *req, onion_response *res){
+	json_object *hello=json_object_new_object();
+	json_object_object_add(hello, "message", json_object_new_string("Hello, world"));
+	
+	const char *hello_str=json_object_to_json_string(hello);
+	int size=strlen(hello_str);
+
+	onion_response_set_header(res, "Content-Type","application/json");
+	onion_response_set_length(res, size);
+	onion_response_write(res, hello_str, size);
+	json_object_put(hello);
+	return OCS_PROCESSED;
+}
+
+/// Do one sqlite petition
+onion_connection_status return_db(MYSQL *db, onion_request *req, onion_response *res){
+	char query[256];
+	char *error;
+	const char *nqueries_str=onion_request_get_query(req,"queries");
+	int queries=(nqueries_str) ? atoi(nqueries_str) : 1;
+	
+	
+
+	json_object *json=json_object_new_object();
+	json_object *array=json_object_new_array();
+	int i;
+	for (i=0;i<queries;i++){
+		json_object *obj=json_object_new_object();
+		
+		snprintf(query,sizeof(query), "SELECT * FROM World WHERE id = %d", 1 + (rand()%10000));
+		mysql_query(db, query);
+		MYSQL_RES *sqlres = mysql_store_result(db);
+		MYSQL_ROW row = mysql_fetch_row(sqlres);
+		
+		json_object_object_add(obj, "randomNumber", json_object_new_int( atoi(row[1]) ));
+		json_object_array_add(array, obj);
+		mysql_free_result(sqlres);
+	}
+	json_object_object_add(json,"json",array);
+	const char *str=json_object_to_json_string(json);
+	int size=strlen(str);
+	onion_response_set_header(res,"Content-Type","application/json");
+	onion_response_set_length(res, size);
+	onion_response_write(res, str, size);
+	
+	json_object_put(json);
+	return OCS_PROCESSED;
+}
+
+#define NCONN 10
+// Some data needed by the handler
+struct test_data{
+	onion_dict *hello;
+	MYSQL *db[NCONN];
+	int free_db[NCONN];
+	pthread_mutex_t mutex;
+	sem_t sem;
+};
+
+MYSQL *get_connection(struct test_data *data){
+	while( 1 ){
+		sem_wait(&data->sem);
+		pthread_mutex_lock(&data->mutex);
+		int i;
+		for (i=0;i<NCONN;i++){
+			if (data->free_db[i]){
+				data->free_db[i]=0;
+				pthread_mutex_unlock(&data->mutex);
+				return data->db[i];
+			}
+		}
+		
+		pthread_mutex_unlock(&data->mutex); // I think it should never get here, but just in case
+		sem_post(&data->sem);
+	}
+}
+
+void free_connection(struct test_data *data, MYSQL *db){
+	int i;
+	for (i=0;i<NCONN;i++){
+		if (data->db[i]==db){
+			pthread_mutex_lock(&data->mutex);
+			data->free_db[i]=1;
+			pthread_mutex_unlock(&data->mutex);
+			sem_post(&data->sem);
+		}
+	}
+}
+
+/// Multiplexes to the proper handler depending on the path.
+/// As there is no proper database connection pool, take one connection randomly, and uses it.
+onion_connection_status muxer(struct test_data *data, onion_request *req, onion_response *res){
+	const char *path=onion_request_get_path(req);
+	if (strcmp(path, "")==0)
+		return return_json(data->hello, req, res);
+	if (strcmp(path, "json")==0)
+		return return_json_libjson(NULL, req, res);
+	
+	if (strcmp(path, "db")==0){
+		MYSQL *db=get_connection(data);
+		int ret=return_db(db, req, res);
+		free_connection(data, db);
+		return ret;
+	}
+	
+	return OCS_INTERNAL_ERROR;
+}
+
+onion *o=NULL;
+
+static void shutdown_server(int _){
+	if (o) 
+		onion_listen_stop(o);
+}
+
+
+/// Creates the onion http server, creates some server data, creates the handler, listens.
+int main(void){
+	signal(SIGINT,shutdown_server);
+	signal(SIGTERM,shutdown_server);
+
+	o=onion_new(O_POOL);
+	
+	struct test_data data;
+	data.hello=onion_dict_new();
+	
+	int i;
+	for (i=0;i<NCONN;i++){
+		data.db[i]=mysql_init(NULL);
+		data.free_db[i]=1;
+		if (data.db[i]==NULL){
+			ONION_ERROR("Cant create db connection: %s", mysql_error(data.db[i]));
+			return 1;
+		}
+		if (mysql_real_connect(data.db[i], "localhost", 
+                        "benchmarkdbuser", "benchmarkdbpass", "hello_world", 0, NULL, 0) == NULL) {
+			ONION_ERROR("Error %u: %s\n", mysql_errno(data.db[i]), mysql_error(data.db[i]));
+			return 1;
+		}
+	}
+	pthread_mutex_init(&data.mutex,NULL);
+	sem_init(&data.sem,0, NCONN);
+	
+	onion_dict_add(data.hello,"message","Hello, world", 0);
+
+	onion_set_root_handler(o, onion_handler_new((void*)&muxer, (void*)&data, NULL));
+
+	printf("Listening at http://localhost:8080/\n");
+	onion_listen(o);
+	
+	onion_dict_free(data.hello);
+	for (i=0;i<NCONN;i++){
+		mysql_close(data.db[i]);
+	}
+	onion_free(o);
+	return 0;
+}

+ 20 - 0
onion/setup.py

@@ -0,0 +1,20 @@
+import subprocess
+import sys
+import os
+import setup_util 
+
+def start(args):
+  setup_util.replace_text("onion/hello.c", "mysql_real_connect\(data.db\[i\], \".*\",", "mysql_real_connect(data.db[i], \"" + args.database_host + "\",")
+  os.putenv("ONION_LOG","noinfo")
+  subprocess.Popen("make && ./hello", shell=True, cwd="onion")
+  return 0
+
+def stop():
+  
+  p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+  out, err = p.communicate()
+  for line in out.splitlines():
+    if 'hello' in line:
+      pid = int(line.split(None, 2)[1])
+      os.kill(pid, 9)
+  return 0

+ 21 - 0
openresty/README.md

@@ -0,0 +1,21 @@
+# Openresty (Nginx + Lua(jit) Benchmark Test
+
+The lua app is inside [app.lua](app.lua)
+The nginx conf is inside [nginx.conf](nginx.conf)
+Requires a nginx compiled with ngx_lua module, see [openresty.org](http://openresty.org)
+
+Requires mysql hostname specified as IP address, if not possible then add resolver conf to nginx.conf.
+
+
+## Test URLs
+### JSON Encoding 
+
+http://localhost:8080/json
+
+### Single Row Random Query
+
+http://localhost:8080/db
+
+### Variable Row Query Test
+
+http://localhost:8080/db?queries=2

+ 0 - 0
openresty/__init__.py


+ 30 - 0
openresty/app.lua

@@ -0,0 +1,30 @@
+local cjson = require "cjson"
+local mysql = require "resty.mysql"
+local math = require "math"
+
+local mysqlconn = {
+    host = "DBHOSTNAME",
+    port = 3306,
+    database = "hello_world",
+    user = "benchmarkdbuser",
+    password = "benchmarkdbpass"
+}
+
+ngx.header.content_type = 'application/json'
+
+if ngx.var.uri == '/json' then
+    local resp = {message = "Hello, World!"}
+    ngx.print( cjson.encode(resp) )
+
+elseif ngx.var.uri == '/db' then
+    local db, err = mysql:new()
+    local ok, err = db:connect(mysqlconn)
+    local num_queries = tonumber(ngx.req.get_uri_args()["queries"]) or 1
+    local worlds = {}
+    for i=1, num_queries do
+        local wid = math.random(1, 10000)
+        table.insert(worlds, db:query('SELECT * FROM World WHERE id = '..wid)[1])
+    end
+    ngx.print( cjson.encode(worlds) )
+    local ok, err = db:set_keepalive(0, 256)
+end

+ 13 - 0
openresty/benchmark_config

@@ -0,0 +1,13 @@
+{
+  "framework": "openresty",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "port": 8080,
+      "sort": 50
+    }
+  }]
+}

+ 17 - 0
openresty/nginx.conf

@@ -0,0 +1,17 @@
+#worker_processes  1;
+pid        /tmp/nginx.pid;
+error_log /dev/null crit;
+#error_log /tmp/test.log error;
+events {
+    worker_connections  16384;
+}
+
+http {
+    access_log off;
+    server {
+        listen       8080;
+        location / {
+            content_by_lua_file '/home/pfalls/FrameworkBenchmarks/openresty/app.lua';
+        }
+    }
+}

+ 16 - 0
openresty/setup.py

@@ -0,0 +1,16 @@
+import subprocess
+import sys
+import setup_util
+import os
+
+def start(args):
+  setup_util.replace_text("openresty/nginx.conf", "CWD", os.getcwd())
+  setup_util.replace_text("openresty/app.lua", "DBHOSTNAME", args.database_host)
+  subprocess.Popen('sudo /usr/local/openresty/nginx/sbin/nginx -c `pwd`/nginx.conf -g "worker_processes ' + str((args.max_threads)) + ';"', shell=True, cwd="openresty")
+
+  return 0
+
+def stop():
+  subprocess.Popen('sudo /usr/local/openresty/nginx/sbin/nginx -c `pwd`/nginx.conf -s stop', shell=True, cwd="openresty")
+
+  return 0

+ 9 - 0
php-symfony2/.gitignore

@@ -0,0 +1,9 @@
+/app/cache
+/app/logs
+/bin
+/vendors
+/build
+/dist
+.DS_Store
+/tags
+.idea

+ 10 - 0
php-symfony2/.travis.yml

@@ -0,0 +1,10 @@
+language: php
+
+php:
+  - 5.3.3
+  - 5.3
+  - 5.4
+
+before_script: composer install
+
+script: phpunit -c app

+ 19 - 0
php-symfony2/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2004-2013 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 37 - 0
php-symfony2/README.md

@@ -0,0 +1,37 @@
+# Cake PHP Benchmarking Test
+
+This is the Symfony 2 PHP portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+Uses the PHP standard [JSON encoder](http://www.php.net/manual/en/function.json-encode.php).
+
+* [JSON test controller](src/Skamander/BenchmarkBundle/BenchController.php)
+
+
+### Data-Store/Database Mapping Test
+Uses the Symfony 2/Doctrine 2 Entity functionality.
+
+* [DB test controller](src/Skamander/BenchmarkBundle/BenchController.php)
+* [DB test model](src/Skamander/BenchmarkBundle/World.php)
+
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Symfony Version 2.2.1](http://symfony.com/)
+* [PHP Version 5.4.13](http://www.php.net/) with FPM and APC
+* [nginx 1.2.7](http://nginx.org/)
+* [MySQL 5.5.29](https://dev.mysql.com/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost/json
+
+### Data-Store/Database Mapping Test
+
+http://localhost/db
+
+### Variable Query Test
+    
+http://localhost/db?queries=2

+ 0 - 0
php-symfony2/__init__.py


+ 1 - 0
php-symfony2/app/.htaccess

@@ -0,0 +1 @@
+deny from all

+ 9 - 0
php-symfony2/app/AppCache.php

@@ -0,0 +1,9 @@
+<?php
+
+require_once __DIR__.'/AppKernel.php';
+
+use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
+
+class AppCache extends HttpCache
+{
+}

+ 39 - 0
php-symfony2/app/AppKernel.php

@@ -0,0 +1,39 @@
+<?php
+
+use Symfony\Component\HttpKernel\Kernel;
+use Symfony\Component\Config\Loader\LoaderInterface;
+
+class AppKernel extends Kernel
+{
+    public function registerBundles()
+    {
+        $bundles = array(
+            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
+            new Symfony\Bundle\SecurityBundle\SecurityBundle(),
+            new Symfony\Bundle\TwigBundle\TwigBundle(),
+            new Symfony\Bundle\MonologBundle\MonologBundle(),
+            new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
+            new Symfony\Bundle\AsseticBundle\AsseticBundle(),
+            new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
+            new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
+            new JMS\AopBundle\JMSAopBundle(),
+            new JMS\DiExtraBundle\JMSDiExtraBundle($this),
+            new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),
+            new Skamander\BenchmarkBundle\SkamanderBenchmarkBundle(),
+        );
+
+        if (in_array($this->getEnvironment(), array('dev', 'test'))) {
+            $bundles[] = new Acme\DemoBundle\AcmeDemoBundle();
+            $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
+            $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
+            $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
+        }
+
+        return $bundles;
+    }
+
+    public function registerContainerConfiguration(LoaderInterface $loader)
+    {
+        $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
+    }
+}

+ 13 - 0
php-symfony2/app/Resources/views/base.html.twig

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="UTF-8" />
+        <title>{% block title %}Welcome!{% endblock %}</title>
+        {% block stylesheets %}{% endblock %}
+        <link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
+    </head>
+    <body>
+        {% block body %}{% endblock %}
+        {% block javascripts %}{% endblock %}
+    </body>
+</html>

+ 669 - 0
php-symfony2/app/SymfonyRequirements.php

@@ -0,0 +1,669 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Users of PHP 5.2 should be able to run the requirements checks.
+ * This is why the file and all classes must be compatible with PHP 5.2+
+ * (e.g. not using namespaces and closures).
+ *
+ * ************** CAUTION **************
+ *
+ * DO NOT EDIT THIS FILE as it will be overriden by Composer as part of
+ * the installation/update process. The original file resides in the
+ * SensioDistributionBundle.
+ *
+ * ************** CAUTION **************
+ */
+
+/**
+ * Represents a single PHP requirement, e.g. an installed extension.
+ * It can be a mandatory requirement or an optional recommendation.
+ * There is a special subclass, named PhpIniRequirement, to check a php.ini configuration.
+ *
+ * @author Tobias Schultze <http://tobion.de>
+ */
+class Requirement
+{
+    private $fulfilled;
+    private $testMessage;
+    private $helpText;
+    private $helpHtml;
+    private $optional;
+
+    /**
+     * Constructor that initializes the requirement.
+     *
+     * @param Boolean     $fulfilled   Whether the requirement is fulfilled
+     * @param string      $testMessage The message for testing the requirement
+     * @param string      $helpHtml    The help text formatted in HTML for resolving the problem
+     * @param string|null $helpText    The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
+     * @param Boolean     $optional    Whether this is only an optional recommendation not a mandatory requirement
+     */
+    public function __construct($fulfilled, $testMessage, $helpHtml, $helpText = null, $optional = false)
+    {
+        $this->fulfilled = (Boolean) $fulfilled;
+        $this->testMessage = (string) $testMessage;
+        $this->helpHtml = (string) $helpHtml;
+        $this->helpText = null === $helpText ? strip_tags($this->helpHtml) : (string) $helpText;
+        $this->optional = (Boolean) $optional;
+    }
+
+    /**
+     * Returns whether the requirement is fulfilled.
+     *
+     * @return Boolean true if fulfilled, otherwise false
+     */
+    public function isFulfilled()
+    {
+        return $this->fulfilled;
+    }
+
+    /**
+     * Returns the message for testing the requirement.
+     *
+     * @return string The test message
+     */
+    public function getTestMessage()
+    {
+        return $this->testMessage;
+    }
+
+    /**
+     * Returns the help text for resolving the problem
+     *
+     * @return string The help text
+     */
+    public function getHelpText()
+    {
+        return $this->helpText;
+    }
+
+    /**
+     * Returns the help text formatted in HTML.
+     *
+     * @return string The HTML help
+     */
+    public function getHelpHtml()
+    {
+        return $this->helpHtml;
+    }
+
+    /**
+     * Returns whether this is only an optional recommendation and not a mandatory requirement.
+     *
+     * @return Boolean true if optional, false if mandatory
+     */
+    public function isOptional()
+    {
+        return $this->optional;
+    }
+}
+
+/**
+ * Represents a PHP requirement in form of a php.ini configuration.
+ *
+ * @author Tobias Schultze <http://tobion.de>
+ */
+class PhpIniRequirement extends Requirement
+{
+    /**
+     * Constructor that initializes the requirement.
+     *
+     * @param string           $cfgName    The configuration name used for ini_get()
+     * @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false,
+                                                    or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
+     * @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
+                                                    This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
+                                                    Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
+     * @param string|null $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived)
+     * @param string|null $helpHtml    The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived)
+     * @param string|null $helpText    The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
+     * @param Boolean     $optional    Whether this is only an optional recommendation not a mandatory requirement
+     */
+    public function __construct($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null, $optional = false)
+    {
+        $cfgValue = ini_get($cfgName);
+
+        if (is_callable($evaluation)) {
+            if (null === $testMessage || null === $helpHtml) {
+                throw new InvalidArgumentException('You must provide the parameters testMessage and helpHtml for a callback evaluation.');
+            }
+
+            $fulfilled = call_user_func($evaluation, $cfgValue);
+        } else {
+            if (null === $testMessage) {
+                $testMessage = sprintf('%s %s be %s in php.ini',
+                    $cfgName,
+                    $optional ? 'should' : 'must',
+                    $evaluation ? 'enabled' : 'disabled'
+                );
+            }
+
+            if (null === $helpHtml) {
+                $helpHtml = sprintf('Set <strong>%s</strong> to <strong>%s</strong> in php.ini<a href="#phpini">*</a>.',
+                    $cfgName,
+                    $evaluation ? 'on' : 'off'
+                );
+            }
+
+            $fulfilled = $evaluation == $cfgValue;
+        }
+
+        parent::__construct($fulfilled || ($approveCfgAbsence && false === $cfgValue), $testMessage, $helpHtml, $helpText, $optional);
+    }
+}
+
+/**
+ * A RequirementCollection represents a set of Requirement instances.
+ *
+ * @author Tobias Schultze <http://tobion.de>
+ */
+class RequirementCollection implements IteratorAggregate
+{
+    private $requirements = array();
+
+    /**
+     * Gets the current RequirementCollection as an Iterator.
+     *
+     * @return Traversable A Traversable interface
+     */
+    public function getIterator()
+    {
+        return new ArrayIterator($this->requirements);
+    }
+
+    /**
+     * Adds a Requirement.
+     *
+     * @param Requirement $requirement A Requirement instance
+     */
+    public function add(Requirement $requirement)
+    {
+        $this->requirements[] = $requirement;
+    }
+
+    /**
+     * Adds a mandatory requirement.
+     *
+     * @param Boolean     $fulfilled   Whether the requirement is fulfilled
+     * @param string      $testMessage The message for testing the requirement
+     * @param string      $helpHtml    The help text formatted in HTML for resolving the problem
+     * @param string|null $helpText    The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
+     */
+    public function addRequirement($fulfilled, $testMessage, $helpHtml, $helpText = null)
+    {
+        $this->add(new Requirement($fulfilled, $testMessage, $helpHtml, $helpText, false));
+    }
+
+    /**
+     * Adds an optional recommendation.
+     *
+     * @param Boolean     $fulfilled   Whether the recommendation is fulfilled
+     * @param string      $testMessage The message for testing the recommendation
+     * @param string      $helpHtml    The help text formatted in HTML for resolving the problem
+     * @param string|null $helpText    The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
+     */
+    public function addRecommendation($fulfilled, $testMessage, $helpHtml, $helpText = null)
+    {
+        $this->add(new Requirement($fulfilled, $testMessage, $helpHtml, $helpText, true));
+    }
+
+    /**
+     * Adds a mandatory requirement in form of a php.ini configuration.
+     *
+     * @param string           $cfgName    The configuration name used for ini_get()
+     * @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false,
+                                                    or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
+     * @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
+                                                    This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
+                                                    Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
+     * @param string      $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived)
+     * @param string      $helpHtml    The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived)
+     * @param string|null $helpText    The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
+     */
+    public function addPhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null)
+    {
+        $this->add(new PhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence, $testMessage, $helpHtml, $helpText, false));
+    }
+
+    /**
+     * Adds an optional recommendation in form of a php.ini configuration.
+     *
+     * @param string           $cfgName    The configuration name used for ini_get()
+     * @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false,
+                                                    or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
+     * @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
+                                                    This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
+                                                    Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
+     * @param string      $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived)
+     * @param string      $helpHtml    The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived)
+     * @param string|null $helpText    The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
+     */
+    public function addPhpIniRecommendation($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null)
+    {
+        $this->add(new PhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence, $testMessage, $helpHtml, $helpText, true));
+    }
+
+    /**
+     * Adds a requirement collection to the current set of requirements.
+     *
+     * @param RequirementCollection $collection A RequirementCollection instance
+     */
+    public function addCollection(RequirementCollection $collection)
+    {
+        $this->requirements = array_merge($this->requirements, $collection->all());
+    }
+
+    /**
+     * Returns both requirements and recommendations.
+     *
+     * @return array Array of Requirement instances
+     */
+    public function all()
+    {
+        return $this->requirements;
+    }
+
+    /**
+     * Returns all mandatory requirements.
+     *
+     * @return array Array of Requirement instances
+     */
+    public function getRequirements()
+    {
+        $array = array();
+        foreach ($this->requirements as $req) {
+            if (!$req->isOptional()) {
+                $array[] = $req;
+            }
+        }
+
+        return $array;
+    }
+
+    /**
+     * Returns the mandatory requirements that were not met.
+     *
+     * @return array Array of Requirement instances
+     */
+    public function getFailedRequirements()
+    {
+        $array = array();
+        foreach ($this->requirements as $req) {
+            if (!$req->isFulfilled() && !$req->isOptional()) {
+                $array[] = $req;
+            }
+        }
+
+        return $array;
+    }
+
+    /**
+     * Returns all optional recommmendations.
+     *
+     * @return array Array of Requirement instances
+     */
+    public function getRecommendations()
+    {
+        $array = array();
+        foreach ($this->requirements as $req) {
+            if ($req->isOptional()) {
+                $array[] = $req;
+            }
+        }
+
+        return $array;
+    }
+
+    /**
+     * Returns the recommendations that were not met.
+     *
+     * @return array Array of Requirement instances
+     */
+    public function getFailedRecommendations()
+    {
+        $array = array();
+        foreach ($this->requirements as $req) {
+            if (!$req->isFulfilled() && $req->isOptional()) {
+                $array[] = $req;
+            }
+        }
+
+        return $array;
+    }
+
+    /**
+     * Returns whether a php.ini configuration is not correct.
+     *
+     * @return Boolean php.ini configuration problem?
+     */
+    public function hasPhpIniConfigIssue()
+    {
+        foreach ($this->requirements as $req) {
+            if (!$req->isFulfilled() && $req instanceof PhpIniRequirement) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns the PHP configuration file (php.ini) path.
+     *
+     * @return string|false php.ini file path
+     */
+    public function getPhpIniConfigPath()
+    {
+        return get_cfg_var('cfg_file_path');
+    }
+}
+
+/**
+ * This class specifies all requirements and optional recommendations that
+ * are necessary to run the Symfony Standard Edition.
+ *
+ * @author Tobias Schultze <http://tobion.de>
+ * @author Fabien Potencier <[email protected]>
+ */
+class SymfonyRequirements extends RequirementCollection
+{
+    const REQUIRED_PHP_VERSION = '5.3.3';
+
+    /**
+     * Constructor that initializes the requirements.
+     */
+    public function __construct()
+    {
+        /* mandatory requirements follow */
+
+        $installedPhpVersion = phpversion();
+
+        $this->addRequirement(
+            version_compare($installedPhpVersion, self::REQUIRED_PHP_VERSION, '>='),
+            sprintf('PHP version must be at least %s (%s installed)', self::REQUIRED_PHP_VERSION, $installedPhpVersion),
+            sprintf('You are running PHP version "<strong>%s</strong>", but Symfony needs at least PHP "<strong>%s</strong>" to run.
+                Before using Symfony, upgrade your PHP installation, preferably to the latest version.',
+                $installedPhpVersion, self::REQUIRED_PHP_VERSION),
+            sprintf('Install PHP %s or newer (installed version is %s)', self::REQUIRED_PHP_VERSION, $installedPhpVersion)
+        );
+
+        $this->addRequirement(
+            version_compare($installedPhpVersion, '5.3.16', '!='),
+            'PHP version must not be 5.3.16 as Symfony won\'t work properly with it',
+            'Install PHP 5.3.17 or newer (or downgrade to an earlier PHP version)'
+        );
+
+        $this->addRequirement(
+            is_dir(__DIR__.'/../vendor/composer'),
+            'Vendor libraries must be installed',
+            'Vendor libraries are missing. Install composer following instructions from <a href="http://getcomposer.org/">http://getcomposer.org/</a>. ' .
+                'Then run "<strong>php composer.phar install</strong>" to install them.'
+        );
+
+        $baseDir = basename(__DIR__);
+
+        $this->addRequirement(
+            is_writable(__DIR__.'/cache'),
+            "$baseDir/cache/ directory must be writable",
+            "Change the permissions of the \"<strong>$baseDir/cache/</strong>\" directory so that the web server can write into it."
+        );
+
+        $this->addRequirement(
+            is_writable(__DIR__.'/logs'),
+            "$baseDir/logs/ directory must be writable",
+            "Change the permissions of the \"<strong>$baseDir/logs/</strong>\" directory so that the web server can write into it."
+        );
+
+        $this->addPhpIniRequirement(
+            'date.timezone', true, false,
+            'date.timezone setting must be set',
+            'Set the "<strong>date.timezone</strong>" setting in php.ini<a href="#phpini">*</a> (like Europe/Paris).'
+        );
+
+        if (version_compare($installedPhpVersion, self::REQUIRED_PHP_VERSION, '>=')) {
+            $timezones = array();
+            foreach (DateTimeZone::listAbbreviations() as $abbreviations) {
+                foreach ($abbreviations as $abbreviation) {
+                    $timezones[$abbreviation['timezone_id']] = true;
+                }
+            }
+
+            $this->addRequirement(
+                isset($timezones[date_default_timezone_get()]),
+                sprintf('Configured default timezone "%s" must be supported by your installation of PHP', date_default_timezone_get()),
+                'Your default timezone is not supported by PHP. Check for typos in your <strong>php.ini</strong> file and have a look at the list of deprecated timezones at <a href="http://php.net/manual/en/timezones.others.php">http://php.net/manual/en/timezones.others.php</a>.'
+            );
+        }
+
+        $this->addRequirement(
+            function_exists('json_encode'),
+            'json_encode() must be available',
+            'Install and enable the <strong>JSON</strong> extension.'
+        );
+
+        $this->addRequirement(
+            function_exists('session_start'),
+            'session_start() must be available',
+            'Install and enable the <strong>session</strong> extension.'
+        );
+
+        $this->addRequirement(
+            function_exists('ctype_alpha'),
+            'ctype_alpha() must be available',
+            'Install and enable the <strong>ctype</strong> extension.'
+        );
+
+        $this->addRequirement(
+            function_exists('token_get_all'),
+            'token_get_all() must be available',
+            'Install and enable the <strong>Tokenizer</strong> extension.'
+        );
+
+        $this->addRequirement(
+            function_exists('simplexml_import_dom'),
+            'simplexml_import_dom() must be available',
+            'Install and enable the <strong>SimpleXML</strong> extension.'
+        );
+
+        if (function_exists('apc_store') && ini_get('apc.enabled')) {
+            if (version_compare($installedPhpVersion, '5.4.0', '>=')) {
+                $this->addRequirement(
+                    version_compare(phpversion('apc'), '3.1.13', '>='),
+                    'APC version must be at least 3.1.13 when using PHP 5.4',
+                    'Upgrade your <strong>APC</strong> extension (3.1.13+).'
+                );
+            } else {
+                $this->addRequirement(
+                    version_compare(phpversion('apc'), '3.0.17', '>='),
+                    'APC version must be at least 3.0.17',
+                    'Upgrade your <strong>APC</strong> extension (3.0.17+).'
+                );
+            }
+        }
+
+        $this->addPhpIniRequirement('detect_unicode', false);
+
+        if (extension_loaded('suhosin')) {
+            $this->addPhpIniRequirement(
+                'suhosin.executor.include.whitelist',
+                create_function('$cfgValue', 'return false !== stripos($cfgValue, "phar");'),
+                false,
+                'suhosin.executor.include.whitelist must be configured correctly in php.ini',
+                'Add "<strong>phar</strong>" to <strong>suhosin.executor.include.whitelist</strong> in php.ini<a href="#phpini">*</a>.'
+            );
+        }
+
+        if (extension_loaded('xdebug')) {
+            $this->addPhpIniRequirement(
+                'xdebug.show_exception_trace', false, true
+            );
+
+            $this->addPhpIniRequirement(
+                'xdebug.scream', false, true
+            );
+
+            $this->addPhpIniRecommendation(
+                'xdebug.max_nesting_level',
+                create_function('$cfgValue', 'return $cfgValue > 100;'),
+                true,
+                'xdebug.max_nesting_level should be above 100 in php.ini',
+                'Set "<strong>xdebug.max_nesting_level</strong>" to e.g. "<strong>250</strong>" in php.ini<a href="#phpini">*</a> to stop Xdebug\'s infinite recursion protection erroneously throwing a fatal error in your project.'
+            );
+        }
+
+        $pcreVersion = defined('PCRE_VERSION') ? (float) PCRE_VERSION : null;
+
+        $this->addRequirement(
+            null !== $pcreVersion,
+            'PCRE extension must be available',
+            'Install the <strong>PCRE</strong> extension (version 8.0+).'
+        );
+
+        /* optional recommendations follow */
+
+        $this->addRecommendation(
+            file_get_contents(__FILE__) === file_get_contents(__DIR__.'/../vendor/sensio/distribution-bundle/Sensio/Bundle/DistributionBundle/Resources/skeleton/app/SymfonyRequirements.php'),
+            'Requirements file should be up-to-date',
+            'Your requirements file is outdated. Run composer install and re-check your configuration.'
+        );
+
+        $this->addRecommendation(
+            version_compare($installedPhpVersion, '5.3.4', '>='),
+            'You should use at least PHP 5.3.4 due to PHP bug #52083 in earlier versions',
+            'Your project might malfunction randomly due to PHP bug #52083 ("Notice: Trying to get property of non-object"). Install PHP 5.3.4 or newer.'
+        );
+
+        $this->addRecommendation(
+            version_compare($installedPhpVersion, '5.3.8', '>='),
+            'When using annotations you should have at least PHP 5.3.8 due to PHP bug #55156',
+            'Install PHP 5.3.8 or newer if your project uses annotations.'
+        );
+
+        $this->addRecommendation(
+            version_compare($installedPhpVersion, '5.4.0', '!='),
+            'You should not use PHP 5.4.0 due to the PHP bug #61453',
+            'Your project might not work properly due to the PHP bug #61453 ("Cannot dump definitions which have method calls"). Install PHP 5.4.1 or newer.'
+        );
+
+        if (null !== $pcreVersion) {
+            $this->addRecommendation(
+                $pcreVersion >= 8.0,
+                sprintf('PCRE extension should be at least version 8.0 (%s installed)', $pcreVersion),
+                '<strong>PCRE 8.0+</strong> is preconfigured in PHP since 5.3.2 but you are using an outdated version of it. Symfony probably works anyway but it is recommended to upgrade your PCRE extension.'
+            );
+        }
+
+        $this->addRecommendation(
+            class_exists('DomDocument'),
+            'PHP-XML module should be installed',
+            'Install and enable the <strong>PHP-XML</strong> module.'
+        );
+
+        $this->addRecommendation(
+            function_exists('mb_strlen'),
+            'mb_strlen() should be available',
+            'Install and enable the <strong>mbstring</strong> extension.'
+        );
+
+        $this->addRecommendation(
+            function_exists('iconv'),
+            'iconv() should be available',
+            'Install and enable the <strong>iconv</strong> extension.'
+        );
+
+        $this->addRecommendation(
+            function_exists('utf8_decode'),
+            'utf8_decode() should be available',
+            'Install and enable the <strong>XML</strong> extension.'
+        );
+
+        if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
+            $this->addRecommendation(
+                function_exists('posix_isatty'),
+                'posix_isatty() should be available',
+                'Install and enable the <strong>php_posix</strong> extension (used to colorize the CLI output).'
+            );
+        }
+
+        $this->addRecommendation(
+            class_exists('Locale'),
+            'intl extension should be available',
+            'Install and enable the <strong>intl</strong> extension (used for validators).'
+        );
+
+        if (class_exists('Collator')) {
+            $this->addRecommendation(
+                null !== new Collator('fr_FR'),
+                'intl extension should be correctly configured',
+                'The intl extension does not behave properly. This problem is typical on PHP 5.3.X x64 WIN builds.'
+            );
+        }
+
+        if (class_exists('Locale')) {
+            if (defined('INTL_ICU_VERSION')) {
+                $version = INTL_ICU_VERSION;
+            } else {
+                $reflector = new ReflectionExtension('intl');
+
+                ob_start();
+                $reflector->info();
+                $output = strip_tags(ob_get_clean());
+
+                preg_match('/^ICU version +(?:=> )?(.*)$/m', $output, $matches);
+                $version = $matches[1];
+            }
+
+            $this->addRecommendation(
+                version_compare($version, '4.0', '>='),
+                'intl ICU version should be at least 4+',
+                'Upgrade your <strong>intl</strong> extension with a newer ICU version (4+).'
+            );
+        }
+
+        $accelerator =
+            (function_exists('apc_store') && ini_get('apc.enabled'))
+            ||
+            function_exists('eaccelerator_put') && ini_get('eaccelerator.enable')
+            ||
+            function_exists('xcache_set')
+        ;
+
+        $this->addRecommendation(
+            $accelerator,
+            'a PHP accelerator should be installed',
+            'Install and enable a <strong>PHP accelerator</strong> like APC (highly recommended).'
+        );
+
+        $this->addPhpIniRecommendation('short_open_tag', false);
+
+        $this->addPhpIniRecommendation('magic_quotes_gpc', false, true);
+
+        $this->addPhpIniRecommendation('register_globals', false, true);
+
+        $this->addPhpIniRecommendation('session.auto_start', false);
+
+        $this->addRecommendation(
+            class_exists('PDO'),
+            'PDO should be installed',
+            'Install <strong>PDO</strong> (mandatory for Doctrine).'
+        );
+
+        if (class_exists('PDO')) {
+            $drivers = PDO::getAvailableDrivers();
+            $this->addRecommendation(
+                count($drivers),
+                sprintf('PDO should have some drivers installed (currently available: %s)', count($drivers) ? implode(', ', $drivers) : 'none'),
+                'Install <strong>PDO drivers</strong> (mandatory for Doctrine).'
+            );
+        }
+    }
+}

+ 14 - 0
php-symfony2/app/autoload.php

@@ -0,0 +1,14 @@
+<?php
+
+use Doctrine\Common\Annotations\AnnotationRegistry;
+
+$loader = require __DIR__.'/../vendor/autoload.php';
+
+// intl
+if (!function_exists('intl_get_error_code')) {
+    require_once __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs/functions.php';
+}
+
+AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
+
+return $loader;

+ 1137 - 0
php-symfony2/app/bootstrap.php.cache

@@ -0,0 +1,1137 @@
+<?php
+
+namespace { $loader = require_once __DIR__.'/autoload.php'; }
+
+ 
+namespace Symfony\Component\DependencyInjection
+{
+interface ContainerAwareInterface
+{
+public function setContainer(ContainerInterface $container = null);
+}
+}
+namespace Symfony\Component\DependencyInjection
+{
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
+use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
+interface ContainerInterface
+{
+const EXCEPTION_ON_INVALID_REFERENCE = 1;
+const NULL_ON_INVALID_REFERENCE = 2;
+const IGNORE_ON_INVALID_REFERENCE = 3;
+const SCOPE_CONTAINER ='container';
+const SCOPE_PROTOTYPE ='prototype';
+public function set($id, $service, $scope = self::SCOPE_CONTAINER);
+public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE);
+public function has($id);
+public function getParameter($name);
+public function hasParameter($name);
+public function setParameter($name, $value);
+public function enterScope($name);
+public function leaveScope($name);
+public function addScope(ScopeInterface $scope);
+public function hasScope($name);
+public function isScopeActive($name);
+}
+}
+namespace Symfony\Component\DependencyInjection
+{
+interface IntrospectableContainerInterface extends ContainerInterface
+{
+public function initialized($id);
+}
+}
+namespace Symfony\Component\DependencyInjection
+{
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
+use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
+use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
+class Container implements IntrospectableContainerInterface
+{
+protected $parameterBag;
+protected $services;
+protected $scopes;
+protected $scopeChildren;
+protected $scopedServices;
+protected $scopeStacks;
+protected $loading = array();
+public function __construct(ParameterBagInterface $parameterBag = null)
+{
+$this->parameterBag = null === $parameterBag ? new ParameterBag() : $parameterBag;
+$this->services = array();
+$this->scopes = array();
+$this->scopeChildren = array();
+$this->scopedServices = array();
+$this->scopeStacks = array();
+$this->set('service_container', $this);
+}
+public function compile()
+{
+$this->parameterBag->resolve();
+$this->parameterBag = new FrozenParameterBag($this->parameterBag->all());
+}
+public function isFrozen()
+{
+return $this->parameterBag instanceof FrozenParameterBag;
+}
+public function getParameterBag()
+{
+return $this->parameterBag;
+}
+public function getParameter($name)
+{
+return $this->parameterBag->get($name);
+}
+public function hasParameter($name)
+{
+return $this->parameterBag->has($name);
+}
+public function setParameter($name, $value)
+{
+$this->parameterBag->set($name, $value);
+}
+public function set($id, $service, $scope = self::SCOPE_CONTAINER)
+{
+if (self::SCOPE_PROTOTYPE === $scope) {
+throw new InvalidArgumentException(sprintf('You cannot set service "%s" of scope "prototype".', $id));
+}
+$id = strtolower($id);
+if (self::SCOPE_CONTAINER !== $scope) {
+if (!isset($this->scopedServices[$scope])) {
+throw new RuntimeException(sprintf('You cannot set service "%s" of inactive scope.', $id));
+}
+$this->scopedServices[$scope][$id] = $service;
+}
+$this->services[$id] = $service;
+}
+public function has($id)
+{
+$id = strtolower($id);
+return isset($this->services[$id]) || method_exists($this,'get'.strtr($id, array('_'=>'','.'=>'_')).'Service');
+}
+public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE)
+{
+$id = strtolower($id);
+if (isset($this->services[$id])) {
+return $this->services[$id];
+}
+if (isset($this->loading[$id])) {
+throw new ServiceCircularReferenceException($id, array_keys($this->loading));
+}
+if (method_exists($this, $method ='get'.strtr($id, array('_'=>'','.'=>'_')).'Service')) {
+$this->loading[$id] = true;
+try {
+$service = $this->$method();
+} catch (\Exception $e) {
+unset($this->loading[$id]);
+if (isset($this->services[$id])) {
+unset($this->services[$id]);
+}
+throw $e;
+}
+unset($this->loading[$id]);
+return $service;
+}
+if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
+throw new ServiceNotFoundException($id);
+}
+}
+public function initialized($id)
+{
+return isset($this->services[strtolower($id)]);
+}
+public function getServiceIds()
+{
+$ids = array();
+$r = new \ReflectionClass($this);
+foreach ($r->getMethods() as $method) {
+if (preg_match('/^get(.+)Service$/', $method->name, $match)) {
+$ids[] = self::underscore($match[1]);
+}
+}
+return array_unique(array_merge($ids, array_keys($this->services)));
+}
+public function enterScope($name)
+{
+if (!isset($this->scopes[$name])) {
+throw new InvalidArgumentException(sprintf('The scope "%s" does not exist.', $name));
+}
+if (self::SCOPE_CONTAINER !== $this->scopes[$name] && !isset($this->scopedServices[$this->scopes[$name]])) {
+throw new RuntimeException(sprintf('The parent scope "%s" must be active when entering this scope.', $this->scopes[$name]));
+}
+if (isset($this->scopedServices[$name])) {
+$services = array($this->services, $name => $this->scopedServices[$name]);
+unset($this->scopedServices[$name]);
+foreach ($this->scopeChildren[$name] as $child) {
+if (isset($this->scopedServices[$child])) {
+$services[$child] = $this->scopedServices[$child];
+unset($this->scopedServices[$child]);
+}
+}
+$this->services = call_user_func_array('array_diff_key', $services);
+array_shift($services);
+if (!isset($this->scopeStacks[$name])) {
+$this->scopeStacks[$name] = new \SplStack();
+}
+$this->scopeStacks[$name]->push($services);
+}
+$this->scopedServices[$name] = array();
+}
+public function leaveScope($name)
+{
+if (!isset($this->scopedServices[$name])) {
+throw new InvalidArgumentException(sprintf('The scope "%s" is not active.', $name));
+}
+$services = array($this->services, $this->scopedServices[$name]);
+unset($this->scopedServices[$name]);
+foreach ($this->scopeChildren[$name] as $child) {
+if (!isset($this->scopedServices[$child])) {
+continue;
+}
+$services[] = $this->scopedServices[$child];
+unset($this->scopedServices[$child]);
+}
+$this->services = call_user_func_array('array_diff_key', $services);
+if (isset($this->scopeStacks[$name]) && count($this->scopeStacks[$name]) > 0) {
+$services = $this->scopeStacks[$name]->pop();
+$this->scopedServices += $services;
+array_unshift($services, $this->services);
+$this->services = call_user_func_array('array_merge', $services);
+}
+}
+public function addScope(ScopeInterface $scope)
+{
+$name = $scope->getName();
+$parentScope = $scope->getParentName();
+if (self::SCOPE_CONTAINER === $name || self::SCOPE_PROTOTYPE === $name) {
+throw new InvalidArgumentException(sprintf('The scope "%s" is reserved.', $name));
+}
+if (isset($this->scopes[$name])) {
+throw new InvalidArgumentException(sprintf('A scope with name "%s" already exists.', $name));
+}
+if (self::SCOPE_CONTAINER !== $parentScope && !isset($this->scopes[$parentScope])) {
+throw new InvalidArgumentException(sprintf('The parent scope "%s" does not exist, or is invalid.', $parentScope));
+}
+$this->scopes[$name] = $parentScope;
+$this->scopeChildren[$name] = array();
+while ($parentScope !== self::SCOPE_CONTAINER) {
+$this->scopeChildren[$parentScope][] = $name;
+$parentScope = $this->scopes[$parentScope];
+}
+}
+public function hasScope($name)
+{
+return isset($this->scopes[$name]);
+}
+public function isScopeActive($name)
+{
+return isset($this->scopedServices[$name]);
+}
+public static function camelize($id)
+{
+return preg_replace_callback('/(^|_|\.)+(.)/', function ($match) { return ('.'=== $match[1] ?'_':'').strtoupper($match[2]); }, $id);
+}
+public static function underscore($id)
+{
+return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/','/([a-z\d])([A-Z])/'), array('\\1_\\2','\\1_\\2'), strtr($id,'_','.')));
+}
+}
+}
+namespace Symfony\Component\HttpKernel
+{
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+interface HttpKernelInterface
+{
+const MASTER_REQUEST = 1;
+const SUB_REQUEST = 2;
+public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
+}
+}
+namespace Symfony\Component\HttpKernel
+{
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\Bundle\BundleInterface;
+use Symfony\Component\Config\Loader\LoaderInterface;
+interface KernelInterface extends HttpKernelInterface, \Serializable
+{
+public function registerBundles();
+public function registerContainerConfiguration(LoaderInterface $loader);
+public function boot();
+public function shutdown();
+public function getBundles();
+public function isClassInActiveBundle($class);
+public function getBundle($name, $first = true);
+public function locateResource($name, $dir = null, $first = true);
+public function getName();
+public function getEnvironment();
+public function isDebug();
+public function getRootDir();
+public function getContainer();
+public function getStartTime();
+public function getCacheDir();
+public function getLogDir();
+public function getCharset();
+}
+}
+namespace Symfony\Component\HttpKernel
+{
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+interface TerminableInterface
+{
+public function terminate(Request $request, Response $response);
+}
+}
+namespace Symfony\Component\HttpKernel
+{
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
+use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
+use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
+use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
+use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
+use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\Bundle\BundleInterface;
+use Symfony\Component\HttpKernel\Config\FileLocator;
+use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
+use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass;
+use Symfony\Component\HttpKernel\Debug\ErrorHandler;
+use Symfony\Component\HttpKernel\Debug\ExceptionHandler;
+use Symfony\Component\Config\Loader\LoaderResolver;
+use Symfony\Component\Config\Loader\DelegatingLoader;
+use Symfony\Component\Config\ConfigCache;
+use Symfony\Component\ClassLoader\ClassCollectionLoader;
+use Symfony\Component\ClassLoader\DebugClassLoader;
+abstract class Kernel implements KernelInterface, TerminableInterface
+{
+protected $bundles;
+protected $bundleMap;
+protected $container;
+protected $rootDir;
+protected $environment;
+protected $debug;
+protected $booted;
+protected $name;
+protected $startTime;
+protected $classes;
+protected $errorReportingLevel;
+const VERSION ='2.2.1';
+const VERSION_ID ='20101';
+const MAJOR_VERSION ='2';
+const MINOR_VERSION ='2';
+const RELEASE_VERSION ='1';
+const EXTRA_VERSION ='';
+public function __construct($environment, $debug)
+{
+$this->environment = $environment;
+$this->debug = (Boolean) $debug;
+$this->booted = false;
+$this->rootDir = $this->getRootDir();
+$this->name = $this->getName();
+$this->classes = array();
+$this->bundles = array();
+if ($this->debug) {
+$this->startTime = microtime(true);
+}
+$this->init();
+}
+public function init()
+{
+ini_set('display_errors', 0);
+if ($this->debug) {
+error_reporting(-1);
+DebugClassLoader::enable();
+ErrorHandler::register($this->errorReportingLevel);
+if ('cli'!== php_sapi_name()) {
+ExceptionHandler::register();
+} else {
+ini_set('display_errors', 1);
+}
+}
+}
+public function __clone()
+{
+if ($this->debug) {
+$this->startTime = microtime(true);
+}
+$this->booted = false;
+$this->container = null;
+}
+public function boot()
+{
+if (true === $this->booted) {
+return;
+}
+$this->initializeBundles();
+$this->initializeContainer();
+foreach ($this->getBundles() as $bundle) {
+$bundle->setContainer($this->container);
+$bundle->boot();
+}
+$this->booted = true;
+}
+public function terminate(Request $request, Response $response)
+{
+if (false === $this->booted) {
+return;
+}
+if ($this->getHttpKernel() instanceof TerminableInterface) {
+$this->getHttpKernel()->terminate($request, $response);
+}
+}
+public function shutdown()
+{
+if (false === $this->booted) {
+return;
+}
+$this->booted = false;
+foreach ($this->getBundles() as $bundle) {
+$bundle->shutdown();
+$bundle->setContainer(null);
+}
+$this->container = null;
+}
+public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
+{
+if (false === $this->booted) {
+$this->boot();
+}
+return $this->getHttpKernel()->handle($request, $type, $catch);
+}
+protected function getHttpKernel()
+{
+return $this->container->get('http_kernel');
+}
+public function getBundles()
+{
+return $this->bundles;
+}
+public function isClassInActiveBundle($class)
+{
+foreach ($this->getBundles() as $bundle) {
+if (0 === strpos($class, $bundle->getNamespace())) {
+return true;
+}
+}
+return false;
+}
+public function getBundle($name, $first = true)
+{
+if (!isset($this->bundleMap[$name])) {
+throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, get_class($this)));
+}
+if (true === $first) {
+return $this->bundleMap[$name][0];
+}
+return $this->bundleMap[$name];
+}
+public function locateResource($name, $dir = null, $first = true)
+{
+if ('@'!== $name[0]) {
+throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name));
+}
+if (false !== strpos($name,'..')) {
+throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name));
+}
+$bundleName = substr($name, 1);
+$path ='';
+if (false !== strpos($bundleName,'/')) {
+list($bundleName, $path) = explode('/', $bundleName, 2);
+}
+$isResource = 0 === strpos($path,'Resources') && null !== $dir;
+$overridePath = substr($path, 9);
+$resourceBundle = null;
+$bundles = $this->getBundle($bundleName, false);
+$files = array();
+foreach ($bundles as $bundle) {
+if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) {
+if (null !== $resourceBundle) {
+throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.',
+$file,
+$resourceBundle,
+$dir.'/'.$bundles[0]->getName().$overridePath
+));
+}
+if ($first) {
+return $file;
+}
+$files[] = $file;
+}
+if (file_exists($file = $bundle->getPath().'/'.$path)) {
+if ($first && !$isResource) {
+return $file;
+}
+$files[] = $file;
+$resourceBundle = $bundle->getName();
+}
+}
+if (count($files) > 0) {
+return $first && $isResource ? $files[0] : $files;
+}
+throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name));
+}
+public function getName()
+{
+if (null === $this->name) {
+$this->name = preg_replace('/[^a-zA-Z0-9_]+/','', basename($this->rootDir));
+}
+return $this->name;
+}
+public function getEnvironment()
+{
+return $this->environment;
+}
+public function isDebug()
+{
+return $this->debug;
+}
+public function getRootDir()
+{
+if (null === $this->rootDir) {
+$r = new \ReflectionObject($this);
+$this->rootDir = str_replace('\\','/', dirname($r->getFileName()));
+}
+return $this->rootDir;
+}
+public function getContainer()
+{
+return $this->container;
+}
+public function loadClassCache($name ='classes', $extension ='.php')
+{
+if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) {
+ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension);
+}
+}
+public function setClassCache(array $classes)
+{
+file_put_contents($this->getCacheDir().'/classes.map', sprintf('<?php return %s;', var_export($classes, true)));
+}
+public function getStartTime()
+{
+return $this->debug ? $this->startTime : -INF;
+}
+public function getCacheDir()
+{
+return $this->rootDir.'/cache/'.$this->environment;
+}
+public function getLogDir()
+{
+return $this->rootDir.'/logs';
+}
+public function getCharset()
+{
+return'UTF-8';
+}
+protected function initializeBundles()
+{
+$this->bundles = array();
+$topMostBundles = array();
+$directChildren = array();
+foreach ($this->registerBundles() as $bundle) {
+$name = $bundle->getName();
+if (isset($this->bundles[$name])) {
+throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name));
+}
+$this->bundles[$name] = $bundle;
+if ($parentName = $bundle->getParent()) {
+if (isset($directChildren[$parentName])) {
+throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName]));
+}
+if ($parentName == $name) {
+throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name));
+}
+$directChildren[$parentName] = $name;
+} else {
+$topMostBundles[$name] = $bundle;
+}
+}
+if (count($diff = array_values(array_diff(array_keys($directChildren), array_keys($this->bundles))))) {
+throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0]));
+}
+$this->bundleMap = array();
+foreach ($topMostBundles as $name => $bundle) {
+$bundleMap = array($bundle);
+$hierarchy = array($name);
+while (isset($directChildren[$name])) {
+$name = $directChildren[$name];
+array_unshift($bundleMap, $this->bundles[$name]);
+$hierarchy[] = $name;
+}
+foreach ($hierarchy as $bundle) {
+$this->bundleMap[$bundle] = $bundleMap;
+array_pop($bundleMap);
+}
+}
+}
+protected function getContainerClass()
+{
+return $this->name.ucfirst($this->environment).($this->debug ?'Debug':'').'ProjectContainer';
+}
+protected function getContainerBaseClass()
+{
+return'Container';
+}
+protected function initializeContainer()
+{
+$class = $this->getContainerClass();
+$cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug);
+$fresh = true;
+if (!$cache->isFresh()) {
+$container = $this->buildContainer();
+$this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());
+$fresh = false;
+}
+require_once $cache;
+$this->container = new $class();
+$this->container->set('kernel', $this);
+if (!$fresh && $this->container->has('cache_warmer')) {
+$this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
+}
+}
+protected function getKernelParameters()
+{
+$bundles = array();
+foreach ($this->bundles as $name => $bundle) {
+$bundles[$name] = get_class($bundle);
+}
+return array_merge(
+array('kernel.root_dir'=> $this->rootDir,'kernel.environment'=> $this->environment,'kernel.debug'=> $this->debug,'kernel.name'=> $this->name,'kernel.cache_dir'=> $this->getCacheDir(),'kernel.logs_dir'=> $this->getLogDir(),'kernel.bundles'=> $bundles,'kernel.charset'=> $this->getCharset(),'kernel.container_class'=> $this->getContainerClass(),
+),
+$this->getEnvParameters()
+);
+}
+protected function getEnvParameters()
+{
+$parameters = array();
+foreach ($_SERVER as $key => $value) {
+if (0 === strpos($key,'SYMFONY__')) {
+$parameters[strtolower(str_replace('__','.', substr($key, 9)))] = $value;
+}
+}
+return $parameters;
+}
+protected function buildContainer()
+{
+foreach (array('cache'=> $this->getCacheDir(),'logs'=> $this->getLogDir()) as $name => $dir) {
+if (!is_dir($dir)) {
+if (false === @mkdir($dir, 0777, true)) {
+throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir));
+}
+} elseif (!is_writable($dir)) {
+throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir));
+}
+}
+$container = $this->getContainerBuilder();
+$extensions = array();
+foreach ($this->bundles as $bundle) {
+if ($extension = $bundle->getContainerExtension()) {
+$container->registerExtension($extension);
+$extensions[] = $extension->getAlias();
+}
+if ($this->debug) {
+$container->addObjectResource($bundle);
+}
+}
+foreach ($this->bundles as $bundle) {
+$bundle->build($container);
+}
+$container->addObjectResource($this);
+$container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions));
+if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) {
+$container->merge($cont);
+}
+$container->addCompilerPass(new AddClassesToCachePass($this));
+$container->compile();
+return $container;
+}
+protected function getContainerBuilder()
+{
+return new ContainerBuilder(new ParameterBag($this->getKernelParameters()));
+}
+protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class, $baseClass)
+{
+$dumper = new PhpDumper($container);
+$content = $dumper->dump(array('class'=> $class,'base_class'=> $baseClass));
+if (!$this->debug) {
+$content = self::stripComments($content);
+}
+$cache->write($content, $container->getResources());
+}
+protected function getContainerLoader(ContainerInterface $container)
+{
+$locator = new FileLocator($this);
+$resolver = new LoaderResolver(array(
+new XmlFileLoader($container, $locator),
+new YamlFileLoader($container, $locator),
+new IniFileLoader($container, $locator),
+new PhpFileLoader($container, $locator),
+new ClosureLoader($container),
+));
+return new DelegatingLoader($resolver);
+}
+public static function stripComments($source)
+{
+if (!function_exists('token_get_all')) {
+return $source;
+}
+$rawChunk ='';
+$output ='';
+$tokens = token_get_all($source);
+for (reset($tokens); false !== $token = current($tokens); next($tokens)) {
+if (is_string($token)) {
+$rawChunk .= $token;
+} elseif (T_START_HEREDOC === $token[0]) {
+$output .= preg_replace(array('/\s+$/Sm','/\n+/S'),"\n", $rawChunk) . $token[1];
+do {
+$token = next($tokens);
+$output .= $token[1];
+} while ($token[0] !== T_END_HEREDOC);
+$rawChunk ='';
+} elseif (!in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
+$rawChunk .= $token[1];
+}
+}
+$output .= preg_replace(array('/\s+$/Sm','/\n+/S'),"\n", $rawChunk);
+return $output;
+}
+public function serialize()
+{
+return serialize(array($this->environment, $this->debug));
+}
+public function unserialize($data)
+{
+list($environment, $debug) = unserialize($data);
+$this->__construct($environment, $debug);
+}
+}
+}
+namespace Symfony\Component\ClassLoader
+{
+class ApcClassLoader
+{
+private $prefix;
+protected $decorated;
+public function __construct($prefix, $decorated)
+{
+if (!extension_loaded('apc')) {
+throw new \RuntimeException('Unable to use ApcClassLoader as APC is not enabled.');
+}
+if (!method_exists($decorated,'findFile')) {
+throw new \InvalidArgumentException('The class finder must implement a "findFile" method.');
+}
+$this->prefix = $prefix;
+$this->decorated = $decorated;
+}
+public function register($prepend = false)
+{
+spl_autoload_register(array($this,'loadClass'), true, $prepend);
+}
+public function unregister()
+{
+spl_autoload_unregister(array($this,'loadClass'));
+}
+public function loadClass($class)
+{
+if ($file = $this->findFile($class)) {
+require $file;
+return true;
+}
+}
+public function findFile($class)
+{
+if (false === $file = apc_fetch($this->prefix.$class)) {
+apc_store($this->prefix.$class, $file = $this->decorated->findFile($class));
+}
+return $file;
+}
+public function __call($method, $args)
+{
+return call_user_func_array(array($this->decorated, $method), $args);
+}
+}
+}
+namespace Symfony\Component\HttpKernel\Bundle
+{
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
+interface BundleInterface extends ContainerAwareInterface
+{
+public function boot();
+public function shutdown();
+public function build(ContainerBuilder $container);
+public function getContainerExtension();
+public function getParent();
+public function getName();
+public function getNamespace();
+public function getPath();
+}
+}
+namespace Symfony\Component\DependencyInjection
+{
+abstract class ContainerAware implements ContainerAwareInterface
+{
+protected $container;
+public function setContainer(ContainerInterface $container = null)
+{
+$this->container = $container;
+}
+}
+}
+namespace Symfony\Component\HttpKernel\Bundle
+{
+use Symfony\Component\DependencyInjection\ContainerAware;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\Console\Application;
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
+abstract class Bundle extends ContainerAware implements BundleInterface
+{
+protected $name;
+protected $reflected;
+protected $extension;
+public function boot()
+{
+}
+public function shutdown()
+{
+}
+public function build(ContainerBuilder $container)
+{
+}
+public function getContainerExtension()
+{
+if (null === $this->extension) {
+$basename = preg_replace('/Bundle$/','', $this->getName());
+$class = $this->getNamespace().'\\DependencyInjection\\'.$basename.'Extension';
+if (class_exists($class)) {
+$extension = new $class();
+$expectedAlias = Container::underscore($basename);
+if ($expectedAlias != $extension->getAlias()) {
+throw new \LogicException(sprintf('The extension alias for the default extension of a '.'bundle must be the underscored version of the '.'bundle name ("%s" instead of "%s")',
+$expectedAlias, $extension->getAlias()
+));
+}
+$this->extension = $extension;
+} else {
+$this->extension = false;
+}
+}
+if ($this->extension) {
+return $this->extension;
+}
+}
+public function getNamespace()
+{
+if (null === $this->reflected) {
+$this->reflected = new \ReflectionObject($this);
+}
+return $this->reflected->getNamespaceName();
+}
+public function getPath()
+{
+if (null === $this->reflected) {
+$this->reflected = new \ReflectionObject($this);
+}
+return dirname($this->reflected->getFileName());
+}
+public function getParent()
+{
+return null;
+}
+final public function getName()
+{
+if (null !== $this->name) {
+return $this->name;
+}
+$name = get_class($this);
+$pos = strrpos($name,'\\');
+return $this->name = false === $pos ? $name : substr($name, $pos + 1);
+}
+public function registerCommands(Application $application)
+{
+if (!is_dir($dir = $this->getPath().'/Command')) {
+return;
+}
+$finder = new Finder();
+$finder->files()->name('*Command.php')->in($dir);
+$prefix = $this->getNamespace().'\\Command';
+foreach ($finder as $file) {
+$ns = $prefix;
+if ($relativePath = $file->getRelativePath()) {
+$ns .='\\'.strtr($relativePath,'/','\\');
+}
+$r = new \ReflectionClass($ns.'\\'.$file->getBasename('.php'));
+if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract()) {
+$application->add($r->newInstance());
+}
+}
+}
+}
+}
+namespace Symfony\Component\Config
+{
+use Symfony\Component\Config\Resource\ResourceInterface;
+class ConfigCache
+{
+private $debug;
+private $file;
+public function __construct($file, $debug)
+{
+$this->file = $file;
+$this->debug = (Boolean) $debug;
+}
+public function __toString()
+{
+return $this->file;
+}
+public function isFresh()
+{
+if (!is_file($this->file)) {
+return false;
+}
+if (!$this->debug) {
+return true;
+}
+$metadata = $this->file.'.meta';
+if (!is_file($metadata)) {
+return false;
+}
+$time = filemtime($this->file);
+$meta = unserialize(file_get_contents($metadata));
+foreach ($meta as $resource) {
+if (!$resource->isFresh($time)) {
+return false;
+}
+}
+return true;
+}
+public function write($content, array $metadata = null)
+{
+$dir = dirname($this->file);
+if (!is_dir($dir)) {
+if (false === @mkdir($dir, 0777, true)) {
+throw new \RuntimeException(sprintf('Unable to create the %s directory', $dir));
+}
+} elseif (!is_writable($dir)) {
+throw new \RuntimeException(sprintf('Unable to write in the %s directory', $dir));
+}
+$tmpFile = tempnam($dir, basename($this->file));
+if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $this->file)) {
+@chmod($this->file, 0666 & ~umask());
+} else {
+throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $this->file));
+}
+if (null !== $metadata && true === $this->debug) {
+$file = $this->file.'.meta';
+$tmpFile = tempnam($dir, basename($file));
+if (false !== @file_put_contents($tmpFile, serialize($metadata)) && @rename($tmpFile, $file)) {
+@chmod($file, 0666 & ~umask());
+}
+}
+}
+}
+}
+namespace Symfony\Component\HttpKernel
+{
+use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
+use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
+use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
+use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
+use Symfony\Component\HttpKernel\Event\PostResponseEvent;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+class HttpKernel implements HttpKernelInterface, TerminableInterface
+{
+protected $dispatcher;
+protected $resolver;
+public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver)
+{
+$this->dispatcher = $dispatcher;
+$this->resolver = $resolver;
+}
+public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
+{
+try {
+return $this->handleRaw($request, $type);
+} catch (\Exception $e) {
+if (false === $catch) {
+throw $e;
+}
+return $this->handleException($e, $request, $type);
+}
+}
+public function terminate(Request $request, Response $response)
+{
+$this->dispatcher->dispatch(KernelEvents::TERMINATE, new PostResponseEvent($this, $request, $response));
+}
+private function handleRaw(Request $request, $type = self::MASTER_REQUEST)
+{
+$event = new GetResponseEvent($this, $request, $type);
+$this->dispatcher->dispatch(KernelEvents::REQUEST, $event);
+if ($event->hasResponse()) {
+return $this->filterResponse($event->getResponse(), $request, $type);
+}
+if (false === $controller = $this->resolver->getController($request)) {
+throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". Maybe you forgot to add the matching route in your routing configuration?', $request->getPathInfo()));
+}
+$event = new FilterControllerEvent($this, $controller, $request, $type);
+$this->dispatcher->dispatch(KernelEvents::CONTROLLER, $event);
+$controller = $event->getController();
+$arguments = $this->resolver->getArguments($request, $controller);
+$response = call_user_func_array($controller, $arguments);
+if (!$response instanceof Response) {
+$event = new GetResponseForControllerResultEvent($this, $request, $type, $response);
+$this->dispatcher->dispatch(KernelEvents::VIEW, $event);
+if ($event->hasResponse()) {
+$response = $event->getResponse();
+}
+if (!$response instanceof Response) {
+$msg = sprintf('The controller must return a response (%s given).', $this->varToString($response));
+if (null === $response) {
+$msg .=' Did you forget to add a return statement somewhere in your controller?';
+}
+throw new \LogicException($msg);
+}
+}
+return $this->filterResponse($response, $request, $type);
+}
+private function filterResponse(Response $response, Request $request, $type)
+{
+$event = new FilterResponseEvent($this, $request, $type, $response);
+$this->dispatcher->dispatch(KernelEvents::RESPONSE, $event);
+return $event->getResponse();
+}
+private function handleException(\Exception $e, $request, $type)
+{
+$event = new GetResponseForExceptionEvent($this, $request, $type, $e);
+$this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event);
+$e = $event->getException();
+if (!$event->hasResponse()) {
+throw $e;
+}
+$response = $event->getResponse();
+if ($response->headers->has('X-Status-Code')) {
+$response->setStatusCode($response->headers->get('X-Status-Code'));
+$response->headers->remove('X-Status-Code');
+} elseif (!$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) {
+if ($e instanceof HttpExceptionInterface) {
+$response->setStatusCode($e->getStatusCode());
+$response->headers->add($e->getHeaders());
+} else {
+$response->setStatusCode(500);
+}
+}
+try {
+return $this->filterResponse($response, $request, $type);
+} catch (\Exception $e) {
+return $response;
+}
+}
+private function varToString($var)
+{
+if (is_object($var)) {
+return sprintf('Object(%s)', get_class($var));
+}
+if (is_array($var)) {
+$a = array();
+foreach ($var as $k => $v) {
+$a[] = sprintf('%s => %s', $k, $this->varToString($v));
+}
+return sprintf("Array(%s)", implode(', ', $a));
+}
+if (is_resource($var)) {
+return sprintf('Resource(%s)', get_resource_type($var));
+}
+if (null === $var) {
+return'null';
+}
+if (false === $var) {
+return'false';
+}
+if (true === $var) {
+return'true';
+}
+return (string) $var;
+}
+}
+}
+namespace Symfony\Component\HttpKernel\DependencyInjection
+{
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\HttpKernel;
+use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+class ContainerAwareHttpKernel extends HttpKernel
+{
+protected $container;
+public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver)
+{
+parent::__construct($dispatcher, $controllerResolver);
+$this->container = $container;
+}
+public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
+{
+$request->headers->set('X-Php-Ob-Level', ob_get_level());
+$this->container->enterScope('request');
+$this->container->set('request', $request,'request');
+try {
+$response = parent::handle($request, $type, $catch);
+} catch (\Exception $e) {
+$this->container->leaveScope('request');
+throw $e;
+}
+$this->container->leaveScope('request');
+return $response;
+}
+}
+}
+namespace Symfony\Bundle\FrameworkBundle
+{
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel;
+class HttpKernel extends ContainerAwareHttpKernel
+{
+public function forward($controller, array $attributes = array(), array $query = array())
+{
+trigger_error('forward() is deprecated since version 2.2 and will be removed in 2.3.', E_USER_DEPRECATED);
+$attributes['_controller'] = $controller;
+$subRequest = $this->container->get('request')->duplicate($query, null, $attributes);
+return $this->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
+}
+public function render($uri, array $options = array())
+{
+trigger_error('render() is deprecated since version 2.2 and will be removed in 2.3. Use Symfony\Component\HttpKernel\Fragment\FragmentHandler::render() instead.', E_USER_DEPRECATED);
+$options = $this->renderer->fixOptions($options);
+$strategy = isset($options['strategy']) ? $options['strategy'] :'default';
+unset($options['strategy']);
+$this->container->get('fragment.handler')->render($uri, $strategy, $options);
+}
+}
+}
+
+namespace { return $loader; }
+            

+ 55 - 0
php-symfony2/app/check.php

@@ -0,0 +1,55 @@
+<?php
+
+require_once dirname(__FILE__).'/SymfonyRequirements.php';
+
+$symfonyRequirements = new SymfonyRequirements();
+
+$iniPath = $symfonyRequirements->getPhpIniConfigPath();
+
+echo "********************************\n";
+echo "*                              *\n";
+echo "*  Symfony requirements check  *\n";
+echo "*                              *\n";
+echo "********************************\n\n";
+
+echo $iniPath ? sprintf("* Configuration file used by PHP: %s\n\n", $iniPath) : "* WARNING: No configuration file (php.ini) used by PHP!\n\n";
+
+echo "** ATTENTION **\n";
+echo "*  The PHP CLI can use a different php.ini file\n";
+echo "*  than the one used with your web server.\n";
+if ('\\' == DIRECTORY_SEPARATOR) {
+    echo "*  (especially on the Windows platform)\n";
+}
+echo "*  To be on the safe side, please also launch the requirements check\n";
+echo "*  from your web server using the web/config.php script.\n";
+
+echo_title('Mandatory requirements');
+
+foreach ($symfonyRequirements->getRequirements() as $req) {
+    echo_requirement($req);
+}
+
+echo_title('Optional recommendations');
+
+foreach ($symfonyRequirements->getRecommendations() as $req) {
+    echo_requirement($req);
+}
+
+/**
+ * Prints a Requirement instance
+ */
+function echo_requirement(Requirement $requirement)
+{
+    $result = $requirement->isFulfilled() ? 'OK' : ($requirement->isOptional() ? 'WARNING' : 'ERROR');
+    echo ' ' . str_pad($result, 9);
+    echo $requirement->getTestMessage() . "\n";
+
+    if (!$requirement->isFulfilled()) {
+        echo sprintf("          %s\n\n", $requirement->getHelpText());
+    }
+}
+
+function echo_title($title)
+{
+    echo "\n** $title **\n\n";
+}

+ 65 - 0
php-symfony2/app/config/config.yml

@@ -0,0 +1,65 @@
+imports:
+    - { resource: parameters.yml }
+    - { resource: security.yml }
+
+framework:
+    #esi:             ~
+    #translator:      { fallback: %locale% }
+    secret:          %secret%
+    router:
+        resource: "%kernel.root_dir%/config/routing.yml"
+        strict_requirements: %kernel.debug%
+    form:            ~
+    csrf_protection: ~
+    validation:      { enable_annotations: true }
+    templating:
+        engines: ['twig']
+        #assets_version: SomeVersionScheme
+    default_locale:  "%locale%"
+    trusted_proxies: ~
+    session:         ~
+    fragments:       ~
+
+# Twig Configuration
+twig:
+    debug:            %kernel.debug%
+    strict_variables: %kernel.debug%
+
+# Assetic Configuration
+assetic:
+    debug:          %kernel.debug%
+    use_controller: false
+    bundles:        [ ]
+    #java: /usr/bin/java
+    filters:
+        cssrewrite: ~
+        #closure:
+        #    jar: %kernel.root_dir%/Resources/java/compiler.jar
+        #yui_css:
+        #    jar: %kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar
+
+# Doctrine Configuration
+doctrine:
+    dbal:
+        driver:   %database_driver%
+        host:     %database_host%
+        port:     %database_port%
+        dbname:   %database_name%
+        user:     %database_user%
+        password: %database_password%
+        charset:  UTF8
+        # if using pdo_sqlite as your database driver, add the path in parameters.yml
+        # e.g. database_path: %kernel.root_dir%/data/data.db3
+        # path:     %database_path%
+
+    orm:
+        auto_generate_proxy_classes: %kernel.debug%
+        auto_mapping: true
+
+# Swiftmailer Configuration
+swiftmailer:
+    transport: %mailer_transport%
+    host:      %mailer_host%
+    username:  %mailer_user%
+    password:  %mailer_password%
+    spool:     { type: memory }

+ 29 - 0
php-symfony2/app/config/config_dev.yml

@@ -0,0 +1,29 @@
+imports:
+    - { resource: config.yml }
+
+framework:
+    router:   { resource: "%kernel.root_dir%/config/routing_dev.yml" }
+    profiler: { only_exceptions: false }
+
+web_profiler:
+    toolbar: true
+    intercept_redirects: false
+
+monolog:
+    handlers:
+        main:
+            type:  stream
+            path:  %kernel.logs_dir%/%kernel.environment%.log
+            level: debug
+        firephp:
+            type:  firephp
+            level: info
+        chromephp:
+            type:  chromephp
+            level: info
+
+assetic:
+    use_controller: true
+
+#swiftmailer:
+#    delivery_address: [email protected]

+ 29 - 0
php-symfony2/app/config/config_prod.yml

@@ -0,0 +1,29 @@
+imports:
+    - { resource: config.yml }
+
+# In production environment you should know that the parameters for URL generation
+# always pass the requirements. Otherwise it would break your link (or even site with
+# strict_requirements = true). So we can disable the requirements check completely for
+# enhanced performance with strict_requirements = null.
+framework:
+    router:
+        strict_requirements: null
+    #validation:
+    #    cache: apc
+
+#doctrine:
+#    orm:
+#        metadata_cache_driver: apc
+#        result_cache_driver: apc
+#        query_cache_driver: apc
+
+monolog:
+    handlers:
+        main:
+            type:         fingers_crossed
+            action_level: error
+            handler:      nested
+        nested:
+            type:  stream
+            path:  %kernel.logs_dir%/%kernel.environment%.log
+            level: debug

+ 16 - 0
php-symfony2/app/config/config_test.yml

@@ -0,0 +1,16 @@
+imports:
+    - { resource: config_dev.yml }
+
+framework:
+    test: ~
+    session:
+        storage_id: session.storage.mock_file
+    profiler:
+        enabled: false
+
+web_profiler:
+    toolbar: false
+    intercept_redirects: false
+
+swiftmailer:
+    disable_delivery: true

+ 14 - 0
php-symfony2/app/config/parameters.yml

@@ -0,0 +1,14 @@
+parameters:
+    database_driver: pdo_mysql
+    database_host: 192.168.100.102
+    database_port: null
+    database_name: hello_world
+    database_user: benchmarkdbuser
+    database_password: benchmarkdbpass
+    mailer_transport: smtp
+    mailer_host: 127.0.0.1
+    mailer_user: null
+    mailer_password: null
+    locale: en
+    secret: 2d50e353f5d24683c46e298ec0aead14
+    database_path: null

+ 3 - 0
php-symfony2/app/config/routing.yml

@@ -0,0 +1,3 @@
+_bench:
+    resource: "@SkamanderBenchmarkBundle/Controller/BenchController.php"
+    type:     annotation

+ 27 - 0
php-symfony2/app/config/routing_dev.yml

@@ -0,0 +1,27 @@
+_welcome:
+    pattern:  /
+    defaults: { _controller: AcmeDemoBundle:Welcome:index }
+
+_demo_secured:
+    resource: "@AcmeDemoBundle/Controller/SecuredController.php"
+    type:     annotation
+
+_demo:
+    resource: "@AcmeDemoBundle/Controller/DemoController.php"
+    type:     annotation
+    prefix:   /demo
+
+_wdt:
+    resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml"
+    prefix:   /_wdt
+
+_profiler:
+    resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml"
+    prefix:   /_profiler
+
+_configurator:
+    resource: "@SensioDistributionBundle/Resources/config/routing/webconfigurator.xml"
+    prefix:   /_configurator
+
+_main:
+    resource: routing.yml

+ 42 - 0
php-symfony2/app/config/security.yml

@@ -0,0 +1,42 @@
+jms_security_extra:
+    secure_all_services: false
+    expressions: true
+
+security:
+    encoders:
+        Symfony\Component\Security\Core\User\User: plaintext
+
+    role_hierarchy:
+        ROLE_ADMIN:       ROLE_USER
+        ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
+
+    providers:
+        in_memory:
+            memory:
+                users:
+                    user:  { password: userpass, roles: [ 'ROLE_USER' ] }
+                    admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
+
+    firewalls:
+        dev:
+            pattern:  ^/(_(profiler|wdt)|css|images|js)/
+            security: false
+
+        login:
+            pattern:  ^/demo/secured/login$
+            security: false
+
+        secured_area:
+            pattern:    ^/demo/secured/
+            form_login:
+                check_path: _security_check
+                login_path: _demo_login
+            logout:
+                path:   _demo_logout
+                target: _demo
+            #anonymous: ~
+            #http_basic:
+            #    realm: "Secured Demo Area"
+
+    access_control:
+        #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }

+ 22 - 0
php-symfony2/app/console

@@ -0,0 +1,22 @@
+#!/usr/bin/env php
+<?php
+
+// if you don't want to setup permissions the proper way, just uncomment the following PHP line
+// read http://symfony.com/doc/current/book/installation.html#configuration-and-setup for more information
+//umask(0000);
+
+set_time_limit(0);
+
+require_once __DIR__.'/bootstrap.php.cache';
+require_once __DIR__.'/AppKernel.php';
+
+use Symfony\Bundle\FrameworkBundle\Console\Application;
+use Symfony\Component\Console\Input\ArgvInput;
+
+$input = new ArgvInput();
+$env = $input->getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'dev');
+$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(array('--no-debug', '')) && $env !== 'prod';
+
+$kernel = new AppKernel($env, $debug);
+$application = new Application($kernel);
+$application->run($input);

+ 41 - 0
php-symfony2/app/phpunit.xml.dist

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->
+<phpunit
+    backupGlobals               = "false"
+    backupStaticAttributes      = "false"
+    colors                      = "true"
+    convertErrorsToExceptions   = "true"
+    convertNoticesToExceptions  = "true"
+    convertWarningsToExceptions = "true"
+    processIsolation            = "false"
+    stopOnFailure               = "false"
+    syntaxCheck                 = "false"
+    bootstrap                   = "bootstrap.php.cache" >
+
+    <testsuites>
+        <testsuite name="Project Test Suite">
+            <directory>../src/*/*Bundle/Tests</directory>
+            <directory>../src/*/Bundle/*Bundle/Tests</directory>
+        </testsuite>
+    </testsuites>
+
+    <!--
+    <php>
+        <server name="KERNEL_DIR" value="/path/to/your/app/" />
+    </php>
+    -->
+
+    <filter>
+        <whitelist>
+            <directory>../src</directory>
+            <exclude>
+                <directory>../src/*/*Bundle/Resources</directory>
+                <directory>../src/*/*Bundle/Tests</directory>
+                <directory>../src/*/Bundle/*Bundle/Resources</directory>
+                <directory>../src/*/Bundle/*Bundle/Tests</directory>
+            </exclude>
+        </whitelist>
+    </filter>
+
+</phpunit>

+ 13 - 0
php-symfony2/benchmark_config

@@ -0,0 +1,13 @@
+{
+  "framework": "php-symfony2",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "port": 8080,
+      "sort": 51
+    }
+  }]
+}

Some files were not shown because too many files changed in this diff