]> dev.renevier.net Git - syp.git/blobdiff - api.php
real api and clearer separation between server and client
[syp.git] / api.php
diff --git a/api.php b/api.php
new file mode 100644 (file)
index 0000000..93f27bd
--- /dev/null
+++ b/api.php
@@ -0,0 +1,287 @@
+<?php
+/* Copyright (c) 2009 Arnaud Renevier, Inc, published under the modified BSD
+   license. */
+
+require_once ("./inc/settings.php");
+require_once ("./inc/db/mysql.php");
+require_once ("./inc/utils.php");
+
+function exit_document ($body) {
+    exit ("<html><head></head><body>$body</body></html>");
+}
+
+function success_auth () {
+    success ("auth");
+}
+
+function success_feature ($feature, $request) {
+    $res = "<success request=\"$request\"><feature>";
+    $res .= "<id>" .  $feature->id .  "</id>";
+
+    $res .= "<imgurl>" .
+             ($feature->imgpath ? 
+                    full_url_from_filename ($feature->imgpath)
+                    : "") .
+             "</imgurl>";
+
+    $res .= "<description>" .
+                 htmlspecialchars ($feature->description) .
+                 "</description>";
+
+    // XXX: we do not use <title> because that would be interpreted and
+    // altered by browers html parser
+    $res .= "<heading>" . 
+            htmlspecialchars ($feature->title) .
+            "</heading>";
+
+    $res .= "<lon>" . $feature->lon . "</lon>";
+    $res .= "<lat>" . $feature->lat . "</lat>";
+    $res .= "</feature></success>";
+    exit_document ($res);
+}
+
+function success_delete_feature ($feature) {
+    $res = "<success request=\"del\"><feature>";
+    $res .= "<id>" .  $feature->id .  "</id>";
+    $res .= "</feature></success>";
+    exit_document ($res);
+}
+
+function success ($reason) {
+    exit_document ("<success request=\"$reason\"></success>");
+}
+
+function error ($reason) {
+    exit_document ("<error reason=\"$reason\"></error>");
+}
+
+function error_feature ($id, $reason) {
+    $res = "<error reason=\"$reason\"><feature>";
+    $res .= "<id>" .  $id .  "</id>";
+    $res .= "</feature></error>";
+    exit_document ($res);
+}
+
+function nochange_error ($id) {
+    error_feature ($id, "nochange");
+}
+function unreferenced_error ($id) {
+    error_feature ($id, "unreferenced");
+}
+
+function server_error () {
+    error ("server");
+}
+
+function unauthorized_error () {
+    error ("unauthorized");
+}
+
+function request_error () {
+    error ("request");
+}
+
+function file_too_big_error () {
+    error ("toobig");
+}
+
+function notanimage_error () {
+    error ("notimage");
+}
+
+function save_uploaded_file ($file, $con) {
+    $dest = "";
+    if (isset ($file) && ($file ["error"] != UPLOAD_ERR_NO_FILE)) {
+        img_check_upload ($file);
+        $dest = unique_file (UPLOADDIR, $file ["name"], $con);
+        if (!isset ($dest) || 
+                (!move_uploaded_file ($file ["tmp_name"], $dest))) {
+            server_error ();
+        }
+    }
+    return basename($dest);
+}
+
+function img_check_upload ($file) {
+    if (!is_uploaded_file ($file ["tmp_name"])) {
+        if ($file ["error"] ==  UPLOAD_ERR_INI_SIZE) {
+            file_too_big_error ();
+        } else {
+            server_error ();
+        }
+    }
+    if (!getimagesize ($file ["tmp_name"])) {
+        notanimage_error ();
+    }
+}
+
+function delete_image_if_unused ($imgpath, $con) {
+    if ($con->imgpath_exists ($imgpath)) {
+        return false;
+    }
+    $path = UPLOADDIR . "/" . $imgpath;
+    if (file_exists($path)) {
+        unlink ($path);
+        return true;
+    } else {
+        return false;
+    }
+}
+
+function unique_file ($dirname, $relpath, $con) {
+   $relpath = str_replace ('/', '', $relpath); // strip slashes from path
+   $relpath = str_replace ('\\', '', $relpath); // strip antislashes from path
+   $filename = $dirname . '/' . $relpath;
+   $counter = 1;
+
+   $dotpos = strrpos ($relpath, '.');
+   if ($dotpos) {
+       $base = substr ($relpath, 0, $dotpos);
+       $ext = substr ($relpath, $dotpos + 1);
+   } else {
+       $base = $relpath;
+       $ext = "";
+   }
+
+   while ($counter < 1000) {
+       if (!file_exists ($filename) && 
+           !($con->imgpath_exists (basename ($filename)))) {
+           return $filename;
+       } else {
+            $counter++;
+            $filename = $dirname . '/' . $base . '_' . $counter . '.' . $ext;
+       }
+   }
+   // we tried to find an unused filename 1000 times. Give up now.
+   return null;
+}
+
+function main ($con) {
+    if (!isset ($_POST ["request"])) {
+        request_error ();
+    }
+    if ($_POST ["request"] == "auth") {
+        $pwd = unquote ($_POST["password"]);
+        $user = "admin";
+        if ($con->checkpwdmd5 ($user, md5 ($pwd))) {
+            // cookie will be valid for 2 weeks. I've chosen that value
+            // arbitrarily, and it may change in the future.
+            $time = time () + 14 * 60 * 24 * 60;
+            $cookie_name = sprintf ("%sauth", DBPREFIX);
+            setcookie ($cookie_name, md5 ($pwd), $time, "" , "", false, true);
+            success_auth ();
+        } else {
+            unauthorized_error ();
+        }
+    }
+    if (!($con->checkpwdmd5 ("admin",
+                             $_COOKIE [sprintf ("%sauth", DBPREFIX)]))) {
+        unauthorized_error ();
+    }
+
+    switch ($_POST ["request"]) {
+        case "update":
+            $id = $_POST ["fid"];
+            $feature = $con->getfeature ($id);
+            if (!isset ($feature)) {
+                unreferenced_error ($id);
+            }
+
+            // no file uploaded, but editor currently has an image: it means
+            // image was not changed
+            if ($_POST ["keep_img"] == "yes") {
+                $imgpath = $feature->imgpath;
+            } else {
+                $imgpath = save_uploaded_file ($_FILES ["image_file"], $con);
+            }
+
+            $lon = $_POST ["lon"];
+            $lat = $_POST ["lat"];
+            $title = unquote ($_POST ["title"]);
+            $description = unquote ($_POST ["description"]);
+
+            try {
+                $new_feature = new feature ($id, $lon, $lat, $imgpath, $title, $description);
+            } catch (Exception $e) {
+                request_error ();
+            }
+
+            if (($new_feature->lon == $feature->lon) &&
+                ($new_feature->lat == $feature->lat) &&
+                ($new_feature->title == $feature->title) &&
+                ($new_feature->imgpath == $feature->imgpath) &&
+                ($new_feature->description == $feature->description)) {
+                nochange_error ($feature->id);
+            }
+
+            $old_imgpath = "";
+            if ($feature->imgpath && ($feature->imgpath != $new_feature->imgpath)) {
+                $old_imgpath = $feature->imgpath;
+            }
+
+            try {
+                $con->save_feature ($new_feature);
+            } catch (Exception $e) {
+                server_error ();
+            }
+            if ($old_imgpath) {
+                try {
+                    delete_image_if_unused ($old_imgpath, $con); 
+                } catch (Exception $e) {}
+            }
+            success_feature ($new_feature, "update");
+        break;
+        case "add":
+            $imgpath = save_uploaded_file ($_FILES ["image_file"], $con);
+
+            $lon = $_POST ["lon"];
+            $lat = $_POST ["lat"];
+            $title = unquote ($_POST ["title"]);
+            $description = unquote ($_POST ["description"]);
+            try {
+                $feature = new feature (null, $lon, $lat, $imgpath, $title, $description);
+            } catch (Exception $e) {
+                request_error ();
+            }
+            try {
+                $feature = $con->save_feature ($feature);
+            } catch (Exception $e) {
+                server_error ();
+            }
+            success_feature ($feature, "add");
+        break;
+        case "del":
+            $id = $_POST ["fid"];
+            $feature = $con->getfeature ($id);
+            if (!isset ($feature)) {
+                unreferenced_error ($id);
+            }
+            $imgpath = $feature->imgpath;
+
+            try {
+                $con->delete_feature ($feature);
+            } catch (Exception $e) {
+                server_error ();
+            }
+
+            try {
+                delete_image_if_unused ($imgpath, $con);
+            } catch (Exception $e) {}
+
+            success_delete_feature ($feature);
+        default:
+            request_error();
+        break;
+    }
+
+    server_error ();
+}
+
+try {
+    $connection->connect (DBHOST, DBUSER, DBPWD, DBNAME, DBPREFIX);
+} catch (Exception $e) {
+    server_error ();
+}
+
+main ($connection);
+?>