Page MenuHomeDevCentral

No OneTemporary

diff --git a/controllers/footer.php b/controllers/footer.php
new file mode 100644
index 0000000..1edb219
--- /dev/null
+++ b/controllers/footer.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * Footer
+ *
+ * @package Databases
+ * @subpackage Controllers
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2013 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @filesource
+ */
+
+///
+/// Version
+///
+
+$revision = substr(`git rev-list --reverse HEAD | nl | tail -n1 | awk '{print $2}'`, 0, 8);
+$build = 'r';
+$build .= trim(`git rev-list --reverse HEAD | nl | tail -n1 | awk '{print $1}'`);
+$version = "Git revision: $revision | Version: alpha preview (build $build)";
+
+
+///
+/// HTML output
+///
+$smarty->assign('version', $version);
+$smarty->display('footer.tpl');
+
+?>
diff --git a/controllers/header.php b/controllers/header.php
new file mode 100644
index 0000000..5ceb3b2
--- /dev/null
+++ b/controllers/header.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * Header
+ *
+ * (c) 2013, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * This controller handle the header (MOTD, html header)
+ *
+ * @package Zed
+ * @subpackage Controllers
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2013 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @filesource
+ *
+ * @todo cache MOTD fragments (sql performance)
+ */
+
+//
+// HTML output
+//
+
+//Prints the template
+$smarty->display('header.tpl');
+
+/**
+ * This constant indicates the header have been printed
+ */
+define('HEADER_PRINTED', true);
+
+?>
diff --git a/controllers/home.php b/controllers/home.php
new file mode 100644
index 0000000..2d2770b
--- /dev/null
+++ b/controllers/home.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * Homepage
+ *
+ * (c) 2013, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * This controller handle the / URL.
+ *
+ * @package Databases
+ * @subpackage Controllers
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2013 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @filesource
+ */
+
+//
+// Lists of database
+//
+$databases = Databases::getDatabases();
+
+//
+// HTML output
+//
+
+//Serves header
+$smarty->assign('PAGE_TITLE', lang_get('Welcome'));
+include('header.php');
+
+//Serves body
+$smarty->assign('databases', $databases);
+$smarty->display('home.tpl');
+
+//Serves footer
+$smarty->assign("screen", "Home console");
+include('footer.php');
+
+?>
diff --git a/css/NotInKnowledgeExtinction.css b/css/NotInKnowledgeExtinction.css
new file mode 100644
index 0000000..851438f
--- /dev/null
+++ b/css/NotInKnowledgeExtinction.css
@@ -0,0 +1,87 @@
+@charset "utf-8";
+
+/* -------------------------------------------------------------
+ Databases - Not into knowledge extinction
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ Author: Dereckson
+ Tags: orange gray black
+ Filename: NotInKnowledgeExtinction.css
+ Created: 2013-10-03
+ Licence: Creative Commons BY 3.0
+ ------------------------------------------------------------- */
+
+/* -------------------------------------------------------------
+ Fonts
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+@import url("http://openfontlibrary.org/face/benveno");
+
+
+/* -------------------------------------------------------------
+ Page
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+body {
+ margin: 0 0 0 0;
+ background-color: #F9F6EF;
+}
+
+/* -------------------------------------------------------------
+ Header
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+header {
+ background-color: black;
+ padding: 1em 0 0.25em 2em;
+}
+
+/* -------------------------------------------------------------
+ Footer
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+footer {
+ padding-top: 1em;
+ background-color: #E33005;
+}
+
+footer p {
+ font-size: 0.75em;
+}
+
+footer p strong {
+ color: white;
+}
+
+footer hr {
+ border: none;
+ height: 1px;
+ background-color: #CE2A06;
+}
+
+footer .sep {
+ border-right: 1px solid #CE2A06;
+}
+
+footer .copyright {
+ margin-top: 1em;
+ padding: 1em 0 0.25em 0;
+ background-image: url(../img/binding_dark.png);
+ color: white;
+}
+
+footer .copyright p {
+ color: #ccc;
+}
+
+/* -------------------------------------------------------------
+ Titles
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+h1, h2, h3, h4, h5, h6 {
+ font-weight: 400;
+ font-family: 'BonvenoCF';
+}
+
+h1 {
+ color: #E33005;
+}
diff --git a/img/Nasqueron.png b/img/Nasqueron.png
new file mode 100644
index 0000000..4b58be3
Binary files /dev/null and b/img/Nasqueron.png differ
diff --git a/includes/autoload.php b/includes/autoload.php
new file mode 100644
index 0000000..d186402
--- /dev/null
+++ b/includes/autoload.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * Autoloads classes
+ */
+spl_autoload_register(function ($className) {
+ //Classes
+ $classes['Database'] = './includes/databases/database.php';
+ $classes['Databases'] = './includes/databases/databases.php';
+
+ $classes['User'] = './includes/objects/user.php';
+
+ //Loader
+ if (array_key_exists($className, $classes)) {
+ require_once($classes[$className]);
+ }
+});
diff --git a/includes/config.php b/includes/config.php
new file mode 100755
index 0000000..44a54b1
--- /dev/null
+++ b/includes/config.php
@@ -0,0 +1,118 @@
+<?php
+
+/**
+ * Autogenerable configuration file
+ *
+ * (c) 2013, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * @package Databases
+ * @subpackage Keruald
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2013 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @filesource
+ */
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// I. SQL configuration ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+//SQL configuration
+$Config['sql']['product'] = 'MySQL'; //Only MySQL is currently implemented
+$Config['sql']['host'] = 'localhost';
+$Config['sql']['username'] = 'db51';
+$Config['sql']['password'] = 'databases51';
+$Config['sql']['database'] = 'db51';
+
+//SQL tables
+$prefix = '';
+define('TABLE_MOTD', $prefix . 'motd');
+define('TABLE_SESSIONS', $prefix . 'sessions');
+define('TABLE_USERS', $prefix . 'users');
+define('TABLE_USERS_AUTH', $prefix . 'users_auth');
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// II. Site configuration ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+//Default theme
+$Config['DefaultTheme'] = "NotInKnowledgeExtinction";
+
+//Dates
+date_default_timezone_set("UTC");
+
+//Secret key, used for some verification hashes in URLs or forms.
+$Config['SecretKey'] = 'Lorem ipsum dolor';
+
+//When reading files, buffer size
+define('BUFFER_SIZE', 4096);
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// III. Script URLs ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+$Config['SiteURL'] = get_server_url();
+$Config['BaseURL'] = '';
+
+//AJAX callbacks URL
+$Config['DoURL'] = $Config['SiteURL'] . "/do.php";
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// IV. Static content ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+//Where the static content is located?
+//Static content = 4 directories: js, css, img and content
+//On default installation, those directories are at site root.
+//To improve site performance, you can use a CDN for that.
+//
+//Recommanded setting: $Config['StaticContentURL'] = $Config['SiteURL'];
+//Or if Zed is the site root: $Config['StaticContentURL'] = '';
+//With CoralCDN: $Config['StaticContentURL'] = . '.nyud.net';
+//
+$Config['StaticContentURL'] = '';
+//$Config['StaticContentURL'] = get_server_url() . '.nyud.net';
+
+//ImageMagick paths
+//Be careful on Windows platform convert could match the NTFS convert command.
+$Config['ImageMagick']['convert'] = 'convert';
+$Config['ImageMagick']['mogrify'] = 'mogrify';
+$Config['ImageMagick']['composite'] = 'composite';
+$Config['ImageMagick']['identify'] = 'identify';
+
+//Databases
+define('DATABASES_DIR', 'data');
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// V. Caching ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Some data (Smarty, OpenID and sessions) are cached in the cache directory.
+ *
+ * Security tip: you can move this cache directory outside the webserver tree.
+ */
+define('CACHE_DIR', 'cache');
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// VI. Sessions and authentication code ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+//If you want to use a common table of sessions / user handling
+//with several websites, specify a different resource id for each site.
+$Config['ResourceID'] = 24;
+
+?>
diff --git a/includes/core.php b/includes/core.php
new file mode 100755
index 0000000..e9c30b3
--- /dev/null
+++ b/includes/core.php
@@ -0,0 +1,641 @@
+<?php
+
+/**
+ * Core: helper methods and main libraries loader
+ *
+ * (c) 2013, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * @package Databases
+ * @subpackage Keruald
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2013 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @version 0.1
+ * @link http://scherzo.dereckson.be/doc/zed
+ * @link http://zed.dereckson.be/
+ * @filesource
+ */
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// Configures PHP and loads site-wide used libraries ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+//No register globals
+ini_set('register_globals', 'off');
+error_reporting(E_ALL & ~E_NOTICE);
+
+//Load libraries
+include_once("config.php"); //Site config
+include_once("error.php"); //Error management
+include_once("mysql.php"); //MySQL layer
+include_once("sessions.php"); //Sessions handler
+include_once("autoload.php"); //__autoload()
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// Information helper methods ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Gets the nickname from the specified user ID
+ *
+ * @param integer $user_id The specified user ID
+ * @return string The perso's nickname
+ */
+function get_name ($user_id) {
+ global $db;
+ $user_id = $db->sql_escape($user_id);
+ $sql = 'SELECT username FROM '. TABLE_USERS . " WHERE user_id = '$user_id'";
+ if (!$result = $db->sql_query($sql)) message_die(SQL_ERROR, "Can't query users table.", '', __LINE__, __FILE__, $sql);
+ $row = $db->sql_fetchrow($result);
+ return $row['username'];
+}
+
+/**
+ * Gets the user ID from the specified username
+ *
+ * @param string $username The username
+ * @return integer the user ID
+ */
+function get_userid ($username) {
+ global $db;
+ $username = $db->sql_escape($username);
+ $sql = 'SELECT user_id FROM '. TABLE_USERS . " WHERE username LIKE '$username'";
+ if (!$result = $db->sql_query($sql)) message_die(SQL_ERROR, "Can't query users table.", '', __LINE__, __FILE__, $sql);
+ $row = $db->sql_fetchrow($result);
+ return $row['user_id'];
+}
+
+/**
+ * Gets an information from the application global registry
+ *
+ * @param string $key the registry's key
+ * @return string The key value
+ */
+function registry_get ($key) {
+ global $db;
+ $key = $db->sql_escape($key);
+ $sql = "SELECT registry_value FROM " . TABLE_REGISTRY . " WHERE registry_key = '$key'";
+ if (!$result = $db->sql_query($sql)) message_die(SQL_ERROR, "Can't read registry.", '', __LINE__, __FILE__, $sql);
+
+ $row = $db->sql_fetchrow($result);
+ return $row['registry_value'];
+}
+
+/**
+ * Sets an information in the application global registry
+ *
+ * @param string $key the registry key
+ * @param string $value the value to store at the specified registry key
+ */
+function registry_set ($key, $value) {
+ global $db;
+ $key = $db->sql_escape($key);
+ $value = $db->sql_escape($value);
+ $sql = "REPLACE INTO " . TABLE_REGISTRY . " (registry_key, registry_value) VALUES ('$key', '$value')";
+ if (!$db->sql_query($sql))
+ message_die(SQL_ERROR, "Can't update registry", '', __LINE__, __FILE__, $sql);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// Misc helper methods ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Generates a random string, according the specified format.
+ *
+ * <code>
+ * echo generate_random_string('AAA111'); //this could output SDQ245.
+ * </code>
+ *
+ * @author Pierre Habart <p.habart@ifrance.com>
+ *
+ * @param string $format The format e.g. AAA111
+ * @return string a random string
+ */
+function generate_random_string ($format) {
+ mt_srand((double)microtime()*1000000);
+ $str_to_return="";
+
+ $t_alphabet=explode(",","A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z");
+ $t_number=explode(",","1,2,3,4,5,6,7,8,9,0");
+
+ for ($i=0;$i<strlen($format);$i++)
+ {
+ if (preg_match("/^[a-zA-Z]/",$format[$i]))
+ {
+ $add=$t_alphabet[mt_rand() % sizeof($t_alphabet)];
+ if (preg_match("/^[a-z]/",$format[$i]))
+ $add=strtolower($add);
+ }
+ elseif(preg_match("/^[0-9]/",$format[$i]))
+ $add=$t_number[mt_rand() % sizeof($t_number)];
+ else $add="?";
+
+ $str_to_return.=$add;
+ }
+ return $str_to_return;
+}
+
+//Plural management
+
+/**
+ * Returns "s" when the $amount request a plural
+ * This function is a French plural helper.
+ *
+ * @param $amount the amount of objects
+ * @return string 's' if $amount implies a plural ; '' if it implies a singular.
+ */
+function s ($amount) {
+ if ($amount >= 2 || $amount <= -2) return "s";
+}
+
+/**
+ * Returns "x" when the $amount request a plural
+ * This function is a French plural helper.
+ *
+ * @param $amount the amount of objects
+ * @return string 'x' if $amount implies a plural ; '' if it implies a singular.
+ */
+function x ($amount) {
+ if ($amount >= 2 || $amount <= -2) return "x";
+}
+
+//Debug
+
+/**
+ * Prints human-readable information about a variable.
+ *
+ * It behaves like the print_r command, but the output is enclosed in pre tags,
+ * to have a preformatted HTML output.
+ *
+ * @param mixed The expression to be printed
+ */
+function dprint_r ($expression) {
+ echo '<pre>';
+ print_r($expression);
+ echo '</pre>';
+}
+
+//GUID
+
+/**
+ * Generates a GUID, or more precisely an UUID
+ * @link http://en.wikipedia.org/wiki/Universally_Unique_Identifier Wikipedia, Universally Unique Identifier.
+ *
+ * A UUID is a 36 chars string of 32 hexadecimal and 4 dashes, with a
+ * very high probability to be unique.
+ *
+ * @return string the UUID
+ */
+function new_guid() {
+ $characters = explode(",","a,b,c,d,e,f,0,1,2,3,4,5,6,7,8,9");
+ $guid = "";
+ for ($i = 0 ; $i < 36 ; $i++) {
+ if ($i == 8 || $i == 13 || $i == 18 || $i == 23) {
+ $guid .= "-";
+ } else {
+ $guid .= $characters[mt_rand() % sizeof($characters)];
+ }
+ }
+ return $guid;
+}
+
+/**
+ * Determines if the expression is a valid UUID (a guid without {}).
+ * @see new_guid
+ *
+ * @param string $expression the expression to chjeck
+ * @return boolean true if the specified expression is a valid UUID ; otherwise, false.
+ */
+function is_guid ($expression) {
+ //We avoid regexp to speed up the check
+ //A guid is a 36 characters string
+ if (strlen($expression) != 36) return false;
+
+ $expression = strtolower($expression);
+ for ($i = 0 ; $i < 36 ; $i++) {
+ if ($i == 8 || $i == 13 || $i == 18 || $i == 23) {
+ //with dashes
+ if ($expression[$i] != "-") return false;
+ } else {
+ //and numbers
+ if (!is_numeric($expression[$i]) && $expression[$i] != 'a' && $expression[$i] != 'b' && $expression[$i] != 'c' && $expression[$i] != 'd' && $expression[$i] != 'e' && $expression[$i] != 'f' ) return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * Gets file extension
+ *
+ * @param string $file the file to get the extension
+ * @return string the extension froùm the specified tfile
+ */
+function get_extension ($file) {
+ $dotPosition = strrpos($file, ".");
+ return substr($file, $dotPosition + 1);
+}
+
+/**
+ * Determines if a string starts with specified substring
+ *
+ * @param string $haystack the string to check
+ * @param string $needle the substring to determines if it's the start
+ * @param boolean $case_sensitive determines if the search must be case sensitive
+ * @return boolean true if $haystack starts with $needle ; otherwise, false.
+ */
+function string_starts_with ($haystack, $needle, $case_sensitive = true) {
+ if (!$case_sensitive) {
+ $haystack = strtoupper($haystack);
+ $needle = strtoupper($needle);
+ }
+ if ($haystack == $needle) return true;
+ return strpos($haystack, $needle) === 0;
+}
+
+/**
+ * Inserts a message into the supralog
+ *
+ * @param string $category the entry category
+ * @param string $message the message to log
+ * @param string $source the entry source.
+ */
+function supralog ($category, $message, $source = null) {
+ global $db, $CurrentUser, $CurrentPerso;
+ $category = $db->sql_query_express($category);
+ $message = $db->sql_query_express($message);
+ $source = $db->sql_query_express($source ? $source : $_SERVER['SERVER_ADDR']);
+ $ip = $_SERVER['REMOTE_ADDR'];
+ $sql = "INSERT INTO " . TABLE_LOG .
+ " (entry_ip, user_id, user_id, entry_category, entry_message, entry_source) VALUES
+ ('$ip', $CurrentUser->id, $CurrentPerso->id, '$category', '$message', '$source')";
+ if ( !($result = $db->sql_query($sql)) )
+ message_die(SQL_ERROR, "Can't log this entry.", '', __LINE__, __FILE__, $sql);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// Localization (l10n) ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Defines the LANG constant, to lang to print
+ *
+ * This information is contained in the session, or if not yet defined,
+ * it's to determine according the user's browser preferences.
+ * @see find_lang
+ */
+function initialize_lang () {
+ //If $_SESSION['lang'] doesn't exist yet, find a common language
+ if (!array_key_exists('lang', $_SESSION)) {
+ $lang = find_lang();
+ $_SESSION['lang'] = $lang ? $lang : '-';
+ }
+
+ if ($_SESSION['lang'] != '-')
+ define('LANG', $_SESSION['lang']);
+}
+
+/**
+ * Gets a common lang spoken by the site and the user's browser
+ * @see get_http_accept_languages
+ *
+ * @return string the language
+ */
+function find_lang () {
+ if (file_exists('lang') && is_dir('lang')) {
+ //Gets lang/ subdirectories: this is the list of available languages
+ $handle = opendir('lang');
+ while ($file = readdir($handle)) {
+ if ($file != '.' && $file != '..' && is_dir("lang/$file")) {
+ $langs[] = $file;
+ }
+ }
+
+ //The array $langs contains now the language available.
+ //Gets the langs the user should want:
+ if (!$userlangs = get_http_accept_languages())
+ return;
+
+ //Gets the intersection between the both languages arrays
+ //If it matches, returns first result
+ $intersect = array_intersect($userlangs, $langs);
+ if (count($intersect)) {
+ return $intersect[0];
+ }
+
+ //Now it's okay with Opera and Firefox but Internet Explorer will
+ //by default return en-US and not en or fr-BE and not fr, so second pass
+ foreach ($userlangs as $userlang) {
+ $lang = explode('-', $userlang);
+ if (count($lang) > 1)
+ $userlangs2[] = $lang[0];
+ }
+ $intersect = array_intersect($userlangs2, $langs);
+ if (count($intersect)) {
+ return $intersect[0];
+ }
+ }
+}
+
+/**
+ * Gets the languages accepted by the browser, by order of priority.
+ *
+ * This will read the HTTP_ACCEPT_LANGUAGE variable sent by the browser in the
+ * HTTP request.
+ *
+ * @return Array an array of string, each item a language accepted by browser
+ */
+function get_http_accept_languages () {
+ //What language to print is sent by browser in HTTP_ACCEPT_LANGUAGE var.
+ //This will be something like en,fr;q=0.8,fr-fr;q=0.5,en-us;q=0.3
+
+ if (!array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER)) {
+ return null;
+ }
+
+ $http_accept_language = explode(',', $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
+ foreach ($http_accept_language as $language) {
+ $userlang = explode(';q=', $language);
+ if (count($userlang) == 1) {
+ $userlangs[] = array(1, $language);
+ } else {
+ $userlangs[] = array($userlang[1], $userlang[0]);
+ }
+ }
+ rsort($userlangs);
+ foreach ($userlangs as $userlang) {
+ $result[] = $userlang[1];
+ }
+ return $result;
+}
+
+/**
+ * Loads specified language Smarty configuration file
+ *
+ * @param string $file the file to load
+ * @param mixed $sections array of section names, single section or null
+ */
+function lang_load ($file, $sections = null) {
+ global $smarty;
+
+ //Loads English file as fallback if some parameters are missing
+ if (file_exists("lang/en/$file"))
+ $smarty->configLoad("lang/en/$file", $sections);
+
+ //Loads wanted file (if it exists and a language have been defined)
+ if (defined('LANG') && LANG != 'en' && file_exists('lang/' . LANG . '/' . $file))
+ $smarty->configLoad('lang/' . LANG . '/' . $file, $sections);
+}
+
+/**
+ * Gets a specified language expression defined in configuration file
+ *
+ * @param string $key the configuration key matching the value to get
+ * @return string The value in the configuration file
+ */
+function lang_get ($key) {
+ global $smarty;
+
+ $smartyConfValue = $smarty->config_vars[$key];
+ return $smartyConfValue ? $smartyConfValue : "#$key#";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// Zed date and time helper methods ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Converts a YYYYMMDD or YYYY-MM-DD timestamp to unixtime
+ * @link http://en.wikipedia.org/wiki/Unix_time Unix time
+ *
+ * @param string $timestamp the timestamp to convert
+ * @return inteeger the unixtime
+ */
+function to_unixtime ($timestamp) {
+ switch (strlen($timestamp)) {
+ case 8:
+ //YYYYMMDD
+ return mktime(0, 0, 0, substr($timestamp, 4, 2), substr($timestamp, 6, 2), substr($timestamp, 0, 4));
+
+ case 10:
+ //YYYY-MM-DD
+ return mktime(0, 0, 0, substr($timestamp, 5, 2), substr($timestamp, 8, 2), substr($timestamp, 0, 4));
+
+ default:
+ throw new Exception("timestamp is not a valid YYYYMMDD or YYYY-MM-DD timestamp: $timestamp");
+ }
+}
+
+/**
+ * Converts a unixtime to the YYYYMMDD or YYYY-MM-DD timestamp format
+ * @see to_unixtime
+ *
+ * @param int $unixtime the time to convert
+ * @param int $format 8 or 10. If 8 (default), will output YYYYMMDD. If 10, YYYY-MM-DD.
+ * @return string the timestamp
+ */
+function to_timestamp ($unixtime = null, $format = 8) {
+ //If no parameter is specified (or null, or false), current time is used
+ //==== allows to_timestamp(0) to return correct 1970-1-1 value.
+ if ($unixtime === null || $unixtime === false) $unixtime = time();
+
+ switch ($format) {
+ case 8:
+ //YYYYMMDD
+ return date('Ymd', $unixtime);
+
+ case 10:
+ //YYYY-MM-DD
+ return date('Y-m-d', $unixtime);
+
+ default:
+ throw new Exception("format must be 8 (YYYYMMDD) or 10 (YYYY-MM-DD) and not $format.");
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// URL helpers functions ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Gets the URL matching the specified resource.
+ *
+ * Example:
+ * <code>
+ * $url = get_url('ship', $ship);
+ * echo $url; //if $ship contains S00001, this should print /ship/S00001
+ * </code>
+ *
+ * @param string $resource,... the resources
+ * @return string the URL matching the specified resource
+ */
+function get_url () {
+ global $Config;
+ if (func_num_args() > 0) {
+ $pieces = func_get_args();
+ return $Config['BaseURL'] . '/' . implode('/', $pieces);
+ } elseif ($Config['BaseURL'] == "" || $Config['BaseURL'] == $_SERVER["PHP_SELF"]) {
+ return "/";
+ } else {
+ return $Config['BaseURL'];
+ }
+}
+
+/**
+ * Gets the current page URL
+ *
+ * @return string the current page URL
+ */
+function get_page_url () {
+ $url = $_SERVER['SCRIPT_NAME'] . $_SERVER['PATH_INFO'];
+ if (substr($url, -10) == $_SERVER["PHP_SELF"]) {
+ return substr($url, 0, -9);
+ }
+ return $url;
+}
+
+/**
+ * Gets the server URL
+ * @todo find a way to detect https:// on non standard port
+ *
+ * @return string the server URL
+ */
+function get_server_url () {
+ switch ($port = $_SERVER['SERVER_PORT']) {
+ case '80':
+ return "http://$_SERVER[SERVER_NAME]";
+
+ case '443':
+ return "https://$_SERVER[SERVER_NAME]";
+
+ default:
+ return "http://$_SERVER[SERVER_NAME]:$_SERVER[SERVER_PORT]";
+ }
+}
+
+/**
+ * Gets $_SERVER['PATH_INFO'] or computes the equivalent if not defined.
+ *
+ * This function allows the entry point controllers to get the current URL
+ * in a consistent way, for any redirection configuration
+ *
+ * So with /foo/bar, /index.php/foo/bar, /zed/index.php/foo/bar or /zed/foo/bar
+ * get_current_url will return /foo/bar
+ *
+ * @return string the relevant URL part
+ */
+function get_current_url () {
+ global $Config;
+
+ //Gets relevant URL part from relevant $_SERVER variables
+ if (array_key_exists('PATH_INFO', $_SERVER)) {
+ //Without mod_rewrite, and url like /index.php/controller
+ //we use PATH_INFO. It's the easiest case.
+ return $_SERVER["PATH_INFO"];
+ }
+
+ //In other cases, we'll need to get the relevant part of the URL
+ $current_url = get_server_url() . $_SERVER['REQUEST_URI'];
+
+ //Relevant URL part starts after the site URL
+ $len = strlen($Config['SiteURL']);
+
+ //We need to assert it's the correct site
+ if (substr($current_url, 0, $len) != $Config['SiteURL']) {
+ dieprint_r(GENERAL_ERROR, "Edit includes/config.php and specify the correct site URL<br /><strong>Current value:</strong> $Config[SiteURL]<br /><strong>Expected value:</strong> a string starting by " . get_server_url(), "Setup");
+ }
+
+ if (array_key_exists('REDIRECT_URL', $_SERVER)) {
+ //With mod_rewrite, we can use REDIRECT_URL
+ //We takes the end of the URL, ie *FROM* $len position
+ return substr(get_server_url() . $_SERVER["REDIRECT_URL"], $len);
+ }
+
+ //Last possibility: use REQUEST_URI, but remove QUERY_STRING
+ //If you need to edit here, use $_SERVER['REQUEST_URI']
+ //but you need to discard $_SERVER['QUERY_STRING']
+
+ //We takes the end of the URL, ie *FROM* $len position
+ $url = substr(get_server_url() . $_SERVER["REQUEST_URI"], $len);
+
+ //But if there are a query string (?action=... we need to discard it)
+ if ($_SERVER['QUERY_STRING']) {
+ return substr($url, 0, strlen($url) - strlen($_SERVER['QUERY_STRING']) - 1);
+ }
+
+ return $url;
+}
+
+/**
+ * Gets an array of url fragments to be processed by controller
+ * @see get_current_url
+ *
+ * This method is used by the controllers entry points to know the URL and
+ * call relevant subcontrollers.
+ *
+ * @return Array an array of string, one for each URL fragment
+ */
+function get_current_url_fragments () {
+ $url_source = get_current_url();
+ if ($url_source == $_SERVER["PHP_SELF"]) return array();
+ return explode('/', substr($url_source, 1));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// ///
+/// URL xmlHttpRequest helpers functions ///
+/// ///
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Gets an hash value to check the integrity of URLs in /do.php calls
+ *
+ * @param Array $args the args to compute the hash
+ * @return the hash paramater for your xmlHttpRequest url
+ */
+function get_xhr_hash ($args) {
+ global $Config;
+
+ array_shift($args);
+ return md5($_SESSION['ID'] . $Config['SecretKey'] . implode('', $args));
+}
+
+/**
+ * Gets the URL to call do.php, the xmlHttpRequest controller
+ *
+ * @return string the xmlHttpRequest url, with an integrity hash
+ */
+function get_xhr_hashed_url () {
+ global $Config;
+
+ $args = func_get_args();
+ $args[] = get_xhr_hash($args);
+ return $Config['DoURL'] . '/' . implode('/', $args);
+}
+
+/**
+ * Gets the URL to call do.php, the xmlHttpRequest controller
+ *
+ * @return string the xmlHttpRequest url
+ */
+function get_xhr_url () {
+ global $Config;
+
+ $args = func_get_args();
+ return $Config['DoURL'] . '/' .implode('/', $args);
+}
+
+?>
diff --git a/includes/databases/database.php b/includes/databases/database.php
new file mode 100644
index 0000000..07d3d7a
--- /dev/null
+++ b/includes/databases/database.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * Database
+ *
+ * (c) 2010, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * @package Databases
+ * @subpackage Databases
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2013 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @link http://zed.dereckson.be/
+ * @filesource
+ */
+
+class Database {
+
+}
diff --git a/includes/databases/databases.php b/includes/databases/databases.php
new file mode 100644
index 0000000..055037b
--- /dev/null
+++ b/includes/databases/databases.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * Databases utilities
+ *
+ * (c) 2010, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * @package Databases
+ * @subpackage Databases
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2013 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @link http://zed.dereckson.be/
+ * @filesource
+ */
+
+class Databases {
+ public static function getDatabases () {
+ $dirs = array_filter(glob(DATABASES_DIR . '/*'), 'is_dir');
+ $len = strlen(DATABASES_DIR) + 1;
+ array_walk(
+ $dirs,
+ function (&$value) use ($len) {
+ $value = substr($value, $len);
+ }
+ );
+ return $dirs;
+ }
+}
diff --git a/includes/error.php b/includes/error.php
new file mode 100755
index 0000000..0c9a861
--- /dev/null
+++ b/includes/error.php
@@ -0,0 +1,255 @@
+<?php
+
+/**
+ * Error handler
+ *
+ * (c) 2013, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * This error handler uses the same idea and message_die methode signature
+ * of the phpBB 2 one.
+ *
+ * @package Zed
+ * @subpackage Keruald
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2013 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @filesource
+ *
+ * @todo delete old_message_die method and write alternative HTML textual output
+ * in the message_die method
+ */
+
+///
+/// Error constants
+///
+
+/**
+ * SQL_ERROR is the constant meaning the error is a SQL error.
+ *
+ * As a message_die function parameter, it allows to add SQL specific debug information.
+ */
+define ("SQL_ERROR", 65);
+
+/**
+ * HACK_ERROR is the constant meaning access is non authorized to the resource.
+ *
+ * It encompasses two problematics:
+ * the URL points to a resource belonging to another user or for the current user have no access right (for malformed URL, pick instead GENERAL_ERROR) ;
+ * the user is anonymous, instead to be logged in.
+ *
+ * A suggested way to handle the second problematic is to store in hidden input
+ * fields or better in the session the previous form data, and to print a login
+ * form.
+ *
+ * If you implement this, you don't even need to distinguishes between the two
+ * cases, as once logged in, the regular HACK_ERROR could also be printed.
+ */
+define ("HACK_ERROR", 99);
+
+/**
+ * GENERAL_ERROR is the constant meaning the error is general, ie not covered by
+ * another more specific error constant.
+ */
+define ("GENERAL_ERROR", 117);
+
+///
+/// Error helper functions
+///
+
+/**
+ * Output a general error, with human-readable information about the specified
+ * expression as error message ; terminates the current script.
+ *
+ * @see message_die
+ *
+ * @param mixed $expression the expression to be printed
+ * @param string $title the message title (optionnal, default will be 'Debug')
+ */
+function dieprint_r ($expression, $title = '') {
+ if (!$title) {
+ $title = 'Debug'; //if title is omitted or false/null, default title
+ }
+ message_die(GENERAL_ERROR, '<pre>' . print_r($expression, true) .'</pre>', $title);
+}
+
+/**
+ * Outputs an error message and terminates the current script.
+ *
+ * Error will be output through Smarty one of the following templates :
+ * error_block.tpl if the header have already been printed ;
+ * error.tpl if the error ocurred before the header were called and printed.
+ *
+ * If smarty couldn't be loaded, old_message_die method will be called, which
+ * produces a table output.
+ *
+ * @param int $msg_code an integer constant identifying the error (HACK_ERROR, SQL_ERROR, GENERAL_ERROR)
+ * @param string $msg_text the error message text (optionnal, but recommanded)
+ * @param string $msg_title the error message title (optionnal)
+ * @param int $err_line the line number of the file where the error occured (optionnal, suggested value is __LINE__)
+ * @param string $err_line the path of file where the error occured (optionnal, suggested value is __FILE__)
+ * @param string $sql the SQL query (optionnal, used only if msg_code is SQL_ERROR)
+ */
+function message_die ($msg_code, $msg_text = '', $msg_title = '', $err_line = '', $err_file = '', $sql = '') {
+ global $smarty, $db;
+
+ if ($smarty) {
+ $debug_text = $msg_text;
+
+ if ($err_line && $err_file)
+ $debug_text .= ' &mdash; ' . $err_file. ', ' . lang_get('line') . ' ' . $err_line ;
+
+ switch ($msg_code) {
+ case HACK_ERROR:
+ $smarty->assign('TITLE', lang_get('UnauthorizedAccess'));
+ break;
+
+ case SQL_ERROR:
+ $smarty->assign('TITLE', lang_get('SQLError'));
+ $sql_error = $db->sql_error();
+ if ($sql_error['message'] != '') {
+ $debug_text .= '<br />' . lang_get('Error') . ' n° ' . $sql_error['code'] . lang_get('_t') .
+ ' ' .$sql_error['message'];
+ }
+ $debug_text .= "</p><h2>Query:</h2><p>$sql";
+ break;
+
+ default:
+ $smarty->assign('WAP', "Message code error.<br />Expected: HACK_ERROR, SQL_ERROR, GENERAL_ERROR");
+ //Falls to GENERAL_ERROR
+
+ case GENERAL_ERROR:
+ if ($msg_title)
+ $smarty->assign('TITLE', $msg_title);
+ else
+ $smarty->assign('TITLE', lang_get('GeneralError'));
+ break;
+ }
+
+
+ $smarty->assign('ERROR_TEXT', $debug_text);
+ $template = (defined('HEADER_PRINTED') && HEADER_PRINTED) ? "error_block.tpl" : "error.tpl";
+ $smarty->display($template);
+ exit;
+ } else {
+ old_message_die($msg_code, $msg_text, $msg_title, $err_line, $err_file, $sql);
+ }
+}
+
+/**
+ * Outputs an error message and terminates the current script.
+ *
+ * This is the message_die method from Espace Win, used on Zed as fallback if Smarty isn't initialized yet.
+ *
+ * @param int $msg_code an integer constant identifying the error (HACK_ERROR, SQL_ERROR, GENERAL_ERROR)
+ * @param string $msg_text the error message text (optionnal, but recommanded)
+ * @param string $msg_title the error message title (optionnal)
+ * @param int $err_line the line number of the file where the error occured (optionnal, suggested value is __LINE__)
+ * @param string $err_line the path of file where the error occured (optionnal, suggested value is __FILE__)
+ * @param string $sql the SQL query (optionnal, used only if msg_code is SQL_ERROR)
+ *
+ * @deprecated since 0.1
+ */
+function old_message_die($msg_code, $msg_text = '', $msg_title = '', $err_line = '', $err_file = '', $sql = '')
+{
+ global $db, $Utilisateur;
+ $sql_store = $sql;
+
+ if ($msg_code == HACK_ERROR && $Utilisateur[user_id] < 1000) {
+ global $LoginResult;
+ foreach ($_POST as $name => $value) {
+ $champs .= "<input type=hidden name=$name value=\"$value\" />";
+ }
+ $titre = "Qui êtes-vous ?";
+ $debug_text = "Vous devez être authentifié pour accéder à cette page.";
+ $debug_text .= "
+ <FORM method='post'>
+ $champs
+ <table border='0'>
+ <tr>
+ <td><STRONG>Login</STRONG></td>
+ <td><input name='Login' type='text' id='Login' value='$_POST[Login]' size='10' /></td>
+ <td><STRONG>Mot de passe</STRONG></td>
+ <td>
+ <input name='MotDePasse' type='password' id='MotDePasse' size='10' />
+ <input type='submit' name='LoginBox' value='Connexion' />
+ </td>
+ </tr>
+ <tr>
+ <td align=center COLSPAN=4><a href='/?Topic=My&Article=Enregistrer'>Je d&eacute;sire ouvrir un compte</a></td>
+ </tr>
+ </TABLE><span class=error>$LoginResult</span>
+ </FORM>
+ ";
+ } elseif ($msg_code == HACK_ERROR) {
+ $titre = "Accès non autorisé";
+ $debug_text = $msg_text;
+ } elseif ($msg_code == SQL_ERROR) {
+ $titre = "Erreur dans la requête SQL";
+ $sql_error = $db->sql_error();
+ $debug_text = $msg_text;
+ if ( $err_line != '' && $err_file != '') $debug_text .= ' dans ' . $err_file. ', ligne ' . $err_line ;
+ if ( $sql_error['message'] != '' ) $debug_text .= '<br />Erreur n° ' . $sql_error['code'] . ' : ' . $sql_error['message'];
+ if ( $sql_store != '' ) $debug_text .= "<br /><strong>$sql_store</strong>";
+ } elseif ($msg_code == GENERAL_ERROR) {
+ $titre = $msg_title;
+ $debug_text = $msg_text;
+ if ($err_line && $err_file) {
+ $debug_text .= "<BR />$err_file, ligne $err_line";
+ }
+ }
+
+ echo "
+ <TABLE height='100%' cellSpacing=0 cellPadding=0 width='100%' border=0>
+ <TBODY>
+ <TR>
+ <TD vAlign=top align=middle>
+ <TABLE cellSpacing=0 cellPadding=0 border=0>
+ <TBODY>
+ <TR>
+ <TD vAlign=top rowSpan=5><IMG height=177 alt=''
+ src='/_pict/error/notfound.jpg' width=163 border=0></TD>
+ <TD colSpan=4><IMG height=2 alt='' src='/_pict/error/mrblue.gif'
+ width=500 border=0></TD>
+ <TD><IMG height=2 alt='' src='/_pict/error/undercover.gif' width=1
+ border=0></TD></TR>
+ <TR>
+ <TD vAlign=bottom rowSpan=4 bgcolor='#FFFFFF'><IMG height=43 alt=''
+ src='/_pict/error/ecke.gif' width=14 border=0></TD>
+ <TD vAlign=center align=middle rowSpan=2 bgcolor='#FFFFFF'>
+ <TABLE cellSpacing=1 cellPadding=0 width=470 border=0>
+ <TBODY>
+ <TR>
+ <TD><FONT face='Verdana, Helvetica, sans-serif' color=red
+ size=4><B>$titre</B></FONT><BR>
+ <IMG height=5 alt=''
+ src='/_pict/error/undercover.gif' width=14 border=0><BR></TD></TR>
+ <TR>
+ <TD><FONT face='Verdana, Helvetica, sans-serif' color=black
+ size=2>$debug_text</FONT></TD></TR></TBODY></TABLE></TD>
+ <TD align=right width=2 rowSpan=2 bgcolor='#FFFFFF'><IMG height=146 alt=''
+ src='/_pict/error/mrblue.gif' width=2 border=0></TD>
+ <TD bgcolor='#FFFFFF'><IMG height=132 alt='' src='/_pict/error/undercover.gif' width=1
+ border=0></TD>
+ </TR>
+ <TR>
+ <TD><IMG height=14 alt='' src='/_pict/error/undercover.gif' width=1
+ border=0></TD></TR>
+ <TR>
+ <TD colSpan=2><IMG height=2 alt='' src='/_pict/error/mrblue.gif'
+ width=486 border=0></TD>
+ <TD><IMG height=2 alt='' src='/_pict/error/undercover.gif' width=1
+ border=0></TD></TR>
+ <TR>
+ <TD colSpan=2><IMG height=27 alt='' src='/_pict/error/undercover.gif'
+ width=486 border=0></TD>
+ <TD><IMG height=27 alt='' src='/_pict/error/undercover.gif' width=1
+ border=0></TD></TR></TBODY></TABLE>
+ <P>&nbsp;</P>
+ </TD></TR></TBODY></TABLE>
+ ";
+
+ exit;
+}
+
+?>
\ No newline at end of file
diff --git a/includes/login.php b/includes/login.php
new file mode 100755
index 0000000..83e468d
--- /dev/null
+++ b/includes/login.php
@@ -0,0 +1,148 @@
+<?php
+
+/**
+ * Login/logout
+ *
+ * Zed. The immensity of stars. The HyperShip. The people.
+ *
+ * (c) 2010, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * @package Zed
+ * @subpackage Keruald
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2010 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @version 0.1
+ * @link http://scherzo.dereckson.be/doc/zed
+ * @link http://zed.dereckson.be/
+ * @filesource
+ *
+ * @todo Pick between DumbStore and FileStore and cleans the file accordingly.
+ */
+
+///
+/// OpenID helper code
+///
+
+require_once('Auth/OpenID/Consumer.php');
+require_once('Auth/OpenID/FileStore.php');
+
+/**
+ * Gets an Auth_OpenID_Consumer instance
+ *
+ * @return Auth_OpenID_Consumer the instance
+ */
+function get_openid_consumer () {
+ if (!file_exists('/dev/urandom')) {
+ //We don't have a reliable source of random numbers
+ define('Auth_OpenID_RAND_SOURCE', null);
+ }
+
+ $fs = new Auth_OpenID_FileStore(CACHE_DIR . '/openid');
+ return new Auth_OpenID_Consumer($fs);
+}
+
+/**
+ * Logs in the user if the OpenID is recognized.
+ * Otherwise, sets an error message.
+ *
+ * @param string $url The OpenID URL
+ */
+function openid_login ($url) {
+ global $db, $_SESSION, $LoginError, $LoginSuccessful;
+ $url = $db->sql_escape($url);
+ $sql = 'SELECT user_id FROM ' . TABLE_USERS_AUTH
+ . " WHERE auth_type = 'OpenID' AND auth_identity LIKE '$url'";
+ if ($user_id = $db->sql_query_express($sql)) {
+ $sql = "UPDATE " . TABLE_SESSIONS . " SET user_id = '$user_id' WHERE session_id LIKE '$_SESSION[ID]'";
+ if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Can't update session table", '', __LINE__, __FILE__, $sql);
+ $LoginSuccessful = true;
+ setcookie("LastOpenID", $url, time() + 2592000);
+ header("location: " . get_url());
+ } else {
+ $LoginError = "Read the source to get an invite.";
+ }
+}
+
+///
+/// Login procedural code
+///
+
+$action = isset($_GET['action']) ? $_GET['action'] : '';
+
+if ($action == 'openid.login') {
+ //Gets Auth_OpenID_Consumer instance
+ $consumer = get_openid_consumer();
+
+ //Completes the OpenID transaction
+ $reply = $consumer->complete(get_server_url() . $_SERVER['REQUEST_URI']);
+ if ($reply->status == Auth_OpenID_SUCCESS) {
+ openid_login($reply->endpoint->claimed_id);
+ } elseif ($reply->message) {
+ //TODO: $reply->message could be rather long and won't fit in the UI
+ //space. You can wish to add code to print $LoginError elsewhere if
+ //too long.
+ $LoginError = "[OpenID] $reply->message";
+ } else {
+ $LoginError = "[OpenID] $reply->status";
+ }
+} elseif (isset($_POST['LogIn'])) {
+ //User have filled login form
+ if ($_POST['openid']) {
+ //Gets Auth_OpenID_Consumer instance
+ $consumer = get_openid_consumer();
+
+ //Starts the OpenID transaction and redirects user to provider url
+ if ($request = $consumer->begin($_POST['openid'])) {
+ $url = $request->redirectURL(get_server_url(), "$Config[SiteURL]/?action=openid.login", false);
+ header("location: $url");
+ $LoginError = '<a href="' . $url . '">Click here to continue login</a>';
+ } else {
+ $LoginError = 'Invalid OpenID URL.';
+ }
+ } else {
+ //Login
+
+ //Authentications way, the user/password in last.
+ //OpenID is handled by a separate logic.
+ $Login = $_POST['username'];
+ $authentications = array();
+ if ($useYubiCloud = array_key_exists('YubiCloud', $Config) ) {
+ $authentications[] = new YubiCloudAuthentication($_POST['password'], $Login);
+ }
+ if ($Login) {
+ $authentications[] = new UserPasswordAuthentication($Login, $_POST['password']);
+ }
+
+ $loginSuccessful = false;
+ foreach ($authentications as $authentication) {
+ if ($authentication->isValid()) {
+ $loginSuccessful = true;
+ //Logs in user
+ login($authentication->getUserID(), $Login);
+ } else {
+ $loginError = $authentication->getError();
+ }
+ if (!$authentication->canTryNextAuthenticationMethod()) {
+ break;
+ }
+ }
+
+ //Tests if the password wouldn't match an invite code
+ //If so, redirects people using login page as invitation claim page
+ if (!$LoginSuccessful) {
+ $code = $db->sql_escape($_POST['password']);
+ $sql = "SELECT * FROM " . TABLE_USERS_INVITES . " WHERE invite_code = '$code'";
+ if (!$result = $db->sql_query($sql)) {
+ message_die(SQL_ERROR, "Can't get invites", '', __LINE__, __FILE__, $sql);
+ }
+ if ($row = $db->sql_fetchrow($result)) {
+ $url = get_url('invite', $_POST['password']);
+ header('location: ' . $url);
+ }
+ }
+ }
+} elseif (isset($_POST['LogOut']) || $action == "user.logout") {
+ Logout();
+}
diff --git a/includes/mysql.php b/includes/mysql.php
new file mode 100755
index 0000000..862ad65
--- /dev/null
+++ b/includes/mysql.php
@@ -0,0 +1,178 @@
+<?php
+
+/**
+ * MySQL layer and helper class
+ *
+ * (c) 2013, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * @package Databases
+ * @subpackage Keruald
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2013 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @filesource
+ */
+
+if (!defined('SQL_LAYER')) {
+ /**
+ * Defines the SQL engine layer implented for our SQL abstraction class:
+ * MySQL
+ */
+ define('SQL_LAYER', 'mysql');
+
+ /**
+ * SQL database class
+ *
+ * This is the MySQL implementation of our SQL abstraction layer
+ */
+ class sql_db {
+ /*
+ * @var int the connection identifier
+ */
+ private $id;
+
+ /**
+ * Initializes a new instance of the database abstraction class, for MySQL engine
+ *
+ * @param string $host the SQL server to connect [optionnal, by default localhost]
+ * @param string $username the SQL username [optionnal, by default root]
+ * @param string $password the SQL password [optionnal, by default blank]
+ * @param string $database the database to select [optionnal]
+ */
+ function __construct($host = 'localhost', $username = 'root', $password = '' , $database = '') {
+ //Connects to the MySQL server
+ $this->id = @mysql_connect($host, $username, $password) or $this->sql_die(); //or die ("Can't connect to SQL server.");
+
+ //Selects database
+ if ($database != '') {
+ mysql_select_db($database, $this->id);
+ }
+ }
+
+
+ /**
+ * Outputs a can't connect to the SQL server message and exits.
+ * It's called on connect failure
+ */
+ function sql_die () {
+ //You can custom here code when you can't connect to SQL server
+ //e.g. in a demo or appliance context, include('start.html'); exit;
+ die ("Can't connect to SQL server.");
+ //include('start.html');
+ //exit;
+ }
+
+ /**
+ * Sends a unique query to the database
+ *
+ * @param string $query the query to execute
+ * @return resource if the query is successful, a resource identifier ; otherwise, false
+ */
+ function sql_query ($query) {
+ return mysql_query($query, $this->id);
+ }
+
+ /**
+ * Fetches a row of result into an associative array
+ *
+ * @param resource $result The result that is being evaluated, from sql_query
+ * @return array an associative array with columns names as keys and row values as values
+ */
+ function sql_fetchrow ($result) {
+ return mysql_fetch_array($result);
+ }
+
+ /**
+ * Gets last SQL error information
+ *
+ * @return array an array with two keys, code and message, containing error information
+ */
+ function sql_error () {
+ $error['code'] = mysql_errno($this->id);
+ $error['message'] = mysql_error($this->id);
+ return $error;
+ }
+
+
+ /**
+ * Gets the number of rows affected or returned by a query
+ *
+ * @return int the number of rows affected (delete/insert/update) or the number of rows in query result
+ */
+ function sql_numrows ($result) {
+ return mysql_num_rows($result);
+ }
+
+ /**
+ * Gets the primary key value of the last query (works only in INSERT context)
+ *
+ * @return int the primary key value
+ */
+ function sql_nextid () {
+ return mysql_insert_id($this->id);
+ }
+
+ /**
+ * Express query method, returns an immediate and unique result
+ *
+ * @param string $query the query to execute
+ * @param string $error_message the error message
+ * @param boolean $return_as_string return result as string, and not as an array
+ * @return mixed the row or the scalar result
+ */
+ function sql_query_express ($query = '', $error_message = "Impossible d'exécuter cette requête.", $return_as_string = true) {
+ if ($query === '' || $query === false || $query === null) {
+ //No query, no value
+ return '';
+ } elseif (!$result = $this->sql_query($query)) {
+ message_die(SQL_ERROR, $error_message, '', __LINE__, __FILE__, $query);
+ } else {
+ //Fetches row
+ $row = $this->sql_fetchrow($result);
+
+ //If $return_as_string is true, returns first query item (scalar mode) ; otherwise, returns row
+ return $return_as_string ? $row[0] : $row;
+ }
+ }
+
+ /**
+ * Escapes a SQL expression
+ *
+ * @param string $expression The expression to escape
+ * @return string The escaped expression
+ */
+ function sql_escape ($expression) {
+ return mysql_real_escape_string($expression);
+ }
+
+ /*
+ * Sets the client character set (requires MySQL 5.0.7+).
+ *
+ * @param string $encoding the charset encoding to set
+ */
+ function set_charset ($encoding) {
+ if (function_exists('mysql_set_charset')) {
+ //>=PHP 5.2.3
+ mysql_set_charset($encoding, $this->id);
+ } else {
+ //Old PHP version
+ $this->sql_query("SET NAMES '$encoding'");
+ }
+ }
+ }
+
+ /**
+ * The main sql_db instance
+ *
+ * @global sql_db $db
+ */
+ $db = new sql_db($Config['sql']['host'], $Config['sql']['username'], $Config['sql']['password'], $Config['sql']['database']);
+ $db->set_charset('utf8');
+
+ //By security, we unset the SQL parameters, so you can safely output Zed
+ //config parts (there's still the problem of the secret key, but it's less
+ //a security problem than database password)
+ unset($Config['sql']);
+}
+?>
\ No newline at end of file
diff --git a/includes/objects/user.php b/includes/objects/user.php
new file mode 100755
index 0000000..2ff6ae3
--- /dev/null
+++ b/includes/objects/user.php
@@ -0,0 +1,246 @@
+<?php
+
+/**
+ * User class
+ *
+ * Zed. The immensity of stars. The HyperShip. The people.
+ *
+ * (c) 2010, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * [DESIGN BY CONTRACT NOTE] No more than one OpenID per user
+ *
+ * @package Zed
+ * @subpackage Model
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2010 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @version 0.1
+ * @link http://scherzo.dereckson.be/doc/zed
+ * @link http://zed.dereckson.be/
+ * @filesource
+ */
+
+/**
+ * User class
+ *
+ * This class maps the users and users_openid tables.
+ *
+ * It also provides helper methods to check if a login is available,
+ * or to retrieve a username from e-mail address.
+ */
+class User {
+
+ public $id;
+ public $name;
+ public $password;
+ public $active = 0;
+ public $actkey;
+ public $email;
+ public $regdate;
+
+ public static $hashtable_id = array();
+ public static $hashtable_name = array();
+
+ /**
+ * Initializes a new instance
+ *
+ * @param int $id the primary key
+ */
+ function __construct ($id = null) {
+ if ($id) {
+ $this->id = $id;
+ $this->load_from_database();
+ }
+ }
+
+ /**
+ * Initializes a new User instance if needed or get already available one.
+ *
+ * @param mixed $data user ID or name
+ * @return User the user instance
+ */
+ static function get ($data = null) {
+ if ($data) {
+ //Checks in the hashtables if we already have loaded this instance
+ if (is_numeric($data)) {
+ if (array_key_exists($data, User::$hashtable_id)) {
+ return User::$hashtable_id[$data];
+ }
+ } else {
+ if (array_key_exists($data, User::$hashtable_name)) {
+ return User::$hashtable_name[$data];
+ }
+ }
+ }
+
+ $user = new User($data);
+ return $user;
+ }
+
+ /**
+ * Loads the object User (ie fill the properties) from the $_POST array
+ */
+ function load_from_form () {
+ if (array_key_exists('name', $_POST)) $this->name = $_POST['name'];
+ if (array_key_exists('password', $_POST)) $this->password = $_POST['password'];
+ if (array_key_exists('active', $_POST)) $this->active = $_POST['active'];
+ if (array_key_exists('actkey', $_POST)) $this->actkey = $_POST['actkey'];
+ if (array_key_exists('email', $_POST)) $this->email = $_POST['email'];
+ if (array_key_exists('regdate', $_POST)) $this->regdate = $_POST['regdate'];
+ }
+
+ /**
+ * Loads the object User (ie fill the properties) from the database
+ */
+ function load_from_database () {
+ global $db;
+ $sql = "SELECT * FROM " . TABLE_USERS . " WHERE user_id = '" . $this->id . "'";
+ if ( !($result = $db->sql_query($sql)) ) message_die(SQL_ERROR, "Unable to query users", '', __LINE__, __FILE__, $sql);
+ if (!$row = $db->sql_fetchrow($result)) {
+ $this->lastError = "User unkwown: " . $this->id;
+ return false;
+ }
+ $this->name = $row['username'];
+ $this->password = $row['user_password'];
+ $this->active = $row['user_active'];
+ $this->actkey = $row['user_actkey'];
+ $this->email = $row['user_email'];
+ $this->regdate = $row['user_regdate'];
+
+ //Puts object in hashtables
+ Perso::$hashtable_id[$this->id] = $this;
+ Perso::$hashtable_name[$this->name] = $this;
+
+ return true;
+ }
+
+ /**
+ * Saves to database
+ */
+ function save_to_database () {
+ global $db;
+
+ $id = $this->id ? "'" . $db->sql_escape($this->id) . "'" : 'NULL';
+ $name = $db->sql_escape($this->name);
+ $password = $db->sql_escape($this->password);
+ $active = $db->sql_escape($this->active);
+ $actkey = $db->sql_escape($this->actkey);
+ $email = $db->sql_escape($this->email);
+ $regdate = $this->regdate ? "'" . $db->sql_escape($this->regdate) . "'" : 'NULL';
+
+ //Updates or inserts
+ $sql = "REPLACE INTO " . TABLE_USERS . " (`user_id`, `username`, `user_password`, `user_active`, `user_actkey`, `user_email`, `user_regdate`) VALUES ($id, '$name', '$password', '$active', '$actkey', '$email', $regdate)";
+ if (!$db->sql_query($sql)) {
+ message_die(SQL_ERROR, "Unable to save", '', __LINE__, __FILE__, $sql);
+ }
+
+ if (!$id) {
+ //Gets new record id value
+ $this->id = $db->sql_nextid();
+ }
+ }
+
+ /**
+ * Updates the specified field in the database record
+ */
+ function save_field ($field) {
+ global $db;
+ if (!$this->id) {
+ message_die(GENERAL_ERROR, "You're trying to update a record not yet saved in the database");
+ }
+ $id = $db->sql_escape($this->id);
+ $value = $db->sql_escape($this->$field);
+ $sql = "UPDATE " . TABLE_USERS . " SET `$field` = '$value' WHERE user_id = '$id'";
+ if (!$db->sql_query($sql)) {
+ message_die(SQL_ERROR, "Unable to save $field field", '', __LINE__, __FILE__, $sql);
+ }
+ }
+
+ /**
+ * Generates a unique user id
+ */
+ function generate_id () {
+ global $db;
+
+ do {
+ $this->id = rand(2001, 5999);
+ $sql = "SELECT COUNT(*) FROM " . TABLE_USERS . " WHERE user_id = $this->id LOCK IN SHARE MODE;";
+ if (!$result = $db->sql_query($sql)) {
+ message_die(SQL_ERROR, "Can't access users table", '', __LINE__, __FILE__, $sql);
+ }
+ $row = $db->sql_fetchrow($result);
+ } while ($row[0]);
+ }
+
+ /**
+ * Fills password field with encrypted version of the specified clear password
+ *
+ * @param string $newpassword The user's new password
+ */
+ public function set_password ($newpassword) {
+ $this->password = md5($newpassword);
+ }
+
+ /**
+ * Deletes OpenID for this user
+ */
+ public function delete_OpenID () {
+ $this->set_OpenID('');
+ }
+
+ /**
+ * Sets OpenID for this user
+ *
+ * @param string $url OpenID endpoint URL
+ */
+ public function set_OpenID ($url) {
+ global $db;
+ if (!$this->id) $this->save_to_database();
+ $url = $db->sql_escape($url);
+ $sql = "DELETE FROM " . TABLE_USERS_AUTH . " WHERE auth_type = 'OpenID' AND user_id = $this->id";
+ if (!$db->sql_query($sql))
+ message_die(SQL_ERROR, "Can't delete old OpenID", '', __LINE__, __FILE__, $sql);
+ if ($url != '') {
+ $sql = "INSERT INTO " . TABLE_USERS_AUTH . " (auth_type, auth_identity, user_id) VALUES ('OpenID', '$url', $this->id)";
+ if (!$db->sql_query($sql))
+ message_die(SQL_ERROR, "Can't add new OpenID", '', __LINE__, __FILE__, $sql);
+ }
+ }
+
+ /**
+ * Checks if a login is available
+ *
+ * @param string $login the login to check
+ * @return bool true if the specified login is available ; otherwise, false.
+ */
+ public static function is_available_login ($login) {
+ global $db;
+ $sql = "SELECT COUNT(*) FROM " . TABLE_USERS . " WHERE username LIKE '$login' LOCK IN SHARE MODE;";
+ if (!$result = $db->sql_query($sql)) {
+ message_die(SQL_ERROR, "Utilisateurs non parsable", '', __LINE__, __FILE__, $sql);
+ }
+ $row = $db->sql_fetchrow($result);
+ return ($row[0] ? false : true);
+ }
+
+ /**
+ * Gets username from specified e-mail
+ *
+ * @param string $mail the mail to search
+ * @return string|bool the username matching the mail if found ; otherwise, false.
+ */
+ public static function get_username_from_email ($mail) {
+ global $db;
+ $sql = "SELECT username FROM " . TABLE_USERS . " WHERE user_email LIKE '$mail' LOCK IN SHARE MODE;";
+ if (!$result = $db->sql_query($sql)) {
+ message_die(SQL_ERROR, "Utilisateurs non parsable", '', __LINE__, __FILE__, $sql);
+ }
+ if ($row = $db->sql_fetchrow($result)) {
+ return $row['username'];
+ }
+ return false;
+ }
+}
+
+?>
diff --git a/includes/sessions.php b/includes/sessions.php
new file mode 100755
index 0000000..9ff2e90
--- /dev/null
+++ b/includes/sessions.php
@@ -0,0 +1,146 @@
+<?php
+
+/**
+ * Sessions
+ *
+ * (c) 2013, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * This file provides functions to manage sessions. It's not currently properly
+ * documented, as it's a temporary old session file, which will be updated soon.
+ *
+ * @package Zed
+ * @subpackage Keruald
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2013 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @filesource
+ *
+ * @todo Replaces this code by the unified Keruald session class.
+ */
+
+function decode_ip ($int_ip) {
+ $hexipbang = explode('.', chunk_split($int_ip, 2, '.'));
+ return hexdec($hexipbang[0]). '.' . hexdec($hexipbang[1]) . '.' . hexdec($hexipbang[2]) . '.' . hexdec($hexipbang[3]);
+}
+
+function encode_ip ($dotquad_ip) {
+ $ip_sep = explode('.', $dotquad_ip);
+ return sprintf('%02x%02x%02x%02x', $ip_sep[0], $ip_sep[1], $ip_sep[2], $ip_sep[3]);
+}
+
+function session_update () {
+ global $db, $IP, $Config;
+ //Nettoyage de la session
+ /* Initialisation */
+ $time_online = 5 * 60; // Temps après lequel l'utilisateur n'est plus considéré comme online
+ $time_session = 2 * 60 * 60; // Durée de vie de la session
+
+ $heureActuelle = time(); //Timestamp UNIX et non MySQL
+
+ /* On fait le ménage */
+ $sql = "UPDATE " . TABLE_SESSIONS . " SET online=0 WHERE HeureLimite < $heureActuelle";
+ if (!$db->sql_query($sql)) message_die(SQL_ERROR, 'Impossible de mettre à jour les sessions (utilisateurs offline)', '', __LINE__, __FILE__, $sql);
+
+ $sql = "DELETE FROM " . TABLE_SESSIONS . " WHERE SessionLimite < $heureActuelle";
+ if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Impossible d'effacer les sessions expirées", '', __LINE__, __FILE__, $sql);
+
+ /* Création / mise à jour de la session utilisateur */
+ if (!$_SESSION[ID]) {
+ $_SESSION[ID] = md5(generate_random_string("AAAA1234"));
+ }
+
+ $sql = "SELECT * FROM " . TABLE_SESSIONS . " WHERE session_id LIKE '$_SESSION[ID]'";
+ if ( !($result = $db->sql_query($sql)) ) message_die(SQL_ERROR, "Problème critique avec les sessions.", '', __LINE__, __FILE__, $sql);
+
+ if ($db->sql_numrows($result) == 0) {
+ $sql = "INSERT INTO " . TABLE_SESSIONS . " (IP, session_id, `Where`, HeureLimite, SessionLimite) VALUES ('$IP', '$_SESSION[ID]', $Config[ResourceID], $heureActuelle + $time_online, $heureActuelle + $time_session)";
+ if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Impossible de créer une nouvelle session", '', __LINE__, __FILE__, $sql);
+ } else {
+ $sql = "UPDATE " . TABLE_SESSIONS . " SET online=1, HeureLimite = $heureActuelle + $time_online, SessionLimite= $heureActuelle + $time_session WHERE session_id = '$_SESSION[ID]'";
+ if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Impossible de mettre à jour la session", '', __LINE__, __FILE__, $sql);
+ }
+}
+
+function nbc () {
+//Renvoi du nombre d'usagers connectés
+ global $db, $Config;
+ $sql = "SELECT count(*) FROM " . TABLE_SESSIONS . " WHERE online=1 AND `Where` = $Config[ResourceID]";
+ if ( !($result = $db->sql_query($sql)) ) message_die(SQL_ERROR, "Impossible d'obtenir le nombre d'utilisateurs connectés sur le site web", '', __LINE__, __FILE__, $sql);
+ $row = $db->sql_fetchrow($result);
+ return $row[0];
+}
+
+function get_info ($info)
+//Renvoie une variable de la session
+{
+ global $db;
+ $sql = "SELECT $info FROM " . TABLE_SESSIONS . " WHERE session_id LIKE '$_SESSION[ID]'";
+ if ( !($result = $db->sql_query($sql)) ) message_die(SQL_ERROR, "Impossible d'obtenir $info", '', __LINE__, __FILE__, $sql);
+ $row = $db->sql_fetchrow($result);
+ return $row[$info];
+}
+
+function get_logged_user ()
+//Renvoie toutes les informations d'un utilisateur
+{
+ global $db;
+ $sql = "SELECT * FROM " . TABLE_SESSIONS . " WHERE session_id LIKE '$_SESSION[ID]'";
+ if ( !($result = $db->sql_query($sql)) ) message_die(SQL_ERROR, "Impossible d'obtenir les informations de l'utilisateur", '', __LINE__, __FILE__, $sql);
+ $row = $db->sql_fetchrow($result);
+
+ require_once('includes/objects/user.php');
+ $user = User::get($row['user_id']);
+
+ $user->session = $row;
+
+ return $user;
+}
+
+function set_info ($info, $value)
+//Définit une variable session
+{
+ global $db;
+ $value = ($value === null) ? 'NULL' : "'" . $db->sql_escape($value) . "'";
+ $sql = "UPDATE " . TABLE_SESSIONS . " SET $info = $value WHERE session_id LIKE '$_SESSION[ID]'";
+ if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Impossible de définir $info", '', __LINE__, __FILE__, $sql);
+}
+
+/**
+ * Destroys $_SESSION array values, help ID
+ */
+function clean_session () {
+ foreach ($_SESSION as $key => $value) {
+ if ($key != 'ID') unset($_SESSION[$key]);
+ }
+}
+
+
+/**
+ * Logs in user
+ */
+
+function login ($user_id, $username) {
+ global $db;
+ $sql = "UPDATE " . TABLE_SESSIONS . " SET user_id = '$user_id' WHERE session_id LIKE '$_SESSION[ID]'";
+ if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Impossible de procéder à la connexion", '', __LINE__, __FILE__, $sql);
+
+ //We send a cookie to print automatically the last username on the login
+ //page during 30 days.
+ if (username) {
+ setcookie("LastUsername", $username, time() + 2592000);
+ }
+}
+
+/**
+ * Logs out user
+ */
+function logout () {
+ //Anonymous user in session table
+ global $db;
+ $sql = "UPDATE " . TABLE_SESSIONS . " SET user_id = '-1', perso_id = NULL WHERE session_id LIKE '$_SESSION[ID]'";
+ if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Impossible de procéder à la déconnexion", '', __LINE__, __FILE__, $sql);
+ clean_session();
+}
+
+?>
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..f1aa091
--- /dev/null
+++ b/index.php
@@ -0,0 +1,87 @@
+<?php
+
+/**
+ * Application entry point
+ *
+ * (c) 2010, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * @package Databases
+ * @subpackage EntryPoints
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @copyright 2013 Sébastien Santoro aka Dereckson
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD
+ * @link http://zed.dereckson.be/
+ * @filesource
+ */
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// Initialization
+///
+
+//Keruald (formelly Pluton) library
+include('includes/core.php');
+
+//Session
+$IP = encode_ip($_SERVER["REMOTE_ADDR"]);
+session_start();
+$_SESSION['ID'] = session_id();
+session_update(); //updates or creates the session
+
+include("includes/login.php"); //login/logout
+$CurrentUser = get_logged_user(); //Gets current user infos
+
+//Skin and accent to load
+define('THEME', 'NotInKnowledgeExtinction');
+
+//Loads Smarty
+require('includes/Smarty/Smarty.class.php');
+$smarty = new Smarty();
+$current_dir = dirname(__FILE__);
+$smarty->setTemplateDir($current_dir . '/skins/' . THEME);
+
+$smarty->compile_dir = CACHE_DIR . '/compiled';
+$smarty->cache_dir = CACHE_DIR;
+$smarty->config_dir = $current_dir;
+
+$smarty->config_vars['StaticContentURL'] = $Config['StaticContentURL'];
+
+//Loads language files
+initialize_lang();
+lang_load('core.conf');
+
+//Gets URL
+$url = get_current_url_fragments();
+
+////////////////////////////////////////////////////////////////
+///
+/// Calls the specific controller to serve the requested page
+///
+
+switch ($controller = $url[0]) {
+ case '':
+ include('controllers/home.php');
+ break;
+
+ case 'foo':
+ case 'bar':
+ include("controllers/$controller.php");
+ break;
+
+ case 'quux':
+ //It's like a test/debug console/sandbox, you put what you want into
+ if (file_exists('dev/quux.php')) {
+ include('dev/quux.php');
+ } else {
+ message_die(GENERAL_ERROR, "Quux lost in Hollywood.", "Nay");
+ }
+ break;
+
+ default:
+ //TODO: returns a prettier 404 page
+ header("Status: 404 Not Found");
+ dieprint_r($url, 'Unknown URL');
+}
+
+?>
diff --git a/lang/en/core.conf b/lang/en/core.conf
new file mode 100644
index 0000000..cd87cd7
--- /dev/null
+++ b/lang/en/core.conf
@@ -0,0 +1,8 @@
+ApplicationTitle = "Nasqueron Databases"
+Welcome = "Welcome to Nasqueron Databases"
+
+# Errors
+BackToHome = "Go to home"
+
+# Footer
+NasqueronPoem = "A sphere with no solid core at all."
diff --git a/skins/NotInKnowledgeExtinction/error.tpl b/skins/NotInKnowledgeExtinction/error.tpl
new file mode 100644
index 0000000..ec41d23
--- /dev/null
+++ b/skins/NotInKnowledgeExtinction/error.tpl
@@ -0,0 +1,9 @@
+ <!-- Error -->
+ <div class="content_wrapper">
+ <h1>{$TITLE}</h1>
+ <div class="content">
+ <p>{$ERROR_TEXT}</p>
+ <p><a href="{get_url()}">{#BackToHome#}</a></p>
+ </div>
+ </div>
+ <div class="clear"></div>
diff --git a/skins/NotInKnowledgeExtinction/footer.tpl b/skins/NotInKnowledgeExtinction/footer.tpl
new file mode 100644
index 0000000..e9397c5
--- /dev/null
+++ b/skins/NotInKnowledgeExtinction/footer.tpl
@@ -0,0 +1,62 @@
+ <footer>
+ <div class="row">
+ <div class="large-3 columns sep" style="text-align: center">
+ <img src="{#StaticContentURL#}/img/Nasqueron.png" /></p>
+ <p><strong>Nasqueron</strong> is a community of developers & creative people.</p>
+ <hr />
+ <p><strong>Nasqueron Databases</strong> is a collection of databases, and small applications build on the top of these databases.</p>
+ </div>
+ <div class="large-3 columns sep">
+ <h4>License</h4>
+ <p>This is <em>open data</em>, licensed under the Open Data Commons Open Database License (ODbL). </p>
+ <p>Please note the lyrics excerpts are copyrighted, and have been included in the database per the right to quote.</p></p>
+
+ <h4>Reuse data</h4>
+ <p>You can freely reuse our data. We're willing to build API or prepare dumps to help you upon request.</p>
+ </div>
+ <div class="large-3 columns sep">
+ <h4>Newsletter</h4>
+ <p>Stay in touch and get informed when we add a new database.</p>
+ <form method="post">
+ <div class="row collapse">
+ <div class="small-10 columns">
+ <input type="text" name="mail" id="mail" placeholder="username@domain.tld">
+ </div>
+ <div class="small-2 columns">
+ <input type="submit" class="button prefix" value="OK" />
+ </div>
+ </div>
+ </form>
+ <hr />
+ <h4>Participate</h4>
+ <p>If you wish to participate, your help is welcome.</p>
+ </div>
+ <div class="large-3 columns" style="text-align: right">
+ <img src="http://www.clker.com/cliparts/i/D/E/7/A/J/database-symbol-md.png" style="margin-top: 2em;" />
+ </div>
+ </div>
+
+ <div class="copyright">
+ <div class="row">
+ <div class="large-6 small-4 columns">
+ <p>2013, Nasqueron | Nasqueron Databases</p>
+ <p>{#NasqueronPoem#}</p>
+ </div>
+ <div class="large-6 small-8 columns">
+ <p style="text-align: right">{$version}</p>
+ </div>
+ </div>
+ </div>
+ </footer>
+
+ <script>
+ document.write('<script src={#StaticContentURL#}/' +
+ ('__proto__' in {} ? 'js/vendor/zepto' : 'js/vendor/jquery') +
+ '.js><\/script>')
+ </script>
+ <script src="{#StaticContentURL#}/js/foundation.min.js"></script>
+ <script>
+ $(document).foundation();
+ </script>
+</body>
+</html>
diff --git a/skins/NotInKnowledgeExtinction/header.tpl b/skins/NotInKnowledgeExtinction/header.tpl
new file mode 100644
index 0000000..1128831
--- /dev/null
+++ b/skins/NotInKnowledgeExtinction/header.tpl
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
+<!--[if gt IE 8]><!--><html class="no-js" lang="en" > <!--<![endif]-->
+
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width">
+ <title>{$PAGE_TITLE}</title>
+
+ <link rel="stylesheet" href="{#StaticContentURL#}/css/foundation.css">
+ <link rel="stylesheet" href="{#StaticContentURL#}/css/NotInKnowledgeExtinction.css">
+ <script src="{#StaticContentURL#}/js/vendor/custom.modernizr.js"></script>
+</head>
+<body>
+ <header>
+ <h1>{if $DATABASE_NAME}{$DATABASE_NAME}{else}{#ApplicationTitle#}{/if}</h1>
+ </header>
diff --git a/skins/NotInKnowledgeExtinction/home.tpl b/skins/NotInKnowledgeExtinction/home.tpl
new file mode 100644
index 0000000..3c2a920
--- /dev/null
+++ b/skins/NotInKnowledgeExtinction/home.tpl
@@ -0,0 +1,25 @@
+ <section class="row" id="databases" style="min-height: 300px;">
+ <div class="large-4 columns">
+ <h4>Databases list</h4>
+ <ul>
+{foreach $databases as $database}
+ <li>{$database}</li>
+{/foreach}
+ </ul>
+ </div>
+
+ <div class="large-4 columns">
+ <a href="grid.php" class="pic" id="featureGrid"></a>
+ <h4><a href="grid.php">Flexible Grid</a></h4>
+
+ <p>The flexible grid can adapt to any size screen, from phones to TVs.</p>
+
+ </div>
+ <div class="large-4 columns">
+ <a href="prototyping.php" class="pic" id="featurePrototype"></a>
+ <h4><a href="prototyping.php">Rapid Prototyping</a></h4>
+
+ <p>Dozens of elements and styles to help you go from coded prototype to polished product.</p>
+
+ </div>
+ </section>

File Metadata

Mime Type
text/x-diff
Expires
Thu, Apr 16, 05:00 (1 d, 6 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3616054
Default Alt Text
(78 KB)

Event Timeline