From 035d3cd4c2b6f64e01797b100d598958231023bd Mon Sep 17 00:00:00 2001 From: Edmar Moretti Date: Thu, 22 Nov 2007 13:25:59 +0000 Subject: [PATCH] Adicionada a biblioteca kmlmapserver em pacotes --- pacotes/kmlmapserver/LICENCE | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/kmlmapserver/README | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/kmlmapserver/cache/index.html | 0 pacotes/kmlmapserver/classes/kmlserver.class.php | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/kmlmapserver/classes/layerserver.class.php | 908 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/kmlmapserver/classes/symbolserver.class.php | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/kmlmapserver/classes/zip.class.php | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/kmlmapserver/doc/index.html | 4 ++++ pacotes/kmlmapserver/kmlservice.php | 30 ++++++++++++++++++++++++++++++ 9 files changed, 1741 insertions(+), 0 deletions(-) create mode 100644 pacotes/kmlmapserver/LICENCE create mode 100644 pacotes/kmlmapserver/README create mode 100644 pacotes/kmlmapserver/cache/index.html create mode 100644 pacotes/kmlmapserver/classes/kmlserver.class.php create mode 100644 pacotes/kmlmapserver/classes/layerserver.class.php create mode 100644 pacotes/kmlmapserver/classes/symbolserver.class.php create mode 100644 pacotes/kmlmapserver/classes/zip.class.php create mode 100644 pacotes/kmlmapserver/doc/index.html create mode 100644 pacotes/kmlmapserver/kmlservice.php diff --git a/pacotes/kmlmapserver/LICENCE b/pacotes/kmlmapserver/LICENCE new file mode 100644 index 0000000..853047c --- /dev/null +++ b/pacotes/kmlmapserver/LICENCE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/pacotes/kmlmapserver/README b/pacotes/kmlmapserver/README new file mode 100644 index 0000000..f0b705a --- /dev/null +++ b/pacotes/kmlmapserver/README @@ -0,0 +1,92 @@ +KML mapserver wrapper +------------------------------------- + +* What is this thing? + this is a wrapper around UNM Mapserver, to serve KML data in a WFS-like manner + +* Requirements + PHP5 with simplexml + +* Configuration + Configuration is done through CGI-style calls and through some optional metadata in the mapfile + + METADATA: + RESULT_FIELDS # from which field take the name for the feature + # defaults to the first field + + DESCRIPTION_TEMPLATE # if present, this is used for placemark features + # tooltip. Parameters surrounded by "%" char are substituted + # with real values from the corresponding field for the feature + + DESCRIPTION # All those metadata are searched (in this order) to get a layer + OWS_TITLE # description + WFS_TITLE + WMS_TITLE + + KML_CACHE # number of second the cache will lasts + # if empty or not exists, the cache will be disabled for that layer + + KML_SKIP # if equals to "true", kml output is disabled for this layer, + # default is false + + KML_ADD_POINT # If not empty, add a point with balloon to start and end + # line geometries. Value is the icon url. + + + CGI-PARAMETERS: + * - request = string - optional - request type (OGC WFS like) + * - map = string - required - path to mapfile + * - typename = string - optional - (can be a csv list) - layer name(s), if empty, all layers are returned + * - filter = string - optional - filter encoding (single layer requests only) + * - bbox = string - optional - standard bbox specification (Not yet implemented) + * - encoding = string - optional - default to ISO-8859-1 + +* Filters + Only PropertyIsEqualTo and PropertyIsLike are supported ATM. + +* Encoding + kml is UTF-8, mapfile and attributes could have other encodings, you can set encoding via request parameter, otherwise ISO-8859-1 is used as default. + +* Raster support + Raster layer are supported as standard WMS network links, it is necessary to add EPSG:4326 to WMS_SRS metadata on all mapfile layers. + Mapfile must be correctly configured as WMS server (i.e. all required metadata must be set). + +* KMZ compressed output + +* Styles and classes + There is limited support for classes and style: + * only one style for each class is parsed, if you have multiple styles in one class, the values of the last one are used + * only color, outlinecolor, backgroundcolor, symbol, size and width are parsed + +* Cache + A simple caching for single layer requests is available. + If you want to use the cache, set KML_CACHE layer metadata to the number of seconds the cache should last. + A web server writeable "cache" directory must exists at the same level of the main script + +* Know issues + * Filled polygons fail to wrap on the mountains (this seems a GE bug), a define('TREAT_POLY_AS_LINE', true) control this behaviour + +EXAMPLE CALLS +------------------------------------ +Single layer: +http://localhost/kmlserver/service.php?map=/map/mapfile-ogc.map&typename=sfumo,vngeo_ospitalita + +Two layers (one raster and one vector): +http://localhost/kmlserver/service.php?map=/map/mapfile-ogc.map&typename=vngeo_ospitalita + +All layers as network links: +http://localhost/kmlserver/service.php?map=/map/mapfile-ogc.map + +Single layer with filter: +http://localhost/kmlserver/service.php?map=/map/mapfile-ogc.map&typename=comuni&filter=toponimoRiederalp + + +ICON SERVER +------------------------------------- +Returns a PNG icon for a give poin layer/class combination +Example calls: +http://localhost/kmlserver/symbolservice.php?map=/map/mapfile-ogc.map&typename=vngeo_ospitalita&class=Alberghi + +If you want transparent icons, set PNG output format to RGBA and IMAGECOLOR to the transparent color + + diff --git a/pacotes/kmlmapserver/cache/index.html b/pacotes/kmlmapserver/cache/index.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pacotes/kmlmapserver/cache/index.html diff --git a/pacotes/kmlmapserver/classes/kmlserver.class.php b/pacotes/kmlmapserver/classes/kmlserver.class.php new file mode 100644 index 0000000..0770e16 --- /dev/null +++ b/pacotes/kmlmapserver/classes/kmlserver.class.php @@ -0,0 +1,102 @@ + +* accepted parameters (case insensitive): +* - request = string - request type (OGC WFS like), can be kml (default), kmz, icon +* - map = string - path to mapfile +* - typename = string - (can be a csv list) - layer name(s) +* - filter = string - filter encoding +* - bbox = string - (csv) - bounding box csv +* +* +* +* +* @author Alessandro Pasotti +* @copyright 2007 ItOpen.it - All rights reserved +* @package KMLMAPSERVER + +This file is part of KMLMAPSERVER. + + KMLMAPSERVER is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + KMLMAPSERVER is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with KMLMAPSERVER; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + + +if (!extension_loaded('MapScript')) +{ + dl( 'php_mapscript.' . PHP_SHLIB_SUFFIX ); +} + + +/** +* Main server class, wraps real kml or icon servers +*/ + +class KmlServer { + + /** server instance */ + var $service; + + /** request */ + var $request; + + /** debug flag */ + var $_debug = false; + + /** + * Initialize + * + */ + function KmlServer(){ + $this->get_request(); + if($this->service == 'icon'){ + include 'symbolserver.class.php'; + $this->service = new SymbolServer(); + $this->service->run(); + } else { + include 'layerserver.class.php'; + $this->service = new LayerServer(); + $this->service->run(); + } + } + + /** + * Get all request parameters + */ + function get_request(){ + $this->service = $this->load_parm('service'); + if(!$this->service){ + $this->service= 'kml'; + } + } + + /** + * Get a request parameter + * @param string $name + * @return string the parameter value or empty string if null + */ + function load_parm($name){ + if(!isset($_REQUEST[$name])) return ''; + $value = $_REQUEST[$name]; + if(get_magic_quotes_gpc() != 1) $value = addslashes($value); + //$value = escapeshellcmd($value); + return $value; + } +} +?> \ No newline at end of file diff --git a/pacotes/kmlmapserver/classes/layerserver.class.php b/pacotes/kmlmapserver/classes/layerserver.class.php new file mode 100644 index 0000000..1116b2b --- /dev/null +++ b/pacotes/kmlmapserver/classes/layerserver.class.php @@ -0,0 +1,908 @@ + +* accepted parameters (case insensitive): +* - request = string - request type (OGC WFS like), can be kml (default), kmz, icon +* - map = string - path to mapfile +* - typename = string - (can be a csv list) - layer name(s) +* - filter = string - filter encoding +* - bbox = string - (csv) - bounding box csv +* - encoding = string - data and mapfile encoding, defaults to ISO-8859-1 +* +* +* +* +* @author Alessandro Pasotti +* @copyright 2007 ItOpen.it - All rights reserved +* @package KMLMAPSERVER + +This file is part of KMLMAPSERVER. + + KMLMAPSERVER is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + KMLMAPSERVER is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with KMLMAPSERVER; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + + +/** Fix a GE bug for filled polygons */ +define('TREAT_POLY_AS_LINE', true); + +/** Enable cache */ +define('ENABLE_CACHE', true); + +if (!extension_loaded('MapScript')) +{ + dl( 'php_mapscript.' . PHP_SHLIB_SUFFIX ); +} + + +/** +* Main server class +*/ + +class LayerServer { + + /** map file path */ + var $map; + + /** request */ + var $request; + + /** map instance */ + var $map_object; + + /** layer name(s) passed on the request */ + var $typename; + + /** array of requested layer objects (hash with layer name as key) */ + var $layers; + + /** filters */ + var $filter; + + /** bounding box */ + var $bbox; + + /** error messages */ + var $errors; + + /** send zipped data */ + var $_zipped = false; + + /** internal XML buffer */ + var $_xml; + + /** input projection */ + var $in_proj; + + /** output projection */ + var $out_proj; + + /** debug flag */ + var $_debug = false; + + /** end point */ + var $endpoint; + + /** custom style counter */ + var $style_counter = 0; + + /** + * Mapfile and data encoding encoding + * XMl output must be UTF-8, attributes and METADATA based strings + * must be converted to UTF-8, encoding defaults to ISO-8859-1, if + * your encoding is different, you can set it through CGI style parameters + */ + var $encoding; + + /** + * send networklink + * wether folder should contain networklinks instead of real geometries + * it is automatically set when all layers are requested + */ + var $_networklink; + + + /** + * Initialize + * + */ + function LayerServer(){ + $this->errors = array(); + // Load request parameters + $this->get_request(); + + $this->style_counter = 0; + + // Load map + if(!$this->has_error()) { + $this->load_map(); + } + + } + + /** + * Run the server and sends data + * @return string or void + */ + function run(){ + // Check cache + if(ENABLE_CACHE){ + $cache_file = $this->get_cache_file_name(); + if(file_exists($cache_file)){ + // Check if is not expired + $layer = $this->map_object->getLayerByName($this->typename); + if(filectime($cache_file) + $layer->getMetadata('KML_CACHE') < (time())) { + error_log('removing cache ' . $cache_file); + //error_log('ctime : ' . filectime($cache_file) . ' , ' . time() . ' lm ' . $layer->getMetadata('KML_CACHE')); + @unlink($cache_file); + } else { + $this->send_header(); + error_log('sending cache ' . $cache_file); + readfile($cache_file); + exit; + } + } + } + + // If not layer are requested, send all as networklinks + if(!$this->typename){ + $this->_networklink = true; + $this->typename = $this->get_layer_list(); + } else { + $this->_networklink = false; + } + + $this->_xml = new SimpleXMLElement(''); + // Prepare projection + $this->in_proj = ms_newProjectionObj($this->map_object->getProjection()); + // Set projection to GOOGLE earth's projection + $this->out_proj = ms_newProjectionObj("init=epsg:4326"); + // Set endpoint + //die($_SERVER['REQUEST_URI']); + $this->endpoint = ($_SERVER['HTTPS'] ? 'https' : 'http') . '://'.$_SERVER['SERVER_NAME'] . ($_SERVER['SERVER_PORT'] ? ':'.$_SERVER['SERVER_PORT'] : '') . $_SERVER['PHP_SELF']; + + + // Process request + if(!$this->has_error()) { + $this->process_request(); + } + if($this->has_error()){ + $this->add_errors(); + } + return $this->send_stream($this->get_kml()); + } + + /** + * Set debug flag + * @param boolean $value + */ + function set_debug($value){ + $this->_debug = $value; + } + + /** + * Get all request parameters + */ + function get_request(){ + $this->map = $this->load_parm('map'); + $this->bbox = $this->load_parm('bbox'); + $this->filter = $this->load_parm('filter'); + $this->typename = $this->load_parm('typename'); + $this->encoding = $this->load_parm('encoding', 'ISO-8859-1'); + $this->request = $this->load_parm('request', 'kml'); + + if($this->request == 'kmz') { + $this->_zipped = true; + } + + if(!$this->map){ + $this->set_error('No mapfile specified'); + } + } + + /** + * Apply filter + * @return array + */ + function apply_filter(&$layer, &$filter){ + if($layer->connectiontype == MS_POSTGIS){ + if($filter->PropertyIsEqualTo){ + $searchstring = '"'.$filter->PropertyIsEqualTo->PropertyName . ' = ' . '\''.addslashes($filter->PropertyIsEqualTo->Literal).'\''.'"'; + $searchfield = $filter->PropertyIsEqualTo->PropertyName; + } elseif($filter->PropertyIsLike){ + $searchfield = $filter->PropertyIsLike->PropertyName; + $searchstring ='"'.$filter->PropertyIsLike->PropertyName . ' LIKE \'%' . addslashes($filter->PropertyIsLike->Literal) . '%\''.'"'; + } + } elseif($layer->connectiontype == MS_SHAPEFILE || $layer->connectiontype == MS_OGR){ + if($filter->PropertyIsEqualTo){ + $searchstring = $filter->PropertyIsEqualTo->Literal; + $searchfield = $filter->PropertyIsEqualTo->PropertyName; + } elseif($filter->PropertyIsLike){ + $searchstring = $filter->PropertyIsLike->Literal; + $searchfield = $filter->PropertyIsLike->PropertyName; + } + } + return array($searchfield, $searchstring); + } + + /** + * Process request + */ + function process_request(){ + // Get layer(s) + $layers = split(',', $this->typename); + if($this->_networklink){ + foreach($layers as $layer){ + $this->add_networklink($layer); + } + } else { + foreach($layers as $layer){ + $this->process_layer_request($layer); + } + } + } + + /** + * Add a networklink + */ + function add_networklink(&$layer_name){ + $nl =& $this->_xml->Document->addChild('NetworkLink'); + + $layer = @$this->map_object->getLayerByName($layer_name); + $nl->addChild('name', $this->get_layer_description($layer)); + $nl->addChild('visibility', 0); + $link =& $nl->addChild('Link'); + $link->addChild('href', $this->endpoint . '?map=' . $this->map . '&typename=' . urlencode($layer_name) . '&request=' . ($this->_zipped ? 'kmz' : 'kml')); + } + + + /** + * Process a single layer + * @return boolean false on error + */ + function process_layer_request(&$layer_name){ + + $layer = @$this->map_object->getLayerByName($layer_name); + + if(!$layer){ + $this->set_error('Layer not found ' . $layer_name, $layer_name); + return false; + } + + // Add to layer list + $this->layers[$layer_name] =& $layer; + + // Get custom template if any + $description_template = $layer->getMetadata('DESCRIPTION_TEMPLATE'); + + // Set on + $layer->set( 'status', MS_ON ); + + // Set kml title from layer description (default to layer name) + $layer_desc = $this->get_layer_description($layer); + + // Now switch raster layers + //var_dump($layer->type == MS_LAYER_RASTER); + if($layer->type == MS_LAYER_RASTER){ + // Check if wms_onlineresource metadata is set + $wms_link = $this->map_object->getMetadata('wms_onlineresource'); + if(!$wms_link){ + $wms_link = $this->map_object->getMetadata('ows_onlineresource'); + } + if(!$wms_link){ + $this->set_error('No WMS server available for ' . $layer_name, $layer_name); + return false; + } + // Add parameters to OGC server call + // Fix & + $wms_link = preg_replace('/&/', '&', $wms_link); + $wms_link .= 'VERSION=1.1.1&REQUEST=GetMap&SRS=EPSG:4326&STYLES=&BGCOLOR=0xFFFFFF&FORMAT=image/png&TRANSPARENT=TRUE&'; + // Link ok, create folder + $folder =& $this->_xml->Document->addChild('GroundOverlay'); + $folder->addChild('description', $this->get_layer_description($layer)); + $folder->addChild('name', $layer_desc); + $this->add_wms_link($folder, $layer, $wms_link); + } else { + + // Apply filter + if($this->filter){ + // Try loading as XML + try { + $filter = @new SimpleXMLElement($this->filter); + list($searchfield, $searchstring) = $this->apply_filter($layer, $filter); + if(! ($searchfield && $searchstring)){ + $this->set_error('Error parsing filter', $layer_name); + return false; + } + } catch (Exception $e) { + $this->set_error('Wrong XML filter', $layer_name); + $this->filter = null; + return false; + } + } + + // Get results + if(MS_SUCCESS == $layer->open()){ + // Search which column to use to identify the feature + $namecol = $layer->getMetadata('RESULT_FIELDS'); + if(!$namecol){ + $cols = array_values($layer->getItems()); + $namecol = $cols[0]; + } + // Add classes + $folder =& $this->_xml->Document->addChild('Folder'); + $class_list = $this->parse_classes($layer, $folder, $namecol, $title_field, $description_template); + + //die(print_r($class_list, true)); + $folder->addChild('description', $this->get_layer_description($layer)); + $folder->addChild('name', $layer_desc); + + //print("$searchfield && $searchstring"); + if($searchfield && $searchstring){ + if(@$layer->queryByAttributes($searchfield, $searchstring, MS_MULTIPLE) == MS_SUCCESS){ + $layer->open(); + //var_dump($layer->getItems()); die(); + for ($j=0; $j < $layer->getNumResults(); $j++) + { + // get next shape row + $result = $layer->getResult($j); + $shape = $layer->getShape($result->tileindex, $result->shapeindex); + $this->process_shape($layer, $shape, $class_list, $folder, $namecol); + // end for loop + } + } else { + $this->set_error('Query returned no data', $layer_name); + return false; + } + } else { // Get all shapes + $status = $layer->whichShapes($this->map_object->extent); + while ($shape = $layer->nextShape()) { + $this->process_shape($layer, $shape, $class_list, $folder,$namecol ); + } + } + $layer->close(); + } else { + $this->set_error('Layer cannot be opened', $layer_name); + return false; + } + } + return true; + } + + /** + * Process the shape + */ + function process_shape(&$layer, &$shape, &$class_list, &$folder, &$namecol){ + $shape->project($this->in_proj, $this->out_proj); + // Assign style + if($layer->classitem){ + $style_id = $this->get_shape_class($layer->classitem, $shape->values, $class_list); + } + if(!$style_id){ + // Get first class + $class_keys = array_keys($class_list); + $style_id = $class_keys[0]; + } + // Add the feature + if(array_key_exists('folder', $class_list[$style_id])) { + $feature_folder =& $class_list[$style_id]['folder']; + } else { + //die('missing folder for ' . $style_id); + $feature_folder =& $folder; + } + if(!is_object($feature_folder)){ + $folder_name = $feature_folder; + $feature_folder =& $folder ->addChild('Folder'); + $feature_folder->addChild('name', $folder_name); + } + // Add style class + $style_url =& $this->add_style($layer, $feature_folder, $style_id, $class_list[$style_id], $namecol, $shape->values); + + $wkt = $shape->toWkt(); + $placemark =& $this->add_feature($feature_folder, $wkt, $shape->values[$namecol], $shape->values, $description_template, $class_list[$style_id]); + + $placemark->addChild('styleUrl', '#'. $style_url); + + } + + /** + * Add the feature to the result set + * @return reference to placemark object + */ + function &add_feature(&$folder, &$wkt, $featurename, $attributes, $description_template, $style_data){ + $pm = $folder->addChild('Placemark'); + //if($featurename == 'VERCELLI') {var_dump($wkt); die();} + $pm->addChild('name', iconv($this->encoding, 'utf-8', $featurename)); + $pm->addChild('description', $this->get_feature_description($featurename, $attributes, $description_template)); + // Now parse the wkt + if(strpos($wkt, 'MULTILINESTRING') !== false){ + $this->add_multilinestring($wkt, $pm, $featurename, $style_data['icon']); + } elseif(strpos($wkt, 'LINESTRING') !== false){ + $this->add_linestring($wkt, $pm, $featurename, $style_data['icon']); + } elseif(strpos($wkt, 'POINT') !== false){ + $this->add_point($wkt, $pm, $featurename); + } elseif(strpos($wkt, 'MULTIPOLYGON') !== false){ + if(TREAT_POLY_AS_LINE){ + $ml = $pm->addChild('MultiGeometry'); + foreach(split('\), \(', $wkt) as $line){ + $this->add_multilinestring($line, $ml, $featurename ); + } + } else { + $this->add_multipolygon($wkt, $pm, $featurename); + } + } elseif(strpos($wkt, 'POLYGON') !== false){ + if(TREAT_POLY_AS_LINE){ + $this->add_multilinestring($wkt, $pm, $featurename); + } else { + $this->add_polygon($wkt, $pm, $featurename); + } + } else { + // Error? + } + return $pm; + } + + /** + * Add a linestring + */ + function add_linestring(&$wkt, &$element, $featurename, $add_points){ + preg_match('/(\d+[^\(\)]*\d)/', $wkt, $data); + $data = str_replace(', ', '#', $data[1]); + $data = str_replace(' ', ',', $data); + $data = str_replace('#', ' ', $data); + if($add_points){ + preg_match('/^(\d+\.\d+,\d+\.\d+).*(\d+\.\d+,\d+\.\d+)$/', $data, $points); + if(count($points) == 3){ + $mg = $element->addChild('MultiGeometry'); + $ls = $mg->addChild('LineString'); + $pt1 = $mg->addChild('Point'); + $pt1->addChild('coordinates', $points[1]); + $pt2 = $mg->addChild('Point'); + $pt2->addChild('coordinates', $points[2]); + } else { + die('errore'); + $ls = $element->addChild('LineString'); + } + //print_r($points);die(); + } else { + $ls = $element->addChild('LineString'); + } + $ls->addChild('coordinates', $data); + } + + /** + * Add a multilinestring + */ + function add_multilinestring(&$wkt, &$element, $featurename, $add_points){ + $ml = $element->addChild('MultiGeometry'); + foreach(split('\), \(', $wkt) as $line){ + $this->add_linestring($line, $ml, $featurename, $add_points ); + } + } + + /** + * Add a point + */ + function add_point(&$wkt, &$element, $featurename){ + $pt = $element->addChild('Point'); + preg_match('/(\d\.?\d+\s\d+\.?\d+)/', $wkt, $data); + $data = str_replace(' ', ',', $data[1]); + $pt->addChild('coordinates', $data); + } + + + /** + * Add a polygon + */ + function add_polygon(&$wkt, &$element, $featurename){ + $ml = $element->addChild('Polygon'); + foreach(split('\), \(', $wkt) as $line){ + preg_match('/(\d+[^\(\)]*\d)/', $wkt, $data); + $data = str_replace(', ', '#', $data[1]); + $data = str_replace(' ', ',', $data); + // Add 1 meter height + $data = str_replace('#', ',1 ', $data) . ',1'; + $ml->addChild('tessellate', 1); + //$element->addChild('altitudeMode', 'relativeToGround'); + $element->addChild('altitudeMode', 'clampToGround'); + $ob = $ml->addChild('outerBoundaryIs'); + $ls = $ob->addChild('LinearRing'); + $ls->addChild('coordinates', $data); + } + } + + + /** + * Add a multipolygon + * FIXME: untested, should take holes into account + */ + function add_multipolygon(&$wkt, &$element, $featurename){ + $ml = $element->addChild('MultiGeometry'); + foreach(split('\), \(', $wkt) as $line){ + $this->add_polygon($line, $ml, $featurename ); + } + } + + + /** + * Get the feature description + */ + function get_feature_description($featurename, $attributes, $description_template){ + // Compute hyperlink + if($description_template){ + $description = $description_template; + foreach($attributes as $k => $val){ + $description = str_replace("%$k%", iconv($this->encoding, 'utf-8', $val), $description); + } + } else { + $description = iconv($this->encoding, 'utf-8', $featurename); + } + return htmlentities($description); + } + + + /** + * Parse classes + * @return array hash of 'style_id' => style_data) + */ + function parse_classes(&$layer, &$folder, &$namecol, &$title_field, &$description_template ){ + $style_ar = array(); + $numclasses = $layer->numclasses; + for($i = 0; $i < $numclasses; $i++){ + $class = $layer->getClass($i); + $label = $class->label; + if($label){ + $style['label_color'] = $label->color; + $style['label_size'] = $label->size; + } + // Get styles + for($j = 0; $j < $class->numstyles; $j++){ + $_style = $class->getStyle($j); + $style['color'] = $_style->color; + $style['outlinecolor'] = $_style->outlinecolor; + $style['width'] = $_style->size; // Lines + $style['backgroundcolor'] = $_style->backgroundcolor; + $style['icon'] = $this->get_icon_url($layer, $class->name); + $style['icon_width'] = $_style->size; // Points + + } + $style['expression'] = $class->getExpression(); + // Set description_template if any + $style['description_template'] = $description_template; + // Get icon for lines if any + if($icon = $layer->getMetadata('KML_ADD_POINT')){ + $style['icon'] = $icon; + $style['icon_width'] = 32; + } + // Create style element + $style_id = preg_replace('/[^A-z0-9]/', '_', $layer->name . $class->name); + //$this->add_style($layer, $folder, $style_id, $style, $namecol, $title_field ); + // create folder if more than one class + if($numclasses > 1){ + $style['folder'] =& $class->name; + //$folder->addChild('Folder'); + //$style['folder']->addChild('name', $class->name); + } + $style_ar[$style_id] = $style; + } + return $style_ar; + } + + /** + * Return a CSV list of all layer names in the mapfile + * FIXME: filter out ANNOTATIONS and other "strange" layers + */ + function get_layer_list(){ + $layer_list = array(); + for($i = 0; $i < $this->map_object->numlayers; $i++){ + $layer =& $this->map_object->getLayer($i); + $kml_skip = $layer->getMetadata('KML_SKIP'); + if(strtolower($kml_skip) !== 'true'){ + $layer_list[] = $layer->name; + } + } + return join(',', $layer_list); + } + + + /** + * Return the class for the shape, default to last class if not match + */ + function get_shape_class(&$classitem, &$values, &$class_list){ + //var_dump($class_list); die(); + foreach($class_list as $style_id => $style_data){ + if($style_data['expression'] && preg_match($style_data['expression'], $values[$classitem])){ + //print "get_shape_class($classitem) ".$values[$classitem]." matches
"; + return $style_id; + } + } + //print "get_shape_class($classitem) ".$values[$classitem]." no matches
"; + return $style_id; + } + + /** + * Add the style + * @return the style URL + */ + function add_style(&$layer, &$folder, $style_id, &$style_data){ + // Calculare style URL + /* + if($style_data['description_template']){ + $this->style_counter++; + $style_id .= '_'.$this->style_counter; + $balloon_data = $this->get_feature_description($attributes[$namecol], $attributes, $style_data['description_template']); + } + */ + // Check if the style already exists + $expr = '//*[@id=\''.$style_id.'\']'; + if($folder->xpath($expr)) { + return $style_id; + } + $new_style =& $folder->addChild('Style'); + $new_style['id'] = $style_id; + // Switch layer type + switch($layer->type){ + case MS_LAYER_POINT: + $this->add_style_point($new_style, $style_data); + break; + case MS_LAYER_POLYGON: + $this->add_style_polygon($new_style, $style_data); + break; + case MS_LAYER_LINE: + $this->add_style_line($new_style, $style_data); + // Add KML_ADD_POINT icon + if($style_data['icon']){ + $this->add_style_point($new_style, $style_data); + } + break; + } + return $style_id; + } + + /** + * Add style for lines + */ + function add_style_line(&$new_style, &$style_data){ + if($style_data['outlinecolor']->red != -1){ + $st =& $new_style->addChild('LineStyle'); + $st->addChild('color', sprintf('FF%02X%02X%02X', $style_data['outlinecolor']->blue, $style_data['outlinecolor']->green, $style_data['outlinecolor']->red)); + if($width) { + $st->addChild('width', $width); + } + } elseif($style_data['color']->red != -1){ + $st =& $new_style->addChild('LineStyle'); + $st->addChild('color', sprintf('FF%02X%02X%02X', $style_data['color']->blue, $style_data['color']->green, $style_data['color']->red)); + if($width) { + $st->addChild('width', $width); + } + } + } + + /** + * Add style for points + */ + function add_style_point(&$new_style, &$style_data){ + if($style_data['icon']){ + $st =& $new_style->addChild('IconStyle'); + if($style_data['width'] && $style_data['icon_width'] != 32){ + $st->addChild('scale', $style_data['icon_width'] / 32); + } + $icon =& $st->addChild('Icon'); + $icon->addChild('href', htmlentities($style_data['icon'])); + } + /*/ Add the balloon style if description_template is set + if($style_data['description_template']){ + $this->add_balloon_style($new_style, $balloon_data); + } + */ + // Label size and color + if($style_data['label_size'] || $style_data['label_color']){ + $ls =& $new_style->addChild('LabelStyle'); + if($style_data['label_size'] != -1 && $style_data['label_size'] != 32){ + $ls->addChild('scale', $style_data['label_size'] / 32); + } + if($style_data['label_color']->red != -1){ + $ls->addChild('color', sprintf('FF%02X%02X%02X', $style_data['label_color']->blue, $style_data['label_color']->green, $style_data['label_color']->red)); + } + } + } + + /** + * Add style for polygons + */ + function add_style_polygon(&$new_style, &$style_data){ + // Get also outline styles + $this->add_style_line($new_style, $style_data); + $st =& $new_style->addChild('PolyStyle'); + //die(print_r($backgroundcolor, true)); + if($style_data['backgroundcolor']->red != -1){ + $st->addChild('color', sprintf('FF%02X%02X%02X', $style_data['backgroundcolor']->blue, $style_data['backgroundcolor']->green, $style_data['backgroundcolor']->red)); + $st->addChild('fill', 0); + } else { + $st->addChild('fill', 0); + } + $st->addChild('outline', 1); + } + + /** + * Add a WMS raster link + */ + function add_wms_link(&$folder, &$layer, &$link){ + // Build up the KML response document. + $icon =& $folder->addChild('Icon'); + $icon->addChild('href', $link . 'layers=' . $layer->name); + //$icon->addChild('viewBoundScale', 1.5); + $icon->addChild('viewRefreshMode', 'onStop'); + $llbox =& $folder->addChild('LatLonBox'); + $ext = $this->map_object->extent; + $ext->project($this->in_proj, $this->out_proj); + $llbox->north = $ext->maxy; + $llbox->south = $ext->miny; + $llbox->east = $ext->maxx; + $llbox->west = $ext->minx; + // Reset original projection + $ext->project($this->out_proj, $this->in_proj); + } + + /** + * Get the url for a point icon + */ + function get_icon_url($layer, $classname){ + return $this->endpoint . '?service=icon&map=' . $this->map . '&typename=' . urlencode($layer->name) . '&classname=' . urlencode($classname); + } + + /** + * Get the layer description + */ + function get_layer_description(&$layer){ + $description = $layer->getMetadata('DESCRIPTION'); + if(!$description){ + $description = $layer->getMetadata('OWS_TITLE'); + } + if(!$description){ + $description = $layer->getMetadata('WFS_TITLE'); + } + if(!$description){ + $description = $layer->getMetadata('WMS_TITLE'); + } + if(!$description){ + $description = $layer->name; + } + return $description; + } + + + + /** + * Add style for balloon + * @param string style XML id + * @param string column name for title + */ + function add_balloon_style(&$style, $balloon_data){ + $balloon =& $style->addChild('BalloonStyle'); + $balloon->addChild('text', htmlentities($balloon_data)); + } + + + /** + * Get a request parameter + * @param string $name + * @param string $default parameter optional + * @return string the parameter value or empty string if null + */ + function load_parm($name, $default = ''){ + if(!isset($_REQUEST[$name])) return $default; + $value = $_REQUEST[$name]; + if(get_magic_quotes_gpc() != 1) $value = addslashes($value); + //$value = escapeshellcmd($value); + return $value; + } + + /** + * Set error message + * @param string $message + * @param string $layer name + */ + function set_error($message, $layer = 'Error'){ + $this->errors[$layer][] = $message; + } + + + /** + * Load the map and create the map instance + */ + function load_map(){ + if(!file_exists($this->map) && is_readable($this->map)){ + $this->set_error('Cannot read mapfile '. $this->map); + } else { + $this->map_object = ms_newMapObj($this->map); + if(!$this->map_object){ + $this->set_error('Cannot load mapfile '. $this->map); + } + } + } + + /** + * Test if has errors + * @return boolean + */ + function has_error(){ + return count($this->errors) > 0; + } + + /** + * Add error messages to folders TAGS + */ + function add_errors(){ + foreach($this->errors as $layer => $errors){ + $folder =& $this->_xml->Document->addChild('Folder'); + $folder->addChild('name', $layer); + $folder->addChild('description', '

' . join("

\n

", $errors) . "

"); + } + return $errorxml; + } + + /** + * Fetch XML and format it + */ + function get_kml(){ + $doc = new DOMDocument('1.0'); + $doc->formatOutput = true; + $domnode = dom_import_simplexml($this->_xml); + $domnode = $doc->importNode($domnode, true); + $domnode = $doc->appendChild($domnode); + return $doc->saveXML(); + } + + /** + * Send header + */ + function send_header(){ + header('Content-type: application/vnd.google-earth.km'.($this->_zipped ? 'z' : 'l').'+XML'); + } + + /** + * Calculate cache file name + */ + function get_cache_file_name(){ + return 'cache/'. md5($_SERVER['QUERY_STRING']) . ($this->_zipped ? '.kmz' : '.kml'); + } + + /** + * Send stream + */ + function send_stream($data){ + $this->send_header(); + // Compress data + if($this->_zipped){ + include("zip.class.php"); + $ziper = new zipfile(); + $ziper->addFile($data, 'doc.kml'); + $data = $ziper->file(); + } + // Create cache if needed + if(ENABLE_CACHE && count($this->layers) == 1 && $this->layers[$this->typename]->getMetadata('KML_CACHE')) { + error_log( 'creating cache ' . $this->get_cache_file_name() ); + file_put_contents($this->get_cache_file_name(), $data); + } + print $data; + exit(); + } +} +?> \ No newline at end of file diff --git a/pacotes/kmlmapserver/classes/symbolserver.class.php b/pacotes/kmlmapserver/classes/symbolserver.class.php new file mode 100644 index 0000000..e2f3cca --- /dev/null +++ b/pacotes/kmlmapserver/classes/symbolserver.class.php @@ -0,0 +1,210 @@ + +* accepted parameters (case insensitive): +* - map = string - path to mapfile +* - typename = string - layer name +* - classname = string - class name +* +* +* @author Alessandro Pasotti +* @copyright 2007 ItOpen.it - All rights reserved +* @package KMLSERVER + +This file is part of KMLMAPSERVER. + + KMLMAPSERVER is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + KMLMAPSERVER is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with KMLMAPSERVER; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +class SymbolServer { + + /** map file path */ + var $map; + + /** map instance */ + var $map_object; + + /** layer name */ + var $typename; + + /** class */ + var $classname; + + /** class index */ + var $classindex; + + /** icon_layer */ + var $icon_layer; + + /** icon point object */ + var $iconpoint; + + + function SymbolServer(){ + $this->errors = array(); + // Load request parameters + $this->get_request(); + // Load map + if(!$this->has_error()) { + $this->load_map(); + } + } + + /** + * Run the server and sends data + * @return string or void + */ + function run(){ + // Process request + if(!$this->has_error()) { + $this->process_request(); + } + if($this->has_error()){ + $this->send_errors(); + } else { + $this->send_icon(); + } + } + + + /** + * Process request + */ + function process_request(){ + $layer = @$this->map_object->getLayerByName($this->typename); + if(!$layer){ + $this->set_error('Layer not found ' . $layer_name, $layer_name); + return false; + } + // Get class + $class = null; + for($i = 0; $i < $layer->numclasses; $i++){ + $_class = @$layer->getClass($i); + if($this->classname == $_class->name){ + $class =& $_class; + $this->classindex = $i; + break; + } + } + if(!$class){ + $this->set_error('Class name not found ' . $layer_name, $this->classname); + return false; + } + // Get symbol size + for($i = 0; $i < $class->numstyles; $i++){ + $_style = @$class->getStyle($i); + if($_style->symbolname){ + // 64 pixel is standard Google Earth pushpin + //$_style->set('size', 64); + $symbolsize = $_style->size; + break; + } + } + // Provide a default here + if(!$symbolsize) { + $symbolsize = 10; + } + $ext = $this->map_object->extent; + $centerx = ($ext->maxx - $ext->minx)/2; + $centery = ($ext->maxy - $ext->miny)/2; + + // Create a new layer + $this->icon_layer = ms_newLayerObj($this->map_object, $layer); + $this->map_object->setSize($symbolsize, $symbolsize); + $this->map_object->setExtent($centerx - $symbolsize, $centery - $symbolsize, $centerx + $symbolsize, $centery + $symbolsize); + $this->icon_layer->set( 'status', MS_ON ); + $this->iconpoint = ms_newPointObj(); + $this->iconpoint->setXY($centerx, $centery); + } + + /** + * Test if has errors + * @return boolean + */ + function has_error(){ + return count($this->errors) > 0; + } + + /** + * Get all request parameters + */ + function get_request(){ + $this->map = $this->load_parm('map'); + $this->typename = $this->load_parm('typename'); + $this->classname= $this->load_parm('classname'); + if(!$this->map){ + $this->set_error('No mapfile specified'); + } + if(!$this->typename){ + $this->set_error('No typename (layer) specified'); + } + } + + /** + * Get a request parameter + * @param string $name + * @return string the parameter value or empty string if null + */ + function load_parm($name){ + if(!isset($_REQUEST[$name])) return ''; + $value = $_REQUEST[$name]; + if(get_magic_quotes_gpc() != 1) $value = addslashes($value); + //$value = escapeshellcmd($value); + return $value; + } + + /** + * Set error message + * @param string $message + * @param string $layer name + */ + function set_error($message, $layer = 'Error'){ + $this->errors[$layer][] = $message; + } + + /** + * Load the map and create the map instance + */ + function load_map(){ + if(!file_exists($this->map) && is_readable($this->map)){ + $this->set_error('Cannot read mapfile '. $this->map); + } else { + $this->map_object = ms_newMapObj($this->map); + if(!$this->map_object){ + $this->set_error('Cannot load mapfile '. $this->map); + } + } + } + + function send_errors(){ + print_r($this->errors); + } + + function send_icon(){ + header('Content-type:image/png'); + // Set transparency (needs imageformat RBGA in the mapfile too) + $this->map_object->set('transparent', 'on'); + $img = $this->map_object->draw(); + $this->iconpoint->draw($this->map_object, $this->icon_layer, $img, $this->classindex, ''); + $img->saveImage(''); + } + +} +?> \ No newline at end of file diff --git a/pacotes/kmlmapserver/classes/zip.class.php b/pacotes/kmlmapserver/classes/zip.class.php new file mode 100644 index 0000000..84f21cf --- /dev/null +++ b/pacotes/kmlmapserver/classes/zip.class.php @@ -0,0 +1,230 @@ + +* +* http://www.zend.com/codex.php?id=470&single=1 +* by Denis125 +* +* a patch from Peter Listiak for last modified +* date and time of the compressed file +* +* Official ZIP file format: http://www.pkware.com/appnote.txt +* +* @access public +*/ +class zipfile +{ + /** + * Array to store compressed data + * + * @var array $datasec + */ + var $datasec = array(); + + /** + * Central directory + * + * @var array $ctrl_dir + */ + var $ctrl_dir = array(); + + /** + * End of central directory record + * + * @var string $eof_ctrl_dir + */ + var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00"; + + /** + * Last offset position + * + * @var integer $old_offset + */ + var $old_offset = 0; + + + /** + * Converts an Unix timestamp to a four byte DOS date and time format (date + * in high two bytes, time in low two bytes allowing magnitude comparison). + * + * @param integer the current Unix timestamp + * + * @return integer the current date in a four byte DOS format + * + * @access private + */ + function unix2DosTime($unixtime = 0) { + $timearray = ($unixtime == 0) ? getdate() : getdate($unixtime); + + if ($timearray['year'] < 1980) { + $timearray['year'] = 1980; + $timearray['mon'] = 1; + $timearray['mday'] = 1; + $timearray['hours'] = 0; + $timearray['minutes'] = 0; + $timearray['seconds'] = 0; + } // end if + + return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | + ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1); + } // end of the 'unix2DosTime()' method + + + /** + * Adds "file" to archive + * + * @param string file contents + * @param string name of the file in the archive (may contains the path) + * @param integer the current timestamp + * + * @access public + */ + function addFile($data, $name, $time = 0) + { + $name = str_replace('\\', '/', $name); + + $dtime = dechex($this->unix2DosTime($time)); + $hexdtime = '\x' . $dtime[6] . $dtime[7] + . '\x' . $dtime[4] . $dtime[5] + . '\x' . $dtime[2] . $dtime[3] + . '\x' . $dtime[0] . $dtime[1]; + eval('$hexdtime = "' . $hexdtime . '";'); + + $fr = "\x50\x4b\x03\x04"; + $fr .= "\x14\x00"; // ver needed to extract + $fr .= "\x00\x00"; // gen purpose bit flag + $fr .= "\x08\x00"; // compression method + $fr .= $hexdtime; // last mod time and date + + // "local file header" segment + $unc_len = strlen($data); + $crc = crc32($data); + $zdata = gzcompress($data); + $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug + $c_len = strlen($zdata); + $fr .= pack('V', $crc); // crc32 + $fr .= pack('V', $c_len); // compressed filesize + $fr .= pack('V', $unc_len); // uncompressed filesize + $fr .= pack('v', strlen($name)); // length of filename + $fr .= pack('v', 0); // extra field length + $fr .= $name; + + // "file data" segment + $fr .= $zdata; + + // "data descriptor" segment (optional but necessary if archive is not + // served as file) + $fr .= pack('V', $crc); // crc32 + $fr .= pack('V', $c_len); // compressed filesize + $fr .= pack('V', $unc_len); // uncompressed filesize + + // add this entry to array + $this -> datasec[] = $fr; + + // now add to central directory record + $cdrec = "\x50\x4b\x01\x02"; + $cdrec .= "\x00\x00"; // version made by + $cdrec .= "\x14\x00"; // version needed to extract + $cdrec .= "\x00\x00"; // gen purpose bit flag + $cdrec .= "\x08\x00"; // compression method + $cdrec .= $hexdtime; // last mod time & date + $cdrec .= pack('V', $crc); // crc32 + $cdrec .= pack('V', $c_len); // compressed filesize + $cdrec .= pack('V', $unc_len); // uncompressed filesize + $cdrec .= pack('v', strlen($name) ); // length of filename + $cdrec .= pack('v', 0 ); // extra field length + $cdrec .= pack('v', 0 ); // file comment length + $cdrec .= pack('v', 0 ); // disk number start + $cdrec .= pack('v', 0 ); // internal file attributes + $cdrec .= pack('V', 32 ); // external file attributes - 'archive' bit set + + $cdrec .= pack('V', $this -> old_offset ); // relative offset of local header + $this -> old_offset += strlen($fr); + + $cdrec .= $name; + + // optional extra field, file comment goes here + // save to central directory + $this -> ctrl_dir[] = $cdrec; + } // end of the 'addFile()' method + + + /** + * Dumps out file + * + * @return string the zipped file + * + * @access public + */ + function file() + { + $data = implode('', $this -> datasec); + $ctrldir = implode('', $this -> ctrl_dir); + + return + $data . + $ctrldir . + $this -> eof_ctrl_dir . + pack('v', sizeof($this -> ctrl_dir)) . // total # of entries "on this disk" + pack('v', sizeof($this -> ctrl_dir)) . // total # of entries overall + pack('V', strlen($ctrldir)) . // size of central dir + pack('V', strlen($data)) . // offset to start of central dir + "\x00\x00"; // .zip file comment length + } // end of the 'file()' method + + + /** + * A Wrapper of original addFile Function + * + * Created By Hasin Hayder at 29th Jan, 1:29 AM + * + * @param array An Array of files with relative/absolute path to be added in Zip File + * + * @access public + */ + function addFiles($files /*Only Pass Array*/) + { + foreach($files as $file) + { + if (is_file($file)) //directory check + { + $data = implode("",file($file)); + $this->addFile($data,$file); + } + } + } + + /** + * A Wrapper of original file Function + * + * Created By Hasin Hayder at 29th Jan, 1:29 AM + * + * @param string Output file name + * + * @access public + */ + function output($file) + { + $fp=fopen($file,"w"); + fwrite($fp,$this->file()); + fclose($fp); + } + + + +} // end of the 'zipfile' class +?> \ No newline at end of file diff --git a/pacotes/kmlmapserver/doc/index.html b/pacotes/kmlmapserver/doc/index.html new file mode 100644 index 0000000..adf20a8 --- /dev/null +++ b/pacotes/kmlmapserver/doc/index.html @@ -0,0 +1,4 @@ +

See online docs here:
+ +http://www.itopen.it/soluzioni/webmapping/kml-map-server/ +

\ No newline at end of file diff --git a/pacotes/kmlmapserver/kmlservice.php b/pacotes/kmlmapserver/kmlservice.php new file mode 100644 index 0000000..adef6d5 --- /dev/null +++ b/pacotes/kmlmapserver/kmlservice.php @@ -0,0 +1,30 @@ + \ No newline at end of file -- libgit2 0.21.2