]> dev.renevier.net Git - syp.git/commitdiff
multi user administration
authorarno <arenevier@fdn.fr>
Tue, 11 Aug 2009 09:42:27 +0000 (11:42 +0200)
committerarno <arenevier@fdn.fr>
Sat, 15 Aug 2009 23:01:29 +0000 (01:01 +0200)
api.php
devdoc/api.txt
inc/db/anydb.php
inc/db/mysql.php
inc/templates_admin.php
inc/templates_index.php
items.php
js/admin.js
js/syp.js
logout.php
media/admin.css

diff --git a/api.php b/api.php
index 2054350084a29108e54982d3de468354805b33da..a9df091477a85e509b4b71e9ed1c7ba3001d15dc 100644 (file)
--- a/api.php
+++ b/api.php
@@ -10,8 +10,11 @@ function exit_document ($body) {
     exit ("<html><head></head><body>$body</body></html>");
 }
 
-function success_auth () {
-    success ("auth");
+function success_auth ($user) {
+    $res = "<success request=\"$reason\"><user>" . 
+            htmlspecialchars ($user) .
+            "</user></success>";
+    exit_document ($res);
 }
 
 function success_feature ($feature, $request) {
@@ -167,27 +170,28 @@ function unique_file ($dirname, $relpath, $con) {
    return null;
 }
 
-function check_auth ($con, $pwd, $cookie_name, $auth_only) {
+function check_auth ($con, $user, $pwd, $auth_only) {
     $authentificated = false;
-    $user = "admin";
 
-    if ($pwd) {
+    if (isset ($pwd)) {
         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;
-            setcookie ($cookie_name, md5 ($pwd), $time, "" , "", false, true);
+            setcookie (sprintf ("%sauth", DBPREFIX), md5 ($pwd), $time, "" , "", false, true);
+            setcookie (sprintf ("%suser", DBPREFIX), $user, $time, "" , "", false, true);
             $authentificated = true;
             if ($auth_only) {
-                success_auth ();
+                success_auth ($user);
             }
         } else {
             unauthorized_error ();
         }
     }
 
-    if (!$authentificated && !($con->checkpwdmd5 ($user,
-                             $_COOKIE [$cookie_name]))) {
+    if (!$authentificated && !($con->checkpwdmd5 (
+                             $_COOKIE [sprintf ("%suser",  DBPREFIX)],
+                             $_COOKIE [sprintf ("%sauth",  DBPREFIX)]))) {
         unauthorized_error ();
     }
 }
@@ -197,11 +201,14 @@ function main ($con) {
         request_error ();
     }
 
-    $pwd = unquote ($_POST["password"]);
-    $cookie_name = sprintf ("%sauth", DBPREFIX);
+    $pwd = unquote ($_POST ["password"]);
+    $user = unquote ($_POST ["user"]);
     // does user only want authentication or does he want to do other things
     $auth_only = ($_POST ["request"] == "auth");
-    check_auth ($con, $pwd, $cookie_name, $auth_only);
+    check_auth ($con, $user, $pwd, $auth_only);
+    if (!$user) {
+        $user = $_COOKIE [sprintf ("%suser",  DBPREFIX)];
+    }
 
     switch ($_POST ["request"]) {
         case "update":
@@ -210,6 +217,9 @@ function main ($con) {
             if (!isset ($feature)) {
                 unreferenced_error ($id);
             }
+            if ($feature->user != $user) {
+                unauthorized_error ();
+            }
 
             // no file uploaded, but editor currently has an image: it means
             // image was not changed
@@ -225,7 +235,7 @@ function main ($con) {
             $description = unquote ($_POST ["description"]);
 
             try {
-                $new_feature = new feature ($id, $lon, $lat, $imgpath, $title, $description, 0);
+                $new_feature = new feature ($id, $lon, $lat, $imgpath, $title, $description, 0, $user);
             } catch (Exception $e) {
                 request_error ();
             }
@@ -263,7 +273,7 @@ function main ($con) {
             $title = unquote ($_POST ["title"]);
             $description = unquote ($_POST ["description"]);
             try {
-                $feature = new feature (null, $lon, $lat, $imgpath, $title, $description, 0);
+                $feature = new feature (null, $lon, $lat, $imgpath, $title, $description, 0, $user);
             } catch (Exception $e) {
                 request_error ();
             }
@@ -280,6 +290,9 @@ function main ($con) {
             if (!isset ($feature)) {
                 unreferenced_error ($id);
             }
+            if ($feature->user != $user) {
+                unauthorized_error ();
+            }
             $imgpath = $feature->imgpath;
 
             try {
index 590964a2cbaf3f391a702918acee9ef5a870259f..e02b78dc8872a4c24762f7d2b8fdfe205339350b 100644 (file)
@@ -11,9 +11,9 @@ Client submits a classic html form to server.
 **note**: In this documentation, php notation is used (`_POST` and `_FILES`),
 but server may be written in any language.
 
-` _POST["password"]` may contains user password. If it is set, access is
- checked. If it is not set, authentification cookie is checked. If neither are
present, or if one of them is wrong, access is denied.
+` _POST["password"]` and `_POST["user"] may contain user name and password. If
+ they are set, access is checked. If they is not set, cookies are checked. If
neither are present.
 
 `_POST["request"]` is either:
 
@@ -74,8 +74,8 @@ as _text/html_
 
 ## success handling:
 
- * `<success request="auth"></success>`:
-     authentication was successfull
+ * `<success request="auth"><user>?user_name?</name></success>`:
+     authentication was successfull. ?user_name? is name of authenticated user.
 
  * `<success request="del">
      <feature>
index bb80032a274eb3e4b898728f24f80c2e3c29b394..8ccdf127a7194631a5cf3f5e207619d47818ea3b 100644 (file)
@@ -10,10 +10,11 @@ class feature {
     private $title = null;
     private $description = null;
     private $date = 0;
+    private $user = null;
 
     const err_lonlat_invalid = 1;
 
-    function __construct ($id, $lon, $lat, $imgpath, $title, $description, $date) {
+    function __construct ($id, $lon, $lat, $imgpath, $title, $description, $date, $user) {
         $this->imgpath = $imgpath;
 
         // id
@@ -30,6 +31,9 @@ class feature {
         // date
         $this->date = $date;
 
+        // user
+        $this->user = $user;
+
         // longitude
         if (!isset ($lon) || !is_numeric ($lon) ||
              ($lon < -180) || ($lon > 180)) {
@@ -118,9 +122,10 @@ interface anydbConnection {
     public function getfeature($id);
 
     /*
-     * returns an array of available features
+     * returns an array of features managed by $user. If $user is undefined or
+     * if user is "admin", return all available features.
      */
-    public function listfeatures();
+    public function listfeatures($user);
 
     /*
      * returns the most recent features sorted by date. If $num_features is not
@@ -133,14 +138,6 @@ interface anydbConnection {
      */
     public function imgpath_exists($imgpath);
 
-    /*
-     * returns Minimum Bounding Rectangle containing all feature locations.
-     * That function must return a result even if database is not functional.
-     * Minimum Bounding Rectangle is presented as an Array:
-     *      [bottom, left, top, right]
-     */
-    public function mbr();
-
     /*
      * get name of database backend
      */
index 8e3fcf85394d618b97c7d1bbd4e68e8ee7abf859..043e86d7818b853cd84951f4ae1ec9352e8cd5cf 100644 (file)
@@ -107,20 +107,22 @@ class mysqlConnection implements anydbConnection {
               $query = sprintf ("INSERT INTO %sitems
                               (imgpath, title, description, location, date, user)
                                 VALUES ('%s', '%s', '%s', 
-                               GeomFromText('POINT(%s %s)'), NOW(), 'admin')", 
+                               GeomFromText('POINT(%s %s)'), NOW(), '%s')", 
                               $this->dbprefix,
                               mysql_real_escape_string ($feature->imgpath),
                               mysql_real_escape_string ($feature->title),
                               mysql_real_escape_string ($feature->description),
                               $feature->lon,
-                              $feature->lat
+                              $feature->lat,
+                              mysql_real_escape_string ($feature->user)
                     );
 
                 $this->_execute_query ($query);
                 $id = mysql_insert_id ();
                 return new feature ($id, $feature->lon, $feature->lat,
                                     $feature->imgpath, $feature->title,
-                                    $feature->description, $feature->date);
+                                    $feature->description, $feature->date,
+                                    $feature->user);
         }
     }
 
@@ -134,8 +136,8 @@ class mysqlConnection implements anydbConnection {
 
     public function getfeature ($id) {
         $query = sprintf ("SELECT id, imgpath, title, description, AsText(location)
-                           AS location, UNIX_TIMESTAMP(date) AS date FROM %sitems
-                           WHERE id = '%s';", 
+                           AS location, UNIX_TIMESTAMP(date) AS date, user
+                           FROM %sitems WHERE id = '%s';", 
                         $this->dbprefix, mysql_real_escape_string ($id));
         $row = mysql_fetch_assoc ($this->_execute_query ($query));
         if ($row === false) {
@@ -144,10 +146,18 @@ class mysqlConnection implements anydbConnection {
         return $this->_feature_frow_row ($row);
     }
 
-    public function listfeatures () {
+    public function listfeatures ($user) {
+        if ($user && ($user != "admin")) {
+            $from_user_query = sprintf (" WHERE user = '%s' ",
+                                        mysql_real_escape_string ($user));
+        } else {
+            $from_user_query = "";
+        }
+
         $query = sprintf ("SELECT id, imgpath, title, description, AsText(location)
-                            AS location, UNIX_TIMESTAMP(date) AS date FROM %sitems;",
-                          $this->dbprefix);
+                            AS location, UNIX_TIMESTAMP(date) AS date, user
+                            FROM %sitems %s;",
+                          $this->dbprefix, $from_user_query);
 
         $features = array ();
         $res = $this->_execute_query ($query);
@@ -163,7 +173,7 @@ class mysqlConnection implements anydbConnection {
     public function mostrecentfeatures ($num_features) {
         $query = sprintf ("SELECT id, imgpath, title, description,
                            AsText(location) AS location, UNIX_TIMESTAMP(date)
-                           AS date FROM %sitems ORDER BY date DESC",
+                           AS date, user FROM %sitems ORDER BY date DESC",
                            $this->dbprefix);
         if ($num_features) {
             $query .= sprintf (" LIMIT %d", $num_features);
@@ -186,46 +196,6 @@ class mysqlConnection implements anydbConnection {
         return ($res [0] >= 1) ? true : false;
     }
 
-    public function mbr () {
-        $maxlon = -180;
-        $minlon = 180;
-        $maxlat = -88;
-        $minlat = 88;
-
-        if (!$this->link) {
-            return array ($minlon, $minlat, $maxlon, $maxlat);
-        }
-        try {
-            $features = $this->listfeatures ();
-        } catch (Exception $e) {
-            return array ($minlon, $minlat, $maxlon, $maxlat);
-        }
-
-        if (count ($features) == 0) {
-            return array ($minlon, $minlat, $maxlon, $maxlat);
-        } else if (count ($features) == 1) { 
-            // in case there's only one feature, we show an area of at least 
-            // 4 x 4 degrees
-            $feature = $features [0];
-
-            $minlon = max ($feature->lon - 2, -180);
-            $maxlon = min ($feature->lon + 2, 180);
-            $minlat = max ($feature->lat - 2, -90);
-            $maxlat = min ($feature->lat + 2, 90);
-
-            return array ($minlon, $minlat, $maxlon, $maxlat);
-        } else {
-            foreach ($features as $feature) {
-                $minlon = min ($feature->lon, $minlon);
-                $minlat = min ($feature->lat, $minlat);
-                $maxlon = max ($feature->lon, $maxlon);
-                $maxlat = max ($feature->lat, $maxlat);
-            }
-
-            return array ($minlon, $minlat, $maxlon, $maxlat);
-        }
-    }
-
     public function getdbname () {
         return "Mysql";
     }
@@ -247,7 +217,7 @@ class mysqlConnection implements anydbConnection {
         try {
             $feature = new feature ($row ["id"], $lon, $lat, $row ["imgpath"],
                                     $row ["title"], $row ["description"],
-                                    $row ["date"]);
+                                    $row ["date"], $row ["user"]);
         } catch (Exception $e) {
             return null;
         }
index 3931aa0beee3b0db547b8fd4672bcacf1aad8f5e..814ca4566c362a5473478a46ebbe4c23fc981228 100644 (file)
@@ -35,6 +35,10 @@ if (!$usrtblexists || !$itemstblexists) {
 <?php
     exit ();
     } // if ($error)
+
+    $user = $_COOKIE [sprintf ("%suser", DBPREFIX)];
+    $pwd = $_COOKIE [sprintf ("%sauth", DBPREFIX)];
+    $logged = ($connection->checkpwdmd5 ($user, $pwd));
 ?>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">  
@@ -65,11 +69,9 @@ if (!$usrtblexists || !$itemstblexists) {
             UpdateSucces: "<?php ptrans('Save took place correctly.')?>"
         };
 
-        <?php 
-            $bbox = $connection->mbr ();
-            printf ("var sypOrig = [%.18F, %.18F, %.18F, %.18F];\n",
-                    $bbox [0], $bbox [1], $bbox [2], $bbox [3]); 
-        ?>
+        var sypSettings =  {
+            loggedUser: <?php printf ($logged ? "\"$user\"": "null")?>
+        };
 
       </script>
       <script src="./js/jquery-1.3.2.js" type="text/javascript"></script>
@@ -143,8 +145,7 @@ if (!$usrtblexists || !$itemstblexists) {
 
       <div id="login_area"
         <?php 
-        if ($connection->checkpwdmd5 ("admin", 
-                               $_COOKIE [sprintf ("%sauth", DBPREFIX)])) {
+        if ($logged) {
             echo ' class="hidden"';
         }
       ?>>
@@ -154,6 +155,10 @@ if (!$usrtblexists || !$itemstblexists) {
         <form id="login_form" method="post">
         <div id="cookie_warning" class="center warn"><?php ptrans('You need to have cookies enabled to administrate SYP')?></div>
             <table>
+                <tr>
+                    <td><label for="user"><?php ptrans('user')?></label></td>
+                    <td style="width: 100%"><input id="user" name="user"></td>
+                </tr>
                 <tr>
                     <td><label for="password"><?php ptrans('password')?></label></td>
                     <td style="width: 100%"><input id="password" name="password" type="password"></td>
index 9f54d3b0b93e7d3703f59f4daad95b9db8f1a87d..64b965fe5181fb2b1663a3dd8ab3e05666ff6f01 100644 (file)
@@ -10,12 +10,17 @@ try {
 } catch (Exception $e) {
 }
 
-$bbox = $connection->mbr ();
 if (defined ("THUMBSMAXSIZE") && (THUMBSMAXSIZE > 0)) {
     $thumbsmaxsize = THUMBSMAXSIZE;
 } else {
     $thumbsmaxsize = 400; // default value;
 }
+
+if (defined ("POPUPNEARFEATURE") && (POPUPNEARFEATURE)) {
+    $popupnearfeature = true;
+} else {
+    $popupnearfeature = false;
+}
 ?>
 <html lang="<?php echo $lang?>">
 <head>
@@ -46,16 +51,9 @@ if (defined ("THUMBSMAXSIZE") && (THUMBSMAXSIZE > 0)) {
             propulsedByLink: "<?php ptrans('propulsed by <a href=\"http://syp.renevier.net\">syp</a>')?>",
             noImageRegistered: "<?php ptrans('There is no image registered on this site.')?>"
         };
-        <?php
-            printf ("var sypOrig = [%.18F, %.18F, %.18F, %.18F];\n",
-                    $bbox [0], $bbox [1], $bbox [2], $bbox [3]);
-
-            if (defined ("POPUPNEARFEATURE") && (POPUPNEARFEATURE)) {
-                printf ("var sypPopupNearFeature = true;\n");
-            } else {
-                printf ("var sypPopupNearFeature = false;\n");
-            }
-        ?>
+        var sypSettings =  {
+            popupNearfeature: <?php printf ($popupnearfeature ? "true": "false")?>
+        };
     </script>
     <script src="./openlayers/OpenLayers.js" type="text/javascript"></script>
     <script src="./js/syp.js" type="text/javascript"></script>
index e7a97231572a689dc0d4185706e66d2a7aab7b33..cd2cd91bb14c6aff37a52a2f250ce4e2231b4c26 100644 (file)
--- a/items.php
+++ b/items.php
@@ -79,7 +79,7 @@ function main ($features) {
 
 try {
     $connection->connect (DBHOST, DBUSER, DBPWD, DBNAME, DBPREFIX);
-    $features = $connection->listfeatures ();
+    $features = $connection->listfeatures ($_GET ['from_user']);
 } catch (Exception $e) {
     exit ("server error");
 }
index 259c914ae8c446165e8a5c613463687845c5612c..d950aeba91275e5055d3f0dda8f87508d8e3ea6b 100644 (file)
@@ -55,11 +55,11 @@ OpenLayers.Control.SypDragFeature = OpenLayers.Class (OpenLayers.Control.DragFea
 });
 
 var Admin = {
-    Settings: {
-        MARKER_ICON: "media/marker-normal.png",
-        MARKER_SELECT_ICON: "media/marker-selected.png",
-        MARKER_TEMPORARY_ICON: "media/marker-temp.png",
-        MARKER_HEIGHT: 25
+    Markers: {
+        ICON: "media/marker-normal.png",
+        SELECT_ICON: "media/marker-selected.png",
+        TEMPORARY_ICON: "media/marker-temp.png",
+        HEIGHT: 25
     },
 
     map: null,
@@ -83,37 +83,14 @@ var Admin = {
          });
 
          this.baseLayer = this.createBaseLayer ();
-         this.dataLayer = this.createDataLayer ();
-         this.map.addLayers([this.baseLayer, this.dataLayer]);
+         this.map.addLayer(this.baseLayer);
 
-         // controls
-         this.selFeatureControl = this.createSelectFeatureControl();
-         this.map.addControl(this.selFeatureControl);
-         this.moveFeatureControl = this.createMoveFeatureControl();
-         this.map.addControl(this.moveFeatureControl);
-         this.addFeatureControl = this.createNewfeatureControl();
-         this.map.addControl(this.addFeatureControl);
-
-         // position
-         var centerBounds = new OpenLayers.Bounds();
-
-         var mapProj = this.map.getProjectionObject();
-         var sypOrigProj = new OpenLayers.Projection("EPSG:4326");
-
-         var bottomLeft = new OpenLayers.LonLat(sypOrig[0],sypOrig[1]);
-         bottomLeft = bottomLeft.transform(sypOrigProj, mapProj);
-         var topRight = new OpenLayers.LonLat(sypOrig[2],sypOrig[3])
-         topRight = topRight.transform(sypOrigProj, mapProj);
-
-         centerBounds.extend(bottomLeft);
-         centerBounds.extend(topRight);
-
-         // at that moment, ie does not know size of the map, we need to update
-         // manually
-         this.map.updateSize();
-         this.map.zoomToExtent(centerBounds);
-
-         this.reset();
+         this.map.setCenter(new OpenLayers.LonLat(0, 0), 0);
+         if (sypSettings.loggedUser) {
+            this.dataLayer = this.createDataLayer (sypSettings.loggedUser);
+            this.map.addLayer(this.dataLayer);
+            this.reset();
+         }
     },
 
     reset: function() {
@@ -131,44 +108,52 @@ var Admin = {
         return new OpenLayers.Layer.OSM("OSM");
     },
 
-    createDataLayer: function () {
+    createDataLayer: function (user) {
         var styleMap = new OpenLayers.StyleMap (
                         {"default": {
-                             externalGraphic: this.Settings.MARKER_ICON,
-                             graphicHeight: this.Settings.MARKER_HEIGHT || 32 
+                             externalGraphic: this.Markers.ICON,
+                             graphicHeight: this.Markers.HEIGHT || 32 
                                 },
                          "temporary": { 
-                             externalGraphic: this.Settings.MARKER_TEMPORARY_ICON,
-                             graphicHeight: this.Settings.MARKER_HEIGHT || 32 
+                             externalGraphic: this.Markers.TEMPORARY_ICON,
+                             graphicHeight: this.Markers.HEIGHT || 32 
                          },
                          "select": { 
-                             externalGraphic: this.Settings.MARKER_SELECT_ICON,
-                             graphicHeight: this.Settings.MARKER_HEIGHT || 32 
+                             externalGraphic: this.Markers.SELECT_ICON,
+                             graphicHeight: this.Markers.HEIGHT || 32 
                     }});
 
-        var layer = new OpenLayers.Layer.GML("KML", "items.php", 
+        var layer = new OpenLayers.Layer.GML("KML", "items.php?from_user=" + encodeURIComponent(user),
            {
             styleMap: styleMap,
             format: OpenLayers.Format.KML, 
             projection: this.map.displayProjection,
             eventListeners: { scope: this,
-                loadend: this.checkForFeatures
+                loadend: this.dataLayerEndLoad
             }
        });
 
+        // controls
+        this.selFeatureControl = this.createSelectFeatureControl(layer)
+        this.map.addControl(this.selFeatureControl);
+        this.moveFeatureControl = this.createMoveFeatureControl(layer)
+        this.map.addControl(this.moveFeatureControl);
+        this.addFeatureControl = this.createNewfeatureControl();
+        this.map.addControl(this.addFeatureControl);
+
         return layer;
     },
 
-    createMoveFeatureControl: function () {
+    createMoveFeatureControl: function (layer) {
         var control = new OpenLayers.Control.SypDragFeature(
-                this.dataLayer, {
+                layer, {
                          });
         return control;
     },
 
-    createSelectFeatureControl: function () {
+    createSelectFeatureControl: function (layer) {
         var control = new OpenLayers.Control.SelectFeature(
-                this.dataLayer, {
+                layer, {
                         onSelect: OpenLayers.Function.bind(this.onFeatureSelect, this)
                          });
         return control;
@@ -243,10 +228,38 @@ var Admin = {
         $("#title").select().focus(); 
     },
 
+    dataLayerEndLoad: function() {
+        // only set zoom extent once
+        this.dataLayer.events.unregister('loadend', this, this.dataLayerEndLoad);
+        this.dataLayer.events.register('loadend', this, this.checkForFeatures);
+
+        if (!this.checkForFeatures()) {
+            return;
+        }
+
+        var map = this.map;
+        var orig = this.Utils.mbr (this.dataLayer);
+        var centerBounds = new OpenLayers.Bounds();
+
+        var mapProj = map.getProjectionObject();
+        var sypOrigProj = new OpenLayers.Projection("EPSG:4326");
+
+        var bottomLeft = new OpenLayers.LonLat(orig[0],orig[1]);
+        bottomLeft = bottomLeft.transform(sypOrigProj, mapProj);
+        var topRight = new OpenLayers.LonLat(orig[2],orig[3])
+        topRight = topRight.transform(sypOrigProj, mapProj);
+
+        centerBounds.extend(bottomLeft);
+        centerBounds.extend(topRight);
+        map.zoomToExtent(centerBounds);
+    },
+
     checkForFeatures: function () {
-        if (this.dataLayer.features.length != 0) {
+        var features = this.dataLayer.features;
+        if (features.length != 0) {
             $("#instructions").text(SypStrings.SelectHowto);
         }
+        return !!features.length;
     },
 
     addNewFeature: function () {
@@ -290,6 +303,59 @@ var Admin = {
     },
 
     Utils: {
+        /* minimum bounds rectangle containing all feature locations.
+         * FIXME: if two features are close, but separated by 180th meridian,
+         * their mbr will span the whole earth. Actually, 179° lon and -170°
+         * lon are considerated very near.
+         */
+        mbr: function (layer) {
+            var features = [];
+            var map = layer.map;
+
+            var mapProj = map.getProjectionObject();
+            var sypOrigProj = new OpenLayers.Projection("EPSG:4326");
+
+            for (var i =0; i < layer.features.length; i++) {
+                if (layer.features[i].cluster) {
+                    features = features.concat(layer.features[i].cluster);
+                } else {
+                    features = features.concat(layer.features);
+                }
+            }
+
+            var minlon = 180;
+            var minlat = 88;
+            var maxlon = -180;
+            var maxlat = -88;
+
+            if (features.length == 0) {
+                // keep default values
+            } else if (features.length == 1) {
+                // in case there's only one feature, we show an area of at least 
+                // 4 x 4 degrees
+                var pos = features[0].geometry.getBounds().getCenterLonLat().clone();
+                var lonlat = pos.transform(mapProj, sypOrigProj);
+
+                minlon = Math.max (lonlat.lon - 2, -180);
+                maxlon = Math.min (lonlat.lon + 2, 180);
+                minlat = Math.max (lonlat.lat - 2, -90);
+                maxlat = Math.min (lonlat.lat + 2, 90);
+            } else {
+                for (var i = 0; i < features.length; i++) {
+                    var pos = features[i].geometry.getBounds().getCenterLonLat().clone();
+                    var lonlat = pos.transform(mapProj, sypOrigProj);
+                    minlon = Math.min (lonlat.lon, minlon);
+                    minlat = Math.min (lonlat.lat, minlat);
+                    maxlon = Math.max (lonlat.lon, maxlon);
+                    maxlat = Math.max (lonlat.lat, maxlat);
+                }
+            }
+
+            return [minlon, minlat, maxlon, maxlat];
+
+        },
+
+
         escapeHTML: function (str) {
             if (!str) {
                 return "";
@@ -404,6 +470,8 @@ var FeatureMgr = {
                 switch (xml.documentElement.getAttribute("reason")) {
                     case "unauthorized":
                         $("#login_area").show();
+                        $("#password").val("");
+                        $("#user").val(sypSettings.loggedUser).focus().select();
                         $("#cookie_warning").show();
                         this.reset();
                         Admin.cancelCurrentFeature();
@@ -593,7 +661,7 @@ var pwdMgr = {
 
     init: function () {
         $("#login_form").submit(this.submit);
-        $("#password").focus().select();
+        $("#user").focus().select();
     },
 
     reset: function() {
@@ -613,8 +681,8 @@ var pwdMgr = {
                     window.setTimeout(function() { 
                             // removes focus from #password before disabling it. Otherwise, opera
                             // prevents re-focusing it after re-enabling it.
-                            $("#password").blur(); 
-                            $("#login_submit, #password").attr("disabled", "disabled");
+                            $("#user, #password").blur(); 
+                            $("#login_submit, #user, #password").attr("disabled", "disabled");
                     }, 0)
                 },
                 oncomplete: OpenLayers.Function.bind(pwdMgr.ajaxReply, pwdMgr)
@@ -629,14 +697,14 @@ var pwdMgr = {
         $("#pwd_throbber").css("visibility", "hidden");
         // here, we need a timeout because onsend timeout sometimes has not been triggered yet
         window.setTimeout(function() {
-            $("#login_submit, #password").removeAttr("disabled");
+            $("#login_submit, #user, #password").removeAttr("disabled");
         }, 0);
 
         if (!data) {
             this.commError(SypStrings.ServerError);
             $("#login_error").show();
             window.setTimeout(function() {
-                    $("#password").focus().select();
+                    $("#user").focus().select();
             }, 0);
             return;
         }
@@ -660,12 +728,32 @@ var pwdMgr = {
                 }
                 $("#login_error").show();
                 window.setTimeout(function() {
-                        $("#password").focus().select();
+                        $("#user").focus().select();
                 }, 0);
             break;
             case "success":
-                this.reset();
                 $("#login_area").hide();
+
+                user = $(xml).find("USER,user").text();
+                sypSettings.loggedUser = user;
+
+                if (Admin.selFeatureControl) {
+                    Admin.selFeatureControl.destroy();
+                }
+                if (Admin.moveFeatureControl) {
+                    Admin.moveFeatureControl.destroy();
+                }
+                if (Admin.addFeatureControl) {
+                    Admin.addFeatureControl.destroy();
+                }
+                if (Admin.dataLayer) {
+                    Admin.dataLayer.destroy();
+                }
+
+                Admin.dataLayer = Admin.createDataLayer(user);
+                Admin.map.addLayer(Admin.dataLayer);
+                Admin.reset();
+
             break;
             default:
                 this.commError(SypStrings.UnconsistentError);
index 2c87c2b34bb83b64ae8fe784d9558f2343d519d8..40735c791cbb516ea273c0fe40a0e85d58ecb28b 100644 (file)
--- a/js/syp.js
+++ b/js/syp.js
@@ -17,10 +17,10 @@ OpenLayers.Control.SypAttribution = OpenLayers.Class (OpenLayers.Control.Attribu
 });
 
 var SYP = {
-    Settings: {
-        MARKER_ICON: "media/marker-normal.png",
-        MARKER_SELECT_ICON: "media/marker-selected.png",
-        MARKER_HEIGHT: 25
+    Markers: {
+        ICON: "media/marker-normal.png",
+        SELECT_ICON: "media/marker-selected.png",
+        HEIGHT: 25
     },
 
     map: null,
@@ -49,19 +49,7 @@ var SYP = {
         this.selectControl.activate();
 
         if (!this.map.getCenter()) {
-            var centerBounds = new OpenLayers.Bounds();
-
-            var mapProj = this.map.getProjectionObject();
-            var sypOrigProj = new OpenLayers.Projection("EPSG:4326");
-
-            var bottomLeft = new OpenLayers.LonLat(sypOrig[0],sypOrig[1]);
-            bottomLeft = bottomLeft.transform(sypOrigProj, mapProj);
-            var topRight = new OpenLayers.LonLat(sypOrig[2],sypOrig[3])
-            topRight = topRight.transform(sypOrigProj, mapProj);
-
-            centerBounds.extend(bottomLeft);
-            centerBounds.extend(topRight);
-            this.map.zoomToExtent(centerBounds);
+            this.map.setCenter(new OpenLayers.LonLat(0, 0), 0);
         }
     },
 
@@ -71,20 +59,20 @@ var SYP = {
 
     createDataLayer: function(map) {
         var defaultStyle = new OpenLayers.Style({
-            externalGraphic: this.Settings.MARKER_ICON,
+            externalGraphic: this.Markers.ICON,
             graphicHeight: "${height}"
         }, {
             context: {
                 height: function(feature) {
-                    var defaultHeight = SYP.Settings.MARKER_HEIGHT || 32;
+                    var defaultHeight = SYP.Markers.HEIGHT || 32;
                     var increase = 4 * (feature.attributes.count - 1);
                     return Math.min(defaultHeight + increase, 50);
                 }
             }
         });
         var selectStyle = new OpenLayers.Style({
-            externalGraphic: this.Settings.MARKER_SELECT_ICON,
-            graphicHeight: this.Settings.MARKER_HEIGHT || 32 
+            externalGraphic: this.Markers.SELECT_ICON,
+            graphicHeight: this.Markers.HEIGHT || 32 
         });
         var styleMap = new OpenLayers.StyleMap (
                         {"default": defaultStyle,
@@ -99,7 +87,7 @@ var SYP = {
             format: OpenLayers.Format.KML, 
             projection: this.map.displayProjection,
             eventListeners: { scope: this,
-                              loadend: this.checkForFeatures
+                              loadend: this.dataLayerEndLoad
                             }
            });
 
@@ -117,12 +105,38 @@ var SYP = {
         return control;
     },
 
+    dataLayerEndLoad: function() {
+        if (!this.checkForFeatures()) {
+            return;
+        }
+
+        var map = this.map;
+        if (map.getControlsByClass("OpenLayers.Control.ArgParser")[0].lat
+            == undefined) { // map center was not set in ArgParser control.
+            var orig = this.Utils.mbr (this.dataLayer);
+            var centerBounds = new OpenLayers.Bounds();
+
+            var mapProj = map.getProjectionObject();
+            var sypOrigProj = new OpenLayers.Projection("EPSG:4326");
+
+            var bottomLeft = new OpenLayers.LonLat(orig[0],orig[1]);
+            bottomLeft = bottomLeft.transform(sypOrigProj, mapProj);
+            var topRight = new OpenLayers.LonLat(orig[2],orig[3])
+            topRight = topRight.transform(sypOrigProj, mapProj);
+
+            centerBounds.extend(bottomLeft);
+            centerBounds.extend(topRight);
+            map.zoomToExtent(centerBounds);
+        }
+    },
+
     checkForFeatures: function() {
         var features = this.dataLayer.features;
         if (features.length == 0) {
             var message = SypStrings.noImageRegistered;
             this.Utils.displayUserMessage(message, "warn");
         }
+        return !!features.length;
     },
 
     createPopup: function(position, contentHTML) {
@@ -170,7 +184,7 @@ var SYP = {
         var popup = feature.popup;
 
         var popupPos = null;
-        if (sypPopupNearFeature) {
+        if (sypSettings.popupNearfeature) {
             popupPos = feature.geometry.getBounds().getCenterLonLat();
         } else {
             popupPos = SYP.Utils.brCorner(map, 8);
@@ -257,6 +271,59 @@ var SYP = {
             corner = map.getLonLatFromPixel(cornerAsPx);
             return corner;
         },
+
+        /* minimum bounds rectangle containing all feature locations.
+         * FIXME: if two features are close, but separated by 180th meridian,
+         * their mbr will span the whole earth. Actually, 179° lon and -170°
+         * lon are considerated very near.
+         */
+        mbr: function (layer) {
+            var features = [];
+            var map = layer.map;
+
+            var mapProj = map.getProjectionObject();
+            var sypOrigProj = new OpenLayers.Projection("EPSG:4326");
+
+            for (var i =0; i < layer.features.length; i++) {
+                if (layer.features[i].cluster) {
+                    features = features.concat(layer.features[i].cluster);
+                } else {
+                    features = features.concat(layer.features);
+                }
+            }
+
+            var minlon = 180;
+            var minlat = 88;
+            var maxlon = -180;
+            var maxlat = -88;
+
+            if (features.length == 0) {
+                // keep default values
+            } else if (features.length == 1) {
+                // in case there's only one feature, we show an area of at least 
+                // 4 x 4 degrees
+                var pos = features[0].geometry.getBounds().getCenterLonLat().clone();
+                var lonlat = pos.transform(mapProj, sypOrigProj);
+
+                minlon = Math.max (lonlat.lon - 2, -180);
+                maxlon = Math.min (lonlat.lon + 2, 180);
+                minlat = Math.max (lonlat.lat - 2, -90);
+                maxlat = Math.min (lonlat.lat + 2, 90);
+            } else {
+                for (var i = 0; i < features.length; i++) {
+                    var pos = features[i].geometry.getBounds().getCenterLonLat().clone();
+                    var lonlat = pos.transform(mapProj, sypOrigProj);
+                    minlon = Math.min (lonlat.lon, minlon);
+                    minlat = Math.min (lonlat.lat, minlat);
+                    maxlon = Math.max (lonlat.lon, maxlon);
+                    maxlat = Math.max (lonlat.lat, maxlat);
+                }
+            }
+
+            return [minlon, minlat, maxlon, maxlat];
+
+        },
+
         displayUserMessage: function(message, status) {
             var div = document.getElementById('message');
             while (div.firstChild)
index 9285e6a7ccb57ee9d7e97df673d4b2f740a63930..02b4b0795ffa54fbb27795342e184cd5d605c650 100644 (file)
@@ -4,8 +4,8 @@
 
 require_once ("./inc/settings.php");
 
-$cookie_name = sprintf ("%sauth", DBPREFIX);
-setcookie ($cookie_name, "", time () - 3600, "" , "",false, true);
+setcookie (sprintf ("%sauth", DBPREFIX), "", time () - 3600, "" , "",false, true);
+setcookie (sprintf ("%suser", DBPREFIX), "", time () - 3600, "" , "",false, true);
 header ('Location: index.php');
 
 ?>
index 04cdf4eff1c95b977784a1eda062289a8fcf01d3..9757300bb8c5d5176f51e79fff7e5551309bf26d 100644 (file)
@@ -149,7 +149,7 @@ html>/**/body #img { /* hide from ie7 */
     display: none;
 }
 
-#password {
+#password, #user {
     display: block;
     width: 100%;
 }