Commit 7b665111 authored by Sebastian Kummer's avatar Sebastian Kummer

Merge pull request #333 in ZP/z-push from develop to release/2.3

* commit 'bafa51ea':
  ZP-1007 Changed wbxml debug output to FATAL loglevel.
  ZP-1007 Always log Wbxml debug data in case there is an error during RequestHandler->Handle().
  ZP-1005 Check if database name is confirm the SQL naming standards.
  ZP-1002 is_null doesn't check for isset generating an undefined key warning.
  ZP-1002 replace tabs with spaces.
  ZP-1002 SQL state backend fails with PostgreSQL.
  ZP-985 Packages for Red Hat Software collections make actually no use of them. Released under the Affero GNU General Public License (AGPL) version 3.
parents b55a50bc bafa51ea
...@@ -13,7 +13,11 @@ BuildRoot: %_tmppath/%name-%version-build ...@@ -13,7 +13,11 @@ BuildRoot: %_tmppath/%name-%version-build
%if 0%{?suse_version} %if 0%{?suse_version}
%define apache_dir %_sysconfdir/apache2 %define apache_dir %_sysconfdir/apache2
%else %else
%define apache_dir %_sysconfdir/httpd %if "%_repository" == "RHEL_6_PHP_56" || "%_repository" == "RHEL_7_PHP_56"
%define apache_dir /opt/rh/httpd24/root/etc/httpd/
%else
%define apache_dir %_sysconfdir/httpd
%endif
%endif %endif
%description %description
...@@ -96,7 +100,11 @@ Backend for Z-Push, that adds the ability to connect to a ldap server ...@@ -96,7 +100,11 @@ Backend for Z-Push, that adds the ability to connect to a ldap server
Summary: Z-Push Kopano backend Summary: Z-Push Kopano backend
Group: Productivity/Networking/Email/Utilities Group: Productivity/Networking/Email/Utilities
Requires: %name-common = %version Requires: %name-common = %version
%if 0%{?fedora_version} || 0%{?centos_version} || 0%{?rhel_version}
Requires: php-mapi-webapp
%else
Requires: php-mapi Requires: php-mapi
%endif
Provides: %name-backend Provides: %name-backend
%description -n %name-backend-kopano %description -n %name-backend-kopano
...@@ -459,7 +467,7 @@ install -Dpm 644 config/apache2/z-push-autodiscover.conf \ ...@@ -459,7 +467,7 @@ install -Dpm 644 config/apache2/z-push-autodiscover.conf \
%dir %zpush_dir/backend/ipcsharedmemory/ %dir %zpush_dir/backend/ipcsharedmemory/
%zpush_dir/backend/ipcsharedmemory %zpush_dir/backend/ipcsharedmemory
# IPCMEMCACHED # IPC-MEMCACHED
%files -n %name-ipc-memcached %files -n %name-ipc-memcached
%defattr(-, root, root) %defattr(-, root, root)
%dir %zpush_dir/backend %dir %zpush_dir/backend
......
...@@ -84,6 +84,10 @@ class SqlStateMachine implements IStateMachine { ...@@ -84,6 +84,10 @@ class SqlStateMachine implements IStateMachine {
throw new FatalMisconfigurationException("SqlStateMachine(): missing configuration for the state sql. Check STATE_SQL_* values in the configuration."); throw new FatalMisconfigurationException("SqlStateMachine(): missing configuration for the state sql. Check STATE_SQL_* values in the configuration.");
} }
if (!preg_match('/[0-9a-zA-Z$_]+/', STATE_SQL_DATABASE)) {
throw new FatalMisconfigurationException(sprintf("SqlStateMachine(): invalid database name '%s'. The name may contain ASCII 7bit letters, numbers and the '$' and '_' signs. Please change your configuration.", STATE_SQL_DATABASE));
}
$this->options = array(); $this->options = array();
if (trim(STATE_SQL_OPTIONS)) { if (trim(STATE_SQL_OPTIONS)) {
$this->options = unserialize(STATE_SQL_OPTIONS); $this->options = unserialize(STATE_SQL_OPTIONS);
...@@ -145,8 +149,8 @@ class SqlStateMachine implements IStateMachine { ...@@ -145,8 +149,8 @@ class SqlStateMachine implements IStateMachine {
$hash = null; $hash = null;
$record = null; $record = null;
try { try {
$sth = $this->getStateHashStatement($key);
$params = $this->getParams($devid, $type, $key, $counter); $params = $this->getParams($devid, $type, $key, $counter);
$sth = $this->getStateHashStatement($params);
$sth->execute($params); $sth->execute($params);
$record = $sth->fetch(PDO::FETCH_ASSOC); $record = $sth->fetch(PDO::FETCH_ASSOC);
...@@ -189,8 +193,8 @@ class SqlStateMachine implements IStateMachine { ...@@ -189,8 +193,8 @@ class SqlStateMachine implements IStateMachine {
if ($counter && $cleanstates) if ($counter && $cleanstates)
$this->CleanStates($devid, $type, $key, $counter); $this->CleanStates($devid, $type, $key, $counter);
$sql = "SELECT state_data FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($key) .":key AND counter = :counter";
$params = $this->getParams($devid, $type, $key, $counter); $params = $this->getParams($devid, $type, $key, $counter);
$sql = "SELECT state_data FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($params, ':key') ." AND counter = :counter";
$data = null; $data = null;
$sth = null; $sth = null;
...@@ -242,8 +246,8 @@ class SqlStateMachine implements IStateMachine { ...@@ -242,8 +246,8 @@ class SqlStateMachine implements IStateMachine {
$key = $this->returnNullified($key); $key = $this->returnNullified($key);
ZLog::Write(LOGLEVEL_DEBUG, sprintf("SqlStateMachine->SetState(): devid:'%s' type:'%s' key:'%s' counter:'%s'", $devid, $type, Utils::PrintAsString($key), Utils::PrintAsString($counter))); ZLog::Write(LOGLEVEL_DEBUG, sprintf("SqlStateMachine->SetState(): devid:'%s' type:'%s' key:'%s' counter:'%s'", $devid, $type, Utils::PrintAsString($key), Utils::PrintAsString($counter)));
$sql = "SELECT device_id FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($key) .":key AND counter = :counter";
$params = $this->getParams($devid, $type, $key, $counter); $params = $this->getParams($devid, $type, $key, $counter);
$sql = "SELECT device_id FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($params, ':key') ." AND counter = :counter";
$sth = null; $sth = null;
$record = null; $record = null;
...@@ -263,14 +267,14 @@ class SqlStateMachine implements IStateMachine { ...@@ -263,14 +267,14 @@ class SqlStateMachine implements IStateMachine {
} }
else { else {
// Existing record, we update it // Existing record, we update it
$sql = "UPDATE {$this->states_table} SET state_data = :data, updated_at = :updated_at WHERE device_id = :devid AND state_type = :type AND uuid ". $this->getSQLOp($key) .":key AND counter = :counter"; $sql = "UPDATE {$this->states_table} SET state_data = :data, updated_at = :updated_at WHERE device_id = :devid AND state_type = :type AND uuid ". $this->getSQLOp($params, ':key') ." AND counter = :counter";
$sth = $this->getDbh()->prepare($sql); $sth = $this->getDbh()->prepare($sql);
} }
$sth->bindParam(":devid", $devid, PDO::PARAM_STR); $sth->bindParam(":devid", $devid, PDO::PARAM_STR);
$sth->bindParam(":type", $type, PDO::PARAM_STR); $sth->bindParam(":type", $type, PDO::PARAM_STR);
$sth->bindParam(":key", $key, PDO::PARAM_STR); if (!$record || isset($key)) $sth->bindParam(":key", $key, PDO::PARAM_STR);
$sth->bindValue(":counter", ($counter === false ? 0 : $counter), PDO::PARAM_INT); $sth->bindValue(":counter", ($counter === false ? 0 : $counter), PDO::PARAM_INT);
$sth->bindValue(":data", serialize($state), PDO::PARAM_LOB); $sth->bindValue(":data", serialize($state), PDO::PARAM_LOB);
$sth->bindValue(":updated_at", $this->getNow(), PDO::PARAM_STR); $sth->bindValue(":updated_at", $this->getNow(), PDO::PARAM_STR);
...@@ -312,17 +316,17 @@ class SqlStateMachine implements IStateMachine { ...@@ -312,17 +316,17 @@ class SqlStateMachine implements IStateMachine {
$key = $this->returnNullified($key); $key = $this->returnNullified($key);
ZLog::Write(LOGLEVEL_DEBUG, sprintf("SqlStateMachine->CleanStates(): devid:'%s' type:'%s' key:'%s' counter:'%s' thisCounterOnly:'%s'", $devid, $type, Utils::PrintAsString($key), Utils::PrintAsString($counter), Utils::PrintAsString($thisCounterOnly))); ZLog::Write(LOGLEVEL_DEBUG, sprintf("SqlStateMachine->CleanStates(): devid:'%s' type:'%s' key:'%s' counter:'%s' thisCounterOnly:'%s'", $devid, $type, Utils::PrintAsString($key), Utils::PrintAsString($counter), Utils::PrintAsString($thisCounterOnly)));
$params = $this->getParams($devid, $type, $key, $counter);
if ($counter === false) { if ($counter === false) {
// Remove all the states. Counter are 0 or >0, then deleting >= 0 deletes all // Remove all the states. Counter are 0 or >0, then deleting >= 0 deletes all
$sql = "DELETE FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($key) .":key AND counter >= :counter"; $sql = "DELETE FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($params, ':key') ." AND counter >= :counter";
} }
else if ($counter !== false && $thisCounterOnly === true) { else if ($counter !== false && $thisCounterOnly === true) {
$sql = "DELETE FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($key).":key AND counter = :counter"; $sql = "DELETE FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($params, ':key') ." AND counter = :counter";
} }
else { else {
$sql = "DELETE FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($key) .":key AND counter < :counter"; $sql = "DELETE FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid". $this->getSQLOp($params, ':key') ." AND counter < :counter";
} }
$params = $this->getParams($devid, $type, $key, $counter);
$sth = null; $sth = null;
try { try {
...@@ -492,8 +496,6 @@ class SqlStateMachine implements IStateMachine { ...@@ -492,8 +496,6 @@ class SqlStateMachine implements IStateMachine {
* @return int * @return int
*/ */
public function GetStateVersion() { public function GetStateVersion() {
ZLog::Write(LOGLEVEL_DEBUG, "SqlStateMachine->GetStateVersion().");
$sth = null; $sth = null;
$record = null; $record = null;
$version = IStateMachine::STATEVERSION_01; $version = IStateMachine::STATEVERSION_01;
...@@ -651,18 +653,20 @@ class SqlStateMachine implements IStateMachine { ...@@ -651,18 +653,20 @@ class SqlStateMachine implements IStateMachine {
/** /**
* Returns the SQL operator for the parameter. * Returns the SQL operator for the parameter.
* If the parameter is null then " IS " is returned, else " = ". * If the parameter is null then " IS NULL" is returned, else " = $key".
* *
* @param mixed $param * @param array& $params $params[$key] will be unset, if is_null($params[$key])
* @param string $key eg. ":key"
* *
* @access protected * @access protected
* @return string * @return string
*/ */
protected function getSQLOp($param) { protected function getSQLOp(&$params, $key) {
if ($param == null) { if (!array_key_exists($key, $params) || (array_key_exists($key, $params) && is_null($params[$key]))) {
return " IS "; unset($params[$key]);
return " IS NULL";
} }
return " = "; return " = $key";
} }
/** /**
...@@ -701,16 +705,20 @@ class SqlStateMachine implements IStateMachine { ...@@ -701,16 +705,20 @@ class SqlStateMachine implements IStateMachine {
/** /**
* Prepares PDOStatement which will be used to get the state hash. * Prepares PDOStatement which will be used to get the state hash.
* *
* @param string $key state uuid * @param array& $params $params[$key] will be unset, if is_null($params[$key])
* @param string $key =':key'
* @access protected * @access protected
* @return PDOStatement * @return PDOStatement
*/ */
protected function getStateHashStatement($key) { protected function getStateHashStatement(&$params, $key=':key') {
if (!isset($this->stateHashStatement) || $this->stateHashStatement == null) { if (!isset($this->stateHashStatement) || $this->stateHashStatement == null) {
$sql = "SELECT updated_at FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid ". (($key == null) ? " IS " : " = ") . ":key AND counter = :counter"; $sql = "SELECT updated_at FROM {$this->states_table} WHERE device_id = :devid AND state_type = :type AND uuid ". $this->getSQLOp($params, $key) ." AND counter = :counter";
$this->stateHashStatement = $this->getDbh()->prepare($sql); $this->stateHashStatement = $this->getDbh()->prepare($sql);
} }
else {
$this->getSQLOp($params, $key); // need to unset $params[':key'] for NULL
}
return $this->stateHashStatement; return $this->stateHashStatement;
} }
/** /**
...@@ -721,7 +729,6 @@ class SqlStateMachine implements IStateMachine { ...@@ -721,7 +729,6 @@ class SqlStateMachine implements IStateMachine {
* @throws UnavailableException * @throws UnavailableException
*/ */
protected function checkDbAndTables() { protected function checkDbAndTables() {
ZLog::Write(LOGLEVEL_DEBUG, "SqlStateMachine->checkDbAndTables(): Checking if database and tables are available.");
try { try {
$sqlStmt = sprintf("SHOW TABLES FROM %s", STATE_SQL_DATABASE); $sqlStmt = sprintf("SHOW TABLES FROM %s", STATE_SQL_DATABASE);
$sth = $this->getDbh(false)->prepare($sqlStmt); $sth = $this->getDbh(false)->prepare($sqlStmt);
...@@ -762,7 +769,7 @@ class SqlStateMachine implements IStateMachine { ...@@ -762,7 +769,7 @@ class SqlStateMachine implements IStateMachine {
$sqlStmt = sprintf("CREATE DATABASE %s", STATE_SQL_DATABASE); $sqlStmt = sprintf("CREATE DATABASE %s", STATE_SQL_DATABASE);
$sth = $dbh->prepare($sqlStmt); $sth = $dbh->prepare($sqlStmt);
$sth->execute(); $sth->execute();
ZLog::Write(LOGLEVEL_DEBUG, "SqlStateMachine->createDB(): Database created succesfully."); ZLog::Write(LOGLEVEL_DEBUG, "SqlStateMachine->createDB(): Database created successfully.");
$this->createTables(); $this->createTables();
$this->clearConnection($dbh); $this->clearConnection($dbh);
return true; return true;
...@@ -790,7 +797,7 @@ class SqlStateMachine implements IStateMachine { ...@@ -790,7 +797,7 @@ class SqlStateMachine implements IStateMachine {
)); ));
$sth = $this->getDbh()->prepare($sqlStmt); $sth = $this->getDbh()->prepare($sqlStmt);
$sth->execute(); $sth->execute();
ZLog::Write(LOGLEVEL_DEBUG, "SqlStateMachine->createTables(): tables created succesfully."); ZLog::Write(LOGLEVEL_DEBUG, "SqlStateMachine->createTables(): tables created successfully.");
return true; return true;
} }
catch (PDOException $ex) { catch (PDOException $ex) {
......
...@@ -207,7 +207,7 @@ include_once(ZPUSH_CONFIG); ...@@ -207,7 +207,7 @@ include_once(ZPUSH_CONFIG);
// This could be a WBXML problem.. try to get the complete request // This could be a WBXML problem.. try to get the complete request
else if ($ex instanceof WBXMLException) { else if ($ex instanceof WBXMLException) {
ZLog::Write(LOGLEVEL_FATAL, "Request could not be processed correctly due to a WBXMLException. Please report this including WBXML debug data logged. Be aware that the debug data could contain confidential information."); ZLog::Write(LOGLEVEL_FATAL, "Request could not be processed correctly due to a WBXMLException. Please report this including the 'WBXML debug data' logged. Be aware that the debug data could contain confidential information.");
} }
// Try to output some kind of error information. This is only possible if // Try to output some kind of error information. This is only possible if
......
...@@ -124,8 +124,14 @@ abstract class RequestProcessor { ...@@ -124,8 +124,14 @@ abstract class RequestProcessor {
$handler = ZPush::GetRequestHandlerForCommand(Request::GetCommandCode()); $handler = ZPush::GetRequestHandlerForCommand(Request::GetCommandCode());
// if there is an error decoding wbxml, consume remaining data and include it in the WBXMLException // if there is an error decoding wbxml, consume remaining data and include it in the WBXMLException
if (!$handler->Handle(Request::GetCommandCode())) { try {
throw new WBXMLException("Debug data: " . Request::GetInputAsBase64()); if (!$handler->Handle(Request::GetCommandCode())) {
throw new WBXMLException(sprintf("Unknown error in %s->Handle()", get_class($handler)));
}
}
catch (Exception $ex) {
ZLog::Write(LOGLEVEL_FATAL, "WBXML debug data: " . Request::GetInputAsBase64(), false);
throw $ex;
} }
// also log WBXML in happy case // also log WBXML in happy case
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment