Page MenuHomeDevCentral

No OneTemporary

This document is not UTF8. It was detected as ISO-8859-1 (Latin 1) and converted to UTF8 for display.
diff --git a/includes/core.php b/includes/core.php
index 9319987..c00af3a 100755
--- a/includes/core.php
+++ b/includes/core.php
@@ -1,310 +1,345 @@
<?php
/*
* Keruald, core libraries for Pluton and Xen engines.
* (c) 2010, Sébastien Santoro aka Dereckson, some rights reserved
* Released under BSD license
*
* Core
*
* 0.1 2010-02-27 2:04 DcK
*/
////////////////////////////////////////////////////////////////////////////////
/// ///
/// Configures PHP and loads site-wide used libraries ///
/// ///
////////////////////////////////////////////////////////////////////////////////
//Disables register globals
ini_set('register_globals', 'off');
//Reports all errors, help notices (including STRICT in PHP 6)
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("session.php"); //Sessions handler
////////////////////////////////////////////////////////////////////////////////
/// ///
/// Information helper functions ///
/// ///
////////////////////////////////////////////////////////////////////////////////
/*
* Gets the username matching specified user id
* @param string $user_id the user ID
* @return string the username
*/
function get_username ($user_id) {
global $db;
$user_id = $db->sql_escape($user_id);
$sql = 'SELECT username FROM '. TABLE_USERS . " WHERE user_id = '$userid'";
return $db->sql_query_express($sql, "Can't get username from specified user id");
}
/*
* Gets the user id matching specified username
* @param string $username the username
* @return string 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'";
return $db->sql_query_express($sql, "Can't get user id from specified username");
}
////////////////////////////////////////////////////////////////////////////////
/// ///
/// Misc helper functions ///
/// ///
////////////////////////////////////////////////////////////////////////////////
//Plural management
/*
* Gets a "s" if the specified amount requests the plural
* @param mixed $amount the quantity (should be numeric)
* @return string 's' if the amount is greater or equal than 2 ; otherwise, ''
*/
function s ($amount) {
if ($amount >= 2 || $amount <= -2 ) return 's';
}
/*
* Prints human-readable information about a variable, wrapped in a <pre> block
* @param mixed $mixed the variable to dump
*/
function dprint_r ($mixed) {
echo '<pre>';
print_r($mixed);
echo '</pre>';
}
/*
* Generates a new GUID
* @return string a guid (without {})
*/
function new_guid () {
//The guid chars
$chars = explode(',', 'a,b,c,d,e,f,0,1,2,3,4,5,6,7,8,9');
//Let's build our 36 characters string
//e.g. 68ed40c6-f5bb-4a4a-8659-3adf23536b75
$guid = "";
for ($i = 0 ; $i < 36 ; $i++) {
if ($i == 8 || $i == 13 || $i == 18 || $i == 23) {
//Dashes at position 9, 14, 19 and 24
$guid .= "-";
} else {
//0-f hex digit elsewhere
$guid .= $chars[mt_rand() % sizeof($characters)];
}
}
return $guid;
}
/*
* Determines if the expression is a valid guid (in uuid notation, without {})
* @param string $expression the guid to check
* @return true if the expression is a valid guid ; 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 hex 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
*/
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;
+ if (!$case_sensitive) {
+ $haystack = strtoupper($haystack);
+ $needle = strtoupper($needle);
+ }
+ if ($haystack == $needle) return true;
+ return strpos($haystack, $needle) === 0;
+}
+
+/**
+ * Gets the portion of the string between $includeFrom and $includeTo
+ */
+function string_between ($haystack, $from, $to, $includeFrom = false, $includeTo = false) {
+ //Gets start position
+ $pos1 = strpos($haystack, $from);
+ if ($pos1 === false) {
+ return "";
+ }
+ if (!$includeFrom) $pos1 += strlen($from);
+
+ //Gets end position
+ $pos2 = strpos($haystack, $to, $pos1 + strlen($from));
+ if ($pos2 === false) {
+ return substr($haystack, $pos1);
+ }
+ if ($includeTo) $pos2 += strlen($includeTo);
+
+ //Gets middle part
+ return substr($haystack, $pos1, $pos2 - $pos1);
}
////////////////////////////////////////////////////////////////////////////////
/// ///
/// URL helpers functions ///
/// ///
////////////////////////////////////////////////////////////////////////////////
/*
* Gets URL
* @return string URL
*/
function get_url () {
global $Config;
if (func_num_args() > 0) {
$pieces = func_get_args();
return $Config['BaseURL'] . '/' . implode('/', $pieces);
} elseif ($Config['BaseURL'] == "" || $Config['BaseURL'] == "/index.php") {
return "/";
} else {
return $Config['BaseURL'];
}
}
/*
* Gets page URL
* @return string URL
*/
function get_page_url () {
$url = $_SERVER['SCRIPT_NAME'] . $_SERVER['PATH_INFO'];
if (substr($url, -10) == "/index.php") {
return substr($url, 0, -9);
}
return $url;
}
/*
* Gets 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.
* @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
* @return array an array containing URL fragments
*/
function get_current_url_fragments () {
$url_source = get_current_url();
if ($url_source == '/index.php') return array();
return explode('/', substr($url_source, 1));
}
+/**
+ * Gets the URL for the specified resources
+ *
+ * @param ... string a arbitray number of path info
+ */
+function get_url_for () {
+ global $Config;
+ $url = get_server_url() . '/' . $Config[BaseURL];
+ if (func_num_args()) {
+ $url .= implode('/', func_get_args());
+ }
+ return $url;
+}
+
////////////////////////////////////////////////////////////////////////////////
/// ///
/// 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);
}
-
-?>
\ No newline at end of file
diff --git a/includes/document.php b/includes/document.php
index 031b1ce..82cd746 100755
--- a/includes/document.php
+++ b/includes/document.php
@@ -1,302 +1,358 @@
<?php
/*
* Keruald, core libraries for Pluton and Xen engines.
* (c) 2010, Sébastien Santoro aka Dereckson, some rights reserved
* Released under BSD license
*
* @package Pluton
* @subpackage Pluton
* @copyright Copyright (c) 2010-2011, Sébastien Santoro aka Dereckson
* @license Released under BSD license
* @version 0.1
*/
class Document {
/**
* URL, before any treatment
*/
public $url;
/**
* Topic, with - as topic seperator
*/
public $topic;
/**
* Article, without extension
*/
public $article;
/**
* Extension, without .
*/
public $extension;
/**
* HTTP status code (200, 404, etC.)
*/
public $status;
/**
* Document title
*/
public $title;
/**
* Document description
*/
public $description;
/**
* Content to write in <head> block
*/
public $head;
+ /**
+ * Content to write at the end of the document.
+ * This is after the site footer.
+ * To write something before, use a local _footer.php file.
+ */
+ public $footer;
+
+ /**
+ * If true, doesn't print the header
+ * @var boolean
+ */
+ public $noheader = false;
+
+ /**
+ * If true, doesn't print the footer
+ * @var boolean
+ */
+ public $nofooter = false;
+
/**
* Initializes a new instance of Session object
*/
public function __construct ($url) {
$this->url = self::clean_url($url);
$this->get_document();
}
/**
* Finds the document
*/
private function find_document () {
//URL matches an existing file or directory
if (file_exists($this->url)) {
if (is_dir($this->url)) {
//Ensures we've a trailing /
$url = (substr($this->url, -1) == '/') ? $this->url : $this->url . '/';
if (file_exists($url . 'index.html')) {
$this->url = $url . 'index.html';
} elseif (file_exists($url . 'index.php')) {
$this->url = $url . 'index.php';
} else {
return false; //empty directory
}
}
return true;
}
- //Try other extensions
+ //Tries other extensions
$extensions_to_try = array('html', 'php');
$pathinfo = pathinfo($this->url);
foreach ($extensions_to_try as $ext) {
$file = "$pathinfo[dirname]/$pathinfo[filename].$ext";
if (file_exists($file)) {
$this->url = $file;
return true;
}
}
- //Handle homepages
+ //Handles homepages
if ($this->is_homepage($this->url)) {
$this->url = "_index/index.html";
return true;
}
+ //Fixes common problems
+ if (!string_starts_with($_SERVER["REQUEST_URI"], $_SERVER["DOCUMENT_URI"])) {
+ // Webserver hasn't been configured to send directly the query to
+ // $_SERVER["DOCUMENT_URI"]. This is the engine job instead.
+ $file = substr($_SERVER["DOCUMENT_URI"], 1); //Drops initial /
+ if (file_exists($file)) {
+ $this->url = $file;
+ return true;
+ }
+ }
+
return false;
}
/**
* Gets the document matching the URL
*/
private function get_document () {
global $Config;
//Finds the document
if ($this->find_document()) {
$this->status = 200;
} else {
-/*
- print_r($this);
- phpinfo(32);
- die();
-*/
- $this->url = $Config['Errorpage'];
+ $this->url = $Config['Pages']['Error404']; //TODO: choose and document error implementation
$this->status = 404;
}
//Fills info from URL
$pathinfo = pathinfo($this->url);
if (!$this->is_homepage()) {
$this->topic = str_replace('/', '-', $pathinfo['dirname']);
$this->article = $pathinfo['filename']; //PHP 5.2.0+
}
$this->extension = strtolower($pathinfo['extension']);
$this->title = "[$this->article]";
//Fills info from _documents.xml
$this->get_description();
}
/**
* Cleans specified URL
*
* @param string $url the URL to clean
* @return string clean URL
*/
public static function clean_url ($url) {
global $Config;
if ($Config['AllowTopicArticleRequest'] && self::hasTopicArticleRequest()) {
//This legacy mode allows site with 2001 Pluton version like
//espace-win.net to make a smoother transition.
//Cf. www.w3.org/Provider/Style/URI.html Cool URIs don't change
//Topic (?Topic=...)
if (array_key_exists('Topic', $_REQUEST)) {
$url = str_replace('-', '/', $_REQUEST['Topic']) . '/';
}
//Article (&Article=...)
if (array_key_exists('Article', $_REQUEST)) {
$url .= $_REQUEST['Article'];
} else {
$url .= 'index';
}
//Extension (&ext=...)
if (array_key_exists('ext', $_REQUEST)) {
$url .= '.';
$url .= $_REQUEST['ext'];
} else {
$url .= '.html';
}
return $url;
}
//Homepage?
if ($url == '' || $url == '/' || $url == $Config['BaseURL'] || $url == $Config['BaseURL'] . '/') {
return $Config['Homepage'];
}
return substr($url, 1);
}
/**
* Determines if the HTTP request contains Topic, Article or ext parameters
*
* @return bool true if the HTTP request contains Topic, Article or ext parameters ; otherwise, false
*/
public static function hasTopicArticleRequest () {
return array_key_exists('Topic', $_REQUEST) || array_key_exists('Article', $_REQUEST) || array_key_exists('ext', $_REQUEST);
}
/**
* Determines if the current document is the homepage.
*
* @return bool true if the current document is the homepage ; otherwise, false.
*/
public function is_homepage () {
global $Config;
//return $this->url == $Config['Homepage'];
if ( $this->url == $Config['Homepage']) return true;
if ($this->topic == "_index" && substr($this->article, 0, 5) == "index") return true;
return false;
}
/**
* Gets footer file (_footer.php) path in the current or parent directories
*
* @return string the path to the current footer if found ; otherwise, null. (or null if no footer is found)
*/
public function get_footer () {
$dirs = explode('-', $this->topic);
for ($i = count($dirs) ; $i > 0 ; $i--) {
$footer = join($dirs, '/') . '/_footer.php';
if (file_exists($footer)) {
return $footer;
}
array_pop($dirs);
}
return null;
}
/**
- * Prints the document
- *
- * Use this method if you don't wish to have access to any other global
- * variables than $db, $Config, $Session and $CurrentUser.
- *
- * A more flexible method is the body of this method in _includes/body.php
- * and to add in your skin <?php include('_includes/body.php'); ?>
+ * Prints the document body
*/
- public function render () {
+ public function render_body () {
global $db, $Config, $Session, $CurrentUser;
$document = $this;
//404 header
if ($this->status == 404) {
header("Status: 404 Not Found");
}
//Header content
- $header = str_replace('-', '/', $this->topic) . '/_header.php';
- if (file_exists($header)) {
+ if (!$this->noheader) {
+ $header = $this->get_directory() . '/_header.php';
+ if (file_exists($header)) {
include($header);
- }
+ }
+ }
//Includes file
switch ($this->extension) {
case 'txt':
echo "<pre>";
include($this->url);
echo "</pre>";
break;
case 'png':
case 'jpg':
case 'gif':
case 'svg':
case 'bmp':
echo "<div align=center><img src=\"$this->url\" /></div>";
break;
default:
include($this->url);
}
//Footer
- if ($footer = $this->get_footer()) {
+ if (!$nofooter && $footer = $this->get_footer()) {
include($footer);
}
+ }
+ /**
+ * Prints the document
+ *
+ * Use this method if you don't wish to have access to any other global
+ * variables than $db, $Config, $Session and $CurrentUser.
+ *
+ * A more flexible method is the body of this method in _includes/body.php
+ * and to add in your skin <?php include('_includes/body.php'); ?>
+ */
+ function render () {
+ //Global variables for the header and the footer
+ global $db, $Config, $Session, $CurrentUser;
+ $document = $this;
+
+ //HTML output
+ $theme = $Config['Theme'];
+ if (!$this->noheader) include("themes/$theme/header.php");
+ $this->render_body();
+ if (!$this->nofooter) include("themes/$theme/footer.php");
}
/**
* Gets the document description
*/
function get_description () {
+ if ($this->status == 404) {
+ $this->title = "404 Not Found";
+ $this->description = "The requested resource hasn't been found.";
+ return;
+ }
+
if ($description = self::get_description_from_documentsXml($this->topic, $this->article)) {
- $variables = [ 'title', 'description', 'head' ];
+ $variables = [ 'title', 'description', 'head', 'footer' ];
foreach ($variables as $variable) {
if (isset($description->$variable)) {
$this->$variable = (string)$description->$variable;
}
}
+
+ $shortTags = [ 'noheader', 'nofooter' ];
+ foreach ($shortTags as $shortTag) {
+ if (isset($description->$shortTag)) {
+ $this->$shortTag = true;
+ }
+ }
}
}
public static function get_description_from_documentsXml ($topic, $article) {
$topicDocuments = str_replace('-', '/', $topic) . '/_documents.xml';
if (file_exists($topicDocuments)) {
$xml = simplexml_load_file($topicDocuments, null, LIBXML_NOCDATA);
if (is_array($xml->document)) {
$documents = $xml->document;
} else {
$documents = [ $xml->document ];
}
foreach ($documents as $document) {
if ($document->article == $article) {
return $document;
}
}
return null;
}
}
-}
-?>
+ public function get_directory () {
+ return str_replace('-', '/', $this->topic);
+ }
+}
diff --git a/includes/error.php b/includes/error.php
index a730a8c..fad3ae2 100755
--- a/includes/error.php
+++ b/includes/error.php
@@ -1,110 +1,109 @@
<?php
/*
* Keruald, core libraries for Pluton and Xen engines.
* (c) 2010, Sébastien Santoro aka Dereckson, some rights reserved
* Released under BSD license
*
* Error handling
*
* 0.1 2010-02-27 16:00 DcK
*
* @todo add exception handling facilities
*
* There are 3 standard error types:
* - SQL_ERROR error during a sql query
* - HACK_ERROR error trying to access a protected resource
* - GENERAL_ERROR miscelleanous error
*
* The message_die/SQL_ERROR idea were found in phpBB 2 code.
*
* Tip: use HACK_ERROR when an user can't access a page, and edit message_die
* to output a login/pass form if the user isn't logged in, so the user
* will be invited to log in properly and legetimely access to the page.
* (cf. the Pluton's error.php for a sample)
*
* Tip: if you use a MVC model or at least templates, message_die should calls
* an error template but only if the template engine is initialized.
* (cf. the Xen's error.php for a sample)
*
* Tip: evaluate the cost/benefit to output a SQL error to the user and consider
* not to output the sql query or the error code to standard users.
*
* Tip: if you need more help to understand where exactly the error have occured
* consider Advanced PHP debugger: www.php.net/manual/en/book.apd.php
*/
//Error code constants
define ("SQL_ERROR", 65);
define ("HACK_ERROR", 99);
define ("GENERAL_ERROR", 117);
/*
* Prints human-readable information about a variable
* wrapped in a general error and dies
* @param mixed $mixed the variable to dump
*/
function dieprint_r ($var, $title = '') {
if (!$title) $title = 'Debug';
//GENERAL_ERROR with print_r call as message
message_die(GENERAL_ERROR, '<pre>' . print_r($var, true) .'</pre>', $title);
}
/*
* Prints an error message and dies
* @param int $code A constant identifying the type of error (SQL_ERROR, HACK_ERROR or GENERAL_ERROR)
* @param string $text the error description
* @param string $text the error title
* @param int $line the file line the error have occured (typically __LINE__)
* @param string $file the file the error have occured (typically __FILE__)
* @param string $sql the sql query which caused the error
*/
function message_die ($code, $text = '', $title = '', $line = '', $file = '', $sql = '') {
//Ensures we've an error text
$text = $text ? $text : "An error have occured";
//Adds file and line information to error text
if ($file) {
$text .= " — $file";
if ($line) {
$text .= ", line $line";
}
}
//Ensures we've an error title and adds relevant extra information
switch ($code) {
case HACK_ERROR:
$title = $title ? $title : "Access non authorized";
break;
case SQL_ERROR:
global $db;
$title = $title ? $title : "SQL error";
//Gets SQL error information
$sqlError = $db->sql_error();
if ($sqlError['message'] != '') {
$text .= "<br />Error n° $sqlError[code]: $sqlError[message]";
}
$text .= '<br />&nbsp;<br />Query: ';
$text .= $sql;
break;
default:
//TODO: here can be added code to handle error error ;-)
//Falls to GENERAL_ERROR
case GENERAL_ERROR:
$title = $title ? $title : "General error";
break;
}
//HTML output of $title and $text variables
echo '<div class="FatalError"><p class="FatalErrorTitle">', $title,
'</p><p>', $text, '</p></div>';
exit;
}
-?>
\ No newline at end of file
diff --git a/includes/mysql.php b/includes/mysql.php
index 9f0121d..aa43f45 100755
--- a/includes/mysql.php
+++ b/includes/mysql.php
@@ -1,152 +1,151 @@
<?php
/*
* Keruald, core libraries for Pluton and Xen engines.
* (c) 2010, Sébastien Santoro aka Dereckson, some rights reserved
* Released under BSD license
*
* MySQL layer and helper class
*
* 0.1 2010-02-27 1:52 DcK
*
*/
if (!defined('SQL_LAYER')) {
define('SQL_LAYER', 'MySQL');
/*
* SQL layer and helper class: MySQL
*
* @package Keruald
* @subpackage Keruald
* @copyright Copyright (c) 2010, Sébastien Santoro aka Dereckson
* @license Released under BSD license
* @version 0.1
*/
class sql_db {
/*
* @var int the connection identifier
*/
private $id;
/*
* Initializes a new instance of the database abstraction class, for MySQL engine
*/
function __construct($host = 'localhost', $username = '', $password = '', $database = '') {
//Connects to MySQL server
$this->id = @mysql_connect($host, $username, $password) or $this->sql_die();
//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
*/
private 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.");
}
/*
* Sends a unique query to the database
* @return mixed if the query is successful, a result identifier ; otherwise, false
*/
function sql_query ($query) {
return mysql_query($query, $this->id);
}
/*
* Fetches a row of result into an associative array
* @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)) {
//An error have occured
message_die(SQL_ERROR, $error_message, '', '', '', $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);
}
/*
* Set charset
*/
function set_charset ($encoding) {
if (function_exists('mysql_set_charset')) {
//>PHP 5.2.3
mysql_set_charset($encoding, $this->id);
} else {
//TODO: set connection variables to utf8
}
}
}
//Creates an instance of this database class with configuration values
$db = new sql_db($Config['sql']['host'], $Config['sql']['username'], $Config['sql']['password'], $Config['sql']['database']);
//To improve security, we unset sql parameters
unset($Config['sql']);
//Sets SQL connexion in UTF8. PHP 5.2.3+
$db->set_charset('utf8');
}
-?>
\ No newline at end of file
diff --git a/includes/objects/user.php b/includes/objects/user.php
index 23692a8..f12a76e 100755
--- a/includes/objects/user.php
+++ b/includes/objects/user.php
@@ -1,194 +1,192 @@
<?php
/*
* Keruald, core libraries for Pluton and Xen engines.
* (c) 2010, Sébastien Santoro aka Dereckson, some rights reserved
* Released under BSD license
*
* User class
*
* 0.1 2010-02-27 20:51 DcK
*
* @package Keruald
* @subpackage Keruald
* @copyright Copyright (c) 2010, Dereckson
* @license Released under BSD license
* @version 0.1
*
*/
class User {
public $id;
public $name;
public $password;
public $active = 0;
public $email;
public $regdate;
/*
* Initializes a new instance
* @param int $id the primary key
*/
function __construct ($id = null) {
if ($id) {
$this->id = $id;
$this->load_from_database();
}
}
/*
* 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->load_from_row($row);
return true;
}
/*
* Loads the object User (ie fill the properties) from the database row
*/
function load_from_row ($row) {
$this->id = $row['user_id'];
$this->name = $row['username'];
$this->password = $row['user_password'];
$this->active = $row['user_active'] ? true : false;
$this->email = $row['user_email'];
$this->regdate = $row['user_regdate'];
}
/*
* 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 = $this->active ? 1 : 0;
$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_email`, `user_regdate`) VALUES ($id, '$name', '$password', $active, '$email', $regdate)";
if (!$db->sql_query($sql)) {
message_die(SQL_ERROR, "Unable to save user", '', __LINE__, __FILE__, $sql);
}
if (!$this->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 = mt_rand(2001, 9999);
$sql = "SELECT COUNT(*) FROM " . TABLE_USERS . " WHERE user_id = $this->id";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't check if a user id is free", '', __LINE__, __FILE__, $sql);
}
$row = $db->sql_fetchrow($result);
} while ($row[0]);
}
/*
* Fills password field with encrypted version
* of the specified clear password
*/
public function set_password ($newpassword) {
$this->password = md5($newpassword);
}
/*
* Checks if a login is available
* @param string $login the login to check
* @return boolean true if the login is avaiable ; otherwise, false.
*/
public static function is_available_login ($login) {
global $db;
$sql = "SELECT COUNT(*) FROM " . TABLE_USERS . " WHERE username = '$login'";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't check if the specified login is available", '', __LINE__, __FILE__, $sql);
}
$row = $db->sql_fetchrow($result);
return ($row[0] == 0);
}
/*
* Initializes a new User instance ready to have its property filled
* @return User the new user instance
*/
public static function create () {
$user = new User();
$user->generate_id();
$user->active = true;
return $user;
}
/*
* Gets user from specified e-mail
* @return User the user matching the specified e-mail ; null, if the mail were not found.
*/
public static function get_user_from_email ($mail) {
global $db;
$sql = "SELECT username FROM " . TABLE_USERS . " WHERE user_email = '$mail'";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't get user", '', __LINE__, __FILE__, $sql);
}
if ($row = $db->sql_fetchrow($result)) {
//E-mail found.
$user = new User();
$user->load_from_row($row);
return $user;
}
//E-mail not found.
return null;
}
}
-
-?>
\ No newline at end of file
diff --git a/includes/session.php b/includes/session.php
index 6508411..32b860d 100755
--- a/includes/session.php
+++ b/includes/session.php
@@ -1,250 +1,248 @@
<?php
/*
* Keruald, core libraries for Pluton and Xen engines.
* (c) 2010, Sébastien Santoro aka Dereckson, some rights reserved
* Released under BSD license
*
* Session
*
* 0.1 2010-02-26 18:06 DcK
*
* This class uses a singleton pattern, as we only need one single instance.
* Cf. http://www.php.net/manual/en/language.oop5.patterns.php
*
* @package Keruald
* @subpackage Keruald
* @copyright Copyright (c) 2010, Sébastien Santoro aka Dereckson
* @license Released under BSD license
* @version 0.1
*/
class Session {
/*
* @var Session current session instance
*/
private static $instance;
/*
* Gets or initializes current session instance
* @return Session current session instance
*/
public static function load () {
if (!isset(self::$instance)) {
//Creates new session instance
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
/*
* @var string session ID
*/
public $id;
/*
* @var string remote client IP
*/
public $ip;
/*
* Initializes a new instance of Session object
*/
private function __construct () {
//Starts PHP session, and gets id
session_start();
$_SESSION['ID'] = session_id();
$this->id = $_SESSION['ID'];
//Gets remote client IP
$this->ip = self::get_ip();
//Updates or creates the session in database
$this->update();
}
/*
* Gets remote client IP address
* @return string IP
*/
public static function get_ip () {
//mod_proxy + mod_rewrite (old pluton url scheme) will define 127.0.0.1
//in REMOTE_ADDR, and will store ip in HTTP_X_FORWARDED_FOR variable.
//Some ISP/orgz proxies also use this setting.
if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
return $_SERVER['HTTP_X_FORWARDED_FOR'];
}
//Standard cases
return $_SERVER['REMOTE_ADDR'];
}
/*
* Cleans up session
* i. deletes expired session
* ii. sets offline relevant sessions
*/
public static function clean_old_sessions () {
global $db, $Config;
//Gets session and online status lifetime (in seconds)
//If not specified in config, sets default 5 and 120 minutes values
$onlineDuration = array_key_exists('OnlineDuration', $Config) ? $Config['OnlineDuration'] : 300;
$sessionDuration = array_key_exists('SessionDuration', $Config) ? $Config['SessionDuration'] : 7200;
$resource = array_key_exists('ResourceID', $Config) ? '\'' . $db->sql_escape($Config['ResourceID']) . '\'' : 'default';
//Deletes expired sessions
$sql = "DELETE FROM " . TABLE_SESSIONS . " WHERE session_resource = $resource AND TIMESTAMPDIFF(SECOND, session_updated, NOW()) > $sessionDuration";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Can't delete expired sessions", '', __LINE__, __FILE__, $sql);
//Online -> offline
$sql = "UPDATE " . TABLE_SESSIONS . " SET session_online = 0 WHERE TIMESTAMPDIFF(SECOND, session_updated, NOW()) > $onlineDuration AND session_resource = $resource";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, 'Can\'t update sessions online statuses', '', __LINE__, __FILE__, $sql);
}
/*
* Updates or creates a session in the database
*/
public function update () {
global $db, $Config;
//Cleans up session
//To boost SQL performances, try a random trigger
// e.g. if (rand(1, 100) < 3) self::clean_old_sessions();
//or comment this line and execute a cron script you launch each minute.
self::clean_old_sessions();
//Saves session in database.
//If the session already exists, it updates the field online and updated.
$id = $db->sql_escape($this->id);
$resource = array_key_exists('ResourceID', $Config) ? '\'' . $db->sql_escape($Config['ResourceID']) . '\'' : 'default';
$user_id = $db->sql_escape(ANONYMOUS_USER);
$sql = "INSERT INTO " . TABLE_SESSIONS . " (session_id, session_ip, session_resource, user_id) VALUES ('$id', '$this->ip', $resource, '$user_id') ON DUPLICATE KEY UPDATE session_online = 1";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, 'Can\'t save current session', '', __LINE__, __FILE__, $sql);
}
/*
* Gets the number of online users
* @return int the online users count
*/
public function count_online () {
//Keeps result for later method call
static $count = -1;
if ($count == -1) {
//Queries sessions table
global $db, $Config;
$resource = array_key_exists('ResourceID', $Config) ? '\'' . $db->sql_escape($Config['ResourceID']) . '\'' : 'default';
$sql = "SELECT count(*) FROM " . TABLE_SESSIONS . " WHERE session_resource = $resource AND session_online = 1";
$count = (int)$db->sql_query_express($sql, "Can't count online users");
}
//Returns number of users online
return $count;
}
/*
* Gets the value of a custom session table field
* @param string $info the field to get
* @return string the session specified field's value
*/
public function get_info ($info) {
global $db;
$id = $db->sql_escape($this->id);
$sql = "SELECT `$info` FROM " . TABLE_SESSIONS . " WHERE session_id = '$id'";
return $db->sql_query_express($sql, "Can't get session $info info");
}
/*
* Sets the value of a custom session table field to the specified value
* @param string $info the field to update
* @param string $value the value to set
*/
public function set_info ($info, $value) {
global $db;
$value = ($value === null) ? 'NULL' : "'" . $db->sql_escape($value) . "'";
$id = $db->sql_escape($this->id);
$sql = "UPDATE " . TABLE_SESSIONS . " SET `$info` = $value WHERE session_id = '$id'";
if (!$db->sql_query($sql))
message_die(SQL_ERROR, "Can't set session $info info", '', __LINE__, __FILE__, $sql);
}
/*
* Gets logged user information
* @return User the logged user information
*/
public function get_logged_user () {
global $db;
//Gets session information
$id = $db->sql_escape($this->id);
$sql = "SELECT * FROM " . TABLE_SESSIONS . " WHERE session_id = '$id'";
if (!$result = $db->sql_query($sql))
message_die(SQL_ERROR, "Can't query session information", '', __LINE__, __FILE__, $sql);
$row = $db->sql_fetchrow($result);
//Gets user instance
require_once('includes/objects/user.php');
$user = new User($row['user_id']);
//Adds session property to this user instance
$user->session = $row;
//Returns user instance
return $user;
}
/*
* Cleans session
* This method is to be called when an event implies a session destroy
*/
public function clean () {
//Destroies $_SESSION array values, help ID
foreach ($_SESSION as $key => $value) {
if ($key != 'ID') unset($_SESSION[$key]);
}
}
/*
* Updates the session in an user login context
* @param string $user_id the user ID
*/
public function user_login ($user_id) {
global $db;
//Sets specified user ID in sessions table
$user_id = $db->sql_escape($user_id);
$id = $db->sql_escape($this->id);
$sql = "UPDATE " . TABLE_SESSIONS . " SET user_id = '$user_id' WHERE session_id = '$id'";
if (!$db->sql_query($sql))
message_die(SQL_ERROR, "Can't set logged in status", '', __LINE__, __FILE__, $sql);
}
/*
* Updates the session in an user logout context
*/
public function user_logout () {
global $db;
//Sets anonymous user in sessions table
$user_id = $db->sql_escape(ANONYMOUS_USER);
$id = $db->sql_escape($this->id);
$sql = "UPDATE " . TABLE_SESSIONS . " SET user_id = '$user_id' WHERE session_id = '$id'";
if (!$db->sql_query($sql))
message_die(SQL_ERROR, "Can't set logged out status", '', __LINE__, __FILE__, $sql);
//Cleans session
$this->clean();
}
}
//The user_id matching anonymous user
if (!defined('ANONYMOUS_USER')) define('ANONYMOUS_USER', -1);
-
-?>
\ No newline at end of file
diff --git a/index.php b/index.php
index a5355b0..bbfc041 100755
--- a/index.php
+++ b/index.php
@@ -1,65 +1,68 @@
<?php
-/*
+/**
* Keruald, core libraries for Pluton and Xen engines.
* (c) 2010, Sébastien Santoro aka Dereckson, some rights reserved
* Released under BSD license
*
* Application entry point
*
* Keruald is mainly a repository for common libraries elements between
* engines like Pluton (content-oriented site) and Xen (MVC).
*
* You should consider to start with one of those.
*
*/
////////////////////////////////////////////////////////////////////////////////
///
/// Initialization
///
+define('IN_KERUALD', true);
+define('IN_PLUTON', true);
+
//Keruald libraries
include('includes/core.php');
//Pluton libraries
include('includes/document.php');
+//Site libraries
+include('includes/core2.php');
+
////////////////////////////////////////////////////////////////////////////////
///
/// Session
///
//[TODO] If your session contains classes, and you don't implement __autoload,
//you've to require those items before session_start();
//You can implement this here or in _includes/sessions.php
//Starts a new session or recovers current session
$Session = Session::load();
//Handles login or logout
//include("includes/login.php");
//Gets current user information
$CurrentUser = $Session->get_logged_user();
////////////////////////////////////////////////////////////////////////////////
///
/// Your application initialization logic
///
//[TODO] Loads your template engine or prepares the document to print
//[TODO] Loads languages file if you're into L10n
////////////////////////////////////////////////////////////////////////////////
///
/// Serves the requested page
///
$url = get_current_url();
-$theme = $Config['Theme'];
-$document = new Document($url);
-include("themes/$theme/header.php");
+$document = new Document($url);
$document->render();
-include("themes/$theme/footer.php");
diff --git a/stylesheets/app.css b/stylesheets/app.css
index fd7a647..594ff8c 100644
--- a/stylesheets/app.css
+++ b/stylesheets/app.css
@@ -1,213 +1,246 @@
@charset "utf-8";
/* -------------------------------------------------------------
Zed
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Author: Dereckson
Tags: Foundation, red, gray, Ralf Lauren, vintage
Filename: app.css
Version: 1.0
Created: 2013-01-16
Updated: 2013-01-16
Licence: Creative Commons BY 3.0
------------------------------------------------------------- */
/* -------------------------------------------------------------
Table of contents
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
:: Main styles
:: Header
:: Content
:: Footer
:: Dark variation
:: Typography
:: Foundation Icons Fonts
*/
/* -------------------------------------------------------------
Main styles
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
body {
background-color: #703030;
font-family: 'Source Sans Pro', sans-serif;
}
h1, h2, h3, h4, h5, h6 {
font-family: 'Source Sans Pro', sans-serif;
font-weight: 300;
}
h1, h3, h4, h5, h6 {
}
/* -------------------------------------------------------------
Header
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
body {
background-image: url(/images/RalfFallsIntoFoundation/topborder.png);
background-repeat: repeat-x;
margin-top: 1.25em;
margin-bottom: 0;
}
header {
background-color: #2F343B;
background-image: url(/images/patterns/square_bg.png);
color: white
}
header h1 {
color: #7E827A;
font-size: 37px;
}
header a {
color: white;
}
/* -------------------------------------------------------------
Content
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#content {
background-image: url(/images/RalfFallsIntoFoundation/contentborder.png);
background-repeat: repeat-x;
background-color: white;
padding-top: 1em;
margin-bottom: 0;
min-height: 400px;
}
+.justify p {
+ text-align: justify;
+}
+
+.accordion h4, .accordion h5, .accordion h6 {
+ color: black;
+}
+
/* -------------------------------------------------------------
Footer
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
footer {
background-image: url(/images/RalfFallsIntoFoundation/footerborder.png);
background-repeat: repeat-x;
background-color: white;
margin-bottom: 0;
padding-top: 2em;
background-color: #703030;
color: white;
font-family: 'Source Sans Pro', sans-serif;
font-weight: 400;
}
footer hr {
width: 75%;
height: 1px;
margin: 0em auto 1em auto;
background: url(/images/RalfFallsIntoFoundation/hr.png) top center;
background-repeat: no-repeat;
border: none !important;
}
footer a {
color: #D6BCB1;
}
footer a:hover {
color: #C77966;
}
footer a:active {
color: #A35636;
}
footer dl {
font-variant: small-caps;
}
footer dt {
color: white;
font-weight: 600;
}
footer dd {
padding-left: 1em;
}
.extrainfos {
}
footer .extrainfos strong {
font-variant: small-caps;
}
/* -------------------------------------------------------------
Dark variation
Dedicated to André Bertrand.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#content.dark {
background-color: black;
background-image: none;
}
.dark .row {
color: #7E827A;
}
.dark h2 {
font-weight: 200;
color: #C77966;
}
.dark h3 {
color: #E3CDA4;
}
+.dark h4, h5, h6 {
+ color: #7E827A;
+}
+
+.dark a {
+ color: #D6BCB1;
+}
+
+.dark a:hover {
+ color: #C77966;
+}
+
+.dark a:active {
+ color: #A35636;
+}
+
+.dark hr {
+ background-color: #101010;
+ border: none;
+ height: 1px;
+}
+
+.dark .accordion a {
+ color: #2F343B;
+}
+
footer.dark {
background-image: url(/images/RalfFallsIntoFoundation/footerborder.png);
}
/* -------------------------------------------------------------
Typography
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
.ampersand {
font-family: 'Caslon Ampersand';
margin-right: 0.1em;
}
-
/* -------------------------------------------------------------
Foundation Icons Fonts
www.zurb.com/playground/foundation-icons
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
[class*="social foundicon-"]:before { font-family: "SocialFoundicons"; }
[class*="general foundicon-"]:before { font-family: "GeneralFoundicons"; }
[class*="gen-enclosed foundicon-"]:before { font-family: "GeneralEnclosedFoundicons"; }
[class*="accessibility foundicon-"]:before { font-family: "AccessibilityFoundicons"; }
i {
font-style: normal;
}
i:hover {
color: #703030;
}
footer i:hover {
color: #2F343B;
}
#action-icons {
padding: 1em 1em;
font-size: 2em;
float: right;
}
header h1 i {
margin-right: 0.25em;
color: #C77966;
}
diff --git a/themes/RalfFallsIntoFoundation/footer.php b/themes/RalfFallsIntoFoundation/footer.php
index de10128..d73ab31 100755
--- a/themes/RalfFallsIntoFoundation/footer.php
+++ b/themes/RalfFallsIntoFoundation/footer.php
@@ -1,59 +1,60 @@
</div></section>
<!-- Footer -->
<footer><div class="row">
<div class="twelve columns"><hr />
<div class="row">
<div class="three columns">
<p>This site is a repository of tools.</p>
<p>This is also an experiment to create a site based on Pluton, Foundation, Hg <span class="ampersand">&</span> Nasqueron.</p>
</div>
<div class="three columns">
<dl>
<dt>Gerrit</dt>
- <dd>Activity feeds</dd>
+ <dd><a href="/wikimedia/dev/feeds/">Activity feeds</a></dd>
<dd>RSS generator</dd>
</dl>
</div>
<div class="three columns">
<dl>
<dt>Network</dt>
<dd><a href="/network/mx.php">MX</a></dd>
</dl>
</div>
<div class="three columns">
<dl>
<dt>Gadgets</dt>
<dd><a href="/gadgets/motd-variations.php">MOTD in Jive <span class="ampersand">&</span> Valspeak</a></dd>
</dl>
</div>
</div>
</div>
<div class="twelve columns"><hr />
<div class="row extrainfos">
<div class="six columns">
<p><i class="general foundicon-settings"></i> <strong>Options:</strong> <a href="javascript:SetUITonality('dark');">dark mode</a> | <a href="javascript:SetUITonality('light');">light mode</a></p>
</div>
</div>
<div class="row extrainfos">
<div class="seven columns">
- <p><i class="general foundicon-globe"></i> <strong>Service author:</strong> <a href="http://www.dereckson.be/">Dereckson</a> | <strong>Powered by</strong> <a href="http://keruald.sf.net">Keruald/Pluton</a> <span class="ampersand">&</span> <a href="http://foundation.zurb.com/">Foundation</a>.</p>
+ <p><i class="general foundicon-globe"></i> <strong>Crafted by</strong> <a href="http://www.dereckson.be/">Dereckson</a> | <strong>Powered by</strong> <a href="http://keruald.sf.net">Keruald/Pluton</a> <span class="ampersand">&</span> <a href="http://foundation.zurb.com/">Foundation</a>.</p>
</div>
<div class="five columns">
<ul class="link-list right">
<li><a href="http://www.dereckson.be/tools">DcK Area's tools</a></li>
<li><a href="http://www.espace-win.org/Tools">Espace Win's tools</a></li>
<li><a href="http://www.toolserver.org/~dereckson/">Toolserver</a></li>
</ul>
</div>
</div>
</div>
</div></footer>
<script src="/javascripts/foundation.min.js"></script>
<script src="/javascripts/jquery.cookie.js"></script>
<script src="/javascripts/app.js"></script>
+ <?= $document->footer ?>
</body>
</html>
diff --git a/themes/RalfFallsIntoFoundation/header.php b/themes/RalfFallsIntoFoundation/header.php
index 373ae0a..8562730 100755
--- a/themes/RalfFallsIntoFoundation/header.php
+++ b/themes/RalfFallsIntoFoundation/header.php
@@ -1,60 +1,60 @@
<!DOCTYPE html>
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
<!--[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" />
<!-- Set the viewport width to device width for mobile -->
<meta name="viewport" content="width=device-width" />
<title><?= $document->title ?> - Tools</title>
<!-- Included CSS Files (Uncompressed) -->
<!--
<link rel="stylesheet" href="/stylesheets/foundation.css">
-->
<!-- Included CSS Files (Compressed) -->
<link rel="stylesheet" href="/stylesheets/foundation.min.css">
<script src="javascripts/modernizr.foundation.js"></script>
<link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,600,400italic' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="/stylesheets/general_foundicons.css">
<link rel="stylesheet" href="/stylesheets/general_enclosed_foundicons.css">
<link rel="stylesheet" href="/stylesheets/social_foundicons.css">
<link rel="stylesheet" href="/stylesheets/accessibility_foundicons.css">
<!--[if lt IE 8]>
<link href="/stylesheets/general_foundicons_ie7.css" media="screen" rel="stylesheet" type="text/css" />
<link href="/stylesheets/general_enclosed_foundicons_ie7.css" media="screen" rel="stylesheet" type="text/css" />
<link href="/stylesheets/social_foundicons_ie7.css" media="screen" rel="stylesheet" type="text/css" />
<link href="/stylesheets/accessibility_foundicons_ie7.css" media="screen" rel="stylesheet" type="text/css" />
<![endif]-->
<link rel="stylesheet" href="/stylesheets/caslon_ampersand.css">
<link rel="stylesheet" href="/stylesheets/app.css">
<?= $document->head ?>
</head>
<body>
<!-- Header -->
<header>
<div class="row">
<div class="twelve columns">
<h1><a href="/"><i class="general foundicon-tools"></i></a><?= $document->title ?></h1>
</div>
</div>
<div class="row">
<div class="six columns">
- <p><i class="accessibility foundicon-question"></i><br />
+ <?php if ($document->description) echo '<p><i class="accessibility foundicon-question"></i><br />'; ?>
<?= $document->description ?>
</p>
</div>
<div class="six columns">
<p class="right"><a href="/"><i class="accessibility foundicon-braille"></i></a><br />
Tools — <em>Small utilities, gadgets and scripts to perform daily tasks.</em></p>
</div>
</div>
</header>
<!-- Body -->
- <section id="content"><div class="row">
+ <section id="content"<?php if (isset($_COOKIE["UITonality"]) && $_COOKIE["UITonality"] != "light") { echo " class=\"$_COOKIE[UITonality]\""; } ?>><div class="row">

File Metadata

Mime Type
text/x-diff
Expires
Mon, Nov 25, 19:30 (4 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2260856
Default Alt Text
(61 KB)

Event Timeline