From acbb8dff1439b0d05709a93fff356e7f6b829da6 Mon Sep 17 00:00:00 2001
From: Ludovic Pouzenc <lpouzenc@gmail.com>
Date: Wed, 30 Oct 2013 14:04:56 +0100
Subject: INI et Unicode. Avancée sur fonctions AJAX et trados.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 code/admin/add.php    |  4 ++--
 code/admin/admin.js   |  3 ++-
 code/admin/ajax.php   |  9 +++++----
 code/admin/render.php | 17 +++++++----------
 code/admin/utils.php  | 35 ++++++++++++++++++++++++-----------
 5 files changed, 40 insertions(+), 28 deletions(-)

(limited to 'code/admin')

diff --git a/code/admin/add.php b/code/admin/add.php
index 0869dd5..cb2ff16 100644
--- a/code/admin/add.php
+++ b/code/admin/add.php
@@ -10,7 +10,7 @@
 	l10n_init($site_conf['site_admin_lang']);
 
 	// URL parameter parsing
-	$kind = sanitize($_GET, 'kind', '/[^a-z_]+/', 'page'); /* Could be : page, media */
+	$kind = sanitize($_GET, 'kind', RE_IDENTIFIER_CLEANER, 'page'); /* Could be : page, media */
 
 	// Pre-computed because used twice
 	$page_title = _('Admin') . ' - ' . ( ($kind=='media')?_('Add a media'):_('Add a page') );
@@ -43,7 +43,7 @@
 </fieldset>
 
 <fieldset>
-<legend><?=($kind=='media')?_('Media folder'):_('Page folder')?></legend>
+<legend><?=_('Selected folder')?></legend>
 <label for="fold_path"><?=_('Folder path')?></label>
 <input id="fold_path" name="fold_path" readonly="readonly" value="<?=_('(choose a folder in the tree)')?>"><br>
 
diff --git a/code/admin/admin.js b/code/admin/admin.js
index 669658d..9c2536e 100644
--- a/code/admin/admin.js
+++ b/code/admin/admin.js
@@ -57,10 +57,11 @@ function save_page_props() {
 	microAjaxJSON(url, function (parsed_json) {
 		if ( parsed_json.result != "OK" ) {
 			alert("Error\nResult: " + parsed_json.result + "\nRequest: " + url);
-			return;
 		}
 		//TODO : says to user that the work is done
 	});
+
+	load_page_props(path);
 }
 
 function save_media_props() {
diff --git a/code/admin/ajax.php b/code/admin/ajax.php
index 0893843..fd6dab5 100644
--- a/code/admin/ajax.php
+++ b/code/admin/ajax.php
@@ -15,11 +15,12 @@
 	}
 
 	function save_page_props($path) {
-		//TODO : Should validate props here also...
 		$props=load_page_props($path);
 
 		foreach ( array('page_title', 'page_description', 'page_keywords') as $k ) {
-			if ( array_key_exists($k,$_GET) ) $props[$k]=$_GET[$k];
+			if ( array_key_exists($k,$_GET) ) {
+				$props[$k]= sanitize($_GET, $k, RE_TEXT_LINE_CLEANER, '');
+			}
 		}
 
 		$ini_path="content/$path/props.ini";
@@ -31,8 +32,8 @@
 	}
 
 	// URL params clean-up
-	$action=sanitize($_GET, 'action', '/[^a-z_]+/', 'none'); /* Could be : load_page_props, load_media_props... */
-	$path=sanitize($_GET, 'path', '/[^a-z0-9\/]+/', ''); // Never put \. in this regex
+	$action=sanitize($_GET, 'action', RE_IDENTIFIER_CLEANER, 'none'); /* Could be : load_page_props, load_media_props... */
+	$path = sanitize($_GET, 'path', RE_RELPATH_CLEANER, ''); 
 
 	switch($action) {
 		case 'load_page_props':
diff --git a/code/admin/render.php b/code/admin/render.php
index 2d49f01..0492224 100644
--- a/code/admin/render.php
+++ b/code/admin/render.php
@@ -6,18 +6,15 @@
 	if ( ! is_array($site_conf) ) trigger_error("Error parsing site_conf.ini", E_USER_ERROR);
 
 	if (PHP_SAPI === 'cli') {
-		// In cli mode, take args from the command line
-		$params=array(
-			'action' => 'publish',
-			'page' => $argv[1]
-		);
+		// In cli mode, take page name from the command line (publish only)
+		$action='publish';
+		$page = sanitize($argv, 1, RE_RELPATH_CLEANER, '');
 	} else {
-		// In web mode, take from args from GET request
-		$params=&$_GET;
+		// In web mode, enforce authentication and take from args from GET request
+		need_auth();
+		$action=sanitize($_GET, 'action', RE_IDENTIFIER_CLEANER, 'preview'); /* Could be : preview, edit, publish */
+		$page = sanitize($_GET, 'page', RE_RELPATH_CLEANER, $site_conf['site_default_page']);
 	}
-	// params clean-up
-	$action=sanitize($params, 'action', '/[^a-z_]+/', 'preview'); /* Could be : preview, edit, publish */
-	$page=sanitize($params, 'page', '/[^a-z0-9\/]+/', $site_conf['site_default_page']); // Never put \. in this regex
 
 	// Template vars init ($page, $page_path, $page_props, $page_tpl_url)
 	$page_path = "content/$page"; 
diff --git a/code/admin/utils.php b/code/admin/utils.php
index f02146a..9612535 100644
--- a/code/admin/utils.php
+++ b/code/admin/utils.php
@@ -1,4 +1,9 @@
 <?php
+	define('RE_TEXT_LINE_CLEANER', '/["\p{C}\p{Zl}\p{Zp}]+/u');
+	define('RE_IDENTIFIER_CLEANER', '/[^a-zA-Z0-9_]+/');
+	define('RE_LANG_IDENT_CLEANER', '/[^a-zA-Z\/\_-]+/');
+	define('RE_RELPATH_CLEANER', '/[^a-zA-Z0-9_\/-]+/'); // Never put \. in this regex
+
 	function sanitize($arg_array, $arg_key, $replace_chars_re, $default_value) {
 		//FIXME :  should check string type and strlen !
 		if ( ! array_key_exists($arg_key, $arg_array) ) return $default_value;
@@ -33,20 +38,21 @@
 
 	function load_ini_site_conf($ini_path) {
 		$sanitize_site_conf = array(
-			'site_admin_lang' => array( 'replace_chars_re' => '/[^a-zA-Z\/\_-]+/', 'default_value' => 'C' ),
-			'site_default_page' => array( 'replace_chars_re' => '/[^a-z0-9\/]+/', 'default_value' => 'en/index' ),
+			'site_admin_lang'	=> array( 'replace_chars_re' => RE_LANG_IDENT_CLEANER, 'default_value' => 'C' ),
+			'site_default_page'	=> array( 'replace_chars_re' => RE_RELPATH_CLEANER, 'default_value' => 'en/index' ),
 		);
 		return sanitize_ini($ini_path, $sanitize_site_conf);
 	}
 
 	function load_ini_page_props($page) {
+		
 		$sanitize_page_props = array(
 			//FIXME : title regex : all but html special chars ?
-			'page_title'    => array( 'replace_chars_re' => '/[^\w !_,.-]+/', 'default_value' => '(missing title in props.ini)' ),
-			'page_template' => array( 'replace_chars_re' => '/[^a-z0-9]+/', 'default_value' => 'default' ),
-			'page_layout'   => array( 'replace_chars_re' => '/[^a-z0-9]+/', 'default_value' => 'article' ),
-			'page_description' => array( 'replace_chars_re' => '/[^\w !_,.-]+/', 'default_value' => '(missing description in props.ini)' ),
-			'page_keywords'    => array( 'replace_chars_re' => '/[^\w !_,.-]+/', 'default_value' => '(missing keywords in props.ini)' ),
+			'page_template'		=> array( 'replace_chars_re' => RE_IDENTIFIER_CLEANER, 'default_value' => 'default' ),
+			'page_layout'   	=> array( 'replace_chars_re' => RE_IDENTIFIER_CLEANER, 'default_value' => 'article' ),
+			'page_title'		=> array( 'replace_chars_re' => RE_TEXT_LINE_CLEANER, 'default_value' => '(missing)' ),
+			'page_description'	=> array( 'replace_chars_re' => RE_TEXT_LINE_CLEANER, 'default_value' => '(missing)' ),
+			'page_keywords'		=> array( 'replace_chars_re' => RE_TEXT_LINE_CLEANER, 'default_value' => '(missing)' ),
 		);
 		$ini_path="content/$page/props.ini";
 		return sanitize_ini($ini_path, $sanitize_page_props);
@@ -136,10 +142,12 @@
 
 	function safe_put_file($path, $content) {
 		//FIXME : if exists, then mktemp, put in it then rm and mv. Right preservation problems ?
+		$res=FALSE;
 		if ($handle = fopen($path, 'w')) {
 			$res = fwrite($handle, $content);
 			fclose($handle);
 		}
+		return $res;
 	}
 
 	function _write_ini_file_r(&$content, $assoc_arr, $has_sections)
@@ -158,10 +166,13 @@
 					}
 				}
 			} else {
-				if ( preg_match('/^\w+$/',$val)===1 )
+				if ( preg_match(RE_IDENTIFIER_CLEANER,$val)===1 ) {
+					// Need to quote the value
+					$content .= "$key = \"" . str_replace('"', '', $val) . "\"\n";
+				} else {
+					// No need to quote
 					$content .= "$key = $val\n";
-				else
-					$content .= "$key = \"" . str_replace('"', '\"', $val) . "\"\n";
+				}
 			}
 		}
 	}
@@ -170,8 +181,10 @@
 		$res=FALSE;
 		$content = '';
 		_write_ini_file_r($content, $assoc_arr, $has_sections);
+
 		if (is_string($content) && strlen($content) > 0) {
-			safe_put_file($path, $content);
+			//TODO : check if produced ini is readable again !
+			$res = safe_put_file($path, $content);
 		}
 
 		return $res;
-- 
cgit v1.2.3