Jesus Loves GRASS

Technical blog about GRASS/GIS,open source geoinformatics and MAPSERVER.

Friday, April 20, 2007

PHP popup

This is the PHP that will make the popup, it is more or less prepared for when the WFS is installed:

<?php
/* This PHP will generate the HTML code for the final submission of the request
The Javascript calling string is :
url_str='popup.php?service='+OWS_service+'&request=getCoverage&COVERAGE='+OWS_name+'&CRS='+CRS+'&BBOX='+BBOX.join(",")+'&RESX='+RESX[0]+'&RESY='+(-1*parseFloat(RESY[1]))+'&FORMAT='+FORMAT; */

?>

<body>
<table width="350px" border="0">
<tbody>
<tr bgcolor="#CFCFCF" >
<td><?php echo(strtoupper($_GET["service"])); ?> name:</td>
<!--getting the name of layer -->
<?php if (strnatcasecmp ($_GET["service"],'wcs') == 0){
$OWS_name=$_GET["COVERAGE"];
}
?>
<td align="center" ><?php echo($OWS_name); ?></td>
</tr>
<tr>
<td>CRS (projection):</td>
<td align="center"><?php echo($_GET["CRS"]); ?></td>
</tr>
<tr bgcolor="#CFCFCF">
<!-- getting the bbox back to array -->
<?php
$BBOX=explode(",",$_GET["BBOX"]); ?>
<td>BBOX minX:</td>
<td align="center"><?php echo($BBOX[0]); echo(" º N"); ?></td>
</tr>
<tr>
<td>BBOX minY:</td>
<td align="center"><?php echo($BBOX[1]); echo(" º N"); ?></td>
</tr>
<tr bgcolor="#CFCFCF">
<td>BBOX maxX:</td>
<td align="center"><?php echo($BBOX[2]); echo(" º W"); ?></td>
</tr>
<tr>
<td>BBOX maxY:</td>
<td align="center"><?php echo($BBOX[3]); echo(" º W"); ?></td>
</tr>
<tr bgcolor="#CFCFCF">
<td>ResX:</td>
<td align="center"><?php echo($_GET["RESX"]); ?></td>
</tr>
<tr>
<td>ResY:</td>
<td align="center"><?php echo("-"); echo($_GET["RESY"]); ?></td>
</tr>
<tr bgcolor="#CFCFCF">
<td>Format:</td>
<td align="center"><?php echo($_GET["FORMAT"]); ?></td>
</tr>
</tbody>
</table>

<!--building request-->
<?php
//checking the service
if (strnatcasecmp ($_GET["service"],'wcs') == 0) {

//start of form
echo('<FORM action="ows.php" method="GET"><input type="hidden" name="service" value="WCS"><input type="hidden" name="request" value="getCoverage"><input type="hidden" name="coverage" value="');echo($OWS_name);echo('">');

//mid section
echo('<input type="hidden" name="CRS" value="');echo($_GET["CRS"]);echo('">');
echo('<input type="hidden" name="BBOX" value="');echo($_GET["BBOX"]);echo('">');
echo('<input type="hidden" name="RESX" value="');echo($_GET["RESX"]);echo('">');
echo('<input type="hidden" name="RESY" value="');echo($_GET["RESY"]);echo('">');
echo('<input type="hidden" name="FORMAT" value="');echo($_GET["FORMAT"]);echo('">');

//final secion
echo('<p align="center"><INPUT type="submit" value="Request Coverage"></p></FORM>');

}
?>

Labels: , ,

OWS_request

The Legend is static and is drawn at the start up so I couldn't make a link in the download icon making a specific WxS request.

The solution was a javascript function that is called when the icon is pressed. This function will get the service and the name of the layer, later it will request adicional information (getDescription) so that a proper WxC can be performed.

After getting all the information the functions opens a window and calls a PHP file (passing by GET all the information for the WxS). The new pop-up will have all the values hidden inside a form. When the user click on "submit" the final WxS will be performed. The pop-up also containes a table with all the information on the request

function OWS_request (OWS_name, OWS_service) {
//example of request
//ows.php?service=srtm10x&request=getCoverage&COVERAGE=srtm10x+&CRS=epgs:4326&BBOX=41,75,45,50&RESX=0.00833&RESY=0.00833&FORMAT=GEOTIFFINT16';


//Creation of the XTMLHTTP object and request of information coverage
request=new getXMLHTTP()
var URL='ows.php?service=WCS&request=describeCoverage&coverage='+OWS_name;
request.open ('GET',URL,false) ; //wait for response
request.send(null);
var xmldoc=request.responseXML;
//necessary info: CRS,RESX,RESY,FORMAT,BBOX the name is alreay given
//the XML programming was from the AJAX for Dummies
//for example the tag gml:offsetVector has the name offsetVector the GML is nothing
var CRSnode=xmldoc.getElementsByTagName("requestResponseCRSs");
var CRS=CRSnode[0].firstChild.nodeValue;
var RESnode=xmldoc.getElementsByTagName("offsetVector");
var sRESX=RESnode[0].firstChild.nodeValue;
var RESX=sRESX.split(" "); //array with resx in this case the first value is the important one
var sRESY=RESnode[1].firstChild.nodeValue;
var RESY=sRESY.split(" ");
var FORMATnode=xmldoc.getElementsByTagName("formats");
var FORMAT=FORMATnode[0].firstChild.nodeValue;

/*The BBOX comes from the getGeoExtents, were it is defined that
gminx=minx;
gmaxx=maxx;
gmaxy=maxy;
gminy=miny;

These are golbal variables, so no problem to access them, also they are always changed according to the events of kamap

BBOX = lower left (min x, min y) and upper right (max x, max y)
*/
var BBOX = new Array(gminx,gminy,gmaxx,gmaxy);

//creation of the URL that passes the information to the popup.php
//note: RESY fix in the string (it canot be negative)
var url_str='popup.php?service='+OWS_service+'&request=getCoverage&COVERAGE='+OWS_name+'&CRS='+CRS+'&BBOX='+BBOX.join(",")+'&RESX='+RESX[0]+'&RESY='+(-1*parseFloat(RESY[1]))+'&FORMAT='+FORMAT;

//open window
var window_popup=window.open(url_str,null,"height=300,width=375");
};

Labels: , ,

Layer's HTML

The HTML that generate the Legend is in member createLayerHTML of the Kalegend.

After the HTML for the query control I added the following if (a bit similar to the query one


if (this.showDownloadControl) {
td = document.createElement('td');
td.width = '14';
if (oLayer.isDownload()) {
a = document.createElement('a');
a.href ='javascript:OWS_request(\"'+oLayer.name+'\",\"'+oLayer.ows_service+'\")';
img = document.createElement( 'img' );
img.width = '14';
img.height = '14';
img.src = 'images/download_ok.png';
img.border='0';
img.id=oLayer.name;
img.alt = "OWS download request";
img.title = "OWS download request";
a.appendChild(img);
td = document.createElement( 'td' );
td.appendChild(a);

} else {
img = document.createElement( 'img' );
img.width = '14';
img.height = '14';
img.src = 'images/download_no.png';
img.oLayer = oLayer;
img.id=oLayer.name;
img.alt = "OWS not available";
img.title = "OWS not available";
td = document.createElement( 'td' );
td.appendChild(img);
}
td.width = '16';
tr.appendChild(td);
}

This code will simpely check if the layer can/can't be downloaded and give the specific icon

Monday, April 16, 2007

WCS and WFS metadata

I forgot that aside from the information if the map is downloadable or not is is also necessary to know what service, so another metadata tag was added

METADATA
"ows_service" "wcs"
END

it can be "wcs" or "wfs"

The programming is basically the same for the download but simpler since is it only a property and it doesn't need functions like isDownload()

The getMetadata is a bit different because the wcs and wfs are string and need '', otherwise the javascript eval() will not work (this functions runs the init.php reply)

$ows_service = "null";
if ($oLayer->getMetaData ("ows_service") !="") {
if(strcasecmp($oLayer->getMetaData("ows_service"), "wcs") == 0)
$ows_service = "'wcs'";

if(strcasecmp($oLayer->getMetaData("ows_service"), "wfs") == 0)
$ows_service = "'wfs'";

}

Labels: , , ,

Sunday, April 15, 2007

Let there be KaLEGEND

To start the KaLegend object has its options defined in the myOnload() function of the StartUp.js (which is located in the /tools/kaAqua path....)

I defined the option of download like the other properties:

legendOptions.download = typeof gbLegendDownloadControl != 'undefined' ? gbLegendDownloadControl : true;

the gbLegendDownloadControl is not necessary, it is just here to look good :)

jumping to the kaLengend constructor in the kaLegend.js, It was added a new property:

this.showDownloadControl=true;

and some codelines lower:

this.showDownloadControl = typeof options.download != 'undefined' ? options.download : true;

the standard options is to show the controls unless otherwise defined in the options.download

Labels: , , ,

_map / _layer object and new methods/properties

The previous post passed the metadadata to a php variable that contains the properties of the layers, later these values are passed to the object it self when is created by the constructor funcion.

The layer object contains several important methods and properties that will be used mainly by kaLegend to draw everything that is needed to download the layer

The layer object is defined in the kaMap.js and in the "contructor" function (is it correct to call it constructor ?! ) It was added:

this.download = (typeof(o.download) != 'undefined') ? o.download : false;

This is necessary to be certain that the layer always has this property as true or false

The next step is to create a member that returns is a layer is donwloable or not

_layer.prototype.isDownload = function() {
return this.download;
}

the member isDownload will be usefull in the _map object, since this object need a method that gives the list of downloadable layers

_map.prototype.getDownloadLayers = function() {
var r = [];
var l = this.getLayers();
for( var i=0; i<l.length; i++) {
if (l[i].isDownload()) {
r.push(l[i]);
}
}
return r;
};

Labels: , , ,

Fetching Metadata

THe metadata contained in the MAP file is fetched at init.php and based on the programming already there:

$download = "false";
if ($oLayer->getMetaData ("download") !="") {
if(strcasecmp($oLayer->getMetaData("download"), "true") == 0)
$download = "true";
}

This will get the metadata from dowload in the MAP file and pass the value to the $download variable of PHP, as default the $download is false

Then the $download is integrated in the layer as another property:

$szLayers .= "map.addLayer(new _layer( { ".
"name:'".$groupName."',".
"visible:".$status.",".
"opacity:".$opacity.",".
"imageformat:'".$imageformat."',".
"queryable:".$szQueryable.",".
"download:".$download.",".
"tileSource:'".$tileSource."',".
"redrawInterval:".$redrawInterval.",".
"refreshInterval:".$refreshInterval.",".
"scales: new Array('".implode("','",$groupScaleVis)."')}));";

The line in bold was added to the properties of the layer

Labels: , ,

New MAP metadata

I hace decided to use the same strategy of "is the layer queryable" but this time to the WCS so that users can download the layers, by simplely clicking in a small icon

The first thing is that information concerning the layer is has to be indicated in the MAP file as metadata and then retrived by kamap

Now the MAP file to have a WCS layer downloaded by the Kamap needs the following metadata

METADATA
"download" "true"
END

Labels: , , , ,

Sunday, April 08, 2007

segmentation fault in WCS

I was going thru the WCS and started to have segmentation faults and everything was crashing,
finally I discovered the problem

The RESX and RESY are postive numbers, despite sometimes RESY being given as a negative value.

The funny thing was the PID was crashing and the sript was sending a ows.php reply, even more funny is that wcs_resolution is given with Y as negative value, at least in all the examples that I saw

Also I read the documentation and it says that BBOX is required, well actually not !!! without the BBOX it will reply with all the layer.

Labels: , ,

Saturday, April 07, 2007

WCS headache

Well Today I had a huge headache


The big problem started when I was doing a DescribeCoverage request and was getting nothing, as if there was no WCS layers (I had all the WCS metadata inside the map file), the result was only this

<CoverageDescription version="1.0.0" updateSequence="0" xsi:schemaLocation="http://www.opengis.net/wcs http://schemas.opengis.net/wcs/1.0.0/describeCoverage.xsd">
</CoverageDescription>

So no error, no major problems and of course nothing on the net!!!

I tryed to make a getCoverage and got an error message concerning projection,

Since my server is jailed there was no epsg file for the mapserver to read, I never had a problem with projections because I never had the need for epsg, since my projection was like this:

PROJECTION
"proj=latlong"
"ellps=WGS84"
"datum=WGS84"
END

(no: "init=epsg:4326")

So copying the epsg file to the chroot and adding the location of it to the map file solved the problem (CONFIG "PROJ_LIB" "/usr/local/share/proj")

Then I got a nice reply fron the DescribeCoverage, still I got some problems with the GetCoverage because instead of epsg I had epgs (....I hate this type of mistakes)

It took me several hours to discover all the problems....I wish that a better error log system would be in place for WxS

Labels: , , ,

HTTP Header

This makes the HTTPS for a tiff file with name srtm-10x:

header('Content-type: image/tif');
header('Content-Disposition: attachment; filename="srtm-10x.tiff"');

Labels: , ,

Friday, April 06, 2007

WEP Cracking

I can't belive that a WEP key can be cracked in 60 seconds

http://blogs.zdnet.com/hardware/?p=347

It took me 3 weeks to crack my neighboors WEP using Kismet!!!! To discover that he had a stupid password.

Maybe I should use WAP instead.

Labels: , ,

Thursday, April 05, 2007

WCS wrapper for Mapserver

WMS,WFS and WCS is how it is possible to connected to a webGIS server and to download data:
WMS == Raster as an image
WFS == Vectorial information
WCS == Raster as a layer (original raster with values)

The request of WxF is normally done by a GET to the Mapserv program (is like a normal CGI-BIN for program execution), well I don't want Apache to run any program, so the solution is a wrapper PHP script, where the script catches the requests and uses them for a valid WCS reply.

The wrapper is very simple and there is a basic example on the mapserver home page, This is a wrapper with small modifications to work with WCS:

<?php
/*ows.php?service=WCS&version=1.0.0&Request=GetCapabilities*/
$request = ms_newowsrequestobj();

//$request->loadparams();

foreach ($_GET as $k=>$v) {
$request->setParameter($k, $v);
}



// forcing to version 1.0.0
$request->setParameter("VeRsIoN","1.0.0");

ms_ioinstallstdouttobuffer();

$oMap = ms_newMapobj("/usr/local/apache2/htdocs/secure/ms/data/calter.map");
$oMap->owsdispatch($request);
$contenttype = ms_iostripstdoutbuffercontenttype();
$buffer = ms_iogetstdoutbufferstring();

header('Content-type: application/xml');
echo $buffer;

ms_ioresethandlers();

?>

For start Mapserver only suports WCS version 1.0.0 so any request for higher versions has to be redirect:
$request->setParameter("VeRsIoN","1.0.0");

There seems to be a bug with $request->loadparams(); this produces an empy file reply from the server with no errors, so the solution it to get the parameters directely from the GET
foreach ($_GET as $k=>$v) {
$request->setParameter($k, $v);
}

if replacing $_GET for $_POST is should be possible to use POST to request the WCS, mapserver only accepts GET.

Labels: , , , , ,

Email hidding

I did a small info page concerning the webGIS, it is a page with a semi-transparent background, like the KaExplorer example, but ported to KaAqua. Anyway I had to put some email and as usual I have hidden the email using a common javascript procedure, where the email is transformed in to an array of number and then the documment.write() reconverts back to letter.

http://www.dynamicdrive.com/emailriddler/

For my big surprise, when I make the page appear inside a div tag the documment.write() doesn't work , and there is no errors not in the javascript console or in the apache.

I have no idea why or even found the reason why, in the end I had to hide the email using simple echo() in PHP

Labels: , , , ,

Everything is now locked !!!!

Well the acesses to the mapserver is now locked !!!!!!!

For locking the system with a login I used the PHP classes called adminpro that I got from the site:

http://www.phpclasses.org/

The programming was done by Giorgios from Greece, and is the most straight forward login system based on MySQL, that I know, all programming is simple to follow and the configuration is very simple.

I had some problems making the socket connection to the MySQL, I don't understand why the socket wouldn't work, the file was inside chroot but I was having error messages saying no socket.

I couln't find much about the problem on the net, so instead of socket I used a direct connection: 127.0.0.1:3306

I don't know if this is secure but it worked !!!

<?php include("adminpro_class.php");
$prot=new protect();
if ($prot->showPage) {
?>

<!-- HTML/PHP GOES HERE --!>

<!-- end of php protection-->
<?php } ?>

Cool and simple !!!

Labels: , , , ,

Ka-maps instalation

The installation of ka-maps was simple and the only problems was the paths to the calter.map and the config.php paths, I had to change several javascripts files but in the end everything was working fine.

The KaAqua was my favourite and it looks cool with the transparent stuff, I also love the legend box and how you can close/open it

Labels: , , , ,

Why not Openlayers ?

Despite the look of Ka-maps, there is the problem of Ka-maps not having an API and at first the code looked a bit confusing.

So I have a look at Openlayers, they seem to be more organized than Ka-maps but I didnt liked that the server requests are based on WxS and there is no PHP as "back-office", never the less the options given like the connection to google and virtual earth extremely interresting.

So in the end I started to work with Ka-maps

Labels: , ,

Why not Ka-map

Since chameleon was a disaster I then decided to give a look at ka-maps

I found a nice tutorial on setting up ka-maps/AJAX

http://www.xml.com/pub/a/2005/08/10/ka-map.html

Also the page from ominiverdi is kick ass because it was a wiki and several examples

http://www.ominiverdi.org/

Why not Chameleon

I can't belive that I haven't posted anything for one month !!!!! Despite one week vacation things have progressed.

I did some research on chameleon and how the tools/widgets from chameleon could help me. Chameleon is done by DM solutions and basically you put tags on your HTML/PHP and it gets replaced by a widget, the concept is extremely cool and efficient, I think cold fusion works in the same way?

The problem is that I couldn't make it work I spent some days fighting it and there was always problems with paths and configuration files, even the tools that should help you work with chameleon were messy and the documentation was not very helpfull

The instalation of chameleon seems to be straight forward if you use a special installation pack called FGS is seems even better

Well my mapserver is chrooted and the apache is not compiled with Alias module (due to security concerns) so in the end it was extremely problematic trying to install chameleon in the server.

So I gave up

Labels: , , ,