From 3b38ca36fc18d34999073625a9c66dc2f05747a3 Mon Sep 17 00:00:00 2001 From: arno Date: Tue, 11 Aug 2009 11:42:27 +0200 Subject: [PATCH] multi user administration --- api.php | 41 +++++--- devdoc/api.txt | 10 +- inc/db/anydb.php | 19 ++-- inc/db/mysql.php | 70 ++++---------- inc/templates_admin.php | 19 ++-- inc/templates_index.php | 20 ++-- items.php | 2 +- js/admin.js | 200 +++++++++++++++++++++++++++++----------- js/syp.js | 113 ++++++++++++++++++----- logout.php | 4 +- media/admin.css | 2 +- 11 files changed, 319 insertions(+), 181 deletions(-) diff --git a/api.php b/api.php index 2054350..a9df091 100644 --- a/api.php +++ b/api.php @@ -10,8 +10,11 @@ function exit_document ($body) { exit ("$body"); } -function success_auth () { - success ("auth"); +function success_auth ($user) { + $res = "" . + htmlspecialchars ($user) . + ""; + 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 { diff --git a/devdoc/api.txt b/devdoc/api.txt index 590964a..e02b78d 100644 --- a/devdoc/api.txt +++ b/devdoc/api.txt @@ -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: - * ``: - authentication was successfull + * `?user_name?`: + authentication was successfull. ?user_name? is name of authenticated user. * ` diff --git a/inc/db/anydb.php b/inc/db/anydb.php index bb80032..8ccdf12 100644 --- a/inc/db/anydb.php +++ b/inc/db/anydb.php @@ -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 */ diff --git a/inc/db/mysql.php b/inc/db/mysql.php index 8e3fcf8..043e86d 100644 --- a/inc/db/mysql.php +++ b/inc/db/mysql.php @@ -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; } diff --git a/inc/templates_admin.php b/inc/templates_admin.php index 3931aa0..814ca45 100644 --- a/inc/templates_admin.php +++ b/inc/templates_admin.php @@ -35,6 +35,10 @@ if (!$usrtblexists || !$itemstblexists) { checkpwdmd5 ($user, $pwd)); ?> @@ -65,11 +69,9 @@ if (!$usrtblexists || !$itemstblexists) { UpdateSucces: "" }; - mbr (); - printf ("var sypOrig = [%.18F, %.18F, %.18F, %.18F];\n", - $bbox [0], $bbox [1], $bbox [2], $bbox [3]); - ?> + var sypSettings = { + loggedUser: + }; @@ -143,8 +145,7 @@ if (!$usrtblexists || !$itemstblexists) {
checkpwdmd5 ("admin", - $_COOKIE [sprintf ("%sauth", DBPREFIX)])) { + if ($logged) { echo ' class="hidden"'; } ?>> @@ -154,6 +155,10 @@ if (!$usrtblexists || !$itemstblexists) {
+ + + + diff --git a/inc/templates_index.php b/inc/templates_index.php index 9f54d3b..64b965f 100644 --- a/inc/templates_index.php +++ b/inc/templates_index.php @@ -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; +} ?> @@ -46,16 +51,9 @@ if (defined ("THUMBSMAXSIZE") && (THUMBSMAXSIZE > 0)) { propulsedByLink: "syp')?>", noImageRegistered: "" }; - + var sypSettings = { + popupNearfeature: + }; diff --git a/items.php b/items.php index e7a9723..cd2cd91 100644 --- 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"); } diff --git a/js/admin.js b/js/admin.js index 259c914..d950aeb 100644 --- a/js/admin.js +++ b/js/admin.js @@ -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); diff --git a/js/syp.js b/js/syp.js index 2c87c2b..40735c7 100644 --- 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) diff --git a/logout.php b/logout.php index 9285e6a..02b4b07 100644 --- a/logout.php +++ b/logout.php @@ -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'); ?> diff --git a/media/admin.css b/media/admin.css index 04cdf4e..9757300 100644 --- a/media/admin.css +++ b/media/admin.css @@ -149,7 +149,7 @@ html>/**/body #img { /* hide from ie7 */ display: none; } -#password { +#password, #user { display: block; width: 100%; } -- 2.39.2