source: trunk/mapbender/http/nav/alkisnav_adr.php @ 399

Revision 399, 15.1 KB checked in by frank.jaeger, 6 years ago (diff)

ALKIS-Navigation für Mapbender 2: Input Validation für alle Parameter. Kleine Korrekturen.

RevLine 
[66]1<?php
[399]2/*      Navigation mit ALKIS-Daten im Mapbender 2 - Teil Adressen-Suche
3        Datenbank-Struktur aus dem norGIS-ALKIS-Importer.
[376]4Version vom
5        2016-02-11 Version fÃŒr norGIS-ALKIS-Import aus Version Classic abgeleitet.
6        2016-03-02 $gemeinde auf feste LÀnge korrigieren
7        2016-11-28 Gemeinsam genutzte Datenbanken ermöglichen
[399]8        2018-02-15 Strikte Input-Validation der Parameter
9ToDo:
[306]10        -       Gruppierung (mit Zeile) der Straßenliste nach Gemeinde
[140]11        -       Eingabe aus "Balken" von Buchauskunft "Lage" zulassen: Numerisch: Gem-Str-Haus-lfd
[306]12                -- lfd (NebengebÀude) als Untergliederung der geklickten Haus-Nr anzeigen
[140]13                Analog zur Zerlegung des FS-Kennz in _fls
[197]14        -       Mouse-Over in Straßenliste soll Position zeigen.
15                Dazu in der DB eine Tabelle mit Koordinate zum StraßenschlÃŒssel aufbauen.
[85]16*/
[356]17
[399]18$cntget = extract($_GET);
[356]19
[399]20// Input-Validation
21// Parameter aus Konfiguration oder Links sollten keine "Eingabefehler" enthalten.
22// Entweder falsche Konfiguration oder Hack. Programm sofort abbrechen.
23if (!isset($gkz) or !preg_match('#^[0-9]{3}$#', $gkz)) {die("Eingabefehler gkz");} // Mandant, muss!
24
25if(isset($epsg)) { // SRS, kann. Wenn als Parameter ...
26        if (preg_match('#^EPSG:[0-9]{4,5}$#', $epsg)) { // Prefix aus MB-Mapframe
27                $epsg = str_replace("EPSG:", "" , $epsg);
28        } elseif (!preg_match('#^[0-9]{4,5}$#', $epsg)) { // nur die Nummer
29                die("Eingabefehler epsg");
30        }
31} else { // Nichts ÃŒbergeben
32        $epsg=$gui_epsg; // dann default aus Conf
33}
34
35// Filter-Parameter fÃŒr Gemeindenummer in Kreis-Datenbank aus der Mapbender GUI-Konfiguration
36if (isset($gemeinde) AND trim($gemeinde, '0') != "") {
37        if (!preg_match('#^[0-9]{1,3}$#', $gemeinde)) {die("Eingabefehler Gemeinde");}
38        $gemeinde=str_pad($gemeinde, 3, "0", STR_PAD_LEFT);
39        if(strpos($gemeinde, ",") === false) {
40                $gfilter = 1; // Einzelwert
41        } else {
42                $gfilter = 2; // Liste
43        }
44} else { // Kein Filter
45        $gemeinde = "";
46        $gfilter = 0;
47}
48// // http://skrzmaptest01.asp.krzwan.de/mapbender/nav/alkisnav_adr.php?gkz=210&gemeinde=004&epsg=25832&str_schl=0575800401798
49if (isset($str_schl) ) {
50        if (!preg_match('#^[0-9]{4,13}$#', $str_schl)) {die("Eingabefehler Stra&zlig;enschl&uuml;ssel");}
51} else {
52        $str_schl="";
53}
54
[187]55include("../../conf/alkisnav_conf.php");
[306]56include("alkisnav_fkt.php"); // Funktionen
[376]57$con = pg_connect ($dbconn) or die ("Fehler bei der Verbindung zur Datenbank ".$dbpre.$dbgkz);
[356]58
[278]59echo <<<END
[376]60<!doctype html>
61<html lang="de">
[187]62<head>
63        <meta http-equiv="cache-control" content="no-cache">
64        <meta http-equiv="pragma" content="no-cache">
65        <meta http-equiv="expires" content="0">
[376]66        <meta charset="utf-8">
[187]67        <title>ALKIS-Suche Adressen</title>
68        <link rel="stylesheet" type="text/css" href="alkisnav.css">
[278]69        <script type='text/javascript'>
70                function transtitle (trans) { // Titel der letzten Transaktion anzeigen
71                        document.getElementById('transaktiontitle').innerHTML = trans;
72                }
[306]73                function imFenster(dieURL) {
74                        var link = encodeURI(dieURL);
75                        window.open(link,'','left=10,top=10,width=620,height=800,resizable=yes,menubar=no,toolbar=no,location=no,status=no,scrollbars=yes');
76                }
[278]77        </script>
[187]78</head>
[66]79<body>
[280]80<a href='javascript:history.back()'>
[356]81        <img src="ico/zurueck.png" width="16" height="16" alt="&lt;&lt;" title="zur&uuml;ck">
82</a>&nbsp;
83<span title='zuletzt ausgef&uuml;hrte Aktion'>
84        <dfn class='title' id='transaktiontitle'></dfn>
85</span>
[66]86
[278]87END;
88
[376]89function suchStrName() {
90        // Strassen nach Name(-nsanfang)
[306]91        global $street, $scalestr, $str_schl, $gkz, $gemeinde, $epsg, $gfilter, $debug, $auskpath;
[376]92        //if ($debug > 1) {echo "<p class='dbg'>function suchStrName()<p>";} // Ablauf-Verfolgung
93
94        $linelimit=120;  // -> in Conf?
95        $str_schl=""; // Loeschen vorh. Ergebnis
96        preg_match("/^(\D+)(\d*)(\D*)/",$street,$matches); # 4 matches name/nr/zusatz
97        //echo "match: 1='".$matches[1]."', 2='".$matches[2]."', 3='".$matches[3]."'";
[187]98        $matches[1] = preg_replace("/strasse/i","str", $matches[1]);
[66]99        $matches[1] = preg_replace("/str\./i","str", $matches[1]);
[376]100
[187]101        if(preg_match("/\*/",$matches[1])){
102                $match=trim(preg_replace("/\*/i","%", strtoupper($matches[1])));
103        } else {
104                $match=trim($matches[1])."%";
[66]105        }
[376]106
[399]107        $sql ="SELECT g.gemeinde, g.bezeichnung AS gemname, k.gml_id, k.bezeichnung, k.schluesselgesamt, k.lage "
108        ."FROM ax_lagebezeichnungkatalogeintrag k "
109        ."JOIN ax_gemeinde g ON k.land=g.land AND k.regierungsbezirk=g.regierungsbezirk AND k.kreis=g.kreis AND k.gemeinde=g.gemeinde "
110        ."WHERE k.bezeichnung ILIKE $1 AND k.endet IS NULL AND g.endet IS NULL ";
[376]111
[85]112        switch ($gfilter) {
113                case 1: // Einzelwert
[330]114                        $sql.="AND k.gemeinde='".$gemeinde."' ";
[85]115                        break;
116                case 2: // Liste
[330]117                        $sql.="AND k.gemeinde in (".str_replace(",", "','", $gemeinde).") ";
[85]118                        break;
119                default: // kein Filter
120                        break;
[66]121        }
[306]122        $sql.="ORDER BY g.bezeichnung, k.bezeichnung, k.lage LIMIT $2 ;";
[68]123        $v=array($match,$linelimit);
124        $res=pg_prepare("", $sql);
125        $res=pg_execute("", $v);
[330]126
127        if (!$res) {
128                echo "\n<p class='err'>Fehler bei Name</p>";
129                if ($debug > 2) {echo "<p class='dbg'>SQL = '".$sql."'<p>";}
130                return;
131        }
132
[187]133        $cnt = 0;
[306]134        $gwgem="";
[66]135        while($row = pg_fetch_array($res)) {
[306]136                $gemname=$row["gemname"];
137                $gemnr=$row["gemeinde"] ;
138                if ($gwgem != $gemname) {
139                        if ($gfilter != 1) {
140                                zeile_gemeinde($gemnr, $gemname, false); // ToDo: aber ohne Link oder Link verarbeiten können
141                        }
142                        $gwgem=$gemname;
143                }
144                $gkey=$row["schluesselgesamt"]; // Land-RegBez-Kreis-Gem-Strasse - fÃŒr weitere Suche
145                $skey=$row["lage"]; // Nur Str.-schl. daraus
146                $kgml=$row["gml_id"]; // ID von Katalog
[376]147                $sname=htmlentities($row["bezeichnung"], ENT_QUOTES, "UTF-8");
148                zeile_strasse ($gkey, $skey, $sname, $kgml, $gemname);
[187]149                $cnt++;
150        }
[356]151
[66]152        if($cnt == 0) {
[376]153                echo "\n<p class='anz'>Keine Stra&szlig;e</p>";
154                //if ($debug > 2) {echo "<p class='err'>SQL = '".$sql."'<br>$1 = '".$match."'<p>";}
[66]155        } elseif($cnt == 1) { // Eindeutig
[68]156                $str_schl=$gkey; // dann gleich weiter
[66]157        } elseif($cnt >= $linelimit) {
[376]158                echo "\n<p class='anz'>".$cnt." Stra&szlig;en ... und weitere</p>";                     
[278]159        } elseif ($cnt > 1) {
160                echo "\n<p class='anz'>".$cnt." Stra&szlig;en</p>";     
161        }
[187]162        return;
163}
[66]164
[306]165function suchStrKey() { // Strassen nach num. Schluessel
166        global $street, $scalestr, $str_schl, $gkz, $gemeinde, $epsg, $gfilter, $debug, $auskpath;
[376]167        //if ($debug > 1) {echo "<p class='dbg'>function suchStrKey()<p>";} // Ablauf-Verfolgung
[306]168        $linelimit=60;
[187]169        if(preg_match("/\*/",$street)) {
[68]170                $match=trim(preg_replace("/\*/i","%",$street));
[306]171                // fuehrende Nullen eingeben oder fuehrende Wildcard
[187]172        } else {
173                $match=str_pad($street, 5, "0", STR_PAD_LEFT); // "Wie eine Zahl" verarbeiten
[68]174        }
[399]175        $sql ="SELECT g.bezeichnung AS gemname, k.gml_id, k.bezeichnung, k.schluesselgesamt, k.lage "
176        ."FROM ax_lagebezeichnungkatalogeintrag as k "
177        ."JOIN ax_gemeinde g ON k.land=g.land AND k.regierungsbezirk=g.regierungsbezirk AND k.kreis=g.kreis AND k.gemeinde=g.gemeinde "
178        ."WHERE k.lage LIKE $1 AND k.endet IS NULL AND g.endet IS NULL ";
[85]179        switch ($gfilter) {
180                case 1: // Einzelwert
[330]181                        $sql.="AND k.gemeinde='".$gemeinde."' ";
[85]182                        break;
183                case 2: // Liste
[330]184                        $sql.="AND k.gemeinde in ('".str_replace(",", "','", $gemeinde)."') ";
[85]185                        break;
[68]186        }
[187]187        $sql.="ORDER BY k.lage, k.bezeichnung LIMIT $2 ;";
[330]188
[68]189        $v=array($match,$linelimit);
190        $res=pg_prepare("", $sql);
191        $res=pg_execute("", $v);
[330]192        if (!$res) {
193                echo "\n<p class='err'>Fehler bei Schl&uuml;ssel</p>";
194                return;
195        }
[187]196        $cnt = 0;
[68]197        while($row = pg_fetch_array($res)) {
198                $sname=htmlentities($row["bezeichnung"], ENT_QUOTES, "UTF-8");         
199                $gkey=$row["schluesselgesamt"];
200                $gemname=htmlentities($row["gemname"], ENT_QUOTES, "UTF-8");
201                $skey=$row["lage"];
[306]202                $kgml=$row["gml_id"]; // ID von Katalog
[376]203                zeile_strasse ($gkey, $skey, $sname, $kgml, $gemname);
[187]204                $cnt++;
205        }
[68]206        if($cnt == 0) {
[278]207                echo "\n<p class='anz'>Keine Stra&szlig;e mit Schl&uuml;ssel ".$match."</p>";
[68]208        } elseif($cnt == 1) { // Eindeutig
209                $str_schl=$gkey; // dann gleich weiter
[278]210        } elseif ($cnt >= $linelimit) {
211                echo "\n<p>".$cnt." Stra&szlig;en ... und weitere</p>";                 
212        } elseif ($cnt > 1) {
213                echo "\n<p class='anz'>".$cnt." Stra&szlig;en</p>";     
[68]214        }       
[187]215        return;
[68]216}
217
[306]218function suchHausZurStr($showParent) { // Haeuser zu einer Strasse
[309]219        global $str_schl, $gkz, $scalestr, $scalehs, $epsg, $gemeinde, $epsg, $gfilter, $debug, $auskpath;
[376]220        //if ($debug > 1) {echo "<p class='dbg'>function suchHausZurStr()<p>";} // Ablauf-Verfolgung
[306]221
222        // Head
[66]223        // Strasse zum Strassenschluessel
[399]224        $sql ="SELECT g.bezeichnung AS gemname, k.gml_id AS kgml, k.bezeichnung, k.land, k.regierungsbezirk, k.kreis, k.gemeinde, k.lage "
225        ."FROM ax_lagebezeichnungkatalogeintrag as k "
226        ."JOIN ax_gemeinde g ON k.land=g.land AND k.regierungsbezirk=g.regierungsbezirk AND k.kreis=g.kreis AND k.gemeinde=g.gemeinde "
227        ."WHERE k.schluesselgesamt = $1 AND k.endet IS NULL AND g.endet IS NULL LIMIT 1";
[330]228
[306]229        $v=array($str_schl);    // Schluessel-Gesamt ..
[66]230        $res=pg_prepare("", $sql);
231        $res=pg_execute("", $v);
[330]232        if (!$res) {
233                echo "\n<p class='err'>Fehler bei Name zum Stra&szlig;enschl&uuml;ssel</p>";
234                if ($debug > 2) {echo "<p class='dbg'>SQL = '".$sql."'<p>";}
235                return;
236        }
237
[306]238        if($row = pg_fetch_array($res)) { // .. gefunden
[309]239                $kgml=$row["kgml"]; // ID aus Katalog
[66]240                $sname=$row["bezeichnung"];
[306]241                $land =$row["land"];    // Einzel-Felder fÃŒr JOIN _lagebezeichnung_
[66]242                $regb =$row["regierungsbezirk"];
243                $kreis=$row["kreis"];
244                $gemnd=$row["gemeinde"];
[306]245                $nr=$row["lage"];
[83]246                $gemname=htmlentities($row["gemname"], ENT_QUOTES, "UTF-8");
247                if ($showParent) {
[306]248                        // EINE Koordinate zur Strasse besorgen
[309]249                        // ax_Flurstueck >zeigtAuf> ax_LagebezeichnungOhneHausnummer
[197]250                        $sqlko ="SELECT ";
[86]251                        if($epsg == "25832") { // Transform nicht notwendig
[399]252                                $sqlko.="st_x(st_Centroid(f.wkb_geometry)) AS x, st_y(st_Centroid(f.wkb_geometry)) AS y ";
[197]253                        } else {
[399]254                                $sqlko.="st_x(st_transform(st_Centroid(f.wkb_geometry), ".$epsg.")) AS x, "
255                                ."st_y(st_transform(st_Centroid(f.wkb_geometry), ".$epsg.")) AS y ";
[86]256                        }
[399]257                        $sqlko.="FROM ax_lagebezeichnungohnehausnummer o JOIN ax_flurstueck f ON o.gml_id=ANY(f.zeigtauf) "
258                        ."WHERE o.land= $1 AND o.regierungsbezirk= $2 AND o.kreis= $3 AND o.gemeinde= $4 AND o.lage= $5 LIMIT 1;"; // die erstbeste Koordinate
[376]259
[83]260                        $v=array($land,$regb,$kreis,$gemnd,$nr);
261                        $resko=pg_prepare("", $sqlko);
262                        $resko=pg_execute("", $v);
263                        if ($resko) {
264                                $rowko=pg_fetch_array($resko);
265                                $x=$rowko["x"];
266                                $y=$rowko["y"];
267                        } else {               
268                                echo "\n<p class='err'>Fehler bei Koordinate zur Stra&szlig;e</p>";
269                        }
[309]270
[376]271                        // "function zeile_strasse()" hier nicht verwendbar. ZusÀtzlicher Map-Link mit Koordinate
[309]272                        // Icon -> Buchnachweis
[356]273                        echo "\n\t<br><a href='javascript:imFenster(\"".$auskpath."alkisstrasse.php?gkz=".$gkz."&amp;gmlid=".$kgml."\")'>";
274                                echo "\n\t\t<img class='nwlink' src='ico/Lage_mit_Haus.png' width='16' height='16' alt='STR' title='Buchauskunft zur Stra&szlig;e'>";
[309]275                        echo "\n\t</a>";
276
[83]277                        if ($x > 0) { // Koord. bekommen?
[399]278                                echo "\n\t<a title='Positionieren 1:".$scalestr."' href='javascript:" // mit Link
279                                                ."transtitle(\"auf Stra&szlig;e positioniert\"); "
280                                                ."parent.parent.parent.mb_repaintScale(\"mapframe1\",".$x.",".$y.",".$scalestr."); "
281                                                ."parent.parent.showHighlight(".$x.",".$y."); "
282                                                ."' " // end href
283                                        ."\n\t\tonmouseover='parent.parent.showHighlight(" .$x. "," .$y. ")' "
284                                        ."\n\t\tonmouseout='parent.parent.hideHighlight()'"
285                                .">\n\t\t".$sname." (".$nr.")\n\t</a>";
[197]286                        } else { // keine Koord. gefunden
[83]287                                echo $sname." (".$nr.")"; // nur Anzeige, ohne Link
288                        }
[85]289                        switch ($gfilter) {
290                                case 0: // Kein Filter
291                                        echo " in ".$gemname;
292                                        break;
293                                case 2: // Liste
294                                        echo " in ".$gemname;
295                                        break;
296                        }                       
[66]297                }
[83]298                echo "\n<hr>";
[306]299
300                // Body
[66]301                // Haeuser zum Strassenschluessel
[306]302                $sql="SELECT min(replace(h.hausnummer,' ','')) AS hsnr, ";
[86]303                if($epsg == "25832") { // Transform nicht notwendig
[399]304                        $sql.="avg (st_x(p.wkb_geometry)) AS x, avg (st_y(p.wkb_geometry)) AS y ";             
[197]305                } else { 
[399]306                        $sql.="avg (st_x(st_transform(p.wkb_geometry,".$epsg."))) AS x, "
307                        ."avg (st_y(st_transform(p.wkb_geometry,".$epsg."))) AS y ";           
[86]308                }
[399]309                $sql.="FROM ap_pto p JOIN ax_lagebezeichnungmithausnummer h ON h.gml_id=ANY(p.dientzurdarstellungvon) "
310                ."WHERE p.art='HNR' AND h.land= $1 AND h.regierungsbezirk= $2 AND h.kreis= $3 AND h.gemeinde= $4 AND h.lage= $5 "
311                ."AND p.endet IS NULL AND h.endet IS NULL "
312                ."GROUP BY lpad(split_part(hausnummer,' ',1), 4, '0'), split_part(hausnummer,' ',2) "
313                ."ORDER BY lpad(split_part(hausnummer,' ',1), 4, '0'), split_part(hausnummer,' ',2);";
[356]314                // Problem: In der Datenbank gibt es mehrere hausnummern-Koordinaten fÃŒr verschiedene
315                // MaßstÀbe der Kartendarstellung
316                // Diese sollten nicht mehrfach gelistet werden. FÃŒr die Positionierung "irgendeine" nehmen.
[306]317                // Lösung: ÃŒber GROUP BY in SQL. Alternative Lösungen wÀren:
318                //  1. Gruppenwechsel bei Abarbeitung des Result
319                //  2. Subquery mit LIMIT 1 statt JOIN
[356]320                //  3. Koordinate aus dem Mittelpunkt der GebÀude-Geometrie verwenden statt aus dem PrÀsentationsobjekt der Hausnummer
[197]321
[83]322                $v=array($land,$regb,$kreis,$gemnd,$nr);
[68]323                $resh=pg_prepare("", $sql);
324                $resh=pg_execute("", $v);
[330]325                if (!$resh) {
326                        echo "\n<p class='err'>Fehler bei H&auml;user zum Stra&szlig;enschl&uuml;ssel</p>";
327                        if ($debug > 2) {echo "<p class='dbg'>SQL='".$sql."'<br>Array=".$v."</p>";}
328                        return;
329                }
[306]330
[187]331                $cnt=0;
332                $count=0;
333                echo "\n<table>";
[197]334                while($rowh = pg_fetch_array($resh)) { // mehrere HsNr je Zeile
[356]335                        if($count == 0) {echo "\n<tr>";}       
[197]336                        $hsnr=$rowh["hsnr"];
[187]337                        $x=$rowh["x"];
338                        $y=$rowh["y"];
[399]339                        echo "\n\t<td class='hsnr'>"
340                                ."<a href='javascript:transtitle(\"auf Haus ".$hsnr." positioniert\"); "
341                                        ."parent.parent.parent.mb_repaintScale(\"mapframe1\",".$x.",".$y.",".$scalehs."); "
342                                        ."parent.parent.showHighlight(".$x.",".$y.");' "
343                                        ."onmouseover='parent.parent.showHighlight(".$x.",".$y.")' "
344                                        ."onmouseout='parent.parent.hideHighlight()"
345                                ."'>".$hsnr."</a>"
346                        ."</td>";
[187]347                        $cnt++;
348                        $count++;
[356]349                        if($count == 7) { // Max. Hausnummern je Zeile (Test: 3stellige HsNr mit Zusatz)
[66]350                                echo "\n</tr>";
351                                $count = 0;
[187]352                        }
353                }
[66]354                if($count > 0) {echo "\n</tr>";}
355                echo "\n</table>";
[306]356                if ($cnt > 1) {
357                        echo "\n<p class='anz'>".$cnt." Hausnummern</p>";
358                }
[66]359        } else {
[278]360                echo "\n<p class='anz'>Keine Stra&szlig;e</p>";
[187]361        }
362        return;
363}
[66]364// ===========
365// Start hier!
366// ===========
[376]367
[399]368// Validation: Eingabefeld aus Formular.
369// Suchbegriff (Straßenname) oder StraßenschlÃŒssel.
370// Hier formatierte Meldung und html-Foot.
371if (isset($street) and $street != "" ) {
372        if (!preg_match('#^[0-9a-zA-ZÀöÌÄÖÜß* -.]{1,25}$#', $street)) {
373                echo "<p class='err'>Eingabe unzul&auml;ssig!</p>";
374                $street="";
375        }
[85]376} else {
[399]377        $street="";
[85]378}
[306]379
[399]380if ($str_schl != "") { // aus Link
[278]381        $trans="Hausnummern zur Stra&szlig;e";
[83]382        suchHausZurStr(true);
[399]383} elseif($street != "") { // Eingabe in Formular
[376]384        if (trim($street, "*,0..9, ") == "") { // Zahl, ggf. mit Wildcard
[278]385                $trans="Suche Stra&szlig;enschl&uuml;ssel \"".$street."\"";
386                suchStrKey();
[376]387        } else { // Name suchen
[356]388                $trans="Suche Stra&szlig;enname \"".$street."*\"";
[278]389                suchStrName();
[187]390        }
[356]391        if($str_schl != "") { // EINdeutiges Ergebnis
[278]392                $trans="1 Stra&szlig;e gefunden, Hausnummern";
[187]393                suchHausZurStr(false);
[83]394        }
[356]395} else {
396        $trans="keine Eingabe";
[68]397}
[356]398
399// Nach Durchlaufen des PHP-Scriptes die zuletzt ausgefÃŒhrte Transaktion
[376]400//  im Kopf des Ergebnisrahmens anzeigen.
[356]401// Dazu die im HTML-Header definierte Javascript-Function benutzen.
402// Alternativ wird auch aus dem Javascript "positionieren Karte" dieser Titel gesetzt.
[283]403echo "
404<script type='text/javascript'>
405        transtitle ('".$trans."') ;
406</script>";
[278]407
[66]408?>
[68]409
[187]410</body>
411</html>
Note: See TracBrowser for help on using the repository browser.