Process the HTTP request methods, such as GET, POST, HEAD, OPTIONS, etc...
Add validation against these request methods on a per path basis.
Improve path processing logic (there is still more work to do).
Other fixes and improvements.
I specifically added an nginx example configuration file (it still requires separate PHP-fcgi configuration).
const REQUEST_IF_RANGE = 22;
const REQUEST_IF_UNMODIFIED_SINCE = 23;
const REQUEST_MAX_FORWARDS = 24;
- const REQUEST_ORIGIN = 25;
- const REQUEST_POST = 26;
- const REQUEST_PRAGMA = 27;
- const REQUEST_PROXY_AUTHORIZATION = 28;
- const REQUEST_RANGE = 29;
- const REQUEST_REFERER = 30;
- const REQUEST_SCRIPT_NAME = 31;
- const REQUEST_TE = 32;
- const REQUEST_UPGRADE = 33;
- const REQUEST_URI = 34;
- const REQUEST_USER_AGENT = 35;
- const REQUEST_VIA = 36;
- const REQUEST_WARNING = 37;
+ const REQUEST_METHOD = 25;
+ const REQUEST_ORIGIN = 26;
+ const REQUEST_POST = 27;
+ const REQUEST_PRAGMA = 28;
+ const REQUEST_PROXY_AUTHORIZATION = 29;
+ const REQUEST_RANGE = 30;
+ const REQUEST_REFERER = 31;
+ const REQUEST_SCRIPT_NAME = 32;
+ const REQUEST_TE = 33;
+ const REQUEST_UPGRADE = 34;
+ const REQUEST_URI = 35;
+ const REQUEST_USER_AGENT = 36;
+ const REQUEST_VIA = 37;
+ const REQUEST_WARNING = 38;
const REQUEST_UNKNOWN = 999;
// non-standard, but supported, request headers
self::REQUEST_IF_RANGE,
self::REQUEST_IF_UNMODIFIED_SINCE,
self::REQUEST_MAX_FORWARDS,
+ self::REQUEST_METHOD,
self::REQUEST_ORIGIN,
self::REQUEST_PRAGMA,
self::REQUEST_PROXY_AUTHORIZATION,
unset($headers['max_forwards']);
}
+ // request method is stored in $_SERVER['REQUEST_METHOD'] and should always be defined (by PHP) for valid HTTP requests.
+ if (isset($_SERVER['REQUEST_METHOD'])) {
+ $this->p_load_request_method();
+ }
+
if (array_key_exists('origin', $this->headers)) {
$this->p_load_request_origin();
unset($headers['origin']);
if (is_array($uri)) {
$uri_string = $this->pr_rfc_string_combine_uri_array($uri);
- if ($combined === FALSE) {
+ if ($uri_string === FALSE) {
unset($parts);
unset($combined);
}
/**
+ * Load and process the HTTP request parameter: request method.
+ *
+ * @see: https://tools.ietf.org/html/rfc2616#section-5.1.1
+ */
+ private function p_load_request_method() {
+ $this->request[self::REQUEST_METHOD]['defined'] = TRUE;
+
+ $method_string = c_base_utf8::s_lowercase($_SERVER['REQUEST_METHOD'])->get_value_exact();
+ if ($method_string == 'get') {
+ $this->request[self::REQUEST_METHOD]['data'] = self::HTTP_METHOD_GET;
+ }
+ elseif ($method_string == 'head') {
+ $this->request[self::REQUEST_METHOD]['data'] = self::HTTP_METHOD_HEAD;
+ }
+ elseif ($method_string == 'post') {
+ $this->request[self::REQUEST_METHOD]['data'] = self::HTTP_METHOD_POST;
+ }
+ elseif ($method_string == 'put') {
+ $this->request[self::REQUEST_METHOD]['data'] = self::HTTP_METHOD_PUT;
+ }
+ elseif ($method_string == 'delete') {
+ $this->request[self::REQUEST_METHOD]['data'] = self::HTTP_METHOD_DELETE;
+ }
+ elseif ($method_string == 'trace') {
+ $this->request[self::REQUEST_METHOD]['data'] = self::HTTP_METHOD_TRACE;
+ }
+ elseif ($method_string == 'options') {
+ $this->request[self::REQUEST_METHOD]['data'] = self::HTTP_METHOD_OPTIONS;
+ }
+ elseif ($method_string == 'connect') {
+ $this->request[self::REQUEST_METHOD]['data'] = self::HTTP_METHOD_CONNECT;
+ }
+ elseif ($method_string == 'patch') {
+ $this->request[self::REQUEST_METHOD]['data'] = self::HTTP_METHOD_PATCH;
+ }
+ elseif ($method_string == 'track') {
+ $this->request[self::REQUEST_METHOD]['data'] = self::HTTP_METHOD_TRACK;
+ }
+ elseif ($method_string == 'debug') {
+ $this->request[self::REQUEST_METHOD]['data'] = self::HTTP_METHOD_DEBUG;
+ }
+ else {
+ // use 'none' to represent all unknown methods.
+ $this->request[self::REQUEST_METHOD]['data'] = self::HTTP_METHOD_NONE;
+ }
+ unset($method_string);
+
+ $this->request[self::REQUEST_METHOD]['invalid'] = FALSE;
+ }
+
+ /**
* Load and process the HTTP request parameter: origin.
*
* Errata: I cannot find Origin specified in the RFC's that I looked at.
}
if (isset($pieces[1])) {
- $lower_piece_1 = preg_replace('/(^\s+)|(\s+$)/us', '', c_base_utf8::s_lowercase($pieces[0]))->get_value_exact();
- $lower_piece_2 = preg_replace('/(^\s+)|(\s+$)/us', '', c_base_utf8::s_lowercase($pieces[1]))->get_value_exact();
+ $lower_piece_1 = preg_replace('/(^\s+)|(\s+$)/us', '', c_base_utf8::s_lowercase($pieces[0])->get_value_exact());
+ $lower_piece_2 = preg_replace('/(^\s+)|(\s+$)/us', '', c_base_utf8::s_lowercase($pieces[1])->get_value_exact());
if ($lower_piece_1 == 'trident') {
$result['engine_name_machine'] = 'trident';
$pieces = mb_split('/', $agent_matches[0]);
$total_pieces = count($pieces);
if ($total_pieces == 2) {
- $lower_piece_1 = preg_replace('/(^\s+)|(\s+$)/us', '', c_base_utf8::s_lowercase($pieces[0]))->get_value_exact();
- $lower_piece_2 = preg_replace('/(^\s+)|(\s+$)/us', '', c_base_utf8::s_lowercase($pieces[1]))->get_value_exact();
+ $lower_piece_1 = preg_replace('/(^\s+)|(\s+$)/us', '', c_base_utf8::s_lowercase($pieces[0])->get_value_exact());
+ $lower_piece_2 = preg_replace('/(^\s+)|(\s+$)/us', '', c_base_utf8::s_lowercase($pieces[1])->get_value_exact());
if ($lower_piece_1 == 'curl') {
$result['engine_name_machine'] = 'curl';
class c_base_path extends c_base_rfc_string {
use t_base_return_value_exact;
+ private const DEFAULT_ALLOWED_METHODS = array(
+ c_base_http::HTTP_METHOD_GET => c_base_http::HTTP_METHOD_GET,
+ c_base_http::HTTP_METHOD_POST => c_base_http::HTTP_METHOD_POST,
+ c_base_http::HTTP_METHOD_HEAD => c_base_http::HTTP_METHOD_HEAD,
+ c_base_http::HTTP_METHOD_OPTIONS => c_base_http::HTTP_METHOD_OPTIONS,
+ );
+
protected $id_group = NULL;
protected $is_content = NULL;
protected $include_directory = NULL;
protected $include_name = NULL;
+ protected $allowed_methods = NULL;
+
/**
* Class constructor.
*/
$this->include_directory = NULL;
$this->include_name = NULL;
+
+ $this->allowed_methods = self::DEFAULT_ALLOWED_METHODS;
}
/**
unset($this->include_directory);
unset($this->include_name);
+ unset($this->allowed_methods);
+
parent::__destruct();
}
}
/**
+ * Assign an allowed http method.
+ *
+ * @param int $method
+ * The id of the method to allow.
+ * @param bool $append
+ * (optional) When TRUE, the method id is appended.
+ * When FALSE, the array is re-created with $method as the only array value.
+ *
+ * @return c_base_return_status
+ * TRUE on success, FALSE otherwise.
+ */
+ public function set_allowed_method($method, $append = TRUE) {
+ if (!is_int($method)) {
+ $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'method', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+ return c_base_return_error::s_false($error);
+ }
+
+ if (!is_bool($append)) {
+ $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'append', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+ return c_base_return_error::s_false($error);
+ }
+
+ if (!$append) {
+ $this->allowed_methods = array();
+ }
+
+ $this->allowed_methods[$method] = $method;
+ return new c_base_return_true();
+ }
+
+ /**
+ * Assign all allowed http methods.
+ *
+ * @param array $method
+ * An array of method ids of the method to allow.
+ *
+ * @return c_base_return_status
+ * TRUE on success, FALSE otherwise.
+ */
+ public function set_allowed_methods($methods) {
+ if (!is_array($methods)) {
+ $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'methods', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+ return c_base_return_error::s_false($error);
+ }
+
+ $this->allowed_methods = array();
+ foreach ($methods as $method) {
+ if (is_int($method)) {
+ $this->allowed_methods[$method] = $method;
+ }
+ }
+ unset($method);
+
+ return new c_base_return_true();
+ }
+
+ /**
* Gets the ID sort setting.
*
* @return c_base_return_int
}
/**
+ * Get the assigned include path name.
+ *
+ * This is the suffix part of the path.
+ *
+ * @return c_base_return_array
+ * An array of allowed methods is returned.
+ * An empty array with the error bit set is returned on error.
+ */
+ public function get_allowed_methods() {
+ if (!is_array($this->allowed_methods)) {
+ $this->allowed_methods = self::DEFAULT_ALLOWED_METHODS;
+ }
+
+ return c_base_return_array::s_new($this->allowed_methods);
+ }
+
+ /**
* Execute using the specified path, rendering the page.
*
* @param c_base_http $http
* An executed array object with error bit set is returned on error.
*/
public function do_execute(&$http, &$database, &$session, $settings = array()) {
+ $executed = new c_base_path_executed();
+
if (!($http instanceof c_base_http)) {
$error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'http', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
- return c_base_return_error::s_value(array(), 'c_base_path_executed', $error);
+ $executed->set_error($error);
+ unset($error);
}
-
- if (!($database instanceof c_base_database)) {
+ elseif (!($database instanceof c_base_database)) {
$error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'database', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
- return c_base_return_error::s_value(array(), 'c_base_path_executed', $error);
+ $executed->set_error($error);
+ unset($error);
}
-
- if (!($session instanceof c_base_session)) {
+ elseif (!($session instanceof c_base_session)) {
$error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'session', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
- return c_base_return_error::s_value(array(), 'c_base_path_executed', $error);
+ $executed->set_error($error);
+ unset($error);
}
-
- if (!is_array($settings)) {
+ elseif (!is_array($settings)) {
$error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'settings', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
- return c_base_return_error::s_value(array(), 'c_base_path_executed', $error);
+ $executed->set_error($error);
+ unset($error);
}
- return new c_base_path_executed();
+ return $executed;
}
/**
// @fixme: $value is returned unsanitized until this code is implemented.
return c_base_return_value::s_new($_POST[$id]);
}
+
+ /**
+ * Obtains the current HTTP request method.
+ *
+ * @param c_base_http &$http
+ * The HTTP information object.
+ *
+ * @return int
+ * An HTTP request method is always returned.
+ */
+ protected function pr_get_method(&$http) {
+ $method = $http->get_request(c_base_http::REQUEST_METHOD)->get_value_exact();
+ if (isset($method['data']) && is_int($method['data'])) {
+ $method = $method['data'];
+ }
+ else {
+ $method = c_base_http::HTTP_METHOD_NONE;
+ }
+
+ return $method;
+ }
}
/**
/**
* Assign output.
*
- * @param c_base_return
+ * @param c_base_return|null
* The output to assign.
+ * NULL may be specified to remove any output.
*
* @return c_base_return_status
* TRUE is returned on success.
* FALSE with error bit set is returned on error.
*/
public function set_output($output) {
- if (!($output instanceof c_base_return)) {
+ if (!is_null($output) && !($output instanceof c_base_return)) {
$error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'output', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
return c_base_return_error::s_false($error);
}
* @param string|null $name
* (optional) The suffix path (relative to the PHP includes) to include that contains the requested path.
* When not NULL, both $directory and $name must not be NULL.
+ * @param array|null $allowed_methods
+ * (optional) An array of ids of allowed methods.
+ * When NULL, this value is ignored.
*
* @return c_base_return_status
* TRUE is returned on success.
* FALSE with error bit set is returned on error.
*/
- public function set_path($path, $handler, $include_directory = NULL, $include_name = NULL) {
+ public function set_path($path, $handler, $include_directory = NULL, $include_name = NULL, $allowed_methods = NULL) {
if (!is_string($path)) {
$error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'path', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
return c_base_return_error::s_false($error);
return c_base_return_error::s_false($error);
}
+
+ // get allowed methods
+ $path_object = new c_base_path();
+ if (is_null($allowed_methods)) {
+ $methods = $path_object->get_allowed_methods()->get_value_exact();
+ if (!is_array($methods)) {
+ $methods = array();
+ }
+ }
+ else {
+ $methods = $allowed_methods;
+ }
+
+
if (mb_strlen($path) == 0) {
- $this->root = array('handler' => $handler, 'include_directory' => $include_directory, 'include_name' => $include_name, 'is_root' => TRUE);
+ unset($path_object);
+ $this->root = array('handler' => $handler, 'include_directory' => $include_directory, 'include_name' => $include_name, 'is_root' => TRUE, 'methods' => $methods);
return new c_base_return_true();
}
- $path_object = new c_base_path();
- $valid_path = $path_object->set_value($path);
+ if (!is_null($allowed_methods) && !is_array($allowed_methods)) {
+ unset($path_object);
+ $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'allowed_methods', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+ return c_base_return_error::s_false($error);
+ }
+ $valid_path = $path_object->set_value($path);
if (!$valid_path) {
unset($path_object);
unset($valid_path);
}
unset($valid_path);
-
$path_string = $path_object->get_value_exact();
unset($path_object);
$depth_current = 1;
$depth_total = count($path_parts);
- foreach ($path_parts as $path_part) {
- if ($depth_current == $depth_total) {
- $path_tree['include_directory'] = $include_directory;
- $path_tree['include_name'] = $include_name;
- $path_tree['handler'] = $handler;
- break;
- }
- if (!isset($path_tree['paths'][$path_part])) {
- $path_tree['paths'][$path_part] = array(
- 'paths' => array(),
- 'include_directory' => NULL,
- 'include_name' => NULL,
- 'handler' => NULL,
- );
- }
+ // make sure the first path exists.
+ $path_part = array_shift($path_parts);
+ if (!array_key_exists($path_part, $path_tree)) {
+ $path_tree[$path_part] = array(
+ 'paths' => array(),
+ 'include_directory' => NULL,
+ 'include_name' => NULL,
+ 'handler' => NULL,
+ 'methods' => array(),
+ );
+ }
+
+ $path_tree = &$path_tree[$path_part];
+ if ($depth_current == $depth_total) {
+ $path_tree['include_directory'] = $include_directory;
+ $path_tree['include_name'] = $include_name;
+ $path_tree['handler'] = $handler;
+ $path_tree['methods'] = $methods;
+ }
+ else {
+ foreach ($path_parts as $path_part) {
+ if (!isset($path_tree['paths'][$path_part])) {
+ $path_tree['paths'][$path_part] = array(
+ 'paths' => array(),
+ 'include_directory' => NULL,
+ 'include_name' => NULL,
+ 'handler' => NULL,
+ 'methods' => array(),
+ );
+ }
- $path_tree = &$path_tree['paths'][$path_part];
- $depth_current++;
+ $path_tree = &$path_tree['paths'][$path_part];
+ $depth_current++;
+
+ if ($depth_current == $depth_total) {
+ $path_tree['include_directory'] = $include_directory;
+ $path_tree['include_name'] = $include_name;
+ $path_tree['handler'] = $handler;
+ $path_tree['methods'] = $methods;
+ break;
+ }
+ }
}
unset($path_part);
unset($path_parts);
$depth_total = count($path_parts);
$found = NULL;
$path_tree = &$this->paths[$id_group];
- foreach ($path_parts as $path_part) {
- if ($depth_current == $depth_total) {
- if (isset($path_tree['handler'])) {
- $found = array('include_directory' => $path_tree['include_directory'], 'include_name' => $path_tree['include_name'], 'handler' => $path_tree['handler']);
- break;
- }
+
+ // @fixme: the current design needs to handle multiple possible wildcard paths when searching (such as '/a/b/c/%', '/a/%/c', where '/a/b/c/%' would prevent '/a/%/c' from ever matching).
+ $path_part = array_shift($path_parts);
+ if (array_key_exists($path_part, $path_tree) || array_key_exists('%', $path_tree)) {
+ if (array_key_exists($path_part, $path_tree)) {
+ $path_tree = &$path_tree[$path_part];
+ }
+ else {
+ $path_tree = &$path_tree['%'];
}
- if (!isset($path_tree['paths'][$path_part])) {
- if ($depth_current == $depth_total) {
- if (isset($path_tree['handler'])) {
- $found = array('include_directory' => $path_tree['include_directory'], 'include_name' => $path_tree['include_name'], 'handler' => $path_tree['handler']);
+ if ($depth_current == $depth_total) {
+ $found = array(
+ 'include_directory' => $path_tree['include_directory'],
+ 'include_name' => $path_tree['include_name'],
+ 'handler' => $path_tree['handler'],
+ 'methods' => $path_tree['methods'],
+ );
+ }
+ else {
+ foreach ($path_parts as $path_part) {
+ if (array_key_exists($path_part, $path_tree['paths'])) {
+ $path_tree = &$path_tree['paths'][$path_part];
+ $depth_current++;
+ }
+ elseif (array_key_exists('%', $path_tree['paths'])) {
+ $path_tree = &$path_tree['paths']['%'];
+ $depth_current++;
+ }
+ else {
break;
}
- }
- if (isset($path_tree['paths']['%'])) {
- $path_tree = &$path_tree['paths']['%'];
- $depth_current++;
- continue;
+ if ($depth_current == $depth_total) {
+ $found = array(
+ 'include_directory' => $path_tree['include_directory'],
+ 'include_name' => $path_tree['include_name'],
+ 'handler' => $path_tree['handler'],
+ 'methods' => $path_tree['methods'],
+ );
+ break;
+ }
}
-
- break;
}
-
- $path_tree = &$path_tree['paths'][$path_part];
- $depth_current++;
}
unset($path_part);
unset($path_parts);
unset($depth_total);
unset($path_tree);
- if (is_array($found)) {
+ if (is_array($found) && !is_null($found['handler'])) {
return c_base_return_array::s_new($found);
}
unset($found);
// require a single closing '/' at the end of the path.
$this->socket_directory = preg_replace('@/*$@i', '', $socket_directory) . '/';
+
+ // if the directory is changed after the socket path is defined, then update the socket path.
+ if (!is_null($this->socket_path)) {
+ $this->socket_path = $this->socket_directory . $this->system_name . self::SOCKET_PATH_SUFFIX;
+ }
+
return new c_base_return_true();
}
return c_base_return_error::s_false($error);
}
+ // make sure the socket directory is defined before assigning the socket path based on the system name.
+ if (is_null($this->socket_directory)) {
+ $this->socket_directory = self::SOCKET_PATH_PREFIX;
+ }
+
$this->system_name = basename($system_name);
$this->socket_path = $this->socket_directory . $this->system_name . self::SOCKET_PATH_SUFFIX;
--- /dev/null
+server {
+ listen 80 default_server;
+ listen 443 default_server ssl;
+
+ ssl_certificate server.crt;
+ ssl_certificate_key server.key;
+ ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
+ ssl_ciphers HIGH:!aNULL:!MD5;
+
+ # Disable nginx server http header
+ server_tokens off;
+ more_clear_headers 'Server';
+
+ # set the root website files (do not store the PHP source code here, do not even provide an index.php)
+ root /var/www;
+
+ # Make site accessible from http://localhost/
+ server_name localhost;
+
+ # send all paths to the PHP fastcgi service.
+ location ~* {
+ include fastcgi_params;
+
+ #fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_index index.php;
+ fastcgi_param SCRIPT_FILENAME /var/git/koopa/program/reservation/index.php;
+ #fastcgi_intercept_errors on;
+ fastcgi_pass 127.0.0.1:9000;
+ }
+}
$settings['session_max'] = 1800; // 30 minutes
// ldap information
- $settings['ldap_server'] = 'ldaps://127.0.0.1:1636/';
- $settings['ldap_base_dn'] = 'ou=users,ou=People';
- $settings['ldap_fields'] = array('mail', 'gecos', 'givenname', 'cn', 'sn', 'employeenumber');
+ $settings['ldap_server'] = NULL; // 'ldaps://127.0.0.1:1636/';
+ $settings['ldap_base_dn'] = '';
+ $settings['ldap_fields'] = array();
// base settings
$settings['base_scheme'] = 'https';
* Http object.
*/
function reservation_send_response($http) {
+ // get current http header method, which may determine which headers to set or not set.
+ $method = $http->get_request(c_base_http::REQUEST_METHOD)->get_value_exact();
+ if (isset($method['data']) && is_int($method['data'])) {
+ $method = $method['data'];
+ }
+ else {
+ $method = c_base_http::HTTP_METHOD_NONE;
+ }
+
// add headers
$http->set_response_date();
$http->set_response_content_type('text/html');
$http->set_response_vary('Accept-Language');
#$http->set_response_warning('1234 This site is under active development.');
+
// finalize the content prior to sending headers to ensure header accuracy.
$http->encode_response_content();
+ // http head method responses do not sent content.
+ if ($method === c_base_http::HTTP_METHOD_HEAD) {
+ $http->set_response_content('', FALSE);
+ }
+
// manually disable output buffering (if enabled) when transfer headers and content.
$old_output_buffering = ini_get('output_buffering');
* Http object.
* @param c_base_session &$session
* Session information.
- * @param string $markup
- * The HTML markup.
+ * @param string $output
+ * The output string.
+ * Can be any string, such as HTML markup.
*/
-function reservation_build_response(&$http, &$session, $markup) {
+function reservation_build_response(&$http, &$session, $output) {
$http->set_response_checksum_header(c_base_http::CHECKSUM_ACTION_AUTO);
- $http->set_response_content($markup);
+ $http->set_response_content($output);
// send the session cookie if a session id is specified.
// 5: build or finalize theme.
- $markup = reservation_render_theme($http, $output)->get_value_exact();
- unset($output);
+ if (($output instanceof c_base_return_null)) {
+ $output = '';
+ }
+ else {
+ $output = reservation_render_theme($http, $output)->get_value_exact();
+ }
gc_collect_cycles();
// 6: build response information.
- reservation_build_response($http, $session, $markup);
- unset($markup);
+ reservation_build_response($http, $session, $output);
+ unset($output);
gc_collect_cycles();
require_once(self::PATH_REDIRECTS);
$destination = $settings['uri'];
- $destination['path'] = $settings['base_path'] . '/u/dashboard';
+ $destination['path'] = $settings['base_path'] . 'u/dashboard';
// note: by using a SEE OTHER redirect, the client knows to make a GET request and that the redirect is temporary.
$redirect = c_reservation_path_redirect::s_create_redirect($destination, c_base_http_status::SEE_OTHER, FALSE);
if (empty($_POST['login_form-username'])) {
$problems[] = c_base_form_problem::s_create_error('login_form-username', 'No valid username has been supplied.');
}
+ elseif ($_POST['login_form-username'] == 'u_reservation_public') {
+ // explicitly deny access to internal user accounts
+ $problems[] = c_base_form_problem::s_create_error('login_form-username', 'Unable to login, an incorrect user name or password has been specified.');
+ }
if (empty($_POST['login_form-password'])) {
$problems[] = c_base_form_problem::s_create_error('login_form-password', 'No valid password has been supplied.');
}
- // explicitly deny access to internal user accounts
- if ($_POST['login_form-username'] == 'u_reservation_public') {
- $problems[] = c_base_form_problem::s_create_error('login_form-username', 'Unable to login, an incorrect user name or password has been specified.');
- }
-
// return current list of problems before continuing to login attempt with credentials.
if (!empty($problems)) {
return c_base_return_array::s_new($problems);
if (isset($ldap['status']) && $ldap['status'] instanceof c_base_return_false) {
$problems[] = c_base_form_problem::s_create_error('login_form-username', 'Failed to retrieve ldap information for specified user.');
-
- // @todo: handle error situation.
}
$user_data = reservation_database_get_user_data($database, $_POST['login_form-username'], $ldap['data'])->get_value();
'data' => NULL,
);
+
+ // ldap support is disabled if ldap_server is set to NULL.
+ if (is_null($settings['ldap_server'])) {
+ return c_base_return_array::s_new($return_data);
+ }
+
+
$ldap = new c_base_ldap();
$ldap->set_name($settings['ldap_server']);
#$ldap->set_bind_name('');
require_once('common/base/classes/base_return.php');
require_once('common/base/classes/base_markup.php');
require_once('common/base/classes/base_html.php');
+require_once('common/base/classes/base_http.php');
require_once('common/base/classes/base_charset.php');
require_once('common/base/classes/base_ascii.php');
require_once('common/base/classes/base_form.php');
$this->p_paths_create();
+ // load the http method.
+ $method = $this->http->get_request(c_base_http::REQUEST_METHOD)->get_value_exact();
+ if (isset($method['data']) && is_int($method['data'])) {
+ $method = $method['data'];
+ }
+ else {
+ $method = c_base_http::HTTP_METHOD_NONE;
+ }
+
+
// find the path
$handler_settings = $this->paths->find_path($this->settings['uri']['path'])->get_value();
-
if (!is_array($handler_settings)) {
+ // for all invalid pages, report bad method if not HTTP GET or HTTP POST.
+ if ($method !== c_base_http::HTTP_METHOD_GET && $method !== c_base_http::HTTP_METHOD_POST) {
+ unset($method);
+
+ $failure_path = $this->p_get_path_bad_method();
+
+ return $failure_path->do_execute($this->http, $this->database, $this->session, $this->settings);
+ }
+ unset($method);
+
$not_found = $this->p_get_path_not_found();
return $not_found->do_execute($this->http, $this->database, $this->session, $this->settings);
}
+ // validate allowed methods.
+ if (isset($handler_settings['methods']) && is_array($handler_settings['methods'])) {
+ if (!array_key_exists($method, $handler_settings['methods'])) {
+ unset($method);
+
+ $failure_path = $this->p_get_path_bad_method();
+
+ return $failure_path->do_execute($this->http, $this->database, $this->session, $this->settings);
+ }
+ }
+
+
+ // HTTP OPTIONS method does not process the page, only returns available methods.
+ if ($method === c_base_http::HTTP_METHOD_OPTIONS) {
+ unset($method);
+
+ $options_method_path = $this->p_get_path_options_method();
+
+ if (isset($handler_settings['methods']) && is_array($handler_settings['methods'])) {
+ $options_method_path->set_allowed_methods($handler_settings['methods']);
+ }
+ else {
+ $options_method_path->set_allowed_methods(array());
+ }
+
+ return $options_method_path->do_execute($this->http, $this->database, $this->session, $this->settings);
+ }
+
+
if (array_key_exists('redirect', $handler_settings)) {
+ unset($method);
+
// successfully logged in.
require_once(self::PATH_REDIRECTS . self::NAME_REDIRECTS . '.php');
}
unset($handler_settings);
- // handle request method validation.
- if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
- // @todo: considering limiting _POST to different path groups here.
- }
- elseif (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'GET') {
- $id_group = $this->path->get_id_group()->get_value_exact();
-
- // all paths except /s/ and /x/ may use GET.
- if ($id_group === c_base_ascii::LOWER_S || $id_group === c_base_ascii::LOWER_X) {
- $failure_path = $this->p_get_path_bad_method();
-
- return $failure_path->do_execute($this->http, $this->database, $this->session, $this->settings);
- }
- unset($id_group);
- }
- else {
- $failure_path = $this->p_get_path_bad_method();
-
- return $failure_path->do_execute($this->http, $this->database, $this->session, $this->settings);
- }
-
- return $this->p_paths_normal();
+ return $this->p_paths_normal($method);
}
/**
$this->paths->set_path('', 'c_reservation_path_user_dashboard', 'program/reservation/paths/u/', 'dashboard.php');
// create login/logout paths
- $this->paths->set_path('/u/login', 'c_reservation_path_user_login', 'program/reservation/', 'login.php');
- $this->paths->set_path('/u/logout', 'c_reservation_path_user_logout', 'program/reservation/', 'logout.php');
+ $this->paths->set_path('/u/login', 'c_reservation_path_user_login', 'program/reservation/paths/u/', 'login.php');
+ $this->paths->set_path('/u/logout', 'c_reservation_path_user_logout', 'program/reservation/paths/u/', 'logout.php');
// user dashboard
$this->paths->set_path('/u/dashboard', 'c_reservation_path_user_dashboard', 'program/reservation/paths/u/', 'dashboard.php');
/**
* Process request paths and determine what to do.
*
+ * @param int $method
+ * The id of the HTTP request method.
+ *
* @return c_base_path_executed
* The execution results.
* The execution results with the error bit set on error.
*/
- private function p_paths_normal() {
+ private function p_paths_normal($method) {
$id_group = $this->path->get_id_group()->get_value_exact();
// regardless of path-specific settings, the following paths always require login credentials to access.
}
/**
+ * Load and return the internal server error path.
+ */
+ private function p_get_path_options_method() {
+ return new c_reservation_path_options_method();
+ }
+
+ /**
* Load and save the current preferred language alias.
*
* This will be stored in $this->alias.
return new $class();
}
}
+
+/**
+ * Provide the HTTP options response.
+ *
+ * This does not provide any content body.
+ */
+final class c_reservation_path_options_method extends c_base_path {
+
+ /**
+ * Implements do_execute().
+ */
+ public function do_execute(&$http, &$database, &$session, $settings = array()) {
+ // the parent function performs validation on the parameters.
+ $executed = parent::do_execute($http, $database, $session, $settings);
+ if (c_base_return::s_has_error($executed)) {
+ return $executed;
+ }
+
+
+ // assign HTTP response status.
+ $allowed_methods = $this->allowed_methods;
+ $allowed_method = array_shift($allowed_methods);
+ $http->set_response_allow($allowed_method, TRUE);
+
+ if (!empty($allowed_methods)) {
+ foreach ($allowed_methods as $allowed_method) {
+ $http->set_response_allow($allowed_method);
+ }
+ }
+ unset($allowed_method);
+ unset($allowed_methods);
+
+ return $executed;
+ }
+
+ /**
+ * Load the title text associated with this page.
+ *
+ * This is provided here as a means for a language class to override with a custom language for the title.
+ *
+ * @return string|null
+ * A string is returned as the custom title.
+ * NULL is returned to enforce default title.
+ */
+ protected function pr_get_title() {
+ return NULL;
+ }
+
+ /**
+ * Load text for a supported language.
+ *
+ * @param int $index
+ * A number representing which block of text to return.
+ */
+ protected function pr_get_text($code) {
+ switch ($code) {
+ case 0:
+ return 'Server Error';
+ case 1:
+ return 'Something went wrong while processing your request, please try again later.';
+ }
+
+ return '';
+ }
+}
+
gcc -g source/c/sessionize_ldap_accounts_in_postgresql.c -o /programs/bin/sessionize_ldap_accounts_in_postgresql
Add and enable the init script:
- cp -v source/bash/sessionize_ldap_accounts_in_postgresql.sh /etc/init.d/sessionize_ldap_accounts_in_postgresql
- chkconfig --add sessionize_ldap_accounts_in_postgresql
- chkconfig sessionize_ldap_accounts_in_postgresql on
+ cp -v source/bash/sessionize_accounts.sh /etc/init.d/sessionize_accounts
+ chkconfig --add sessionize_accounts
+ chkconfig sessionize_accounts on
Configure the settings (assuming system called "example"):
mkdir -vp /programs/settings/sessionize_ldap_accounts_in_postgresql/
### END INIT INFO
# Source function library.
-. /etc/rc.d/init.d/functions
+if [[ -f /etc/rc.d/init.d/functions ]] ; then
+ . /etc/rc.d/init.d/functions
+fi
main() {
local process_owner=
local path_service="/usr/local/bin/php ${path_programs}bin/sessionize_accounts-server.php"
local path_settings="${path_programs}settings/sessionize_accounts/"
local path_systems="${path_settings}systems.settings"
- local path_pids="/var/run/sessionize_accounts/"
- local path_socket_directory="/var/www/sockets/sessionize_accounts/"
+ local path_pids="/programs/run/sessionize_accounts/"
+ local path_socket_directory="/programs/sockets/sessionize_accounts/"
+ local path_socket_name="sessions.socket"
local parameter_system=$2
local sa_systems=
local i=
# make sure no session socket already exists before starting.
# this assumes that the pid file has already been checked and therefore no existing process is using the socket file (aka: assume this is a stale socket file).
- if [[ -e $path_socket_directory/$sa_system/sessions.socket ]] ; then
- rm -f $path_socket_directory/$sa_system/sessions.socket
+ if [[ -e $path_socket_directory/$sa_system/$path_socket_name ]] ; then
+ rm -f $path_socket_directory/$sa_system/$path_socket_name
fi
if [[ $process_owner == "" ]] ; then
result=$?
fi
+ # make sure the socket can be written to.
+ if [[ -e $path_socket_directory/$sa_system/$path_socket_name ]] ; then
+ chmod ugo+w $path_socket_directory/$sa_system/$path_socket_name
+ fi
+
if [[ $result -ne 0 ]] ; then
echo "Failed to start process, command: $path_service \"$sa_system\"."
any_failure=1
sleep 0.1
# cleanup the session socket ad pid file.
- rm -f $path_socket_directory/$sa_system/sessions.socket
+ rm -f $path_socket_directory/$sa_system/$path_socket_name
rm -f $pid_file
fi
}
// long running processes should have PHP's garbage collection enabled, otherwise no cleanup ever happens.
gc_enable();
- $pid_path_directory = '/var/run/sessionize_accounts/';
+ $pid_path_directory = '/programs/run/sessionize_accounts/';
$pid_path = $pid_path_directory . $argv[1] . '.pid';
- $socket_path = '/var/www/sockets/sessionize_accounts/' . $argv[1] . '/sessions.socket';
+ $socket_path = '/programs/sockets/sessionize_accounts/' . $argv[1] . '/sessions.socket';
$socket_family = AF_UNIX;
$socket_port = 0;
$socket_protocol = 0;