Преглед на файлове

Merge branch 'master' of biuro.biall-net.pl:plabudda/se

# By Piotr Labudda
# Via Piotr Labudda
* 'master' of biuro.biall-net.pl:plabudda/se:
  add Request to fix $_SERVER usage after apache upgrade (Server.app 5)
  fix wfs server: add data and qgis version, rm old wfs
  Fix Typepecial for zasob - split query to words
a.binder преди 10 години
родител
ревизия
dc11639588

+ 4 - 6
SE/api.php

@@ -1,12 +1,12 @@
 <?php
 
-if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on') {
+require_once dirname(__FILE__) . '/se-lib/bootstrap.php';
+
+if (!Request::isHttps()) {
 	header("Location: https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
 	exit();
 }
 
-require_once dirname(__FILE__) . '/se-lib/bootstrap.php';
-
 date_default_timezone_set('Europe/Warsaw');// PHP 5 >= 5.1.0 required by date functions
 
 $errorReportingLevel = E_ALL & ~E_NOTICE;
@@ -35,9 +35,7 @@ if ('LOGOUT' == V::get('LOGIN', '', $_GET)) {
 	$apiUser->auth();
 }
 
-$reqUri = V::get('REQUEST_URI', '', $_SERVER);
-$reqScript = V::get('SCRIPT_NAME', '', $_SERVER);
-$taskPath = str_replace($reqScript, '', $reqUri);
+$taskPath = Request::getRewriteTaskPath();
 IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">taskPath (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($taskPath);echo'</pre>';}
 
 $api = new Api();

+ 0 - 715
SE/caldav-client.php

@@ -1,715 +0,0 @@
-<?php
-
-/**
-* A Class for connecting to a caldav server
-*
-* @package   awl
-* removed curl - now using fsockopen
-* changed 2009 by Andres Obrero - Switzerland andres@obrero.ch
-*
-* @subpackage   caldav
-* @author Andrew McMillan <debian@mcmillan.net.nz>
-* @author Roland 'roslai' Liebl <myroundcube@mail4us.net>
-* @copyright Andrew McMillan
-* @license   http://gnu.org/copyleft/gpl.html GNU GPL v2
-*/
-
-/**
-* Mods: Added support for DIGEST authentication
-*/
-
-
-/**
-* A class for accessing DAViCal via CalDAV, as a client
-*
-* @package   awl
-*/
-class CalDAVClient {
-  /**
-  * Server, username, password, calendar
-  *
-  * @var string
-  */
-  var $base_url, $user, $pass, $auth, $entry, $protocol, $server, $port;
-
-  /**
-  * The useragent which is send to the caldav server
-  *
-  * @var string
-  */
-  var $user_agent = 'DAViCalClient';
-
-  var $headers = array();
-  var $body = "";
-  var $requestMethod = "GET";
-  var $httpRequest = ""; // for debugging http headers sent
-  var $xmlRequest = ""; // for debugging xml sent
-  var $httpResponse = ""; // for debugging http headers received
-  var $xmlResponse = ""; // for debugging xml received
-
-  /**
-  * Constructor, initialises the class
-  *
-  * @param string $base_url  The URL for the calendar server
-  * @param string $user      The name of the user logging in
-  * @param string $pass      The password for that user
-  * @param string $auth      The authentication method
-  *                          basic | detect
-  */
-  function CalDAVClient( $base_url, $user, $pass, $auth = 'basic' ) {
-    $this->user = $user;
-    $this->pass = $pass;
-    $this->auth = $auth;
-    $this->headers = array();
-    
-    if ( preg_match( '#^(https?)://([a-z0-9.-]+)(:([0-9]+))?(/.*)$#', $base_url, $matches ) ) {
-      $this->server = $matches[2];
-      $this->base_url = $matches[5];
-      if ( $matches[1] == 'https' ) {
-        $this->protocol = 'ssl';
-        $this->port = 443;
-      }
-      else {
-        $this->protocol = 'tcp';
-        $this->port = 80;
-      }
-      if ( $matches[4] != '' ) {
-        $this->port = intval($matches[4]);
-      }
-      return true;
-    }
-    else {
-      //trigger_error("Invalid URL: '".$base_url."'", E_USER_ERROR);
-      return false;
-    }
-  }
-
-  /**
-  * Adds an If-Match or If-None-Match header
-  *
-  * @param bool $match to Match or Not to Match, that is the question!
-  * @param string $etag The etag to match / not match against.
-  */
-  function SetMatch( $match, $etag = '*' ) {
-    $this->headers[] = sprintf( "%s-Match: \"%s\"", ($match ? "If" : "If-None"), $etag);
-  }
-
-/**
-  * Add a Depth: header.  Valid values are 0, 1 or infinity
-  *
-  * @param int $depth  The depth, default to infinity
-  */
-  function SetDepth( $depth = '0' ) {
-    $this->headers[] = 'Depth: '. ($depth == '1' ? "1" : ($depth == 'infinity' ? $depth : "0") );
-  }
-
-  /**
-  * Add a Depth: header.  Valid values are 1 or infinity
-  *
-  * @param int $depth  The depth, default to infinity
-  */
-  function SetUserAgent( $user_agent = null ) {
-    if ( !isset($user_agent) ) $user_agent = $this->user_agent;
-    $this->user_agent = $user_agent;
-  }
-
-  /**
-  * Add a Content-type: header.
-  *
-  * @param int $type  The content type
-  */
-  function SetContentType( $type ) {
-    $this->headers[] = "Content-type: $type";
-  }
-
-  /**
-  * Split response into httpResponse and xmlResponse
-  *
-  * @param string Response from server
-   */
-  function ParseResponse( $response ) {
-      $pos = strpos($response, '<?xml');
-      if ($pos === false) {
-        $this->httpResponse = trim($response);
-      }
-      else {
-        $this->httpResponse = trim(substr($response, 0, $pos));
-        $this->xmlResponse = trim(substr($response, $pos));
-      }
-  }
-
-  /**
-   * Output http request headers
-   *
-   * @return HTTP headers
-   */
-  function GetHttpRequest() {
-      return $this->httpRequest;
-  }
-  /**
-   * Output http response headers
-   *
-   * @return HTTP headers
-   */
-  function GetHttpResponse() {
-      return $this->httpResponse;
-  }
-  /**
-   * Output xml request
-   *
-   * @return raw xml
-   */
-  function GetXmlRequest() {
-      return $this->xmlRequest;
-  }
-  /**
-   * Output xml response
-   *
-   * @return raw xml
-   */
-  function GetXmlResponse() {
-      return $this->xmlResponse;
-  }
-
-  /**
-  * Send a request to the server
-  *
-  * @param string $relative_url The URL to make the request to, relative to $base_url
-  *
-  * @return string The content of the response from the server
-  */
-  function DoRequest( $relative_url = "" ) {
-
-    if(!defined("_FSOCK_TIMEOUT")){ define("_FSOCK_TIMEOUT", 10); }
-    if(!function_exists('curl_init')){
-      $headers = array();
-      $headers[] = $this->requestMethod." ". $this->base_url . $relative_url . " HTTP/1.1";
-      if($this->auth == 'detect'){
-        if($auth = $this->GetAuthHeader())
-          $headers[] = $auth;
-      }
-      else if($this->auth == 'basic')
-        $headers[] = "Authorization: Basic ".base64_encode($this->user .":". $this->pass );
-      $headers[] = "Host: ".$this->server .":".$this->port;
-
-      foreach( $this->headers as $ii => $head ) {
-        $headers[] = $head;
-      }
-      $headers[] = "Content-Length: " . strlen($this->body);
-      $headers[] = "User-Agent: " . $this->user_agent;
-      $headers[] = 'Connection: close';
-      $this->httpRequest = join("\r\n",$headers);
-    
-      $this->xmlRequest = $this->body;
-
-      //write_log('request', "\r\nRequest:\r\n__________\r\n" . $this->httpRequest."\r\n\r\n".$this->body);
-      $fip = @fsockopen( $this->protocol . '://' . $this->server, $this->port, $errno, $errstr, _FSOCK_TIMEOUT); //error handling?
-      if ( !(@get_resource_type($fip) == 'stream') ) return false;
-      if ( !fwrite($fip, $this->httpRequest."\r\n\r\n".$this->body) ) { fclose($fip); return false; }
-      $rsp = "";
-      while( !feof($fip) ) { $rsp .= fgets($fip,8192);}
-      fclose($fip);
-      $this->headers = array();
-      $this->ParseResponse($rsp);
-      //write_log('request',"\r\n__________\r\nResponse:\r\n__________\r\n$rsp");
-      return $rsp;
-    }
-    else{
-      $s = '';
-      if($this->protocol == ssl)
-        $s = 's';
-	$headers[] = $this->requestMethod." ". $this->base_url . $relative_url . " HTTP/1.1";
-	$headers[] = "Host: ".$this->server .":".$this->port;
-	foreach( $this->headers as $ii => $head ) {
-		$headers[] = $head;
-	}
-	$headers[] = "Content-Length: " . strlen($this->body);
-	$headers[] = "User-Agent: " . $this->user_agent;
-	$headers[] = 'Connection: close';
-      $ch = curl_init();
-      curl_setopt($ch, CURLOPT_URL, 'http'.$s.'://'.$this->server.':'.$this->port.$this->base_url.$relative_url);
-      //write_log('request', "\r\nRequest:\r\n__________\r\n" . 'http'.$s.'://'.$this->server.':'.$this->port.$this->base_url.$relative_url . "\r\n\r\n" . $this->body);
-      curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
-      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
-      curl_setopt($ch, CURLOPT_HEADER, TRUE);
-      curl_setopt($ch, CURLOPT_TIMEOUT, _FSOCK_TIMEOUT);
-      if($this->auth == 'basic')
-        $auth = CURLAUTH_BASIC;
-      else
-        $auth = CURLAUTH_DIGEST;
-      curl_setopt($ch, CURLOPT_HTTPAUTH, $auth);
-      curl_setopt($ch, CURLOPT_USERPWD, $this->user.':'.$this->pass);
-      curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->requestMethod);
-      curl_setopt($ch, CURLOPT_POSTFIELDS, $this->body);
-      foreach($this->headers as $header) {
-        if(stripos($header, 'Content-type:') !== false) {
-          curl_setopt($ch, CURLOPT_HTTPHEADER, array($header));
-          break;
-        }
-      }
-      $rsp = curl_exec($ch);
-      if(curl_errno($ch)){
-        curl_close($ch);
-        $this->headers = array();
-        return false;
-      }
-      else {
-        curl_close($ch);
-        $this->headers = array();  // reset the headers array for our next request
-        $this->ParseResponse($rsp);
-        //write_log('request',"\r\n__________\r\nResponse:\r\n__________\r\n$rsp");
-        return $rsp;
-      }
-    }
-  }
-
-  /**
-  * Send an OPTIONS request to the server
-  *
-  * @param string $relative_url The URL to make the request to, relative to $base_url
-  *
-  * @return array The allowed options
-  */
-  function DoOptionsRequest( $relative_url = "" ) {
-    $this->requestMethod = "OPTIONS";
-    $this->body = "";
-    $headers = $this->DoRequest($relative_url);
-    $options_header = preg_replace( '/^.*Allow: ([a-z, ]+)\r?\n.*/is', '$1', $headers );
-    $options = array_flip( preg_split( '/[, ]+/', $options_header ));
-    return $options;
-  }
-
-
-
-  /**
-  * Send an XML request to the server (e.g. PROPFIND, REPORT, MKCALENDAR)
-  *
-  * @param string $method The method (PROPFIND, REPORT, etc) to use with the request
-  * @param string $xml The XML to send along with the request
-  * @param string $relative_url The URL to make the request to, relative to $base_url
-  *
-  * @return array An array of the allowed methods
-  */
-  function DoXMLRequest( $request_method, $xml, $relative_url = '' ) {
-    $this->body = $xml;
-    $this->requestMethod = $request_method;
-    $this->SetContentType("text/xml");
-    return $this->DoRequest($relative_url);
-  }
-
-
-
-  /**
-  * Get a single item from the server.
-  *
-  * @param string $relative_url The part of the URL after the calendar
-  */
-  function DoGETRequest( $relative_url ) {
-    $this->body = "";
-    $this->requestMethod = "GET";
-    return $this->DoRequest( $relative_url );
-  }
-
-
-  /**
-  * PUT a text/icalendar resource, returning the etag
-  *
-  * @param string $relative_url The URL to make the request to, relative to $base_url
-  * @param string $icalendar The iCalendar resource to send to the server
-  * @param string $etag The etag of an existing resource to be overwritten, or '*' for a new resource.
-  *
-  * @return string The content of the response from the server
-  */
-  function DoPUTRequest( $relative_url, $icalendar, $etag = null ) {
-    $this->body = $icalendar;
-    $this->requestMethod = "PUT";
-    if ( $etag != null ) {
-      $this->SetMatch( ($etag != '*'), $etag );
-    }
-    $this->SetContentType("text/calendar");
-    $headers = $this->DoRequest($relative_url);
-
-    /**
-    * RSCDS will always return the real etag on PUT.  Other CalDAV servers may need
-    * more work, but we are assuming we are running against RSCDS in this case.
-    */
-    $etag = preg_replace( '/^.*Etag: "?([^"\r\n]+)"?\r?\n.*/is', '$1', $headers );
-    return $etag;
-  }
-
-
-  /**
-  * DELETE a text/icalendar resource
-  *
-  * @param string $relative_url The URL to make the request to, relative to $base_url
-  * @param string $etag The etag of an existing resource to be deleted, or '*' for any resource at that URL.
-  *
-  * @return int The HTTP Result Code for the DELETE
-  */
-  function DoDELETERequest( $relative_url, $etag = null ) {
-    $this->body = "";
-
-    $this->requestMethod = "DELETE";
-    if ( $etag != null ) {
-      $this->SetMatch( true, $etag );
-    }
-    $this->DoRequest($relative_url);
-    return $this->resultcode;
-  }
-
-
-  /**
-  * Given XML for a calendar query, return an array of the events (/todos) in the
-  * response.  Each event in the array will have a 'href', 'etag' and '$response_type'
-  * part, where the 'href' is relative to the calendar and the '$response_type' contains the
-  * definition of the calendar data in iCalendar format.
-  *
-  * @param string $filter XML fragment which is the <filter> element of a calendar-query
-  * @param string $relative_url The URL relative to the base_url specified when the calendar was opened.  Default ''.
-  * @param string $report_type Used as a name for the array element containing the calendar data. @deprecated
-  *
-  * @return array An array of the relative URLs, etags, and events from the server.  Each element of the array will
-  *               be an array with 'href', 'etag' and 'data' elements, corresponding to the URL, the server-supplied
-  *               etag (which only varies when the data changes) and the calendar data in iCalendar format.
-  */
-  function DoCalendarQuery( $filter, $relative_url = '' ) {
-    $xml = <<<EOXML
-<?xml version="1.0" encoding="utf-8" ?>
-<C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
-  <D:prop>
-    <C:calendar-data/>
-    <D:getetag/>
-  </D:prop>
-$filter
-</C:calendar-query>
-EOXML;
-    $this->DoXMLRequest( 'REPORT', $xml, $relative_url );
-    $xml_parser = xml_parser_create_ns('UTF-8');
-    $this->xml_tags = array();
-    xml_parser_set_option ( $xml_parser, XML_OPTION_SKIP_WHITE, 0 );
-    xml_parse_into_struct( $xml_parser, $this->xmlResponse, $this->xml_tags );
-    xml_parser_free($xml_parser);
-
-    $report = array();
-    foreach( $this->xml_tags as $k => $v ) {
-      switch( $v['tag'] ) {
-        case 'DAV::RESPONSE':
-          if ( $v['type'] == 'open' ) {
-            $response = array();
-          }
-          elseif ( $v['type'] == 'close' ) {
-            $report[] = $response;
-          }
-          break;
-        case 'DAV::HREF':
-          $response['href'] = basename( $v['value'] );
-          break;
-        case 'DAV::GETETAG':
-          $response['etag'] = preg_replace('/^"?([^"]+)"?/', '$1', $v['value']);
-          break;
-        case 'URN:IETF:PARAMS:XML:NS:CALDAV:CALENDAR-DATA':
-          $response['data'] = $v['value'];
-          break;
-      }
-    }
-    return $report;
-  }
-
-
-  /**
-  * Get the events in a range from $start to $finish.  The dates should be in the
-  * format yyyymmddThhmmssZ and should be in GMT.  The events are returned as an
-  * array of event arrays.  Each event array will have a 'href', 'etag' and 'event'
-  * part, where the 'href' is relative to the calendar and the event contains the
-  * definition of the event in iCalendar format.
-  *
-  * @param timestamp $start The start time for the period
-  * @param timestamp $finish The finish time for the period
-  * @param string    $relative_url The URL relative to the base_url specified when the calendar was opened.  Default ''.
-  *
-  * @return array An array of the relative URLs, etags, and events, returned from DoCalendarQuery() @see DoCalendarQuery()
-  */
-  function GetEvents( $start = null, $finish = null, $relative_url = '' ) {
-    $filter = "";
-    if ( isset($start) && isset($finish) )
-        $range = "<C:time-range start=\"$start\" end=\"$finish\"/>";
-    else
-        $range = '';
-    $filter = <<<EOFILTER
-  <C:filter>
-    <C:comp-filter name="VCALENDAR">
-      <C:comp-filter name="VEVENT">
-        $range
-      </C:comp-filter>
-    </C:comp-filter>
-  </C:filter>
-EOFILTER;
-
-    return $this->DoCalendarQuery($filter, $relative_url);
-  }
-  
-  /**
-  * Get the event alarms in a range from $start to $finish.  The dates should be in the
-  * format yyyymmddThhmmssZ and should be in GMT.  The event alarms are returned as an
-  * array of event arrays.  Each event array will have a 'href', 'etag' and 'event'
-  * part, where the 'href' is relative to the calendar and the event contains the
-  * definition of the event in iCalendar format.
-  *
-  * @param timestamp $start The start time for the period
-  * @param timestamp $finish The finish time for the period
-  * @param string    $relative_url The URL relative to the base_url specified when the calendar was opened.  Default ''.
-  *
-  * @return array An array of the relative URLs, etags, and events, returned from DoCalendarQuery() @see DoCalendarQuery()
-  */
-  function GetEventAlarms( $start = null, $finish = null, $relative_url = '' ) {
-    $filter = "";
-    if ( isset($start) && isset($finish) )
-        $range = "<C:time-range start=\"$start\" end=\"$finish\"/>";
-    else
-        $range = '';
-    $filter = <<<EOFILTER
-  <C:filter>
-    <C:comp-filter name="VCALENDAR">
-      <C:comp-filter name="VEVENT">
-        <C:comp-filter name="VALARM">
-          $range
-        </C:comp-filter>
-      </C:comp-filter>
-    </C:comp-filter>
-  </C:filter>
-EOFILTER;
-
-    return $this->DoCalendarQuery($filter, $relative_url);
-  }
-  
-
-
-  /**
-  * Get the todo's in a range from $start to $finish.  The dates should be in the
-  * format yyyymmddThhmmssZ and should be in GMT.  The events are returned as an
-  * array of event arrays.  Each event array will have a 'href', 'etag' and 'event'
-  * part, where the 'href' is relative to the calendar and the event contains the
-  * definition of the event in iCalendar format.
-  *
-  * @param timestamp $start The start time for the period
-  * @param timestamp $finish The finish time for the period
-  * @param boolean   $completed Whether to include completed tasks
-  * @param boolean   $cancelled Whether to include cancelled tasks
-  * @param string    $relative_url The URL relative to the base_url specified when the calendar was opened.  Default ''.
-  *
-  * @return array An array of the relative URLs, etags, and events, returned from DoCalendarQuery() @see DoCalendarQuery()
-  */
-  function GetTodos( $start, $finish, $completed = false, $cancelled = false, $relative_url = "" ) {
-
-    if ( $start && $finish ) {
-$time_range = <<<EOTIME
-                <C:time-range start="$start" end="$finish"/>
-EOTIME;
-    }
-
-    // Warning!  May contain traces of double negatives...
-    $neg_cancelled = ( $cancelled === true ? "no" : "yes" );
-    $neg_completed = ( $cancelled === true ? "no" : "yes" );
-
-    $filter = <<<EOFILTER
-  <C:filter>
-    <C:comp-filter name="VCALENDAR">
-          <C:comp-filter name="VTODO">
-                <C:prop-filter name="STATUS">
-                        <C:text-match negate-condition="$neg_completed">COMPLETED</C:text-match>
-                </C:prop-filter>
-                <C:prop-filter name="STATUS">
-                        <C:text-match negate-condition="$neg_cancelled">CANCELLED</C:text-match>
-                </C:prop-filter>$time_range
-          </C:comp-filter>
-    </C:comp-filter>
-  </C:filter>
-EOFILTER;
-
-    return $this->DoCalendarQuery($filter, $relative_url);
-  }
-
-
-  /**
-  * Get the calendar entry by UID
-  *
-  * @param uid
-  * @param string    $relative_url The URL relative to the base_url specified when the calendar was opened.  Default ''.
-  *
-  * @return array An array of the relative URL, etag, and calendar data returned from DoCalendarQuery() @see DoCalendarQuery()
-  */
-  function GetEntryByUid( $uid, $relative_url = '' ) {
-    $filter = "";
-    if ( $uid ) {
-      $filter = <<<EOFILTER
-  <C:filter>
-    <C:comp-filter name="VCALENDAR">
-          <C:comp-filter name="VEVENT">
-                <C:prop-filter name="UID">
-                        <C:text-match icollation="i;octet">$uid</C:text-match>
-                </C:prop-filter>
-          </C:comp-filter>
-    </C:comp-filter>
-  </C:filter>
-EOFILTER;
-    }
-
-    return $this->DoCalendarQuery($filter, $relative_url);
-  }
-
-
-  /**
-  * Get the calendar entry by HREF
-  *
-  * @param string    $href         The href from a call to GetEvents or GetTodos etc.
-  * @param string    $relative_url The URL relative to the base_url specified when the calendar was opened.  Default ''.
-  *
-  * @return string The iCalendar of the calendar entry
-  */
-  function GetEntryByHref( $href, $relative_url = '' ) {
-    return $this->DoGETRequest( $relative_url . $href );
-  }
-  
-  /**
-  * Get the Authentication header (BASIC or DIGEST)
-  *
-  * @return string Authentication header
-  */
-
-  function GetAuthHeader() {
-    $file = substr($this->base_url . $relative_url, 1);
-    if (!$fp = fsockopen($this->protocol . '://' . $this->server, $this->port, $errno, $errstr, _FSOCK_TIMEOUT))
-      return false;
-       
-    //first do the non-authenticated header so that the server
-    //sends back a 401 error containing its nonce and opaque
-    $out = $this->requestMethod . " /$file HTTP/1.1\r\n";
-    $out .= "Host: " . $this->server . "\r\n";
-    $out .= "Connection: Close\r\n\r\n";
-
-    fwrite($fp, $out);
-
-    //read the reply and look for the WWW-Authenticate element
-    while (!feof($fp)) {
-      $line = fgets($fp, 512);
-      if (stripos($line,"WWW-Authenticate: BASIC") !== false){
-        fclose($fp);
-        return "Authorization: Basic ".base64_encode($this->user .":". $this->pass );
-      }
-      else if (stripos($line,"WWW-Authenticate: Digest") !== false){
-        $authline=trim(substr($line,18));
-      }
-    }
-    fclose($fp);
-    
-    if(!$authline)
-      return false;
-   
-    //split up the WWW-Authenticate string to find digest-realm,nonce and opaque values
-    //if qop value is presented as a comma-seperated list (e.g auth,auth-int) then it won't be retrieved correctly
-    //but that doesn't matter because going to use 'auth' anyway
-    $authlinearr=explode(",",$authline);
-    $autharr=array();
-   
-    foreach ($authlinearr as $el) {
-      $elarr=explode("=",$el);
-      //the substr here is used to remove the double quotes from the values
-      $autharr[trim($elarr[0])]=substr($elarr[1],1,strlen($elarr[1])-2);
-    }
-   
-    //these are all the vals required from the server
-    $nonce=$autharr['nonce'];
-    $opaque=$autharr['opaque'];
-    $drealm=$autharr['Digest realm'];
-   
-    //client nonce can be anything since this authentication session is not going to be persistent
-    //likewise for the cookie - just call it MyCookie
-    $cnonce="sausages";
-   
-    //calculate the hashes of A1 and A2 as described in RFC 2617
-    $a1=$this->user . ":$drealm:" . $this->pass ;$a2= $this->requestMethod . ":/$file";
-    $ha1=md5($a1);$ha2=md5($a2);
-   
-    //calculate the response hash as described in RFC 2617
-    $concat = $ha1.':'.$nonce.':00000001:'.$cnonce.':auth:'.$ha2;
-    $response=md5($concat);
-   
-    //put together the Authorization Request Header
-    $out = "Authorization: Digest username=\"" . $this->user . "\", realm=\"$drealm\", qop=\"auth\", algorithm=\"MD5\", uri=\"/$file\", nonce=\"$nonce\", nc=00000001, cnonce=\"$cnonce\", opaque=\"$opaque\", response=\"$response\"";
-    return $out;
-  }
-
-}
-
-/**
-* Usage example
-*
-* $cal = new CalDAVClient( "http://calendar.example.com/caldav.php/username/calendar/", "username", "password", "calendar" );
-* $options = $cal->DoOptionsRequest();
-* if ( isset($options["PROPFIND"]) ) {
-*   // Fetch some information about the events in that calendar
-*   $cal->SetDepth(1);
-*   $folder_xml = $cal->DoXMLRequest("PROPFIND", '<?xml version="1.0" encoding="utf-8" ?><propfind xmlns="DAV:"><prop><getcontentlength/><getcontenttype/><resourcetype/><getetag/></prop></propfind>' );
-* }
-* // Fetch all events for February
-* $events = $cal->GetEvents("20070101T000000Z","20070201T000000Z");
-* foreach ( $events AS $k => $event ) {
-*   do_something_with_event_data( $event['data'] );
-* }
-* $acc = array();
-* $acc["google"] = array(
-* "user"=>"kunsttherapie@gmail.com",
-* "pass"=>"xxxxx",
-* "server"=>"ssl://www.google.com",
-* "port"=>"443",
-* "uri"=>"https://www.google.com/calendar/dav/kunsttherapie@gmail.com/events/",
-* );
-*
-* $acc["davical"] = array(
-* "user"=>"some_user",
-* "pass"=>"big secret",
-* "server"=>"calendar.foo.bar",
-* "port"=>"80",
-* "uri"=>"http://calendar.foo.bar/caldav.php/some_user/home/",
-* );
-* //*******************************
-*
-* $account = $acc["davical"];
-*
-* //*******************************
-* $cal = new CalDAVClient( $account["uri"], $account["user"], $account["pass"], "", $account["server"], $account["port"] );
-* $options = $cal->DoOptionsRequest();
-* print_r($options);
-*
-* //*******************************
-* //*******************************
-*
-* $xmlC = <<<PROPP
-* <?xml version="1.0" encoding="utf-8" ?>
-* <D:propfind xmlns:D="DAV:" xmlns:C="http://calendarserver.org/ns/">
-*     <D:prop>
-*             <D:displayname />
-*             <C:getctag />
-*             <D:resourcetype />
-*
-*     </D:prop>
-* </D:propfind>
-* PROPP;
-* //if ( isset($options["PROPFIND"]) ) {
-*   // Fetch some information about the events in that calendar
-* //  $cal->SetDepth(1);
-* //  $folder_xml = $cal->DoXMLRequest("PROPFIND", $xmlC);
-* //  print_r( $folder_xml);
-* //}
-*
-* // Fetch all events for February
-* $events = $cal->GetEvents("20090201T000000Z","20090301T000000Z");
-* foreach ( $events as $k => $event ) {
-*     print_r($event['data']);
-*     print "\n---------------------------------------------\n";
-* }
-*
-* //*******************************
-* //*******************************
-*/
-?>

+ 0 - 1396
SE/caldav.php

@@ -1,1396 +0,0 @@
-<?php
-
-require_once(INSTALL_PATH . 'plugins/calendar/program/backend/backend.php');
-require_once(INSTALL_PATH . 'plugins/calendar/program/backend/caldav/caldav-client.php');
-
-final class calendar_caldav extends Backend 
-{
-  private $rcmail;
-  private $type;
-  public  $utils;
-  private $usertimezone;
-  private $username;
-  private $caldav;
-  public $caldavs = array();
-  private $account;
-  
-  public function __construct($rcmail, $type) {
-    $this->rcmail = $rcmail;
-    $this->type = $type;
-    $url = $this->rcmail->config->get('caldav_url', false);
-    if(!$url)
-      return;
-    if ($rcmail->config->get('timezone') === "auto") {
-      $tz = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : date('Z')/3600;
-    }
-    else {
-      $tz = $rcmail->config->get('timezone');
-      if($rcmail->config->get('dst_active')) {
-        $tz++;
-      }
-    }
-    $this->usertimezone = $tz;
-    
-    $user = $this->rcmail->config->get('caldav_user','demo');
-    $pass = $this->rcmail->config->get('caldav_password',$this->rcmail->encrypt('pass'));
-    $auth = $this->rcmail->config->get('caldav_auth','basic');
-    $extr = $this->rcmail->config->get('caldav_extr','1');
-    
-    $account = array(
-      'user' => $user,
-      'pass' => $pass,
-      'url'  => $url,
-      'auth' => $auth,
-      'extr' => $extr,
-    );
-    $this->account = $account;
-    $this->connect($account['url'], $account['user'], $account['pass'], $account['auth']);
-    $public_caldavs = $rcmail->config->get('public_caldavs', array());
-    foreach($public_caldavs as $category => $caldav){
-      $public_caldavs[$category]['pass'] = $rcmail->encrypt($caldav['pass']);
-    }
-    $caldavs = array_merge($rcmail->config->get('caldavs', array()), $public_caldavs);
-    $this->caldavs = $caldavs;
-  }
-  
-  private function connect($url, $user, $pass, $auth = 'basic'){
-    if($this->type == 'caldav'){
-      $rcmail = $this->rcmail;
-      $googleuser = $rcmail->config->get('googleuser', false);
-      $googlepass= $rcmail->config->get('googlepass', false);
-      if($user == '%gu'){
-        if($googleuser){
-          $user = str_replace('%gu', $googleuser, $user);
-        }
-      }
-      else if($user == '%u'){
-        $user = str_replace('%u', $_SESSION['username'], $user);
-      }
-      $pass_clear = false;
-      if($pass == '%gp'){
-        if($googlepass){
-          $pass = str_replace('%gp', $rcmail->decrypt($googlepass), $pass);
-          $pass_clear = true;
-        }
-      }
-      else if($pass == '%p'){
-        $pass = str_replace('%p', $rcmail->decrypt($_SESSION['password']), $pass);
-        $pass_clear = true;
-      }
-      if(!$pass_clear){
-        $pass = $this->rcmail->decrypt($pass);
-        if($pass == '%gp'){
-          if($googlepass){
-            $pass = str_replace('%gp', $rcmail->decrypt($googlepass), $pass);
-          }
-        }
-        else if($pass == '%p'){
-          $pass = str_replace('%p', $rcmail->decrypt($_SESSION['password']), $pass);
-      }
-      }
-      if(strpos($url,'%gu'))
-        $url = str_replace('%gu', $googleuser, $url);
-      if(strpos($url,'%u'))
-        $url = str_replace('%u', $_SESSION['username'], $url);
-      $url = slashify($url);
-      if($url == "/"){
-        $url = 'https://www.google.com/calendar/dav/john.doe@gmail.com/events/';
-      }
-      if(!$auth)
-        $auth = 'basic';
-      if($user != '%u' && $user != '%gu' && $pass !='%p' && $pass != '%gp' && strpos($url, '%u') === false && strpos($url, '%gu') === false)
-        $ret = $this->caldav = new CalDAVClient(trim($url), trim($user), trim($pass), trim($auth));
-      if(!$ret){
-        write_log('calendar',"CalDAV Invalid URL: '".$account['url']."'");
-        $ret = $this->caldav = new CalDAVClient('', '', '', '');
-      }
-    }
-  }
-  
-  private function q($str) {
-    return $this->rcmail->db->quoteIdentifier($str);
-  }
-  
-  private function table($str) {
-    return $this->rcmail->db->quoteIdentifier(get_table_name($str));
-  }
-  
-  private function generateId(){
-    $letters="abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-    for($i = 0; $i<=6; $i++){
-      $rndStr .= $letters[(rand() % strlen($letters))];
-    }
-    $icalStamp = date("Ymd\THis\Z");
-    return $icalStamp."-".$rndStr;
-  }
-
-  private function syncCalDAV($events,$request='PUT',$categories=false){
-    $return = false;
-    if($this->type == 'caldav'){
-      $event = $this->utils->exportEvents(0,0,$events);
-      $caldav_props = unserialize($events[0]['caldav']);
-      $this->connect($this->account['url'], $this->account['user'], $this->account['pass'], $this->account['auth']);
-      if($categories){
-        $caldavs = $this->caldavs;
-        if(!empty($caldavs[$categories])){
-          $this->connect($caldavs[$categories]['url'],$caldavs[$categories]['user'],$caldavs[$categories]['pass'],$caldavs[$categories]['auth']);
-        }
-      }
-      if($request == 'DELETE'){
-        $this->caldav->DoDELETERequest($caldav_props[0] . '.ics');
-        $return = true;
-      }
-      else if($request == 'PUT'){
-        $ret = $this->caldav->DoPUTRequest($caldav_props[0].'.ics', $event, $caldav_props[1]);
-        if($ret){
-          if(stripos($ret,'HTTP/1.1') !== false){
-            if(stripos($ret,'HTTP/1.1 204') !== false || $caldav_props[2] == '*'){
-              $ret = $this->caldav->GetEntryByHref($caldav_props[0]);
-              $count = preg_match('/Etag:(.*?)\n/i',$ret,$temp);
-              if($count > 0){
-                $etag = trim(str_replace('"','',$temp[1]));
-                $caldav_props = array($caldav_props[0], $etag, $caldav_props[2]);
-              }
-            }
-            else{
-              $caldav_props = null;
-            }
-          }
-          else{
-            $caldav_props = array($caldav_props[0], $ret, $caldav_props[2]);
-          }
-          if(is_array($caldav_props)){
-            $query = $this->rcmail->db->query(
-              "UPDATE " . $this->table('events') . " 
-              SET ".$this->q('caldav')."=?
-              WHERE ".$this->q('uid')."=?
-              AND ".$this->q('user_id')."=?",
-              serialize($caldav_props),
-              $events[0]['uid'],
-              $this->rcmail->user->ID
-            );
-            $return = true;
-          }
-          else{
-            $this->replicateEvents($events[0]['start'],$events[0]['start'] + 86400,$events[0]['categories']);
-          }
-        }
-      }
-    }
-    else{
-      $return = true;
-    }
-    return $return;
-  }
-  
-  public function searchEvents($str) {
-    if (!empty($this->rcmail->user->ID)) {
-      $cal_searchset = $this->rcmail->config->get('cal_searchset', array('summary'));
-      $all_day = '';
-      $str = str_replace(array('\\'),array(''),$str);
-      $str = str_replace('%','\%',$str);
-      $str = str_replace('*','%',$str);
-      $method = 'LIKE';
-      $wildcard = '%';
-      if(strlen($str) > 2){
-        $sql_filter = " AND (" . $this->rcmail->db->ilike($cal_searchset[0], $wildcard.$str.$wildcard);
-        if(count($cal_searchset) > 1){
-          for($i=1;$i<count($cal_searchset);$i++){
-            if($cal_searchset[$i] == 'all_day'){
-              $all_day .= " AND " . $this->q('all_day') . "=1";
-            }
-            else{
-              $sql_filter .= " OR " . $this->rcmail->db->ilike($cal_searchset[$i], $wildcard.$str.$wildcard);
-            }
-          }
-          $sql_filter .= ")";
-        }
-        $sql_result = $this->rcmail->db->query(
-          "SELECT * FROM ".$this->table('events').
-          " WHERE " . $this->q('del') . "<>1".
-          " AND " . $this->q('user_id') . "=?".
-          $all_day.
-          $sql_filter.
-          " ORDER BY " . $this->q('summary'),
-          $this->rcmail->user->ID);
-        while ($sql_result && ($sql_arr = $this->rcmail->db->fetch_assoc($sql_result))) {
-          $results[$sql_arr['event_id']] = $sql_arr;
-        }
-        if(!$_SESSION['removelayers']){
-          $events_table = $this->rcmail->config->get('db_table_events', 'events');
-          $this->rcmail->config->set('db_table_events',$this->rcmail->config->get('db_table_events_cache', 'events_cache'));
-          $sql_result = $this->rcmail->db->query(
-            "SELECT * FROM ".$this->table('events').
-            " WHERE " . $this->q('del') . "<>1".
-            " AND " . $this->q('user_id') . "=?".
-            $all_day.
-            $sql_filter.
-            " ORDER BY " . $this->q('summary'),
-            $this->rcmail->user->ID);
-          while ($sql_result && ($sql_arr = $this->rcmail->db->fetch_assoc($sql_result))) {
-            $results['c'.$sql_arr['event_id']] = $sql_arr;
-          }
-          $feeds = array_merge((array)$this->rcmail->config->get('public_calendarfeeds',array()),(array)$this->rcmail->config->get('calendarfeeds',array()));
-          foreach($feeds as $url => $category){
-            $arr = parse_url($url);
-            if($arr['path'] == './'){
-              if($_SERVER['HTTPS'])
-                $https = 's';
-              else
-                $https = '';
-              $url = 'http' . $https . "://" . $_SERVER['HTTP_HOST'] . ':' . $_SERVER['SERVER_PORT'] . substr($url,1);
-              $arr = parse_url($url);
-            }
-            $con = '?';
-            if(strstr($url,'?'))
-              $con = '&';
-            if(stripos($arr['query'],'plugin.calendar_showlayer') && strtolower($arr['host']) == strtolower($_SERVER['HTTP_HOST'])){
-              $user_id = $this->rcmail->user->ID;
-              $temparr = explode('&',$arr['query']);
-              foreach($temparr as $key => $val){
-                if(strpos($val,'_userid=') === 0){
-                  $temp = explode("=",$val);
-                  $remote_user = $temp[1];
-                  $this->rcmail->user->ID = $remote_user;
-                  $sql_result = $this->rcmail->db->query(
-                    "SELECT * FROM ".$this->table('events').
-                    " WHERE " . $this->q('del') . "<>1".
-                    " AND " . $this->q('user_id') . "=?".
-                    $all_day.
-                    $sql_filter.
-                    " ORDER BY " . $this->q('summary'),
-                    $this->rcmail->user->ID);
-                  while ($sql_result && ($sql_arr = $this->rcmail->db->fetch_assoc($sql_result))) {
-                    $results['c'.$sql_arr['event_id']] = $sql_arr;
-                  }
-                  $this->rcmail->user->ID = $user_id;
-                  break;
-                }
-              }
-            }
-          }
-          $this->rcmail->config->set('db_table_events', $events_table);
-          $arr = $this->utils->getUser($remote_user);
-          $prefs = unserialize($arr['preferences']);
-          $events_table = $this->rcmail->config->get('db_table_events', 'events');
-          $db_table = str_replace('_caldav','',$events_table);
-          $map = $this->rcmail->config->get('backend_db_table_map',array());
-          if($prefs['backend'] == 'caldav'){
-            $db_table .= $map['caldav'];
-          }
-          else{
-            $db_table .= $map['database'];
-          }
-          foreach($feeds as $url => $category){
-            $arr = parse_url($url);
-            $con = '?';
-            if(strstr($url,'?'))
-              $con = '&';
-            if(stripos($arr['query'],'plugin.calendar_showlayer') && strtolower($arr['host']) == strtolower($_SERVER['HTTP_HOST'])){
-              $user_id = $this->rcmail->user->ID;
-              $temparr = explode('&',$arr['query']);
-              foreach($temparr as $key => $val){
-                if(strpos($val,'_userid=') === 0){
-                  $temp = explode("=",$val);
-                  $remote_user = $temp[1];
-                  $this->rcmail->user->ID = $remote_user;
-                  $sql_result = $this->rcmail->db->query(
-                    "SELECT * FROM ".$db_table.
-                    " WHERE " . $this->q('del') . "<>1".
-                    " AND " . $this->q('user_id') . "=?".
-                    $all_day.
-                    $sql_filter.
-                    " ORDER BY " . $this->q('summary'),
-                    $this->rcmail->user->ID);
-                  while ($sql_result && ($sql_arr = $this->rcmail->db->fetch_assoc($sql_result))) {
-                    $results[$sql_arr['event_id']] = $sql_arr;
-                  }
-                  $this->rcmail->user->ID = $user_id;
-                  break;
-                }
-              }
-            }
-          }
-          $this->rcmail->config->set('db_table_events', $events_table);
-        }
-      }
-    }
-    if(is_array($results)){
-      $ret = $results;
-    }
-    else
-      $ret = false;
-    return $ret;
-  }
-  
-  public function scheduleReminders($event){
-    if (!empty($this->rcmail->user->ID) && $event) {
-      $map = $this->rcmail->config->get('backend_db_table_map');
-      if(stripos($this->table('events'),$map['caldav'])){
-        $col = 'caldav';
-      }
-      else{
-        if($this->rcmail->config->get('db_table_events_cache') == get_table_name('events')){
-          $col = 'cache';
-        }
-        else{
-          $col = 'events';
-        }
-      }
-      $query = $this->rcmail->db->query(
-        "DELETE FROM " . $this->table('reminders') . "
-        WHERE ".$this->q($col)."=? AND ".$this->q('user_id')."=?",
-        $event['event_id'],
-        $this->rcmail->user->ID
-      );
-      if($event['del'] == '1'){
-        return;
-      }
-      if($event['recurring'] != 0){
-        $events = $this->getEvents(
-          time() - 86400,
-          time() + 86400,
-          array(),
-          false,
-          array('uid',$event['uid'])
-        );
-      }
-      else{
-        $events[0] = $event;
-      }
-      if(is_array($events)){
-        $start = time();
-        $props = array();
-        $props['user_id'] = $this->rcmail->user->ID;
-        if($_SESSION['username'])
-          $props['username'] = $_SESSION['username'];
-        else{
-          $user = $this->utils->getUser($props['user_id']);
-          $props['username'] = $user['username'];
-        }
-        $props['user_data'] = $this->rcmail->user->data;
-        $props['lang'] = $this->rcmail->user->language;
-        foreach($events as $key => $event){
-          if($event['reminderservice'] != '0'){
-            $next = $event['start'] - $event['reminder'];
-            $schedule = false;
-            if($event['reminderservice'] == 'popup'){
-              if(!$event['remindersent'])
-                $schedule = true; // schedule missed reminders
-              if($next > $start)
-                $schedule = true; // always schedule future reminders
-            }
-            else if($event['reminderservice'] == 'email'){
-              if($next > $start && $event['clone'])
-                $schedule = true; // schedule future reminders for recurring events
-              if(!$event['remindersent'] && !$event['clone'] && $next > $start)
-                $schedule = true; // schedule future reminders for single events
-              if(!empty($this->caldavs[$event['categories']])){
-                if($this->caldavs[$event['categories']]['extr'] == 'external')
-                  $schedule = false;
-              }
-              else{
-                if($this->account['extr'] == 'external')
-                  $schedule = false;
-              }
-            }
-            if($schedule){
-              $mapped = $this->utils->eventArrayMap($event);
-              $props['event'] = $mapped;
-              $props['ics'] = $this->utils->exportEvents(0,0,array(0=>$event), false, true);
-              $query = $this->rcmail->db->query(
-                "INSERT INTO " . $this->table('reminders') . "
-                (".
-                  $this->q('user_id').", ".
-                  $this->q($col).", ".
-                  $this->q('type').", ".
-                  $this->q('props').", ".
-                  $this->q('runtime').")
-                VALUES (?, ?, ?, ?, ?)",
-                $this->rcmail->user->ID,
-                $event['event_id'],
-                $event['reminderservice'],
-                serialize($props),
-                $next
-              );
-              if($event['reminderservice'] == 'email'){
-                break;
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-
-  public function newEvent(
-    $start,
-    $end,
-    $summary,
-    $description,
-    $location,
-    $categories,
-    $allDay,
-    $recur,
-    $expires,
-    $occurrences,
-    $byday=false,
-    $bymonth=false,
-    $bymonthday=false,
-    $recurrence_id=false,
-    $exdates=false,
-    $reminderbefore=false,
-    $remindertype=false,
-    $remindermailto=false,
-    $uid=false,
-    $client=false
-  ) {
-    if (!empty($this->rcmail->user->ID)) {
-      $srecur = (string) $recur;
-      $rr = substr($recur,0,1);
-      $recur = substr($recur,1);
-      // PostgreSQL sets 'f' instead of '0' for false, which messes up our conditionals!
-      if ($byday==false) $byday='0';
-      if ($bymonth==false) $bymonth='0';
-      if ($bymonthday==false) $bymonthday='0';
-      if ($recurrence_id==false) $recurrence_id='0';
-      if ($exdates==false) $exdates='0';
-      if ($recur==false) $recur='0';
-      if ($reminderbefore==false) $reminderbefore='0';
-      if ($remindertype==false) $remindertype='0';
-      if ($remindermailto==false) $remindermailto='0';
-      if ($uid==false) $uid='0';
-      if ($client==false) $client='0';
-      //
-      if(!$uid)
-        $uid = $this->generateId();
-      $exists = $this->getEventByUID($uid, $recurrence_id);
-      if(is_array($exists)){
-        if($exists['del'] != '0'){
-          $query = $this->rcmail->db->query(
-            "UPDATE " . $this->table('events') . " 
-              SET ".$this->q('del')."=?
-              WHERE ".$this->q('event_id')."=?
-              AND ".$this->q('user_id')."=?",
-            0,
-            $exists['event_id'],
-            $this->rcmail->user->ID
-          );
-        }
-        if(
-          $start != $exists['start'] ||
-          $end != $exists['end'] ||
-          $summary != $exists['summary'] ||
-          $description != $exists['description'] ||
-          $location != $exists['location'] ||
-          $categories != $exists['categories'] ||
-          $recurrence_id != $exists['recurrence_id'] ||
-          $exdates != $exists['exdates'] ||
-          $reminderbefore != $exists['reminder'] ||
-          $remindertype != $exists['reminderservice'] ||
-          $remindermailto != $exists['remindermailto'] ||
-          $srecur != $exists['rr'] . $exists['recurring'] ||
-          $expires != $exists['expires'] ||
-          $occurences != $exists['occurences'] ||
-          $byday != $exists['byday'] ||
-          $bymonth != $exists['bymonth'] ||
-          $bymonthday != $exists['bymonthday'] ||
-          $allDay != $exists['all_day']
-        ){
-          $ret = $this->editEvent(
-            $exists['event_id'],
-            $start,
-            $end,
-            $summary,
-            $description,
-            $location,
-            $categories,
-            $srecur,
-            $expires,
-            $occurrences,
-            $byday,
-            $bymonth,
-            $bymonthday,
-            $recurrence_id,
-            $exdates,
-            $reminderbefore,
-            $remindertype,
-            $remindermailto,
-            $allDay
-          );
-        }
-        else{
-          $ret = $exists;
-        }
-        $ret['edit'] = 1;
-        return $ret;
-      }
-      $query = $this->rcmail->db->query(
-        "INSERT INTO " . $this->table('events') . "
-         (".
-           $this->q('user_id').", ".
-           $this->q('start').", ".
-           $this->q('end').", ".
-           $this->q('summary').", ".
-           $this->q('description').", ".
-           $this->q('location').", ".
-           $this->q('categories').", ".
-           $this->q('all_day').", ".
-           $this->q('recurring').", ".
-           $this->q('rr').", ".
-           $this->q('expires').", ".
-           $this->q('occurrences').", ".
-           $this->q('byday').", ".
-           $this->q('bymonth').", ".
-           $this->q('bymonthday').", ".
-           $this->q('reminder').", ".
-           $this->q('reminderservice').", ".
-           $this->q('remindermailto').", ".
-           $this->q('remindersent').", ".
-           $this->q('recurrence_id').", ".
-           $this->q('exdates').", ".
-           $this->q('uid').", ".
-           $this->q('client').", ".
-           $this->q('caldav').", ".
-           $this->q('timestamp').")
-         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
-        $this->rcmail->user->ID,
-        $start,
-        $end,
-        $summary,
-        $description,
-        $location,
-        $categories,
-        $allDay,
-        $recur,
-        $rr,
-        $expires,
-        $occurrences,
-        $byday,
-        $bymonth,
-        $bymonthday,
-        $reminderbefore,
-        $remindertype,
-        $remindermailto,
-        0,
-        $recurrence_id,
-        $exdates,
-        $uid,
-        $client,
-        serialize(array(0 => $uid, 1 => false, 2 => '*')),
-        date('Y-m-d H:i:s', time())
-      );
-      $id = $this->rcmail->db->insert_id($this->rcmail->config->get('db_sequencs_events'));
-      $events = $this->getEventsByUID($uid);
-      //find me: investigate why this is here ...
-      if($this->rcmail->action == 'plugin.newEvent' || $this->rcmail->action == 'plugin.editEvent' || $this->rcmail->action == 'plugin.saveical' || $this->rcmail->action == 'plugin.calendar_upload' || $this->rcmail->action == 'plugin.moveEvent'|| $this->rcmail->action == 'plugin.resizeEvent' || $this->rcmail->action == 'plugin.calendar_showlayer'){
-        $events[0]['sync'] = $this->syncCalDAV($events,'PUT',$categories);
-      }
-      $this->calModified($this->rcmail->user->ID);
-      $this->scheduleReminders($events[0]);
-      return $events[0];
-    }
-  }
-
-  public function editEvent(
-    $id,
-    $start,
-    $end,
-    $summary,
-    $description,
-    $location,
-    $categories,
-    $recur,
-    $expires,
-    $occurrences,
-    $byday=false,
-    $bymonth=false,
-    $bymonthday=false,
-    $recurrence_id=false,
-    $exdates=false,
-    $reminderbefore=false,
-    $remindertype=false,
-    $remindermailto=false,
-    $allDay=false,
-    $old_categories=false
-  ) {
-    if (!empty($this->rcmail->user->ID)) {
-      $srecur = $recur;
-      $rr = substr($recur,0,1);
-      $recur = substr($recur,1);
-      // PostgreSQL sets 'f' instead of '0' for false, which messes up our conditionals! 
-      if ($byday==false) $byday='0';
-      if ($bymonth==false) $bymonth='0';
-      if ($bymonthday==false) $bymonthday='0';
-      if ($recurrence_id==false) $recurrence_id='0';
-      if ($exdates==false) $exdates='0';
-      if ($reminderbefore==false) $reminderbefore='0';
-      if ($remindertype==false) $remindertype='0';
-      if ($remindermailto==false) $remindermailto='0';
-      if ($allday==false) $allday='0';
-      if ($recurrence_id==false) $recurrence_id='0';
-      if ($recur==false) $recur='0';
-      if ($uid==false) $uid='0';
-      if ($client==false) $client='0';
-      //
-      $query = $this->rcmail->db->query(
-        "UPDATE " . $this->table('events') . " 
-         SET ".
-           $this->q('summary')."=?, ".
-           $this->q('start')."=?, ".
-           $this->q('end')."=?, ".
-           $this->q('description')."=?, ".
-           $this->q('location')."=?, ".
-           $this->q('categories')."=?, ".
-           $this->q('rr')."=?, ".
-           $this->q('recurring')."=?, ".
-           $this->q('expires')."=?, ".
-           $this->q('occurrences')."=?, ".
-           $this->q('byday')."=?, ".
-           $this->q('bymonth')."=?, ".
-           $this->q('bymonthday')."=?, ".
-           $this->q('recurrence_id')."=?, ".
-           $this->q('exdates')."=?, ".
-           $this->q('all_day')."=?, ".
-           $this->q('reminder')."=?, ".
-           $this->q('reminderservice')."=?, ".
-           $this->q('remindermailto')."=?, ".
-           $this->q('remindersent')."=?, ".
-           $this->q('timestamp')."=?, ".
-           $this->q('del')."=?, ".
-           $this->q('notified')."=?
-         WHERE ".$this->q('event_id')."=?
-         AND ".$this->q('user_id')."=?",
-        $summary,
-        $start,
-        $end,
-        $description,
-        $location,
-        $categories,
-        $rr,
-        $recur,
-        $expires,
-        $occurrences,
-        $byday,
-        $bymonth,
-        $bymonthday,
-        $recurrence_id,
-        $exdates,
-        $allDay,
-        $reminderbefore,
-        $remindertype,
-        $remindermailto,
-        0,
-        date('Y-m-d H:i:s', time()),
-        0,
-        0,
-        $id,
-        $this->rcmail->user->ID
-      );
-      $this->calModified($this->rcmail->user->ID);
-      $event = $this->getEvent($id);
-      // find me: get uid from GUI and calendar.php
-      $events = $this->getEventsByUID($event['uid']);
-      $this->scheduleReminders($events[0]);
-      if($this->type == 'caldav'){
-        //find me: investigate why this is here ...
-        if($this->rcmail->action == 'plugin.editEvent' || $this->rcmail->action == 'plugin.newEvent' || $this->rcmail->action == 'plugin.calendar_upload' || $this->rcmail->action == 'plugin.calendar_showlayer'){
-          $caldavs = $this->caldavs;
-          if($categories != $old_categories){
-            if(!empty($caldavs[$old_categories]) || !empty($caldavs[$categories])){
-              $sync = $this->newEvent($start, $end, $summary, $description, $location, $categories, $allDay, $srecur, $expires, $occurrences, $byday, $bymonth, $bymonthday);
-              if($sync)
-                $events[0] = $this->removeEvent($id, $old_categories);
-            }
-            else{
-              $events[0]['sync'] = $this->syncCalDAV($events);
-            }
-          }
-          else{
-            $events[0]['sync'] = $this->syncCalDAV($events);
-          }
-        }
-      }
-      else{
-        $events[0]['sync'] = true;
-      }
-      return $events[0];
-    }
-  }
-
-  public function moveEvent(
-    $id,
-    $start,
-    $end,
-    $allDay,
-    $reminder
-  ) {
-    if (!empty($this->rcmail->user->ID)) {
-      $query = $this->rcmail->db->query(
-        "UPDATE " . $this->table('events') . " 
-         SET ".$this->q('start')."=?, ".
-               $this->q('end')."=?, ".
-               $this->q('all_day')."=?, ".
-               $this->q('remindersent')."=?, ".
-               $this->q('timestamp')."=?, ".
-               $this->q('notified')."=?
-         WHERE ".$this->q('event_id')."=?
-         AND ".$this->q('user_id')."=?",
-        $start,
-        $end,
-        $allDay,
-        0,
-        date('Y-m-d H:i:s', time()),
-        0,
-        $id,
-        $this->rcmail->user->ID
-      );
-      $this->calModified($this->rcmail->user->ID);
-      $event = $this->getEvent($id);
-      // find me: get uid from GUI and calendar.php
-      $events = $this->getEventsByUID($event['uid']);
-      if($this->rcmail->action == 'plugin.moveEvent'){
-        $events[0]['sync'] = $this->syncCalDAV($events,'PUT',$events[0]['categories']);
-      }
-      $this->scheduleReminders($events[0]);
-      return $events[0];
-    }
-  }
-  
-  public function resizeEvent(
-    $id,
-    $start,
-    $end,
-    $reminder
-  ) {
-    if (!empty($this->rcmail->user->ID)) {
-      $query = $this->rcmail->db->query(
-        "UPDATE " . $this->table('events') . " 
-         SET ".$this->q('start')."=?, ".
-               $this->q('end')."=?, ".
-               $this->q('remindersent')."=?, ".
-               $this->q('timestamp')."=?, ".
-               $this->q('notified')."=?
-         WHERE ".$this->q('event_id')."=?
-         AND ".$this->q('user_id')."=?",
-        $start,
-        $end,
-        0,
-        date('Y-m-d H:i:s', time()),
-        0,
-        $id,
-        $this->rcmail->user->ID
-      );
-      $this->calModified($this->rcmail->user->ID);
-      $event = $this->getEvent($id);
-      // find me: get uid from GUI and calendar.php
-      $events = $this->getEventsByUID($event['uid']);
-      if($this->rcmail->action == 'plugin.resizeEvent'){
-        $events[0]['sync'] = $this->syncCalDAV($events,'PUT',$events[0]['categories']);
-      }
-      $this->scheduleReminders($events[0]);
-      return $events[0];
-    }
-  }
-
-  public function removeEvent($id, $categories=false) {
-    if (!empty($this->rcmail->user->ID)) {
-      $query = $this->rcmail->db->query(
-        "UPDATE " . $this->table('events') . " 
-         SET ".$this->q('del')."=?, ".$this->q('timestamp')."=?
-         WHERE ".$this->q('event_id')."=?
-         AND ".$this->q('user_id')."=?",
-        1,
-        date('Y-m-d H:i:s', time()),
-        $id,
-        $this->rcmail->user->ID
-      );
-      $event = $this->getEvent($id);
-      // find me: get uid from GUI and calendar.php
-      $events = $this->getEventsByUID($event['uid']);
-      //find me: investigate why this is here ...
-      if($this->rcmail->action == 'plugin.editEvent' || $this->rcmail->action == 'plugin.removeEvent' || $this->rcmail->action == 'plugin.calendar_showlayer'){
-        $caldav_props = unserialize($event['caldav']);
-        $caldavs = $this->caldavs;
-        if($event['recurrence_id'] != 0){
-          $initialevent = $this->getEventByUID($event['uid']);
-          if($initialevent['exdates']){
-            $exdates = (array) @unserialize($initialevent['exdates']);
-            $exdates[] = (int) $event['start'];
-          }
-          else{
-            $exdates = array((int) $event['start']);
-          }
-          $initialevent['exdates'] = serialize($exdates);
-          $initialevent['recurrence_id'] = null;
-          $events[0]['sync'] = $this->syncCalDAV(array(0 => $initialevent),'PUT',$initialevent['categories']);
-        }
-        else{
-          if(!$categories)
-            $categories = $events[0]['categories'];
-          $events[0]['sync'] = $this->syncCalDAV($events,'DELETE',$categories);
-        }
-      }
-      $this->calModified($this->rcmail->user->ID);
-      $this->scheduleReminders($events[0]);
-      return $events[0];
-    }
-  }
-  
-  public function purgeEvents() {
-   if (!empty($this->rcmail->user->ID)) {
-      $query = $this->rcmail->db->query(
-        "DELETE FROM " . $this->table('events') . "
-         WHERE ".$this->q('user_id')."=?
-         AND ".$this->q('del')."<>?",
-         $this->rcmail->user->ID,
-         0
-      );
-    } 
-  }
-  
-  public function removeDuplicate($id) {
-    if (!empty($this->rcmail->user->ID)) {
-      $query = $this->rcmail->db->query(
-        "DELETE FROM " . $this->table('events') . "
-         WHERE ".$this->q('user_id')."=? AND ".$this->q('event_id')."=?",
-         $this->rcmail->user->ID,
-         $id
-      );
-      $this->calModified($this->rcmail->user->ID, true);
-    }  
-  }
-  
-  public function truncateEvents($mode=0) {
-    if (!empty($this->rcmail->user->ID)) {
-      if($mode == 0){
-        $query = $this->rcmail->db->query(
-          "DELETE FROM " . $this->table('events') . "
-          WHERE ".$this->q('user_id')."=? AND ".$this->q('del')."=?",
-          $this->rcmail->user->ID,
-          1
-        );
-        $this->calModified($this->rcmail->user->ID, true);
-      }
-      else if($mode == 1){
-        $query = $this->rcmail->db->query(
-          "UPDATE " . $this->table('events') . " 
-          SET ".$this->q('del')."=?, ".$this->q('timestamp')."=?
-          WHERE ".$this->q('user_id')."=?",
-          2,
-          date('Y-m-d H:i:s', time()),
-          $this->rcmail->user->ID
-        );
-      }
-      else if($mode == 2){
-        $query = $this->rcmail->db->query(
-          "UPDATE " . $this->table('events') . " 
-          SET ".$this->q('del')."=?, ".$this->q('timestamp')."=?
-          WHERE ".$this->q('user_id')."=?",
-          0,
-          date('Y-m-d H:i:s', time()),
-          $this->rcmail->user->ID
-        );
-      }
-      else if($mode == 3){
-        $query = $this->rcmail->db->query(
-          "DELETE FROM " . $this->table('events') . "
-          WHERE ".$this->q('user_id')."=?",
-          $this->rcmail->user->ID
-        );
-      }
-    }
-  }
-  
-  public function exportEvents($categories=false){
-    if($this->type == 'caldav'){
-      if($categories){
-        $caldavs = $this->caldavs;
-        if(is_array($caldavs[$categories])){
-          $this->connect($caldavs[$categories]['url'],$caldavs[$categories]['user'],$caldavs[$categories]['pass'],$caldavs[$categories]['auth']);
-        }
-      }
-      $response = trim($this->caldav->DoRequest());
-      $temparr = explode("\r\n\r\n", $response,2);
-      return $temparr[1];
-    }
-  }
-  
-  private function _getEvents(
-    $estart,
-    $eend,
-    $category=false,
-    $type='events'
-  ) {
-    if($this->type == 'caldav'){
-      $events = array();
-      $map = $this->rcmail->config->get('backend_db_table_map');
-      if(stripos($this->table('events'),$map['caldav'])){
-        $startYear  = date('Y',$estart);
-        $startMonth = date('m',$estart);
-        $startDay   = date('d',$estart);
-        $endYear    = date('Y',$eend  );
-        $endMonth   = date('m',$eend  );
-        $endDay     = date('d',$eend  );
-        $caldavs = $this->caldavs;
-        if(!$category || ($category && !$caldavs[$category])){
-          if($type == 'events'){
-            $events = (array) $this->caldav->GetEvents($startYear.$startMonth.$startDay."T000000Z",$endYear.$endMonth.$endDay."T000000Z");
-          }
-          else if($type == 'alarms'){
-            // cron login successful ?
-            if(method_exists($this->caldav, 'GetEventAlarms')){
-              $events = (array) $this->caldav->GetEventAlarms($startYear.$startMonth.$startDay."T000000Z",$endYear.$endMonth.$endDay."T000000Z");
-            }
-          }
-        }
-        else{
-          if($category && $caldavs[$category]){
-            $caldav = $caldavs[$category];
-            $this->connect($caldav['url'],$caldav['user'],$caldav['pass'],$caldav['auth']);
-            $startYear  = date('Y',$estart);
-            $startMonth = date('m',$estart);
-            $startDay   = date('d',$estart);
-            if($type == 'events'){
-              $layers = (array) $this->caldav->GetEvents($startYear.$startMonth.$startDay."T000000Z",$endYear.$endMonth.$endDay."T000000Z");
-            }
-            else if($type == 'alarms'){
-              $layers = (array) $this->caldav->GetEventAlarms($startYear.$startMonth.$startDay."T000000Z",$endYear.$endMonth.$endDay."T000000Z");
-            }
-            foreach($layers as $key => $layer){
-              $layers[$key]['data'] = str_replace("\nCATEGORIES:","\nX-CATEGORIES:",$layers[$key]['data']);
-              $insert = "\nCATEGORIES:" . $category;
-              $layers[$key]['data'] = str_replace("\nBEGIN:VEVENT", "\nBEGIN:VEVENT" . $insert, $layers[$key]['data']);
-            }
-            $events = $layers;
-          }
-        }
-        $concat = '';
-        foreach($events as $key => $val){
-          $insert = "\nX-HREF:".$val['href']."\nX-ETAG:".$val['etag'];
-          $val['data'] = str_replace("\nBEGIN:VEVENT", "\nBEGIN:VEVENT" . $insert, $val['data']);
-          $concat .= $val['data'];
-        }
-        if($concat != ''){
-          $this->utils->importEvents($concat);
-          $query = $this->rcmail->db->query(
-            "UPDATE " . $this->table('events') . " 
-            SET ".$this->q('timestamp')."=?, ".$this->q('notified')."=?
-            WHERE ".$this->q('user_id')."=?",
-            '0',
-            '1',
-            $this->rcmail->user->ID
-          );
-        }
-      }
-    }
-  }
-  
-  public function removeReminder(
-    $id,
-    $event_id,
-    $ts
-  ) {
-    if (!empty($this->rcmail->user->ID)) {
-      if(!$id && !$event_id){
-        $reminders = (array) $this->getReminders($ts);
-        $query = $this->rcmail->db->query(
-          "DELETE FROM " . $this->table('reminders') . "
-          WHERE " . $this->q('type') . "=? AND ".$this->q('user_id')."=? AND " . $this->q('runtime') . "<?",
-          'popup',
-          $this->rcmail->user->ID,
-          $ts
-        );
-        foreach($reminders as $reminder){
-          $query = $this->rcmail->db->query(
-            "UPDATE " .$this->table('events') . " 
-            SET ". $this->q('remindersent')."=?
-            WHERE ".$this->q('event_id')."=?
-            AND ".$this->q('user_id')."=?",
-            $ts,
-            $reminder['id'],
-            $this->rcmail->user->ID
-          );
-        }
-      }
-      else{
-        $query = $this->rcmail->db->query(
-          "DELETE FROM " . $this->table('reminders') . "
-          WHERE " . $this->q('reminder_id') . "=? AND ".$this->q('user_id')."=?",
-          $id,
-          $this->rcmail->user->ID
-        );
-        $query = $this->rcmail->db->query(
-          "UPDATE " .$this->table('events') . " 
-          SET ". $this->q('remindersent')."=?
-          WHERE ".$this->q('event_id')."=?
-          AND ".$this->q('user_id')."=?",
-          $ts,
-          $event_id,
-          $this->rcmail->user->ID
-        );
-      }
-    }
-  }
-  
-  public function getReminders(
-    $start,
-    $type='popup'
-  ) {
-    $ret = array();
-    if (!empty($this->rcmail->user->ID)) {
-      $result = $this->rcmail->db->query(
-        "SELECT * FROM " . $this->table('reminders') . " 
-         WHERE ".$this->q('user_id')."=? AND ".$this->q('runtime')."<? AND ".$this->q('type')."=?",
-         $this->rcmail->user->ID,
-         $start,
-         $type
-      );
-      $reminders = array();
-      while ($result && ($reminder = $this->rcmail->db->fetch_assoc($result))) {
-        $reminders[] = $reminder;
-      }
-      foreach($reminders as $key => $val){
-        $col = 'events';
-        if($val['caldav'] != '0')
-          $col = 'caldav';
-        else if($val['cache'] != '0')
-          $col = 'cache';
-        $result = $this->rcmail->db->query(
-          "SELECT * FROM " . $this->table('events') . " 
-          WHERE ".$this->q('user_id')."=? AND ".$this->q('event_id')."=?",
-          $this->rcmail->user->ID,
-          $val[$col]
-        );
-        if($result){
-          $event = $this->rcmail->db->fetch_assoc($result);
-          if($event['recurring'] != '0'){
-            $duration = 0;
-            if($event['end'] != '0'){
-              $duration = (int) $event['end'] - (int) $event['start'];
-            }
-            $start = (int) $val['runtime'] + (int) $event['reminder'];
-            $end = $start + $duration;
-            $event['start'] = $start;
-            if($event['end'] != '0'){
-              $event['end'] = $start + $duration;
-            }
-          }
-          $event['reminder_id'] = $val['reminder_id'];
-          $ret[$event['start'] . $event['uid'] . $event['event_id']] = $this->utils->eventArrayMap($event);
-        }
-      }
-    }
-    return $ret;
-  }
-  
-  public function replicateEvents(
-    $estart,
-    $eend,
-    $category=false,
-    $type='events'
-  ){
-    if (!empty($this->rcmail->user->ID)) {
-      $this->_getEvents($estart, $eend, $category, $type);
-    }
-  }
-  
-  public function getEvents(
-    $estart,
-    $eend,
-    $labels=array(),
-    $category=false,
-    $filter=false,
-    $client=false,
-    $type='events'
-  ) {
-    if (!empty($this->rcmail->user->ID)) {
-      $mem_limit = (int) ini_get('memory_limit');
-      $start = -1;
-      $end = $eend + 1;
-      if($filter){
-        $filterfield = $filter[0];
-        $filtercomp = '=?';
-        $filterval = $filter[1];
-      }
-      else{
-        $filterfield = 'del';
-        $filtercomp = '<>?';
-        $filterval = 1;
-      }
-      $result = $this->rcmail->db->query(
-        "SELECT * FROM " . $this->table('events') . " 
-         WHERE ".$this->q('user_id')."=? AND ".
-                 $this->q('start').">? AND ".
-                 $this->q('start')."<? AND ".
-                 $this->q($filterfield) . $filtercomp,
-         $this->rcmail->user->ID,
-         $start,
-         $end,
-         $filterval
-      );
-      $events = array();
-      while ($result && ($event = $this->rcmail->db->fetch_assoc($result))) {
-        if($this->rcmail->action == 'plugin.getEvents'){
-          $db_category = $event['categories'];
-          if($category){
-            if($db_category != $category){
-              continue;
-            }
-          }
-          else{
-            $caldavs = $this->caldavs;
-            if(!empty($caldavs[$db_category])){
-              continue;
-            }
-          }
-        }
-        // backwards compatibility
-        if(empty($event['rr'])){
-          switch($event['recurring']){
-            case    86400:
-            case    86401:
-              $event['rr'] = 'd';
-              break;
-            case   604800:
-            case  1209600:
-            case  1814400:
-            case  2419200:
-              $event['rr'] = 'w';
-              break;
-            case  2592000:
-              $event['rr'] = 'm';
-              break;
-            case 31536000:
-              $event['rr'] = 'y';
-              break;
-          }
-        }
-        $append = $event['start'];
-        $add = true;
-        if($event['exdates']){
-          $exdates = @unserialize($event['exdates']);
-          if(is_array($exdates) && count($exdates) > 0){
-            $exdates = $this->utils->array_flatten($exdates);
-            $exdates = array_flip($exdates);
-            if(isset($exdates[$event['start']])){
-              $add = false;
-            }
-          }
-        }
-        if($event['recurrence_id']){
-          $append = $event['recurrence_id'];
-        }
-        if($event['start'] >= $estart || $event['end'] >= $estart || $event['recurring'] != 0){
-          if($event['start'] >= $estart || $event['end'] >= $estart){
-            if($add){
-              $events[md5($event['uid'].$append)]=array( 
-               'event_id'        => (int)    $event['event_id'],
-                'uid'             => (string) $event['uid'], 
-                'start'           => (int)    $event['start'], 
-                'end'             => (int)    $event['end'],
-                'expires'         => (string) $event['expires'],
-                'rr'              => (string) $event['rr'],
-                'recur'           => (string) $event['recurring'],
-                'occurrences'     => (int)    $event['occurrences'],
-                'recurrence_id'   => (string) $event['recurrence_id'],
-                'summary'         => (string) $event['summary'], 
-                'description'     => (string) $event['description'],
-                'location'        => (string) $event['location'],
-                'categories'      => (string) $event['categories'],
-                'all_day'         => (int)    $event['all_day'],
-                'timestamp'       => (string) $event['timestamp'],
-                'del'             => (int)    $event['del'],
-                'notified'        => (int)    $event['notified'],
-                'byday'           => (string) $event['byday'],
-                'bymonth'         => (string) $event['bymonth'],
-                'bymonthday'      => (string) $event['bymonthday'],
-                'reminder'        => (int)    $event['reminder'],
-                'reminderservice' => (string) $event['reminderservice'],
-                'remindermailto'  => (string) $event['remindermailto'],
-                'editable'        => true,
-                'clone'           => false 
-              );
-            }
-          }
-          if($event['recurring'] != 0 && !$client){
-            $rrule = $this->utils->rrule($event);
-            if($rrule){
-              $basedate = date('Ymd\THis',$event['start']);
-              $rule = new RRule(new iCalDate($basedate), $rrule);
-              do{
-                $date = $rule->GetNext();
-                if(isset($date)){
-                  $clone_date = $date->Render();
-                  $clone_start = strtotime($clone_date);
-                  $clone_end = strtotime($clone_date) + $event['end'] - $event['start'];
-                  $dst_adjust = 0;
-                  if(date('I', $event['start']) != date('I', $clone_start)){
-                    if(date('I',$event['start']) == 0 && date('I',$clone_start) == 1)
-                      $dst_adjust = 3600;
-                    else
-                      $dst_adjust = -3600;
-                  }
-                  $clone_start = $clone_start + $dst_adjust;
-                  $clone_end = $clone_end + $dst_adjust;
-                  if($clone_start > $event['start'] && $clone_start > $estart){
-                    if(!isset($exdates[$clone_start])){
-                      if($add){
-                        $set_clone = (string) $event['start'];
-                        $set_clone_end = (string) $event['end'];
-                      }
-                      else{
-                        $set_clone = false;
-                        $set_clone_end = false;
-                        $add = true;
-                      }
-                      $event['editable'] = true;
-                      $event['recur'] = $event['recurring'];
-                      $events[md5($event['uid'].$clone_start)] = array( 
-                        'event_id'        => (int) $event['event_id'],
-                        'uid'             => (string) $event['uid'],
-                        'start'           => (int) $clone_start,
-                        'end'             => (int) $clone_end,
-                        'expires'         => (string) $event['expires'],
-                        'rr'              => (string) $event['rr'],
-                        'recur'           => (string) $event['recurring'],
-                        'occurrences'     => (int)    $event['occurrences'],
-                        'recurrence_id'   => (string) $event['recurrence_id'],
-                        'summary'         => (string) $event['summary'], 
-                        'description'     => (string) $event['description'],
-                        'location'        => (string) $event['location'],
-                        'categories'      => (string) $event['categories'],
-                        'all_day'         => (int)    $event['all_day'],
-                        'timestamp'       => (string) $event['timestamp'],
-                        'del'             => (int)    $event['del'],
-                        'byday'           => (string) $event['byday'],
-                        'bymonth'         => (string) $event['bymonth'],
-                        'bymonthday'      => (string) $event['bymonthday'],
-                        'reminder'        => (int)    $event['reminder'],
-                        'reminderservice' => (string) $event['reminderservice'],
-                        'remindermailto'  => (string) $event['remindermailto'],
-                        'editable'        => (bool)   $event['editable'],
-                        'clone'           => $set_clone,
-                        'clone_end'       => $set_clone_end,
-                        'caldav'          => (string) $event['caldav'],
-                        'notified'        => (int) $event['notified'],
-                        'initial'         => (array) $this->utils->eventArrayMap($event)
-                      );
-                    }
-                  }
-                }
-              }
-              while(isset($date) && strtotime($date->Render()) <= $eend);
-            }
-          }
-        }
-      }
-      $public_caldavs = $this->rcmail->config->get('public_caldavs', array());
-      foreach($events as $key => $event){
-        $category = $event['categories'];
-        if(!empty($public_caldavs[$category]) && $public_caldavs[$category]['readonly']){
-          $events[$key]['editable'] = false;
-        }
-      }
-      return $events;
-    }
-  }
-  
-  private function calModified($userid=false,$del=false) {
-    if($userid && !$del){
-      file_put_contents('./plugins/calendar/temp/' . $userid . '.pid', time());
-    }
-    if($userid && $del){
-      @unlink('./plugins/calendar/temp/' . $userid . '.pid');
-    }
-  }
-
-  public function removeTimestamps() {
-    if (!empty($this->rcmail->user->ID)) {
-      $query = $this->rcmail->db->query(
-        "UPDATE " . $this->table('events') . " 
-         SET ".$this->q('timestamp')."=?
-         WHERE ".$this->q('user_id')."=?",
-        '0',
-        $this->rcmail->user->ID
-      );
-    }
-  }
-  
-  public function getEvent($eventid){
-    if (!empty($this->rcmail->user->ID)) {
-      $result = $this->rcmail->db->query(
-        "SELECT * FROM " . $this->table('events') . " 
-         WHERE ".$this->q('user_id')."=? AND ".$this->q('event_id')."=?",
-         $this->rcmail->user->ID,
-         $eventid
-      );
-      $event = $this->rcmail->db->fetch_assoc($result);
-      if($event){
-        $event['recur'] = $event['recurring'];
-        return $event;
-      }
-    }
-    return array();
-  }
-  
-  public function getEventByUID($uid, $recurrence_id=0){
-    $event = array();
-    if (!empty($this->rcmail->user->ID)) {
-      $result = $this->rcmail->db->query(
-        "SELECT * FROM " . $this->table('events') . " 
-         WHERE ".$this->q('user_id')."=? AND ".$this->q('uid')."=? AND ".$this->q('recurrence_id')."=?",
-         $this->rcmail->user->ID,
-         $uid,
-         $recurrence_id
-      );
-      while ($result && ($event = $this->rcmail->db->fetch_assoc($result))){
-        $events[] = $event;
-      }
-      if(is_array($events) && count($events) > 1)
-        write_log('calendar', "ERROR: Event with UID " . $event['uid'] . " is not unique");
-      $event = $events[0];
-    }
-    return $event;
-  }
-  
-  public function getEventsByUID($uid){
-    if (!empty($this->rcmail->user->ID)) {
-      $result = $this->rcmail->db->query(
-        "SELECT * FROM " . $this->table('events') . " 
-         WHERE ".$this->q('user_id')."=? AND ".$this->q('uid')."=?",
-         $this->rcmail->user->ID,
-         $uid
-      );
-      while ($result && ($event = $this->rcmail->db->fetch_assoc($result))){
-        $temparr[] = $event;
-      }
-    }
-    $i = 0;
-    $events = array();
-    if(is_array($temparr)){
-      foreach($temparr as $key => $event){
-        if(!$event['recurrence_id']){
-          if(!empty($events[0]))
-            write_log('calendar', "ERROR: Event with UID " . $event['uid'] . " is not unique");
-          $events[0] = $event;
-        }
-        else{
-          $events[$i] = $event;
-        }
-        $i++;
-      }
-    }
-    return $events;
-  }
-  
-  public function test($str = 'db_table_events') {
-    $this->rcmail->db->db_handle->loadModule('Manager');
-    if(!PEAR::isError($result = $this->rcmail->db->db_handle->listTableFields($this->rcmail->config->get($str))))
-      $ret = $result;
-    else
-      $ret = array();
-    return $ret;
-  }
-}
-?>

+ 0 - 1
SE/procesy5.php

@@ -1699,7 +1699,6 @@ function lay_procesy_user_panel() {
 			echo '<th class="logo" style="width:5%; white-space:nowrap;">';
 			echo '<a href="index.php">SE</a>';
 			echo ' / ';
-			//echo App::link("PROCESY", $_SERVER['PHP_SELF'], array('class'=>'logo', 'title'=>"PROCESY"));
 			echo App::link("ODSWIEZ", '');
 		echo'</th>';
 		echo'<td class="main-menu">';// center

+ 6 - 0
SE/se-lib/Api.php

@@ -3,12 +3,17 @@
 class Api {
 
 	private $_apiUser;
+	private $_apiBaseUri;
 	private $_request;
 
 	public function setUser($user) {
 		$this->_apiUser = $user;
 	}
 
+	public function setBaseUri($uri) {
+		$this->_apiBaseUri = $uri;
+	}
+
 	public function execute($url) {
 		$request = $this->parseUrl($url);
 
@@ -21,6 +26,7 @@ class Api {
 		}
 		$apiRouter = new $apiRouterClassName();
 		$apiRouter->setUser($this->_apiUser);
+		$apiRouter->setBaseUri($this->_apiBaseUri);
 		$responseDocument = $apiRouter->execute($request);
 		if (empty($responseDocument)) {
 			throw new HttpException("No result", 404);

+ 1 - 1
SE/se-lib/Api/Table.php

@@ -97,7 +97,7 @@ class Api_Table {
 		if (!$dataSource) {
 			throw new HttpException("DataSource not exists", 404);
 		}
-		$requestBodyXml = file_get_contents('php://input');
+		$requestBodyXml = Request::getRequestBody();
 		IF(V::get('DBG_ERROR_LOG','',$_REQUEST)){trigger_error("request body:'{$requestBodyXml}'", E_USER_NOTICE);}
 		IF(V::get('DBG_ERROR_LOG','',$_REQUEST)){trigger_error("request headers:'" . json_encode(getallheaders()) . "'", E_USER_NOTICE);}
 		IF(V::get('DBG_ERROR_LOG','',$_REQUEST)){trigger_error("request post:'" . json_encode($_POST) . "'", E_USER_NOTICE);}

+ 14 - 35
SE/se-lib/Api/Wfs.php → SE/se-lib/Api/WfsData.php

@@ -1,40 +1,18 @@
 <?php
 
+Lib::loadClass('ApiRouteBase');
 Lib::loadClass('ApiDataSourceTodo');// TODO: @see Entity/Source/Mysql from feature-schema-install
 Lib::loadClass('Api_WfsException');
-Lib::loadClass('Api_WfsServer');
+Lib::loadClass('Api_WfsDataServer');
 Lib::loadClass('UserAcl');
 
-class Api_Wfs {
+class Api_WfsData extends ApiRouteBase {// TODO: extends Api_WfsBase which extends ApiBase
 
-	private $_apiUser;
-	private $_dataSourceName;
-	private $_tblName;
-	private $_tblSchema;
-
-	public function setUser($user) {
-		$this->_apiUser = $user;
-	}
-
-	private function reqDBG($request, $line) {
-		$reqLog = "[" . date("Y-m-d H:m:s") . "] WFS: ---- {$_SERVER['REQUEST_METHOD']}: {$_SERVER['REQUEST_URI']}";
-		if ($_SERVER['REQUEST_METHOD'] == 'POST') $reqLog .= "\n------------ POST:\n" . file_get_contents("php://input");
-		if (!empty($request)) $reqLog .= "\n------------ request: " . json_encode($request);
-		$reqLog .= "\n------------ END.";
-		$this->DBG($reqLog, $line);
-	}
-
-	private function DBG($reqLog, $line) {
-		$errorLogFile = APP_PATH_ROOT . "/wfs.log";
-		if (!is_writable($errorLogFile)) {
-			$fp = @fopen($errorLogFile, "w");
-			if ($fp === false) {
-				return;
-			}
-			@fclose($fp);
-		}
-		error_log("L.{$line}:{$reqLog}\n", 3, $errorLogFile);
-	}
+	public $_apiUser;
+	public $_apiBaseUri;
+	public $_dataSourceName;
+	public $_tblName;
+	public $_tblSchema;
 
 	public function execute($request) {
 
@@ -75,10 +53,10 @@ class Api_Wfs {
 		// return document tree - array of arrays
 	}
 
-	private function wfsServerAction($request) {
+	public function wfsServerAction($request) {
 	}
 
-	private function wfsExceptionAction($e) {
+	public function wfsExceptionAction($e) {
 		$dom = new DOMDocument('1.0', 'utf-8');
 		$dom->formatOutput = true;
 		$dom->preserveWhiteSpace = false;
@@ -94,7 +72,7 @@ class Api_Wfs {
 		return $dom->saveXML();
 	}
 
-	private function dataSourceAction($request) {
+	public function dataSourceAction($request) {
 		$document = '';
 		//$userAcl = User::getAcl();
 		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">user (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($this->_apiUser);echo'</pre>';}
@@ -104,7 +82,8 @@ class Api_Wfs {
 		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">$userAcl (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($userAcl);echo'</pre>';}
 
 		$this->DBG("WfsServer(" . $this->_apiUser->getID() . ") ...", __LINE__);
-		$wfsServer = new Api_WfsServer($userAcl);
+		$wfsServer = new Api_WfsDataServer($userAcl);
+		$wfsServer->setBaseUri($this->_apiBaseUri);
 		if ('WFS' != V::get('SERVICE', '', $request->query)) {
 			throw new Api_WfsException("Only WFS Service is allowed");
 		}
@@ -134,7 +113,7 @@ class Api_Wfs {
 		// TODO: return $document;
 	}
 
-	private function mainWpsAction($request) {
+	public function mainWpsAction($request) {
 		return array('TODO:'=>'TODO: Show main WPS GetCapabilities');
 	}
 

+ 244 - 0
SE/se-lib/Api/WfsDataServer.php

@@ -0,0 +1,244 @@
+<?php
+
+Lib::loadClass('Api_WfsServerBase');
+Lib::loadClass('Api_WfsException');
+Lib::loadClass('Api_WfsGeomTypeConverter');
+
+class Api_WfsDataServer extends Api_WfsServerBase {
+
+	public function parseXMLRequest() {
+		$data = array();
+		$reqContent = Request::getRequestBody();
+		if (empty($reqContent)) {
+			throw new Exception("Empty request");
+		}
+		$parserXml = xml_parser_create();
+		xml_parser_set_option($parserXml, XML_OPTION_CASE_FOLDING, 0);
+		xml_parser_set_option($parserXml, XML_OPTION_SKIP_WHITE, 1);
+		if (0 == xml_parse_into_struct($parserXml, $reqContent, $tags)) {
+			throw new Exception("Error parsing xml");
+		}
+		xml_parser_free($parserXml);
+		if (empty($tags)) {
+			throw new Exception("Empty structure from request");
+		}
+
+		$rootTagName = V::get('tag', '', $tags[0]);
+		if ('Transaction' == $rootTagName) {
+			return $this->_parseTransactionXmlStruct($reqContent, $tags);
+		}
+
+		throw new Api_WfsException("TODO ... L." . __LINE__, 501);
+
+		$xml = new SimpleXMLElement($reqContent);
+		$namespaces = $xml->getNameSpaces(true);
+
+		if ('Transaction' == $xml->getName()) {
+			$this->_parseTransactionXml($xml);
+		}
+		else {
+			throw new Api_WfsException("Not Implemented " . htmlspecialchars($xml->getName()), 501);
+		}
+	}
+
+	public function getFeatureAction() {
+		$type = V::get('TYPENAME', '', $_REQUEST);
+		$typeEx = explode(':', $type);
+		$maxFeatures = V::get('MAXFEATURES', '10000', $_REQUEST, 'int');// TODO: Set Deafult Limit
+		$ogcFilter = V::get('Filter', '', $_REQUEST);
+		$srsname = V::get('SRSNAME', '', $_REQUEST);// eg. EPSG:4326
+		if (count($typeEx) == 2) {
+			return $this->getFeatures($typeEx[0], $typeEx[1], $maxFeatures, $srsname, $ogcFilter);
+		} else {
+			throw new HttpException("Wrong param TYPENAME", 400);
+		}
+	}
+
+	public function getFeatures($nsPrefix, $type, $maxFeatures, $srsname, $ogcFilter = '') {
+		$DBG = (V::get('DBG_GEO', '', $_GET) > 0);// TODO: Profiler
+		$typeName = "{$nsPrefix}:{$type}";
+		$acl = $this->getAclFromTypeName($typeName);
+		$fldList = $acl->getRealFieldList();
+
+		$baseNsUri = $this->getBaseNamespaceUri();
+		$wfsNs = 'p5_default_db_' . $type;//$nsPrefix;
+		$wfsNsUri = "{$baseNsUri}/" . substr($nsPrefix, 3) . '/' . $type;
+
+		// get BBox from geom_field (only one geom fld is allowed)
+		$geomFld = null;
+		{
+			foreach ($fldList as $fldName) {
+				if ($acl->isGeomField($fldName)) {
+					$geomFld = $fldName;
+				}
+			}
+		}
+
+if($DBG){echo "ogcFilter(" . strlen($ogcFilter) . "): {$ogcFilter}\n";}
+		$searchParams = array();
+		$searchParams['limit'] = $maxFeatures;
+		$searchParams['order_by'] = $acl->getPrimaryKeyField();
+		$searchParams['order_dir'] = 'DESC';
+		if (strlen($ogcFilter) > 0) $searchParams['ogc:Filter'] = $ogcFilter;
+if($DBG){echo 'getItems:';print_r($searchParams);echo "\n";}
+		$items = $acl->getItems($searchParams);
+
+		$dom = new DOMDocument('1.0', 'utf-8');
+		$dom->formatOutput = true;
+		$dom->preserveWhiteSpace = false;
+		$rootNode = $dom->createElementNS('http://www.opengis.net/wfs', 'wfs:FeatureCollection');
+		$dom->appendChild($rootNode);
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.opengis.net/wfs');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:wfs', 'http://www.opengis.net/wfs');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $wfsNs, $wfsNsUri);
+		$rootNode->setAttribute('xsi:schemaLocation', 'http://www.opengis.net/wfs');// TODO: add DescribeFeatureType xsd uri
+
+if($DBG){echo '(geomFld: '.$geomFld.'):';print_r($acl->getFieldType($geomFld));echo "\n";}
+		if (empty($items)) {
+			$pKeyField = $acl->getPrimaryKeyField();
+			$fakeItem = new stdClass();
+			$fakeItem->{$pKeyField} = 0;
+			$items[0] = $fakeItem;
+		}
+		foreach ($items as $itemKey => $item) {
+
+if($DBG){echo 'item['.$itemKey.'] ('.$geomFld.')isEmpty('.empty($item->{$geomFld}).'):';print_r($item->{$geomFld});echo "\n";}
+
+			$featureMemberNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:featureMember');
+			$rootNode->appendChild($featureMemberNode);
+				$featureNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$type}");
+				$featureMemberNode->appendChild($featureNode);
+				$featureNode->setAttribute('fid', "{$type}.{$itemKey}");
+					foreach ($fldList as $fldName) {
+						$featureFldNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$fldName}");
+						if ($acl->isGeomField($fldName)) {
+							$geomNode = $this->_typeConverter->createGmlFromWkt($item->{$fldName}, $dom);
+							if (!$geomNode) continue;
+							$featureFldNode->appendChild($geomNode);
+						} else {
+							$featureFldNode->nodeValue = str_replace('&', '&amp;', $item->{$fldName});
+							if (empty($featureFldNode->nodeValue)) {
+								continue;
+							}
+						}
+						$featureNode->appendChild($featureFldNode);
+					}
+		}
+
+		return $dom->saveXml();
+	}
+
+	public function describeFeatureTypeAction() {
+		$type = V::get('TYPENAME', '', $_REQUEST);
+		if (empty($type)) {
+			throw new HttpException("Wrong param TYPENAME", 400);
+		}
+		$typeEx = explode(':', $type);
+		if (count($typeEx) != 2) {
+			throw new HttpException("Wrong param TYPENAME", 400);
+		}
+		return $this->getDescribeFeatureType($typeEx[0], $typeEx[1]);
+	}
+
+	public function getDescribeFeatureType($nsPrefix, $type) {
+		$typeName = "{$nsPrefix}:{$type}";
+		$acl = $this->getAclFromTypeName($typeName);
+
+		$baseNsUri = $this->getBaseNamespaceUri();
+		$wfsNs = 'p5_default_db_' . $type;//$nsPrefix;
+		$wfsNsUri = "{$baseNsUri}/" . substr($nsPrefix, 3) . '/' . $type;
+
+		if (empty($type)) {
+			throw new HttpException("Feature Type Name not defined", 400);
+		}
+		if (!$this->isAllowedFeatureType($nsPrefix, $type)) {
+			throw new Api_WfsException("Could not find type: " . htmlspecialchars($type));
+		}
+
+		$typeName = $type . 'Type';
+		$fldList = $acl->getRealFieldList();
+		header('Content-type: application/xml');
+		// <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="http://webgis.regione.sardegna.it:80/geoserver/schemas/gml/2.1.2/feature.xsd"/>
+		//	<xsd:element name="{type}" substitutionGroup="gml:_Feature" type="dbu:{typeName}"/>
+
+		$dom = new DOMDocument('1.0', 'utf-8');
+		$dom->formatOutput = true;
+		$dom->preserveWhiteSpace = false;
+		$rootNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:schema');
+		$dom->appendChild($rootNode);
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $wfsNs, $wfsNsUri);
+		$rootNode->setAttribute('elementFormDefault', 'qualified');
+		$rootNode->setAttribute('targetNamespace', $wfsNsUri);
+
+		$cTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexType');
+		$rootNode->appendChild($cTypeNode);
+		$cTypeNode->setAttribute('name', $typeName);
+
+		$cConNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexContent');
+		$cTypeNode->appendChild($cConNode);
+
+		$extNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:extension');
+		$cConNode->appendChild($extNode);
+		$extNode->setAttribute('base', 'gml:AbstractFeatureType');
+
+		$seqNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:sequence');
+		$extNode->appendChild($seqNode);
+
+		// <xsd:element maxOccurs="1" minOccurs="0" name="{$fldName}" nillable="true" type="xsd:integer"/>
+		$pKeyField = $acl->getPrimaryKeyField();
+		foreach ($fldList as $fldName) {
+			$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
+			$seqNode->appendChild($elNode);
+			$elNode->setAttribute('name', $fldName);
+			$minOccurs = 0;
+			if ($pKeyField == $fldName) {
+				$minOccurs = '1';
+			} else {
+				$minOccurs = '0';
+			}
+			$elNode->setAttribute('minOccurs', $minOccurs);
+			if ($acl->isIntegerField($fldName)) {
+				$fldType = 'xsd:integer';
+			}
+			else if ($acl->isDecimalField($fldName)) {
+				$fldType = 'xsd:decimal';
+			}
+			else if ($acl->isDateField($fldName)) {
+				$fldType = 'xsd:date';
+			}
+			else if ($acl->isDateTimeField($fldName)) {
+				$fldType = 'xsd:dateTime';
+			}
+			else if ($acl->isGeomField($fldName)) {
+				$fldType = 'gml:GeometryPropertyType';
+				//$fldType = 'gml:Polygon';// nie działa musi być gml:GeometryPropertyType
+			}
+			else {
+				$fldType = 'xsd:string';
+			}
+			$elNode->setAttribute('type', $fldType);
+			$elNode->setAttribute('nillable', 'true');
+		}
+
+		$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
+		$rootNode->appendChild($elNode);
+		$elNode->setAttribute('name', $type);
+		$elNode->setAttribute('type', $wfsNs . ':' . $typeName);
+
+		echo $dom->saveXML();
+	}
+
+	public function getCapabilitiesAction() {
+		$wfsServerUrl = $this->getBaseUri();
+		$serviceTitle = "Web Feature Service";
+		$serviceDescription = "This is the reference implementation of WFS 1.0.0 and WFS 1.1.0, supports all WFS operations including Transaction.";
+
+		//header('Content-type: application/xml; charset="utf-8"');
+		header('Content-type: application/xml');
+		$this->_getCapabilities($wfsServerUrl, $serviceTitle, $serviceDescription);
+	}
+
+}

+ 121 - 0
SE/se-lib/Api/WfsQgis.php

@@ -0,0 +1,121 @@
+<?php
+
+Lib::loadClass('ApiRouteBase');
+Lib::loadClass('ApiDataSourceTodo');// TODO: @see Entity/Source/Mysql from feature-schema-install
+Lib::loadClass('Api_WfsException');
+Lib::loadClass('Api_WfsQgisServer');
+Lib::loadClass('UserAcl');
+
+class Api_WfsQgis extends ApiRouteBase {// TODO: extends Api_WfsBase which extends ApiBase
+
+	public $_apiUser;
+	public $_apiBaseUri;
+	public $_dataSourceName;
+	public $_tblName;
+	public $_tblSchema;
+
+	public function execute($request) {
+
+		$this->reqDBG($request, __LINE__);
+
+		/* TODO: return response xml document
+		$responseDocument = null;
+		try {
+			$responseDocument = $this->wfsServerAction($request);
+		} catch (Api_WfsException $e) {// TODO: create WfsException - http://schemas.opengis.net/wfs/1.0.0/OGC-exception.xsd
+		//} catch (Exception $e) {// TODO: create WfsException - http://schemas.opengis.net/wfs/1.0.0/OGC-exception.xsd
+			$responseDocument = $this->wfsExceptionAction($request, $e);
+		}
+		return $responseDocument;
+		*/
+
+		if (empty($request->segments)) {
+			//$this->mainWpsAction($request);// show list of posible data source
+			throw new HttpException("Bad Request", 400);
+		} else {
+			$this->_dataSourceName = array_shift($request->segments);
+			$this->DBG("dataSourceAction({$this->_dataSourceName}) ...", __LINE__);
+			try {
+				$this->dataSourceAction($request);
+			} catch (Api_WfsException $e) {
+				$responseDocument = $this->wfsExceptionAction($e);
+				header('Content-type: application/xml');
+				echo $responseDocument;
+			} catch (Exception $e) {
+				$responseDocument = $this->wfsExceptionAction($e);
+				header('Content-type: application/xml');
+				echo $responseDocument;
+			}
+			$this->DBG("dataSourceAction() END", __LINE__);
+		}
+
+		exit;
+		// return document tree - array of arrays
+	}
+
+	public function wfsServerAction($request) {
+	}
+
+	public function wfsExceptionAction($e) {
+		$dom = new DOMDocument('1.0', 'utf-8');
+		$dom->formatOutput = true;
+		$dom->preserveWhiteSpace = false;
+		$rootNode = $dom->createElementNS('http://www.opengis.net/ogc', 'ServiceExceptionReport');
+		$dom->appendChild($rootNode);
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
+		$rootNode->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation', 'http://www.opengis.net/ogc http://schemas.opengis.net/wfs/1.0.0/OGC-exception.xsd');
+		$rootNode->setAttribute('version', '1.2.0');
+
+		$srvExNode = $dom->createElement('ServiceException', $e->getMessage());
+		$rootNode->appendChild($srvExNode);
+
+		return $dom->saveXML();
+	}
+
+	public function dataSourceAction($request) {
+		$document = '';
+		//$userAcl = User::getAcl();
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">user (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($this->_apiUser);echo'</pre>';}
+		$userAcl = new UserAcl($this->_apiUser->getID(), $use_cache = true);
+		$userAcl->fetchGroups();
+		$userAcl->fetchAllPerms(true);
+		DBG::_('DBG', '>2', 'userAcl', $userAcl, __CLASS__, __FUNCTION__, __LINE__);
+
+		$this->DBG("WfsServer(" . $this->_apiUser->getID() . ") ...", __LINE__);
+		$wfsServer = new Api_WfsQgisServer($userAcl);
+		$wfsServer->setBaseUri($this->_apiBaseUri);
+		DBG::_('DBG', true, 'getBaseNamespaceUri:', $wfsServer->getBaseNamespaceUri(), __CLASS__, __FUNCTION__, __LINE__);
+		if ('WFS' != V::get('SERVICE', '', $request->query)) {
+			throw new Api_WfsException("Only WFS Service is allowed");
+		}
+		$req = V::get('REQUEST', '', $request->query);
+		if (!empty($req)) {
+			$methodName = "{$req}Action";
+			if (!method_exists($wfsServer, $methodName)) {
+				throw new Api_WfsException("Not Implemented " . htmlspecialchars($req), 501);
+			}
+			$this->DBG("WfsServer->{$methodName}() ...", __LINE__);
+			$document = $wfsServer->$methodName($urlQuery);
+		}
+		else {
+			$this->DBG("WfsServer->parseXMLRequest() ...", __LINE__);
+			$document = $wfsServer->parseXMLRequest();
+
+			header('Content-type: application/xml');
+			echo '<?xml version="1.0" encoding="UTF-8"?>';
+			echo $document; exit;// TODO: return $document;
+		}
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">$document (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($document);echo'</pre>';}
+
+		header('Content-type: application/xml');
+		echo $document; exit;// TODO: return $document;
+
+		exit;
+		// TODO: return $document;
+	}
+
+	public function mainWpsAction($request) {
+		return array('TODO:'=>'TODO: Show main WPS GetCapabilities');
+	}
+
+}

+ 288 - 0
SE/se-lib/Api/WfsQgisServer.php

@@ -0,0 +1,288 @@
+<?php
+
+Lib::loadClass('Api_WfsServerBase');
+Lib::loadClass('Api_WfsException');
+Lib::loadClass('Api_WfsGeomTypeConverter');
+
+class Api_WfsQgisServer extends Api_WfsServerBase {
+
+	public function parseXMLRequest() {
+		$data = array();
+		$reqContent = Request::getRequestBody();
+		if (empty($reqContent)) {
+			throw new Exception("Empty request");
+		}
+		$parserXml = xml_parser_create();
+		xml_parser_set_option($parserXml, XML_OPTION_CASE_FOLDING, 0);
+		xml_parser_set_option($parserXml, XML_OPTION_SKIP_WHITE, 1);
+		if (0 == xml_parse_into_struct($parserXml, $reqContent, $tags)) {
+			throw new Exception("Error parsing xml");
+		}
+		xml_parser_free($parserXml);
+		if (empty($tags)) {
+			throw new Exception("Empty structure from request");
+		}
+
+		$rootTagName = V::get('tag', '', $tags[0]);
+		if ('Transaction' == $rootTagName) {
+			return $this->_parseTransactionXmlStruct($reqContent, $tags);
+		}
+
+		throw new Api_WfsException("TODO ... L." . __LINE__, 501);
+
+		$xml = new SimpleXMLElement($reqContent);
+		$namespaces = $xml->getNameSpaces(true);
+
+		if ('Transaction' == $xml->getName()) {
+			$this->_parseTransactionXml($xml);
+		}
+		else {
+			throw new Api_WfsException("Not Implemented " . htmlspecialchars($xml->getName()), 501);
+		}
+	}
+
+	public function getFeatureAction() {
+		$type = V::get('TYPENAME', '', $_REQUEST);
+		$typeEx = explode(':', $type);
+		$maxFeatures = V::get('MAXFEATURES', '10000', $_REQUEST, 'int');// TODO: Set Deafult Limit
+		$srsname = V::get('SRSNAME', '', $_REQUEST);// eg. EPSG:4326
+		if (count($typeEx) == 2) {
+			return $this->getFeatures($typeEx[0], $typeEx[1], $maxFeatures, $srsname);
+		} else {
+			throw new HttpException("Wrong param TYPENAME", 400);
+		}
+	}
+
+	public function getFeatures($nsPrefix, $type, $maxFeatures, $srsname) {
+		$DBG = (V::get('DBG_GEO', '', $_GET) > 0);// TODO: Profiler
+		$typeName = "{$nsPrefix}:{$type}";
+		$acl = $this->getAclFromTypeName($typeName);
+		$fldList = $acl->getRealFieldList();
+
+		$baseNsUri = $this->getBaseNamespaceUri();
+		$wfsNs = 'p5_default_db_' . $type;//$nsPrefix;
+		$wfsNsUri = "{$baseNsUri}/" . substr($nsPrefix, 3) . '/' . $type;
+
+		// get BBox from geom_field (only one geom fld is allowed)
+		$geomFld = null;
+		{
+			foreach ($fldList as $fldName) {
+				if ($acl->isGeomField($fldName)) {
+					$geomFld = $fldName;
+				}
+			}
+		}
+
+		$dbGeomType = $acl->getGeomFieldType($geomFld);
+
+		$searchParams = array();
+		$searchParams['limit'] = $maxFeatures;
+		$searchParams['order_by'] = $acl->getPrimaryKeyField();
+		$searchParams['order_dir'] = 'DESC';
+		if ($geomFld) $searchParams["f_{$geomFld}"] = 'IS NOT NULL';
+		if ($geomFld) $searchParams["f_{$geomFld}"] = 'GeometryType=' . strtoupper($dbGeomType);
+		//if ($geomFld) $searchParams["f_{$geomFld}"] = 'GeometryType=LINESTRING';
+if($DBG){echo 'getItems:';print_r($searchParams);echo "\n";}
+		$items = $acl->getItems($searchParams);
+
+		$dom = new DOMDocument('1.0', 'utf-8');
+		$dom->formatOutput = true;
+		$dom->preserveWhiteSpace = false;
+		$rootNode = $dom->createElementNS('http://www.opengis.net/wfs', 'wfs:FeatureCollection');
+		$dom->appendChild($rootNode);
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.opengis.net/wfs');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:wfs', 'http://www.opengis.net/wfs');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $wfsNs, $wfsNsUri);
+		$rootNode->setAttribute('xsi:schemaLocation', 'http://www.opengis.net/wfs');// TODO: add DescribeFeatureType xsd uri
+
+if(0){// TODO: get BBOX for add features
+			$boundedByNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:boundedBy');
+			$rootNode->appendChild($boundedByNode);
+				$boxNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:Box');
+				$boundedByNode->appendChild($boxNode);
+				$boxNode->setAttribute('srsName', "http://www.opengis.net/gml/srs/epsg.xml#4326");// TODO: EPSG
+					$coordinatesNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:coordinates');
+					$boxNode->appendChild($coordinatesNode);
+					$coordinatesNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
+					$coordinatesNode->setAttribute('decimal', '.');
+					$coordinatesNode->setAttribute('cs', ',');
+					$coordinatesNode->setAttribute('ts', ' ');
+					$coordinatesNode->nodeValue = '1544947.6295,4322758.105 1548002.2259,4330464.1001';// TODO: coordinates for all items?
+}
+
+if($DBG){echo '(geomFld: '.$geomFld.'):';print_r($acl->getFieldType($geomFld));echo "\n";}
+		if (empty($items)) {
+			$pKeyField = $acl->getPrimaryKeyField();
+			$fakeItem = new stdClass();
+			$fakeItem->{$pKeyField} = 0;
+			if ('polygon' == $dbGeomType) {
+				$fakeItem->the_geom = "POLYGON(())";
+			} else if ('linestring' == $dbGeomType) {
+				$fakeItem->the_geom = "LINESTRING()";
+			} else if ('point' == $dbGeomType) {
+				$fakeItem->the_geom = "POINT(0,0)";
+			}
+			$items[0] = $fakeItem;
+		}
+		foreach ($items as $itemKey => $item) {
+			//if($item->ID == 19)continue;
+
+if($DBG){echo 'item['.$itemKey.'] ('.$geomFld.')isEmpty('.empty($item->{$geomFld}).'):';print_r($item->{$geomFld});echo "\n";}
+			if ($geomFld) {
+				if (empty($item->{$geomFld})) {
+					continue;// QGIS crash when WFS contain features with empty geom field
+				}
+			}
+
+			$featureMemberNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:featureMember');
+			$rootNode->appendChild($featureMemberNode);
+				$featureNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$type}");
+				$featureMemberNode->appendChild($featureNode);
+				$featureNode->setAttribute('fid', "{$type}.{$itemKey}");
+if(0){// TODO: get BBOX
+					$boundedByNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:boundedBy');
+					$featureNode->appendChild($boundedByNode);
+						$boxNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:Box');
+						$boundedByNode->appendChild($boxNode);
+						$boxNode->setAttribute('srsName', "http://www.opengis.net/gml/srs/epsg.xml#4326");// TODO: EPSG
+							$coordinatesNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:coordinates');
+							$boxNode->appendChild($coordinatesNode);
+							$coordinatesNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
+							$coordinatesNode->setAttribute('decimal', '.');
+							$coordinatesNode->setAttribute('cs', ',');
+							$coordinatesNode->setAttribute('ts', ' ');
+							$coordinatesNode->nodeValue = '1546472.2363,4328949.5775 1548002.2259,4330464.1001';// TODO: coordinates for item?
+}
+					foreach ($fldList as $fldName) {
+						$featureFldNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$fldName}");
+						if ($acl->isGeomField($fldName)) {
+							$geomNode = $this->_typeConverter->createGmlFromWkt($item->{$fldName}, $dom);
+							if (!$geomNode) continue;
+							$featureFldNode->appendChild($geomNode);
+						} else {
+							$featureFldNode->nodeValue = str_replace('&', '&amp;', $item->{$fldName});
+							if (empty($featureFldNode->nodeValue)) {
+								continue;
+							}
+						}
+						$featureNode->appendChild($featureFldNode);
+					}
+		}
+
+		return $dom->saveXml();
+	}
+
+	public function describeFeatureTypeAction() {
+		$type = V::get('TYPENAME', '', $_REQUEST);
+		if (empty($type)) {
+			throw new HttpException("Wrong param TYPENAME", 400);
+		}
+		$typeEx = explode(':', $type);
+		if (count($typeEx) != 2) {
+			throw new HttpException("Wrong param TYPENAME", 400);
+		}
+		return $this->getDescribeFeatureType($typeEx[0], $typeEx[1]);
+	}
+
+	public function getDescribeFeatureType($nsPrefix, $type) {
+		$typeName = "{$nsPrefix}:{$type}";
+		$acl = $this->getAclFromTypeName($typeName);
+
+		$baseNsUri = $this->getBaseNamespaceUri();
+		$wfsNs = 'p5_default_db_' . $type;//$nsPrefix;
+		$wfsNsUri = "{$baseNsUri}/" . substr($nsPrefix, 3) . '/' . $type;
+
+		if (empty($type)) {
+			throw new HttpException("Feature Type Name not defined", 400);
+		}
+		if (!$this->isAllowedFeatureType($nsPrefix, $type)) {
+			throw new Api_WfsException("Could not find type: " . htmlspecialchars($type));
+		}
+
+		$typeName = $type . 'Type';
+		$fldList = $acl->getRealFieldList();
+		header('Content-type: application/xml');
+		// <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="http://webgis.regione.sardegna.it:80/geoserver/schemas/gml/2.1.2/feature.xsd"/>
+		//	<xsd:element name="{type}" substitutionGroup="gml:_Feature" type="dbu:{typeName}"/>
+
+		$dom = new DOMDocument('1.0', 'utf-8');
+		$dom->formatOutput = true;
+		$dom->preserveWhiteSpace = false;
+		$rootNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:schema');
+		$dom->appendChild($rootNode);
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $wfsNs, $wfsNsUri);
+		$rootNode->setAttribute('elementFormDefault', 'qualified');
+		$rootNode->setAttribute('targetNamespace', $wfsNsUri);
+
+		$cTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexType');
+		$rootNode->appendChild($cTypeNode);
+		$cTypeNode->setAttribute('name', $typeName);
+
+		$cConNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexContent');
+		$cTypeNode->appendChild($cConNode);
+
+		$extNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:extension');
+		$cConNode->appendChild($extNode);
+		$extNode->setAttribute('base', 'gml:AbstractFeatureType');
+
+		$seqNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:sequence');
+		$extNode->appendChild($seqNode);
+
+		// <xsd:element maxOccurs="1" minOccurs="0" name="{$fldName}" nillable="true" type="xsd:integer"/>
+		$pKeyField = $acl->getPrimaryKeyField();
+		foreach ($fldList as $fldName) {
+			$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
+			$seqNode->appendChild($elNode);
+			$elNode->setAttribute('name', $fldName);
+			$minOccurs = 0;
+			if ($pKeyField == $fldName) {
+				$minOccurs = '1';
+			} else {
+				$minOccurs = '0';
+			}
+			$elNode->setAttribute('minOccurs', $minOccurs);
+			if ($acl->isIntegerField($fldName)) {
+				$fldType = 'xsd:integer';
+			}
+			else if ($acl->isDecimalField($fldName)) {
+				$fldType = 'xsd:decimal';
+			}
+			else if ($acl->isDateField($fldName)) {
+				$fldType = 'xsd:date';
+			}
+			else if ($acl->isDateTimeField($fldName)) {
+				$fldType = 'xsd:dateTime';
+			}
+			else if ($acl->isGeomField($fldName)) {
+				$fldType = 'gml:GeometryPropertyType';
+				//$fldType = 'gml:Polygon';// nie działa musi być gml:GeometryPropertyType
+			}
+			else {
+				$fldType = 'xsd:string';
+			}
+			$elNode->setAttribute('type', $fldType);
+			$elNode->setAttribute('nillable', 'true');
+		}
+
+		$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
+		$rootNode->appendChild($elNode);
+		$elNode->setAttribute('name', $type);
+		$elNode->setAttribute('type', $wfsNs . ':' . $typeName);
+
+		echo $dom->saveXML();
+	}
+
+	public function getCapabilitiesAction() {
+		$wfsServerUrl = $this->getBaseUri();
+		$serviceTitle = "Web Feature Service for QGIS";
+		$serviceDescription = "This is the reference implementation of WFS 1.0.0 and WFS 1.1.0, supports all WFS operations including Transaction.";
+
+		//header('Content-type: application/xml; charset="utf-8"');
+		header('Content-type: application/xml');
+		$this->_getCapabilities($wfsServerUrl, $serviceTitle, $serviceDescription);
+	}
+
+}

Файловите разлики са ограничени, защото са твърде много
+ 57 - 1101
SE/se-lib/Api/WfsServerBase.php


+ 36 - 0
SE/se-lib/ApiRouteBase.php

@@ -0,0 +1,36 @@
+<?php
+
+class ApiRouteBase {
+
+	public $_apiUser;
+	public $_apiBaseUri;
+
+	public function setUser($user) {
+		$this->_apiUser = $user;
+	}
+
+	public function setBaseUri($uri) {
+		$this->_apiBaseUri = $uri;
+	}
+
+	public function reqDBG($request, $line) {
+		$reqLog = "[" . date("Y-m-d H:m:s") . "] WFS: ---- {$_SERVER['REQUEST_METHOD']}: {$_SERVER['REQUEST_URI']}";
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') $reqLog .= "\n------------ POST:\n" . Request::getRequestBody();
+		if (!empty($request)) $reqLog .= "\n------------ request: " . json_encode($request);
+		$reqLog .= "\n------------ END.";
+		$this->DBG($reqLog, $line);
+	}
+
+	public function DBG($reqLog, $line) {
+		$errorLogFile = APP_PATH_ROOT . "/wfs.log";
+		if (!is_writable($errorLogFile)) {
+			$fp = @fopen($errorLogFile, "w");
+			if ($fp === false) {
+				return;
+			}
+			@fclose($fp);
+		}
+		error_log("L.{$line}:{$reqLog}\n", 3, $errorLogFile);
+	}
+
+}

+ 4 - 5
SE/se-lib/Data_Source.php

@@ -576,14 +576,13 @@ XSL_CONVERT_OGC_FILTER_TO_XML_TASK_LIST;
 					$sql_where_and[] = "t.`{$fldName}`='{$v}'";
 				}
 				else {
-					$searchWords = explode(' ', $v);
+					$queryWhereBuilder = new SqlQueryWhereBuilder();
+					$searchWords = $queryWhereBuilder->splitQueryToWords($v);
 					$sqlWhereWords = array();
 					if (!empty($searchWords)) {
 						foreach ($searchWords as $word) {
-							if (!empty($word)) {
-								$word = $this->_db->_($word);
-								$sqlWhereWords[] = "t.`{$fldName}` like '%{$word}%'";
-							}
+							$sqlWord = $this->_db->_($word);
+							$sqlWhereWords[] = "t.`{$fldName}` like '%{$sqlWord}%'";
 						}
 					}
 					if (!empty($searchWords)) {

+ 68 - 0
SE/se-lib/Request.php

@@ -0,0 +1,68 @@
+<?php
+
+class Request {
+
+	// @usage: Request::isHttps();
+	public static function isHttps() {
+		// method for previous apache: !empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on'
+		// [forwarded] => 1
+		// [HTTP_X_FORWARDED_PROTO] => https
+    // [HTTP_X_FORWARDED_PORT] => 443
+		if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO']) {
+			return true;
+		} else if (!empty($_SERVER['HTTPS']) && 'on' == $_SERVER['HTTPS']) {
+			return true;
+		}
+		return false;
+	}
+
+	// @usage: Request::getScriptUri();
+	public static function getScriptUri() {
+		// [SCRIPT_URI] => http://biuro.biall-net.pl:34543/dev-pl/se-master/wfs-qgis.php/default_db/
+		// [SCRIPT_URL] => /dev-pl/se-master/wfs-qgis.php/default_db/
+		// [SCRIPT_NAME] => /dev-pl/se-master/wfs-qgis.php
+		// [HTTP_HOST] => biuro.biall-net.pl
+		$uri = (Request::isHttps())? 'https://' : 'http://';
+		$uri .= "{$_SERVER['HTTP_HOST']}{$_SERVER['SCRIPT_URL']}";
+		return $uri;
+	}
+
+	// @usage: Request::getPathUri();
+	public static function getPathUri() {
+		// [SCRIPT_URI] => http://biuro.biall-net.pl:34543/dev-pl/se-master/wfs-qgis.php/default_db/
+		// [SCRIPT_URL] => /dev-pl/se-master/wfs-qgis.php/default_db/
+		// [SCRIPT_NAME] => /dev-pl/se-master/wfs-qgis.php
+		// [HTTP_HOST] => biuro.biall-net.pl
+		$uri = (Request::isHttps())? 'https://' : 'http://';
+		$uri .= $_SERVER['HTTP_HOST'];
+		$scriptPath = '';
+		$scriptName = $_SERVER['SCRIPT_NAME'];
+		if ('/' == substr($scriptName, -1)) {
+			$scriptPath = $scriptName;
+		} else {
+			$scriptPathEx = explode('/', $scriptName);
+			array_pop($scriptPathEx);
+			$scriptPath = implode('/', $scriptPathEx) . '/';
+		}
+		$uri .= $scriptPath;
+		return $uri;
+	}
+
+	// @usage: Request::getRewriteTaskPath();
+	public static function getRewriteTaskPath() {
+		$reqUri = $_SERVER['REQUEST_URI'];
+		$reqScript = $_SERVER['SCRIPT_NAME'];
+		$taskPath = str_replace($reqScript, '', $reqUri);
+		return $taskPath;
+	}
+
+	// @usage: Request::getRequestBody();
+	public static function getRequestBody() {
+		static $requestBody = null;
+		if (null === $requestBody) {
+			$requestBody = file_get_contents("php://input");
+		}
+		return $requestBody;
+	}
+
+}

+ 13 - 0
SE/se-lib/SqlQueryWhereBuilder.php

@@ -109,4 +109,17 @@ class SqlQueryWhereBuilder {
 		return false;
 	}
 
+	public function splitQueryToWords($q) {
+		$searchWords = explode(' ', $q);
+		$sqlSearchWords = array();
+		if (!empty($searchWords)) {
+			foreach ($searchWords as $word) {
+				if (!empty($word)) {
+					$sqlSearchWords[] = $word;
+				}
+			}
+		}
+		return $sqlSearchWords;
+	}
+
 }

+ 1 - 1
SE/se-lib/TableAjaxMap.php

@@ -1542,7 +1542,7 @@ class TableAjaxMapWpsServer {
 
 	public function parseXMLRequest() {
 		$data = array();
-		$reqContent = file_get_contents('php://input');
+		$reqContent = Request::getRequestBody();
 		$xml = new SimpleXMLElement($reqContent);
 
 		if ('GetFeature' == $xml->getName()) {

+ 51 - 28
SE/se-lib/TypespecialVariable.php

@@ -1,6 +1,7 @@
 <?php
 
 Lib::loadClass('TypespecialBase');
+Lib::loadClass('SqlQueryWhereBuilder');
 
 class TypespecialVariable extends TypespecialBase {
 
@@ -508,48 +509,70 @@ jQuery(document).ready(function(){
 			}
 			case '__ZASOB': {
 				$db = DB::getDB();
-				$query = trim($query, ' %');
-				$query = $db->_($query);
-				$sqlLimit = 20;
-				$sqlSelectLabel = "concat(z.`TYPE`, ' ', z.`DESC`)";
-				$sqlWhere = "";
+				$sqlQuery = new stdClass();
+				$sqlQuery->limit = 20;
+				$sqlQuery->orderBy = "";
+				$sqlQuery->selectLabel = "concat(z.`TYPE`, ' ', z.`DESC`)";
+				$sqlQuery->selectAddBestFit = "";
+				$sqlQuery->whereAddQueryByWords = "";
+
+				$sqlWhereAddType = "";
 				if (!empty($params['zasob_type_in'])) {
 					if (is_scalar($params['zasob_type_in'])) $params['zasob_type_in'] = array($params['zasob_type_in']);
-					$sqlWhere = " and z.`TYPE` IN('" . implode("','", $params['zasob_type_in']) . "') ";
+					$sqlWhereAddType = " and z.`TYPE` IN('" . implode("','", $params['zasob_type_in']) . "') ";
 
 					if (in_array('KOMORKA', $params['zasob_type_in'])) {
-						$sqlSelectLabel = "concat(z.`TYPE`, ' ', z.`DESC` , ' (', (select zp.`DESC` from `CRM_LISTA_ZASOBOW` as zp where zp.`ID`=z.`PARENT_ID` limit 1), ')')";
+						$sqlQuery->selectLabel = "concat(z.`TYPE`, ' ', z.`DESC` , ' (', (select zp.`DESC` from `CRM_LISTA_ZASOBOW` as zp where zp.`ID`=z.`PARENT_ID` limit 1), ')')";
 					}
 				}
+				$query = trim($query, ' %');
+				$sqlQuery->_queryByWords = array();
 				if (is_numeric($query)) {
-					$sql = "select z.`ID`
-							, {$sqlSelectLabel} as `LABEL`
-							, IF (z.`ID`='{$query}', 1000,
-							      IF (z.`ID` like '{$query}%', 900, 100)
-							     ) as _bestFit
-						from `CRM_LISTA_ZASOBOW` as z
-						where z.`A_STATUS` in('NORMAL', 'WAITING')
-							and (z.`ID` like '%{$query}%' or z.`DESC` like '%{$query}%')
-							{$sqlWhere}
-						order by _bestFit DESC
-						limit {$sqlLimit}
+					$sqlQueryNum = intval($query);
+					$sqlQuery->_queryByWords[] = "z.`ID` like '%{$sqlQueryNum}%'";
+					$sqlQuery->selectAddBestFit = "
+						, IF (z.`ID`='{$sqlQueryNum}', 1000,
+							IF (z.`ID` like '{$sqlQueryNum}%', 900, 100)
+						) as _bestFit
 					";
+					$sqlQuery->orderBy = "order by _bestFit DESC";
 				} else {
-					$sql = "select z.`ID`
-							, {$sqlSelectLabel} as `LABEL`
-						from `CRM_LISTA_ZASOBOW` as z
-						where z.`A_STATUS` in('NORMAL', 'WAITING')
-							and (z.`ID` like '%{$query}%' or z.`DESC` like '%{$query}%')
-							{$sqlWhere}
-						limit {$sqlLimit}
-					";
+					$queryWhereBuilder = new SqlQueryWhereBuilder();
+					$searchWords = $queryWhereBuilder->splitQueryToWords($query);
+					DBG::_('DBG_TS', '>2', "SqlQueryWhereBuilder->splitQueryToWords({$query})", $searchWords, __CLASS__, __FUNCTION__, __LINE__);
+					$sqlWords = array();
+					if (!empty($searchWords)) {
+						foreach ($searchWords as $word) {
+							if (is_numeric($word)) {
+								$sqlWord = intval($word);
+								$sqlQuery->_queryByWords[] = " ( z.`ID` like '%{$sqlWord}%' or z.`DESC` like '%{$sqlWord}%' ) ";
+							} else {
+								$sqlWord = $db->_($word);
+								$sqlQuery->_queryByWords[] = "z.`DESC` like '%{$sqlWord}%'";
+							}
+						}
+					}
 				}
-				if(V::get('DBG_TS', 0, $_GET) > 2){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">sql (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($sql);echo'</pre>';}
+				if (!empty($sqlQuery->_queryByWords)) {
+					$sqlQuery->whereAddQueryByWords = " and (" . implode(" and ", $sqlQuery->_queryByWords) . ")";
+				}
+
+				$sql = "select z.`ID`
+						, {$sqlQuery->selectLabel} as `LABEL`
+						{$sqlQuery->selectAddBestFit}
+					from `CRM_LISTA_ZASOBOW` as z
+					where z.`A_STATUS` in('NORMAL', 'WAITING')
+						{$sqlQuery->whereAddQueryByWords}
+						{$sqlWhereAddType}
+					{$sqlQuery->orderBy}
+					limit {$sqlQuery->limit}
+				";
+				DBG::_('DBG_TS', '>2', "sql", $sql, __CLASS__, __FUNCTION__, __LINE__);
 				$res = $db->query($sql);
 				while ($r = $db->fetch($res)) {
 					$values[] = (object)array('id'=>$r->ID, 'param_out'=>$r->LABEL);
 				}
-				if(V::get('DBG_TS', 0, $_GET) > 2){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">values (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($values);echo'</pre>';}
+				DBG::_('DBG_TS', '>2', "values", $values, __CLASS__, __FUNCTION__, __LINE__);
 				break;
 			}
 			case '__PROCES': {

+ 1 - 0
SE/se-lib/bootstrap.php

@@ -20,3 +20,4 @@ Lib::loadClass('Http');
 Lib::loadClass('HttpException');
 Lib::loadClass('StorageException');
 Lib::loadClass('Router');
+Lib::loadClass('Request');

+ 2 - 2
SE/superedit-OPEN_LAYERS_WPS.php

@@ -112,7 +112,7 @@ SQL;
 	
 
 //$_POST['url'] = 'http://demo.opengeo.org/geoserver/wfs';
-//$entityBody = file_get_contents('php://input');
+//$entityBody = Request::getRequestBody();
 	$url = V::get('_url', '', $_GET);
 	if ($url) {// @see OpenLayers/examples/proxy.cgi
 		$allowedHosts = array('www.openlayers.org', 'openlayers.org', 
@@ -947,7 +947,7 @@ class WpsServer {
 
 	public function parseXMLRequest() {
 		$data = array();
-		$reqContent = file_get_contents('php://input');
+		$reqContent = Request::getRequestBody();
 		$xml = new SimpleXMLElement($reqContent);
 
 		if ('GetFeature' == $xml->getName()) {

+ 2 - 9
SE/superedit-PROCES_MENU.php

@@ -103,10 +103,7 @@ function PROCES_MENU() {
 			$tblId = V::get('tblId', 0, $_REQUEST, 'int');
 			$tableProcesInitIds = ACL::getTableProcesInitIds($tblId);
 			$tableProcesIdsCSV = implode(",", $tableProcesInitIds);
-			$url = $_SERVER['SCRIPT_URI'];
-			$url = substr($url, 0, strrpos($url, '/'));
-			$url .= "/procesy5.php?task=CRM_PROCES&filtr_id={$tableProcesIdsCSV}&filtr_ids=%2B&filtr_ob=%2B&filtr_img=%2B";
-			//echo $url; exit;
+			$url = Request::getPathUri() . "procesy5.php?task=CRM_PROCES&filtr_id={$tableProcesIdsCSV}&filtr_ids=%2B&filtr_ob=%2B&filtr_img=%2B";
 			if (!headers_sent()) {
 				header('HTTP/1.1 303 See Other');
 				header('Location: '.$url);
@@ -127,12 +124,8 @@ function PROCES_MENU() {
 			// 							<a href="procesy5.php?task=CRM_PROCES echo "&filtr_id={$userProcesIdsCSV}&filtr_ids=%2B&filtr_ob=%2B&filtr_img=%2B";  ">Moje Procesy</a>
 			$userAcl = User::getAcl();
 			$usedProcesInitIds = $userAcl->getUserProcesInitIds();
-			//print_r($usedProcesInitIds);
 			$userProcesIdsCSV = implode(",", $usedProcesInitIds);
-			$url = $_SERVER['SCRIPT_URI'];
-			$url = substr($url, 0, strrpos($url, '/'));
-			$url .= "/procesy5.php?task=CRM_PROCES&filtr_id={$userProcesIdsCSV}&filtr_ids=%2B&filtr_ob=%2B&filtr_img=%2B";
-			//echo $url; exit;
+			$url = Request::getPathUri() . "procesy5.php?task=CRM_PROCES&filtr_id={$userProcesIdsCSV}&filtr_ids=%2B&filtr_ob=%2B&filtr_img=%2B";
 			if (!headers_sent()) {
 				header('HTTP/1.1 303 See Other');
 				header('Location: '.$url);

+ 62 - 0
SE/wfs-data.php

@@ -0,0 +1,62 @@
+<?php
+
+// Api for QGIS moved to wfs-qgis.php
+
+require_once dirname(__FILE__) . '/se-lib/bootstrap.php';
+
+if (!Request::isHttps()) {
+	header("Location: https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
+	exit();
+}
+
+date_default_timezone_set('Europe/Warsaw');// PHP 5 >= 5.1.0 required by date functions
+
+$errorReportingLevel = E_ALL & ~E_NOTICE;
+error_reporting($errorReportingLevel);
+ini_set('error_reporting', $errorReportingLevel);
+
+if (file_exists(APP_PATH_ROOT . "/config/.config_{$_SERVER['SERVER_NAME']}.php")) {
+	require APP_PATH_ROOT . "/config/.config_{$_SERVER['SERVER_NAME']}.php";
+}
+if (file_exists(APP_PATH_ROOT . "/.config.php")) include APP_PATH_ROOT . "/.config.php";
+
+require_once APP_PATH_ROOT . "/superedit-SEF.php";
+SEF('DEBUG_S');
+
+Lib::loadClass('ApiUser');
+Lib::loadClass('Api');
+
+session_start();
+session_write_close();
+
+$apiUser = new ApiUser();
+// ?LOGIN=LOGOUT
+if ('LOGOUT' == V::get('LOGIN', '', $_GET)) {
+	$apiUser->logout();
+} else {
+	$apiUser->auth();
+}
+
+set_time_limit(5 * 60);
+
+$taskPath = Request::getRewriteTaskPath();
+$taskPath = "/xml/wfsData{$taskPath}";
+IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">taskPath (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($taskPath);echo'</pre>';}
+
+$api = new Api();
+$api->setUser($apiUser);
+$apiBaseUri = Request::getScriptUri();
+$api->setBaseUri($apiBaseUri);
+try {
+	$api->execute($taskPath);
+}
+catch (HttpException $e) {
+	Http::sendHeaderByCode($e->getCode());
+	echo $e->getMessage();
+}
+catch (Exception $e) {
+	Http::sendHeaderByCode(500);
+	echo $e->getMessage();
+}
+
+?>

+ 62 - 0
SE/wfs-qgis.php

@@ -0,0 +1,62 @@
+<?php
+
+// Api for QGIS moved to wfs-qgis.php
+
+require_once dirname(__FILE__) . '/se-lib/bootstrap.php';
+
+if (!Request::isHttps()) {
+	header("Location: https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
+	exit();
+}
+
+date_default_timezone_set('Europe/Warsaw');// PHP 5 >= 5.1.0 required by date functions
+
+$errorReportingLevel = E_ALL & ~E_NOTICE;
+error_reporting($errorReportingLevel);
+ini_set('error_reporting', $errorReportingLevel);
+
+if (file_exists(APP_PATH_ROOT . "/config/.config_{$_SERVER['SERVER_NAME']}.php")) {
+	require APP_PATH_ROOT . "/config/.config_{$_SERVER['SERVER_NAME']}.php";
+}
+if (file_exists(APP_PATH_ROOT . "/.config.php")) include APP_PATH_ROOT . "/.config.php";
+
+require_once APP_PATH_ROOT . "/superedit-SEF.php";
+SEF('DEBUG_S');
+
+Lib::loadClass('ApiUser');
+Lib::loadClass('Api');
+
+session_start();
+session_write_close();
+
+$apiUser = new ApiUser();
+// ?LOGIN=LOGOUT
+if ('LOGOUT' == V::get('LOGIN', '', $_GET)) {
+	$apiUser->logout();
+} else {
+	$apiUser->auth();
+}
+
+set_time_limit(5 * 60);
+
+$taskPath = Request::getRewriteTaskPath();
+$taskPath = "/xml/wfsQgis{$taskPath}";
+IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">taskPath (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($taskPath);echo'</pre>';}
+
+$api = new Api();
+$api->setUser($apiUser);
+$apiBaseUri = Request::getScriptUri();
+$api->setBaseUri($apiBaseUri);
+try {
+	$api->execute($taskPath);
+}
+catch (HttpException $e) {
+	Http::sendHeaderByCode($e->getCode());
+	echo $e->getMessage();
+}
+catch (Exception $e) {
+	Http::sendHeaderByCode(500);
+	echo $e->getMessage();
+}
+
+?>

+ 9 - 11
SE/wfs.php

@@ -4,13 +4,13 @@
 	?SERVICE=WFS&REQUEST=GetCapabilities&VERSION=1.0.0
  */
 
-if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on') {
+require_once dirname(__FILE__) . '/se-lib/bootstrap.php';
+
+if (!Request::isHttps()) {
 	header("Location: https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
 	exit();
 }
 
-require_once dirname(__FILE__) . '/se-lib/bootstrap.php';
-
 date_default_timezone_set('Europe/Warsaw');// PHP 5 >= 5.1.0 required by date functions
 
 $errorReportingLevel = E_ALL & ~E_NOTICE;
@@ -41,13 +41,16 @@ if ('LOGOUT' == V::get('LOGIN', '', $_GET)) {
 
 set_time_limit(5 * 60);
 
-$reqUri = V::get('REQUEST_URI', '', $_SERVER);
-$reqScript = V::get('SCRIPT_NAME', '', $_SERVER);
-$taskPath = str_replace($reqScript, '', $reqUri);
+$taskPath = Request::getRewriteTaskPath();
 IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">taskPath (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($taskPath);echo'</pre>';}
+if ('/xml/wfs' == substr($taskPath, 0, 8)) {
+	$taskPath = "/xml/wfsQgis/" . substr($taskPath, 9);
+}
 
 $api = new Api();
 $api->setUser($apiUser);
+$apiBaseUri = Request::getScriptUri();
+$api->setBaseUri($apiBaseUri);
 try {
 	$api->execute($taskPath);
 }
@@ -60,9 +63,4 @@ catch (Exception $e) {
 	echo $e->getMessage();
 }
 
-IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">PHP_AUTH_USER (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($_SERVER['PHP_AUTH_USER']);echo'</pre>';}
-IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">REQUEST_URI (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($_SERVER['REQUEST_URI']);echo'</pre>';}
-IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">SCRIPT_NAME (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($_SERVER['SCRIPT_NAME']);echo'</pre>';}
-IF(V::get('DBG','',$_GET)){die("\nEOF L." . __LINE__);}
-
 ?>

Някои файлове не бяха показани, защото твърде много файлове са промени