]> Kevux Git Server - koopa/commitdiff
Progress: continuing development, database work, use c_base_return on more classes...
authorKevin Day <thekevinday@gmail.com>
Sat, 25 Feb 2017 01:18:28 +0000 (19:18 -0600)
committerKevin Day <thekevinday@gmail.com>
Sat, 25 Feb 2017 01:18:28 +0000 (19:18 -0600)
Further work on building the database structure.

Added some missing roles:
- Requester
- Editor

A number of inconsistencies have been identified and resolved.

After reviewing my use of c_base_cookie as extending the class c_base_return, I have decided that to do that everywhere possible.
This simplifies the return structure that I complicated when I decided to use the c_base_return return type development design.

I noticed that there is still some cookie functionality that I could implement.
This adds support for 'same site' and 'host only'.
These are functionally equivalent except that I think 'same site' is a little more granular.

This also adds one of my test scripts under examples.
It is very likely not completely up to date with the database changes.

Many other changes.

37 files changed:
common/base/classes/base_access.php
common/base/classes/base_cookie.php
common/base/classes/base_database.php
common/base/classes/base_debug.php
common/base/classes/base_email.php
common/base/classes/base_error.php
common/base/classes/base_error_messages_english.php
common/base/classes/base_form.php [new file with mode: 0644]
common/base/classes/base_html.php
common/base/classes/base_http.php
common/base/classes/base_ldap.php
common/base/classes/base_log.php
common/base/classes/base_markup.php
common/base/classes/base_rfc_char.php
common/base/classes/base_rfc_string.php
common/base/classes/base_session.php
common/theme/classes/theme_dom.php
common/theme/classes/theme_html.php
database/sql/reservation/base-associations.sql
database/sql/reservation/base-fields.sql
database/sql/reservation/base-first.sql
database/sql/reservation/base-groups.sql
database/sql/reservation/base-log_groups.sql
database/sql/reservation/base-log_problems.sql
database/sql/reservation/base-log_types.sql
database/sql/reservation/base-log_users.sql
database/sql/reservation/base-main.sql
database/sql/reservation/base-paths.sql
database/sql/reservation/base-requests.sql
database/sql/reservation/base-statistics.sql
database/sql/reservation/base-users.sql
documentation/access_roles.txt
examples/test.php [new file with mode: 0755]
program/reservation/index.php
program/reservation/reservation_database.php
program/reservation/reservation_paths.php
program/reservation/reservation_session.php

index 162d1902d23ba3f68aaa24e33dafd7d4f4f0dadf..5812b23a3841e348459cd344726cff8e746d9ce5 100644 (file)
@@ -28,22 +28,28 @@ require_once('common/base/classes/base_ldap.php');
  * - Drafter: account is for making templates, drafts, ideas, etc.. (this is a lesser form of "editer").
  * - Editer: account is for editors who add/manage/create content.
  * - Reviewer: account is for users who review something (such as a user who approves content for publishing).
+ * - Insurer: account is for users who deal with insurance related information.
+ * - Financer: account is for users who deal with financial related information.
  * - Publisher: account is for users who perform publishing (marking content available and complete).
+ * - Auditor: account is for users who perform auditing. This account has read access to almost all data on the system.
  * - Manager: account is for users who manager the entire system. This is a non-technical administration account.
  * - Administer: account is for users who have full administrative access to the system. This is a technical administration account and supercedes Manager.
  */
-class c_base_roles {
+class c_base_roles extends c_base_return {
   const NONE       = 0;
   const PUBLIC     = 1;
   const SYSTEM     = 2;
   const USER       = 3;
   const REQUESTER  = 4;
   const DRAFTER    = 5;
-  const EDITER     = 6;
+  const EDITOR     = 6;
   const REVIEWER   = 7;
-  const PUBLISHER  = 8;
-  const MANAGER    = 9;
-  const ADMINISTER = 10;
+  const INSURER    = 8;
+  const FINANCER   = 9;
+  const PUBLISHER  = 10;
+  const AUDITOR    = 11;
+  const MANAGER    = 12;
+  const ADMINISTER = 13;
 
   private $public;
   private $system;
@@ -52,7 +58,10 @@ class c_base_roles {
   private $drafter;
   private $editer;
   private $reviewer;
+  private $insurer;
+  private $financer;
   private $publisher;
+  private $auditor;
   private $manager;
   private $administer;
 
@@ -60,6 +69,8 @@ class c_base_roles {
    * Class constructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->public     = TRUE;
     $this->system     = FALSE;
     $this->user       = FALSE;
@@ -67,7 +78,10 @@ class c_base_roles {
     $this->drafter    = FALSE;
     $this->editer     = FALSE;
     $this->reviewer   = FALSE;
+    $this->financer   = FALSE;
+    $this->insurer    = FALSE;
     $this->publisher  = FALSE;
+    $this->auditor    = FALSE;
     $this->manager    = FALSE;
     $this->administer = FALSE;
   }
@@ -83,9 +97,35 @@ class c_base_roles {
     unset($this->drafter);
     unset($this->editer);
     unset($this->reviewer);
+    unset($this->financer);
+    unset($this->insurer);
     unset($this->publisher);
+    unset($this->auditor);
     unset($this->manager);
     unset($this->administer);
+
+    parent::__destruct();
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, array());
   }
 
   /**
@@ -124,6 +164,7 @@ class c_base_roles {
         $this->editer     = FALSE;
         $this->reviewer   = FALSE;
         $this->publisher  = FALSE;
+        $this->auditor    = FALSE;
         $this->manager    = FALSE;
         $this->administer = FALSE;
       }
@@ -143,15 +184,24 @@ class c_base_roles {
     elseif ($role === self::DRAFTER) {
       $this->drafter = $value;
     }
-    elseif ($role === self::EDITER) {
+    elseif ($role === self::EDITOR) {
       $this->editer = $value;
     }
     elseif ($role === self::REVIEWER) {
       $this->reviewer = $value;
     }
+    elseif ($role === self::FINANCER) {
+      $this->financer = $value;
+    }
+    elseif ($role === self::INSURER) {
+      $this->insurer = $value;
+    }
     elseif ($role === self::PUBLISHER) {
       $this->publisher = $value;
     }
+    elseif ($role === self::AUDITOR) {
+      $this->auditor = $value;
+    }
     elseif ($role === self::MANAGER) {
       $this->manager = $value;
     }
@@ -185,7 +235,7 @@ class c_base_roles {
     }
 
     if ($role === self::NONE) {
-      if (!($this->public || $this->system || $this->user || $this->requester || $this->drafter || $this->editer || $this->reviewer || $this->publisher || $this->manager || $this->administer)) {
+      if (!($this->public || $this->system || $this->user || $this->requester || $this->drafter || $this->editer || $this->reviewer || $this->publisher || $this->auditor || $this->manager || $this->administer)) {
         return new c_base_return_true();
       }
     }
@@ -214,7 +264,7 @@ class c_base_roles {
         return new c_base_return_true();
       }
     }
-    elseif ($role === self::EDITER) {
+    elseif ($role === self::EDITOR) {
       if ($this->editer) {
         return new c_base_return_true();
       }
@@ -224,11 +274,26 @@ class c_base_roles {
         return new c_base_return_true();
       }
     }
+    elseif ($role === self::FINANCER) {
+      if ($this->financer) {
+        return new c_base_return_true();
+      }
+    }
+    elseif ($role === self::INSURER) {
+      if ($this->insurer) {
+        return new c_base_return_true();
+      }
+    }
     elseif ($role === self::PUBLISHER) {
       if ($this->publisher) {
         return new c_base_return_true();
       }
     }
+    elseif ($role === self::AUDITOR) {
+      if ($this->auditor) {
+        return new c_base_return_true();
+      }
+    }
     elseif ($role === self::MANAGER) {
       if ($this->manager) {
         return new c_base_return_true();
@@ -242,4 +307,69 @@ class c_base_roles {
 
     return new c_base_return_false();
   }
+
+  /**
+   * Get an array of all currently assigned roles.
+   *
+   * @return c_base_return_array
+   *   An array of roles are returned.
+   *   An array with error bit set is returned on error.
+   */
+  public function get_roles() {
+    $roles = array();
+
+    if ($this->public) {
+      $roles[self::PUBLIC] = self::PUBLIC;
+    }
+
+    if ($this->system) {
+      $roles[self::SYSTEM] = self::SYSTEM;
+    }
+
+    if ($this->user) {
+      $roles[self::USER] = self::USER;
+    }
+
+    if ($this->requester) {
+      $roles[self::REQUESTER] = self::REQUESTER;
+    }
+
+    if ($this->drafter) {
+      $roles[self::DRAFTER] = self::DRAFTER;
+    }
+
+    if ($this->editer) {
+      $roles[self::EDITOR] = self::EDITOR;
+    }
+
+    if ($this->reviewer) {
+      $roles[self::REVIEWER] = self::REVIEWER;
+    }
+
+    if ($this->financer) {
+      $roles[self::FINANCER] = self::FINANCER;
+    }
+
+    if ($this->insurer) {
+      $roles[self::INSURER] = self::INSURER;
+    }
+
+    if ($this->publisher) {
+      $roles[self::PUBLISHER] = self::PUBLISHER;
+    }
+
+    if ($this->auditor) {
+      $roles[self::AUDITOR] = self::AUDITOR;
+    }
+
+    if ($this->manager) {
+      $roles[self::MANAGER] = self::MANAGER;
+    }
+
+    if ($this->administer) {
+      $roles[self::ADMINISTER] = self::ADMINISTER;
+    }
+
+    return c_base_return_array::s_new($roles);
+  }
 }
index 4b08163b0768956b11bf7a538a405aca680b9802..91f20a8eda8f8a8fe7384d5628c088c4a4837935 100644 (file)
@@ -16,10 +16,12 @@ require_once('common/base/classes/base_return.php');
  * This class overrides c_base_return_array() such that some of its return values are in a different form than expected.
  * This will utilize c_base_return_* as return values.
  *
- * @todo: review this class, for some reason I decided to use c_base_return_array as this class supertype.
- *        Is that a good idea, because it feels a bit abusive?
+ * @todo: there seems to be a non-standard cookie flag called 'storeid'.
+ *        I cannot find any decent documentation, so I will not implement it at this time.
  *
  * @see: http://us.php.net/manual/en/features.cookies.php
+ * @see: https://tools.ietf.org/html/rfc6265
+ * @see: https://tools.ietf.org/html/draft-west-first-party-cookies
  * @see: setcookie()
  */
 class c_base_cookie extends c_base_return_array {
@@ -28,6 +30,11 @@ class c_base_cookie extends c_base_return_array {
   const DEFAULT_JSON_ENCODE_DEPTH = 512;
   const CHECKSUM_ALGORITHM = 'sha256';
 
+  const SAME_SITE_NONE    = 0;
+  const SAME_SITE_RELAXED = 1;
+  const SAME_SITE_STRICT  = 2;
+
+
   private $name;
   private $secure;
   private $max_age;
@@ -36,7 +43,8 @@ class c_base_cookie extends c_base_return_array {
   private $domain;
   private $http_only;
   private $first_only;
-  private $data;
+  private $host_only;
+  private $same_site;
   private $json_encode_depth;
 
 
@@ -44,6 +52,8 @@ class c_base_cookie extends c_base_return_array {
    * Class constructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->name = NULL;
     $this->secure = TRUE;
     $this->max_age = NULL;
@@ -52,12 +62,11 @@ class c_base_cookie extends c_base_return_array {
     $this->domain = NULL;
     $this->http_only = FALSE;
     $this->first_only = TRUE;
-    $this->data = array();
+    $this->host_only = TRUE;
+    $this->same_site = TRUE;
     $this->json_encode_depth = self::DEFAULT_JSON_ENCODE_DEPTH;
 
     $this->p_set_lifetime_default();
-
-    parent::__construct();
   }
 
   /**
@@ -72,7 +81,8 @@ class c_base_cookie extends c_base_return_array {
     unset($this->domain);
     unset($this->http_only);
     unset($this->first_only);
-    unset($this->data);
+    unset($this->host_only);
+    unset($this->same_site);
     unset($this->json_encode_depth);
 
     parent::__destruct();
@@ -366,13 +376,13 @@ class c_base_cookie extends c_base_return_array {
   }
 
   /**
-   * Assigns the cookie http only flag.
+   * Assigns the cookie httponly flag.
    *
    * Set this to TRUE to only allow http protocol to utilize this cookie.
    * According to the PHP documentation, this prohibits javascript from accessing the cookie.
    *
    * @param bool $http_only
-   *   The http-only status for the cookie.
+   *   The httponly status for the cookie.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
@@ -388,10 +398,10 @@ class c_base_cookie extends c_base_return_array {
   }
 
   /**
-   * Returns the stored cookie http only flag.
+   * Returns the stored cookie httponly flag.
    *
    * @return c_base_return_bool
-   *   The cookie http only flag.
+   *   The cookie httponly flag.
    */
   public function get_http_only() {
     // this flag should never be undefined, if it is NULL, then force the default.
@@ -403,13 +413,13 @@ class c_base_cookie extends c_base_return_array {
   }
 
   /**
-   * Assigns the cookie http firsty-party flag.
+   * Assigns the cookie http first-party flag.
    *
    * Set this to TRUE to only allow the cookie to be used as first party only.
    * According to the PHP documentation, this tells browsers to never allow this to be used as a thirdy-party cookie.
    *
    * @param bool $first_only
-   *   The first-only status for the cookie.
+   *   The first-party status for the cookie.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
@@ -425,59 +435,106 @@ class c_base_cookie extends c_base_return_array {
   }
 
   /**
-   * Returns the stored cookie http only flag.
+   * Returns the stored cookie first-party flag.
    *
    * @return c_base_return_bool
-   *   The cookie http only flag.
+   *   The cookie first-party flag.
    */
   public function get_first_only() {
     // this flag should never be undefined, if it is NULL, then force the default.
-    if (is_null($this->http_only)) {
-      $this->http_only = FALSE;
+    if (is_null($this->first_only)) {
+      $this->first_only = FALSE;
     }
 
-    return c_base_return_bool::s_new($this->http_only);
+    return c_base_return_bool::s_new($this->first_only);
   }
 
   /**
-   * Assign the data.
+   * Assigns the cookie hostyonly flag.
    *
-   * Cookies values associated with this class are only stored as an array.
-   * Be sure to wrap your values in an array.
-   * The array key 'checksum' will be created if one does not already exist when building the cookie.
+   * Set this to TRUE to only allow the cookie to be used as host party only.
    *
-   * @param array $data
-   *   Any value so long as it is an array.
-   *   NULL is not allowed.
-   *   FALSE with the error bit set is returned on error.
+   * @param bool $host_only
+   *   The hostonly status for the cookie.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *
+   * @see: https://tools.ietf.org/html/rfc6265#section-5.4
    */
-  public function set_data($data) {
-    if (!is_array($data)) {
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'data', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+  public function set_host_only($host_only) {
+    if (!is_bool($host_only)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'host_only', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
       return c_base_return_error::s_false($error);
     }
 
-    $this->data = $data;
+    $this->host_only = $host_only;
     return new c_base_return_true();
   }
 
   /**
-   * Return the data.
+   * Returns the stored cookie hostonly flag.
    *
-   * @return c_base_return_array
-   *   The value array stored within this class.
-   *   NULL may be returned if there is no defined valid array.
-   *   FALSE with the error bit set is returned on error.
+   * @return c_base_return_bool
+   *   The cookie hostonly flag.
+   */
+  public function get_host_only() {
+    // this flag should never be undefined, if it is NULL, then force the default.
+    if (is_null($this->host_only)) {
+      $this->host_only = FALSE;
+    }
+
+    return c_base_return_bool::s_new($this->host_only);
+  }
+
+  /**
+   * Assigns the cookie samesite flag.
+   *
+   * This also assignes the 'samesite' cookie setting which is functionality similar to hostonly.
+   *
+   * @param bool $same_site
+   *   The samesite status for the cookie.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *
+   * @see: https://tools.ietf.org/html/draft-west-first-party-cookies
+   */
+  public function set_same_site($same_site) {
+    if (!is_int($same_site)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'same_site', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    switch ($same_site) {
+      case self::SAME_SITE_NONE:
+      case self::SAME_SITE_RELAXED:
+      case self::SAME_SITE_STRICT:
+        $this->same_site = $same_site;
+        break;
+      default:
+        $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'same_site', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+        return c_base_return_error::s_false($error);
+    }
+
+    return new c_base_return_true();
+  }
+
+  /**
+   * Returns the stored cookie samesite flag.
+   *
+   * @return c_base_return_bool
+   *   The cookie hostonly flag.
+   *
+   * @see: https://tools.ietf.org/html/draft-west-first-party-cookies
    */
-  public function get_data() {
-    if (!is_null($this->data) && !is_array($this->data)) {
-      $this->data = array();
+  public function get_same_site() {
+    // this flag should never be undefined, if it is NULL, then force the default.
+    if (is_null($this->same_site)) {
+      $this->same_site = self::SAME_SITE_RELAXED;
     }
 
-    return c_base_return_array::s_new($this->data);
+    return c_base_return_int::s_new($this->same_site);
   }
 
   /**
@@ -498,17 +555,17 @@ class c_base_cookie extends c_base_return_array {
       return c_base_return_error::s_false($error);
     }
 
-    if (is_null($this->data)) {
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':variable_name' => 'this->data', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_VARIABLE);
+    if (is_null($this->value)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':variable_name' => 'this->value', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_VARIABLE);
       return c_base_return_error::s_false($error);
     }
 
-    $cookie = $this->p_build_cookie($checksum);
-    if ($cookie instanceof c_base_return_false) {
-      return c_base_return_error::s_false($cookie->get_error());
+    $set_cookie = $this->p_build_set_cookie($checksum);
+    if ($set_cookie instanceof c_base_return_false) {
+      return c_base_return_error::s_false($set_cookie->get_error());
     }
 
-    return $cookie;
+    return $set_cookie;
   }
 
   /**
@@ -584,13 +641,13 @@ class c_base_cookie extends c_base_return_array {
       return c_base_return_error::s_false($error);
     }
 
-    if (is_null($this->data)) {
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':variable_name' => 'this->data', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_VARIABLE);
+    if (is_null($this->value)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':variable_name' => 'this->value', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_VARIABLE);
       return c_base_return_error::s_false($error);
     }
 
-    $cookie = $this->p_build_cookie($checksum);
-    if ($cookie instanceof c_base_return_false) {
+    $set_cookie = $this->p_build_set_cookie($checksum);
+    if ($set_cookie instanceof c_base_return_false) {
       return c_base_return_error::s_false($cookie->get_error());
     }
 
@@ -598,9 +655,9 @@ class c_base_cookie extends c_base_return_array {
       return new c_base_return_false();
     }
 
-    header($cookie->get_value_exact(), FALSE);
+    header($set_cookie->get_value_exact(), FALSE);
 
-    unset($cookie);
+    unset($set_cookie);
     unset($data);
 
     return new c_base_return_true();
@@ -616,7 +673,7 @@ class c_base_cookie extends c_base_return_array {
    *   TRUE on success, FALSE otherwise.
    */
   public function do_pull() {
-    if (!isset($_COOKIE) || !array_key_exists($this->name, $_COOKIE)) {
+    if (!isset($_COOKIE) || !is_array($_COOKIE) || !array_key_exists($this->name, $_COOKIE)) {
       // This is not an error, but there is no cookie to pull.
       // simply return false without the error flag set.
       return new c_base_return_false();
@@ -631,7 +688,7 @@ class c_base_cookie extends c_base_return_array {
       return c_base_return_error::s_false($error);
     }
 
-    $this->data = $data;
+    $this->value = $data;
     unset($data);
 
     return new c_base_return_true();
@@ -651,17 +708,17 @@ class c_base_cookie extends c_base_return_array {
    *   On error FALSE is returned with the error bit set.
    */
   public function validate() {
-    if (!is_array($this->data)) {
+    if (!is_array($this->value)) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':variable_name' => 'this->data')), i_base_error_messages::INVALID_VARIABLE);
       return c_base_return_error::s_false($error);
     }
 
-    if (!array_key_exists('checksum', $this->data)) {
+    if (!array_key_exists('checksum', $this->value)) {
       return new c_base_return_false();
     }
 
     $checksum = $this->p_build_checksum();
-    if ($this->data['checksum'] == $checksum) {
+    if ($this->value['checksum'] == $checksum) {
       unset($checksum);
       return new c_base_return_true();
     }
@@ -744,21 +801,21 @@ class c_base_cookie extends c_base_return_array {
    * @see: hash()
    */
   private function p_build_checksum() {
-    if (!is_array($this->data)) {
-      $this->data = array();
+    if (!is_array($this->value)) {
+      $this->value = array();
     }
 
-    $has_checksum = array_key_exists('checksum', $this->data);
+    $has_checksum = array_key_exists('checksum', $this->value);
     $checksum = NULL;
     if ($has_checksum) {
-      $checksum = $this->data['checksum'];
-      unset($this->data['checksum']);
+      $checksum = $this->value['checksum'];
+      unset($this->value['checksum']);
     }
 
-    $json = json_encode($this->data, 0, $this->json_encode_depth);
+    $json = json_encode($this->value, 0, $this->json_encode_depth);
     if ($json === FALSE) {
       if ($has_checksum) {
-        $this->data['checksum'] = $checksum;
+        $this->value['checksum'] = $checksum;
       }
 
       unset($has_checksum);
@@ -770,7 +827,7 @@ class c_base_cookie extends c_base_return_array {
 
     $generated = hash(c_base_cookie::CHECKSUM_ALGORITHM, $json);
     if ($has_checksum) {
-      $this->data['checksum'] = $checksum;
+      $this->value['checksum'] = $checksum;
     }
 
     unset($has_checksum);
@@ -807,19 +864,19 @@ class c_base_cookie extends c_base_return_array {
    * @see: header()
    * @see: headers_sent().
    */
-  private function p_build_cookie($checksum = TRUE) {
+  private function p_build_set_cookie($checksum = TRUE) {
     if ($checksum) {
-      unset($this->data['checksum']);
-      $this->data['checksum'] = $this->p_build_checksum();
+      unset($this->value['checksum']);
+      $this->value['checksum'] = $this->p_build_checksum();
 
-      if (is_null($this->data['checksum'])) {
-        unset($this->data['checksum']);
+      if (is_null($this->value['checksum'])) {
+        unset($this->value['checksum']);
         $error = c_base_error::s_log(NULL, array('arguments' => array(':operation_name' => 'this->p_build_checksum', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::OPERATION_FAILURE);
         return c_base_return_error::s_false($error);
       }
     }
 
-    $json = json_encode($this->data, 0, $this->json_encode_depth);
+    $json = json_encode($this->value, 0, $this->json_encode_depth);
     if ($json === FALSE) {
       unset($json);
       $error = c_base_error::s_log(NULL, array('arguments' => array(':operation_name' => 'json_encode', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::OPERATION_FAILURE);
@@ -864,6 +921,24 @@ class c_base_cookie extends c_base_return_array {
       $cookie .= ' first-party;';
     }
 
+    // the rfc is unclear as it calls the hostonly flag by the name of host-only-flag.
+    // it does not seem to directly state that the host-only-flag should be defined as 'hostonly' and not 'host-only-flag'.
+    if ($this->host_only) {
+      $cookie .= ' hostonly;';
+    }
+
+    switch ($this->same_site) {
+      case self::SAME_SITE_NONE:
+        $cookie .= ' samesite=no_restriction;';
+        break;
+      case self::SAME_SITE_RELAXED:
+        $cookie .= ' samesite=lax;';
+        break;
+      case self::SAME_SITE_STRICT:
+        $cookie .= ' samesite=strict;';
+        break;
+    }
+
     return c_base_return_string::s_new($cookie);
   }
 }
index 327fb4f65967038352f32d16db0b92be3d406df1..2d66eeb64eac8e85b15c361e27981ed717ef6df4 100644 (file)
@@ -42,7 +42,7 @@ class c_base_connection_string extends c_base_return_string {
   private $host;
   private $host_addr;
   private $port;
-  private $database_name;
+  private $database;
   private $user;
   private $password;
   private $connect_timeout;
@@ -56,10 +56,12 @@ class c_base_connection_string extends c_base_return_string {
    * Class destructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->host = NULL;
     $this->host_addr = NULL;
     $this->port = NULL;
-    $this->database_name = NULL;
+    $this->database = NULL;
     $this->user = NULL;
     $this->password = NULL;
     $this->connect_timeout = NULL;
@@ -68,8 +70,6 @@ class c_base_connection_string extends c_base_return_string {
     $this->service = NULL;
 
     $this->error = NULL;
-
-    parent::__construct();
   }
 
   /**
@@ -81,7 +81,7 @@ class c_base_connection_string extends c_base_return_string {
     unset($this->host);
     unset($this->host_addr);
     unset($this->port);
-    unset($this->database_name);
+    unset($this->database);
     unset($this->user);
     unset($this->password);
     unset($this->connect_timeout);
@@ -232,20 +232,20 @@ class c_base_connection_string extends c_base_return_string {
   /**
    * Assign database name.
    *
-   * @param string $database_name
+   * @param string $database
    *   The database name string.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
    *   FALSE with the error bit set is returned on error.
    */
-  public function set_database_name($database_name) {
-    if (!is_string($database_name)) {
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'database_name', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+  public function set_database($database) {
+    if (!is_string($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_false($error);
     }
 
-    $this->database_name = $database_name;
+    $this->database = $database;
     return new c_base_return_true();
   }
 
@@ -256,12 +256,12 @@ class c_base_connection_string extends c_base_return_string {
    *   The database name string on success.
    *   The error bit set is on error.
    */
-  public function get_database_name() {
-    if (!is_string($this->database_name)) {
-      $this->database_name = '';
+  public function get_database() {
+    if (!is_string($this->database)) {
+      $this->database = '';
     }
 
-    return c_base_return_string::s_new($this->database_name);
+    return c_base_return_string::s_new($this->database);
   }
 
   /**
@@ -513,8 +513,8 @@ class c_base_connection_string extends c_base_return_string {
       $this->value .= ' port=' . $this->p_escape_string($this->port);
     }
 
-    if (!empty($this->database_name)) {
-      $this->value .= ' database_name=' . $this->p_escape_string($this->database_name);
+    if (!empty($this->database)) {
+      $this->value .= ' dbname=' . $this->p_escape_string($this->database);
     }
 
     if (!empty($this->user)) {
@@ -579,20 +579,10 @@ class c_base_connection_string extends c_base_return_string {
 /**
  * A generic class for managing database connections.
  *
- * errata:
- *   There are a number of cases where PHP's postgresql documentation is unclear on what 'failure' is.
- *   In certain cases, it mentions failure as an error.
- *   In other cases, it just says failure.
- *   If failure happens as a part of normal, expected behavior, then it should not be construed as an error because failure is expected behavior.
- *   If failure happens due to something unexpected or invalid, then it should be construed as an error.
- *   This is a context issue and I may be overthinking it.
- *   I will need to come back later and review my return results.
- *   For now, I am assuming failure means error as that seems like the most obvious interpretation.
- *
  * @require class c_base_return
  * @require class c_base_session
  */
-class c_base_database {
+class c_base_database extends c_base_return {
   private $session;
   private $persistent;
   private $database;
@@ -605,6 +595,8 @@ class c_base_database {
    * Class constructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->session = NULL;
     $this->persistent = NULL;
     $this->database = NULL;
@@ -632,6 +624,29 @@ class c_base_database {
     unset($this->connection_string);
 
     unset($this->connected);
+
+    parent::__destruct();
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, array());
   }
 
   /**
@@ -657,7 +672,7 @@ class c_base_database {
   /**
    * Returns the session information.
    *
-   * @return c_base_session_return
+   * @return c_base_session
    *   A session object on success.
    *   The error bit set is on error.
    */
@@ -666,7 +681,7 @@ class c_base_database {
       $this->session = new c_base_session();
     }
 
-    return c_base_session_return::s_value_exact($this->session);
+    return $this->session;
   }
 
   /**
@@ -853,7 +868,7 @@ class c_base_database {
     if ($database === FALSE) {
       unset($database);
 
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $this->connection_string->get_database_name()->get_value_exact(), ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_CONNECTION_FAILURE);
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $this->connection_string->get_database()->get_value_exact(), ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_CONNECTION_FAILURE);
       return c_base_return_error::s_false($error);
     }
 
@@ -881,9 +896,9 @@ class c_base_database {
    */
   public function do_disconnect() {
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -907,9 +922,9 @@ class c_base_database {
    */
   public function do_flush() {
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1025,9 +1040,9 @@ class c_base_database {
    */
   public function do_reset() {
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1067,9 +1082,9 @@ class c_base_database {
    */
   public function do_ping() {
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1107,9 +1122,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1138,9 +1153,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1169,9 +1184,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1200,9 +1215,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1228,9 +1243,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1255,9 +1270,9 @@ class c_base_database {
    */
   public function get_client_encoding() {
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1288,9 +1303,9 @@ class c_base_database {
    */
   public function consume_input() {
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1337,9 +1352,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1390,9 +1405,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1452,9 +1467,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1532,9 +1547,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1566,9 +1581,9 @@ class c_base_database {
    */
   public function get_result() {
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1619,9 +1634,9 @@ class c_base_database {
    */
   public function do_cancel() {
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1695,9 +1710,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1784,9 +1799,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1869,9 +1884,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -1953,9 +1968,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -2011,9 +2026,9 @@ class c_base_database {
     }
 
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -2044,9 +2059,9 @@ class c_base_database {
    */
   public function set_error_verbosity($verbosity) {
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -2069,9 +2084,9 @@ class c_base_database {
    */
   public function get_last_error() {
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -2097,9 +2112,9 @@ class c_base_database {
    */
   public function get_last_notice() {
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -2132,9 +2147,9 @@ class c_base_database {
    */
   public function get_transaction_status() {
     if (!is_resource($this->database)) {
-      $database_name = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database_name()->get_value_exact() : '';
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
-      unset($database_name);
+      $database = ($this->connection_string instanceof c_base_connection_string) ? $this->connection_string->get_database()->get_value_exact() : '';
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database);
       return c_base_return_error::s_false($error);
     }
 
@@ -2187,6 +2202,13 @@ class c_base_database {
 class c_base_database_result extends c_base_return_resource {
 
   /**
+   * Class constructor.
+   */
+  public function __construct() {
+    parent::__construct();
+  }
+
+  /**
    * Class destructor.
    */
   public function __destruct() {
@@ -2909,9 +2931,9 @@ class c_base_database_query extends c_base_return_array {
    * Class constructor.
    */
   public function __construct() {
-    $this->p_initialize();
-
     parent::__construct();
+
+    $this->p_initialize();
   }
 
   /**
index 6092260b5daa5606975291508aac042c688ede28..50020deb560bcb9e4beae2480328100f005fe360 100644 (file)
@@ -11,7 +11,7 @@ require_once('common/base/classes/base_return.php');
 /**
  * A generic class for performing debugging.
  */
-class c_base_debug {
+class c_base_debug extends c_base_return {
   private static $ps_debugging = FALSE;
 
   private $time_start;
@@ -29,6 +29,8 @@ class c_base_debug {
    * Class constructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->time_start = NULL;
     $this->time_stop = NULL;
 
@@ -53,6 +55,29 @@ class c_base_debug {
     unset($this->memory_allocated_start);
     unset($this->memory_allocated_stop);
     unset($this->memory_allocated_peak);
+
+    parent::__destruct();
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, '');
   }
 
   /**
index 7cd98a6ef145d77eb10be97580b5fa2e794b75ec..fdfe70980191fdcb12c5a7f8cc6c20871331cf4d 100644 (file)
@@ -34,6 +34,27 @@ class c_base_email extends c_base_rfc_string {
 
 
   /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, '');
+  }
+
+  /**
    * Decode and check that the given e-mail address is valid.
    *
    * Validation is done according to rfc5322, rfc6854, and rfc7231.
@@ -374,7 +395,7 @@ class c_base_email extends c_base_rfc_string {
         // there may be multiple comments, so do not break at this point.
       }
       elseif (!$this->pr_rfc_char_is_fws($code)) {
-        // the first non-comment, non-fws char should be the start of the [machine_name].
+        // the first non-comment, non-fws char should be the start of the [name_machine].
         break;
       }
     }
@@ -388,7 +409,7 @@ class c_base_email extends c_base_rfc_string {
       return $result;
     }
 
-    // process [machine_name].
+    // process [name_machine].
     $started = FALSE;
     $stopped = FALSE;
     $comments = FALSE;
index 185c3f175e4c7cd7bbd429295862e1811d1fab20..6d4b7492e2e19e7f7ac5527914dc6ed2bb853c0f 100644 (file)
@@ -499,17 +499,19 @@ interface i_base_error_messages {
   const INVALID_ARGUMENT              = 1;
   const INVALID_FORMAT                = 2;
   const INVALID_VARIABLE              = 3;
-  const OPERATION_FAILURE             = 4;
-  const OPERATION_UNECESSARY          = 5;
-  const FUNCTION_FAILURE              = 6;
-  const NOT_FOUND_ARRAY_INDEX         = 7;
-  const NOT_FOUND_DIRECTORY           = 8;
-  const NOT_FOUND_FILE                = 9;
-  const NO_CONNECTION                 = 10;
-  const NO_SUPPORT                    = 11;
-  const POSTGRESQL_CONNECTION_FAILURE = 12;
-  const POSTGRESQL_NO_CONNECTION      = 13;
-  const POSTGRESQL_NO_RESOURCE        = 14;
+  const INVALID_SESSION               = 4;
+  const OPERATION_FAILURE             = 5;
+  const OPERATION_UNECESSARY          = 6;
+  const FUNCTION_FAILURE              = 7;
+  const NOT_FOUND_ARRAY_INDEX         = 8;
+  const NOT_FOUND_DIRECTORY           = 9;
+  const NOT_FOUND_FILE                = 10;
+  const NO_CONNECTION                 = 11;
+  const NO_SUPPORT                    = 12;
+  const NO_SESSION                    = 13;
+  const POSTGRESQL_CONNECTION_FAILURE = 14;
+  const POSTGRESQL_NO_CONNECTION      = 15;
+  const POSTGRESQL_NO_RESOURCE        = 16;
 
 
   /**
index d2e8f3c94335b7a9e88ffd7c18e38d22fb62436e..9ec232e274a8d979e80ac39574a286a8a4904f41 100644 (file)
@@ -10,7 +10,7 @@ require_once('common/base/classes/base_languages.php');
 /**
  * English language version of common error messages.
  */
-class c_base_error_messages_eng extends i_base_error_messages {
+final class c_base_error_messages_english extends i_base_error_messages {
 
   /**
    * Returns a standard error message associated with the given code.
diff --git a/common/base/classes/base_form.php b/common/base/classes/base_form.php
new file mode 100644 (file)
index 0000000..bb7889e
--- /dev/null
@@ -0,0 +1,205 @@
+<?php
+/**
+ * @file
+ * Provides a class for managing forms.
+ */
+
+// include required files.
+require_once('common/base/classes/base_error.php');
+require_once('common/base/classes/base_return.php');
+
+/**
+ * A class for form problems.
+ *
+ * Prolems include both errors and warnings, but the distinction between the two is left to the caller.
+ * The stored string value is intended to be the problem message.
+ *
+ * @todo: come up with a list of problem codes and add a problem id variable.
+ */
+class c_base_form_problem extends c_base_return_string {
+  private $fields;
+  private $arguments;
+
+
+  /**
+   * Class constructor.
+   */
+  public function __construct() {
+    parent::__construct();
+
+    $this->fields = NULL;
+    $this->arguments = NULL;
+  }
+
+  /**
+   * Class destructor.
+   */
+  public function __destruct() {
+    unset($this->fields);
+    unset($this->arguments);
+
+    parent::__destruct();
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, array());
+  }
+
+  /**
+   * Associations a field via the field name with this problem.
+   *
+   * @param string $field_name
+   *   The field name to assign.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
+   *
+   * @see: c_base_session::save()
+   */
+  public function set_field($field_name) {
+    if (!is_string($field_name) && !empty($field_name)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'field_name', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (!is_array($this->fields)) {
+      $this->fields = array();
+    }
+
+    $this->fields[$field_name] = $field_name;
+    return new c_base_return_true();
+  }
+
+  /**
+   * Unassociates a field via the field name with this problem.
+   *
+   * @param string $field_name
+   *   The field name to assign.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
+   *   FALSE without error bit set is returned if the field name is not assigned.
+   *
+   * @see: c_base_session::save()
+   */
+  public function unset_field($field_name) {
+    if (!is_string($field_name) && !empty($field_name)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'field_name', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (is_null($this->fields) || !array_key_exists($field_name, $this->fields)) {
+      return new c_base_return_false();
+    }
+
+    unset($this->fields[$field_name]);
+    return new c_base_return_true();
+  }
+
+  /**
+   * Returns all fields associated with this problem.
+   *
+   * @return c_base_return_array|c_base_return_status
+   *   An array of field names.
+   *   FALSE with the error bit set is returned on error.
+   */
+  public function get_fields() {
+    if (!is_array($this->fields)) {
+      $this->fields = array();
+    }
+
+    return c_base_return_array::s_new($this->fields);
+  }
+
+  /**
+   * Associations a field via the field name with this problem.
+   *
+   * @param string $index
+   *   The index name to be associated with this message.
+   * @param string $value
+   *   A string representing the value to be associated with the index.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
+   *
+   * @see: c_base_session::save()
+   */
+  public function set_argument($index, $value) {
+    if (!is_string($index) && !empty($index)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'index', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (!is_string($value)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'value', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (!is_array($this->arguments)) {
+      $this->arguments = array();
+    }
+
+    $this->arguments[$index] = $value;
+    return new c_base_return_true();
+  }
+
+  /**
+   * Gets the argument value assigned at the specified index.
+   *
+   * @return c_base_return_value|c_base_return_status
+   *   An array of field names.
+   *   FALSE with the error bit set is returned on error.
+   *   FALSE without error bit set is returned if the index is not assigned.
+   */
+  public function get_argument($index) {
+    if (!is_string($index) && !empty($index)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'index', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (!is_array($this->arguments)) {
+      $this->arguments = array();
+    }
+
+    if (!array_key_exists($index, $this->arguments)) {
+      return new c_base_return_false();
+    }
+
+    return c_base_return_value::s_new($this->fields);
+  }
+
+  /**
+   * Returns all arguments associated with this problem.
+   *
+   * @return c_base_return_array|c_base_return_status
+   *   An array of field names.
+   *   FALSE with the error bit set is returned on error.
+   */
+  public function get_arguments() {
+    if (!is_array($this->arguments)) {
+      $this->arguments = array();
+    }
+
+    return c_base_return_array::s_new($this->arguments);
+  }
+}
index d1c7dac3c6a6cc63d6ecb206cca8d1ee202b6942..51da35c144c5c56dc00e8c9fc585235f59528b26 100644 (file)
@@ -20,7 +20,7 @@ require_once('common/base/classes/base_markup.php');
  *
  * @todo: add support for non-standard tag attributes, which will just be a string or NULL.
  */
-class c_base_html {
+class c_base_html extends c_base_return {
   private $id;
   private $attributes;
   private $attributes_body;
@@ -33,6 +33,8 @@ class c_base_html {
    * Class constructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->id = NULL;
     $this->attributes = array();
     $this->attributes_body = array();
@@ -49,6 +51,29 @@ class c_base_html {
     unset($this->attributes_body);
     unset($this->headers);
     unset($this->body);
+
+    parent::__destruct();
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, '');
   }
 
   /**
@@ -231,7 +256,7 @@ class c_base_html {
    * @param int $delta
    *   The position in the array of the tag to get.
    *
-   * @return c_base_markup_tag_return|c_base_return_status
+   * @return c_base_markup_tag|c_base_return_status
    *   The tag, if found at delta.
    *   FALSE is returned if no tag is at delta.
    *   FALSE with error bit set is returned on error.
@@ -246,7 +271,7 @@ class c_base_html {
       return new c_base_return_false();
     }
 
-    return c_base_markup_tag_return::s_new($this->body[$delta]);
+    return $this->body[$delta];
   }
 
   /**
@@ -322,7 +347,7 @@ class c_base_html {
    * @param int $delta
    *   The position in the array of the header to get.
    *
-   * @return c_base_markup_tag_return|c_base_return_status
+   * @return c_base_markup_tag|c_base_return_status
    *   The header, if found at delta.
    *   FALSE is returned if no header is at delta.
    *   FALSE with error bit set is returned on error.
@@ -337,7 +362,7 @@ class c_base_html {
       return new c_base_return_false();
     }
 
-    return c_base_markup_tag_return::s_new($this->headers[$delta]);
+    return $this->headers[$delta];
   }
 
   /**
@@ -483,8 +508,6 @@ class c_base_html {
     return TRUE;
   }
 
-
-
   /**
    * Get the value of a single attribute assigned to this object.
    *
@@ -1303,79 +1326,3 @@ class c_base_html {
     return new c_base_return_true();
   }
 }
-
-/**
- * A return class whose value is represented as a generic c_base_markup_tag_return.
- */
-class c_base_html_return extends c_base_return_object {
-  use t_base_return_value_exact;
-
-  /**
-   * @see: t_base_return_value::p_s_new()
-   */
-  public static function s_new($value) {
-    return self::p_s_new($value, __CLASS__);
-  }
-
-  /**
-   * @see: t_base_return_value::p_s_value()
-   */
-  public static function s_value($return) {
-    return self::p_s_value($return, __CLASS__);
-  }
-
-  /**
-   * @see: t_base_return_value_exact::p_s_value_exact()
-   */
-  public static function s_value_exact($return) {
-    return self::p_s_value_exact($return, __CLASS__, new c_base_html());
-  }
-
-  /**
-   * Assign the value.
-   *
-   * @param c_base_html $value
-   *   Any value so long as it is an resource.
-   *   NULL is not allowed.
-   *
-   * @return bool
-   *   TRUE on success, FALSE otherwise.
-   */
-  public function set_value($value) {
-    if (!($value instanceof c_base_html)) {
-      return FALSE;
-    }
-
-    $this->value = $value;
-    return TRUE;
-  }
-
-  /**
-   * Return the value.
-   *
-   * @return c_base_html|null $value
-   *   The value c_base_html stored within this class.
-   *   NULL may be returned if there is no defined valid c_base_markup_tag.
-   */
-  public function get_value() {
-    if (!is_null($this->value) && !($this->value instanceof c_base_html)) {
-      $this->value = NULL;
-    }
-
-    return $this->value;
-  }
-
-  /**
-   * Return the value of the expected type.
-   *
-   * @return c_base_html $value
-   *   The value c_base_html stored within this class.
-   */
-  public function get_value_exact() {
-    if (!($this->value instanceof c_base_html)) {
-      $this->value = new c_base_html();
-    }
-
-    return $this->value;
-  }
-}
index f3fb081bdcf11623d09cda624fc74cc0e4aabdb2..7da3494a4cf8eacf45986dbfe1a6f43001f2f8eb 100644 (file)
@@ -230,6 +230,8 @@ class c_base_http extends c_base_rfc_string {
    * Class constructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->headers = NULL;
     $this->headers_sent = FALSE;
     $this->request = array();
@@ -258,6 +260,29 @@ class c_base_http extends c_base_rfc_string {
     unset($this->buffer_enabled);
 
     unset($this->language_class);
+
+    parent::__destruct();
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, '');
   }
 
   /**
@@ -267,18 +292,45 @@ class c_base_http extends c_base_rfc_string {
    *
    * @param int|null $header_name
    *   (optional) The numeric id of the request or NULL to load all requests.
+   * @param int|string|null $delta
+   *   (optional) For headers that have an array of data, this represents and index position within that array.
+   *   For all other headers, this does nothing.
    *
-   * @return c_base_return_array|c_base_return_status
+   * @return c_base_return_array|c_base_return_value|c_base_return_status
    *   The HTTP request array or an array containing the request field information.
+   *   FALSE without error bit set is returned when the requested header name is undefined.
    *   FALSE with error bit set is returned on error.
    */
-  public function get_request($header_name = NULL) {
+  public function get_request($header_name = NULL, $delta = NULL) {
+    if (!is_null($header_name) && !is_int($header_name)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'header_name', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (!is_null($delta) && !is_int($delta) && !is_string($delta)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'delta', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
     if (is_null($header_name)) {
       return c_base_return_array::s_new($this->request);
     }
 
-    if (!is_int($header_name) || !array_key_exists($header_name, $this->request)) {
-      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'header_name', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+    if (!array_key_exists($header_name, $this->request)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':index_name' => $header_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::NOT_FOUND_ARRAY_INDEX);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (!is_null($delta)) {
+      if (isset($this->request[$header_name]['data']) && is_array($this->request[$header_name]['data']) && array_key_exists($delta, $this->request[$header_name]['data'])) {
+        if ($this->request[$header_name]['data'][$delta] instanceof c_base_return) {
+          return $this->request[$header_name]['data'][$delta];
+        }
+
+        return c_base_return_value::s_new($this->request[$header_name]['data'][$delta]);
+      }
+
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':index_name' => $delta, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::NOT_FOUND_ARRAY_INDEX);
       return c_base_return_error::s_false($error);
     }
 
@@ -288,13 +340,57 @@ class c_base_http extends c_base_rfc_string {
   /**
    * Get the HTTP response array.
    *
-   * Load the entire HTTP response array.
+   * Load the entire HTTP response array or a specific response field.
    *
-   * @return c_base_return_array
-   *   The HTTP response array.
+   * @param int|null $header_name
+   *   (optional) The numeric id of the response or NULL to load all responses.
+   * @param int|string|null $delta
+   *   (optional) For headers that have an array of data, this represents and index position within that array.
+   *   For all other headers, this does nothing.
+   *
+   * @return c_base_return_array|c_base_return_string|c_base_return_value|c_base_return_status
+   *   The HTTP response array or string for a given field or the entire HTTP response array.
+   *   FALSE without error bit set is returned when the requested header name is undefined.
+   *   FALSE with error bit set is returned on error.
    */
-  public function get_response() {
-    return c_base_return_array::s_new($this->response);
+  public function get_response($header_name = NULL, $delta = NULL) {
+    if (!is_null($header_name) && !is_int($header_name)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'header_name', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (!is_null($delta) && !is_int($delta) && !is_string($delta)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'delta', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (is_null($header_name)) {
+      return c_base_return_array::s_new($this->response);
+    }
+
+    if (!array_key_exists($header_name, $this->response)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':index_name' => $header_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::NOT_FOUND_ARRAY_INDEX);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (is_array($this->response[$header_name])) {
+      if (is_null($delta)) {
+        return c_base_return_array::s_new($this->response[$header_name]);
+      }
+
+      if (isset($this->response[$header_name]) && is_array($this->response[$header_name]) && array_key_exists($delta, $this->response[$header_name])) {
+        if ($this->response[$header_name][$delta] instanceof c_base_return) {
+          return $this->response[$header_name][$delta];
+        }
+
+        return c_base_return_value::s_new($this->response[$header_name][$delta]);
+      }
+
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':index_name' => $delta, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::NOT_FOUND_ARRAY_INDEX);
+      return c_base_return_error::s_false($error);
+    }
+
+    return c_base_return_string::s_new($this->response[$header_name]);
   }
 
   /**
@@ -305,6 +401,7 @@ class c_base_http extends c_base_rfc_string {
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with error bit set is returned on error.
    */
   public function set_language_class($class_name) {
     if (!is_string($class_name) || !is_subclass_of('i_base_language', $class_name) ) {
@@ -321,6 +418,7 @@ class c_base_http extends c_base_rfc_string {
    *
    * @return c_base_return_string
    *   The language class string.
+   *   FALSE with error bit set is returned on error.
    */
   public function get_language_class() {
     if (is_null($this->language_class)) {
@@ -337,6 +435,7 @@ class c_base_http extends c_base_rfc_string {
    * @return c_base_return_float|c_base_return_status
    *   The HTTP request time.
    *   FALSE without error bit is returned when the request timestamp has not yet been loaded
+   *   FALSE with error bit set is returned on error.
    */
   public function get_request_time() {
     if (is_null($this->request_time)) {
@@ -348,6 +447,10 @@ class c_base_http extends c_base_rfc_string {
 
   /**
    * Load, process, and interpret all of the supported http request headers.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with error bit set is returned on error.
    */
   public function do_load_request() {
     if (!is_array($this->headers)) {
@@ -8279,79 +8382,3 @@ class c_base_http extends c_base_rfc_string {
     return FALSE;
   }
 }
-
-/**
- * A return class whose value is represented as a generic c_base_markup_tag_return.
- */
-class c_base_http_return extends c_base_return_object {
-  use t_base_return_value_exact;
-
-  /**
-   * @see: t_base_return_value::p_s_new()
-   */
-  public static function s_new($value) {
-    return self::p_s_new($value, __CLASS__);
-  }
-
-  /**
-   * @see: t_base_return_value::p_s_value()
-   */
-  public static function s_value($return) {
-    return self::p_s_value($return, __CLASS__);
-  }
-
-  /**
-   * @see: t_base_return_value_exact::p_s_value_exact()
-   */
-  public static function s_value_exact($return) {
-    return self::p_s_value_exact($return, __CLASS__, new c_base_http());
-  }
-
-  /**
-   * Assign the value.
-   *
-   * @param c_base_http $value
-   *   Any value so long as it is an resource.
-   *   NULL is not allowed.
-   *
-   * @return bool
-   *   TRUE on success, FALSE otherwise.
-   */
-  public function set_value($value) {
-    if (!($value instanceof c_base_http)) {
-      return FALSE;
-    }
-
-    $this->value = $value;
-    return TRUE;
-  }
-
-  /**
-   * Return the value.
-   *
-   * @return c_base_http|null $value
-   *   The value c_base_http stored within this class.
-   *   NULL may be returned if there is no defined valid c_base_markup_tag.
-   */
-  public function get_value() {
-    if (!is_null($this->value) && !($this->value instanceof c_base_http)) {
-      $this->value = NULL;
-    }
-
-    return $this->value;
-  }
-
-  /**
-   * Return the value of the expected type.
-   *
-   * @return c_base_http $value
-   *   The value c_base_html stored within this class.
-   */
-  public function get_value_exact() {
-    if (!($this->value instanceof c_base_http)) {
-      $this->value = new c_base_html();
-    }
-
-    return $this->value;
-  }
-}
index 04e642eace8341ad2fd37338879768b18628ed0d..81c90e01fbc97732e3948dec55eea672a70c2c0e 100644 (file)
@@ -13,7 +13,7 @@ require_once('common/base/classes/base_return.php');
 /**
  * A class for managing ldap connections.
  */
-class c_base_ldap {
+class c_base_ldap extends c_base_return {
   private $ldap;
   private $name;
 
@@ -25,6 +25,8 @@ class c_base_ldap {
    * Class constructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->ldap = NULL;
     $this->name = NULL;
 
@@ -41,6 +43,29 @@ class c_base_ldap {
 
     unset($this->bind_name);
     unset($this->bind_password);
+
+    parent::__destruct();
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, '');
   }
 
   /**
@@ -623,6 +648,8 @@ class c_base_ldap_result extends c_base_return_resource {
    * Class constructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->ldap = NULL;
     $this->entry = NULL;
   }
index 6be9bb45d8cc15ea6fe5a7e7c92aa02815dd30a1..8242bf9ae87dbe0faa23eb6613372d8551bf8b76 100644 (file)
@@ -7,7 +7,7 @@
 /**
  * A generic class for managing the logs.
  */
-class c_base_log {
+class c_base_log extends c_base_return {
   const TYPE_NONE       = 0;
   const TYPE_BASE       = 1; // for low-level entries.
   const TYPE_REQUEST    = 2; // accessing the site (generally page requests).
@@ -75,6 +75,8 @@ class c_base_log {
    * Class constructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->type = self::TYPE_NONE;
     $this->data = array();
   }
@@ -85,6 +87,29 @@ class c_base_log {
   public function __destruct() {
     unset($this->type);
     unset($this->data);
+
+    parent::__destruct();
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, '');
   }
 
   /**
@@ -212,7 +237,7 @@ class c_base_log {
     if (is_int($key)) {
       if ($key < 0) {
         $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'key', ':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);
       }
     }
     elseif (!is_string($key)) {
@@ -225,6 +250,10 @@ class c_base_log {
       return c_base_return_error::s_false($error);
     }
 
+    if ($this->data[$key] instanceof c_base_return) {
+      return $this->data[$key];
+    }
+
     return c_base_return_value::s_new($this->data[$key]);
   }
 }
index 0601c2872952e3f35707a2276ac7b5d464470b27..2ee90f0215023f6d5ccca6fb3bbc38d2badd6f5e 100644 (file)
@@ -352,7 +352,7 @@ class c_base_markup_attributes {
  *
  * @todo: add support for non-standard tag attributes, which will just be a string or NULL.
  */
-class c_base_markup_tag {
+class c_base_markup_tag extends c_base_return {
   const TYPE_NONE                       = 0;
   const TYPE_A                          = 1;
   const TYPE_ABBR                       = 2;
@@ -524,6 +524,8 @@ class c_base_markup_tag {
    * Class constructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->attributes = array();
     $this->tags = array();
     $this->tags_total = 0;
@@ -540,6 +542,29 @@ class c_base_markup_tag {
     unset($this->tags_total);
     unset($this->text);
     unset($this->type);
+
+    parent::__destruct();
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, '');
   }
 
   /**
@@ -1818,79 +1843,3 @@ class c_base_markup_tag {
     return TRUE;
   }
 }
-
-/**
- * A return class whose value is represented as a generic c_base_markup_tag_return.
- */
-class c_base_markup_tag_return extends c_base_return_value {
-  use t_base_return_value_exact;
-
-  /**
-   * @see: t_base_return_value::p_s_new()
-   */
-  public static function s_new($value) {
-    return self::p_s_new($value, __CLASS__);
-  }
-
-  /**
-   * @see: t_base_return_value::p_s_value()
-   */
-  public static function s_value($return) {
-    return self::p_s_value($return, __CLASS__);
-  }
-
-  /**
-   * @see: t_base_return_value_exact::p_s_value_exact()
-   */
-  public static function s_value_exact($return) {
-    return self::p_s_value_exact($return, __CLASS__, new c_base_markup_tag());
-  }
-
-  /**
-   * Assign the value.
-   *
-   * @param resource $value
-   *   Any value so long as it is an resource.
-   *   NULL is not allowed.
-   *
-   * @return bool
-   *   TRUE on success, FALSE otherwise.
-   */
-  public function set_value($value) {
-    if (!($value instanceof c_base_markup_tag)) {
-      return FALSE;
-    }
-
-    $this->value = $value;
-    return TRUE;
-  }
-
-  /**
-   * Return the value.
-   *
-   * @return c_base_markup_tag|null $value
-   *   The value c_base_markup_tag stored within this class.
-   *   NULL may be returned if there is no defined valid c_base_markup_tag.
-   */
-  public function get_value() {
-    if (!is_null($this->value) && !($this->value instanceof c_base_markup_tag)) {
-      $this->value = NULL;
-    }
-
-    return $this->value;
-  }
-
-  /**
-   * Return the value of the expected type.
-   *
-   * @return c_base_markup_tag $value
-   *   The value c_base_markup_tag stored within this class.
-   */
-  public function get_value_exact() {
-    if (!($this->value instanceof c_base_markup_tag)) {
-      $this->value = new c_base_markup_tag();
-    }
-
-    return $this->value;
-  }
-}
index 99e682b9eb981647fc1c5e9b33b98da05e93be0e..f163bb2dc274a6a2f691b92d2ecd14dd6c0b9620 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 // include required files.
+require_once('common/base/classes/base_return.php');
 require_once('common/base/classes/base_ascii.php');
 require_once('common/base/classes/base_utf8.php');
 
@@ -41,7 +42,28 @@ require_once('common/base/classes/base_utf8.php');
  * @require class c_base_ascii
  * @require class c_base_utf8
  */
-abstract class c_base_rfc_char {
+abstract class c_base_rfc_char extends c_base_return {
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, '');
+  }
 
   /**
    * Check to see if character is: text.
index c65fdb75e2904a289ec1fb565d3e89a9478b02ff..a26e931e6cf08022822d13f887b45e72c078c2ea 100644 (file)
@@ -45,6 +45,27 @@ abstract class c_base_rfc_string extends c_base_rfc_char {
   const STOP_AT_CLOSING_CHARACTER = -1;
 
   /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, '');
+  }
+
+  /**
    * Converts a string into a ordinals array and a characters array.
    *
    * The ordinals and characters returned by this are utf8-friendly such that the caller need only use a counter to navigate.
index 6d5c9e97c4cfb8a2bc53e6942f25c29b0ff40d3b..28b57c34fb90347efc2656c6fd9045cd06995571 100644 (file)
@@ -7,6 +7,7 @@
 // include required files.
 require_once('common/base/classes/base_error.php');
 require_once('common/base/classes/base_return.php');
+require_once('common/base/classes/base_form.php');
 
 /**
  * A class for managing sessions.
@@ -16,18 +17,21 @@ require_once('common/base/classes/base_return.php');
  * This session key can be used to retrieve a password between requests and to access the database.
  * The database can then be used to retrieve any session variables.
  */
-class c_base_session {
+class c_base_session extends c_base_return {
   const PACKET_MAX_LENGTH = 8192;
   const SOCKET_PATH_PREFIX = '/programs/sockets/sessionize_accounts/';
   const SOCKET_PATH_SUFFIX = '/sessions.socket';
   const PASSWORD_CLEAR_TEXT_LENGTH = 2048;
 
   private $socket;
+  private $socket_directory;
   private $socket_path;
   private $socket_timeout;
 
   private $system_name;
 
+  private $cookie;
+
   private $name;
   private $id_user;
   private $host;
@@ -35,20 +39,25 @@ class c_base_session {
   private $session_id;
   private $settings;
 
-  private $error;
-
   private $timeout_expire;
   private $timeout_max;
 
+  private $problems;
+
 
   /**
    * Class constructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->socket = NULL;
+    $this->socket_directory = NULL;
     $this->socket_path = NULL;
     $this->socket_timeout = NULL;
 
+    $this->cookie = NULL;
+
     $this->system_name = NULL;
 
     $this->name = NULL;
@@ -58,10 +67,10 @@ class c_base_session {
     $this->session_id = NULL;
     $this->settings = NULL;
 
-    $this->error = NULL;
-
     $this->timeout_expire = NULL;
     $this->timeout_max = NULL;
+
+    $this->problems = NULL;
   }
 
   /**
@@ -75,9 +84,12 @@ class c_base_session {
     }
 
     unset($this->socket);
+    unset($this->socket_directory);
     unset($this->socket_path);
     unset($this->socket_timeout);
 
+    unset($this->cookie);
+
     unset($this->system_name);
 
     unset($this->name);
@@ -88,29 +100,146 @@ class c_base_session {
     unset($this->special);
     unset($this->settings);
 
-    unset($this->error);
-
     unset($this->timeout_expire);
     unset($this->timeout_max);
+
+    unset($this->problems);
+
+    parent::__destruct();
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, array());
+  }
+
+  /**
+   * Assigns the socket directory name, which is used to create the socket path.
+   *
+   * If not specified, then self::SOCKET_PATH_PREFIX will be used.
+   *
+   * @param string|null $socket_directory
+   *   A directory name.
+   *   Set to NULL to remove any existing values.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
+   */
+  public function set_socket_directory($socket_directory) {
+    if (!is_null($socket_directory) && (!is_string($socket_directory) || empty($socket_directory))) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'socket_directory', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (is_null($socket_directory)) {
+      $this->socket_directory = NULL;
+      return new c_base_return_true();
+    }
+
+    if (!is_dir($socket_directory)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':direction_name' => $socket_directory, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::NOT_FOUND_DIRECTORY);
+      return c_base_return_error::s_false($error);
+    }
+
+    // require a single closing '/' at the end of the path.
+    $this->socket_directory = preg_replace('@/*$@i', '', $socket_directory) . '/';
+
+    return new c_base_return_true();
+  }
+
+  /**
+   * Returns the stored socket directory name.
+   *
+   * @return c_base_return_string|c_base_return_null
+   *   The system name string or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
+   */
+  public function get_socket_directory() {
+    if (is_null($this->socket_directory)) {
+      return new c_base_return_null();
+    }
+
+    return c_base_return_string::s_new($this->socket_directory);
+  }
+
+  /**
+   * Assigns the cookie associated with this session.
+   *
+   * @param c_base_cookie|null $cookie
+   *   The session cookie.
+   *   Set to NULL to remove any existing values.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
+   */
+  public function set_cookie($cookie) {
+    if (!is_null($cookie) && !($cookie instanceof c_base_cookie)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'cookie', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    $this->cookie = $cookie;
+
+    return new c_base_return_true();
+  }
+
+  /**
+   * Returns the stored system name.
+   *
+   * @return c_base_cookie|c_base_return_null
+   *   The session cookie or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
+   */
+  public function get_cookie() {
+    if (is_null($this->cookie)) {
+      return new c_base_return_null();
+    }
+
+    return $this->cookie;
   }
 
   /**
    * Assigns the system name, which is used to create the socket path.
    *
-   * @param string $system_name
+   * @param string|null $system_name
    *   A system name string.
+   *   Set to NULL to remove any existing values.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    */
   public function set_system_name($system_name) {
-    if (!is_string($system_name) || empty($system_name)) {
+    if (!is_null($system_name) && (!is_string($system_name) || empty($system_name))) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'system_name', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
       return c_base_return_error::s_false($error);
     }
 
+    if (is_null($this->socket_directory)) {
+      $this->socket_directory = NULL;
+      return new c_base_return_true();
+    }
+
     $this->system_name = basename($system_name);
-    $this->socket_path = self::SOCKET_PATH_PREFIX . $this->system_name . self::SOCKET_PATH_SUFFIX;
+    $this->socket_path = $this->socket_directory . $this->system_name . self::SOCKET_PATH_SUFFIX;
 
     return new c_base_return_true();
   }
@@ -120,26 +249,38 @@ class c_base_session {
    *
    * @return c_base_return_string
    *   The system name string or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
    */
   public function get_system_name() {
+    if (is_null($this->system_name)) {
+      return new c_base_return_null();
+    }
+
     return c_base_return_string::s_new($this->system_name);
   }
 
   /**
    * Assigns the user name associated with the session.
    *
-   * @param string $name
+   * @param string|null $name
    *   The user name.
+   *   Set to NULL to remove any existing values.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    */
   public function set_name($name) {
-    if (!is_string($name) || empty($name)) {
+    if (!is_null($name) && (!is_string($name) || empty($name))) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'name', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
       return c_base_return_error::s_false($error);
     }
 
+    if (is_null($name)) {
+      $this->name = NULL;
+      return new c_base_return_true();
+    }
+
     if (mb_strlen($name) == 0 || preg_match('/^(\w|-)+$/i', $name) != 1) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':format_name' => 'name', ':expected_format' => '. Alphanumeric and dash characters only', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_FORMAT);
       return c_base_return_error::s_false($error);
@@ -152,58 +293,78 @@ class c_base_session {
   /**
    * Returns the stored user name.
    *
-   * @return c_base_return_string
-   *   The user name string.
+   * @return c_base_return_string|c_base_return_null
+   *   The user name string or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
    */
   public function get_name() {
+    if (is_null($this->name)) {
+      return new c_base_return_null();
+    }
+
     return c_base_return_string::s_new($this->name);
   }
 
   /**
    * Assigns the user id associated with the session.
    *
-   * @param int $id_user
+   * @param int|null $id_user
    *   The user id.
    *   This must be greater than or equal to 0.
+   *   Set to NULL to remove any existing values.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    */
   public function set_id_user($id_user) {
-    if ((is_int($id_user) && $id_user < 0) || !is_int($id_user) && (!is_string($id_user) || !(is_numeric($id_user) && (int) $id_user >= 0))) {
+    if (!is_null($id_user) && ((is_int($id_user) && $id_user < 0))) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'id_user', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
       return c_base_return_error::s_false($error);
     }
 
-    $this->id_user = (int) $id_user;
+    $this->id_user = $id_user;
+
     return new c_base_return_true();
   }
 
   /**
    * Returns the stored user id.
    *
-   * @return c_base_return_int
-   *   The user id_user integer.
+   * @return c_base_return_int|c_base_return_null
+   *   The user id_user integer or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
    */
   public function get_id_user() {
+    if (is_null($this->id_user)) {
+      return new c_base_return_null();
+    }
+
     return c_base_return_int::s_new($this->id_user);
   }
 
   /**
    * Assigns the host ip address associated with the session.
    *
-   * @param string $host
+   * @param string|null $host
    *   The host ip address.
+   *   Set to NULL to remove any existing values.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    */
   public function set_host($host) {
-    if (!is_string($host) || empty($host)) {
+    if (!is_null($host) && (!is_string($host) || empty($host))) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'host', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
       return c_base_return_error::s_false($error);
     }
 
+    if (is_null($host)) {
+      $this->host = nULL;
+      return new c_base_return_true();
+    }
+
     if (mb_strlen($host) == 0 || ip2long($host) === FALSE) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'host', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
       return c_base_return_error::s_false($error);
@@ -216,10 +377,15 @@ class c_base_session {
   /**
    * Returns the stored host ip address.
    *
-   * @return c_base_return_string
-   *   The host ip address string.
+   * @return c_base_return_string|c_base_return_null
+   *   The host ip address string or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
    */
   public function get_host() {
+    if (is_null($this->host)) {
+      return new c_base_return_null();
+    }
+
     return c_base_return_string::s_new($this->host);
   }
 
@@ -231,10 +397,11 @@ class c_base_session {
    *
    * @param string|null $password
    *   The password.
-   *   Assigning null disable the password.
+   *   Set to NULL to remove any existing values.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: c_base_session::load()
    */
@@ -262,10 +429,15 @@ class c_base_session {
   /**
    * Returns the stored password.
    *
-   * @return c_base_return_string
-   *   The password string.
+   * @return c_base_return_string|c_base_return_null
+   *   The password string or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
    */
   public function get_password() {
+    if (is_null($this->password)) {
+      return new c_base_return_null();
+    }
+
     return c_base_return_string::s_new($this->password);
   }
 
@@ -274,14 +446,75 @@ class c_base_session {
    *
    * The settings provides optional information that a service may want to store with a particular session.
    *
-   * @param array $settings
+   * @param $setting
+   *   A value to assign at the specified delta.
+   *   Can be any variable type.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
+   */
+  public function set_setting($delta, $setting) {
+    if (!is_int($delta) && !is_string($delta)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'delta', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (!is_array($this->settings)) {
+      $this->settings = array();
+    }
+
+    $this->settings[$delta] = $setting;
+    return new c_base_return_true();
+  }
+
+  /**
+   * Returns a specific index within the stored settings.
+   *
+   * @param int|string $delta
+   *   (optional) If an integer or a string, represents a specific index in the given settings array.
+   *
+   * @return c_base_return_value|c_base_return_null
+   *   The settings array value at the specified delta or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
+   */
+  public function get_setting($delta) {
+    if (!is_int($delta) && !is_string($delta)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'delta', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    if (is_null($this->settings)) {
+      return new c_base_return_null();
+    }
+
+    if (!array_key_exists($delta, $this->settings)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':index_name' => $delta, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::NOT_FOUND_ARRAY_INDEX);
+      return c_base_return_error::s_false($error);
+    }
+
+    if ($this->settings[$delta] instanceof c_base_return) {
+      return $this->settings[$delta];
+    }
+
+    return c_base_return_value::s_new($this->settings[$delta]);
+  }
+
+  /**
+   * Assigns the settings associated with the session.
+   *
+   * The settings provides optional information that a service may want to store with a particular session.
+   *
+   * @param array|null $settings
    *   The settings array to assign.
+   *   Set to NULL to remove any existing values.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    */
   public function set_settings($settings) {
-    if (!is_array($settings)) {
+    if (!is_null($settings) && !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_false($error);
     }
@@ -293,10 +526,15 @@ class c_base_session {
   /**
    * Returns the stored settings.
    *
-   * @return c_base_return_array
-   *   The settings array.
+   * @return c_base_return_array|c_base_return_null
+   *   The settings array or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
    */
   public function get_settings() {
+    if (is_null($this->settings)) {
+      return new c_base_return_null();
+    }
+
     return c_base_return_array::s_new($this->settings);
   }
 
@@ -321,20 +559,27 @@ class c_base_session {
    * Manually assign this for existing sessions only.
    * This should be auto-populated when a new session is saved.
    *
-   * @param string $session_id
+   * @param string|null $session_id
    *   The session id string.
+   *   Set to NULL to remove any existing values.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: c_base_session::save()
    */
   public function set_session_id($session_id) {
-    if (!is_string($session_id) || empty($session_id)) {
+    if (!is_null($session_id) && (!is_string($session_id) || empty($session_id))) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'session_id', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
       return c_base_return_error::s_false($error);
     }
 
+    if (is_null($session_id)) {
+      $this->session_id = NULL;
+      return new c_base_return_true();
+    }
+
     // deny 0-length session_id.
     if (mb_strlen($session_id) == 0) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'session_id', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
@@ -348,26 +593,33 @@ class c_base_session {
   /**
    * Returns the stored session id.
    *
-   * @return c_base_return_string
-   *   The session id string.
+   * @return c_base_return_string|c_base_return_null
+   *   The session id string or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
    */
   public function get_session_id() {
+    if (is_null($this->session_id)) {
+      return new c_base_return_null();
+    }
+
     return c_base_return_string::s_new($this->session_id);
   }
 
   /**
    * Assigns the session expiration timeout.
    *
-   * @param int $timeout_expire
+   * @param int|null $timeout_expire
    *   The unix timestamp for the expiration timeout.
+   *   Set to NULL to remove any existing values.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: c_base_session::save()
    */
   public function set_timeout_expire($timeout_expire) {
-    if (!is_int($timeout_expire)) {
+    if (!is_null($timeout_expire) && !is_int($timeout_expire)) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'timeout_expire', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
       return c_base_return_error::s_false($error);
     }
@@ -379,26 +631,33 @@ class c_base_session {
   /**
    * Returns the unix timestamp for the session expiration timeout.
    *
-   * @return c_base_return_int
-   *   The unix timestamp for the session expiration timeout.
+   * @return c_base_return_int|c_base_return_null
+   *   The unix timestamp for the session expiration timeout or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
    */
   public function get_timeout_expire() {
+    if (is_null($this->timeout_expire)) {
+      return new c_base_return_null();
+    }
+
     return c_base_return_int::s_new($this->timeout_expire);
   }
 
   /**
    * Assigns the max session timeout.
    *
-   * @param int $timeout_max
+   * @param int|null $timeout_max
    *   The unix timestamp for the max session timeout.
+   *   Set to NULL to remove any existing values.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: c_base_session::save()
    */
   public function set_timeout_max($timeout_max) {
-    if (!is_int($timeout_max)) {
+    if (!is_null($timeout_max) && !is_int($timeout_max)) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'timeout_max', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
       return c_base_return_error::s_false($error);
     }
@@ -410,18 +669,73 @@ class c_base_session {
   /**
    * Returns the unix timestamp for the max timeout.
    *
-   * @return c_base_return_int
-   *   The unix timestamp for the max timeout.
+   * @return c_base_return_int|c_base_return_null
+   *   The unix timestamp for the max timeout or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
    */
   public function get_timeout_max() {
+    if (is_null($this->timeout_max)) {
+      return new c_base_return_null();
+    }
+
     return c_base_return_int::s_new($this->timeout_max);
   }
 
   /**
+   * Assigns an array of form problems.
+   *
+   * @param array|null $problems
+   *   An array of form problems.
+   *   Set to NULL to remove any existing values.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
+   */
+  public function set_problems($problems) {
+    if (!is_null($problems) && !is_array($problems)) {
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'problems', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
+      return c_base_return_error::s_false($error);
+    }
+
+    $this->problems = array();
+
+    if (is_null($problems)) {
+      return new c_base_return_true();
+    }
+
+    foreach ($problems as $problem) {
+      if ($problem instanceof c_base_form_problem) {
+        $this->problems[] = $problem;
+      }
+    }
+    unset($problem);
+
+    $this->problems = $problems;
+    return new c_base_return_true();
+  }
+
+  /**
+   * Returns the unix timestamp for the max timeout.
+   *
+   * @return c_base_return_array
+   *   An array containing any problems associated with forms for this session.
+   *   FALSE with the error bit set is returned on error.
+   */
+  public function get_problems() {
+    if (is_null($this->problems)) {
+      $this->problems = array();
+    }
+
+    return c_base_return_array::s_new($this->problems);
+  }
+
+  /**
    * Assigns the max session timeout.
    *
-   * @param int $seconds
+   * @param int|null $seconds
    *   Number of seconds until timeout is reached.
+   *   Set to NULL to remove any existing values.
    * @param int $microseconds
    *   (optional) Number of microseconds until timeout is reached.
    * @param bool $receive
@@ -430,11 +744,12 @@ class c_base_session {
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: socket_set_option()
    */
   public function set_socket_timeout($seconds, $microseconds = 0, $receive = TRUE) {
-    if (!is_int($seconds) || $seconds < 0) {
+    if (!is_null($seconds) && (!is_int($seconds) || $seconds < 0)) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'seconds', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT);
       return c_base_return_error::s_false($error);
     }
@@ -449,6 +764,11 @@ class c_base_session {
       return c_base_return_error::s_false($error);
     }
 
+    if (is_null($seconds)) {
+      $this->socket_timeout = NULL;
+      return new c_base_return_true();
+    }
+
     if (!is_array($this->socket_timeout)) {
       $this->socket_timeout = array(
         'send' => NULL,
@@ -475,35 +795,18 @@ class c_base_session {
   /**
    * Returns the unix timestamp for the max timeout.
    *
-   * @return c_base_return_int
-   *   The unix timestamp for the max timeout.
+   * @return c_base_return_int|c_base_return_null
+   *   The unix timestamp for the max timeout or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: socket_get_option()
    */
   public function get_socket_timeout() {
-    return c_base_return_array::s_new($this->socket_timeout);
-  }
-
-  /**
-   * Returns the stored error array.
-   *
-   * This should be called after a load() or a save() command to check to see if the socket returned any error.
-   *
-   * This does not return the socket error, for that use self::get_error_socket()
-   *
-   * @return c_base_return_array|c_base_return_status
-   *   The error array or boolean returned by the socket when transferring data or NULL if there are no socket errors.
-   *   A value of FALSE means that no error was returned by the socket.
-   *   A value of an array() for both load() and save() would contain the socket error message.
-   *
-   * @see: self::get_error_socket()
-   */
-  public function get_error() {
-    if (is_bool($this->error)) {
-      c_base_return_bool::s_new($this->error);
+    if (is_null($this->socket_timeout)) {
+      return new c_base_return_null();
     }
 
-    return c_base_return_array::s_new($this->error);
+    return c_base_return_array::s_new($this->socket_timeout);
   }
 
   /**
@@ -512,7 +815,8 @@ class c_base_session {
    * Use self::get_error() to get the error reported in the packet and not the socket.
    *
    * @return c_base_return_int
-   *   Number representing the socket error.
+   *   Number representing the socket error or NULL if undefined.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: self::get_error()
    * @see: socket_last_error()
@@ -531,6 +835,7 @@ class c_base_session {
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: self::get_error_socket()
    * @see: socket_clear_error()
@@ -605,6 +910,7 @@ class c_base_session {
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    */
   public function do_disconnect() {
     if (!is_resource($this->socket)) {
@@ -626,6 +932,7 @@ class c_base_session {
    *
    * @return c_base_return_status
    *   TRUE when connected, FALSE otherwise.
+   *   FALSE with the error bit set is returned on error.
    */
   public function is_connected() {
     if (is_resource($this->socket)) {
@@ -640,6 +947,7 @@ class c_base_session {
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE on failure.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: c_base_session::do_connect()
    * @see: c_base_session::p_transfer()
@@ -662,10 +970,10 @@ class c_base_session {
 
     $response = $this->p_transfer(array('ip' => $this->host, 'session_id' => $this->session_id));
     if (c_base_return::s_has_error($response)) {
-      return $response->get_error();
+      return c_base_return_error::s_false($response->get_error());
     }
 
-    $response = c_base_return_array::s_value_exact($response);
+    $response = $response->get_value_exact();
     if (empty($response['result']) || !is_array($response['result'])) {
       unset($response);
 
@@ -724,6 +1032,7 @@ class c_base_session {
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE on failure.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: c_base_session::set_name()
    * @see: c_base_session::set_host()
@@ -814,6 +1123,7 @@ class c_base_session {
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE on failure.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: self::do_connect()
    * @see: self::p_transfer()
@@ -870,6 +1180,7 @@ class c_base_session {
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE on failure.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: self::do_connect()
    * @see: self::p_transfer()
@@ -882,7 +1193,7 @@ class c_base_session {
 
     $response = $this->p_transfer(array('flush' => TRUE));
     if (c_base_return::s_has_error($response)) {
-      return $response->get_error();
+      return c_base_return_error::s_false($response->get_error());
     }
 
     $response = c_base_return_array::s_value_exact($response);
@@ -906,13 +1217,11 @@ class c_base_session {
    * @return c_base_return_status|c_base_return_array
    *   An array is returned on success.
    *   FALSE is returned otherwise.
+   *   FALSE with the error bit set is returned on error.
    *
    * @see: c_base_session::do_connect()
    */
   private function p_transfer($request) {
-    unset($this->error);
-    $this->error = NULL;
-
     $json = json_encode($request);
 
     $written = @socket_write($this->socket, $json);
@@ -937,10 +1246,6 @@ class c_base_session {
     $response = json_decode($json, TRUE);
     unset($json);
 
-    if (isset($response['error'])) {
-      $this->error = $response['error'];
-    }
-
     if ($response === FALSE) {
       $error = c_base_error::s_log(NULL, array('arguments' => array(':operation_name' => 'json_decode', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::OPERATION_FAILURE);
       return c_base_return_error::s_false($error);
@@ -949,78 +1254,3 @@ class c_base_session {
     return c_base_return_array::s_new($response);
   }
 }
-
-/**
- * A return class whose value is represented as a c_base_session.
- */
-class c_base_session_return extends c_base_return_value {
-  use t_base_return_value_exact;
-
-  /**
-   * @see: t_base_return_value::p_s_new()
-   */
-  public static function s_new($value) {
-    return self::p_s_new($value, __CLASS__);
-  }
-
-  /**
-   * @see: t_base_return_value::p_s_value()
-   */
-  public static function s_value($return) {
-    return self::p_s_value($return, __CLASS__);
-  }
-
-  /**
-   * @see: t_base_return_value_exact::p_s_value_exact()
-   */
-  public static function s_value_exact($return) {
-    return self::p_s_value_exact($return, __CLASS__, new c_base_session());
-  }
-
-  /**
-   * Assign the value.
-   *
-   * @param c_base_session $value
-   *   Any value so long as it is a c_base_session object.
-   *   NULL is not allowed.
-   *
-   * @return c_base_return_status
-   *   TRUE on success, FALSE otherwise.
-   */
-  public function set_value($value) {
-    if (!($value instanceof c_base_session)) {
-      return FALSE;
-    }
-
-    $this->value = $value;
-    return TRUE;
-  }
-
-  /**
-   * Return the value.
-   *
-   * @return c_base_session $value
-   *   The value array stored within this class.
-   */
-  public function get_value() {
-    if (!($this->value instanceof c_base_session)) {
-      $this->value = NULL;
-    }
-
-    return $this->value;
-  }
-
-  /**
-   * Return the value of the expected type.
-   *
-   * @return c_base_session $value
-   *   The value c_base_session stored within this class.
-   */
-  public function get_value_exact() {
-    if (!($this->value instanceof c_base_session)) {
-      $this->value = new c_base_session();
-    }
-
-    return $this->value;
-  }
-}
index 129713bdf64b24a2f132ce86e09d96417c55ce2b..39065d1bb99cba6fd400e2ca92914acadfc5a746 100644 (file)
@@ -27,7 +27,7 @@ class c_theme_dom extends DOMDocument {
    * Class constructor.
    */
   public function __construct() {
-    super.__construct('1.0', 'UTF-8');
+    parent::__construct('1.0', 'UTF-8');
   }
 
   /**
index 49140f47584bf66ead0adc2641c481cc10940b47..f51544db15013268c0d6f39e4d4cbcddaed5ddfe 100644 (file)
@@ -24,7 +24,7 @@ require_once('common/base/classes/base_mime.php');
  * There are amazing levels of inconsistency in HTML5, but for now this class implements HTML5 as closely as possible.
  * Future versions of this may violate the standard in favor of consistency and sanity.
  */
-class c_theme_html {
+class c_theme_html extends c_base_return {
   const DEFAULT_MAX_RECURSION_DEPTH = 16384;
 
   private $html;
@@ -36,6 +36,8 @@ class c_theme_html {
    * Class constructor.
    */
   public function __construct() {
+    parent::__construct();
+
     $this->html = NULL;
     $this->markup = NULL;
     $this->http = NULL;
@@ -50,6 +52,29 @@ class c_theme_html {
     unset($this->markup);
     unset($this->http);
     unset($this->max_recursion_depth);
+
+    parent::__destruct();
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, '');
   }
 
   /**
@@ -62,7 +87,7 @@ class c_theme_html {
    * @param array|null $classes
    *   (optional) An array of strings representing additional classes to append.
    *
-   * @return c_base_markup_tag_return|c_base_return_status
+   * @return c_base_markup_tag|c_base_return_status
    *   A newly created tag is returned on success.
    *   FALSE with the error bit set is returned on error.
    */
@@ -111,7 +136,7 @@ class c_theme_html {
     $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CLASS, $class);
     unset($class);
 
-    return c_base_markup_tag_return::s_new($tag);
+    return $tag;
   }
 
   /**
@@ -137,7 +162,7 @@ class c_theme_html {
   /**
    * Get the markup html assigned to this object.
    *
-   * @return c_base_html_return|c_base_return_status
+   * @return c_base_html|c_base_return_status
    *   The markup html object.
    *   FALSE is returned if no id is assigned.
    *   FALSE with error bit set is returned on error.
@@ -147,7 +172,7 @@ class c_theme_html {
       $this->html = new c_base_html();
     }
 
-    return c_base_html_return::s_new($this->html);
+    return $this->html;
   }
 
   /**
@@ -210,7 +235,7 @@ class c_theme_html {
   /**
    * Get the HTTP information
    *
-   * @return c_base_html_return|c_base_return_status
+   * @return c_base_http|c_base_return_status
    *   The markup tags object.
    *   FALSE is returned if no id is assigned.
    *   FALSE with error bit set is returned on error.
@@ -220,7 +245,7 @@ class c_theme_html {
       $this->http = new c_base_http();
     }
 
-    return c_base_http_return::s_new($this->http);
+    return $this->http;
   }
 
   /**
@@ -244,9 +269,9 @@ class c_theme_html {
   }
 
   /**
-   * Get the markup html assigned to this object.
+   * Get the maximum recursion depth integer assigned to this object.
    *
-   * @return c_base_html_return|c_base_return_status
+   * @return c_base_return_int|c_base_return_status
    *   The markup html object.
    *   FALSE is returned if no id is assigned.
    *   FALSE with error bit set is returned on error.
index 170fe3e8bf72cbd51cd1b8d64054b6ee1aa00292..e71961a3fe907b292711d4cbbdcd948f6e6d210f 100644 (file)
@@ -6,7 +6,7 @@ start transaction;
 
 /** Custom database specific settings (do this on every connection made) **/
 set bytea_output to hex;
-set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,drafters,users,public;
+set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,editors,drafters,requesters,users,public;
 set datestyle to us;
 
 
@@ -14,12 +14,12 @@ set datestyle to us;
 /*** Associations ***/
 create table managers.t_associations (
   id bigint not null,
-  id_owner bigint not null,
+  id_manager bigint not null,
   id_group bigint,
   id_coordinator bigint not null,
 
   name_machine varchar(128) not null,
-  name_machine_owner varchar(128) not null,
+  name_machine_manager varchar(128) not null,
   name_machine_coordinator varchar(128) not null,
   name_human varchar(256) not null,
 
@@ -37,7 +37,7 @@ create table managers.t_associations (
 
   constraint cc_associations_id check (id > 0),
 
-  constraint cf_associations_id_owner foreign key (id_owner, name_machine_owner) references administers.t_users (id, name_machine) on delete restrict on update cascade,
+  constraint cf_associations_id_manager foreign key (id_manager, name_machine_manager) references administers.t_users (id, name_machine) on delete restrict on update cascade,
   constraint cf_associations_id_coordinator foreign key (id_coordinator, name_machine_coordinator) references administers.t_users (id, name_machine) on delete restrict on update cascade,
   constraint cf_associations_group foreign key (id_group) references managers.t_groups (id) on delete restrict on update cascade,
   constraint cf_associations_field_affiliation foreign key (field_affiliation) references managers.t_field_affiliations (id) on delete restrict on update cascade,
@@ -58,8 +58,8 @@ grant usage on managers.s_associations_id to reservation_users;
 /*** provide current user access to their own information ***/
 create view users.v_associations_self with (security_barrier=true) as
   with allowed_groups as (select id from users.v_groups_self)
-  select id, id_owner, id_group, id_coordinator, name_machine, name_machine_owner, name_machine_cooordinator, name_human, date_created, date_changed, field_affiliation, field_classification from managers.t_associations
-    where is_deleted is not true and ((group_id is null and (name_machine_owner)::text = (current_user)::text) or group_id in (select * from allowed_groups));
+  select id, id_manager, id_group, id_coordinator, name_machine, name_machine_manager, name_machine_coordinator, name_human, date_created, date_changed, field_affiliation, field_classification from managers.t_associations
+    where is_deleted is not true and ((id_group is null and (name_machine_manager)::text = (current_user)::text) or id_group in (select * from allowed_groups));
 
 grant select on users.v_associations_self to reservation_users;
 
@@ -67,27 +67,25 @@ grant select on users.v_associations_self to reservation_users;
 /*** provide current user access to associations who they are assigned as the coordinator of ***/
 create view users.v_associations_coordinator_self with (security_barrier=true) as
   with allowed_groups as (select id from users.v_groups_self)
-  select id, id_owner, id_group, id_coordinator, name_machine, name_machine_owner, name_machine_cooordinator, name_human, date_created, date_changed, field_affiliation, field_classification from managers.t_associations
-    where is_deleted is not true and (name_machine_coordinator)::text = (current_user)::text);
+  select id, id_manager, id_group, id_coordinator, name_machine, name_machine_manager, name_machine_coordinator, name_human, date_created, date_changed, field_affiliation, field_classification from managers.t_associations
+    where is_deleted is not true and (name_machine_coordinator)::text = (current_user)::text;
 
 grant select on users.v_associations_coordinator_self to reservation_users;
 
 
 /** provide current user access to insert their own associations **/
 create view users.v_associations_self_insert with (security_barrier=true) as
-  with allowed_groups as (select id from users.v_groups_self)
-  select id, id_owner, id_group, id_coordinator, name_machine, name_machine_owner, name_machine_cooordinator, name_human, field_affiliation, field_classification from managers.t_associations
-    where is_deleted is not true and (group_id is null or group_id in (select * from allowed_groups)) and (name_machine_owner)::text = (current_user)::text
+  select id, id_manager, id_group, id_coordinator, name_machine, name_machine_manager, name_machine_coordinator, name_human, field_affiliation, field_classification from managers.t_associations
+    where is_deleted is not true and (id_group is null or id_group in (select id from users.v_groups_self)) and (name_machine_manager)::text = (current_user)::text
     with check option;
 
 grant insert on users.v_associations_self_insert to reservation_users;
 
 
 /** provide current user access to update their own associations **/
-create view public.v_associations_self_update with (security_barrier=true) as
-  with allowed_groups as (select id from users.v_groups_self)
-  select id, id_group, id_coordinator, name_machine, name_machine_cooordinator, name_human, date_changed, field_affiliation, field_classification from managers.t_associations
-    where is_deleted is not true and (group_id is null or group_id in (select * from allowed_groups)) and date_changed = localtimestamp and (name_machine_owner)::text = (current_user)::text
+create view users.v_associations_self_update with (security_barrier=true) as
+  select id, id_group, id_coordinator, name_machine, name_machine_coordinator, name_human, date_changed, field_affiliation, field_classification from managers.t_associations
+    where is_deleted is not true and (id_group is null or id_group in (select id from users.v_groups_self)) and date_changed = localtimestamp and (name_machine_manager)::text = (current_user)::text
     with check option;
 
 grant insert on users.v_associations_self_update to reservation_users;
index acce227a9c3eada25524d69d5433e4010c4ea38c..4d309d244736b3d6629e7b9b397021e6402acfe4 100644 (file)
@@ -6,7 +6,7 @@ start transaction;
 
 /** Custom database specific settings (do this on every connection made) **/
 set bytea_output to hex;
-set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,drafters,users,public;
+set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,editors,drafters,requesters,users,public;
 set datestyle to us;
 
 
index 2bf5e64afcba399fd11f4d7a21eb55a1dc0bcb9a..84f29f678ed61a5b78dd3521eeee7d8b9c652f97 100644 (file)
@@ -14,7 +14,9 @@ create role reservation_users_publisher inherit nologin;
 create role reservation_users_insurer inherit nologin;
 create role reservation_users_financer inherit nologin;
 create role reservation_users_reviewer inherit nologin;
+create role reservation_users_editor inherit nologin;
 create role reservation_users_drafter inherit nologin;
+create role reservation_users_requester inherit nologin;
 
 grant reservation_users to reservation_users_administer with admin option;
 grant reservation_users to reservation_users_manager with admin option;
@@ -23,7 +25,9 @@ grant reservation_users to reservation_users_publisher;
 grant reservation_users to reservation_users_insurer;
 grant reservation_users to reservation_users_financer;
 grant reservation_users to reservation_users_reviewer;
+grant reservation_users to reservation_users_editor;
 grant reservation_users to reservation_users_drafter;
+grant reservation_users to reservation_users_requester;
 
 grant reservation_users_manager to reservation_users_administer with admin option;
 
@@ -42,9 +46,15 @@ grant reservation_users_financer to reservation_users_manager with admin option;
 grant reservation_users_reviewer to reservation_users_administer with admin option;
 grant reservation_users_reviewer to reservation_users_manager with admin option;
 
+grant reservation_users_editor to reservation_users_administer with admin option;
+grant reservation_users_editor to reservation_users_manager with admin option;
+
 grant reservation_users_drafter to reservation_users_administer with admin option;
 grant reservation_users_drafter to reservation_users_manager with admin option;
 
+grant reservation_users_requester to reservation_users_administer with admin option;
+grant reservation_users_requester to reservation_users_manager with admin option;
+
 /** This is the role the database should use to connect to to perform system activity **/
 create role reservation_user;
 
index 72f317b8d0aac6bf81fa6ef297884711c6bdc915..0d0b020d025e926757bbf52ebf5c7d6a846ad511 100644 (file)
@@ -6,17 +6,24 @@ start transaction;
 
 /** Custom database specific settings (do this on every connection made) **/
 set bytea_output to hex;
-set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,drafters,users,public;
+set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,editors,drafters,requesters,users,public;
 set datestyle to us;
 
 
+/* Note about composite groups (is_composite)
+  Instead of having an array of multiple groups assigned to one entity or having a table of group and entity associates, use a group that logically represents multiple groups.
+  For example, if I want to add both group_1 and group_2 to entity_a, then I can create group_3 and put all users from group_1 and group_2 in it.
+  @todo: I will likely need to create a composite groups table to manage the relations between a composite group and its non-composites for management purposes.
+
+  @todo: with this composite groups design, I can get rid of the user to groups table and need users only to be assigned to a single (composite) group.
+         the current flaw with this design may be with access control in creating or auto-creating composite groups.
+*/
 
 /** Groups **/
 create table managers.t_groups (
   id bigint not null,
   id_sort smallint not null default 0,
   id_external bigint,
-  id_creator bigint not null,
   id_manager bigint,
 
   name_machine varchar(128) not null,
@@ -31,6 +38,9 @@ create table managers.t_groups (
 
   is_deleted boolean default false not null,
   is_locked boolean default false not null,
+  is_composite boolean default false not null,
+
+  can_manage_paths boolean default false not null,
 
   settings json,
 
@@ -43,7 +53,6 @@ create table managers.t_groups (
   constraint cu_groups_name_machine unique (name_machine),
   constraint cu_groups_user unique (id, name_machine),
 
-  constraint cf_t_groups_creator foreign key (id_creator, name_machine_creator) references administers.t_users (id, name_machine) on delete restrict on update cascade,
   constraint cf_t_groups_manager foreign key (id_manager, name_machine_manager) references administers.t_users (id, name_machine) on delete restrict on update cascade
 );
 
@@ -88,7 +97,7 @@ create index ci_groups_id_sort_z on managers.t_groups (id_sort) with (fillfactor
 
 
 /** Groups to Users Association **/
-create table managers.t_groups_users (
+create table managers.t_group_users (
   id_user bigint not null,
   id_group bigint not null,
 
@@ -96,8 +105,8 @@ create table managers.t_groups_users (
 
   constraint cu_groups_id unique (id_user, id_group),
 
-  constraint cf_t_groups_users_user foreign key (id_user, name_machine_user) references administers.t_users (id, name_machine) on delete cascade on update cascade,
-  constraint cf_t_groups_users_group foreign key (id_group) references managers.t_groups (id) on delete cascade on update cascade
+  constraint cf_t_group_users_user foreign key (id_user, name_machine_user) references administers.t_users (id, name_machine) on delete cascade on update cascade,
+  constraint cf_t_group_users_group foreign key (id_group) references managers.t_groups (id) on delete cascade on update cascade
 );
 
 grant select,insert,update on managers.t_groups to reservation_users_administer;
@@ -105,32 +114,59 @@ grant select,insert,update on managers.t_groups to reservation_users_manager;
 grant select on managers.t_groups to reservation_users_auditor;
 
 
+/*** provide group manages access to manage users assigned to their groups ***/
+create view users.v_group_users_manage with (security_barrier=true) as
+  select gu.id_user, gu.id_group from managers.t_group_users gu
+    inner join managers.t_groups g on g.id = gu.id_group
+    where g.is_deleted is not true and (g.name_machine_manager)::text = (current_user)::text;
+
+grant select, insert, update, delete on users.v_group_users_manage to reservation_users;
+
+
 /*** provide current user access to their own information ***/
 create view users.v_groups_self with (security_barrier=true) as
-  select g.id, g.id_sort, g.id_external, g.id_creator, g.id_manager, g.name_machine, g.name_human, g.is_locked, g.date_created, g.date_changed, g.date_synced, g.settings from managers.t_groups g
-    inner join managers.t_groups_users gu on g.id = gu.id_group
+  select g.id, g.id_sort, g.id_external, g.id_manager, g.name_machine, g.name_human, g.is_locked, g.is_composite, g.date_created, g.date_changed, g.date_synced, g.can_manage_paths, g.settings from managers.t_groups g
+    inner join managers.t_group_users gu on g.id = gu.id_group
     where g.is_deleted is not true and (gu.name_machine_user)::text = (current_user)::text;
 
 grant select on users.v_groups_self to reservation_users;
 
 
-/*** provide group manages access to manage users assigned to their groups ***/
-create view users.v_groups_users_manage with (security_barrier=true) as
-  select gu.id_user, gu.id_group from managers.t_groups_users gu
-    inner join managers.t_groups g on g.id = gu.id_group
-    where g.is_deleted is not true and (gu.name_machine_manager)::text = (current_user)::text;
-
-grant select, insert, update, delete on users.v_groups_self to reservation_users;
-
-
 /*** provide group manages access to manage users their groups ***/
 create view users.v_groups_manage with (security_barrier=true) as
-  select g.id, g.id_sort, g.id_external, g.name_machine, g.name_human, g.is_locked, g.date_changed, g.date_synced, g.settings from managers.t_groups g
-    inner join managers.t_groups_users gu on g.id = gu.id_group
-    where g.is_deleted is not true and date_changed = localtimestamp and (date_synced is null or date_synced = localtimestamp) and (gu.name_machine_user)::text = (current_user)::text;
+  select g.id, g.id_sort, g.id_external, g.name_machine, g.name_human, g.is_locked, g.is_composite, g.date_changed, g.date_synced, g.can_manage_paths, g.settings from managers.t_groups g
+    inner join managers.t_group_users gu on g.id = gu.id_group
+    where g.is_deleted is not true and (date_changed is null or date_changed = localtimestamp) and (date_synced is null or date_synced = localtimestamp) and (gu.name_machine_user)::text = (current_user)::text;
 
 grant select, insert, update on users.v_groups_manage to reservation_users;
 
 
 
+
+/** Groups Composites **/
+create table managers.t_group_composites (
+  id_composite bigint not null,
+  id_group bigint not null,
+
+  constraint cu_group_composites_id unique (id_composite, id_group),
+
+  constraint cf_t_group_composites_composite foreign key (id_composite) references managers.t_groups (id) on delete cascade on update cascade,
+  constraint cf_t_group_composites_group foreign key (id_group) references managers.t_groups (id) on delete cascade on update cascade
+);
+
+grant select,insert,update on managers.t_groups to reservation_users_administer;
+grant select,insert,update on managers.t_groups to reservation_users_manager;
+grant select on managers.t_groups to reservation_users_auditor;
+
+
+/*** provide group manages access to composite groups containing groups they belong to. ***/
+create view users.v_group_composites with (security_barrier=true) as
+  with allowed_groups as (select id from users.v_groups_self)
+  select gc.id_composite, gc.id_group from managers.t_group_composites gc
+    inner join managers.t_groups g on g.id = gc.id_group
+    where g.is_deleted is not true and (g.is_locked is not true or (g.name_machine_manager)::text = (current_user)::text) and ((g.name_machine_manager)::text = (current_user)::text or gc.id_group in (select * from allowed_groups));
+
+grant select on users.v_group_composites to reservation_users;
+
+
 commit transaction;
index 5e91e4ae203bc2c1abf95ac7b8f028028493a54e..61dfb60eb95effec3ad47328e15a61f82be3c2cb 100644 (file)
@@ -6,7 +6,7 @@ start transaction;
 
 /** Custom database specific settings (do this on every connection made) **/
 set bytea_output to hex;
-set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,drafters,users,public;
+set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,editors,drafters,requesters,users,public;
 set datestyle to us;
 
 
@@ -29,7 +29,7 @@ create table managers.t_log_groups (
 
   constraint cf_log_groups_id_user foreign key (id_user, name_machine_user) references administers.t_users (id, name_machine) on delete restrict on update cascade,
   constraint cf_log_groups_id_group foreign key (id_group) references managers.t_groups (id) on delete restrict on update cascade,
-  constraint cf_log_groups_log_type foreign key (log_type) references managers.t_log_types (id) on delete restrict on update cascade,
+  constraint cf_log_groups_log_type foreign key (log_type) references managers.t_log_types (id) on delete restrict on update cascade
 );
 
 create sequence managers.s_log_groups_id owned by managers.t_log_groups.id;
@@ -44,7 +44,7 @@ grant usage on managers.s_log_groups_id to reservation_users;
 
 /** only allow select and insert for users when user id is current user **/
 create view users.v_log_groups_self with (security_barrier=true) as
-  gselect id, id_user, id_group, log_type, log_details, log_date from managers.t_log_groups
+  select id, id_user, id_group, log_type, log_details, log_date from managers.t_log_groups
     where (name_machine_user)::text = (current_user)::text;
 
 grant select on users.v_log_groups_self to reservation_users;
@@ -59,7 +59,7 @@ grant insert on users.v_log_groups_self_insert to reservation_users;
 
 
 /*** provide group user activity logging ***/
-create table managers.t_log_groups_users (
+create table managers.t_log_group_users (
   id bigint not null,
   id_user bigint default 1 not null,
   id_group bigint not null,
@@ -69,38 +69,38 @@ create table managers.t_log_groups_users (
   log_type bigint not null,
   log_date timestamp default localtimestamp not null,
 
-  constraint cp_log_groups_id primary key (id),
+  constraint cp_log_group_users_id primary key (id),
 
-  constraint cc_log_groups_id check (id > 0),
+  constraint cc_log_group_users_id check (id > 0),
 
-  constraint cf_log_groups_id_user foreign key (id_user, name_machine_user) references administers.t_users (id, name_machine) on delete restrict on update cascade,
-  constraint cf_log_groups_id_group foreign key (id_group) references managers.t_groups (id) on delete restrict on update cascade,
-  constraint cf_log_groups_log_type foreign key (log_type) references managers.t_log_types (id) on delete restrict on update cascade,
+  constraint cf_log_group_users_id_user foreign key (id_user, name_machine_user) references administers.t_users (id, name_machine) on delete restrict on update cascade,
+  constraint cf_log_group_users_id_group foreign key (id_group) references managers.t_groups (id) on delete restrict on update cascade,
+  constraint cf_log_group_users_log_type foreign key (log_type) references managers.t_log_types (id) on delete restrict on update cascade
 );
 
-create sequence managers.s_log_groups_users_id owned by managers.t_log_groups_users.id;
-alter table managers.t_log_groups_users alter column id set default nextval('managers.s_log_groups_users_id'::regclass);
+create sequence managers.s_log_group_users_id owned by managers.t_log_group_users.id;
+alter table managers.t_log_group_users alter column id set default nextval('managers.s_log_group_users_id'::regclass);
 
-grant select on managers.t_log_groups_users to reservation_users_administer;
-grant select on managers.t_log_groups_users to reservation_users_manager;
-grant select on managers.t_log_groups_users to reservation_users_auditor;
-grant select,usage on managers.s_log_groups_users_id to reservation_users_administer;
-grant usage on managers.s_log_groups_users_id to reservation_users;
+grant select on managers.t_log_group_users to reservation_users_administer;
+grant select on managers.t_log_group_users to reservation_users_manager;
+grant select on managers.t_log_group_users to reservation_users_auditor;
+grant select,usage on managers.s_log_group_users_id to reservation_users_administer;
+grant usage on managers.s_log_group_users_id to reservation_users;
 
 
 /** only allow select and insert for users when user id is current user **/
-create view users.v_log_groups_users_self with (security_barrier=true) as
-  select id, id_user, id_group, log_type, log_date from managers.t_log_groups_users
+create view users.v_log_group_users_self with (security_barrier=true) as
+  select id, id_user, id_group, log_type, log_date from managers.t_log_group_users
     where (name_machine_user)::text = (current_user)::text;
 
-grant select on users.v_log_groups_users_self to reservation_users;
+grant select on users.v_log_group_users_self to reservation_users;
 
-create view users.v_log_groups_users_self_insert with (security_barrier=true) as
-  select id_user, id_group, name_machine_user, log_type from managers.t_log_groups_users
+create view users.v_log_group_users_self_insert with (security_barrier=true) as
+  select id_user, id_group, name_machine_user, log_type from managers.t_log_group_users
     where (name_machine_user)::text = (current_user)::text
     with check option;
 
-grant insert on users.v_log_groups_users_self_insert to reservation_users;
+grant insert on users.v_log_group_users_self_insert to reservation_users;
 
 
 
index 19ded9be4e6f98259284f118cd55a6b46244ef6b..abb1e255661139367ef50da58be49b35659b73a0 100644 (file)
@@ -6,7 +6,7 @@ start transaction;
 
 /** Custom database specific settings (do this on every connection made) **/
 set bytea_output to hex;
-set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,drafters,users,public;
+set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,editors,drafters,requesters,users,public;
 set datestyle to us;
 
 
@@ -29,9 +29,9 @@ create table managers.t_log_problems (
   constraint cu_log_problems_name_machine unique (name_machine)
 );
 
-grant select on managers.t_log_activity to reservation_users_administer;
-grant select on managers.t_log_activity to reservation_users_manager;
-grant select on managers.t_log_activity to reservation_users_auditor;
+grant select on managers.t_log_problems to reservation_users_administer;
+grant select on managers.t_log_problems to reservation_users_manager;
+grant select on managers.t_log_problems to reservation_users_auditor;
 
 
 
@@ -66,7 +66,7 @@ create view users.v_log_problems_users_self with (security_barrier=true) as
   select id_problem, id_user, date_created, log_details from managers.t_log_problems_users
     where (name_machine_user)::text = (current_user)::text;
 
-grant select on users.v_log_activity_self to reservation_users;
+grant select on users.v_log_problems_users_self to reservation_users;
 
 create view users.v_log_problems_users_self_insert with (security_barrier=true) as
   select id_problem, id_user, name_machine_user, log_details from managers.t_log_problems_users
index dd43b4b0d06716a0e35a80f397f984e82366576e..5ea2a47b044a79c6ef4107d7188c4208e2aa913a 100644 (file)
@@ -6,7 +6,7 @@ start transaction;
 
 /** Custom database specific settings (do this on every connection made) **/
 set bytea_output to hex;
-set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,drafters,users,public;
+set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,editors,drafters,requesters,users,public;
 set datestyle to us;
 
 
@@ -18,6 +18,7 @@ create table managers.t_log_types (
   name_machine varchar(128) not null,
   name_human varchar(256) not null,
 
+  is_locked boolean default false not null,
   is_deleted boolean default false not null,
 
   date_created timestamp default localtimestamp not null,
@@ -39,8 +40,15 @@ grant select on managers.t_log_types to reservation_users_manager;
 grant select on managers.t_log_types to reservation_users_auditor;
 grant select,usage on managers.s_log_types_id to reservation_users_administer;
 
+create index ci_log_types_deleted_not on managers.t_log_types (id)
+  where is_deleted is not true;
+
+create index ci_log_types_public on managers.t_log_types (id)
+  where is_deleted is not true and is_locked is not true;
+
 create view public.v_log_types with (security_barrier=true) as
-  select id, name_machine, name_human from managers.t_log_types;
+  select id, name_machine, name_human from managers.t_log_types
+  where is_deleted is not true and is_locked is not true;
 
 grant select on public.v_log_types to reservation_users;
 grant select on public.v_log_types to public_users;
index d938c738d1e63f6c62ab6900878d2fa0bcb25c06..d3996abd8586e4d2ce7577883eb933543de96275 100644 (file)
@@ -4,6 +4,13 @@ start transaction;
 
 
 
+/** Custom database specific settings (do this on every connection made) **/
+set bytea_output to hex;
+set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,editors,drafters,requesters,users,public;
+set datestyle to us;
+
+
+
 /*** provide user activity logging ***/
 create table managers.t_log_users (
   id bigint not null,
@@ -110,19 +117,16 @@ create index ci_log_users_response_code_redirects on managers.t_log_users (id)
 create index ci_log_users_response_code_notable on managers.t_log_users (id)
   where response_code in (400, 403, 404, 410, 500, 503);
 
-/** when using current_user reserved function/word the index gets ignored. To prevent this, create a manual/custom index and alter the behavior of the views to be more explicit. **/
-create unique index ci_log_users_current_user on managers.t_log_users (name_machine_user) with (fillfactor = 100);
-
 
 /** only allow select and insert for users when user id is current user **/
 create view users.v_log_users_self with (security_barrier=true) as
-  select id, id_user, log_title, log_type, log_severity, log_details, log_date, request_client from managers.t_log_users
+  select id, id_user, log_title, log_type, log_severity, log_details, log_date, request_client, response_code from managers.t_log_users
     where (name_machine_user)::text = (current_user)::text;
 
 grant select on users.v_log_users_self to reservation_users;
 
 create view users.v_log_users_self_insert with (security_barrier=true) as
-  select id_user, name_machine_user, log_title, log_type, log_severity, log_details, request_client from managers.t_log_users
+  select id_user, name_machine_user, log_title, log_type, log_severity, log_details, request_client, response_code from managers.t_log_users
     where (name_machine_user)::text = (current_user)::text
     with check option;
 
@@ -131,7 +135,7 @@ grant insert on users.v_log_users_self_insert to reservation_users;
 
 /** only allow insert for the public user **/
 create view public.v_log_users_self_insert with (security_barrier=true) as
-  select id_user, name_machine_user, log_title, log_type, log_severity, log_details, request_client from managers.t_log_users
+  select id_user, name_machine_user, log_title, log_type, log_severity, log_details, request_client, response_code from managers.t_log_users
     where id_user = 1 and name_machine_user = 'unknown'
     with check option;
 
@@ -140,7 +144,7 @@ grant insert on public.v_log_users_self_insert to public_users;
 
 /** only allow insert for the system user **/
 create view system.v_log_users_self_insert with (security_barrier=true) as
-  select id_user, name_machine_user, log_title, log_type, log_severity, log_details, request_client from managers.t_log_users
+  select id_user, name_machine_user, log_title, log_type, log_severity, log_details, request_client, response_code from managers.t_log_users
     where id_user = 2 and name_machine_user = 'system'
     with check option;
 
@@ -206,8 +210,6 @@ create index ci_log_activity_response_code_503 on managers.t_log_activity (id)
 create index ci_log_activity_response_code_notable on managers.t_log_activity (id)
   where response_code in (403, 404, 410, 500, 503);
 
-/** when using current_user reserved function/word the index gets ignored. To prevent this, create a manual/custom index and alter the behavior of the views to be more explicit. **/
-create unique index ci_log_activity_current_user on managers.t_log_activity (name_machine_user) with (fillfactor = 100);
 
 
 /** only allow select and insert for users when user id is current user **/
index 33b2ee2e9f094290fb685ae825a2ab3f6f840281..266af797a0de3160070890bbcf20bae5f4091d23 100644 (file)
@@ -15,7 +15,7 @@ start transaction;
 
 /** Custom database specific settings (do this on every connection made) **/
 set bytea_output to hex;
-set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,drafters,users,public;
+set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,editors,drafters,requesters,users,public;
 set datestyle to us;
 
 
@@ -29,7 +29,9 @@ create schema publishers authorization reservation_users_publisher;
 create schema insurer authorization reservation_users_insurer;
 create schema financer authorization reservation_users_financer;
 create schema reviewers authorization reservation_users_reviewer;
+create schema editors authorization reservation_users_editor;
 create schema drafters authorization reservation_users_drafter;
+create schema requesters authorization reservation_users_requester;
 create schema users authorization reservation_users;
 
 revoke create on schema system from reservation_user;
@@ -40,7 +42,9 @@ revoke create on schema publishers from reservation_users_publisher;
 revoke create on schema insurer from reservation_users_insurer;
 revoke create on schema financer from reservation_users_financer;
 revoke create on schema reviewers from reservation_users_reviewer;
+revoke create on schema editors from reservation_users_editor;
 revoke create on schema drafters from reservation_users_drafter;
+revoke create on schema requesters from reservation_users_requester;
 revoke create on schema users from reservation_users;
 
 grant usage on schema system to reservation_user;
@@ -51,7 +55,9 @@ grant usage on schema publishers to reservation_users_publisher;
 grant usage on schema insurer to reservation_users_insurer;
 grant usage on schema financer to reservation_users_financer;
 grant usage on schema reviewers to reservation_users_reviewer;
+grant usage on schema editors to reservation_users_editor;
 grant usage on schema drafters to reservation_users_drafter;
+grant usage on schema requesters to reservation_users_requester;
 grant usage on schema users to reservation_users;
 
 grant create,usage on schema system to postgres;
@@ -62,7 +68,9 @@ grant create,usage on schema publishers to postgres;
 grant create,usage on schema insurer to postgres;
 grant create,usage on schema financer to postgres;
 grant create,usage on schema reviewers to postgres;
+grant create,usage on schema editors to postgres;
 grant create,usage on schema drafters to postgres;
+grant create,usage on schema requesters to postgres;
 grant create,usage on schema users to postgres;
 
 
index f45d3db36abbb40d7f14655b5e937d05e09ecd5d..d263a9204ec6fadf4bd14579f553dc681bcafc6a 100644 (file)
@@ -1,5 +1,5 @@
 /** Standardized SQL Structure - Content **/
-/** This depends on: base-structure.sql **/
+/** This depends on: base-groups.sql **/
 start transaction;
 
 
@@ -11,4 +11,113 @@ set datestyle to us;
 
 
 
+/*** provide path type id and names ***/
+create table managers.t_path_types (
+  id bigint not null,
+
+  name_machine varchar(128) not null,
+  name_human varchar(256) not null,
+
+  is_locked boolean default false not null,
+  is_deleted boolean default false not null,
+
+  date_created timestamp default localtimestamp not null,
+  date_changed timestamp default localtimestamp not null,
+  date_deleted timestamp,
+
+  constraint cp_path_types_id primary key (id),
+
+  constraint cu_path_types_user unique (name_machine),
+
+  constraint cc_path_types_id check (id > 0)
+);
+
+create sequence managers.s_path_types_id owned by managers.t_path_types.id;
+alter table managers.t_path_types alter column id set default nextval('managers.s_path_types_id'::regclass);
+
+grant select,insert,update on managers.t_path_types to reservation_users_administer;
+grant select on managers.t_path_types to reservation_users_manager;
+grant select on managers.t_path_types to reservation_users_auditor;
+grant select,usage on managers.s_path_types_id to reservation_users_administer;
+
+create index ci_path_types_deleted_not on managers.t_path_types (id)
+  where is_deleted is not true;
+
+create index ci_path_types_public on managers.t_path_types (id)
+  where is_deleted is not true and is_locked is not true;
+
+create view public.v_path_types with (security_barrier=true) as
+  select id, name_machine, name_human from managers.t_path_types
+  where is_deleted is not true and is_locked is not true;
+
+grant select on public.v_path_types to reservation_users;
+grant select on public.v_path_types to public_users;
+
+
+/* @todo: pre-populate the path types. */
+
+
+/* @todo: with its current design, the id_access field needs a trigger to maintain its up to date status if/when group ids change. */
+/* @todo: come up with a design for dynamic path management via users/managers (as opposed to hardcoded paths in source). */
+/*** provide paths table (@todo: this is added as a stub and needs to be finished) ***/
+create table managers.t_paths (
+  id bigint not null,
+  id_type bigint not null,
+  id_group bigint,
+
+  name_machine varchar(128) not null,
+  name_human varchar(256) not null,
+
+  is_private boolean default true not null,
+  is_locked boolean default false not null,
+  is_deleted boolean default false not null,
+
+  date_created timestamp default localtimestamp not null,
+  date_changed timestamp default localtimestamp not null,
+  date_deleted timestamp,
+
+  constraint cp_paths_id primary key (id),
+
+  constraint cu_paths_name_machine unique (name_machine),
+
+  constraint cc_paths_id check (id > 0),
+
+  constraint cf_paths_id_type foreign key (id_type) references managers.t_path_types (id) on delete restrict on update cascade,
+  constraint cf_paths_id_group foreign key (id_group) references managers.t_groups (id) on delete restrict on update cascade
+);
+
+create sequence managers.s_paths_id owned by managers.t_paths.id;
+alter table managers.t_paths alter column id set default nextval('managers.s_paths_id'::regclass);
+
+grant select on managers.t_paths to reservation_users_administer;
+grant select on managers.t_paths to reservation_users_manager;
+grant select on managers.t_paths to reservation_users_auditor;
+grant select,usage on managers.s_paths_id to reservation_users_administer;
+grant usage on managers.s_paths_id to reservation_users;
+
+create index ci_paths_deleted_not on managers.t_paths (id)
+  where is_deleted is not true;
+
+create index ci_paths_private_not on managers.t_paths (id)
+  where is_deleted is not true and is_private is not true;
+
+create index ci_paths_locked_not on managers.t_paths (id)
+  where is_deleted is not true and is_locked is not true;
+
+create index ci_paths_public on managers.t_paths (id)
+  where is_deleted is not true and is_locked is not true and is_private is not true;
+
+create view users.v_paths with (security_barrier=true) as
+  with allowed_groups as (select id from users.v_groups_self)
+  select id, id_type, id_group, name_machine, name_human, is_private from managers.t_paths
+  where is_deleted is not true and (is_locked is not true or id_group in (select * from allowed_groups)) and (is_private is not true or (is_private is true and id_group in (select * from allowed_groups)));
+
+grant select on users.v_paths to reservation_users;
+
+create view public.v_paths with (security_barrier=true) as
+  select id, id_type, name_machine, name_human from managers.t_paths
+  where is_deleted is not true and is_locked is not true and is_private is not true;
+
+grant select on public.v_path_types to public_users;
+
 commit transaction;
index 24f3129b9320e4ff9949981c9097832463aadc7c..49279fd4b2322487b62832f8e0e72ed86f323803 100644 (file)
@@ -6,7 +6,7 @@ start transaction;
 
 /** Custom database specific settings (do this on every connection made) **/
 set bytea_output to hex;
-set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,drafters,users,public;
+set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,editors,drafters,requesters,users,public;
 set datestyle to us;
 
 
@@ -19,6 +19,7 @@ create table managers.t_request_types (
   name_machine varchar(128) not null,
   name_human varchar(256) not null,
 
+  is_locked boolean default false not null,
   is_deleted boolean default false not null,
 
   date_created timestamp default localtimestamp not null,
@@ -40,11 +41,17 @@ grant select on managers.t_request_types to reservation_users_auditor;
 grant select,usage on managers.s_request_types_id to reservation_users_administer;
 grant select,usage on managers.s_request_types_id to reservation_users_manager;
 
-create view users.v_request_types with (security_barrier=true) as
+create index ci_request_types_deleted_not on managers.t_request_types (id)
+  where is_deleted is not true;
+
+create index ci_request_types_public on managers.t_request_types (id)
+  where is_deleted is not true and is_locked is not true;
+
+create view requesters.v_request_types with (security_barrier=true) as
   select id, id_external, name_machine, name_human from managers.t_request_types
-  where is_deleted is false;
+  where is_deleted is not true and is_locked is not true;
 
-grant select on users.v_request_types to reservation_users;
+grant select on requesters.v_request_types to reservation_users_requester;
 
 /** @todo: consider creating default request types **/
 
@@ -53,12 +60,13 @@ grant select on users.v_request_types to reservation_users;
 /*** Requests ***/
 create table managers.t_requests (
   id bigint not null,
-  id_owner bigint not null,
   id_revision bigint not null,
   id_type bigint not null,
+  id_association bigint not null,
+  id_creator bigint not null,
 
   name_machine varchar(128) not null,
-  name_machine_owner varchar(128) not null,
+  name_machine_creator varchar(128) not null,
   name_human varchar(256) not null,
 
   is_approved boolean default false not null,
@@ -116,7 +124,7 @@ create table managers.t_requests (
   field_setup_round_tables_8ft public.ct_field_needed_with_total not null,
   field_setup_security public.ct_field_needed_with_details not null,
   field_setup_special_requests public.ct_field_needed_with_details not null,
-  field_setup_standard_blue_chairs public.ct_field_needed_with_total not null;
+  field_setup_standard_blue_chairs public.ct_field_needed_with_total not null,
   field_services_alcohol_served public.ct_field_served_with_caterer not null,
   field_services_food public.ct_field_served_with_caterer not null,
   field_services_open_flames public.ct_field_used_with_details not null,
@@ -129,9 +137,11 @@ create table managers.t_requests (
   constraint cu_requests_name_machine unique (name_machine),
 
   constraint cc_requests_id check (id > 0),
+  constraint cc_requests_approved check ((is_approved is true and is_denied is not true) or (is_approved is not true and is_denied is true)),
 
-  constraint cf_requests_id_owner foreign key (id_owner, name_machine_owner) references administers.t_users (id, name_machine) on delete restrict on update cascade,
-  constraint cf_requests_request_type foreign key (id_type) references managers.t_request_types (id) on delete restrict on update cascade
+  constraint cf_requests_id_creator foreign key (id_creator, name_machine_creator) references administers.t_users (id, name_machine) on delete restrict on update cascade,
+  constraint cf_requests_request_type foreign key (id_type) references managers.t_request_types (id) on delete restrict on update cascade,
+  constraint cf_requests_association foreign key (id_association) references managers.t_associations (id) on delete restrict on update cascade
 );
 
 create sequence managers.s_requests_id owned by managers.t_requests.id;
@@ -145,9 +155,43 @@ grant select,usage on managers.s_requests_id to reservation_users_manager;
 grant usage on managers.s_requests_id to reservation_users;
 
 
-/** @todo: create all appropriate views, including individual views for is_cancelled, is_deleted, is_published, is_unpublished, is_denied, and is_troubled **/
+/** @todo: create all appropriate views (and indexes), including individual views for is_cancelled, is_deleted, is_published, is_unpublished, is_denied, and is_troubled **/
+create index ci_requests_deleted_not on managers.t_requests (id)
+  where is_deleted is not true;
+
+create index ci_requests_approved on managers.t_requests (id)
+  where is_deleted is not true and is_cancelled is not true and is_approved is true;
+
+create index ci_requests_approved_cancelled on managers.t_requests (id)
+  where is_deleted is not true and is_cancelled is true and is_approved is true;
+
+
+/*** approved requests (but not cancelled) ***/
+create view users.v_requests_approved with (security_barrier=true) as
+  select id, id_revision, id_type, id_association, name_machine, name_human, is_troubled, date_created, date_changed, field_additional, field_dates, field_fees_custodial, field_fees_equipment, field_fees_facilities, field_fees_grounds, field_fees_maintenance, field_fees_other, field_fees_security, field_fees_university, field_location, field_information_attendance, field_information_organization, field_information_adviser_approval, field_insurance_affiliated, field_insurance_contractor, field_insurance_unaffiliated, field_plans_activities, field_plans_audience, field_plans_description, field_presentation_designing_material, field_presentation_external_audio_person, field_presentation_production, field_presentation_printed_material, field_presentation_publicity, field_presentation_technical_equipment, field_presentation_university_logo, field_registration_revenue, field_registration_phone, field_registration_required, field_registration_ticket_dates, field_registration_ticket_phone, field_registration_ticket_price, field_registration_ticket_website, field_registration_website, field_setup_other_tables, field_setup_parking_assistance, field_setup_podium, field_setup_portable_stage, field_setup_rectangular_tables_8ft, field_setup_road_closures, field_setup_round_tables_8ft, field_setup_security, field_setup_special_requests, field_setup_standard_blue_chairs, field_services_alcohol_served, field_services_food, field_services_open_flames, field_title, in_state, in_step from managers.t_requests
+    where is_deleted is not true and is_cancelled is not true and is_approved is true;
+
+grant select on users.v_requests_approved to reservation_users;
+
+
+/*** approved requests (only cancelled) ***/
+create view users.v_requests_approved_cancelled with (security_barrier=true) as
+  select id, id_revision, id_type, id_association, name_machine, name_human, is_troubled, date_created, date_changed, field_additional, field_dates, field_fees_custodial, field_fees_equipment, field_fees_facilities, field_fees_grounds, field_fees_maintenance, field_fees_other, field_fees_security, field_fees_university, field_location, field_information_attendance, field_information_organization, field_information_adviser_approval, field_insurance_affiliated, field_insurance_contractor, field_insurance_unaffiliated, field_plans_activities, field_plans_audience, field_plans_description, field_presentation_designing_material, field_presentation_external_audio_person, field_presentation_production, field_presentation_printed_material, field_presentation_publicity, field_presentation_technical_equipment, field_presentation_university_logo, field_registration_revenue, field_registration_phone, field_registration_required, field_registration_ticket_dates, field_registration_ticket_phone, field_registration_ticket_price, field_registration_ticket_website, field_registration_website, field_setup_other_tables, field_setup_parking_assistance, field_setup_podium, field_setup_portable_stage, field_setup_rectangular_tables_8ft, field_setup_road_closures, field_setup_round_tables_8ft, field_setup_security, field_setup_special_requests, field_setup_standard_blue_chairs, field_services_alcohol_served, field_services_food, field_services_open_flames, field_title, in_state, in_step from managers.t_requests
+    where is_deleted is not true and is_cancelled is true and is_approved is true;
+
+grant select on users.v_requests_approved to reservation_users;
+
+
+/*** requests the current user can manage (do determine this, the associations table is join and because it is already joined, add the additional fields provided by assocation). ***/
+/* @todo: review this to see if I can come up with a better way than doing an inner join on associations. */
+create view users.v_requests_self with (security_barrier=true) as
+  select r.id, r.id_revision, r.id_type, r.id_association, a.id_group, a.id_coordinator, r.name_machine, a.name_machine_coordinator, r.name_human, a.name_human as name_human_association, r.is_troubled, r.date_created, r.date_changed, r.field_additional, r.field_dates, r.field_fees_custodial, r.field_fees_equipment, r.field_fees_facilities, r.field_fees_grounds, r.field_fees_maintenance, r.field_fees_other, r.field_fees_security, r.field_fees_university, r.field_location, r.field_information_attendance, r.field_information_organization, r.field_information_adviser_approval, r.field_insurance_affiliated, r.field_insurance_contractor, r.field_insurance_unaffiliated, r.field_plans_activities, r.field_plans_audience, r.field_plans_description, r.field_presentation_designing_material, r.field_presentation_external_audio_person, r.field_presentation_production, r.field_presentation_printed_material, r.field_presentation_publicity, r.field_presentation_technical_equipment, r.field_presentation_university_logo, r.field_registration_revenue, r.field_registration_phone, r.field_registration_required, r.field_registration_ticket_dates, r.field_registration_ticket_phone, r.field_registration_ticket_price, r.field_registration_ticket_website, r.field_registration_website, r.field_setup_other_tables, r.field_setup_parking_assistance, r.field_setup_podium, r.field_setup_portable_stage, r.field_setup_rectangular_tables_8ft, r.field_setup_road_closures, r.field_setup_round_tables_8ft, r.field_setup_security, r.field_setup_special_requests, r.field_setup_standard_blue_chairs, r.field_services_alcohol_served, r.field_services_food, r.field_services_open_flames, r.field_title, a.field_affiliation, a.field_classification, r.in_state, r.in_step from managers.t_requests r
+    inner join managers.t_associations a on  r.id_association = a.id
+    where r.is_deleted is not true and a.is_deleted is not true and ((id_group is null and (a.name_machine_manager)::text = (current_user)::text) or a.id in (select id from users.v_associations_self));
+
+grant select on users.v_requests_self to reservation_users;
 
 
-/** @todo: create "managers.t_requests_revision" that is identical to "managers.t_requests" with all the columns allowed to be null.
+/** @todo: create "managers.t_requests_revision" that is identical to "managers.t_requests" with all the columns allowed to be null. **/
 
 commit transaction;
index 6b06ffb9a5dd58f81e1aa5a0944572ea100c9d0e..99a87791ea39776a3edecd77b4476b378c48aa8e 100644 (file)
@@ -6,7 +6,7 @@ start transaction;
 
 /** Custom database specific settings (do this on every connection made) **/
 set bytea_output to hex;
-set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,drafters,users,public;
+set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,editors,drafters,requesters,users,public;
 set datestyle to us;
 
 
index b68bb46c5a2d76d1470f15e2c59fb35a1d8a9839..4f7e1e64e936f7e256815a02c1eed408779e2c04 100644 (file)
@@ -6,7 +6,7 @@ start transaction;
 
 /** Custom database specific settings (do this on every connection made) **/
 set bytea_output to hex;
-set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,drafters,users,public;
+set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,editors,drafters,requesters,users,public;
 set datestyle to us;
 
 
@@ -62,9 +62,6 @@ create index ci_users_private_not on administers.t_users (id)
 create index ci_users_private_email_not on administers.t_users (id)
   where is_deleted is not true and is_private is not true and (address_email).private is not true;
 
-/** when using current_user reserved function/word the index gets ignored. To prevent this, create a manual/custom index and alter the behavior of the views to be more explicit. **/
-create unique index ci_users_current_user on administers.t_users (name_machine) with (fillfactor = 100);
-
 create index ci_users_id_sort_a on administers.t_users (id_sort) with (fillfactor = 100) where id_sort = 97;
 create index ci_users_id_sort_b on administers.t_users (id_sort) with (fillfactor = 100) where id_sort = 98;
 create index ci_users_id_sort_c on administers.t_users (id_sort) with (fillfactor = 100) where id_sort = 99;
@@ -227,6 +224,7 @@ grant select on administers.vm_users_date_synced_previous_year to reservation_us
 grant select on administers.vm_users_date_synced_previous_year to reservation_users_manager;
 
 
+
 /*** provide sequence id preservation table ***/
 create table administers.t_users_sequences (
   id bigint not null,
@@ -246,9 +244,6 @@ create table administers.t_users_sequences (
 grant select,insert,update,delete on administers.t_users_sequences to reservation_users_administer;
 grant select on administers.t_users_sequences to reservation_users_auditor;
 
-/** when using current_user reserved function/word the index gets ignored. To prevent this, create a manual/custom index and alter the behavior of the views to be more explicit. **/
-create unique index ci_users_sequences_current_user on administers.t_users_sequences (name_machine) with (fillfactor = 40);
-
 create view public.v_users_sequences_locked with (security_barrier=true) as
   select id, id_user, name_machine, is_locked, date_expire from administers.t_users_sequences
     where is_locked is true and date_expire >= current_timestamp and (name_machine)::text = (current_user)::text
index 4f487a8d6391f9e412441d9019946aba4b23b85c..e69f7466484fcc9c3ab6cea20bc377ae597a16e5 100644 (file)
@@ -34,10 +34,19 @@ The roles:
   - This role is intended for users who need to approve, deny, or otherwise be involved in some sort of workflow process.
   - It should be very common for projects to have a sub-set of reviewer access roles via tables.
 
+- editor:
+  - This role is intended for users who need to make changes (edit content).
+  - This role does not grant the access to create any content or make any requests.
+  - With the reservation system example. thos would be a request for a reservation.
+
 - drafter:
   - This role is intended for users who create content but are not allowed to publish that content.
   - This is primarily used for workflow.
 
+- requester:
+  - This role is intended for users who need to make a request.
+  - With the reservation system example. thos would be a request for a reservation.
+
 - (system)_users:
   - Replace (system) with the appropriate name for the system, generally the database name (for example, the reservation system, this would be reservation_users).
   - Provides basic access to the database, such as ldap integration.
diff --git a/examples/test.php b/examples/test.php
new file mode 100755 (executable)
index 0000000..b381058
--- /dev/null
@@ -0,0 +1,1122 @@
+<?php
+  // make sure the class files can be loaded (be sure to customize this as necessary).
+  set_include_path('/var/www/koopa');
+
+  require_once('common/base/classes/base_error.php');
+  require_once('common/base/classes/base_return.php');
+  require_once('common/base/classes/base_session.php');
+  require_once('common/base/classes/base_cookie.php');
+  require_once('common/base/classes/base_database.php');
+  require_once('common/base/classes/base_ldap.php');
+
+
+  function headers($stuff) {
+    if (isset($stuff['cookie_existence']['cookie'])) {
+      $stuff['cookie_existence']['cookie']->do_push();
+    }
+
+    if (isset($stuff['cookie_login']['cookie'])) {
+      $stuff['cookie_login']['cookie']->do_push();
+    }
+  }
+
+  function theme($stuff) {
+    print("<h1>Testing</h1>\n");
+    print("The following is a test of the database design and base database and cookied functionality.<br>");
+    print("<br>");
+
+    if (isset($_SERVER["HTTPS"])) {
+      print("1) You are using HTTPS.<br>");
+      print("<br>");
+    }
+    else {
+      print("1) You are not using HTTPS.<br>");
+      print("<br>");
+    }
+
+    print("2) _SERVER: <br>");
+    #foreach ($_SERVER as $key => $value) {
+    #  print(" - $key = " . print_r($value, TRUE) . "<br>");
+    #}
+    print(" - output disabled.<br>");
+    unset($key);
+    unset($value);
+    print("<br>");
+
+    // Useful _SERVER Variables:
+    //   REQUEST_TIME, REQUEST_TIME_FLOAT
+    //   HTTPS, HTTP_HOST
+    //   HTTP_USER_AGENT
+    //   HTTP_ACCEPT, HTTP_ACCEPT_LANGUAGE, HTTP_ACCEPT_ENCODING
+    //   HTTP_DNT
+    //   HTTP_CONNECTION, HTTP_CACHE_CONTRO
+    //   HTTP_AUTHORIZATION
+    //   protossl (which = 's' for https, and = '' for http)
+    //   SERVER_NAME, SERVER_ADDR, SERVER_PORT
+    //   REMOTE_ADDR, REMOTE_PORT
+    //   DOCUMENT_ROOT
+    //   REQUEST_SCHEME
+    //   CONTEXT_PREFIX, CONTEXT_DOCUMENT_ROOT
+    //   SERVER_PROTOCOL
+    //   REQUEST_METHOD, REQUEST_URI, SCRIPT_NAME
+    //   QUERY_STRING
+    //   QUERY_STRING
+
+    // running php from command line exposes user space environmental variables, such as:
+    // TERM, SHELL, USER, HOME, _
+
+    print("<h2>Cookie Test</h2>\n");
+    if (isset($stuff['cookie_existence']['new'])) {
+      print("3) A new existence cookie has been created.<br>");
+      print($stuff['cookie_existence']['new']);
+    }
+    elseif (isset($stuff['cookie_existence']['exists'])) {
+      print("3) The existence cookie has been loaded.<br>");
+      print($stuff['cookie_existence']['exists']);
+    }
+    else {
+      print("3) Disabled<br>");
+    }
+
+
+    print("<h2>Login, Session, and Database Connection Test</h2>\n");
+    if (isset($stuff['login']) && isset($_SERVER["HTTPS"])) {
+      print("4) Login<br>");
+      print($stuff['login']);
+    }
+    else {
+      print("4) Disabled<br>");
+    }
+
+
+    print("<h2>LDAP Test</h2>\n");
+    if (isset($stuff['ldap']) && isset($_SERVER["HTTPS"])) {
+      print("5) LDAP<br>");
+      if (isset($stuff['ldap']['markup'])) {
+        print($stuff['ldap']['markup']);
+      }
+    }
+    else {
+      print("5) Disabled<br>");
+    }
+
+
+    if (isset($stuff['resources'])) {
+      $difference_seconds = microtime(TRUE) - $stuff['resources']['time'];
+      $difference_milli = $difference_seconds * 1000;
+      $mu_1 = memory_get_usage(TRUE);
+      $mu_2 = memory_get_usage();
+      $mp_1 = memory_get_peak_usage(TRUE);
+      $mp_2 = memory_get_peak_usage();
+
+      print("<h2>Resources</h2>\n");
+      print("6) Time Taken: " . sprintf('%.10g', $difference_milli) . " milliseconds (" . sprintf('%.06g', $difference_seconds)  . " seconds).<br>");
+      print("7) Memory Usage (Real): " . $mu_1 . " bytes (" . sprintf('%.06g', $mu_1 / 1024 / 1024) . " megabytes).<br>");
+      print("8) Memory Usage (emalloc): " . $mu_2 . " bytes (" . sprintf('%.06g', $mu_2 / 1024 / 1024) . " megabytes)<br>");
+      print("9) Peak Memory Usage (Real): " . $mp_1 . " bytes (" . sprintf('%.06g', $mp_1 / 1024 / 1024) . " megabytes).<br>");
+      print("10) Peak Memory Usage (emalloc): " . $mp_2 . " bytes (" . sprintf('%.06g', $mp_2 / 1024 / 1024) . " megabytes).<br>");
+    }
+  }
+
+  function session(&$stuff) {
+    $database = new c_base_database();
+
+    $remote_address = '127.0.0.1';
+    if (!empty($_SERVER['REMOTE_ADDR'])) {
+      $remote_address = $_SERVER['REMOTE_ADDR'];
+    }
+
+    // cookie is used to determine whether or not the user is logged in.
+    $cookie = new c_base_cookie();
+    $cookie->set_name("test-logged_in-localhost");
+    $cookie->set_path('/');
+    $cookie->set_domain('.localhost');
+    $cookie->set_secure(TRUE);
+    $cookie->set_http_only(TRUE);
+    $cookie->set_first_only(TRUE);
+    $cookie->set_same_site(c_base_cookie::SAME_SITE_STRICT);
+
+    $logged_in = FALSE;
+    $failure = FALSE;
+
+    if ($cookie->do_pull() instanceof c_base_return_true) {
+      $data = $cookie->get_value_exact();
+
+      if ($cookie->validate() instanceof c_base_return_true && !empty($data['session_id'])) {
+        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['form_id'])) {
+          if ($_POST['form_id'] == 'logout_form') {
+            // delete the session.
+            $session = new c_base_session();
+            $session->set_socket_directory('/programs/sockets/sessionize_accounts/');
+            $session->set_system_name('reservation');
+            $session->set_host($remote_address);
+            $session->set_session_id($data['session_id']);
+
+            $result = $session->do_connect();
+            if ($result instanceof c_base_return_true) {
+              unset($connected);
+              $session->do_pull();
+
+              $name = $session->get_name()->get_value();
+              $password = $session->get_password()->get_value();
+              assign_database_string($database, $name, $password, $session);
+              unset($name);
+              unset($password);
+
+              $connected = connect_database($database);
+              if ($connected) {
+                set_log_user($database, 'logout');
+                $database->do_disconnect();
+              }
+              unset($connected);
+
+              $result = $session->do_terminate();
+              $session->do_disconnect();
+            }
+            unset($session);
+            unset($result);
+
+            // delete the cookie.
+            $cookie->set_expires(-1);
+            $cookie->set_max_age(-1);
+            $stuff['cookie_login']['cookie'] = $cookie;
+          }
+        }
+        else {
+          $session = new c_base_session();
+          $session->set_socket_directory('/programs/sockets/sessionize_accounts/');
+          $session->set_system_name('reservation');
+          $session->set_host($remote_address);
+          $session->set_session_id($data['session_id']);
+
+          $result = $session->do_connect();
+          $failure = c_base_return::s_has_error($result);
+          if (!$failure) {
+            $result = $session->do_pull();
+            $session->do_disconnect();
+
+            $connected = FALSE;
+            if ($result instanceof c_base_return_true) {
+              $name = $session->get_name()->get_value();
+              $password = $session->get_password()->get_value();
+              assign_database_string($database, $name, $password, $session);
+              unset($name);
+              unset($password);
+
+              $connected = connect_database($database);
+
+              if (!isset($stuff['login'])) {
+                $stuff['login'] = '';
+              }
+
+              if ($connected) {
+                $stuff['login'] .= 'Connected: success<br>' . "\n";
+              }
+              else {
+                $stuff['login'] .= 'Connected: failure<br>' . "\n";
+              }
+            }
+            unset($result);
+
+            if ($connected) {
+              // check to see if the session timeout has been extended and if so, then update the cookie.
+              $session_expire = $session->get_timeout_expire()->get_value_exact();
+              $session_seconds = $session_expire - time();
+              if ($session_seconds == 0) {
+                $session_seconds = -1;
+              }
+              if ($session_expire > $data['expire']) {
+                $data['expire'] = gmdate("D, d-M-Y H:i:s T", $session_expire);
+                $cookie->set_value($data);
+                $cookie->set_expires($session_expire);
+                $stuff['cookie_login']['cookie'] = $cookie;
+              }
+
+              if (!isset($stuff['login'])) {
+                $stuff['login'] = '';
+              }
+
+              $user_data = get_user_data($database, $session->get_name()->get_value_exact(), $ldap_data);
+
+              $stuff['login'] .= ' - You are logged in as: ' . $session->get_name()->get_value_exact() . '<br>' . "\n";
+              $stuff['login'] .= ' - Your user id is: ' . $session->get_id_user()->get_value_exact() . '<br>' . "\n";
+              #$stuff['login'] .= ' - Your password is: ' . $session->get_password()->get_value_exact() . '<br>' . "\n";
+              $stuff['login'] .= ' - You will be auto-logged out at: ' . $data['expire'] . '<br>' . "\n";
+              $stuff['login'] .= '<br>' . "\n";
+              $stuff['login'] .= 'Your user data is: <br>' . "\n";
+              $stuff['login'] .= print_r($user_data, TRUE) . "<br>";
+              $stuff['login'] .= '<br>' . "\n";
+              $logged_in = TRUE;
+
+              ldap($stuff, $session->get_name()->get_value_exact());
+              set_log_activity($database, $session->get_id_user()->get_value_exact());
+              get_database_data($database, $stuff, $session->get_id_user()->get_value_exact());
+
+              if ($session->get_id_user()->get_value_exact() > 0) {
+                $log = get_log_activity($database);
+                $table = build_log_activity_table($log);
+                $stuff['login'] .= "<br>" . $table . "<br>";
+
+                unset($log);
+                unset($table);
+              }
+
+              if ($session->get_id_user()->get_value_exact() > 0) {
+                $log = get_log_users($database);
+                $table = build_log_users_table($log);
+                $stuff['login'] .= "<br>" . $table . "<br>";
+
+                unset($log);
+                unset($table);
+              }
+            }
+            else {
+              if (!isset($stuff['login'])) {
+                $stuff['login'] = '';
+              }
+
+              $error = $session->get_error();
+              $stuff['login'] .= ' - Failed to load requested session, error: ' . print_r($error, TRUE) . "<br><br>";
+              unset($error);
+            }
+          }
+
+          unset($session);
+        }
+      }
+      unset($data);
+    }
+    else {
+      if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['form_id'])) {
+        if ($_POST['form_id'] == 'login_form' && !empty($_POST['login_name']) && isset($_POST['login_password'])) {
+          $connected = FALSE;
+          $session = new c_base_session();
+          $session->set_socket_directory('/programs/sockets/sessionize_accounts/');
+          $session->set_system_name('reservation');
+          $session->set_name($_POST['login_name']);
+          $session->set_host($remote_address);
+          $session->set_password($_POST['login_password']);
+
+          $user_data = array();
+          $account_exists = check_login_access($database, $_POST['login_name'], $_POST['login_password'], $session);
+          if (!$account_exists) {
+            $user_id = 1;
+            $session->set_name('public_user');
+            $session->set_password(NULL);
+            if (!isset($stuff['login'])) {
+              $stuff['login'] = '';
+            }
+            $stuff['login'] .= "DEBUG: does not exist and does not exist in ldap (falling back to the public account to access the database).<br>";
+
+            $database->set_session($session);
+            #$database->set_persistent(TRUE);
+            assign_database_string($database, 'public_user', NULL, $session);
+            $connected = connect_database($database);
+
+            if ($connected) {
+              set_log_user($database, 'login_failure', $_POST['login_name'], 403);
+
+              $stuff['login'] .= ' - Accessing database as: public_user' . '<br>' . "\n";
+              $stuff['login'] .= ' - Your user id is: 1 ' . '<br>' . "\n";
+              $stuff['login'] .= '<br>' . "\n";
+              $logged_in = TRUE;
+
+              set_log_activity($database, $user_id);
+            }
+          }
+          else {
+            if (!isset($stuff['login'])) {
+              $stuff['login'] = '';
+            }
+
+            $ldap_data = NULL;
+            ldap($stuff, $session->get_name()->get_value_exact());
+            if (!empty($stuff['ldap']['data'])) {
+              $ldap_data = $stuff['ldap']['data'];
+            }
+
+            $connected = TRUE;
+            $stuff['login'] .= "DEBUG: account already exists or exists in ldap.<br>";
+            $user_data = get_user_data($database, $_POST['login_name'], $ldap_data);
+            $user_id = $user_data['id_user'];
+            unset($user_data['id_user']);
+            unset($ldap_data);
+          }
+          $session->set_id_user($user_id);
+          $session->set_settings($user_data);
+
+          if (!$connected) {
+            $failure = TRUE;
+          }
+          else {
+            set_log_user($database, 'login');
+
+            $result = $session->do_connect();
+            $failure = c_base_return::s_has_error($result);
+          }
+
+          if (!$failure) {
+            $result = $session->do_push(600, 1800); // (10 minutes, 30 minutes)
+            $session->do_disconnect();
+
+            $session_expire = $session->get_timeout_expire()->get_value_exact();
+            $session_max = $session->get_timeout_max()->get_value_exact();
+            $expire_string = date("D, d M Y H:i:s T", $session_expire);
+            $cookie->set_expires($session_expire);
+            $cookie->set_max_age(NULL);
+
+            if ($result instanceof c_base_return_true) {
+              $data = array(
+                'session_id' => $session->get_session_id()->get_value_exact(),
+                'expire' => gmdate("D, d-M-Y H:i:s T", $session_expire), // unecessary, but provided for debug purposes.
+              );
+              $cookie->set_value($data);
+              $stuff['cookie_login']['cookie'] = $cookie;
+
+              if (!isset($stuff['login'])) {
+                $stuff['login'] = '';
+              }
+
+              $stuff['login'] .= ' - You are logged in as: ' . $session->get_name()->get_value_exact() . '<br>' . "\n";
+              $stuff['login'] .= ' - Your user id is: ' . $session->get_id_user()->get_value_exact() . '<br>' . "\n";
+              #$stuff['login'] .= ' - Your password is: ' . $session->get_password()->get_value_exact() . '<br>' . "\n";
+              $stuff['login'] .= ' - You will be auto-logged out at: ' . $expire_string . ' (' . $session_expire . ')' . '<br>' . "\n";
+              $stuff['login'] .= '<br>' . "\n";
+              $stuff['login'] .= 'Your user data is: <br>' . "\n";
+              $stuff['login'] .= print_r($user_data, TRUE) . "<br>";
+              $stuff['login'] .= '<br>' . "\n";
+              $logged_in = TRUE;
+
+              if (!isset($stuff['ldap']['markup'])) {
+                ldap($stuff, $session->get_name()->get_value_exact());
+              }
+
+              set_log_activity($database, $user_id);
+              get_database_data($database, $stuff, $user_id);
+
+              if ($session->get_id_user()->get_value_exact() > 0) {
+                $log = get_log_activity($database);
+                $table = build_log_activity_table($log);
+                $stuff['login'] .= "<br>" . $table . "<br>";
+
+                unset($log);
+                unset($table);
+              }
+
+              if ($session->get_id_user()->get_value_exact() > 0) {
+                $log = get_log_users($database);
+                $table = build_log_users_table($log);
+                $stuff['login'] .= "<br>" . $table . "<br>";
+
+                unset($log);
+                unset($table);
+              }
+
+              unset($user_id);
+              unset($user_data);
+            }
+            else {
+              if (!isset($stuff['login'])) {
+                $stuff['login'] = '';
+              }
+
+              $error = $session->get_error();
+              $stuff['login'] .= ' - failed to save requested session, error: ' . print_r($error, TRUE) . "<br>";
+              unset($error);
+            }
+          }
+
+          unset($session);
+        }
+      }
+    }
+    unset($cookie);
+
+    login_form($stuff, $logged_in);
+
+    $database->do_disconnect();
+    unset($database);
+  }
+
+  function login_form(&$stuff, $logged_in = FALSE) {
+    if (!isset($stuff['login'])) {
+      $stuff['login'] = '';
+    }
+
+    $stuff['login'] .= '<form id="login_form" name="login_form" method="post">' . "\n";
+
+    if ($logged_in) {
+      $stuff['login'] .= '  <input type="hidden" name="form_id" value="logout_form">' . "\n";
+      $stuff['login'] .= '  <input type="submit" value="Logout">' . "\n";
+    }
+    else {
+      $stuff['login'] .= '  <input type="hidden" name="form_id" value="login_form">' . "\n";
+      $stuff['login'] .= '  <input type="text" name="login_name">' . "\n";
+      $stuff['login'] .= '  <input type="password" name="login_password">' . "\n";
+      $stuff['login'] .= '  <input type="submit" value="Login">' . "\n";
+    }
+    $stuff['login'] .= '</form>' . "\n";
+    $stuff['login'] .= '<br>' . "\n";
+
+    #$stuff['login'] .= '_SERVER[REQUEST_METHOD]= ' . print_r($_SERVER["REQUEST_METHOD"], TRUE) . "<br>";
+    #$stuff['login'] .= '_GET = ' . print_r($_GET, TRUE) . "<br>";
+    #$stuff['login'] .= '_POST = ' . print_r($_POST, TRUE) . "<br>";
+    #$stuff['login'] .= '<br>' . "\n";
+  }
+
+  function get_database_data(&$database, &$stuff, $user_id) {
+    $stuff['login'] .= 'query: "select * from v_users;"<br>' . "\n";
+    $query_result = $database->do_query('select * from v_users');
+    if ($query_result instanceof c_base_database_result) {
+      $all = $query_result->fetch_all();
+      $stuff['login'] .= "<ol>";
+      foreach ($all->get_value_exact() as $row) {
+        $stuff['login'] .= "<li>";
+        foreach ($row as $column => $value) {
+          $stuff['login'] .= " '$column' = '$value'";
+        }
+        $stuff['login'] .= "</li>\n";
+        unset($column);
+        unset($value);
+      }
+      unset($row);
+      unset($row_number);
+    }
+    $stuff['login'] .= '</ol><br>' . "\n";
+
+    $stuff['login'] .= '<br>' . "\n";
+  }
+
+  function check_login_access(&$database, $username, $password, $session) {
+    if ($username == 'public_user') return FALSE;
+
+    $database->set_session($session);
+    assign_database_string($database, $username, $password, $session);
+
+    $connected = connect_database($database);
+    if ($connected) {
+      return TRUE;
+    }
+
+    // it is possible the user name might not exist, so try to create it.
+    $ensure_result = ensure_user_account($_POST['login_name']);
+
+    // try again now that the system has attempted to ensure the user account exists.
+    $connected = connect_database($database);
+    if ($connected) {
+      set_log_user($database, 'create_user');
+      return TRUE;
+    }
+
+    return FALSE;
+  }
+
+  function assign_database_string(&$database, $username, $password, $session) {
+    $database->set_session($session);
+
+    $connection_string = new c_base_connection_string();
+    $connection_string->set_host('127.0.0.1');
+    $connection_string->set_port(5095);
+    $connection_string->set_database('reservation');
+    $connection_string->set_user($username);
+    $connection_string->set_password($password);
+    $connection_string->set_ssl_mode('require');
+    $connection_string->set_connect_timeout(4);
+    $database->set_connection_string($connection_string);
+    unset($connection_string);
+  }
+
+  function connect_database(&$database) {
+    if (!($database->do_connect() instanceof c_base_return_true)) {
+      return FALSE;
+    }
+
+    $database->do_query('set bytea_output to hex;');
+    $database->do_query('set search_path to system,administers,managers,publishers,reviewers,drafters,users,public;');
+    $database->do_query('set datestyle to us;');
+
+    return TRUE;
+  }
+
+  function set_log_user(&$database, $type, $user_name = NULL, $response_code = 200) {
+    $query_string = '';
+    #$query_string .= 'insert into v_log_users_self_insert (id_user, name_machine_user, log_title, log_type, log_severity, log_details, request_client, response_code)';
+    #$query_string .= ' values (coalesce((select id from v_users_self), 1), coalesce((select name_machine_user from v_users_self), \'unknown\'), $1, $2, $3, $4, ($5, $6, $7), $8); ';
+    $query_string .= 'insert into v_log_users_self_insert (id_user, log_title, log_type, log_severity, log_details, request_client, response_code)';
+    $query_string .= ' values (coalesce((select id from v_users_self), 1), $1, $2, $3, $4, ($5, $6, $7), $8); ';
+
+    $query_parameters = array();
+    $query_parameters[4] = json_encode(NULL);
+    $query_parameters[5] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
+    $query_parameters[6] = isset($_SERVER['REMOTE_PORT']) ? $_SERVER['REMOTE_PORT'] : 0;
+    $query_parameters[7] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '' ; // @todo: test providing NULL.
+    $query_parameters[8] = $response_code;
+
+    if ($type == 'login' ) {
+      $query_parameters[1] = "Logging in to system.";
+      $query_parameters[2] = 17;
+      $query_parameters[3] = 1;
+    }
+    elseif ($type == 'logout' ) {
+      $query_parameters[1] = "Logging out of system.";
+      $query_parameters[2] = 18;
+      $query_parameters[3] = 1;
+    }
+    elseif ($type == 'create' ) {
+      $query_parameters[1] = "Created user account.";
+      $query_parameters[2] = 27;
+      $query_parameters[3] = 1;
+    }
+    elseif ($type == 'login_failure' ) {
+      $query_parameters[1] = "Failed to login as the user '" . $user_name . "'.";
+      $query_parameters[2] = 17;
+      $query_parameters[3] = 2;
+      $query_parameters[4] = json_encode(array('user_name' => $user_name));
+    }
+    else {
+      return FALSE;
+    }
+
+    ksort($query_parameters);
+
+    $query_result = $database->do_query($query_string, $query_parameters);
+    unset($query_string);
+    unset($query_parameters);
+
+    return TRUE;
+  }
+
+  function set_log_activity(&$database, $user_id, $response_code = 200) {
+    $connected = connect_database($database);
+
+    if (!isset($stuff['login'])) {
+      $stuff['login'] = '';
+    }
+
+    if ($connected) {
+      $stuff['login'] .= 'Connected: success<br>' . "\n";
+    }
+    else {
+      $stuff['login'] .= 'Connected: failure<br>' . "\n";
+    }
+
+    if ($connected) {
+      $name_machine_user = 'current_user';
+      if (!is_int($user_id) || $user_id == 1) {
+        $user_id = 1;
+        $name_machine_user = '\'unknown\'';
+      }
+
+      $query_string = '';
+      $query_string .= 'insert into v_log_activity_self_insert (id_user, name_machine_user, request_path, request_arguments, request_client, request_headers, response_headers, response_code) values ($1, ' . $name_machine_user . ', $2, $3, ($4, $5, $6), $7, $8, $9); ';
+
+      // @todo: populate headers.
+      $request_headers = json_encode(NULL);
+      $response_headers = json_encode(NULL);
+
+      $query_parameters = array();
+      $query_parameters[] = $user_id;
+      $query_parameters[] = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/';
+      $query_parameters[] = is_array($_GET) && !empty($_GET) ? print_r(array_keys($_GET), TRUE) : '';
+      $query_parameters[] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
+      $query_parameters[] = isset($_SERVER['REMOTE_PORT']) ? $_SERVER['REMOTE_PORT'] : 0;
+      $query_parameters[] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : NULL;
+      $query_parameters[] = $request_headers;
+      $query_parameters[] = $response_headers;
+      $query_parameters[] = $response_code;
+      unset($response_headers);
+      unset($request_headers);
+      unset($response_code);
+
+      // for debugging.
+      #print($query_string . '<br>');
+      #print_r($query_parameters);
+      #print('<br>');
+
+      $query_result = $database->do_query($query_string, $query_parameters);
+      unset($query_string);
+      unset($query_parameters);
+    }
+    else {
+      return FALSE;
+    }
+
+    return TRUE;
+  }
+
+  function get_user_data(&$database, $user_name, $ldap_data = NULL) {
+    $id_sort = (int) ord($user_name[0]);
+    $sort_string = ' where id_sort = ' . $id_sort;
+
+    $user_data = array(
+      'id_user' => NULL,
+      'id_sort' => $id_sort,
+    );
+    $query_result = $database->do_query('select id, id_external, name_human, address_email, is_private, is_locked, date_created, date_changed, settings from v_users_self' . $sort_string);
+    if ($query_result instanceof c_base_database_result) {
+      if ($query_result->number_of_rows()->get_value_exact() > 0) {
+        $result = $query_result->fetch_row();
+        if (!($result instanceof c_base_return_false)) {
+          $result_array = $result->get_value();
+          if (!empty($result_array)) {
+            $user_data['id_user'] = $result_array[0];
+            $user_data['id_external'] = $result_array[1];
+            $user_data['name_human'] = $result_array[2];
+            $user_data['address_email'] = $result_array[3];
+            $user_data['is_private'] = $result_array[4];
+            $user_data['is_locked'] = $result_array[5];
+            $user_data['date_created'] = $result_array[6];
+            $user_data['date_changed'] = $result_array[7];
+            $user_data['settings'] = json_decode($result_array[8], TRUE);
+          }
+        }
+      }
+    }
+
+    if (is_null($user_data['id_user'])) {
+      if (is_null($ldap_data)) {
+        $query_result = $database->do_query('insert into v_users_self_insert (id_sort, name_machine) values (' . $id_sort . ', user)');
+      }
+      else {
+        $email = explode('@', $ldap_data['mail']);
+        $parameters = array(
+          $ldap_data['givenname'],
+          $ldap_data['sn'],
+          $ldap_data['cn'],
+          $email[0],
+          $email[1],
+          $ldap_data['employeenumber'],
+        );
+        #$query_result = $database->do_query('insert into v_users_self_insert (id_sort, name_machine, name_human.first, name_human.last, name_human.complete, address_email.name, address_email.domain, address_email.private, id_external) values (' . $id_sort . ', user, $1, $2, $3, $4, $5, t, $6)', $parameters);
+        $query_result = $database->do_query('insert into v_users_self_insert (id_sort, name_machine, name_human.first, name_human.last, name_human.complete, address_email, id_external) values (' . $id_sort . ', user, $1, $2, $3, ($4, $5, TRUE), $6)', $parameters);
+      }
+
+      $user_data['id_user'] = 1;
+      $query_result = $database->do_query('select id, id_external, name_human, address_email, is_private, is_locked, date_created, date_changed, settings from v_users_self' . $sort_string);
+      if ($query_result instanceof c_base_database_result) {
+        if ($query_result->number_of_rows()->get_value_exact() > 0) {
+          $result = $query_result->fetch_row();
+          if (!($result instanceof c_base_return_false)) {
+            $result_array = $result->get_value();
+            $user_data['id_user'] = $result_array[0];
+            $user_data['id_external'] = $result_array[1];
+            $user_data['name_human'] = $result_array[2];
+            $user_data['address_email'] = $result_array[3];
+            $user_data['is_private'] = $result_array[4];
+            $user_data['is_locked'] = $result_array[5];
+            $user_data['date_created'] = $result_array[6];
+            $user_data['date_changed'] = $result_array[7];
+            $user_data['settings'] = json_decode($result_array[8], TRUE);
+          }
+        }
+      }
+    }
+
+    return $user_data;
+  }
+
+  function get_log_activity(&$database) {
+    $values = array();
+
+    $user_id = NULL;
+    $query_result = $database->do_query('select id, request_path, request_date, request_client, response_code from v_log_activity_self order by request_date desc limit 20;');
+    if ($query_result instanceof c_base_database_result) {
+     $total_rows = $query_result->number_of_rows()->get_value_exact();
+
+      if ($total_rows > 0) {
+        for ($i = 0; $i < $total_rows; $i++) {
+          $result = $query_result->fetch_row();
+          if (!($result instanceof c_base_return_false)) {
+            $values[$i] = $result->get_value();
+          }
+        }
+      }
+    }
+
+    return $values;
+  }
+
+  function get_log_users(&$database) {
+    $values = array();
+
+    $user_id = NULL;
+    $query_result = $database->do_query('select id, log_title, log_type, log_date, request_client, response_code from v_log_users_self order by log_date desc limit 10;');
+    if ($query_result instanceof c_base_database_result) {
+     $total_rows = $query_result->number_of_rows()->get_value_exact();
+
+      if ($total_rows > 0) {
+        for ($i = 0; $i < $total_rows; $i++) {
+          $result = $query_result->fetch_row();
+          if (!($result instanceof c_base_return_false)) {
+            $values[$i] = $result->get_value();
+          }
+        }
+      }
+    }
+
+    return $values;
+  }
+
+  function build_log_activity_table($activity) {
+    $table = '<table id="log_activity-history" border="1" width="100%" style="min-width: 600px; max-width: 1500px; margin-left: auto; margin-right: auto;">';
+    $table .= '<caption>Activity History (Latest 20 Entries)</caption>';
+    $table .= '<thead>';
+    $table .= '<tr>';
+    $table .= '<th>ID</th>';
+    $table .= '<th>Path</th>';
+    $table .= '<th>Date</th>';
+    $table .= '<th>Client</th>';
+    $table .= '<th>HTTP Code</th>';
+    $table .= '</tr>';
+    $table .= '</thead>';
+    $table .= '<tbody>';
+
+    $total = count($activity);
+    if ($total > 0) {
+      for ($i = 0; $i < $total; $i++) {
+        $table .= '<tr>';
+        $table .= '<td>' . $activity[$i][0] . '</td>';
+        $table .= '<td>' . $activity[$i][1] . '</td>';
+        $table .= '<td>' . $activity[$i][2] . '</td>';
+        $table .= '<td>' . $activity[$i][3] . '</td>';
+        $table .= '<td>' . $activity[$i][4] . '</td>';
+        $table .= '</tr>';
+      }
+      unset($i);
+    }
+    else {
+      $table .= '<tr><td colspan="5">No Entries Found</td></tr>';
+    }
+    unset($total);
+
+    $table .= '</tbody>';
+    $table .= '</table>';
+
+    return $table;
+  }
+
+  function build_log_users_table($activity) {
+    $table = '<table id="log_user-history" border="1" width="100%" style="min-width: 600px; max-width: 1500px; margin-left: auto; margin-right: auto;">';
+    $table .= '<caption>User History (Latest 10 Entries)</caption>';
+    $table .= '<thead>';
+    $table .= '<tr>';
+    $table .= '<th>ID</th>';
+    $table .= '<th>Title</th>';
+    $table .= '<th>Type</th>';
+    $table .= '<th>Date</th>';
+    $table .= '<th>Client</th>';
+    $table .= '<th>HTTP Code</th>';
+    $table .= '</tr>';
+    $table .= '</thead>';
+    $table .= '<tbody>';
+
+    $total = count($activity);
+    if ($total > 0) {
+      for ($i = 0; $i < $total; $i++) {
+        $table .= '<tr>';
+        $table .= '<td>' . $activity[$i][0] . '</td>';
+        $table .= '<td>' . $activity[$i][1] . '</td>';
+        $table .= '<td>' . $activity[$i][2] . '</td>';
+        $table .= '<td>' . $activity[$i][3] . '</td>';
+        $table .= '<td>' . $activity[$i][4] . '</td>';
+        $table .= '<td>' . $activity[$i][5] . '</td>';
+        $table .= '</tr>';
+      }
+      unset($i);
+    }
+    else {
+      $table .= '<tr><td colspan="6">No Entries Found</td></tr>';
+    }
+    unset($total);
+
+    $table .= '</tbody>';
+    $table .= '</table>';
+
+    return $table;
+  }
+
+  function ensure_user_account($user_name) {
+    $socket_path = "127.0.0.1";
+    $socket_family = AF_INET;
+    $socket_port = 5433;
+    $socket_protocol = SOL_TCP;
+
+    $socket_type = SOCK_STREAM;
+
+    $packet_size_target = 63;
+    $packet_size_client = 1;
+
+    $socket = socket_create($socket_family, $socket_type, $socket_protocol);
+    if ($socket === FALSE) {
+      socket_close($socket);
+      return FALSE;
+    }
+    unset($socket);
+
+    $connected = socket_connect($socket, $socket_path, $socket_port);
+    if ($connected === FALSE) {
+      socket_close($socket);
+      return FALSE;
+    }
+    unset($connected);
+
+    $name_length = strlen(trim($user_name));
+    $difference = $packet_size_target - $name_length;
+
+    if ($difference > 0) {
+      // the packet expects a packet to be NULL terminated or at most $packet_size_target.
+      $packet = pack('a' . $name_length . 'x' . $difference, trim($user_name));
+    }
+    else {
+      $packet = pack('a' . $name_length, $user_name);
+    }
+
+    $written = socket_write($socket, $packet, $packet_size_target);
+    if ($written === FALSE) {
+      socket_close($socket);
+      return FALSE;
+    }
+    unset($written);
+
+    $response = socket_read($socket, $packet_size_client);
+    socket_close($socket);
+    if (!is_string($response) || strlen($response) == 0) {
+      return FALSE;
+    }
+    unset($response);
+
+    // an integer is expected to be returned by the socket.
+    $response_packet = unpack('C', $response);
+    $response_value = (int) $response_packet[1];
+
+    // response codes as defined in the c source file:
+    //    0 = no problems detected.
+    //    1 = invalid user name, bad characters, or name too long.
+    //    2 = failed to connect to the ldap server and could not query the ldap name.
+    //    3 = user name not found in ldap database.
+    //    4 = failed to connect to the database.
+    //    5 = error returned while executing the SQL command.
+    //    6 = error occured while reading input from the user (such as via recv()).
+    //    7 = error occured while writing input from the user (such as via send()).
+    //    8 = the received packet is invalid, such as wrong length.
+    //   10 = connection timed out when reading or writing.
+    //   11 = the connection is being forced closed.
+    //   12 = the connection is closing because the service is quitting.
+    return $response_value;
+  }
+
+  function ldap(&$stuff, $username) {
+    $stuff['ldap']['markup'] = '';
+    $stuff['ldap']['data'] = array();
+
+    $ldap = new c_base_ldap();
+    $ldap->set_name('ldaps://127.0.0.1:1636/');
+    #$ldap->set_bind_name('');
+    #$ldap->set_bind_password('');
+    $connected = $ldap->do_connect();
+    if (c_base_return::s_has_error($connected)) {
+      $message = $ldap->get_error_message();
+      if ($message instanceof c_base_return_string) {
+        $message = $message->get_value();
+      }
+      else {
+        $message = NULL;
+      }
+
+      $stuff['ldap']['markup'] .= 'Connection Failed' . "<br>";
+      $stuff['ldap']['markup'] .= 'ERROR: ' . $message . "<br>";
+      unset($message);
+      return;
+    }
+
+    $base_dn = 'ou=users,ou=People';
+    $filter = '(uid=' . $username . ')';
+
+    $read = $ldap->do_search($base_dn, $filter, array('mail', 'gecos', 'givenname', 'cn', 'sn', 'employeenumber'));
+    if (c_base_return::s_has_error($read)) {
+      $message = $ldap->get_error_message();
+      if ($message instanceof c_base_return_string) {
+        $message = $message->get_value();
+      }
+      else {
+        $message = NULL;
+      }
+
+      $stuff['ldap']['markup'] .= 'ERROR: ' . $message . "<br>";
+      unset($message);
+
+      $ldap->do_disconnect();
+      return;
+    }
+
+    $entries = $read->get_entry_all();
+    if ($entries instanceof c_base_return_array) {
+      $entries = $entries->get_value();
+    }
+    else {
+      $entries = array();
+    }
+
+    if ($entries['count'] > 0) {
+      $entry = array(
+        'uid' => $username,
+        'mail' => $entries[0]['mail'][0],
+        'gecos' => $entries[0]['gecos'][0],
+        'givenname' => $entries[0]['givenname'][0],
+        'cn' => $entries[0]['cn'][0],
+        'sn' => $entries[0]['sn'][0],
+        'employeenumber' => $entries[0]['employeenumber'][0],
+      );
+      $stuff['ldap']['data'] = $entry;
+
+      $stuff['ldap']['markup'] .= "<ul>\n";
+      $stuff['ldap']['markup'] .= '<li>name: ' . $entry['uid'] . "</li>\n";
+      $stuff['ldap']['markup'] .= '<li>e-mail: ' . $entry['mail'] . "</li>\n";
+      $stuff['ldap']['markup'] .= '<li>gecos: ' . $entry['gecos'] . "</li>\n";
+      $stuff['ldap']['markup'] .= '<li>givenname: ' . $entry['givenname'] . "</li>\n";
+      $stuff['ldap']['markup'] .= '<li>cn: ' . $entry['cn'] . "</li>\n";
+      $stuff['ldap']['markup'] .= '<li>sn: ' . $entry['sn'] . "</li>\n";
+      $stuff['ldap']['markup'] .= '<li>employeenumber: ' . $entry['employeenumber'] . "</li>\n";
+      $stuff['ldap']['markup'] .= "</ul>\n";
+    }
+    else {
+      $stuff['ldap']['data'] = NULL;
+
+      $stuff['ldap']['markup'] .= "No LDAP entry found.\n";
+    }
+  }
+
+  function existence_cookie(&$stuff) {
+    $agent_string = 'unknown';
+    if (isset($_SERVER['HTTP_USER_AGENT'])) {
+      $agent_string = $_SERVER['HTTP_USER_AGENT'];
+    }
+
+
+    // create an existence cookie
+    $cookie = new c_base_cookie();
+    $cookie->set_name("test-cookie_existence-" . (isset($_SERVER["HTTPS"]) ? '-ssl' : '-no_ssl'));
+    $cookie->set_path('/');
+    $cookie->set_domain('.localhost');
+    $cookie->set_secure(isset($_SERVER["HTTPS"]));
+    $cookie->set_max_age(600);
+    $cookie->set_http_only(TRUE);
+    $cookie->set_first_only(TRUE);
+    $cookie->set_same_site(c_base_cookie::SAME_SITE_STRICT);
+
+    $result = $cookie->do_pull();
+    if ($result instanceof c_base_return_true) {
+      $data = $cookie->get_value_exact();
+
+      $same_site = '';
+      switch ($cookie->get_same_site()->get_value_exact()) {
+        case c_base_cookie::SAME_SITE_NONE:
+          $same_site = 'no restriction';
+          break;
+        case c_base_cookie::SAME_SITE_RELAXED:
+          $same_site = 'relaxed';
+          break;
+        case c_base_cookie::SAME_SITE_STRICT:
+          $same_site = 'strict';
+          break;
+      }
+
+      #$expire_string = date("D, d M Y H:i:s T", $cookie->get_expires()->get_value_exact());
+      #$max_age_string = date("D, d M Y H:i:s T", $cookie->get_max_age()->get_value_exact());
+      $max_age_string = $cookie->get_max_age()->get_value_exact();
+
+      $validated = "Invalid";
+      if ($cookie->validate() instanceof c_base_return_true) {
+        $validated = "Valid";
+      }
+
+      $stuff['cookie_existence'] = array('exists' => array());
+      $stuff['cookie_existence']['exists'] = " - The cookie settings:<br>";
+      $stuff['cookie_existence']['exists'] .= " -- Name: '" . $cookie->get_name()->get_value_exact() . "'<br>";
+      $stuff['cookie_existence']['exists'] .= " -- Domain: '" . $cookie->get_domain()->get_value_exact() . "'<br>";
+      $stuff['cookie_existence']['exists'] .= " -- Path: '" . $cookie->get_path()->get_value_exact() . "'<br>";
+      $stuff['cookie_existence']['exists'] .= " -- Value:<br>";
+      $stuff['cookie_existence']['exists'] .= " ---- Message: " . $data['message'] . "<br>";
+      $stuff['cookie_existence']['exists'] .= " ---- Expire: " . $data['expire'] . "<br>";
+      $stuff['cookie_existence']['exists'] .= " ---- Checksum: " . $data['checksum'] . "<br>";
+      $stuff['cookie_existence']['exists'] .= " ---- Checksum Validity: " . $validated . "<br>";
+      $stuff['cookie_existence']['exists'] .= " -- Max-Age: '" . $max_age_string . "'<br>";
+      #$stuff['cookie_existence']['exists'] .= " -- Expires: '" . $expire_string . "'<br>";
+      $stuff['cookie_existence']['exists'] .= " -- HTTP Only: '" . ($cookie->get_http_only()->get_value_exact() ? 'True' : 'False') . "'<br>";
+      $stuff['cookie_existence']['exists'] .= " -- First Only: '" . ($cookie->get_first_only()->get_value_exact() ? 'True' : 'False') . "'<br>";
+      $stuff['cookie_existence']['exists'] .= " -- Same Site: '" . $same_site . "'<br>";
+      $stuff['cookie_existence']['exists'] .= "<br>";
+
+      unset($data);
+      unset($validated);
+      unset($expire_string);
+      unset($max_age_string);
+      unset($same_site);
+    }
+    else {
+      $expire = '+10 minutes';
+      $expire_stamp = strtotime($expire);
+      $expire_string = date("D, d M Y H:i:s T", $expire_stamp);
+      $same_site = '';
+      switch ($cookie->get_same_site()->get_value_exact()) {
+        case c_base_cookie::SAME_SITE_NONE:
+          $same_site = 'no restriction';
+          break;
+        case c_base_cookie::SAME_SITE_RELAXED:
+          $same_site = 'relaxed';
+          break;
+        case c_base_cookie::SAME_SITE_STRICT:
+          $same_site = 'strict';
+          break;
+      }
+
+      #$max_age_string = date("D, d M Y H:i:s T", $cookie->get_max_age()->get_value_exact());
+      $max_age_string = $cookie->get_max_age()->get_value_exact();
+
+      $data = array(
+        'message' => "Your agent string is: " . $agent_string,
+        'expire' => gmdate("D, d-M-Y H:i:s T", $expire_stamp),
+      );
+      $cookie->set_value($data);
+      $cookie->set_expires($expire_stamp);
+      $checksum = $cookie->build_checksum()->get_value_exact();
+
+      $stuff['cookie_existence'] = array('new' => array());
+      $stuff['cookie_existence']['new'] = " - The following cookie should be generated:<br>";
+      $stuff['cookie_existence']['new'] .= " -- Name: '" . $cookie->get_name()->get_value_exact() . "'<br>";
+      $stuff['cookie_existence']['new'] .= " -- Domain: '" . $cookie->get_domain()->get_value_exact() . "'<br>";
+      $stuff['cookie_existence']['new'] .= " -- Path: '" . $cookie->get_path()->get_value_exact() . "'<br>";
+      $stuff['cookie_existence']['new'] .= " -- Value:<br>";
+      $stuff['cookie_existence']['new'] .= " ---- Message: " . $data['message'] . "<br>";
+      $stuff['cookie_existence']['new'] .= " ---- Expire: " . $data['expire'] . "<br>";
+      $stuff['cookie_existence']['new'] .= " ---- Checksum (expected): " . $checksum . "<br>";
+      $stuff['cookie_existence']['new'] .= " -- Max-Age: '" . $max_age_string . "'<br>";
+      $stuff['cookie_existence']['new'] .= " -- Expires: '" . $expire . "', or: '" . $expire_string . "'<br>";
+      $stuff['cookie_existence']['new'] .= " -- HTTP Only: '" . ($cookie->get_http_only()->get_value_exact() ? 'True' : 'False') . "'<br>";
+      $stuff['cookie_existence']['new'] .= " -- First Only: '" . ($cookie->get_first_only()->get_value_exact() ? 'True' : 'False') . "'<br>";
+      $stuff['cookie_existence']['new'] .= " -- Same Site: '" . $same_site . "'<br>";
+      $stuff['cookie_existence']['new'] .= "<br>";
+      $stuff['cookie_existence']['cookie'] = $cookie;
+
+      unset($data);
+      unset($checksum);
+      unset($expire);
+      unset($expire_string);
+      unset($expire_stamp);
+      unset($max_age_string);
+      unset($same_site);
+    }
+    unset($result);
+    unset($agent_string);
+  }
+
+  $stuff = array(
+    'resources' => array(
+      'time' => microtime(TRUE),
+     ),
+  );
+
+  existence_cookie($stuff);
+  session($stuff);
+  headers($stuff);
+  theme($stuff);
index d2588908fe05df5545f4ff2b5a2f0f8edeb37f21..0228b9e419625bce48a393eb62adc2c421a28687 100644 (file)
     $settings['cookie_name'] = 'reservation-session';
     $settings['cookie_path'] = '/';
     $settings['cookie_domain'] = '.localhost';
+    $settings['cookie_http_only'] = FALSE; // setting this to false will allow javascript to access this cookie, such as for ajax.
+    $settings['cookie_host_only'] = TRUE;
+    $settings['cookie_same_site'] = c_base_cookie::SAME_SITE_STRICT;
+    $settings['session_socket'] = '/program/sockets/sessionize_accounts/';
     $settings['session_system'] = 'reservation';
     $settings['session_expire'] = 600; // 10 minutes
     $settings['session_max'] = 1800; // 30 minutes
    *   System settings
    * @param c_base_session &$session
    *   Session information.
-   * @param c_base_cookie &$cookie_login
-   *   Session login cookie.
    */
-  function reservation_process_request(&$http, &$database, &$settings, &$session, &$cookie_login) {
+  function reservation_process_request(&$http, &$database, &$settings, &$session) {
     $html = new c_base_html();
 
 
 
 
     // assign base header tag
-    #$tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_BASE)->get_value_exact();
+    #$tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_BASE);
     #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_HREF, 'http://localhost/');
     #$html->set_header($tag);
     #unset($tag);
 
 
     // assign http-equiv header tag
-    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META);
     $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_HTTP_EQUIV, 'Content-Type');
     $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT, 'text/html; charset=utf-8');
     $html->set_header($tag);
 
 
     // assign charset header tag
-    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META);
     $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CHARACTER_SET, c_base_charset::UTF_8);
     $html->set_header($tag);
     unset($tag);
 
 
     // assign canonical header tag
-    #$tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    #$tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META);
     #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_REL, 'canonical');
     #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_HREF, 'http://localhost/');
     #$html->set_header($tag);
 
 
     // assign shortlink header tag
-    #$tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    #$tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META);
     #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_REL, 'shortlink');
     #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_HREF, '/');
     #$html->set_header($tag);
 
 
     // assign description header tag
-    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META);
     $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_NAME, 'description');
     $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT, 'A reservation/scheduling system.');
     $html->set_header($tag);
 
 
     // assign distribution header tag
-    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META);
     $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_NAME, 'distribution');
     $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT, 'web');
     $html->set_header($tag);
 
 
     // assign robots header tag
-    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META);
     $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_NAME, 'robots');
     $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT, 'INDEX,FOLLOW');
     $html->set_header($tag);
 
 
     // assign expires header tag
-    #$tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    #$tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META);
     #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_HTTP_EQUIV, 'expires');
     #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT, date('r', strtotime('+30 minutes')));
     #$html->set_header($tag);
 
 
     // assign viewport header tag
-    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META);
     $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_NAME, 'viewport');
     $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT, 'width=device-width, initial-scale=1');
     $html->set_header($tag);
     unset($tag);
 
-
-    // define any global css/javascript here as appropriate link/script c_base_markup_tag tag types.
-
-
     // finish building pages.
     if (!isset($_SERVER["HTTPS"])) {
-      reservation_build_page_require_https($html);
+      reservation_build_page_require_https($html, $settings, $session);
     }
-    elseif ($session === FALSE) {
-      // check to see if user has filled out the login form.
-      if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['form_id']) && $_POST['form_id'] == 'login_form') {
-        $problems = reservation_attempt_login($database, $settings, $session, $cookie_login);
-
-        if ($problems instanceof c_base_return_false) {
-          // @todo: render default page.
-          reservation_build_page_dashboard($html);
-          // @todo: process and handle different paths here and load page as requested.
+    elseif ($settings['database_user'] == 'public_user') {
+      // if the session cookie exists, but the user is still public_user, then the cookie is no longer valid.
+      if (empty($session->get_session_id()->get_value_exact())) {
+        // check to see if user has filled out the login form.
+        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['form_id']) && $_POST['form_id'] == 'login_form') {
+          $problems = reservation_attempt_login($database, $settings, $session);
+
+          if ($problems instanceof c_base_return_false) {
+            reservation_build_page_dashboard($html, $settings, $session);
+            // @todo: process and handle different paths here and load page as requested.
+          }
+          else {
+            // store the problems in the session object (because session as a subclass of c_base_return).
+            $session->set_problems($problems);
+
+            // @todo: render login failure.
+            reservation_process_path_public($html, $settings, $session);
+          }
+          unset($problems);
         }
         else {
-
-          // @todo: render login failure.
-          // $logged_in should be an array of error messages.
-          reservation_build_login_page($html, $problems->get_value());
+          reservation_process_path_public($html, $settings, $session);
         }
       }
       else {
-        reservation_build_login_page($html);
+        $cookie_login = $session->get_cookie();
+
+        // delete the cookie.
+        $cookie_login->set_expires(-1);
+        $cookie_login->set_max_age(-1);
+        $session->set_cookie($cookie_login);
+        unset($cookie_login);
+
+        reservation_process_path_public($html, $settings, $session);
       }
     }
     else {
-      reservation_build_page_dashboard($html);
-      // @todo: process and handle different paths here and load page as requested.
+      // load current database settings.
+      reservation_database_string($database, $settings);
+
+      // load current user roles
+      reservation_get_current_roles($database, $settings, $session); // @todo: handle returnr result errors.
+
+      if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['form_id'])) {
+        reservation_process_forms($html, $settings, $session);
+      }
+      else {
+        reservation_process_path($html, $settings, $session);
+      }
     }
 
-    return c_base_html_return::s_new($html);
+    return $html;
   }
 
   /**
   }
 
   /**
+   * Build the HTTP response.
+   *
+   * @param c_base_http &$http
+   *   Http object.
+   * @param c_base_session &$session
+   *   Session information.
+   * @param string $markup
+   *   The HTML markup.
+   */
+  function reservation_build_response(&$http, &$session, $markup) {
+    $http->set_response_content($markup);
+
+
+    // send the session cookie if a session id is specified.
+    $session_id = $session->get_session_id()->get_value_exact();
+    if (!empty($session_id)) {
+      $cookie_login = $session->get_cookie();
+
+      if ($cookie_login instanceof c_base_cookie) {
+        $http->set_response_set_cookie($cookie_login);
+      }
+      unset($cookie_login);
+    }
+    unset($session_id);
+
+    return new c_base_return_true();
+  }
+
+  /**
    * Main Program Function
    */
   function reservation_main() {
 
 
     // 3: process session information
-    $cookie_login = new c_base_cookie();
-    $session = reservation_process_sessions($settings, $cookie_login)->get_value_exact();
+    $session = reservation_process_sessions($http, $settings);
     gc_collect_cycles();
 
 
     // 4: perform actions, process work.
     $database = new c_base_database();
-    $html = reservation_process_request($http, $database, $settings, $session, $cookie_login)->get_value();
+    $html = reservation_process_request($http, $database, $settings, $session);
     if (!($html instanceof c_base_html)) {
       $html = new c_base_html();
     }
 
 
     // 6: build response information.
-    $http->set_response_content($markup);
-    $http->set_response_set_cookie($cookie_login);
+    reservation_build_response($http, $session, $markup);
     unset($markup);
-    unset($cookie_login);
     gc_collect_cycles();
 
 
index 185fc5b113ffde7d925077d21f89dcc6045031b9..4132a8058db78cfe3632411b65b5e6bc87409e07 100644 (file)
@@ -3,10 +3,11 @@
  * @file
  * Provides reservation database functions.
  */
-  #require_once('../../common/base/classes/base_error.php');
-  #require_once('../../common/base/classes/base_return.php');
-  #require_once('../../common/base/classes/base_session.php');
-  #require_once('../../common/base/classes/base_database.php');
+  require_once('common/base/classes/base_error.php');
+  require_once('common/base/classes/base_return.php');
+  require_once('common/base/classes/base_session.php');
+  require_once('common/base/classes/base_database.php');
+  require_once('common/base/classes/base_access.php');
 
   /**
    * Build the database connection string.
@@ -34,7 +35,7 @@
     $connection_string = new c_base_connection_string();
     $connection_string->set_host($settings['database_host']);
     $connection_string->set_port($settings['database_port']);
-    $connection_string->set_database_name($settings['database_name']);
+    $connection_string->set_database($settings['database_name']);
     $connection_string->set_user($settings['database_user']);
 
     if (!is_null($settings['database_password'])) {
@@ -74,7 +75,7 @@
 
     // configure default settings.
     $database->do_query('set bytea_output to hex;');
-    $database->do_query('set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,drafters,users,public;');
+    $database->do_query('set search_path to system,administers,managers,auditors,publishers,insurers,financers,reviewers,editors,drafters,requesters,users,public;');
     $database->do_query('set datestyle to us;');
 
     return new c_base_return_true();
       return c_base_return_error::s_false($error);
     }
 
+    $id_sort = (int) ord($user_name[0]);
+
     $user_data = array(
       'id_user' => NULL,
       'id_sort' => $id_sort,
     );
 
-    $id_sort = (int) ord($user_name[0]);
-
     $parameters = array(
       $id_sort,
       $user_name,
 
     return c_base_return_array::s_new($return_data);
   }
+
+  /**
+   * Get all roles assigned to the current user.
+   *
+   * @param c_base_database &$database
+   *   The database object.
+   * @param array &$settings
+   *   The system settings array.
+   * @param c_base_session &$session
+   *   The current session.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with error bit set is returned on error.
+   */
+  function reservation_get_current_roles($database, $settings, &$session) {
+    $connected = $database->is_connected();
+    if ($connected instanceof c_base_return_false) {
+      $connected = reservation_database_connect($database);
+    }
+
+    $roles = new c_base_roles();
+
+
+    // if there is no session, then assume that this is a public account.
+    if (empty($session->get_session_id()->get_value_exact())) {
+      $roles->set_role(c_base_roles::PUBLIC, TRUE);
+      $session->set_setting('roles', $roles);
+      unset($roles);
+
+      return new c_base_return_true();
+    }
+
+
+    // if unable to connect to database to retrieve other roles, just return the ppublic role.
+    if ($connected instanceof c_base_return_false) {
+      $roles->set_role(c_base_roles::PUBLIC, TRUE);
+      $session->set_setting('roles', $roles);
+      unset($roles);
+
+      $connection_string = $database->get_connection_string();
+      $database_name = ($connection_string instanceof c_base_connection_string) ? $connection_string->get_database()->get_value_exact() : '';
+      unset($connection_string);
+
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':database_name' => $database_name, ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::POSTGRESQL_NO_CONNECTION);
+      unset($database_name);
+
+      return c_base_return_error::s_false($error);
+    }
+    unset($connected);
+
+
+    // assign default roles.
+    $roles->set_role(c_base_roles::PUBLIC, FALSE);
+    $roles->set_role(c_base_roles::USER, TRUE);
+
+
+    // load all postgresql roles.
+    $result = $database->do_query('SELECT role_name FROM information_schema.enabled_roles');
+    if ($result instanceof c_base_database_result) {
+      $rows = $result->fetch_all()->get_value_exact();
+
+      foreach ($rows as $row) {
+        if (!array_key_exists('role_name', $row)) {
+          continue;
+        }
+
+        switch ($row['role_name']) {
+          case $settings['database_name'] . '_requester':
+            $roles->set_role(c_base_roles::REQUESTER, TRUE);
+            break;
+          case $settings['database_name'] . '_drafter':
+            $roles->set_role(c_base_roles::DRAFTER, TRUE);
+            break;
+          case $settings['database_name'] . '_editor':
+            $roles->set_role(c_base_roles::EDITOR, TRUE);
+            break;
+          case $settings['database_name'] . '_reviewer':
+            $roles->set_role(c_base_roles::REVIEWER, TRUE);
+            break;
+          case $settings['database_name'] . '_financer':
+            $roles->set_role(c_base_roles::FINANCER, TRUE);
+            break;
+          case $settings['database_name'] . '_insurer':
+            $roles->set_role(c_base_roles::INSURER, TRUE);
+            break;
+          case $settings['database_name'] . '_publisher':
+            $roles->set_role(c_base_roles::PUBLISHER, TRUE);
+            break;
+          case $settings['database_name'] . '_auditor':
+            $roles->set_role(c_base_roles::AUDITOR, TRUE);
+            break;
+          case $settings['database_name'] . '_manager':
+            $roles->set_role(c_base_roles::MANAGER, TRUE);
+            break;
+          case $settings['database_name'] . '_administer':
+            $roles->set_role(c_base_roles::ADMINISTER, TRUE);
+            break;
+        }
+      }
+      unset($row);
+      unset($rows);
+    }
+    unset($result);
+
+    $session->set_setting('roles', $roles);
+    unset($roles);
+
+    return new c_base_return_true();
+  }
index db09e627d774fb51ada6295ac86181bad8b38439..aa7ba2c114399abfdcd1294e13005589fe3917b7 100644 (file)
@@ -8,6 +8,7 @@
   require_once('common/base/classes/base_markup.php');
   require_once('common/base/classes/base_html.php');
   require_once('common/base/classes/base_charset.php');
+  require_once('common/base/classes/base_form.php');
 
   require_once('program/reservation/reservation_database.php');
   require_once('program/reservation/reservation_session.php');
  *
  * @param c_base_html &$html
  *   The html page object.
- * @param null|array $problems
- *   (optional) An array of problems to report when building the form.
- *   This is specified only after a form is submitted.
- *
- * @return c_base_html_return
- *   The markup tags object.
+ * @param array $settings
+ *   The system settings array.
+ * @param c_base_session &$session
+ *   The current session.
  */
-function reservation_build_login_page(&$html, $problems = NULL) {
+function reservation_build_login_page(&$html, $settings, $session) {
   $problem_fields = array();
   $problem_messages = array();
 
+  // @fixme: create a form problems array in session and use that.
+  $problems = $session->get_problems();
   if (is_array($problems)) {
     foreach ($problems as $problem) {
       if (!empty($problem['fields']) && is_array($problem['fields'])) {
@@ -43,16 +44,17 @@ function reservation_build_login_page(&$html, $problems = NULL) {
     }
     unset($problem);
   }
+  unset($problems);
 
   if (!empty($problem_messages)) {
-    $messages = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER, 'form_problems', array('form_problems'))->get_value_exact();
+    $messages = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER, 'form_problems', array('form_problems'));
     foreach ($problem_messages as $problem_delta => $problem_message) {
       $class = array(
         'form_problems-problem',
         'form_problems-problem-' . $problem_delta,
       );
 
-      $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER, 'form_problems-problem-' . $problem_delta, $class)->get_value_exact();
+      $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER, 'form_problems-problem-' . $problem_delta, $class);
       $tag->set_text($problem_message);
       unset($class);
 
@@ -68,28 +70,28 @@ function reservation_build_login_page(&$html, $problems = NULL) {
   unset($problem_messages);
 
   // login form
-  $form = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_FORM, 'login_form', array('login_form'))->get_value_exact();
+  $form = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_FORM, 'login_form', array('login_form'));
   $form->set_attribute(c_base_markup_attributes::ATTRIBUTE_METHOD, 'post');
   $form->set_attribute(c_base_markup_attributes::ATTRIBUTE_ROLE, 'form');
   $form->set_attribute(c_base_markup_attributes::ATTRIBUTE_ACCEPT_CHARACTER_SET, c_base_charset::UTF_8);
 
 
   // H1
-  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_H1)->get_value_exact();
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_H1);
   $tag->set_text('Login to System');
   $form->set_tag($tag);
   unset($tag);
 
 
   // hidden form data
-  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_HIDDEN, 'form_id', array('login_form-id'))->get_value_exact();
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_HIDDEN, 'form_id', array('login_form-id'));
   $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE, 'login_form');
   $form->set_tag($tag);
   unset($tag);
 
 
   // label: username
-  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_LABEL, NULL, array('login_form-label-username'))->get_value_exact();
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_LABEL, NULL, array('login_form-label-username'));
   $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_FOR, 'login_form-username');
   $tag->set_text('Username');
   $form->set_tag($tag);
@@ -104,7 +106,7 @@ function reservation_build_login_page(&$html, $problems = NULL) {
     $class[] = 'field_has_problem';
   }
 
-  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_TEXT, 'login_form-username', $class)->get_value_exact();
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_TEXT, 'login_form-username', $class);
   unset($class);
 
   $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_REQUIRED, TRUE);
@@ -113,7 +115,7 @@ function reservation_build_login_page(&$html, $problems = NULL) {
 
 
   // label: password
-  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_LABEL, NULL, array('login_form-label-password'))->get_value_exact();
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_LABEL, NULL, array('login_form-label-password'));
   $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_FOR, 'login_form-password');
   $tag->set_text('Password');
   $form->set_tag($tag);
@@ -128,7 +130,7 @@ function reservation_build_login_page(&$html, $problems = NULL) {
     $class[] = 'field_has_problem';
   }
 
-  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_PASSWORD, 'login_form-password', $class)->get_value_exact();
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_PASSWORD, 'login_form-password', $class);
   unset($class);
 
   $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_REQUIRED, TRUE);
@@ -137,14 +139,14 @@ function reservation_build_login_page(&$html, $problems = NULL) {
 
 
   // button: reset
-  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_RESET, 'login_form-reset', array('login_form-button-reset'))->get_value_exact();
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_RESET, 'login_form-reset', array('login_form-button-reset'));
   $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE, 'Reset');
   $form->set_tag($tag);
   unset($tag);
 
 
   // button: submit
-  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_SUBMIT, 'login_form-login', array('login_form-button-login'))->get_value_exact();
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_SUBMIT, 'login_form-login', array('login_form-button-login'));
   $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE, 'Login');
   $form->set_tag($tag);
   unset($tag);
@@ -163,36 +165,40 @@ function reservation_build_login_page(&$html, $problems = NULL) {
  *   The system settings array.
  * @param c_base_session &$session
  *   The current session.
- * @param c_base_cookie &$cookie_login
- *   Session login cookie.
  *
  * @return c_base_return_array|c_base_return_status
  *   FALSE on success.
  *   An array of problems on failure.
  *   FALSE with error bit set is returned on error.
  */
-function reservation_attempt_login(&$database, &$settings, &$session, &$cookie_login) {
+function reservation_attempt_login(&$database, &$settings, &$session) {
   $problems = array();
   if (empty($_POST['login_form-username'])) {
-    $problems[] = array(
-      'fields' => array('login_form-username'),
-      'messages' => 'No valid username has been supplied.',
-    );
+    $problem = new c_base_form_problem();
+    $problem->set_field('login_form-username');
+    $problem->set_value('No valid username has been supplied.');
+
+    $problems[] = $problem;
+    unset($problem);
   }
 
   if (empty($_POST['login_form-password'])) {
-    $problems[] = array(
-      'fields' => array('login_form-password'),
-      'messages' => 'No valid password has been supplied.',
-    );
+    $problem = new c_base_form_problem();
+    $problem->set_field('login_form-password');
+    $problem->set_value('No valid password has been supplied.');
+
+    $problems[] = $problem;
+    unset($problem);
   }
 
   // explicitly deny access to internal user accounts
   if ($_POST['login_form-username'] == 'public_user') {
-    $problems[] = array(
-      'fields' => array('login_form-username'),
-      'messages' => 'Unable to login, an incorrect user name or password has been specified.',
-    );
+    $problem = new c_base_form_problem();
+    $problem->set_field('login_form-username');
+    $problem->set_value('Unable to login, an incorrect user name or password has been specified.');
+
+    $problems[] = $problem;
+    unset($problem);
   }
 
   // return current list of problems before continuing to login attempt with credentials.
@@ -200,20 +206,6 @@ function reservation_attempt_login(&$database, &$settings, &$session, &$cookie_l
     return c_base_return_array::s_new($problems);
   }
 
-
-  // assign username and password to both session and database.
-  if (!($session instanceof c_base_session)) {
-    $session = new c_base_session();
-  }
-
-  if (empty($_SERVER['REMOTE_ADDR'])) {
-    $session->set_host('0.0.0.0');
-  }
-  else {
-    $session->set_host($_SERVER['REMOTE_ADDR']);
-  }
-
-  $session->set_system_name($settings['session_system']);
   $session->set_name($_POST['login_form-username']);
   $session->set_password($_POST['login_form-password']);
   $settings['database_user'] = $_POST['login_form-username'];
@@ -248,10 +240,12 @@ function reservation_attempt_login(&$database, &$settings, &$session, &$cookie_l
   }
 
   if ($connected instanceof c_base_return_false) {
-    $problems[] = array(
-      'fields' => array('login_form-username'),
-      'messages' => 'Unable to login, an incorrect user or password has been specified.',
-    );
+    $problem = new c_base_form_problem();
+    $problem->set_field('login_form-username');
+    $problem->set_value('Unable to login, an incorrect user or password has been specified.');
+
+    $problems[] = $problem;
+    unset($problem);
   }
   else {
     // @todo: add log entry.
@@ -263,7 +257,15 @@ function reservation_attempt_login(&$database, &$settings, &$session, &$cookie_l
 
     // the session needs to be opened and the data needs to be saved on successful login.
     $result = $session->do_connect();
-    if (!c_base_return::s_has_error($result)) {
+    if (c_base_return::s_has_error($result)) {
+      // @todo: process each error message.
+      $problem = new c_base_form_problem();
+      $problem->set_value('Failed to load session.');
+
+      $problems[] = $problem;
+      unset($problem);
+    }
+    else {
       $ldap = reservation_database_load_ldap_data($settings, $_POST['login_form-username'])->get_value();
       if ($ldap instanceof c_base_return_false || !is_array($ldap)) {
         $ldap = array(
@@ -273,6 +275,12 @@ function reservation_attempt_login(&$database, &$settings, &$session, &$cookie_l
 
       if (isset($ldap['status']) && $ldap['status'] instanceof c_base_return_false) {
         // @todo: handle error situation.
+        $problem = new c_base_form_problem();
+        $problem->set_field('login_form-username');
+        $problem->set_value('Failed to retrieve ldap information for specified user.');
+
+        $problems[] = $problem;
+        unset($problem);
       }
 
       $user_data = reservation_database_get_user_data($database, $_POST['login_form-username'], $ldap['data'])->get_value();
@@ -283,22 +291,29 @@ function reservation_attempt_login(&$database, &$settings, &$session, &$cookie_l
 
       // @todo: get and use user id from $user_data.
 
-      $result = $session->do_push($settings['session_expire'], $settings['session_max']);
+      $pushed = $session->do_push($settings['session_expire'], $settings['session_max']);
       $session->do_disconnect();
 
       $session_expire = $session->get_timeout_expire()->get_value_exact();
-      $cookie_login->set_expires($session_expire);
-      $cookie_login->set_max_age(NULL);
+      $cookie_login = $session->get_cookie();
 
-      if ($result instanceof c_base_return_true) {
-        $data = array(
-          'session_id' => $session->get_session_id()->get_value_exact(),
-          'expire' => gmdate("D, d-M-Y H:i:s T", $session_expire), // unecessary, but provided for debug purposes.
-        );
-        $cookie_login->set_data($data);
+      if ($cookie_login instanceof c_base_cookie) {
+        $cookie_login->set_expires($session_expire);
+        $cookie_login->set_max_age(NULL);
+
+        if ($pushed instanceof c_base_return_true) {
+          $data = array(
+            'session_id' => $session->get_session_id()->get_value_exact(),
+            'expire' => gmdate("D, d-M-Y H:i:s T", $session_expire), // unecessary, but provided for debug purposes.
+          );
+
+          $cookie_login->set_value($data);
+          $session->set_cookie($cookie_login);
+        }
       }
-      unset($result);
+      unset($cookie_login);
       unset($session_expire);
+      unset($pushed);
     }
     unset($result);
 
@@ -315,36 +330,162 @@ function reservation_attempt_login(&$database, &$settings, &$session, &$cookie_l
 
 /**
  * Build the HTTPS requirement page.
+ *
  * @param c_base_html &$html
  *   The html page object.
- *
- * @return c_base_html_return
- *   The markup tags object.
+ * @param array $settings
+ *   The system settings array.
+   * @param c_base_session &$session
+   *   The current session.
  */
-function reservation_build_page_require_https(&$html) {
-  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_H1)->get_value_exact();
+function reservation_build_page_require_https(&$html, $settings, &$session) {
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_H1);
   $tag->set_text('HTTPS Connection is Required');
   $html->set_tag($tag);
+  unset($tag);
 
-  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER)->get_value_exact();
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER);
   $tag->set_text('Please use a secure connection to access this website.');
   $html->set_tag($tag);
+  unset($tag);
 }
 
 /**
  * Build the dashboard page.
+ *
  * @param c_base_html &$html
  *   The html page object.
- *
- * @return c_base_html_return
- *   The markup tags object.
+ * @param array $settings
+ *   The system settings array.
+ * @param c_base_session &$session
+ *   The current session.
  */
-function reservation_build_page_dashboard(&$html) {
-  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_H1)->get_value_exact();
+function reservation_build_page_dashboard(&$html, $settings, &$session) {
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_H1);
   $tag->set_text('Dashboard');
   $html->set_tag($tag);
+  unset($tag);
 
-  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER)->get_value_exact();
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER);
   $tag->set_text('All links will go here.');
   $html->set_tag($tag);
+  unset($tag);
+
+  $roles = array();
+  $roles_object = $session->get_setting('roles');
+  if ($roles_object instanceof c_base_roles) {
+    $roles = $roles_object->get_roles()->get_value_exact();
+  }
+  unset($roles_object);
+
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER);
+  $tag->set_text('You are currently logged in as: ' . $settings['database_user']);
+  $html->set_tag($tag);
+  unset($tag);
+
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER);
+  $tag->set_text('You are currently assigned the following roles:');
+  $html->set_tag($tag);
+  unset($tag);
+
+  $tag_ul = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_UNORDERED_LIST);
+
+  foreach ($roles as $role) {
+    $tag_li = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_LIST_ITEM);
+
+    switch ($role) {
+      case c_base_roles::PUBLIC:
+        $tag_li->set_text('Public');
+        break;
+      case c_base_roles::USER:
+        $tag_li->set_text('User');
+        break;
+      case c_base_roles::REQUESTER:
+        $tag_li->set_text('Requester');
+        break;
+      case c_base_roles::DRAFTER:
+        $tag_li->set_text('Drafter');
+        break;
+      case c_base_roles::EDITOR:
+        $tag_li->set_text('Editor');
+        break;
+      case c_base_roles::REVIEWER:
+        $tag_li->set_text('Reviewer');
+        break;
+      case c_base_roles::FINANCER:
+        $tag_li->set_text('Financer');
+        break;
+      case c_base_roles::INSURER:
+        $tag_li->set_text('Insurer');
+        break;
+      case c_base_roles::PUBLISHER:
+        $tag_li->set_text('Publisher');
+        break;
+      case c_base_roles::AUDITOR:
+        $tag_li->set_text('Auditor');
+        break;
+      case c_base_roles::MANAGER:
+        $tag_li->set_text('Manager');
+        break;
+      case c_base_roles::ADMINISTER:
+        $tag_li->set_text('Administer');
+        break;
+    }
+
+    $tag_ul->set_tag($tag_li);
+    unset($tag_li);
+  }
+  unset($role);
+
+  $html->set_tag($tag_ul);
+}
+
+/**
+ * Process and build requested forms.
+ *
+ * @param c_base_html &$html
+ *   The html page object.
+ * @param array $settings
+ *   The system settings array.
+ * @param c_base_session &$session
+ *   The current session.
+ */
+function reservation_process_forms(&$html, $settings, &$session) {
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_H1);
+  $tag->set_text('Form Processing');
+  $html->set_tag($tag);
+  unset($tag);
+
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER);
+  $tag->set_text('This function is called to process specific forms.');
+  $html->set_tag($tag);
+  unset($tag);
+}
+
+/**
+ * Process request path and determine what to do.
+ *
+ * @param c_base_html &$html
+ *   The html page object.
+ * @param array $settings
+ *   The system settings array.
+ * @param c_base_session &$session
+ *   The current session.
+ */
+function reservation_process_path(&$html, $settings, &$session) {
+  reservation_build_page_dashboard($html, $settings, $session);
+}
+
+/**
+ * Process request path for public users and determine what to do.
+ *
+ * @param c_base_html &$html
+ *   The html page object.
+ * @param array $settings
+ *   The system settings array.
+ * @param c_base_session &$session
+ *   The current session.
+ */
+function reservation_process_path_public(&$html, $settings, &$session) {
+  reservation_build_login_page($html, $settings, $session);
 }
index afc9bb64ae782702a285e5a2abd51980c7e42e25..083d11200593e778912e79cddce2b3a951393bf0 100644 (file)
   /**
    * Process session information.
    *
+   * @param c_base_http &$http
+   *   Http object.
    * @param array &$settings
    *   System settings.
-   * @param c_base_cookie &$cookie_login
-   *   A login cookie object.
    *
-   * @param c_base_return_status|c_base_session
+   * @param c_base_session
    *   Session information is returned on success.
-   *   FALSE is returned when no session is defined.
-   *   FALSE with error bit set is returned on error.
+   *   Session information with error bit set is returned on error.
    */
-  function reservation_process_sessions(&$settings, &$cookie_login) {
+  function reservation_process_sessions(&$http, &$settings) {
+    $cookie_login = $http->get_request(c_base_http::REQUEST_COOKIE, $settings['cookie_name']);
+
+    $no_session = FALSE;
+    if (!($cookie_login instanceof c_base_cookie)) {
+      $cookie_login = new c_base_cookie();
+
+      $no_session = TRUE;
+    }
+
+    // create a session object regardless of login session cookie.
+    $session = new c_base_session();
+    $session->set_socket_directory($settings['session_socket']);
+    $session->set_system_name($settings['session_system']);
+
+    // the requester should not have any control over specifying/changing these settings, so overwrite whatever is defined by the request cookie.
     $cookie_login->set_name($settings['cookie_name']);
     $cookie_login->set_path($settings['cookie_path']);
     $cookie_login->set_domain($settings['cookie_domain']);
+    $cookie_login->set_http_only($settings['cookie_http_only']);
+    $cookie_login->set_host_only($settings['cookie_host_only']);
+    $cookie_login->set_same_site($settings['cookie_same_site']);
     $cookie_login->set_secure(TRUE);
 
-    $pulled = $cookie_login->do_pull();
-    if ($pulled instanceof c_base_return_true) {
-      $cookie_data = $cookie_login->get_data()->get_value_exact();
+    if (empty($_SERVER['REMOTE_ADDR'])) {
+      $session->set_host('0.0.0.0');
+    }
+    else {
+      $session->set_host($_SERVER['REMOTE_ADDR']);
+    }
 
-      if (!($cookie_login->validate() instanceof c_base_return_true) || empty($cookie_data['session_id'])) {
-        // cookie_login failed validation or the cookie contains no session id.
-        return new c_base_return_false();
-      }
+    // no session cookie has been defined, so there is no existing session to load.
+    if ($no_session) {
+      $session->set_cookie($cookie_login);
+      unset($cookie_login);
+      unset($no_session);
 
-      $session = new c_base_session();
-      $session->set_system_name($settings['session_system']);
-      $session->set_session_id($cookie_data['session_id']);
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':session_name' => $settings['cookie_name'], ':function_name' => __FUNCTION__)), i_base_error_messages::NO_SESSION);
+      $session->set_error($error);
+      unset($error);
 
-      if (empty($_SERVER['REMOTE_ADDR'])) {
-        $session->set_host('0.0.0.0');
-      }
-      else {
-        $session->set_host($_SERVER['REMOTE_ADDR']);
-      }
+      return $session;
+    }
+    unset($no_session);
 
-      $session_connection = $session->do_connect();
-      if (c_base_return::s_has_error($session_connection)) {
-        return $session_connection;
-      }
+    $cookie_data = $cookie_login->get_value_exact();
+    if (!($cookie_login->validate() instanceof c_base_return_true) || empty($cookie_data['session_id'])) {
+      $session->set_cookie($cookie_login);
+      unset($cookie_login);
 
-      $result = $session->do_pull();
-      $session->do_disconnect();
+      // cookie_login failed validation or the cookie contains no session id.
+      $error = c_base_error::s_log(NULL, array('arguments' => array(':session_name' => $settings['cookie_name'], ':function_name' => __FUNCTION__)), i_base_error_messages::SESSION_INVALID);
+      $session->set_error($error);
+      unset($error);
 
-      if ($result instanceof c_base_return_true) {
-        $user_name = $session->get_name()->get_value();
-        $password = $session->get_password()->get_value();
+      return $session;
+    }
 
-        if (is_string($user_name) && is_string($password)) {
-          $settings['database_user'] = $user_name;
-          $settings['database_password'] = $password;
-        }
-      }
+    $session->set_session_id($cookie_data['session_id']);
 
-      // check to see if the session timeout has been extended and if so, then update the cookie.
-      $session_expire = $session->get_timeout_expire()->get_value_exact();
-      $session_seconds = $session_expire - time();
-      if ($session_seconds == 0) {
-        $session_seconds = -1;
-      }
-      if ($session_expire > $cookie_data['expire']) {
-        $cookie_data['expire'] = gmdate("D, d-M-Y H:i:s T", $session_expire);
-        $cookie_login->set_data($value);
-        $cookie_login->set_expires($session_expire);
+
+    // connect to the session using the given session id.
+    $session_connection = $session->do_connect();
+    if (c_base_return::s_has_error($session_connection)) {
+      $session->set_cookie($cookie_login);
+      unset($cookie_login);
+
+      $session->set_error($session_connection->get_error());
+      unset($error);
+
+      return $session;
+    }
+
+    $result = $session->do_pull();
+    $session->do_disconnect();
+
+    if ($result instanceof c_base_return_true) {
+      $user_name = $session->get_name()->get_value();
+      $password = $session->get_password()->get_value();
+
+      if (is_string($user_name) && is_string($password)) {
+        $settings['database_user'] = $user_name;
+        $settings['database_password'] = $password;
       }
+    }
+
 
-      return c_base_session_return::s_new($session);
+    // check to see if the session timeout has been extended and if so, then update the cookie.
+    $session_expire = $session->get_timeout_expire()->get_value_exact();
+    $session_seconds = $session_expire - time();
+    if ($session_seconds == 0) {
+      $session_seconds = -1;
     }
 
-    return new c_base_return_false();
+    if ($session_expire > $cookie_data['expire']) {
+      $cookie_data['expire'] = gmdate("D, d-M-Y H:i:s T", $session_expire);
+      $cookie_login->set_value($cookie_data);
+      $cookie_login->set_expires($session_expire);
+    }
+
+    $session->set_cookie($cookie_login);
+    unset($cookie_login);
+
+    return $session;
   }
 
   /**
     }
     unset($written);
 
-    $response = socket_read($socket, $packet_size_client);
+    $response = @socket_read($socket, $packet_size_client);
     socket_close($socket);
     unset($socket);
     unset($packet_size_client);