Example #1
0
 /**
  * Call this from Elefant's bootstrap.php file so that
  * links to `/{app_url}/*` map to `/saasy/*`.
  *
  * Usage:
  *
  *     saasy\App::bootstrap ($controller);
  *
  * @param \Controller $controller
  */
 public static function bootstrap($controller)
 {
     self::$controller = $controller;
     $conf = self::conf();
     $alias = $conf['App Settings']['app_alias'];
     // Rewrite /app_alias/ to /saasy/
     if ($_SERVER['REQUEST_URI'] === '/' . $alias) {
         $_SERVER['REQUEST_URI'] = '/saasy';
     } elseif (strpos($_SERVER['REQUEST_URI'], '/' . $alias . '/') === 0) {
         $_SERVER['REQUEST_URI'] = str_replace('/' . $alias . '/', '/saasy/', $_SERVER['REQUEST_URI']);
     }
     // Add bootstrap.js
     $page = $controller->page();
     $page->add_script('/apps/saasy/bootstrap/js/bootstrap.min.js');
     $page->add_script('<script>$(function(){$("input[type=submit]").addClass("btn");});</script>');
     // Get the customer from the subdomain
     $sub = self::subdomain();
     if ($sub) {
         /** @var $customer Customer */
         $customer = Customer::query()->where('subdomain', $sub)->single();
         if ($customer && !$customer->error) {
             self::customer($customer);
             // Get the account from the user
             if (\User::require_login()) {
                 /** @var $acct Account */
                 $acct = Account::query()->where('user', \User::val('id'))->where('customer', $customer->id)->single();
                 if ($acct && !$acct->error) {
                     self::acct($acct);
                 }
             }
         }
     }
 }
Example #2
0
	/**
	 * The front controller only has one static method, `run()`, which
	 * 
	 */
	public static function run ($argv, $argc) {
		/**
		 * For compatibility with PHP 5.4's built-in web server, we bypass
		 * the front controller for requests with file extensions and
		 * return false.
		 */
		if (php_sapi_name () === 'cli-server' && isset ($_SERVER['REQUEST_URI']) && preg_match ('/\.[a-zA-Z0-9]+$/', parse_url ($_SERVER['REQUEST_URI'], PHP_URL_PATH))) {
			return false;
		}

		/**
		 * Normalize slashes for servers that are still poorly
		 * configured...
		 */
		if (get_magic_quotes_gpc ()) {
			function stripslashes_gpc (&$value) {
				$value = stripslashes ($value);
			}
			array_walk_recursive ($_GET, 'stripslashes_gpc');
			array_walk_recursive ($_POST, 'stripslashes_gpc');
			array_walk_recursive ($_COOKIE, 'stripslashes_gpc');
			array_walk_recursive ($_REQUEST, 'stripslashes_gpc');
		}

		/**
		 * Check ELEFANT_ENV environment variable to determine which
		 * configuration to load. Also include the Elefant version,
		 * autoloader, and core functions, and set the default
		 * timezone to avoid warnings in date functions.
		 */
		define ('ELEFANT_ENV', getenv ('ELEFANT_ENV') ? getenv ('ELEFANT_ENV') : 'config');
		require ('conf/version.php');
		require ('lib/Autoloader.php');
		require ('lib/Functions.php');
		date_default_timezone_set(conf ('General', 'timezone'));
		ini_set ('session.cookie_httponly', 1);
		ini_set ('session.use_only_cookies', 1);

		/**
		 * Set the default error reporting level to All except Notices,
		 * and turn off displaying errors. Error handling/debugging can
		 * be done by setting conf[General][debug] to true, causing full
		 * debug traces to be displayed with highlighted code in the
		 * browser (*for development purposes only*), or by checking
		 * the error log for errors.
		 */
		error_reporting (E_ALL & ~E_NOTICE);
		if (conf ('General', 'display_errors')) {
			ini_set ('display_errors', 'On');
		} else {
			ini_set ('display_errors', 'Off');
		}

		/**
		 * Enable the debugger if conf[General][debug] is true.
		 */
		require ('lib/Debugger.php');
		Debugger::start (conf ('General', 'debug'));

		/**
		 * Include the core libraries used by the front controller
		 * to dispatch and respond to requests.
		 */
		require ('lib/DB.php');
		require ('lib/Page.php');
		require ('lib/I18n.php');
		require ('lib/Controller.php');
		require ('lib/Template.php');
		require ('lib/View.php');

		/**
		 * If we're on the command line, set the request to use
		 * the first argument passed to the script.
		 */
		if (defined ('STDIN')) {
			$_SERVER['REQUEST_URI'] = '/' . $argv[1];
		}

		/**
		 * Initialize some core objects. These function as singletons
		 * because only one instance of them per request is desired
		 * (no duplicate execution for things like loading translation
		 * files).
		 */
		$i18n = new I18n ('lang', conf ('I18n'));
		$page = new Page;
		$controller = new Controller (conf ('Hooks'));
		$tpl = new Template (conf ('General', 'charset'), $controller);
		$controller->page ($page);
		$controller->i18n ($i18n);
		$controller->template ($tpl);
		View::init ($tpl);

		/**
		 * Check for a bootstrap.php file in the root of the site
		 * and if found, use it for additional app-level configurations
		 * (Dependency Injection, custom logging settings, etc.).
		 */
		if (file_exists ('bootstrap.php')) {
			require ('bootstrap.php');
		}

		/**
		 * Initialize the built-in cache support. Provides a
		 * consistent cache API (based on Memcache) so we can always
		 * include caching in our handlers and in the front controller.
		 */
		if (! isset ($cache) || ! is_object ($cache)) {
			$cache = Cache::init (conf ('Cache'));
		}
		$controller->cache ($cache);

		/**
		 * Provide global access to core objects, although the preferred
		 * way of accessing these is via the Controller object (`$this`
		 * in handlers).
		 */
		$GLOBALS['i18n'] = $i18n;
		$GLOBALS['page'] = $page;
		$GLOBALS['controller'] = $controller;
		$GLOBALS['tpl'] = $tpl;
		$GLOBALS['cache'] = $cache;

		/**
		 * Run any config level route overrides.
		 */
		if (file_exists ('conf/routes.php')) {
			$_routes = parse_ini_file ('conf/routes.php',true);
			if (isset($_routes['Disable'])){
			foreach ($_routes['Disable'] as $_route => $_strict) {
				if (
					(!$_strict && strpos($_SERVER['REQUEST_URI'],$_route) === 0 && $_SERVER['REQUEST_URI'] !== $_route) //match from left, exclude exact
					|| 
					($_strict && $_SERVER['REQUEST_URI'] == $_route) // match exact
				) {
					$page->body = $controller->run (conf ('General', 'error_handler'), array (
						'code' => 404,
						'title' => 'Page not found.',
						'message' => ''
					));
					echo $page->render ($tpl, $controller); // render 404 page and exit
					return true;
				}
			}}
			if (isset($_routes['Redirect'])){
			foreach ($_routes['Redirect'] as $_old => $_new) {
				if ($_old !== $_new && $_SERVER['REQUEST_URI'] == $_old) $controller->redirect($_new);
			}}
			if (isset($_routes['Alias'])){
			foreach ($_routes['Alias'] as $_old => $_new) {
				if (strpos($_SERVER['REQUEST_URI'],$_old) === 0) {
					$_SERVER['REQUEST_URI'] = str_replace($_old,$_new,$_SERVER['REQUEST_URI']);
					break;
				}
			}}
			unset($_routes);
		}

		/**
		 * Route the request to the appropriate handler and get
		 * the handler's response.
		 */
		if ($i18n->url_includes_lang) {
			$handler = $controller->route ($i18n->new_request_uri);
		} else {
			$handler = $controller->route ($_SERVER['REQUEST_URI']);
		}
		$page->body = $controller->handle ($handler, false);

		/**
		 * Control caching of the response
		 */
		if (conf ('Cache', 'control') && !conf ('General', 'debug')) {
			/* Cache control is ON */
			if (session_id () === '' && $page->cache_control)
			{
				if (isset ($_SERVER["SERVER_SOFTWARE"]) && strpos ($_SERVER["SERVER_SOFTWARE"],"nginx") !== false) {
					/* Allow NGINX to cache this request  - see http://wiki.nginx.org/X-accel */
					$controller->header ('X-Accel-Buffering: yes');
					$controller->header ('X-Accel-Expires: ' . conf ('Cache', 'expires'));
				}
				/* Standard http headers */
				$controller->header ('Cache-Control: public, no-cache="set-cookie", must-revalidate, proxy-revalidate, max-age=0');
				$controller->header ('Pragma: public');
				$controller->header ('Expires: ' . gmdate ('D, d M Y H:i:s', time () + conf ('Cache', 'expires')) . ' GMT');
			} else {
				if (isset ($_SERVER["SERVER_SOFTWARE"]) && strpos ($_SERVER["SERVER_SOFTWARE"],"nginx") !== false) {
					/* Do NOT allow NGINX to cache this request - see http://wiki.nginx.org/X-accel */
					$controller->header ('X-Accel-Buffering: no');
					$controller->header ('X-Accel-Expires: 0');
				}

				/* Standard http headers */
				$controller->header ('Pragma: no-cache');
				$controller->header ('Cache-Control: no-cache, must-revalidate');
				$controller->header ('Expires: 0');
			}
		} else {
			if (isset ($_SERVER["SERVER_SOFTWARE"]) && strpos ($_SERVER["SERVER_SOFTWARE"],"nginx") !== false) {
				/* Do NOT allow NGINX to cache this request by default  - see http://wiki.nginx.org/X-accel */
				$controller->header ('X-Accel-Buffering: no');
				$controller->header ('X-Accel-Expires: 0');
			}
		}

		/**
		 * Render and send the output to the client, using gzip
		 * compression if conf[General][compress_output] is true.
		 */
		$out = $page->render ($tpl, $controller);
		if (extension_loaded ('zlib') && conf ('General', 'compress_output')) {
			ini_set ('zlib.output_compression', 4096);
		}
		@session_write_close ();
		echo $out;
		return true;
	}
Example #3
0
 function test_rest_api()
 {
     $c = new Controller();
     $c->page(new Page());
     $test_api = new RestTestApi();
     // GET bap/bop/boop should match GET bap/bop/boop
     ob_start();
     $_SERVER['REQUEST_METHOD'] = 'GET';
     $c->params = array('bap', 'bop', 'boop');
     $c->restful($test_api);
     $res = ob_get_clean();
     ob_start();
     $test_api->wrap('it works');
     $exp = ob_get_clean();
     $this->assertEquals($exp, $res);
     // POST foo/123 should match ALL foo/%d
     ob_start();
     $_SERVER['REQUEST_METHOD'] = 'POST';
     $c->params = array('foo', '123');
     $c->restful($test_api);
     $res = ob_get_clean();
     ob_start();
     $test_api->wrap('123');
     $exp = ob_get_clean();
     $this->assertEquals($exp, $res);
     // GET bar/hello should match GET bar/%s
     ob_start();
     $_SERVER['REQUEST_METHOD'] = 'GET';
     $c->params = array('bar', 'hello');
     $c->restful($test_api);
     $res = ob_get_clean();
     ob_start();
     $test_api->wrap('hello');
     $exp = ob_get_clean();
     $this->assertEquals($exp, $res);
     // POST bar/hello should fail to match GET bar/%s
     ob_start();
     $_SERVER['REQUEST_METHOD'] = 'POST';
     $c->params = array('bar', 'hello');
     $c->restful($test_api);
     $res = ob_get_clean();
     ob_start();
     $test_api->error('Invalid action name');
     $exp = ob_get_clean();
     $this->assertEquals($exp, $res);
     // GET one/and/two/and should match GET one/%s/two/%s
     ob_start();
     $_SERVER['REQUEST_METHOD'] = 'GET';
     $c->params = array('one', 'and', 'two', 'and');
     $c->restful($test_api);
     $res = ob_get_clean();
     ob_start();
     $test_api->wrap(array('and', 'and'));
     $exp = ob_get_clean();
     $this->assertEquals($exp, $res);
     // GET standard should match get_standard()
     ob_start();
     $_SERVER['REQUEST_METHOD'] = 'GET';
     $c->params = array('standard');
     $c->restful($test_api);
     $res = ob_get_clean();
     ob_start();
     $test_api->wrap('it works');
     $exp = ob_get_clean();
     $this->assertEquals($exp, $res);
     // POST standard should fail to match get_standard()
     ob_start();
     $_SERVER['REQUEST_METHOD'] = 'POST';
     $c->params = array('standard');
     $c->restful($test_api);
     $res = ob_get_clean();
     ob_start();
     $test_api->error('Invalid action name');
     $exp = ob_get_clean();
     $this->assertEquals($exp, $res);
     // GET asdf/foo should fail to match all
     ob_start();
     $_SERVER['REQUEST_METHOD'] = 'GET';
     $c->params = array('asdf', 'foo');
     $c->restful($test_api);
     $res = ob_get_clean();
     ob_start();
     $test_api->error('Invalid action name');
     $err = ob_get_clean();
     $this->assertEquals($err, $res);
 }
Example #4
0
 /**
  * Run an internal request from one handler to another.
  */
 public function run($uri, $data = array(), $internal = true)
 {
     $c = new Controller(count(self::$hooks) > 0 ? self::$hooks : conf('Hooks'));
     $c->page($this->_page);
     $c->i18n($this->_i18n);
     $c->template($this->_tpl);
     $c->cache($this->_cache);
     $handler = $c->route($uri);
     if (!isset(self::$called[$uri])) {
         self::$called[$uri] = 1;
     } else {
         self::$called[$uri]++;
     }
     return $c->handle($handler, $internal, $data);
 }