commit e68abb6abc2ac2a1cef359cbce41b96231193201
Author: Jocelyn Delande <jocelyn at delalande dot fr>
Date:   Wed Dec 18 14:17:24 2013 +0100

    first steps of add_reference.php webservice : input validation/sanitization and RefPoint class

diff --git a/ajax/add_reference.php b/ajax/add_reference.php
new file mode 100644
index 0000000..c177376
--- /dev/null
+++ b/ajax/add_reference.php
@@ -0,0 +1,30 @@
+<?php
+require_once('../class/FormValidator.class.php');
+require_once('../class/RefPoint.class.php');
+require_once('../class/site_point.class.php');
+
+$fields_spec = array('x'         => array('required', 'numeric', 'positive'),
+                     'y'         => array('required', 'numeric', 'positive'),
+                     'panorama'  => array('required'),
+                     'ref_point' => array('required'));
+
+
+$validator = new FormValidator($fields_spec);
+if ($validator->validate($_REQUEST)) {
+  $vals = $validator->sane_values();
+
+  // temp test code
+  echo '<h1>pano !</h1>';
+  $pano = site_point::get($vals['panorama']);
+  var_dump($pano->get_params());
+
+  echo '<h1>ref point !</h1>';
+  $ref_point_name = urldecode($vals['ref_point']);
+  var_dump(RefPoint::get($ref_point_name));
+
+ } else {
+   echo var_dump($validator->errors());
+ }
+
+// Test url : clear ;curl 'http://localhost/~jocelyn/panorama/ajax/add_reference.php?x=42&y=42&panorama=pano_couttolenc_bords_jointifs&ref_point=%C3%89glise%20saint-jacques'
+?>
diff --git a/class/FormValidator.class.php b/class/FormValidator.class.php
new file mode 100644
index 0000000..dffc1bd
--- /dev/null
+++ b/class/FormValidator.class.php
@@ -0,0 +1,114 @@
+<?php
+
+class FieldValidationError extends Exception {}
+
+class FormValidator {
+	/* A tool to validate the parameters of a request (GET/POST) against a set
+	 * of rules.
+	 *
+	 **/
+	private $errors;
+	private $sanitized;
+	public static $validator;
+  public static $field_validators;
+  private $format;
+
+	public function __construct($format) {
+		$this->errors = array();
+		$this->sanitized = array();
+    $this->format = $format;
+	}
+
+	public function validate($request) {
+		/** Validate the given request
+		 *  value dict against the validator rules.
+		 *
+		 * @param $request a dict like $_REQUEST, $_GET or $_POST
+		 * @returns true if valid, false else.
+		 */
+		$this->errors = array();
+		$sanitized = array();
+		foreach($this->format as $fieldname => $validators) {
+			$err = false;
+			$sanitized_f = false;
+			foreach($validators as $validator) {
+				if ($validator == 'required') {
+					if (! isset($request[$fieldname])) {
+						$err = 'n\'est pas renseigné';
+						break;
+					} else {
+						$sanitized_f = $request[$fieldname];
+					}
+				} else {
+					$val = $request[$fieldname];
+					try {
+						$sanitized_f = $this->validate_field($validator, $val);
+					} catch (FieldValidationError $e) {
+						$err = $e->getMessage();
+						break;
+					}
+				}
+			}
+			if ($err) {
+				$this->errors[$fieldname] = $err;
+			} else {
+				$sanitized[$fieldname] = $sanitized_f;
+			}
+		}
+		$this->sanitized = $sanitized;
+
+		return ($err == false);
+	}
+
+	public function validate_field($validator, $content) {
+		/** Returns sanitized value if ok, throws a FieldValidationError otherwise
+		 */
+		if (isset(self::$field_validators[$validator])) {
+			$f = self::$field_validators[$validator];
+			return $f($content);
+		} else {
+			throw new FieldValidationError("'$validator' validator does not exist");
+		}
+	}
+
+	public function errors() {
+		/** An associative array form-key => error
+		 */
+		return $this->errors;
+	}
+
+	public function sane_values() {
+		return $this->sanitized;
+	}
+
+	public static function register($name, $function) {
+		self::$field_validators[$name] = $function;
+	}
+}
+FormValidator::$field_validators = array();
+
+
+FormValidator::register(
+  'numeric',
+  function ($v) {
+	  $sanitized = floatval($v);
+    if ($sanitized === false) {
+	  	throw new FieldValidationError('n\'est pas une valeur numérique');
+	  } else {
+		  return $sanitized;
+	  }
+  }
+);
+
+FormValidator::register(
+  'positive',
+  function ($v) {
+	  if ($v < 0) {
+		  throw new FieldValidationError('est négatif');
+	  } else {
+		  return floatval($v);
+	  }
+  }
+);
+
+?>
diff --git a/class/RefPoint.class.php b/class/RefPoint.class.php
new file mode 100644
index 0000000..6f68852
--- /dev/null
+++ b/class/RefPoint.class.php
@@ -0,0 +1,28 @@
+<?php
+require_once(dirname(__FILE__).'/../constants.inc.php');
+
+//
+class RefPoint {
+  static $all_ref_points_cache;
+
+  public static function load_if_needed() {
+    if (!isset(self::$all_ref_points_cache)) {
+      $ref_points_filename = '../ref_points.local.php';
+	  if (file_exists($ref_points_filename)) {
+	    require($ref_points_filename);
+        self::$all_ref_points_cache = $ref_points;
+	    return $ref_points;
+	  } else {
+	    return array();
+      }
+    }
+   return self::$all_ref_points_cache;
+  }
+
+  public static function get($name) {
+    self::load_if_needed();
+    return self::$all_ref_points_cache[$name];
+  }
+
+}
+?>
