Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatthieu_ <matthieu_@59fd770c-687e-43c8-a1e3-f5a4ff64c105>2007-07-24 16:57:04 +0400
committermatthieu_ <matthieu_@59fd770c-687e-43c8-a1e3-f5a4ff64c105>2007-07-24 16:57:04 +0400
commita105bf4d9021d0e0f003d06418e6002fc7cfb16e (patch)
tree83a11cf9d9f02aaa41b0b7c93674eea72abe7912 /modules
parente7c34bf93ae288f17ec1402660e9e5a83e1cb72e (diff)
First code commit
(from subclipse)
Diffstat (limited to 'modules')
-rwxr-xr-xmodules/Access.php167
-rwxr-xr-xmodules/Apiable.php21
-rwxr-xr-xmodules/Config.php26
-rwxr-xr-xmodules/ErrorHandler.php35
-rwxr-xr-xmodules/Log.php20
-rwxr-xr-xmodules/Piwik.php166
-rwxr-xr-xmodules/PublicApi.php217
-rwxr-xr-xmodules/SitesManager.php194
-rwxr-xr-xmodules/UsersManager.php190
9 files changed, 1036 insertions, 0 deletions
diff --git a/modules/Access.php b/modules/Access.php
new file mode 100755
index 0000000000..7f1e9c4744
--- /dev/null
+++ b/modules/Access.php
@@ -0,0 +1,167 @@
+<?php
+class Piwik_Access
+{
+ private $acl = null;
+ private $rolesByIdsite = null;
+ private $idsitesByRole = null;
+ private $identity = null; //login
+ private $isSuperUser = false;
+
+ const SUCCESS_SUPERUSER_AUTH_CODE = 42;
+
+ static private $availableRoles = array('anonymous', 'view', 'admin', 'superuser');
+
+ public function __construct( $auth)
+ {
+ $this->auth = $auth;
+ $this->loadRoles();
+ }
+
+ private function loadRoles()
+ {
+ $rolesByIdsite = $idsitesByRole = array();
+
+ // roles = array ( idsite => roleIdSite, idsite2 => roleIdSite2)
+ $result = $this->auth->authenticate();
+
+ // case the superUser is logged in
+ if($result->getCode() == Piwik_Access::SUCCESS_SUPERUSER_AUTH_CODE)
+ {
+ $this->isSuperUser = true;
+ $sitesId = Piwik_SitesManager::getAllSitesId();
+ foreach($sitesId as $idSite)
+ {
+ $rolesByIdsite[$idSite] = 'superuser';
+ $idsitesByRole['superuser'][] = $idSite;
+ }
+ }
+ // valid authentification (normal user logged in)
+ elseif($result->isValid())
+ {
+ $this->identity = $result->getIdentity();
+
+ $db = Zend_Registry::get('db');
+ $rolesRaw = $db->fetchAll("SELECT role, idsite FROM ".Piwik::prefixTable('role').
+ " WHERE login=?", $this->identity);
+
+ foreach($rolesRaw as $role)
+ {
+ $rolesByIdsite[$role['idsite']] = $role['role'];
+ $idsitesByRole[$role['role']][] = $role['idsite'];
+ }
+ }
+
+ $this->rolesByIdsite = $rolesByIdsite;
+ $this->idsitesByRole = $idsitesByRole;
+ }
+
+ static public function getListRoles()
+ {
+ return self::$availableRoles;
+ }
+
+ private function isRoleAllowed( $roleRequired, $idSite )
+ {
+ // if no role specified, the current role is anonymous
+ $role = 'anonymous';
+
+ if(isset($this->rolesByIdsite[$idSite]))
+ {
+ $role = $this->rolesByIdsite[$idSite];
+ }
+
+ switch($roleRequired)
+ {
+ case 'anonymous':
+ return true;
+ break;
+
+ case 'view':
+ return ($role == 'view' || $role == 'admin' || $role == 'superuser');
+ break;
+
+ case 'admin':
+ return ($role == 'admin' || $role == 'superuser');
+ break;
+
+ case 'superuser':
+ return ($role == 'superuser');
+ break;
+ }
+ }
+
+ public function getIdsitesWithViewAccess()
+ {
+ return $this->idsitesByRole['view'];
+ }
+ public function getIdsitesWithAdminAccess()
+ {
+ return array_merge(
+ $this->idsitesByRole['view'],
+ $this->idsitesByRole['admin']);
+
+ }
+ // is the current authentificated user allowed to access
+ // the method with the idsite given the minimumRole
+ // false means no IdSite provided to the method. null means apply the method to all the websites on which the user has
+ // the access required.
+ public function isAllowed( $minimumRole, $idSites = false )
+ {
+ // *use cases
+ // view + 1/2/3 with 1/2 view and 3 anonymous => refused
+ // view + 1/2/3 with 1/2 view and 3 admin => allowed
+ // view + 1/2/3 with 1/2 anonymous and 3 admin => refused
+ // view + null with 1/2 anonymous and 3 admin => allowed
+ // admin + null with 1/2 view => refused
+ // admin + 1 with 1 view => refused
+ // admin + 1 with 1 admin => allowed
+ // admin + null with 1 admin => allowed
+ // superuser + 1 with 1 admin => refused
+ if(is_null($idSites))
+ {
+ if(isset($this->idsitesByRole[$minimumRole]))
+ {
+ $idSites = $this->idsitesByRole[$minimumRole];
+ }
+ else
+ {
+ $idSites = array();
+ }
+ }
+
+ // when the method called doesn't accept an IdSite parameter, then we must be a superUser
+ if($idSites === false)
+ {
+ if(!$this->isSuperUser)
+ {
+ throw new Exception("Access to this resource requires a 'superuser' role.");
+ }
+ }
+ else
+ {
+ if(!is_array($idSites))
+ {
+ $idSites = array($idSites);
+ }
+
+ // when the method called accepts an IdSite parameter, then we test that the user has a minimumRole matching
+ // for at least one website. For example, if the minimumRole is "admin" then the user must have at least
+ // one "admin" role for a website to be allowed to execute the method.
+ // Then the method itself must take care of restricting its scope on the website with the "admin" right.
+ elseif(count($idSites) > 0)
+ {
+ foreach($idSites as $idsite)
+ {
+ if(!$this->isRoleAllowed($minimumRole, $idsite))
+ {
+ throw new Exception("Access to this resource requires a '$minimumRole' role for the idsite = $idsite.");
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+}
+
+?>
diff --git a/modules/Apiable.php b/modules/Apiable.php
new file mode 100755
index 0000000000..824f2d8aee
--- /dev/null
+++ b/modules/Apiable.php
@@ -0,0 +1,21 @@
+<?php
+class Piwik_Apiable
+{
+ protected function __construct()
+ {
+ }
+
+ public function getMinimumRoleRequired( $methodName )
+ {
+ if(isset($this->roles[$methodName]))
+ {
+ $minimumRole = $this->roles[$methodName];
+ }
+ else
+ {
+ $minimumRole = 'superuser';
+ }
+ return $minimumRole;
+ }
+}
+?> \ No newline at end of file
diff --git a/modules/Config.php b/modules/Config.php
new file mode 100755
index 0000000000..267a71e3ba
--- /dev/null
+++ b/modules/Config.php
@@ -0,0 +1,26 @@
+<?php
+class Piwik_Config extends Zend_Config_Ini
+{
+ function __construct()
+ {
+ $pathIniFile = PIWIK_INCLUDE_PATH . '/config/config.ini';
+
+ parent::__construct($pathIniFile, null, true);
+
+ Zend_Registry::set('config', $this);
+
+ $this->setPrefixTables();
+ }
+
+ public function setTestEnvironment()
+ {
+ $this->database = $this->database_tests;
+ $this->setPrefixTables();
+ }
+
+ public function setPrefixTables()
+ {
+ Zend_Registry::set('tablesPrefix', $this->database->tables_prefix);
+ }
+}
+?>
diff --git a/modules/ErrorHandler.php b/modules/ErrorHandler.php
new file mode 100755
index 0000000000..5a30682815
--- /dev/null
+++ b/modules/ErrorHandler.php
@@ -0,0 +1,35 @@
+<?php
+function Piwik_ErrorHandler($errno, $errstr, $errfile, $errline)
+{
+ $errno = $errno & error_reporting();
+ if($errno == 0) return;
+ if(!defined('E_STRICT')) define('E_STRICT', 2048);
+ if(!defined('E_RECOVERABLE_ERROR')) define('E_RECOVERABLE_ERROR', 4096);
+ print "\n<div style='word-wrap: break-word; border: 3px solid red; padding:4px; width:70%; background-color:#FFFF96;'><b>";
+ switch($errno){
+ case E_ERROR: print "Error"; break;
+ case E_WARNING: print "Warning"; break;
+ case E_PARSE: print "Parse Error"; break;
+ case E_NOTICE: print "Notice"; break;
+ case E_CORE_ERROR: print "Core Error"; break;
+ case E_CORE_WARNING: print "Core Warning"; break;
+ case E_COMPILE_ERROR: print "Compile Error"; break;
+ case E_COMPILE_WARNING: print "Compile Warning"; break;
+ case E_USER_ERROR: print "User Error"; break;
+ case E_USER_WARNING: print "User Warning"; break;
+ case E_USER_NOTICE: print "User Notice"; break;
+ case E_STRICT: print "Strict Notice"; break;
+ case E_RECOVERABLE_ERROR: print "Recoverable Error"; break;
+ default: print "Unknown error ($errno)"; break;
+ }
+ print ":</b> <i>$errstr</i> in <b>$errfile</b> on line <b>$errline</b>\n";
+ print("<br><br>Backtrace --><DIV style='font-family:Courier;font-size:10pt'>");
+
+ ob_start();
+ debug_print_backtrace();
+ $out1 = ob_get_clean();
+ print(str_replace("\n", "<br>", $out1));
+ print("</div><br><br>");
+ print "\n</pre></div><br>";
+}
+?>
diff --git a/modules/Log.php b/modules/Log.php
new file mode 100755
index 0000000000..169364e388
--- /dev/null
+++ b/modules/Log.php
@@ -0,0 +1,20 @@
+<?php
+Zend_Loader::loadClass('Zend_Log');
+Zend_Loader::loadClass('Zend_Registry');
+
+class Piwik_Log extends Zend_Log
+{
+ function __construct()
+ {
+ parent::__construct();
+
+ Zend_Loader::loadClass('Zend_Log_Writer_Stream');
+ $writer = new Zend_Log_Writer_Stream('php://output');
+ $formatter = new Zend_Log_Formatter_Simple('%message% <br>' . PHP_EOL);
+ $writer->setFormatter($formatter);
+ $this->addWriter($writer);
+ Zend_Registry::set('logger', $this);
+ }
+}
+
+?>
diff --git a/modules/Piwik.php b/modules/Piwik.php
new file mode 100755
index 0000000000..b5b7b20afd
--- /dev/null
+++ b/modules/Piwik.php
@@ -0,0 +1,166 @@
+<?php
+
+class Piwik
+{
+ const CLASSES_PREFIX = "Piwik_";
+
+ static public function log($message, $priority = Zend_Log::NOTICE)
+ {
+ Zend_Registry::get('logger')->log($message . PHP_EOL, $priority);
+ }
+
+ static public function getTablesCreateSql()
+ {
+ $config = Zend_Registry::get('config');
+ $prefixTables = $config->database->tables_prefix;
+ $tables = array(
+ 'user' => "CREATE TABLE {$prefixTables}user (
+ login VARCHAR(20) NOT NULL,
+ password CHAR(32) NOT NULL,
+ alias VARCHAR(45) NOT NULL,
+ email VARCHAR(100) NOT NULL,
+ token_auth CHAR(32) NOT NULL,
+ date_registered TIMESTAMP NOT NULL,
+ PRIMARY KEY(login)
+ )
+ ",
+
+ 'role' => "CREATE TABLE {$prefixTables}role (
+ login VARCHAR(20) NOT NULL,
+ idsite INTEGER UNSIGNED NOT NULL,
+ role VARCHAR(10) NULL,
+ PRIMARY KEY(login, idsite)
+ )
+ ",
+
+ 'site' => "CREATE TABLE {$prefixTables}site (
+ idsite INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ name VARCHAR(90) NOT NULL,
+ main_url VARCHAR(255) NOT NULL,
+ PRIMARY KEY(idsite)
+ )
+ ",
+
+ 'site_url' => "CREATE TABLE {$prefixTables}site_url (
+ idsite INTEGER(10) UNSIGNED NOT NULL,
+ url VARCHAR(255) NOT NULL,
+ PRIMARY KEY(idsite, url)
+ )
+ ",
+
+ );
+ return $tables;
+ }
+
+ static public function prefixClass( $class )
+ {
+ if(substr_count($class, Piwik::CLASSES_PREFIX) > 0)
+ {
+ return $class;
+ }
+ return Piwik::CLASSES_PREFIX.$class;
+ }
+
+ static public function prefixTable( $table )
+ {
+ $config = Zend_Registry::get('config');
+ $prefixTables = $config->database->tables_prefix;
+ return $prefixTables . $table;
+ }
+
+ static public function getTablesNames()
+ {
+ $aTables = array_keys(self::getTablesCreateSql());
+ $config = Zend_Registry::get('config');
+ $prefixTables = $config->database->tables_prefix;
+ $return = array();
+ foreach($aTables as $table)
+ {
+ $return[] = $prefixTables.$table;
+ }
+ return $return;
+ }
+
+ static public function getTablesInstalled()
+ {
+ $allMyTables = self::getTablesNames();
+
+ $db = Zend_Registry::get('db');
+ $allTables = $db->fetchCol('SHOW TABLES');
+
+ $intersect = array_intersect($allTables, $allMyTables);
+
+ return $intersect;
+ }
+
+ static public function createDatabase()
+ {
+ $db = Zend_Registry::get('db');
+ $dbName = Zend_Registry::get('config')->database->dbname;
+ $db->query("CREATE DATABASE IF NOT EXISTS ".$dbName);
+ }
+
+ static public function dropDatabase()
+ {
+ $db = Zend_Registry::get('db');
+ $dbName = Zend_Registry::get('config')->database->dbname;
+ $db->query("DROP DATABASE IF EXISTS ".$dbName);
+ }
+
+
+ static public function createDatabaseObject()
+ {
+ $config = Zend_Registry::get('config');
+ $db = Zend_Db::factory($config->database->adapter, $config->database->toArray());
+ Zend_Db_Table::setDefaultAdapter($db);
+ Zend_Registry::set('db', $db);
+ }
+
+ static public function createLogObject()
+ {
+ $log = new Piwik_Log;
+ }
+ static public function createConfigObject()
+ {
+ $config = new Piwik_Config;
+
+ assert(count($config) != 0);
+ }
+
+ static public function createTables()
+ {
+ $db = Zend_Registry::get('db');
+
+ $config = Zend_Registry::get('config');
+ $prefixTables = $config->database->tables_prefix;
+
+ Piwik::log("Creating ". implode(", ", self::getTablesNames()));
+
+ $tablesToCreate = self::getTablesCreateSql();
+
+ $tablesAlreadyInstalled = self::getTablesInstalled();
+
+ foreach($tablesToCreate as $tableName => $tableSql)
+ {
+ $tableName = $prefixTables . $tableName;
+
+ // if the table doesn't exist already
+ if(!in_array($tableName, $tablesAlreadyInstalled))
+ {
+ $db->query( $tableSql );
+ }
+ }
+ }
+
+ static public function uninstall()
+ {
+ // delete tables
+ //create tables
+ $db = Zend_Registry::get('db');
+
+ Piwik::log("Droping ". implode(", ", self::getTablesNames()));
+
+ $db->query( "DROP TABLE IF EXISTS ". implode(", ", self::getTablesNames()) );
+ }
+}
+?>
diff --git a/modules/PublicApi.php b/modules/PublicApi.php
new file mode 100755
index 0000000000..c536e1025b
--- /dev/null
+++ b/modules/PublicApi.php
@@ -0,0 +1,217 @@
+<?php
+class Piwik_PublicApi
+{
+ static $classCalled = null;
+ private $api = null;
+
+ private $methodsNotToPublish = array('getMinimumRoleRequired');
+
+ static private $instance = null;
+ protected function __construct()
+ {}
+
+ static public function getInstance()
+ {
+ if (self::$instance == null)
+ {
+ $c = __CLASS__;
+ self::$instance = new $c();
+ }
+ return self::$instance;
+ }
+
+ public function registerClass( $class )
+ {
+ Zend_Loader::loadClass($class);
+
+ $rClass = new ReflectionClass($class);
+
+ if(!$rClass->isSubclassOf(new ReflectionClass("Piwik_Apiable")))
+ {
+ throw new Exception("To publish its public methods in the API, the class '$class' must be a subclass of 'Piwik_Apiable'.");
+ }
+
+ Piwik::log("List of the public methods for the class $class");
+
+ $rMethods = $rClass->getMethods();
+ foreach($rMethods as $method)
+ {
+ if($method->isPublic()
+ && !$method->isConstructor()
+ && !in_array($method->getName(), $this->methodsNotToPublish )
+ )
+ {
+ $name = $method->getName();
+
+ $parameters = $method->getParameters();
+
+ $aParameters = array();
+ foreach($parameters as $parameter)
+ {
+ $nameVariable = $parameter->getName();
+
+ $defaultValue = '';
+ if($parameter->isDefaultValueAvailable())
+ {
+ $defaultValue = $parameter->getDefaultValue();
+ }
+
+ $aParameters[$nameVariable] = $defaultValue;
+ }
+ $this->api[$class][$name]['parameters'] = $aParameters;
+ $this->api[$class][$name]['numberOfRequiredParameters'] = $method->getNumberOfRequiredParameters();
+
+ Piwik::log("- $name is public ".$this->getStrListParameters($class, $name));
+ }
+ }
+ }
+
+ private function getStrListParameters($class, $name)
+ {
+ $aParameters = $this->getParametersList($class, $name);
+ $asParameters = array();
+ foreach($aParameters as $nameVariable=> $defaultValue)
+ {
+ $str = $nameVariable;
+ if(!empty($defaultValue))
+ {
+ $str .= " = $defaultValue";
+ }
+ $asParameters[] = $str;
+ }
+ $sParameters = implode(", ", $asParameters);
+ return "[$sParameters]";
+ }
+ private function getParametersList($class, $name)
+ {
+ return $this->api[$class][$name]['parameters'];
+ }
+ private function getNumberOfRequiredParameters($class, $name)
+ {
+ return $this->api[$class][$name]['numberOfRequiredParameters'];
+ }
+
+ private function isMethodAvailable( $className, $methodName)
+ {
+ return isset($this->api[$className][$methodName]);
+ }
+ public function __get($name)
+ {
+ self::$classCalled = $name;
+ return $this;
+ }
+
+ private function getIdSitesParameter($class, $name, $parameters)
+ {
+ $paramsDefaultValues = $this->getParametersList($class, $name);
+ $parametersNames = array_keys($paramsDefaultValues);
+ $parametersNames = array_map("strtolower", $parametersNames);
+
+ $sitesIdToLookFor = array("idsites", "idsite", "sitesid", "siteid", "siteids");
+
+ $newlyFound = false;
+ $found = false;
+ foreach($sitesIdToLookFor as $strIdSite)
+ {
+ $newlyFound = array_search($strIdSite, $parametersNames);
+ if($newlyFound !== false
+ && $found !== false)
+ {
+ throw new Exception("
+ It seems that the parameters list ".$this->getStrListParameters($class, $name)." contains two potential IdSite parameters.
+ Please rename the method parameters so that only one IdSite can be found in the method parameters list.
+ The following string are considered as being idSite parameter names : [".implode(", ", $sitesIdToLookFor)."]" );
+ }
+ elseif($newlyFound !== false)
+ {
+ $found = $newlyFound;
+ }
+ }
+
+ if($found===false)
+ {
+ return false;
+ }
+ else
+ {
+ if(isset($parameters[$found]))
+ {
+ $parameters[$found];
+ }
+ else
+ {
+ $values = array_values($paramsDefaultValues);
+ if(isset($values[$found]))
+ {
+ return $values[$found];
+ }
+ else
+ {
+ exit("must test this case and the other ones...");
+ }
+ }
+ }
+ }
+
+ private function checkNumberOfParametersMatch($className, $methodName, $parameters)
+ {
+ $nbParamsGiven = count($parameters);
+ $nbParamsRequired = $this->getNumberOfRequiredParameters($className, $methodName);
+
+ if($nbParamsGiven < $nbParamsRequired)
+ {
+ throw new Exception("The number of parameters provided ($nbParamsGiven) is less than the number of required parameters ($nbParamsRequired) for this method.
+ Please check the method API.");
+ }
+ elseif($nbParamsGiven > $nbParamsRequired)
+ {
+ throw new Exception("The number of parameters provided ($nbParamsGiven) is greater than the number of required parameters ($nbParamsRequired) for this method.
+ Please check the method API.");
+ }
+ return true;
+
+ }
+ public function __call($methodName, $parameters )
+ {
+ assert(!is_null(self::$classCalled));
+
+ $args = @implode(", ", $parameters);
+
+ $className = Piwik::prefixClass(self::$classCalled);
+ if(!method_exists("$className", "getInstance"))
+ {
+ throw new Exception("Objects that provide an API must be Singleton and have a 'static public function getInstance()' method.");
+ }
+ $object = null;
+ eval("\$object = $className::getInstance();");
+
+ // check method exists
+ if(!$this->isMethodAvailable($className, $methodName))
+ {
+ throw new Exception("The method '$methodName' does not exist or is not available in the module '".self::$classCalled."'.");
+ }
+ Piwik::log("Calling ".self::$classCalled.".$methodName [$args]");
+
+ try {
+ // first check number of parameters do match
+ $this->checkNumberOfParametersMatch($className, $methodName, $parameters);
+
+ $idSites = $this->getIdSitesParameter($className, $methodName, $parameters);
+
+ $access = Zend_Registry::get('access');
+ $access->isAllowed( $object->getMinimumRoleRequired($methodName), $idSites);
+ Piwik::log('Access granted!');
+
+ // call the method
+ call_user_func(array($object, $methodName), $parameters);
+ }
+ catch( Exception $e)
+ {
+ Piwik::log("Error during API call...". $e->getMessage());
+ exit;
+ }
+
+ self::$classCalled = null;
+ }
+}
+?> \ No newline at end of file
diff --git a/modules/SitesManager.php b/modules/SitesManager.php
new file mode 100755
index 0000000000..9ffd74b61f
--- /dev/null
+++ b/modules/SitesManager.php
@@ -0,0 +1,194 @@
+<?php
+
+class Piwik_SitesManager extends Piwik_APIable
+{
+ static private $instance = null;
+ protected function __construct()
+ {
+ parent::__construct();
+ }
+
+ static public function getInstance()
+ {
+ if (self::$instance == null)
+ {
+ $c = __CLASS__;
+ self::$instance = new $c();
+ }
+ return self::$instance;
+ }
+
+ protected $roles = array(
+ 'getSites' => 'anonymous',
+ 'getSitesId' => 'anonymous',
+ 'getSiteUrlsFromId' => 'view',
+ 'replaceSiteUrls' => 'admin',
+ 'siteExists' => 'anonymous',
+ );
+
+ static private function checkName($name)
+ {
+ if(empty($name))
+ {
+ throw new Exception("The site name can't be empty.");
+ }
+ }
+
+ static private function checkUrls($aUrls)
+ {
+ foreach($aUrls as $url)
+ {
+ if(!self::isValidUrl($url))
+ {
+ throw new Exception("The url '$url' is not a valid URL.");
+ }
+ }
+ }
+
+ static private function cleanParameterUrls( $aUrls )
+ {
+ if(!is_array($aUrls))
+ {
+ $aUrls = array($aUrls);
+ }
+ foreach($aUrls as &$url)
+ {
+ $url = self::removeTrailingSlash($url);
+ }
+ return $aUrls;
+ }
+
+ static private function checkIdsite($idsite)
+ {
+ if(!is_int($idsite)
+ || $idsite <= 0)
+ {
+ throw new Exception("Idsite must be an integer > 0.");
+ }
+
+ if(!self::siteExists($idsite))
+ {
+ throw new Exception("The site with Idsite = $idsite doesn't exist.");
+ }
+ }
+
+ static public function addSite( $name, $aUrls )
+ {
+ self::checkName($name);
+ $aUrls = self::cleanParameterUrls($aUrls);
+ self::checkUrls($aUrls);
+
+ if(count($aUrls) == 0)
+ {
+ throw new Exception("You must specify at least one URL for the site.");
+ }
+
+ $db = Zend_Registry::get('db');
+
+ $url = $aUrls[0];
+ $aUrls = array_slice($aUrls, 1);
+
+ $db->insert(Piwik::prefixTable("site"), array(
+ 'name' => $name,
+ 'main_url' => $url,
+ )
+ );
+
+ $idSite = $db->lastInsertId();
+
+ self::insertSiteUrls($idSite, $aUrls);
+ }
+
+ static private function insertSiteUrls($idSite, $aUrls)
+ {
+ $db = Zend_Registry::get('db');
+ foreach($aUrls as $url)
+ {
+ $db->insert(Piwik::prefixTable("site_url"), array(
+ 'idsite' => $idSite,
+ 'url' => $url
+ )
+ );
+ }
+ }
+
+ static public function addSiteUrls( $idsite, $aUrls)
+ {
+ $urls = self::getSiteUrlsFromId($idsite);
+ $toInsert = array_diff($aUrls, $urls);
+ self::insertSiteUrls($idsite, $toInsert);
+ }
+
+ static public function replaceSiteUrls( $idsite, $aUrls)
+ {
+ self::checkIdsite($idsite);
+ $aUrls = self::cleanParameterUrls($aUrls);
+ self::checkUrls($aUrls);
+
+ self::deleteSiteUrls($idsite);
+ self::addSiteUrls($idsite, $aUrls);
+ }
+
+ static private function deleteSiteUrls($idsite)
+ {
+ $db = Zend_Registry::get('db');
+ $db->query("DELETE FROM ".Piwik::prefixTable("site_url") ." WHERE idsite = ?", $idsite);
+ }
+
+ static public function getSites()
+ {
+ $db = Zend_Registry::get('db');
+ $sites = $db->fetchAll("SELECT * FROM ".Piwik::prefixTable("site"));
+ return $sites;
+ }
+
+ static public function getSiteUrlsFromId( $idsite )
+ {
+ $db = Zend_Registry::get('db');
+ $urls = $db->fetchCol("SELECT url FROM ".Piwik::prefixTable("site_url"). " WHERE idsite = ?", $idsite);
+ return $urls;
+ }
+ static public function getSitesId()
+ {
+ $sites = self::getSites();
+ $aSitesId = array();
+ foreach($sites as $site)
+ {
+ $aSitesId[] = $site["idsite"];
+ }
+ return $aSitesId;
+ }
+
+ static public function getAllSitesId()
+ {
+ $db = Zend_Registry::get('db');
+ $idSites = $db->fetchCol("SELECT idsite FROM ".Piwik::prefixTable('site'));
+ return $idSites;
+ }
+
+ static public function getSitesIdWithAdminAccess()
+ {
+ return array();
+ }
+
+ static public function siteExists( $idsite )
+ {
+ $sites = self::getSitesId();
+ return in_array($idsite, $sites);
+ }
+
+ static private function removeTrailingSlash($url)
+ {
+ // if there is a final slash, we take the URL without this slash (expected URL format)
+ if($url[strlen($url)-1] == '/')
+ {
+ $url = substr($url,0,strlen($url)-1);
+ }
+ return $url;
+ }
+ static private function isValidUrl( $url )
+ {
+ return ereg('^http[s]?://[A-Za-z0-9\/_.-]', $url);
+ }
+}
+?>
diff --git a/modules/UsersManager.php b/modules/UsersManager.php
new file mode 100755
index 0000000000..a09fd57f28
--- /dev/null
+++ b/modules/UsersManager.php
@@ -0,0 +1,190 @@
+<?php
+//
+// getSiteFromId( id )
+// getSiteFromUrl( mainUrl )
+// getSites( accessType )
+// getNumberOfSites()
+// getNumberOfSitesWithAdminAccess()
+Zend_Loader::loadClass("Piwik_Access");
+
+
+class Piwik_UsersManager extends Piwik_APIable
+{
+//
+// getUsersExtended()
+//
+// getUserFromLogin( login )
+// getUserFromEmail( email )
+//
+ static private $instance = null;
+ protected function __construct()
+ {
+ parent::__construct();
+ }
+
+ static public function getInstance()
+ {
+ if (self::$instance == null)
+ {
+ $c = __CLASS__;
+ self::$instance = new $c();
+ }
+ return self::$instance;
+ }
+
+ static public function getUsers()
+ {
+ $db = Zend_Registry::get('db');
+ $prefix = Zend_Registry::get("tablesPrefix");
+ $users = $db->fetchCol("SELECT login FROM ".Piwik::prefixTable("user"));
+ return $users;
+ }
+
+ static public function addUser( $userLogin, $password, $alias, $email )
+ {
+ if(self::userExists($userLogin))
+ {
+ throw new Exception("Login $login already exists.");
+ }
+ if(!self::isValidLoginString($userLogin))
+ {
+ throw new Exception("The login must contain only letters, numbers, or the characters '_' or '-' or '.'.");
+ }
+ if(!self::isValidPasswordString($password))
+ {
+ throw new Exception("The password must contain at least 6 characters including at least one number.");
+ }
+ if(!self::isValidEmailString($email))
+ {
+ throw new Exception("The email doesn't have a valid format.");
+ }
+
+ $db = Zend_Registry::get('db');
+
+ $db->insert( Piwik::prefixTable("user"), array(
+ 'login' => $userLogin,
+ 'password' => md5($password),
+ 'alias' => $alias,
+ 'email' => $email,
+ 'token_auth' => self::getTokenAuth($userLogin,$password)
+ )
+ );
+
+
+ }
+
+ static public function deleteUser( $userLogin )
+ {
+ if(!self::userExists($userLogin))
+ {
+ throw new Exception("User $userLogin doesn't exist therefore it can't be deleted.");
+ }
+
+ $db = Zend_Registry::get('db');
+ $db->query("DELETE FROM ".Piwik::prefixTable("user")." WHERE login = ?", $userLogin);
+
+ }
+
+ static public function userExists( $userLogin )
+ {
+ $aLogins = self::getUsers();
+ return in_array($userLogin, $aLogins);
+ }
+
+ // role = anonymous / view / admin / superuser
+ static public function setUserRole( $role, $userLogin, $idSites = null)
+ {
+ $roles = Piwik_Access::getListRoles();
+ // do not allow to set the superUser role
+ unset($roles[array_search("superuser", $roles)]);
+
+ if(!in_array($role,$roles))
+ {
+ throw new Exception("The parameter role must have one of the following values : [ ". implode(", ", $roles)." ]");
+ }
+ if(!self::userExists($userLogin))
+ {
+ throw new Exception("User '$userLogin' doesn't exist.");
+ }
+
+ if(is_null($idSites))
+ {
+ $idSites = Piwik_SitesManager::getSitesIdWithAdminAccess();
+ }
+ elseif(!is_array($idSites))
+ {
+ $idSites = array($idSites);
+ }
+
+ foreach($idSites as $idsite)
+ {
+ if( !is_null($idsite)
+ && !Piwik_SitesManager::siteExists($idsite))
+ {
+ throw new Exception("Site id = $idsite doesn't exist.");
+ }
+ }
+
+ // delete UserRole
+ $db = Zend_Registry::get('db');
+
+ foreach($idSites as $idsite)
+ {
+ $db->query( "DELETE FROM ".Piwik::prefixTable("role").
+ " WHERE idsite = ? AND login = ?",
+ array($idsite, $userLogin)
+ );
+ }
+
+ // if the role is anonymous then we don't save it as this is the default value
+ // when no role are specified
+ if($role != "anonymous")
+ {
+ foreach($idSites as $idsite)
+ {
+ $db->insert( Piwik::prefixTable("role"),
+ array( "idsite" => $idsite,
+ "login" => $userLogin,
+ "role" => $role)
+ );
+ }
+ }
+
+ }
+
+ static private function getTokenAuth($userLogin, $password)
+ {
+ return md5($userLogin . $password . time());
+
+ }
+ static private function isValidEmailString( $email )
+ {
+ return (preg_match('/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z]{2,4}$/', $email) > 0);
+ }
+
+ static private function isValidLoginString( $input )
+ {
+ return preg_match('/^[A-Za-z0-9\_\.-]*$/', $input) > 0;
+ }
+
+ static private function isValidPasswordString( $input )
+ {
+ $isNumeric = false;
+
+ $l = strlen($input);
+ if( $l < 6)
+ {
+ return false;
+ }
+
+ for($i = 0; $i < $l ; $i++)
+ {
+ if(is_numeric($input[$i]))
+ {
+ $isNumeric=true;
+ }
+ }
+ return $isNumeric;
+ }
+
+} \ No newline at end of file