0010816: Plugins for request dispatcher
authorFlávio Gomes da Silva Lisboa <flavio.lisboa@serpro.gov.br>
Mon, 9 Feb 2015 18:05:17 +0000 (16:05 -0200)
committerLars Kneschke <l.kneschke@metaways.de>
Mon, 20 Apr 2015 11:37:36 +0000 (13:37 +0200)
- Decoupled specific server classes from Tinebase
- Created interface for dispatch plugins
- Added dispatch plugins tests

Change-Id: I57c467566c7472807d4ff1e7dd8e9142d5d5a09b
Reviewed-on: https://gerrit.tine20.org/tine20/3069
Tested-by: jenkins user
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
Reviewed-by: Flávio Gomes da Silva Lisboa <flavio.lisboa@serpro.gov.br>
Reviewed-by: Lars Kneschke <l.kneschke@metaways.de>
24 files changed:
tests/tine20/ActiveSync/AllTests.php
tests/tine20/ActiveSync/Server/PluginTests.php [new file with mode: 0644]
tests/tine20/Tinebase/AllTests.php
tests/tine20/Tinebase/Server/AllServerTests.php [new file with mode: 0644]
tests/tine20/Tinebase/Server/AllTests.php [new file with mode: 0644]
tests/tine20/Tinebase/Server/Plugin/AllTests.php [new file with mode: 0644]
tests/tine20/Tinebase/Server/Plugin/HttpTests.php [new file with mode: 0644]
tests/tine20/Tinebase/Server/Plugin/JsonTests.php [new file with mode: 0644]
tests/tine20/Tinebase/Server/Plugin/WebDAVTests.php [new file with mode: 0644]
tests/tine20/Voipmanager/AllTests.php
tests/tine20/Voipmanager/Server/PluginTests.php [new file with mode: 0644]
tine20/ActiveSync/Config.php
tine20/ActiveSync/Server/Plugin.php [new file with mode: 0644]
tine20/Setup/Core.php
tine20/Tinebase/Config.php
tine20/Tinebase/Config/Abstract.php
tine20/Tinebase/Core.php
tine20/Tinebase/Server/Plugin/Cli.php [new file with mode: 0644]
tine20/Tinebase/Server/Plugin/Http.php [new file with mode: 0644]
tine20/Tinebase/Server/Plugin/Interface.php [new file with mode: 0644]
tine20/Tinebase/Server/Plugin/Json.php [new file with mode: 0644]
tine20/Tinebase/Server/Plugin/WebDAV.php [new file with mode: 0644]
tine20/Voipmanager/Config.php [new file with mode: 0644]
tine20/Voipmanager/Server/Plugin.php [new file with mode: 0644]

index 2a6bcac..f4893b0 100755 (executable)
@@ -29,8 +29,8 @@ class ActiveSync_AllTests
         $suite->addTest(ActiveSync_Backend_AllTests::suite());
         
         $suite->addTestSuite('ActiveSync_TimezoneConverterTest');
-        
         $suite->addTestSuite('ActiveSync_Frontend_JsonTests');
+        $suite->addTestSuite('ActiveSync_Server_PluginTests');
         
         return $suite;
     }
diff --git a/tests/tine20/ActiveSync/Server/PluginTests.php b/tests/tine20/ActiveSync/Server/PluginTests.php
new file mode 100644 (file)
index 0000000..94f98d1
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Tine 2.0 - http://www.tine20.org
+ * 
+ * @package     ActiveSync
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2015-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Lars Kneschke <l.kneschke@metaways.de>
+ */
+
+/**
+ * Test class for ActiveSync_Server_Plugin
+ * 
+ * @package     ActiveSync
+ * @subpackage  Server
+ */
+class ActiveSync_Server_PluginTests extends TestCase
+{
+    /**
+     * test general functionality of ActiveSync_Server_Plugin
+     */
+    public function testServerGetParameter()
+    {
+        $request = \Zend\Http\PhpEnvironment\Request::fromString(<<<EOS
+POST /index.php?frontend=activesync HTTP/1.1\r
+Host: localhost\r
+Depth: 0\r
+User-Agent: Mozilla/5.0 (X11; Linux i686; rv:15.0) Gecko/20120824 Thunderbird/15.0 Lightning/1.7\r
+EOS
+        );
+        
+        $request->setQuery(new Zend\Stdlib\Parameters(array('frontend' => 'activesync')));
+        
+        $server = Tinebase_Core::getDispatchServer($request);
+        
+        $this->assertInstanceOf('ActiveSync_Server_Http', $server);
+    }
+}
index c1f0f3a..c102d3c 100644 (file)
@@ -68,6 +68,7 @@ class Tinebase_AllTests
         $suite->addTestSuite('Tinebase_Redis_QueueTest');
         $suite->addTestSuite('Tinebase_Pluggable_ConcreteTest');
         $suite->addTestSuite('Tinebase_TempFileTest');
+        $suite->addTestSuite('Tinebase_Server_AllTests');
         
         $suite->addTest(Tinebase_User_AllTests::suite());
         $suite->addTest(Tinebase_Group_AllTests::suite());
diff --git a/tests/tine20/Tinebase/Server/AllServerTests.php b/tests/tine20/Tinebase/Server/AllServerTests.php
new file mode 100644 (file)
index 0000000..af7a8ab
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Tine 2.0 - http://www.tine20.org
+ * 
+ * @package     Tinebase
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html
+ * @copyright   Copyright (c) 2015-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Lars Kneschke <l.kneschke@metaways.de>
+ */
+
+/**
+ * 
+ * @package     Tinebase
+ * @subpackage  Server
+ *
+ */
+class Tinebase_Server_AllServerTests
+{
+    public static function suite() 
+    {
+        $suite = new PHPUnit_Framework_TestSuite('Tine 2.0 Tinebase All Server Tests');
+        $suite->addTestSuite('Tinebase_Server_WebDAVTests');
+        
+        return $suite;
+    }
+}
diff --git a/tests/tine20/Tinebase/Server/AllTests.php b/tests/tine20/Tinebase/Server/AllTests.php
new file mode 100644 (file)
index 0000000..50e7e2a
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Tine 2.0 - http://www.tine20.org
+ * 
+ * @package     Tinebase
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html
+ * @copyright   Copyright (c) 2015-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Lars Kneschke <l.kneschke@metaways.de>
+ */
+
+/**
+ * 
+ * @package     Tinebase
+ * @subpackage  Server
+ *
+ */
+class Tinebase_Server_AllTests
+{
+    public static function suite() 
+    {
+        $suite = new PHPUnit_Framework_TestSuite('Tine 2.0 Tinebase All Server Tests');
+        $suite->addTestSuite('Tinebase_Server_Plugin_AllTests');
+        
+        return $suite;
+    }
+}
diff --git a/tests/tine20/Tinebase/Server/Plugin/AllTests.php b/tests/tine20/Tinebase/Server/Plugin/AllTests.php
new file mode 100644 (file)
index 0000000..400b665
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Tine 2.0 - http://www.tine20.org
+ * 
+ * @package     Tinebase
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html
+ * @copyright   Copyright (c) 2015-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Lars Kneschke <l.kneschke@metaways.de>
+ */
+
+/**
+ * 
+ * @package     Tinebase
+ * @subpackage  Server
+ *
+ */
+class Tinebase_Server_Plugin_AllTests
+{
+    public static function suite() 
+    {
+        $suite = new PHPUnit_Framework_TestSuite('Tine 2.0 Tinebase All Server Plugin Tests');
+        $suite->addTestSuite('Tinebase_Server_Plugin_HttpTests');
+        $suite->addTestSuite('Tinebase_Server_Plugin_JsonTests');
+        $suite->addTestSuite('Tinebase_Server_Plugin_WebDAVTests');
+        
+        return $suite;
+    }
+}
diff --git a/tests/tine20/Tinebase/Server/Plugin/HttpTests.php b/tests/tine20/Tinebase/Server/Plugin/HttpTests.php
new file mode 100644 (file)
index 0000000..9c898d6
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Tine 2.0 - http://www.tine20.org
+ * 
+ * @package     Tinebase
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2015-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Lars Kneschke <l.kneschke@metaways.de>
+ */
+
+/**
+ * Test class for Tinebase_Server_Plugin_Http
+ * 
+ * @package     Tinebase
+ * @subpackage  Server
+ */
+class Tinebase_Server_Plugin_HttpTests extends TestCase
+{
+    /**
+     * test general functionality of Tinebase_Server_Plugin_Http
+     */
+    public function testServer()
+    {
+        $request = \Zend\Http\PhpEnvironment\Request::fromString(<<<EOS
+POST /index.php?frontend=webdav HTTP/1.1\r
+Host: localhost\r
+User-Agent: Mozilla/5.0 (X11; Linux i686; rv:15.0) Gecko/20120824 Thunderbird/15.0 Lightning/1.7\r
+EOS
+        );
+        
+        $server = Tinebase_Server_Plugin_Http::getServer($request);
+        
+        $this->assertInstanceOf('Tinebase_Server_Http', $server);
+    }
+}
diff --git a/tests/tine20/Tinebase/Server/Plugin/JsonTests.php b/tests/tine20/Tinebase/Server/Plugin/JsonTests.php
new file mode 100644 (file)
index 0000000..d380177
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Tine 2.0 - http://www.tine20.org
+ * 
+ * @package     Tinebase
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2015-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Lars Kneschke <l.kneschke@metaways.de>
+ */
+
+/**
+ * Test class for Tinebase_Server_Plugin_Json
+ * 
+ * @package     Tinebase
+ * @subpackage  Server
+ */
+class Tinebase_Server_Plugin_JsonTests extends TestCase
+{
+    /**
+     * test with ContentType header set to application/json
+     */
+    public function testServerContentType()
+    {
+        $request = \Zend\Http\PhpEnvironment\Request::fromString(<<<EOS
+POST /index.php HTTP/1.1\r
+Host: localhost\r
+Content-Type: application/json\r
+User-Agent: Mozilla/5.0 (X11; Linux i686; rv:15.0) Gecko/20120824 Thunderbird/15.0 Lightning/1.7\r
+EOS
+        );
+        
+        $server = Tinebase_Core::getDispatchServer($request);
+        
+        $this->assertInstanceOf('Tinebase_Server_Json', $server);
+    }
+    
+    /**
+     * test with ACCESS-CONTROL-REQUEST-METHOD header set
+     */
+    public function testServerCORSHeader()
+    {
+        $request = \Zend\Http\PhpEnvironment\Request::fromString(<<<EOS
+POST /index.php HTTP/1.1\r
+Host: localhost\r
+ACCESS-CONTROL-REQUEST-METHOD: application/json\r
+User-Agent: Mozilla/5.0 (X11; Linux i686; rv:15.0) Gecko/20120824 Thunderbird/15.0 Lightning/1.7\r
+EOS
+        );
+        
+        $server = Tinebase_Core::getDispatchServer($request);
+        
+        $this->assertInstanceOf('Tinebase_Server_Json', $server);
+    }
+    
+    /**
+     * test with post parameter requestType set to JSON
+     */
+    public function testServerPostParameter()
+    {
+        $request = \Zend\Http\PhpEnvironment\Request::fromString(<<<EOS
+POST /index.php?requestType=JSON HTTP/1.1\r
+Host: localhost\r
+User-Agent: Mozilla/5.0 (X11; Linux i686; rv:15.0) Gecko/20120824 Thunderbird/15.0 Lightning/1.7\r
+EOS
+        );
+        
+        $request->setPost(new Zend\Stdlib\Parameters(array('requestType' => 'JSON')));
+        
+        $server = Tinebase_Core::getDispatchServer($request);
+        
+        $this->assertInstanceOf('Tinebase_Server_Json', $server);
+    }
+}
diff --git a/tests/tine20/Tinebase/Server/Plugin/WebDAVTests.php b/tests/tine20/Tinebase/Server/Plugin/WebDAVTests.php
new file mode 100644 (file)
index 0000000..3e95456
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Tine 2.0 - http://www.tine20.org
+ * 
+ * @package     Tinebase
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2015-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Lars Kneschke <l.kneschke@metaways.de>
+ */
+
+/**
+ * Test class for Tinebase_Server_Plugin_WebDAV
+ * 
+ * @package     Tinebase
+ * @subpackage  Server
+ */
+class Tinebase_Server_Plugin_WebDAVTests extends TestCase
+{
+    /**
+     * test general functionality of Tinebase_Server_Plugin_WebDAV
+     */
+    public function testServerGetParameter()
+    {
+        $request = \Zend\Http\PhpEnvironment\Request::fromString(<<<EOS
+POST /index.php?frontend=webdav HTTP/1.1\r
+Host: localhost\r
+Depth: 0\r
+User-Agent: Mozilla/5.0 (X11; Linux i686; rv:15.0) Gecko/20120824 Thunderbird/15.0 Lightning/1.7\r
+EOS
+        );
+        
+        $request->setQuery(new Zend\Stdlib\Parameters(array('frontend' => 'webdav')));
+        
+        $server = Tinebase_Core::getDispatchServer($request);
+        
+        $this->assertInstanceOf('Tinebase_Server_WebDAV', $server);
+    }
+}
index a854dfb..02b34ad 100644 (file)
@@ -27,6 +27,7 @@ class Voipmanager_AllTests
         $suite->addTestSuite('Voipmanager_ControllerTest');
         $suite->addTestSuite('Voipmanager_JsonTest');
         $suite->addTestSuite('Voipmanager_SnomTest');
+        $suite->addTestSuite('Voipmanager_Server_PluginTests');
         //$suite->addTestSuite('Voipmanager_Backend_Snom_PhoneTest');
         return $suite;
     }
diff --git a/tests/tine20/Voipmanager/Server/PluginTests.php b/tests/tine20/Voipmanager/Server/PluginTests.php
new file mode 100644 (file)
index 0000000..76d9d7e
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Tine 2.0 - http://www.tine20.org
+ * 
+ * @package     Voipmanager
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2015-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Lars Kneschke <l.kneschke@metaways.de>
+ */
+
+/**
+ * Test class for Voipmanager_Server_Plugin
+ * 
+ * @package     Voipmanager
+ * @subpackage  Server
+ */
+class Voipmanager_Server_PluginTests extends TestCase
+{
+    /**
+     * test general functionality of Voipmanager_Server_Plugin
+     */
+    public function testServerUserAgentSnom()
+    {
+        $request = \Zend\Http\PhpEnvironment\Request::fromString(<<<EOS
+POST /index.php?frontend=activesync HTTP/1.1\r
+Host: localhost\r
+User-Agent: Mozilla/4.0 (compatible; snom320-SIP 8.4.35 1.1.3-n)\r
+EOS
+        );
+        
+        $server = Tinebase_Core::getDispatchServer($request);
+        
+        $this->assertInstanceOf('Voipmanager_Server_Snom', $server);
+    }
+    
+    /**
+     * test general functionality of Voipmanager_Server_Plugin
+     */
+    public function testServerUserAgentAsterisk()
+    {
+        $request = \Zend\Http\PhpEnvironment\Request::fromString(<<<EOS
+POST /index.php?frontend=activesync HTTP/1.1\r
+Host: localhost\r
+User-Agent: asterisk-libcurl-agent/1.0\r
+EOS
+        );
+        
+        $server = Tinebase_Core::getDispatchServer($request);
+        
+        $this->assertInstanceOf('Voipmanager_Server_Asterisk', $server);
+    }
+}
index 0f5fd42..3f69956 100644 (file)
@@ -127,6 +127,15 @@ class ActiveSync_Config extends Tinebase_Config_Abstract
     private static $_instance = NULL;
     
     /**
+     * server classes
+     *
+     * @var array
+     */
+    protected static $_serverPlugins = array(
+        'ActiveSync_Server_Plugin' => 50
+    );
+    
+    /**
      * the constructor
      *
      * don't use the constructor. use the singleton 
diff --git a/tine20/ActiveSync/Server/Plugin.php b/tine20/ActiveSync/Server/Plugin.php
new file mode 100644 (file)
index 0000000..6941aec
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     ActiveSync
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2008-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2015 Serpro (http://www.serpro.gov.br)
+ * @author      Flávio Gomes da Silva Lisboa <flavio.lisboa@serpro.gov.br>
+ */
+
+/**
+ * server plugin to dispatch ActiveSync requests
+ *
+ * @package     ActiveSync
+ * @subpackage  Server
+ */
+class ActiveSync_Server_Plugin implements Tinebase_Server_Plugin_Interface
+{
+    /**
+     * (non-PHPdoc)
+     * @see Tinebase_Server_Plugin_Interface::getServer()
+     */
+    public static function getServer(\Zend\Http\Request $request)
+    {
+        if ((isset($_SERVER['REDIRECT_ACTIVESYNC']) && $_SERVER['REDIRECT_ACTIVESYNC'] == 'true') || // legacy
+            ($request->getQuery('frontend') === 'activesync')
+        ) {
+            return new ActiveSync_Server_Http();
+        }
+    }
+}
index 1a0a1b9..fd972f0 100644 (file)
@@ -82,6 +82,7 @@ class Setup_Core extends Tinebase_Core
     /**
      * dispatch request
      *
+     * @see Tinebase_Core::dispatchRequest()
      */
     public static function dispatchRequest()
     {
index 945c0a8..8e2a085 100644 (file)
@@ -730,19 +730,31 @@ class Tinebase_Config extends Tinebase_Config_Abstract
      * @var Tinebase_Config
      */
     private static $_instance = NULL;
-    
+
+    /**
+     * server classes
+     *
+     * @var array
+     */
+    protected static $_serverPlugins = array(
+        'Tinebase_Server_Plugin_Json'   => 80,
+        'Tinebase_Server_Plugin_WebDAV' => 80,
+        'Tinebase_Server_Plugin_Cli'    => 90,
+        'Tinebase_Server_Plugin_Http'   => 100
+    );
+
     /**
      * the constructor
      *
      * don't use the constructor. use the singleton 
-     */    
+     */
     private function __construct() {}
     
     /**
      * the constructor
      *
      * don't use the constructor. use the singleton 
-     */    
+     */
     private function __clone() {}
     
     /**
index 12c29ff..bd75154 100644 (file)
@@ -110,7 +110,14 @@ abstract class Tinebase_Config_Abstract
      * @var array
      */
     protected $_cachedApplicationConfig = NULL;
-    
+
+    /**
+     * server classes
+     *
+     * @var array
+     */
+    protected static $_serverPlugins = array();
+
     /**
      * get properties definitions 
      * 
@@ -545,6 +552,16 @@ abstract class Tinebase_Config_Abstract
     }
     
     /**
+     * Get list of server classes
+     *
+     * @return array
+     */
+    public static function getServerPlugins()
+    {
+        return static::$_serverPlugins;
+    }
+    
+    /**
      * check if config system is ready
      * 
      * @todo check db setup
index b86be98..b1645ef 100644 (file)
@@ -165,7 +165,14 @@ class Tinebase_Core
      * minimal version of Oracle supported
      */
     const ORACLE_MINIMAL_VERSION = '9.0.0';
-    
+
+    /**
+     * Key for storing server plugins into cache
+     *
+     * @var string
+     */
+    const TINEBASE_SERVER_PLUGINS = 'Tinebase_Server_Plugins';
+
     /**
      * Application Instance Cache
      * @var array
@@ -184,7 +191,14 @@ class Tinebase_Core
      * @var int
      */
     protected static $logLevel;
-    
+
+    /**
+     * Server classes provided by applications
+     *
+     * @var array
+     */
+    protected static $_serverPlugins = array();
+
     /******************************* DISPATCH *********************************/
     
     /**
@@ -223,76 +237,17 @@ class Tinebase_Core
 //         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
 //             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " " . $request->toString());
 //         }
-        
-        /**************************** JSON API *****************************/
-        if (($request->getHeaders('X-TINE20-REQUEST-TYPE') && $request->getHeaders('X-TINE20-REQUEST-TYPE')->getFieldValue() === 'JSON')  ||
-            ($request->getHeaders('CONTENT-TYPE') && substr($request->getHeaders('CONTENT-TYPE')->getFieldValue(),0,16) === 'application/json') ||
-            ($request->getPost('requestType') === 'JSON') ||
-            ($request->getMethod() == \Zend\Http\Request::METHOD_OPTIONS && $request->getHeaders()->has('ACCESS-CONTROL-REQUEST-METHOD'))
-        ) {
-            $server = new Tinebase_Server_Json();
-            
-        /**************************** SNOM API *****************************/
-        } else if (
-            $request->getHeaders('USER-AGENT') &&
-            preg_match('/^Mozilla\/4\.0 \(compatible; (snom...)\-SIP (\d+\.\d+\.\d+)/i', $request->getHeaders('USER-AGENT')->getFieldValue())
-        ) {
-            $server = new Voipmanager_Server_Snom();
-            
-        /**************************** ASTERISK API *****************************/
-        } else if (
-            $request->getHeaders('USER-AGENT') &&
-            $request->getHeaders('USER-AGENT')->getFieldValue() === 'asterisk-libcurl-agent/1.0'
-        ) {
-            $server = new Voipmanager_Server_Asterisk();
-            
-        /**************************** ActiveSync API ****************************
-         * RewriteRule ^Microsoft-Server-ActiveSync index.php?frontend=activesync [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
-         */
-        } else if (
-            (isset($_SERVER['REDIRECT_ACTIVESYNC']) && $_SERVER['REDIRECT_ACTIVESYNC'] == 'true') || // legacy
-            ($request->getQuery('frontend') === 'activesync')
-        ) {
-            $server = new ActiveSync_Server_Http();
-            self::set('serverclassname', get_class($server));
 
-        /**************************** WebDAV / CardDAV / CalDAV API **********************************
-         * RewriteCond %{REQUEST_METHOD} !^(GET|POST)$
-         * RewriteRule ^/$            /index.php?frontend=webdav [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
-         *
-         * RewriteRule ^/addressbooks /index.php?frontend=webdav [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
-         * RewriteRule ^/calendars    /index.php?frontend=webdav [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
-         * RewriteRule ^/principals   /index.php?frontend=webdav [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
-         * RewriteRule ^/webdav       /index.php?frontend=webdav [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
-         */
-        } else if ($request->getQuery('frontend') === 'webdav') {
-            $server = new Tinebase_Server_WebDAV();
-            
-        /**************************** CLI API *****************************/
-        } else if (php_sapi_name() == 'cli') {
-            $server = new Tinebase_Server_Cli();
-            
-        /**************************** HTTP API ****************************/
-        } else {
-            
-            /**************************** OpenID ****************************
-             * RewriteRule ^/users/(.*)                      /index.php?frontend=openid&username=$1 [L,QSA]
-             */
-            if (isset($_SERVER['HTTP_ACCEPT']) && stripos($_SERVER['HTTP_ACCEPT'], 'application/xrds+xml') !== FALSE) {
-                $_REQUEST['method'] = 'Tinebase.getXRDS';
-            } else if ((isset($_SERVER['REDIRECT_USERINFOPAGE']) && $_SERVER['REDIRECT_USERINFOPAGE'] == 'true') ||
-                      (isset($_REQUEST['frontend']) && $_REQUEST['frontend'] == 'openid')) {
-                $_REQUEST['method'] = 'Tinebase.userInfoPage';
-            }
+        // Test server conditions from server plugins
+        foreach(self::_getServerPlugins() as $serverPlugin){
+            $server = call_user_func_array(array($serverPlugin,'getServer'), array($request));
             
-            if (!isset($_REQUEST['method']) && (isset($_REQUEST['openid_action']) || isset($_REQUEST['openid_assoc_handle'])) ) {
-                $_REQUEST['method'] = 'Tinebase.openId';
+            if ($server instanceof Tinebase_Server_Interface) {
+                Tinebase_Core::set('serverclassname', get_class($server));
+                
+                return $server;
             }
-            
-            $server = new Tinebase_Server_Http();
         }
-        
-        return $server;
     }
     
     /**
@@ -1571,4 +1526,83 @@ class Tinebase_Core
     {
         return shell_exec(escapeshellcmd($cmd));
     }
+
+    /**
+     * Search server plugins from applications configuration
+     *
+     */
+    protected static function _searchServerPlugins()
+    {
+        $cache = Tinebase_Core::getCache();
+        
+        if ($cache &&
+            $plugins = $cache->load(self::TINEBASE_SERVER_PLUGINS)
+        ) {
+            return $plugins;
+        }
+        
+        // get list of available applications
+        $applications = array();
+        
+        $d = dir(realpath(__DIR__ . '/../'));
+        
+        while (false !== ($entry = $d->read())) {
+           if ($entry[0] == '.') {
+               continue;
+           }
+           
+           if (ctype_upper($entry[0])){
+                $applications[] = $entry;
+           }
+        }
+        
+        $d->close();
+        
+        // get list of plugins
+        $plugins = array();
+        
+        foreach ($applications as $application) {
+            $config = $application . '_Config';
+            
+            try {
+                if (class_exists($config)) {
+                    $reflectedClass = new ReflectionClass($config);
+                    
+                    if ($reflectedClass->isSubclassOf('Tinebase_Config_Abstract')) {
+                        $plugins = array_merge(
+                            $plugins,
+                            call_user_func(array($config,'getServerPlugins'))
+                        );
+                    }
+                }
+            } catch (Exception $e) {
+                Tinebase_Exception::log($e);
+            }
+        }
+        
+        // sort plugins by priority
+        asort($plugins);
+        
+        $plugins = array_keys($plugins);
+        
+        if ($cache) {
+            $cache->save($plugins, self::TINEBASE_SERVER_PLUGINS);
+        }
+        
+        return $plugins;
+    }
+
+    /**
+     * Return server plugins ensuring that they were found
+     *
+     * @return array
+     */
+    protected static function _getServerPlugins()
+    {
+        if (empty(self::$_serverPlugins)) {
+           self::$_serverPlugins = self::_searchServerPlugins();
+        }
+        
+        return self::$_serverPlugins;
+    }
 }
diff --git a/tine20/Tinebase/Server/Plugin/Cli.php b/tine20/Tinebase/Server/Plugin/Cli.php
new file mode 100644 (file)
index 0000000..bd883f5
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     Tinebase
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2008-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2015 Serpro (http://www.serpro.gov.br)
+ * @author      Flávio Gomes da Silva Lisboa <flavio.lisboa@serpro.gov.br>
+ */
+
+/**
+ * server plugin to dispatch CLI requests
+ *
+ * @package     Tinebase
+ * @subpackage  Server
+ */
+class Tinebase_Server_Plugin_Cli implements Tinebase_Server_Plugin_Interface
+{
+    /**
+     * (non-PHPdoc)
+     * @see Tinebase_Server_Plugin_Interface::getServer()
+     */
+    public static function getServer(\Zend\Http\Request $request)
+    {
+        /**************************** CLI API *****************************/
+        if (php_sapi_name() == 'cli') {
+            return new Tinebase_Server_Cli();
+        }
+    }
+}
diff --git a/tine20/Tinebase/Server/Plugin/Http.php b/tine20/Tinebase/Server/Plugin/Http.php
new file mode 100644 (file)
index 0000000..bad34a3
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     Tinebase
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2008-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2015 Serpro (http://www.serpro.gov.br)
+ * @author      Flávio Gomes da Silva Lisboa <flavio.lisboa@serpro.gov.br>
+ */
+
+/**
+ * server plugin to dispatch HTTP requests
+ * 
+ * should be the last plugins, as it handles all requests
+ *
+ * @package     Tinebase
+ * @subpackage  Server
+ */
+class Tinebase_Server_Plugin_Http implements Tinebase_Server_Plugin_Interface
+{
+    /**
+     * (non-PHPdoc)
+     * @see Tinebase_Server_Plugin_Interface::getServer()
+     */
+    public static function getServer(\Zend\Http\Request $request)
+    {
+        /**************************** OpenID ****************************
+         * RewriteRule ^/users/(.*)                      /index.php?frontend=openid&username=$1 [L,QSA]
+         */
+        if (isset($_SERVER['HTTP_ACCEPT']) && stripos($_SERVER['HTTP_ACCEPT'], 'application/xrds+xml') !== FALSE) {
+            $_REQUEST['method'] = 'Tinebase.getXRDS';
+        } else if ((isset($_SERVER['REDIRECT_USERINFOPAGE']) && $_SERVER['REDIRECT_USERINFOPAGE'] == 'true') ||
+                   (isset($_REQUEST['frontend']) && $_REQUEST['frontend'] == 'openid')) {
+            $_REQUEST['method'] = 'Tinebase.userInfoPage';
+        }
+
+        if (!isset($_REQUEST['method']) && (isset($_REQUEST['openid_action']) || isset($_REQUEST['openid_assoc_handle'])) ) {
+            $_REQUEST['method'] = 'Tinebase.openId';
+        }
+
+        return new Tinebase_Server_Http();
+    }
+}
\ No newline at end of file
diff --git a/tine20/Tinebase/Server/Plugin/Interface.php b/tine20/Tinebase/Server/Plugin/Interface.php
new file mode 100644 (file)
index 0000000..3b102c6
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     Tinebase
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2007-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2015 Serpro (http://www.serpro.gov.br)
+ * @author      Flávio Gomes da Silva Lisboa <flavio.lisboa@serpro.gov.br>
+ *
+ */
+
+/**
+ * Server Interface for plugins
+ *
+ * @package     Tinebase
+ * @subpackage  Server
+ */
+interface Tinebase_Server_Plugin_Interface
+{
+    /**
+     * return server class of $request matches specific criteria
+     * 
+     * @param Zend\Http\Request $request
+     * @return Tinebase_Server_Interface
+     */
+    public static function getServer(\Zend\Http\Request $request);
+}
diff --git a/tine20/Tinebase/Server/Plugin/Json.php b/tine20/Tinebase/Server/Plugin/Json.php
new file mode 100644 (file)
index 0000000..d656a66
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     Tinebase
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2008-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2015 Serpro (http://www.serpro.gov.br)
+ * @author      Flávio Gomes da Silva Lisboa <flavio.lisboa@serpro.gov.br>
+ */
+
+/**
+ * server plugin to dispatch JSON requests
+ *
+ * @package     Tinebase
+ * @subpackage  Server
+ */
+class Tinebase_Server_Plugin_Json implements Tinebase_Server_Plugin_Interface
+{
+    /**
+     * (non-PHPdoc)
+     * @see Tinebase_Server_Plugin_Interface::getServer()
+     */
+    public static function getServer(\Zend\Http\Request $request)
+    {
+        /**************************** JSON API *****************************/
+        if (($request->getHeaders('X-TINE20-REQUEST-TYPE') && $request->getHeaders('X-TINE20-REQUEST-TYPE')->getFieldValue() === 'JSON')  ||
+            ($request->getHeaders('CONTENT-TYPE') && substr($request->getHeaders('CONTENT-TYPE')->getFieldValue(),0,16) === 'application/json') ||
+            ($request->getPost('requestType') === 'JSON') ||
+            ($request->getHeaders('ACCESS-CONTROL-REQUEST-METHOD'))
+        ) {
+            return new Tinebase_Server_Json();
+        }
+    }
+}
\ No newline at end of file
diff --git a/tine20/Tinebase/Server/Plugin/WebDAV.php b/tine20/Tinebase/Server/Plugin/WebDAV.php
new file mode 100644 (file)
index 0000000..3558b50
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     Tinebase
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2008-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2015 Serpro (http://www.serpro.gov.br)
+ * @author      Flávio Gomes da Silva Lisboa <flavio.lisboa@serpro.gov.br>
+ */
+
+/**
+ * server plugin to dispatch WebDAV requests
+ *
+ * @package     Tinebase
+ * @subpackage  Server
+ */
+class Tinebase_Server_Plugin_WebDAV implements Tinebase_Server_Plugin_Interface
+{
+    /**
+     * (non-PHPdoc)
+     * @see Tinebase_Server_Plugin_Interface::getServer()
+     */
+    public static function getServer(\Zend\Http\Request $request)
+    {
+        /**************************** WebDAV / CardDAV / CalDAV API **********************************
+         * RewriteCond %{REQUEST_METHOD} !^(GET|POST)$
+         * RewriteRule ^/$            /index.php?frontend=webdav [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
+         *
+         * RewriteRule ^/addressbooks /index.php?frontend=webdav [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
+         * RewriteRule ^/calendars    /index.php?frontend=webdav [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
+         * RewriteRule ^/principals   /index.php?frontend=webdav [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
+         * RewriteRule ^/webdav       /index.php?frontend=webdav [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
+         */
+        if ($request->getQuery('frontend') === 'webdav') {
+            return new Tinebase_Server_WebDAV();
+        }
+    }
+}
diff --git a/tine20/Voipmanager/Config.php b/tine20/Voipmanager/Config.php
new file mode 100644 (file)
index 0000000..65ab9b7
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     Voipmanager
+ * @subpackage  Config
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2007-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Flávio Gomes da Silva Lisboa <flavio.lisboa@serpro.gov.br>
+ */
+
+/**
+ * Config class for Voipmanager
+ *
+ * @package     Voipmanager
+ * @subpackage  Config
+ *
+ */
+ class Voipmanager_Config extends Tinebase_Config_Abstract
+ {
+     /**
+      * holds the instance of the singleton
+      *
+      * @var Voipmanager_Config
+      */
+     private static $_instance = NULL;
+     
+     /**
+      * (non-PHPdoc)
+      * @see tine20/Tinebase/Config/Definition::$_properties
+      */
+     protected static $_properties = array();
+     
+     /**
+      * server classes
+      *
+      * @var array
+      */
+     protected static $_serverPlugins = array(
+         'Voipmanager_Server_Plugin' => 50
+     );
+     
+     /**
+      * the constructor
+      *
+      * don't use the constructor. use the singleton
+      */
+     private function __construct() {}
+     
+     /**
+      * the constructor
+      *
+      * don't use the constructor. use the singleton
+      */
+     private function __clone() {}
+     
+     /**
+      * Returns instance of Tinebase_Config
+      *
+      * @return Voipmanager_Config
+      */
+     public static function getInstance()
+     {
+         if (self::$_instance === NULL) {
+             self::$_instance = new self();
+         }
+         
+         return self::$_instance;
+     }
+     
+     /**
+      * (non-PHPdoc)
+      * @see tine20/Tinebase/Config/Abstract::getProperties()
+      */
+     public static function getProperties()
+     {
+         return self::$_properties;
+     }
+ }
\ No newline at end of file
diff --git a/tine20/Voipmanager/Server/Plugin.php b/tine20/Voipmanager/Server/Plugin.php
new file mode 100644 (file)
index 0000000..14e0eeb
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     Voipmanager
+ * @subpackage  Server
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @copyright   Copyright (c) 2008-2015 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2015 Serpro (http://www.serpro.gov.br)
+ * @author      Flávio Gomes da Silva Lisboa <flavio.lisboa@serpro.gov.br>
+ */
+
+/**
+ * server plugin to dispatch requests from SNOM phones and Asterisk server
+ *
+ * @package     Voipmanager
+ * @subpackage  Server
+ */
+class Voipmanager_Server_Plugin implements Tinebase_Server_Plugin_Interface
+{
+    /**
+     * (non-PHPdoc)
+     * @see Tinebase_Server_Plugin_Interface::getServer()
+     */
+    public static function getServer(\Zend\Http\Request $request)
+    {
+        /**************************** SNOM API *****************************/
+        if (
+            $request->getHeaders('USER-AGENT') &&
+            preg_match('/^Mozilla\/4\.0 \(compatible; (snom...)\-SIP (\d+\.\d+\.\d+)/i', $request->getHeaders('USER-AGENT')->getFieldValue())
+        ) {
+            return new Voipmanager_Server_Snom();
+        /**************************** ASTERISK API *****************************/
+        } else if (
+            $request->getHeaders('USER-AGENT') &&
+            $request->getHeaders('USER-AGENT')->getFieldValue() === 'asterisk-libcurl-agent/1.0'
+        ) {
+            return new Voipmanager_Server_Asterisk();
+        }
+    }
+}