code-igniter-v3-giggi: update release v1
diff --git a/application/config/config.php b/application/config/config.php
index 1031522..5e82e23 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -23,7 +23,7 @@
 | a PHP script and you can easily do that on your own.
 |
 */
-$config['base_url'] = '';
+$config['base_url'] = 'https://www.giggi.me/';
 
 /*
 |--------------------------------------------------------------------------
@@ -35,7 +35,7 @@
 | variable so that it is blank.
 |
 */
-$config['index_page'] = 'index.php';
+$config['index_page'] = '';
 
 /*
 |--------------------------------------------------------------------------
@@ -64,7 +64,7 @@
 |
 | https://codeigniter.com/user_guide/general/urls.html
 */
-$config['url_suffix'] = '';
+$config['url_suffix'] = '.html';
 
 /*
 |--------------------------------------------------------------------------
diff --git a/application/config/database.php b/application/config/database.php
index 0088ef1..01eb5b4 100644
--- a/application/config/database.php
+++ b/application/config/database.php
@@ -70,9 +70,31 @@
 | The $query_builder variables lets you determine whether or not to load
 | the query builder class.
 */
-$active_group = 'default';
+$active_group = 'dev';
 $query_builder = TRUE;
 
+$db['dev'] = array(
+	'dsn'	=> '',
+	'hostname' => getenv('MYSQL_HOSTNAME'),
+	'username' => getenv('MYSQL_USER'),
+	'password' => getenv('MYSQL_PASSWORD'),
+	'database' => getenv('MYSQL_DATABASE'),
+	'dbdriver' => 'mysqli',
+	'dbprefix' => '',
+	'pconnect' => FALSE,
+	'db_debug' => TRUE,
+	'cache_on' => FALSE,
+	'cachedir' => '',
+	'char_set' => 'utf8',
+	'dbcollat' => 'utf8_general_ci',
+	'swap_pre' => '',
+	'encrypt' => TRUE,
+	'compress' => FALSE,
+	'stricton' => FALSE,
+	'failover' => array(),
+	'save_queries' => TRUE
+);
+
 $db['default'] = array(
 	'dsn'	=> '',
 	'hostname' => 'localhost',
diff --git a/application/config/routes.php b/application/config/routes.php
index 1b45740..ec2e36c 100644
--- a/application/config/routes.php
+++ b/application/config/routes.php
@@ -49,6 +49,41 @@
 | Examples:	my-controller/index	-> my_controller/index
 |		my-controller/my-method	-> my_controller/my_method
 */
-$route['default_controller'] = 'welcome';
+/* Requested URI is empty - https://www.giggi.me */
+$route['default_controller'] = 'pelican/index';
+
+/* Requested URI is 'about' - https://www.giggi.me/about */
+$route['(^about$|page/about)'] = 'pelican/view/about';
+
+/* Requested URI is 'blog' - https://www.giggi.me/blog */
+$route['^blog$'] = 'pelican/view/blog';
+
+/* Requested URI is 'blog' - https://www.giggi.me/blog/foo.html */
+$route['^blog/(.+)'] = 'pelican/view/$1';
+
+/* Requested URI is 'category' - https://www.giggi.me/category/bar.html */
+$route['^category/(.+)'] = 'pelican/view/$1';
+
+/* Requested URI is 'ftp' - https://www.giggi.me/ftp */
+$route['(^ftp$|page/ftp)'] = 'pelican/view/ftp';
+
+/* Requested URI is 'git' - https://www.giggi.me/gerrit */
+$route['gerrit'] = 'pelican/view/index';
+
+/* Requested URI is 'git' - https://www.giggi.me/git */
+$route['(^git$|page/git)'] = 'pelican/view/git';
+
+/* Requested URI is 'home' - https://www.giggi.me/home */
+$route['home'] = 'pelican/index';
+
+/* Requested URI is 'invite' - https://www.giggi.me/invite */
+$route['(^invite$|page/invite)'] = 'invite/view/invite';
+
+/* Requested URI is 'login' - https://www.giggi.me/login */
+$route['(^login$|page/login)'] = 'login/view/login';
+
+/* Requested URI is 'mail' - https://www.giggi.me/mail */
+$route['(^mail$|page/mail)'] = 'pelican/view/mail';
+
 $route['404_override'] = '';
 $route['translate_uri_dashes'] = FALSE;
diff --git a/application/controllers/Invite.php b/application/controllers/Invite.php
new file mode 100644
index 0000000..9c98621
--- /dev/null
+++ b/application/controllers/Invite.php
@@ -0,0 +1,95 @@
+<?php
+
+class Invite extends CI_Controller {
+    private function is_valid_file($rel_path = '/', $file_html = 'home.html')
+    {
+        $abs_path = APPPATH.$rel_path.$file_html;
+        if (file_exists($abs_path))
+            return true;
+
+        return false;
+    }
+
+    private function is_post_invalid()
+    {
+        return !$this->form_validation->run();
+    }
+    
+	public function view($file_name = 'invite')
+	{
+        $file_html = $file_name.'.html';
+        if ($this->is_valid_file('views/page/', $file_html))
+        {
+            /* Got to open a connection here as validation may require one */
+            if (!$this->load->database())
+                redirect(base_url('index.html'));
+
+            $this->load->helper(array('form', 'url'));
+            $this->load->library('form_validation');
+
+            $this->form_validation->set_rules('username', 'Username',
+                'required|min_length[5]|max_length[12]|is_unique[users.username]',
+                array(
+                    'required' => 'You must provide a %s',
+                    'min_length' => '%s must be more than 5 chars',
+                    'max_length' => '%s must be less than 12 chars',
+                    'is_unique' => 'This %s already exists'
+                )
+            );
+
+            $this->form_validation->set_rules('password', 'Password', 'required',
+                array('required' => 'You must provide a %s')
+            );
+
+            $this->form_validation->set_rules('passconf', 'Password Confirmation',
+                'required|matches[password]',
+                array(
+                    'required' => 'You must provide a %s',
+                    'matches' => 'Passowrd confirmation didn\'t match'
+                )
+            );
+
+            $this->form_validation->set_rules('email', 'Email', 'required',
+                array('required' => 'You must provide a %s')
+            );
+
+            if ($this->is_post_invalid())
+            {
+                /* Validation errors already set */
+            }
+            else
+            {
+                /* Add backticks on ientifiers */
+                $this->db->protect_identifiers('users', TRUE);
+
+                /* Always use query bindings as they are automatically escaped */
+                $stmt = "INSERT INTO users (username, email, password) VALUES (?, ?, ?)";
+                $data = $this->input->post(array('username', 'email'));
+                $password = $this->input->post('password');
+                $hash_password = password_hash($password, PASSWORD_DEFAULT);
+                $data['password'] = $hash_password;
+
+                if (!$this->db->query($stmt, $data))
+                {
+                    /* Debug:
+                     *
+                     * $error = $this->db->error();
+                     * var_dump($error);
+                     */
+                    $this->form_validation->set_message('submit_msg', 'Didn\'t work, :|');
+                }
+                else
+                { 
+                    $this->form_validation->set_string('Invite succesfully sent');
+                }
+            }
+
+            $this->db->close();
+            $this->load->view('page/'.$file_html);
+        }
+        else 
+        {
+            redirect(base_url('index.html'));
+        }
+	}
+}
diff --git a/application/controllers/Login.php b/application/controllers/Login.php
new file mode 100644
index 0000000..91e1abe
--- /dev/null
+++ b/application/controllers/Login.php
@@ -0,0 +1,112 @@
+<?php
+
+class Login extends CI_Controller {
+    private function is_valid_file($rel_path = '/', $file_html = 'home.html')
+    {
+        $abs_path = APPPATH.$rel_path.$file_html;
+        if (file_exists($abs_path))
+            return true;
+
+        return false;
+    }
+
+    private function is_post_valid()
+    {
+        return $this->form_validation->run();
+    }
+
+    private function is_username_valid($username = NULL, $db_username = NULL)
+    {
+        if (!$username || !$db_username)
+            return false;
+
+        return !strcmp($username, $db_username);
+    }
+
+    private function is_password_valid($password = NULL, $db_password = NULL)
+    {
+        if (!$password || !$db_password)
+            return false;
+
+        return verify_password($password, $db_password);
+    }
+
+    private function is_login_valid($db_username = NULL, $db_password = NULL)
+    {
+        if (!$db_username || !$db_password)
+            return false;
+
+        $username = $this->input->post('username');
+        $password = $this->input->post('password');
+
+        if (!$this->is_username_valid($username, $db_username))
+            return false;
+
+        if (!$this->is_password_valid($password, $db_password))
+            return false;
+
+        return true;
+    }
+
+    public function view($file_name = 'login')
+    {
+        $file_html = $file_name.'.html';
+        if ($this->is_valid_file('views/page/', $file_html))
+        {
+            /* Got to open a connection here as validation may require one */
+            if (!$this->load->database())
+                redirect(base_url('index.html'));
+
+            $this->load->helper(array('form', 'url'));
+            $this->load->library('form_validation');
+
+            $this->form_validation->set_rules('username', 'Username', 'required',
+                array('required' => 'You must provide a %s')
+            );
+
+            $this->form_validation->set_rules('password', 'Password', 'required',
+                array('required' => 'You must provide a %s')
+            );
+
+            if ($this->is_post_valid())
+            {
+                /* Add backticks on ientifiers */
+                $this->db->protect_identifiers('users', TRUE);
+
+                /* Always use query bindings as they are automatically escaped */
+                $stmt = "SELECT FROM users (username, password)";
+                $data = $this->db->query($stmt, $data);
+
+                /* Return an array of row objects, empty array on failure */
+                $db_data = $data->result();
+                if ($db_data && $db_data[0])
+                {
+                    $db_username = $db_data[0]->username;
+                    $db_password = $db_data[0]->password;
+                    if (is_login_valid($db_username, $db_passowrd))
+                    {
+                        /* Initialize session data */
+                        $this->form_validation->set_string('Login successful');
+                    }
+                    else
+                    {
+                        /* Debug:
+                         *
+                         * $error = $this->db->error();
+                         * var_dump($error);
+                         */
+                        $this->form_validation->set_message('submit_msg', 'Didn\'t work, :|');
+                    }
+                }
+            }
+
+            /* Validation errors already set, if any */
+            $this->db->close();
+            $this->load->view('page/'.$file_html);
+        }
+        else
+        {
+            redirect(base_url('index.html'));
+        }
+    }
+}
diff --git a/application/controllers/Pelican.php b/application/controllers/Pelican.php
new file mode 100644
index 0000000..35eeb2d
--- /dev/null
+++ b/application/controllers/Pelican.php
@@ -0,0 +1,42 @@
+<?php
+
+class Pelican extends CI_Controller {
+    private function is_valid_file($rel_path = '/', $file_html = 'home.html')
+    {
+        $abs_path = APPPATH.$rel_path.$file_html;
+        if (file_exists($abs_path))
+            return true;
+
+        return false;
+    }
+
+    public function index()
+    {
+        $this->load->view('index.html');
+    }
+
+    public function view($file_name = 'home')
+    {
+        $file_html = $file_name.'.html';
+        if ($this->is_valid_file('views/blog/', $file_html))
+        {
+            $this->load->view('blog/'.$file_html);
+        }
+        else if ($this->is_valid_file('views/category/', $file_html))
+        {
+            $this->load->view('category/'.$file_html);
+        }
+        else if ($this->is_valid_file('views/page/', $file_html))
+        {
+            $this->load->view('page/'.$file_html);
+        }
+        else if ($this->is_valid_file('views/', $file_html))
+        {
+            $this->load->view($file_html);
+        }
+        else
+        {
+            $this->index();
+        }
+    }
+}
diff --git a/application/controllers/Welcome.php b/application/controllers/Welcome.php
deleted file mode 100644
index 9213c0c..0000000
--- a/application/controllers/Welcome.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-defined('BASEPATH') OR exit('No direct script access allowed');
-
-class Welcome extends CI_Controller {
-
-	/**
-	 * Index Page for this controller.
-	 *
-	 * Maps to the following URL
-	 * 		http://example.com/index.php/welcome
-	 *	- or -
-	 * 		http://example.com/index.php/welcome/index
-	 *	- or -
-	 * Since this controller is set as the default controller in
-	 * config/routes.php, it's displayed at http://example.com/
-	 *
-	 * So any other public methods not prefixed with an underscore will
-	 * map to /index.php/welcome/<method_name>
-	 * @see https://codeigniter.com/user_guide/general/urls.html
-	 */
-	public function index()
-	{
-		$this->load->view('welcome_message');
-	}
-}
diff --git a/application/views/index.html b/application/views/index.html
deleted file mode 100644
index b702fbc..0000000
--- a/application/views/index.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-	<title>403 Forbidden</title>
-</head>
-<body>
-
-<p>Directory access is forbidden.</p>
-
-</body>
-</html>
diff --git a/application/views/welcome_message.php b/application/views/welcome_message.php
deleted file mode 100644
index f511563..0000000
--- a/application/views/welcome_message.php
+++ /dev/null
@@ -1,89 +0,0 @@
-<?php
-defined('BASEPATH') OR exit('No direct script access allowed');
-?><!DOCTYPE html>
-<html lang="en">
-<head>
-	<meta charset="utf-8">
-	<title>Welcome to CodeIgniter</title>
-
-	<style type="text/css">
-
-	::selection { background-color: #E13300; color: white; }
-	::-moz-selection { background-color: #E13300; color: white; }
-
-	body {
-		background-color: #fff;
-		margin: 40px;
-		font: 13px/20px normal Helvetica, Arial, sans-serif;
-		color: #4F5155;
-	}
-
-	a {
-		color: #003399;
-		background-color: transparent;
-		font-weight: normal;
-	}
-
-	h1 {
-		color: #444;
-		background-color: transparent;
-		border-bottom: 1px solid #D0D0D0;
-		font-size: 19px;
-		font-weight: normal;
-		margin: 0 0 14px 0;
-		padding: 14px 15px 10px 15px;
-	}
-
-	code {
-		font-family: Consolas, Monaco, Courier New, Courier, monospace;
-		font-size: 12px;
-		background-color: #f9f9f9;
-		border: 1px solid #D0D0D0;
-		color: #002166;
-		display: block;
-		margin: 14px 0 14px 0;
-		padding: 12px 10px 12px 10px;
-	}
-
-	#body {
-		margin: 0 15px 0 15px;
-	}
-
-	p.footer {
-		text-align: right;
-		font-size: 11px;
-		border-top: 1px solid #D0D0D0;
-		line-height: 32px;
-		padding: 0 10px 0 10px;
-		margin: 20px 0 0 0;
-	}
-
-	#container {
-		margin: 10px;
-		border: 1px solid #D0D0D0;
-		box-shadow: 0 0 8px #D0D0D0;
-	}
-	</style>
-</head>
-<body>
-
-<div id="container">
-	<h1>Welcome to CodeIgniter!</h1>
-
-	<div id="body">
-		<p>The page you are looking at is being generated dynamically by CodeIgniter.</p>
-
-		<p>If you would like to edit this page you'll find it located at:</p>
-		<code>application/views/welcome_message.php</code>
-
-		<p>The corresponding controller for this page is found at:</p>
-		<code>application/controllers/Welcome.php</code>
-
-		<p>If you are exploring CodeIgniter for the very first time, you should start by reading the <a href="user_guide/">User Guide</a>.</p>
-	</div>
-
-	<p class="footer">Page rendered in <strong>{elapsed_time}</strong> seconds. <?php echo  (ENVIRONMENT === 'development') ?  'CodeIgniter Version <strong>' . CI_VERSION . '</strong>' : '' ?></p>
-</div>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/index.php b/index.php
index e505504..818d1cb 100755
--- a/index.php
+++ b/index.php
@@ -97,7 +97,7 @@
  * This variable must contain the name of your "system" directory.
  * Set the path if it is not in the same directory as this file.
  */
-	$system_path = 'system';
+	$system_path = '/var/www/system';
 
 /*
  *---------------------------------------------------------------
@@ -114,7 +114,7 @@
  *
  * NO TRAILING SLASH!
  */
-	$application_folder = 'application';
+	$application_folder = '/var/www/application';
 
 /*
  *---------------------------------------------------------------
diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php
index 5910d8e..726f9aa 100644
--- a/system/helpers/form_helper.php
+++ b/system/helpers/form_helper.php
@@ -901,6 +901,32 @@
 
 // ------------------------------------------------------------------------
 
+if ( ! function_exists('form_message'))
+{
+	/**
+	 * Form Message
+	 *
+	 * Returns the message for a specific form field. This is a helper for the
+	 * form validation class.
+	 *
+	 * @param	string
+	 * @param	string
+	 * @param	string
+	 * @return	string
+	 */
+	function form_message($field = '', $prefix = '', $suffix = '')
+	{
+		if (FALSE === ($OBJ =& _get_validation_object()))
+		{
+			return '';
+		}
+
+		return $OBJ->message($field, $prefix, $suffix);
+	}
+}
+
+// ------------------------------------------------------------------------
+
 if ( ! function_exists('validation_errors'))
 {
 	/**
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index 1bd5549..c068614 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -105,6 +105,27 @@
 	protected $error_string		= '';
 
 	/**
+	 * Start tag for message wrapping
+	 *
+	 * @var string
+	 */
+	protected $_message_prefix	= '<p>';
+
+	/**
+	 * End tag for message wrapping
+	 *
+	 * @var string
+	 */
+	protected $_message_suffix	= '</p>';
+
+	/**
+	 * Custom message
+	 *
+	 * @var string
+	 */
+	protected $message_string	= '';
+
+	/**
 	 * Whether the form data has been validated as safe
 	 *
 	 * @var bool
@@ -300,6 +321,24 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Set Message
+	 *
+	 * Lets users set their own messages on the fly. Note:
+	 * The key name has to match the function name that it corresponds to.
+	 *
+	 * @param	array
+	 * @param	string
+	 * @return	CI_Form_validation
+	 */
+	public function set_string($msg = '')
+	{
+		$this->message_string = $msg;
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Set The Error Delimiter
 	 *
 	 * Permits a prefix/suffix to be added to each error message
@@ -350,6 +389,35 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Get Message
+	 *
+	 * Gets the message associated with a particular field
+	 *
+	 * @param	string	$field	Field name
+	 * @param	string	$prefix	HTML start tag
+	 * @param 	string	$suffix	HTML end tag
+	 * @return	string
+	 */
+	public function message($field, $prefix = '', $suffix = '')
+	{
+        /* No class specific message field */
+
+		if ($prefix === '')
+		{
+			$prefix = $this->_message_prefix;
+		}
+
+		if ($suffix === '')
+		{
+			$suffix = $this->_message_suffix;
+		}
+
+		return $prefix.$this->message_string.$suffix;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Get Array of Error Messages
 	 *
 	 * Returns the error messages as an array