+ *
+ * {@internal
+ * created 2000-01-01
+ * modified 2008-07-03, bilal arslan, added security fix
+ *
+ * $Id: ct_ldap.inc 1315 2011-03-03 00:02:52Z xmurrix $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class CT_Ldap {
+ ##
+ ## Configurable parameters
+ ##
+ var $ldap_host = "localhost";
+ var $ldap_port = 389;
+ var $basedn = "dc=your-domain, dc=com";
+ var $rootdn = "cn=root, dc=your-domain, dc=com";
+ var $rootpw = "secret";
+ var $objclass = "phplibdata";
+
+ ## end of configuration
+
+ var $ds;
+
+ function ac_start() {
+ $this->ds = ldap_connect($this->ldap_host, $this->ldap_port);
+ if(!$this->ds) {
+ $this->ac_halt("LDAP connect failed");
+ }
+ if(!ldap_bind($this->ds, $this->rootdn, $this->rootpw)) {
+ $this->ac_halt("LDAP bind failed");
+ }
+ }
+
+ function ac_halt($msg="") {
+ echo "Session_ldap failed: ".htmlentities($msg)." \n";
+ exit;
+ }
+
+ function ac_store($id, $name, $str) {
+ $dn = "cn=$id_$name, ".$this->basedn;
+ $entry = array(
+ "cn" => "$id_$name",
+ "str" => $str,
+ "objectclass" => $this->objclass
+ );
+ if(!@ldap_modify($this->ds, $dn, $entry)) {
+ if(!ldap_add($this->ds, $dn, $entry)) {
+ $this->ac_halt("LDAP add failed");
+ }
+ }
+ }
+
+ function ac_delete($id, $name) {
+ ldap_delete($this->ds, "cn=$id_$name, ".$this->basedn);
+ }
+
+ function ac_get_value($id, $name) {
+ $sr = ldap_search($this->ds, $this->basedn, "cn=$id_$name");
+ $inf = ldap_get_entries($this->ds, $sr);
+ $str = $inf[0]["str"][0];
+ ldap_free_result($sr);
+ return $str;
+ }
+
+ function ac_release_lock() {
+
+ }
+
+ function ac_get_lock() {
+
+ }
+
+ function ac_newid($str, $name) {
+ return $str;
+ }
+
+ function ac_auth($username, $password) {
+ ## we need a username and a md5() encrypted password
+ $sr = ldap_search($this->ds, $this->basedn, "username=$username");
+ if(ldap_count_entries($this->ds, $sr) > 0) {
+ $inf = ldap_get_entries($this->ds, $sr);
+ $passmd5 = $inf[0]["password"][0];
+ if(md5($password) == $passmd5) {
+ return array($inf[0]["uid"][0],
+ $inf[0]["perms"][0]);
+ }
+ }
+ return array();
+ }
+};
+?>
diff --git a/conlib/ct_null.inc b/conlib/ct_null.inc
new file mode 100644
index 0000000..668d33e
--- /dev/null
+++ b/conlib/ct_null.inc
@@ -0,0 +1,72 @@
+
+ * @author Sascha Schumann
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release
+ * @deprecated file deprecated in contenido release
+ *
+ * {@internal
+ * created 2000-01-01
+ * modified 2008-07-03, bilal arslan, added security fix
+ *
+ * $Id: ct_null.inc 1315 2011-03-03 00:02:52Z xmurrix $:
+ * }}
+ *
+ */
+ if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class CT_Null {
+ function ac_start() {
+ }
+
+ function ac_get_lock() {
+ }
+
+ function ac_release_lock() {
+ }
+
+ function ac_newid($str, $name) {
+ return $str;
+ }
+
+ function ac_store($id, $name, $str) {
+ return true;
+ }
+
+ function ac_delete($id, $name) {
+ }
+
+ function ac_gc($gc_time, $name) {
+ }
+
+ function ac_halt($s) {
+ echo "$s ";
+ exit;
+ }
+
+ function ac_get_value($id, $name) {
+ return "";
+ }
+}
+?>
diff --git a/conlib/ct_session.inc b/conlib/ct_session.inc
new file mode 100644
index 0000000..691e214
--- /dev/null
+++ b/conlib/ct_session.inc
@@ -0,0 +1,122 @@
+
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release 4.8.15
+ *
+ * {@internal
+ * created 2011-03-18
+ *
+ * $Id: $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class CT_Session
+{
+ /**
+ * Namespace in superglobal $_SESSION
+ * @var string
+ */
+ protected $_sNameSpace = 'ct_session_ns';
+
+ /**
+ * Session container's intialize method, configures PHP session and starts
+ * it, if not done before.
+ *
+ * @param array $aOptions Session container configuration as follows:
+ * - $aOptions['namespace'] (string) Namespace to use
+ * - $aOptions['session.*'] (string) Each possible session configuration
+ * see php.ini
+ */
+ public function ac_start(array $aOptions = array())
+ {
+ // set namespace
+ if (isset($aOptions['namespace'])) {
+ $this->_sNameSpace = $aOptions['namespace'];
+ }
+
+ // configure session
+ foreach ($aOptions as $k => $v) {
+ if (strpos($k, 'session.') === 0) {
+ @ini_set($k, $v);
+ }
+ }
+
+ if (!isset($_SESSION)) {
+ session_start();
+ }
+
+ if (!isset($_SESSION[$this->_sNameSpace])) {
+ $_SESSION[$this->_sNameSpace] = array();
+ }
+ }
+
+ public function ac_get_lock()
+ {
+ // no need to lock session
+ }
+
+ public function ac_release_lock()
+ {
+ // no need to release lock session
+ }
+
+ public function ac_gc($gc_time, $name)
+ {
+ // no need for garbace collection, will be done by PHP's gc
+ }
+
+ public function ac_store($id, $name, $str)
+ {
+ $_SESSION[$this->_sNameSpace][$name] = $str;
+ return true;
+ }
+
+ public function ac_get_value($id, $name)
+ {
+ return isset($_SESSION[$this->_sNameSpace][$name]) ? $_SESSION[$this->_sNameSpace][$name] : '';
+ }
+
+ public function ac_delete($id, $name)
+ {
+ // don't destroy session, untill backend and frontend uses it
+ #session_destroy();
+ if (isset($_SESSION[$this->_sNameSpace][$name])) {
+ $_SESSION[$this->_sNameSpace][$name] = '';
+ }
+ }
+
+ public function ac_newid($str, $name)
+ {
+ session_regenerate_id(false);
+ return session_id();
+ }
+
+ public function ac_halt($s)
+ {
+ die($s);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlib/ct_shm.inc b/conlib/ct_shm.inc
new file mode 100644
index 0000000..c0c7b19
--- /dev/null
+++ b/conlib/ct_shm.inc
@@ -0,0 +1,117 @@
+
+ * @con_notice
+ *
+ *
+ * @package ContenidoBackendArea
+ * @version 1.2
+ * @author Sascha Schumann
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release
+ * @deprecated file deprecated in contenido release
+ *
+ * {@internal
+ * created 2000-01-01
+ * modified 2008-07-03, bilal arslan, added security fix
+ *
+ * $Id: ct_shm.inc 1315 2011-03-03 00:02:52Z xmurrix $:
+ * }}
+ *
+ */
+
+ if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class CT_Shm {
+ ##
+ ## Define these parameters by overwriting or by
+ ## deriving your own class from it (recommened)
+ ##
+
+ var $max_sessions = 500; ## maximum supported sessions
+ var $shm_key = 900000; ## key of shared memory segment (unique)
+ var $shm_size = 64000; ## size in bytes
+
+ ## end of configuration
+
+ var $shmid; ## our shared memory handle
+ var $semid; ## our semaphore handle
+
+ function extract($id) {
+ return substr($id, 0, strpos($id, "_"));
+ }
+
+ function ac_start() {
+ $this->shmid = shm_attach($this->shm_key, $this->shm_size, 0600);
+ }
+
+ function ac_get_lock() {
+ $this->semid = sem_get($this->shm_key + 1);
+ sem_acquire($this->semid);
+ }
+
+ function ac_release_lock() {
+ shm_detach($this->shmid);
+ sem_release($this->semid);
+ }
+
+ function ac_newid($str, $name) {
+ for($i = 1; $i <= $this->max_sessions &&
+ (@shm_get_var($this->shmid, $i) != false); $i++);
+ $id = $i."_".$str;
+ $this->ac_store($id, $name, "");
+ return $id;
+ }
+
+ function ac_store($id, $name, $str) {
+ $val = "$id;".urlencode($name).";".urlencode($str).";".time();
+ shm_put_var($this->shmid, $this->extract($id), $val);
+ return true;
+ }
+
+ function ac_delete($id, $name) {
+ shm_remove_var($this->shmid, $this->extract($id));
+ }
+
+ function ac_gc($gc_time, $name) {
+ $cmp = time() - $gc_time * 60;
+ for($i = 1; $i <= $this->max_sessions; $i++) {
+ if(($val = @shm_get_var($this->shmid, $i)) != false) {
+ $dat = explode(";", $val);
+ if($name == $dat[1] && intval($dat[3]) < $cmp) {
+ shm_remove_var($this->shmid, $i);
+ }
+ }
+ }
+ }
+
+ function ac_halt($s) {
+ echo "$s ";
+ exit;
+ }
+
+ function ac_get_value($id, $name) {
+ $i = $this->extract($id);
+ $var = shm_get_var($this->shmid, $i);
+ if($var == "") return("");
+ $dat = explode(";", $var);
+ ## if classname or md5 id does not match...
+ if($name != urldecode($dat[1]) || $dat[0] != $id)
+ $this->ac_halt("security stop");
+ return urldecode($dat[2]);
+ }
+}
+?>
diff --git a/conlib/ct_sql.inc b/conlib/ct_sql.inc
new file mode 100644
index 0000000..60b73d0
--- /dev/null
+++ b/conlib/ct_sql.inc
@@ -0,0 +1,204 @@
+
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release
+ * @deprecated file deprecated in contenido release
+ *
+ * {@internal
+ * created 2002-07-21
+ * modified 2008-07-03, bilal arslan, added security fix
+ * modified 2009-11-06, Murat Purc, replaced deprecated functions (PHP 5.3 ready)
+ *
+ * $Id: ct_sql.inc 1094 2009-11-06 01:22:13Z xmurrix $:
+ * }}
+ *
+ */
+
+ if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class CT_Sql {
+ ##
+ ## Define these parameters by overwriting or by
+ ## deriving your own class from it (recommened)
+ ##
+
+
+ var $database_lock_semaphore = "";
+
+ var $encoding_mode = "base64";
+
+ ## end of configuration
+
+ var $db;
+
+ function ac_start() {
+ $name = $this->database_class;
+ $this->db = new $name;
+ }
+
+ function ac_get_lock() {
+ if ( "" != $this->database_lock_semaphore ) {
+ $query = sprintf("SELECT get_lock('%s')", $this->database_lock_semaphore);
+ while ( ! $this->db->query($query)) {
+ $t = 1 + time(); while ( $t > time() ) { ; }
+ }
+ }
+ }
+
+ function ac_release_lock() {
+ if ( "" != $this->database_lock_semaphore ) {
+ $query = sprintf("SELECT release_lock('%s')", $this->database_lock_semaphore);
+ $this->db->query($query);
+ }
+ }
+
+ function ac_gc($gc_time, $name) {
+
+// Security Fix
+ $timeout = time();
+ $sqldate = date("YmdHis", $timeout - (Contenido_Security::escapeDB($gc_time, $this->db) * 60));
+ $this->db->query(sprintf("DELETE FROM %s WHERE changed < '%s' AND name = '%s'",
+ $this->database_table,
+ $sqldate,
+ Contenido_Security::escapeDB($name, $this->db)));
+ }
+
+ function ac_store($id, $name, $str) {
+
+// Security Fix
+ $ret = true;
+
+ switch ( $this->encoding_mode ) {
+ case "slashes":
+ $str = addslashes($name . ":" . $str);
+ break;
+
+ case "base64":
+ default:
+ $str = base64_encode($name . ":" . $str);
+ };
+
+ $name = addslashes($name);
+
+ ## update duration of visit
+ global $HTTP_REFERER, $HTTP_USER_AGENT, $REMOTE_ADDR;
+
+ $now = date("YmdHis", time());
+ $uquery = sprintf("update %s set val='%s', changed='%s' where sid='%s' and name='%s'",
+ $this->database_table,
+ $str,
+ $now,
+ Contenido_Security::escapeDB($id, $this->db),
+ Contenido_Security::escapeDB($name, $this->db));
+ $squery = sprintf("select count(*) from %s where val='%s' and changed='%s' and sid='%s' and name='%s'",
+ $this->database_table,
+ $str,
+ $now,
+ Contenido_Security::escapeDB($id, $this->db),
+ Contenido_Security::escapeDB($name, $this->db));
+ $iquery = sprintf("insert into %s ( sid, name, val, changed ) values ('%s', '%s', '%s', '%s')",
+ $this->database_table,
+ Contenido_Security::escapeDB($id, $this->db),
+ Contenido_Security::escapeDB($name, $this->db),
+ $str,
+ $now);
+
+ $this->db->lock($this->database_table);
+ $this->db->query($uquery);
+
+ # FIRST test to see if any rows were affected.
+ # Zero rows affected could mean either there were no matching rows
+ # whatsoever, OR that the update statement did match a row but made
+ # no changes to the table data (i.e. UPDATE tbl SET col = 'x', when
+ # "col" is _already_ set to 'x') so then,
+ # SECOND, query(SELECT...) on the sid to determine if the row is in
+ # fact there,
+ # THIRD, verify that there is at least one row present, and if there
+ # is not, then
+ # FOURTH, insert the row as we've determined that it does not exist.
+
+ if ( $this->db->affected_rows() == 0
+ && $this->db->query($squery)
+ && $this->db->next_record() && $this->db->f(0) == 0
+ && !$this->db->query($iquery)) {
+
+ $ret = false;
+ }
+
+ $this->db->unlock();
+
+ return $ret;
+ }
+
+ function ac_delete($id, $name) {
+// Security Fix
+ $this->db->query(sprintf("delete from %s where name = '%s' and sid = '%s'",
+ $this->database_table,
+ Contenido_Security::escapeDB($name, $this->db),
+ Contenido_Security::escapeDB($id, $this->db)));
+ }
+
+ function ac_get_value($id, $name) {
+
+// Security Fix
+ $this->db->query(sprintf("select val from %s where sid = '%s' and name = '%s'",
+ $this->database_table,
+ Contenido_Security::escapeDB($id, $this->db),
+ Contenido_Security::escapeDB($name, $this->db)));
+
+ if ($this->db->next_record()) {
+ $str = $this->db->f("val");
+ $str2 = base64_decode( $str );
+
+ if (preg_match('/^' . $name . ':.*/', $str2)) {
+ $str = preg_replace('/^' . $name . ':/', '', $str2);
+ } else {
+
+ $str3 = stripslashes( $str );
+
+ if (preg_match('/^' . $name . ':.*/', $str3)) {
+ $str = preg_replace('/^' . $name . ':/', '', $str3);
+ } else {
+
+ switch ( $this->encoding_mode ) {
+ case "slashes":
+ $str = stripslashes($str);
+ break;
+
+ case "base64":
+ default:
+ $str = base64_decode($str);
+ }
+ }
+ };
+ return $str;
+ };
+ return "";
+ }
+
+ function ac_newid($str, $name) {
+ return $str;
+ }
+
+ function ac_halt($s) {
+ $this->db->halt($s);
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlib/db_mysql.inc b/conlib/db_mysql.inc
new file mode 100644
index 0000000..8a192cc
--- /dev/null
+++ b/conlib/db_mysql.inc
@@ -0,0 +1,436 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release
+ *
+ * {@internal
+ * created 2002-07-21
+ * modified 2008-07-04, bilal arslan, added security fix
+ * modified 2009-10-29, Murat Purc, removed deprecated functions (PHP 5.3 ready) extended DB_Sql_Abstract, added/optimized some functioms and some formatting
+ * modified 2009-12-18, Murat Purc, Replaced mysql_list_fields() against a SQL statement, see [#CON-262]
+ * modified 2011-03-03, Murat Purc, Some redesign and improvements (partial adaption to PHP 5 and extending DB_Sql_Abstract).
+ * modified 2011-03-13, Murat Purc, Cleanup and documentation.
+ * modified 2011-04-22, Murat Purc, Connect to DB server without database and more
+ * readable connection settings.
+ * modified 2011-05-17, Ortwin Pinke, bugfix in methode nextid().
+ *
+ * $Id: db_mysql.inc 1359 2011-05-17 13:24:24Z oldperl $:
+ * }}
+ *
+ */
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class DB_Sql extends DB_Sql_Abstract {
+
+ /**
+ * Constructor.
+ *
+ * @param array $options Optional assoziative options
+ */
+ public function __construct(array $options = array()) {
+ $options = array_merge($options, array(
+ 'type' => 'mysql'
+ ));
+ parent::__construct($options);
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_connect()
+ */
+ protected function _connect() {
+ $aCon = $this->_aDbCfg['connection'];
+ if (!isset($aCon['host']) || !isset($aCon['user']) || !isset($aCon['password'])) {
+ $this->halt('MySQL _connect() Connection settings not complete');
+ return null;
+ }
+
+ // establish connection, select database
+ $dbh = @mysql_connect($aCon['host'], $aCon['user'], $aCon['password']);
+ if (!$dbh || !is_resource($dbh)) {
+ $this->halt('MySQL _connect() Failed');
+ return null;
+ }
+
+ // set charset, default utf8
+ if (isset($aCon['charset'])) {
+ @mysql_set_charset($aCon['charset'], $dbh);
+ } else {
+ @mysql_set_charset($aCon['charset'], 'utf8');
+ }
+ //echo mysql_client_encoding($dbh);
+
+ if (isset($aCon['database'])) {
+ if (!@mysql_select_db($aCon['database'], $dbh)) {
+ $this->halt('MySQL _connect() Cannot use database ' . $aCon['database']);
+ return null;
+ }
+ $this->Database = $aCon['database'];
+ }
+
+ $this->User = $aCon['user'];
+
+ return $dbh;
+ }
+
+ /**
+ * Discard the query result
+ */
+ public function free() {
+ @mysql_free_result($this->Query_ID);
+ $this->Query_ID = 0;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_query()
+ */
+ protected function _query($sQuery) {
+ $this->Query_ID = @mysql_query($sQuery, $this->Link_ID);
+ $this->Row = 0;
+ $this->Error = $this->_getErrorMessage();
+ $this->Errno = $this->_getErrorNumber();
+ if (!$this->Query_ID) {
+ $this->halt($sQuery);
+ }
+ }
+
+ /**
+ * @see DB_Sql_Abstract::next_record()
+ */
+ public function next_record() {
+ $this->Record = @mysql_fetch_array($this->Query_ID);
+ $this->Row += 1;
+ $this->Error = $this->_getErrorMessage();
+ $this->Errno = $this->_getErrorNumber();
+
+ $stat = is_array($this->Record);
+ if (!$stat && $this->Auto_Free) {
+ $this->free();
+ }
+ return $stat;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::seek()
+ */
+ public function seek($pos = 0) {
+ $status = @mysql_data_seek($this->Query_ID, $pos);
+ if ($status) {
+ $this->Row = $pos;
+ } else {
+ $this->halt("seek($pos) failed: result has " . $this->num_rows() . " rows.");
+ // half assed attempt to save the day, but do not consider this
+ // documented or even desireable behaviour.
+ @mysql_data_seek($this->Query_ID, $this->num_rows());
+ $this->Row = $this->num_rows();
+ return 0;
+ }
+
+ return 1;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::lock()
+ */
+ public function lock($table, $mode = 'write') {
+ if ($this->_bNolock == true) {
+ return true;
+ }
+ $query = 'LOCK TABLES ';
+ if (is_array($table)) {
+ while (list($key, $value) = each($table)) {
+ if (!is_int($key)) {
+ // texts key are "read", "read local", "write", "low priority write"
+ $query .= "$value $key, ";
+ } else {
+ $query .= "$value $mode, ";
+ }
+ }
+ $query = substr($query, 0, -2);
+ } else {
+ $query .= "$table $mode";
+ }
+ $res = $this->query($query);
+ if (!$res) {
+ $this->halt('lock() failed.');
+ return 0;
+ }
+ return $res;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::unlock()
+ */
+ public function unlock() {
+ if ($this->_bNolock == true) {
+ return true;
+ }
+
+ $res = $this->query('UNLOCK TABLES');
+ if (!$res) {
+ $this->halt('unlock() failed.');
+ }
+ return $res;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::affected_rows()
+ */
+ public function affected_rows() {
+ return ($this->Link_ID) ? mysql_affected_rows($this->Link_ID) : 0;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::num_rows()
+ */
+ public function num_rows() {
+ return ($this->Query_ID) ? mysql_num_rows($this->Query_ID) : 0;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::num_fields()
+ */
+ public function num_fields() {
+ return ($this->Query_ID) ? mysql_num_fields($this->Query_ID) : 0;
+ }
+
+ /**
+ * get next possible id for requested db-table and update sequence table
+ *
+ * @param string $seq_name name of db-table to get nextid
+ * @return int nextid for requested table or 0 if an error occured
+ */
+ public function nextid($seq_name) {
+ $this->connect();
+
+ if ($this->lock($this->Seq_Table)) {
+ /* get sequence number (locked) and increment */
+ $q = sprintf("SELECT nextid FROM `%s` WHERE seq_name = '%s'", $this->Seq_Table, $seq_name);
+ $id = @mysql_query($q, $this->Link_ID);
+ $res = @mysql_fetch_array($id);
+
+ /* No current value, make one */
+ if (!is_array($res)) {
+ $currentid = 0;
+ $q = sprintf("INSERT INTO `%s` VALUES('%s', %s)", $this->Seq_Table, $seq_name, $currentid);
+ $id = @mysql_query($q, $this->Link_ID);
+ } else {
+ $currentid = $res['nextid'];
+ }
+ $nextid = $currentid + 1;
+ $q = sprintf("UPDATE `%s` SET nextid = '%s' WHERE seq_name = '%s'", $this->Seq_Table, $nextid, $seq_name);
+ $id = @mysql_query($q, $this->Link_ID);
+ $this->unlock();
+ } else {
+ $this->halt('Cannot lock ' . $this->Seq_Table . ' - has it been created?');
+ return 0;
+ }
+ return $nextid;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::disconnect()
+ */
+ public function disconnect() {
+ $this->_debug("Debug: Disconnecting $this->Link_ID...");
+ if (is_resource($this->Link_ID)) {
+ mysql_close($this->Link_ID);
+ $this->_removeConnection($this->Link_ID);
+ }
+ $this->Link_ID = 0;
+ $this->Query_ID = 0;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_metaData()
+ */
+ protected function _metaData($table = '', $full = false) {
+ $count = 0;
+ $id = 0;
+ $res = array();
+
+ /*
+ * Due to compatibility problems with Table we changed the behavior
+ * of metadata();
+ * depending on $full, metadata returns the following values:
+ *
+ * - full is false (default):
+ * $result[]:
+ * [0]["table"] table name
+ * [0]["name"] field name
+ * [0]["type"] field type
+ * [0]["len"] field length
+ * [0]["flags"] field flags
+ *
+ * - full is true
+ * $result[]:
+ * ["num_fields"] number of metadata records
+ * [0]["table"] table name
+ * [0]["name"] field name
+ * [0]["type"] field type
+ * [0]["len"] field length
+ * [0]["flags"] field flags
+ * ["meta"][field name] index of field named "field name"
+ * This last one could be used if you have a field name, but no index.
+ * Test: if (isset($result['meta']['myfield'])) { ...
+ */
+
+ // if no $table specified, assume that we are working with a query
+ // result
+ if (!empty($table)) {
+ $this->connect();
+ $id = mysql_query(sprintf('SELECT * FROM `%s` LIMIT 1', $table), $this->Link_ID); // PHP 5.3 fix 07.2009 O.Pinke, PHP 5.3 crashes with deprecated mysql_list_fields()
+ if (!$id) {
+ $this->halt('Metadata query failed.');
+ return false;
+ }
+ } else {
+ $id = $this->Query_ID;
+ if (!$id) {
+ $this->halt('No query specified.');
+ return false;
+ }
+ }
+
+ $count = @mysql_num_fields($id);
+
+ // made this IF due to performance (one if is faster than $count if's)
+ for ($i = 0; $i < $count; $i++) {
+ $res[$i]['table'] = @mysql_field_table($id, $i);
+ $res[$i]['name'] = @mysql_field_name($id, $i);
+ $res[$i]['type'] = @mysql_field_type($id, $i);
+ $res[$i]['len'] = @mysql_field_len($id, $i);
+ $res[$i]['flags'] = @mysql_field_flags($id, $i);
+ if ($full) {
+ $res['meta'][$res[$i]['name']] = $i;
+ }
+ }
+ if ($full) {
+ $res['num_fields'] = $count;
+ }
+
+ // free the result only if we were called on a table
+ if ($table) {
+ @mysql_free_result($id);
+ }
+ return $res;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_tableNames()
+ */
+ protected function _tableNames() {
+ $return = array();
+ $this->connect();
+ $h = @mysql_query('SHOW TABLES', $this->Link_ID);
+ $i = 0;
+ if (isset($h) && @mysql_num_rows($h) > 0) {
+ while ($info = @mysql_fetch_row($h)) {
+ $return[$i]['table_name'] = $info[0];
+ $return[$i]['tablespace_name'] = $this->Database;
+ $return[$i]['database'] = $this->Database;
+ $i++;
+ }
+ @mysql_free_result($h);
+ }
+ return $return;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::escape()
+ */
+ public function escape($sString) {
+ if (!is_string($sString))
+ return $sString;
+ $sResult = '';
+ if (is_resource($this->Link_ID) || $this->connect()) {
+ $sResult = mysql_real_escape_string($sString, $this->Link_ID);
+ }
+ return $sResult;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_serverInfo()
+ */
+ protected function _serverInfo() {
+ $arr['description'] = mysql_get_server_info($this->Link_ID);
+ return $arr;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_getErrorMessage()
+ */
+ protected function _getErrorMessage() {
+ if (is_resource($this->Link_ID)) {
+ return mysql_error($this->Link_ID);
+ } else {
+ return mysql_error();
+ }
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_getErrorNumber()
+ */
+ protected function _getErrorNumber() {
+ if (is_resource($this->Link_ID)) {
+ return mysql_errno($this->Link_ID);
+ } else {
+ return mysql_errno();
+ }
+ }
+
+ /**
+ * This method equates to mysql_fetch_object(). It returns the current
+ * result set as object or null if no result set is left. If optional
+ * param $sClassName is set, the result object is an instance of class
+ * $sClassName.
+ *
+ * @return object
+ *
+ * @author Holger Librenz
+ * @version 1.0
+ */
+ public function getResultObject($sClassName = null) {
+ $oResult = null;
+
+ if (is_resource($this->Link_ID) && is_resource($this->Query_ID)) {
+ if ($sClassName == null) {
+ $oResult = mysql_fetch_object($this->Query_ID);
+ } else {
+ $oResult = mysql_fetch_object($this->Query_ID, $sClassName);
+ }
+ }
+
+ return $oResult;
+ }
+
+ public function getServerInfo() {
+ return mysql_get_server_info($this->Link_ID);
+ }
+
+ public function getClientEncoding() {
+ return mysql_client_encoding($this->Link_ID);
+ }
+
+ public function getClientInfo() {
+ return mysql_get_client_info();
+ }
+}
diff --git a/conlib/db_mysqli.inc b/conlib/db_mysqli.inc
new file mode 100644
index 0000000..ae21dc1
--- /dev/null
+++ b/conlib/db_mysqli.inc
@@ -0,0 +1,500 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release
+ *
+ * {@internal
+ * created 2000-01-01
+ * modified 2008-07-04, bilal arslan, added security fix
+ * modified 2009-10-29, Murat Purc, removed deprecated functions (PHP 5.3 ready) extended DB_Sql_Abstract, added/optimized some functioms and some formatting
+ * modified 2009-12-29, Murat Purc, replaced is_resource() against mysqli compatible check [#CON-290]
+ * modified 2011-03-03, Murat Purc, Some redesign and improvements (partial adaption to PHP 5 and extending DB_Sql_Abstract).
+ * modified 2011-03-13, Murat Purc, Cleanup and documentation.
+ * modified 2011-04-22, Murat Purc, Connect to DB server without database and more
+ * readable connection settings.
+ *
+ * $Id: db_mysqli.inc 1350 2011-04-22 15:53:39Z xmurrix $:
+ * }}
+ *
+ */
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class DB_Sql extends DB_Sql_Abstract {
+
+ protected $_aDataTypes = array(
+ 0 => 'decimal',
+ 1 => 'tinyint',
+ 2 => 'smallint',
+ 3 => 'int',
+ 4 => 'float',
+ 5 => 'double',
+ 7 => 'timestamp',
+ 8 => 'bigint',
+ 9 => 'mediumint',
+ 10 => 'date',
+ 11 => 'time',
+ 12 => 'datetime',
+ 13 => 'year',
+ 252 => 'blob', // text, blob, tinyblob,mediumblob, etc...
+ 253 => 'string', // varchar and char
+ 254 => 'enum',
+ );
+
+ /**
+ * Constructor.
+ *
+ * @param array $options Optional assoziative options
+ */
+ public function __construct(array $options = array()) {
+ $options = array_merge($options, array(
+ 'type' => 'mysqli',
+ ));
+ parent::__construct($options);
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_connect()
+ */
+ protected function _connect() {
+ // feasible connection values are:
+ // - $options['connection']['host'] (string) Hostname or ip
+ // - $options['connection']['database'] (string) Database name
+ // - $options['connection']['user'] (string) User name
+ // - $options['connection']['password'] (string) User password
+ // - $options['connection']['options'] (array) Optional, MySQLi options array
+ // - $options['connection']['socket'] (int) Optional, socket
+ // - $options['connection']['port'] (int) Optional, port
+ // - $options['connection']['flags'] (int) Optional, flags
+ // see http://www.php.net/manual/en/mysqli.real-connect.php
+// extract($this->_aDbCfg['connection']);
+
+ if (!extension_loaded('mysqli')) {
+ $this->halt('MySQLi _connect() extension not loaded!');
+ return null;
+ }
+
+ $dbh = mysqli_init();
+ //print_r($dbh);
+ if (!$dbh) {
+ $this->halt('MySQLi _connect() Init failed');
+ return null;
+ }
+
+ $aCon = $this->_aDbCfg['connection'];
+ if (!isset($aCon['host']) || !isset($aCon['user']) || !isset($aCon['password'])) {
+ $this->halt('MySQLi _connect() Connection settings not complete');
+ return null;
+ }
+
+
+ // set existing option flags
+ if (isset($aCon['options']) && is_array($aCon['options'])) {
+ foreach ($aCon['options'] as $optKey => $optVal) {
+ mysqli_options($dbh, $optKey, $optVal);
+ }
+ }
+
+ if (($iPos = strpos($aCon['host'], ':')) !== false) {
+ list($aCon['host'], $aCon['port']) = explode(':', $aCon['host']);
+ } else {
+ $aCon['port'] = null;
+ }
+
+ if (!isset($aCon['socket'])) {
+ $aCon['socket'] = null;
+ }
+ if (!isset($aCon['flags'])) {
+ $aCon['flags'] = null;
+ }
+ if (!isset($aCon['database'])) {
+ $aCon['database'] = null;
+ }
+
+ $res = mysqli_real_connect(
+ $dbh, $aCon['host'], $aCon['user'], $aCon['password'], $aCon['database'], $aCon['port'], $aCon['socket'], $aCon['flags']
+ );
+
+
+ if (isset($aCon['charset'])) {
+ @mysqli_set_charset($dbh, $aCon['charset']);
+ } else {
+ @mysqli_set_charset($dbh, 'utf8');
+ }
+
+ //echo mysqli_character_set_name($dbh);
+
+ if ($res && $dbh && $aCon['database']) {
+ if (!@mysqli_select_db($dbh, $aCon['database'])) {
+ $this->halt('MySQLi _connect() Cannot use database ' . $aCon['database']);
+ return null;
+ }
+ $this->Database = $aCon['database'];
+ }
+
+ $this->User = $aCon['user'];
+
+ return $dbh;
+ }
+
+ /**
+ * Discard the query result
+ */
+ public function free() {
+ if (is_object($this->Query_ID)) {
+ mysqli_free_result($this->Query_ID);
+ }
+ $this->Query_ID = 0;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_query()
+ */
+ protected function _query($sQuery) {
+ $this->Query_ID = mysqli_query($this->Link_ID, $sQuery);
+ $this->Row = 0;
+ $this->Errno = $this->_getErrorNumber();
+ $this->Error = $this->_getErrorMessage();
+ if (!$this->Query_ID) {
+ $this->halt($sQuery);
+ }
+ }
+
+ /**
+ * @see DB_Sql_Abstract::next_record()
+ */
+ public function next_record() {
+ $this->Record = mysqli_fetch_array($this->Query_ID, MYSQLI_BOTH);
+ $this->Row += 1;
+ $this->Errno = $this->_getErrorNumber();
+ $this->Error = $this->_getErrorMessage();
+
+ $stat = is_array($this->Record);
+ if (!$stat && $this->Auto_Free) {
+ $this->free();
+ }
+ return $stat;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::seek()
+ */
+ public function seek($pos = 0) {
+ $status = mysqli_data_seek($this->Query_ID, $pos);
+ if ($status) {
+ $this->Row = $pos;
+ } else {
+ $this->halt("seek($pos) failed: result has " . $this->num_rows() . " rows.");
+ // half assed attempt to save the day, but do not consider this
+ // documented or even desireable behaviour.
+ mysqli_data_seek($this->Query_ID, $this->num_rows());
+ $this->Row = $this->num_rows();
+ return 0;
+ }
+
+ return 1;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::lock()
+ */
+ public function lock($table, $mode = 'write') {
+ if ($this->_bNolock == true) {
+ return true;
+ }
+ $query = 'LOCK TABLES ';
+ if (is_array($table)) {
+ while (list ($key, $value) = each($table)) {
+ if (!is_int($key)) {
+ // texts key are "read", "read local", "write", "low priority write"
+ $query .= "$value $key, ";
+ } else {
+ $query .= "$value $mode, ";
+ }
+ }
+ $query = substr($query, 0, -2);
+ } else {
+ $query .= "$table $mode";
+ }
+ $res = $this->query($query);
+ if (!$res) {
+ $this->halt('lock() failed.');
+ return 0;
+ }
+ return $res;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::unlock()
+ */
+ public function unlock() {
+ if ($this->_bNolock == true) {
+ return true;
+ }
+
+ $res = $this->query('UNLOCK TABLES');
+ if (!$res) {
+ $this->halt('unlock() failed.');
+ }
+ return $res;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::affected_rows()
+ */
+ public function affected_rows() {
+ return ($this->Link_ID) ? mysqli_affected_rows($this->Link_ID) : 0;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::num_rows()
+ */
+ public function num_rows() {
+ return ($this->Query_ID) ? mysqli_num_rows($this->Query_ID) : 0;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::num_fields()
+ */
+ public function num_fields() {
+ return ($this->Query_ID) ? mysqli_num_fields($this->Query_ID) : 0;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::nextid()
+ */
+ public function nextid($seq_name) {
+ $this->connect();
+
+ if ($this->lock($this->Seq_Table)) {
+ /* get sequence number (locked) and increment */
+ $q = sprintf("SELECT nextid FROM `%s` WHERE seq_name = '%s'", $this->Seq_Table, $seq_name);
+ $id = mysqli_query($this->Link_ID, $q);
+ $res = mysqli_fetch_array($id, MYSQLI_BOTH);
+
+ /* No current value, make one */
+ if (!is_array($res)) {
+ $currentid = 0;
+ $q = sprintf("INSERT INTO `%s` VALUES('%s', %s)", $this->Seq_Table, $seq_name, $currentid);
+ $id = mysqli_query($this->Link_ID, $q);
+ } else {
+ $currentid = $res["nextid"];
+ }
+ $nextid = $currentid + 1;
+ $q = sprintf("UPDATE `%s` set nextid = '%s' WHERE seq_name = '%s'", $this->Seq_Table, $nextid, $seq_name);
+ $id = mysqli_query($this->Link_ID, $q);
+ $this->unlock();
+ } else {
+ $this->halt('Cannot lock ' . $this->Seq_Table . ' - has it been created?');
+ return 0;
+ }
+ return $nextid;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::disconnect()
+ */
+ public function disconnect() {
+ //$this->_debug("Debug: Disconnecting $this->Link_ID...");
+ if (is_resource($this->Link_ID)) {
+ mysqli_close($this->Link_ID);
+ $this->_removeConnection($this->Link_ID);
+ }
+ $this->Link_ID = 0;
+ $this->Query_ID = 0;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_metaData()
+ */
+ protected function _metaData($table = '', $full = false) {
+ $count = 0;
+ $id = 0;
+ $res = array();
+
+ /*
+ * Due to compatibility problems with Table we changed the behavior
+ * of metadata();
+ * depending on $full, metadata returns the following values:
+ *
+ * - full is false (default):
+ * $result[]:
+ * [0]["table"] table name
+ * [0]["name"] field name
+ * [0]["type"] field type
+ * [0]["len"] field length
+ * [0]["flags"] field flags
+ *
+ * - full is true
+ * $result[]:
+ * ["num_fields"] number of metadata records
+ * [0]["table"] table name
+ * [0]["name"] field name
+ * [0]["type"] field type
+ * [0]["len"] field length
+ * [0]["flags"] field flags
+ * ["meta"][field name] index of field named "field name"
+ * This last one could be used if you have a field name, but no index.
+ * Test: if (isset($result['meta']['myfield'])) { ...
+ */
+
+ // if no $table specified, assume that we are working with a query
+ // result
+ if ($table) {
+ $this->connect();
+ $id = mysqli_query($this->Link_ID, sprintf("SELECT * FROM `%s` LIMIT 1", $table));
+ if (!$id) {
+ $this->halt('Metadata query failed.');
+ return false;
+ }
+ } else {
+ $id = $this->Query_ID;
+ if (!$id) {
+ $this->halt('No query specified.');
+ return false;
+ }
+ }
+
+ $count = mysqli_num_fields($id);
+
+ // made this IF due to performance (one if is faster than $count if's)
+ for ($i = 0; $i < $count; $i ++) {
+ $finfo = mysqli_fetch_field($id);
+ $res[$i]['table'] = $finfo->table;
+ $res[$i]['name'] = $finfo->name;
+ $res[$i]['type'] = $this->_aDataTypes[$finfo->type];
+ $res[$i]['len'] = $finfo->max_length;
+ $res[$i]['flags'] = $finfo->flags;
+ if ($full) {
+ $res['meta'][$res[$i]['name']] = $i;
+ }
+ }
+ if ($full) {
+ $res['num_fields'] = $count;
+ }
+
+ // free the result only if we were called on a table
+ if ($table) {
+ mysqli_free_result($id);
+ }
+ return $res;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::escape()
+ */
+ public function escape($sString) {
+ $sResult = '';
+ if (is_resource($this->Link_ID) || $this->connect()) {
+ $sResult = mysqli_real_escape_string($this->Link_ID, $sString);
+ };
+ return $sResult;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_tableNames()
+ */
+ protected function _tableNames() {
+ $return = array();
+ $this->connect();
+ $h = @mysqli_query($this->Link_ID, 'SHOW TABLES');
+ $i = 0;
+ if (isset($h) && @mysqli_num_rows($h) > 0) {
+ while ($info = mysqli_fetch_row($h)) {
+ $return[$i]['table_name'] = $info[0];
+ $return[$i]['tablespace_name'] = $this->Database;
+ $return[$i]['database'] = $this->Database;
+ $i ++;
+ }
+
+ mysqli_free_result($h);
+ }
+ return $return;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_serverInfo()
+ */
+ protected function _serverInfo() {
+ $arr['description'] = mysqli_get_server_info($this->Link_ID);
+ return $arr;
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_getErrorMessage()
+ */
+ protected function _getErrorMessage() {
+ if ($this->Link_ID) {
+ return @mysqli_error($this->Link_ID);
+ } else {
+ return @mysqli_connect_error();
+ }
+ }
+
+ /**
+ * @see DB_Sql_Abstract::_getErrorNumber()
+ */
+ protected function _getErrorNumber() {
+ if ($this->Link_ID) {
+ return @mysqli_errno($this->Link_ID);
+ } else {
+ return @mysqli_connect_errno();
+ }
+ }
+
+ /**
+ * This method equates to mysqli_fetch_object(). It returns the current
+ * result set as object or null if no result set is left. If optional
+ * param $sClassName is set, the result object is an instance of class
+ * $sClassName.
+ *
+ * @return object|null
+ *
+ * @author Holger Librenz
+ * @version 1.0
+ */
+ public function getResultObject($sClassName = null) {
+ $oResult = null;
+
+ if (is_resource($this->Link_ID) && is_resource($this->Query_ID)) {
+ if ($sClassName == null) {
+ $oResult = mysqli_fetch_object($this->Query_ID);
+ } else {
+ $oResult = mysqli_fetch_object($this->Query_ID, $sClassName);
+ }
+ }
+
+ return $oResult;
+ }
+
+ public function getServerInfo() {
+ return mysqli_get_server_info($this->Link_ID);
+ }
+
+ public function getClientEncoding() {
+ $oCharSet = mysqli_get_charset($this->Link_ID);
+ return $oCharSet->charset;
+ }
+
+ public function getClientInfo() {
+ return mysqli_get_client_info();
+ }
+}
\ No newline at end of file
diff --git a/conlib/db_pdo_mysql.inc b/conlib/db_pdo_mysql.inc
new file mode 100644
index 0000000..6b758d4
--- /dev/null
+++ b/conlib/db_pdo_mysql.inc
@@ -0,0 +1,513 @@
+
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release 4.8.15
+ *
+ * {@internal
+ * created 2011-02-28
+ * modified 2011-03-13, Murat Purc, Cleanup and documentation.
+ * modified 2011-04-22, Murat Purc, Connect to DB server without database and more
+ * readable connection settings.
+ *
+ * $Id: $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class DB_Sql extends DB_Sql_Abstract
+{
+
+ /**
+ * PDO connection
+ * @var PDO
+ */
+ public $Query_ID;
+
+ /**
+ * PDO statement
+ * @var PDOStatement
+ */
+ public $Link_ID;
+
+ protected $_aDataTypes = array(
+ PDO::PARAM_BOOL => 'bool',
+ PDO::PARAM_NULL => 'null',
+ PDO::PARAM_INT => 'int',
+ PDO::PARAM_STR => 'string',
+ PDO::PARAM_LOB => 'blob',
+ PDO::PARAM_STMT => 'statement'
+ );
+
+
+ /**
+ * Constructor.
+ *
+ * @param array $options Optional assoziative options
+ */
+ public function __construct(array $options = array())
+ {
+ $options = array_merge($options, array(
+ 'type' => 'pdo_mysql',
+ ));
+ parent::__construct($options);
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::_connect()
+ */
+ protected function _connect()
+ {
+ $aCon = $this->_aDbCfg['connection'];
+ if (!isset($aCon['host']) || !isset($aCon['user']) || !isset($aCon['password'])) {
+ $this->halt('MySQL _connect() Connection settings not complete');
+ return null;
+ }
+
+ $dsn = 'mysql:';
+ if (isset($aCon['database'])) {
+ $dsn .= 'dbname=' . $aCon['database'] . ';';
+ }
+ $dsn .= 'host=' . $aCon['host'];
+
+ if (!isset($aCon['driver_options']) || !is_array($aCon['driver_options'])) {
+ $aCon['driver_options'] = array();
+ }
+
+ try {
+ // Create a new PDO connection
+ $dbh = new PDO($dsn, $aCon['user'], $aCon['password'], $aCon['driver_options']);
+ } catch (PDOException $e) {
+ $this->Errno = $e->getCode();
+ $this->Error = $e->getMessage();
+ }
+
+ if (!$dbh) {
+ $this->halt('PDO_MySQL _connect() Failed');
+ return null;
+ }
+
+ if (isset($aCon['database'])) {
+ $this->Database = $aCon['database'];
+ }
+ $this->User = $aCon['user'];
+
+ return $dbh;
+ }
+
+
+ /**
+ * Discard the query result
+ */
+ public function free()
+ {
+ if ($this->Query_ID) {
+ $this->Query_ID->closeCursor();
+ unset($this->Query_ID);
+ }
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::_query()
+ */
+ protected function _query($sQuery)
+ {
+ $this->Query_ID = $this->Link_ID->query($sQuery);
+ $this->Row = 0;
+ $this->Errno = $this->_getErrorNumber();
+ $this->Error = $this->_getErrorMessage();
+ if (!$this->Query_ID) {
+ $this->halt($sQuery);
+ }
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::next_record()
+ */
+ public function next_record()
+ {
+ $this->Record = $this->Query_ID->fetch(PDO::FETCH_BOTH);
+ $this->Row += 1;
+ $this->Errno = $this->_getErrorNumber();
+ $this->Error = $this->_getErrorMessage();
+ $stat = is_array($this->Record);
+ if (!$stat && $this->Auto_Free) {
+ $this->free();
+ }
+ return $stat;
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::seek()
+ */
+ public function seek($pos = 0)
+ {
+ throw new Exception('seek not supported');
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::lock()
+ */
+ public function lock($table, $mode = 'write')
+ {
+ if ($this->_bNolock == true) {
+ return true;
+ }
+ $query = 'LOCK TABLES ';
+ if (is_array($table)) {
+ while (list ($key, $value) = each($table)) {
+ if (!is_int($key)) {
+ // texts key are "read", "read local", "write", "low priority write"
+ $query .= "$value $key, ";
+ } else {
+ $query .= "$value $mode, ";
+ }
+ }
+ $query = substr($query, 0, -2);
+ } else {
+ $query .= "$table $mode";
+ }
+ $res = $this->query($query);
+ if (!$res) {
+ $this->halt('lock() failed.');
+ return 0;
+ }
+ return $res;
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::unlock()
+ */
+ public function unlock()
+ {
+ if ($this->_bNolock == true) {
+ return true;
+ }
+
+ $res = $this->query('UNLOCK TABLES');
+ if (!$res) {
+ $this->halt('unlock() failed.');
+ }
+ return $res;
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::affected_rows()
+ */
+ public function affected_rows()
+ {
+ return ($this->Query_ID) ? $this->Query_ID->rowCount() : 0;
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::num_rows()
+ */
+ public function num_rows()
+ {
+ if ($this->Query_ID) {
+ // clone statement and get count by using fetchAll
+ $stmt = clone $this->Query_ID;
+ $res = $stmt->fetchAll();
+ return (is_array($res)) ? count($stmt->fetchAll()) : 0;
+ } else {
+ return 0;
+ }
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::num_fields()
+ */
+ public function num_fields()
+ {
+ return count($this->Record / 2);
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::nextid()
+ */
+ public function nextid($seq_name)
+ {
+ $this->connect();
+
+ if ($this->lock($this->Seq_Table)) {
+ /* get sequence number (locked) and increment */
+ $q = sprintf("SELECT nextid FROM `%s` WHERE seq_name = '%s'", $this->Seq_Table, $seq_name);
+ $stmt = $this->Link_ID->query($q);
+ $res = ($stmt) ? $stmt->fetch(PDO::FETCH_BOTH) : null;
+
+ /* No current value, make one */
+ if (!is_array($res)) {
+ $currentid = 0;
+ $q = sprintf("INSERT INTO `%s` VALUES('%s', %s)", $this->Seq_Table, $seq_name, $currentid);
+ $stmt = $this->Link_ID->query($q);
+ } else {
+ $currentid = $res['nextid'];
+ }
+ $nextid = $currentid + 1;
+ $q = sprintf("UPDATE `%s` set nextid = '%s' WHERE seq_name = '%s'", $this->Seq_Table, $nextid, $seq_name);
+ $stmt = $this->Link_ID->query($q);
+ $this->unlock();
+ } else {
+ $this->halt('Cannot lock ' . $this->Seq_Table . ' - has it been created?');
+ return 0;
+ }
+ return $nextid;
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::disconnect()
+ */
+ public function disconnect()
+ {
+ $this->_debug("Debug: Disconnecting $this->Link_ID...");
+ // Destroy the PDO and PDOStatement object
+ $this->_removeConnection($this->Link_ID);
+ $this->Link_ID = null;
+ $this->Query_ID = null;
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::_metaData()
+ */
+ protected function _metaData($table = '', $full = false)
+ {
+ $count = 0;
+ $id = 0;
+ $res = array();
+
+ /*
+ * Due to compatibility problems with Table we changed the behavior
+ * of metadata();
+ * depending on $full, metadata returns the following values:
+ *
+ * - full is false (default):
+ * $result[]:
+ * [0]["table"] table name
+ * [0]["name"] field name
+ * [0]["type"] field type
+ * [0]["len"] field length
+ * [0]["flags"] field flags
+ *
+ * - full is true
+ * $result[]:
+ * ["num_fields"] number of metadata records
+ * [0]["table"] table name
+ * [0]["name"] field name
+ * [0]["type"] field type
+ * [0]["len"] field length
+ * [0]["flags"] field flags
+ * ["meta"][field name] index of field named "field name"
+ * This last one could be used if you have a field name, but no index.
+ * Test: if (isset($result['meta']['myfield'])) { ...
+ */
+
+ // if no $table specified, assume that we are working with a query
+ // result
+ if ($table) {
+ $this->connect();
+ $stmt = $this->Link_ID->query(sprintf("DESCRIBE `%s`", $table));
+ if (!$stmt) {
+ $this->halt('Metadata query failed.');
+ return false;
+ }
+ } else {
+ $stmt = $this->Query_ID;
+ if (!$stmt) {
+ $this->halt('No query specified.');
+ return false;
+ }
+ }
+
+ // loop thru the result and collect meta data
+ $res = array();
+ while ($rs = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $field = $this->_getFieldTypeDetails($rs['Type']);
+ $item = array();
+ $item['table'] = $table;
+ $item['name'] = $rs['Field'];
+ $item['type'] = $field['type'];
+ $item['len'] = $field['size'];
+ $item['flags'] = null; // @todo detect field flags
+ $res[$count] = $item;
+ if ($full) {
+ $res['meta'][$item['name']] = $count;
+ }
+ $count++;
+ }
+ if ($full) {
+ $res['num_fields'] = $count;
+ }
+
+ unset($stmt);
+
+ return $res;
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::escape()
+ */
+ public function escape($sString)
+ {
+ $sResult = '';
+ $sResult = str_replace("'", "''", $sString);
+ // @todo adapt pdo quote method to own requirements
+# if ($this->connect()) {
+# $sResult = $this->Link_ID->quote($sString);
+# }
+ return $sResult;
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::_tableNames()
+ */
+ protected function _tableNames()
+ {
+ $return = array();
+
+ $stmt = $this->Link_ID->query('SHOW TABLES');
+ $i = 0;
+ while ($rs = $stmt->fetch(PDO::FETCH_NUM)) {
+ $return[$i]['table_name'] = $rs[0];
+ $return[$i]['tablespace_name'] = $this->Database;
+ $return[$i]['database'] = $this->Database;
+ $i ++;
+ }
+
+ unset($stmt);
+
+ return $return;
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::_serverInfo()
+ */
+ protected function _serverInfo()
+ {
+ $arr['description'] = $this->Link_ID->getAttribute(PDO::ATTR_SERVER_INFO);
+ $arr['version'] = $this->Link_ID->getAttribute(PDO::ATTR_SERVER_VERSION);
+ return $arr;
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::_getErrorMessage()
+ */
+ protected function _getErrorMessage()
+ {
+ $err = null;
+ if ($this->Query_ID) {
+ $err = $this->Query_ID->errorInfo();
+ } elseif ($this->Link_ID) {
+ $err = $this->Link_ID->errorInfo();
+ }
+ if (null !== $err && (int) $err[0] > 0) {
+ return $err[2];
+ }
+ }
+
+
+ /**
+ * @see DB_Sql_Abstract::_getErrorNumber()
+ */
+ protected function _getErrorNumber()
+ {
+ $err = null;
+ if ($this->Query_ID) {
+ $err = $this->Query_ID->errorCode();
+ } elseif ($this->Link_ID) {
+ $err = $this->Link_ID->errorCode();
+ }
+ if (null !== $err && (int) $err[0] > 0) {
+ return $err[0];
+ }
+ }
+
+
+ protected function _getFieldTypeDetails($field)
+ {
+ $ret = array('type' => null, 'size' => null);
+ if (!$field) {
+ return $ret;
+ }
+ if (preg_match('/^([a-z].*)\(([0-9].*)\)/', $field, $matches)) {
+ $ret = array('type' => $matches[1], 'size' => (int) $matches[2]);
+ } else {
+ $ret['type'] = $field;
+ }
+ return $ret;
+ }
+
+ /**
+ * This method festches the current result set and returns the it as object or
+ * null if no result set is left. If optional param $sClassName is set, the
+ * result object is an instance of class $sClassName.
+ *
+ * @param string sClassName Optional the classname to instantiate.
+ * @return object|null
+ */
+ public function getResultObject($sClassName = null)
+ {
+ $oResult = null;
+
+ if ($this->Link_ID && $this->Query_ID) {
+ if ($rs = $this->Query_ID->fetch(PDO::FETCH_ASSOC)) {
+ if ($sClassName == null) {
+ $oResult = (object) $rs;
+ } else {
+ $oResult = new $sClassName();
+ foreach ($rs as $key => $value) {
+ $oResult->{$key} = $value;
+ }
+ }
+ }
+ }
+
+ return $oResult;
+ }
+
+ public function getServerInfo() {
+ return '';
+ }
+
+ public function getClientEncoding() {
+ return '';
+ }
+
+}
diff --git a/conlib/db_sql_abstract.inc b/conlib/db_sql_abstract.inc
new file mode 100644
index 0000000..8ea766e
--- /dev/null
+++ b/conlib/db_sql_abstract.inc
@@ -0,0 +1,804 @@
+
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since Contenido release 4.8.15
+ *
+ * {@internal
+ * created 2011-03-03
+ * modified 2011-03-13, Murat Purc, Added FETCH_* constants, extended toArray(),
+ * moved close(), table_names() and server_info()
+ * from child implementations.
+ *
+ * $Id:$:
+ * }}
+ *
+ */
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+abstract class DB_Sql_Abstract {
+
+ const HALT_YES = 'yes';
+ const HALT_NO = 'no';
+ const HALT_REPORT = 'report';
+ const FETCH_NUMERIC = 'numeric';
+ const FETCH_ASSOC = 'assoc';
+ const FETCH_BOTH = 'both';
+
+ /**
+ * Assoziative list of database connections
+ * @array
+ */
+ protected static $_connectionCache = array();
+
+ /**
+ * Assoziative list of database tables metadata
+ * @array
+ */
+ protected static $_metaCache = array();
+
+ /**
+ * Sequence table name
+ * @var string
+ */
+ public $Seq_Table = '';
+
+ /**
+ * Flag to print debug messages
+ * @var bool
+ */
+ public $Debug = false;
+
+ /**
+ * Database name
+ * @var string
+ */
+ public $Database = '';
+
+ /**
+ * Database connection user name
+ * @var string
+ */
+ public $User = '';
+
+ /**
+ * Database connection password
+ * @var string
+ */
+ public $Password = '';
+
+ /**
+ * Database connection resource
+ * @var resource|int
+ */
+ public $Link_ID = 0;
+
+ /**
+ * Resource identifier of last executed query
+ * @var resource
+ */
+ public $Query_ID = 0;
+
+ /**
+ * Recordset data array. Could contain either indexed or assoziative result set (or both)
+ * @var array
+ */
+ public $Record = array();
+
+ /**
+ * The row position inside last executed select result
+ * @var int
+ */
+ public $Row;
+
+ /**
+ * Database error number
+ * @var int
+ */
+ public $Errno = 0;
+
+ /**
+ * Database error message
+ * @var string
+ */
+ public $Error = '';
+
+ /**
+ * Flag to automatic free results
+ * @var int
+ */
+ public $Auto_Free = 0;
+
+ /**
+ * Database identification string.
+ * @var string
+ */
+ public $type = '';
+
+ /**
+ * Revision. This is an api revision, not a CVS revision
+ * @var string
+ */
+ public $revision = '1.3';
+
+ /**
+ * Halt status during occured errors. Feasible values are
+ * - "yes" (halt with message)
+ * - "no" (ignore errors quietly)
+ * - "report" (ignore errror, but spit a warning)
+ * @var string
+ */
+ public $Halt_On_Error = 'no';
+
+ /**
+ * Text to prepend to the halt message
+ * @var string
+ */
+ protected $_sHaltMsgPrefix = '';
+
+ /**
+ * Default database connection for all instances
+ * @var array
+ */
+ protected static $_aDefaultDbCfg = array();
+
+ /**
+ * Database connection configuration for current instance
+ * @var array
+ */
+ protected $_aDbCfg;
+
+ /**
+ * Enable profiling
+ * @var bool
+ */
+ protected $_bProfile = false;
+
+ /**
+ * Don't lock tables
+ * @var bool
+ */
+ protected $_bNolock = false;
+
+ /**
+ * Profile data array
+ * @var array
+ */
+ protected static $_aProfileData = array();
+ // @todo intended to map new protected properties against old public
+ // properties by using magic __call method
+ protected $_oldProperties = array(
+ 'Seq_Table' => '_sSeqTable',
+ 'Debug' => '_bDebug',
+ 'Database' => '_sDatabase',
+ 'User' => '_sUser',
+ 'Password' => '_sPassword',
+ 'Link_ID' => '_mLinkId',
+ 'Query_ID' => '_mQueryId',
+ 'Auto_Free' => '_iAutoFree',
+ 'type' => '_sType',
+ 'revision' => '_sRevision',
+ 'Halt_On_Error' => '_sHaltOnError',
+ );
+
+ /**
+ * Constructor, sets passed options and connects to the DBMS, if not done before.
+ *
+ * Uses default connection settings, passed $options['db_connection'] settings
+ * will overwrite connection settings for current instance.
+ *
+ * @param array $options Assoziative options as follows:
+ * - $options['sequenceTable'] (string) Optional, the sequence table name
+ * - $options['nolock'] (bool) Optional, not lock table
+ * - $options['haltBehavior'] (string) Optional, halt behavior on occured errors
+ * - $options['haltMsgPrefix'] (string) Optional, Text to prepend to the halt message
+ * - $options['type'] (string) Database driver name
+ * - $options['enableProfiling'] (bool) Optional, flag to enable profiling
+ * - $options['connection'] (array) Optional, assoziative connection settings
+ * @return void
+ */
+ protected function __construct(array $options) {
+ // use default connection configuration, but overwrite it by passed options
+ $this->_aDbCfg = array_merge(self::$_aDefaultDbCfg, $options);
+
+ if (isset($this->_aDbCfg['sequenceTable']) && is_string($this->_aDbCfg['sequenceTable'])) {
+ $this->Seq_Table = $this->_aDbCfg['sequenceTable'];
+ }
+
+ if (isset($this->_aDbCfg['haltBehavior'])) {
+ switch ($this->_aDbCfg['haltBehavior']) {
+ case self::HALT_YES:
+ $this->Halt_On_Error = self::HALT_YES;
+ break;
+ case self::HALT_NO:
+ $this->Halt_On_Error = self::HALT_NO;
+ break;
+ case self::HALT_REPORT:
+ $this->Halt_On_Error = self::HALT_REPORT;
+ break;
+ }
+ }
+
+ if (isset($this->_aDbCfg['haltMsgPrefix']) && is_string($this->_aDbCfg['haltMsgPrefix'])) {
+ $this->_sHaltMsgPrefix = $this->_aDbCfg['haltMsgPrefix'];
+ }
+
+ if (isset($this->_aDbCfg['type']) && is_string($this->_aDbCfg['type'])) {
+ $this->type = $this->_aDbCfg['type'];
+ }
+
+ if (isset($this->_aDbCfg['nolock']) && is_bool($this->_aDbCfg['nolock'])) {
+ $this->_bNolock = (bool) $this->_aDbCfg['nolock'];
+ }
+ if (isset($this->_aDbCfg['enableProfiling']) && is_bool($this->_aDbCfg['enableProfiling'])) {
+ $this->_bProfile = (bool) $this->_aDbCfg['enableProfiling'];
+ }
+
+ $this->connect();
+ }
+
+ /**
+ * Setter for default database configuration, the connection values.
+ *
+ * @param array $defaultDbCfg
+ */
+ public static function setDefaultConfiguration(array $defaultDbCfg) {
+ self::$_aDefaultDbCfg = $defaultDbCfg;
+ }
+
+ /**
+ * Establishes a connection to the database server.
+ *
+ * @return object|resource|int|null Connection handler. Return value depends on
+ * used driver and is null in case of an error.
+ */
+ public function connect() {
+ if ($this->Link_ID = $this->_getConnection($this->_aDbCfg['connection'])) {
+ return $this->Link_ID;
+ } else {
+ if ($this->Link_ID = $this->_connect()) {
+ $this->_setConnection($this->_aDbCfg['connection'], $this->Link_ID);
+ return $this->Link_ID;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Resource id/object of current connection
+ *
+ * @return mixed The resource id/object of current connection
+ */
+ public function link_id() {
+ return $this->Link_ID;
+ }
+
+ /**
+ * Returns connection from connection cache
+ *
+ * @param mixed $data Connection data array
+ * @return mixed Either The connection (object, resource, integer) or null
+ */
+ protected function _getConnection($data) {
+ $hash = md5($this->type . '-' . (is_array($data) ? implode('-', $data) : (string) $data));
+ return (isset(self::$_connectionCache[$hash])) ? self::$_connectionCache[$hash] : null;
+ }
+
+ /**
+ * Stores connection in connection cache
+ *
+ * @param mixed $data Connection data array
+ * @param mixed $connection The connection to store in cache
+ * @return void
+ */
+ protected function _setConnection($data, $connection) {
+ $hash = md5($this->type . '-' . (is_array($data) ? implode('-', $data) : (string) $data));
+ self::$_connectionCache[$hash] = $connection;
+ }
+
+ /**
+ * Removes connection from cache
+ *
+ * @param mixed $connection The connection to remove in cache
+ * @return void
+ */
+ protected function _removeConnection($connection) {
+ foreach (self::$_connectionCache as $hash => $res) {
+ if ($res == $connection) {
+ unset(self::$_connectionCache[$hash]);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Returns the current cursor
+ *
+ * @return resource Current cursor
+ */
+ public function query_id() {
+ return $this->Query_ID;
+ }
+
+ /**
+ * Connects to the database.
+ *
+ * @return object|resource|int|null Connection handler. Return value depends on
+ * used driver and is null in case of an error.
+ */
+ abstract protected function _connect();
+
+ /**
+ * Executes the query.
+ *
+ * @param string $sQuery The query to execute.
+ * @param mixed Accepts additional unlimited parameter, where the parameter
+ * will be replaced against format definitions in query.
+ * @return resource|int|object|bool Depends on used database driver, false on error
+ */
+ public function query($sQuery) {
+ // No empty queries, please, since PHP4 chokes on them
+ if ($sQuery == '') {
+ // The empty query string is passed on from the constructor, when calling
+ // the class without a query, e.g. in situations '$db = new DB_Sql_Subclass;'
+ return false;
+ }
+
+ $aArgs = func_get_args();
+ if (count($aArgs) > 1) {
+ array_shift($aArgs);
+ $sQuery = $this->_prepareQueryf($sQuery, $aArgs);
+ }
+
+ if (!$this->connect()) {
+ return false;
+ }
+
+ // new query, discard previous result
+ if ($this->Query_ID) {
+ $this->free();
+ }
+
+ $this->_debug('Debug: query = ' . $sQuery);
+
+ if ($this->_bProfile) {
+ $fStart = microtime(true);
+ }
+
+ $this->_query($sQuery);
+
+ if ($this->_bProfile) {
+ $fEnd = microtime(true);
+ $this->_addProfileData($fStart, $fEnd, $sQuery);
+ }
+
+ // Will return nada if it fails. That's fine.
+ return $this->Query_ID;
+ }
+
+ /**
+ * Executes the query.
+ *
+ * @param string $sQuery The query to execute
+ * @return void
+ */
+ abstract protected function _query($sQuery);
+
+ /**
+ * Prepares a query with parameter for execution.
+ *
+ * @param string $sQuery
+ * @param array $aArgs Arguments array containing the query with formatting
+ * signs and the entries.
+ * Examples:
+ *
+ * $obj->_prepareQueryf('SELECT * FROM `%s` WHERE id = %d', 'tablename', 123);
+ * $obj->_prepareQueryf('SELECT * FROM `%s` WHERE id = %d AND user = %d', 'tablename', 123, 3);
+ *
+ * @return string
+ */
+ protected function _prepareQueryf($sQuery, array $aArgs) {
+ if (count($aArgs) > 0) {
+ $aArgs = array_map(array($this, 'escape'), $aArgs);
+ array_unshift($aArgs, $sQuery);
+ $sQuery = call_user_func_array('sprintf', $aArgs);
+ }
+ return $sQuery;
+ }
+
+ /**
+ * Moves the result to the next record, if exists and returns the status of the movement
+ *
+ * @return int Flag about move status 1 on success or 0
+ */
+ abstract public function next_record();
+
+ /**
+ * Moves the cursor (position inside current result sets).
+ *
+ * @param int $pos The positon to move to inside the current result set
+ * @return void
+ */
+ abstract public function seek($pos = 0);
+
+ /**
+ * Locks the desired table.
+ *
+ * @param string $table The table to lock
+ * @param string $mode The lock mode. Only mode 'write' is supported!
+ * @return int Status of lock success (1 or 0)
+ */
+ abstract public function lock($table, $mode = 'write');
+
+ /**
+ * Frees a previous locked result.
+ *
+ * @return int Status of lock success (1 or 0)
+ */
+ abstract public function unlock();
+
+ /**
+ * Parses te table structure and generates a metadata from it.
+ *
+ * @param string $table The table to get metadata or empty string to retrieve
+ * metadata of all tables
+ * @param bool $full Flag to load full metada
+ * @return array Depends on used database and on parameter $full
+ */
+ public function metadata($table = '', $full = false) {
+ $key = (string) $this->Database . '_' . $table . '_' . (($full) ? '1' : '0');
+
+ if (!isset(self::$_metaCache[$key])) {
+ // get meta data
+ self::$_metaCache[$key] = $this->_metaData($table, $full);
+ }
+
+ return self::$_metaCache[$key];
+ }
+
+ /**
+ * Parses te table structure and generates a metadata from it.
+ *
+ * @param string $table The table to get metadata or empty string to retrieve
+ * metadata of all tables
+ * @param bool $full Flag to load full metada
+ * @return array Depends on used database and on parameter $full
+ */
+ abstract protected function _metaData($table = '', $full = false);
+
+ /**
+ * Returns number of affected rows from last executed query (update, delete)
+ *
+ * @return int Number of affected rows
+ */
+ abstract public function affected_rows();
+
+ /**
+ * Returns the number of rows from last executed select query.
+ *
+ * @return int The number of rows from last select query result
+ */
+ abstract public function num_rows();
+
+ /**
+ * Returns the number of fields (colums) from current record set
+ *
+ * @return int Number of fields
+ */
+ abstract public function num_fields();
+
+ /**
+ * Returns the number of rows (record set).
+ * Shortcut for function num_rows().
+ *
+ * @return int Number of rows
+ */
+ public function nf() {
+ return $this->num_rows();
+ }
+
+ /**
+ * Displays the number of rows (record set) using print.
+ *
+ * @return void
+ */
+ public function np() {
+ print $this->num_rows();
+ }
+
+ /**
+ * Returns the desired field value from current record set.
+ *
+ * @param mixed The field name or index position
+ * @param mixed The default value to return
+ * @return mixed The value of field
+ */
+ public function f($Name, $default = null) {
+ return (isset($this->Record[$Name])) ? $this->Record[$Name] : $default;
+ }
+
+ /**
+ * Displays the desired field value from current record set using print.
+ *
+ * @param mixed The field name or index position
+ * @return void
+ */
+ public function p($Name) {
+ if (isset($this->Record[$Name])) {
+ print $this->Record[$Name];
+ }
+ }
+
+ /**
+ * Returns current recordset as a assoziative and/or indexed array.
+ *
+ * @param string $fetchMode One of DB_SQL_Abstract::FETCH_* constants
+ * @return array
+ */
+ public function toArray($fetchMode = DB_SQL_Abstract::FETCH_ASSOC) {
+ switch ($fetchMode) {
+ case self::FETCH_NUMERIC:
+ case self::FETCH_ASSOC:
+ case self::FETCH_BOTH:
+ // donut
+ break;
+ default:
+ $fetchMode = DB_SQL_Abstract::FETCH_ASSOC;
+ break;
+ }
+
+ $aResult = array();
+ if (is_array($this->Record)) {
+ foreach ($this->Record as $key => $value) {
+ if ($fetchMode == self::FETCH_ASSOC && !is_numeric($key)) {
+ $aResult[$key] = $value;
+ } elseif ($fetchMode == self::FETCH_NUMERIC && is_numeric($key)) {
+ $aResult[$key] = $value;
+ } else {
+ $aResult[$key] = $value;
+ }
+ }
+ }
+ return $aResult;
+ }
+
+ /**
+ * Returns current recordset as a object
+ *
+ * @return stdClass
+ */
+ public function toObject() {
+ return (object) $this->toArray(self::FETCH_ASSOC);
+ }
+
+ /**
+ * Returns the next id (sequence number).
+ *
+ * @param string $seq_name The sequence name to get the next id from
+ * @return int The next id or 0 on error
+ */
+ abstract public function nextid($seq_name);
+
+ /**
+ * Wrapper method for disconnect()
+ * @see DB_Sql_Abstract::disconnect()
+ */
+ public function close() {
+ $this->disconnect();
+ }
+
+ /**
+ * Closes the connection and frees the query id.
+ *
+ * @return void
+ */
+ abstract public function disconnect();
+
+ /**
+ * Error handling
+ *
+ * Error handler function, delegates passed message to the function haltmsg() if propery
+ * $this->Halt_On_Error is not set to self::HALT_REPORT.
+ *
+ * Terminates further script execution if $this->Halt_On_Error is set to self::HALT_YES
+ *
+ * @param string $sMsg The message to use for error handling
+ * @return void
+ */
+ public function halt($sMsg) {
+ if ($this->Halt_On_Error == self::HALT_REPORT) {
+ $this->haltmsg($this->_sHaltMsgPrefix . $sMsg);
+ }
+
+ if ($this->Halt_On_Error == self::HALT_YES) {
+ die('Session halted.');
+ }
+ }
+
+ /**
+ * Logs passed message, basically the last db error to the error log.
+ * Concatenates a detailed error message and invokey PHP's error_log() method.
+ *
+ * @param string $sMsg
+ * @return void
+ */
+ public function haltmsg($sMsg) {
+ $sName = 'ConLite DB';
+ if (!$this->Error) {
+ $this->Error = $this->_getErrorMessage();
+ }
+ if (!$this->Errno) {
+ $this->Errno = $this->_getErrorNumber();
+ }
+
+ $sMsg = sprintf("%s error: %s (%s) - info: %s\n", $sName, $this->Errno, $this->Error, $sMsg);
+ error_log($sMsg);
+ }
+
+ /**
+ * Returns names of existing tables.
+ *
+ * @return array|null Indexed array containing assoziative table data as
+ * follows or null:
+ * - $info[$i]['table_name']
+ * - $info[$i]['tablespace_name']
+ * - $info[$i]['database']
+ */
+ public function table_names() {
+ if (!$this->connect()) {
+ return null;
+ }
+ if (method_exists($this, '_tableNames')) {
+ return $this->_tableNames();
+ }
+ return null;
+ }
+
+ /**
+ * Implemetation for table_names() in child classes
+ * @see DB_Sql_Abstract::table_names()
+ */
+ abstract protected function _tableNames();
+
+ /**
+ * Escape string for using in SQL-Statement.
+ *
+ * @param string $sString The string to escape
+ * @return string Escaped string
+ */
+ abstract public function escape($sString);
+
+ /**
+ * Returns information about DB server. The return value depends allways on
+ * used DBMS.
+ *
+ * @return array|null Assoziative array as follows or null:
+ * - $arr['description'] (string) Optional, server description
+ * - $arr['version'] (string) Optional, server version
+ */
+ public function server_info() {
+ if (!$this->connect()) {
+ return null;
+ }
+ if (method_exists($this, '_serverInfo')) {
+ return $this->_serverInfo();
+ }
+ return null;
+ }
+
+ /**
+ * Implemetation for server_info() in child classes.
+ * @see DB_Sql_Abstract::server_info()
+ */
+ abstract protected function _serverInfo();
+
+ /**
+ * Returns error message of last occured error.
+ *
+ * @return string
+ */
+ public function getErrorMessage() {
+ return $this->Error;
+ }
+
+ /**
+ * Returns error message of last occured error by using databases interface.
+ *
+ * @return string
+ */
+ abstract protected function _getErrorMessage();
+
+ /**
+ * Returns error code of last occured error by using databases interface.
+ *
+ * @return int
+ */
+ public function getErrorNumber() {
+ return $this->Errno;
+ }
+
+ /**
+ * Returns error code of last occured error by using databases interface.
+ *
+ * @return int
+ */
+ abstract protected function _getErrorNumber();
+
+ /**
+ * Adds a entry to the profile data.
+ *
+ * @param float $fStartTime
+ * @param float $fEndTime
+ * @param string $sQuery
+ * @return void
+ */
+ protected static function _addProfileData($fStartTime, $fEndTime, $sQuery) {
+ self::$_aProfileData[] = array(
+ 'time' => $fEndTime - $fStartTime,
+ 'query' => $sQuery
+ );
+ }
+
+ /**
+ * Returns collected profile data.
+ *
+ * @return array Profile data array like:
+ * - $arr[$i]['time'] (float) Elapsed time to execute the query
+ * - $arr[$i]['query'] (string) The query itself
+ */
+ public static function getProfileData() {
+ return self::$_aProfileData;
+ }
+
+ /**
+ * Displays the passed message, if debug is enabled (see $this->Debug)
+ *
+ * @param string $sMsg The message to display
+ * @return void
+ */
+ protected function _debug($sMsg) {
+ if ($this->Debug) {
+ printf("" . $sMsg . " \n");
+ }
+ }
+
+ /**
+ * returns info about db-server
+ *
+ * return string
+ */
+ abstract public function getServerInfo();
+
+ /**
+ * returns client encoding
+ *
+ * return string
+ */
+ abstract public function getClientEncoding();
+
+ /**
+ * returns client info
+ *
+ * return string
+ */
+ abstract public function getClientInfo();
+}
diff --git a/conlib/index.php b/conlib/index.php
new file mode 100644
index 0000000..ef8b776
--- /dev/null
+++ b/conlib/index.php
@@ -0,0 +1,4 @@
+
diff --git a/conlib/local.php b/conlib/local.php
new file mode 100644
index 0000000..22d1145
--- /dev/null
+++ b/conlib/local.php
@@ -0,0 +1,896 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ *
+ * {@internal
+ * created 2000-01-01
+ * modified 2008-07-04, bilal arslan, added security fix
+ * modified 2010-02-02, Ingo van Peeren, added local method connect() in order
+ * to allow only one database connection, see [CON-300]
+ * modified 2010-02-17, Ingo van Peeren, only one connection for mysqli too
+ * modified 2011-03-03, Murat Purc, some redesign/improvements (partial adaption to PHP 5)
+ * modified 2011-03-18, Murat Purc, Fixed occuring "Duplicated entry" errors by using CT_Sql, see [CON-370]
+ * modified 2011-03-21, Murat Purc, added Contenido_CT_Session to uses PHP's session implementation
+ *
+ * $Id: local.php 300 2014-01-30 14:28:53Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ * DB-class for all DB handling
+ */
+class DB_ConLite extends DB_Sql
+{
+ /**
+ * Constructor of database class.
+ *
+ * @param array $options Optional assoziative options. The value depends
+ * on used DBMS, but is generally as follows:
+ * - $options['connection']['host'] (string) Hostname or ip
+ * - $options['connection']['database'] (string) Database name
+ * - $options['connection']['user'] (string) User name
+ * - $options['connection']['password'] (string) User password
+ * - $options['nolock'] (bool) Optional, not lock table
+ * - $options['sequenceTable'] (string) Optional, sequesnce table
+ * - $options['haltBehavior'] (string) Optional, halt behavior on occured errors
+ * - $options['haltMsgPrefix'] (string) Optional, Text to prepend to the halt message
+ * - $options['enableProfiling'] (bool) Optional, flag to enable profiling
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ global $cachemeta;
+
+ parent::__construct($options);
+
+ if (!is_array($cachemeta)) {
+ $cachemeta = array();
+ }
+
+ // TODO check this out
+ // HerrB: Checked and disabled. Kills umlauts, if tables are latin1_general.
+
+ // try to use the new connection and get the needed encryption
+ //$this->query("SET NAMES 'utf8'");
+ }
+
+
+ /**
+ * Fetches the next recordset from result set
+ *
+ * @param bool
+ */
+ public function next_record()
+ {
+ global $cCurrentModule;
+ // FIXME For what reason is NoRecord used???
+ $this->NoRecord = false;
+ if (!$this->Query_ID) {
+ $this->NoRecord = true;
+ if ($cCurrentModule > 0) {
+ $this->halt("next_record called with no query pending in Module ID $cCurrentModule.");
+ } else {
+ $this->halt("next_record called with no query pending.");
+ }
+ return false;
+ }
+
+ return parent::next_record();
+ }
+
+
+ /**
+ * Returns the metada of passed table
+ *
+ * @param string $sTable The tablename of empty string to retrieve metadata of all tables!
+ * @return array|bool Assoziative metadata array (result depends on used db driver)
+ * or false in case of an error
+ * @deprecated Use db drivers toArray() method instead
+ */
+ public function copyResultToArray($sTable = '')
+ {
+ global $cachemeta;
+
+ $aValues = array();
+
+ if ($sTable != '') {
+ if (array_key_exists($sTable, $cachemeta)) {
+ $aMetadata = $cachemeta[$sTable];
+ } else {
+ $cachemeta[$sTable] = $this->metadata($sTable);
+ $aMetadata = $cachemeta[$sTable];
+ }
+ } else {
+ $aMetadata = $this->metadata($sTable);
+ }
+
+ if (!is_array($aMetadata) || count($aMetadata) == 0) {
+ return false;
+ }
+
+ foreach ($aMetadata as $entry) {
+ $aValues[$entry['name']] = $this->f($entry['name']);
+ }
+
+ return $aValues;
+ }
+}
+
+/**
+ * Wrapper class for old contenido class
+ *
+ * @deprecated since version 2.0.0, use DB_ConLite instead
+ */
+class DB_Contenido extends DB_ConLite {
+
+ /**
+ *
+ * @deprecated since version 2.0.0
+ * @param array $options
+ */
+ public function __construct(array $options = array()) {
+ parent::__construct($options);
+ }
+}
+
+
+class Contenido_CT_Sql extends CT_Sql
+{
+ /**
+ * Database class name
+ * @var string
+ */
+ public $database_class = 'DB_Contenido';
+
+ /**
+ * And find our session data in this table.
+ * @var string
+ */
+ public $database_table = '';
+
+ public function __construct()
+ {
+ global $cfg;
+ $this->database_table = $cfg['tab']['phplib_active_sessions'];
+ }
+
+ /**
+ * Stores the session data in database table.
+ *
+ * Overwrites parents and uses MySQLs REPLACE statement, to prevent race
+ * conditions while executing INSERT statements by multiple frames in backend.
+ *
+ * - Existing entry will be overwritten
+ * - Non existing entry will be added
+ *
+ * @param string $id The session id (hash)
+ * @param string $name Name of the session
+ * @param string $str The value to store
+ * @return bool
+ */
+ public function ac_store($id, $name, $str)
+ {
+ switch ($this->encoding_mode) {
+ case 'slashes':
+ $str = addslashes($name . ':' . $str);
+ break;
+ case 'base64':
+ default:
+ $str = base64_encode($name . ':' . $str);
+ }
+
+ $name = addslashes($name);
+ $now = date('YmdHis', time());
+
+ $iquery = sprintf(
+ "REPLACE INTO %s (sid, name, val, changed) VALUES ('%s', '%s', '%s', '%s')",
+ $this->database_table, $id, $name, $str, $now
+ );
+
+ return ($this->db->query($iquery)) ? true : false;
+ }
+}
+
+
+/**
+ * Implements the interface class for storing session data to disk using file
+ * session container of phplib.
+ */
+class Contenido_CT_File extends CT_File
+{
+ /**
+ * The maximum length for one line in session file.
+ * @var int
+ */
+ public $iLineLength = 999999;
+
+ /**
+ * Overrides standard constructor for setting up file path to the one which is
+ * configured in php.ini
+ *
+ * @return Contenido_CT_File
+ *
+ * @author Holger Librenz
+ */
+ public function __construct()
+ {
+ global $cfg;
+
+ if (isset($cfg['session_line_length']) && !empty($cfg['session_line_length'])) {
+ $this->iLineLength = (int) $cfg['session_line_length'];
+ }
+
+ // get php.ini value for session path
+ $this->file_path = session_save_path() . '/';
+ }
+
+ /**
+ * Overrides get method, because standard byte count is not really senseful for
+ * contenido!
+ *
+ * @param string $sId
+ * @param string $sName
+ * @return mixed
+ */
+ public function ac_get_value($sId, $sName)
+ {
+ if (file_exists($this->file_path . "$sId$sName")) {
+ $f = fopen($this->file_path . "$sId$sName", 'r');
+ if ($f<0) {
+ return '';
+ }
+
+ $s = fgets($f, $this->iLineLength);
+ fclose($f);
+
+ return urldecode($s);
+ } else {
+ return '';
+ }
+ }
+}
+
+class Contenido_CT_Shm extends CT_Shm
+{
+ public function __construct()
+ {
+ $this->ac_start();
+ }
+}
+
+
+/**
+ * Contenido session container, uses PHP's session implementation.
+ *
+ * NOTE: Is experimental, so don't use this in a production environment.
+ *
+ * To use this, set session container in contenido/includes/config.misc.php to
+ * $cfg["session_container"] = 'session';
+ *
+ * @todo Make session container configurable
+ *
+ * @author Murat Purc
+ */
+class Contenido_CT_Session extends CT_Session
+{
+ public function __construct()
+ {
+ $this->ac_start(array(
+ 'namespace' => 'contenido_ct_session_ns',
+ 'session.hash_function' => '1', // use sha-1 function
+ 'session.hash_bits_per_character' => '5', // and set 5 character to achieve 32 chars
+# 'session.save_path' => 'your path',
+# 'session.name' => 'your session name',
+# 'session.gc_maxlifetime' => 'your lifetime in seconds',
+ ));
+ }
+}
+
+class Contenido_Session extends Session
+{
+ public $classname = 'Contenido_Session';
+ public $cookiename = 'contenido'; ## defaults to classname
+ public $magic = '934ComeOnEileen'; ## ID seed
+ public $mode = 'get'; ## We propagate session IDs with cookies
+ public $fallback_mode = 'cookie';
+ public $lifetime = 0; ## 0 = do session cookies, else minutes
+ public $that_class = 'Contenido_CT_Sql'; ## name of data storage container
+ public $gc_probability = 5;
+
+ public function __construct()
+ {
+ global $cfg;
+
+ $sFallback = 'sql';
+ $sClassPrefix = 'Contenido_CT_';
+
+ $sStorageContainer = strtolower($cfg['session_container']);
+
+ if (class_exists ($sClassPrefix . ucfirst($sStorageContainer))) {
+ $sClass = $sClassPrefix . ucfirst($sStorageContainer);
+ } else {
+ $sClass = $sClassPrefix . ucfirst($sFallback);
+ }
+
+ $this->that_class = $sClass;
+ }
+
+ public function delete()
+ {
+ $oCol = new InUseCollection();
+ $oCol->removeSessionMarks($this->id);
+ parent::delete();
+ }
+}
+
+
+class Contenido_Frontend_Session extends Session
+{
+ public $classname = 'Contenido_Frontend_Session';
+ public $cookiename = 'sid'; ## defaults to classname
+ public $magic = 'Phillipip'; ## ID seed
+ public $mode = 'cookie'; ## We propagate session IDs with cookies
+ public $fallback_mode = 'cookie';
+ public $lifetime = 0; ## 0 = do session cookies, else minutes
+ public $that_class = 'Contenido_CT_Sql'; ## name of data storage container
+ public $gc_probability = 5;
+
+ public function __construct()
+ {
+ global $load_lang, $load_client, $cfg;
+
+ $this->cookiename = 'sid_' . $load_client . '_' . $load_lang;
+
+ $this->setExpires(time()+3600);
+
+ // added 2007-10-11, H. Librenz
+ // bugfix (found by dodger77): we need alternative session containers
+ // also in frontend
+ $sFallback = 'sql';
+ $sClassPrefix = 'Contenido_CT_';
+
+ $sStorageContainer = strtolower($cfg['session_container']);
+
+ if (class_exists($sClassPrefix . ucfirst($sStorageContainer))) {
+ $sClass = $sClassPrefix . ucfirst($sStorageContainer);
+ } else {
+ $sClass = $sClassPrefix . ucfirst($sFallback);
+ }
+
+ $this->that_class = $sClass;
+ }
+}
+
+class Contenido_Auth extends Auth
+{
+ public $classname = 'Contenido_Auth';
+ public $lifetime = 15;
+ public $database_class = 'DB_Contenido';
+ public $database_table = 'con_phplib_auth_user';
+
+ public function auth_loginform()
+ {
+ global $sess, $_PHPLIB;
+ include($_PHPLIB['libdir'] . 'loginform.ihtml');
+ }
+
+ public function auth_validatelogin()
+ {
+ global $username, $password;
+
+ if ($password == '') {
+ return false;
+ }
+
+ if (isset($username)) {
+ $this->auth['uname'] = $username; ## This provides access for 'loginform.ihtml'
+ } elseif ($this->nobody){ ## provides for 'default login cancel'
+ $uid = $this->auth['uname'] = $this->auth['uid'] = 'nobody';
+ return $uid;
+ }
+ $uid = false;
+
+ $this->db->query(
+ sprintf("SELECT user_id, perms FROM %s WHERE username = '%s' AND password = '%s'",
+ $this->database_table, addslashes($username), addslashes($password))
+ );
+
+ while ($this->db->next_record()) {
+ $uid = $this->db->f('user_id');
+ $this->auth['perm'] = $this->db->f('perms');
+ }
+ return $uid;
+ }
+}
+
+
+class Contenido_Default_Auth extends Contenido_Auth
+{
+ public $classname = 'Contenido_Default_Auth';
+ public $lifetime = 1;
+ public $nobody = true;
+
+ public function auth_loginform()
+ {
+ global $sess, $_PHPLIB;
+ include($_PHPLIB['libdir'] . 'defloginform.ihtml');
+ }
+}
+
+
+class Contenido_Challenge_Auth extends Auth
+{
+ public $classname = 'Contenido_Challenge_Auth';
+ public $lifetime = 1;
+ public $magic = 'Simsalabim'; ## Challenge seed
+ public $database_class = 'DB_Contenido';
+ public $database_table = 'con_phplib_auth_user';
+
+ public function auth_loginform()
+ {
+ global $sess, $challenge, $_PHPLIB;
+
+ $challenge = md5(uniqid($this->magic));
+ $sess->register('challenge');
+
+ include($_PHPLIB['libdir'] . 'crloginform.ihtml');
+ }
+
+ public function auth_validatelogin()
+ {
+ global $username, $password, $challenge, $response, $timestamp;
+
+ if ($password == '') {
+ return false;
+ }
+
+ if (isset($username)) {
+ // This provides access for 'loginform.ihtml'
+ $this->auth['uname'] = $username;
+ }
+
+ // Sanity check: If the user presses 'reload', don't allow a login with the data
+ // again. Instead, prompt again.
+ if ($timestamp < (time() - 60 * 15)) {
+ return false;
+ }
+ $this->db->query(
+ sprintf("SELECT user_id, perms, password FROM %s WHERE username = '%s'",
+ $this->database_table, addslashes($username))
+ );
+
+ while ($this->db->next_record()) {
+ $uid = $this->db->f('user_id');
+ $perm = $this->db->f('perms');
+ $pass = $this->db->f('password');
+ }
+ $exspected_response = md5("$username:$pass:$challenge");
+
+ // True when JS is disabled
+ if ($response == '') {
+ if ($password != $pass) {
+ return false;
+ } else {
+ $this->auth['perm'] = $perm;
+ return $uid;
+ }
+ }
+
+ // Response is set, JS is enabled
+ if ($exspected_response != $response) {
+ return false;
+ } else {
+ $this->auth['perm'] = $perm;
+ return $uid;
+ }
+ }
+}
+
+##
+## Contenido_Challenge_Crypt_Auth: Keep passwords in md5 hashes rather
+## than cleartext in database
+## Author: Jim Zajkowski
+
+class Contenido_Challenge_Crypt_Auth extends Auth
+{
+ public $classname = 'Contenido_Challenge_Crypt_Auth';
+ public $lifetime = 15;
+ public $magic = 'Frrobo123xxica'; ## Challenge seed
+ public $database_class = 'DB_Contenido';
+ public $database_table = '';
+ public $group_table = '';
+ public $member_table = '';
+
+ public function __construct()
+ {
+ global $cfg;
+ $this->database_table = $cfg['tab']['phplib_auth_user_md5'];
+ $this->group_table = $cfg['tab']['groups'];
+ $this->member_table = $cfg['tab']['groupmembers'];
+ $this->lifetime = $cfg['backend']['timeout'];
+
+ if ($this->lifetime == 0) {
+ $this->lifetime = 15;
+ }
+ }
+
+ public function auth_loginform()
+ {
+ global $sess, $challenge, $_PHPLIB, $cfg;
+
+ $challenge = md5(uniqid($this->magic));
+ $sess->register('challenge');
+
+ include($cfg['path']['contenido'] . 'main.loginform.php');
+ }
+
+ public function auth_loglogin($uid)
+ {
+ global $cfg, $client, $lang, $auth, $sess, $saveLoginTime;
+
+ $perm = new Contenido_Perm();
+ $timestamp = date('Y-m-d H:i:s');
+ $idcatart = '0';
+
+ /* Find the first accessible client and language for the user */
+ // All the needed information should be available in clients_lang - but the previous code was designed with a
+ // reference to the clients table. Maybe fail-safe technology, who knows...
+ $sql = 'SELECT tblClientsLang.idclient, tblClientsLang.idlang FROM ' .
+ $cfg['tab']['clients'] . ' AS tblClients, ' . $cfg['tab']['clients_lang'] . ' AS tblClientsLang ' .
+ 'WHERE tblClients.idclient = tblClientsLang.idclient ORDER BY idclient ASC, idlang ASC';
+ $this->db->query($sql);
+
+ $bFound = false;
+ while ($this->db->next_record() && !$bFound) {
+ $iTmpClient = $this->db->f('idclient');
+ $iTmpLang = $this->db->f('idlang');
+
+ if ($perm->have_perm_client_lang($iTmpClient, $iTmpLang)) {
+ $client = $iTmpClient;
+ $lang = $iTmpLang;
+ $bFound = true;
+ }
+ }
+
+ if (isset($idcat) && isset($idart)) {
+ // SECURITY FIX
+ $sql = "SELECT idcatart
+ FROM
+ ". $cfg['tab']['cat_art'] ."
+ WHERE
+ idcat = '".Contenido_Security::toInteger($idcat)."' AND
+ idart = '".Contenido_Security::toInteger($idart)."'";
+
+ $this->db->query($sql);
+ $this->db->next_record();
+ $idcatart = $this->db->f('idcatart');
+ }
+
+ if (!is_numeric($client) || !is_numeric($lang)) {
+ return;
+ }
+
+ $idaction = $perm->getIDForAction('login');
+ $lastentry = $this->db->nextid($cfg['tab']['actionlog']);
+
+ $sql = "INSERT INTO
+ ". $cfg['tab']['actionlog']."
+ SET
+ idlog = $lastentry,
+ user_id = '" . $uid . "',
+ idclient = '".Contenido_Security::toInteger($client)."',
+ idlang = '".Contenido_Security::toInteger($lang)."',
+ idaction = $idaction,
+ idcatart = $idcatart,
+ logtimestamp = '$timestamp'";
+
+ $this->db->query($sql);
+ $sess->register('saveLoginTime');
+ $saveLoginTime = true;
+ }
+
+ public function auth_validatelogin()
+ {
+ global $username, $password, $challenge, $response, $formtimestamp, $auth_handlers;
+
+ $gperm = array();
+
+ if ($password == '') {
+ return false;
+ }
+
+ if (($formtimestamp + (60*15)) < time()) {
+ return false;
+ }
+
+ if (isset($username)) {
+ $this->auth['uname'] = $username; ## This provides access for 'loginform.ihtml'
+ } elseif ($this->nobody) { ## provides for 'default login cancel'
+ $uid = $this->auth['uname'] = $this->auth['uid'] = 'nobody';
+ return $uid;
+ }
+
+ $uid = false;
+ $perm = false;
+ $pass = false;
+
+ $sDate = date('Y-m-d');
+
+ $this->db->query(sprintf("SELECT user_id, perms, password FROM %s WHERE username = '%s' AND
+ (valid_from <= '".$sDate."' OR valid_from = '0000-00-00' OR valid_from is NULL) AND
+ (valid_to >= '".$sDate."' OR valid_to = '0000-00-00' OR valid_to is NULL)",
+ $this->database_table,
+ Contenido_Security::escapeDB($username, $this->db)
+ ));
+
+ $sMaintenanceMode = getSystemProperty('maintenance', 'mode');
+ while($this->db->next_record()) {
+ $uid = $this->db->f('user_id');
+ $perm = $this->db->f('perms');
+ $pass = $this->db->f('password'); ## Password is stored as a md5 hash
+
+ $bInMaintenance = false;
+ if ($sMaintenanceMode == 'enabled') {
+ #sysadmins are allowed to login every time
+ if (!preg_match('/sysadmin/', $perm)) {
+ $bInMaintenance = true;
+ }
+ }
+
+ if ($bInMaintenance) {
+ unset($uid);
+ unset($perm);
+ unset($pass);
+ }
+
+ if (is_array($auth_handlers) && !$bInMaintenance) {
+ if (array_key_exists($pass, $auth_handlers)) {
+ $success = call_user_func($auth_handlers[$pass], $username, $password);
+
+ if ($success) {
+ $uid = md5($username);
+ $pass = md5($password);
+ }
+ }
+ }
+ }
+
+ if ($uid == false) {
+ ## No user found, sleep and exit
+ sleep(5);
+ return false;
+ } else {
+ $this->db->query(sprintf("SELECT a.group_id AS group_id, a.perms AS perms ".
+ "FROM %s AS a, %s AS b WHERE a.group_id = b.group_id AND b.user_id = '%s'",
+ $this->group_table,
+ $this->member_table,
+ $uid
+ ));
+
+ if ($perm != '') {
+ $gperm[] = $perm;
+ }
+
+ while ($this->db->next_record()) {
+ $gperm[] = $this->db->f('perms');
+ }
+
+ if (is_array($gperm)) {
+ $perm = implode(',',$gperm);
+ }
+
+ if ($response == '') { ## True when JS is disabled
+ if (md5($password) != $pass) { ## md5 hash for non-JavaScript browsers
+ sleep(5);
+ return false;
+ } else {
+ $this->auth['perm'] = $perm;
+ $this->auth_loglogin($uid);
+ return $uid;
+ }
+ }
+
+ $expected_response = md5("$username:$pass:$challenge");
+
+ if ($expected_response != $response) { ## Response is set, JS is enabled
+ sleep(5);
+ return false;
+ } else {
+ $this->auth['perm'] = $perm;
+ $this->auth_loglogin($uid);
+ return $uid;
+ }
+ }
+ }
+}
+
+class Contenido_Frontend_Challenge_Crypt_Auth extends Auth
+{
+ public $classname = 'Contenido_Frontend_Challenge_Crypt_Auth';
+ public $lifetime = 15;
+ public $magic = 'Frrobo123xxica'; ## Challenge seed
+ public $database_class = 'DB_Contenido';
+ public $database_table = '';
+ public $fe_database_table = '';
+ public $group_table = '';
+ public $member_table = '';
+ public $nobody = true;
+
+ public function __construct()
+ {
+ global $cfg;
+ $this->database_table = $cfg['tab']['phplib_auth_user_md5'];
+ $this->fe_database_table = $cfg['tab']['frontendusers'];
+ $this->group_table = $cfg['tab']['groups'];
+ $this->member_table = $cfg['tab']['groupmembers'];
+ }
+
+ public function auth_preauth()
+ {
+ global $password;
+
+ if ($password == '') {
+ /* Stay as nobody when an empty password is passed */
+ $uid = $this->auth['uname'] = $this->auth['uid'] = 'nobody';
+ return false;
+ }
+
+ return $this->auth_validatelogin();
+ }
+
+ public function auth_loginform()
+ {
+ global $sess, $challenge, $_PHPLIB, $client, $cfgClient;
+
+ $challenge = md5(uniqid($this->magic));
+ $sess->register('challenge');
+
+ include($cfgClient[$client]['path']['frontend'].'front_crcloginform.inc.php');
+ }
+
+ public function auth_validatelogin()
+ {
+ global $username, $password, $challenge, $response, $auth_handlers, $client;
+
+ $client = (int)$client;
+
+ if(isset($username)) {
+ $this->auth['uname'] = $username; ## This provides access for 'loginform.ihtml'
+ } else if ($this->nobody) { ## provides for 'default login cancel'
+ $uid = $this->auth['uname'] = $this->auth['uid'] = 'nobody';
+ return $uid;
+ }
+
+ $uid = false;
+
+ /* Authentification via frontend users */
+ $this->db->query(sprintf("SELECT idfrontenduser, password FROM %s WHERE username = '%s' AND idclient='$client' AND active='1'",
+ $this->fe_database_table,
+ Contenido_Security::escapeDB(urlencode($username), $this->db)
+ ));
+
+ if ($this->db->next_record()) {
+ $uid = $this->db->f('idfrontenduser');
+ $perm = 'frontend';
+ $pass = $this->db->f('password');
+ }
+
+ if ($uid == false) {
+ /* Authentification via backend users */
+ $this->db->query(sprintf("SELECT user_id, perms, password FROM %s WHERE username = '%s'",
+ $this->database_table,
+ Contenido_Security::escapeDB($username, $this->db) ));
+
+ while($this->db->next_record()) {
+ $uid = $this->db->f('user_id');
+ $perm = $this->db->f('perms');
+ $pass = $this->db->f('password'); ## Password is stored as a md5 hash
+
+ if (is_array($auth_handlers)) {
+ if (array_key_exists($pass, $auth_handlers)) {
+ $success = call_user_func($auth_handlers[$pass], $username, $password);
+ if ($success) {
+ $uid = md5($username);
+ $pass = md5($password);
+ }
+ }
+ }
+ }
+
+ if ($uid !== false) {
+ $this->db->query(sprintf("SELECT a.group_id AS group_id, a.perms AS perms ".
+ "FROM %s AS a, %s AS b WHERE a.group_id = b.group_id AND ".
+ "b.user_id = '%s'",
+ $this->group_table,
+ $this->member_table,
+ $uid
+ ));
+
+ /* Deactivated: Backend user would be sysadmin when logged on as frontend user
+ * (and perms would be checked), see http://www.contenido.org/forum/viewtopic.php?p=85666#85666
+ $perm = 'sysadmin'; */
+ if ($perm != '') {
+ $gperm[] = $perm;
+ }
+
+ while ($this->db->next_record()) {
+ $gperm[] = $this->db->f('perms');
+ }
+
+ if (is_array($gperm)) {
+ $perm = implode(',',$gperm);
+ }
+ }
+ }
+
+ if ($uid == false) {
+ ## User not found, sleep and exit
+ sleep(5);
+ return false;
+ } else {
+ if ($response == '') { ## True when JS is disabled
+ if (md5($password) != $pass) { ## md5 hash for non-JavaScript browsers
+ sleep(5);
+ return false;
+ } else {
+ $this->auth['perm'] = $perm;
+ return $uid;
+ }
+ }
+
+ $expected_response = md5("$username:$pass:$challenge");
+ if ($expected_response != $response) { ## Response is set, JS is enabled
+ sleep(5);
+ return false;
+ } else {
+ $this->auth['perm'] = $perm;
+ return $uid;
+ }
+ }
+ }
+}
+
+/**
+ * Registers an external auth handler
+ */
+function register_auth_handler($aHandlers)
+{
+ global $auth_handlers;
+
+ if (!is_array($auth_handlers)) {
+ $auth_handlers = array();
+ }
+
+ if (!is_array($aHandlers)) {
+ $aHandlers = Array($aHandlers);
+ }
+
+ foreach ($aHandlers as $sHandler) {
+ if (!in_array($sHandler, $auth_handlers)) {
+ $auth_handlers[md5($sHandler)] = $sHandler;
+ }
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlib/page.inc b/conlib/page.inc
new file mode 100644
index 0000000..81b74dd
--- /dev/null
+++ b/conlib/page.inc
@@ -0,0 +1,110 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release
+ * @deprecated file deprecated in contenido release
+ *
+ * {@internal
+ * created 2002-07-21
+ * modified 2008-07-04, bilal arslan, added security fix
+ *
+ * $Id: page.inc 1315 2011-03-03 00:02:52Z xmurrix $:
+ * }}
+ *
+ */
+ if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+function page_open($feature) {
+ global $_PHPLIB;
+
+ # enable sess and all dependent features.
+ if (isset($feature["sess"])) {
+ global $sess;
+ $sess = new $feature["sess"];
+ $sess->start();
+
+ # the auth feature depends on sess
+ if (isset($feature["auth"])) {
+ global $auth;
+
+ if (!isset($auth)) {
+ $auth = new $feature["auth"];
+ }
+ $auth->start();
+
+
+ # the perm feature depends on auth and sess
+ if (isset($feature["perm"])) {
+ global $perm;
+
+ if (!isset($perm)) {
+ $perm = new $feature["perm"];
+ }
+ }
+
+ # the user feature depends on auth and sess
+ if (isset($feature["user"])) {
+ global $user;
+
+ if (!isset($user)) {
+ $user = new $feature["user"];
+ }
+ $user->start($auth->auth["uid"]);
+ }
+ }
+
+ ## Load the auto_init-File, if one is specified.
+ if (($sess->auto_init != "") && !$sess->in) {
+ $sess->in = 1;
+ include($_PHPLIB["libdir"] . $sess->auto_init);
+ if ($sess->secure_auto_init != "") {
+ $sess->freeze();
+ }
+ }
+ }
+}
+
+function page_close() {
+ global $sess, $user;
+
+ if (isset($sess)) {
+ $sess->freeze();
+ if (isset($user) && method_exists($user, "freeze")) {
+ $user->freeze();
+ }
+ }
+}
+
+function sess_load($session) {
+ reset($session);
+ while (list($k,$v) = each($session)) {
+ $GLOBALS[$k] = new $v;
+ $GLOBALS[$k]->start();
+ }
+}
+
+function sess_save($session) {
+ reset($session);
+ while (list(,$v) = each($session)) {
+ $GLOBALS[$v]->freeze();
+ }
+}
+?>
diff --git a/conlib/perm.inc b/conlib/perm.inc
new file mode 100644
index 0000000..f8b6f17
--- /dev/null
+++ b/conlib/perm.inc
@@ -0,0 +1,678 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release
+ * @deprecated file deprecated in contenido release
+ *
+ * {@internal
+ * created 2002-08-16
+ * modified 2008-07-04, bilal arslan, added security fix
+ * modified 2009-10-29, Murat Purc, replaced deprecated functions (PHP 5.3 ready) and some formatting
+ *
+ * $Id: perm.inc 1315 2011-03-03 00:02:52Z xmurrix $:
+ * }}
+ *
+ */
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class Contenido_Perm {
+
+ var $classname = "Contenido_Perm";
+ var $areacache = array();
+ var $actioncache = array();
+ var $db;
+ var $db_perm;
+
+ function getGroupsForUser($user) {
+ global $cfg;
+
+ if (!is_object($this->db)) {
+ $this->db = new DB_Contenido;
+ }
+
+ $sql = "SELECT group_id FROM
+ " . $cfg["tab"]["groupmembers"] . "
+ WHERE user_id = '" . Contenido_Security::escapeDB($user, $this->db) . "'";
+ $this->db->query($sql);
+
+ $groups = array();
+
+ while ($this->db->next_record()) {
+ $groups[] = $this->db->f("group_id");
+ }
+
+ return $groups;
+ }
+
+ function getIDForArea($area) {
+ global $cfg;
+
+ if (!is_object($this->db_perm)) {
+ $this->db_perm = new DB_Contenido;
+ }
+
+ if (!is_numeric($area)) {
+ if (!@ array_key_exists($area, $this->areacache)) {
+ $sql = "SELECT idarea
+ FROM
+ " . $cfg["tab"]["area"] . "
+ WHERE
+ name = \"" . Contenido_Security::escapeDB($area, $this->db_perm) . "\"";
+ $this->db_perm->query($sql);
+
+ $this->db_perm->next_record();
+ $this->areacache[$area] = $this->db_perm->f("idarea");
+ $area = $this->db_perm->f(0);
+ } else {
+ $area = $this->areacache[$area];
+ }
+
+ return ($area);
+ }
+
+ return $area;
+ }
+
+ function getIDForAction($action) {
+
+ global $cfg;
+
+ if (!is_object($this->db_perm)) {
+ $this->db_perm = new DB_Contenido;
+ }
+
+ if (!is_numeric($action)) {
+ if (!@ array_key_exists($action, $this->actioncache)) {
+ $sql = "SELECT idaction
+ FROM
+ " . $cfg["tab"]["actions"] . "
+ WHERE
+ name = \"" . Contenido_Security::escapeDB($action, $this->db_perm) . "\"";
+
+ $this->db_perm->query($sql);
+ $this->db_perm->next_record();
+
+ $this->actioncache[$action] = $this->db_perm->f("idaction");
+ $action = $this->db_perm->f(0);
+ } else {
+ $action = $this->actioncache[$action];
+ }
+ return ($action);
+ }
+
+ return $action;
+ }
+
+ function load_permissions($force = false) {
+
+ global $sess, $area_rights, $item_rights, $db, $client, $lang, $auth, $cfg, $changelang, $changeclient;
+
+ $return = "1";
+ //if not admin or sysadmin
+ if (!$this->have_perm()) {
+ $return = isset($area_rights);
+
+ if (!isset($area_rights) || !isset($item_rights) || isset($changeclient) || isset($changelang) || $force) {
+ $return = "3";
+ //register variables
+ $sess->register("area_rights");
+ $sess->register("item_rights");
+ $item_rights = array();
+
+ $groups = $this->getGroupsForUser($auth->auth["uid"]);
+
+ if (is_array($groups)) {
+ foreach ($groups as $group) {
+ $this->load_permissions_for_user($group);
+ }
+ }
+
+ $this->load_permissions_for_user($auth->auth["uid"]);
+ }
+ }
+
+ return $return;
+ }
+
+ function load_permissions_for_user($user) {
+ global $db, $client, $lang, $cfg;
+ global $area_rights, $item_rights;
+ $sql = "SELECT *
+ FROM " . $cfg["tab"]["rights"] . "
+ WHERE user_id='" . Contenido_Security::escapeDB($user, $db) . "' AND idcat='0' AND idclient='" . Contenido_Security::toInteger($client) . "' AND idlang='" . Contenido_Security::toInteger($lang) . "'";
+ $db->query($sql);
+
+ if (!is_array($area_rights)) {
+ $area_rights = array();
+ }
+ while ($db->next_record()) {
+ $area_rights[$db->f("idarea")][$db->f("idaction")] = true;
+ }
+
+ // Select Rights for Article and Sructure Atention Hard code Areas
+ $sql = "SELECT
+ idarea
+ FROM
+ " . $cfg["tab"]["area"];
+ $db->query($sql);
+
+ $tmp_area = array();
+ while ($db->next_record()) {
+ array_push($tmp_area, $db->f("idarea"));
+ }
+
+ $tmp_area_string = implode("','", array_keys($tmp_area));
+ $sql = "SELECT
+ idarea, idaction, idcat
+ FROM " . $cfg["tab"]["rights"] . "
+ WHERE user_id='" . Contenido_Security::escapeDB($user, $db) . "' AND idclient='" . Contenido_Security::toInteger($client) . "' AND idlang='" . Contenido_Security::toInteger($lang) . "' AND idarea IN ('$tmp_area_string') AND idcat != '0'";
+ $db->query($sql);
+
+ while ($db->next_record()) {
+ $item_rights[$db->f(0)][$db->f(1)][$db->f(2)] = $db->f(2);
+ }
+ }
+
+ function have_perm_area_action_anyitem($area, $action = 0) {
+
+ if ($this->have_perm_area_action($area, $action)) {
+ return true;
+ }
+
+ $area = $this->getIDForArea($area);
+ $action = $this->getIDForAction($action);
+
+ global $item_rights;
+
+ if (isset($item_rights[$area][$action])) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ function have_perm_area_action_item($area, $action, $itemid) {
+ global $item_rights, $auth, $client, $lang, $cfg;
+
+ if (!is_object($this->db)) {
+ $this->db = new DB_Contenido;
+ }
+
+ $area = $this->getIDForArea($area);
+ $action = $this->getIDForAction($action);
+
+ if ($this->have_perm()) {
+ return true;
+ } else {
+ //if the user has a right on this action in this area check for the items
+ if ($this->have_perm_area_action($area, $action)) {
+ return true;
+ }
+ //check rights for the action in this area at this item
+ if (isset($item_rights[$area][$action][$itemid])) {
+ //if have action for area + action +item check right for client and lang
+ return true;
+ } elseif ($item_rights[$area] != "noright") {
+
+ $groupsForUser = $this->getGroupsForUser($auth->auth[uid]);
+ $groupsForUser[] = $auth->auth[uid];
+
+ $tmp_userstring = implode("','", $groupsForUser);
+
+ $sql = "SELECT *
+ FROM " . $cfg["tab"]["rights"] . "
+ WHERE user_id IN ('" . $tmp_userstring . "') AND idclient = '" . Contenido_Security::toInteger($client) . "' AND idlang = '" . Contenido_Security::toInteger($lang) . "' AND idarea = '$area' AND idcat != '0'";
+ $this->db->query($sql);
+
+ //if there are no rights for this area set the flag norights
+ if ($this->db->nf() == 0) {
+ $item_rights[$area] = "noright";
+ return false;
+ }
+
+ while ($this->db->next_record()) {
+ $item_rights[$this->db->f("idarea")][$this->db->f("idaction")][$this->db->f("idcat")] = $this->db->f("idcat");
+ }
+
+ //check
+ if (isset($item_rights[$area][$action][$itemid])) {
+ //if have action for area + action +item check right for client and lang
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ function getParentAreaId($area) {
+
+ global $client, $lang, $cfg, $sess;
+
+ if (!is_object($this->db)) {
+ $this->db = new DB_Contenido;
+ }
+
+ if (is_numeric($area)) {
+ $sql = "SELECT
+ b.name
+ FROM
+ " . $cfg["tab"]["area"] . " AS a,
+ " . $cfg["tab"]["area"] . " AS b
+ WHERE
+ a.idarea = '" . Contenido_Security::toInteger($area) . "' AND
+ b.name = a.parent_id";
+ } else {
+ $sql = "SELECT
+ b.name
+ FROM
+ " . $cfg["tab"]["area"] . " AS a,
+ " . $cfg["tab"]["area"] . " AS b
+ WHERE
+ a.name = '" . Contenido_Security::escapeDB($area, $this->db) . "' AND
+ b.name = a.parent_id";
+ }
+ $this->db->query($sql);
+
+ if ($this->db->next_record()) {
+ return $this->db->f(0);
+ } else {
+ return $area;
+ }
+ }
+
+ function have_perm_area_action($area, $action = 0) {
+ global $area_rights, $client, $lang, $cfg;
+ //if not admin or sysadmin
+ if (!is_object($this->db_perm)) {
+ $this->db_perm = new DB_Contenido;
+ }
+
+ $area = $this->getIDForArea($area);
+ $action = $this->getIDForAction($action);
+
+ if ($action == 0) {
+ $area = $this->getParentAreaId($area);
+ }
+
+ $area = $this->getIDForArea($area);
+
+ if (!$this->have_perm()) {
+
+ if ($action == 0 && $area_rights[$area]) {
+ //if have action for area + action check right for client and lang
+ return ($this->have_perm_client_lang($client, $lang));
+ }
+
+ //check rights for the action in this area
+ if ($area_rights[$area][$action]) {
+ //if have action for area + action check right for client and lang
+ return $this->have_perm_client_lang($client, $lang);
+ }
+
+ return false;
+ }
+ return true;
+ }
+
+ function have_perm_client_lang($client, $lang) {
+ // Changed back to a full featured function, as have_perm
+ // needs $client as global variable - not provided by this
+ // function
+ //return ($this->have_perm("client[$client],lang[$lang]"));
+
+ global $auth;
+
+ if (!isset($auth->auth['perm'])) {
+ $auth->auth['perm'] = '';
+ }
+
+ // Split the permissions of the user
+ $userperm = explode(',', $auth->auth['perm']);
+
+ if (in_array('sysadmin', $userperm)) {
+ return true; // User is sysadmin
+ } elseif (in_array("admin[$client]", $userperm)) {
+ return true; // User is admin
+ } else {
+ // Check rights for the client and the language
+ $pageperm = explode(',', "client[$client],lang[$lang]");
+ foreach ($pageperm as $value) {
+ if (!in_array($value, $userperm)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * hasClientPermission
+ * Checks if a user has access rights for a specific client.
+ *
+ * @param integer $iClient idclient to check, or false for the current client
+ * @param object $oUser User object to check against, or false for the current user
+ */
+ function hasClientPermission($iClient = false, $oUser = false) {
+ global $auth;
+
+ if ($iClient === false) {
+ global $client;
+ $iClient = $client;
+ }
+
+ $oUser = $this->_checkUserObject($oUser);
+
+ if ($this->isSysadmin($oUser) || $this->isClientAdmin($iClient, $oUser) || $this->isClientUser($iClient, $oUser)) {
+ return true;
+ } else {
+ return false;
+ }
+ /* Commented out Timo Trautmann, because here only client access is checked, possibility for admin or sysadmin access was ignored
+ functions isSysadmin isClientAdmin isClientUser also handles permission for groups
+ #Check clients' rights of users' group(s)
+ $aGroups = $this->getGroupsForUser($auth->auth["uid"]);
+ if (is_array($aGroups))
+ {
+ foreach ($aGroups as $group)
+ {
+ $oGroup = new Group;
+ $oGroup->loadGroupByGroupID ($group);
+
+ if ($this->isClientGroup($iClient, $oGroup))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ } */
+ }
+
+ /**
+ * isClientUser
+ * Checks if the given user has access permission for a client
+ *
+ * @param integer $iClient idclient to check
+ * @param object $oUser User object to check against
+ */
+ function isClientUser($iClient, $oUser) {
+ $oUser = $this->_checkUserObject($oUser);
+
+ $aPermissions = explode(",", $oUser->getEffectiveUserPerms());
+
+ if (in_array("client[$iClient]", $aPermissions)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * isClientGroup
+ * Checks if the given group has access permission for a client
+ *
+ * @param integer $iClient idclient to check
+ * @param object $oGroup Group object to check against
+ */
+ function isClientGroup($iClient, $oGroup) {
+ $aPermissions = explode(",", $oGroup->getField("perms"));
+
+ if (in_array("client[$iClient]", $aPermissions)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * isClientAdmin
+ * Checks if the given user has an admin permission
+ *
+ * @param integer $iClient idclient to check
+ * @param object $oUser User object to check against
+ */
+ function isClientAdmin($iClient, $oUser) {
+ $oUser = $this->_checkUserObject($oUser);
+
+ $aPermissions = explode(",", $oUser->getEffectiveUserPerms());
+ if (in_array("admin[$iClient]", $aPermissions)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks if the given user has sysadmin permission
+ *
+ * @param User $oUser userobject or false (default)
+ * @return boolean true if user is sysadmin
+ */
+ public function isSysadmin($oUser = FALSE) {
+ $oUser2Check = $this->_checkUserObject($oUser);
+ if(!is_object($oUser2Check)) {
+ return false;
+ }
+ $aPermissions = explode(",", $oUser2Check->getEffectiveUserPerms());
+ if (in_array("sysadmin", $aPermissions)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * _checkUserObject
+ *
+ * Checks if the given object is a user object.
+ *
+ * If oUser is false, initialize the object from the currently logged in user. If oUser is not
+ * a object of the class User, issue a warning.
+ *
+ * @parameter object oUser User object
+ * @access private
+ */
+ private function _checkUserObject($oUser) {
+ if ($oUser === false) {
+ global $currentuser;
+ $oUser = $currentuser;
+ }
+
+ if (!is_object($oUser)) {
+ global $auth;
+ $oUser = new User;
+ $oUser->loadUserByUserID($auth->auth["uid"]);
+ }
+
+ if (strtolower(get_class($oUser)) != "user") {
+ cWarning(__FILE__, __LINE__, "oUser parameter is not of type User");
+ }
+
+ return $oUser;
+ }
+
+ /**
+ * @deprecated
+ */
+ function have_perm_client($p = 'x') {
+ global $auth, $client;
+
+ if (!isset($auth->auth['perm'])) {
+ $auth->auth['perm'] = '';
+ }
+
+ //split the permissions of the user
+ $userperm = explode(',', $auth->auth['perm']);
+
+ //if User is sysadmin or admin at this client return true
+ if (in_array('sysadmin', $userperm)) {
+ return true;
+ }
+
+ //if there are more permissions to ask split them
+ $pageperm = explode(',', $p);
+ foreach ($pageperm as $value) {
+ if (!in_array($value, $userperm)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function have_perm($p = 'x') {
+ global $auth, $client;
+
+ if (!isset($auth->auth['perm'])) {
+ $auth->auth['perm'] = '';
+ }
+
+ //split the permissions of the user
+ $userperm = explode(',', $auth->auth['perm']);
+
+ //if User is sysadmin or admin at this client return true
+ if (in_array('sysadmin', $userperm)) {
+ return true;
+ } elseif (in_array("admin[$client]", $userperm)) {
+ return true;
+ //else check rights for the client and the language
+ } else {
+ //if there are more permissions to ask split them
+ $pageperm = explode(',', $p);
+ foreach ($pageperm as $value) {
+ if (!in_array($value, $userperm)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ //checks if an item have any perms
+ function have_perm_item($mainarea, $itemid) {
+
+ global $cfg, $item_rights, $cfg, $client, $lang, $auth, $area_tree, $sess;
+
+ $mainarea = $this->getIDForArea($mainarea);
+
+ //if is not admin or sysadmin
+ if (!$this->have_perm()) {
+
+ if (!is_object($this->db)) {
+ $this->db = new DB_Contenido;
+ }
+
+ $this->showareas($mainarea);
+
+ $flg = false;
+ //check if there are any rights for this areas
+ foreach ($area_tree[$mainarea] as $value) {
+ // if the flag noright is set there are no rights in this area
+ if ($item_rights[$value] == "noright") {
+ continue;
+ } elseif (is_array($item_rights[$value])) {
+ //if there are any rights
+ foreach ($item_rights[$value] as $value2) {
+ if (in_array($itemid, $value2)) {
+ return true;
+ }
+ }
+ } elseif ($item_rights[$value] != "noright") {
+
+ $groupsForUser = $this->getGroupsForUser($auth->auth[uid]);
+ $groupsForUser[] = $auth->auth[uid];
+
+ //else search for rights for this user in this area
+ $sql = "SELECT
+ *
+ FROM
+ " . $cfg["tab"]["rights"] . "
+ WHERE
+ user_id IN ('" . implode("','", $groupsForUser) . "') AND
+ idclient = '" . Contenido_Security::toInteger($client) . "' AND
+ idlang = '" . Contenido_Security::toInteger($lang) . "' AND
+ idarea = '$value' AND
+ idcat != '0'";
+ $this->db->query($sql);
+
+ //if there are no rights for this area set the flag norights
+ if ($this->db->affected_rows() == 0) {
+ $item_rights[$value] = "noright";
+ }
+
+ //set the rights
+ while ($this->db->next_record()) {
+ if ($this->db->f("idcat") == $itemid) {
+ $flg = true;
+ }
+ $item_rights[$this->db->f("idarea")][$this->db->f("idaction")][$this->db->f("idcat")] = $this->db->f("idcat");
+ }
+ } //end if
+ } //end for
+ return $flg;
+ } //end if
+ return true;
+ }
+
+ function showareas($mainarea) {
+
+ global $area_tree, $sess, $perm, $cfg;
+
+ if (!is_object($this->db)) {
+ $this->db = new DB_Contenido;
+ }
+
+ $mainarea = $this->getIDForArea($mainarea);
+
+ //if $area_tree for this area is not register
+ if (!isset($area_tree[$mainarea])) {
+ $sess->register("area_tree");
+
+ // parent_id uses the name not the idarea
+ $sql = "SELECT
+ name
+ FROM
+ " . $cfg["tab"]["area"] . "
+ WHERE
+ idarea='$mainarea'";
+
+ $this->db->query($sql);
+ $this->db->next_record();
+ $name = $this->db->f("name");
+
+ //check which subareas are there and write them in the array
+ $sql = "SELECT
+ idarea
+ FROM
+ " . $cfg["tab"]["area"] . "
+ WHERE
+ parent_id='$name' OR
+ idarea='$mainarea'";
+
+ $this->db->query($sql);
+ $area_tree[$mainarea] = array();
+ while ($this->db->next_record()) {
+ $area_tree[$mainarea][] = $this->db->f("idarea");
+ }
+ }
+ return $mainarea;
+ }
+
+}
diff --git a/conlib/prepend.php b/conlib/prepend.php
new file mode 100644
index 0000000..a14d20c
--- /dev/null
+++ b/conlib/prepend.php
@@ -0,0 +1,69 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ *
+ *
+ * {@internal
+ * created 2000-01-01
+ * modified 2008-07-04, bilal arslan, added security fix
+ * modified 2009-10-29, Murat Purc, automatic loading of configured database driver
+ * modified 2011-03-21, Murat Purc, inclusion of ct_session.inc
+ *
+ * $Id: prepend.php 67 2012-05-09 13:28:03Z oldperl $:
+ * }}
+ *
+ */
+
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+$_PHPLIB = array();
+$_PHPLIB['libdir'] = str_replace ('\\', '/', dirname(__FILE__) . '/');
+
+global $cfg;
+
+require($_PHPLIB['libdir'] . 'db_sql_abstract.inc');
+
+// include/require database driver
+$dbDriverFileName = 'db_' . $cfg['database_extension'] . '.inc';
+if (is_file($_PHPLIB['libdir'] . $dbDriverFileName)) {
+ require_once($_PHPLIB['libdir'] . $dbDriverFileName);
+} else {
+ die('Invalid database extension: ' . $cfg['database_extension']);
+}
+unset($dbDriverFileName);
+
+require_once($_PHPLIB['libdir'] . 'ct_sql.inc'); // Data storage container: database
+require_once($_PHPLIB['libdir'] . 'ct_file.inc'); // Data storage container: file
+require_once($_PHPLIB['libdir'] . 'ct_shm.inc'); // Data storage container: memory
+require_once($_PHPLIB['libdir'] . 'ct_session.inc');// Data storage container: memory
+require_once($_PHPLIB['libdir'] . 'ct_null.inc'); // Data storage container: null -
+ // no session container - Contenido does not work
+
+require_once($_PHPLIB['libdir'] . 'session.inc'); // Required for everything below.
+require_once($_PHPLIB['libdir'] . 'auth.inc'); // Disable this, if you are not using authentication.
+require_once($_PHPLIB['libdir'] . 'perm.inc'); // Disable this, if you are not using permission checks.
+
+// Additional require statements go before this line
+
+require_once($_PHPLIB['libdir'] . 'local.php'); // Required, contains your local configuration.
+
+require_once($_PHPLIB['libdir'] . 'page.inc'); // Required, contains the page management functions.
diff --git a/conlib/session.inc b/conlib/session.inc
new file mode 100644
index 0000000..05dc56e
--- /dev/null
+++ b/conlib/session.inc
@@ -0,0 +1,536 @@
+
+ * @copyright (c) 2014, ConLite Team
+ * @link http://conlite.org ConLite Portal
+ *
+ * $Id:$
+ */
+
+/**
+ * @package ContenidoBackendArea
+ * @version 1.1.1.2
+ * @author Boris Erdmann, Kristian Koehntopp
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ */
+
+if(!defined('CON_FRAMEWORK')) {die('Illegal call');}
+
+/**
+ * old session class, now only extends new cSession
+ *
+ * @deprecated since version 2.0
+ */
+class Session extends cSession {
+
+}
+
+
+class cSession {
+
+ var $classname = "Session"; ## Needed for object serialization.
+ ## Define the parameters of your session by either overwriting
+ ## these values or by subclassing session (recommended).
+ var $magic = ""; ## Some string you should change.
+ var $mode = "cookie"; ## We propagate session IDs with cookies
+ var $fallback_mode; ## If this doesn't work, fall back...
+ var $lifetime = 0; ## 0 = do session cookies, else minutes
+ var $cookie_domain = ""; ## If set, the domain for which the
+ ## session cookie is set.
+ var $gc_time = 1440; ## Purge all session data older than 1440 minutes.
+ var $gc_probability = 5; ## Garbage collect probability in percent
+ var $auto_init = ""; ## Name of the autoinit-File, if any.
+ var $secure_auto_init = 1; ## Set to 0 only, if all pages call
+ ## page_close() guaranteed.
+ var $allowcache = "no"; ## "passive", "no", "private" or "public"
+ var $allowcache_expire = 1440; ## If you allowcache, data expires in this
+ ## many minutes.
+ var $that_class = ""; ## Name of data storage container
+ ##
+ ## End of parameters.
+ ##
+ var $name; ## Session name
+ var $id; ## Unique Session ID
+ var $that;
+ var $pt = array(); ## This Array contains the registered things
+ var $in = 0; ## Marker: Did we already include the autoinit file?
+ var $expires; ## Expire date
+ var $_expires;
+
+ ## register($things):
+ ##
+ ## call this function to register the things that should become persistent
+
+ function register($things) {
+ $things = explode(",", $things);
+ reset($things);
+ while (list(, $thing) = each($things)) {
+ $thing = trim($thing);
+ if ($thing) {
+ $this->pt[$thing] = true;
+ }
+ }
+ }
+
+ function setExpires($time) {
+ $this->_expires = $time;
+ }
+
+ function is_registered($name) {
+ if (isset($this->pt[$name]) && $this->pt[$name] == true)
+ return true;
+ return false;
+ }
+
+ function unregister($things) {
+ $things = explode(",", $things);
+ reset($things);
+ while (list(, $thing) = each($things)) {
+ $thing = trim($thing);
+ if ($thing) {
+ unset($this->pt[$thing]);
+ }
+ }
+ }
+
+ ## get_id():
+ ##
+ ## Propagate the session id according to mode and lifetime.
+ ## Will create a new id if necessary. To take over abandoned sessions,
+ ## one may provide the new session id as a parameter (not recommended).
+
+ function get_id($id = "") {
+ global $_COOKIE, $_GET, $_POST, $QUERY_STRING;
+ $newid = true;
+
+ $this->name = $this->cookiename == "" ? $this->classname : $this->cookiename;
+
+ if ("" == $id) {
+ $newid = false;
+ switch ($this->mode) {
+ case "get":
+ $id = isset($_GET[$this->name]) ?
+ $_GET[$this->name] :
+ ( isset($_POST[$this->name]) ?
+ $_POST[$this->name] :
+ "");
+ break;
+ case "cookie":
+ $id = isset($_COOKIE[$this->name]) ?
+ $_COOKIE[$this->name] : "";
+ break;
+ default:
+ die("This has not been coded yet.");
+ break;
+ }
+ }
+
+ if ("" == $id) {
+ $newid = true;
+ $id = $this->that->ac_newid(md5(uniqid($this->magic)), $this->name);
+ }
+
+ switch ($this->mode) {
+ case "cookie":
+ if ($newid && ( 0 == $this->lifetime )) {
+ SetCookie($this->name, $id, 0, "/", $this->cookie_domain);
+ }
+ if (0 < $this->lifetime) {
+ SetCookie($this->name, $id, time() + $this->lifetime * 60, "/", $this->cookie_domain);
+ }
+
+ // Remove session ID info from QUERY String - it is in cookie
+ if (isset($QUERY_STRING) && ("" != $QUERY_STRING)) {
+ $QUERY_STRING = preg_replace(
+ "/(^|&)" . quotemeta(urlencode($this->name)) . "=" . $id . "(&|$)/", "\\1", $QUERY_STRING);
+ }
+ break;
+ case "get":
+ if (isset($QUERY_STRING) && ("" != $QUERY_STRING)) {
+ $QUERY_STRING = preg_replace(
+ "/(^|&)" . quotemeta(urlencode($this->name)) . "=" . $id . "(&|$)/", "\\1", $QUERY_STRING);
+ }
+ break;
+ default:
+ ;
+ break;
+ }
+ $this->id = $id;
+ }
+
+ ## put_id():
+ ##
+ ## Stop using the current session id (unset cookie, ...) and
+ ## abandon a session.
+
+ function put_id() {
+ global $_COOKIE;
+
+ switch ($this->mode) {
+ case "cookie":
+ $this->name = $this->cookiename == "" ? $this->classname : $this->cookiename;
+ SetCookie($this->name, "", 0, "/", $this->cookie_domain);
+ $_COOKIE[$this->name] = "";
+ break;
+
+ default:
+ // do nothing. We don't need to die for modes other than cookie here.
+ break;
+ }
+ }
+
+ ## delete():
+ ##
+ ## Delete the current session record and put the session id.
+
+ function delete() {
+ $this->that->ac_delete($this->id, $this->name);
+ $this->put_id();
+ }
+
+ ## url($url):
+ ##
+ ## Helper function: returns $url concatenated with the current
+ ## session $id.
+
+ function url($url) {
+ // Remove existing session info from url
+ $url = preg_replace(
+ "/([&?])" . quotemeta(urlencode($this->name)) . "=" . $this->id . "(&|$)/", "\\1", $url);
+
+ // Remove trailing ?/& if needed
+ $url = preg_replace("/[&?]+$/", "", $url);
+
+ switch ($this->mode) {
+ case "get":
+ $url .= ( strpos($url, "?") != false ? "&" : "?" ) .
+ urlencode($this->name) . "=" . $this->id;
+ break;
+ default:
+ ;
+ break;
+ }
+
+ // Encode naughty characters in the URL
+ $url = str_replace(array("<", ">", " ", "\"", "'"), array("%3C", "%3E", "+", "%22", "%27"), $url);
+ return $url;
+ }
+
+ function purl($url) {
+ print $this->url($url);
+ }
+
+ /**
+ *
+ * @param array $aParam
+ * @return string
+ */
+ function self_url($aParam = array()) {
+ $sURI = $_SERVER["PHP_SELF"];
+ parse_str($_SERVER["QUERY_STRING"], $aQuery);
+ $aQuery = array_merge($aQuery, $aParam);
+ $sQuery = http_build_query($aQuery,'','&');
+
+ return $this->url($_SERVER["PHP_SELF"] . "?" . $sQuery);
+ }
+
+ function pself_url() {
+ print $this->self_url();
+ }
+
+ function hidden_session($mode = 0) {
+ if ($mode) {
+ return sprintf(" \n", $this->name, $this->id);
+ } else {
+ printf(" \n", $this->name, $this->id);
+ }
+ }
+
+ function add_query($qarray) {
+ global $PHP_SELF;
+ global $QUERY_STRING;
+
+ if ((isset($QUERY_STRING) && ("" != $QUERY_STRING)) || ($this->mode == "get")) {
+ $sep_char = "&";
+ } else {
+ $sep_char = "?";
+ }
+
+ $qstring = "";
+ while (list($k, $v) = each($qarray)) {
+ $qstring .= $sep_char . urlencode($k) . "=" . urlencode($v);
+ $sep_char = "&";
+ }
+
+ return $qstring;
+ }
+
+ function padd_query($qarray) {
+ print $this->add_query($qarray);
+ }
+
+ ## serialize($var,&$str):
+ ##
+ ## appends a serialized representation of $$var
+ ## at the end of $str.
+ ##
+ ## To be able to serialize an object, the object must implement
+ ## a variable $classname (containing the name of the class as string)
+ ## and a variable $persistent_slots (containing the names of the slots
+ ## to be saved as an array of strings).
+
+ function serialize($var, &$str) {
+ static $t, $l, $k;
+
+ ## Determine the type of $$var
+ eval("\$t = gettype(\$$var);");
+ switch ($t) {
+
+ case "array":
+ ## $$var is an array. Enumerate the elements and serialize them.
+ eval("reset(\$$var); \$l = gettype(list(\$k)=each(\$$var));");
+ $str .= "\$$var = array(); ";
+ while ("array" == $l) {
+ ## Structural recursion
+ $this->serialize($var . "['" . preg_replace("/([\\'])/", "\\\\1", $k) . "']", $str);
+ eval("\$l = gettype(list(\$k)=each(\$$var));");
+ }
+
+ break;
+ case "object":
+ ## $$var is an object. Enumerate the slots and serialize them.
+ eval("\$k = \$${var}->classname; \$l = reset(\$${var}->persistent_slots);");
+ $str.="\$$var = new $k; ";
+ while ($l) {
+ ## Structural recursion.
+ $this->serialize($var . "->" . $l, $str);
+ eval("\$l = next(\$${var}->persistent_slots);");
+ }
+
+ break;
+ default:
+ ## $$var is an atom. Extract it to $l, then generate code.
+ eval("\$l = \$$var;");
+ $str.="\$$var = '" . preg_replace("/([\\'])/", "\\\\1", $l) . "'; ";
+ break;
+ }
+ }
+
+ function get_lock() {
+ $this->that->ac_get_lock();
+ }
+
+ function release_lock() {
+ $this->that->ac_release_lock();
+ }
+
+ ## freeze():
+ ##
+ ## freezes all registered things ( scalar variables, arrays, objects ) into
+ ## a database table
+
+ function freeze() {
+ $str = "";
+//print "DBG: "; var_dump($this->pt); print " \n";
+ $this->serialize("this->in", $str);
+ $this->serialize("this->pt", $str);
+
+ reset($this->pt);
+ while (list($thing) = each($this->pt)) {
+ $thing = trim($thing);
+ if ($thing && isset($GLOBALS[$thing])) {
+ $this->serialize("GLOBALS['" . $thing . "']", $str);
+ }
+ }
+//return;
+ $r = $this->that->ac_store($this->id, $this->name, $str);
+ $this->release_lock();
+
+ if (!$r)
+ $this->that->ac_halt("Session: freeze() failed.");
+ }
+
+ ## thaw:
+ ##
+ ## Reload frozen variables from the database and microwave them.
+
+ function thaw() {
+ $this->get_lock();
+
+ $vals = $this->that->ac_get_value($this->id, $this->name);
+ eval(sprintf(";%s", $vals));
+ }
+
+ ##
+ ## Variable precedence functions
+ ##
+
+ function reimport_get_vars() {
+ $this->reimport_any_vars("_GET");
+ }
+
+ function reimport_post_vars() {
+ $this->reimport_any_vars("_POST");
+ }
+
+ function reimport_cookie_vars() {
+ $this->reimport_any_vars("HTTP_COOKIE_VARS");
+ }
+
+ function reimport_any_vars($arrayname) {
+ global $$arrayname;
+
+ if (!is_array($$arrayname))
+ return;
+
+ reset($$arrayname);
+ while (list($key, $val) = each($$arrayname)) {
+ $GLOBALS[$key] = $val;
+ }
+ }
+
+ ##
+ ## All this is support infrastructure for the start() method
+ ##
+
+ function set_container() {
+ $name = $this->that_class;
+ $this->that = new $name;
+
+ $this->that->ac_start();
+ }
+
+ function set_tokenname() {
+ $this->name = $this->cookiename == "" ? $this->classname : $this->cookiename;
+ }
+
+ function release_token($sid = "") {
+ global $_COOKIE, $_POST, $_GET,
+ $HTTP_HOST, $HTTPS;
+
+ if (isset($this->fallback_mode) && ("get" == $this->fallback_mode) && ("cookie" == $this->mode) && (!isset($_COOKIE[$this->name]))) {
+
+ // Looks like no cookie here - check GET/POST params
+ if (isset($_GET[$this->name]) || isset($_POST[$this->name])) {
+ // Session info passed via GET/POST - go to fallback_mode
+ $this->mode = $this->fallback_mode;
+ } else {
+ // It seems to be the first load of this page -
+ // no cookie and no GET/POST params
+ // Generate session ID and setup cookie.
+ $this->get_id($sid);
+
+ // Next line is to generate correct self_url() later
+ $this->mode = $this->fallback_mode;
+
+ if (isset($HTTPS) && $HTTPS == 'on') {
+ ## You will need to fix suexec as well, if you
+ ## use Apache and CGI PHP
+ $PROTOCOL = 'https';
+ } else {
+ $PROTOCOL = 'http';
+ }
+ header("Status: 302 Moved Temporarily");
+ header("Location: " . $PROTOCOL . "://" . $HTTP_HOST . $this->self_url());
+ exit;
+ }
+ }
+ }
+
+ function put_headers() {
+ # Allowing a limited amount of caching, as suggested by
+ # Padraic Renaghan on phplib@lists.netuse.de.
+ #
+ # Note that in HTTP/1.1 the Cache-Control headers override the Expires
+ # headers and HTTP/1.0 ignores headers it does not recognize (e.g,
+ # Cache-Control). Mulitple Cache-Control directives are split into
+ # mulitple headers to better support MSIE 4.x.
+ #
+ # Added pre- and post-check for MSIE 5.x as suggested by R.C.Winters,
+ # see http://msdn.microsoft.com/workshop/author/perf/perftips.asp#Use%20Cache-Control%20Extensions
+ # for details
+ switch ($this->allowcache) {
+
+ case "passive":
+ $mod_gmt = gmdate("D, d M Y H:i:s", getlastmod()) . " GMT";
+ header("Last-Modified: " . $mod_gmt);
+ # possibly ie5 needs the pre-check line. This needs testing.
+ header("Cache-Control: post-check=0, pre-check=0");
+ break;
+
+ case "public":
+ $exp_gmt = gmdate("D, d M Y H:i:s", time() + $this->allowcache_expire * 60) . " GMT";
+ $mod_gmt = gmdate("D, d M Y H:i:s", getlastmod()) . " GMT";
+ header("Expires: " . $exp_gmt);
+ header("Last-Modified: " . $mod_gmt);
+ header("Cache-Control: public");
+ header("Cache-Control: max-age=" . $this->allowcache_expire * 60);
+ break;
+
+ case "private":
+ $mod_gmt = gmdate("D, d M Y H:i:s", getlastmod()) . " GMT";
+ header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
+ header("Last-Modified: " . $mod_gmt);
+ header("Cache-Control: private");
+ header("Cache-Control: max-age=" . $this->allowcache_expire * 60);
+ header("Cache-Control: pre-check=" . $this->allowcache_expire * 60);
+ break;
+
+ default:
+ $rand = md5(mt_rand());
+ $mod_gmt = gmdate("D, d M Y H:i:s", time() - 3600) . " GMT";
+
+ if ($this->_expires > 0) {
+ header("Expires: " . gmdate("D, d M Y H:i:s", $this->_expires) . " GMT");
+ } else {
+ header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
+ }
+
+ header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
+ header("Cache-Control:no-store, no-cache, must-revalidate");
+ header("Cache-Control: post-check=0, pre-check=0", false);
+ header("Cache-control: private, no-cache");
+ header("Pragma: no-cache");
+ header("ETag: $rand");
+
+ break;
+ }
+ }
+
+ ##
+ ## Garbage collection
+ ##
+ ## Destroy all session data older than this
+ ##
+
+ function gc() {
+ srand(time());
+ if ((rand() % 100) < $this->gc_probability) {
+ $this->that->ac_gc($this->gc_time, $this->name);
+ }
+ }
+
+ ##
+ ## Initialization
+ ##
+
+ function start($sid = "") {
+ $this->set_container();
+ $this->set_tokenname();
+ $this->put_headers();
+ $this->release_token($sid);
+ $this->get_id($sid);
+ $this->thaw();
+ $this->gc();
+ $this->setExpires(0);
+ }
+
+}
diff --git a/conlite/.directory b/conlite/.directory
new file mode 100644
index 0000000..d730ff7
--- /dev/null
+++ b/conlite/.directory
@@ -0,0 +1,4 @@
+[Dolphin]
+Timestamp=2016,9,20,14,42,23
+Version=3
+ViewMode=1
diff --git a/conlite/.htaccess_recommended b/conlite/.htaccess_recommended
new file mode 100644
index 0000000..de49335
--- /dev/null
+++ b/conlite/.htaccess_recommended
@@ -0,0 +1,30 @@
+################################################################################
+# Apache settings for Contenido backend
+#
+# @version 0.0.1
+# @author Murat Purc
+# @copyright four for business AG
+# @license http://www.contenido.org/license/LIZENZ.txt
+# @link http://www.4fb.de
+# @link http://www.contenido.org
+# @since file available since contenido release 4.8.15
+#
+# $Id: .htaccess_recommended 1297 2011-02-10 22:48:38Z xmurrix $
+################################################################################
+
+
+# Some rules to configure ETags
+FileETag MTime Size
+
+
+ ExpiresActive on
+ ExpiresDefault "access plus 1 year"
+
+
+
+# Some rules to compress files
+
+
+ SetOutputFilter DEFLATE
+
+
diff --git a/conlite/ajaxmain.php b/conlite/ajaxmain.php
new file mode 100644
index 0000000..ab0b7b2
--- /dev/null
+++ b/conlite/ajaxmain.php
@@ -0,0 +1,230 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created 2008-09-08, Ingo van Peeren
+ * modified 2010-05-20, Murat Purc, standardized Contenido startup and security check invocations, see [#CON-307]
+ * modified 2011-02-08, Dominik Ziegler, removed old PHP compatibility stuff as contenido now requires at least PHP 5
+ *
+ * $Id: ajaxmain.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined("CON_FRAMEWORK")) {
+ define("CON_FRAMEWORK", true);
+}
+
+// Contenido startup process
+include_once ('./includes/startup.php');
+
+$cfg["debug"]["backend_exectime"]["fullstart"] = getmicrotime();
+
+cInclude ("includes", 'functions.api.php');
+cInclude ("includes", 'functions.forms.php');
+
+page_open(array('sess' => 'Contenido_Session',
+ 'auth' => 'Contenido_Challenge_Crypt_Auth',
+ 'perm' => 'Contenido_Perm'));
+
+i18nInit($cfg["path"]["contenido"].$cfg["path"]["locale"], $belang);
+
+/**
+ * Bugfix
+ * @see http://contenido.org/forum/viewtopic.php?t=18291
+ *
+ * added by H. Librenz (2007-12-07)
+ */
+//includePluginConf();
+require_once $cfg['path']['contenido'] . $cfg['path']['includes'] . 'functions.includePluginConf.php';
+
+cInclude ("includes", 'cfg_language_de.inc.php');
+
+# Create Contenido classes
+$db = new DB_ConLite;
+$notification = new Contenido_Notification;
+$classarea = new Area();
+$classlayout = new Layout();
+$classclient = new Client();
+$classuser = new User();
+
+$currentuser = new User();
+$currentuser->loadUserByUserID($auth->auth["uid"]);
+
+
+# change Client
+if (isset($changeclient) && is_numeric($changeclient) ) {
+ $client = $changeclient;
+ unset($lang);
+}
+
+# Sprache wechseln
+if (isset($changelang) && is_numeric($changelang) ) {
+ unset($area_rights);
+ unset($item_rights);
+
+ $lang = $changelang;
+}
+
+if (!is_numeric($client) ||
+ (!$perm->have_perm_client("client[".$client."]") &&
+ !$perm->have_perm_client("admin[".$client."]")))
+{
+ // use first client which is accessible
+ $sess->register("client");
+ $sql = "SELECT idclient FROM ".$cfg["tab"]["clients"]." ORDER BY idclient ASC";
+ $db->query($sql);
+
+ while ($db->next_record())
+ {
+ $mclient = $db->f("idclient");
+
+ if ($perm->have_perm_client("client[".$mclient."]") ||
+ $perm->have_perm_client("admin[".$mclient."]") )
+ {
+ unset($lang);
+ $client = $mclient;
+ break;
+ }
+ }
+} else {
+ $sess->register("client");
+}
+
+if (!is_numeric($lang) || $lang == "") {
+ $sess->register("lang");
+ # search for the first language of this client
+ $sql = "SELECT * FROM ".$cfg["tab"]["lang"]." AS A, ".$cfg["tab"]["clients_lang"]." AS B WHERE A.idlang=B.idlang AND idclient='".Contenido_Security::toInteger($client)."' ORDER BY A.idlang ASC";
+ $db->query($sql);
+ $db->next_record();
+ $lang = $db->f("idlang");
+} else {
+ $sess->register("lang");
+}
+
+// send right encoding http header
+sendEncodingHeader($db, $cfg, $lang);
+
+$perm->load_permissions();
+
+# Create Contenido classes
+$xml = new XML_doc;
+$tpl = new Template;
+$backend = new Contenido_Backend;
+//$backend->debug=true;
+
+# Register session variables
+$sess->register("sess_area");
+
+if (isset($area)) {
+ $sess_area = $area;
+} else {
+ $area = ( isset($sess_area) && $sess_area != "" ) ? $sess_area : 'login';
+}
+
+$sess->register("cfgClient");
+$sess->register("errsite_idcat");
+$sess->register("errsite_idart");
+
+if ($cfgClient["set"] != "set")
+{
+ rereadClients ();
+}
+
+# Initialize Contenido_Backend.
+# Load all actions from the DB
+# and check if permission is
+# granted.
+if ($cfg["debug"]["rendering"] == true)
+{
+ $oldmemusage = memory_get_usage();
+}
+
+# Select area
+$backend->select($area);
+
+$cfg["debug"]["backend_exectime"]["start"] = getmicrotime();
+
+# If $action is set -> User klicked some button/link
+# get the appopriate code for this action and evaluate it.
+
+if (isset($action) && $action != "")
+{
+ if (!isset($idart))
+ {
+ $idart = 0;
+ }
+
+ $backend->log($idcat, $idart, $client, $lang, $action);
+}
+
+
+if (isset($action)) {
+ if ($backend->getCode($action) != '') {
+ if ($backend->debug == 1) {
+ echo 'Executing: '."\n";
+ echo $backend->getCode($action)."\n";
+ echo ' ';
+ }
+ eval($backend->getCode($action));
+
+ } else {
+ if ($backend->debug == 1) {
+ echo 'Executing: '."\n";
+ echo "no code available in action\n";
+ echo ' ';
+ }
+ }
+}
+
+if(isset($_REQUEST['ajax']) && $_REQUEST['ajax'] != '') {
+ $oAjax = new Ajax();
+ $sReturn = $oAjax->handle($_REQUEST['ajax']);
+ echo $sReturn;
+} else {
+ include_once($cfg['path']['contenido'].$cfg['path']['includes'] ."ajax/include.ajax." . $area . ".php");
+}
+
+$cfg["debug"]["backend_exectime"]["end"] = getmicrotime();
+
+if ($cfg["debug"]["rendering"] == true)
+{
+ echo "Building this page (excluding contenido includes) took: " . ($cfg["debug"]["backend_exectime"]["end"] - $cfg["debug"]["backend_exectime"]["start"])." seconds ";
+ echo "Building the complete page took: " . ($cfg["debug"]["backend_exectime"]["end"] - $cfg["debug"]["backend_exectime"]["fullstart"])." seconds ";
+
+ echo "Include memory usage: ".human_readable_size(memory_get_usage()-$oldmemusage)." ";
+ echo "Complete memory usage: ".human_readable_size(memory_get_usage())." ";
+}
+
+/**
+ * Start User Tracking (who is online)
+ *
+ **/
+$oActiveUser = new ActiveUsers($db, $cfg, $auth);
+$oActiveUser->startUsersTracking();
+/**
+ *
+ * End of the User Tracking
+ */
+
+page_close();
+
+?>
\ No newline at end of file
diff --git a/conlite/backend_search.php b/conlite/backend_search.php
new file mode 100644
index 0000000..a7e5582
--- /dev/null
+++ b/conlite/backend_search.php
@@ -0,0 +1,781 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created 2007-04-20
+ * modified 2008-06-15, Rudi Bieller, Bugfix CON-149
+ * modified 2008-06-27, Frederic Schneider, add security fix
+ * modified 2008-06-27, Timo.Trautmann, Encoding Header added
+ * modified 2008-07-02, Frederic Schneider, querys escaped and include security class
+ * modified 2008-09-08, Oliver Lohkemper, Fixed: "Fatal error: Class 'PropertyCollection' not found"
+ * modified 2010-05-20, Murat Purc, standardized Contenido startup and security check invocations, see [#CON-307]
+ *
+ * $Id: backend_search.php 312 2014-06-18 11:01:08Z oldperl $:
+ * }}
+ *
+ */
+
+/*
+ * 16.01.2008
+ * Thorsten Granz
+ * Added 'store search' function
+ * Added showinng values of search in searchform (Timo Trautmann)
+ */
+
+if (!defined("CON_FRAMEWORK")) {
+ define("CON_FRAMEWORK", true);
+}
+
+// Contenido startup process
+include_once (dirname(__FILE__) . '/includes/startup.php');
+
+page_open(array('sess' => 'Contenido_Session',
+ 'auth' => 'Contenido_Challenge_Crypt_Auth',
+ 'perm' => 'Contenido_Perm'));
+
+i18nInit($cfg["path"]["contenido"].$cfg["path"]["locale"], $belang);
+
+# Variablen initialisieren
+$db = new DB_ConLite;
+$db2 = new DB_ConLite;
+
+// Session
+$sSession = '';
+$sSession_tmp = '';
+// Session 'Anhang' fuer URLs
+$sSessionAppend = '';
+
+// SprachID
+$iSpeachID = $lang;
+$iSpeachID_tmp = NULL;
+
+// Suche - ID
+$iSearchID = NULL;
+$iSearchID_tmp = 0;
+
+// Suche - Text
+$sSearchStr = NULL;
+$sSearchStr_tmp = '';
+
+// Suche - Date type
+$sSearchStrDateType = NULL;
+$sSearchStrDateType_tmp = '';
+
+// Suche - Date from
+$sSearchStrDateFrom = NULL;
+$sSearchStrDateFrom_tmp = '';
+
+// Suche - Date to
+$sSearchStrDateTo = NULL;
+$sSearchStrDateTo_tmp = '';
+
+$where = '';
+
+// SprachID ermitteln
+$iLangID = ((int) $lang > 0?(int) $lang:1);
+
+// effektive Einstellung fuer Zeitdarstellung holen
+$dateformat = getEffectiveSetting("backend", "timeformat_date", "Y-m-d");
+
+// fuer das Initialiseren der Sub-Navi benoetigte Werte
+$sLoadSubnavi = '';
+$iIDCat = 0;
+$iIDTpl = 0;
+
+// Session- und Sprachdaten aus Formularanfrage sichern
+if (isset($_POST[$sess->name])) {
+ $sSession_tmp = trim (strip_tags ($_POST[$sess->name]));
+} elseif (isset($_GET[$sess->name])) {
+ $sSession_tmp = trim (strip_tags ($_GET[$sess->name]));
+}
+
+if (strlen($sSession_tmp) > 0) {
+ $sSession = $sSession_tmp;
+}
+
+if (isset($_POST['speach'])) {
+ $iSpeachID_tmp = (int) $_POST['speach'];
+ if ((string) $iSpeachID_tmp === $_POST['speach']) {
+ $iSpeachID = $iSpeachID_tmp;
+ }
+}
+if( !empty($sSession) ) {
+ //Backend
+ page_open(array (
+ 'sess' => 'Contenido_Session',
+ 'auth' => 'Contenido_Challenge_Crypt_Auth',
+ 'perm' => 'Contenido_Perm'
+ ));
+ i18nInit($cfg["path"]["contenido"].$cfg["path"]["locale"], $belang);
+} else {
+ //Frontend
+ page_open(array ('sess' => 'Contenido_Frontend_Session', 'auth' => 'Contenido_Frontend_Challenge_Crypt_Auth', 'perm' => 'Contenido_Perm'));
+}
+
+/*
+ * SAVE SEARCH
+ * Some orientation info:
+ * 1. User is calling a stored search -> fetch search values from con_properties and put them in PHP variables used for searching
+ * 2. User has entered some search values -> standard search in DB
+ * 3. User pressed 'save search' -> show 'successfully stored' message & use the stored search id to show the result again
+ */
+
+$save_title = 'save_title';
+$save_id = 'save_id';
+$save_date_from = 'save_date_from';
+$save_date_from_year = 'save_date_from_year';
+$save_date_from_month = 'save_date_from_month';
+$save_date_from_day = 'save_date_from_day';
+$save_date_to = 'save_date_to';
+$save_date_to_year = 'save_date_to_year';
+$save_date_to_month = 'save_date_to_month';
+$save_date_to_day = 'save_date_to_day';
+$save_date_field = 'save_date_field';
+$save_author = 'save_author';
+$save_name = 'save_name';
+$type = 'savedsearch'; // section for saved searches in con_properties
+$refreshScript = ''; // refresh top left frame
+$saveSuccessfull = ''; // Sucessfully stored message
+
+/* Function for generating refresh JavaScript for form in left_top */
+function generateJs ($aValues) {
+ if (is_array($aValues)) {
+ global $save_title;
+ global $save_id;
+ global $save_date_from_year;
+ global $save_date_from_month;
+ global $save_date_from_day;
+ global $save_date_to_year;
+ global $save_date_to_month;
+ global $save_date_to_day;
+ global $save_date_field;
+ global $save_author;
+ global $save_name;
+
+ return 'function refresh_article_search_form (refresh) {
+ var oFrame = top.content.left.left_top;
+ if (oFrame) {
+ oForm = oFrame.document.backend_search;
+
+ oForm.bs_search_text.value = "'.$aValues[$save_title].'";
+ oForm.bs_search_id.value = "'.$aValues[$save_id].'";
+ oForm.bs_search_date_type.value = "'.$aValues[$save_date_field].'";
+
+ oFrame.toggle_tr_visibility("tr_date_from");
+ oFrame.toggle_tr_visibility("tr_date_to");
+
+ oForm.bs_search_date_from_day.value = "'.$aValues[$save_date_from_day].'";
+ oForm.bs_search_date_from_month.value = "'.$aValues[$save_date_to_month].'";
+ oForm.bs_search_date_from_year.value = "'.$aValues[$save_date_from_year].'";
+
+ oForm.bs_search_date_to_day.value = "'.$aValues[$save_date_to_day].'";
+ oForm.bs_search_date_to_month.value = "'.$aValues[$save_date_to_month].'";
+ oForm.bs_search_date_to_year.value = "'.$aValues[$save_date_to_year].'";
+
+ oForm.bs_search_author.value = "'.$aValues[$save_author].'";
+ }
+ }
+ refresh_article_search_form ();
+ ';
+ } else {
+ return false;
+ }
+}
+
+/** Function masks string for inserting into SQL statement
+ *
+ * @param string $sString
+ * @return string
+ */
+function mask ($sString) {
+ $sString = str_replace('\\', '\\\\', $sString);
+ $sString = str_replace('\'', '\\\'', $sString);
+ $sString = str_replace('"', '\\"', $sString);
+ return $sString;
+}
+
+$sScript = '';
+
+/* Searches in generic db for a - Search */
+function getSearchResults($itemidReq, $itemtypeReq)
+{
+ global $save_title;
+ global $save_id;
+ global $save_date_from;
+ global $save_date_from_year;
+ global $save_date_from_month;
+ global $save_date_from_day;
+ global $save_date_to;
+ global $save_date_to_year;
+ global $save_date_to_month;
+ global $save_date_to_day;
+ global $save_date_field;
+ global $save_author;
+ global $save_name;
+ global $type;
+
+ $retValue = array();
+ // Request from DB
+ $propertyCollection = new PropertyCollection;
+ $results = $propertyCollection->getValuesByType($itemtypeReq, $itemidReq, $type);
+
+ // Put results in returning Array
+ $retValue[$save_title] = $results[$save_title];
+ $retValue[$save_id] = $results[$save_id];
+ $retValue[$save_date_field] = $results[$save_date_field];
+ $retValue[$save_author] = $results[$save_author];
+
+ // Date from
+ $sSearchStrDateFromDay_tmp = 0;
+ $sSearchStrDateFromMonth_tmp = 0;
+ $sSearchStrDateFromYear_tmp = 0;
+ $saveDateFrom = $results[$save_date_from];
+ if( isset($saveDateFrom) && sizeof($saveDateFrom)>0 )
+ {
+ $saveDateFrom = str_replace(' 00:00:00', '', $saveDateFrom);
+ $saveDateFromParts = explode('-', $saveDateFrom);
+ if(sizeof($saveDateFromParts) == 3)
+ {
+ $retValue[$save_date_from_year] = $saveDateFromParts[0];
+ $retValue[$save_date_from_month] = $saveDateFromParts[1];
+ $retValue[$save_date_from_day] = $saveDateFromParts[2];
+ }
+ }
+ // Date to
+ $sSearchStrDateToDay_tmp = 0;
+ $sSearchStrDateToMonth_tmp = 0;
+ $sSearchStrDateToYear_tmp = 0;
+ $saveDateTo = $results[$save_date_to];
+ if( isset($saveDateTo) && sizeof($saveDateTo)>0 )
+ {
+ $saveDateTo = str_replace(' 23:59:59', '', $saveDateTo);
+ $saveDateToParts = explode('-', $saveDateTo);
+ if(sizeof($saveDateToParts) == 3)
+ {
+ $retValue[$save_date_to_year] = $saveDateToParts[0];
+ $retValue[$save_date_to_month] = $saveDateToParts[1];
+ $retValue[$save_date_to_day] = $saveDateToParts[2];
+ }
+ }
+ return $retValue;
+}
+
+// SAVE CURRENT SEARCH
+if( sizeof($_GET) == 0 && isset($_POST['save_search']) )
+{
+ $itemtype = rand(0,10000);
+ $itemid = time();
+ $propertyCollection = new PropertyCollection;
+
+ /**
+ * Getting values from POST and storing them to DB
+ * no checking for consistency done here because these values have already been checked when
+ * building form sending this POST
+ */
+
+ // Title / Content
+ $propertyCollection->setValue($itemtype, $itemid, $type, $save_title, $_POST[$save_title]);
+ // ID
+ $propertyCollection->setValue($itemtype, $itemid, $type, $save_id, $_POST[$save_id]);
+ // Date from
+ $propertyCollection->setValue($itemtype, $itemid, $type, $save_date_from, $_POST[$save_date_from]);
+ // Date to
+ $propertyCollection->setValue($itemtype, $itemid, $type, $save_date_to, $_POST[$save_date_to]);
+ // Date type
+ $propertyCollection->setValue($itemtype, $itemid, $type, $save_date_field, $_POST[$save_date_field]);
+ // Author
+ $propertyCollection->setValue($itemtype, $itemid, $type, $save_author, $_POST[$save_author]);
+ // Name of search (displayed to user)
+ $propertyCollection->setValue($itemtype, $itemid, $type, $save_name, $_POST[$save_name]);
+
+ // Call search we justed saved to show results
+ $searchResults = getSearchResults($itemid, $itemtype);
+ $sSearchStr_tmp = $searchResults[$save_title];
+ $iSearchID_tmp = $searchResults[$save_id];
+ $sSearchStrDateType_tmp = $searchResults[$save_date_field];
+ $sSearchStrDateFromDay_tmp = $searchResults[$save_date_from_day];
+ $sSearchStrDateFromMonth_tmp = $searchResults[$save_date_from_month];
+ $sSearchStrDateFromYear_tmp = $searchResults[$save_date_from_year];
+ $sSearchStrDateToDay_tmp = $searchResults[$save_date_to_day];
+ $sSearchStrDateToMonth_tmp = $searchResults[$save_date_to_month];
+ $sSearchStrDateToYear_tmp = $searchResults[$save_date_to_year];
+ $sSearchStrAuthor_tmp = $searchResults[$save_author];
+
+ $sScript = generateJs($searchResults);
+
+ // Reload top left to show new search name
+ $refreshScript .= 'top.content.left.left_top.location.href = top.content.left.left_top.location.href+"&save_search=true";';
+
+ // Message for successfull saving
+ $saveSuccessfull = i18n("Thank you for saving this search from extinction !");
+}
+// STORED SEARCH HAS BEEN CALLED
+elseif( sizeof($_GET) > 0)
+{
+ $itemtypeReq = $_GET['itemtype'];
+ $itemidReq = $_GET['itemid'];
+ // Do we have the request parameters we need to fetch search values of stored search ?
+ if( (isset($itemtypeReq) && strlen($itemtypeReq)>0) &&
+ (isset($itemidReq) && strlen($itemidReq)>0)
+ )
+ {
+ $searchResults = getSearchResults($itemidReq, $itemtypeReq);
+ $sSearchStr_tmp = $searchResults[$save_title];
+ $iSearchID_tmp = $searchResults[$save_id];
+ $sSearchStrDateType_tmp = $searchResults[$save_date_field];
+ $sSearchStrDateFromDay_tmp = $searchResults[$save_date_from_day];
+ $sSearchStrDateFromMonth_tmp = $searchResults[$save_date_from_month];
+ $sSearchStrDateFromYear_tmp = $searchResults[$save_date_from_year];
+ $sSearchStrDateToDay_tmp = $searchResults[$save_date_to_day];
+ $sSearchStrDateToMonth_tmp = $searchResults[$save_date_to_month];
+ $sSearchStrDateToYear_tmp = $searchResults[$save_date_to_year];
+ $sSearchStrAuthor_tmp = $searchResults[$save_author];
+
+ $sSearchStrDateFrom_tmp = $searchResults[$save_date_from];
+ $sSearchStrDateTo_tmp = $searchResults[$save_date_to];
+
+ #script for refreshing search form with stored search options
+ $sScript = generateJs($searchResults);
+
+ }
+ elseif( isset($_GET['recentedit']) )
+ {
+ // compute current day minus one week
+ $actDate = time();
+ $weekInSeconds = 60 * 60 * 24 * 7; // seconds, minutes, hours, days
+ $oneWeekEarlier = $actDate - $weekInSeconds;
+
+ $sSearchStrDateType_tmp = 'lastmodified';
+ $sSearchStrDateFromDay_tmp = date('d', $oneWeekEarlier);
+ $sSearchStrDateFromMonth_tmp = date('m', $oneWeekEarlier);
+ $sSearchStrDateFromYear_tmp = date('Y', $oneWeekEarlier);
+ $sSearchStrDateToDay_tmp = date('d', $actDate);
+ $sSearchStrDateToMonth_tmp = date('m', $actDate);
+ $sSearchStrDateToYear_tmp = date('Y', $actDate);
+ }
+ elseif( isset($_GET['myarticles']) )
+ {
+ $sSearchStrAuthor_tmp = $auth->auth['uname'];
+ }
+}
+// STANDARD SEARCH
+elseif( sizeof($_GET) == 0 && isset($_POST) )
+{
+ $sSearchStr_tmp = trim (strip_tags ($_POST['bs_search_text']));
+ $iSearchID_tmp = (int) $_POST['bs_search_id'];
+ $sSearchStrDateType_tmp = trim (strip_tags ($_POST['bs_search_date_type']));
+ $sSearchStrDateFromDay_tmp = (int) trim (strip_tags ($_POST['bs_search_date_from_day']));
+ $sSearchStrDateFromMonth_tmp = (int) trim (strip_tags ($_POST['bs_search_date_from_month']));
+ $sSearchStrDateFromYear_tmp = (int) trim (strip_tags ($_POST['bs_search_date_from_year']));
+ $sSearchStrDateToDay_tmp = (int) trim (strip_tags ($_POST['bs_search_date_to_day']));
+ $sSearchStrDateToMonth_tmp = (int) trim (strip_tags ($_POST['bs_search_date_to_month']));
+ $sSearchStrDateToYear_tmp = (int) trim (strip_tags ($_POST['bs_search_date_to_year']));
+ $sSearchStrAuthor_tmp = trim (strip_tags ($_POST['bs_search_author']));
+}
+// else ERROR
+// No code here, empty results caught later in code
+
+// Title / Content
+if (!empty($sSearchStr_tmp)) {
+ $sSearchStr = $sSearchStr_tmp;
+}
+// Article ID
+if ($iSearchID_tmp > 0) {
+ $iSearchID = $iSearchID_tmp;
+}
+// Date
+if ($sSearchStrDateType_tmp != 'n/a') {
+ if (($sSearchStrDateFromDay_tmp > 0) && ($sSearchStrDateFromMonth_tmp > 0) && ($sSearchStrDateFromYear_tmp > 0)) {
+ $sSearchStrDateFrom = $sSearchStrDateFromYear_tmp.'-'.$sSearchStrDateFromMonth_tmp.'-'.$sSearchStrDateFromDay_tmp.' 00:00:00';
+ } else {
+ $sSearchStrDateFrom = '';
+ }
+
+ if (($sSearchStrDateToDay_tmp > 0) && ($sSearchStrDateToMonth_tmp > 0) && ($sSearchStrDateToYear_tmp > 0)) {
+ $sSearchStrDateTo = $sSearchStrDateToYear_tmp.'-'.$sSearchStrDateToMonth_tmp.'-'.$sSearchStrDateToDay_tmp.' 23:59:59';
+ } else {
+ $sSearchStrDateTo = '';
+ }
+
+ $sDateFieldName = $sSearchStrDateType_tmp;
+} else {
+ $sDateFieldName = '';
+}
+// Author
+if (!empty($sSearchStrAuthor_tmp)) {
+ $sSearchStrAuthor = $sSearchStrAuthor_tmp;
+}
+
+# liest den gesuchten Artikel aus der Datenbank
+$sql_1 = "SELECT
+ DISTINCT a.idart, a.idartlang, a.title, a.online, a.locked, a.idartlang, a.created, a.published,
+ a.artsort, a.lastmodified, b.idcat, b.idcatart, b.idcatart, c.startidartlang,
+ c.idcatlang, e.name as 'tplname'
+ FROM ".$cfg['tab']['art_lang']." as a
+ LEFT JOIN ".$cfg['tab']['cat_art']." as b ON a.idart = b.idart
+ LEFT JOIN ".$cfg['tab']['cat_lang']." as c ON a.idartlang = c.startidartlang
+ LEFT JOIN ".$cfg['tab']['tpl_conf']." as d ON a.idtplcfg = d.idtplcfg
+ LEFT JOIN ".$cfg['tab']['tpl']." as e ON d.idtpl = e.`idtpl`
+ LEFT JOIN ".$cfg['tab']['content']." as f ON f.idartlang = a.idartlang
+ WHERE
+ (a.idlang = ".Contenido_Security::toInteger($iSpeachID).")
+ ";
+
+$where = "";
+
+$bNoCriteria = true;
+
+// Article ID
+if (!is_null($iSearchID)) {
+ $where.= " AND (a.idart = ".Contenido_Security::toInteger($iSearchID).")";
+ $bNoCriteria = false;
+}
+
+// es soll nach Text gesucht werden
+if (!empty($sSearchStr)) {
+ $where.= " AND ((a.title LIKE '%" . mask(Contenido_Security::escapeDB($sSearchStr, $db)) . "%')";
+ $where.= " OR (f.value LIKE '%" . mask(Contenido_Security::escapeDB($sSearchStr, $db)) . "%'))";
+ $bNoCriteria = false;
+}
+
+if (!empty($sSearchStrDateFrom) && ($sDateFieldName != '')) {
+ $where.= " AND (a.".Contenido_Security::escapeDB($sDateFieldName, $db)." >= '".mask(Contenido_Security::escapeDB($sSearchStrDateFrom, $db))."')";
+ $bNoCriteria = false;
+}
+
+if (!empty($sSearchStrDateTo) && ($sDateFieldName != '')) {
+ $where.= " AND (a.".$sDateFieldName." <= '".mask(Contenido_Security::escapeDB($sSearchStrDateTo, $db))."')";
+ $bNoCriteria = false;
+}
+
+if (!empty($sSearchStrAuthor) && ($sSearchStrAuthor != 'n/a')) {
+ // es soll nach Autor gesucht werden
+ $where.= " AND ((a.author = '" . mask(Contenido_Security::escapeDB($sSearchStrAuthor, $db)) . "') OR (a.modifiedby = '" . mask(Contenido_Security::escapeDB($sSearchStrAuthor, $db))."'))";
+ $bNoCriteria = false;
+}
+
+if (!empty($where)) {
+ $sql_1 .= $where;
+ $db->query($sql_1);
+}
+
+if (!empty($sSession)) {
+ $sSessionAppend = '?contenido=' . $sSession;
+}
+
+$tpl = new Template();
+
+$tpl->setEncoding('iso-8859-1');
+$tpl->set('s', 'SESSID', $sSession);
+$tpl->set('s', 'SCRIPT', $sScript);
+$tpl->set('s', 'SESSNAME', $sess->name);
+$tpl->set('s', 'TITLE', i18n('Search results'));
+$tpl->set('s', 'TH_START', i18n("Article"));
+$tpl->set('s', 'TH_TITLE', i18n("Title"));
+$tpl->set('s', 'TH_CHANGED', i18n("Changed"));
+$tpl->set('s', 'TH_PUBLISHED', i18n("Published"));
+$tpl->set('s', 'TH_SORTORDER', i18n("Sort order"));
+$tpl->set('s', 'TH_TEMPLATE', i18n("Template"));
+$tpl->set('s', 'TH_ACTIONS', i18n("Actions"));
+
+// Refresh top left frame
+$tpl->set('s', 'REFRESH', $refreshScript);
+
+// Successfully stored Message
+$tpl->set('s', 'SEARCHSTOREDMESSAGE', $saveSuccessfull);
+$iAffectedRows = $db->affected_rows();
+if (empty($where) || $iAffectedRows <= 0) {
+ $sNoArticle = i18n("Missing search value.");
+ $sNothingFound = i18n("No article found.");
+
+ if( $bNoCriteria ) {
+ $sErrOut = $sNoArticle;
+ } else {
+ $sErrOut = $sNothingFound;
+ }
+
+ $sRow = '' . $sErrOut . ' ';
+ $tpl->set('d', 'ROWS', $sRow);
+ $tpl->next();
+} else {
+ $bHit = false;
+
+ for ($i = 0; $i < $iAffectedRows; $i++) {
+
+ // reinitialisiere Hilfs-String
+ $sRow = '';
+
+ $db->next_record();
+
+ $idcat = $db->f("idcat");
+ $check_rights = $perm->have_perm_area_action("con", "con_makestart");
+
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action("con", "con_makeonline");
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action("con", "con_deleteart");
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action("con", "con_tplcfg_edit");
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action("con", "con_makecatonline");
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action("con", "con_changetemplate");
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action("con_editcontent", "con_editart");
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action("con_editart", "con_edit");
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action("con_editart", "con_newart");
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action("con_editart", "con_saveart");
+ }
+
+ #Check rights per cat
+ if (!$check_rights) {
+ //hotfix timo trautmann 2008-12-10 also check rights in associated groups
+ $aGroupsForUser = $perm->getGroupsForUser($auth->auth[uid]);
+ $aGroupsForUser[] = $auth->auth[uid];
+ $sTmpUserString = implode("','", $aGroupsForUser);
+
+ #Check if any rights are applied to current user or his groups
+ $sql = "SELECT *
+ FROM ".$cfg["tab"]["rights"]."
+ WHERE user_id IN ('".$sTmpUserString."') AND idclient = '".Contenido_Security::toInteger($client)."' AND idlang = '".Contenido_Security::toInteger($lang)."' AND idcat = '".Contenido_Security::toInteger($idcat)."'";
+ $db2->query($sql);
+
+ if ($db2->num_rows() != 0) {
+
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action_item("con", "con_makestart",$idcat);
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action_item("con", "con_makeonline",$idcat);
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action_item("con", "con_deleteart",$idcat);
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action_item("con", "con_tplcfg_edit",$idcat);
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action_item("con", "con_makecatonline",$idcat);
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action_item("con", "con_changetemplate",$idcat);
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action_item("con_editcontent", "con_editart",$idcat);
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action_item("con_editart", "con_edit",$idcat);
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action_item("con_editart", "con_newart",$idcat);
+ }
+ if (!$check_rights) {
+ $check_rights = $perm->have_perm_area_action_item("con_editart", "con_saveart",$idcat);
+ }
+ }
+ }
+ if ($check_rights) {
+ $bHit = true;
+
+ $idart = $db->f("idart");
+ $idartlang = $db->f("idartlang");
+ $idcatart = $db->f("idcatart");
+ $idcatlang = $db->f("idcatlang");
+ $title = $db->f("title");
+ $idartlang = $db->f("idartlang");
+ $created = date($dateformat, strtotime($db->f("created")));
+ $lastmodified = date($dateformat, strtotime($db->f("lastmodified")));
+ $published = date($dateformat, strtotime($db->f("published")));
+ $online = $db->f("online");
+ $locked = $db->f("locked");
+ $startidartlang = $db->f("startidartlang");
+ $templatename = $db->f("tplname");
+
+ // fuer den ersten gefundenen Artikel die Werte fuer CategoryID und TemplateID merken
+ if ($i == 0) {
+ $iIDCat = $idcat;
+ $iIDTpl = $idtpl;
+ }
+
+ /* Funktion zum umwandeln in Startartikel/normale Artikel*/
+ if ($perm->have_perm_area_action_item("con", "con_makestart",$idcat) && 0 == 1) {
+ if( $startidartlang == $idartlang ) {
+ $sFlagTitle = i18n('Flag as normal article');
+ $makeStartarticle = " ";
+ } else {
+ $sFlagTitle = i18n('Flag as start article');
+ $makeStartarticle = " ";
+ }
+ } else {
+ if( $startidartlang == $idartlang ) {
+ $makeStartarticle = " ";
+ } else {
+ $makeStartarticle = " ";
+ }
+ }
+
+ /* Funktion zum online/offline stellen */
+ if( $online==1 ) {
+ $sOnlineStatus = i18n('Make offline');
+ $bgColorRow = "background-color: #E2E2E2;";
+ $setOnOff = " ";
+ } else {
+ $sOnlineStatus = i18n('Make online');
+ $bgColorRow = "background-color: #E2D9D9;";
+ $setOnOff = " ";
+ }
+ /* Funktion zum Artikel sperren/entsperren */
+ if( $locked==1 ) {
+ $sLockStatus = i18n('Unfreeze article');
+ $lockArticle = " ";
+ } else {
+ $sLockStatus = i18n('Freeze article');
+ $lockArticle = " ";
+ }
+
+ /* Templatename */
+ if (!empty($templatename)) {
+ $sTemplateName = clHtmlEntities($templatename);
+ } else {
+ $sTemplateName = '--- ' . i18n("None") . ' ---';
+ }
+
+ $todoListeSubject = i18n("Reminder");
+
+ $sReminder = i18n("Set reminder / add to todo list");
+ $sDuplicateArticle = i18n("Duplicate article");
+ $sArticleProperty = i18n("Article properties");
+ $sConfigureTpl = i18n("Configure template");
+ $sDeleteArticle = i18n("Delete article");
+ $sDeleteArticleQuestion = i18n("Do you really want to delete following article");
+
+ $sRowId = "$idart-$idartlang-$idcat-0-$idcatart-$iLangID";
+
+ if ($i == 0) {
+ $tpl->set('s', 'FIRST_ROWID', $sRowId);
+ }
+
+ if ($online == 1 OR ($i % 2 == 1)) {
+ $bgColorRow = '#E2E2E2';
+ } else {
+ $bgColorRow = '#E2E2E2';
+ }
+
+ if ($perm->have_perm_area_action_item("con_editcontent", "con_editart",$idcat)) {
+ $editart = "".$db->f("title")." ";
+ } else {
+ $editart = $db->f("title");
+ }
+
+ if ($perm->have_perm_area_action_item("con", "con_duplicate",$idcat)) {
+ $duplicate = " ";
+ } else {
+ $duplicate = "";
+ }
+
+ if ($perm->have_perm_area_action_item("con", "con_deleteart",$idcat)) {
+ $delete = "$db->f('title') ", "deleteArticle($idart,$idcat)")\" title=\"$sDeleteArticle\"> ";
+ }else {
+ $delete = "";
+ }
+
+ $sRow = '' . "\n";
+ $sRow .= $makeStartarticle . "\n";
+ $sRow .= "$editart
+ $lastmodified
+ $published
+ ".$db->f("artsort")."
+ $sTemplateName
+
+
+ $properties
+ $tplconfig
+ $duplicate
+ $delete
+
+ ";
+
+ $tpl->set('d', 'ROWS', $sRow);
+ $tpl->next();
+ } #if
+ } #for
+
+ if (!$bHit) {
+
+ $sNothingFound = i18n("No article found.");
+
+ $sRow = '' . $sNothingFound . ' ';
+ $tpl->set('d', 'ROWS', $sRow);
+ $tpl->next();
+ }
+
+ $sLoadSubnavi = 'parent.parent.frames["right"].frames["right_top"].location.href = \'main.php?area=con&frame=3&idcat=' . $iIDCat . '&idtpl=' . $iIDTpl . '&contenido=' . $sSession . "';";
+} #if
+
+
+###########################
+# Save Search Parameters
+###########################
+
+if($bHit && sizeof($_GET) == 0 && isset($_POST) ) {
+ // Build form with hidden fields that contain all search parameters to be stored using generic db
+ $searchForm = '';
+ $tpl->set('s', 'STORESEARCHFORM', $searchForm);
+
+ // Title / Header for 'store the search' form
+ $tpl->set('s', 'STORESEARCHINFO', i18n("Save this Search"));
+} else {
+ $tpl->set('s', 'STORESEARCHINFO', '');
+ $tpl->set('s', 'STORESEARCHFORM', '');
+}
+
+$tpl->set('s', 'SUBNAVI', $sLoadSubnavi);
+sendEncodingHeader($db, $cfg, $lang);
+$tpl->generate($cfg['path']['templates'] . 'template.backend_search_results.html');
+?>
diff --git a/conlite/cache/deprecated.txt b/conlite/cache/deprecated.txt
new file mode 100644
index 0000000..0e406df
--- /dev/null
+++ b/conlite/cache/deprecated.txt
@@ -0,0 +1,2 @@
+This folder is marked as deprecated and will be deleted in next versions of ConLite.
+Please use folders in data-directory instead!
\ No newline at end of file
diff --git a/conlite/classes/Contenido_Category/Contenido_Category.class.php b/conlite/classes/Contenido_Category/Contenido_Category.class.php
new file mode 100644
index 0000000..3f9c5c7
--- /dev/null
+++ b/conlite/classes/Contenido_Category/Contenido_Category.class.php
@@ -0,0 +1,904 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-15
+ * modified 2008-02-22 Contenido_Categories now implements Countable
+ * modified 2008-08-20 Removed unnecessary/redundant security fixes (typecasting is already done in getter methods) that were made during security fixing phase
+ * changed method setDebug() in Contenido_Category_Base to allow all debug modes available
+ * modified 2009-01-05 Bugfix in Contenido_Categories::load() Subcategories will be loaded only if set so.
+ * modified 2009-01-14 Removed duplicate row in sql select at method load()
+ * $Id: Contenido_Category.class.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+/**
+ * Implementation of a Contenido Category.
+ * @version 0.9.0
+ * @author Rudi Bieller
+ * @copyright four for business AG
+ * {@internal
+ * created 2008-02-15
+ * }}
+ */
+class Contenido_Category extends Contenido_Category_Base {
+ /**#@+
+ * @var int
+ * @access protected
+ */
+ protected $iIdCat;
+ protected $iIdClient;
+ protected $iIdParent;
+ protected $iIdPre;
+ protected $iIdPost;
+ protected $iStatus;
+ /**#@-*/
+
+ /**#@+
+ * @var string
+ * @access protected
+ */
+ protected $sAuthor;
+ protected $sCreated;
+ protected $sModified;
+ /**#@-*/
+
+ /**
+ * @var obj
+ * @access protected
+ */
+ protected $oCategoryLanguage;
+ /**
+ * @var int
+ * @access protected
+ */
+ protected $iIdLang;
+
+ /**
+ * @var boolean
+ * @access protected
+ */
+ protected $bLoadSubCategories;
+
+ /**
+ * @var obj
+ * @access protected
+ */
+ protected $oSubCategories; // if required, this holds the SubCategories of current Category
+
+ /**
+ * @var boolean
+ * @access protected
+ */
+ protected $bHasSubCategories;
+
+ /**
+ * @var int
+ * @access protected
+ */
+ protected $iCurrentSubCategoriesLoadDepth; // current level of SubCategories
+
+ /**
+ * @var int
+ * @access protected
+ */
+ protected $iSubCategoriesLoadDepth; // up to which level should SubCategories be loaded
+
+ /**
+ * @var obj DB_ConLite
+ * @access private
+ */
+ private $_oDb;
+
+
+ /**
+ * Constructor.
+ * @access public
+ * @param DB_ConLite $oDb
+ * @param array $aCfg
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function __construct(DB_ConLite $oDb, array $aCfg) {
+ parent::__construct($oDb, $aCfg);
+ $this->oSubCategories = null;
+ $this->bHasSubCategories = false;
+ $this->iSubCategoriesLoadDepth = 0;
+ $this->iCurrentSubCategoriesLoadDepth = 0;
+ }
+
+ /**
+ * Loads properties for a given idcat. Optionally, also properties from catlang will be loaded into object.
+ *
+ * @access public
+ * @param int $iIdCat
+ * @param boolean $bIncludeLanguage If set to true, also creates Contenido_Category_Language object
+ * @param int $iIdlang If $bIncludeLanguage is set to true, you must set this value, too or use setIdLang() before!
+ * @return boolean
+ * @throws InvalidArgumentException
+ * @throws Exception TODO
+ * @author Rudi Bieller
+ */
+ public function load($iIdCat, $bIncludeLanguage = false, $iIdlang = -1) {
+ if (intval($iIdCat) <= 0) {
+ throw new InvalidArgumentException('Idcat to load must be greater than 0!');
+ }
+ $this->setIdLang($iIdlang);
+ if ($bIncludeLanguage === true && $this->getIdLang() == -1) {
+ throw new InvalidArgumentException('When setting $bIncludeLanguage to true you must provide an $iIdlang!');
+ }
+ $sSql = 'SELECT
+ idclient, parentid, preid, postid, status, author, created, lastmodified
+ FROM
+ ' . $this->aCfg['tab']['cat'] . '
+ WHERE
+ idcat = ' . Contenido_Security::toInteger($iIdCat);
+ if ($this->bDbg === true) {
+ $this->oDbg->show($sSql, 'Contenido_Category::load($iIdCat, $bIncludeLanguage = false, $iIdlang = -1): $sSql');
+ }
+ $this->oDb->query($sSql);
+ if ($this->oDb->Errno != 0) {
+ return false;
+ }
+ $this->oDb->next_record();
+ $this->setIdCat($iIdCat);
+ $this->setIdClient($this->oDb->f('idclient'));
+ $this->setIdParent($this->oDb->f('parentid'));
+ $this->setIdPre($this->oDb->f('preid'));
+ $this->setIdPost($this->oDb->f('postid'));
+ $this->setStatus($this->oDb->f('status'));
+ $this->setAuthor($this->oDb->f('author'));
+ $this->setDateCreated($this->oDb->f('created'));
+ $this->setDateModified($this->oDb->f('lastmodified'));
+ if ($bIncludeLanguage === true) {
+ try {
+ $oCategoryLanguage = new Contenido_Category_Language($this->oDb, $this->aCfg);
+ $oCategoryLanguage->setDebug($this->bDbg, $this->sDbgMode);
+ $oCategoryLanguage->setIdCat($this->getIdCat());
+ $oCategoryLanguage->setIdLang($this->getIdLang());
+ $oCategoryLanguage->load();
+ $this->setCategoryLanguage($oCategoryLanguage);
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+ if ($this->bLoadSubCategories === true) {
+ $this->_getSubCategories($iIdCat, $bIncludeLanguage, $iIdlang);
+ }
+ return true;
+ }
+
+ /**
+ * Loads SubCategories depending on values for $this->bLoadSubCategories and $this->iSubCategoriesLoadDepth
+ * @access private
+ * @param int $iIdcat
+ * @param boolean $bIncludeLanguage If set to true, also creates Contenido_Category_Language object
+ * @param int $iIdlang If $bIncludeLanguage is set to true, you must set this value, too or use setIdLang() before!
+ * @return Contenido_Categories
+ * @author Rudi Bieller
+ */
+ private function _getSubCategories($iIdcat, $bIncludeLanguage = false, $iIdlang = -1) {
+ if (intval($iIdcat) <= 0) {
+ throw new InvalidArgumentException('Idcat to load must be greater than 0!');
+ }
+ if ($bIncludeLanguage === true && $this->getIdLang() == -1) {
+ throw new InvalidArgumentException('When setting $bIncludeLanguage to true you must provide an $iIdlang!');
+ }
+ // if we don't have a Contenido_Categories object created yet, do it now
+ if (is_null($this->oSubCategories)) {
+ $this->oSubCategories = new Contenido_Categories($this->oDb, $this->aCfg);
+ $this->_oDb = new DB_ConLite();
+ }
+ $aSubCategories = $this->_getSubCategoriesAsArray($iIdcat);
+ // current load depth: $this->iCurrentSubCategoriesLoadDepth
+ // load depth to go to: $this->iSubCategoriesLoadDepth
+ foreach ($aSubCategories as $iIdcatCurrent) {
+ try {
+ $oCategory = new Contenido_Category($this->_oDb, $this->aCfg);
+ $oCategory->setDebug($this->bDbg, $this->sDbgMode);
+ if ($this->iSubCategoriesLoadDepth > 0) {
+ $oCategory->setloadSubCategories($this->bLoadSubCategories, ($this->iSubCategoriesLoadDepth - 1));
+ }
+ $oCategory->load($iIdcatCurrent, $bIncludeLanguage, $iIdlang);
+ $this->oSubCategories->add($oCategory);
+ } catch (InvalidArgumentException $e) {
+ throw $e;
+ }
+ }
+ }
+
+ /**
+ * Return array with idcats of subcategories of given idcat
+ * @access private
+ * @param int $iIdcat
+ * @return array
+ * @author Rudi Bieller
+ */
+ private function _getSubCategoriesAsArray($iIdcat) {
+ if (intval($iIdcat) <= 0) {
+ throw new InvalidArgumentException('Idcat to load must be greater than 0!');
+ }
+ $aSubCats = array();
+ $sSql = 'SELECT
+ cattree.idcat
+ FROM
+ '.$this->aCfg["tab"]["cat_tree"].' AS cattree,
+ '.$this->aCfg["tab"]["cat"].' AS cat,
+ '.$this->aCfg["tab"]["cat_lang"].' AS catlang
+ WHERE
+ cattree.idcat = cat.idcat AND
+ cat.idcat = catlang.idcat AND
+ cat.idclient = ' . $this->getIdClient() . ' AND
+ catlang.idlang = ' . $this->getIdLang() . ' AND
+ catlang.visible = 1 AND
+ cat.parentid = ' . Contenido_Security::toInteger($iIdcat) .'
+ ORDER BY
+ cattree.idtree';
+ if ($this->bDbg === true) {
+ $this->oDbg->show($sSql, 'Contenido_Category::_getSubCategoriesAsArray($iIdcat): $sSql');
+ }
+ $this->oDb->query($sSql);
+ if ($this->oDb->Errno != 0) {
+ return false;
+ }
+ while ($this->oDb->next_record()) {
+ $aSubCats[] = $this->oDb->f('idcat');
+ }
+ return $aSubCats;
+ }
+
+ // SETTER
+
+ /**
+ * If you need to load SubCategories, set to true and set how deep SubCategories should be loaded
+ * @access public
+ * @param boolean $bLoad
+ * @param int $iLoadDepth
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function setloadSubCategories($bLoad = false, $iLoadDepth = 0) {
+ $this->bLoadSubCategories = (boolean) $bLoad;
+ $this->iSubCategoriesLoadDepth = (int) $iLoadDepth;
+ }
+
+ /**
+ * Set internal property with SubCategories of current Category
+ * @access public
+ * @param Contenido_Categories $oCategories
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function setSubCategories(Contenido_Categories $oCategories) {
+ $this->oSubCategories = $oCategories;
+ }
+
+ public function setCategoryLanguage(Contenido_Category_Language $oCatLang) {
+ $this->oCategoryLanguage = $oCatLang;
+ }
+
+ public function setIdCat($iIdcat) {
+ $this->iIdCat = (int) $iIdcat;
+ }
+ public function setIdClient($iIdcient) {
+ $this->iIdClient = (int) $iIdcient;
+ }
+ public function setIdParent($iIdcatParent) {
+ $this->iIdParent = (int) $iIdcatParent;
+ }
+ public function setIdPre($iIdcatPre) {
+ $this->iIdPre = (int) $iIdcatPre;
+ }
+ public function setIdPost($iIdcatPost) {
+ $this->iIdPost = (int) $iIdcatPost;
+ }
+ public function setStatus($iStatus) {
+ $iStatus = (int) $iStatus;
+ $aValid = array(0, 1);
+ if (!in_array($iStatus, $aValid)) {
+ throw new InvalidArgumentException('Status must be either 0 or 1');
+ }
+ $this->iStatus = $iStatus;
+ }
+ public function setAuthor($sAuthor) {
+ // TODO: input validation, strlen 32
+ $this->sAuthor = (string) $sAuthor;
+ }
+ public function setDateCreated($sDateCreated) {
+ // TODO: input validation, correct date/datetime format
+ $this->sCreated = (string) $sDateCreated;
+ }
+ public function setDateModified($sDateModified) {
+ // TODO: input validation, correct date/datetime format
+ $this->sModified = (string) $sDateModified;
+ }
+ public function setIdLang($iIdlang) {
+ $this->iIdLang = (int) $iIdlang;
+ }
+
+ // GETTER
+
+ public function getSubCategories() {
+ return is_null($this->oSubCategories) ? new Contenido_Categories($this->oDb, $this->aCfg) : $this->oSubCategories;
+ }
+
+ public function getCategoryLanguage() {
+ return !is_null($this->oCategoryLanguage) ? $this->oCategoryLanguage : new Contenido_Category_Language($this->oDb, $this->aCfg);
+ }
+
+ public function getIdCat() {
+ return !is_null($this->iIdCat) ? (int) $this->iIdCat : -1;
+ }
+ public function getIdClient() {
+ return !is_null($this->iIdClient) ? (int) $this->iIdClient : -1;
+ }
+ public function getIdParent() {
+ return !is_null($this->iIdParent) ? (int) $this->iIdParent : -1;
+ }
+ public function getIdPre() {
+ return !is_null($this->iIdPre) ? (int) $this->iIdPre : -1;
+ }
+ public function getIdPost() {
+ return !is_null($this->iIdPost) ? (int) $this->iIdPost : -1;
+ }
+ public function getStatus() {
+ return !is_null($this->iStatus) ? (int) $this->iStatus : -1;
+ }
+ public function getAuthor() {
+ return !is_null($this->sAuthor) ? (string) $this->sAuthor : '';
+ }
+ public function getDateCreated() {
+ return !is_null($this->sCreated) ? (string) $this->sCreated : '';
+ }
+ public function getDateModified() {
+ return !is_null($this->sModified) ? (string) $this->sModified : '';
+ }
+ public function getIdLang() {
+ return (!is_null($this->iIdLang) && $this->iIdLang > 0) ? (int) $this->iIdLang : -1;
+ }
+}
+
+/**
+ * Implementation of a "Collection" of Contenido Categories.
+ * @version 0.9.0
+ * @author Rudi Bieller
+ * @copyright four for business AG
+ * {@internal
+ * created 2008-02-15
+ * modified 2008-02-25 Implemented ArrayAccess; added methods reverse(), ksort() and krsort().
+ * }}
+ */
+class Contenido_Categories extends Contenido_Category_Base implements IteratorAggregate, ArrayAccess, Countable {
+ /**
+ * @var array
+ * @access protected
+ */
+ protected $aContenidoCategories;
+ /**
+ * @var int
+ * @access protected
+ */
+ protected $iIdLang;
+ /**
+ * @var boolean
+ * @access protected
+ */
+ protected $bLoadSubCategories;
+
+ /**
+ * @var int
+ * @access protected
+ */
+ protected $iSubCategoriesLoadDepth; // up to which level should SubCategories be loaded
+
+ /**
+ * Constructor.
+ * @access public
+ * @param DB_ConLite $oDb
+ * @param array $aCfg
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function __construct(DB_ConLite $oDb, array $aCfg) {
+ parent::__construct($oDb, $aCfg);
+ $this->aContenidoCategories = array();
+ $this->bLoadSubCategories = false;
+ $this->iSubCategoriesLoadDepth = 0;
+ }
+
+ /**
+ * Loads a range of Category-IDs.
+ * @access public
+ * @param array $aCategoryIds
+ * @param boolean $bIncludeLanguage
+ * @param int $iIdlang If $bIncludeLanguage is set to true, you must set this value, too or use setIdLang() before!
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function load(array $aCategoryIds, $bIncludeLanguage = false, $iIdlang = -1) {
+ $this->setIdLang($iIdlang);
+ if (sizeof($aCategoryIds) > 0) {
+ // loop over passed category ids and create single Category object on each run
+ foreach ($aCategoryIds as $iId) {
+ $iIdLang = $this->getIdLang();
+ $oCategory = new Contenido_Category($this->oDb, $this->aCfg);
+ $oCategory->setDebug($this->bDbg, $this->sDbgMode);
+ if ($this->iSubCategoriesLoadDepth > 0) {
+ $oCategory->setloadSubCategories($this->bLoadSubCategories, $this->iSubCategoriesLoadDepth);
+ }
+ $oCategory->load($iId, $bIncludeLanguage, $iIdLang);
+ $this->add($oCategory);
+ }
+ }
+ }
+
+ /**
+ * Add a Contenido_Category object into internal array ("Collection")
+ * @access public
+ * @param Contenido_Category $oContenidoCategory
+ * @param int $iOffset
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function add(Contenido_Category $oContenidoCategory, $iOffset = null) {
+ $this->offsetSet($iOffset, $oContenidoCategory);
+ }
+
+ /**
+ * If you need to load SubCategories, set to true and set how deep SubCategories should be loaded
+ * @access public
+ * @param boolean $bLoad
+ * @param int $iLoadDepth
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function setloadSubCategories($bLoad = false, $iLoadDepth = 0) {
+ $this->bLoadSubCategories = (boolean) $bLoad;
+ $this->iSubCategoriesLoadDepth = (int) $iLoadDepth;
+ }
+
+ /**
+ * Set internal property for Contenido-Idlang
+ * @access public
+ * @param int $iIdlang
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function setIdLang($iIdlang) {
+ $this->iIdLang = (int) $iIdlang;
+ }
+
+ /**
+ * Get internal property for Contenido-Idlang
+ * @access public
+ * @return int
+ * @author Rudi Bieller
+ */
+ public function getIdLang() {
+ return (!is_null($this->iIdLang) && $this->iIdLang > 0) ? (int) $this->iIdLang : -1;
+ }
+
+ /**
+ * Interface method for Iterator.
+ * @access public
+ * @return ArrayObject
+ * @author Rudi Bieller
+ */
+ public function getIterator () {
+ return new ArrayObject($this->aContenidoCategories);
+ }
+
+ /**
+ * Interface method for Countable.
+ * @access public
+ * @return int
+ * @author Rudi Bieller
+ */
+ public function count () {
+ return sizeof($this->aContenidoCategories);
+ }
+
+ /**
+ * Sort list of Contenido_Category objects by assigned key
+ * @access public
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function ksort() {
+ ksort($this->aContenidoCategories);
+ }
+
+ /**
+ * Sort list of Contenido_Category objects by assigned key in reverse order
+ * @access public
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function krsort() {
+ krsort($this->aContenidoCategories);
+ }
+
+ /**
+ * Sort list of Contenido_Category objects in reverse order
+ * @access public
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function reverse() {
+ $this->aContenidoCategories = array_reverse($this->aContenidoCategories);
+ }
+
+ // Methods for ArrayAccess
+
+ /**
+ * Interface method for ArrayAccess.
+ * @access public
+ * @param int $mOffset
+ * @return boolean
+ * @author Rudi Bieller
+ */
+ public function offsetExists($mOffset) {
+ return array_key_exists($this->aContenidoCategories, $mOffset);
+ }
+ /**
+ * Interface method for ArrayAccess.
+ * @access public
+ * @param int $mOffset
+ * @return obj
+ * @author Rudi Bieller
+ */
+ public function offsetGet($mOffset) {
+ return $this->aContenidoCategories[$mOffset];
+ }
+ /**
+ * Interface method for ArrayAccess.
+ * @access public
+ * @param int $mOffset
+ * @param mixed $mValue
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function offsetSet($mOffset, $mValue) {
+ if (is_null($mOffset)) {
+ $this->aContenidoCategories[] = $mValue;
+ } else {
+ $this->aContenidoCategories[$mOffset] = $mValue;
+ }
+ }
+ /**
+ * Interface method for ArrayAccess.
+ * @access public
+ * @param int $mOffset
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function offsetUnset($mOffset) {
+ unset($this->aContenidoCategories[$mOffset]);
+ }
+}
+
+/**
+ * Implementation of a Contenido Category for a given Contenido Language.
+ * @version 0.9.0
+ * @author Rudi Bieller
+ * @copyright four for business AG
+ * {@internal
+ * created 2008-02-15
+ * }}
+ */
+class Contenido_Category_Language extends Contenido_Category_Base {
+ /**#@+
+ * @var int
+ * @access protected
+ */
+ protected $iIdCatlang;
+ protected $iIdCat;
+ protected $iIdLang;
+ protected $iIdTplcfg;
+ /**#@-*/
+
+ /**
+ * @var string
+ * @access protected
+ */
+ protected $sName;
+ protected $sAlias;
+
+ /**#@+
+ * @var int
+ * @access protected
+ */
+ protected $iVisible;
+ protected $iPublic;
+ protected $iStatus;
+ /**#@-*/
+
+ /**#@+
+ * @var string
+ * @access protected
+ */
+ protected $sAuthor;
+ protected $sDateCreated;
+ protected $sDateModified;
+ /**#@-*/
+
+ /**
+ * @var int
+ * @access protected
+ */
+ protected $iStartIdartlang;
+ /**
+ * @var string
+ * @access protected
+ */
+ protected $sUrlname;
+
+ /**
+ * Constructor.
+ * @access public
+ * @param DB_ConLite $oDb
+ * @param array $aCfg
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function __construct(DB_ConLite $oDb, array $aCfg) {
+ parent::__construct($oDb, $aCfg);
+ }
+
+ /**
+ * Load cat_lang for a given idcat.
+ * @access public
+ * @param int $iIdCatLang
+ * @return boolean
+ * @author Rudi Bieller
+ */
+ public function load($iIdCatLang = null) {
+ if ($this->getIdCat() == -1 || $this->getIdLang() == -1) {
+ throw new Exception('idcat and idlang must be set in order to load from con_cat_lang!');
+ }
+ if (is_null($iIdCatLang)) {
+ $sSql = 'SELECT
+ idcatlang, idtplcfg, name, visible, public, status, author, created, lastmodified, startidartlang, urlname
+ FROM
+ ' . $this->aCfg["tab"]["cat_lang"] . '
+ WHERE
+ idcat = ' . $this->getIdCat() . ' AND
+ idlang = ' . $this->getIdLang();
+ } else {
+ $sSql = 'SELECT
+ idcatlang, idtplcfg, name, visible, public, status, author, created, lastmodified, startidartlang, urlname
+ FROM
+ ' . $this->aCfg["tab"]["cat_lang"] . '
+ WHERE
+ idcatlang = ' . Contenido_Security::toInteger($iIdCatLang);
+ }
+ $this->oDb->query($sSql);
+ if ($this->oDb->Errno != 0) {
+ return false;
+ }
+ $this->oDb->next_record();
+ $this->setIdCatLang($this->oDb->f('idcatlang'));
+ $this->setIdCat($this->getIdCat());
+ $this->setIdLang($this->getIdLang());
+ $this->setIdTemplateConfig($this->oDb->f('idtplcfg'));
+ $this->setName($this->oDb->f('name'));
+ $this->setAlias($this->oDb->f('urlname'));
+ $this->setVisible($this->oDb->f('visible'));
+ $this->setPublic($this->oDb->f('public'));
+ $this->setStatus($this->oDb->f('status'));
+ $this->setAuthor($this->oDb->f('author'));
+ $this->setDateCreated($this->oDb->f('created'));
+ $this->setDateLastModified($this->oDb->f('lastmodified'));
+ $this->setStartIdLang($this->oDb->f('startidartlang'));
+ $this->setUrlName($this->oDb->f('urlname'));
+ return true;
+ }
+
+ // SETTER
+
+ public function setIdCatLang($iIdcatlang) {
+ $this->iIdCatlang = (int) $iIdcatlang;
+ }
+ public function setIdCat($iIdcat) {
+ $this->iIdCat = (int) $iIdcat;
+ }
+ public function setIdLang($iIdlang) {
+ $this->iIdlang = (int) $iIdlang;
+ }
+ public function setIdTemplateConfig($iIdTplcfg) {
+ $this->iIdTplcfg = (int) $iIdTplcfg;
+ }
+ public function setName($sName) {
+ $this->sName = (string) $sName;
+ }
+ public function setAlias($sAlias) {
+ $this->sAlias = (string) $sAlias;
+ }
+ public function setVisible($iVisible) {
+ $iVisible = (int) $iVisible;
+ $aValid = array(0,1);
+ if (!in_array($iVisible, $aValid)) {
+ throw new InvalidArgumentException('Visible must be either 0 or 1');
+ }
+ $this->iVisible = $iVisible;
+ }
+ public function setPublic($iPublic) {
+ $iPublic = (int) $iPublic;
+ $aValid = array(0,1);
+ if (!in_array($iPublic, $aValid)) {
+ throw new InvalidArgumentException('Public must be either 0 or 1');
+ }
+ $this->iPublic = $iPublic;
+ }
+ public function setStatus($iStatus) {
+ $iStatus = (int) $iStatus;
+ $aValid = array(0,1);
+ if (!in_array($iStatus, $aValid)) {
+ throw new InvalidArgumentException('Status must be either 0 or 1');
+ }
+ $this->iStatus = $iStatus;
+ }
+ public function setAuthor($sAuthor) {
+ $this->sAuthor = (string) $sAuthor;
+ }
+ public function setDateCreated($sDateCreated) {
+ $this->sDateCreated = (string) $sDateCreated;
+ }
+ public function setDateLastModified($sDateLastModified) {
+ $this->sDateModified = (string) $sDateLastModified;
+ }
+ public function setStartIdLang($iStartIdlang) {
+ $this->iStartIdartlang = (int) $iStartIdlang;
+ }
+ public function setUrlName($sUrlName) {
+ $this->sUrlname = (string) $sUrlName;
+ }
+
+ // GETTER
+
+ public function getIdCatLang() {
+ return !is_null($this->iIdCatlang) ? (int) $this->iIdCatlang : -1;
+ }
+ public function getIdCat() {
+ return !is_null($this->iIdCat) ? (int) $this->iIdCat : -1;
+ }
+ public function getIdLang() {
+ return !is_null($this->iIdlang) ? (int) $this->iIdlang : -1;
+ }
+ public function getIdTemplateConfig() {
+ return !is_null($this->iIdTplcfg) ? (int) $this->iIdTplcfg : -1;
+ }
+ public function getName() {
+ return !is_null($this->sName) ? (string) $this->sName : '';
+ }
+ public function getAlias() {
+ return !is_null($this->sAlias) ? (string) $this->sAlias : '';
+ }
+ public function getVisible() {
+ return !is_null($this->iVisible) ? (int) $this->iVisible : -1;
+ }
+ public function getPublic() {
+ return !is_null($this->iPublic) ? (int) $this->iPublic : -1;
+ }
+ public function getStatus() {
+ return !is_null($this->iStatus) ? (int) $this->iStatus : -1;
+ }
+ public function getAuthor() {
+ return !is_null($this->sAuthor) ? (string) $this->sAuthor : '';
+ }
+ public function getDateCreated() {
+ return !is_null($this->sDateCreated) ? (string) $this->sDateCreated : '';
+ }
+ public function getDateLastModified() {
+ return !is_null($this->sDateModified) ? (string) $this->sDateModified : '';
+ }
+ public function getStartIdLang() {
+ return !is_null($this->iStartIdartlang) ? (int) $this->iStartIdartlang : -1;
+ }
+ public function getUrlName() {
+ return !is_null($this->sUrlname) ? (string) $this->sUrlname : '';
+ }
+}
+
+/**
+ * Base class for Contenido_Category, Contenido_Categories, Contenido_Category_Language.
+ * @version 0.9.0
+ * @author Rudi Bieller
+ * @copyright four for business AG
+ * {@internal
+ * created 2008-02-15
+ * }}
+ */
+class Contenido_Category_Base {
+ /**
+ * @var obj
+ * @access protected
+ */
+ protected $oDb;
+ /**
+ * @var array
+ * @access protected
+ */
+ protected $aCfg;
+ /**
+ * @var boolean
+ * @access protected
+ */
+ protected $bDbg;
+ /**
+ * @var string
+ * @access protected
+ */
+ protected $sDbgMode;
+ /**
+ * @var obj
+ * @access protected
+ */
+ protected $oDbg;
+
+ /**
+ * Constructor.
+ * @access public
+ * @param DB_ConLite $oDb
+ * @param array $aCfg
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function __construct(DB_ConLite $oDb, array $aCfg) {
+ $this->oDb = $oDb;
+ $this->aCfg = $aCfg;
+ $this->bDbg = false;
+ $this->oDbg = null;
+ }
+
+ /**
+ * Set internal property for debugging on/off and choose appropriate debug object
+ * @access public
+ * @param boolean $bDebug
+ * @param string $sDebugMode
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function setDebug($bDebug = true, $sDebugMode = 'visible') {
+ if ($bDebug === false) {
+ $this->bDbg = false;
+ $this->oDbg = null;
+ $this->sDbgMode = 'hidden';
+ } else {
+ if (!in_array($sDebugMode, array('visible', 'visible_adv', 'file', 'devnull', 'hidden'))) {
+ $sDebugMode = 'devnull';
+ }
+ try {
+ $this->sDbgMode = $sDebugMode;
+ $this->bDbg = true;
+ $this->oDbg = DebuggerFactory::getDebugger($sDebugMode);
+ } catch (InvalidArgumentException $e) {
+ throw $e;
+ }
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Contenido_Category/Contenido_Category_Articles.class.php b/conlite/classes/Contenido_Category/Contenido_Category_Articles.class.php
new file mode 100644
index 0000000..3c84f4a
--- /dev/null
+++ b/conlite/classes/Contenido_Category/Contenido_Category_Articles.class.php
@@ -0,0 +1,458 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release 4.8.9
+ *
+ * {@internal
+ * created 2008-08-21
+ * modified 2009-04-09: Timo Trautmann fixed inconsistence bug in getNonStartArticlesInCategory()
+ * modified 2010-10-28 Ortwin Pinke, changed behaviour for $sOrderBy in getNonStartArticlesInCategory()
+ *
+ *
+ * $Id: Contenido_Category_Articles.class.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class Contenido_Category_Articles extends Contenido_Category_Base {
+ /**#@+
+ * @var int
+ * @access protected
+ */
+ protected $iClient;
+ protected $iLang;
+ /**#@+
+ * @var obj
+ * @access protected
+ */
+ protected $oArticle;
+ protected $oArticleCollection;
+
+ /**
+ * Constructor
+ * @access public
+ * @param DB_ConLite $oDb
+ * @param array $aCfg
+ * @param int $iClient
+ * @param int $iLang
+ * @return void
+ */
+ public function __construct(DB_ConLite $oDb, array $aCfg, $iClient, $iLang) {
+ parent::__construct($oDb, $aCfg);
+ $this->setClient($iClient);
+ $this->setLang($iLang);
+ }
+
+ /**
+ * Return array with article-objects of a category.
+ * @access public
+ * @param int $iCategoryId
+ * @param string $sOrderBy
+ * @param string $sOrder
+ * @param boolean $bArticleIdAsKey
+ * @param int $iOnlineStatus 0-offline, 1-online, 2-both
+ * @return array An array with Article objects
+ * @throws Exception In case of a sql query that crashes
+ */
+ public function getArticlesInCategory($iCategoryId, $sOrderBy = "creationdate", $sOrder = "ASC", $bArticleIdAsKey = false, $iOnlineStatus = 2) {
+ $aReturn = array();
+ $sSql = $this->_buildQuery('idcat = '.Contenido_Security::toInteger($iCategoryId), $sOrderBy, $sOrder, $iOnlineStatus);
+ if ($this->bDbg === true) {
+ $this->oDbg->show($sSql, 'Contenido_Category_Articles::getArticlesInCategory() $sSql');
+ }
+
+ $this->oDb->query($sSql);
+
+ $bHasErrors = $this->oDb->Errno == 0 ? $bHasErrors = false : $bHasErrors = true;
+ if ($bHasErrors === false && $this->oDb->num_rows() > 0) {
+ while($this->oDb->next_record()) {
+ if ($bArticleIdAsKey === false) {
+ $aReturn[] = new Article($this->oDb->f('idart'), $this->getClient(), $this->getLang());
+ } else {
+ $aReturn[intval($this->oDb->f('idart'))] = new Article($this->oDb->f('idart'), $this->getClient(), $this->getLang());
+ }
+ }
+ }
+ if ($bHasErrors === true) {
+ throw new Exception('Error in SQL-Query! Errno: '.$this->oDb->Errno.', Error: '.$this->oDb->Error.', SQL: '.$sSql);
+ }
+ return $aReturn;
+ }
+
+ /**
+ * Return array with article-objects of a category that are online.
+ * @access public
+ * @param int $iCategoryId
+ * @param string $sOrderBy
+ * @param string $sOrder
+ * @param boolean $bArticleIdAsKey
+ * @param int $iOnlineStatus 0-offline, 1-online, 2-both
+ * @return array An array with Article objects
+ * @throws Exception In case of a sql query that crashes
+ */
+ public function getOnlineArticlesInCategory($iCategoryId, $sOrderBy = "creationdate", $sOrder = "ASC", $bArticleIdAsKey = false) {
+ try {
+ return $this->getArticlesInCategory($iCategoryId, $sOrderBy, $sOrder, $bArticleIdAsKey, 1);
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+
+ /**
+ * Return array with article-objects of a category that are offline.
+ * @access public
+ * @param int $iCategoryId
+ * @param string $sOrderBy
+ * @param string $sOrder
+ * @param boolean $bArticleIdAsKey
+ * @param int $iOnlineStatus 0-offline, 1-online, 2-both
+ * @return array An array with Article objects
+ * @throws Exception In case of a sql query that crashes
+ */
+ public function getOfflineArticlesInCategory($iCategoryId, $sOrderBy = "creationdate", $sOrder = "ASC", $bArticleIdAsKey = false) {
+ try {
+ return $this->getArticlesInCategory($iCategoryId, $sOrderBy, $sOrder, $bArticleIdAsKey, 0);
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+
+ /**
+ * Return array with article-objects of a category range.
+ * @access public
+ * @param array $aCategoryIds
+ * @param string $sOrderBy
+ * @param string $sOrder
+ * @param boolean $bArticleIdAsKey
+ * @param int $iOnlineStatus 0-offline, 1-online, 2-both
+ * @return array An array with Article objects
+ * @throws Exception In case of a sql query that crashes or wrong parameters
+ */
+ public function getArticlesInCategoryRange(array $aCategoryIds, $sOrderBy = "creationdate", $sOrder = "ASC", $bArticleIdAsKey = false, $iOnlineStatus = 2) {
+ $aReturn = array();
+ $aSqlIn = array();
+ if (sizeof($aCategoryIds) > 0) {
+ foreach ($aCategoryIds as $iId) {
+ $aSqlIn[] = Contenido_Security::toInteger($iId);
+ }
+ } else {
+ throw new Exception('$aCategoryIds must contain at least one item!');
+ }
+ $sSql = $this->_buildQuery('idcat IN('.implode(', ', $aSqlIn).')', $sOrderBy, $sOrder, $iOnlineStatus);
+ if ($this->bDbg === true) {
+ $this->oDbg->show($sSql, 'Contenido_Category_Articles::getArticlesInCategory() $sSql');
+ }
+ $this->oDb->query($sSql);
+ $bHasErrors = $this->oDb->Errno == 0 ? false : true;
+ if ($bHasErrors === false && $this->oDb->num_rows() > 0) {
+ while($this->oDb->next_record()) {
+ if ($bArticleIdAsKey === false) {
+ $aReturn[] = new Article($this->oDb->f('idart'), $this->getClient(), $this->getLang());
+ } else {
+ $aReturn[intval($this->oDb->f('idart'))] = new Article($this->oDb->f('idart'), $this->getClient(), $this->getLang());
+ }
+ }
+ }
+ if ($bHasErrors === true) {
+ throw new Exception('Error in SQL-Query! Errno: '.$this->oDb->Errno.', Error: '.$this->oDb->Error.', SQL: '.$sSql);
+ }
+ return $aReturn;
+ }
+
+ /**
+ * Return array with online article-objects of a category range.
+ * @access public
+ * @param array $aCategoryIds
+ * @param string $sOrderBy
+ * @param string $sOrder
+ * @param boolean $bArticleIdAsKey
+ * @param int $iOnlineStatus 0-offline, 1-online, 2-both
+ * @return array An array with Article objects
+ * @throws Exception In case of a sql query that crashes
+ */
+ public function getOnlineArticlesInCategoryRange(array $aCategoryIds, $sOrderBy = "creationdate", $sOrder = "ASC", $bArticleIdAsKey = false) {
+ try {
+ return $this->getArticlesInCategoryRange($aCategoryIds, $sOrderBy, $sOrder, $bArticleIdAsKey, 1);
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+
+ /**
+ * Return array with offline article-objects of a category range.
+ * @access public
+ * @param array $aCategoryIds
+ * @param string $sOrderBy
+ * @param string $sOrder
+ * @param boolean $bArticleIdAsKey
+ * @param int $iOnlineStatus 0-offline, 1-online, 2-both
+ * @return array An array with Article objects
+ * @throws Exception In case of a sql query that crashes
+ */
+ public function getOfflineArticlesInCategoryRange(array $aCategoryIds, $sOrderBy = "creationdate", $sOrder = "ASC", $bArticleIdAsKey = false) {
+ try {
+ return $this->getArticlesInCategoryRange($aCategoryIds, $sOrderBy, $sOrder, $bArticleIdAsKey, 0);
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+
+ /**
+ * Return start article of a given category.
+ * Remember to check for idart: if intval(idart) == 0, given idcat has no start article!
+ * @access public
+ * @param int $iCategoryId
+ * @return obj Article
+ */
+ public function getStartArticleInCategory($iCategoryId) {
+ $aOptions = array(
+ 'idcat' => Contenido_Security::toInteger($iCategoryId),
+ 'lang' => $this->getLang(),
+ 'client' => $this->getClient(),
+ 'start' => true
+ );
+ $this->oArticleCollection = new ArticleCollection($aOptions);
+ return $this->oArticleCollection->startArticle();
+ }
+
+ /**
+ * Return non start articles of a given category.
+ * Remember to check for idart: if intval(idart) == 0, given idcat has no start article!
+ * @access public
+ * @param int $iCategoryId
+ * @param string $sOrderBy Valid are fields of tbl. con_art_lang
+ * @param string $sOrderDirection
+ * @param boolean $bArticleIdAsKey
+ * @return array An array with Article objects if any were found
+ */
+ public function getNonStartArticlesInCategory($iCategoryId, $sOrderBy = 'created', $sOrderDirection = 'DESC', $bArticleIdAsKey = false) {
+ if (!in_array(strtolower($sOrderDirection), array('asc', 'desc'))) {
+ $sOrderDirection = 'DESC';
+ }
+
+ if($sOrderBy != 'created') {
+
+ switch ($sOrderBy) {
+ case 'sortsequence':
+ $sOrderBy = 'artsort';
+ break;
+ case 'modificationdate':
+ $sOrderBy = 'lastmodified';
+ break;
+ case 'creationdate':
+ $sOrderBy = 'created';
+ break;
+ case 'publisheddate':
+ $sOrderBy = 'published';
+ break;
+
+ default:
+ $sOrderBy = 'created';
+ }
+ }
+
+ $aReturn = array();
+ $aOptions = array(
+ 'idcat' => Contenido_Security::toInteger($iCategoryId),
+ 'lang' => $this->getLang(),
+ 'client' => $this->getClient(),
+ 'start' => false,
+ 'order' => Contenido_Security::escapeDB($sOrderBy, $this->oDb),
+ 'direction' => $sOrderDirection
+ );
+
+ $this->oArticleCollection = new ArticleCollection($aOptions);
+ while ($oArticle = $this->oArticleCollection->nextArticle()) {
+ if ($bArticleIdAsKey === false) {
+ $aReturn[] = $oArticle;
+ } else {
+ $aReturn[$oArticle->values['idart']] = $oArticle;
+ }
+ }
+ return $aReturn;
+ }
+
+ /**
+ * Return start articles of a given category range.
+ * Remember to check for idart: if intval(idart) == 0, given idcat has no start article!
+ * @access public
+ * @param array $aCategoryIds
+ * @param boolean $bArticleIdAsKey
+ * @return array An array with Article objects if any were found
+ */
+ public function getStartArticlesInCategoryRange(array $aCategoryIds, $bArticleIdAsKey = false) {
+ $aReturn = array();
+ if (sizeof($aCategoryIds) > 0) {
+ foreach ($aCategoryIds as $iIdcat) {
+ $aOptions = array(
+ 'idcat' => Contenido_Security::toInteger($iIdcat),
+ 'lang' => $this->getLang(),
+ 'client' => $this->getClient(),
+ 'start' => true
+ );
+ $this->oArticleCollection = new ArticleCollection($aOptions);
+ if ($bArticleIdAsKey === false) {
+ $aReturn[] = $this->oArticleCollection->startArticle();
+ } else {
+ $oStartArticle = $this->oArticleCollection->startArticle();
+ $aReturn[$oStartArticle->values['idart']] = $oStartArticle;
+ }
+ }
+ }
+ return $aReturn;
+ }
+
+ /**
+ * Return non start articles of a given category range.
+ * Remember to check for idart: if intval(idart) == 0, given idcat has no start article!
+ * Sortorder is applied to each category and not overall!
+ * @access public
+ * @param array $aCategoryIds
+ * @param string $sOrderBy Valid are fields of tbl. con_art_lang
+ * @param string $sOrderDirection
+ * @param boolean $bArticleIdAsKey
+ * @return array An array with Article objects if any were found
+ * TODO: must be fixed so order by condition is working correctly (works now just by category, not overall)
+ */
+ public function getNonStartArticlesInCategoryRange(array $aCategoryIds, $sOrderBy = 'created', $sOrderDirection = 'DESC', $bArticleIdAsKey = false) {
+ throw new Exception('Method not implemented yet!');
+ if (!in_array(strtolower($sOrderDirection), array('asc', 'desc'))) {
+ $sOrderDirection = 'DESC';
+ }
+ $aReturn = array();
+ if (sizeof($aCategoryIds) > 0) {
+ foreach ($aCategoryIds as $iIdcat) {
+ $aOptions = array(
+ 'idcat' => Contenido_Security::toInteger($iIdcat),
+ 'lang' => $this->getLang(),
+ 'client' => $this->getClient(),
+ 'start' => false,
+ 'order' => Contenido_Security::escapeDB($sOrderBy, $this->oDb),
+ 'direction' => $sOrderDirection
+ );
+ $this->oArticleCollection = new ArticleCollection($aOptions);
+ if ($bArticleIdAsKey === false) {
+ $aReturn[] = $this->oArticleCollection->startArticle();
+ } else {
+ $oStartArticle = $this->oArticleCollection->startArticle();
+ $aReturn[$oStartArticle->values['idart']] = $oStartArticle;
+ }
+ }
+ }
+ return $aReturn;
+ }
+
+ public function getCategoryByArticleId($iArticleId) {
+ throw new Exception('Method not implemented yet!');
+ }
+
+ // Getter/Setter
+
+ public function setLang($iLang) {
+ $this->iLang = (int) $iLang;
+ }
+
+ public function setClient($iClient) {
+ $this->iClient = (int) $iClient;
+ }
+
+
+ public function getLang() {
+ return (int) $this->iLang;
+ }
+
+ public function getClient() {
+ return (int) $this->iClient;
+ }
+
+ /**
+ * Builds SQL query to be used to fetch articles of one/more category/categories
+ *
+ * @param string $sCategorySelect Must bei either "idcat = 1" or "idcat IN(1,2,3)". Not very beautiful...
+ * @param string $sOrderBy
+ * @param string $sOrder
+ * @param int $iOnlineStatus
+ * @return unknown
+ */
+ private function _buildQuery($sCategorySelect, $sOrderBy = "creationdate", $sOrder = "ASC", $iOnlineStatus = 2) {
+ $sReturn = '';
+ $sCategorySelect = str_replace(';', '', $sCategorySelect);
+ // determine online state
+ switch ($iOnlineStatus) {
+ case 0:
+ $sOnline = 'artlang.online = 0';
+ break;
+ case 1:
+ $sOnline = 'artlang.online = 1';
+ break;
+ case 2:
+ default:
+ $sOnline = ' (artlang.online = 1 OR artlang.online = 0) ';
+ break;
+ }
+ // determine order condition
+ if (!in_array(strtolower($sOrder), array('asc', 'desc'))) {
+ $sOrder = 'ASC';
+ }
+ switch ($sOrderBy) { // TODO: extend to more valid items
+ case "sortsequence":
+ $sOrderCondition = 'ORDER BY artlang.artsort '.$sOrder;
+ break;
+ case "creationdate":
+ $sOrderCondition = 'ORDER BY artlang.created '.$sOrder;
+ break;
+ case "modificationdate":
+ $sOrderCondition = 'ORDER BY artlang.lastmodified '.$sOrder;
+ break;
+ case "publisheddate":
+ $sOrderCondition = 'ORDER BY artlang.published '.$sOrder;
+ break;
+ default:
+ $sOrderCondition = 'ORDER BY artlang.artsort '.$sOrder;
+ break;
+ }
+ $sSql = 'SELECT
+ artlang.idart, artlang.online
+ FROM
+ '.$this->aCfg['tab']['art_lang'].' AS artlang,
+ '.$this->aCfg['tab']['art'].' AS art,
+ '.$this->aCfg['tab']['cat_art'].' AS catart
+ WHERE
+ catart.'.$sCategorySelect.' AND
+ art.idclient = '.$this->getClient().' AND
+ artlang.idlang = '.$this->getLang().' AND
+ '.$sOnline.' AND
+ art.idart = catart.idart AND
+ artlang.idart = art.idart
+ '.$sOrderCondition.' ';
+
+ return $sSql;
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Contenido_Category/Sample.php b/conlite/classes/Contenido_Category/Sample.php
new file mode 100644
index 0000000..957513b
--- /dev/null
+++ b/conlite/classes/Contenido_Category/Sample.php
@@ -0,0 +1,120 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-19
+ * modified 2008-08-25 Added samples for Contenido_CategoryArticle
+ * $Id: Sample.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+// SAMPLE Contenido_Category ###
+
+try {
+ // load a single category
+ $oConCat = new Contenido_Category($db, $cfg);
+ //$oConCat->setloadSubCategories(true, 2); // will load subcategories of this idcat until given level
+ $oConCat->load(1, true, $lang); // also load lang
+ echo $oConCat->getIdCat().' :'.$oConCat->getCategoryLanguage()->getName().' ';
+
+ // load several categories
+ $oConCats = new Contenido_Categories($db, $cfg);
+ $oConCats->load(array(1,2,5,10), true, $lang);
+ // add a category
+ $oConCats->add($oConCat);
+ // see how many we've got
+ $iNumCats = $oConCats->count();
+ // sort cats in reverse order
+ $oConCats->reverse();
+
+ foreach ($oConCats as $oConCat) {
+ echo $oConCat->getIdCat().' :'.$oConCat->getCategoryLanguage()->getName().' ';
+ }
+} catch (InvalidArgumentException $eI) {
+ echo 'Some error occured: ' . $eI->getMessage() . ': ' . $eI->getFile() . ' at line '.$eI->getLine() . ' ('.$eI->getTraceAsString().')';
+} catch (Exception $e) {
+ echo 'Some error occured: ' . $e->getMessage() . ': ' . $e->getFile() . ' at line '.$e->getLine() . ' ('.$e->getTraceAsString().')';
+}
+
+// SAMPLE Contenido_CategoryArticle ###
+
+try {
+ $oConCatArt = new Contenido_Category_Articles($db, $cfg, $client, $lang);
+ // ###
+ // get start article of 1 given category
+ // ###
+ $oStartArticle = $oConCatArt->getStartArticleInCategory(3);
+ echo 'Article object of start article: ';
+ $iStartArticle = $oConCatArt->getStartArticleInCategory(3)->getField('idart');
+ echo '
idart of start article: '.intval($iStartArticle).'
';
+ // ###
+ // get start articles of several given categories
+ // ###
+ $aStartArticles = $oConCatArt->getStartArticlesInCategoryRange(array(3,4,5,6,7,8));
+ foreach ($aStartArticles as $oArticle) {
+ $iStartArticle = $oArticle->getField('idart');
+ $sStartTitle = $oArticle->getField('title');
+ echo 'Start article idart of idcat range: '.strval($iStartArticle).' / '.print_r(array(3,4,5,6,7,8), true).'
';
+ }
+ // ###
+ // get non start article of 1 given category
+ // ###
+ $aNonStartArticles = $oConCatArt->getNonStartArticlesInCategory(3, 'created', 'asc');
+ foreach ($aNonStartArticles as $oArticle) {
+ $iNonStartArticle = $oArticle->getField('idart');
+ $sNonStartTitle = $oArticle->getField('title');
+ echo 'Non start article idart of idcat: '.strval($iNonStartArticle).' / 3
';
+ }
+ // ###
+ // get articles of 1 given category, online and offline
+ // ###
+ $aArticlesOfCategory = $oConCatArt->getArticlesInCategory(3, 'sortorder', 'DESC', true);
+ foreach ($aArticlesOfCategory as $oArticle) {
+ $iArticle = $oArticle->getField('idart');
+ $sTitle = $oArticle->getField('title');
+ echo 'article idart of current article: '.strval($iArticle).' / '.$sTitle.'
';
+ }
+ // ###
+ // get articles of several given categories, online and offline
+ // ###
+ $aArticlesOfCategory = $oConCatArt->getArticlesInCategoryRange(array(3,4,5,6,7), 'sortorder', 'DESC', true);
+ foreach ($aArticlesOfCategory as $oArticle) {
+ $iArticle = $oArticle->getField('idart');
+ $sTitle = $oArticle->getField('title');
+ echo 'article idart of current article: '.strval($iArticle).' / '.$sTitle.'
';
+ }
+} catch (Exception $e) {
+ echo 'Some error occured: ' . $e->getMessage() . ': ' . $e->getFile() . ' at line '.$e->getLine() . ' ('.$e->getTraceAsString().')';
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Contenido_FrontendNavigation/Contenido_FrontendNavigation.class.php b/conlite/classes/Contenido_FrontendNavigation/Contenido_FrontendNavigation.class.php
new file mode 100644
index 0000000..099f2ef
--- /dev/null
+++ b/conlite/classes/Contenido_FrontendNavigation/Contenido_FrontendNavigation.class.php
@@ -0,0 +1,284 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-15
+ * modified 2008-04-25 added method getLevel() and property aLevel, modified loadSubCategories() accordingly
+ * modified 2008-09-22 Bugfix in loading protected subcategories when logged in as backenduser
+ * modified 2009-01-05 Timo Trautmann L:138 commented out not neccessary condidion which makes categories visible which shouldn't be displayed
+ * modified 2009-01-05 Rudi Bieller Fixed bug in permission check at strpos() call line 138ff
+ * modified 2009-01-13 Rudi Bieller Added methods isActiveChild() and isActiveParent()
+ * modified 2009-01-14 Rudi Bieller Changed contenido_security escaping to intval
+ * Added method isActiveChildOfRootOfCategory()
+ * modified 2009-04-29 Rudi Bieller Bugfix in isActiveChild()
+ *
+ * $Id: Contenido_FrontendNavigation.class.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class Contenido_FrontendNavigation extends Contenido_FrontendNavigation_Base {
+ /**
+ * @var obj
+ * @access protected
+ */
+ protected $oAuth; // for validating against fe-authentication
+
+ /**
+ * @var array
+ * @access protected
+ */
+ protected $aLevel;
+
+ /**
+ * @var int
+ * @access protected
+ */
+ protected $iRootCat;
+
+ /**
+ * Constructor.
+ * @access public
+ * @param DB_ConLite $oDb
+ * @param array $aCfg
+ * @param int $iClient
+ * @param int $iLang
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function __construct(DB_ConLite $oDb, array $aCfg, $iClient, $iLang, array $aCfgClient) {
+ parent::__construct($oDb, $aCfg, $iClient, $iLang, $aCfgClient);
+ $this->iRootCat = -1;
+ }
+
+ /**
+ * Load Subcategories of a given Category-ID.
+ * If you need Categories by FrontendPermission, you need to call method setAuth() before (!) calling loadSubCategories().
+ * loadSubCategories() then automatically checks against FrontendPermission.
+ * @access protected
+ * @param int $iIdcat
+ * @param boolean $bAsObjects If set to true, will load Subcategories as objects, otherwise as Array.
+ * @param boolean $bWithSubCategories Set to true to also load subcategories of loaded SubCategories
+ * @param int $iSubCategoriesLoadDepth Up to shich level should SubCategories be loaded. Defaults to 3 for a 3-level Navigation.
+ * @return boolean
+ * @author Rudi Bieller
+ */
+ protected function loadSubCategories($iIdcat, $bAsObjects = true, $bWithSubCategories = false, $iSubCategoriesLoadDepth = 3) {
+ $iIdcat = (int) $iIdcat;
+ $bUseAuth = (is_null($this->oAuth)
+ || (get_class($this->oAuth) != 'Auth'
+ && get_class($this->oAuth) != 'Contenido_Frontend_Challenge_Crypt_Auth')
+ && get_class($this->oAuth) != 'Contenido_Challenge_Crypt_Auth')
+ ? false
+ : true;
+ $sFieldsToSelect = 'cattree.idcat, cattree.level';
+ if ($bUseAuth === true) {
+ $sFieldsToSelect = 'cattree.idcat, cattree.level, catlang.public, catlang.idcatlang';
+ if((strlen($this->oAuth->auth['uid']) > 0) && ($this->oAuth->auth['uid'] != 'nobody')) {
+ $oFrontendGroupMemberCollection = new FrontendGroupMemberCollection();
+ $oFrontendGroupMemberCollection->setWhere('idfrontenduser', $this->oAuth->auth['uid']);
+ $oFrontendGroupMemberCollection->addResultField('idfrontendgroup');
+ $oFrontendGroupMemberCollection->query();
+ $aFeGroups = array();
+
+ while($oFEGroup = $oFrontendGroupMemberCollection->next()) {
+ $aFeGroups[] = $oFEGroup->get("idfrontendgroup");
+ }
+ $iNumFeGroups = count($aFeGroups);
+ }
+ // initialize fe-permission object
+ $oFrontendPermissionCollection = new FrontendPermissionCollection();
+ }
+ $sSqlPublic = $bUseAuth === true ? '' : 'catlang.public = 1 AND ';
+ $sSql = 'SELECT '.$sFieldsToSelect.' FROM '
+ .$this->aCfg["tab"]["cat_tree"].' AS cattree, '
+ .$this->aCfg["tab"]["cat"].' AS cat, '
+ .$this->aCfg["tab"]["cat_lang"].' AS catlang
+ WHERE
+ cattree.idcat = cat.idcat AND
+ cat.idcat = catlang.idcat AND
+ cat.idclient = '.intval($this->iClient).' AND
+ catlang.idlang = '.intval($this->iLang).' AND
+ catlang.visible = 1 AND '
+ .$sSqlPublic
+ .'cat.parentid = '.intval($iIdcat)
+ .' ORDER BY cattree.idtree';
+ if ($this->bDbg === true) {
+ $this->oDbg->show($sSql, 'Contenido_FrontendNavigation::loadSubCategories($iIdcat, $bAsObjects = true): $sSql');
+ }
+ $this->oDb->query($sSql);
+ if ($this->oDb->Errno != 0) {
+ return false;
+ }
+ $this->aCategories = array();
+ while ($this->oDb->next_record()) {
+ // check against fe-auth and against be-access
+ if ($bUseAuth === true && intval($this->oDb->f('public')) == 0) {
+ $sPerms = strval($this->oAuth->auth['perm']);
+ if (strpos($sPerms, 'sysadmin') !== false || strpos($sPerms, 'admin' !== false)
+ || (strpos($sPerms, 'client['.strval($this->iClient).']') !== false && strpos($sPerms, 'lang['.strval($this->iLang).']') !== false)) {
+ $this->aCategories[] = (int) $this->oDb->f('idcat');
+ $this->aLevel[(int) $this->oDb->f('idcat')] = (int) $this->oDb->f('level');
+ } else {
+ if ($iNumFeGroups > 0) {
+ for ($i = 0; $i < $iNumFeGroups; $i++) {
+ if($oFrontendPermissionCollection->checkPerm($aFeGroups[$i], 'category', 'access', $this->oDb->f('idcatlang'), true)) {
+ $this->aCategories[] = (int) $this->oDb->f('idcat');
+ $this->aLevel[(int) $this->oDb->f('idcat')] = (int) $this->oDb->f('level');
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ $this->aCategories[] = (int) $this->oDb->f('idcat');
+ $this->aLevel[(int) $this->oDb->f('idcat')] = (int) $this->oDb->f('level');
+ }
+ }
+ if($bAsObjects === true) {
+ $oCategories = new Contenido_Categories(new DB_ConLite(), $this->aCfg);
+ $oCategories->setDebug($this->bDbg, $this->sDbgMode);
+ $oCategories->setIdLang($this->iLang);
+ $oCategories->setloadSubCategories($bWithSubCategories, $iSubCategoriesLoadDepth);
+ $oCategories->load($this->aCategories, true, $this->iLang);
+ $this->oCategories = $oCategories;
+ }
+ }
+
+ /**
+ * Load and return Subcategories of a given Category.
+ * If you need Categories by FrontendPermission, you need to call method setAuth() before (!) calling loadSubCategories().
+ * loadSubCategories() then automatically checks against FrontendPermission.
+ * @access public
+ * @param int $iIdcat
+ * @param boolean $bAsObjects If set to true, will load Subcategories as objects, otherwise as Array.
+ * @param boolean $bWithSubCategories Set to true to also load subcategories of loaded SubCategories
+ * @param int $iSubCategoriesLoadDepth Up to shich level should SubCategories be loaded. Defaults to 3 for a 3-level Navigation.
+ * @return mixed Contenido_Categories or Array, depending on value for $bAsObjects
+ * @author Rudi Bieller
+ */
+ public function getSubCategories($iIdcat, $bAsObjects = true, $bWithSubCategories = false, $iSubCategoriesLoadDepth = 3) {
+ $this->loadSubCategories($iIdcat, $bAsObjects, $bWithSubCategories, $iSubCategoriesLoadDepth);
+ return $bAsObjects === true ? $this->oCategories : $this->aCategories;
+ }
+
+ /**
+ * Get Level of a given idcat. If idcat wasn't loaded yet, level will be queried.
+ * @access public
+ * @param int $iIdcat
+ * @return int Level of requested idcat. In case of an error, -1 is returned.
+ */
+ public function getLevel($iIdcat) {
+ if (isset($this->aLevel[intval($iIdcat)])) {
+ return $this->aLevel[intval($iIdcat)];
+ }
+ $sSql = 'SELECT level FROM ' . $this->aCfg["tab"]["cat_tree"] . ' WHERE idcat = ' . Contenido_Security::escapeDB(intval($iIdcat), $this->oDb);
+ $this->oDb->query($sSql);
+ if ($this->oDb->Errno != 0) {
+ return -1;
+ }
+ if ($this->oDb->num_rows() > 0) {
+ $this->oDb->next_record();
+ return intval($this->oDb->f('level'));
+ }
+ return -1;
+ }
+
+ /**
+ * Check if current idcat is an active parent category of a given Contenido_Category
+ * @access public
+ * @param Contenido_Category $oCategory
+ * @param int $iCurrentIdcat
+ * @return boolean
+ * @author Rudi Bieller
+ */
+ public function isActiveParent(Contenido_Category $oCategory, $iCurrentIdcat) {
+ if ($oCategory->getIdParent() > 0) {
+ $iCurrentIdcat = (int) $iCurrentIdcat;
+ if ($oCategory->getIdParent() == $iCurrentIdcat) {
+ return true;
+ }
+ $oBreadcrumb = new Contenido_FrontendNavigation_Breadcrumb($this->oDb, $this->aCfg, $this->iClient, $this->iLang, $this->aCfgClient);
+ $aBreadcrumb = $oBreadcrumb->getAsArray($oCategory->getIdParent());
+ return in_array($iCurrentIdcat, $aBreadcrumb);
+ }
+ return false;
+ }
+ /**
+ * Check if current idcat is an active child category of a given Contenido_Category
+ * @access public
+ * @param Contenido_Category $oCategory
+ * @param int $iCurrentIdcat
+ * @return boolean
+ * @author Rudi Bieller
+ */
+ public function isActiveChild(Contenido_Category $oCategory, $iCurrentIdcat) {
+ if ($oCategory->getSubCategories()->count() > 0) {
+ $iCurrentIdcat = (int) $iCurrentIdcat;
+ $oChildCategories = $oCategory->getSubCategories();
+ foreach ($oChildCategories as $oChildCat) {
+ if ($oChildCat->getIdCat() == $iCurrentIdcat || $this->isActiveChild($oChildCat, $iCurrentIdcat) === true) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Checks if needle cat is in breadcrumb of haystack up to top level.
+ * @access public
+ * @param int $iNeedleCat
+ * @param int $iTreeHaystackCat
+ * @return boolean
+ */
+ public function isInPathToRoot($iNeedleCat, $iTreeHaystackCat) {
+ $oBreadcrumb = new Contenido_FrontendNavigation_Breadcrumb($this->oDb, $this->aCfg, $this->iClient, $this->iLang, $this->aCfgClient);
+ $aBreadCats = $oBreadcrumb->getAsArray($iTreeHaystackCat, ($this->getLevel($this->getRootCat())+1));
+ return in_array($iNeedleCat, $aBreadCats);
+ }
+
+ /**
+ * Set internal property for Auth object to load only those categories the FE-User has right to see.
+ * Use this method if you have protected Categories and need to check agains FrontendUser Rights.
+ * @access public
+ * @param Auth $oAuth
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function setAuth(Auth $oAuth) {
+ $this->oAuth = $oAuth;
+ }
+
+ public function setRootCat($iIdcat) {
+ $this->iRootCat = (int) $iIdcat;
+ }
+
+ public function getRootCat() {
+ return (int) $this->iRootCat;
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Contenido_FrontendNavigation/Contenido_FrontendNavigation_Base.class.php b/conlite/classes/Contenido_FrontendNavigation/Contenido_FrontendNavigation_Base.class.php
new file mode 100644
index 0000000..9f4f3fe
--- /dev/null
+++ b/conlite/classes/Contenido_FrontendNavigation/Contenido_FrontendNavigation_Base.class.php
@@ -0,0 +1,157 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-15
+ *
+ * $Id: Contenido_FrontendNavigation_Base.class.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class Contenido_FrontendNavigation_Base {
+ /**#@+
+ * @var int
+ * @access protected
+ */
+ protected $iLang;
+ protected $iClient;
+ /**#@-*/
+
+ /**
+ * @var array
+ * @access protected
+ */
+ protected $aCategories;
+
+ /**
+ * @var obj
+ * @access protected
+ */
+ protected $oCategories;
+
+ // needed properties for db queries
+ /**
+ * @var obj
+ * @access protected
+ */
+ protected $oDb;
+ /**
+ * @var array
+ * @access protected
+ */
+ protected $aCfg;
+ /**
+ * @var array
+ * @access protected
+ */
+ protected $aCfgClient;
+ /**
+ * @var boolean
+ * @access protected
+ */
+ protected $bDbg;
+ /**
+ * @var string
+ * @access protected
+ */
+ protected $sDbgMode;
+ /**
+ * @var obj
+ * @access protected
+ */
+ protected $oDbg;
+
+ /**
+ * Constructor.
+ * @access public
+ * @param DB_ConLite $oDb
+ * @param array $aCfg
+ * @param int $iClient
+ * @param int $iLang
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function __construct(DB_ConLite $oDb, array $aCfg, $iClient, $iLang, array $aCfgClient) {
+ $this->oDb = $oDb;
+ $this->aCfg = $aCfg;
+ $this->iClient = (int) $iClient;
+ $this->iLang = (int) $iLang;
+ $this->aCfgClient = $aCfgClient;
+ $this->_iCurrentLoadDepth = 1;
+ $this->_aSubCategories = array();
+ $this->bDbg = false;
+ $this->oDbg = null;
+ }
+
+ /**
+ * Get a URL to a Navigation point.
+ * Depending on style of URL needed, values of $aParams differ.
+ * @access public
+ * @param array $aParams Parameters needed to build the URL
+ * @param string $sStyle Available styles are: front_content, custom, custom_path
+ * @param array $aConfig As default this is Contenido_UrlBuilderConfig::getConfig(), can be overridden by setting this value
+ * @param boolean $bUseAbsolutePath If true, will use absolute http://www.xy.com/ as "prefix"
+ * @return void
+ * @throws InvalidArgumentException
+ * @see appropriate Contenido_UrlBuilder for details on needed params
+ * @todo Apply other styles as soon as they are available
+ */
+ public function getUrl(array $aParams, $sStyle = 'custom_path', array $aConfig = array(), $bUseAbsolutePath = false) {
+ try {
+ $oUrlBuilder = Contenido_UrlBuilderFactory::getUrlBuilder($sStyle);
+ if ($bUseAbsolutePath === true) {
+ $oUrlBuilder->setHttpBasePath($this->aCfgClient[$this->iClient]['path']['htmlpath']);
+ }
+ $oUrlBuilder->buildUrl($aParams, $bUseAbsolutePath, $aConfig);
+ return $oUrlBuilder->getUrl();
+ } catch (InvalidArgumentException $e) {
+ throw $e;
+ }
+ }
+
+ /**
+ * Set internal property for debugging on/off and choose appropriate debug object
+ * @access public
+ * @param boolean $bDebug
+ * @param string $sDebugMode
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function setDebug($bDebug = true, $sDebugMode = 'visible') {
+ if (!in_array($sDebugMode, array('visible', 'hidden'))) {
+ $sDebugMode = 'hidden';
+ }
+ $this->sDbgMode = $sDebugMode;
+ if ($bDebug === true) {
+ $this->bDbg = true;
+ $this->oDbg = DebuggerFactory::getDebugger($sDebugMode);
+ } else {
+ $this->bDbg = false;
+ $this->oDbg = null;
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Contenido_FrontendNavigation/Contenido_FrontendNavigation_Breadcrumb.class.php b/conlite/classes/Contenido_FrontendNavigation/Contenido_FrontendNavigation_Breadcrumb.class.php
new file mode 100644
index 0000000..4b7676e
--- /dev/null
+++ b/conlite/classes/Contenido_FrontendNavigation/Contenido_FrontendNavigation_Breadcrumb.class.php
@@ -0,0 +1,166 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-15
+ * @todo Add possibility to load subcategories
+ *
+ * $Id: Contenido_FrontendNavigation_Breadcrumb.class.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class Contenido_FrontendNavigation_Breadcrumb extends Contenido_FrontendNavigation_Base {
+ /**
+ * @var int
+ * @access private
+ * @desc Used for breadcrumb loop over tree
+ */
+ private $_iCurrentLevel;
+
+ /**
+ * @var boolean
+ * @access private
+ */
+ private $_bAsArray;
+
+ /**
+ * @var array
+ * @access private
+ */
+ private $_aCategories;
+
+ /**
+ * Constructor.
+ * @access public
+ * @param DB_ConLite $oDb
+ * @param array $aCfg
+ * @param int $iClient
+ * @param int $iLang
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function __construct(DB_ConLite $oDb, array $aCfg, $iClient, $iLang, array $aCfgClient) {
+ parent::__construct($oDb, $aCfg, $iClient, $iLang, $aCfgClient);
+ $this->oCategories = null;
+ $this->_bAsArray = false;
+ }
+
+ /**
+ * Assuming we are in a Sub-Category and need to get the path to it starting at its root.
+ * Here, the path starts at root node.
+ * @access public
+ * @param int $iBaseCategoryId idcat of Sub-Category
+ * @param int $iRootLevel Level until which the path should be created
+ * @param boolean $bReset If true, will reset internal property $this->oCategories to an empty object
+ * @return array
+ * @author Rudi Bieller
+ * @todo Add possibility to return an array
+ */
+ public function get($iBaseCategoryId, $iRootLevel = 0, $bReset = false) {
+ $this->getBreadcrumb($iBaseCategoryId, $iRootLevel, $bReset);
+ $this->oCategories->reverse(); // For a breadcrumb, we start at the main category, not the current one.
+ return $this->oCategories;
+ }
+
+ /**
+ * Assuming we are in a Sub-Category and need to get the path to it starting at its root.
+ * Here, the path starts at root node.
+ * @access public
+ * @param int $iBaseCategoryId idcat of Sub-Category
+ * @param int $iRootLevel Level until which the path should be created
+ * @param boolean $bReset If true, will reset internal property $this->oCategories to an empty object
+ * @return array
+ * @author Rudi Bieller
+ * @todo Add possibility to return an array
+ */
+ public function getAsArray($iBaseCategoryId, $iRootLevel = 0, $bReset = false) {
+ $this->_bAsArray = true;
+ $this->getBreadcrumb($iBaseCategoryId, $iRootLevel, $bReset);
+ $this->_aCategories = array_reverse($this->_aCategories); // For a breadcrumb, we start at the main category, not the current one.
+ return $this->_aCategories;
+ }
+
+ /**
+ * Assuming we are in a Sub-Category and need to get the path to it starting at its root.
+ * This method goes recursively until the desired top level is reached and adds a Contenido_Category with each loop.
+ * @access protected
+ * @param int $iBaseCategoryId idcat of Sub-Category
+ * @param int $iRootLevel Level until which the path should be created
+ * @param boolean $bReset If true, will reset internal property $this->oCategories to an empty object
+ * @return array
+ * @author Rudi Bieller
+ */
+ protected function getBreadcrumb($iBaseCategoryId, $iRootLevel = 0, $bReset = false) {
+ // this method calls itself, so check if this happened already
+ if ($bReset === true || is_null($this->oCategories) || $this->oCategories->count() == 0) {
+ $this->oCategories = new Contenido_Categories($this->oDb, $this->aCfg);
+ }
+ $iRootLevel = (int) $iRootLevel;
+ $iBaseCategoryId = (int) $iBaseCategoryId;
+ $sSql = 'SELECT
+ catlang.idcat AS idcat,
+ cat.parentid AS parentid,
+ cattree.level as level
+ FROM
+ '.$this->aCfg["tab"]["cat_lang"].' AS catlang,
+ '.$this->aCfg["tab"]["cat"].' AS cat,
+ '.$this->aCfg["tab"]["cat_tree"].' AS cattree
+ WHERE
+ catlang.idlang = ' . Contenido_Security::escapeDB($this->iLang, $this->oDb) . ' AND
+ cat.idclient = ' . Contenido_Security::escapeDB($this->iClient, $this->oDb) . ' AND
+ cat.idcat = ' . Contenido_Security::escapeDB($iBaseCategoryId, $this->oDb) . ' AND
+ catlang.idcat = cat.idcat AND
+ cattree.idcat = cat.idcat';
+ if ($this->bDbg === true) {
+ $this->oDbg->show($sSql, 'Contenido_FrontendNavigation_Breadcrumb::getBreadcrumb($iBaseCategoryId, $iRootLevel = 0, $bReset = false): $sSql');
+ }
+ $this->oDb->query($sSql);
+ if ($this->oDb->Errno != 0) {
+ return false;
+ }
+ $this->oDb->next_record();
+ if ($this->_bAsArray === false) {
+ $oContenidoCategory = new Contenido_Category(new DB_ConLite(), $this->aCfg);
+ $oContenidoCategory->load(intval($this->oDb->f('idcat')), true, $this->iLang);
+ $this->oCategories->add($oContenidoCategory, $oContenidoCategory->getIdCat());
+ } else {
+ $this->_aCategories[] = intval($this->oDb->f('idcat'));
+ }
+ $this->_iCurrentLevel = (int) $this->oDb->f('level');
+ // if we are not at level 0, loop until we are
+ if ($this->_iCurrentLevel > $iRootLevel) {
+ while ($this->_iCurrentLevel > $iRootLevel) {
+ $this->getBreadcrumb($this->oDb->f('parentid'), $iRootLevel);
+ }
+ }
+ if ($this->_bAsArray === false) {
+ return $this->oCategories;
+ } else {
+ return $this->_aCategories;
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Contenido_FrontendNavigation/Sample.php b/conlite/classes/Contenido_FrontendNavigation/Sample.php
new file mode 100644
index 0000000..c4c2558
--- /dev/null
+++ b/conlite/classes/Contenido_FrontendNavigation/Sample.php
@@ -0,0 +1,126 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-19
+ *
+ * $Id: Sample.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+// #####################################################################################################################
+// ########### standard navigation
+// ########### retrieve subcategories of a given category and output them with idcat and name
+// #####################################################################################################################
+
+try {
+ $oFeNav = new Contenido_FrontendNavigation($db, $cfg, $client, $lang, $cfgClient);
+ $oContenidoCategories = $oFeNav->getSubCategories($idcat, true); // use some valid idcat of "home" or whatever
+ //$oContenidoCategories = $oFeNav->getSubCategories($idcat, true, true, 2); // for loading subcategories up to level 2
+ if ($oContenidoCategories->count() > 0) {
+ foreach ($oContenidoCategories as $oContenidoCategory) {
+ // output idcat and name of cat
+ echo ''.$oContenidoCategory->getIdCat().' | '.$oContenidoCategory->getCategoryLanguage()->getName().'
';
+ }
+ }
+} catch (InvalidArgumentException $eI) {
+ echo 'Some error occured: ' . $eI->getMessage() . ': ' . $eI->getFile() . ' at line '.$eI->getLine() . ' ('.$eI->getTraceAsString().')';
+} catch (Exception $e) {
+ echo 'Some error occured: ' . $e->getMessage() . ': ' . $e->getFile() . ' at line '.$e->getLine() . ' ('.$e->getTraceAsString().')';
+}
+
+
+// #####################################################################################################################
+// ########### breadcrumb navigation
+// ########### retrieve breadcrumb from a given category up to a given level and output the categories with idcat and name
+// #####################################################################################################################
+
+try {
+ $oBreadcrumb = new Contenido_FrontendNavigation_Breadcrumb($db, $cfg, $client, $lang, $cfgClient);
+ $oBreadCategories = $oBreadcrumb->get($idcat);
+ foreach ($oBreadCategories as $oBreadCategory) {
+ echo 'Bread '.$oBreadCategory->getIdCat().', '.$oBreadCategory->getCategoryLanguage()->getName().'
';
+ }
+} catch (InvalidArgumentException $eI) {
+ echo 'Some error occured: ' . $eI->getMessage() . ': ' . $eI->getFile() . ' at line '.$eI->getLine() . ' ('.$eI->getTraceAsString().')';
+} catch (Exception $e) {
+ echo 'Some error occured: ' . $e->getMessage() . ': ' . $e->getFile() . ' at line '.$e->getLine() . ' ('.$e->getTraceAsString().')';
+}
+
+
+// #####################################################################################################################
+// ########### standard navigation with some funky URLs
+// ########### retrieve subcategories of a given category and output them linked with different styles:
+// ########### front_content.php?idcat=1
+// ########### index-a-1.html
+// ########### cat1/cat2/index-a-1.html
+// ########### http://www.someurl.com/index-b-13-91.html
+// ########### /path/path/path/rocknroll,goodies,1,2,3.4fb
+// #####################################################################################################################
+
+// build Navigation with different types of URL style
+$aUrlStyleFunky = array('prefix' => 'rocknroll', 'suffix' => '.4fb', 'separator' => ','); // to create some other style of url
+try {
+ $oFeNav = new Contenido_FrontendNavigation($db, $cfg, $client, $lang, $cfgClient);
+ $oContenidoCategories = $oFeNav->getSubCategories(12, true); // use some valid idcat of "home" or whatever
+ if ($oContenidoCategories->count() > 0) {
+ foreach ($oContenidoCategories as $oContenidoCategory) {
+ // get needed data
+ $iIdcat = $oContenidoCategory->getIdCat();
+ $iParentIdcat = $oContenidoCategory->getIdParent();
+ $sCatName = $oContenidoCategory->getCategoryLanguage()->getName();
+
+ // -> front_content.php?idcat=1
+ $sUrl1 = 'click1 ';
+ // -> index-a-1.html
+ $sUrl2 = 'click2 ';
+ // -> cat1/cat2/index-a-1.html
+ $sUrl3 = 'click3 ';
+ // -> http://someurl.com/path0/path1/index-b-13-91.html
+ $sUrl4 = 'click4 ';
+ // -> /cat0/cat1/cat1/rocknroll,members,1,2,3.4fb (where "cat" being languagedependent)
+ $sUrl5 = 'click5 ';
+ echo 'idcat: '.$iIdcat.' | '.
+ 'parent idcat: ' . $iParentIdcat.' | '.
+ 'category name: ' . $sCatName.' | '.
+ 'URL: '.$sUrl1.' - '.$sUrl2.' - '.$sUrl3.' - '.$sUrl4.' - '.$sUrl5.'
';
+ }
+ }
+} catch (InvalidArgumentException $eI) {
+ echo 'Some error occured: ' . $eI->getMessage() . ': ' . $eI->getFile() . ' at line '.$eI->getLine() . ' ('.$eI->getTraceAsString().')';
+} catch (Exception $e) {
+ echo 'Some error occured: ' . $e->getMessage() . ': ' . $e->getFile() . ' at line '.$e->getLine() . ' ('.$e->getTraceAsString().')';
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Debug/Debug_DevNull.class.php b/conlite/classes/Debug/Debug_DevNull.class.php
new file mode 100644
index 0000000..fba2387
--- /dev/null
+++ b/conlite/classes/Debug/Debug_DevNull.class.php
@@ -0,0 +1,93 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-05-07
+ * modified 2008-05-21 Added methods add(), reset(), showAll()
+ * modified 2008-06-25 Removed die() from show() method
+ *
+ * $Id: Debug_DevNull.class.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+include_once('IDebug.php');
+
+class Debug_DevNull implements IDebug {
+
+ static private $_instance;
+
+ /**
+ * Constructor
+ * @access private
+ */
+ private function __construct() {
+
+ }
+
+ /**
+ * static
+ * @access public
+ */
+ static public function getInstance() {
+ if (self::$_instance == null) {
+ self::$_instance = new Debug_DevNull();
+ }
+ return self::$_instance;
+ }
+
+ /**
+ * Outputs contents of passed variable to /dev/null
+ *
+ * @access public
+ * @param mixed $mVariable The variable to be displayed
+ * @param string $sVariableDescription The variable's name or description
+ * @param boolean $bExit If set to true, your app will NOT die() after output of current var
+ * @return void
+ */
+ public function show($mVariable, $sVariableDescription='', $bExit = false) {}
+
+ /**
+ * Interface implementation
+ * @access public
+ * @param mixed $mVariable
+ * @param string $sVariableDescription
+ * @return void
+ */
+ public function add($mVariable, $sVariableDescription = '') {}
+ /**
+ * Interface implementation
+ * @access public
+ * @return void
+ */
+ public function reset() {}
+ /**
+ * Interface implementation
+ * @access public
+ * @return string Here an empty string
+ */
+ public function showAll() {}
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Debug/Debug_File.class.php b/conlite/classes/Debug/Debug_File.class.php
new file mode 100644
index 0000000..4c0ca9e
--- /dev/null
+++ b/conlite/classes/Debug/Debug_File.class.php
@@ -0,0 +1,128 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2007-01-01
+ * modified 2008-05-21 Added methods add(), reset(), showAll()
+ * modified 2010-05-20 Murat Purc, Hey, last change was nearly 2 years ago ;-)... Fixed generated warnings, see [#CON-309]
+ *
+ * $Id: Debug_File.class.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+include_once('IDebug.php');
+
+class Debug_File implements IDebug {
+
+ static private $_instance;
+ static private $_hFileHandle;
+ private $_sPathToLogs;
+ private $_sFileName;
+ private $_sPathToFile;
+
+ /**
+ * Constructor
+ * Opens filehandle for debug-logfile
+ * @access private
+ * @return void
+ */
+ private function __construct() {
+ global $cfg; // omfg, I know... TODO
+ $this->_sPathToLogs = $cfg['path']['contenido'].'logs'.DIRECTORY_SEPARATOR;
+ $this->_sFileName = 'debug.log';
+ $this->_sPathToFile = $this->_sPathToLogs.$this->_sFileName;
+ if (file_exists($this->_sPathToLogs) && is_writeable($this->_sPathToLogs)) {
+ self::$_hFileHandle = @fopen($this->_sPathToFile, 'a+'); // keep it quiet, might be used in production systems
+ }
+ }
+
+ /**
+ * Closes file handle upon destruction of object
+ * @access public
+ * @return void
+ */
+ public function __destruct() {
+ if (is_resource(self::$_hFileHandle)) {
+ fclose(self::$_hFileHandle);
+ }
+ }
+
+ /**
+ * static
+ * @access public
+ * @return void
+ */
+ static public function getInstance() {
+ if (self::$_instance == null) {
+ self::$_instance = new Debug_File();
+ }
+ return self::$_instance;
+ }
+
+ /**
+ * Outputs contents of passed variable in a preformatted, readable way
+ *
+ * @access public
+ * @param mixed $mVariable The variable to be displayed
+ * @param string $sVariableDescription The variable's name or description
+ * @param boolean $bExit If set to true, your app will die() after output of current var
+ * @return void
+ */
+ public function show($mVariable, $sVariableDescription='', $bExit = false)
+ {
+ if (is_resource(self::$_hFileHandle) && is_writeable($this->_sPathToFile)) {
+ $sDate = date('Y-m-d H:i:s');
+ fwrite(self::$_hFileHandle, '#################### '.$sDate.' ####################'."\n");
+ fwrite(self::$_hFileHandle, $sVariableDescription."\n");
+ fwrite(self::$_hFileHandle, print_r($mVariable, true)."\n");
+ fwrite(self::$_hFileHandle, '#################### /'.$sDate.' ###################'."\n\n");
+ }
+ }
+
+ /**
+ * Interface implementation
+ * @access public
+ * @param mixed $mVariable
+ * @param string $sVariableDescription
+ * @return void
+ */
+ public function add($mVariable, $sVariableDescription = '') {}
+ /**
+ * Interface implementation
+ * @access public
+ * @return void
+ */
+ public function reset() {}
+ /**
+ * Interface implementation
+ * @access public
+ * @return string Here an empty string
+ */
+ public function showAll() {}
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Debug/Debug_Hidden.class.php b/conlite/classes/Debug/Debug_Hidden.class.php
new file mode 100644
index 0000000..2fcd6c6
--- /dev/null
+++ b/conlite/classes/Debug/Debug_Hidden.class.php
@@ -0,0 +1,110 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2007-01-01
+ * modified 2008-05-21 Added methods add(), reset(), showAll()
+ *
+ * $Id: Debug_Hidden.class.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+include_once('IDebug.php');
+
+class Debug_Hidden implements IDebug {
+
+ static private $_instance;
+
+ /**
+ * Constructor
+ * @access private
+ */
+ private function __construct() {
+
+ }
+
+ /**
+ * static
+ * @access public
+ */
+ static public function getInstance() {
+ if (self::$_instance == null) {
+ self::$_instance = new Debug_Hidden();
+ }
+ return self::$_instance;
+ }
+
+ /**
+ * Outputs contents of passed variable in a preformatted, readable way
+ *
+ * @access public
+ * @param mixed $mVariable The variable to be displayed
+ * @param string $sVariableDescription The variable's name or description
+ * @param boolean $bExit If set to true, your app will die() after output of current var
+ * @return void
+ */
+ public function show($mVariable, $sVariableDescription='', $bExit = false)
+ {
+ echo "\n \n";
+ echo '' . "\n";
+ echo "\n \n";
+
+ if ($bExit === true) {
+ die();
+ }
+ }
+
+ /**
+ * Interface implementation
+ * @access public
+ * @param mixed $mVariable
+ * @param string $sVariableDescription
+ * @return void
+ */
+ public function add($mVariable, $sVariableDescription = '') {}
+ /**
+ * Interface implementation
+ * @access public
+ * @return void
+ */
+ public function reset() {}
+ /**
+ * Interface implementation
+ * @access public
+ * @return string Here an empty string
+ */
+ public function showAll() {}
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Debug/Debug_Visible.class.php b/conlite/classes/Debug/Debug_Visible.class.php
new file mode 100644
index 0000000..58072e3
--- /dev/null
+++ b/conlite/classes/Debug/Debug_Visible.class.php
@@ -0,0 +1,146 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2007-01-01
+ * modified 2008-05-21 Added methods add(), reset(), showAll()
+ *
+ * $Id: Debug_Visible.class.php 312 2014-06-18 11:01:08Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+include_once('IDebug.php');
+
+class Debug_Visible implements IDebug {
+
+ static private $_instance;
+
+ /**
+ * Constructor
+ * @access private
+ */
+ private function __construct() {
+
+ }
+
+ /**
+ * static
+ * @access public
+ */
+ static public function getInstance() {
+ if (self::$_instance == null) {
+ self::$_instance = new Debug_Visible();
+ }
+ return self::$_instance;
+ }
+
+ /**
+ * Outputs contents of passed variable in a preformatted, readable way
+ *
+ * @access public
+ * @param mixed $mVariable The variable to be displayed
+ * @param string $sVariableDescription The variable's name or description
+ * @param boolean $bExit If set to true, your app will die() after output of current var
+ * @return void
+ */
+ public function show($mVariable, $sVariableDescription='', $bExit = false)
+ {
+ $bTextarea = false;
+ $bPlainText = false;
+ if (is_array($mVariable)) {
+ if (sizeof($mVariable) > 10) {
+ $bTextarea = true;
+ } else {
+ $bPlainText = true;
+ }
+ }
+ if (is_object($mVariable)) {
+ $bTextarea = true;
+ }
+ if (is_string($mVariable)) {
+ if (preg_match('/<(.*)>/', $mVariable)) {
+ if (strlen($mVariable) > 40) {
+ $bTextarea = true;
+ } else {
+ $bPlainText = true;
+ $mVariable = clHtmlSpecialChars($mVariable);
+ }
+ } else {
+ $bPlainText = true;
+ }
+ }
+ echo ''."\n";
+ echo '
DEBUG '.$sVariableDescription.'
'."\n";
+ if ($bTextarea === true) {
+ echo '
';
+ } elseif ($bPlainText === true) {
+ echo '';
+ } else {
+ echo '';
+ }
+ echo '
';
+ if ($bExit === true) {
+ die('debugg\'ed
'."\n");
+ }
+ }
+
+ /**
+ * Interface implementation
+ * @access public
+ * @param mixed $mVariable
+ * @param string $sVariableDescription
+ * @return void
+ */
+ public function add($mVariable, $sVariableDescription = '') {}
+ /**
+ * Interface implementation
+ * @access public
+ * @return void
+ */
+ public function reset() {}
+ /**
+ * Interface implementation
+ * @access public
+ * @return string Here an empty string
+ */
+ public function showAll() {}
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Debug/Debug_VisibleAdv.class.php b/conlite/classes/Debug/Debug_VisibleAdv.class.php
new file mode 100644
index 0000000..afec7a7
--- /dev/null
+++ b/conlite/classes/Debug/Debug_VisibleAdv.class.php
@@ -0,0 +1,291 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-05-20
+ *
+ * $Id: Debug_VisibleAdv.class.php 312 2014-06-18 11:01:08Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+include_once('IDebug.php');
+
+class Debug_VisibleAdv implements IDebug, Countable {
+
+ static private $_instance;
+ private $_aItems;
+ private $_bIsOffline = false;
+
+
+ /**
+ * Constructor
+ * @access private
+ */
+ private function __construct() {
+ $this->_aItems = array();
+ }
+
+ /**
+ * static
+ * @access public
+ */
+ static public function getInstance() {
+ if (self::$_instance == null) {
+ self::$_instance = new Debug_VisibleAdv();
+ }
+ return self::$_instance;
+ }
+
+ public function switchOffline($bOffline) {
+ if(is_bool($bOffline)) {
+ $this->_bIsOffline = $bOffline;
+ }
+ }
+
+
+ /**
+ * Add a Debug item to internal collection.
+ * @access public
+ * @param mixed $mVariable
+ * @param string $sVariableDescription
+ * @return void;
+ */
+ public function add($mVariable, $sVariableDescription = '') {
+ if($this->_bIsOffline) return;
+ $oItem = new Debug_VisibleAdv_Item();
+ $oItem->setValue($mVariable);
+ $oItem->setDescription($sVariableDescription);
+ $this->_aItems[] = $oItem;
+ }
+
+ /**
+ * Reset internal collection with Debug items.
+ * @access public
+ * @return void
+ */
+ public function reset() {
+ $this->_aItems = array();
+ }
+
+ /**
+ * Outputs all Debug items in collection to screen in a HTML Box at left top of page.
+ * @access public
+ * @return void
+ */
+ public function showAll() {
+ if($this->_bIsOffline) return;
+ if ($this->count() > 0) {
+ $sHtml = '
+
+ ';
+ $sHtml .= '
+
con dbg
+
(x)
+
';
+ $sBlocks = '';
+ $i = 1;
+ foreach ($this->_aItems as $oItem) {
+ $sItemName = strlen($oItem->getDescription()) > 0 ? $oItem->getDescription() : ('debug item #'.$i);
+ $sItemValue = $this->_prepareValue($oItem->getValue());
+ $sHtml .= "\n".'
'.$sItemName.'
+
'.$sItemValue.'
'."\n";
+ ++$i;
+ }
+ $sHtml .= '
+
';
+ echo $sHtml;
+ }
+ }
+
+ /**
+ * Prepares Debug item value for output as string representation.
+ * @access private
+ * @param mixed $mValue
+ * @return string
+ */
+ private function _prepareValue($mValue) {
+ $bTextarea = false;
+ $bPlainText = false;
+ $sReturn = '';
+ if (is_array($mValue)) {
+ if (sizeof($mValue) > 10) {
+ $bTextarea = true;
+ } else {
+ $bPlainText = true;
+ }
+ }
+ if (is_object($mValue)) {
+ $bTextarea = ($this->_useXDebug())?false:true;
+ }
+ if (is_string($mValue)) {
+ if (preg_match('/<(.*)>/', $mValue)) {
+ if (strlen($mValue) > 40) {
+ $bTextarea = true;
+ } else {
+ $bPlainText = true;
+ $mValue = clHtmlSpecialChars($mValue);
+ }
+ } else {
+ $bPlainText = true;
+ }
+ }
+
+ if ($bTextarea === true) {
+ $sReturn .= '';
+ } elseif ($bPlainText === true) {
+ $sReturn .= '';
+ } else {
+ $sReturn .= '';
+ }
+ return $sReturn;
+ }
+
+ /**
+ * Implemenation of Countable interface
+ * @access public
+ * @return int
+ */
+ public function count() {
+ return sizeof($this->_aItems);
+ }
+
+ /**
+ * Outputs contents of passed variable in a preformatted, readable way
+ *
+ * @access public
+ * @param mixed $mVariable The variable to be displayed
+ * @param string $sVariableDescription The variable's name or description
+ * @param boolean $bExit If set to true, your app will die() after output of current var
+ * @return void
+ */
+ public function show($mVariable, $sVariableDescription='', $bExit = false) {
+ if($this->_bIsOffline) return;
+ try {
+ $oDbgVisible = DebuggerFactory::getDebugger('visible');
+ } catch (Exception $e) {
+ //throw $e;
+ echo $e->getMessage();
+ }
+ $oDbgVisible->show($mVariable, $sVariableDescription, $bExit);
+ }
+
+ private function _useXDebug() {
+ if(function_exists("xdebug_is_enabled")) {
+ return (xdebug_is_enabled() === true)?true:false;
+ }
+ return false;
+ }
+}
+
+/**
+ * An object representing one Debug item of a Debug_VisibleBlock.
+ */
+class Debug_VisibleAdv_Item {
+ private $_mValue;
+ private $_sDescription;
+
+ /**
+ * Set value of item
+ * @access public
+ * @return void
+ */
+ public function setValue($mValue) {
+ $this->_mValue = $mValue;
+ }
+
+ /**
+ * Set name/description of item
+ * @access public
+ * @return void
+ */
+ public function setDescription($sDescription) {
+ $this->_sDescription = $sDescription;
+ }
+
+ /**
+ * Get value of item
+ * @access public
+ * @return mixed
+ */
+ public function getValue() {
+ return $this->_mValue;
+ }
+
+ /**
+ * Get name/description of item
+ * @access public
+ * @return string
+ */
+ public function getDescription() {
+ return $this->_sDescription;
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Debug/DebuggerFactory.class.php b/conlite/classes/Debug/DebuggerFactory.class.php
new file mode 100644
index 0000000..041647d
--- /dev/null
+++ b/conlite/classes/Debug/DebuggerFactory.class.php
@@ -0,0 +1,76 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2007-03-27
+ * modified 2008-05-07 Added Debug_DevNull, extended Exception message.
+ * modified 2008-05-21 Added Debug_VisibleAdv
+ *
+ * $Id: DebuggerFactory.class.php 9 2011-07-27 06:22:34Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ *
+ */
+class DebuggerFactory {
+
+ /**
+ *
+ * @param type $sType
+ * @return Debug_VisibleAdv
+ */
+ public static function getDebugger($sType) {
+ $oDebugger = null;
+ switch ($sType) {
+ case 'visible':
+ include_once('Debug_Visible.class.php');
+ $oDebugger = Debug_Visible::getInstance();
+ break;
+ case 'visible_adv':
+ include_once('Debug_VisibleAdv.class.php');
+ /** @var $oDebugger Debug_VisibleAdv */
+ $oDebugger = Debug_VisibleAdv::getInstance();
+ break;
+ case 'hidden':
+ include_once('Debug_Hidden.class.php');
+ $oDebugger = Debug_Hidden::getInstance();
+ break;
+ case 'file':
+ include_once('Debug_File.class.php');
+ $oDebugger = Debug_File::getInstance();
+ break;
+ case 'devnull':
+ include_once('Debug_DevNull.class.php');
+ $oDebugger = Debug_DevNull::getInstance();
+ break;
+ default:
+ throw new InvalidArgumentException('This type of debugger is unknown to DebuggerFactory: '.$sType);
+ break;
+ }
+ return $oDebugger;
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Debug/IDebug.php b/conlite/classes/Debug/IDebug.php
new file mode 100644
index 0000000..d04d006
--- /dev/null
+++ b/conlite/classes/Debug/IDebug.php
@@ -0,0 +1,42 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2007-01-01
+ * modified 2008-05-21 Added methods add(), reset(), showAll()
+ *
+ * $Id: IDebug.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+interface IDebug {
+ static public function getInstance();
+ public function show($mVariable, $sVariableDescription = '', $bExit = false);
+ public function add($mVariable, $sVariableDescription = '');
+ public function reset();
+ public function showAll();
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/Debug/Sample.php b/conlite/classes/Debug/Sample.php
new file mode 100644
index 0000000..10b6c61
--- /dev/null
+++ b/conlite/classes/Debug/Sample.php
@@ -0,0 +1,91 @@
+'.print_r($mMyVar, true).'';
+ * you can now write $oDbg->show($mMyVar);
+ * and get a formatted, readable representation of the passed variable.
+ *
+ * There are Objects to display the contents of a variable
+ * to screen, to html comments and to a file.
+ *
+ * When using Debug_File, there will be a debug.log created in /contenido/logs/
+ *
+ * Using the Factory you can simply change the type of debugger by passing the type to load.
+ * By using "devnull" you can keep your debug code while in production systems and turn it on again by changing to "file" or "hidden" if needed.
+ *
+ *
+ * Requirements:
+ * @con_php_req 5.0
+ *
+ *
+ * @package Contenido Backend classes
+ * @version 1.0.0
+ * @author Rudi Bieller
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-19
+ * modified 2008-05-23 Added Debug_DevNull and Debug_VisibleAdv
+ *
+ * $Id: Sample.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+$oMyObj = new stdClass();
+$oMyObj->sTest = 'some property value';
+$oMyObj->aTest = array('item1', 'item2');
+
+$aMyArray = array('somekey' => 'somevalue');
+
+$iMyInt = 5;
+
+$fMyFloat = 5.12;
+
+$sMyString = 'my string looks like this';
+
+// print debug info to screen
+$oDbgVisible = DebuggerFactory::getDebugger('visible');
+$oDbgVisible->show($oMyObj, 'some comments if needed');
+$oDbgVisible->show($aMyArray, 'some comments if needed');
+$oDbgVisible->show($fMyFloat, 'some comments if needed');
+
+// print debug info to screen inside a box that can be toggled and does not crash your layout
+$oDbgVisibleAdv = DebuggerFactory::getDebugger('visible_adv');
+$oDbgVisibleAdv->add($oMyObj, 'some comments if needed');
+$oDbgVisibleAdv->add($aMyArray, 'some comments if needed');
+$oDbgVisibleAdv->add($fMyFloat, 'some comments if needed');
+$oDbgVisibleAdv->showAll(); // prints out a small html box at left top of page
+$oDbgVisibleAdv->show($fMyFloat, 'some comments if needed'); // also possible here
+
+// print debug info to screen in html comments
+$oDbgHidden = DebuggerFactory::getDebugger('hidden');
+$oDbgHidden->show($oMyObj, 'some comments if needed');
+$oDbgHidden->show($aMyArray, 'some comments if needed');
+$oDbgHidden->show($fMyFloat, 'some comments if needed');
+
+// print debug info to a logfile
+$oDbgFile = DebuggerFactory::getDebugger('file');
+$oDbgFile->show($oMyObj, 'some comments if needed');
+$oDbgFile->show($aMyArray, 'some comments if needed');
+$oDbgFile->show($fMyFloat, 'some comments if needed');
+
+// send debug info to dev/null
+$oDbgDevnull = DebuggerFactory::getDebugger('devnull');
+$oDbgDevnull->show($oMyObj, 'some comments if needed');
+$oDbgDevnull->show($aMyArray, 'some comments if needed');
+$oDbgDevnull->show($fMyFloat, 'some comments if needed');
+?>
\ No newline at end of file
diff --git a/conlite/classes/Url/Contenido_Url.class.php b/conlite/classes/Url/Contenido_Url.class.php
new file mode 100644
index 0000000..bb0cfe5
--- /dev/null
+++ b/conlite/classes/Url/Contenido_Url.class.php
@@ -0,0 +1,294 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2009-09-29
+ * modified 2008-12-23, Murat Purc, added functions buildRedirect(), composeByComponents() and
+ * isExternalUrl() and exended flexibility of build()
+ * modified 2008-12-26, Murat Purc, added execution of chains 'Contenido.Frontend.PreprocessUrlBuilding'
+ * and 'Contenido.Frontend.PostprocessUrlBuilding' to build()
+ * modified 2009-01-13, Murat Purc, added new function isIdentifiableFrontContentUrl() for better
+ * identification of internal urls
+ * modified 2009-10-27, Murat Purc, fixed/modified CEC_Hook, see [#CON-256]
+ * modified 2011-05-20, Murat Purc, fixed wrong condition in function parse(), see [#CON-399]
+ *
+ * $Id: Contenido_Url.class.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+
+final class Contenido_Url {
+
+ /**
+ * Self instance.
+ *
+ * @var Contenido_Url
+ */
+ static private $_instance;
+
+ /**
+ * UrlBuilder instance.
+ *
+ * @var Contenido_UrlBuilder
+ */
+ private $_oUrlBuilder;
+
+ /**
+ * UrlBuilder name.
+ *
+ * @var string
+ */
+ private $_sUrlBuilderName;
+
+
+ /**
+ * Constructor of Contenido_Url. Is not callable from outside.
+ *
+ * Gets the UrlBuilder configuration and creates an UrlBuilder instance.
+ */
+ private function __construct() {
+ $this->_sUrlBuilderName = Contenido_UrlBuilderConfig::getUrlBuilderName();
+ $this->_oUrlBuilder = Contenido_UrlBuilderFactory::getUrlBuilder(
+ $this->_sUrlBuilderName
+ );
+ }
+
+
+ /**
+ * Returns self instance
+ *
+ * @return Contenido_Url
+ */
+ public static function getInstance() {
+ if (self::$_instance == null) {
+ self::$_instance = new Contenido_Url();
+ }
+ return self::$_instance;
+ }
+
+
+ /**
+ * Creates a URL to frontend page.
+ *
+ * @param mixed $param Either url or assoziative array containing parameter:
+ * - url: front_content.php?idcat=12&lang=1
+ * - params: array('idcat' => 12, 'lang' => 1)
+ * Required values depend on used UrlBuilder, but a must have is 'lang'.
+ * @param boolean $bUseAbsolutePath Flag to create absolute Urls
+ * @param array $aConfig If not set, UrlBuilderConfig::getConfig() will be used by the URLBuilder
+ * @return string The Url build by UrlBuilder
+ */
+ public function build($param, $bUseAbsolutePath=false, array $aConfig=array()) {
+
+ if (!is_array($param)) {
+ $arr = $this->parse($param);
+ $param = $arr['params'];
+ }
+
+ // fallback for urls to homepage (/ or front_content.php)
+ if (count($param) == 0 || (!isset($param['idart']) && !isset($param['idartlang']) &&
+ !isset($param['idcat']) && !isset($param['idcatlang']) && !isset($param['idcatart']))) {
+ $param['idcat'] = getEffectiveSetting('navigation', 'idcat-home', 1);
+ }
+
+ // execute preprocess hook
+ $aHookParams = array(
+ 'param' => $param, 'bUseAbsolutePath' => $bUseAbsolutePath, 'aConfig' => $aConfig
+ );
+ if ($aResult = CEC_Hook::executeAndReturn('Contenido.Frontend.PreprocessUrlBuilding', $aHookParams)) {
+ $param = (isset($aResult['param'])) ? $aResult['param'] : '';
+ if (isset($aResult['bUseAbsolutePath'])) {
+ $bUseAbsolutePath = (bool) $aResult['bUseAbsolutePath'];
+ }
+ if (isset($aResult['aConfig']) && is_array($aResult['aConfig'])) {
+ $aConfig = $aResult['aConfig'];
+ }
+ }
+
+ if ($this->_sUrlBuilderName == 'custom_path' && !isset($aParams['level'])) {
+ // downwards compatibility to Contenido_UrlBuilder_CustomPath
+ $aParams['level'] = '1';
+ }
+
+ if (!isset($param['lang'])) {
+ // another downwards compatibility to Contenido_UrlBuilder_CustomPath
+ throw new InvalidArgumentException('$param[lang] must be set!');
+ }
+
+ if ($this->_sUrlBuilderName == 'custom_path' && count($param) <= 3) {
+ // third downwards compatibility
+ $param['_c_p_'] = '1';
+ }
+
+ $this->_oUrlBuilder->buildUrl($param, $bUseAbsolutePath, $aConfig);
+
+ $url = $this->_oUrlBuilder->getUrl();
+
+ // execute postprocess hook
+ if ($result = CEC_Hook::executeAndReturn('Contenido.Frontend.PostprocessUrlBuilding', $url)) {
+ $url = (string) $result;
+ }
+
+ return $url;
+ }
+
+
+ /**
+ * Creates a URL used to redirect to frontend page.
+ *
+ * @param mixed $param Either url or assoziative array containing parameter:
+ * - url: front_content.php?idcat=12&lang=1
+ * - params: array('idcat' => 12, 'lang' => 1)
+ * Required values depend on used UrlBuilder, but a must have is 'lang'.
+ * @param array $aConfig If not set, UrlBuilderConfig::getConfig() will be used by the URLBuilder
+ * @return string The redirect Url build by UrlBuilder
+ */
+ public function buildRedirect($param, array $aConfig=array()) {
+ $url = $this->build($param, true, $aConfig);
+ return str_replace('&', '&', $url);
+ }
+
+
+ /**
+ * Splits passed url into its components
+ *
+ * @param string $sUrl The Url to strip down
+ * @return array Assoziative array created by using parse_url() having the key 'params' which
+ * includes the parameter value pairs.
+ */
+ public function parse($sUrl){
+ $aUrl = @parse_url($sUrl);
+ if (isset($aUrl['query'])) {
+ $aUrl['query'] = str_replace('&', '&', $aUrl['query']);
+ parse_str($aUrl['query'], $aUrl['params']);
+ }
+ if (!isset($aUrl['params']) || !is_array($aUrl['params'])) {
+ $aUrl['params'] = array();
+ }
+ return $aUrl;
+ }
+
+
+ /**
+ * Composes a url using passed components array
+ *
+ * @param array Assoziative array created by parse_url()
+ * @return string $sUrl The composed Url
+ */
+ public function composeByComponents(array $aComponents) {
+ $sUrl = (isset($aComponents['scheme']) ? $aComponents['scheme'] . '://' : '') .
+ (isset($aComponents['user']) ? $aComponents['user'] . ':' : '') .
+ (isset($aComponents['pass']) ? $aComponents['pass'] . '@' : '') .
+ (isset($aComponents['host']) ? $aComponents['host'] : '') .
+ (isset($aComponents['port']) ? ':' . $aComponents['port'] : '') .
+ (isset($aComponents['path']) ? $aComponents['path'] : '') .
+ (isset($aComponents['query']) ? '?' . $aComponents['query'] : '') .
+ (isset($aComponents['fragment']) ? '#' . $aComponents['fragment'] : '');
+ return $sUrl;
+ }
+
+
+ /**
+ * Checks, if passed url is an external url while performing hostname check
+ *
+ * @param string $sUrl Url to check
+ * @return bool True if url is a external url, otherwhise false
+ */
+ public function isExternalUrl($sUrl) {
+ $aComponents = $this->parse($sUrl);
+ if (!isset($aComponents['host'])) {
+ return false;
+ }
+ if (!$path = $this->_oUrlBuilder->getHttpBasePath()) {
+ return false;
+ }
+
+ $aComponents2 = $this->parse($path);
+ if (!isset($aComponents2['host'])) {
+ return false;
+ }
+
+ return (strtolower($aComponents['host']) !== strtolower($aComponents2['host']));
+ }
+
+
+ /**
+ * Checks, if passed url is an identifiable internal url.
+ *
+ * Following urls will be identified as a internal url:
+ * - "/", "/?idart=123", "/?idcat=123", ...
+ * - "front_content.php", "front_content.php?idart=123", "front_content.php?idcat=123", ...
+ * - The path component of an client HTML base path: e. g. "/cms/", "/cms/?idart=123", "/cms/?idcat=123"
+ * - Also possible: "/cms/front_content.php", "/cms/front_content.php?idart=123", "/cms/front_content.php?idcat=123"
+ * All of them prefixed with protocol and client host (e. g. http://host/) will also be identified
+ * as a internal Url.
+ *
+ * Other Urls, even internal Urls like /unknown/path/to/some/page.html will not be identified as
+ * internal url event if they are real working clean URLs.
+ *
+ * @param string $sUrl Url to check
+ * @return bool True if url is identifiable internal url, otherwhise false
+ */
+ public function isIdentifiableFrontContentUrl($sUrl){
+ if ($this->isExternalUrl($sUrl)) {
+ // detect a external url, return false
+ return false;
+ }
+
+ $aComponents = $this->parse($sUrl);
+ if (!isset($aComponents['path']) || $aComponents['path'] == '') {
+ return false;
+ }
+
+ $clientPath = '';
+ if ($httpBasePath = $this->_oUrlBuilder->getHttpBasePath()) {
+ $aComponents2 = $this->parse($httpBasePath);
+ if (isset($aComponents2['path'])) {
+ $clientPath = $aComponents2['path'];
+ }
+ }
+
+ $path = $aComponents['path'];
+ if ($path == '/' || strpos($path, 'front_content.php') === 0 ||
+ strpos($path, '/front_content.php') > 0 || ($clientPath !== '' && $clientPath == $path)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Returns UrlBuilder instance.
+ *
+ * @return Contenido_UrlBuilder
+ */
+ public function getUrlBuilder() {
+ return $this->_oUrlBuilder;
+ }
+
+}
+
diff --git a/conlite/classes/UrlBuilder/Contenido_UrlBuilder.class.php b/conlite/classes/UrlBuilder/Contenido_UrlBuilder.class.php
new file mode 100644
index 0000000..46e49e2
--- /dev/null
+++ b/conlite/classes/UrlBuilder/Contenido_UrlBuilder.class.php
@@ -0,0 +1,98 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-21
+ * modified 2008-09-29, Murat Purc, added getHttpBasePath() method
+ *
+ * $Id: Contenido_UrlBuilder.class.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+abstract class Contenido_UrlBuilder {
+ /**
+ * @var string
+ * @access protected
+ * @desc Holds final value of built URL
+ */
+ protected $sUrl; // needed in this context
+ /**
+ * @var string
+ * @access protected
+ * @desc Holds URL that is used as base for an absolute path, e.g. http://contenido.org/
+ */
+ protected $sHttpBasePath; // needed in this context
+
+ /**
+ * Implementation of Singleton. Get instance of concrete Contenido_UrlBuilder_XYZ
+ * @access public
+ * @return obj Contenido_UrlBuilder_Frontcontent
+ * @author Rudi Bieller
+ */
+ abstract public static function getInstance();
+
+ /**
+ * Set http base path, e.g. http://contenido.org/
+ * @access public
+ * @return void
+ * @author Rudi Bieller
+ */
+ public function setHttpBasePath($sBasePath) {
+ $this->sHttpBasePath = (string) $sBasePath;
+ }
+
+ /**
+ * Return http base path, e.g. http://contenido.org/
+ * @return string
+ */
+ public function getHttpBasePath() {
+ return $this->sHttpBasePath;
+ }
+
+ /**
+ * Builds a URL in index-a-1.html style.
+ * Index keys of $aParams will be used as "a", corresponding values as "1" in this sample.
+ *
+ * @param array $aParams
+ * @param boolean $bUseAbsolutePath
+ * @param string $sSeparator
+ * @return void
+ * @throws InvalidArgumentException
+ * @author Rudi Bieller
+ */
+ abstract public function buildUrl(array $aParams, $bUseAbsolutePath = false);
+
+ /**
+ * Return built URL
+ * @access public
+ * @return string
+ * @author Rudi Bieller
+ */
+ public function getUrl() {
+ return (string) $this->sUrl;
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/UrlBuilder/Contenido_UrlBuilderConfig.class.php b/conlite/classes/UrlBuilder/Contenido_UrlBuilderConfig.class.php
new file mode 100644
index 0000000..6ecf438
--- /dev/null
+++ b/conlite/classes/UrlBuilder/Contenido_UrlBuilderConfig.class.php
@@ -0,0 +1,122 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-28
+ * modified 2008-09-29, Murat Purc, added features to set and get configuration
+ * $Id: Contenido_UrlBuilderConfig.class.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+if (!class_exists('NotInitializedException')) {
+ class NotInitializedException extends Exception {}
+}
+
+
+/**
+ * Class to manage UrlBuilder configuration.
+ *
+ * The Contenido_UrlBuilderConfig::setConfig() must be called at least once to initialize the desired
+ * UrlBuilder.
+ *
+ * Usage:
+ * ------
+ *
+ * // Example for default front_content UrlBuilder
+ * $myCfg['name'] = 'front_content';
+ * $myCfg['config'] = array();
+ * Contenido_UrlBuilderConfig::setConfig($myCfg);
+ *
+ * // Example for CustomPath UrlBuilder
+ * $myCfg['name'] = 'custom_path';
+ * $myCfg['config'] = array('prefix' => 'rocknroll', 'suffix' => '.4fb', 'separator' => ',');
+ * Contenido_UrlBuilderConfig::setConfig($myCfg);
+ *
+ *
+ */
+class Contenido_UrlBuilderConfig {
+
+ /**
+ * UrlBuilder configuration array
+ * @var array
+ */
+ private static $_aUrlBuilderCfg = array(
+ 'config' => array('prefix' => 'index', 'suffix' => '.html', 'separator' => '-')
+ );
+
+
+ /**
+ * Set UlrBuilder configuration
+ *
+ * @param array $cfg Assoziative configuration array as follows:
+ * - $cfg['name'] = Name of UrlBuilder class to use
+ * - $cfg['config'] = UrlBuilder configuration
+ * @throws InvalidArgumentException If $cfg ist empty, $cfg['name'] is missing or $cfg['config']
+ * exists but is not a array
+ */
+ public static function setConfig(array $cfg) {
+ if (count($cfg) == 0) {
+ throw new InvalidArgumentException('Contenido_UrlBuilderConfig: Empty configuration');
+ } elseif (!isset($cfg['name']) || (string) $cfg['name'] === '') {
+ throw new InvalidArgumentException('Contenido_UrlBuilderConfig: Missing UrlBuilder name');
+ } elseif (isset($cfg['config']) && !is_array($cfg['config'])) {
+ throw new InvalidArgumentException('Contenido_UrlBuilderConfig: Invalid UrlBuilder configuration');
+ }
+
+ self::$_aUrlBuilderCfg = $cfg;
+ }
+
+
+ /**
+ * Returns UrlBuilder name
+ *
+ * @return string UrlBuilder name
+ * @throws NotInitializedException If UrlBuilder configuration wasn't initialized before
+ */
+ public static function getUrlBuilderName() {
+ if (!is_array(self::$_aUrlBuilderCfg) || !isset(self::$_aUrlBuilderCfg['name'])) {
+ throw new NotInitializedException('Contenido_UrlBuilderConfig: Configuration is not set');
+ }
+
+ return self::$_aUrlBuilderCfg['name'];
+ }
+
+
+ /**
+ * Returns UrlBuilder configuration
+ *
+ * @return array UrlBuilder configuration
+ * @throws NotInitializedException If UrlBuilder configuration wasn't initialized before
+ */
+ public static function getConfig() {
+ if (!is_array(self::$_aUrlBuilderCfg)) {
+ throw new NotInitializedException('Contenido_UrlBuilderConfig: Configuration is not set');
+ }
+
+ return self::$_aUrlBuilderCfg['config'];
+ }
+
+}
diff --git a/conlite/classes/UrlBuilder/Contenido_UrlBuilderFactory.class.php b/conlite/classes/UrlBuilder/Contenido_UrlBuilderFactory.class.php
new file mode 100644
index 0000000..596a40e
--- /dev/null
+++ b/conlite/classes/UrlBuilder/Contenido_UrlBuilderFactory.class.php
@@ -0,0 +1,80 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-18
+ * modified 2008-09-29, Murat Purc, add instantiation of userdefined UrlBuilder
+ * modified 2008-12-22, Murat Purc, fixed file exists check of userdefined UrlBuilder
+ * modified 2009-01-01, Murat Purc, changed call of call_user_func to support php previous to 5.2.3
+ *
+ * $Id: Contenido_UrlBuilderFactory.class.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class Contenido_UrlBuilderFactory {
+ /**
+ * Returns desired UrlBuilder object.
+ *
+ * @param string $sBuilder For now, those are valid: front_content, custom, custom_path or a
+ * Userdefined UrlBuilder name. The name must be a subpart of the
+ * UrlBuilder class, e. g. 'MyUrlBuilder' for Contenido_UrlBuilder_MyUrlBuilder.
+ * The classfile must be named like Contenido_UrlBuilder_MyUrlBuilder.class.php
+ * and it must be reside in /contenido/classes/UrlBuilder/ folder.
+ * @return Contenido_UrlBuilder
+ * @throws InvalidArgumentException In case unknown type of builder is requested you'll get an Exception
+ */
+ public static function getUrlBuilder($sBuilder) {
+ switch($sBuilder) {
+ case 'front_content':
+ return Contenido_UrlBuilder_Frontcontent::getInstance();
+ break;
+ case 'custom':
+ return Contenido_UrlBuilder_Custom::getInstance();
+ break;
+ case 'custom_path':
+ return Contenido_UrlBuilder_CustomPath::getInstance();
+ break;
+ default:
+ if ((string) $sBuilder !== '') {
+ $sClassName = 'Contenido_UrlBuilder_' . $sBuilder;
+ $sFileName = 'Contenido_UrlBuilder_' . $sBuilder . '.class.php';
+ $sPath = str_replace('\\', '/', dirname(__FILE__)) . '/';
+ if (!file_exists($sPath . $sFileName)) {
+ throw new InvalidArgumentException('The classfile of Contenido_UrlBuilder couldn\'t included by Contenido_UrlBuilderFactory: '.$sBuilder.'!');
+ }
+ cInclude('classes', 'UrlBuilder/' . $sFileName);
+ if (!class_exists($sClassName)) {
+ throw new InvalidArgumentException('The classfile of Contenido_UrlBuilder couldn\'t included by Contenido_UrlBuilderFactory: '.$sBuilder.'!');
+ }
+ return call_user_func(array($sClassName, 'getInstance'));
+ }
+
+ throw new InvalidArgumentException('Invalid/Empty Contenido_UrlBuilder passed to Contenido_UrlBuilderFactory: '.$sBuilder.'!');
+ break;
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/UrlBuilder/Contenido_UrlBuilder_Custom.class.php b/conlite/classes/UrlBuilder/Contenido_UrlBuilder_Custom.class.php
new file mode 100644
index 0000000..059fd17
--- /dev/null
+++ b/conlite/classes/UrlBuilder/Contenido_UrlBuilder_Custom.class.php
@@ -0,0 +1,98 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-20
+ * modified 2008-02-28 Changed to using Config for URL style
+ *
+ * $Id: Contenido_UrlBuilder_Custom.class.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+include_once('Contenido_UrlBuilder.class.php');
+
+class Contenido_UrlBuilder_Custom extends Contenido_UrlBuilder {
+ static private $_instance; // object instance
+ private $aConfig;
+
+ /**
+ * Constructor
+ * @access private
+ * @return void
+ * @author Rudi Bieller
+ */
+ private function __construct() {
+ $this->sHttpBasePath = '';
+ }
+
+ /**
+ * Get instance of Contenido_UrlBuilder_Frontcontent
+ * @access public
+ * @return obj Contenido_UrlBuilder_Frontcontent
+ * @author Rudi Bieller
+ */
+ public static function getInstance() {
+ if (self::$_instance == null) {
+ self::$_instance = new Contenido_UrlBuilder_Custom();
+ }
+ return self::$_instance;
+ }
+
+ /**
+ * Builds a URL in index-a-1.html style.
+ * Index keys of $aParams will be used as "a", corresponding values as "1" in this sample.
+ *
+ * @param array $aParams
+ * @param boolean $bUseAbsolutePath
+ * @param array $aConfig If not set, will use UrlBuilderConfig::getConfig()
+ * @return void
+ * @throws InvalidArgumentException
+ * @author Rudi Bieller
+ */
+ public function buildUrl(array $aParams, $bUseAbsolutePath = false, array $aConfig = array()) {
+ if (sizeof($aParams) == 0) {
+ throw new InvalidArgumentException('$aParams must have at least one entry!');
+ }
+ // if no config passed or not all parameters available, use default config
+ if (sizeof($aConfig) == 0 || !isset($aConfig['prefix']) || !isset($aConfig['suffix']) || !isset($aConfig['separator'])) {
+ include_once('Contenido_UrlBuilderConfig.class.php');
+ $aConfig = Contenido_UrlBuilderConfig::getConfig();
+ }
+ $this->aConfig = $aConfig;
+
+ $this->sUrl = $bUseAbsolutePath === true ? $this->sHttpBasePath : '';
+ $this->sUrl .= $this->aConfig['prefix'];
+ foreach ($aParams as $sKey => $mVal) {
+ $sVal = $mVal; // assuming mVal is a string and thus a single value
+ if (is_array($mVal)) { // mVal has more than one value, e.g. index-b-1-2.html
+ $sVal = implode($this->aConfig['separator'], $mVal);
+ }
+ $this->sUrl .= $this->aConfig['separator'] . strval($sKey) . $this->aConfig['separator'] . strval($sVal);
+ }
+ $this->sUrl .= $this->aConfig['suffix'];
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/UrlBuilder/Contenido_UrlBuilder_CustomPath.class.php b/conlite/classes/UrlBuilder/Contenido_UrlBuilder_CustomPath.class.php
new file mode 100644
index 0000000..81be1e7
--- /dev/null
+++ b/conlite/classes/UrlBuilder/Contenido_UrlBuilder_CustomPath.class.php
@@ -0,0 +1,131 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-19
+ * modified 2008-02-28 Changed to using Config for URL style
+ * @todo Somehow get around using prCreateURLNameLocationString()
+ *
+ * $Id: Contenido_UrlBuilder_CustomPath.class.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+include_once('Contenido_UrlBuilder.class.php');
+cInclude('includes', 'functions.pathresolver.php');
+
+class Contenido_UrlBuilder_CustomPath extends Contenido_UrlBuilder {
+ static private $_instance; // object instance
+ private $aConfig;
+
+ /**
+ * Constructor
+ * @access private
+ * @return void
+ * @author Rudi Bieller
+ */
+ private function __construct() {
+ $this->sHttpBasePath = '';
+ }
+
+ /**
+ * Get instance of Contenido_UrlBuilder_Frontcontent
+ * @access public
+ * @return obj Contenido_UrlBuilder_Frontcontent
+ * @author Rudi Bieller
+ */
+ public static function getInstance() {
+ if (self::$_instance == null) {
+ self::$_instance = new Contenido_UrlBuilder_CustomPath();
+ }
+ return self::$_instance;
+ }
+
+ /**
+ * Builds a URL in index-a-1.html style.
+ * Index keys of $aParams will be used as "a", corresponding values as "1" in this sample.
+ * For creating the location string $aParams needs to have keys idcat, level, lang and at least one custom key.
+ * If level is not set, level 0 will be used as default.
+ *
+ * @param array $aParams Required keys are: idcat, level, lang and at least one custom key.
+ * @param boolean $bUseAbsolutePath
+ * @param array $aConfig If not set, will use UrlBuilderConfig::getConfig()
+ * @return void
+ * @throws InvalidArgumentException
+ * @throws Exception
+ * @author Rudi Bieller
+ * @todo Somehow get around using prCreateURLNameLocationString()
+ */
+ public function buildUrl(array $aParams, $bUseAbsolutePath = false, array $aConfig = array()) {
+ if (!isset($aParams['idcat'])) {
+ throw new InvalidArgumentException('$aParams[idcat] must be set!');
+ }
+ if (!isset($aParams['level'])) {
+ //throw new InvalidArgumentException('$aParams[level] must be set! Setting it to 0 will create complete path.');
+ $aParams['level'] = '1';
+ }
+ if (!isset($aParams['lang'])) {
+ throw new InvalidArgumentException('$aParams[lang] must be set!');
+ }
+ if (sizeof($aParams) <= 3) {
+ throw new InvalidArgumentException('$aParams must have at least one custom entry!');
+ }
+ // if no config passed or not all parameters available, use default config
+ if (sizeof($aConfig) == 0 || !isset($aConfig['prefix']) || !isset($aConfig['suffix']) || !isset($aConfig['separator'])) {
+ include_once('Contenido_UrlBuilderConfig.class.php');
+ $aConfig = Contenido_UrlBuilderConfig::getConfig();
+ }
+ $this->aConfig = $aConfig;
+
+ $sCategoryString = '';
+ prCreateURLNameLocationString(intval($aParams['idcat']),
+ "/",
+ $sCategoryString,
+ false,
+ "",
+ $aParams['level'],
+ $aParams['lang'],
+ true,
+ false);
+ if (strlen($sCategoryString) > 0 && substr($sCategoryString, -1) != '/') {
+ $sCategoryString .= '/';
+ }
+ $this->sUrl = $bUseAbsolutePath === true ? $this->sHttpBasePath : '';
+ $this->sUrl .= $sCategoryString;
+ $this->sUrl .= $this->aConfig['prefix'];
+ foreach ($aParams as $sKey => $mVal) {
+ if ($sKey != 'idcat' && $sKey != 'lang' && $sKey != 'level') {
+ $sVal = $mVal; // assuming mVal is a string and thus a single value
+ if (is_array($mVal)) { // mVal has more than one value, e.g. index-b-1-2.html
+ $sVal = implode($this->aConfig['separator'], $mVal);
+ }
+ $this->sUrl .= $this->aConfig['separator'] . strval($sKey) . $this->aConfig['separator'] . strval($sVal);
+ }
+ }
+ $this->sUrl .= $this->aConfig['suffix'];
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/UrlBuilder/Contenido_UrlBuilder_Frontcontent.class.php b/conlite/classes/UrlBuilder/Contenido_UrlBuilder_Frontcontent.class.php
new file mode 100644
index 0000000..00fd724
--- /dev/null
+++ b/conlite/classes/UrlBuilder/Contenido_UrlBuilder_Frontcontent.class.php
@@ -0,0 +1,132 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-19
+ * modified 2008-09-09 Fix of parameter checking in method buildUrl()
+ * modified 2008-09-29, Murat Purc, fix parameter check and third argument for buildUrl()
+ * modified 2008-12-26, Murat Purc, added handling of additional parameter to buildUrl()
+ * modified 2009-01-19 Rudi Bieller Bugfix in buildUrl() for idart (had idcat as param name...)
+ * @todo: add switch for & vs. &
+ *
+ * $Id: Contenido_UrlBuilder_Frontcontent.class.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+include_once('Contenido_UrlBuilder.class.php');
+
+class Contenido_UrlBuilder_Frontcontent extends Contenido_UrlBuilder {
+
+ /**
+ * Self instance
+ * @var Contenido_UrlBuilder_Frontcontent
+ */
+ static private $_instance;
+
+ /**
+ * XHTML compliant parameter composition delemiter
+ * @var string
+ */
+ private $_sAmp = '&';
+
+ /**
+ * Constructor
+ * @access private
+ * @return void
+ * @author Rudi Bieller
+ */
+ private function __construct() {
+ $this->sHttpBasePath = '';
+ }
+
+ /**
+ * Get instance of Contenido_UrlBuilder_Frontcontent
+ * @access public
+ * @return obj Contenido_UrlBuilder_Frontcontent
+ * @author Rudi Bieller
+ */
+ public static function getInstance() {
+ if (self::$_instance == null) {
+ self::$_instance = new Contenido_UrlBuilder_Frontcontent();
+ }
+ return self::$_instance;
+ }
+
+ /**
+ * Builds a URL in front_content.php style.
+ * Depending on which array keys of $aParams are set, the URL is built differently.
+ * Valid array keys are: idcat, idart and idcatart.
+ * Additional array keys will also be added to the generated url.
+ * Internally, the method first tries to create URLs in this order:
+ * front_content.php?idcat=1&idart=1
+ * front_content.php?idcat=1
+ * front_content.php?idart=1
+ * front_content.php?idcatart=1
+ *
+ * @param array $aParams
+ * @param boolean $bUseAbsolutePath
+ * @param array $aConfig Is not used at the moment
+ * @return void
+ * @throws InvalidArgumentException
+ * @throws Exception
+ * @author Rudi Bieller
+ */
+ public function buildUrl(array $aParams, $bUseAbsolutePath = false, array $aConfig = array()) {
+ $bIdcatSet = isset($aParams['idcat']);
+ $bIdartSet = isset($aParams['idart']);
+ $bIdcatArtSet = isset($aParams['idcatart']);
+ if ($bIdcatSet === false && $bIdartSet === false && $bIdcatArtSet === false) {
+ throw new InvalidArgumentException('$aParams must have at least one of the following values set: $aParams[idcat], $aParams[idart] or $aParams[idcatart]!');
+ }
+ $sHttpBasePath = $bUseAbsolutePath === true ? $this->sHttpBasePath : '';
+ if ($bIdcatSet === true) {
+ if ($bIdartSet === true) {
+ $this->sUrl = $sHttpBasePath . 'front_content.php?idcat='.strval($aParams['idcat']).$this->_sAmp.'idart='.strval($aParams['idart']);
+ } else {
+ $this->sUrl = $sHttpBasePath . 'front_content.php?idcat='.strval($aParams['idcat']);
+ }
+ } else {
+ if ($bIdartSet === true) {
+ $this->sUrl = $sHttpBasePath . 'front_content.php?idart='.strval($aParams['idart']);
+ } else {
+ if ($bIdcatArtSet === true) {
+ $this->sUrl = $sHttpBasePath . 'front_content.php?idcatart='.strval($aParams['idcatart']);
+ } else {
+ throw new Exception('Cannot build URL because of missing parameters!');
+ }
+ }
+ }
+
+ // now add additional params
+ foreach ($aParams as $param => $value) {
+ if ($param == 'idcat' || $param == 'idart' || $param == 'idcatart') {
+ continue;
+ }
+ $this->sUrl .= $this->_sAmp . $param .'=' . urlencode(urldecode((string) $value));
+ }
+
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/UrlBuilder/Contenido_UrlBuilder_MR.class.php b/conlite/classes/UrlBuilder/Contenido_UrlBuilder_MR.class.php
new file mode 100644
index 0000000..549d1c7
--- /dev/null
+++ b/conlite/classes/UrlBuilder/Contenido_UrlBuilder_MR.class.php
@@ -0,0 +1,401 @@
+
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since Contenido release 4.8.15
+ *
+ * {@internal
+ * created 2008-05-xx
+ *
+ * $Id: Contenido_UrlBuilder_MR.class.php 217 2013-02-04 14:53:11Z Mansveld $:
+ * }}
+ *
+ */
+
+
+defined('CON_FRAMEWORK') or die('Illegal call');
+
+
+cInclude('classes', 'UrlBuilder/Contenido_UrlBuilder.class.php');
+cInclude('classes', 'UrlBuilder/Contenido_UrlBuilderFactory.class.php');
+
+
+/**
+ * Class to build frontend urls for advandced mod rewrite plugin.
+ * Extends abstract Contenido_UrlBuilder class and implements singleton pattern.
+ *
+ * Usage:
+ *
+ * cInclude('classes', 'UrlBuilder/Contenido_UrlBuilder_MR.class.php');
+ * $url = 'front_content.php?idart=123';
+ * $mrUrlBuilder = Contenido_UrlBuilder_MR::getInstance();
+ * $mrUrlBuilder->buildUrl(array($url));
+ * $newUrl = $mrUrlBuilder->getUrl();
+ *
+ *
+ * @todo Add handling of absolute paths, standardize handling of fragments
+ *
+ *
+ * @author Murat Purc
+ * @package Contenido Backend plugins
+ * @subpackage ModRewrite
+ */
+class Contenido_UrlBuilder_MR extends Contenido_UrlBuilder
+{
+
+ /**
+ * Self instance
+ *
+ * @var Contenido_UrlBuilder_MR
+ */
+ static private $_instance;
+
+ /**
+ * Ampersant used for composing several parameter value pairs
+ *
+ * @var string
+ */
+ private $_sAmp = '&';
+
+ /**
+ * Is XHTML output?
+ *
+ * @var bool
+ */
+ private $_bIsXHTML = false;
+
+ /**
+ * Is HTML5 output?
+ *
+ * @var bool
+ */
+ private $_bIsHTML5 = false;
+
+ /**
+ * Is mod rewrite enabled?
+ *
+ * @var bool
+ */
+ private $_bMREnabled = false;
+
+ /**
+ * Mod Rewrite configuration
+ *
+ * @var array
+ */
+ private $_aMrCfg = null;
+
+
+ /**
+ * Constructor, tries to set some member variables.
+ */
+ private function __construct()
+ {
+ $this->sHttpBasePath = '';
+ if (ModRewrite::isEnabled()) {
+ $this->_aMrCfg = ModRewrite::getConfig();
+ $this->_bMREnabled = true;
+ $this->_bIsXHTML = ((getEffectiveSetting('generator', 'xhtml', 'false') == 'false') ? false : true);
+ $this->_bIsHTML5 = ((getEffectiveSetting('generator', 'html5', 'false') == 'false') ? false : true);
+ $this->_sAmp = ((($this->_bIsXHTML) || ($this->_bIsHTML5)) ? '&' : '&');
+ }
+ }
+
+
+ /**
+ * Returns a instance of Contenido_UrlBuilder_MR
+ *
+ * @return Contenido_UrlBuilder_MR
+ */
+ public static function getInstance()
+ {
+ if (self::$_instance == null) {
+ self::$_instance = new self();
+ }
+ return self::$_instance;
+ }
+
+
+ /**
+ * Builds a URL based on defined mod rewrite settings.
+ *
+ * @param array $params Parameter array, provides only following parameters:
+ *
+ * $params[0] = 'front_content.php?idart=123...'
+ *
+ * @param boolean $bUseAbsolutePath Flag to use absolute path (not used at the moment)
+ * @return string New build url
+ */
+ public function buildUrl(array $params, $bUseAbsolutePath = false)
+ {
+ global $cfgClient, $client;
+
+ ModRewriteDebugger::add($params, 'Contenido_UrlBuilder_MR::buildUrl() $params');
+ $urlDebug['in'] = $params;
+
+ $url = self::_buildUrl($params);
+
+ $urlPrefix = '';
+ if ($bUseAbsolutePath) {
+ $hmlPath = $cfgClient[$client]['path']['htmlpath'];
+ $aComp = parse_url($hmlPath);
+ $urlPrefix = $aComp['scheme'] . '://' . $aComp['host'];
+ if (mr_arrayValue($aComp, 'port', '') !== '') {
+ $urlPrefix .= ':' . $aComp['port'];
+ }
+ }
+
+ $this->sUrl = $urlPrefix . $url;
+
+ $urlDebug['out'] = $this->sUrl;
+ ModRewriteDebugger::add($urlDebug, 'Contenido_UrlBuilder_MR::buildUrl() in -> out');
+ }
+
+
+ /**
+ * Builds the SEO-URL by analyzing passed arguments (parameter value pairs)
+ *
+ * @param array $aParams Parameter array
+ * @return string New build pretty url
+ */
+ private function _buildUrl(array $aParams)
+ {
+ // language should changed, set lang parameter
+ if (isset($aParams['changelang'])) {
+ $aParams['lang'] = $aParams['changelang'];
+ }
+
+ // build the query
+ $sQuery = http_build_query($aParams);
+
+ // get pretty url parts
+ $oMRUrlStack = ModRewriteUrlStack::getInstance();
+ $aPretty = $oMRUrlStack->getPrettyUrlParts('front_content.php?' . $sQuery);
+
+ // get all non contenido related query parameter
+ $sQuery = $this->_createUrlQueryPart($aParams);
+
+ // some presettings of variables
+ $aParts = array();
+
+ // add client id/name if desired
+ if ($param = $this->_getClientParameter($aParams)) {
+ $aParts[] = $param;
+ }
+
+ // add language id/name if desired
+ if ($param = $this->_getLanguageParameter($aParams)) {
+ $aParts[] = $param;
+ }
+
+ // get path part of the url
+ $sPath = $this->_getPath($aPretty);
+ if ($sPath !== '') {
+ $aParts[] = $sPath;
+ }
+ $sPath = implode('/', $aParts) . '/';
+
+ // get pagename part of the url
+ $sArticle = $this->_getArticleName($aPretty, $aParams);
+
+ if ($sArticle !== '') {
+ $sFileExt = $this->_aMrCfg['file_extension'];
+ } else {
+ $sFileExt = '';
+ }
+
+ $sPathAndArticle = $sPath . $sArticle . $sFileExt;
+ if ($this->_aMrCfg['use_lowercase_uri'] == 1) {
+ // use lowercase url
+ $sPathAndArticle = strtolower($sPathAndArticle);
+ }
+
+// $sUrl = $this->_aMrCfg['rootdir'] . $sPathAndArticle . $sQuery;
+ $sUrl = $sPathAndArticle . $sQuery;
+
+ // remove double or more join parameter
+ $sUrl = mr_removeMultipleChars('/', $sUrl);
+ if (substr($sUrl, -2) == '?=') {
+ $sUrl = substr_replace($sUrl, '', -2);
+ }
+
+ // now convert Contenido url to an AMR url
+ $sUrl = ModRewriteUrlUtil::getInstance()->toModRewriteUrl($sUrl);
+
+ return mr_removeMultipleChars('/', $this->_aMrCfg['rootdir'] . $sUrl);
+ }
+
+
+ /**
+ * Loops thru passed parameter array and creates the query part of the URL.
+ * All non Contenido related parameter will be excluded from composition.
+ *
+ * @param array $aArgs Assoziative parameter array
+ * @return string Composed query part for the URL like '?foo=bar¶m=value'
+ */
+ private function _createUrlQueryPart(array $aArgs)
+ {
+ // set list of parameter which are to ignore while setting additional parameter
+ $aIgnoredParams = array(
+ 'idcat', 'idart', 'lang', 'client', 'idcatart', 'idartlang'
+ );
+ if ($this->_aMrCfg['use_language'] == 1) {
+ $aIgnoredParams[] = 'changelang';
+ }
+ if ($this->_aMrCfg['use_client'] == 1) {
+ $aIgnoredParams[] = 'changeclient';
+ }
+
+ // collect additional non contenido related parameters
+ $sQuery = '';
+ foreach ($aArgs as $p => $v) {
+ if (!in_array($p, $aIgnoredParams)) {
+# $sQuery .= urlencode(urldecode($p)) . '=' . urlencode(urldecode($v)) . $this->_sAmp;
+ $p = urlencode(urldecode($p));
+ if (is_array($v)) {
+ // handle query parameter like foobar[0}=a&foobar[1]=b...
+ foreach ($v as $p2 => $v2){
+ $p2 = urlencode(urldecode($p2));
+ $v2 = urlencode(urldecode($v2));
+ $sQuery .= $p . '[' . $p2 . ']=' . $v2 . $this->_sAmp;
+ }
+ } else {
+ $v = urlencode(urldecode($v));
+ $sQuery .= $p . '=' . $v . $this->_sAmp;
+ }
+ }
+ }
+ if (strlen($sQuery) > 0) {
+ $sQuery = '?' . substr($sQuery, 0, - strlen($this->_sAmp));
+ }
+ return $sQuery;
+ }
+
+
+ /**
+ * Returns client id or name depending on settings.
+ *
+ * @param array $aArgs Additional arguments
+ * @return mixed Client id, client name or null
+ */
+ private function _getClientParameter(array $aArgs)
+ {
+ global $client;
+
+ // set client if desired
+ if ($this->_aMrCfg['use_client'] == 1) {
+ $iChangeClient = (isset($aArgs['changeclient'])) ? (int) $aArgs['changeclient'] : 0;
+ $idclient = ($iChangeClient > 0) ? $iChangeClient : $client;
+ if ($this->_aMrCfg['use_client_name'] == 1) {
+ return urlencode(ModRewrite::getClientName($idclient));
+ } else {
+ return $idclient;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Returns language id or name depending on settings.
+ *
+ * @param array $aArgs Additional arguments
+ * @return mixed Language id, language name or null
+ */
+ private function _getLanguageParameter(array $aArgs)
+ {
+ global $lang;
+
+ // set language if desired
+ if ($this->_aMrCfg['use_language'] == 1) {
+ $iChangeLang = (isset($aArgs['changelang'])) ? (int) $aArgs['changelang'] : 0;
+ $idlang = ($iChangeLang > 0) ? $iChangeLang : $lang;
+ if ($this->_aMrCfg['use_language_name'] == 1) {
+ return urlencode(ModRewrite::getLanguageName($idlang));
+ } else {
+ return $idlang;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Returns composed path of url (normally the category structure)
+ *
+ * @param array $aPretty Pretty url array
+ * @return string Path
+ */
+ private function _getPath(array $aPretty)
+ {
+ $sPath = (isset($aPretty['urlpath'])) ? $aPretty['urlpath'] : '';
+
+ // check start directory settings
+ if ($this->_aMrCfg['startfromroot'] == 0 && (strlen($sPath) > 0)) {
+ // splitt string in array
+ $aCategories = explode('/', $sPath);
+
+ // remove first category
+ array_shift($aCategories);
+
+ // implode array with categories to new string
+ $sPath = implode('/', $aCategories);
+ }
+
+ return $sPath;
+ }
+
+
+ /**
+ * Returns articlename depending on current setting
+ *
+ * @param array $aPretty Pretty url array
+ * @param array $aArgs Additional arguments
+ * @return string Articlename
+ */
+ private function _getArticleName(array $aPretty, array $aArgs)
+ {
+ $sArticle = (isset($aPretty['urlname'])) ? $aPretty['urlname'] : '';
+
+ $iIdCat = (isset($aArgs['idcat'])) ? (int) $aArgs['idcat'] : 0;
+ $iIdCatLang = (isset($aArgs['idcatlang'])) ? (int) $aArgs['idcatlang'] : 0;
+ $iIdCatArt = (isset($aArgs['idcatart'])) ? (int) $aArgs['idcatart'] : 0;
+ $iIdArt = (isset($aArgs['idart'])) ? (int) $aArgs['idart'] : 0;
+ $iIdArtLang = (isset($aArgs['idartlang'])) ? (int) $aArgs['idartlang'] : 0;
+
+ // category id was passed but not article id
+ if (($iIdCat > 0 || $iIdCatLang > 0) && $iIdCatArt == 0 && $iIdArt == 0 && $iIdArtLang == 0) {
+ $sArticle = '';
+ if ($this->_aMrCfg['add_startart_name_to_url']) {
+ if ($this->_aMrCfg['default_startart_name'] !== '') {
+ // use default start article name
+ $sArticle = $this->_aMrCfg['default_startart_name'];
+ } else {
+ $sArticle = (isset($aPretty['urlname'])) ? $aPretty['urlname'] : '';
+ }
+ } else {
+ // url is to create without article name
+ $sArticle = '';
+ }
+ }
+
+ return $sArticle;
+ }
+
+
+}
diff --git a/conlite/classes/UrlBuilder/Sample.php b/conlite/classes/UrlBuilder/Sample.php
new file mode 100644
index 0000000..58441de
--- /dev/null
+++ b/conlite/classes/UrlBuilder/Sample.php
@@ -0,0 +1,65 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ *
+ * {@internal
+ * created 2008-02-19
+ *
+ * $Id: Sample.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+// build a front_content.php URL
+try {
+ $aParams = array('idcat' => 1, 'idart' => 5);
+ $oUrlBuilder = Contenido_UrlBuilderFactory::getUrlBuilder('front_content');
+ $oUrlBuilder->setHttpBasePath($cfgClient[$client]['path']['htmlpath']); // needed if you need an absolute url
+ $oUrlBuilder->buildUrl($aParams, true);
+ echo $oUrlBuilder->getUrl();
+} catch (InvalidArgumentException $e) {
+ throw $e;
+}
+
+// build a URL with category path with output /path/path/path/index-b-1-2-3.html (where "path" being languagedependent)
+try {
+ $aParams = array('idcat' => 1, 'lang' => 1, 'level' => 1, 'b' => array(1,2,3));
+ $oUrlBuilder = Contenido_UrlBuilderFactory::getUrlBuilder('custom_path');
+ $oUrlBuilder->buildUrl($aParams);
+ echo $oUrlBuilder->getUrl();
+} catch (InvalidArgumentException $e) {
+ throw $e;
+}
+
+// build a URL with category path with output /path/path/path/rocknroll,goodies,1,2,3.4fb (where "path" being languagedependent)
+try {
+ $aParams = array('idcat' => 1, 'lang' => 1, 'level' => 1, 'goodies' => array(1,2,3));
+ $aConfig = array('prefix' => 'rocknroll', 'suffix' => '.4fb', 'separator' => ',');
+ $oUrlBuilder = Contenido_UrlBuilderFactory::getUrlBuilder('custom_path');
+ $oUrlBuilder->buildUrl($aParams, false, $aConfig);
+ echo $oUrlBuilder->getUrl();
+} catch (InvalidArgumentException $e) {
+ throw $e;
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/abstract_classes/class.conuser.php b/conlite/classes/abstract_classes/class.conuser.php
new file mode 100644
index 0000000..13334c6
--- /dev/null
+++ b/conlite/classes/abstract_classes/class.conuser.php
@@ -0,0 +1,238 @@
+aCfg = $aCfg;
+ }
+
+ if (is_null($oDb)) {
+ $this->oDb = new DB_ConLite();
+ } else {
+ // is it a contenido DB instance?
+ if ($oDb instanceof DB_ConLite) {
+ $this->oDb = $oDb;
+ } else {
+ throw new ConUserException("Given value for \$oDb is not a valid DB_ConLite instance!");
+ }
+ }
+
+ if (!is_null($sUserId)) {
+ $bLoaded = $this->load($sUserId);
+
+ if ($bLoaded == true) {
+ $this->sUserId = $sUserId;
+ } else {
+ throw new ConUserException("No user with given user ID found!");
+ }
+ }
+ }
+
+// /**
+// * This method checks "the mask" of password $sNewPassword. If
+// * it matches the administrators rules iConUser::PASS_OK will be
+// * returned.
+// *
+// * In this abstract class, it always returns PASS_OK!
+// *
+// * @param string $sNewPassword
+// * @return int
+// *
+// * @see iConUser::checkPasswordMask()
+// */
+// public static function checkPasswordMask($sNewPassword) {
+// return iConUser::PASS_OK;
+// }
+
+// /**
+// * Returns true if password $sNewPassword is strong enough.
+// *
+// * In this abstract class, it always returns true.
+// *
+// * @param string $sNewPassword
+// * @return int
+// *
+// * @see iConUser::checkPasswordStrength()
+// */
+// public static function checkPasswordStrength($sNewPassword) {
+// return iConUser::PASS_OK;
+// }
+
+ /**
+ * Returns user id, currently set.
+ *
+ * @return string
+ */
+ public function getUserId () {
+ return $this->sUserId;
+ }
+
+ /**
+ * Sets user ID.
+ *
+ * @param unknown_type $sUserId
+ *
+ * TODO check this
+ */
+ public function setUserId ($sUserId) {
+ $this->sUserId = $sUserId;
+ }
+
+ /**
+ * Generates new user id based on current user name.
+ *
+ * @return string
+ */
+ public function generateUserId () {
+ $sResult = "";
+
+ $sCurUserName = $this->getUserName();
+
+ if (!empty($sCurUserName)) {
+ $sResult = md5($sCurUserName);
+ } else {
+ throw new ConUserException("No user name set yet");
+ }
+
+ $this->sUserId = $sResult;
+
+ return $sResult;
+ }
+
+ /**
+ * Returns user name, currently set
+ *
+ * @return string
+ */
+ public function getUserName () {
+ return $this->sUserName;
+ }
+
+ /**
+ * Sets up new user name.
+ *
+ * @param string $sUserName
+ */
+ public function setUserName ($sUserName) {
+ $this->sUserName = $sUserName;
+ }
+
+ /**
+ * Checks password which has to be set and return PASS_* values (i.e.
+ * on success PASS_OK).
+ *
+ * @param string $sPassword
+ * @return int
+ */
+ public function setPassword ($sPassword) {
+ $iResult = iConUser::PASS_OK;
+
+ $iMaskResult = $this->checkPasswordMask($sPassword);
+ if ($iMaskResult != iConUser::PASS_OK) {
+ $iResult = $iMaskResult;
+ } else {
+ $iStrengthResult = $this->checkPasswordStrength($sPassword);
+
+ if ($iStrengthResult != iConUser::PASS_OK) {
+ $iResult = $iStrengthResult;
+ } else {
+ $this->sPassword = $sPassword;
+ }
+ }
+
+ return $iResult;
+ }
+
+ /**
+ * Returns (unencoded!) password. This method should never be public
+ * available!
+ *
+ * @return string
+ */
+ protected function getPassword () {
+ return $this->sPassword;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/cApi/class.action.php b/conlite/classes/cApi/class.action.php
new file mode 100644
index 0000000..e7284aa
--- /dev/null
+++ b/conlite/classes/cApi/class.action.php
@@ -0,0 +1,109 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ */
+
+// security check
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class cApiActionCollection extends ItemCollection {
+
+ /**
+ *
+ * @global array $cfg
+ */
+ public function __construct() {
+ global $cfg;
+ parent::__construct($cfg['tab']['actions'], 'idaction');
+ $this->_setItemClass("cApiAction");
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function cApiActionCollection() {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+
+ /**
+ *
+ * @param string $area
+ * @param string $name
+ * @param string $code
+ * @param string $location
+ * @param int $relevant
+ * @return cApiAction
+ */
+ public function create($area, $name, $code = "", $location = "", $relevant = 1) {
+ $item = parent::create();
+
+ if (is_string($area)) {
+ $c = new cApiArea();
+ $c->loadBy("name", $area);
+
+ if ($c->virgin) {
+ $area = 0;
+ cWarning(__FILE__, __LINE__, "Could not resolve area [$area] passed to method [create], assuming 0");
+ } else {
+ $area = $c->get("idarea");
+ }
+ }
+
+ $item->set("idarea", $area);
+ $item->set("name", $name);
+ $item->set("code", $code);
+ $item->set("location", $location);
+ $item->set("relevant", $relevant);
+
+ $item->store();
+
+ return ($item);
+ }
+
+}
+
+class cApiAction extends Item {
+
+ protected $_objectInvalid;
+
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false) {
+ global $cfg;
+ $this->_objectInvalid = false;
+
+ parent::__construct($cfg['tab']['actions'], 'idaction');
+ $this->setFilters(array("addslashes"), array("stripslashes"));
+
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+
+ // @todo Where is this used???
+ $this->_wantParameters = array();
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function cApiAction($mId = false) {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct($mId);
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/cApi/class.stat.php b/conlite/classes/cApi/class.stat.php
new file mode 100644
index 0000000..a162ef5
--- /dev/null
+++ b/conlite/classes/cApi/class.stat.php
@@ -0,0 +1,80 @@
+
+ * @copyright (c) 2016, ConLite Team
+ * @license http://www.gnu.de/documents/gpl.en.html GPL v3 (english version)
+ * @license http://www.gnu.de/documents/gpl.de.html GPL v3 (deutsche Version)
+ * @link http://www.conlite.org ConLite.org
+ *
+ * $Id: class.stat.php 438 2016-05-17 17:31:24Z oldperl $
+ */
+
+// security check
+defined('CON_FRAMEWORK') or die('Illegal call');
+
+
+class cApiStatCollection extends ItemCollection {
+
+ public function __construct() {
+ global $cfg;
+ parent::__construct($cfg['tab']['stat'], 'idstat');
+ $this->_setItemClass("cApiStat");
+ }
+
+ public function trackView($iIdCatArt, $iIdLang = NULL, $iIdClient = NULL) {
+ if (empty($iIdCatArt)) {
+ return FALSE;
+ }
+ if (is_null($iIdLang)) {
+ $iIdLang = cRegistry::getLanguageId();
+ }
+
+ if (is_null($iIdClient)) {
+ $iIdClient = cRegistry::getClientId();
+ }
+
+ $this->resetQuery();
+ $this->setWhere('idcatart', $iIdCatArt);
+ $this->setWhere('idlang', $iIdLang);
+ $this->query();
+
+ /* @var $oItem cApiStat */
+ if (FALSE !== $oItem = $this->next()) {
+ $oItem->setField('visited', ((int) $oItem->getField('visited')+1));
+ } else {
+ $oItem = $this->create();
+ if($oItem->isLoaded()) {
+ $oItem->setField('idcatart', $iIdCatArt);
+ $oItem->setField('idlang', $iIdLang);
+ $oItem->setField('idclient', $iIdClient);
+ $oItem->setField('visited', 1);
+ } else {
+ return FALSE;
+ }
+ }
+ $oItem->setField('visitdate', date("Y-m-d H:i:s"));
+ return $oItem->store();
+ }
+}
+
+class cApiStat extends Item {
+
+ public function __construct($mId = false) {
+ global $cfg;
+ parent::__construct($cfg['tab']['stat'], 'idstat');
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/cApi/class.stat_archive.php b/conlite/classes/cApi/class.stat_archive.php
new file mode 100644
index 0000000..de4e607
--- /dev/null
+++ b/conlite/classes/cApi/class.stat_archive.php
@@ -0,0 +1,45 @@
+
+ * @copyright (c) 2016, ConLite Team
+ * @license http://www.gnu.de/documents/gpl.en.html GPL v3 (english version)
+ * @license http://www.gnu.de/documents/gpl.de.html GPL v3 (deutsche Version)
+ * @link http://www.conlite.org ConLite.org
+ *
+ * $Id: class.stat_archive.php 419 2016-01-23 16:48:40Z oldperl $
+ */
+
+// security check
+defined('CON_FRAMEWORK') or die('Illegal call');
+
+
+class cApiStatCollection extends ItemCollection {
+
+ public function __construct() {
+ global $cfg;
+ parent::__construct($cfg['tab']['stat'], 'idstat');
+ $this->_setItemClass("cApiStat");
+ }
+}
+
+class cApiStat extends Item {
+
+ public function __construct($mId = false) {
+ global $cfg;
+ parent::__construct($cfg['tab']['stat'], 'idstat');
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/cApi/class.system_property.php b/conlite/classes/cApi/class.system_property.php
new file mode 100644
index 0000000..d9b284a
--- /dev/null
+++ b/conlite/classes/cApi/class.system_property.php
@@ -0,0 +1,90 @@
+
+ * @copyright (c) 2012-2013, ConLite Team
+ * @license http://www.gnu.de/documents/gpl.en.html GPL v3 (english version)
+ * @license http://www.gnu.de/documents/gpl.de.html GPL v3 (deutsche Version)
+ * @link http://www.conlite.org ConLite.org
+ *
+ * $Id: class.system_property.php 302M 2016-07-21 16:39:58Z (local) $
+ */
+// security check
+defined('CON_FRAMEWORK') or die('Illegal call');
+
+/**
+ * Description of class.system_properties
+ *
+ * @author Ortwin Pinke
+ */
+class cApiSystemPropertyCollection extends ItemCollection {
+
+ public static $_aCachedProperties;
+ public static $_Counter;
+
+ public function __construct() {
+ global $cfg;
+ parent::__construct($cfg['tab']['system_prop'], 'idsystemprop');
+ $this->_setItemClass("cApiSystemProperty");
+ if ($this->_bDebug) {
+ echo "";
+ print_r(cApiSystemPropertyCollection::$_aCachedProperties);
+ echo " ";
+ }
+ }
+
+ public function getSystemProperty($sType, $sName) {
+ // sanitize param
+ $sType = trim($sType);
+ $sName = trim($sName);
+ // use cache if exists
+ if (is_array(self::$_aCachedProperties) && key_exists($sType, self::$_aCachedProperties)) {
+ if (is_array(self::$_aCachedProperties[$sType]) && key_exists($sName, self::$_aCachedProperties[$sType])) {
+ return self::$_aCachedProperties[$sType][$sName]['value'];
+ }
+ }
+ $this->_loadPropertiesByType($sType);
+
+ if (isset(self::$_aCachedProperties[$sType]) && is_array(self::$_aCachedProperties[$sType]) && key_exists($sName, self::$_aCachedProperties[$sType])) {
+ return self::$_aCachedProperties[$sType][$sName]['value'];
+ }
+ return false;
+ }
+
+ private function _loadPropertiesByType($sType) {
+ $this->resetQuery();
+ $this->setWhere('type', $sType);
+ $this->query();
+ if ($this->count() > 0) {
+ self::$_aCachedProperties[$sType] = array();
+ /* $oProperty cApiSystemProperty */
+ while ($oProperty = $this->next()) {
+ self::$_aCachedProperties[$sType][$oProperty->get('name')]['value'] = $oProperty->get('value');
+ self::$_aCachedProperties[$sType][$oProperty->get('name')]['idsystemprop'] = $oProperty->get('idsystemprop');
+ }
+ }
+ }
+
+}
+
+class cApiSystemProperty extends Item {
+
+ public function __construct($mId = false) {
+ global $cfg;
+ parent::__construct($cfg['tab']['system_prop'], 'idsystemprop');
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/cApi/class.upload.meta.php b/conlite/classes/cApi/class.upload.meta.php
new file mode 100644
index 0000000..c658f1e
--- /dev/null
+++ b/conlite/classes/cApi/class.upload.meta.php
@@ -0,0 +1,100 @@
+_setItemClass("cApiUploadMeta");
+
+ // set the join partners so that joins can be used via link() method
+ $this->_setJoinPartner('cApiUploadCollection');
+ }
+
+ public function create($idupl, $idlang, $medianame = '', $description = '', $keywords = '', $internal_notice = '', $copyright = '', $author = '', $created = '', $modified = '', $modifiedby = '') {
+ global $auth;
+
+ if (empty($author)) {
+ $author = $auth->auth['uname'];
+ }
+ if (empty($created)) {
+ $created = date('Y-m-d H:i:s');
+ }
+ if (empty($modified)) {
+ $modified = date('Y-m-d H:i:s');
+ }
+
+ $oItem = $this->createNewItem();
+
+ $oItem->set('idupl', $idupl);
+ $oItem->set('idlang', $idlang);
+ $oItem->set('medianame', $medianame);
+ $oItem->set('description', $description);
+ $oItem->set('keywords', $keywords);
+ $oItem->set('internal_notice', $internal_notice);
+ $oItem->set('author', $author);
+ $oItem->set('created', $created);
+ $oItem->set('modified', $modified);
+ $oItem->set('modifiedby', $modifiedby);
+ $oItem->set('copyright', $copyright);
+ $oItem->store();
+
+ return $oItem;
+ }
+}
+
+class cApiUploadMeta extends Item {
+
+ public function __construct($mId = false) {
+ global $cfg;
+ parent::__construct($cfg["tab"]["upl_meta"], "id_uplmeta");
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+
+ public function loadByUploadIdAndLanguageId($idupl, $idlang) {
+ $aProps = array(
+ 'idupl' => $idupl,
+ 'idlang' => $idlang
+ );
+ $aRecordSet = $this->_oCache->getItemByProperties($aProps);
+ if ($aRecordSet) {
+ // entry in cache found, load entry from cache
+ $this->loadByRecordSet($aRecordSet);
+ return true;
+ } else {
+ $where = $this->db->prepare('idupl = %d AND idlang = %d', $idupl, $idlang);
+ return $this->_loadByWhereClause($where);
+ }
+ }
+
+ public function setField($name, $value, $bSafe = true) {
+ switch ($name) {
+ case 'idupl':
+ case 'idlang':
+ $value = (int) $value;
+ break;
+ }
+
+ parent::setField($name, $value, $bSafe);
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/cApi/class.upload.php b/conlite/classes/cApi/class.upload.php
new file mode 100644
index 0000000..d8314d0
--- /dev/null
+++ b/conlite/classes/cApi/class.upload.php
@@ -0,0 +1,185 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ */
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class cApiUploadCollection extends ItemCollection {
+
+ /**
+ * Constructor Function
+ * @param none
+ */
+ public function __construct() {
+ global $cfg;
+ parent::__construct($cfg["tab"]["upl"], "idupl");
+ $this->_setItemClass("cApiUpload");
+ }
+
+ public function sync($dir, $file) {
+ global $client;
+
+ if (strstr(strtolower($_ENV["OS"]), 'windows') === FALSE) {
+ #Unix style OS distinguish between lower and uppercase file names, i.e. test.gif is not the same as Test.gif
+ $this->select("dirname = BINARY '$dir' AND filename = BINARY '$file' AND idclient = '$client'");
+ } else {
+ #Windows OS doesn't distinguish between lower and uppercase file names, i.e. test.gif is the same as Test.gif in file system
+ $this->select("dirname = '$dir' AND filename = '$file' AND idclient = '$client'");
+ }
+
+ if ($item = $this->next()) {
+ $item->update();
+ } else {
+ $this->create($dir, $file);
+ }
+ }
+
+ public function create($dir, $file) {
+ global $client, $cfg, $auth;
+
+ $item = parent::create();
+
+ $item->set("idclient", $client);
+ $item->set("filename", $file, false);
+ $item->set("dirname", $dir, false);
+ $item->set("author", $auth->auth["uid"]);
+ $item->set("created", date("Y-m-d H:i:s"), false);
+ $item->store();
+
+ $item->update();
+
+ return ($item);
+ }
+
+ public function delete($id) {
+ global $_cecRegistry, $cfgClient, $client;
+ $item = new UploadItem();
+ $item->loadByPrimaryKey($id);
+
+ // Call chain
+ $_cecIterator = $_cecRegistry->getIterator("Contenido.Upl_edit.Delete");
+ if ($_cecIterator->count() > 0) {
+ while ($chainEntry = $_cecIterator->next()) {
+ $chainEntry->execute($item->get('idupl'), $item->get("dirname"), $item->get("filename"));
+ }
+ }
+
+ // delete from Filesystem or DBFS
+ if (is_dbfs($item->get("dirname") . $item->get("filename"))) {
+ $dbfs = new DBFSCollection();
+ $dbfs->remove($item->get("dirname") . $item->get("filename"));
+ } else {
+ if (file_exists($cfgClient[$client]["upl"]["path"] . $item->get("dirname") . $item->get("filename"))) {
+ unlink($cfgClient[$client]["upl"]["path"] . $item->get("dirname") . $item->get("filename"));
+ }
+ }
+
+ // delete in DB
+ return parent::delete($id);
+ }
+}
+
+class cApiUpload extends Item {
+
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false) {
+ global $cfg;
+ parent::__construct($cfg["tab"]["upl"], "idupl");
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function UploadItem($mId = false) {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct($mId = false);
+ }
+
+ public function update() {
+ global $client, $cfgClient;
+
+ if (substr($this->get("dirname"), 0, 5) == "dbfs:") {
+ $isdbfs = true;
+ $dir = $this->get("dirname");
+ } else {
+ $isdbfs = false;
+ $dir = $cfgClient[$client]["upl"]["path"] . $this->get("dirname");
+ }
+
+ $file = $this->get("filename");
+
+ $dbfs = new DBFSCollection();
+
+ $fullfile = $dir . $file;
+
+ // Strip the file extension
+ $dotposition = strrpos($file, ".");
+ $extension = '';
+ if ($dotposition !== false) {
+ $extension = substr($file, $dotposition + 1);
+ }
+
+ if ($isdbfs) {
+ $filesize = $dbfs->getSize($fullfile);
+ } else {
+ if (file_exists($fullfile)) {
+ $filesize = filesize($fullfile);
+ }
+ }
+
+ $touched = false;
+
+ if ($this->get("filetype") != $extension) {
+ $this->set("filetype", $extension);
+ $touched = true;
+ }
+
+ if ($this->get("size") != $filesize) {
+ $this->set("size", $filesize);
+ $touched = true;
+ }
+
+ if ($touched == true) {
+ $this->store();
+ }
+ }
+
+ public function store() {
+ global $auth, $_cecRegistry;
+
+ $this->set("modifiedby", $auth->auth["uid"]);
+ $this->set("lastmodified", date("Y-m-d H:i:s"), false);
+
+ // Call chain
+ $_cecIterator = $_cecRegistry->getIterator("Contenido.Upl_edit.SaveRows");
+ if ($_cecIterator->count() > 0) {
+ while ($chainEntry = $_cecIterator->next()) {
+ $chainEntry->execute($this->get("idupl"), $this->get("dirname"), $this->get("filename"));
+ }
+ }
+
+ return parent::store();
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/cHTML5/class.chtml.php b/conlite/classes/cHTML5/class.chtml.php
new file mode 100644
index 0000000..bb0d3ab
--- /dev/null
+++ b/conlite/classes/cHTML5/class.chtml.php
@@ -0,0 +1,473 @@
+
+ * @copyright (c) 2012, conlite.org
+ * @license http://www.gnu.de/documents/gpl.en.html GPL v3 (english version)
+ * @license http://www.gnu.de/documents/gpl.de.html GPL v3 (deutsche Version)
+ * @link http://www.conlite.org ConLite.org
+ *
+ * $Id: class.chtml.php 442 2016-06-30 09:15:43Z oldperl $
+ */
+
+// security check
+defined('CON_FRAMEWORK') or die('Illegal call');
+
+if (!class_exists("HTML_Common2")) {
+ cInclude("pear", "HTML/Common2.php");
+}
+
+/* Global ID counter */
+$cHTMLIDCount = 0;
+
+/**
+ * Description of cHTML
+ *
+ * @author Ortwin Pinke
+ */
+class cHTML extends HTML_Common2 {
+
+ /**
+ * Storage of the open SGML tag template
+ * @var string
+ */
+ protected $_skeleton_open;
+
+ /**
+ * Storage of a single SGML tag template
+ * @var string
+ */
+ protected $_skeleton_single;
+
+ /**
+ * Storage of the close SGML tag
+ * @var string
+ */
+ protected $_skeleton_close;
+
+ /**
+ * Defines which tag to use
+ * @var string
+ */
+ protected $_tag;
+
+ /**
+ * Defines the style definitions
+ * @var string
+ */
+ protected $_styledefs;
+
+ /**
+ * Defines all scripts which are required by the current element
+ * @var array
+ */
+ protected $_requiredScripts;
+
+ /**
+ * @var boolean Defines if the current tag is a contentless tag
+ */
+ protected $_contentlessTag;
+
+ /**
+ * @var array Defines which JS events contain which scripts
+ */
+ protected $_aEventDefinitions;
+
+ /**
+ * @var array Style definitions
+ */
+ protected $_aStyleDefinitions;
+
+ /**
+ * @var string The content itself
+ */
+ protected $_content;
+
+ protected $_aCfg;
+
+ /**
+ * Constructor Function
+ * Initializes the SGML open/close tags
+ *
+ * @param none
+ * @return void
+ */
+ public function __construct() {
+ global $cfg;
+ $this->_aCfg = $cfg;
+
+ parent::__construct();
+ $this->_skeleton_open = '<%s%s>';
+ $this->_skeleton_close = '%s>';
+
+
+ /* Cache the XHTML setting for performance reasons */
+ if (!is_array($this->_aCfg) || !array_key_exists("generate_xhtml", $this->_aCfg)) {
+ if (function_exists("getEffectiveSetting")) {
+ $bXhtml = (getEffectiveSetting("generator", "xhtml") == 'true'
+ || getEffectiveSetting("generator", "xhtml") === TRUE)?true:false;
+ $this->_aCfg["generate_xhtml"] = $bXhtml;
+ } else {
+ $this->_aCfg["generate_xhtml"] = false;
+ }
+ }
+
+ if($this->_aCfg["generate_xhtml"] === true) {
+ $this->_skeleton_single = '<%s%s />';
+ } else {
+ $this->_skeleton_single = '<%s%s>';
+ }
+
+ $this->_styledefs = array ();
+ $this->_aStyleDefinitions = array();
+ $this->setContentlessTag();
+
+ $this->advanceID();
+ $this->_requiredScripts = array ();
+ $this->_aEventDefinitions = array ();
+ }
+
+ /**
+ *
+ * @param type $contentlessTag
+ */
+ public function setContentlessTag($contentlessTag = true) {
+ $this->_contentlessTag = $contentlessTag;
+ }
+
+ /**
+ * advances to the next ID available in the system.
+ *
+ * This function is useful if you need to use HTML elements
+ * in a loop, but don't want to re-create new objects each time.
+ *
+ * @return void
+ */
+ public function advanceID() {
+ global $cHTMLIDCount;
+
+ $cHTMLIDCount ++;
+ $this->updateAttributes(array ("id" => "m".$cHTMLIDCount));
+ }
+
+ /**
+ * getID: returns the current ID
+ *
+ * @return string current ID
+ */
+ public function getID() {
+ return $this->getAttribute("id");
+ }
+
+ /**
+ * setAlt: sets the alt and title attributes
+ *
+ * Sets the "alt" and "title" tags. Usually, "alt" is used
+ * for accessibility and "title" for mouse overs.
+ *
+ * To set the text for all browsers for mouse over, set "alt"
+ * and "title". IE behaves incorrectly and shows "alt" on
+ * mouse over. Mozilla browsers only show "title" as mouse over.
+ *
+ * @param string $alt Text to set as the "alt" attribute
+ */
+ public function setAlt($alt) {
+ $attributes = array ("alt" => $alt, "title" => $alt);
+ $this->updateAttributes($attributes);
+ }
+
+ /**
+ * sets the ID class
+ *
+ * @param string $class Text to set as the "id"
+ */
+ public function setID($id) {
+ $this->updateAttributes(array ("id" => $id));
+ }
+
+ /**
+ * sets the CSS class
+ *
+ * @param string $class Text to set as the "class" attribute
+ */
+ public function setClass($class) {
+ $this->updateAttributes(array ("class" => $class));
+ }
+
+ /**
+ * sets the CSS style
+ *
+ * @param $class string Text to set as the "style" attribute
+ */
+ public function setStyle($style) {
+ $this->updateAttributes(array ("style" => $style));
+ }
+
+ /**
+ * adds an "onXXX" javascript event handler
+ *
+ * example:
+ * $item->setEvent("change","document.forms[0].submit");
+ *
+ * @param $event string Type of the event
+ * @param $action string Function or action to call (JavaScript Code)
+ */
+ public function setEvent($event, $action) {
+ if (substr($event, 0, 2) != "on") {
+ $this->updateAttributes(array ("on".$event => $action));
+ } else {
+ $this->updateAttributes(array ($event => $action));
+ }
+ }
+
+ /**
+ * removes an event handler
+ *
+ * example:
+ * $item->unsetEvent("change");
+ *
+ * @param $event string Type of the event
+ */
+ public function unsetEvent($event) {
+ if (substr($event, 0, 2) != "on") {
+ $this->removeAttribute("on".$event);
+ } else {
+ $this->removeAttribute($event);
+ }
+ }
+
+ /**
+ * fillSkeleton: Fills the open SGML tag skeleton
+ *
+ * fillSkeleton fills the SGML opener tag with the
+ * specified attributes. Attributes need to be passed
+ * in the stringyfied variant.
+ *
+ * @param $attributes string Attributes to set
+ * @return string filled SGML opener skeleton
+ */
+ public function fillSkeleton($attributes) {
+ if ($this->_contentlessTag == true) {
+ return sprintf($this->_skeleton_single, $this->_tag, $attributes);
+ } else {
+ return sprintf($this->_skeleton_open, $this->_tag, $attributes);
+ }
+ }
+
+ /**
+ * fillCloseSkeleton: Fills the close skeleton
+ *
+ * @param none
+ * @return string filled SGML closer skeleton
+ */
+ public function fillCloseSkeleton() {
+ return sprintf($this->_skeleton_close, $this->_tag);
+ }
+
+ /**
+ * addStyleDefinition
+ *
+ * @deprecated name change, use attachStyleDefinition
+ * @param $entity string Entity to define
+ * @param $definition string Definition for the given entity
+ * @return string filled SGML closing skeleton
+ */
+ public function setStyleDefinition($entity, $definition) {
+ $this->_styledefs[$entity] = $definition;
+ }
+
+ /**
+ * attachStyleDefinition: Attaches a style definition.
+ *
+ * This function is not restricted to a single style, e.g.
+ * you can set multiple style definitions as-is to the handler.
+ *
+ * $example->attachStyle("myIdentifier",
+ * "border: 1px solid black; white-space: nowrap");
+ * $example->attachStyle("myIdentifier2",
+ * "padding: 0px");
+ *
+ * Results in:
+ *
+ * style="border: 1px solid black; white-space: nowrap; padding: 0px;"
+ *
+ * @param $sName string Name for a style definition
+ * @param $sDefinition string Definition for the given entity
+ * @return string filled SGML closing skeleton
+ */
+ public function attachStyleDefinition($sName, $sDefinition) {
+ $this->_aStyleDefinitions[$sName] = $sDefinition;
+ }
+
+ /**
+ *
+ * @param string $script
+ */
+ public function addRequiredScript($script) {
+ if (!is_array($this->_requiredScripts)) {
+ $this->_requiredScripts = array ();
+ }
+ $this->_requiredScripts[] = $script;
+ $this->_requiredScripts = array_unique($this->_requiredScripts);
+ }
+
+ /**
+ *
+ * @param array $aAttributes
+ * @return array
+ */
+ public function updateAttributes($aAttributes) {
+ return $this->mergeAttributes($aAttributes);
+ }
+
+ /**
+ * _setContent: Sets the content of the object
+ *
+ * @param $content string/object String with the content or an object to render.
+ *
+ */
+ public function _setContent($content) {
+ $this->setContentlessTag(false);
+ /* Is it an array? */
+ if(is_array($content)) {
+ unset ($this->_content);
+ $this->_content = "";
+
+ foreach($content as $item) {
+ if(is_object($item)) {
+ if(method_exists($item, "render")) {
+ $this->_content .= $item->render();
+ }
+
+ if(count($item->_requiredScripts) > 0) {
+ $this->_requiredScripts = array_merge($this->_requiredScripts, $item->_requiredScripts);
+ }
+ } else {
+ $this->_content .= $item;
+ }
+ }
+ } else {
+ if(is_object($content)) {
+ if(method_exists($content, "render")) {
+ $this->_content = $content->render();
+ }
+
+ if(count($content->_requiredScripts) > 0) {
+ $this->_requiredScripts = array_merge($this->_requiredScripts, $content->_requiredScripts);
+ }
+ return;
+ } else {
+ $this->_content = $content;
+ }
+ }
+ }
+
+ /**
+ * attachEventDefinition: Attaches the code for an event
+ *
+ * Example to attach an onClick handler:
+ * setEventDefinition("foo", "onClick", "alert('foo');");
+ *
+ * @param $sName string defines the name of the event
+ * @param $sEvent string defines the event (e.g. onClick)
+ * @param $sCode string defines the code
+ */
+ public function attachEventDefinition($sName, $sEvent, $sCode) {
+ $this->_aEventDefinitions[strtolower($sEvent)][$sName] = $sCode;
+ }
+
+ /**
+ * setAttribte: Sets a specific attribute
+ *
+ * @param $sAttributeName string Name of the attribute
+ * @param $sValue string Value of the attribute
+ */
+ public function setAttribute($sAttributeName, $sValue = NULL) {
+ $sAttributeName = strtolower($sAttributeName);
+ if (is_null($sValue)) {
+ $sValue = $sAttributeName;
+ }
+ $this->updateAttributes(array ($sAttributeName => $sValue));
+ }
+
+ /**
+ *
+ * @return string
+ */
+ public function __toString() {
+ return $this->toHtml();
+ }
+
+ /**
+ * Renders the output
+ * If the tag
+ */
+ public function toHTML() {
+ /* Fill style definition */
+ $style = $this->getAttribute("style");
+
+ /* If the style doesn't end with a semicolon, append one */
+ if(is_string($style)) {
+ $style = trim($style);
+
+ if (substr($style, strlen($style) - 1) != ";") {
+ $style .= ";";
+ }
+ }
+
+ foreach($this->_aStyleDefinitions as $sEntry) {
+ $style .= $sEntry;
+
+ if (substr($style, strlen($style) - 1) != ";") {
+ $style .= ";";
+ }
+ }
+
+ foreach($this->_aEventDefinitions as $sEventName => $sEntry) {
+ $aFullCode = array();
+
+ foreach ($sEntry as $sName => $sCode) {
+ $aFullCode[] = $sCode;
+ }
+ $this->setAttribute($sEventName, $this->getAttribute($sEventName).implode(" ", $aFullCode));
+ }
+
+ /* Apply all stored styles */
+ foreach ($this->_styledefs as $key => $value) {
+ $style .= "$key: $value;";
+ }
+
+ if ($style != "") {
+ $this->setStyle($style);
+ }
+
+ if ($this->_content != "" || $this->_contentlessTag == false) {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes).$this->_content.$this->fillCloseSkeleton();
+ } else {
+ /* This is a single style tag */
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes);
+ }
+ }
+
+ /**
+ * render(): Alias for toHtml
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ public function render() {
+ return $this->toHtml();
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/cHTML5/class.chtml5.button.php b/conlite/classes/cHTML5/class.chtml5.button.php
new file mode 100644
index 0000000..d0f8b63
--- /dev/null
+++ b/conlite/classes/cHTML5/class.chtml5.button.php
@@ -0,0 +1,50 @@
+
+ * @copyright (c) 2015, conlite.org
+ * @license http://www.gnu.de/documents/gpl.en.html GPL v3 (english version)
+ * @license http://www.gnu.de/documents/gpl.de.html GPL v3 (deutsche Version)
+ * @link http://www.conlite.org ConLite.org
+ *
+ * $Id: class.chtml5.button.php 369 2015-10-27 10:53:15Z oldperl $
+ */
+
+// security check
+defined('CON_FRAMEWORK') or die('Illegal call');
+
+/**
+ * Creates an ordered or unordered List
+ *
+ * @author Ortwin Pinke
+ */
+class cHTML5Button extends cHTMLFormElement {
+
+
+ public function __construct($name, $id = "", $disabled = "", $tabindex = "", $accesskey = "") {
+ parent::__construct($name, $id, $disabled, $tabindex, $accesskey);
+ $this->setContentlessTag(FALSE);
+ $this->_tag = "button";
+ }
+
+
+ public function setContent($mContent='') {
+ if(is_object($mContent) && method_exists($mContent, "render")) {
+ $mContent = $mContent->render();
+ }
+ $this->_setContent($mContent);
+ }
+
+ public function toHTML() {
+ return parent::toHTML();
+ }
+}
\ No newline at end of file
diff --git a/conlite/classes/cHTML5/class.chtml5.list.element.php b/conlite/classes/cHTML5/class.chtml5.list.element.php
new file mode 100644
index 0000000..029cc8d
--- /dev/null
+++ b/conlite/classes/cHTML5/class.chtml5.list.element.php
@@ -0,0 +1,57 @@
+
+ * @copyright (c) 2015, conlite.org
+ * @license http://www.gnu.de/documents/gpl.en.html GPL v3 (english version)
+ * @license http://www.gnu.de/documents/gpl.de.html GPL v3 (deutsche Version)
+ * @link http://www.conlite.org ConLite.org
+ *
+ * $Id: class.chtml5.list.element.php 369 2015-10-27 10:53:15Z oldperl $
+ */
+// security check
+defined('CON_FRAMEWORK') or die('Illegal call');
+
+/**
+ * Creates a listelement to use with cHTMLList
+ *
+ * @author Ortwin Pinke
+ * @see cHTMLList
+ */
+class cHTML5ListElement extends cHTML {
+
+ /**
+ * Constructor
+ *
+ * @param boolean $bUnorderd use ul or ol default: TRUE = ul
+ */
+ public function __construct($mContent = "") {
+ parent::__construct();
+
+ if (is_object($mContent) && method_exists($mContent, "render")) {
+ $mContent = $mContent->render();
+ }
+ $this->setContent($mContent);
+ $this->setContentlessTag(false);
+ $this->_tag = "li";
+ }
+
+ public function setContent($content) {
+ $this->_setContent($content);
+ }
+
+ public function toHTML() {
+ return parent::toHTML();
+ }
+
+}
diff --git a/conlite/classes/cHTML5/class.chtml5.list.php b/conlite/classes/cHTML5/class.chtml5.list.php
new file mode 100644
index 0000000..c5ca8f3
--- /dev/null
+++ b/conlite/classes/cHTML5/class.chtml5.list.php
@@ -0,0 +1,115 @@
+
+ * @copyright (c) 2015, conlite.org
+ * @license http://www.gnu.de/documents/gpl.en.html GPL v3 (english version)
+ * @license http://www.gnu.de/documents/gpl.de.html GPL v3 (deutsche Version)
+ * @link http://www.conlite.org ConLite.org
+ *
+ * $Id: class.chtml5.list.php 369 2015-10-27 10:53:15Z oldperl $
+ */
+
+// security check
+defined('CON_FRAMEWORK') or die('Illegal call');
+
+/**
+ * Creates an ordered or unordered List
+ *
+ * @author Ortwin Pinke
+ */
+class cHTML5List extends cHTML {
+
+ /**
+ *
+ * @var array Array of cHTMLListElements
+ */
+ protected $_aListElements = array();
+
+ private $_aListElementClasses = array();
+
+ private $_sListElementStyle;
+
+
+
+
+
+
+ /**
+ * Constructor
+ *
+ * @param boolean $bUnorderd use ul or ol default: TRUE = ul
+ */
+ public function __construct($bUnorderd = TRUE) {
+ parent::__construct();
+ $this->setContentlessTag(false);
+ if($bUnorderd) {
+ $this->_tag = "ul";
+ } else {
+ $this->_tag = "ol";
+ }
+ }
+
+ /**
+ * Add listelement
+ *
+ * @param cHTMLListElement $oElement
+ */
+ public function addListElement(cHTML5ListElement $oElement) {
+ $this->_aListElements[] = $oElement;
+ }
+
+ /**
+ * Autofill of list with array of strings or objects
+ * Objects must have a render method
+ *
+ * @see cHTMLListElement
+ * @param array $aContent Array of Strings or Objects
+ */
+ public function autoFill($aContent) {
+ if(is_array($aContent) && count($aContent) > 0) {
+ foreach($aContent as $mContent) {
+ $this->_aListElements[] = new cHTML5ListElement($mContent);
+ }
+ }
+ }
+
+ public function addClassForElements($sClass) {
+ $this->_aListElementClasses[] = $sClass;
+ }
+
+ public function setStyleForElements($sStyle) {
+ $this->_sListElementStyle = $sStyle;
+ }
+
+ public function toHTML() {
+ if(empty($this->_aListElements)) {
+ return FALSE;
+ }
+ $sContent = "";
+ $iCountElementClasses = count($this->_aListElementClasses);
+ /* @var $oListElement cHTML5ListElement */
+ foreach($this->_aListElements as $oListElement) {
+ if($iCountElementClasses > 0) {
+ foreach($this->_aListElementClasses as $sClass) {
+ $oListElement->addClass($sClass);
+ }
+ }
+ if(!empty($this->_sListElementStyle)) {
+ $oListElement->setStyle($this->_sListElementStyle);
+ }
+ $sContent .= $oListElement->render()."\n";
+ }
+ $this->_setContent($sContent);
+ return parent::toHTML();
+ }
+}
\ No newline at end of file
diff --git a/conlite/classes/cHTML5/class.chtml5.meta.php b/conlite/classes/cHTML5/class.chtml5.meta.php
new file mode 100644
index 0000000..5f10f73
--- /dev/null
+++ b/conlite/classes/cHTML5/class.chtml5.meta.php
@@ -0,0 +1,45 @@
+
+ * @copyright (c) 2015, conlite.org
+ * @license http://www.gnu.de/documents/gpl.en.html GPL v3 (english version)
+ * @license http://www.gnu.de/documents/gpl.de.html GPL v3 (deutsche Version)
+ * @link http://www.conlite.org ConLite.org
+ *
+ * $Id: class.chtml5.meta.php 369 2015-10-27 10:53:15Z oldperl $
+ */
+
+// security check
+defined('CON_FRAMEWORK') or die('Illegal call');
+
+/**
+ * Creates an ordered or unordered List
+ *
+ * @author Ortwin Pinke
+ */
+class cHTML5Meta extends cHTML {
+
+ /**
+ * Constructor
+ *
+ * @param boolean $bUnorderd use ul or ol default: TRUE = ul
+ */
+ public function __construct() {
+ parent::__construct();
+ $this->_tag = "meta";
+ }
+
+ public function toHTML() {
+ return parent::toHTML();
+ }
+}
\ No newline at end of file
diff --git a/conlite/classes/class.action.php b/conlite/classes/class.action.php
new file mode 100644
index 0000000..ed78a38
--- /dev/null
+++ b/conlite/classes/class.action.php
@@ -0,0 +1,148 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created 2003
+ * modified 2008-06-30, Frederic Schneider, add security fix
+ * modified 2009-10-15, Dominik Ziegler, getAvailableActions() now also returns the areaname
+ * modified 2010-07-03, Ortwin Pinke, CON-318, only return actions marked as relevant in getAvailableActions()
+ * also fixed doc-comment for getActionName()
+ *
+ * $Id: class.action.php 306 2014-03-13 23:03:26Z oldperl $;
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class Action {
+
+ /**
+ * Constructor Function
+ * @param
+ */
+ function Action() {
+ // empty
+ } // end function
+
+ /**
+ * getAvailableActions()
+ * Returns all actions available in the system
+ * @return array Array with id and name entries
+ */
+ function getAvailableActions() {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ action.idaction,
+ action.name,
+ area.name AS areaname
+ FROM
+ ". $cfg["tab"]["actions"]." AS action
+ LEFT JOIN
+ ". $cfg["tab"]["area"]." AS area
+ ON
+ area.idarea = action.idarea
+ WHERE action.relevant = '1'
+ ORDER BY
+ action.name;";
+
+ $db->query($sql);
+
+ $actions = array();
+
+ while ($db->next_record())
+ {
+
+ $newentry["name"] = $db->f("name");
+ $newentry["areaname"] = $db->f("areaname");
+
+ $actions[$db->f("idaction")] = $newentry;
+
+ }
+
+ return ($actions);
+ } // end function
+
+ /**
+ * getActionName()
+ *
+ * @return string name of given action
+ */
+ function getActionName( $action ) {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ name
+ FROM
+ ". $cfg["tab"]["actions"] ."
+ WHERE
+ idaction = '".Contenido_Security::toInteger($action)."'";
+
+ $db->query($sql);
+ $db->next_record();
+
+ return ($db->f("name"));
+
+ } // end function
+
+ /**
+ * getAreaForAction()
+ * Returns the area for the given action
+ * @return int Integer with the area ID for the given action
+ */
+ function getAreaForAction( $action ) {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ if (!is_numeric($action))
+ {
+ $sql = "SELECT
+ idarea
+ FROM
+ ". $cfg["tab"]["actions"] ."
+ WHERE
+ name = '".Contenido_Security::escapeDB($action, $db)."'";
+ } else {
+ $sql = "SELECT
+ idarea
+ FROM
+ ". $cfg["tab"]["actions"] ."
+ WHERE
+ idaction = '".Contenido_Security::toInteger($action)."'";
+ }
+
+ $db->query($sql);
+ $db->next_record();
+
+ return ($db->f("idarea"));
+
+ } // end function
+} // end class
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.activeusers.php b/conlite/classes/class.activeusers.php
new file mode 100644
index 0000000..ee66c0c
--- /dev/null
+++ b/conlite/classes/class.activeusers.php
@@ -0,0 +1,302 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * $Id: class.activeusers.php 362 2015-10-05 16:31:26Z oldperl $;
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class ActiveUsers {
+
+ var $oDb;
+ var $oCfg;
+ var $oAuth;
+ var $iUserId;
+
+ /**
+ * Constructor
+ *
+ * @param object $db - Contenido Database Object
+ * @param object $cfg
+ * @param object $auth
+ *
+ * @return
+ **/
+ function ActiveUsers($oDb, $oCfg, $oAuth) {
+
+ $this->oCfg= $oCfg;
+ $this->oAuth= $oAuth;
+ $this->oDb= $oDb;
+
+ // init db object
+ if (!is_object($this->oDb) || (is_null($this->oDb))) {
+ $this->oDb= new DB_ConLite;
+ }
+
+ if (!is_resource($this->oDb->Link_ID)) {
+ $this->oDb->connect();
+ }
+
+ // Load the userid
+ $this->iUserId= $this->oAuth->auth["uid"];
+ }
+
+ /**
+ * Start the User Tracking:
+ * 1) First delete all inactive users with timelimit is off
+ * 2) If find user in the table, do update
+ * 3) Else there is no current user do insert new user
+ *
+ *
+ * @return
+ **/
+ function startUsersTracking() {
+
+ // Delete all Contains in the table "online_user" that is older as timeout(current is 60 minutes)
+ $this->deleteInactiveUser();
+
+ $bResult= $this->findUser($this->iUserId);
+ if ($bResult) {
+ // update the curent user
+ $this->updateUser($this->iUserId);
+ } else {
+ // User not found, we can insert the new user
+ $this->insertOnlineUser($this->iUserId);
+ }
+ }
+
+ /**
+ * Insert this user in online_user table
+ *
+ * @param object $db - Contenido Database Object
+ *
+ * @return Returns true if successful else false
+ **/
+ function insertOnlineUser($sUserId) {
+
+ $userid = (string) $sUserId;
+ $sql= "INSERT INTO `" . $this->oCfg["tab"]["online_user"] . "`(`user_id`,`lastaccessed`) VALUES('".Contenido_Security::escapeDB($userid, $this->oDb)."', NOW())";
+
+ if ($this->oDb->query($sql)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Find the this user if exists in the table "online_user"
+ *
+ * @param integer $iUserId - Is the User-Id (get from auth object)
+ *
+ * @return Returns true if this User is found, else false
+ **/
+ function findUser($sUserId) {
+
+ $userid = (string) $sUserId;
+ $bReturn = false;
+ $sql= "SELECT user_id FROM `" . $this->oCfg["tab"]["online_user"] . "` WHERE `user_id`='".Contenido_Security::escapeDB($userid, $this->oDb)."'";
+ $this->oDb->query($sql);
+ if ($this->oDb->next_record()) {
+ $bReturn= true;
+ }
+ return $bReturn;
+ }
+
+ /**
+ * Find all user_ids in the table 'online_user' for get rest information from
+ * table 'con_phplib_auth_user_md5'
+ *
+ *
+ * @return Returns array of user-information
+ **/
+ function findAllUser() {
+
+ $aAllUser= array ();
+ $aUser= array ();
+ $sWebsiteName= "";
+ // get all user_ids
+ $sql= "SELECT `user_id` FROM `" . $this->oCfg["tab"]["online_user"]."`";
+
+ if ($this->oDb->query($sql) && $this->oDb->Errno == 0) {
+
+ if ($this->oDb->num_rows() > 0) {
+ while ($this->oDb->next_record()) { // Table Online User
+
+ $aUser[]= "'" . $this->oDb->f('user_id') . "'";
+ }
+ }
+ }
+ // get data of those users
+ $aAllUser= array ();
+
+ $sSqlIn= implode(', ', $aUser); // '1','2','5','8'
+ $sql= "SELECT user_id, realname, username, perms " .
+ "FROM " . $this->oCfg["tab"]["phplib_auth_user_md5"] . " " .
+ "WHERE user_id IN(" . $sSqlIn . ")";
+
+ if ($this->oDb->query($sql) && $this->oDb->Errno == 0) {
+
+ if ($this->oDb->num_rows() > 0) {
+ while ($this->oDb->next_record()) { // Table Online User
+ $sWebsiteNames = '';
+ $sUserId= $this->oDb->f("user_id");
+ $aAllUser[$sUserId]['realname']= $this->oDb->f("realname");
+ $aAllUser[$sUserId]['username']= $this->oDb->f("username");
+ $sPerms= $this->oDb->f("perms");
+
+ $aPerms= explode(",", $sPerms); //Alle Rechte als array in aPerms packen
+
+ if (in_array("sysadmin", $aPerms)) {
+ $aAllUser[$sUserId]['perms']= 'Systemadministrator';
+
+ } else {
+
+ $bIsAdmin= false;
+ $iCounter= 0;
+ foreach ($aPerms as $sPerm) {
+ $aResults = array();
+ if (preg_match('/^admin\[(\d+)\]$/', $sPerm, $aResults)) {
+ $iClientId= $aResults[1];
+ $bIsAdmin= true;
+ $sWebsiteName = $this->getWebsiteName($iClientId);
+ if ($iCounter == 0 && $sWebsiteName != "") {
+ $sWebsiteNames .= $sWebsiteName;
+ } else if ($sWebsiteName != "") {
+ $sWebsiteNames .= ', ' . $sWebsiteName;
+ }
+
+ $aAllUser[$sUserId]['perms']= "Administrator (" . $sWebsiteNames . ")";
+ $iCounter++;
+
+ } else if (preg_match('/^client\[(\d+)\]$/', $sPerm, $aResults) && !$bIsAdmin) {
+ $iClientId= $aResults[1];
+ $sWebsiteName = $this->getWebsiteName($iClientId);
+ if ($iCounter == 0 && $sWebsiteName != "") {
+ $sWebsiteNames .= $sWebsiteName;
+ } else if ($sWebsiteName != "") {
+ $sWebsiteNames .= ', ' . $sWebsiteName;
+ }
+
+ $aAllUser[$sUserId]['perms']= '(' . $sWebsiteNames . ')';
+ $iCounter++;
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+ }
+
+ return $aAllUser;
+ }
+
+ /**
+ * This function do an update of current timestamp in "online_user"
+ *
+ * @param integer $iUserId - Is the User-Id (get from auth object)
+ *
+ * @return Returns true if successful, else false
+ **/
+ function updateUser($sUserId) {
+
+ $userid= (string) $sUserId;
+ $sql= "UPDATE `" . $this->oCfg["tab"]["online_user"] . "` SET `lastaccessed`=NOW() WHERE `user_id`='".Contenido_Security::escapeDB($userid, $this->oDb)."'";
+ if ($this->oDb->query($sql)) {
+ return true;
+ } else
+ return false;
+
+ }
+
+ /**
+ * Delete all Contains in the table "online_user" that is older as
+ * Backend timeout(currently is $cfg["backend"]["timeout"] = 60)
+ *
+ *
+ * @return Returns true if successful else false
+ **/
+ function deleteInactiveUser() {
+
+ cInclude("config", "config.misc.php");
+ $iSetTimeOut= $this->oCfg["backend"]["timeout"];
+ if ($iSetTimeOut == 0)
+ $iSetTimeOut= 10;
+ $sql= "";
+ $sql= "DELETE FROM `" . $this->oCfg["tab"]["online_user"] . "` WHERE DATE_SUB(now(), INTERVAL '$iSetTimeOut' Minute) >= `lastaccessed`";
+ if ($this->oDb->query($sql)) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+ /**
+ * Get the number of users from the table "online_user"
+ *
+ *
+ * @return Returns if exists a number of users
+ **/
+ function getNumberOfUsers() {
+
+ $iAnzahl= 0;
+ $sql= "SELECT user_id FROM `" . $this->oCfg["tab"]["online_user"]."`";
+ if ($this->oDb->query($sql)) {
+ $iAnzahl= $this->oDb->num_rows();
+ }
+
+ return $iAnzahl;
+ }
+
+ /**
+ * Delete this user from 'online user' table
+ *
+ * @param integer $iUserId - Is the User-Id (get from auth object)
+ *
+ * @return Returns true if successful, else false
+ **/
+ function deleteUser($sUserId) {
+
+ $userid= (string) $sUserId;
+ $sql= "DELETE FROM `" . $this->oCfg["tab"]["online_user"] . "` WHERE `user_id` = '".Contenido_Security::escapeDB($userid, $this->oDb)."'";
+
+ if ($this->oDb->query($sql)) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+ /**
+ * Get the website name from table con_clients
+ *
+ * @param int $iIdClient
+ * @return string|boolean
+ */
+ public function getWebsiteName($iIdClient) {
+ $oClient = new cApiClient($iIdClient);
+ return $oClient->get('name');
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.ajax.php b/conlite/classes/class.ajax.php
new file mode 100644
index 0000000..209ab4f
--- /dev/null
+++ b/conlite/classes/class.ajax.php
@@ -0,0 +1,237 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release 4.8.12
+ *
+ * {@internal
+ * created 2009-04-08
+ *
+ * $Id: class.ajax.php 424 2016-02-25 06:28:41Z oldperl $:
+ * }}
+ *
+ */
+
+/**
+ * Class for outputting some content for Ajax use
+ *
+ */
+class Ajax {
+
+ /**
+ * Constructor of class
+ *
+ * @access public
+ */
+ function __construct() {
+
+ }
+
+ /**
+ * Function for handling requested ajax data
+ *
+ * @param string $sAction - name of requested ajax action
+ * @access public
+ */
+ public function handle($sAction) {
+ $sString = '';
+ switch ($sAction) {
+ //case to get an article select box param name value and idcat were neded (name= name of select box value=selected item)
+ case 'artsel':
+ $sName = (string) $_REQUEST['name'];
+ $iValue = (int) $_REQUEST['value'];
+ $iIdCat = (int) $_REQUEST['idcat'];
+ $sString = buildArticleSelect($sName, $iIdCat, $iValue);
+ break;
+
+ case 'dirlist':
+ global $cfg, $client, $lang, $cfgClient;
+
+ $sDirName = (string) $_REQUEST['dir'];
+ $iFileListId = (int) $_REQUEST['id'];
+ $iIdArtLang = (int) $_REQUEST['idartlang'];
+
+ $oArt = new Article(null, null, null, $iIdArtLang);
+ $sArtReturn = $oArt->getContent('CMS_FILELIST', $iFileListId);
+ $oFileList = new Cms_FileList($sArtReturn, $iFileListId, 0, '', $cfg, null, '', $client, $lang, $cfgClient, null);
+
+ $sString = $oFileList->getDirectoryList($oFileList->buildDirectoryList($cfgClient[$client]['upl']['path'] . $sDirName));
+ break;
+
+ case 'filelist':
+ global $cfg, $client, $lang, $cfgClient;
+
+ $sDirName = (string) $_REQUEST['dir'];
+ $iFileListId = (int) $_REQUEST['id'];
+ $iIdArtLang = (int) $_REQUEST['idartlang'];
+
+ $oArt = new Article(null, null, null, $iIdArtLang);
+ $sArtReturn = $oArt->getContent('CMS_FILELIST', $iFileListId);
+ $oFileList = new Cms_FileList($sArtReturn, $iFileListId, 0, '', $cfg, null, '', $client, $lang, $cfgClient, null);
+
+ $sString = $oFileList->getFileSelect($sDirName);
+ break;
+
+ case 'inused_layout':
+ //list of used templates for a layout
+ global $cfg;
+ $oLayout = new Layout();
+ if ((int) $_REQUEST['id'] > 0 && $oLayout->layoutInUse((int) $_REQUEST['id'], true)) {
+ $oTpl = new Template();
+ $aUsedTpl = $oLayout->getUsedTemplates();
+ if (count($aUsedTpl) > 0) {
+ $sResponse = ' ';
+ foreach ($aUsedTpl as $i => $aTpl) {
+ $oTpl->set('d', 'NAME', $aTpl['tpl_name']);
+ $oTpl->next();
+ }
+
+ $oTpl->set('s', 'HEAD_NAME', i18n('Template name'));
+ $sString = '' .
+ $oTpl->generate($cfg['path']['contenido'] . $cfg['path']['templates'] .
+ $cfg['templates']['inuse_lay_mod'], true) .
+ '
';
+ } else {
+ $sString = i18n("No data found!");
+ }
+ }
+ break;
+
+ case 'inused_module':
+ //list of used templates for a module
+ global $cfg;
+ $oModule = new cApiModule();
+ if ((int) $_REQUEST['id'] > 0 && $oModule->moduleInUse((int) $_REQUEST['id'], true)) {
+ $oTpl = new Template();
+ $aUsedTpl = $oModule->getUsedTemplates();
+ if (count($aUsedTpl) > 0) {
+ foreach ($aUsedTpl as $i => $aTpl) {
+ $oTpl->set('d', 'NAME', $aTpl['tpl_name']);
+ $oTpl->next();
+ }
+
+ $oTpl->set('s', 'HEAD_NAME', i18n('Template name'));
+ $sString = '' .
+ $oTpl->generate($cfg['path']['contenido'] . $cfg['path']['templates'] .
+ $cfg['templates']['inuse_lay_mod'], true) .
+ '
';
+ } else {
+ $sString = i18n("No data found!");
+ }
+ }
+
+ break;
+
+ case 'inused_template':
+ // list of used category and art
+
+ global $cfg;
+ cInclude('backend', 'includes/functions.tpl.php');
+
+ if ((int) $_REQUEST['id'] > 0) {
+ $oTpl = new Template();
+ $oTpl->reset();
+ $aUsedData = tplGetInUsedData((int) $_REQUEST['id']);
+
+ if (isset($aUsedData['cat'])) {
+ $oTpl->set('s', 'HEAD_TYPE', i18n('Category'));
+ foreach ($aUsedData['cat'] as $i => $aCat) {
+ $oTpl->set('d', 'ID', $aCat['idcat']);
+ $oTpl->set('d', 'LANG', $aCat['lang']);
+ $oTpl->set('d', 'NAME', $aCat['name']);
+ $oTpl->next();
+ }
+ $oTpl->set('s', 'HEAD_ID', i18n('idcat'));
+ $oTpl->set('s', 'HEAD_LANG', i18n('idlang'));
+ $oTpl->set('s', 'HEAD_NAME', i18n('Name'));
+ $sResponse = $oTpl->generate($cfg['path']['contenido'] . $cfg['path']['templates'] . $cfg['templates']['inuse_tpl'], true);
+ }
+
+
+ $oTpl->reset();
+
+ if (isset($aUsedData['art'])) {
+ $oTpl->set('s', 'HEAD_TYPE', i18n('Article'));
+ foreach ($aUsedData['art'] as $i => $aArt) {
+ $oTpl->set('d', 'ID', $aArt['idart']);
+ $oTpl->set('d', 'LANG', $aArt['lang']);
+ $oTpl->set('d', 'NAME', $aArt['title']);
+ $oTpl->next();
+ }
+ $oTpl->set('s', 'HEAD_ID', i18n('idart'));
+ $oTpl->set('s', 'HEAD_LANG', i18n('idlang'));
+ $oTpl->set('s', 'HEAD_NAME', i18n('Name'));
+ $sResponse .= $oTpl->generate($cfg['path']['contenido'] . $cfg['path']['templates'] . $cfg['templates']['inuse_tpl'], true);
+ }
+
+ $sString = '' . $sResponse . '
';
+ } else {
+ $sString = i18n("No data found!");
+ }
+
+ break;
+ case 'plugin_request':
+ if (class_exists("pimPlugin")) {
+ if ($_REQUEST['plugin'] === "pluginmanager") {
+ $oPlugin = new pimPluginDummy();
+ } else {
+ $oPlugin = new pimPlugin();
+ $oPlugin->loadBy("folder", $_REQUEST['plugin']);
+ }
+ if ($oPlugin->isLoaded()) {
+ $bActive = ($oPlugin->get("active")) ? TRUE : FALSE;
+ $sPluginFolder = $oPlugin->get("folder");
+ $sPluginPath = cRegistry::getBackendPath()
+ . cRegistry::getConfigValue("path", "plugins")
+ . $sPluginFolder . DIRECTORY_SEPARATOR;
+ $sAjaxClassFile = $sPluginPath
+ . "classes" . DIRECTORY_SEPARATOR
+ . "class." . $sPluginFolder . ".ajax.php";
+ $sAjaxIncludeFile = $sPluginPath
+ . "includes" . DIRECTORY_SEPARATOR
+ . "include." . $sPluginFolder . "_ajax.php";
+ if ($bActive && file_exists($sAjaxClassFile)) {
+ $sClassName = ucfirst($sPluginFolder) . "Ajax";
+ $oPluginAjax = new $sClassName();
+ $sString = $oPluginAjax->handle($_REQUEST['plugin_ajax_action']);
+ if (!empty($sString)) {
+ break;
+ }
+ } else if ($bActive && file_exists($sAjaxIncludeFile)) {
+ $sAjaxFuncName = "ajax_" . $sPluginFolder . "_" . $_REQUEST['plugin_ajax_action'];
+ @include_once $sAjaxIncludeFile;
+ if (function_exists($sAjaxFuncName)) {
+ $sString = $sAjaxFuncName();
+ break;
+ }
+ }
+ }
+ }
+ //if action is unknown generate error message
+ default:
+ $sString = "Unknown Ajax Action";
+ break;
+ }
+
+ return $sString;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.area.php b/conlite/classes/class.area.php
new file mode 100644
index 0000000..aa427c4
--- /dev/null
+++ b/conlite/classes/class.area.php
@@ -0,0 +1,124 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created 2003
+ * modified 2008-06-30, Frederic Schneider, add security fix
+ *
+ * $Id: class.area.php 306 2014-03-13 23:03:26Z oldperl $;
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class Area {
+
+ /**
+ * Constructor Function
+ * @param
+ */
+ function Area() {
+ // empty
+ } // end function
+
+ /**
+ * getAvailableAreas()
+ * Returns all areas available in the system
+ * @return array Array with id and name entries
+ */
+ function getAvailableAreas() {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ idarea,
+ name
+ FROM
+ ". $cfg["tab"]["area"];
+
+ $db->query($sql);
+
+ $areas = array();
+
+ while ($db->next_record())
+ {
+ $newentry["name"] = $db->f("name");
+ $areas[$db->f("idarea")] = $newentry;
+ }
+
+ return ($areas);
+ } // end function
+
+ /**
+ * getAreaName()
+ * Returns the name for a given areaid
+ * @return string String with the name for the area
+ */
+ function getAreaName( $area ) {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ name
+ FROM
+ ". $cfg["tab"]["area"] ."
+ WHERE
+ idarea = '".Contenido_Security::escapeDB($area, $db)."'";
+ $db->query($sql);
+ $db->next_record();
+
+ return ($db->f("name"));
+
+ } // end function
+
+ /**
+ * getAreaID()
+ * Returns the idarea for a given area name
+ * @return int Integer with the ID for the area
+ */
+ function getAreaID( $area ) {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ idarea
+ FROM
+ ". $cfg["tab"]["area"] ."
+ WHERE
+ name = '".Contenido_Security::escapeDB($area, $db)."'";
+
+ $db->query($sql);
+ $db->next_record();
+
+ return ($db->f("idarea"));
+
+ } // end function
+
+
+} // end class
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.art.php b/conlite/classes/class.art.php
new file mode 100644
index 0000000..f450950
--- /dev/null
+++ b/conlite/classes/class.art.php
@@ -0,0 +1,101 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ *
+ * $Id: class.art.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class Art {
+
+ /**
+ * Constructor Function
+ * @param
+ */
+ function Art() {
+ // empty
+ } // end function
+
+ /**
+ * getArtName()
+ * Returns a name for the given article
+ * @return string Returns the name of the given article
+ */
+ function getArtName($article, $idlang) {
+ global $cfg;
+
+ $db = new DB_ConLite;
+ $idlang = Contenido_Security::toInteger($idlang);
+ $article = Contenido_Security::toInteger($article);
+
+ $sql = "SELECT
+ title
+ FROM
+ ". $cfg["tab"]["art_lang"] ."
+ WHERE
+ idlang = '".$idlang."' AND
+ idart = '".$article."'";
+
+ $db->query($sql);
+ $db->next_record();
+
+ return ($db->f("title"));
+
+ } // end function
+
+ /**
+ * getArtIDForCatArt()
+ * Returns a name for the given article
+ * @return string Returns the name of the given article
+ *
+ */
+ function getArtIDForCatArt ( $idcatart)
+ {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ $idcatart = Contenido_Security::toInteger($idcatart);
+
+ $sql = "SELECT
+ idart
+ FROM
+ ". $cfg["tab"]["cat_art"] ."
+ WHERE
+ idcatart = '".$idcatart."'";
+ $db->query($sql);
+ $db->next_record();
+
+ return ($db->f("idart"));
+
+ } // End function
+
+} // end class
+
+?>
diff --git a/conlite/classes/class.article.collector.php b/conlite/classes/class.article.collector.php
new file mode 100644
index 0000000..29c53f9
--- /dev/null
+++ b/conlite/classes/class.article.collector.php
@@ -0,0 +1,267 @@
+setOptions($aOptions);
+ $this->_oArticleLanguage = new cApiArticleLanguage();
+ }
+
+ public function loadArticles() {
+ $this->_getStartArticles();
+
+ // now lets fetch articles
+ $oArtLangColl = new cApiArticleLanguageCollection(); //a
+ $oArtLangColl->link("cApiArticleCollection"); //b
+ $oArtLangColl->link("cApiCategoryArticleCollection"); //c
+
+ $oArtLangColl->addResultField('idcat');
+
+ if (count($this->_aOptions['categories']) > 0) {
+ $oArtLangColl->setWhere("cApiCategoryArticleCollection.idcat", $this->_aOptions['categories'], "IN");
+ }
+ if (count($this->_aOptions['artspecs']) > 0) {
+ $oArtLangColl->setWhere("cApiArticleLanguageCollection.artspec", implode(",", $this->_aOptions['artspec']), "IN");
+ }
+
+ if (count($this->_aStartArticles) > 0) {
+ print_r($this->_aStartArticles);
+ if ($this->_aOptions['start'] == false) {
+ $oArtLangColl->setWhere("cApiArticleLanguageCollection.idartlang", $this->_aStartArticles, "NOTIN");
+ //$sqlStartArticles = "a.idartlang NOT IN ('" . implode("','", $this->_startArticles) . "') AND ";
+ }
+
+ if ($this->_aOptions['startonly'] == true) {
+ echo "startonly";
+ $oArtLangColl->setWhere("cApiArticleLanguageCollection.idartlang", $this->_aStartArticles, "IN");
+ //$sqlStartArticles = "a.idartlang IN ('" . implode("','", $this->_startArticles) . "') AND ";
+ }
+ }
+
+ if ($this->_aOptions['offlineonly'] == true) {
+ //$sql .= " AND a.online = 0";
+ $oArtLangColl->setWhere("cApiArticleLanguageCollection.online", 0);
+ } else if ($this->_aOptions['offline'] == false) {
+ //$sql .= " AND a.online = 1";
+ $oArtLangColl->setWhere("cApiArticleLanguageCollection.online", 1);
+ }
+
+ $oArtLangColl->setWhere("cApiArticleLanguageCollection.idlang", $this->_aOptions['lang']);
+
+ $oArtLangColl->query();
+ echo $oArtLangColl->_lastSQL;
+ if ($oArtLangColl->count() > 0) {
+ $aTable = $oArtLangColl->fetchTable();
+ //echo $oArtLangColl->_lastSQL;
+
+ foreach ($aTable as $aItem) {
+ $this->_aArticles[] = $aItem['idartlang'];
+ }
+ print_r($this->_aArticles);
+ }
+ }
+
+ /**
+ *
+ * @param array $aOptions
+ */
+ public function setOptions(array $aOptions) {
+ if (count($this->_aOptionsDefault) == 0) {
+ $this->_setOptionsDefault();
+ }
+
+ if (isset($aOptions['idcat']) && !isset($aOptions['categories'])) {
+ $aOptions['categories'] = array(
+ $aOptions['idcat']
+ );
+ }
+
+ if (isset($aOptions['with_sub_cats']) && $aOptions['with_sub_cats'] === TRUE) {
+ foreach ($aOptions['categories'] as $iIdcat) {
+ $aTmp = $this->_getSubCats($iIdcat);
+ $aOptions['categories'] = array_merge($aOptions['categories'], $aTmp);
+ }
+ }
+
+ switch ($aOptions['order']) {
+ case 'sortsequence':
+ $aOptions['order'] = 'artsort';
+ break;
+
+ case 'title':
+ $aOptions['order'] = 'title';
+ break;
+
+ case 'modificationdate':
+ $aOptions['order'] = 'lastmodified';
+ break;
+
+ case 'publisheddate':
+ $aOptions['order'] = 'published';
+ break;
+
+ case 'creationdate':
+ default:
+ $aOptions['order'] = 'created';
+ break;
+ }
+
+ $this->_aOptions = array_merge($this->_aOptionsDefault, $aOptions);
+ }
+
+ /**
+ *
+ * @return int article count
+ */
+ public function count() {
+ return count($this->_aArticles);
+ }
+
+ /**
+ * Returns current element
+ *
+ * @return cApiArticleLanguage|int returns article language object or idartlang
+ */
+ public function current() {
+ $iIdartlang = $this->_aArticles[$this->_iCurrentPosition];
+ if ($this->_bAsObject) {
+ $oArticle = new cApiArticleLanguage($iIdartlang);
+ if ($oArticle->isLoaded()) {
+ return $oArticle;
+ } else {
+ throw new Exception(get_class() . ": Cannot load cApiArticleLanguage object for idartlang (" . $iIdartlang . ")!");
+ }
+ } else {
+ return $iIdartlang;
+ }
+ }
+
+ public function getRandomArticle() {
+ $iArtCount = $this->count();
+ if($iArtCount > 0) {
+ if($iArtCount < 2) {
+ return $this->current();
+ } else {
+ $iRand = mt_rand(0, $iArtCount -1);
+ $this->rewind();
+ $this->seek($iRand);
+ return $this->current();
+ }
+ }
+ return FALSE;
+ }
+
+ /**
+ *
+ * @return int current position
+ */
+ public function key() {
+ return $this->_iCurrentPosition;
+ }
+
+ /**
+ *
+ */
+ public function next() {
+ ++$this->_iCurrentPosition;
+ }
+
+ /**
+ * set iterator to start position
+ */
+ public function rewind() {
+ $this->_iCurrentPosition = 0;
+ }
+
+ /**
+ *
+ * @param type $position
+ * @throws OutOfBoundsException
+ */
+ public function seek($position) {
+ $this->_iCurrentPosition = $position;
+
+ if ($this->valid() === false) {
+ throw new OutOfBoundsException(get_class() . ": Invalid seek position: " . $position);
+ }
+ }
+
+ /**
+ * valid position of iterator
+ *
+ * @return boolean
+ */
+ public function valid() {
+ return isset($this->_aArticles[$this->_iCurrentPosition]);
+ }
+
+ private function _setOptionsDefault() {
+ $this->_aOptionsDefault = array(
+ 'categories' => array(),
+ 'lang' => cRegistry::getLanguageId(),
+ 'client' => cRegistry::getClientId(),
+ 'start' => FALSE,
+ 'startonly' => FALSE,
+ 'offline' => FALSE,
+ 'offlineonly' => FALSE,
+ 'artspecs' => array(),
+ 'direction' => 'DESC',
+ 'limit' => 0
+ );
+ }
+
+ /**
+ * Returns Array of first leveled SubCats for a given Idcat
+ *
+ * @param int $iIdcat idcat to search for subcats
+ * @return array
+ */
+ private function _getSubCats($iIdcat) {
+ $aSubCats = array();
+ $oCatColl = new cApiCategoryCollection();
+ $oCatColl->setWhere("parentid", $iIdcat);
+ $oCatColl->query();
+ $aTable = $oCatColl->fetchTable();
+ //print_r($aTable);
+
+ foreach ($aTable as $aItem) {
+ $aSubCats[] = $aItem['idcat'];
+ }
+ //print_r($aSubCats);
+ return $aSubCats;
+ }
+
+ private function _getStartArticles() {
+ $oCatLangColl = new cApiCategoryLanguageCollection();
+ $oCatLangColl->setWhere("idlang", $this->_aOptions['lang']);
+ if(count($this->_aOptions['categories']) > 0) {
+ $oCatLangColl->setWhere("idcat", implode("','", $this->_aOptions['categories']), 'IN');
+ }
+ $oCatLangColl->query();
+ while($oCatLang = $oCatLangColl->next()) {
+ $startId = $oCatLang->get('startidartlang');
+ if ($startId > 0) {
+ $this->_aStartArticles[$oCatLang->get('idcat')] = $startId;
+ }
+ }
+ }
+}
diff --git a/conlite/classes/class.article.php b/conlite/classes/class.article.php
new file mode 100644
index 0000000..5edfa0d
--- /dev/null
+++ b/conlite/classes/class.article.php
@@ -0,0 +1,747 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ * Contenido API - Article Object
+ *
+ * This object represents a Contenido article
+ *
+ * Create object with
+ * $obj = new Article(idart, client, lang [, idartlang]);
+ *
+ * You can now read the article properties with
+ * $obj->getField(property);
+ *
+ * List of article properties:
+ *
+ * idartlang - Language dependant article id
+ * idart - Language indepenant article id
+ * idclient - Id of the client
+ * idtplcfg - Template configuration id
+ * title - Internal Title
+ * pagetitle - HTML Title
+ * summary - Article summary
+ * created - Date created
+ * lastmodified - Date lastmodiefied
+ * author - Article author (username)
+ * online - On-/offline
+ * redirect - Redirect
+ * redirect_url - Redirect URL
+ * artsort - Article sort key
+ * timemgmt - Time management
+ * datestart - Time management start date
+ * dateend - Time management end date
+ * status - Article status
+ * free_use_01 - Free to use
+ * free_use_02 - Free to use
+ * free_use_03 - Free to use
+ * time_move_cat - Move category after time management
+ * time_target_cat - Move category to this cat after time management
+ * time_online_move - Set article online after move
+ * external_redirect - Open article in new window
+ * locked - Article is locked for editing
+ *
+ * You can extract article content with the
+ * $obj->getContent(contype [, number]) method.
+ *
+ * To extract the first headline you can use:
+ *
+ * $headline = $obj->getContent("htmlhead", 1);
+ *
+ * If the second parameter is ommitted the method
+ * returns an array with all available content of
+ * this type. The array has the following schema:
+ *
+ * array( number => content );
+ *
+ * $headlines = $obj->getContent("htmlhead");
+ *
+ * $headlines[1] First headline
+ * $headlines[2] Second headline
+ * $headlines[6] Sixth headline
+ *
+ * Legal content type string are defined in the Contenido
+ * system table 'con_type'. Default content types are:
+ *
+ * NOTE: This parameter is case insesitive, you can use
+ * html or cms_HTML or CmS_HtMl. Your don't need start with
+ * cms, but it won't crash if you do so.
+ *
+ * htmlhead - HTML Headline
+ * html - HTML Text
+ * headline - Headline (no HTML)
+ * text - Text (no HTML)
+ * img - Upload id of the element
+ * imgdescr - Image description
+ * link - Link (URL)
+ * linktarget - Linktarget (_self, _blank, _top ...)
+ * linkdescr - Linkdescription
+ * swf - Upload id of the element
+ *
+ */
+class Article extends Item
+{
+ /**
+ * Config array
+ * @var array
+ */
+ public $tab;
+
+ /**
+ * Article content
+ * @var array
+ */
+ public $content;
+
+ /**
+ * holds idartlang of article
+ *
+ * @var int
+ */
+ protected $_iIdArtLang;
+
+ /**
+ * Constructor
+ *
+ * @param int $idart Article Id
+ * @param int $lang Language Id
+ *
+ * @return void
+ */
+ public function __construct($idart, $client, $lang, $idartlang = 0) {
+ global $cfg;
+
+ $this->tab = $cfg['tab'];
+
+ parent::__construct($this->tab['art_lang'], 'idartlang');
+
+ $idartlang = Contenido_Security::toInteger($idartlang);
+ $this->_iIdArtLang = ($idartlang == 0) ? $this->_getIdArtLang($idart, $lang) : $idartlang;
+
+ $this->loadByPrimaryKey($this->_iIdArtLang);
+ $this->_getArticleContent();
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ function Article($idart, $client, $lang, $idartlang = 0) {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct($idart, $client, $lang, $idartlang);
+ }
+
+ /**
+ * Getter for idartlang of article object
+ *
+ * @author Ortwin Pinke
+ * @since ConLite 0.1.0
+ *
+ * @return int idartlang
+ */
+ public function getIdArtLang() {
+ if(!empty($this->_iIdArtLang) && is_integer($this->_iIdArtLang)) {
+ return $this->_iIdArtLang;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Extract 'idartlang' for a specified 'idart' and 'lang'
+ *
+ * @param int Article id
+ * @param int Language id
+ *
+ * @access private
+ * @return int Language dependant article id
+ */
+ protected function _getIdArtLang($idart, $lang)
+ {
+ $idart = Contenido_Security::toInteger($idart);
+ $lang = Contenido_Security::toInteger($lang);
+
+ $sql = 'SELECT idartlang FROM '.$this->tab['art_lang'].' WHERE idart="'.$idart.'" AND idlang="'.$lang.'"';
+
+ $this->db->query($sql);
+ $this->db->next_record();
+
+ return $this->db->f('idartlang');
+ }
+
+ /**
+ * Load the articles content and stores it in the 'content' property of the
+ * article object
+ *
+ * $article->content[type][number] = value;
+ *
+ * @param none
+ * @return void
+ */
+ protected function _getArticleContent()
+ {
+ $sql = 'SELECT
+ b.type, a.typeid, a.value
+ FROM
+ '.$this->tab['content'].' AS a,
+ '.$this->tab['type'].' AS b
+ WHERE
+ a.idartlang = "'.$this->get('idartlang').'" AND
+ b.idtype = a.idtype
+ ORDER BY
+ a.idtype, a.typeid';
+
+ $this->db->query($sql);
+
+ while ($this->db->next_record()) {
+ $this->content[strtolower($this->db->f('type'))][$this->db->f('typeid')] = urldecode($this->db->f('value'));
+ }
+ }
+
+ /**
+ * Get the value of an article property
+ *
+ * List of article properties:
+ *
+ * idartlang - Language dependant article id
+ * idart - Language indepenant article id
+ * idclient - Id of the client
+ * idtplcfg - Template configuration id
+ * title - Internal Title
+ * pagetitle - HTML Title
+ * summary - Article summary
+ * created - Date created
+ * lastmodified - Date lastmodiefied
+ * author - Article author (username)
+ * online - On-/offline
+ * redirect - Redirect
+ * redirect_url - Redirect URL
+ * artsort - Article sort key
+ * timemgmt - Time management
+ * datestart - Time management start date
+ * dateend - Time management end date
+ * status - Article status
+ * free_use_01 - Free to use
+ * free_use_02 - Free to use
+ * free_use_03 - Free to use
+ * time_move_cat - Move category after time management
+ * time_target_cat - Move category to this cat after time management
+ * time_online_move - Set article online after move
+ * external_redirect - Open article in new window
+ * locked - Article is locked for editing
+ *
+ * @param string Property name
+ * @return mixed Property value
+ */
+ public function getField($name)
+ {
+ return urldecode($this->values[$name]);
+ }
+
+ /**
+ * Get content(s) from an article
+ *
+ * Returns the specified content element or an array("id"=>"value")
+ * if the second parameter is omitted.
+ *
+ * Legal content type string are defined in the Contenido
+ * system table 'con_type'. Default content types are:
+ *
+ * NOTE: Parameter is case insesitive, you can use
+ * html or cms_HTML or CmS_HtMl. Your don't need start with
+ * cms, but it won't crash if you do so.
+ *
+ * htmlhead - HTML Headline
+ * html - HTML Text
+ * headline - Headline (no HTML)
+ * text - Text (no HTML)
+ * img - Upload id of the element
+ * imgdescr - Image description
+ * link - Link (URL)
+ * linktarget - Linktarget (_self, _blank, _top ...)
+ * linkdescr - Linkdescription
+ * swf - Upload id of the element
+ *
+ * @param string CMS_TYPE - Legal cms type string
+ * @param int Id of the content
+ *
+ * @return mixed String/Array Content Data
+ */
+ public function getContent($type, $id = NULL)
+ {
+ if ($type == '') {
+ return 'Class ' . get_class($this) . ': content-type must be specified!';
+ }
+
+ $type = strtolower($type);
+
+ if (!strstr($type, 'cms_')) {
+ $type = 'cms_' . $type;
+ }
+
+ if (is_null($id)) {
+ // return Array
+ return $this->content[$type];
+ }
+
+ // return String
+ return $this->content[$type][$id];
+ }
+
+ /**
+ * Store -DISABLED-
+ *
+ * This Article Object is READ ONLY
+ *
+ * @param none
+ * @access private
+ * @return none
+ */
+ public function store()
+ {
+ return false;
+ }
+}
+
+
+/**
+ * Contenido API - Article Object Collection
+ *
+ * This class is used to manage multiple Contenido
+ * article objects in a collection.
+ *
+ * The constructor awaits an associative array
+ * as parameter with the following schema:
+ *
+ * array( string paramname => mixed value );
+ *
+ * The parameter idcat is required: array('idcat'=>n)
+ *
+ * Legal parameter names are:
+ *
+ * idcat - Contenido Category Id
+ * lang - Language Id, active language if ommited
+ * client - Client Id, active client if ommited
+ * start - include start article in the collection, defaults to false
+ * artspecs - Array of article specifications, which should be considered
+ * order - articles will be orderered by this article property, defaults to 'created'
+ * direction - Order direcion, 'asc' or 'desc' for ascending/descending, defaults to 'asc'
+ * limit - Limit numbers of articles in collection
+ *
+ * You can easy create article lists/teasers with this class.
+ *
+ * To create an article list of category 4 (maybe a news category) use:
+ *
+ * $myList = new ArticleCollection(array("idcat"=>4);
+ *
+ * while ($article = $myList->nextArticle())
+ * {
+ * // Fetch the first headline
+ * $headline = $article->getContent('htmlhead', 1);
+ * $idart = $article->getField('idart');
+ *
+ * // Create a link
+ * echo ''.$headline.' ';
+ * }
+ *
+ * @package Contenido API
+ * @version 1.0
+ *
+ * @author Jan Lengowski
+ * @copyright four for business AG
+ */
+class ArticleCollection
+{
+ /**
+ * Database Object
+ * @var object
+ */
+ public $db;
+
+ /**
+ * Result Counter
+ * @var int
+ */
+ public $cnt = 0;
+
+ /**
+ * Language id
+ * @var int
+ */
+ public $lang;
+
+ /**
+ * Client ID
+ * @var int
+ */
+ public $client;
+
+ /**
+ * Config array
+ * @var array
+ */
+ public $tab;
+
+ /**
+ * Articles
+ * @var array
+ */
+ public $articles;
+
+ /**
+ * Article Specifications
+ * @var array
+ */
+ public $artspecs;
+
+ /**
+ * Include the Start-Article
+ * @var int
+ */
+ public $start;
+
+ /**
+ * Id of the start article
+ * @var int
+ */
+ public $startId;
+
+ /**
+ * Sort order
+ * @var string
+ */
+ public $order;
+
+ /**
+ * Sort direction
+ * @var string
+ */
+ public $direction;
+
+ /**
+ * Limit of numbers of articles in collection
+ * @var int
+ */
+ public $limit;
+
+ /**
+ * Articles in collection
+ * @var int
+ */
+ public $count;
+
+ /**
+ * Pages in Article Collection
+ * @var int
+ */
+ public $iCountPages;
+
+ /**
+ * Results per page
+ * @var int
+ */
+ public $iResultPerPage;
+
+ /**
+ * List of articles, splitted into pages
+ * @var array
+ */
+ public $aPages;
+
+ /**
+ * Article Collection Constructor
+ *
+ * @param array Options array with schema array("option"=>"value");
+ * idcat (required) - Contenido Category Id
+ * lang - Language Id, active language if ommited
+ * client - Client Id, active client if ommited
+ * artspecs - Array of article specifications, which should be considered
+ * start - include start article in the collection, defaults to false
+ * order - articles will be orderered by this property, defaults to 'created'
+ * direction - Order direcion, 'asc' or 'desc' for ascending/descending
+ * limit - Limit numbers of articles in collection
+ *
+ * @return void
+ */
+ public function __construct($options)
+ {
+ global $cfg;
+
+ $this->tab = $cfg['tab'];
+ $this->db = new DB_ConLite();
+
+ if (!is_numeric($options["idcat"])) {
+ return 'idcat has to be defined';
+ }
+
+ $this->_setObjectProperties($options);
+ $this->_getArticlesByCatId($this->idcat);
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ function ArticleCollection($options)
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct($options);
+ }
+
+ /**
+ * Set the Object properties
+ *
+ * @param array Options array with schema array("option"=>"value");
+ * idcat (required) - Contenido Category Id
+ * lang - Language Id, active language if ommited
+ * client - Client Id, active client if ommited
+ * artspecs - Array of article specifications, which should be considered
+ * start - include start article in the collection, defaults to false
+ * order - articles will be ordered by this property, defaults to 'created'
+ * direction - Order direcion, 'ASC' or 'DESC' for ascending/descending
+ * limit - Limit numbers of articles in collection
+ *
+ * @access private
+ * @return void
+ */
+ private function _setObjectProperties($options)
+ {
+ global $client, $lang;
+
+ $lang = Contenido_Security::toInteger($lang);
+ $client = Contenido_Security::toInteger($client);
+
+ $this->idcat = $options['idcat'];
+ $this->lang = (array_key_exists('lang', $options)) ? $options['lang'] : $lang;
+ $this->client = (array_key_exists('client', $options)) ? $options['client'] : $client;
+ $this->start = (array_key_exists('start', $options)) ? $options['start'] : false;
+ $this->offline = (array_key_exists('offline',$options)) ? $options['offline'] : false;
+ $this->order = (array_key_exists('order', $options)) ? $options['order'] : 'created';
+ $this->artspecs = (array_key_exists('artspecs', $options) AND is_array($options['artspecs'])) ? $options['artspecs'] : array();
+ $this->direction = (array_key_exists('direction', $options)) ? $options['direction'] : 'DESC';
+ $this->limit = (array_key_exists('limit', $options) AND is_numeric($options['limit'])) ? $options['limit'] : 0;
+ }
+
+ /**
+ * Extracts all articles from a specified category id and stores them in the
+ * internal article array
+ *
+ * @param int Category Id
+ *
+ * @access private
+ * @return void
+ */
+ private function _getArticlesByCatId($idcat)
+ {
+ global $cfg;
+
+ $idcat = Contenido_Security::toInteger($idcat);
+
+ $sArtSpecs = (count($this->artspecs) > 0) ? " a.artspec IN ('".implode("','", $this->artspecs)."') AND " : '';
+
+ if ($cfg["is_start_compatible"] == true) {
+ $sql = 'SELECT
+ a.idart,
+ c.is_start
+ FROM
+ '.$this->tab['art_lang'].' AS a,
+ '.$this->tab['art'].' AS b,
+ '.$this->tab['cat_art'].' AS c
+ WHERE
+ c.idcat = '.$idcat.' AND
+ b.idclient = '.$this->client.' AND
+ b.idart = c.idart AND
+ a.idart = b.idart AND
+ '.$sArtSpecs.'
+ a.idlang = '.$this->lang.'';
+ } else {
+
+ $sql = 'SELECT
+ a.idart,
+ a.idartlang,
+ c.is_start
+ FROM
+ '.$this->tab['art_lang'].' AS a,
+ '.$this->tab['art'].' AS b,
+ '.$this->tab['cat_art'].' AS c
+ WHERE
+ c.idcat = '.$idcat.' AND
+ b.idclient = '.$this->client.' AND
+ b.idart = c.idart AND
+ a.idart = b.idart AND
+ '.$sArtSpecs.'
+ a.idlang = '.$this->lang.'';
+ }
+
+ if (!$this->offline) {
+ $sql .= ' AND a.online = 1 ';
+ }
+
+ $sql .= ' ORDER BY a.'.$this->order.' '.$this->direction.'';
+
+ $this->db->query($sql);
+
+ if ($cfg["is_start_compatible"] == false) {
+ $db2 = new DB_ConLite();
+ $sql = "SELECT startidartlang FROM ".$cfg["tab"]["cat_lang"]." WHERE idcat='".$idcat."' AND idlang='".$this->lang."'";
+ $db2->query($sql);
+ $db2->next_record();
+
+ $startidartlang = $db2->f("startidartlang");
+
+ if ($startidartlang != 0) {
+ $sql = "SELECT idart FROM ".$cfg["tab"]["art_lang"]." WHERE idartlang='".$startidartlang."'";
+ $db2->query($sql);
+ $db2->next_record();
+ $this->startId = $db2->f("idart");
+ }
+ }
+
+ while ($this->db->next_record()) {
+ if ($cfg["is_start_compatible"] == true) {
+ if ($this->db->f('is_start') == 1) {
+ $this->startId = $this->db->f('idart');
+
+ if ($this->start) {
+ $this->articles[] = $this->db->f('idart');
+ }
+ } else {
+ $this->articles[] = $this->db->f('idart');
+ }
+ } else {
+ if ($this->db->f("idart") == $this->startId) {
+ if ($this->start) {
+ $this->articles[] = $this->db->f('idart');
+ }
+ } else {
+ $this->articles[] = $this->db->f('idart');
+ }
+ }
+ }
+
+ $this->count = count($this->articles);
+ }
+
+ /**
+ * Iterate to the next article, return object of type Contenido Article Object
+ * if an article is found. False otherwise.
+ *
+ * @param none
+ *
+ * @return object Contenido Article Object
+ */
+ public function nextArticle()
+ {
+ $limit = true;
+ if ($this->limit > 0) {
+ if ($this->cnt >= $this->limit)
+ $limit = false;
+ }
+ if ($this->cnt < count($this->articles) AND $limit) {
+ $idart = $this->articles[$this->cnt];
+
+ if (is_numeric($idart)) {
+ $this->cnt ++;
+ return new Article($idart, $this->client, $this->lang);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return ONLY the Start-Article
+ *
+ * @param none
+ * @return object Contenido Article Object
+ * @access public
+ */
+ public function startArticle()
+ {
+ return new Article($this->startId, $this->client, $this->lang);
+ }
+
+ /**
+ * Split the article results into pages of a given size.
+ *
+ * Example:
+ * Article Collection with 5 articles
+ *
+ * [0] => 250
+ * [1] => 251
+ * [2] => 253
+ * [3] => 254
+ * [4] => 255
+ *
+ * $collection->setResultPerPage(2)
+ *
+ * Would split the results into 3 pages
+ *
+ * [0] => [0] => 250
+ * [1] => 251
+ * [1] => [0] => 253
+ * [1] => 254
+ * [2] => [0] => 255
+ *
+ * A page can be selected with
+ *
+ * $collection->setPage(int page)
+ *
+ * @param int $resPerPage
+ * @return void
+ * @access public
+ */
+ public function setResultPerPage($resPerPage)
+ {
+ $this->iResultPerPage = $resPerPage;
+
+ if ($this->iResultPerPage > 0) {
+ if (is_array($this->articles)) {
+ $this->aPages = array_chunk($this->articles, $this->iResultPerPage);
+ $this->iCountPages = count($this->aPages);
+ } else {
+ $this->aPages = array();
+ $this->iCountPages = 0;
+ }
+ }
+ }
+
+ /**
+ * Select a page if the results was divided before.
+ *
+ * $collection->setResultsPerPage(2);
+ * $collection->setPage(1);
+ *
+ * // Iterate through all articles of page two
+ * while ($art = $collection->nextArticle())
+ * { ... }
+ *
+ * @param int $iPage The page of the article collection
+ * @return void
+ * @access public
+ */
+ public function setPage($iPage)
+ {
+ if (is_array($this->aPages[$iPage])) {
+ $this->articles = $this->aPages[$iPage];
+ }
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.artspec.php b/conlite/classes/class.artspec.php
new file mode 100644
index 0000000..e80a118
--- /dev/null
+++ b/conlite/classes/class.artspec.php
@@ -0,0 +1,85 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting
+ *
+ * $Id: class.artspec.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class ArtSpecCollection extends ItemCollection
+{
+ /**
+ * Constructor Function
+ * @param none
+ */
+ public function __construct()
+ {
+ global $cfg;
+ parent::__construct($cfg['tab']['art_spec'], "idartspec");
+ $this->_setItemClass("ArtSpecItem");
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function ArtSpecCollection()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+}
+
+
+/**
+ * Article specification Item
+ */
+class ArtSpecItem extends Item
+{
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false)
+ {
+ global $cfg;
+ parent::__construct($cfg['tab']['art_spec'], "idartspec");
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function ArtSpecItem($mId = false)
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct($mId);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.autoload.php b/conlite/classes/class.autoload.php
new file mode 100644
index 0000000..2614e5e
--- /dev/null
+++ b/conlite/classes/class.autoload.php
@@ -0,0 +1,288 @@
+
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since CONTENIDO release 4.9.0
+ *
+ * {@internal
+ * created 2010-12-27
+ * $Id: class.autoload.php 390 2015-11-09 21:02:55Z oldperl $:
+ * }}
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class cAutoload {
+
+ const ERROR_FILE_NOT_FOUND = 'file_not_found';
+ const ERROR_CLASS_EXISTS = 'class_exists';
+
+ /**
+ * CONTENIDO root path. Path to the folder which contains the CONTENIDO installation.
+ *
+ * @var string
+ */
+ private static $_conRootPath = null;
+
+ /**
+ * Array of interface/class names with related files to include
+ *
+ * @var array
+ */
+ private static $_includeFiles = null;
+
+ /**
+ * Flag containing initialized status
+ *
+ * @var bool
+ */
+ private static $_initialized = null;
+
+ /**
+ * Array to store loaded classnames and the paths to the class files.
+ * $_loadedClasses['classname'] = '/path/to/the/class.php';
+ *
+ * @var array
+ */
+ private static $_loadedClasses = array();
+
+ /**
+ * Array to store invalid classnames and the paths to the class files.
+ * $_errors[pos] = array('class' => classname, 'file' => file, 'error' => errorType);
+ *
+ * @var array
+ */
+ private static $_errors = array();
+
+ /**
+ * Initialization of CONTENIDO autoloader, is to call at least once.
+ *
+ * Registers itself as a __autoload implementation, includes the class map file,
+ * and if exists, the user defined class map file, containing the includes.
+ *
+ * @param array $cfg The CONTENIDO cfg array
+ * @return void
+ */
+ public static function initialize(array $cfg) {
+ if (self::$_initialized == true) {
+ return;
+ }
+
+ self::$_initialized = true;
+ self::$_conRootPath = str_replace('\\', '/', realpath($cfg['path']['contenido'] . '/../')) . '/';
+
+ spl_autoload_register(array(__CLASS__, 'autoload'));
+
+ // load n' store autoloader class map file
+ $file = $cfg['path']['config'] . 'config.autoloader.php';
+ if ($arr = include_once($file)) {
+ self::$_includeFiles = $arr;
+ }
+
+ // load n' store additional autoloader class map file, if exists
+ $file = $cfg['path']['config'] . 'config.autoloader.local.php';
+ if (is_file($file)) {
+ self::addClassmapConfigFile($file);
+ }
+ }
+
+ /**
+ * Adding additional autoloader class map configuration.
+ * NOTE:
+ * Since this autoloader is implemented for CONTENIDO, it doesn't support to
+ * load classfiles being located outside of the CONTENIDO installation folder.
+ *
+ * @param array $config Assoziative class map array as follows:
+ *
+ * // Structure is: "Classname" => "Path to classfile from CONTENIDO installation folder"
+ * $config = array(
+ * 'myPluginsClass' => 'contenido/plugins/myplugin/classes/class.myPluginClass.php',
+ * 'myPluginsOtherClass' => 'contenido/plugins/myplugin/classes/class.myPluginsOtherClass.php',
+ * );
+ *
+ * @return void
+ */
+ public static function addClassmapConfig(array $config) {
+ self::$_includeFiles = array_merge(self::$_includeFiles, $config);
+ }
+
+ /**
+ * Adding additional autoloader class map configuration file.
+ * NOTE:
+ * Since this autoloader is implemented for CONTENIDO, it doesn't support to
+ * load classfiles being located outside of the CONTENIDO installation folder.
+ *
+ * @param string $configFile Full path to class map configuration file.
+ * The provided file must return a class map configuration array as follows:
+ *
+ * // Structure is: "Classname" => "Path to classfile from CONTENIDO installation folder"
+ * return array(
+ * 'myPluginsClass' => 'contenido/plugins/myplugin/classes/class.myPluginClass.php',
+ * 'myPluginsOtherClass' => 'contenido/plugins/myplugin/classes/class.myPluginsOtherClass.php',
+ * 'myCmsClass' => 'cms/includes/class.myCmsClass.php',
+ * );
+ *
+ * @return void
+ */
+ public static function addClassmapConfigFile($configFile) {
+ if (is_file($configFile)) {
+ if ($arr = include_once($configFile)) {
+ if(is_array($arr)) {
+ self::addClassmapConfig($arr);
+ }
+ }
+ }
+ }
+
+ /**
+ * The main __autoload() implementation.
+ * Tries to include the file of passed classname.
+ *
+ * @param string $className The classname
+ * @return void
+ * @throws Exception If autoloader wasn't initialized before
+ */
+ public static function autoload($className) {
+ if (self::$_initialized !== true) {
+ throw new Exception("Autoloader has to be initialized by calling method initialize()");
+ }
+
+ if (isset(self::$_loadedClasses[$className])) {
+ return;
+ }
+
+ $file = '';
+
+ if ($file = self::_getContenidoClassFile($className)) {
+ // load class file from class map
+ self::_loadFile($file);
+ }
+
+ self::$_loadedClasses[$className] = str_replace(self::$_conRootPath, '', $file);
+ }
+
+ /**
+ * Checks, if passed filename is a file, which will be included by the autoloader.
+ *
+ * @param string $file Filename or Filename with a part of the path, e. g.
+ * - class.foobar.php
+ * - classes/class.foobar.php
+ * - contenido/classes/class.foobar.php
+ * @return bool
+ */
+ public static function isAutoloadable($file) {
+ foreach (self::$_includeFiles as $className => $includeFile) {
+ if (strpos($includeFile, $file) !== false) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the loaded classes (@see cAutoload::$_loadedClasses)
+ *
+ * @return array
+ */
+ public static function getLoadedClasses() {
+ return self::$_loadedClasses;
+ }
+
+ /**
+ * Returns the errorlist containing invalid classes (@see cAutoload::$_errors)
+ *
+ * @return array
+ */
+ public static function getErrors() {
+ return self::$_errors;
+ }
+
+ /**
+ * Returns the path to a CONTENIDO class file by processing the given classname
+ *
+ * @param string $className
+ * @return (string|null) Path and filename or null
+ */
+ private static function _getContenidoClassFile($className) {
+ $file = isset(self::$_includeFiles[$className]) ? self::$_conRootPath . self::$_includeFiles[$className] : null;
+ return self::_validateClassAndFile($className, $file);
+ }
+
+ /**
+ * Validates the given class and the file
+ *
+ * @param string $className
+ * @param string $filePathName
+ * @return (string|null) The file if validation was successfull, otherwhise null
+ */
+ private static function _validateClassAndFile($className, $filePathName) {
+ if (class_exists($className)) {
+ self::$_errors[] = array(
+ 'class' => $className,
+ 'file' => str_replace(self::$_conRootPath, '', $filePathName),
+ 'error' => self::ERROR_CLASS_EXISTS
+ );
+ return null;
+ } elseif (!is_file($filePathName)) {
+ self::$_errors[] = array(
+ 'class' => $className,
+ 'file' => str_replace(self::$_conRootPath, '', $filePathName),
+ 'error' => self::ERROR_FILE_NOT_FOUND
+ );
+ return null;
+ }
+
+ return $filePathName;
+ }
+
+ /**
+ * Loads the desired file by invoking require_once method
+ *
+ * @param string $filePathName
+ * @param bool $beQuiet Flag to prevent thrown warnings/errors by using
+ * the error control operator @
+ * @return void
+ */
+ private static function _loadFile($filePathName, $beQuiet = false) {
+ if ($beQuiet) {
+ @require_once($filePathName);
+ } else {
+ require_once($filePathName);
+ }
+ }
+
+}
diff --git a/conlite/classes/class.backend.php b/conlite/classes/class.backend.php
new file mode 100644
index 0000000..f63c195
--- /dev/null
+++ b/conlite/classes/class.backend.php
@@ -0,0 +1,378 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ *
+ * $Id: class.backend.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class Contenido_Backend {
+
+ /**
+ * Debug flag
+ */
+ var $debug = 0;
+
+ /**
+ * Possible actions
+ * @var array
+ */
+ var $actions = array();
+
+ /**
+ * Files
+ * @var array
+ */
+ var $files = array();
+
+ /**
+ * Stores the frame number
+ * @var int
+ */
+ var $frame = 0;
+
+ /**
+ * Errors
+ * @var array
+ */
+ var $errors = array();
+
+ /**
+ * Save area
+ * @var string
+ */
+ var $area = '';
+
+ /**
+ * Constructor
+ */
+ function Contenido_Backend() {
+ # do nothing
+ } # end function
+
+ /**
+ * Set the frame number
+ * in which the file is
+ * loaded
+ * @return void
+ */
+ function setFrame($frame_nr = 0) {
+ $frame_nr = Contenido_Security::toInteger($frame_nr);
+ $this->frame = $frame_nr;
+
+ } # end function
+
+
+ /**
+ * Loads all required data
+ * from the DB and stores it
+ * in the $actions and $files array
+ *
+ * @param $area string selected area
+ * @return
+ */
+ function select($area) {
+ # Required global vars
+ global $cfg, $client, $lang, $db, $perm, $action, $idcat;
+ global $idcat, $idtpl, $idmod, $idlay;
+
+ if (isset($idcat)) {
+ $itemid = $idcat;
+ } elseif (isset($idtpl)) {
+ $itemid = $idtpl;
+ } elseif (isset($idmod)) {
+ $itemid = $idmod;
+ } elseif (isset($idlay)) {
+ $itemid = $idlay;
+ } else {
+ $itemid = 0;
+ }
+
+ $itemid = Contenido_Security::toInteger($itemid);
+ $area = Contenido_Security::escapeDB($area, $db);
+
+ # Store Area
+ $this->area = $area;
+
+ # extract actions
+ $sql = "SELECT
+ b.name AS name,
+ b.code AS code,
+ b.relevant as relevant_action,
+ a.relevant as relevant_area
+ FROM
+ ".$cfg["tab"]["area"]." AS a,
+ ".$cfg["tab"]["actions"]." AS b
+ WHERE
+ a.name = '".$area."' AND
+ b.idarea = a.idarea AND
+ a.online = '1'";
+
+ # Check if the user has
+ # access to this area.
+ # Yes -> Grant him all actions
+ # No -> Grant him only action
+ # which are irrelevant
+ # = (Field 'relevant' is 0)
+
+ if (!$perm->have_perm_area_action($area)) {
+ $sql .= " AND a.relevant = '0'";
+ }
+
+ $db->query($sql);
+
+ while ($db->next_record()) {
+
+ # Save the action only access to
+ # the desired action is granted.
+ # If this action is relevant for rights
+ # check if the user has permission to
+ # execute this action
+
+ if ($db->f("relevant_action") == 1 && $db->f("relevant_area") == 1) {
+
+ if ($perm->have_perm_area_action_item($area, $db->f("name"), $itemid)) {
+ $this->actions[$area][$db->f('name')] = $db->f('code');
+ }
+
+ if ($itemid == 0) {
+ // itemid not available, since its impossible the get the correct rights out
+ // we only check if userrights are given for these three items on any item
+ if ($action=="mod_edit" || $action=="tpl_edit" || $action=="lay_edit") {
+ if ($perm->have_perm_area_action_anyitem($area, $db->f("name"))) {
+ $this->actions[$area][$db->f('name')] = $db->f('code');
+ }
+ }
+ }
+
+ } else {
+ $this->actions[$area][$db->f('name')] = $db->f('code');
+
+ }
+
+
+ } # end while
+
+ $sql = "SELECT
+ b.filename AS name,
+ b.filetype AS type,
+ a.parent_id AS parent_id
+ FROM
+ ".$cfg['tab']['area']." AS a,
+ ".$cfg['tab']['files']." AS b,
+ ".$cfg['tab']['framefiles']." AS c
+ WHERE
+ a.name = '".$area."' AND
+ b.idarea = a.idarea AND
+ b.idfile = c.idfile AND
+ c.idarea = a.idarea AND
+ c.idframe = '".$this->frame."' AND
+ a.online = '1'";
+
+ # Check if the user has
+ # access to this area.
+ # Yes -> Extract all files
+ # No -> Extract only irrelevant
+ # Files = (Field 'relevant' is 0)
+ if (!$perm->have_perm_area_action($area)) {
+ $sql .= " AND a.relevant = '0'";
+ }
+ $sql .= " ORDER BY b.filename";
+
+ $db->query($sql);
+
+ while ($db->next_record()) {
+
+ # Test if entry is a plug-in.
+ # If so don't add the Include path
+ if (strstr($db->f('name'), "/")) {
+ $filepath = $cfg["path"]["plugins"] . $db->f('name');
+ } else {
+ $filepath = $cfg["path"]["includes"] . $db->f('name');
+ }
+
+ # If filetype is Main AND
+ # parent_id is 0 file is
+ # a sub file
+ if ($db->f('parent_id') != 0 && $db->f('type') == 'main'){
+ $this->files['sub'][] = $filepath;
+ }
+
+ $this->files[$db->f('type')][] = $filepath;
+ } # end while
+
+ if ($this->debug) {
+ echo '';
+ echo "Na, wieder scheisse gebaut?? ;-) \n\n";
+ echo "Files: \n\n";
+ print_r($this->files);
+ echo "\n\nActions: \n\n";
+ print_r($this->actions[$this->area]);
+ echo "\n\nInformation: \n\n";
+ echo "Area: $area\n";
+ echo "Action: $action\n";
+ echo "Client: $client\n";
+ echo "Lang: $lang\n";
+ echo ' ';
+ }
+
+
+ } # end function
+
+ /**
+ * Checks if choosen action exists.
+ * If so, execute/eval it.
+ *
+ * @param $action String Action to execute
+ * @return $action String Code for selected Action
+ */
+ function getCode($action) {
+ global $notification;
+
+ if (isset($this->actions[$this->area][$action])) {
+
+ return ($this->actions[$this->area][$action]);
+
+ } else {
+
+ # There is no action or
+ # user has no access to
+ # it
+ }
+
+ } # end function
+
+ /**
+ * Returns the specified file path.
+ * Distinction between 'inc' and 'main'
+ * files.
+ *
+ * 'inc' => Required file like functions/classes etc.
+ * 'main' => Main file
+ *
+ * @param $which String 'inc' / 'main'
+ */
+ function getFile($which) {
+
+ if (isset($this->files[$which])) {
+
+ return $this->files[$which];
+
+ } else {
+
+ # There is no action or
+ # user has no access to
+ # it
+ }
+
+ } # end function
+
+
+ /**
+ * Creates a log entry for the specified parameters.
+ *
+ * @param $idcat Category-ID
+ * @param $idart Article-ID
+ * @param $client Client-ID
+ * @param $lang Language-ID
+ * @param $action Action (ID or canonical name)
+ */
+ function log($idcat, $idart, $client, $lang, $idaction) {
+ global $perm, $auth, $cfg, $classarea, $area;
+
+ $db_log = new DB_ConLite;
+
+ $lastentry = $db_log->nextid($cfg["tab"]["actionlog"]);
+
+ $timestamp = date("Y-m-d H:i:s");
+ $idcatart = "0";
+
+ $idcat = Contenido_Security::toInteger($idcat);
+ $idart = Contenido_Security::toInteger($idart);
+ $client = Contenido_Security::toInteger($client);
+ $lang = Contenido_Security::toInteger($lang);
+ $idaction = Contenido_Security::escapeDB($idaction, $db_log);
+ $area = Contenido_Security::escapeDB($area, $db_log);
+
+ if (!Contenido_Security::isInteger($client)) { return; }
+ if (!Contenido_Security::isInteger($lang)) { return; }
+
+ if (isset($idcat) && isset($idart) && $idcat != "" && $idart != "")
+ {
+ $sql = "SELECT idcatart
+ FROM
+ ". $cfg["tab"]["cat_art"] ."
+ WHERE
+ idcat = '".$idcat."' AND
+ idart = '".$idart."'";
+
+ $db_log->query($sql);
+
+ $db_log->next_record();
+ $idcatart = $db_log->f("idcatart");
+ }
+
+ $oldaction = $idaction;
+ $idaction = $perm->getIDForAction($idaction);
+
+ if ($idaction != "")
+ {
+ $sql = "INSERT INTO
+ ". $cfg["tab"]["actionlog"]."
+ SET
+ idlog = '".$lastentry."',
+ user_id = '".$auth->auth["uid"]."',
+ idclient = '".$client."',
+ idlang = '".$lang."',
+ idaction = '".$idaction."',
+ idcatart = '".$idcatart."',
+ logtimestamp = '".$timestamp."'";
+
+ } else {
+ echo $oldaction. " is not in the actions table! ";
+ echo "Use the following statement to insert it with minimal functionsinto the actions table: ";
+ echo "";
+ $myareaid = $classarea->getAreaID($area);
+
+ $sql = "SELECT max(idaction) FROM " . $cfg["tab"]["actions"];
+ $db_log->query($sql);
+ $db_log->next_record();
+
+ $mynextid = $db_log->f(0) + 1;
+
+
+ echo "INSERT INTO ". $cfg["tab"]["actions"]."
+ SET idaction = '".$mynextid."', idarea = '".$myareaid."', name = '".$oldaction."', relevant = '1'";
+ echo "
";
+
+ }
+ $db_log->query($sql);
+ }
+} # end class Contenido_Backend
+?>
diff --git a/conlite/classes/class.cat.php b/conlite/classes/class.cat.php
new file mode 100644
index 0000000..27fbc51
--- /dev/null
+++ b/conlite/classes/class.cat.php
@@ -0,0 +1,73 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ *
+ * $Id: class.cat.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class Cat {
+
+ /**
+ * Constructor Function
+ * @param
+ */
+ function Cat() {
+ // empty
+ } // end function
+
+ /**
+ * getCatName()
+ * Returns a name for the given category
+ * @return string Returns the name of the given category
+ */
+ function getCatName($category, $idlang) {
+ global $cfg;
+
+ $db = new DB_ConLite;
+ $idlang = Contenido_Security::toInteger($idlang);
+ $category = Contenido_Security::toInteger($category);
+
+ $sql = "SELECT
+ name
+ FROM
+ ". $cfg["tab"]["cat_lang"] ."
+ WHERE
+ idlang = '".$idlang."' AND
+ idcat = '".$category."'";
+
+ $db->query($sql);
+ $db->next_record();
+
+ return ($db->f("name"));
+
+ } // end function
+
+} // end class
+?>
diff --git a/conlite/classes/class.category.php b/conlite/classes/class.category.php
new file mode 100644
index 0000000..e2b570c
--- /dev/null
+++ b/conlite/classes/class.category.php
@@ -0,0 +1,138 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting
+ *
+ * $Id: class.category.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class CategoryCollection extends ItemCollection
+{
+ public function __construct()
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["cat"], "idcat");
+ $this->_setItemClass("CategoryItem");
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function CategoryCollection()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+}
+
+
+class CategoryItem extends Item
+{
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false)
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["cat"], "idcat");
+ $this->setFilters(array(), array());
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function CategoryItem($mId = false)
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+
+ public function loadByPrimaryKey($key)
+ {
+ if (parent::loadByPrimaryKey($key)) {
+ // Load all child language items
+ $catlangs = new CategoryLanguageCollection();
+ $catlangs->select("idcat = '$key'");
+
+ while ($item = $catlangs->next()) {
+ $this->lang[$item->get("idlang")] = $item;
+ }
+ return true;
+ }
+ return false;
+ }
+}
+
+
+class CategoryLanguageCollection extends ItemCollection
+{
+ public function __construct()
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["cat_lang"], "idcatlang");
+ $this->_setItemClass("CategoryLanguageItem");
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function CategoryLanguageCollection()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+}
+
+
+class CategoryLanguageItem extends Item
+{
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false)
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["cat_lang"], "idcatlang");
+ $this->setFilters(array(), array());
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function CategoryLanguageItem($mId = false)
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct($mId);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.cec.php b/conlite/classes/class.cec.php
new file mode 100644
index 0000000..e7e4a0d
--- /dev/null
+++ b/conlite/classes/class.cec.php
@@ -0,0 +1,539 @@
+
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2008-08-28, Murat Purc, add singleton pattern feature
+ * modified 2009-12-30, Murat Purc, redesign of cApiCECRegistry and pApiCECChainItem bearing in mind of
+ * downwards compatibility and documenting the code, see [#CON-291], also regards to [#CON-256]
+ *
+ * $Id: class.cec.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+/**
+ * CEC registry class. Used to register chains and chain functions to invoke.
+ *
+ * Following 3 types of CEC functions/callbacks are supported at the moment:
+ * - Callbacks, which should only be invoked. They don't return a value and have no
+ * break conditions, @see CEC_Hook::execute()
+ * - Callbacks, which should return a value and/or should modify a passed parameter,
+ * @see CEC_Hook::executeAndReturn()
+ * - Callbacks, which should be processed untill a defined break condition achieves,
+ * @see CEC_Hook::executeWhileBreakCondition()
+ *
+ * @author Timo A. Hummel
+ * @author Murat Purc
+ * @package Contenido Backend classes
+ * @subpackage CEC
+ */
+class cApiCECRegistry
+{
+ /**
+ * List of available chains
+ * @var array
+ */
+ private $_aChains;
+
+ /**
+ * Self instance
+ * @var cApiCECRegistry
+ */
+ private static $_instance = null;
+
+
+ /**
+ * Constructor
+ *
+ * @return void
+ */
+ protected function __construct()
+ {
+ $this->_aChains = array();
+ }
+
+
+ /**
+ * Prevent cloning
+ *
+ * @return void
+ */
+ private function __clone()
+ {
+ // donut
+ }
+
+
+ /**
+ * Returns a instance of cApiCECRegistry
+ *
+ * @return cApiCECRegistry
+ */
+ public static function getInstance()
+ {
+ if (self::$_instance == null) {
+ self::$_instance = new cApiCECRegistry();
+ }
+ return self::$_instance;
+ }
+
+
+ /**
+ * Registers a chain (adds the chain to the internal chain holder)
+ *
+ * @param string $sChainName
+ * @param mixed First chain parameter
+ * @param mixed Second chain parameter
+ * @param mixed Third chain parameter...
+ * NOTE: The number of parameter is not restricted, you can pass parameter as
+ * much as you want.
+ * @return void
+ */
+ public function registerChain($sChainName)
+ {
+ $aParam = array();
+ $iNumArgs = func_num_args();
+
+ for ($iCount = 0; $iCount < $iNumArgs; $iCount++) {
+ $aParam[$iCount] = func_get_arg($iCount);
+ }
+
+ $this->_addChain($sChainName, $aParam);
+ }
+
+
+ /**
+ * Unregisters a chain
+ *
+ * @param string $sChainName
+ * @return void
+ */
+ public function unregisterChain($sChainName)
+ {
+ // Check if the chain exists
+ if (!$this->isChainRegistered($sChainName)) {
+ cWarning(__FILE__, __LINE__, "Chain " . $sChainName . " doesn't exist.");
+ return false;
+ }
+
+ $functions = array();
+ $this->_resetIterator($sChainName);
+ $chainFunctions = $this->_aChains[$sChainName]['functions'];
+ foreach ($chainFunctions as $pos => $item) {
+ $functions[] = $item->getFunctionName();
+ }
+
+ foreach ($functions as $p => $func) {
+ $this->removeChainFunction($sChainName, $func);
+ }
+
+ unset($this->_aChains[$sChainName]);
+ }
+
+
+ /**
+ * Checks if a chain is registered or not.
+ *
+ * @param string $sChainName
+ * @return bool
+ */
+ public function isChainRegistered($sChainName)
+ {
+ return (isset($this->_aChains[$sChainName]));
+ }
+
+
+ /**
+ * Returns list of registered chain names
+ *
+ * @return array
+ */
+ public function getRegisteredChainNames()
+ {
+ return array_keys($this->_aChains);
+ }
+
+
+ /**
+ * Adds the chain to the internal chain holder
+ *
+ * @param string $sChainName Chain name
+ * @param array $aParameters Chain parameter
+ * @return void
+ */
+ protected function _addChain($sChainName, array $aParameters = array())
+ {
+ $this->_aChains[$sChainName]['parameters'] = $aParameters;
+ $this->_aChains[$sChainName]['functions'] = array();
+ }
+
+
+ /**
+ * Adds a chain function which is to invoke.
+ *
+ * @param string $sChainName Chain name
+ * @param string $sFunctionName Name of function/callback to invoke. Feasible values are:
+ * - "ClassName->methodName" to invoke a method of a ClassName instance.
+ * A instance of the clas will be created here.
+ * - "ClassName::methodName" to invoke a static method of ClassName.
+ * - "FunctionName" to invoke a function.
+ * NOTE: Necessary files must be manually included before or by defined autoloader.
+ * @return bool True on success, otherwhise false
+ */
+ public function addChainFunction($sChainName, $sFunctionName)
+ {
+ // Check if the chain exists
+ if (!$this->isChainRegistered($sChainName)) {
+ cWarning(__FILE__, __LINE__, "Chain " . $sChainName . " doesn't exist.");
+ return false;
+ }
+
+ if (strpos($sFunctionName, '->') > 0) {
+ // chain function is a method of a object instance
+ list($class, $method) = explode('->', $sFunctionName);
+ if (!class_exists($class)) {
+ cWarning(__FILE__, __LINE__, "Class " . $class . " doesn't exist, can't add " . $sFunctionName . " to chain " . $sChainName);
+ return false;
+ } elseif (!method_exists($class, $method)) {
+ cWarning(__FILE__, __LINE__, "Method " . $method . " in class " . $class . " doesn't exist, can't add " . $sFunctionName . " to chain " . $sChainName);
+ return false;
+ }
+ $call = array(new $class(), $method);
+ } elseif (strpos($sFunctionName, '::') > 0) {
+ // chain function is static method of a object
+ list($class, $method) = explode('::', $sFunctionName);
+ if (!class_exists($class)) {
+ cWarning(__FILE__, __LINE__, "Class " . $class . " doesn't exist, can't add " . $sFunctionName . " to chain " . $sChainName);
+ return false;
+ } elseif (!method_exists($class, $method)) {
+ cWarning(__FILE__, __LINE__, "Method " . $method . " in class " . $class . " doesn't exist, can't add " . $sFunctionName . " to chain " . $sChainName);
+ return false;
+ }
+ $call = array($class, $method);
+ } else {
+ // chain function is a function
+ if (!function_exists($sFunctionName)) {
+ cWarning(__FILE__, __LINE__, "Function " . $sFunctionName . " doesn't exist, can't add to chain " . $sChainName);
+ return false;
+ }
+ $call = $sFunctionName;
+ }
+
+ // Last check if the callback is callable
+ if (!is_callable($call)) {
+ cWarning(__FILE__, __LINE__, "Function " . $sFunctionName . " isn't callable, can't add to chain " . $sChainName);
+ return false;
+ }
+
+ $oChainItem = new pApiCECChainItem($sChainName, $sFunctionName, $this->_aChains[$sChainName]['parameters']);
+ $oChainItem->setCallback($call);
+ array_push($this->_aChains[$sChainName]['functions'], $oChainItem);
+
+ return true;
+ }
+
+
+ /**
+ * Checks if a chain function exists.
+ *
+ * @param string $sChainName Chain name
+ * @param string $sFunctionName Name of function to check
+ * @return bool
+ */
+ public function chainFunctionExists($sChainName, $sFunctionName)
+ {
+ if (!$this->isChainRegistered($sChainName)) {
+ return false;
+ }
+
+ $this->_resetIterator($sChainName);
+ $chainFunctions = $this->_aChains[$sChainName]['functions'];
+ foreach ($chainFunctions as $pos => $item) {
+ if ($item->getFunctionName() == $sFunctionName) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Removes a chain function.
+ *
+ * @param string $sChainName Chain name
+ * @param string $sFunctionName Name of function to remove from chain.
+ */
+ public function removeChainFunction($sChainName, $sFunctionName)
+ {
+ if (!$this->isChainRegistered($sChainName)) {
+ return;
+ }
+
+ $this->_resetIterator($sChainName);
+ $chainFunctions = $this->_aChains[$sChainName]['functions'];
+ foreach ($this->_aChains[$sChainName]['functions'] as $pos => $item) {
+ if ($item->getFunctionName() == $sFunctionName) {
+ unset($this->_aChains[$sChainName]['functions'][$pos]);
+ return;
+ }
+ }
+ }
+
+
+ /**
+ * Returns the iterator for a desired chain.
+ *
+ * @TODO: cIterator should be replaced by ArrayIterator (@see http://www.php.net/spl)
+ * but ArrayIterator uses rewind() instead of reset()...
+ *
+ * @param string $sChainName Chain name
+ * @return cIterator
+ */
+ public function getIterator($sChainName)
+ {
+ return new cIterator($this->_aChains[$sChainName]['functions']);
+ }
+
+
+ /**
+ * Resets the chain iterator.
+ *
+ * @param string $sChainName
+ * @return void
+ */
+ protected function _resetIterator($sChainName)
+ {
+ $iterator = $this->getIterator($sChainName);
+ $iterator->reset();
+ }
+
+}
+
+
+/**
+ * CEC chain item class.
+ *
+ * @author Timo A. Hummel
+ * @author Murat Purc
+ * @package Contenido Backend classes
+ * @subpackage CEC
+ */
+class pApiCECChainItem
+{
+ /**
+ * Chain name
+ * @var string
+ */
+ protected $_sChainName;
+
+ /**
+ * Name of function to invoke
+ * @var string
+ */
+ protected $_sFunctionName;
+
+ /**
+ * Callback name. Contains either the function name to invoke, or a indexed array (class/object and method)
+ * and it's method to execute.
+ * @var array|string
+ */
+ protected $_mCallback;
+
+ /**
+ * Parameter to pass to the function
+ * @var array
+ */
+ protected $_aParameters;
+
+
+ /**
+ * Temporary arguments holder
+ * @var array|null
+ */
+ protected $_mTemporaryArguments;
+
+
+ /**
+ * Constructor, sets the CEC chain item properties.
+ *
+ * @param string $sChainName
+ * @param string $sFunctionName
+ * @param array $aParameters
+ * @return void
+ */
+ public function __construct($sChainName, $sFunctionName, $aParameters)
+ {
+ $this->setChainName($sChainName);
+ $this->setFunctionName($sFunctionName);
+ $this->setParameters($aParameters);
+ $this->setCallback($this->getFunctionName());
+ }
+
+
+ /**
+ * Sets the chain name
+ *
+ * @param string $sChainName
+ * @return void
+ */
+ public function setChainName($sChainName)
+ {
+ $this->_sChainName = $sChainName;
+ }
+
+
+ /**
+ * Returns the chain name
+ *
+ * @return string
+ */
+ public function getChainName()
+ {
+ return $this->_sChainName;
+ }
+
+
+ /**
+ * Sets the function name
+ *
+ * @param string $sFunctionName
+ * @return void
+ */
+ public function setFunctionName($sFunctionName)
+ {
+ $this->_sFunctionName = $sFunctionName;
+ }
+
+
+ /**
+ * Returns the function name
+ *
+ * @return string
+ */
+ public function getFunctionName()
+ {
+ return $this->_sFunctionName;
+ }
+
+
+ /**
+ * Sets the callback parameters
+ *
+ * @param array $aParameters
+ * @return void
+ */
+ public function setParameters(array $aParameters)
+ {
+ $this->_aParameters = $aParameters;
+ }
+
+
+ /**
+ * Returns the function name
+ *
+ * @return array
+ */
+ public function getParameters()
+ {
+ return $this->_aParameters;
+ }
+
+
+ /**
+ * Sets the callback
+ *
+ * @return string|array
+ */
+ public function setCallback($callback)
+ {
+ if (is_string($callback) || is_array($callback)) {
+ $this->_mCallback = $callback;
+ } else {
+ throw new Exception("Passed argument isn't as expected");
+ }
+ }
+
+
+ /**
+ * Returns the callback
+ *
+ * @return string|array
+ */
+ public function getCallback()
+ {
+ return $this->_mCallback;
+ }
+
+
+ /**
+ * Another way to set the arguments before invoking execute() method.
+ *
+ * @param array $args
+ * @return void
+ */
+ public function setTemporaryArguments(array $args=array())
+ {
+ $this->_mTemporaryArguments = $args;
+ }
+
+ /**
+ * Will be invoked by execute() method. If temporary arguments where set before,
+ * it returns them and resets the property.
+ *
+ * @param array $args
+ * @return void
+ */
+ public function getTemporaryArguments()
+ {
+ $args = $this->_mTemporaryArguments;
+ $this->_mTemporaryArguments = null;
+ return $args;
+
+ }
+
+
+ /**
+ * Invokes the CEC function/callback.
+ *
+ * @return mixed If available, the result of the CEC function/callback
+ */
+ public function execute()
+ {
+ // get temporary arguments, if the where set before
+ if (!$args = $this->getTemporaryArguments()) {
+ // no temporary arguments available, get them by func_get_args()
+ $args = func_get_args();
+ }
+ return call_user_func_array($this->getCallback(), $args);
+ }
+
+}
diff --git a/conlite/classes/class.cec_hook.php b/conlite/classes/class.cec_hook.php
new file mode 100644
index 0000000..adb61e9
--- /dev/null
+++ b/conlite/classes/class.cec_hook.php
@@ -0,0 +1,423 @@
+
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release >= 4.8.8
+ *
+ * {@internal
+ * created 2008-08-28, Murat Purc, initial implementation, port from Advanced Mod Rewrite Plugin
+ * modified 2008-09-10, Murat Purc, bugfix: add further condition handling to prevent overwriting of arguments
+ * modified 2008-11-11, Andreas Lindner, when overwriting of arguments is prevented and break condition is set
+ * added anoption to return break condition value directly, otherwise the args would be returned, which is not
+ * desirable under all circumstances
+ * modified 2008-12-26, Murat Purc, bugfix: Not each registered chain function will get the same parameter
+ * modified 2009-12-26, Murat Purc, bugfix/redesign of CEC_Hook, see [#CON-256]
+ *
+ * }}
+ *
+ */
+
+
+/**
+ * Static CEC Hook class, provides some public methods to process registered chains
+ * at CEC (Contenido Extension Chainer).
+ *
+ * Usage:
+ *
+ * // example of executing a cec without a parameter and return value
+ * CEC_Hook::execute('Contenido.Content.Somewhere');
+ *
+ * // example of executing a cec with a parameter but without a return value
+ * $param = 'some value';
+ * CEC_Hook::execute('Contenido.Content.Somewhere', $param);
+ *
+ * // example of executing a cec with multiple parameter but without a return value
+ * $param = array('foo' => $bar, 'foo2' => $bar2);
+ * $param = CEC_Hook::execute('Contenido.Content.Somewhere', $param);
+ *
+ *
+ * // example of executing a cec without a parameter but a return value (with predefined
+ * // default return value)
+ * CEC_Hook::setDefaultReturnValue('this is the default title');
+ * $title = CEC_Hook::executeAndReturn('Contenido.Content.CreateTitletag');
+ *
+ * // example of executing a cec with a parameter and a return value
+ * // (usually the modified version of passed parameter)
+ * $baseHref = $cfgClient[$client]['path']['htmlpath'];
+ * $newBaseHref = CEC_Hook::executeAndReturn('Contenido.Frontend.BaseHrefGeneration', $baseHref);
+ *
+ *
+ * // example of executing a cec with a break condition and default return value
+ * CEC_Hook::setBreakCondition(false, true); // break condition = "false", default return value = "true"
+ * $allow = CEC_Hook::executeWhileBreakCondition('Contenido.Frontend.AllowEdit', $lang, $idcat, $idart, $auth->auth['uid']);
+ * if ($allow == false) {
+ * die("You're not coming in!");
+ * }
+ *
+ * // another example of executing a cec with a break condition and default return value
+ * CEC_Hook::setBreakCondition(true, false); // break condition = "true", default return value = "false"
+ * $allow = CEC_Hook::executeWhileBreakCondition('Contenido.Frontend.CategoryAccess', $lang, $idcat, $auth->auth['uid']);
+ * if ($allow == false) {
+ * die("I said, you're not coming in!");
+ * }
+ *
+ *
+ * @author Murat Purc
+ * @package Contenido Backend classes
+ * @subpackage CEC
+ */
+class CEC_Hook {
+
+ /**
+ * Value to break the cec execution at a true result
+ * @deprecated see CEC_Hook::setConditions()
+ * @var int
+ */
+ const BREAK_AT_TRUE = 'true';
+
+ /**
+ * Value to break the cec execution at a false result
+ * @deprecated see CEC_Hook::setConditions()
+ * @var int
+ */
+ const BREAK_AT_FALSE = 'false';
+
+ /**
+ * Value to break the cec execution at a null result
+ * @deprecated see CEC_Hook::setConditions()
+ * @var int
+ */
+ const BREAK_AT_NULL = 'null';
+
+ /**
+ * Flag to return the set break condition directly.
+ * @deprecated No more needed
+ * @var bool
+ */
+ static private $_returnBreakConditionDirectly = false;
+
+ /**
+ * Flag to overwrite arguments.
+ * @deprecated No more needed
+ * @var bool
+ */
+ static private $_overwriteArguments = true;
+
+ /**
+ * Temporaly stored break condition.
+ * @var int
+ */
+ static private $_breakCondition = null;
+
+ /**
+ * Temporaly stored default return value of CEC functions
+ * @var mixed
+ */
+ static private $_defaultReturnValue = null;
+
+ /**
+ * Temporaly stored position of argument to return. It's used by CEC_Hook::executeAndReturn()
+ * to store/extract the return value into/from arguments list.
+ * @var int
+ */
+ static private $_returnArgumentPos = 1;
+
+
+ /**
+ * Temporaly setting of an execution conditions.
+ *
+ * @deprecated Function is no more needed, still exists due to downwards compatibility!
+ *
+ * This is usefull, if at least on of defined cec functions returns a specific value and the
+ * execution of further functions is no more needed.
+ *
+ * The defined condition will be reset in execute() method.
+ *
+ * @param mixed $condition One of CEC_Hook constants, with following control mechanism:
+ * - CEC_Hook::BREAK_AT_TRUE = Breaks the iteration of cec functions
+ * and returns the parameter, if the result of an function is true.
+ *
+ * - CEC_Hook::BREAK_AT_FALSE = Breaks the iteration of cec functions
+ * and returns the parameter, if the result of an function is false.
+ *
+ * - CEC_Hook::BREAK_AT_NULL = Breaks the iteration of cec functions
+ * and returns the parameter, if the result of an function is null.
+ *
+ * @param bool $overwriteArguments
+ * Flag to prevent overwriting of passed parameter to execute().
+ * Normally the parameter will be overwritten by return value of
+ * executed functions, but this is sometimes a not wanted side effect.
+ *
+ * @param bool $returnbreakconditiondirectly
+ * If a break condition is set and a chain function returns the condition
+ * set, setting this option forces the execute method to directly return
+ * that condition instead of the args
+ *
+ * @param mixed $defaultReturnValue
+ *
+ * @throws InvalidArgumentException If passed type is not one of CEC_Hook constants.
+ */
+ public static function setConditions($condition, $overwriteArguments=true, $returnbreakconditiondirectly=false, $defaultReturnValue=null)
+ {
+ switch ($condition) {
+ case CEC_Hook::BREAK_AT_TRUE:
+ self::$_breakCondition = CEC_Hook::BREAK_AT_TRUE;
+ break;
+ case CEC_Hook::BREAK_AT_FALSE:
+ self::$_breakCondition = CEC_Hook::BREAK_AT_FALSE;
+ break;
+ case CEC_Hook::BREAK_AT_NULL:
+ self::$_breakCondition = CEC_Hook::BREAK_AT_NULL;
+ break;
+ default:
+ throw new InvalidArgumentException('Condition "' . $condition . '" is not supported!');
+ break;
+ }
+
+ self::$_overwriteArguments = (bool) $overwriteArguments;
+
+ self::$_returnBreakConditionDirectly = (bool) $returnbreakconditiondirectly;
+
+ self::$_defaultReturnValue = $defaultReturnValue;
+ }
+
+
+ /**
+ * Temporaly setting of break condition and optional the default return value.
+ *
+ * @param mixed $condition
+ * @param mixed $defaultReturnValue
+ * @return void
+ */
+ public static function setBreakCondition($condition, $defaultReturnValue=null)
+ {
+ self::$_breakCondition = $condition;
+ self::setDefaultReturnValue($defaultReturnValue);
+ }
+
+
+ /**
+ * Temporaly setting of default return value.
+ *
+ * @param mixed $defaultReturnValue
+ * @return void
+ */
+ public static function setDefaultReturnValue($defaultReturnValue)
+ {
+ self::$_defaultReturnValue = $defaultReturnValue;
+ }
+
+
+ /**
+ * Temporaly setting of position in argument to return.
+ *
+ * @param int $pos Position, feasible value greater 0
+ * @return void
+ */
+ public static function setReturnArgumentPos($pos)
+ {
+ if ((int) $pos < 1) {
+ throw new Exception('Invalid return position');
+ }
+ self::$_returnArgumentPos = (int) $pos;
+ }
+
+
+ /**
+ * Method to execute registered functions for Contenido Extension Chainer (CEC).
+ *
+ * Gets the desired CEC iterator and executes each registered chain function by passing the achieved
+ * arguments to it. There is
+ *
+ * @param string $chainName The chain name to process
+ * @param mixed $param1 First parameter which will be forwarded to registered chain functions
+ * @param mixed $param2 Second parameter which will be forwarded to registered chain functions
+ * @param mixed $param3 Third parameter which will be forwarded to registered chain functions
+ * NOTE: There is no restriction for number of passed parameter.
+ * @return void
+ */
+ public static function execute()
+ {
+ // get arguments
+ $args = func_get_args();
+
+ // get chainname
+ $chainName = array_shift($args);
+
+ // process CEC
+ $cecIterator = cApiCECRegistry::getInstance()->getIterator($chainName);
+ if ($cecIterator->count() > 0) {
+ $cecIterator->reset();
+
+ while ($chainEntry = $cecIterator->next()) {
+ // invoke CEC function
+ $chainEntry->setTemporaryArguments($args);
+ $chainEntry->execute();
+ }
+ }
+
+ // reset properties to defaults
+ self::_reset();
+ }
+
+
+ /**
+ * Method to execute registered functions for Contenido Extension Chainer (CEC).
+ *
+ * Gets the desired CEC iterator and executes each registered chain function. You can pass as much
+ * parameter as you want.
+ *
+ * @param string $chainName The chain name to process
+ * @param mixed $param1 First parameter which will be forwarded to registered chain functions
+ * @param mixed $param2 Second parameter which will be forwarded to registered chain functions
+ * @param mixed $param3 Third parameter which will be forwarded to registered chain functions
+ * NOTE: There is no restriction for number of passed parameter.
+ * @return mixed Parameter changed/processed by chain functions.
+ * Note: If no chain function is registered, the first parameter $param after
+ * $chainName will be returned
+ */
+ public static function executeAndReturn()
+ {
+ // get arguments
+ $args = func_get_args();
+
+ // get chainname
+ $chainName = array_shift($args);
+
+ // position of return value in arguments list
+ $pos = self::$_returnArgumentPos - 1;
+
+ // default return value
+ $return = self::$_defaultReturnValue;
+
+ // process CEC
+ $cecIterator = cApiCECRegistry::getInstance()->getIterator($chainName);
+ if ($cecIterator->count() > 0) {
+ $cecIterator->reset();
+
+ while ($chainEntry = $cecIterator->next()) {
+ // invoke CEC function
+ $chainEntry->setTemporaryArguments($args);
+ $return = $chainEntry->execute();
+ if (isset($args[$pos])) {
+ $args[$pos] = $return;
+ }
+ }
+ }
+
+ if (isset($args[$pos])) {
+ $return = $args[$pos];
+ }
+
+ // reset properties to defaults
+ self::_reset();
+
+ return $return;
+ }
+
+
+
+ /**
+ * CEC function to process chains untill a break condition occurs.
+ *
+ * Gets the desired CEC iterator and executes each registered chain function as long as defined break
+ * condition doesn't occur.
+ *
+ * @param string $chainName The chain name to process
+ * @param mixed $param1 First parameter which will be forwarded to registered chain functions
+ * @param mixed $param2 Second parameter which will be forwarded to registered chain functions
+ * @param mixed $param3 Third parameter which will be forwarded to registered chain functions
+ * NOTE: There is no restriction for number of passed parameter.
+ * @return mixed The break condition or it's default value
+ */
+ public static function executeWhileBreakCondition()
+ {
+ // get arguments
+ $args = func_get_args();
+
+ // get chainname
+ $chainName = array_shift($args);
+
+ // break condition and default return value
+ $breakCondition = self::$_breakCondition;
+ $return = self::$_defaultReturnValue;
+
+ // process CEC
+ $cecIterator = cApiCECRegistry::getInstance()->getIterator($chainName);
+ if ($cecIterator->count() > 0) {
+ $cecIterator->reset();
+
+ while ($chainEntry = $cecIterator->next()) {
+ // invoke CEC function
+ $chainEntry->setTemporaryArguments($args);
+ $return = $chainEntry->execute();
+ // process return value
+ if (isset($return) && $return === $breakCondition) {
+ self::_reset();
+ return $return;
+ break;
+ }
+ }
+ }
+
+ // reset properties to defaults
+ self::_reset();
+
+ return $return;
+ }
+
+
+ /**
+ * Resets some properties to defaults
+ *
+ * @return void
+ */
+ private static function _reset()
+ {
+ self::$_breakCondition = null;
+ self::$_returnBreakConditionDirectly = false;
+ self::$_overwriteArguments = true;
+ self::$_defaultReturnValue = null;
+ self::$_returnArgumentPos = 1;
+ }
+
+
+ /**
+ * Used to debug some status informations.
+ *
+ * Writes the debug value into a logfile (see contenido/logs/cec_hook_debug.log).
+ *
+ * @param mixed $var The variable to dump
+ * @param string $msg Additional message
+ * @return void
+ */
+ private static function _debug($var, $msg='')
+ {
+ $content = ($msg !== '') ? $msg . ': ' : '';
+ if (is_object($var) || is_array($var)) {
+ $content .= print_r($var, true);
+ } else {
+ $content .= $var . "\n";
+ }
+
+ $sLogPathName = $GLOBALS['cfg']['path']['contenido'] . 'logs/cec_hook_debug.log';
+ file_put_contents($sLogPathName, $content . "\n", FILE_APPEND);
+ }
+
+}
diff --git a/conlite/classes/class.chartable.php b/conlite/classes/class.chartable.php
new file mode 100644
index 0000000..48c8f77
--- /dev/null
+++ b/conlite/classes/class.chartable.php
@@ -0,0 +1,158 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ *
+ * $Id: class.chartable.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ * cCharacterConverter
+ *
+ * A diacritic mark or diacritic is a mark added to a letter to alter a
+ * word's pronunciation or to distungish between similar words. However,
+ * users of foreign languages are unable to type diacritics (either because
+ * the keyboard mapping doesn't support them, or they are looking to similar
+ * to other characters). Examples for conversions:
+ *
+ * German diacritic char � maps to u and ue.
+ *
+ * Developers can use the diacritic search implemented in the GenericDB to
+ * automatically handle diacritic search conversion.
+ */
+class cCharacterConverter
+{
+ var $_oDB;
+ var $_aAliasCache;
+ var $_aCharCache;
+
+ function cCharacterConverter ()
+ {
+ $this->_oDB = new DB_ConLite;
+ $this->_aAliasCache = array();
+ $this->_aCharCache = array();
+ }
+
+ function fetchDiacriticCharactersForNormalizedChar ($sEncoding, $cNormalizedChar)
+ {
+ global $cfg;
+
+ $cNormalizedChar = Contenido_Security::escapeDB($cNormalizedChar, $this->_oDB);
+ $sEncoding = Contenido_Security::escapeDB($sEncoding, $this->_oDB);
+ $sEncoding = $this->correctEncoding($sEncoding);
+
+ if (!array_key_exists($sEncoding, $this->_aCharCache))
+ {
+ $this->_aCharCache[$sEncoding] = array();
+ }
+
+ if (array_key_exists($cNormalizedChar, $this->_aCharCache[$sEncoding]) && count($this->_aCharCache[$cNormalizedChar][$sEncoding]) > 0)
+ {
+ return $this->_aCharCache[$sEncoding][$cNormalizedChar];
+ }
+
+ $sql = "SELECT charid FROM ".$cfg["tab"]["chartable"]." WHERE encoding = '".$sEncoding."' AND normalized_char = '".$cNormalizedChar."'";
+ $this->_oDB->query($sql);
+
+ $aChars = array();
+
+ $this->_aCharCache[$sEncoding][$cNormalizedChar] = array();
+
+ while ($this->_oDB->next_record())
+ {
+ $aChars[] = chr($this->_oDB->f("charid"));
+ $this->_aCharCache[$sEncoding][$cNormalizedChar][] = chr($this->_oDB->f("charid"));
+ }
+
+ return ($aChars);
+ }
+
+ function fetchNormalizedCharsForDiacriticCharacter ($sEncoding, $cCharacter)
+ {
+ global $cfg;
+
+ $cCharacter = Contenido_Security::escapeDB($cCharacter, $this->_oDB);
+ $sEncoding = Contenido_Security::escapeDB($sEncoding, $this->_oDB);
+ $sEncoding = $this->correctEncoding($sEncoding);
+
+ if (strlen($cCharacter) > 1)
+ {
+ cError(__FILE__, __LINE__, "cCharacter is longer than 1 character");
+ }
+
+ if (!array_key_exists($sEncoding, $this->_aAliasCache))
+ {
+ $this->_aAliasCache[$sEncoding] = array();
+ }
+
+ if (array_key_exists($cCharacter, $this->_aAliasCache[$sEncoding]) && count($this->_aAliasCache[$sEncoding][$cCharacter]) > 0)
+ {
+ return $this->_aAliasCache[$sEncoding][$cCharacter];
+ }
+
+ $sql = "SELECT normalized_char FROM ".$cfg["tab"]["chartable"]." WHERE encoding = '".$sEncoding."' AND charid = '".ord($cCharacter)."'";
+ $this->_oDB->query($sql);
+
+ $aAliases = array();
+
+ $this->_aAliasCache[$sEncoding][$cCharacter] = array();
+
+ while ($this->_oDB->next_record())
+ {
+ $aAliases[] = $this->_oDB->f("normalized_char");
+ $this->_aAliasCache[$sEncoding][$cCharacter][] = $this->_oDB->f("normalized_char");
+ }
+
+ return ($aAliases);
+ }
+
+ function correctEncoding ($sEncoding)
+ {
+ $encodingAliases = array(
+ "win-1250" => array("windows-1250", "windows1250", "win-1250"),
+ "win-1251" => array("windows-1251", "windows1251", "win-1251"),
+ "win-1252" => array("windows-1252", "windows1252", "win-1252"),
+ "win-1253" => array("windows-1253", "windows1253", "win-1253"),
+ "win-1254" => array("windows-1254", "windows1254", "win-1254"),
+ "win-1256" => array("windows-1256", "windows1256", "win-1256"),
+ "win-1257" => array("windows-1257", "windows1257", "win-1257"),
+ "win-1258" => array("windows-1258", "windows1258", "win-1258"));
+
+ foreach ($encodingAliases as $correctAlias => $encodingAlias)
+ {
+ if (in_array($sEncoding, $encodingAlias))
+ {
+ $sEncoding = $correctAlias;
+ }
+ }
+
+ return $sEncoding;
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.cl_db_backup.php b/conlite/classes/class.cl_db_backup.php
new file mode 100644
index 0000000..b047abc
--- /dev/null
+++ b/conlite/classes/class.cl_db_backup.php
@@ -0,0 +1,337 @@
+
+ * @copyright (c) 2012, conlite.org
+ *
+ * $Id: class.cl_db_backup.php 374 2015-11-09 15:59:28Z oldperl $
+ */
+/* @var $sess Contenido_Session */
+/* @var $perm Contenido_Perm */
+/* @var $auth Contenido_Challenge_Crypt_Auth */
+/* @var $notification Contenido_Notification */
+
+// security check
+defined('CON_FRAMEWORK') or die('Illegal call');
+
+class clDbBackup {
+
+ protected $_oDb;
+ protected $_sDumpFile = null;
+ protected $_bCompress = false;
+ protected $_sTmpData = null;
+ protected $_aUsedExt = array('sql', 'gz');
+ protected $_aTableContent = array('_code', '_inuse', '_phplib_active_sessions');
+ protected $_sLogFile;
+
+ /**
+ * Constructor
+ */
+ public function __construct() {
+ $this->_oDb = new DB_ConLite();
+ $this->_sLogFile = CL_BACKUP_LOGFILE;
+ if (isset($_SESSION['dump']['file']) && !empty($_SESSION['dump']['file'])) {
+ $this->_sDumpFile = $_SESSION['dump']['file'];
+ }
+ if (isset($_SESSION['dump']['compress']) && is_bool($_SESSION['dump']['compress'])) {
+ $this->_bCompress = ($_SESSION['dump']['compress']) ? true : false;
+ }
+ }
+
+ /**
+ * Builds and returns an array of dump files for a given dir
+ *
+ * @param string $sPath server path to dump files
+ * @param string $sOrder sort order by
+ * @param string $sDirection sort direction
+ * @return array|boolean returns array of files or false
+ */
+ public function getDumpFiles($sPath, $sOrder = 'date', $sDirection = 'DESC') {
+ $oDirHandle = dir($sPath);
+ $aFiles = array();
+ if (is_object($oDirHandle)) {
+ $iLoop = 0;
+ while (false !== ($sFile = $oDirHandle->read())) {
+ if ($sFile == '..' || $sFile == '.' || $sFile == '.svn')
+ continue;
+ $info = new SplFileInfo($sPath . $sFile); // pathinfo($file->getFilename(), PATHINFO_EXTENSION)
+ if ($info->isFile()) {
+ $sExtension = '';
+ if (version_compare(phpversion(), "5.3.6", ">=")) {
+ $sExtension = $info->getExtension();
+ } else {
+ $sExtension = pathinfo($info->getFilename(), PATHINFO_EXTENSION);
+ }
+
+ if (!in_array($sExtension, $this->_aUsedExt))
+ continue;
+ $aFiles[$iLoop]['ext'] = $sExtension;
+ $aFiles[$iLoop]['size'] = $info->getSize();
+ $aFiles[$iLoop]['readable'] = $info->isReadable();
+ $aFiles[$iLoop]['atime'] = $info->getATime();
+ $aFiles[$iLoop]['ctime'] = $info->getCTime();
+ $aFiles[$iLoop]['mtime'] = $info->getMTime();
+ }
+ $aFiles[$iLoop]['filename'] = $sFile;
+ $iLoop++;
+ }
+ $oDirHandle->close();
+ }
+
+ if (count($aFiles) > 0) {
+ // Hole eine Liste von Spalten
+ foreach ($aFiles as $key => $row) {
+ $time[$key] = $row['ctime'];
+ }
+ array_multisort($time, (($sDirection == 'DESC') ? SORT_DESC : SORT_ASC), $aFiles);
+ }
+ return (count($aFiles) > 0) ? $aFiles : false;
+ }
+
+ /**
+ * Write data to dump file
+ *
+ * @todo make this func protected and give a public wrapper
+ * @param string $sData
+ * @return boolean
+ */
+ public function _writeToDumpFile($sData = null) {
+ if (!is_null($sData))
+ $this->_sTmpData = $sData;
+ if (!is_null($this->_sDumpFile)) {
+ if (!is_null($this->_sTmpData) && !empty($this->_sTmpData)) {
+ if ($this->_bCompress) {
+ $fp = gzopen($this->_sDumpFile, 'ab');
+ gzwrite($fp, $this->_sTmpData, strlen($this->_sTmpData));
+ gzclose($fp);
+ } else {
+ $fp = fopen($this->_sDumpFile, 'ab');
+ fwrite($fp, $this->_sTmpData);
+ fclose($fp);
+ }
+ $this->_sTmpData = null;
+ return true;
+ }
+ }
+ $this->_sTmpData = null;
+ return false;
+ }
+
+ /**
+ * Write table header to dump and return dataset count
+ *
+ * @param string $sTable
+ * @return array
+ */
+ public function _writeTableHeader($sTable) {
+ $data = "DROP TABLE IF EXISTS `$sTable`;\n";
+ $this->_oDb->query('SHOW CREATE TABLE `' . $sTable . '`');
+ $this->_oDb->next_record();
+ $row = $this->_oDb->toArray(); //@mysql_fetch_row($res);
+ $data .= $row[1] . ';' . "\n\n";
+ if (!$this->_noTableData($sTable)) {
+ $data .= "/*!40000 ALTER TABLE `$sTable` DISABLE KEYS */;\n";
+ }
+
+ $this->_writeToDumpFile($data);
+
+ $sql = "SELECT count(*) as `count_records` FROM `" . $sTable . "`";
+ $this->_oDb->query($sql);
+ $this->_oDb->next_record();
+ $res_array = $this->_oDb->toArray();
+
+ return $res_array['count_records'];
+ }
+
+ /**
+ * Write table data to dump file
+ *
+ * @global array $dump
+ * @param string $sTable
+ * @return void
+ */
+ public function _writeTableData($sTable) {
+ global $dump;
+ if ($this->_noTableData($sTable)) {
+ $dump['nr'] ++;
+ $dump['table_offset'] = 0;
+ return;
+ }
+ $table_list = array();
+ $this->_oDb->query("SHOW COLUMNS FROM " . $sTable);
+ while($this->_oDb->next_record()) {
+ $aResult = $this->_oDb->toArray();
+ $table_list[] = $aResult['Field'];
+ }
+
+ $this->_oDb->query('select `' . implode('`,`', $table_list) . '` from ' . $sTable . ' limit ' . $dump['zeilen_offset'] . ',' . ($dump['anzahl_zeilen']));
+ $ergebnisse = $this->_oDb->num_rows();
+
+ $data = '';
+
+ if ($ergebnisse !== false) {
+ if (($ergebnisse + $dump['zeilen_offset']) < $dump['table_records']) {
+ //noch nicht fertig - neuen Startwert festlegen
+ $dump['zeilen_offset']+= $dump['anzahl_zeilen'];
+ } else {
+ //Fertig - naechste Tabelle
+ $dump['nr'] ++;
+ $dump['table_offset'] = 0;
+ }
+
+ //BOF Complete Inserts ja/nein
+ if ($_SESSION['dump']['complete_inserts'] == 'yes') {
+
+ while ($this->_oDb->next_record()) {
+ $rows = $this->_oDb->toArray();
+ $insert = 'INSERT INTO `' . $sTable . '` (`' . implode('`, `', $table_list) . '`) VALUES (';
+ foreach ($table_list as $column) {
+ //EOF NEW TABLE STRUCTURE - LIKE MYSQLDUMPER -functions_dump.php line 186
+ if (!isset($rows[$column])) {
+ $insert.='NULL,';
+ } else if ($rows[$column] != '') {
+ $insert.='\'' . mysql_escape_string($rows[$column]) . '\',';
+ } else {
+ $insert.='\'\',';
+ }
+ //BOF NEW TABLE STRUCTURE - LIKE MYSQLDUMPER
+ }
+ $data .=substr($insert, 0, -1) . ');' . "\n";
+ }
+ } else {
+
+ $lines = array();
+ while ($this->_oDb->next_record()) {
+ $rows = $this->_oDb->toArray();
+ $values = array();
+ foreach ($table_list as $column) {
+ //EOF NEW TABLE STRUCTURE - LIKE MYSQLDUMPER
+ if (!isset($rows[$column])) {
+ $values[] = 'NULL';
+ } else if ($rows[$column] != '') {
+ $values[] = '\'' . mysql_escape_string($rows[$column]) . '\'';
+ } else {
+ $values[] = '\'\'';
+ }
+ //BOF NEW TABLE STRUCTURE - LIKE MYSQLDUMPER
+ }
+ $lines[] = implode(', ', $values);
+ }
+ $tmp = trim(implode("),\n (", $lines));
+ if ($tmp != '') {
+ $data = 'INSERT INTO `' . $sTable . '` (`' . implode('`, `', $table_list) . '`) VALUES' . "\n" . ' (' . $tmp . ");\n";
+ }
+ }
+ //EOF Complete Inserts ja/nein
+ if ($dump['table_offset'] == 0)
+ $data.= "/*!40000 ALTER TABLE `$sTable` ENABLE KEYS */;\n\n";
+
+ $this->_writeToDumpFile($data);
+ }
+ }
+
+ /**
+ * send a file to browser (download) and exit
+ *
+ * @param string $sFileName
+ */
+ public function sendFile($sFileName) {
+ if (is_file($sFileName)) {
+ $path_parts = pathinfo($sFileName);
+ $file_name = $path_parts['basename'];
+ $file_ext = $path_parts['extension'];
+ $file_size = filesize($sFileName);
+ $rTmpFile = @fopen($sFileName, "rb");
+ if ($rTmpFile) {
+ set_time_limit(0);
+ ob_end_clean();
+ // set the headers, prevent caching
+ header("Pragma: public");
+ header("Expires: 0");
+ header("Cache-Control: private", false); // required for certain browsers
+ header("Cache-Control: public, must-revalidate, post-check=0, pre-check=0");
+ header("Content-Disposition: attachment; filename=\"$file_name\"");
+
+ // set the mime type based on extension, add yours if needed.
+ $ctype_default = "application/octet-stream";
+ $content_types = array(
+ "sql" => "application/x-sql",
+ "gz" => "application/x-gzip"
+ );
+ $ctype = isset($content_types[$file_ext]) ? $content_types[$file_ext] : $ctype_default;
+ header("Content-Type: $ctype");
+ header("Content-Transfer-Encoding: binary");
+ header("Content-Length: $file_size");
+
+ while (!feof($rTmpFile)) {
+ print(@fread($rTmpFile, 1024 * 8));
+ ob_flush();
+ flush();
+ if (connection_status() != 0) {
+ @fclose($rTmpFile);
+ exit;
+ }
+ }
+ // file save was a success
+ @fclose($rTmpFile);
+ $this->_writeLogEntry("Downloaded File: " . basename($sFileName));
+ exit;
+ } else {
+ // file couldn't be opened
+ header("HTTP/1.0 500 Internal Server Error");
+ exit;
+ }
+ } else {
+ // file does not exist
+ header("HTTP/1.0 404 Not Found");
+ exit;
+ }
+ }
+
+ /**
+ * Write a log entry
+ */
+ public function writeLog() {
+ $this->_writeLogEntry("Backup generated: " . $this->_sDumpFile);
+ }
+
+ /**
+ * Check against table exclude array for writing table data
+ *
+ * @param string $sTable
+ * @return boolean
+ */
+ protected function _noTableData($sTable) {
+ foreach ($this->_aTableContent as $sExTable) {
+ if (strstr($sTable, $sExTable))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Write to log file
+ *
+ * @global Contenido_Challenge_Crypt_Auth $auth
+ * @param string $sMessage
+ */
+ protected function _writeLogEntry($sMessage) {
+ /* @var $auth Contenido_Challenge_Crypt_Auth */
+ global $auth;
+ if (!empty($auth->auth['uname'])) {
+ $sMessage = "User " . $auth->auth['uname'] . " - " . $sMessage;
+ }
+ $f = @fopen($this->_sLogFile, 'a+');
+ if (is_resource($f)) {
+ @fputs($f, date("m.d.Y g:ia") . " " . $_SERVER['REMOTE_ADDR'] . " " . $sMessage . "\n");
+ @fclose($f);
+ }
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.client.php b/conlite/classes/class.client.php
new file mode 100644
index 0000000..166a000
--- /dev/null
+++ b/conlite/classes/class.client.php
@@ -0,0 +1,167 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ *
+ * $Id: class.client.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class Client {
+
+ /**
+ * Constructor Function
+ * @param
+ */
+ function Client() {
+ // empty
+ } // end function
+
+ /**
+ * getAvailableClients()
+ * Returns all clients available in the system
+ * @return array Array with id and name entries
+ */
+ function getAvailableClients() {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ idclient,
+ name
+ FROM
+ ". $cfg["tab"]["clients"];
+ $db->query($sql);
+
+ $clients = array();
+
+ while ($db->next_record())
+ {
+ $newentry["name"] = $db->f("name");
+ $clients[$db->f("idclient")] = $newentry;
+ }
+
+ return ($clients);
+ } // end function
+
+ /**
+ * getAvailableClients()
+ * Returns all clients available in the system
+ * @return array Array with id and name entries
+ */
+ function getAccessibleClients() {
+ global $cfg, $perm;
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ idclient,
+ name
+ FROM
+ ". $cfg["tab"]["clients"]." ORDER BY idclient ASC";
+ $db->query($sql);
+
+ $clients = array();
+
+ while ($db->next_record())
+ {
+ if ($perm->have_perm_client("client[".$db->f("idclient")."]") ||
+ $perm->have_perm_client("admin[".$db->f("idclient")."]") ||
+ $perm->have_perm_client())
+ {
+ $newentry["name"] = $db->f("name");
+ $clients[$db->f("idclient")] = $newentry;
+ }
+
+ }
+
+ return ($clients);
+ } // end function
+
+ /**
+ * getClientname()
+ * Returns the clientname of the given clientid
+ * @return string Clientname if found, or emptry string if not.
+ */
+ function getClientname ($clientid)
+ {
+ global $cfg;
+ $clientid = Contenido_Security::toInteger($clientid);
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ name
+ FROM
+ ". $cfg["tab"]["clients"]."
+ WHERE
+ idclient = '".$clientid."'";
+
+ $db->query($sql);
+ if ($db->next_record())
+ {
+ return ($db->f("name"));
+ } else {
+ return i18n("No client");
+ }
+
+ } // end function
+
+ /**
+ * hasLanguageAssigned()
+ * Returns if the given client has a language
+ * @return bool true if the client has a language
+ */
+ function hasLanguageAssigned ($clientid)
+ {
+ global $cfg;
+ $clientid = Contenido_Security::toInteger($clientid);
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ idlang
+ FROM
+ ". $cfg["tab"]["clients_lang"]."
+ WHERE
+ idclient = '".$clientid."'";
+
+ $db->query($sql);
+ if ($db->next_record())
+ {
+ return (true);
+ } else {
+ return (false);
+ }
+
+ } // end function
+
+} // end class
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.cms_date.php b/conlite/classes/class.cms_date.php
new file mode 100644
index 0000000..23fce4e
--- /dev/null
+++ b/conlite/classes/class.cms_date.php
@@ -0,0 +1,395 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.8.7
+ *
+ * {@internal
+ * created 2007-07-14 Bilal Arslan, Timo Trautmann
+ * modified 2008-07-28 Bilal Arslan, added new Date format timestamp
+ * modified 2009-04-14 OliverL, added class in Edit- & Save-Link
+ * $Id
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class Cms_Date{
+
+ /**
+ * Contains user input of cms_type
+ * @access private
+ */
+ private $sContent;
+
+ /**
+ * The format value for the calendar
+ * @access private
+ */
+ private $aFormat;
+
+ /**
+ * The number of cms_date[?] parameter
+ * @access private
+ */
+ private $iNumberOfCms;
+
+ /**
+ * The output javascript
+ * @access private
+ */
+ private $sJS;
+
+ /**
+ * The the static variable, controlls howmuch object exists
+ * @access private
+ */
+ private static $iNumOutput;
+
+ /**
+ * The contenido global
+ * @access private
+ */
+ private $iIdArtLang;
+
+ /**
+ * The contenido Edit link
+ * @access private
+ */
+ private $sEditLink;
+
+ /**
+ * The contenido global
+ * @access private
+ */
+ private $aCfg;
+
+ /**
+ * The CmsDate object for call cmsDate functions
+ * @access private
+ */
+ private $sCalName;
+
+ /**
+ * The contenido database object
+ * @access private
+ */
+ private $oDB;
+
+ /**
+ * Input Field Id
+ * @access private
+ */
+ private $sEditAreaId;
+
+ /**
+ * the id of Div Element select box
+ * @access private
+ */
+ private $sDivSelectId;
+
+ /**
+ *
+ * The id of select box
+ * @access private
+ */
+ private $sSelectId;
+
+ /**
+ *
+ * Total count of cms_date
+ * @access private
+ */
+ private $iTotalCount;
+
+ /**
+ * Language of contenido
+ * @access private
+ */
+ private $sContenidoLang;
+
+/**
+ * The Cms_Date object constructor, initializes class variables
+ *
+ * @param {string} $sContent
+ * @param {integer} $iNumberOfCms
+ * @param {integer} $iIdArtLang
+ * @param {string} $sEditLink
+ * @param {Object} $aCfg
+ * @param {Object} $aDB
+ */
+public function __construct($sContent, $iNumberOfCms, $iIdArtLang, $sEditLink, $aCfg, $aDB, $iTotalCount, $sContenidoLang){
+
+ $this->iNumberOfCms = $iNumberOfCms;
+ $this->iIdArtLang = $iIdArtLang;
+ $this->sEditLink = $sEditLink;
+ $this->aCfg = $aCfg;
+
+ // static number for objects
+ Cms_Date::$iNumOutput++;
+ $this->sCalName = "oCalId".Cms_Date::$iNumOutput;
+ $this->oDB = $aDB;
+ $this->sEditAreaId = "";
+ $this->sDivSelectId = "";
+ // if is empty, fill it with space character. Thats important for contenido input area!
+ ($sContent == "") ? $this->sContent = " " : $this->sContent = urldecode($sContent);
+ $this->sSelectId = "";
+ $this->iTotalCount = $iTotalCount;
+ $this->sJS = "";
+ $this->sContenidoLang = $sContenidoLang;
+}
+
+/**
+ * Edit and View all Widgets. This function is calling in edit mode
+ *
+ * @return the all widgets
+ */
+public function getAllWidgetEdit(){
+
+ $this->sContent = urldecode($this->sContent);
+ $this->sContent = AddSlashes(AddSlashes($this->sContent));
+ $this->sContent = str_replace("\\\'", "'", $this->sContent);
+ $this->sContent = str_replace("\$", '\\\$', $this->sContent);
+
+ // Render all Widgetes
+ $this->sContent = $this->getEditingField() . $this->getCalendarButton() . $this->getOkButton() . $this->getSelectBox() . $this->getJsScript();
+ return urldecode($this->sContent);
+}
+
+/**
+ * This function modified cms_content before it is displayed in frontend.
+ * In this case this function is a dummy.
+ *
+ * @return Returns user input of cms_type
+ */
+public function getAllWidgetView(){
+
+ return $this->sContent;
+}
+
+/**
+ * This function set the date format for select-box.
+ * Function displays current day format.
+ * For edit or add formats modified this function.
+ *
+ * @return the format as an array
+ */
+private function getDateFormats(){
+
+ $sMonthName = "";
+ $sDayName = "";
+ $sMonthName = getCanonicalMonth(date('m'));
+ $sDayName = getCanonicalDay(date('w'));
+ $iDay = date('d');
+ $iMonth = date('m');
+ $iYear = date("Y");
+ $iYearShort = date("y");
+
+ $this->aFormat = array(
+ array("0",i18n("Please Choose Format")),
+ array("%d.%m.%Y", date('d.m.Y')),
+ array("%A, %d.%m.%Y", $sDayName . ', ' . $iDay .'.'. $iMonth .'.'. $iYear ),
+ array("%d. %B %Y", $iDay.'. ' .$sMonthName. ' '. $iYear),
+ array("%Y-%m-%d",date('Y-m-d')),
+ array("%y-%m-%d",date('y-m-d')),
+ array("%d/%B/%Y",$iDay .'/'. $sMonthName .'/'. $iYear),
+ array("%d/%m/%y", date('d/m/y')),
+ array("%B %y", $sMonthName . " ". $iYearShort),
+ array("%B-%y", $sMonthName . "-". $iYearShort),
+ array("%d.%m.%Y %H:%M",date('d.m.Y H:i')),
+ array("%m.%d.%Y %H:%M:%S",date('d.m.Y H:i:s')),
+ array("%H:%M",date('H:i')),
+ array("%H:%M:%S",date('H:i:s')),
+ array("%l:%M %P",date('h:i A')),
+ array("%l:%M:%S %P",date('h:i:s A')),
+ array("%s", "Timestamp")
+ );
+
+
+ return $this->aFormat;
+}
+
+/**
+ * This functions given all js-script, what we need for calendar.
+ * Set all js-script here
+ *
+ * @return (String) js-script
+ */
+public function getJsScript(){
+
+ // include only one time this js script
+ if(Cms_Date::$iNumOutput < 2){
+ $this->sJS .= ' ';
+ $this->sJS .= ' ';
+ $this->sJS .= ' ';
+ $this->sJS .= ' ';
+ $this->sJS .= '';
+ }
+
+ $this->sJS .= '';
+
+ // output
+ $this->sJS = AddSlashes(AddSlashes($this->sJS));
+ $this->sJS = str_replace("\\\'", "'", $this->sJS);
+
+ return $this->sJS;
+}
+
+/**
+ * This function builds a Contenido CMS Widget.
+ * A Button for Calendar.
+ *
+ * @return (String)calendar Button widget
+ */
+private function getCalendarButton(){
+
+ // html link for save
+ $oEditAnchor = new cHTMLLink;
+ $oEditAnchor->setClass('CMS_DATE_'.($this->iNumberOfCms).'_EDIT CMS_LINK_EDIT');
+ $oEditAnchor->setLink("javascript:setcontent('$this->iIdArtLang','" . $this->sEditLink . "');");
+ // Calendar Button
+ $oEditButton = new cHTMLImage;
+ $oEditButton->setSrc($this->aCfg["path"]["contenido_fullhtml"] . $this->aCfg["path"]["images"] . "calendar.gif");
+ $oEditButton->setBorder(0);
+ $oEditButton->setStyleDefinition("margin-right", "2px");
+ $oEditButton->setClass('CMS_DATE_'.($this->iNumberOfCms).'_EDIT CMS_LINK_EDIT');
+ $oEditButton->setID("trigger_start" . $this->iNumberOfCms);
+ $oEditButton->setEvent("Click", "$this->sCalName.showCalendar()");
+ $oEditAnchor->setContent($oEditButton);
+ $sFinalEditButton = $oEditButton->render();
+ $sFinalEditButton = AddSlashes(AddSlashes($sFinalEditButton));
+ $sFinalEditButton = str_replace("\\\'", "'", $sFinalEditButton);
+
+ return $sFinalEditButton;
+}
+
+/**
+ * This function builds a Contenido CMS Widget.
+ * A Button for Submit (OK-Button).
+ *
+ * @return (String)Ok Button widget
+ */
+private function getOkButton(){
+
+ // Ok Image
+ $oSaveAnchor = new cHTMLLink;
+ $oSaveAnchor->setClass('CMS_DATE_'.($this->iNumberOfCms).'_SAVE CMS_LINK_SAVE');
+ $oSaveAnchor->setLink("javascript:setcontent('".$this->iIdArtLang."','0')");
+ $oSaveButton = new cHTMLImage;
+ $oSaveButton->setSrc($this->aCfg["path"]["contenido_fullhtml"].$this->aCfg["path"]["images"]."but_ok.gif");
+ $oSaveButton->setBorder(0);
+ $oSaveAnchor->setContent($oSaveButton);
+ $sFinalSaveButton = $oSaveAnchor->render();
+ $sFinalSaveButton = AddSlashes(AddSlashes($sFinalSaveButton));
+ $sFinalSaveButton = str_replace("\\\'", "'", $sFinalSaveButton);
+
+ return $sFinalSaveButton;
+}
+
+/**
+ * This function builds a Contenido CMS Widget.
+ * A Editing Field or input field what we use for calendar.
+ *
+ * @return (String) Editing Field widget
+ */
+private function getEditingField(){
+
+ // Inline Editing Field
+ $oDivBox = new cHTMLDiv();
+ $oDivBox->setStyleDefinition("border", "1px dashed #bfbfbf");
+ $oDivBox->setEvent("Focus", "this.style.border='1px solid #bb5577';");
+ $oDivBox->setEvent("Blur", "this.style.border='1px dashed #bfbfbf';");
+ $this->sEditAreaId = "DATE_" . $this->oDB->f("idtype") . "_" . $this->iNumberOfCms;
+ $oDivBox->setId($this->sEditAreaId);
+ $oDivBox->updateAttributes(array ('contentEditable' => 'true'));
+ $oDivBox->setContent("_REPLACEMENT_");
+ $sFinalEditingDiv = $oDivBox->render();
+ $sFinalEditingDiv = AddSlashes(AddSlashes($sFinalEditingDiv));
+ $sFinalEditingDiv = str_replace("\\\'", "'", $sFinalEditingDiv);
+ $sFinalEditingDiv = str_replace("_REPLACEMENT_", $this->sContent, $sFinalEditingDiv);
+
+ return $sFinalEditingDiv;
+}
+
+/**
+ * This function builds a Contenido CMS Widget.
+ * A Select-Box what is given date formats.
+ * In auoFill we use the function getDateFormats:
+ * For edit or add formats modified this function.
+ *
+ * @return (String)Select-Box widget
+ */
+private function getSelectBox(){
+
+ // Div Format SelectBox
+ $oMenueDiv = new cHTMLDiv();
+ $this->sDivSelectId = "menue-$this->iNumberOfCms";
+ $oMenueDiv->setId($this->sDivSelectId);
+ $oMenueDiv->setStyleDefinition("padding", "4px");
+ $oMenueDiv->setStyleDefinition("background-color", "#ccc");
+ $oMenueDiv->setStyleDefinition("display", "none");
+ $oMenueDiv->setStyleDefinition("width", "239px");
+
+ // Select Box
+ $this->sSelectId = "select_".$this->iNumberOfCms;
+ $oSelectMenue = new cHTMLSelectElement("select-format-$this->iNumberOfCms", "", $this->sSelectId);
+ $oSelectMenue->setEvent("Change", "$this->sCalName.changeFormat(value);");
+ $oSelectMenue->autoFill($this->getDateFormats());
+ $oSelectMenue->setStyle("font-size: 11px; width:239px; font-family: Verdana,Arial,sans-serif");
+ $oMenueDiv->setContent($oSelectMenue);
+ $sFinalSelectBox = $oMenueDiv->render();
+ $sFinalSelectBox= AddSlashes(AddSlashes($sFinalSelectBox ));
+ $sFinalSelectBox= str_replace("\\\'", "'", $sFinalSelectBox);
+
+ return $sFinalSelectBox;
+}
+
+/**
+ * This function gives formatted current language shortcut
+ *
+ * @return (String)Current Language of Contenidos
+ */
+private function getLanguageContenido(){
+ $sLang = "";
+ switch($this->sContenidoLang){
+ case'de_DE': $sLang = "de";
+ break;
+ case'en_US': $sLang = "en";
+ break;
+ default:
+ break;
+ }
+
+ return $sLang;
+}
+
+
+}
+
+
+?>
diff --git a/conlite/classes/class.cms_filelist.php b/conlite/classes/class.cms_filelist.php
new file mode 100644
index 0000000..706a11c
--- /dev/null
+++ b/conlite/classes/class.cms_filelist.php
@@ -0,0 +1,1140 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release 4.8.13
+ *
+ * {@internal
+ * created 2009-10-01
+ * modified 2010-10-29, Dominik Ziegler - fixed CON-362 (removed whitespace from client setting)
+ * $Id: class.cms_filelist.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+cInclude('includes', 'functions.con.php');
+cInclude("includes", "functions.upl.php");
+
+/**
+ * This class provides all methods for the content type CMS_FILELIST. All properties of the file list are
+ * stored as a xml document in the database.
+ */
+class Cms_FileList {
+ /**
+ * Contenido configuration array
+ * @var array
+ * @access private
+ */
+ private $aCfg = array();
+
+ /**
+ * Current id of content type CMS_FILELIST[3] -> 3
+ * @var integer
+ * @access private
+ */
+ private $iId = 0;
+
+ /**
+ * Contenido database object
+ * @var object
+ * @access private
+ */
+ private $oDb = null;
+
+ /**
+ * Idartlang of article, which is currently in edit- or viewmode
+ * @var integer
+ * @access private
+ */
+ private $iIdArtLang = 0;
+
+ /**
+ * List of fieldnames in frontend (properties) which the file list has
+ * and which were also described in the config xml document
+ * @var array
+ * @access private
+ */
+ private $aFileListData = array();
+
+ /**
+ * String contains value of stored content in database
+ * in this case this is the config xml document which is
+ * later parsed and its settings were stored in $aSettings
+ * @var string
+ * @access private
+ */
+ private $sContent = "";
+
+ /**
+ * Array which contains current file list settings
+ * @var array
+ * @access private
+ */
+ private $aSettings = array();
+
+ /**
+ * Current Contenido client id
+ * @var integer
+ * @access private
+ */
+ private $iClient = 0;
+
+ /**
+ * Current Contenido language id
+ * @var integer
+ * @access private
+ */
+ private $iLang = 0;
+
+ /**
+ * Contenido session object
+ * @var object
+ * @access private
+ */
+ private $oSess = null;
+
+ /**
+ * Contenido configuration array for current active client
+ * @var array
+ * @access private
+ */
+ private $aCfgClient = array();
+
+ /**
+ * Array with default file extensions.
+ * @var array
+ * @access private
+ */
+ private $aFileExtensions = array();
+
+ /**
+ * Array with available meta data identifiers.
+ * @var array
+ * @access private
+ */
+ private $aMetaDataIdents = array();
+
+ /**
+ * Array with the date fields.
+ * @var array
+ * @access private
+ */
+ private $aDateFields = array();
+
+ /**
+ * Contenido upload path for current client
+ * @var string
+ * @access private
+ */
+ private $sUploadPath = "";
+
+ /**
+ * Placeholders for labels in frontend.
+ * Important: This must be a static array!
+ * @var array
+ * @access private
+ */
+ private static $aTranslations = array("LABEL_FILESIZE" => "Dateigröße",
+ "LABEL_UPLOAD_DATE" => "Hochgeladen am");
+
+ /**
+ * Constructor of class inits some important class variables and
+ * gets some Contenido global vars, so this class has no need to
+ * use ugly and buggy global commands
+ *
+ * @param string $sContent - xml document from database containing the settings
+ * @param integer $iNumberOfCms - CMS_FILELIST[4] => 4
+ * @param integer $iIdArtLang - Idartlang of current article
+ * @param array $sEditLink - sEditlink for editbuttons, not currently used
+ * @param array $aCfg - Contenido configuration array
+ * @param array $oDB - Contenido database object
+ * @param string $sContenidoLang - Contenido Backend language string
+ * @param integer $iClient - Contenido client id
+ * @param integer $iLang - Contenido frontend language id
+ * @param array $aCfgClient - Contenido Client configuration array
+ * @param object $oSess - Contenido session object
+ *
+ * @access public
+ */
+ function __construct($sContent, $iNumberOfCms, $iIdArtLang, $sEditLink, $aCfg, $oDB, $sContenidoLang, $iClient, $iLang, $aCfgClient, $oSess) {
+ //set arguments to class variables directly
+ $this->aCfg = $aCfg;
+ $this->iId = $iNumberOfCms;
+ $this->iIdArtLang = $iIdArtLang;
+ $this->sContent = urldecode($sContent);
+ $this->iClient = $iClient;
+ $this->iLang = $iLang;
+ $this->aCfgClient = $aCfgClient;
+ $this->oSess = $oSess;
+
+ //init other variables with default values
+ $this->oDb = new DB_ConLite();
+ $this->sUploadPath = $this->aCfgClient[$this->iClient]['upl']['path'];
+
+ //define class array which contains all names of the filelist properties. They were also base for generating dynamic javascripts for
+ //retrival this properties out of html forms and retriving their values to screen
+ $this->aFileListData = array( 'filelist_title', 'filelist_style', 'filelist_directories', 'filelist_incl_subdirectories',
+ 'filelist_manual', 'filelist_sort', 'filelist_incl_metadata', 'filelist_extensions',
+ 'filelist_sortorder', 'filelist_filesizefilter_from', 'filelist_filesizefilter_to',
+ 'filelist_ignore_extensions', 'filelist_manual_files', 'filelist_filecount');
+
+ // defines the default extensions displayed in the filelist
+ // additional extensions can be added via client settings
+ $this->aFileExtensions = array( 'gif', 'jpeg', 'jpg', 'png', 'doc', 'xls', 'pdf', 'txt', 'zip', 'ppt' );
+
+ $this->aDateFields = array( 'ctime' => 'creationdate', 'mtime' => 'modifydate' );
+
+ $this->aMetaDataIdents = array( 'description' => 'Description',
+ 'medianame' => 'Media name',
+ 'copyright' => 'Copyright',
+ 'keywords' => 'Keywords',
+ 'internal_notice' => 'Internal notes');
+
+ // dynamically add file list data based on the meta data idents
+ foreach ( $this->aMetaDataIdents as $sIdentName => $sTranslation ) {
+ $this->aFileListData[] = 'filelist_md_' . $sIdentName . '_limit';
+ }
+
+ // dynamically add file list data based on the date fields
+ foreach ( $this->aDateFields as $sIdentName => $sDateField ) {
+ $this->aFileListData[] = 'filelist_' . $sDateField . 'filter_from';
+ $this->aFileListData[] = 'filelist_' . $sDateField . 'filter_to';
+ }
+
+ //if form is submitted there is a need to store current file list settings
+ //notice: there is also a need, that filelist_id is the same (case: more than one cms file list is used on the same page
+ if (isset($_POST['filelist_action']) && $_POST['filelist_action'] == 'store' &&
+ isset($_POST['filelist_id']) && (int)$_POST['filelist_id'] == $this->iId) {
+ $this->storeFileList();
+ }
+
+ //in sContent XML Document is stored, which contains files settings, call function which parses this document and store
+ //properties as easy accessible array into $aSettings
+ if (trim($this->sContent) != '') {
+ $this->readSettings();
+ }
+ }
+
+ /**
+ * Returns all translation strings for mi18n.
+ *
+ * @param array $aTranslationStrings Array with translation strings
+ * @return array Translation strings
+ */
+ static public function addModuleTranslations($aTranslationStrings) {
+ foreach(self::$aTranslations as $sValue) {
+ $aTranslationStrings[] = $sValue;
+ }
+
+ return $aTranslationStrings;
+ }
+
+
+ /**
+ * Function parses XML document which contains file list settings
+ * and store properties as array into $aSettings
+ *
+ * @access private
+ * @return void
+ */
+ private function readSettings() {
+ //use XMLReader for parsing XML document
+ $oXmlReader = new XMLReader();
+ $oXmlReader->XML($this->sContent);
+
+ $sLastNode = '';
+
+ $bPutInExtArray = $bPutInDirArray = $bPutInFileArray = false;
+
+ $this->aSettings['filelist_extensions'] = array();
+ $this->aSettings['filelist_directories'] = array();
+ $this->aSettings['filelist_manual_files'] = array();
+
+ while($oXmlReader->read()) {
+ switch ($oXmlReader->nodeType) {
+ //read property name (ignore root node or block of manual arts for teaser)
+ case XMLReader::ELEMENT:
+ if ( $oXmlReader->name != 'filelist' &&
+ $oXmlReader->name != 'extensions' &&
+ $oXmlReader->name != 'ext' &&
+ $oXmlReader->name != 'directories' &&
+ $oXmlReader->name != 'dir' &&
+ $oXmlReader->name != 'manual_files' &&
+ $oXmlReader->name != 'file' ) {
+ $sLastNode = 'filelist_'.$oXmlReader->name;
+ $this->aSettings[$sLastNode] = '';
+ }
+
+ if ($oXmlReader->name == 'ext') {
+ $bPutInExtArray = true;
+ }
+
+ if ($oXmlReader->name == 'dir') {
+ $bPutInDirArray = true;
+ }
+
+ if ($oXmlReader->name == 'file') {
+ $bPutInFileArray = true;
+ }
+ break;
+
+ case XMLReader::TEXT:
+ if ($bPutInExtArray == true) {
+ $bPutInExtArray = false;
+ array_push($this->aSettings['filelist_extensions'], $oXmlReader->value);
+ } else if ($bPutInDirArray == true) {
+ $bPutInDirArray = false;
+ array_push($this->aSettings['filelist_directories'], $oXmlReader->value);
+ } else if ($bPutInFileArray == true) {
+ $bPutInFileArray = false;
+ array_push($this->aSettings['filelist_manual_files'], $oXmlReader->value);
+ } else {
+ $this->aSettings[$sLastNode] = $oXmlReader->value;
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Function gets all submitted values for new file list properties from
+ * $_POST array, generates new corresponding config XML Document and
+ * stores it as content, using contenido conSaveContentEntry() function
+ *
+ * @access private
+ * @return void
+ */
+ private function storeFileList() {
+ //create new xml document, its encoding and root node
+ $oXmlDom = new DOMDocument('1.0', 'iso-8859-1');
+ $oXmlDom->formatOutput = true;
+ $oRootNode = $oXmlDom->createElement('filelist');
+ $oXmlDom->appendChild($oRootNode);
+
+ // $this->aFileListData defines all file list properties, so try to read them from $_POST
+ foreach ($this->aFileListData as $sParam) {
+ //in case of article list for manual teaser do a special behaviour
+ if ($sParam == 'filelist_extensions') {
+ $oParam = $oXmlDom->createElement(str_replace('filelist_', '', $sParam));
+ //split all arts to array
+ $aExts = explode(';', Contenido_Security::toString($_POST[$sParam]));
+
+ //for each artid generate subnote in xml document and store its value
+ foreach ($aExts as $sExt) {
+ $sExt = (string) $sExt;
+ if ($sExt != "") {
+ $oExt = $oXmlDom->createElement('ext', $sExt);
+ $oParam->appendChild($oExt);
+ }
+ }
+ } else if ($sParam == 'filelist_directories') {
+ $oParam = $oXmlDom->createElement(str_replace('filelist_', '', $sParam));
+ //split all arts to array
+ $aDirs = explode(';', Contenido_Security::toString($_POST[$sParam]));
+
+ //for each artid generate subnote in xml document and store its value
+ foreach ($aDirs as $sDir) {
+ $sDir = (string) $sDir;
+ if ($sDir != "") {
+ $oDir = $oXmlDom->createElement('dir', $sDir);
+ $oParam->appendChild($oDir);
+ }
+ }
+ } else if ($sParam == 'filelist_manual_files') {
+ $oParam = $oXmlDom->createElement(str_replace('filelist_', '', $sParam));
+ //split all arts to array
+ $aFiles = explode(';', Contenido_Security::toString($_POST[$sParam]));
+
+ //for each artid generate subnote in xml document and store its value
+ foreach ($aFiles as $sFile) {
+ $sFile = (string) $sFile;
+ if ($sFile != "") {
+ $oFile = $oXmlDom->createElement('file', $sFile);
+ $oParam->appendChild($oFile);
+ }
+ }
+ } else if ( $sParam == 'filelist_creationdatefilter_from' || $sParam == 'filelist_creationdatefilter_to' ||
+ $sParam == 'filelist_modifydatefilter_from' || $sParam == 'filelist_modifydatefilter_to' ) {
+
+ $sValue = Contenido_Security::toString($_POST[$sParam]);
+ // check if value is set and if its length equals ten characters
+ // (two for day, two for month, four for year and two for the points)
+ if ( $sValue != "" && $sValue != "DD.MM.YYYY" && strlen( $sValue ) == 10 ) {
+ $aDateSplits = explode(".", $sValue);
+ $iTimestamp = mktime(0, 0, 0, (int) $aDateSplits[1], (int) $aDateSplits[0], (int) $aDateSplits[2]);
+ } else {
+ $iTimestamp = 0;
+ }
+
+ $oParam = $oXmlDom->createElement(str_replace('filelist_', '', $sParam), $iTimestamp);
+ } else {
+ //generate xml node for current property and store its value
+ $oParam = $oXmlDom->createElement(str_replace('filelist_', '', $sParam), Contenido_Security::toString($_POST[$sParam]));
+ }
+
+ $oXmlDom->firstChild->appendChild($oParam);
+ }
+
+ //serialize xml document and store new version in class variable and database
+ conSaveContentEntry($this->iIdArtLang, 'CMS_FILELIST', $this->iId, $oXmlDom->saveXML(), true);
+ $this->sContent = $oXmlDom->saveXML();
+ }
+
+ /**
+ * Function which generate a select box for setting filelist style.
+ * @access private
+ *
+ * @param string $sSelected value of select box which is selected
+ * @return string rendered cHTMLSelectElement
+ */
+ private function getStyleSelect($sSelected) {
+ $oHtmlSelect = new cHTMLSelectElement ('filelist_style', "", 'filelist_style');
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Default Style"), 'cms_filelist_style_default.html', true);
+ $oHtmlSelect->addOptionElement(0, $oHtmlSelectOption);
+
+ $aAdditionalOptions = getEffectiveSettingsByType('cms_filelist_style');
+ $i = 1;
+ foreach ($aAdditionalOptions as $sLabel => $sTemplate) {
+ $oHtmlSelectOption = new cHTMLOptionElement($sLabel, $sTemplate, false);
+ $oHtmlSelect->addOptionElement($i, $oHtmlSelectOption);
+ $i++;
+ }
+
+ $oHtmlSelect->setDefault($sSelected);
+ return $oHtmlSelect->render();
+ }
+
+ /**
+ * Function which generate a select box for the filelist sort.
+ * @access private
+ *
+ * @param string $sSelected value of select box which is selected
+ * @return string rendered cHTMLSelectElement
+ */
+ private function getSortSelect($sSelected) {
+ $oHtmlSelect = new cHTMLSelectElement ('filelist_sort', "", 'filelist_sort');
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Filename"), 'filename', true);
+ $oHtmlSelect->addOptionElement(0, $oHtmlSelectOption);
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("File size"), 'filesize', false);
+ $oHtmlSelect->addOptionElement(1, $oHtmlSelectOption);
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Date created"), 'createdate', false);
+ $oHtmlSelect->addOptionElement(2, $oHtmlSelectOption);
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Date modified"), 'modifydate', false);
+ $oHtmlSelect->addOptionElement(3, $oHtmlSelectOption);
+
+ $oHtmlSelect->setDefault($sSelected);
+
+ return $oHtmlSelect->render();
+ }
+
+ /**
+ * Function which generate a select box for the filelist sort order.
+ * @access private
+ *
+ * @param string $sSelected value of select box which is selected
+ * @return string rendered cHTMLSelectElement
+ */
+ private function getSortOrderSelect($sSelected) {
+ $oHtmlSelect = new cHTMLSelectElement ('filelist_sortorder', "", 'filelist_sortorder');
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Ascending"), 'asc', true);
+ $oHtmlSelect->addOptionElement(0, $oHtmlSelectOption);
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Descending"), 'desc', false);
+ $oHtmlSelect->addOptionElement(1, $oHtmlSelectOption);
+
+ //set default value
+ $oHtmlSelect->setDefault($sSelected);
+
+ return $oHtmlSelect->render();
+ }
+
+ /**
+ * Function which generate a select box for the filelist extensions.
+ * @access private
+ *
+ * @param array $aSelected array with values which are selected
+ * @return string rendered cHTMLSelectElement
+ */
+ private function getExtensionSelect($aSelected) {
+ $oHtmlSelect = new cHTMLSelectElement ('filelist_extensions', "", 'filelist_extensions');
+
+ //set other avariable options manually
+ $i = 1;
+ foreach ( $this->aFileExtensions as $sFileExtension ) {
+ $oHtmlSelectOption = new cHTMLOptionElement( uplGetFileTypeDescription( $sFileExtension ) . " (." . $sFileExtension . ")", $sFileExtension, false );
+ $oHtmlSelectOption->setAlt(uplGetFileTypeDescription( $sFileExtension ) . " (." . $sFileExtension . ")");
+ $oHtmlSelect->addOptionElement($i, $oHtmlSelectOption);
+ $i++;
+ }
+
+ $aAdditionalOptions = getEffectiveSettingsByType('cms_filelist_extensions');
+ foreach ($aAdditionalOptions as $sLabel => $sExtension) {
+ $oHtmlSelectOption = new cHTMLOptionElement( $sLabel . " (." . $sExtension . ")", $sExtension, false );
+ $oHtmlSelectOption->setAlt($sLabel . " (." . $sExtension . ")");
+ $oHtmlSelect->addOptionElement($i, $oHtmlSelectOption);
+ $i++;
+ }
+
+ //set default values
+ $oHtmlSelect->setSelected ( $aSelected );
+ $oHtmlSelect->setMultiselect();
+ $oHtmlSelect->setSize(5);
+ $oHtmlSelect->setClass("manual");
+
+ return $oHtmlSelect->render();
+ }
+
+ /**
+ * Function which generate a select box for the manual files.
+ *
+ * @param array $sDirectoryPath Path to directory of the files
+ * @return string rendered cHTMLSelectElement
+ */
+ public function getFileSelect($sDirectoryPath = "") {
+ $oHtmlSelect = new cHTMLSelectElement ('filelist_filename', "", 'filelist_filename');
+
+ $i = 0;
+ if ($sDirectoryPath != "" ) {
+ $sUploadPath = $this->aCfgClient[$this->iClient]['upl']['path'];
+ $oHandle = opendir($sUploadPath.$sDirectoryPath);
+ while($sEntry = readdir($oHandle)) {
+ if ( $sEntry != "." && $sEntry != ".." &&
+ file_exists( $sUploadPath.$sDirectoryPath."/".$sEntry ) &&
+ !is_dir( $sUploadPath.$sDirectoryPath."/".$sEntry ) ) {
+ $oHtmlSelectOption = new cHTMLOptionElement($sEntry, $sDirectoryPath."/".$sEntry, false);
+ $oHtmlSelect->addOptionElement($i, $oHtmlSelectOption);
+ $i++;
+ }
+ }
+
+ closedir($oHandle);
+ }
+
+ if ( $i == 0 ) {
+ $oHtmlSelectOption = new cHTMLOptionElement( i18n('No files found'), '', false );
+ $oHtmlSelectOption->setAlt( i18n('No files found') );
+ $oHtmlSelectOption->setDisabled( true );
+ $oHtmlSelect->addOptionElement($i, $oHtmlSelectOption);
+ $oHtmlSelect->setDisabled( true );
+ }
+
+ //set default value
+ $oHtmlSelect->setDefault($sSelected);
+
+ return $oHtmlSelect->render();
+ }
+
+ /**
+ * Function which generate a select box for existing files in the manual filelist.
+ *
+ * @param array $sDirectoryPath Path to directory of the files
+ * @return string rendered cHTMLSelectElement
+ */
+ private function getExistingFileSelect() {
+ $aSelectedFiles = $this->aSettings['filelist_manual_files'];
+ $oHtmlSelect = new cHTMLSelectElement ('filelist_manual_files', "", 'filelist_manual_files');
+ $i = 0;
+
+ if (is_array($aSelectedFiles)) {
+ foreach ( $aSelectedFiles as $sSelectedFile ) {
+ $aSplits = explode("/", $sSelectedFile);
+ $iSplitCount = count( $aSplits );
+ $sFileName = $aSplits[$iSplitCount - 1];
+ $oHtmlSelectOption = new cHTMLOptionElement( $sFileName, $sSelectedFile, false );
+ $oHtmlSelectOption->setAlt( $sFileName );
+ $oHtmlSelect->addOptionElement($i, $oHtmlSelectOption);
+ $i++;
+ }
+ }
+
+ //set default values
+ $oHtmlSelect->setMultiselect();
+ $oHtmlSelect->setSize(5);
+ $oHtmlSelect->setClass("manual");
+
+ return $oHtmlSelect->render();
+ }
+
+ public function getMetaDataList() {
+ $oTpl = new Template();
+
+ $i = 1;
+ foreach ( $this->aMetaDataIdents as $sIdentName => $sTranslation ) {
+
+ $iMetaDataLimit = $this->aSettings['filelist_md_' . $sIdentName . '_limit'];
+ if ( !isset ( $iMetaDataLimit ) || $iMetaDataLimit == "" ) {
+ $iMetaDataLimit = 0;
+ }
+
+ $oTpl->set('d', 'METADATA_NAME', $sIdentName);
+ $oTpl->set('d', 'METADATA_DISPLAYNAME', i18n($sTranslation));
+ $oTpl->set('d', 'METADATA_LIMIT', $iMetaDataLimit);
+
+ $i++;
+ $oTpl->next();
+ }
+
+ return $oTpl->generate($this->aCfg['path']['contenido'] . 'templates/standard/template.cms_filelist_metadata_limititem.html', 1);
+ }
+
+ /**
+ * Returns the directory list of an given directory array (by buildDirectoryList()).
+ *
+ * @param array $aDirs Array with directory information
+ * @return string html of the directory list
+ */
+ public function getDirectoryList( $aDirs ) {
+ $oTpl = new Template();
+ $i = 1;
+
+ foreach ( $aDirs as $aDirData ) {
+ $sRelativePath = str_replace( $this->sUploadPath, '', $aDirData['path'] ) . $aDirData['name'];
+ $sLiClasses = '';
+
+ if ( is_array( $this->aSettings['filelist_directories'] ) && in_array( $sRelativePath, $this->aSettings['filelist_directories'] ) ) {
+ $oTpl->set('d', 'DIVCLASS', ' class="active"');
+ } else {
+ $oTpl->set('d', 'DIVCLASS', '');
+ }
+
+ $oTpl->set('d', 'TITLE', $sRelativePath);
+ $oTpl->set('d', 'DIRNAME', $aDirData['name']);
+
+ $bGo = false;
+
+ if (is_array($this->aSettings['filelist_directories'])) {
+ foreach ( $this->aSettings['filelist_directories'] as $sDirectoryName ) {
+ if ( preg_match ('#^'.$sRelativePath.'/.*#', $sDirectoryName) ) {
+ $bGo = true;
+ break;
+ }
+ }
+ }
+
+ if ( $bGo == true ) {
+ $oTpl->set('d', 'SUBDIRLIST', $this->getDirectoryList( $aDirData['sub'] ) );
+ } else if ( isset( $aDirData['sub'] ) && count( $aDirData['sub'] ) > 0 ) {
+ $sLiClasses .= " collapsed";
+ $oTpl->set('d', 'SUBDIRLIST', '');
+ } else {
+ $oTpl->set('d', 'SUBDIRLIST', '');
+ }
+
+ if ($i == count($aDirs)) {
+ $sLiClasses .= " last";
+ }
+
+ if ( $sLiClasses != "" ) {
+ $oTpl->set('d', 'LICLASS', ' class="'.substr($sLiClasses, 1).'"');
+ } else {
+ $oTpl->set('d', 'LICLASS', '');
+ }
+
+ $i++;
+ $oTpl->next();
+ }
+
+ return $oTpl->generate($this->aCfg['path']['contenido'] . 'templates/standard/template.cms_filelist_dirlistitem.html', 1);
+ }
+
+ /**
+ * Builds a directory list by a given upload directory path.
+ *
+ * @param string $sUploadPath Path to directory (per default the root upload path of client)
+ * @return array Array with directory information
+ */
+ public function buildDirectoryList( $sUploadPath = "" ) {
+ if ( $sUploadPath == "") {
+ $sUploadPath = $this->sUploadPath;
+ }
+
+ if ( substr( $sUploadPath, -1 ) != "/" ) {
+ $sUploadPath = $sUploadPath."/";
+ }
+
+ $aDirectories = array();
+ $oHandle = opendir($sUploadPath);
+ $i = 0;
+ while($sEntry = readdir($oHandle)) {
+ if ( $sEntry != "." && $sEntry != ".." && is_dir( $sUploadPath . $sEntry ) ) {
+ $aDirectories[$i]['name'] = $sEntry;
+ $aDirectories[$i]['path'] = $sUploadPath;
+ $aDirectories[$i]['sub'] = $this->buildDirectoryList( $sUploadPath . $sEntry );
+ $i++;
+ }
+ }
+
+ closedir($oHandle);
+ return $aDirectories;
+ }
+
+ /**
+ * Function is called in editmode of contenido an returns filelist view and editbutton
+ *
+ * @return string code for the backend edit view
+ */
+ public function getAllWidgetEdit() {
+ $oTpl = new Template();
+
+ /*Set some values into javascript for a better handling*/
+ $oTpl->set('s', 'CON_PATH', $this->aCfg['path']['contenido_fullhtml']);
+ $oTpl->set('s', 'ID', $this->iId);
+ $oTpl->set('s', 'IDARTLANG', $this->iIdArtLang);
+ $oTpl->set('s', 'CONTENIDO', $_REQUEST['contenido']);
+ $oTpl->set('s', 'FIELDS', "'".implode("','",$this->aFileListData)."'");
+
+ if ( $this->aSettings['filelist_ignore_extensions'] == 'on' ) {
+ $oTpl->set('s', 'IGNOREEXTENSIONS', 'true');
+ } else {
+ $oTpl->set('s', 'IGNOREEXTENSIONS', 'false');
+ }
+
+ /*Start set a lot of translations*/
+ $oTpl->set('s', 'DIRECTORIES', i18n("Directories"));
+ $oTpl->set('s', 'GENERAL', i18n("General"));
+ $oTpl->set('s', 'MANUAL', i18n("Manual"));
+ $oTpl->set('s', 'FILTER', i18n("Filter"));
+
+ $oTpl->set('s', 'LABEL_GENERAL', i18n("General Settings"));
+ $oTpl->set('s', 'LABEL_MANUAL', i18n("Manual Settings"));
+ $oTpl->set('s', 'LABEL_FILTER', i18n("Filter settings"));
+ $oTpl->set('s', 'LABEL_FILELIST_SETTINGS', i18n("File list settings"));
+ $oTpl->set('s', 'LABEL_FILELIST_TITLE', i18n("File list title"));
+ $oTpl->set('s', 'LABEL_FILELIST_FILESIZE_LIMIT', i18n("File size limit"));
+ $oTpl->set('s', 'LABEL_FILELIST_CREATIONDATE_LIMIT', i18n("Creation date limit"));
+ $oTpl->set('s', 'LABEL_FILELIST_MODIFYDATE_LIMIT', i18n("Modify date limit"));
+
+ $oTpl->set('s', 'LABEL_STYLE', i18n("File list style"));
+ $oTpl->set('s', 'LABEL_SOURCE_DIRECTORY', i18n("Source directory"));
+ $oTpl->set('s', 'LABEL_INCLUDE_SUBDIRECTORIES', i18n('Include subdirectories?'));
+ $oTpl->set('s', 'LABEL_INCLUDE_METADATA', i18n('Include meta data?'));
+ $oTpl->set('s', 'LABEL_SORT', i18n("File list sort"));
+ $oTpl->set('s', 'LABEL_SORTORDER', i18n("Sort order"));
+ $oTpl->set('s', 'LABEL_FILE_EXTENSIONS', i18n("Displayed file extensions"));
+ $oTpl->set('s', 'LABEL_IGNORESELECTION', i18n('Ignore selection (use all)'));
+ $oTpl->set('s', 'LABEL_SELECTIONWILLBEIGNORED', i18n('Selection will be ignored!'));
+ $oTpl->set('s', 'LABEL_SELECTALLENTRIES', i18n('Select all entries'));
+ $oTpl->set('s', 'LABEL_MANUAL_FILELIST', i18n("Use manual file list?"));
+ $oTpl->set('s', 'LABEL_DIRECTORY', i18n("Directory"));
+ $oTpl->set('s', 'LABEL_FILE', i18n("File"));
+ $oTpl->set('s', 'LABEL_FILES', i18n("Files"));
+ $oTpl->set('s', 'LABEL_EXISTING_FILES', i18n("Existing files"));
+ $oTpl->set('s', 'LABEL_ADD_FILE', i18n("Add file"));
+ $oTpl->set('s', 'LABEL_FILECOUNT', i18n("File count"));
+ /*End set a lot of translations*/
+
+ /*Start set values into configuration array and generate select boxes used previous defined values*/
+ $oTpl->set('s', 'FILELIST_TITLE', $this->aSettings['filelist_title']);
+ $oTpl->set('s', 'STYLE_SELECT', $this->getStyleSelect($this->aSettings['filelist_style']));
+ $oTpl->set('s', 'DIRECTORY_LIST', $this->getDirectoryList( $this->buildDirectoryList() ));
+ $oTpl->set('s', 'EXTENSION_LIST', $this->getExtensionSelect($this->aSettings['filelist_extensions']));
+
+ if ( $this->aSettings['filelist_incl_subdirectories'] == 'true' ) {
+ $oTpl->set('s', 'FILELIST_INCL_SUBDIRECTORIES', 'checked="checked"');
+ } else {
+ $oTpl->set('s', 'FILELIST_INCL_SUBDIRECTORIES', '');
+ }
+
+ if ( $this->aSettings['filelist_incl_metadata'] == 'true' ) {
+ $oTpl->set('s', 'FILELIST_INCL_METADATA', 'checked="checked"');
+ } else {
+ $oTpl->set('s', 'FILELIST_INCL_METADATA', '');
+ }
+
+ if ( $this->aSettings['filelist_manual'] == 'true' ) {
+ $oTpl->set('s', 'FILELIST_MANUAL', 'checked="checked"');
+ } else {
+ $oTpl->set('s', 'FILELIST_MANUAL', '');
+ }
+
+ foreach ( $this->aDateFields as $sDateField ) {
+ if ( $this->aSettings['filelist_' . $sDateField . 'filter_from'] != 0 ) {
+ $oTpl->set('s', 'FILELIST_' . strtoupper( $sDateField ) . 'FILTER_FROM', date("d.m.Y", $this->aSettings['filelist_' . $sDateField . 'filter_from']));
+ } else {
+ $oTpl->set('s', 'FILELIST_' . strtoupper( $sDateField ) . 'FILTER_FROM', 'DD.MM.YYYY');
+ }
+
+ if ( $this->aSettings['filelist_' . $sDateField . 'filter_to'] != 0 ) {
+ $oTpl->set('s', 'FILELIST_' . strtoupper( $sDateField ) . 'FILTER_TO', date("d.m.Y", $this->aSettings['filelist_' . $sDateField . 'filter_to']));
+ } else {
+ $oTpl->set('s', 'FILELIST_' . strtoupper( $sDateField ) . 'FILTER_TO', 'DD.MM.YYYY');
+ }
+ }
+
+ $iFilesizeLimitFrom = $this->aSettings['filelist_filesizefilter_from'];
+ if ( $iFilesizeLimitFrom == "" ) {
+ $iFilesizeLimitFrom = 0;
+ }
+
+ $iFilesizeLimitTo = $this->aSettings['filelist_filesizefilter_to'];
+ if ( $iFilesizeLimitTo == "" ) {
+ $iFilesizeLimitTo = 0;
+ }
+
+ $iFileCount = $this->aSettings['filelist_filecount'];
+ if ( $iFileCount == "" ) {
+ $iFileCount = 0;
+ }
+
+ $oTpl->set('s', 'FILELIST_FILESIZEFILTER_FROM', $iFilesizeLimitFrom);
+ $oTpl->set('s', 'FILELIST_FILESIZEFILTER_TO', $iFilesizeLimitTo);
+ $oTpl->set('s', 'FILELIST_FILECOUNT', $iFileCount);
+ $oTpl->set('s', 'SORT_SELECT', $this->getSortSelect($this->aSettings['filelist_sort']));
+ $oTpl->set('s', 'FILE_SELECT', $this->getFileSelect());
+ $oTpl->set('s', 'SORTORDER_SELECT', $this->getSortOrderSelect($this->aSettings['filelist_sortorder']));
+ $oTpl->set('s', 'METADATALIST', $this->getMetaDataList());
+ $oTpl->set('s', 'MANUAL_OPTIONS', $this->getExistingFileSelect());
+ /*End set values into configuration array and generate select boxes used previous defined values*/
+
+ $sCode = $oTpl->generate($this->aCfg['path']['contenido'].'templates/standard/template.cms_filelist_edit.html', 1);
+ return $this->getAllWidgetView( true ) . $this->encodeForOutput($sCode);
+ }
+
+ /**
+ * In Contenido content type code is evaled by php. To make this possible,
+ * this function prepares code for evaluation
+ *
+ * @access private
+ *
+ * @param string $sCode code to escape
+ * @return string escaped code
+ */
+ private function encodeForOutput($sCode) {
+ $sCode = (string) $sCode;
+
+ $sCode = AddSlashes(AddSlashes($sCode));
+ $sCode = str_replace("\\\'", "'", $sCode);
+ $sCode = str_replace("\$", '\\\$', $sCode);
+
+ return $sCode;
+ }
+
+ /**
+ * Method to fill single entry (file) of the file list.
+ *
+ * @access private
+ *
+ * @param array $aFileData Array with information about the file
+ * @param object $oTpl Reference of the used template object
+ * @return void
+ */
+ private function fillFileListTemplateEntry($aFileData, &$oTpl) {
+ global $cCurrentModule;
+
+ $sFilename = $aFileData['filename'];
+ $sDirectoryName = $aFileData['path'];
+ $sFileExtension = $aFileData['extension'];
+ $sFileLink = $this->aCfgClient[$this->iClient]['upl']['htmlpath'] . $sDirectoryName . "/" . $sFilename;
+
+ $iFilesize = $aFileData['filesize'];
+ $sFileCreationDate = date( "d.m.Y", $aFileData['filecreationdate'] );
+ $sFileModifyDate = date( "d.m.Y", $aFileData['filemodifydate'] );
+
+ $aMetaData = $aFileData['metadata'];
+
+ $sFilesizeUnit = "Byte";
+ if ( $iFilesize < 1024 ) {
+ $sFilesizeUnit = "Byte";
+ } else if ( $iFilesize < ( 1024 * 1024) ) {
+ $iFilesize = $iFilesize / 1024;
+ $sFilesizeUnit = "KB";
+ } else if ( $iFilesize < ( 1024 * 1024 * 1024 ) ) {
+ $iFilesize = $iFilesize / 1024 / 1024;
+ $sFilesizeUnit = "MB";
+ } else if ( $iFilesize < ( 1024 * 1024 * 1024 * 1024 ) ) {
+ $iFilesize = $iFilesize / 1024 / 1024 / 1024;
+ $sFilesizeUnit = "GB";
+ }
+
+ $sFilesize = number_format( $iFilesize, 2, ',', '.');
+
+ if ( $this->aSettings['filelist_incl_metadata'] == 'true' && count ( $aMetaData ) != 0 ) {
+ $oTpl->set('d', 'FILEMETA_DESCRIPTION', $aMetaData['description']);
+ $oTpl->set('d', 'FILEMETA_MEDIANAME', $aMetaData['medianame']);
+ $oTpl->set('d', 'FILEMETA_KEYWORDS', $aMetaData['keywords']);
+ $oTpl->set('d', 'FILEMETA_INTERNAL_NOTICE', $aMetaData['internal_notice']);
+ $oTpl->set('d', 'FILEMETA_COPYRIGHT', $aMetaData['copyright']);
+ } else {
+ $oTpl->set('d', 'FILEMETA_DESCRIPTION', '');
+ $oTpl->set('d', 'FILEMETA_MEDIANAME', '');
+ $oTpl->set('d', 'FILEMETA_KEYWORDS', '');
+ $oTpl->set('d', 'FILEMETA_INTERNAL_NOTICE', '');
+ $oTpl->set('d', 'FILEMETA_COPYRIGHT', '');
+ }
+
+ $oTpl->set('d', 'FILESIZE_UNIT', $sFilesizeUnit);
+ $oTpl->set('d', 'FILENAME', $sFilename);
+ $oTpl->set('d', 'FILESIZE', $sFilesize);
+ $oTpl->set('d', 'FILEEXTENSION', $sFileExtension);
+ $oTpl->set('d', 'FILECREATIONDATE', $sFileCreationDate);
+ $oTpl->set('d', 'FILEMODIFYDATE', $sFileModifyDate);
+ $oTpl->set('d', 'FILEDIRECTORY', $sDirectoryName);
+ $oTpl->set('d', 'FILELINK', $sFileLink);
+
+ foreach( self::$aTranslations as $sKey => $sValue ) {
+ $oTpl->set('d', $sKey, mi18n( $sValue ));
+ }
+
+ $oTpl->next();
+ return true;
+ }
+
+ /**
+ * Dynamic filelist generator.
+ * This method is executed every time the filelist is displayed.
+ *
+ * @return string output of the filelist
+ */
+ public function getAllWidgetView() {
+ $sCode = '\";?>getAllWidgetOutput();
+ ?>sContent, $this->iId);
+ return $sCode;
+ }
+
+ /**
+ * Checks recursively for sub directories
+ *
+ * @param string $sDirectoryPath Path to directory
+ * @param array $aDirectories Directory array
+ *
+ * @return array Directory array
+ */
+ public function recursiveCheckForSubdirectories( $sDirectoryPath, $aDirectories ) {
+ $oHandle = opendir($this->sUploadPath.$sDirectoryPath);
+ while($sEntry = readdir($oHandle)) {
+ if ( $sEntry != "." && $sEntry != ".." &&
+ is_dir( $this->sUploadPath.$sDirectoryPath."/".$sEntry ) ) {
+ $aDirectories[] = $sDirectoryPath."/".$sEntry;
+ $aDirectories = $this->recursiveCheckForSubdirectories( $sDirectoryPath."/".$sEntry, $aDirectories );
+ }
+ }
+
+ return $aDirectories;
+ }
+
+ /**
+ * Performs all date filters of a file.
+ *
+ * @param array $aFileStats Array with file information
+ *
+ * @return boolean check state (true = tests passed, false = tests not passed)
+ */
+ private function performFileDateFilters ( $aFileStats ) {
+ $bDateCheck = false;
+ foreach ( $this->aDateFields as $sIndex => $sDateField ) {
+ $iDate = $aFileStats[$sIndex];
+ if ( $this->aSettings['filelist_' . $sDateField . 'filter_from'] == 0 && $this->aSettings['filelist_' . $sDateField . 'filter_from'] == 0 ) {
+ $bDateCheck = true;
+ } else if ( $this->aSettings['filelist_' . $sDateField . 'filter_to'] == 0 &&
+ $iDate >= $this->aSettings['filelist_' . $sDateField . 'filter_from'] ) {
+ $bDateCheck = true;
+ } else if ( $this->aSettings['filelist_' . $sDateField . 'filter_from'] == 0 &&
+ $iDate <= $this->aSettings['filelist_' . $sDateField . 'filter_to'] ) {
+ $bDateCheck = true;
+ } else if ( $this->aSettings['filelist_' . $sDateField . 'filter_from'] != 0 &&
+ $this->aSettings['filelist_' . $sDateField . 'filter_to'] != 0 &&
+ $iDate >= $this->aSettings['filelist_' . $sDateField . 'filter_from'] &&
+ $iDate <= $this->aSettings['filelist_' . $sDateField . 'filter_to'] ) {
+ $bDateCheck = true;
+ }
+ }
+
+ return $bDateCheck;
+ }
+
+ /**
+ * Executes the file filters which removes all files not matching the filter criterias.
+ *
+ * @param array $aFileList array with files to check
+ *
+ * @return array array with filtered files
+ */
+ private function applyFileFilters ( $aFileList ) {
+ foreach ( $aFileList as $iIndex => $sFullname ) {
+ $sFilename = basename( $sFullname );
+ $sDirectoryName = str_replace( "/" . $sFilename, '', $sFullname );
+
+ // checking the extension stuff
+ $sExtensionName = uplGetFileExtension( $sFilename );
+
+ if ( $this->aSettings['filelist_ignore_extensions'] == "on" || count( $this->aSettings['filelist_extensions'] ) == 0 ||
+ ( $this->aSettings['filelist_ignore_extensions'] == "off" && in_array( $sExtensionName, $this->aSettings['filelist_extensions'] ) ) ) {
+
+ // checking filesize filter
+ $aFileStats = stat( $this->sUploadPath.$sDirectoryName."/".$sFilename );
+ $iFilesize = $aFileStats['size'];
+
+ $iFilesizeMib = $iFilesize / 1024 / 1024;
+ if ( ( $this->aSettings['filelist_filesizefilter_from'] == 0 &&
+ $this->aSettings['filelist_filesizefilter_to'] == 0 )
+ ||
+ ( $this->aSettings['filelist_filesizefilter_from'] <= $iFilesizeMib &&
+ $this->aSettings['filelist_filesizefilter_to'] >= $iFilesizeMib) ) {
+
+ $bDateCheck = $this->performFileDateFilters ( $aFileStats );
+
+ $iCreationDate = $aFileStats['ctime'];
+ $iModifyFate = $aFileStats['mtime'];
+
+ if ( $bDateCheck == true ) {
+ // conditional stuff is completed, start sorting
+ switch ( $this->aSettings['filelist_sort'] ) {
+ case "filesize":
+ $sIndexName = $iFilesize;
+ break;
+ case "createdate":
+ $sIndexName = $iCreationDate;
+ break;
+ case "modifydate":
+ $sIndexName = $iModifyDate;
+ break;
+ case "filename":
+ default:
+ $sIndexName = strtolower ( $sFilename );
+ }
+
+ if ( $sLastIndex == $sIndexName ) {
+ $j++;
+ } else {
+ $j = 1;
+ }
+ // save current index name
+ $sLastIndex = $sIndexName;
+ $sIndexName = $sIndexName . "." . $j;
+
+ $aFiles[$sIndexName] = array();
+ $aFiles[$sIndexName]['filename'] = $sFilename;
+ $aFiles[$sIndexName]['path'] = $sDirectoryName;
+ $aFiles[$sIndexName]['extension'] = $sExtensionName;
+ $aFiles[$sIndexName]['filesize'] = $iFilesize;
+ $aFiles[$sIndexName]['filemodifydate'] = $iModifyDate;
+ $aFiles[$sIndexName]['filecreationdate'] = $iCreationDate;
+ $i++;
+ } // end if date check
+ } // end if filesize filter
+ } // end if extensions
+ } // end foreach
+
+ return $aFiles;
+ }
+
+ /**
+ * Function is called in edit- and viewmode in order to generate code for output.
+ *
+ * @return string generated code
+ */
+ public function getAllWidgetOutput() {
+ $oTpl = new Template();
+ $aFileList = array();
+ //set title of teaser
+ if ( $this->aSettings['filelist_style'] != "" ) {
+ $oTpl->set('s', 'TITLE', $this->aSettings['filelist_title']);
+ $oTpl->set('s', 'ERROR', '-', 1);
+
+ if ( $this->aSettings['filelist_manual'] == 'true' && count( $this->aSettings['filelist_manual_files'] ) > 0 ) {
+ $aFileList = $this->aSettings['filelist_manual_files'];
+ } else {
+ if ( count ( $this->aSettings['filelist_directories'] ) > 0 ) {
+ $aDirectories = $this->aSettings['filelist_directories'];
+
+ if ( $this->aSettings['filelist_incl_subdirectories'] == 'true' ) {
+ foreach ( $aDirectories as $sDirectoryName ) {
+ $aDirectories = $this->recursiveCheckForSubdirectories($sDirectoryName, $aDirectories);
+ }
+ }
+
+ // strip duplicate directories to save performance
+ $aDirectories = array_unique( $aDirectories );
+
+ foreach ( $aDirectories as $sDirectoryName ) {
+ $oHandle = opendir( $this->sUploadPath . $sDirectoryName );
+
+ while( $sEntry = readdir( $oHandle ) ) {
+ // checking if entry is file and is not a directory
+ if ( $sEntry != "." && $sEntry != ".." && !is_dir( $this->sUploadPath . $sDirectoryName . "/" . $sEntry ) ) {
+ $aFileList[] = $sDirectoryName . "/" . $sEntry;
+ }
+ }
+ closedir( $oHandle );
+ }
+ }
+ }
+
+ $aFiles = $this->applyFileFilters( $aFileList );
+ unset( $aFileList );
+
+ if ( count ( $aFiles ) > 0 ) {
+ // check for descending sort order...
+ if ( $this->aSettings['filelist_sortorder'] == 'desc' ) {
+ krsort( $aFiles ) ;
+ } else {
+ ksort ( $aFiles );
+ }
+
+ $i = 1;
+ foreach ( $aFiles as $aFilenameData ) {
+ if ( ( $this->aSettings['filelist_filecount'] != 0 && $i <= $this->aSettings['filelist_filecount'] ) ||
+ $this->aSettings['filelist_filecount'] == 0 ) {
+ if ( $this->aSettings['filelist_incl_metadata'] == 'true' ) {
+ $aMetaData = array();
+ $this->oDb->query('SELECT upl.idupl, uplmeta.* FROM ' . $this->aCfg['tab']['upl'] . ' AS upl, ' . $this->aCfg['tab']['upl_meta'] . ' AS uplmeta WHERE upl.idupl = uplmeta.idupl AND upl.filename=\''.$aFilenameData['filename'].'\' AND upl.dirname=\''.$aFilenameData['path'].'/\' AND upl.idclient=\''.$this->iClient.'\' AND uplmeta.idlang=\''.$this->iLang.'\'');
+ $this->oDb->next_record();
+
+ foreach ( $this->aMetaDataIdents as $sIdentName => $sTranslation ) {
+ if ( $this->aSettings['filelist_md_' . $sIdentName . '_limit'] > 0 ) {
+ $aMetaData[$sIdentName] = capiStrTrimAfterWord( Contenido_Security::unFilter( $this->oDb->f($sIdentName) ),
+ $this->aSettings['filelist_md_' . $sIdentName . '_limit'] ) . '...';
+ } else {
+ $aMetaData[$sIdentName] = Contenido_Security::unFilter( $this->oDb->f($sIdentName) );
+ }
+ }
+
+ $aFilenameData['metadata'] = $aMetaData;
+ } else {
+ $aFilenameData['metadata'] = array();
+ }
+ $this->fillFileListTemplateEntry( $aFilenameData, $oTpl );
+ $i++;
+ }
+ }
+
+ //generate template
+ $sCode = $oTpl->generate($this->aCfgClient[$this->iClient]['path']['frontend'].'templates/' . $this->aSettings['filelist_style'], 1);
+ }
+ }
+
+ return $sCode;
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.cms_teaser.php b/conlite/classes/class.cms_teaser.php
new file mode 100644
index 0000000..bb430d3
--- /dev/null
+++ b/conlite/classes/class.cms_teaser.php
@@ -0,0 +1,1058 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release 4.8.12
+ *
+ * {@internal
+ * created 2009-04-08
+ * modified 2009-04-14 - added possibility to expand template select by client or system setting using type 'cms_teaser'
+ * modofied 2009-04-21 - added seperate handling for xhtml
+ * modified 2009-05-04 - added sort order sequence
+ * modified 2009-10-01 - Dominik Ziegler, fixed session bug in link
+ * modified 2009-10-12 - Dominik Ziegler, fixed online/offline articles, dynamic teaser generation and translation implemented
+ * modified 2009-10-16 - Dominik Ziegler, added manual date support
+ * modified 2010-01-21 - Dominik Ziegler, strip tags from manual teaser date
+ *
+ * $Id: class.cms_teaser.php 312M 2016-08-12 13:28:16Z (local) $:
+ * }}
+ *
+ */
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+cInclude('includes', 'functions.con.php');
+cInclude('includes', 'functions.api.images.php');
+
+/**
+ * Class handles content type teaser, its editmode and viewmode. All properties of teaser content type
+ * were stored as xml document in database as content in {prefix}_content
+ *
+ */
+class Cms_Teaser {
+
+ /**
+ * Contenido configuration array
+ *
+ * @var array
+ * @access private
+ */
+ private $aCfg;
+
+ /**
+ * Current id of content type CMS_TEASER[3] -> 3
+ *
+ * @var integer
+ * @access private
+ */
+ private $iId;
+
+ /**
+ * Contenido database object
+ *
+ * @var object
+ * @access private
+ */
+ private $oDb;
+
+ /**
+ * Idartlang of article, which is currently in edit- or viewmode
+ *
+ * @var integer
+ * @access private
+ */
+ private $iIdArtLang;
+
+ /**
+ * List of fieldnames in frontend (properties) which the teaser has
+ * and which were also described in the config xml document
+ *
+ * @var array
+ * @access private
+ */
+ private $aTeaserData;
+
+ /**
+ * String contains value of stored content in database
+ * in this case this is the config xml document which is
+ * later parsed and its settings were stored in $aSettings
+ *
+ * @var string
+ * @access private
+ */
+ private $sContent;
+
+ /**
+ * Array which contains current teaser settings
+ *
+ * @var array
+ * @access private
+ */
+ private $aSettings;
+
+ /**
+ * Array which contains all avariable CMS_Types and its ids
+ * in current Contenido isntallation (described as hash [idtype => cmstypename])
+ *
+ * @var array
+ * @access private
+ */
+ private $aCMSTypes;
+
+ /**
+ * current Contenido client id
+ *
+ * @var integer
+ * @access private
+ */
+ private $iClient;
+
+ /**
+ * current Contenido language id
+ *
+ * @var integer
+ * @access private
+ */
+ private $iLang;
+
+ /**
+ * Contenido Session object
+ *
+ * @var object
+ * @access private
+ */
+ private $oSess;
+
+ /**
+ * Contenido configuration array for currently active client
+ *
+ * @var array
+ * @access private
+ */
+ private $aCfgClient;
+
+ /**
+ * print XHTML
+ *
+ * @var string
+ * @access private
+ */
+ private $sUseXHTML;
+
+ /**
+ * Placeholders for labels in frontend.
+ * Important: This must be a static array!
+ * @var array
+ * @access private
+ */
+ private static $aTranslations = array("MORE" => "mehr");
+
+ /**
+ * Constructor of class inits some important class variables and
+ * gets some Contenido global vars, so this class has no need to
+ * use ugly and buggy global commands
+ *
+ * @param string $sContent - xml document from database containing teaser settings
+ * @param integer $iNumberOfCms - CMS_TEASER[4] => 4
+ * @param integer $iIdArtLang - Idartlang of current article
+ * @param array $sEditLink - sEditlink for editbuttons, not currently used
+ * @param array $aCfg - Contenido configuration array
+ * @param array $oDB - Contenido database object (not used because we need own object (else problems by cross query in same object))
+ * @param string $sContenidoLang - Contenido Backend language string
+ * @param integer $iClient - Contenido client id
+ * @param integer $iLang - Contenido frontend language id
+ * @param array $aCfgClient - Contenido Client configuration array
+ *
+ * @access public
+ */
+ function __construct($sContent, $iNumberOfCms, $iIdArtLang, $sEditLink, $aCfg, $oDB, $sContenidoLang, $iClient, $iLang, $aCfgClient, $oSess) {
+ //set arguments to class variables directly
+ $this->aCfg = $aCfg;
+ $this->iId = $iNumberOfCms;
+ $this->iIdArtLang = $iIdArtLang;
+ $this->sContent = urldecode($sContent);
+ $this->iClient = $iClient;
+ $this->iLang = $iLang;
+ $this->aCfgClient = $aCfgClient;
+ $this->oSess = $oSess;
+
+ if (!array_key_exists("generate_xhtml", $aCfg)) {
+ $this->sUseXHTML = getEffectiveSetting("generator", "xhtml", 'false');
+ } else {
+ $this->sUseXHTML = $aCfg['generate_xhtml'];
+ }
+
+ //init other variables with default values
+ $this->aCMSTypes = null;
+ $this->aSettings = array();
+ $this->oDb = new DB_ConLite();
+
+ //define class array which contains all names of teaser properties. They were also base for generating dynamic javascripts for
+ //retrival this properties out of html forms and retriving their values to screen
+ $this->aTeaserData = array('teaser_title', 'teaser_category', 'teaser_count', 'teaser_style', 'teaser_manual',
+ 'teaser_start', 'teaser_source_head', 'teaser_source_head_count', 'teaser_source_text',
+ 'teaser_source_text_count', 'teaser_source_image', 'teaser_source_image_count', 'teaser_filter',
+ 'teaser_sort', 'teaser_sort_order', 'teaser_character_limit', 'teaser_image_width',
+ 'teaser_image_height', 'teaser_manual_art', 'teaser_image_crop', 'teaser_source_date',
+ 'teaser_source_date_count');
+
+ //if form is submitted there is a need to store current teaser settings
+ //notice: there is also a need, that teaser_id is the same (case: more than ohne cms teaser is used on the same page
+ if (isset($_POST['teaser_action']) && $_POST['teaser_action'] == 'store' &&
+ isset($_POST['teaser_id']) && (int) $_POST['teaser_id'] == $this->iId) {
+ $this->storeTeaser();
+ }
+
+ //in sContent XML Document is stored, which contains teaser settings, call function which parses this document and store
+ //properties as easy accessible array into $aSettings
+ if (trim($this->sContent) != '') {
+ $this->readSettings();
+ }
+
+ $this->setDefaultValues();
+ }
+
+ /**
+ * Returns all translation strings for mi18n.
+ *
+ * @param array $aTranslationStrings Array with translation strings
+ * @return array Translation strings
+ */
+ static public function addModuleTranslations($aTranslationStrings) {
+ foreach (self::$aTranslations as $sValue) {
+ $aTranslationStrings[] = $sValue;
+ }
+
+ return $aTranslationStrings;
+ }
+
+ /**
+ * Functen parses XML Document which contains teaser settings
+ * and store properties as array into $aSettings
+ *
+ * @access private
+ */
+ private function readSettings() {
+ //use XMLReader for parsing XML document
+ $oXmlReader = new XMLReader();
+ $oXmlReader->XML($this->sContent);
+ //store nodename in order to retrive property name when content of node is read
+ $sLastNode = '';
+ //in xml document there is a block in this artids for manual teaser were stored
+ //if we were in this block store all values to an art array
+ //this variable defines if we were in this block or not
+ $bPutInArtArray = false;
+ //array for previous described manual art array
+ $this->aSettings['teaser_manual_art'] = array();
+
+ while ($oXmlReader->read()) {
+ switch ($oXmlReader->nodeType) {
+ //read property name (ignore root node or block of manual arts for teaser)
+ case XMLReader::ELEMENT:
+ if ($oXmlReader->name != 'teaser' && $oXmlReader->name != 'manual_art' && $oXmlReader->name != 'art') {
+ $sLastNode = 'teaser_' . $oXmlReader->name;
+ $this->aSettings[$sLastNode] = '';
+ }
+ //if we reach node store all subnotes to artnode array
+ if ($oXmlReader->name == 'art') {
+ $bPutInArtArray = true;
+ }
+ break;
+
+ //in case of a textnode we have previous propertyname and corrsponding value -> store into aSettings
+ //if we were in mode store to corresponding array
+ case XMLReader::TEXT:
+ if ($bPutInArtArray == true) {
+ $bPutInArtArray = false;
+ array_push($this->aSettings['teaser_manual_art'], Contenido_Security::unfilter($oXmlReader->value));
+ } else {
+ $this->aSettings[$sLastNode] = Contenido_Security::unfilter($oXmlReader->value);
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Function gets all submitted values for new teaser properties from
+ * $_POST array, generates new corresponding config XML Document and
+ * stores it as content, using contenido conSaveContentEntry() function
+ *
+ * @access private
+ */
+ private function storeTeaser() {
+ //create new xml document, its encoding and root node
+ $oXmlDom = new DOMDocument('1.0', 'iso-8859-1');
+ $oXmlDom->formatOutput = true;
+ $oRootNode = $oXmlDom->createElement('teaser');
+ $oXmlDom->appendChild($oRootNode);
+
+ //$this->aTeaserData defines all teaser properties, so try to read them from %_POST
+ foreach ($this->aTeaserData as $sParam) {
+ //in case of article list for manual teaser do a special behaviour
+ if ($sParam == 'teaser_manual_art') {
+ $oParam = $oXmlDom->createElement(str_replace('teaser_', '', $sParam));
+ //split all arts to array
+ $aArts = explode(';', Contenido_Security::toString($_POST[$sParam]));
+ //for each artid generate subnote in xml document and store its value
+ foreach ($aArts as $iArt) {
+ $iArt = (int) $iArt;
+ if ($iArt > 0) {
+ $oArt = $oXmlDom->createElement('art', $iArt);
+ $oParam->appendChild($oArt);
+ }
+ }
+ } else {
+ //generate xml node for current property and store its value
+ $oParam = $oXmlDom->createElement(str_replace('teaser_', '', $sParam), Contenido_Security::filter($_POST[$sParam], $this->oDb));
+ }
+
+ $oXmlDom->firstChild->appendChild($oParam);
+ }
+
+ //serialize xml document and store new version in class variable and database
+ conSaveContentEntry($this->iIdArtLang, 'CMS_TEASER', $this->iId, $oXmlDom->saveXML(), true);
+ $this->sContent = $oXmlDom->saveXML();
+ }
+
+ /**
+ * Function which generated a select box for setting number of articles which were
+ * displayed in teaser as a maximum. Only important in editmode
+ *
+ * @param string $sSelected - value of select box which is selected
+ * @return html string of select box
+ *
+ * @access private
+ */
+ private function getCountSelect($sSelected) {
+ $this->oDb = new DB_ConLite();
+
+ $oHtmlSelect = new cHTMLSelectElement('teaser_count', "", 'teaser_count');
+
+ //set please chose option element
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Please choose"), '', true);
+ $oHtmlSelect->addOptionElement(0, $oHtmlSelectOption);
+
+ //generate a select box containing count 1 to 20 for maximum teaser count
+ for ($i = 1; $i <= 20; $i++) {
+ $oHtmlSelectOption = new cHTMLOptionElement($i, $i, false);
+ $oHtmlSelect->addOptionElement($i, $oHtmlSelectOption);
+ }
+
+ //set default value
+ $oHtmlSelect->setDefault($sSelected);
+
+ return $oHtmlSelect->render();
+ }
+
+ /**
+ * Function which generated a select box for setting teaser style
+ * currently two seperate teaser templates were supported
+ *
+ * @param string $sSelected - value of select box which is selected
+ * @return html string of select box
+ *
+ * @access private
+ */
+ private function getStyleSelect($sSelected) {
+ $oHtmlSelect = new cHTMLSelectElement('teaser_style', "", 'teaser_style');
+
+ //set please chose option element
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Please choose"), '', true);
+ $oHtmlSelect->addOptionElement(0, $oHtmlSelectOption);
+
+ //set other avariable options manually
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Block Style"), 'cms_teaser_style_block.html', false);
+ $oHtmlSelect->addOptionElement(1, $oHtmlSelectOption);
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Blog Style"), 'cms_teaser_style_blog.html', false);
+ $oHtmlSelect->addOptionElement(2, $oHtmlSelectOption);
+
+ $aAdditionalOptions = getEffectiveSettingsByType('cms_teaser');
+ $i = 3;
+ foreach ($aAdditionalOptions as $sLabel => $sTemplate) {
+ $oHtmlSelectOption = new cHTMLOptionElement($sLabel, $sTemplate, false);
+ $oHtmlSelect->addOptionElement($i, $oHtmlSelectOption);
+ $i++;
+ }
+
+ //set default value
+ $oHtmlSelect->setDefault($sSelected);
+
+ return $oHtmlSelect->render();
+ }
+
+ /**
+ * Function which generated a select box for setting teaser
+ * sort order argument
+ *
+ * @param string $sSelected - value of select box which is selected
+ * @return html string of select box
+ *
+ * @access private
+ */
+ private function getSortOrderSelect($sSelected) {
+ $oHtmlSelect = new cHTMLSelectElement('teaser_sort_order', "", 'teaser_sort_order');
+
+ //set please chose option element
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Please choose"), '', true);
+ $oHtmlSelect->addOptionElement(0, $oHtmlSelectOption);
+
+ //set other avariable options manually
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Ascending"), 'asc', false);
+ $oHtmlSelect->addOptionElement(1, $oHtmlSelectOption);
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Descending"), 'desc', false);
+ $oHtmlSelect->addOptionElement(2, $oHtmlSelectOption);
+
+ //set default value
+ $oHtmlSelect->setDefault($sSelected);
+
+ return $oHtmlSelect->render();
+ }
+
+ /**
+ * Function which provides select option for cropping teaser images
+ *
+ * @param string $sSelected - value of select box which is selected
+ * @return html string of select box
+ *
+ * @access private
+ */
+ private function getCropSelect($sSelected) {
+ $oHtmlSelect = new cHTMLSelectElement('teaser_image_crop', "", 'teaser_image_crop');
+
+ //set please chose option element
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Please choose"), '', true);
+ $oHtmlSelect->addOptionElement(0, $oHtmlSelectOption);
+
+ //set other avariable options manually
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Scaled"), 'false', false);
+ $oHtmlSelect->addOptionElement(1, $oHtmlSelectOption);
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Cropped"), 'true', false);
+ $oHtmlSelect->addOptionElement(2, $oHtmlSelectOption);
+
+ //set default value
+ $oHtmlSelect->setDefault($sSelected);
+
+ return $oHtmlSelect->render();
+ }
+
+ /**
+ * Function which generated a select box for setting teaser
+ * sort argument
+ *
+ * @param string $sSelected - value of select box which is selected
+ * @return html string of select box
+ *
+ * @access private
+ */
+ private function getSortSelect($sSelected) {
+ $oHtmlSelect = new cHTMLSelectElement('teaser_sort', "", 'teaser_sort');
+
+ //set please chose option element
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Please choose"), '', true);
+ $oHtmlSelect->addOptionElement(0, $oHtmlSelectOption);
+
+ //set other avariable options manually
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Sort Sequence"), 'sortsequence', false);
+ $oHtmlSelect->addOptionElement(1, $oHtmlSelectOption);
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Creationdate"), 'creationdate', false);
+ $oHtmlSelect->addOptionElement(2, $oHtmlSelectOption);
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Publisheddate"), 'publisheddate', false);
+ $oHtmlSelect->addOptionElement(3, $oHtmlSelectOption);
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Modificationdate"), 'modificationdate', false);
+ $oHtmlSelect->addOptionElement(4, $oHtmlSelectOption);
+
+ //set default value
+ $oHtmlSelect->setDefault($sSelected);
+
+ return $oHtmlSelect->render();
+ }
+
+ /**
+ * Function which gets all currenty avariable content types and their ids
+ * from database and store it into class variable aCMSTypes. Because this
+ * information is used multiple, this way causes a better performance to get
+ * this information seperately
+ *
+ * @access private
+ */
+ private function initCmsTypes() {
+ $this->aCMSTypes = array();
+
+ $sSql = 'SELECT * from %s ORDER BY type';
+
+ $this->oDb->query(sprintf($sSql, $this->aCfg['tab']['type']));
+
+ while ($this->oDb->next_record()) {
+ $this->aCMSTypes[$this->oDb->f('idtype')] = $this->oDb->f('type');
+ }
+ }
+
+ /**
+ * Teaser gets informations from other articles and their content typs
+ * Function builds a select box in which coresponding cms type can be selected
+ * after that a text box is rendered for setting id for this conent type to get
+ * informations from. This function is used three times for source defintion of
+ * headline text and teaserimage
+ *
+ * @param unknown_type $sSelectName - name of input elements
+ * @param string $sSelected - value of select box which is selected
+ * @param string $sValue - current value of text box
+ * @return html string of select box
+ *
+ * @access private
+ */
+ private function getTypeSelect($sSelectName, $sSelected, $sValue) {
+ //generate textbox for content type id
+ $oHtmlInput = new cHTMLTextbox($sSelectName . '_count', $sValue, "", "", $sSelectName . '_count');
+
+ //generate content type select
+ $oHtmlSelect = new cHTMLSelectElement($sSelectName, "", $sSelectName);
+
+ $oHtmlSelectOption = new cHTMLOptionElement(i18n("Please choose"), '', true);
+ $oHtmlSelect->addOptionElement(0, $oHtmlSelectOption);
+
+ //use $this->aCMSTypes as basis for this select box which contains all avariable content types in system
+ foreach ($this->aCMSTypes as $sKey => $sValue) {
+ $oHtmlSelectOption = new cHTMLOptionElement($sValue, $sValue, false);
+ $oHtmlSelect->addOptionElement($sKey, $oHtmlSelectOption);
+ }
+
+ $oHtmlSelect->setStyle("width:147px;");
+
+ //set default value
+ $oHtmlSelect->setDefault($sSelected);
+
+ $oHtmlInput->setStyle("width:50px;");
+
+ return $oHtmlSelect->render() . $oHtmlInput->render();
+ }
+
+ /**
+ * Function is called in editmode of contenido an returns teaser view and editbutton
+ *
+ * @return string - escaped html code for further use in contenido and sending to browser
+ *
+ * @access public
+ */
+ public function getAllWidgetEdit() {
+ $this->initCmsTypes();
+
+ $oTpl = new Template();
+ /* Set some values into javascript for a better handling */
+ $oTpl->set('s', 'CON_PATH', $this->aCfg['path']['contenido_fullhtml']);
+ $oTpl->set('s', 'ID', $this->iId);
+ $oTpl->set('s', 'IDARTLANG', $this->iIdArtLang);
+ $oTpl->set('s', 'CONTENIDO', $_REQUEST['contenido']);
+ //output fields for use in javascript
+ $oTpl->set('s', 'FIELDS', "'" . implode("','", $this->aTeaserData) . "'");
+
+ /* Start set a lot of translations */
+ $oTpl->set('s', 'LABEL_TEASERSETTINGS', i18n("Teasersettings"));
+ $oTpl->set('s', 'LABEL_TEASERTITLE', i18n("Teasertitle"));
+ $oTpl->set('s', 'LABEL_START', i18n("Teaser Startarticle"));
+ $oTpl->set('s', 'LABEL_TARGET', i18n("Sourcecategory"));
+ $oTpl->set('s', 'LABEL_COUNT', i18n("Number of Articles"));
+ $oTpl->set('s', 'LABEL_GENERAL', i18n("General Settings"));
+ $oTpl->set('s', 'LABEL_STYLE', i18n("Teaser Style"));
+ $oTpl->set('s', 'LABEL_ADVANCED', i18n("Advanced Teaser Settings"));
+ $oTpl->set('s', 'LABEL_FILTER', i18n("Teaser Filter"));
+ $oTpl->set('s', 'LABEL_SORT', i18n("Teaser Sort"));
+ $oTpl->set('s', 'LABEL_SORT_ORDER', i18n("Sort order"));
+ $oTpl->set('s', 'LABEL_SOURCEHEAD', i18n("Source Headline"));
+ $oTpl->set('s', 'LABEL_SOURCE', i18n("Source Settings"));
+ $oTpl->set('s', 'LABEL_SOURCETEXT', i18n("Source Text"));
+ $oTpl->set('s', 'LABEL_SOURCEIMAGE', i18n("Source Image"));
+ $oTpl->set('s', 'LABEL_SOURCEDATE', i18n("Source Date"));
+
+ $oTpl->set('s', 'LABEL_CAT', i18n("Category"));
+ $oTpl->set('s', 'LABEL_ART', i18n("Article"));
+
+ $oTpl->set('s', 'GENERAL', i18n("General"));
+ $oTpl->set('s', 'ADVANCED', i18n("Advanced"));
+ $oTpl->set('s', 'MANUAL', i18n("Manual"));
+ $oTpl->set('s', 'LABEL_EXISTING_ARTICLES', i18n("Included Articles"));
+ $oTpl->set('s', 'LABEL_ADD_ARTICLE', i18n("Add Article"));
+ $oTpl->set('s', 'LABEL_MANUAL', i18n("Manual Teaser Settings"));
+ $oTpl->set('s', 'LABEL_USE_MANUAL', i18n("Manual Teaser"));
+
+
+ $oTpl->set('s', 'SIZE_SETTINGS', i18n("Size Settings"));
+ $oTpl->set('s', 'LABEL_CHARACTER_LIMIT', i18n("Characterlength"));
+ $oTpl->set('s', 'LABEL_IMAGE_WIDTH', i18n("Imagewidth"));
+ $oTpl->set('s', 'LABEL_IMAGE_HEIGHT', i18n("Imageheight"));
+ $oTpl->set('s', 'LABEL_IMAGE_CROP', i18n("Image Scale"));
+ /* End set a lot of translations */
+
+ /* Start set values into configuration array and generate select boxes used previous defined values CASE CHECKBOXES */
+ if ($this->aSettings['teaser_start'] == 'true') {
+ $oTpl->set('s', 'START_CHECKED', 'checked');
+ } else {
+ $oTpl->set('s', 'START_CHECKED', '');
+ }
+
+ if ($this->aSettings['teaser_manual'] == 'true') {
+ $oTpl->set('s', 'MANUAL_CHECKED', 'checked');
+ } else {
+ $oTpl->set('s', 'MANUAL_CHECKED', '');
+ }
+ /* Start set values into configuration array and generate select boxes used previous defined values CASE CHECKBOXES */
+
+ /* Start set values into configuration array and generate select boxes used previous defined values */
+ $sCatSelect = buildCategorySelect('teaser_category', $this->aSettings['teaser_category'], 0);
+
+ $oTpl->set('s', 'TARGET_SELECT', $sCatSelect);
+ $oTpl->set('s', 'CAT_SELECT', buildCategorySelect('teaser_cat', 0, 0));
+ $oTpl->set('s', 'ART_SELECT', buildArticleSelect('teaser_art', 0, 0));
+ $oTpl->set('s', 'COUNT_SELECT', $this->getCountSelect($this->aSettings['teaser_count']));
+ $oTpl->set('s', 'STYLE_SELECT', $this->getStyleSelect($this->aSettings['teaser_style']));
+ $oTpl->set('s', 'SOURCEHEAD_SELECT', $this->getTypeSelect('teaser_source_head', $this->aSettings['teaser_source_head'], $this->aSettings['teaser_source_head_count']));
+ $oTpl->set('s', 'SOURCETEXT_SELECT', $this->getTypeSelect('teaser_source_text', $this->aSettings['teaser_source_text'], $this->aSettings['teaser_source_text_count']));
+ $oTpl->set('s', 'SOURCEIAMGE_SELECT', $this->getTypeSelect('teaser_source_image', $this->aSettings['teaser_source_image'], $this->aSettings['teaser_source_image_count']));
+ $oTpl->set('s', 'SOURCEDATE_SELECT', $this->getTypeSelect('teaser_source_date', $this->aSettings['teaser_source_date'], $this->aSettings['teaser_source_date_count']));
+ $oTpl->set('s', 'TEASER_TITLE', $this->aSettings['teaser_title']);
+ $oTpl->set('s', 'FILTER_VALUE', $this->aSettings['teaser_filter']);
+ $oTpl->set('s', 'SORT_SELECT', $this->getSortSelect($this->aSettings['teaser_sort']));
+ $oTpl->set('s', 'SORT_ORDER_SELECT', $this->getSortOrderSelect($this->aSettings['teaser_sort_order']));
+ $oTpl->set('s', 'IMAGE_CROP_SELECT', $this->getCropSelect($this->aSettings['teaser_image_crop']));
+ $oTpl->set('s', 'CHARACTER_LIMIT', $this->aSettings['teaser_character_limit']);
+ $oTpl->set('s', 'IMAGE_WIDTH', $this->aSettings['teaser_image_width']);
+ $oTpl->set('s', 'IMAGE_HEIGHT', $this->aSettings['teaser_image_height']);
+ $oTpl->set('s', 'LABEL_ADD', i18n('Add'));
+
+ $sOptions = '';
+ if (is_array($this->aSettings['teaser_manual_art'])) {
+ foreach ($this->aSettings['teaser_manual_art'] as $iIdArt) {
+ $sOptions .= '' . $this->getArtName($iIdArt) . ' ' . "\n";
+ }
+ }
+ $oTpl->set('s', 'MANUAL_OPTIONS', $sOptions);
+ /* End set values into configuration array and generate select boxes used previous defined values */
+
+ $sCode = $oTpl->generate($this->aCfg['path']['contenido'] . 'templates/standard/template.cms_teaser_edit.html', 1);
+
+ //return $this->encodeForOutput($sCode);
+
+ return $this->getAllWidgetView(true) . $this->encodeForOutput($sCode);
+ }
+
+ /**
+ * In Contenido content type code is evaled by php. To make this possible,
+ * this function prepares code for evaluation
+ *
+ * @param string $sCode - code to escape
+ * @return string - escaped code
+ *
+ * @access private
+ */
+ private function encodeForOutput($sCode) {
+ $sCode = (string) $sCode;
+
+ $sCode = AddSlashes(AddSlashes($sCode));
+ $sCode = str_replace("\\\'", "'", $sCode);
+ $sCode = str_replace("\$", '\\\$', $sCode);
+
+ return $sCode;
+ }
+
+ /**
+ * Function sets some default values for teaser in case that there is no
+ * value definied
+ *
+ * @access private
+ */
+ private function setDefaultValues() {
+ //character limit is 120 by default
+ if ((int) $this->aSettings['teaser_character_limit'] == 0) {
+ $this->aSettings['teaser_character_limit'] = 120;
+ }
+
+ //teaser cont is 6 by default
+ if ((int) $this->aSettings['teaser_count'] == 0) {
+ $this->aSettings['teaser_count'] = 6;
+ }
+
+ //teasersort is creationdate by default
+ if (strlen($this->aSettings['teaser_sort']) == 0) {
+ $this->aSettings['teaser_sort'] = 'creationdate';
+ }
+
+ //teaser style is liststyle by default
+ if (strlen($this->aSettings['teaser_style']) == 0) {
+ $this->aSettings['teaser_style'] = 'cms_teaser_style_blog.html';
+ }
+
+ //teaser image width default
+ if ((int) $this->aSettings['teaser_image_width'] == 0) {
+ $this->aSettings['teaser_image_width'] = 100;
+ }
+
+ //teaser image height default
+ if ((int) $this->aSettings['teaser_image_height'] == 0) {
+ $this->aSettings['teaser_image_height'] = 75;
+ }
+
+ //cms type head default
+ if (strlen($this->aSettings['teaser_source_head']) == 0) {
+ $this->aSettings['teaser_source_head'] = 'CMS_HTMLHEAD';
+ }
+
+ //cms type text default
+ if (strlen($this->aSettings['teaser_source_text']) == 0) {
+ $this->aSettings['teaser_source_text'] = 'CMS_HTML';
+ }
+
+ //cms type image default
+ if (strlen($this->aSettings['teaser_source_image']) == 0) {
+ $this->aSettings['teaser_source_image'] = 'CMS_IMG';
+ }
+
+ //cms type date default
+ if (strlen($this->aSettings['teaser_source_date']) == 0) {
+ $this->aSettings['teaser_source_date'] = 'CMS_DATE';
+ }
+
+ //sort order of teaser articles
+ if (strlen($this->aSettings['teaser_sort_order']) == 0) {
+ $this->aSettings['teaser_sort_order'] = 'asc';
+ }
+
+ //teaser image crop option
+ if (strlen($this->aSettings['teaser_image_crop']) == 0 || $this->aSettings['teaser_image_crop'] == 'false') {
+ $this->aSettings['teaser_image_crop'] = 'false';
+ }
+ }
+
+ /**
+ * Function gets path to an image of base of idupload in contenido,
+ * scales this image on basis of teaser settings and returns path to
+ * scaled image. It is also possible to give path to image directly,
+ * in this case set fourth parameter to true
+ *
+ * @param integer $iImage - idupl of image to use for teaser
+ * @param integer $iMaxX - maximum image width
+ * @param integer $iMaxY - maximum image height
+ * @param boolean $bIsFile - in case of a direct file path retrival from database is not needed
+ * @return string - tag contains scaled image
+ *
+ * @access private
+ */
+ private function getImage($iImage, $iMaxX, $iMaxY, $bCropped, $bIsFile = false) {
+ $sContent = '';
+
+ if ($bCropped == 'true') {
+ $bCropped = true;
+ } else {
+ $bCropped = false;
+ }
+
+ //check if there is a need to get image path
+ if ($bIsFile == false) {
+ //get path out of database
+ $sSQL = 'SELECT * FROM ' . $this->aCfg['tab']['upl'] . ' WHERE idupl = ' . $iImage;
+
+ $this->oDb->query($sSQL);
+ if ($this->oDb->next_record()) {
+ $sTeaserImage = $this->aCfgClient[$this->iClient]['path']['frontend'] . 'upload/' . $this->oDb->f("dirname") . $this->oDb->f("filename");
+ }
+ } else {
+ $sTeaserImage = $iImage;
+ }
+
+ //scale image if exists and return it
+ if (file_exists($sTeaserImage)) {
+ //Scale Image using capiImgScale
+ $sImgSrc = capiImgScale($sTeaserImage, $iMaxX, $iMaxY, $bCropped);
+
+ if ($this->sUseXHTML == 'true') {
+ $sLetter = ' /';
+ } else {
+ $sLetter = '';
+ }
+
+ //Put Image into the teasertext
+ $sContent = ' ' . $sContent;
+ }
+
+ return $sContent;
+ }
+
+ /**
+ * Function retrives name of an article by its id from database
+ *
+ * @param integer $iIdArt - Contenido article id
+ * @return string - name of article
+ *
+ * @access private
+ */
+ private function getArtName($iIdArt) {
+ $iIdArt = (int) $iIdArt;
+
+ //get article name from database
+ $sSql = 'SELECT * FROM ' . $this->aCfg['tab']['art_lang'] . ' WHERE idart = ' . $iIdArt;
+ $this->oDb->query($sSql);
+ if ($this->oDb->next_record()) {
+ return $this->oDb->f('title');
+ } else {
+ return 'Unknown Article';
+ }
+ }
+
+ /**
+ * Teaser allows to get a list of ids in which article content is searched in
+ * article like 1,2,5,6 the result with largest character count is returned
+ *
+ * @param object $oArticle - Contenido article object
+ * @param string $sIdType - Name of Content type to extract informations from
+ * @param integer $iIdType - list of ids to search in
+ * @return string - largest result of content
+ *
+ * @access private
+ */
+ private function getArtContent(&$oArticle, $sIdType, $iIdType) {
+ $sReturn = '';
+
+ //split ids, if there is only one id, array has only one place filled, that is also ok
+ $aIds = explode(',', $iIdType);
+ foreach ($aIds as $iCurIdType) {
+ $sTmp = $oArticle->getContent($sIdType, $iCurIdType);
+ //check for largest result and replace when new value is larger
+ if (strlen($sReturn) < strlen($sTmp)) {
+ $sReturn = $sTmp;
+ }
+ }
+
+ return $sReturn;
+ }
+
+ /**
+ * When a HTML Code is given for a Teaser image try to find a image in this code and generate
+ * Teaser image on that basis
+ *
+ * @param string $sContent - HTML string to search image in
+ * @return img tag containing scaled image
+ *
+ * @access private
+ */
+ private function extractImage($sContent) {
+ $sImage = '';
+
+ //search an image tag
+ $sRegEx = "/ ]*?>.*?/i";
+
+ $aMatch = array();
+ preg_match($sRegEx, $sContent, $aMatch);
+
+ //if found extract its src content
+ $sRegEx = "/(src)(=)(['\"]?)([^\"']*)(['\"]?)/i";
+ $aImg = array();
+ preg_match($sRegEx, $aMatch[0], $aImg);
+
+ //check if this image lies in upload folder
+ $iPos = strrpos($aImg[4], $this->aCfgClient[$this->iClient]["upload"]);
+ if (!is_bool($iPos)) {
+ //if it is generate full internal path to image and scale it for display using class internal function getImage()
+ $sFile = $this->aCfgClient[$this->iClient]['path']['frontend'] . $aImg[4];
+ $sImage = $this->getImage($sFile, $this->aSettings['teaser_image_width'], $this->aSettings['teaser_image_height'], $this->aSettings['teaser_image_crop'], true);
+ }
+
+ return $sImage;
+ }
+
+ /**
+ * In edit and view mode this function fills teaser template with informations from an
+ * Contenido article object
+ *
+ * @param object $oArticle - Contenido Article object
+ * @param object $oTpl - Contenido Template object (as reference)
+ * @return boolean - success state of this operation
+ *
+ * @access private
+ */
+ private function fillTeaserTemplateEntry($oArticle, &$oTpl) {
+ global $cCurrentModule;
+
+ //get necessary informations for teaser from articles use properties in a Settings for retirval
+ $sTitle = $this->getArtContent($oArticle, $this->aSettings['teaser_source_head'], $this->aSettings['teaser_source_head_count']);
+ $sText = $this->getArtContent($oArticle, $this->aSettings['teaser_source_text'], $this->aSettings['teaser_source_text_count']);
+ $iImage = $this->getArtContent($oArticle, $this->aSettings['teaser_source_image'], $this->aSettings['teaser_source_image_count']);
+ $sDate = $this->getArtContent($oArticle, $this->aSettings['teaser_source_date'], $this->aSettings['teaser_source_date_count']);
+ $iIdArt = $oArticle->getField('idart');
+ $iPublished = $oArticle->getField('published');
+ $iOnline = $oArticle->getField('online');
+
+ if ($iOnline == 1) {
+ //teaserfilter defines strings which must be contained in text for display.
+ //if string is defined check if article contains this string and abort, if article does not contain this string
+ if ($this->aSettings['teaser_filter'] != '') {
+ $iPosText = strrpos(clHtmlEntityDecode($sText), $this->aSettings['teaser_filter']);
+ $iPosHead = strrpos(clHtmlEntityDecode($sTitle), $this->aSettings['teaser_filter']);
+ if (is_bool($iPosText) && !$iPosText && is_bool($iPosHead) && !$iPosHead) {
+ return false;
+ }
+ }
+
+ //convert date to readable format
+ if (preg_match('/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/', $iPublished, $aResults)) {
+ $iPublished = $aResults[3] . '.' . $aResults[2] . '.' . $aResults[1];
+ }
+
+ //strip tags in teaser text and cut it if it is to long
+ $sTitle = trim(strip_tags($sTitle));
+ $sText = trim(strip_tags($sText));
+ if (strlen($sText) > $this->aSettings['teaser_character_limit']) {
+ $sText = capiStrTrimAfterWord($sText, $this->aSettings['teaser_character_limit']) . '...';
+ }
+
+ //try to get a teaser image directly from cms_img or try to extract if a content type is given, wich contains html
+ if ((int) $iImage > 0) {
+ $sImage = $this->getImage($iImage, $this->aSettings['teaser_image_width'], $this->aSettings['teaser_image_height'], $this->aSettings['teaser_image_crop']);
+ $oTpl->set('d', 'IMAGE', $sImage);
+ } else if (strip_tags($iImage) != $iImage && strlen($iImage) > 0) {
+ $sImage = $this->extractImage($iImage);
+ if (strlen($sImage) > 0) {
+ $oTpl->set('d', 'IMAGE', $sImage);
+ } else {
+ $oTpl->set('d', 'IMAGE', '');
+ }
+ } else {
+ $oTpl->set('d', 'IMAGE', '');
+ }
+
+ // strip all tags from manual teaser date
+ $sDate = strip_tags($sDate);
+
+ //set generated values to teaser template
+ $oTpl->set('d', 'TITLE', $sTitle);
+ $oTpl->set('d', 'TEXT', $sText);
+
+ $oTpl->set('d', 'IDART', $iIdArt);
+ $oTpl->set('d', 'ART_URL', 'front_content.php?idart=' . $iIdArt);
+ $oTpl->set('d', 'PUBLISHED', $iPublished);
+ $oTpl->set('d', 'PUBLISHED_MANUAL', $sDate);
+
+ if ($sDate != "") {
+ $oTpl->set('d', 'PUBLISHED_COMBINED', $sDate);
+ } else {
+ $oTpl->set('d', 'PUBLISHED_COMBINED', $iPublished);
+ }
+
+ foreach (self::$aTranslations as $sKey => $sValue) {
+ $oTpl->set('d', $sKey, mi18n($sValue));
+ }
+
+ $oTpl->next();
+ }
+
+ return true;
+ }
+
+ /**
+ * Function is called in edit- and viewmode in order to generate teasercode for output
+ *
+ * @param boolean $bEditmode - in editmode skip encoding because it is done in getAllWidgetEdit()
+ * @return html string of select box
+ *
+ * @access public
+ */
+ public function getAllWidgetOutput($bEditmode = false) {
+ $oTpl = new Template();
+ //set title of teaser
+ $oTpl->set('s', 'TITLE', $this->aSettings['teaser_title']);
+
+ //decide if it is a manual or category teaser
+ if ($this->aSettings['teaser_manual'] == 'true' && count($this->aSettings['teaser_manual_art']) > 0) {
+ $i = 0;
+ //in manual case get all art to display and generate article objects manually
+ foreach ($this->aSettings['teaser_manual_art'] as $iIdArt) {
+ $oArticle = new Article($iIdArt, $this->iClient, $this->iLang);
+
+ //try to fill teaser image
+ if ($this->fillTeaserTemplateEntry($oArticle, $oTpl)) {
+ $i++;
+
+ //break render, if teaser limit is reached
+ if ($i == $this->aSettings['teaser_count'])
+ break;
+ }
+ }
+ } else {
+ //in case of autmatic teaser use class Contenido_Category_Articles for getting all arts in category
+ $oConCatArt = new Contenido_Category_Articles($this->oDb, $this->aCfg, $this->iClient, $this->iLang);
+ //decide to teaser articles or not
+ if ($this->aSettings['teaser_start'] == 'true') {
+ $aArticles = $oConCatArt->getArticlesInCategory($this->aSettings['teaser_category'], $this->aSettings['teaser_sort'], $this->aSettings['teaser_sort_order']);
+ } else {
+ $aArticles = $oConCatArt->getNonStartArticlesInCategory($this->aSettings['teaser_category'], $this->aSettings['teaser_sort'], $this->aSettings['teaser_sort_order']);
+ }
+
+ $i = 0;
+ //iterate over all found articles
+ foreach ($aArticles as $oArticle) {
+ //try to fill teaser image
+ if ($this->fillTeaserTemplateEntry($oArticle, $oTpl)) {
+ $i++;
+ //break render, if teaser limit is reached
+ if ($i == $this->aSettings['teaser_count'])
+ break;
+ }
+ }
+ }
+
+ $sCode = '';
+ //generate teasertemplate
+ if (file_exists($this->aCfgClient[$this->iClient]['path']['frontend'] . 'templates/' . $this->aSettings['teaser_style'])) {
+ $sCode = $oTpl->generate($this->aCfgClient[$this->iClient]['path']['frontend'] . 'templates/' . $this->aSettings['teaser_style'], 1);
+ }
+
+ return $sCode;
+ //use this to show xml document which contains teaser settings
+ #return ''.clHtmlEntities($this->sContent).' ';
+ }
+
+ /**
+ * Dynamic filelist generator.
+ * This method is executed every time the filelist is displayed.
+ *
+ * @return string output of the filelist
+ */
+ public function getAllWidgetView() {
+ $sCode = '\";?>getAllWidgetOutput();
+ ?>sContent, $this->iId);
+ return $sCode;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.communications.php b/conlite/classes/class.communications.php
new file mode 100644
index 0000000..957e66f
--- /dev/null
+++ b/conlite/classes/class.communications.php
@@ -0,0 +1,111 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting
+ *
+ * $Id: class.communications.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class CommunicationCollection extends ItemCollection
+{
+ /**
+ * Constructor Function
+ * @param none
+ */
+ public function __construct()
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["communications"], "idcommunication");
+ $this->_setItemClass("CommunicationItem");
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function CommunicationCollection()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+
+ /**
+ * Creates a new communication item
+ */
+ public function create()
+ {
+ global $auth, $client;
+ $item = parent::create();
+
+ $client = Contenido_Security::toInteger($client);
+
+ $item->set("idclient", $client);
+ $item->set("author", $auth->auth["uid"]);
+ $item->set("created", date("Y-m-d H:i:s"), false);
+
+ return $item;
+ }
+}
+
+
+/**
+ * Single CommunicationItem Item
+ */
+class CommunicationItem extends Item
+{
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false)
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["communications"], "idcommunication");
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function CommunicationItem($mId = false)
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct($mId);
+ }
+
+ function store()
+ {
+ global $auth;
+ $this->set("modifiedby", $auth->auth["uid"]);
+ $this->set("modified", date("Y-m-d H:i:s"), false);
+
+ parent::store();
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.conuser.php b/conlite/classes/class.conuser.php
new file mode 100644
index 0000000..167c31d
--- /dev/null
+++ b/conlite/classes/class.conuser.php
@@ -0,0 +1,895 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release => 4.8.8
+ *
+ */
+class ConUser extends ConUser_Abstract {
+
+ /**
+ * Realname
+ * @var string
+ */
+ private $sRealName = "";
+
+ /**
+ * Mail address
+ *
+ * @var string
+ */
+ private $sMail = "";
+
+ /**
+ * Telephone number
+ * @var string
+ */
+ private $sTelNumber = "";
+
+ /**
+ * Array of address data fill like below values
+ *
+ * $aAddress['street'], $aAddress['city'], $aAddress['country'], $aAddress['zip']
+ * @var array
+ */
+ private $aAddress = array ();
+
+ /**
+ * To Use Tiny Editor
+ * @var int
+ */
+ private $iUseTiny = null;
+
+ /**
+ * User valid date to
+ * @var string
+ */
+ private $sValidDateTo = null;
+
+ /**
+ * User valid date from
+ * @var string
+ */
+ private $sValidDateFrom = null;
+
+ /**
+ * Permname
+ * @var string
+ */
+ private $sPermName = "";
+
+ /**
+ * Currently not implemented!
+ *
+ * @see ConUser_Abstract::load()
+ *
+ * @param string $sUserId
+ * @return boolean
+ *
+ * @todo implement it
+ */
+ public function load($sUserId) {
+ return true;
+ }
+
+ /**
+ * @see ConUser_Abstract::save()
+ *
+ * @return boolean
+ */
+ public function save() {
+ $bResult = false;
+
+ $sUserId = $this->getUserId ();
+
+ if (! empty ( $sUserId )) {
+ $bResult = $this->update ();
+ } else {
+ $bResult = $this->insert ();
+ }
+
+ return $bResult;
+ }
+
+ /**
+ * Updates a user
+ *
+ * This method update base user informations in user table. It is called
+ * within the iConUser::save() method.
+ *
+ * @return boolean
+ *
+ * @todo add type checks!
+ */
+ protected function update() {
+ $bResult = false;
+
+ $sUserId = $this->getUserId ();
+
+ if (! empty ( $sUserId )) {
+ $sSql = "
+ UPDATE
+ `" . $this->aCfg ["tab"] ["phplib_auth_user_md5"] . "`
+ SET
+ realname = '" . Contenido_Security::escapeDB ( $this->sRealName, $this->oDb ) . "',
+ email = '" . Contenido_Security::escapeDB ( $this->sMail, $this->oDb ) . "',
+ telephone = '" . Contenido_Security::escapeDB ( $this->sTelNumber, $this->oDb ) . "',
+ address_street = '" . Contenido_Security::escapeDB ( $this->aAddress ['street'], $this->oDb ) . "',
+ address_city = '" . Contenido_Security::escapeDB ( $this->aAddress ['city'], $this->oDb ) . "',
+ address_country = '" . Contenido_Security::escapeDB ( $this->aAddress ['country'], $this->oDb ) . "',
+ address_zip = '" . Contenido_Security::escapeDB ( $this->aAddress ['zip'], $this->oDb ) . "',
+ wysi = '" . Contenido_Security::toInteger ( $this->iUseTiny ) . "',
+ valid_from = '" . Contenido_Security::escapeDB ( $this->sValidDateFrom, $this->oDb ) . "',
+ valid_to = '" . Contenido_Security::escapeDB ( $this->sValidDateTo, $this->oDb ) . "',
+ perms = '" . $this->sPermName . "'
+ WHERE
+ user_id = '" . Contenido_Security::escapeDB ( $sUserId, $this->oDb ) . "'";
+
+ // try to update
+ if (! $this->oDb->query ( $sSql )) {
+ throw new ConUserException ( "Could not update user informations" );
+ } else {
+ // try to update password, if set
+ $sNewPass = $this->getPassword();
+
+ if (!is_null($sNewPass)) {
+ $iPassResult = $this->savePassword($sNewPass);
+
+ if ($iPassResult != iConUser::PASS_OK) {
+ // throw an exception, caus I do not know what to do uin that case, cause user update was successful!
+ throw new ConUserException( "Given password is not valid! [#" . $iPassResult . ']',
+ iConUser::EXCEPTION_PASSWORD_INVALID);
+ }
+ }
+
+ $bResult = true;
+ }
+ }
+
+ return $bResult;
+ }
+
+ /**
+ * Creates new user.
+ *
+ * This method creates a new user with base informations. It is called
+ * within the iConUser::save() method.
+ *
+ * @return boolean
+ *
+ * @todo add value checks!
+ */
+ protected function insert() {
+ $bResult = false;
+
+ $sUserName = $this->getUserName ();
+
+ if (! empty ( $sUserName )) {
+
+ // check if user already exists
+ if (self::usernameExists($sUserName)) {
+ throw new ConUserException ("Username already exists!", iConUser::EXCEPTION_USERNAME_EXISTS);
+ }
+
+ // create user id
+ $sNewUserId = $this->generateUserId ();
+
+ $sSql = "
+ INSERT INTO
+ `" . $this->aCfg ["tab"] ["phplib_auth_user_md5"] . "`
+ SET
+ username = '" . Contenido_Security::escapeDB( $sUserName, $this->oDb ) . "',
+ user_id = '" . Contenido_Security::escapeDB ( $sNewUserId, $this->oDb ) . "',
+ realname = '" . Contenido_Security::escapeDB ( $this->sRealName, $this->oDb ) . "',
+ email = '" . Contenido_Security::escapeDB ( $this->sMail, $this->oDb ) . "',
+ telephone = '" . Contenido_Security::escapeDB ( $this->sTelNumber, $this->oDb ) . "',
+ address_street = '" . Contenido_Security::escapeDB ( $this->aAddress ['street'], $this->oDb ) . "',
+ address_city = '" . Contenido_Security::escapeDB ( $this->aAddress ['city'], $this->oDb ) . "',
+ address_country = '" . Contenido_Security::escapeDB ( $this->aAddress ['country'], $this->oDb ) . "',
+ address_zip = '" . Contenido_Security::escapeDB ( $this->aAddress ['zip'], $this->oDb ) . "',
+ wysi = '" . Contenido_Security::toInteger ( $this->iUseTiny ) . "',
+ valid_from = '" . Contenido_Security::escapeDB ( $this->sValidDateFrom, $this->oDb ) . "',
+ valid_to = '" . Contenido_Security::escapeDB ( $this->sValidDateTo, $this->oDb ) . "',
+ perms = '" . Contenido_Security::escapeDB ( $this->sPermName, $this->oDb ) . "'";
+
+ // try to update
+ if (! $this->oDb->query ( $sSql )) {
+ throw new ConUserException ( "Could not create user in database" );
+ } else {
+ if ($this->oDb->affected_rows () == 1) {
+ // set password, if available...
+ $sNewPass = $this->getPassword();
+
+ if (!is_null($sNewPass)) {
+ $iPassResult = $this->savePassword($sNewPass);
+
+ if ($iPassResult != iConUser::PASS_OK) {
+ throw new ConUserException( "Given password is not valid! [#" . $iPassResult . ']',
+ iConUser::EXCEPTION_PASSWORD_INVALID);
+ }
+ }
+
+ $bResult = true;
+ }
+ }
+ }
+
+ return $bResult;
+ }
+
+ /**
+ * Checks if an user with user id $sUserId already exists in DB.
+ *
+ * @param string $iUserId
+ * @return boolean
+ */
+ public function userExists($sUserId) {
+ $bResult = false;
+
+ $sSql = "
+ SELECT
+ count(*) as user_cnt
+ FROM
+ `" . $this->aCfg ["tab"] ["phplib_auth_user_md5"] . "`
+ WHERE
+ user_id = '" . Contenido_Security::escapeDB ( strtolower ( $sUserId ), $this->oDb ) . "'";
+
+ if ($this->oDb->query ( $sSql) !== false && $this->oDb->next_record()) {
+ $iCount = (int) $this->oDb->f('user_cnt');
+
+ $bResult = ($iCount != 0);
+ } else {
+ throw new ConUserException("User existence check failed!");
+ }
+
+ return $bResult;
+ }
+
+ /**
+ * Checks if username $sUsername is already in use.
+ *
+ * @param string $sUsername
+ * @return boolean
+ *
+ * @todo to be implemented
+ */
+ public function usernameExists($sUsername) {
+ $bResult = false;
+
+ /*
+ * Check count of entries that use username $sUsername.
+ * I use count(*) instead of selecting a field (e.g. user_id) cause
+ * MySQL MyISAM tables use optimized
+ */
+ $sSql = "
+ SELECT
+ count(*) as user_cnt
+ FROM
+ `" . $this->aCfg ["tab"] ["phplib_auth_user_md5"] . "`
+ WHERE
+ LOWER(`username`) = '" . Contenido_Security::escapeDB ( strtolower ( $sUsername ), $this->oDb ) . "'";
+
+ if ($this->oDb->query ( $sSql) !== false && $this->oDb->next_record()) {
+ $iCount = (int) $this->oDb->f('user_cnt');
+
+ $bResult = ($iCount != 0);
+ } else {
+ throw new ConUserException("Could check if username is already in use!");
+ }
+
+ return $bResult;
+ }
+
+ /**
+ * @see ConUser_Abstract::savePassword()
+ *
+ * The method uses following config values:
+ *
+ *
+ * @param string $sNewPassword Password to set
+ * @return int
+ *
+ * @throws ConUserException
+ */
+ public function savePassword($sNewPassword) {
+ $iResult = 0;
+
+ // get current user id...
+ $sUserId = $this->getUserId ();
+
+ // check user id...
+ if (empty ( $sUserId )) {
+ throw new ConUserException ( "Could not set password for anonymous user." );
+ } else {
+ $bSaveAllowed = true;
+
+ // check password for strength and complexity
+ if ($this->aCfg ['password'] ['check_password_mask']) {
+ $iMaskResult = self::checkPasswordMask( $sNewPassword );
+
+ if ($iMaskResult != iConUser::PASS_OK) {
+ $iResult = $iMaskResult;
+ } else {
+ $bSaveAllowed = true;
+ }
+ }
+
+ if ($bSaveAllowed && $this->aCfg ['password'] ['use_cracklib']) {
+ $iStrengthResult = iConUser::checkPasswordStrength ( $sNewPassword );
+
+ if ($iStrengthResult != iConUser::PASS_OK) {
+ $iResult = $iStrengthResult;
+ } else {
+ $bSaveAllowed = true;
+ }
+ }
+
+ if ($bSaveAllowed) {
+ // now it is time to save...
+
+ // passwords are encoded as md5 hashes
+ $sPass = self::encodePassword( $sNewPassword );
+ $sSql = "
+ UPDATE
+ `" . $this->aCfg ["tab"] ["phplib_auth_user_md5"] . "`
+ SET
+ password='" . Contenido_Security::escapeDB ( $sPass, $this->oDb ) . "',
+ using_pw_request = '0'
+ WHERE
+ user_id = '" . Contenido_Security::escapeDB ( $sUserId, $this->oDB ) . "'";
+
+ $bQueryResult = $this->oDb->query ( $sSql );
+
+ if (! $bQueryResult || $this->oDb->affected_rows () < 1) {
+ throw new ConUserException ( "Could not set password! A DB error occured." );
+ } else {
+ $iResult = iConUser::PASS_OK;
+ }
+ }
+ }
+
+ return $iResult;
+ }
+
+ /**
+ * Calls constructor in base class.
+ *
+ * @param array $aCfg
+ * @param DB_ConLite $oDB
+ * @param string $sIdUser User ID the instnace of this class represents
+ *
+ * @return ConUser
+ * @throws ConUserException
+ */
+ public function __construct($aCfg, $oDb = null, $sUserId = null) {
+ parent::__construct ( $aCfg, $oDb, $sUserId );
+ }
+
+ /**
+ * This function does update without password column to all columns of con_phplib_auth_user_md5 table.
+ *
+ * @return void
+ */
+ public function saveUser() {
+ if ($this->sIdUser != "") {
+ $sSql = ' UPDATE ' . $this->aCfg ["tab"] ["phplib_auth_user_md5"] . ' SET
+ realname="' . Contenido_Security::escapeDB ( $this->sRealName, $this->oDB ) . '",
+ email="' . Contenido_Security::escapeDB ( $this->sMail, $this->oDB ) . '",
+ telephone="' . Contenido_Security::escapeDB ( $this->sTelNumber, $this->oDB ) . '",
+ address_street="' . Contenido_Security::escapeDB ( $this->aAddress ['street'], $this->oDB ) . '",
+ address_city="' . Contenido_Security::escapeDB ( $this->aAddress ['city'], $this->oDB ) . '",
+ address_country="' . Contenido_Security::escapeDB ( $this->aAddress ['country'], $this->oDB ) . '",
+ address_zip="' . Contenido_Security::escapeDB ( $this->aAddress ['zip'], $this->oDB ) . '",
+ wysi="' . Contenido_Security::toInteger ( $this->iUseTiny ) . '",
+ valid_from="' . Contenido_Security::escapeDB ( $this->sValidDateFrom, $this->oDB ) . '",
+ valid_to="' . Contenido_Security::escapeDB ( $this->sValidDateTo, $this->oDB ) . '",
+ perms="' . $this->sPermName . '"
+ WHERE user_id = "' . Contenido_Security::escapeDB ( $this->sIdUser, $this->oDB ) . '"';
+
+ try {
+ if (( int ) $this->oDB->query ( $sSql ) != 1 || $this->oDB->affected_rows () != 1) {
+ throw new ConDbException ( "Update could not possible" );
+ }
+ } catch ( ConDbException $e ) {
+ print $e->getMessage ();
+ }
+ }
+ }
+
+ /**
+ * Getter method to get user realname
+ * @return string Realname of user
+ */
+ public function getRealName() {
+ return $this->sRealName;
+ }
+
+ /**
+ * Getter method to get user mail
+ * @return string Realname of user
+ */
+ public function getMail() {
+ return $this->sMail;
+ }
+
+ /**
+ * Getter method to get user tel number
+ * @return string Realname of user
+ */
+ public function getTelNumber() {
+ return $this->sTelNumber;
+ }
+
+ /**
+ * Getter method to get user adress data
+ * @return string Realname of user
+ */
+ public function getAddressData() {
+ return $this->aAddress;
+ }
+
+ /**
+ * Getter method to get user wysi
+ * @return string Realname of user
+ */
+ public function getUseTiny() {
+ return $this->iUseTiny;
+ }
+
+ /**
+ * Getter method to get user valid date from-to
+ * @return string Realname of user
+ */
+ public function getValidDateTo() {
+ return $this->sValidDateTo;
+ }
+
+ /**
+ * Getter method to get user valid date from-to
+ * @return string Realname of user
+ */
+ public function getValidDateFrom() {
+ return $this->sValidDateFrom;
+ }
+
+ /**
+ * Getter method to get user perm name
+ * @return string Realname of user
+ */
+ public function getPerms() {
+ return $this->sPermName;
+ }
+
+ /**
+ * Setter method to set user real name
+ * @return void
+ */
+ public function setRealName($sRealName) {
+ $this->sRealName = $sRealName;
+ }
+
+ /**
+ * Setter method to set user mail address
+ * @return void
+ */
+ public function setMail($sMail) {
+ $this->sMail = $sMail;
+ }
+
+ /**
+ * setter method to set user tel number
+ * @return void
+ */
+ public function setTelNumber($sTelNumber) {
+ $this->sTelNumber = $sTelNumber;
+ }
+
+ /**
+ * Setter method to set Adress Data
+ * @return void
+ */
+ public function setAddressData($sAddressStreet, $sAddressCity, $sAddressZip, $sAddressCountry) {
+ $this->aAddress ['street'] = $sAddressStreet;
+ $this->aAddress ['city'] = $sAddressCity;
+ $this->aAddress ['zip'] = $sAddressZip;
+ $this->aAddress ['country'] = $sAddressCountry;
+ }
+
+ /**
+ * Sets value for street.
+ *
+ * @param string $sStreet
+ */
+ public function setStreet ($sStreet) {
+ $this->aAddress['street'] = $sStreet;
+ }
+
+ /**
+ * Sets value for city.
+ *
+ * @param string $sCity
+ */
+ public function setCity ($sCity) {
+ $this->aAddress['city'] = $sCity;
+ }
+
+ /**
+ * Sets value for ZIP.
+ *
+ * @param string $sZip
+ */
+ public function setZip ($sZip) {
+ $this->aAddress['zip'] = $sZip;
+ }
+
+ /**
+ * Sets value for country.
+ *
+ * @param string $sCountry
+ */
+ public function setCountry ($sCountry) {
+ $this->aAddress['country'] = $sCountry;
+ }
+
+ /**
+ * Setter method to set
+ * @return void
+ */
+ public function setUseTiny($iUseTiny) {
+ $this->iUseTiny = $iUseTiny;
+ }
+
+ /**
+ * setter method to set User
+ *
+ * @return void
+ *
+ * TODO add type check
+ */
+ public function setValidDateTo($sValidateTo) {
+ $this->sValidDateTo = $sValidateTo;
+ }
+
+ /**
+ * setter method to set
+ *
+ * @return void
+ *
+ * TODO add type checks
+ */
+ public function setValidDateFrom($sValidateFrom) {
+ $this->sValidDateFrom = $sValidateFrom;
+ }
+
+ /**
+ * setter method to set
+ *
+ * @return void
+ *
+ * TODO add type checks
+ */
+ public function setPerms($aPerms) {
+ $this->sPermName = implode ( ",", $aPerms );
+ }
+
+ /**
+
+ *
+ * Following configuration values are recognized:
+ * $this->aCfg['password']['check_password_mask'], bool
+ * En- or disable these checks...
+ * $this->aCfg['password']['min_length'], int
+ * Minimum length a password has to have. If not set, 8 chars are set as default
+ * $this->aCfg['password']['numbers_mandatory'], int
+ * If set to a value greater than 0, at least $this->aCfg['password']['numbers_mandatory'] numbers
+ * must be in password
+ * $this->aCfg['password']['symbols_mandatory'], int &&
+ * $this->aCfg['password']['symbols_regex'], String
+ * If 'symbols_mandatory' set to a value greater than 0, at least so many symbols has to appear in
+ * given password. What symbols are regcognized can be administrated via 'symbols_regex'. This has
+ * to be a regular expression which is used to "find" the symbols in $sNewPassword. If not set, following
+ * RegEx is used: "/[|!@#$%&*\/=?,;.:\-_+~^�\\\]/"
+ * $this->aCfg['password']['mixed_case_mandatory'], int
+ * If set to a value greater than 0 so many lower and upper case character must appear in the password.
+ * (e.g.: if set to 2, 2 upper and 2 lower case characters must appear)
+ *
+ * @param string $sNewPassword
+ * @return int
+ *
+ */
+ public function checkPasswordMask($sNewPassword) {
+ $iResult = iConUser::PASS_OK;
+
+ if (isset($this->aCfg['password']['check_password_mask']) &&
+ $this->aCfg['password']['check_password_mask'] == true) {
+ // any min length in config set?
+ $iMinLength = iConUser::MIN_PASS_LENGTH_DEFAULT;
+ if (isset( $this->aCfg ['password'] ['min_length'] )) {
+ $iMinLength = ( int ) $this->aCfg ['password'] ['min_length'];
+ }
+
+ // check length...
+ if (strlen ( $sNewPassword ) < $iMinLength) {
+ $iResult = iConUser::PASS_TO_SHORT;
+ }
+
+ // check password elements
+
+ // numbers.....
+ if ($iResult == iConUser::PASS_OK && isset($this->aCfg['password']['numbers_mandatory']) &&
+ (int) $this->aCfg['password']['numbers_mandatory'] > 0) {
+
+ $aNumbersInPassword = array();
+ preg_match_all("/[0-9]/", $sNewPassword, $aNumbersInPassword) ;
+
+ if (count($aNumbersInPassword[0]) < (int) $this->aCfg['password']['numbers_mandatory']) {
+ $iResult = iConUser::PASS_NOT_ENOUGH_NUMBERS;
+ }
+ }
+
+ // symbols....
+ if ($iResult == iConUser::PASS_OK && isset($this->aCfg['password']['symbols_mandatory']) &&
+ (int) $this->aCfg['password']['symbols_mandatory'] > 0) {
+
+ $aSymbols = array();
+ $sSymbolsDefault = "/[|!@#$%&*\/=?,;.:\-_+~^�\\\]/";
+ if (isset($this->aCfg['password']['symbols_regex']) && !empty($this->aCfg['password']['symbols_regex'])) {
+ $sSymbolsDefault = $this->aCfg['password']['symbols_regex'];
+ }
+
+ preg_match_all($sSymbolsDefault, $sNewPassword, $aSymbols);
+
+ if (count($aSymbols[0]) < (int) $this->aCfg['password']['symbols_mandatory']) {
+ $iResult = iConUser::PASS_NOT_ENOUGH_SYMBOLS;
+ }
+ }
+
+ // mixed case??
+ if ($iResult == iConUser::PASS_OK && isset($this->aCfg['password']['mixed_case_mandatory']) &&
+ (int) $this->aCfg['password']['mixed_case_mandatory'] > 0) {
+
+ $aLowerCaseChars = array();
+ $aUpperCaseChars = array();
+
+ preg_match_all("/[a-z]/", $sNewPassword, $aLowerCaseChars);
+ preg_match_all("/[A-Z]/", $sNewPassword, $aUpperCaseChars);
+
+ if ((count($aLowerCaseChars[0]) < (int) $this->aCfg['password']['mixed_case_mandatory']) ||
+ (count($aUpperCaseChars[0]) < (int) $this->aCfg['password']['mixed_case_mandatory'])) {
+ $iResult = iConUser::PASS_NOT_ENOUGH_MIXED_CHARS;
+ }
+ }
+ }
+
+ return $iResult;
+ }
+
+ /**
+ * This password checks the password strength. In "standard" implementation, it uses
+ * cracklib, if administrated and available. Other possible checks are checks against
+ * user list with birth dates or similar, non direct "maskable" checks.
+ *
+ * Following configuration values are recognized:
+ * $this->aCfg['password']['use_cracklib'], bool
+ * En- or disable these checks...
+ * $this->aCfg['password']['cracklib_dict'], string
+ * Path and file name (without file extension!) to dictionary you want to use. This setting is
+ * mandatory!
+ *
+ * Please ensure that you have a working crack module installed. If the function crack_opendict is
+ * not available, the check are omitted and the result is iConUser::PASS_OK.
+ *
+ * @param string $sNewPassword
+ * @return int
+ */
+ public function checkPasswordStrength ($sNewPassword) {
+ $iResult = iConUser::PASS_OK;
+
+ // if cracklib functions available and cracklib checks are enabled, check password against cracklib...
+ if (function_exists('crack_opendict')) {
+ if (isset($this->aCfg['password']['use_cracklib']) && $this->aCfg['password']['use_cracklib'] == true) {
+ //print "CHECK 1 \n";
+ if (isset($this->aCfg['password']['cracklib_dict']) && !empty($this->aCfg['password']['cracklib_dict'])) {
+ $rCrackLib = crack_opendict ($this->aCfg['password']['cracklib_dict']);
+
+ if ($rCrackLib !== false) {
+ $bCrackResult = crack_check ($rCrackLib, $sNewPassword);
+
+ if ($bCrackResult != true) {
+ // check last message and map it to PASS_* constant
+ $sLastMessage = crack_getlastmessage();
+ #echo ' LastMessage: '.$sLastMessage;
+ switch (strtolower($sLastMessage)) {
+ case "strong password": {
+ // hmm, seems as it is strong enough?!
+ $iResult = iConUser::PASS_OK;
+ break;
+ }
+
+ case "it is too short":
+ case "it's way too short": {
+ $iResult = iConUser::PASS_TO_SHORT;
+ break;
+ }
+
+ case "it does not contain enough different characters": {
+ $iResult = iConUser::PASS_NOT_ENOUGH_DIFFERENT_CHARS;
+ break;
+ }
+
+ /*
+ * I list all strings addtionally to default case here for
+ * further "differentiation".
+ */
+ case "it is too simplistic/systematic":
+ case "it is all whitespace":
+ case "it looks like a national insurance number.":
+ case "it is based on a dictionary word":
+ case "it is based on a (reversed) dictionary word":
+ default: {
+ $iResult = iConUser::PASS_NOT_STRONG;
+ break;
+ }
+
+ }
+ }
+ }
+
+ // close dictionary...
+ crack_closedict($rCrackLib);
+ }
+ }
+ }
+
+ return $iResult;
+ }
+
+ /**
+ * This static method provides a simple way to get error messages depending
+ * on error code $iErrorCode, which is returned by checkPassword* methods.
+ *
+ * @param int $iErrorCode
+ * @param array $aCfg Contenido configuration array
+ * @return string
+ */
+ public static function getErrorString ($iErrorCode, $aCfg) {
+ $sError = "";
+
+ switch ($iErrorCode) {
+ case iConUser::PASS_NOT_ENOUGH_MIXED_CHARS: {
+ $sError = sprintf(i18n("Please use at least %d lower and upper case characters in your password!"),
+ $aCfg['password']['mixed_case_mandatory']);
+ break;
+ }
+ case iConUser::PASS_NOT_ENOUGH_NUMBERS: {
+ $sError = sprintf(i18n("Please use at least %d numbers in your password!"),
+ $aCfg['password']['numbers_mandatory']);
+ break;
+ }
+ case iConUser::PASS_NOT_ENOUGH_SYMBOLS : {
+ $sError = sprintf(i18n("Please use at least %d symbols in your password!"),
+ $aCfg['password']['symbols_mandatory']);
+ break;
+ }
+ case iConUser::PASS_TO_SHORT: {
+ $sError = sprintf(i18n("Password is too short! Please use at least %d signs."),
+ ($aCfg['password']['min_length'] > 0 ? $aCfg['password']['min_length'] :
+ iConUser::MIN_PASS_LENGTH_DEFAULT));
+ break;
+ }
+ case iConUser::PASS_NOT_ENOUGH_DIFFERENT_CHARS : {
+ $sError = sprintf(i18n("Password does not contain enough different characters."));
+ break;
+ }
+ case iConUser::PASS_NOT_ENOUGH_MIXED_CHARS: {
+ $sError = sprintf(i18n("Please use at least %d lower and upper case characters in your password!"),
+ $aCfg['password']['mixed_case_mandatory']);
+ break;
+ }
+ case iConUser::PASS_NOT_STRONG: {
+ $sError = i18n("Please choose a more secure password!");
+ break;
+ }
+ default: {
+ $sError = "I do not really know whats happened. But your password does not match the
+ policies! Please consult your administrator. The error code is #" . $iErrorCode;
+ }
+
+ }
+
+ return $sError;
+ }
+
+ /**
+ * {@see iConUser::encodePassword()}
+ *
+ * @param string $sPassword
+ * @return string
+ */
+ public static function encodePassword ($sPassword) {
+ return md5($sPassword);
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.csv.php b/conlite/classes/class.csv.php
new file mode 100644
index 0000000..657dc52
--- /dev/null
+++ b/conlite/classes/class.csv.php
@@ -0,0 +1,81 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ *
+ * $Id: class.csv.php 214 2013-01-25 15:50:04Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class CSV
+{
+
+ var $_data = array();
+ var $_delimiter;
+
+ function CSV ()
+ {
+ $this->_delimiter = ";";
+ }
+
+ function setRow ($row)
+ {
+ $args = func_num_args();
+
+ for ($arg=1;$arg<$args;$arg++)
+ {
+ $ma = func_get_arg($arg);
+ $this->setCell($row, $arg, $ma);
+ }
+ }
+
+ function setCell($row, $cell, $data)
+ {
+ $row = Contenido_Security::escapeDB($row);
+ $cell = Contenido_Security::escapeDB($cell);
+ $data = Contenido_Security::escapeDB($data);
+
+ $data = str_replace('"', '""', $data);
+ $this->_data[$row][$cell] = '"'.$data.'"';
+ }
+
+ function setDelimiter ($delimiter)
+ {
+ $this->_delimiter = $delimiter;
+ }
+
+ function make() {
+ $out = '';
+ foreach ($this->_data as $row => $line) {
+ $out .= implode($this->_delimiter, $line);
+ $out .= "\r\n";
+ }
+ return $out;
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.dbfs.php b/conlite/classes/class.dbfs.php
new file mode 100644
index 0000000..3cf46f9
--- /dev/null
+++ b/conlite/classes/class.dbfs.php
@@ -0,0 +1,435 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created 2003-12-21
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2009-10-13, Dominik Ziegler, added "attachment" to Content-Disposition to force browsers downloading the file
+ * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting
+ * modified 2011-06-02, Murat Purc, Fixed typo in function write()
+ *
+ * $Id: class.dbfs.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class DBFSCollection extends ItemCollection
+{
+ /**
+ * Constructor Function
+ * @param none
+ */
+ public function __construct()
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["dbfs"], "iddbfs");
+ $this->_setItemClass("DBFSItem");
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function DBFSCollection()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+
+ public function outputFile($path)
+ {
+ global $client, $auth;
+
+ $path = Contenido_Security::escapeDB($path, null);
+ $client = Contenido_Security::toInteger($client);
+ $path = $this->strip_path($path);
+ $dir = dirname($path);
+ $file = basename($path);
+
+ if ($dir == ".") {
+ $dir = "";
+ }
+
+ $this->select("dirname = '".$dir."' AND filename = '".$file."' AND idclient = '".$client."' LIMIT 1");
+
+ if ($item = $this->next()) {
+ $properties = new PropertyCollection();
+ // Check if we're allowed to access it
+ if ($properties->getValue("upload", "dbfs:/".$dir."/".$file, "file", "protected") == "1") {
+ if ($auth->auth["uid"] == "nobody") {
+ header("HTTP/1.0 403 Forbidden");
+ return;
+ }
+ }
+ $mimetype = $item->get("mimetype");
+
+ header("Cache-Control: ");// leave blank to avoid IE errors
+ header("Pragma: ");// leave blank to avoid IE errors
+ header("Content-Type: $mimetype");
+ header("Etag: ".md5(mt_rand()));
+
+ // header("Content-Disposition: filename=$file");
+ header("Content-Disposition: attachment; filename=$file");
+
+ echo $item->get("content");
+ }
+ }
+
+ public function writeFromFile($localfile, $targetfile)
+ {
+ $targetfile = $this->strip_path($targetfile);
+ $mimetype = mime_content_type($localfile);
+
+ $this->write($targetfile, file_get_contents($localfile), $mimetype);
+ }
+
+ public function writeToFile($sourcefile, $localfile)
+ {
+ $sourcefile = $this->strip_path($sourcefile);
+
+ file_put_contents($localfile, $this->read($sourcefile));
+ }
+
+ public function write($file, $content = "", $mimetype = "")
+ {
+ $file = $this->strip_path($file);
+
+ if (!$this->file_exists($file)) {
+ $this->create($file, $mimetype);
+ }
+ $this->setContent($file, $content);
+ }
+
+ public function hasFiles($path)
+ {
+ global $client;
+
+ $path = $this->strip_path($path);
+ $client = Contenido_Security::toInteger($client);
+
+ /* Are there any subdirs? */
+ $this->select("dirname LIKE '".$path."/%' AND idclient = '".$client."' LIMIT 1");
+ if ($this->count() > 0) {
+ return true;
+ }
+
+ $this->select("dirname LIKE '".$path."%' AND idclient = '".$client."' LIMIT 2");
+
+ if ($this->count() > 1) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function read($file)
+ {
+ return ($this->getContent($file));
+ }
+
+ public function file_exists($path)
+ {
+ global $client;
+
+ $path = $this->strip_path($path);
+ $dir = dirname($path);
+ $file = basename($path);
+
+ if ($dir == ".") {
+ $dir = "";
+ }
+
+ $client = Contenido_Security::toInteger($client);
+
+ $this->select("dirname = '".$dir."' AND filename = '".$file."' AND idclient = '".$client."' LIMIT 1");
+ if ($this->next()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function dir_exists($path)
+ {
+ global $client;
+
+ $path = $this->strip_path($path);
+
+ if ($path == "") {
+ return true;
+ }
+
+ $client = Contenido_Security::toInteger($client);
+
+ $this->select("dirname = '".$path."' AND filename = '.' AND idclient = '".$client."' LIMIT 1");
+ if ($this->next()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function parent_dir($path)
+ {
+ $path = dirname($path);
+
+ return $path;
+ }
+
+ public function create($path, $mimetype = "", $content = "")
+ {
+ global $client, $cfg, $auth;
+
+ $client = Contenido_Security::toInteger($client);
+
+ if (substr($path,0,1) == "/") {
+ $path = substr($path,1);
+ }
+
+ $dir = dirname($path);
+ $file = basename($path);
+
+ if ($dir == ".") {
+ $dir = "";
+ }
+
+ if ($file == "") {
+ return;
+ }
+
+ if ($file != ".") {
+ if ($dir != "") {
+ // Check if the directory exists. If not, create it.
+ $this->select("dirname = '".$dir."' AND filename = '.' AND idclient = '".$client."' LIMIT 1");
+ if (!$this->next()) {
+ $this->create($dir."/.");
+ }
+ }
+ } else {
+ $parent = $this->parent_dir($dir);
+
+ if ($parent != ".") {
+ if (!$this->dir_exists($parent)) {
+ $this->create($parent."/.");
+ }
+ }
+ }
+
+ if ($dir && !$this->dir_exists($dir) || $file != ".") {
+ $item = parent::create();
+ $item->set("idclient", $client);
+ $item->set("dirname", $dir);
+ $item->set("filename", $file);
+ $item->set("size", strlen($content));
+
+ if ($mimetype != "") {
+ $item->set("mimetype", $mimetype);
+ }
+
+ $item->set("content", $content);
+ $item->set("created", date("Y-m-d H:i:s"), false);
+ $item->set("author", $auth->auth["uid"]);
+ $item->store();
+ }
+ return ($item);
+ }
+
+ public function setContent($path, $content)
+ {
+ global $client;
+
+ $client = Contenido_Security::toInteger($client);
+ $path = $this->strip_path($path);
+ $dirname = dirname($path);
+ $filename = basename($path);
+
+ if ($dirname == ".") {
+ $dirname = "";
+ }
+
+ $this->select("dirname = '".$dirname."' AND filename = '".$filename."' AND idclient = '".$client."' LIMIT 1");
+ if ($item = $this->next()) {
+ $item->set("content", $content);
+ $item->set("size", strlen($content));
+ $item->store();
+ }
+ }
+
+ public function getSize($path)
+ {
+ global $client;
+
+ $client = Contenido_Security::toInteger($client);
+ $path = $this->strip_path($path);
+ $dirname = dirname($path);
+ $filename = basename($path);
+
+ if ($dirname == ".") {
+ $dirname = "";
+ }
+
+ $this->select("dirname = '".$dirname."' AND filename = '".$filename."' AND idclient = '".$client."' LIMIT 1");
+ if ($item = $this->next()) {
+ return $item->get("size");
+ }
+ }
+
+ public function getContent($path)
+ {
+ global $client;
+
+ $client = Contenido_Security::toInteger($client);
+ $dirname = dirname($path);
+ $filename = basename($path);
+
+ if ($dirname == ".") {
+ $dirname = "";
+ }
+
+ $this->select("dirname = '".$dirname."' AND filename = '".$filename."' AND idclient = '".$client."' LIMIT 1");
+ if ($item = $this->next()) {
+ return ($item->get("content"));
+ }
+ }
+
+ public function remove($path)
+ {
+ global $client;
+
+ $client = Contenido_Security::toInteger($client);
+ $path = $this->strip_path($path);
+ $dirname = dirname($path);
+ $filename = basename($path);
+
+ if ($dirname == ".") {
+ $dirname = "";
+ }
+
+ $this->select("dirname = '".$dirname."' AND filename = '".$filename."' AND idclient = '".$client."' LIMIT 1");
+ if ($item = $this->next()) {
+ $this->delete($item->get("iddbfs"));
+ }
+ }
+
+ public function strip_path($path)
+ {
+ if (substr($path,0,5) == "dbfs:") {
+ $path = substr($path,5);
+ }
+
+ if (substr($path,0,1) == "/") {
+ $path = substr($path,1);
+ }
+
+ return $path;
+ }
+
+ /**
+ * checks if time management is activated and if yes then check if file is in period
+ * @param datatype $sPath
+ * @return bool $bAvailable
+ */
+ public function checkTimeManagement($sPath, $oProperties)
+ {
+ global $contenido;
+ if ($contenido) {
+ return true;
+ }
+ $sPath = Contenido_Security::toString($sPath);
+ $bAvailable = true;
+ $iTimeMng = Contenido_Security::toInteger($oProperties->getValue("upload", $sPath, "file", "timemgmt"));
+ if ($iTimeMng == 0) {
+ return true;
+ }
+ $sStartDate = $oProperties->getValue("upload", $sPath, "file", "datestart");
+ $sEndDate = $oProperties->getValue("upload", $sPath, "file", "dateend");
+
+ $iNow = time();
+
+ if ($iNow < $this->dateToTimestamp($sStartDate) ||
+ ($iNow > $this->dateToTimestamp($sEndDate) && (int)$this->dateToTimestamp($sEndDate) > 0)) {
+
+ return false;
+ }
+ return $bAvailable;
+ }
+
+ /**
+ * converts date to timestamp:
+ * @param string $sDate
+ * @return int $iTimestamp
+ */
+ public function dateToTimestamp($sDate)
+ {
+ return strtotime($sDate);
+ }
+}
+
+
+class DBFSItem extends Item
+{
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false)
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["dbfs"], "iddbfs");
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function DBFSItem($mId = false)
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+
+ public function store()
+ {
+ global $auth;
+
+ $this->set("modified", date("Y-m-d H:i:s"), false);
+ $this->set("modifiedby", $auth->auth["uid"]);
+
+ parent::store();
+ }
+
+ public function setField($field, $value, $safe = true)
+ {
+ if ($field == "dirname" || $field == "filename" || $field == "mimetype") {
+ // Don't do safe encoding
+ $safe = false;
+
+ $value = str_replace("'", "", $value);
+ $value = str_replace('"', "", $value);
+ }
+
+ parent::setField($field, $value, $safe);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.excel.php b/conlite/classes/class.excel.php
new file mode 100644
index 0000000..34af9db
--- /dev/null
+++ b/conlite/classes/class.excel.php
@@ -0,0 +1,89 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ *
+ * $Id: class.excel.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+cInclude('pear', 'Spreadsheet/Excel/Writer.php');
+
+class ExcelWorksheet
+{
+ var $_data = array();
+ var $_title;
+ var $_filename;
+
+ function ExcelWorksheet ($title, $filename)
+ {
+ $this->_title = Contenido_Security::escapeDB($title, null);
+ $this->_filename = Contenido_Security::escapeDB($filename, null);
+ }
+
+ function setRow ($row)
+ {
+ $row = Contenido_Security::escapeDB($row, null);
+ $args = func_num_args();
+
+ for ($arg=1;$arg<$args;$arg++)
+ {
+ $ma = func_get_arg($arg);
+ $this->setCell($row, $arg, $ma);
+ }
+ }
+
+ function setCell($row, $cell, $data)
+ {
+ $row = Contenido_Security::escapeDB($row, null);
+ $cell = Contenido_Security::escapeDB($cell, null);
+ $data = Contenido_Security::escapeDB($data, null);
+ $this->_data[$row][$cell] = $data;
+ }
+
+ function make ()
+ {
+
+ $workbook = new Spreadsheet_Excel_Writer();
+ $workbook->send($this->_filename);
+
+ $worksheet = & $workbook->addWorksheet($this->_title);
+
+ foreach ($this->_data as $row => $line)
+ {
+ foreach ($line as $col => $coldata)
+ {
+ $worksheet->writeString($row-1, $col-1, $coldata);
+ }
+
+ }
+
+ $workbook->close();
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.form.php b/conlite/classes/class.form.php
new file mode 100644
index 0000000..b698a49
--- /dev/null
+++ b/conlite/classes/class.form.php
@@ -0,0 +1,683 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2009-10-23, Murat Purc, removed deprecated function (PHP 5.3 ready)
+ *
+ * $Id: class.form.php 80 2012-05-29 12:38:23Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class Form {
+
+ /**
+ * counter
+ * @var int
+ */
+ var $counter = 0;
+
+ /**
+ * passed
+ * @var bool
+ */
+ var $passed = false;
+
+ /**
+ * isSend
+ * @var bool
+ */
+ var $isSend = false;
+
+ /**
+ * debug
+ * @var bool
+ */
+ var $debug = false;
+
+ /**
+ * fields
+ * @var array
+ */
+ var $fields = array();
+
+ /**
+ * defaults
+ * @var array
+ */
+ var $default = array();
+
+ /**
+ * action
+ * @var string
+ */
+ var $action = '';
+
+ /**
+ * method
+ * @var string
+ */
+ var $method = 'post';
+
+ /**
+ * enctype
+ * @var string
+ */
+ var $enctype = '';
+
+ /**
+ * target
+ * @var string
+ */
+ var $target = '_self';
+
+ /**
+ * Constructor Function
+ * @param
+ */
+ function Form() {
+ // empty
+ } // end function
+
+ /**
+ * Add()
+ * Add a form element
+ * @return void
+ */
+ function Add($name) {
+ $name = Contenido_Security::escapeDB($name, null);
+ $this->counter ++;
+ $this->fields[$this->counter]['name'] = $name;
+ } // end function
+
+ /**
+ * SetDefault()
+ * Add a default value
+ * @return void
+ */
+ function SetDefault($name, $value) {
+ $name = Contenido_Security::escapeDB($name, null);
+ $value = Contenido_Security::escapeDB($value, null);
+ $this->default[$name] = $value;
+ } // end function
+
+ /**
+ * Define()
+ * Define properties of the form or the elements
+ * @var string $which Which property to define
+ * @var string $value Values of the property
+ * @return void
+ */
+ function Define($which, $value) {
+ $which = Contenido_Security::escapeDB($which, null);
+ $value = Contenido_Security::escapeDB($value, null);
+ if (0 == $this->counter) {
+ $this->$which = $value;
+ } else {
+ $this->fields[$this->counter][$which] = $value;
+ }
+ } // end function
+
+ /**
+ * Passed()
+ * Checks if the form passed
+ * @return bool TRUE: Form passed without errors, FALSE: Errors
+ */
+ function Passed() {
+ return $this->passed;
+ } // end function
+
+ /**
+ * Form::generate()
+ * @param $template string Path/Filename of the template to use
+ * @return void
+ */
+ function Generate($template) {
+ $template = Contenido_Security::escapeDB($template);
+
+ // get form values
+ $this->GetFormValues();
+
+ // if form was submitted before
+ // validate the fields
+ if ($this->isSend == true) {
+ $this->checkFormValues();
+ }
+
+ // at least one entry is invalid
+ // generate the form
+ if (!$this->passed) {
+
+ // check if the template is a file or a string
+ if(!@file_exists($template)) {
+ // template is a string
+ $tmp_template['complete'] = explode("\n", $template);
+ } else {
+ // template is a file
+ $tmp_template['complete'] = file($template);
+ }
+
+ // line numbers for
+ // the dynamic blocks
+ $tmp_template['line_nr']['start'] = 0;
+ $tmp_template['line_nr']['end'] = 0;
+ $tmp_template['line_nr']['max'] = count($tmp_template['complete']);
+
+ // parts of the template
+ $tmp_template['start'] = '';
+ $tmp_template['block'] = '';
+ $tmp_template['end'] = '';
+
+ // search the template for
+ // dynamic blocks
+ foreach ($tmp_template['complete'] as $line => $content) {
+
+ // search for start block tag
+ if (strstr($content, '')) {
+ $tmp_template['line_nr']['start'] = $line + 1;
+ }
+
+ // search for end block tag
+ if (strstr($content, '')) {
+ $tmp_template['line_nr']['end'] = $line - 1;
+ }
+ }
+
+ // extract start part
+ for ($i=0; $i<$tmp_template['line_nr']['start']; $i++) {
+ $tmp_template['start'] .= $tmp_template['complete'][$i];
+ }
+
+ // extract block
+ for ($i=$tmp_template['line_nr']['start']; $i<=$tmp_template['line_nr']['end']; $i++) {
+ $tmp_template['block'] .= $tmp_template['complete'][$i];
+ }
+
+ // extract end part
+ for ($i=$tmp_template['line_nr']['end']+1; $i<=$tmp_template['line_nr']['max']; $i++) {
+ $tmp_template['end'] .= $tmp_template['complete'][$i];
+ }
+
+ /**
+ * Generate the start template
+ * @access private
+ */
+
+ $tmp_needles[] = '{ACTION}';
+ $tmp_needles[] = '{METHOD}';
+ $tmp_needles[] = '{ENCTYPE}';
+ $tmp_needles[] = '{TARGET}';
+
+ $tmp_replacements[] = $this->action;
+ $tmp_replacements[] = $this->method;
+ $tmp_replacements[] = $this->enctype;
+ $tmp_replacements[] = $this->target;
+
+ unset($tmp_template['complete']);
+
+ $tmp_template['complete'] .= str_replace($tmp_needles, $tmp_replacements, $tmp_template['start']);
+
+ // generate blocks
+ $fieldcount = count($this->fields);
+
+ unset($tmp_needles);
+ $tmp_needles[] = '{CAPTION}';
+ $tmp_needles[] = '{FIELD}';
+ $tmp_needles[] = '{BGCOLOR}';
+
+ for ($i=1; $i<=$fieldcount; $i++) {
+
+ // set default classerror style
+ if (!isset($this->fields[$i]['classerror'])) {
+ $this->fields[$i]['classerror'] = $this->default['classerror'];
+ }
+
+ // set default classcaption style
+ if (!isset($this->fields[$i]['classcaption'])) {
+ $this->fields[$i]['classcaption'] = $this->default['classcaption'];
+ }
+
+ // set default classinput style
+ if (!isset($this->fields[$i]['classinput'])) {
+ $this->fields[$i]['classinput'] = $this->default['classinput'];
+ }
+
+ // unset replacement array
+ unset($tmp_replacements);
+
+ // set the correct caption class
+ if ($this->isSend && $this->fields[$i]['passed'] == false) {
+ // error
+ $tmp_replacements[] = ''.$this->fields[$i]['caption'].' ';
+ } else {
+ // passed
+ $tmp_replacements[] = ''.$this->fields[$i]['caption'].' ';
+ }
+
+ // FormField instance
+ $field = new FormField;
+
+ // Get Code for one element
+ $tmp_replacements[] = $field->GenerateCode($this->fields[$i]);
+
+ // alternate between row background colors
+ if ($this->default['lightcolor'] != '' && $this->default['darkcolor'] != '') {
+ $tmp_replacements[] = (is_int($i/2)) ? $this->default['lightcolor'] : $this->default['darkcolor'];
+ } else {
+ $tmp_replacements[] = '';
+ }
+
+ // replace placeholders with replacements
+ $tmp_template['complete'] .= str_replace($tmp_needles, $tmp_replacements, $tmp_template['block']);
+ }
+
+ // end part
+ $tmp_template['complete'] .= $tmp_template['end'];
+
+ // output
+ echo $tmp_template['complete'];
+
+ // debug info
+ if ($this->debug) {
+ echo '';
+ print_r($this->fields);
+ echo ' ';
+ }
+
+ } else {
+ // there are no errors
+ // and the form passed
+
+ // do nothing
+ }
+
+ } // end function
+
+
+ /**
+ * GetFormValues()
+ * Extract the Form Data from the $_POST or $_GET
+ * global arrays
+ * @return void
+ */
+ function GetFormValues() {
+
+ if (strtolower($this->method) == 'post') {
+ // extract values from the $_POST global array
+ foreach ($this->fields as $id => $element) {
+ // check if value exists, extract it
+ if (isset($_POST[$element['name']])) {
+ $this->fields[$id]['value'] = $_POST[$element['name']];
+ $this->isSend = true;
+ } else {
+ $this->isSend = false;
+ }
+ }
+
+ } elseif (strtolower($this->method) == 'get') {
+ // extract values from the $_GET global array
+ foreach ($this->fields as $id => $element) {
+ // check if value exists, extract it
+ if (isset($_POST[$element['name']])) {
+ $this->fields[$id]['value'] = $_GET[$element['name']];
+ $this->isSend = true;
+ } else {
+ $this->isSend = false;
+ }
+ }
+ }
+
+ } // end function
+
+ /**
+ * CheckFormValues()
+ *
+ * @return void
+ */
+ function CheckFormValues() {
+
+ $tmp_passed = true;
+
+ foreach ($this->fields as $id => $element) {
+
+ $check = new FormCheck;
+
+ switch (strtolower($element['checktype'])) {
+
+ case 'none':
+ $this->fields[$id]['passed'] = true;
+ break;
+
+ case 'simple':
+ if ('checkbox' == $element['type']) {
+ $this->fields[$id]['passed'] = (isset($element['value'])) ? true : false;
+ } else {
+ $this->fields[$id]['passed'] = ('select' == $element['type']) ? $check->isNotEmpty($element['value']) : $check->isNotNull($element['value']);
+ }
+ break;
+
+ case 'numeric':
+ $this->fields[$id]['passed'] = $check->isNumeric($element['value']);
+ break;
+
+ case 'alphabetic':
+ $this->fields[$id]['passed'] = $check->isAlphabetic($element['value']);
+ break;
+
+ case 'email':
+ $this->fields[$id]['passed'] = $check->isEmail($element['value']);
+ break;
+
+ case 'datefromto':
+ $tmp_check = array();
+ $tmp_check[] = $check->isNumeric($element['value']['from']['d']);
+ $tmp_check[] = $check->isNumeric($element['value']['from']['m']);
+ $tmp_check[] = $check->isNumeric($element['value']['from']['y']);
+ $tmp_check[] = $check->isNumeric($element['value']['to']['d']);
+ $tmp_check[] = $check->isNumeric($element['value']['to']['m']);
+ $tmp_check[] = $check->isNumeric($element['value']['to']['y']);
+ $this->fields[$id]['passed'] = (in_array(false, $tmp_check)) ? false : true;
+ unset($tmp_check);
+ break;
+
+ case 'fromto':
+ $tmp_check = array();
+ $tmp_check[] = $check->isNumeric($element['value']['from']);
+ $tmp_check[] = $check->isNumeric($element['value']['to']);
+ $this->fields[$id]['passed'] = (in_array(false, $tmp_check)) ? false : true;
+ unset($tmp_check);
+ break;
+
+ default:
+ if ('checkbox' == $element['type']) {
+ $this->fields[$id]['passed'] = (isset($element['value'])) ? true : false;
+ } else {
+ $this->fields[$id]['passed'] = ('select' == $element['type']) ? $check->isNotEmpty($element['value']) : $check->isNotNull($element['value']);
+ }
+ break;
+
+ } // end switch
+
+ if ($this->fields[$id]['passed'] == false) {
+ $tmp_passed = false;
+ }
+
+ } // end foreach
+
+ $this->passed = $tmp_passed;
+
+ }
+
+
+} // end class
+
+/**
+ * Class Formfield
+ * Class for creating form elements
+ * @author Jan Lengowski
+ * @version 1.0
+ * @copyright four for business 2002
+ */
+class FormField {
+
+ /**
+ * Constructor Function
+ */
+ function FormField() {
+ // do nothing
+ } // end function
+
+ /**
+ * Function GenerateCode()
+ * Created HTML Code depending on
+ * the type of form field selected.
+ * @argument $item array All necessary formfield data
+ */
+ function GenerateCode($item) {
+
+ if (!is_array($item)){
+ // no data
+ exit ('Argument is not an array!');
+
+ } else {
+ // switch form type
+ $tmp_ret_str = '';
+
+ switch (strtolower($item['type'])) {
+
+ case 'caption':
+ // Feld ist nur eine Beschriftung,
+ // HTML ist f�r das Feld erlaubt.
+ $tmp_ret_str = ''.$item['value'].' ';
+ break;
+
+ case 'hidden':
+ // Feld ist versteckt und dient
+ // nur zum �bermitteln von Daten.
+ $tmp_ret_str = ' ';
+ break;
+
+ case 'text':
+ // Feld ist ein einzeiliges Text-
+ // Eingabefeld.
+ $tmp_ret_str = ' ';
+ break;
+
+ case 'textarea':
+ // Feld ist ein mehrzeiliges Text-
+ // Eingabefeld.
+ $tmp_ret_str = '';
+ break;
+
+ case 'select':
+ // Feld ist ein Auswahlfeld.
+ $tmp_ret_str = '';
+
+ if (!is_array($item['values'])) {
+ // no values
+ $tmp_ret_str .= 'no values passed ';
+
+ } else {
+ // values array passed
+ foreach ($item['values'] as $key => $value) {
+
+ if ($item['value'] == $key) {
+ // selected
+ $tmp_ret_str .= ''.$value.' ';
+
+ } else {
+ // unselected
+ $tmp_ret_str .= ''.$value.' ';
+ }
+
+
+ } // end foreach
+
+ }
+
+ $tmp_ret_str .= ' ';
+
+ break;
+
+ case 'radiolist':
+ // Liste mit radio buttons.
+ if (!is_array($item['values'])) {
+ // no values
+ $tmp_ret_str .= 'no values passed ';
+
+ } else {
+ $tmp_ret_str .= '';
+ }
+ break;
+
+ case 'checkbox':
+ if (isset($item['value'])) {
+ $tmp_ret_str .= ' ';
+
+ } else {
+ $tmp_ret_str .= ' ';
+
+ }
+ break;
+
+ case 'datefromto':
+ $tmp_ret_str .= '';
+
+ break;
+
+ /* TimeJob hardcoded dummy */
+ case 'suche':
+ $tmp_ret_str .= ' ';
+ $tmp_ret_str .= ' ';
+ break;
+
+ case 'fromto':
+ $tmp_ret_str .= ' ';
+ $tmp_ret_str .= ' bis ';
+ $tmp_ret_str .= ' ';
+
+ break;
+
+ } // end switch
+
+ return $tmp_ret_str;
+ }
+
+ } // end function
+
+
+} // end class
+
+
+/**
+ * class FormCheck
+ * Class for checking form values
+ * @author Jan Lengowski
+ * @version 1.0
+ * @copyright four for business 2002
+ */
+class FormCheck {
+
+ /**
+ * Constructor function
+ * @access private
+ */
+ function FormCheck () {
+ // empty
+ } // end function
+
+ /**
+ * isNotEmpty()
+ * Checks if a value is NOT empty
+ * @param $value mixed Value to check
+ */
+ function isNotEmpty($value) {
+ return ('' == $value || 0 == $value) ? false : true;
+ } // end function
+
+ /**
+ * isNotNull()
+ * Checks if a value is NOT null
+ * @param $value mixed Value to check
+ */
+ function isNotNull($value) {
+ return ($value) ? true : false;
+ } // end function
+
+ /**
+ * isNumeric()
+ * Checks if a value is numeric
+ * @param $value mixed Value to check
+ */
+ function isNumeric($value) {
+ if ('' != $value) {
+ return (!preg_match('/[^0-9]/', $value)) ? true : false;
+ } else {
+ return false;
+ }
+ } // end function
+
+ /**
+ * isAlphabetic()
+ * Checks if a value is alphabetic
+ * @param $value mixed Value to check
+ */
+ function isAlphabetic($value) {
+ return (!preg_match('/[^a-zA-Z]/', $value)) ? true : false;
+ } // end function
+
+ /**
+ * isEmail()
+ * Checks if a string is a valid email adress
+ * @param $value string eMail string to check
+ */
+ function isEmail($value) {
+ return (preg_match('/^[a-z0-9\.]+@[a-z0-9\.]+\.[a-z]+$/i', $value)) ? true : false;
+ } // end function
+
+} // end class
+
+?>
diff --git a/conlite/classes/class.frontend.groups.php b/conlite/classes/class.frontend.groups.php
new file mode 100644
index 0000000..7bb56ca
--- /dev/null
+++ b/conlite/classes/class.frontend.groups.php
@@ -0,0 +1,249 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Frederic Schneider, add security fix
+ * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting
+ *
+ * $Id: class.frontend.groups.php 312 2014-06-18 11:01:08Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+/**
+ * Frontend group management class
+ */
+class FrontendGroupCollection extends ItemCollection
+{
+ /**
+ * Constructor Function
+ * @param none
+ */
+ public function __construct()
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["frontendgroups"], "idfrontendgroup");
+ $this->_setItemClass("FrontendGroup");
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function FrontendGroupCollection()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+
+ /**
+ * Creates a new group
+ * @param $groupname string Specifies the groupname
+ * @param $password string Specifies the password (optional)
+ */
+ public function create($groupname)
+ {
+ global $client;
+
+ $group = new FrontendGroup();
+
+ #$_arrInFilters = array('urlencode', 'clHtmlSpecialChars', 'addslashes');
+
+ $mangledGroupName = $group->_inFilter($groupname);
+ $this->select("idclient = '$client' AND groupname = '$mangledGroupName'");
+
+ if ($obj = $this->next()) {
+ $groupname = $groupname. md5(rand());
+ }
+
+ $item = parent::create();
+
+ $item->set("idclient", $client);
+ $item->set("groupname", $groupname);
+ $item->store();
+
+ return $item;
+ }
+
+ /**
+ * Overridden delete method to remove groups from groupmember table
+ * before deleting group
+ *
+ * @param $itemID int specifies the frontend user group
+ */
+ public function delete($itemID)
+ {
+ $associations = new FrontendGroupMemberCollection();
+ $associations->select("idfrontendgroup = '$itemID'");
+
+ while ($item = $associations->next()) {
+ $associations->delete($item->get("idfrontendgroupmember"));
+ }
+ parent::delete($itemID);
+ }
+}
+
+
+/**
+ * Single FrontendGroup Item
+ */
+class FrontendGroup extends Item
+{
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false)
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["frontendgroups"], "idfrontendgroup");
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function FrontendGroup($mId = false)
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+}
+
+
+/**
+ * Frontend group member management class
+ */
+class FrontendGroupMemberCollection extends ItemCollection
+{
+ /**
+ * Constructor Function
+ * @param none
+ */
+ public function __construct()
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["frontendgroupmembers"], "idfrontendgroupmember");
+ $this->_setJoinPartner ('FrontendGroupCollection');
+ $this->_setJoinPartner ('FrontendUserCollection');
+ $this->_setItemClass("FrontendGroupMember");
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function FrontendGroupMemberCollection()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+
+ /**
+ * Creates a new association
+ * @param $idfrontendgroup int specifies the frontend group
+ * @param $idfrontenduser int specifies the frontend user
+ */
+ public function create($idfrontendgroup, $idfrontenduser)
+ {
+ $this->select("idfrontendgroup = '$idfrontendgroup' AND idfrontenduser = '$idfrontenduser'");
+
+ if ($this->next()) {
+ return false;
+ }
+
+ $item = parent::create();
+
+ $item->set("idfrontenduser", $idfrontenduser);
+ $item->set("idfrontendgroup", $idfrontendgroup);
+ $item->store();
+
+ return $item;
+ }
+
+ /**
+ * Removes an association
+ * @param $idfrontendgroup int specifies the frontend group
+ * @param $idfrontenduser int specifies the frontend user
+ */
+ public function remove($idfrontendgroup, $idfrontenduser)
+ {
+ $this->select("idfrontendgroup = '$idfrontendgroup' AND idfrontenduser = '$idfrontenduser'");
+
+ if ($item = $this->next()) {
+ $this->delete($item->get("idfrontendgroupmember"));
+ }
+ }
+
+ /**
+ * Returns all users in a single group
+ * @param $idfrontendgroup int specifies the frontend group
+ * @param $asObjects boolean specifies if the function should return objects
+ * @return array FrontendUser items
+ */
+ public function getUsersInGroup($idfrontendgroup, $asObjects = true)
+ {
+ $this->select("idfrontendgroup = '$idfrontendgroup'");
+
+ $objects = array();
+
+ while ($item = $this->next()) {
+ if ($asObjects) {
+ $user = new FrontendUser;
+ $user->loadByPrimaryKey($item->get("idfrontenduser"));
+ $objects[] = $user;
+ } else {
+ $objects[] = $item->get("idfrontenduser");
+ }
+ }
+
+ return ($objects);
+ }
+}
+
+
+/**
+ * Single FrontendGroup Item
+ */
+class FrontendGroupMember extends Item
+{
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false)
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["frontendgroupmembers"], "idfrontendgroupmember");
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function FrontendGroupMember($mId = false)
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct($mId);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.frontend.logic.php b/conlite/classes/class.frontend.logic.php
new file mode 100644
index 0000000..29114f1
--- /dev/null
+++ b/conlite/classes/class.frontend.logic.php
@@ -0,0 +1,85 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Frederic Schneider, add security fix
+ *
+ * $Id: class.frontend.logic.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ * FrontendLogic: This is the base class for all frontend related logic.
+ *
+ * Basically, the class FrontendLogic is the base class for all your objects in
+ * the frontend. Your child classes define how your objects are named, which
+ * actions and items they contain and which item type they've got.
+ *
+ * A word on actions: Each single object of a FrontendLogic subclass has the
+ * same amount of actions. You can't have a different set of actions for
+ * different objects of the same type.
+ */
+class FrontendLogic
+{
+ /**
+ * getFriendlyName: Returns the friendly (e.g. display) name of your
+ * objects.
+ *
+ * @return string Name of the object
+ */
+ function getFriendlyName ()
+ {
+ return "Inherited class *must* override getFriendlyName";
+ }
+
+ /**
+ * listActions: Lists all actions
+ *
+ * The returned array has the format $actionname => $actiondescription
+ *
+ * @return array Array of all actions
+ */
+ function listActions ()
+ {
+ return array("Inherited class *must* override listActions");
+ }
+
+ /**
+ * listItems: Lists all available items
+ *
+ * The returned array has the format $itemid => $itemname
+ *
+ * @return array Array of items
+ */
+ function listItems ()
+ {
+ return array("Inherited class *must* override listItems");
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.frontend.permissions.php b/conlite/classes/class.frontend.permissions.php
new file mode 100644
index 0000000..76faa32
--- /dev/null
+++ b/conlite/classes/class.frontend.permissions.php
@@ -0,0 +1,169 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Frederic Schneider, add security fix
+ * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting
+ *
+ * $Id: class.frontend.permissions.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ * Frontend user management class
+ */
+class FrontendPermissionCollection extends ItemCollection
+{
+
+ protected $_FrontendPermission;
+
+ /**
+ * Constructor Function
+ * @param none
+ */
+ public function __construct()
+ {
+ global $cfg;
+ $this->_FrontendPermission = new FrontendPermission();
+
+ parent::__construct($cfg["tab"]["frontendpermissions"], "idfrontendpermission");
+ $this->_setItemClass("FrontendPermission");
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function FrontendPermissionCollection()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+
+ /**
+ * Creates a new permission entry
+ * @param $group string Specifies the frontend group
+ * @param $plugin string Specifies the plugin
+ * @param $action string Specifies the action
+ * @param $item string Specifies the item
+ */
+ public function create($group, $plugin, $action, $mitem)
+ {
+ global $lang;
+
+ $item = null;
+ if (!$this->checkPerm($group, $plugin, $action, $mitem)) {
+ $item = parent::create();
+ $item->set("idlang", $lang);
+ $item->set("idfrontendgroup", $group);
+ $item->set("plugin", $plugin);
+ $item->set("action", $action);
+ $item->set("item", $mitem);
+
+ $item->store();
+ }
+
+ return $item;
+ }
+
+ public function setPerm($group, $plugin, $action, $item)
+ {
+ $this->create($group, $plugin, $action, $item);
+ }
+
+ public function checkPerm($group, $plugin, $action, $item, $uselang = false)
+ {
+ global $lang;
+
+ #$checklang = ($uselang !== false) ? $uselang : $lang;
+
+ $group = $this->_FrontendPermission->_inFilter($group);
+ $plugin = $this->_FrontendPermission->_inFilter($plugin);
+ $action = $this->_FrontendPermission->_inFilter($action);
+ $item = $this->_FrontendPermission->_inFilter($item);
+
+ // Check for global permisson
+ $this->select("idlang = '$lang' AND idfrontendgroup = '$group' AND plugin = '$plugin' AND action = '$action' AND item = '__GLOBAL__'");
+
+ if ($this->next()) {
+ return true;
+ }
+
+ // Check for item permisson
+ $this->select("idlang = '$lang' AND idfrontendgroup = '$group' AND plugin = '$plugin' AND action = '$action' AND item = '$item'");
+
+ if ($this->next()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function removePerm($group, $plugin, $action, $item, $uselang = false)
+ {
+ global $lang;
+
+ #$checklang = ($uselang !== false) ? $uselang : $lang;
+
+ $group = $this->_FrontendPermission->_inFilter($group);
+ $plugin = $this->_FrontendPermission->_inFilter($plugin);
+ $action = $this->_FrontendPermission->_inFilter($action);
+ $item = $this->_FrontendPermission->_inFilter($item);
+
+ $this->select("idlang = '$lang' AND idfrontendgroup = '$group' AND plugin = '$plugin' AND action = '$action' AND item = '$item'");
+
+ if ($myitem = $this->next()) {
+ $this->delete($myitem->get("idfrontendpermission"));
+ }
+ }
+}
+
+
+/**
+ * Single FrontendPermission Item
+ */
+class FrontendPermission extends Item
+{
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false)
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["frontendpermissions"], "idfrontendpermission");
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function FrontendPermission($mId = false)
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct($mId);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.frontend.users.php b/conlite/classes/class.frontend.users.php
new file mode 100644
index 0000000..9f63479
--- /dev/null
+++ b/conlite/classes/class.frontend.users.php
@@ -0,0 +1,233 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Frederic Schneider, add security fix
+ * modified 2011-03-14, Murat Purc, adapted to new GenericDB partly ported to PHP 5, formatting
+ *
+ * $Id: class.frontend.users.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+/**
+ * Frontend user management class
+ */
+class FrontendUserCollection extends ItemCollection
+{
+ /**
+ * Constructor Function
+ * @param none
+ */
+ public function __construct()
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["frontendusers"], "idfrontenduser");
+ $this->_setItemClass("FrontendUser");
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function FrontendUserCollection()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+
+ /**
+ * Checks if a specific user already exists
+ * @param $sUsername string specifies the username to search for
+ */
+ public function userExists($sUsername)
+ {
+ global $client;
+
+ $oFrontendUserCollection = new FrontendUserCollection();
+
+ $oFrontendUserCollection->setWhere("idclient", $client);
+ $oFrontendUserCollection->setWhere("username", strtolower($sUsername));
+ $oFrontendUserCollection->query();
+
+ if ($oItem = $oFrontendUserCollection->next()) {
+ return ($oItem);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Creates a new user
+ * @param $username string Specifies the username
+ * @param $password string Specifies the password (optional)
+ */
+ public function create($username, $password = "")
+ {
+ global $client, $auth;
+
+ // Check if the username already exists
+ $this->select("idclient='".Contenido_Security::toInteger($client)."' AND username='".urlencode($username)."'");
+
+ if ($this->next()) {
+ return $this->create($username."_".substr(md5(rand()),0,10), $password);
+ }
+
+ $item = parent::create();
+ $item->set("idclient", $client);
+ $item->set("username", $username);
+ $item->set("password", $password);
+ $item->set("created", date("Y-m-d H:i:s"), false);
+ $item->set("author", $auth->auth["uid"]);
+ $item->set("active", 0);
+
+ $item->store();
+
+ // Put this user into the default groups
+ $fegroups = new FrontendGroupCollection();
+ $fegroups->select("idclient = '".Contenido_Security::toInteger($client)."' AND defaultgroup='1'");
+
+ $members = new FrontendGroupMemberCollection;
+
+ $iduser = $item->get("idfrontenduser");
+
+ while ($fegroup = $fegroups->next()) {
+ $idgroup = $fegroup->get("idfrontendgroup");
+ $members->create($idgroup, $iduser);
+ }
+
+ return $item;
+ }
+
+ /**
+ * Overridden delete method to remove user from groupmember table
+ * before deleting user
+ *
+ * @param $itemID int specifies the frontend user
+ */
+ public function delete($itemID)
+ {
+ $associations = new FrontendGroupMemberCollection();
+ $associations->select("idfrontenduser = '$itemID'");
+
+ while ($item = $associations->next()) {
+ $associations->delete($item->get("idfrontendgroupmember"));
+ }
+ parent::delete($itemID);
+ }
+}
+
+
+/**
+ * Single FrontendUser Item
+ */
+class FrontendUser extends Item
+{
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false)
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["frontendusers"], "idfrontenduser");
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function FrontendUser($mId = false)
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct($mId);
+ }
+
+ /**
+ * Overridden setField method to md5 the password
+ * Sets the value of a specific field
+ *
+ * @param string $field Specifies the field to set
+ * @param string $value Specifies the value to set
+ */
+ public function setField($field, $value, $safe = true)
+ {
+ if ($field == "password") {
+ parent::setField($field, md5($value), $safe);
+ } else {
+ parent::setField($field, $value, $safe);
+ }
+ }
+
+ /**
+ * setRawPassword: Sets the password to a raw value
+ * without md5 encoding.
+ *
+ * @param string $password Raw password
+ */
+ public function setRawPassword($password)
+ {
+ return parent::setField("password", $password);
+ }
+
+ /**
+ * Checks if the given password matches the password in the database
+ * @param $password string Password to check
+ * @return boolean True if the password is correct, false otherwise
+ */
+ public function checkPassword($password)
+ {
+ if (md5($password) == $this->get("password")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function store()
+ {
+ global $auth;
+
+ $this->set("modified", date("Y-m-d H:i:s"), false);
+ $this->set("modifiedby", $auth->auth["uid"]);
+ parent::store();
+ }
+
+ public function getGroupsForUser()
+ {
+ $FrontendGroupMemberCollection = new FrontendGroupMemberCollection();
+ $FrontendGroupMemberCollection->setWhere("idfrontenduser", $this->get("idfrontenduser"));
+ $FrontendGroupMemberCollection->query();
+
+ $groups = array();
+
+ while ($FrontendGroupMember = $FrontendGroupMemberCollection->next()) {
+ $groups[] = $FrontendGroupMember->get("idfrontendgroup");
+ }
+
+ return ($groups);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.genericdb.php b/conlite/classes/class.genericdb.php
new file mode 100644
index 0000000..04986d5
--- /dev/null
+++ b/conlite/classes/class.genericdb.php
@@ -0,0 +1,2211 @@
+
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+global $cfg;
+
+// Try to load GenericDB database driver
+$driver_filename = $cfg['path']['contenido'].$cfg['path']['classes'].'drivers/'.$cfg['sql']['gdb_driver'].'/class.gdb.'.$cfg['sql']['gdb_driver'].'.php';
+
+if (file_exists($driver_filename)) {
+ include_once($driver_filename);
+}
+
+
+/**
+ * Class Contenido_ItemException.
+ * @author Murat Purc
+ * @version 0.1
+ * @copyright four for business AG
+ */
+class Contenido_ItemException extends Exception {}
+
+
+/**
+ * Class Contenido_ItemCache.
+ *
+ * Implements features to cache entries, usually result sets of Item classes.
+ * Contains a list of self instances, where each instance contains cached Items
+ * fore one specific table.
+ *
+ * @author Murat Purc
+ * @version 0.1.2
+ * @copyright four for business AG
+ */
+class Contenido_ItemCache
+{
+ /**
+ * List of self instances (Contenido_ItemCache)
+ * @var array
+ */
+ protected static $_oInstances = array();
+
+ /**
+ * Assoziative cache array
+ * @var array
+ */
+ protected $_aItemsCache = array();
+
+ /**
+ * Table name for current instance
+ * @var string
+ */
+ protected $_sTable = '';
+
+ /**
+ * Max number of items to cache
+ * @var int
+ */
+ protected $_iMaxItemsToCache = 10;
+
+ /**
+ * Enable caching
+ * @var bool
+ */
+ protected $_bEnable = false;
+
+ protected $_iFrame;
+
+ /**
+ * Contructor of Contenido_ItemCache
+ * @param string $sTable Table name
+ * @param array $aOptions Options array as follows:
+ * - $aOptions['max_items_to_cache'] = (int) Number of items to cache
+ * - $aOptions['enable'] = (bool) Flag to enable caching
+ */
+ protected function __construct($sTable, array $aOptions = array())
+ {
+ $this->_sTable = $sTable;
+ if (isset($aOptions['max_items_to_cache']) && (int) $aOptions['max_items_to_cache'] > 0) {
+ $this->_iMaxItemsToCache = (int) $aOptions['max_items_to_cache'];
+ }
+ if (isset($aOptions['enable']) && is_bool($aOptions['enable'])) {
+ $this->_bEnable = (bool) $aOptions['enable'];
+ }
+
+ if(isset($_GET['frame']) && is_numeric($_GET['frame'])) {
+ $this->_iFrame = (int) $_GET['frame'];
+ } else {
+ $this->_bEnable = false;
+ }
+ }
+
+ /**
+ * Prevent cloning
+ */
+ protected function __clone()
+ {
+ }
+
+ /**
+ * Returns item cache instance, creates it, if not done before.
+ * Works as a singleton for one specific table.
+ *
+ * @param string $sTable Table name
+ * @param array $aOptions Options array as follows:
+ * - $aOptions['max_items_to_cache'] = (int) Number of items to cache
+ * - $aOptions['enable'] = (bool) Flag to enable caching
+ */
+ public static function getInstance($sTable, array $aOptions = array())
+ {
+ if (!isset(self::$_oInstances[$sTable])) {
+ self::$_oInstances[$sTable] = new self($sTable, $aOptions);
+ }
+ return self::$_oInstances[$sTable];
+ }
+
+ /**
+ * Returns items cache list.
+ *
+ * @return array
+ */
+ public function getItemsCache()
+ {
+ return $this->_aItemsCache[$this->_iFrame];
+ }
+
+ /**
+ * Returns existing entry from cache by it's id.
+ *
+ * @param mixed $mId
+ * @return array|null
+ */
+ public function getItem($mId)
+ {
+ if (!$this->_bEnable) {
+ return null;
+ }
+
+ if (isset($this->_aItemsCache[$this->_iFrame][$mId])) {
+ return $this->_aItemsCache[$this->_iFrame][$mId];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns existing entry from cache by matching propery value.
+ *
+ * @param mixed $mProperty
+ * @param mixed $mValue
+ * @return array|null
+ */
+ public function getItemByProperty($mProperty, $mValue)
+ {
+ if (!$this->_bEnable) {
+ return null;
+ }
+
+ // loop thru all cached entries and try to find a entry by it's property
+ if(is_array($this->_aItemsCache[$this->_iFrame])
+ && count($this->_aItemsCache[$this->_iFrame]) > 0) {
+ foreach ($this->_aItemsCache[$this->_iFrame] as $id => $aEntry) {
+ if (isset($aEntry[$mProperty]) && $aEntry[$mProperty] == $mValue) {
+ return $aEntry;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns existing entry from cache by matching properties and their values.
+ *
+ * @param array $aProperties Assoziative key value pairs
+ * @return array|null
+ */
+ public function getItemByProperties(array $aProperties)
+ {
+ if (!$this->_bEnable) {
+ return null;
+ }
+
+ // loop thru all cached entries and try to find a entry by it's property
+ foreach ($this->_aItemsCache as $id => $aEntry) {
+ $mFound = null;
+ foreach ($aProperties as $key => $value) {
+ if (isset($aEntry[$key]) && $aEntry[$key] == $value) {
+ if (null === $mFound) {
+ $mFound = true;
+ }
+ } else {
+ $mFound = false;
+ break;
+ }
+ if (true === $mFound) {
+ return $aEntry;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adds passed item data to internal cache
+ *
+ * @param mixed $mId
+ * @param array $aData Usually the recordset
+ * @return void
+ */
+ public function addItem($mId, array $aData)
+ {
+ if (!$this->_bEnable) {
+ return null;
+ }
+
+ if(isset($this->_aItemsCache[$this->_iFrame])) {
+ $aTmpItemsArray = $this->_aItemsCache[$this->_iFrame];
+
+ if ($this->_iMaxItemsToCache == count($aTmpItemsArray)) {
+ // we have reached the maximum number of cached items, remove first entry
+ $firstEntryKey = array_shift($aTmpItemsArray);
+ if(is_array($firstEntryKey)) return null;
+ unset($this->_aItemsCache[$this->_iFrame][$firstEntryKey]);
+ }
+ }
+
+ // add entry
+ $this->_aItemsCache[$this->_iFrame][$mId] = $aData;
+ }
+
+ /**
+ * Removes existing cache entry by it's key
+ *
+ * @param mixed $mId
+ * @return void
+ */
+ public function removeItem($mId)
+ {
+ if (!$this->_bEnable) {
+ return null;
+ }
+
+ // remove entry
+ if (isset($this->_aItemsCache[$this->_iFrame][$mId])){
+ unset($this->_aItemsCache[$this->_iFrame][$mId]);
+ }
+ }
+}
+
+
+/**
+ * Class Contenido_ItemBaseAbstract.
+ * Base class with common features for database based items and item collections.
+ *
+ * @author Murat Purc
+ * @version 0.2
+ * @copyright four for business AG
+ */
+abstract class Contenido_ItemBaseAbstract
+{
+ /**
+ * Database instance, contains the database object
+ * @var DB_ConLite
+ */
+ protected $db;
+
+ /**
+ * Second DB instance, is required for some additional queries without
+ * losing an current existing query result.
+ * @var DB_ConLite
+ */
+ protected $secondDb;
+
+ /**
+ * Property collection instance
+ * @var PropertyCollection
+ */
+ protected $properties;
+
+ /**
+ * Item cache instance
+ * @var Contenido_ItemCache
+ */
+ protected static $_oCache;
+
+ /**
+ * GenericDB settings, see $cfg['sql']
+ * @var array
+ */
+ protected $_settings;
+
+ /**
+ * Storage of the source table to use for the information
+ * @var string
+ */
+ protected $table;
+
+ /**
+ * Storage of the primary key
+ * @var string
+ * @todo remove access from public
+ */
+ public $primaryKey;
+
+ /**
+ * Checks for the virginity of created objects. If true, the object
+ * is virgin and no operations on it except load-Functions are allowed.
+ * @todo remove access from public
+ * @var bool
+ */
+ public $virgin;
+
+ /**
+ * Lifetime of results/created objects?
+ * FIXME Not used at the moment!
+ * @var int
+ */
+ protected $lifetime;
+
+ /**
+ * Storage of the last occured error
+ * @var string
+ */
+ protected $lasterror = '';
+
+ /**
+ * Cache the result items
+ * FIXME seems to not used, remove it!
+ * @var array
+ */
+ protected $cache;
+
+ /**
+ * Classname of current instance
+ * @var string
+ */
+ protected $_className;
+
+
+ /**
+ * Sets some common properties
+ *
+ * @param string $sTable Name of table
+ * @param string $sPrimaryKey Primary key of table
+ * @param string $sClassName Name of parent class
+ * @param int $iLifetime Lifetime of the object in seconds (NOT USED!)
+ * @throws Contenido_ItemException If table name or primary key is not set
+ */
+ protected function __construct($sTable, $sPrimaryKey, $sClassName, $iLifetime = 10)
+ {
+ global $cfg;
+
+ $this->db = new DB_ConLite();
+
+ if ($sTable == '') {
+ $sMsg = "$sClassName: No table specified. Inherited classes *need* to set a table";
+ throw new Contenido_ItemException($sMsg);
+ } elseif ($sPrimaryKey == '') {
+ $sMsg = "No primary key specified. Inherited classes *need* to set a primary key";
+ throw new Contenido_ItemException($sMsg);
+ }
+
+ $this->_settings = $cfg['sql'];
+
+ // instanciate caching
+ $aCacheOpt = (isset($this->_settings['cache'])) ? $this->_settings['cache'] : array();
+ self::$_oCache = Contenido_ItemCache::getInstance($sTable, $aCacheOpt);
+
+ $this->table = $sTable;
+ $this->primaryKey = $sPrimaryKey;
+ $this->virgin = true;
+ $this->lifetime = $iLifetime;
+ $this->_className = $sClassName;
+ }
+
+
+ /**
+ * Escape string for using in SQL-Statement.
+ *
+ * @param string $sString The string to escape
+ * @return string Escaped string
+ */
+ public function escape($sString)
+ {
+ return $this->db->escape($sString);
+ }
+
+ /**
+ * Returns the second database instance, usable to run additional statements
+ * without losing current query results.
+ *
+ * @return DB_ConLite
+ */
+ protected function _getSecondDBInstance()
+ {
+ if (!isset($this->secondDb) || !($this->secondDb instanceof DB_ConLite)) {
+ $this->secondDb = new DB_ConLite();
+ }
+ return $this->secondDb;
+ }
+
+ /**
+ * Returns properties instance, instantiates it if not done before.
+ *
+ * @return PropertyCollection
+ */
+ protected function _getPropertiesCollectionInstance()
+ {
+ // Runtime on-demand allocation of the properties object
+ if (!isset($this->properties) || !($this->properties instanceof PropertyCollection)) {
+ $this->properties = new PropertyCollection();
+ }
+ return $this->properties;
+ }
+}
+
+
+/**
+ * Class ItemCollection
+ * Abstract class for database based item collections.
+ *
+ * @author Timo A. Hummel
+ * @author Murat Purc
+ * @version 0.2
+ * @copyright four for business 2003
+ */
+abstract class ItemCollection extends Contenido_ItemBaseAbstract
+{
+ /**
+ * Storage of all result items
+ * @var string Contains all result items
+ */
+ protected $objects;
+
+ /**
+ * GenericDB driver object
+ * @var gdbDriver
+ */
+ protected $_driver;
+
+
+ /**
+ * List of instances of ItemCollection implementations
+ * @var array
+ */
+ protected $_collectionCache = array();
+
+ /**
+ * @var string Single item class
+ */
+ protected $_itemClass;
+
+ /**
+ * @var Item object of single item class
+ */
+ protected $_itemClassInstance = NULL;
+
+ /**
+ * @var object Iterator object for the next() method
+ */
+ protected $_iteratorItem;
+
+ /**
+ * @var array Reverse join partners for this data object
+ */
+ protected $_JoinPartners;
+
+ /**
+ * @var array Forward join partners for this data object
+ */
+ protected $_forwardJoinPartners;
+
+ /**
+ * @var array Where restrictions for the query
+ */
+ protected $_whereRestriction;
+
+ /**
+ * @var array Inner group conditions
+ */
+ protected $_innerGroupConditions = array();
+
+ /**
+ * @var array Group conditions
+ */
+ protected $_groupConditions;
+
+ /**
+ * @var array Result fields for the query
+ */
+ protected $_resultFields = array();
+
+ /**
+ * @var string Encoding
+ */
+ protected $_encoding;
+
+ /**
+ * Stores all operators which are supported by GenericDB
+ * Unsupported operators are passed trough as-is.
+ * @var array
+ */
+ protected $_aOperators;
+
+ /**
+ * Flag to select all fields in a query. Reduces the number of queries send
+ * to the database.
+ * @var bool
+ */
+ protected $_bAllMode = false;
+
+ protected $_order;
+
+ /**
+ * Constructor Function
+ *
+ * @param string $sTable The table to use as information source
+ * @param string $sPrimaryKey The primary key to use
+ * @param int $iLifetime
+ */
+ public function __construct($sTable, $sPrimaryKey, $iLifetime = 10)
+ {
+ parent::__construct($sTable, $sPrimaryKey, get_parent_class($this), $iLifetime);
+
+ $this->resetQuery();
+
+ // Try to load driver
+ $this->_initializeDriver();
+
+ // Try to find out the current encoding
+ if (isset($GLOBALS['lang']) && isset($GLOBALS['aLanguageEncodings'])) {
+ $this->setEncoding($GLOBALS['aLanguageEncodings'][$GLOBALS['lang']]);
+ }
+
+ $this->_aOperators = array(
+ '=', '!=', '<>', '<', '>', '<=', '>=', 'LIKE', 'DIACRITICS'
+ );
+ }
+
+ /**
+ * Defines the reverse links for this table.
+ *
+ * Important: The class specified by $sForeignCollectionClass needs to be a
+ * collection class and has to exist.
+ * Define all links in the constructor of your object.
+ *
+ * @param string $sForeignCollectionClass Specifies the foreign class to use
+ * @return void
+ */
+ protected function _setJoinPartner($sForeignCollectionClass)
+ {
+ if (class_exists($sForeignCollectionClass)) {
+ // Add class
+ if (!in_array($sForeignCollectionClass, $this->_JoinPartners)) {
+ $this->_JoinPartners[] = strtolower($sForeignCollectionClass);
+ }
+ } else {
+ $sMsg = "Could not instanciate class [$sForeignCollectionClass] for use "
+ . "with _setJoinPartner in class " . get_class($this);
+ cWarning(__FILE__, __LINE__, $sMsg);
+ }
+ }
+
+ /**
+ * Method to set the accompanying item object.
+ *
+ * @param string $sClassName Specifies the classname of item
+ * @return void
+ */
+ protected function _setItemClass($sClassName)
+ {
+ if (class_exists($sClassName)) {
+ $this->_itemClass = $sClassName;
+ $this->_itemClassInstance = new $sClassName;
+
+ // Initialize driver in case the developer does a setItemClass-Call
+ // before calling the parent constructor
+ $this->_initializeDriver();
+ $this->_driver->setItemClassInstance($this->_itemClassInstance);
+ } else {
+ $sMsg = "Could not instanciate class [$sClassName] for use with "
+ . "_setItemClass in class " . get_class($this);
+ cWarning(__FILE__, __LINE__, $sMsg);
+ }
+ }
+
+ /**
+ * Initializes the driver to use with GenericDB.
+ *
+ * @param $bForceInit boolean If true, forces the driver to initialize, even if it already exists.
+ */
+ protected function _initializeDriver($bForceInit = false)
+ {
+ if (!is_object($this->_driver) || $bForceInit == true) {
+ $this->_driver = new gdbMySQL();
+ }
+ }
+
+ /**
+ * Sets the encoding.
+ * @param string $sEncoding
+ */
+ public function setEncoding($sEncoding)
+ {
+ $this->_encoding = $sEncoding;
+ $this->_driver->setEncoding($sEncoding);
+ }
+
+ /**
+ * Sets the query to use foreign tables in the resultset
+ * @param string $sForeignClass The class of foreign table to use
+ */
+ public function link($sForeignClass)
+ {
+ if (class_exists($sForeignClass)) {
+ $this->_links[$sForeignClass] = new $sForeignClass;
+ } else {
+ $sMsg = "Could not find class [$sForeignClass] for use with link in class "
+ . get_class($this);
+ cWarning(__FILE__, __LINE__, $sMsg);
+ }
+ }
+
+ /**
+ * Sets the limit for results
+ * @param int $iRowStart
+ * @param int $iRowCount
+ */
+ public function setLimit($iRowStart, $iRowCount)
+ {
+ $this->_limitStart = $iRowStart;
+ $this->_limitCount = $iRowCount;
+ }
+
+ /**
+ * Restricts a query with a where clause
+ * @param string $sField
+ * @param mixed $mRestriction
+ * @param string $sOperator
+ */
+ public function setWhere($sField, $mRestriction, $sOperator = '=')
+ {
+ $sField = strtolower($sField);
+ $this->_where['global'][$sField]['operator'] = $sOperator;
+ $this->_where['global'][$sField]['restriction'] = $mRestriction;
+ }
+
+ /**
+ * Removes a previous set where clause (@see ItemCollection::setWhere).
+ * @param string $sField
+ * @param mixed $mRestriction
+ * @param string $sOperator
+ */
+ public function deleteWhere($sField, $mRestriction, $sOperator = '=')
+ {
+ $sField = strtolower($sField);
+ if (isset($this->_where['global'][$sField]) && is_array($this->_where['global'][$sField])) {
+ if ($this->_where['global'][$sField]['operator'] == $sOperator &&
+ $this->_where['global'][$sField]['restriction'] == $mRestriction) {
+ unset($this->_where['global'][$sField]);
+ }
+ }
+ }
+
+ /**
+ * Restricts a query with a where clause, groupable
+ * @param string $sGroup
+ * @param string $sField
+ * @param mixed $mRestriction
+ * @param string $sOperator
+ */
+ public function setWhereGroup($sGroup, $sField, $mRestriction, $sOperator = '=')
+ {
+ $sField = strtolower($sField);
+ $this->_where['groups'][$sGroup][$sField]['operator'] = $sOperator;
+ $this->_where['groups'][$sGroup][$sField]['restriction'] = $mRestriction;
+ }
+
+ /**
+ * Removes a previous set groupable where clause (@see ItemCollection::setWhereGroup).
+ * @param string $sGroup
+ * @param string $sField
+ * @param mixed $mRestriction
+ * @param string $sOperator
+ */
+ public function deleteWhereGroup($sGroup, $sField, $mRestriction, $sOperator = '=')
+ {
+ $sField = strtolower($sField);
+ if (is_array($this->_where['groups'][$sGroup]) &&
+ isset($this->_where['groups'][$sGroup][$sField]) &&
+ is_array($this->_where['groups'][$sGroup][$sField])) {
+ if ($this->_where['groups'][$sGroup][$sField]['operator'] == $sOperator &&
+ $this->_where['groups'][$sGroup][$sField]['restriction'] == $mRestriction) {
+ unset($this->_where['groups'][$sGroup][$sField]);
+ }
+ }
+ }
+
+ /**
+ * Defines how relations in one group are linked each together
+ * @param string $sGroup
+ * @param string $sCondition
+ */
+ public function setInnerGroupCondition($sGroup, $sCondition = 'AND')
+ {
+ $this->_innerGroupConditions[$sGroup] = $sCondition;
+ }
+
+ /**
+ * Defines how groups are linked to each other
+ * @param string $sGroup1
+ * @param string $sGroup2
+ * @param string $sCondition
+ */
+ public function setGroupCondition($sGroup1, $sGroup2, $sCondition = 'AND')
+ {
+ $this->_groupConditions[$sGroup1][$sGroup2] = $sCondition;
+ }
+
+ /**
+ * Builds a where statement out of the setGroupWhere calls
+ *
+ * @return array With all where statements
+ */
+ protected function _buildGroupWhereStatements()
+ {
+ $aWheres = array();
+ $aGroupWhere = array();
+
+ $mLastGroup = false;
+ $sGroupWhereStatement = '';
+
+ // Find out if there are any defined groups
+ if (count($this->_where['groups']) > 0) {
+ // Step trough all groups
+ foreach ($this->_where['groups'] as $groupname => $group) {
+ $aWheres = array();
+
+ // Fetch restriction, fields and operators and build single group
+ // where statements
+ foreach ($group as $field => $item) {
+ $aWheres[] = $this->_driver->buildOperator($field, $item['operator'], $item['restriction']);
+ }
+
+ // Add completed substatements
+ $sOperator = 'AND';
+ if (isset($this->_innerGroupConditions[$groupname])) {
+ $sOperator = $this->_innerGroupConditions[$groupname];
+ }
+
+ $aGroupWhere[$groupname] = implode(' '.$sOperator.' ', $aWheres);
+ }
+ }
+
+ // Combine groups
+ foreach ($aGroupWhere as $groupname => $group) {
+ if ($mLastGroup != false) {
+ $sOperator = 'AND';
+ // Check if there's a group condition
+ if (isset($this->_groupConditions[$groupname])) {
+ if (isset($this->_groupConditions[$groupname][$mLastGroup])) {
+ $sOperator = $this->_groupConditions[$groupname][$mLastGroup];
+ }
+ }
+
+ // Reverse check
+ if (isset($this->_groupConditions[$mLastGroup])) {
+ if (isset($this->_groupConditions[$mLastGroup][$groupname])) {
+ $sOperator = $this->_groupConditions[$mLastGroup][$groupname];
+ }
+ }
+
+ $sGroupWhereStatement .= ' '.$sOperator.' ('.$group.')';
+ } else {
+ $sGroupWhereStatement .= '('.$group.')';
+ }
+
+ $mLastGroup = $groupname;
+ }
+
+ return $sGroupWhereStatement;
+ }
+
+ /**
+ * Builds a where statement out of the setWhere calls
+ *
+ * @return array With all where statements
+ */
+ protected function _buildWhereStatements()
+ {
+ $aWheres = array();
+
+ // Build global where condition
+ foreach ($this->_where['global'] as $field => $item) {
+ $aWheres[] = $this->_driver->buildOperator($field, $item['operator'], $item['restriction']);
+ }
+
+ return (implode(' AND ', $aWheres));
+ }
+
+ /**
+ * Fetches all tables which will be joined later on.
+ *
+ * The returned array has the following format:
+ *
+ * array(
+ * array(fields),
+ * array(tables),
+ * array(joins),
+ * array(wheres)
+ * );
+ *
+ *
+ * Notes:
+ * The table is the table name which needs to be added to the FROM clause
+ * The join statement which is inserted after the master table
+ * The where statement is combined with all other where statements
+ * The fields to select from
+ *
+ * @todo Reduce complexity of this function, to much code...
+ *
+ * @param ??? $ignoreRoot
+ * @return array Array structure, see above
+ */
+ protected function _fetchJoinTables($ignoreRoot)
+ {
+ $aParameters = array();
+ $aFields = array();
+ $aTables = array();
+ $aJoins = array();
+ $aWheres = array();
+
+ // Fetch linked tables
+ foreach ($this->_links as $link => $object) {
+ $matches = $this->_findReverseJoinPartner(strtolower(get_class($this)), $link);
+
+ if ($matches !== false) {
+ if (isset($matches['desttable'])) {
+ // Driver function: Build query parts
+ $aParameters[] = $this->_driver->buildJoinQuery(
+ $matches['desttable'],
+ strtolower($matches['destclass']),
+ $matches['key'],
+ strtolower($matches['sourceclass']),
+ $matches['key']
+ );
+ } else {
+ foreach ($matches as $match) {
+ $aParameters[] = $this->_driver->buildJoinQuery(
+ $match['desttable'],
+ strtolower($match['destclass']),
+ $match['key'],
+ strtolower($match['sourceclass']),
+ $match['key']
+ );
+ }
+ }
+ } else {
+ // Try forward search
+ $mobject = new $link;
+
+ $matches = $mobject->_findReverseJoinPartner($link, strtolower(get_class($this)));
+
+ if ($matches !== false) {
+ if (isset($matches['desttable'])) {
+ $i = $this->_driver->buildJoinQuery(
+ $mobject->table,
+ strtolower($link),
+ $mobject->primaryKey,
+ strtolower($matches['destclass']),
+ $matches['key']
+ );
+
+ if ($i['field'] == ($link.'.'.$mobject->primaryKey) && $link == $ignoreRoot) {
+ unset($i['join']);
+ }
+ $aParameters[] = $i;
+ } else {
+ foreach ($matches as $match) {
+ $xobject = new $match['sourceclass'];
+
+ $i = $this->_driver->buildJoinQuery(
+ $xobject->table,
+ strtolower($match['sourceclass']),
+ $xobject->primaryKey,
+ strtolower($match['destclass']),
+ $match['key']
+ );
+
+ if ($i['field'] == ($match['sourceclass'] . '.' . $xobject->primaryKey) &&
+ $match['sourceclass'] == $ignoreRoot) {
+ unset($i['join']);
+ }
+ array_unshift($aParameters, $i);
+ }
+ }
+ } else {
+ $bDualSearch = true;
+ // Check first if we are a instance of another class
+ foreach ($mobject->_JoinPartners as $sJoinPartner) {
+ if (class_exists($sJoinPartner)) {
+ if (is_subclass_of($this, $sJoinPartner)) {
+ $matches = $mobject->_findReverseJoinPartner($link, strtolower($sJoinPartner));
+
+ if ($matches !== false) {
+ if ($matches['destclass'] == strtolower($sJoinPartner)) {
+ $matches['destclass'] = get_class($this);
+
+ if (isset($matches['desttable'])) {
+ $i = $this->_driver->buildJoinQuery(
+ $mobject->table,
+ strtolower($link),
+ $mobject->primaryKey,
+ strtolower($matches['destclass']),
+ $matches['key']
+ );
+
+ if ($i['field'] == ($link . '.' . $mobject->primaryKey) &&
+ $link == $ignoreRoot) {
+ unset($i['join']);
+ }
+ $aParameters[] = $i;
+ } else {
+ foreach ($matches as $match) {
+ $xobject = new $match['sourceclass'];
+
+ $i = $this->_driver->buildJoinQuery(
+ $xobject->table,
+ strtolower($match['sourceclass']),
+ $xobject->primaryKey,
+ strtolower($match['destclass']),
+ $match['key']
+ );
+
+ if ($i['field'] == ($match['sourceclass'] . '.' . $xobject->primaryKey) &&
+ $match['sourceclass'] == $ignoreRoot) {
+ unset($i['join']);
+ }
+ array_unshift($aParameters, $i);
+ }
+ }
+ $bDualSearch = false;
+ }
+ }
+ }
+ }
+ }
+
+ if ($bDualSearch) {
+ // Try dual-side search
+ $forward = $this->_resolveLinks();
+ $reverse = $mobject->_resolveLinks();
+
+ $result = array_intersect($forward, $reverse);
+
+ if (count($result) > 0) {
+ // Found an intersection, build references to it
+ foreach ($result as $value) {
+ $oIntersect = new $value;
+ $oIntersect->link(strtolower(get_class($this)));
+ $oIntersect->link(strtolower(get_class($mobject)));
+
+ $aIntersectParameters = $oIntersect->_fetchJoinTables($ignoreRoot);
+
+ $aFields = array_merge($aIntersectParameters['fields'], $aFields);
+ $aTables = array_merge($aIntersectParameters['tables'], $aTables);
+ $aJoins = array_merge($aIntersectParameters['joins'], $aJoins);
+ $aWheres = array_merge($aIntersectParameters['wheres'], $aWheres);
+ }
+ } else {
+ $sMsg = "Could not find join partner for class [$link] in class "
+ . get_class($this)." in neither forward nor reverse direction.";
+ cWarning(__FILE__, __LINE__, $sMsg);
+ }
+ }
+ }
+ }
+ }
+
+ // Add this class
+ $aFields[] = strtolower(strtolower(get_class($this))).'.'.$this->primaryKey;
+
+ // Make the parameters unique
+ foreach ($aParameters as $parameter) {
+ array_unshift($aFields, $parameter['field']);
+ array_unshift($aTables, $parameter['table']);
+ array_unshift($aJoins, $parameter['join']);
+ array_unshift($aWheres, $parameter['where']);
+ }
+
+ $aFields = array_filter(array_unique($aFields));
+ $aTables = array_filter(array_unique($aTables));
+ $aJoins = array_filter(array_unique($aJoins));
+ $aWheres = array_filter(array_unique($aWheres));
+
+ return array(
+ 'fields' => $aFields, 'tables' => $aTables, 'joins' => $aJoins, 'wheres' => $aWheres
+ );
+ }
+
+ /**
+ * Resolves links (class names of joined partners)
+ *
+ * @return array
+ */
+ protected function _resolveLinks()
+ {
+ $aResolvedLinks = array();
+ $aResolvedLinks[] = strtolower(get_class($this));
+
+ foreach ($this->_JoinPartners as $link) {
+ $class = new $link;
+ $aResolvedLinks = array_merge($class->_resolveLinks(), $aResolvedLinks);
+ }
+ return $aResolvedLinks;
+ }
+
+ /**
+ * Resets the properties
+ */
+ public function resetQuery()
+ {
+ $this->setLimit(0, 0);
+ $this->_JoinPartners = array();
+ $this->_forwardJoinPartners = array();
+ $this->_links = array();
+ $this->_where['global'] = array();
+ $this->_where['groups'] = array();
+ $this->_groupConditions = array();
+ $this->_resultFields = array();
+ }
+
+ /**
+ * Builds and runs the query
+ *
+ * @return bool
+ */
+ public function query()
+ {
+ if (!isset($this->_itemClassInstance)) {
+ $sMsg = "GenericDB can't use query() if no item class is set via setItemClass";
+ cWarning(__FILE__, __LINE__, $sMsg);
+ return false;
+ }
+
+ $aGroupWhereStatements = $this->_buildGroupWhereStatements();
+ $sWhereStatements = $this->_buildWhereStatements();
+ $aParameters = $this->_fetchJoinTables(strtolower(get_class($this)));
+
+ $aStatement = array(
+ 'SELECT',
+ implode(', ', (array_merge($aParameters['fields'], $this->_resultFields))),
+ 'FROM',
+ '`' . $this->table . '` AS ' . strtolower(get_class($this))
+ );
+
+ if (count($aParameters['tables']) > 0) {
+ $aStatement[] = implode(', ', $aParameters['tables']);
+ }
+
+ if (count($aParameters['joins']) > 0) {
+ $aStatement[] = implode(' ', $aParameters['joins']);
+ }
+
+ $aWheres = array();
+
+ if (count($aParameters['wheres']) > 0) {
+ $aWheres[] = implode(', ', $aParameters['wheres']);
+ }
+
+ if ($aGroupWhereStatements != '') {
+ $aWheres[] = $aGroupWhereStatements;
+ }
+
+ if ($sWhereStatements != '') {
+ $aWheres[] = $sWhereStatements;
+ }
+
+ if (count($aWheres) > 0) {
+ $aStatement[] = 'WHERE '.implode(' AND ', $aWheres);
+ }
+
+ if ($this->_order != '') {
+ $aStatement[] = 'ORDER BY '.$this->_order;
+ }
+
+ if ($this->_limitStart > 0 || $this->_limitCount > 0) {
+ $iRowStart = intval($this->_limitStart);
+ $iRowCount = intval($this->_limitCount);
+ $aStatement[] = "LIMIT $iRowStart, $iRowCount";
+ }
+
+ $sql = implode(' ', $aStatement);
+
+ $result = $this->db->query($sql);
+ $this->_lastSQL = $sql;
+ // @todo disable all mode in this method for the moment. It has to be verified,
+ // if enabling will result in negative side effects.
+ $this->_bAllMode = false;
+ return ($result) ? true : false;
+ }
+
+ /**
+ * Sets the result order part of the query
+ * (e. g. "fieldname", "fieldname DESC", "fieldname DESC, field2name ASC")
+ * @param string $order
+ */
+ public function setOrder($order)
+ {
+ $this->_order = strtolower($order);
+ }
+
+ /**
+ * Adds a result field
+ * @param string $sField
+ */
+ public function addResultField($sField)
+ {
+ $sField = strtolower($sField);
+ if (!in_array($sField, $this->_resultFields)) {
+ $this->_resultFields[] = $sField;
+ }
+ }
+
+ /**
+ * Removes existing result field
+ * @param string $sField
+ */
+ public function removeResultField($sField)
+ {
+ $sField = strtolower($sField);
+ $key = array_search($sField, $this->_resultFields);
+ if ($key !== false) {
+ unset($this->_resultFields[$key]);
+ }
+ }
+
+ /**
+ * Returns reverse join partner.
+ *
+ * @param string $sParentClass
+ * @param string $sClassName
+ * @param array|bool
+ */
+ protected function _findReverseJoinPartner($sParentClass, $sClassName)
+ {
+ // Make the parameters lowercase, as get_class is buggy
+ $sClassName = strtolower($sClassName);
+ $sParentClass = strtolower($sParentClass);
+
+ // Check if we found a direct link
+ if (in_array($sClassName, $this->_JoinPartners)) {
+ $obj = new $sClassName;
+ return array(
+ 'desttable' => $obj->table, 'destclass' => $sClassName,
+ 'sourceclass' => $sParentClass, 'key' => $obj->primaryKey
+ );
+ } else {
+ // Recurse all items
+ foreach ($this->_JoinPartners as $join => $tmpClassname) {
+ $obj = new $tmpClassname;
+ $status = $obj->_findReverseJoinPartner($tmpClassname, $sClassName);
+
+ if (is_array($status)) {
+ $returns = array();
+
+ if (!isset($status['desttable'])) {
+ foreach ($status as $subitem) {
+ $returns[] = $subitem;
+ }
+ } else {
+ $returns[] = $status;
+ }
+
+ $obj = new $tmpClassname;
+
+ $returns[] = array(
+ 'desttable' => $obj->table, 'destclass' => $tmpClassname,
+ 'sourceclass' => $sParentClass, 'key' => $obj->primaryKey
+ );
+ return ($returns);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Selects all entries from the database. Objects are loaded using their primary key.
+ *
+ * @param string $sWhere Specifies the where clause.
+ * @param string $sGroupBy Specifies the group by clause.
+ * @param string $sOrderBy Specifies the order by clause.
+ * @param string $sLimit Specifies the limit by clause.
+ * @return bool True on success, otherwhise false
+ */
+ public function select($sWhere = '', $sGroupBy = '', $sOrderBy = '', $sLimit = '')
+ {
+ unset($this->objects);
+
+ if ($sWhere == '') {
+ $sWhere = '';
+ } else {
+ $sWhere = ' WHERE '.$sWhere;
+ }
+
+ if ($sGroupBy != '') {
+ $sGroupBy = ' GROUP BY '.$sGroupBy;
+ }
+
+ if ($sOrderBy != '') {
+ $sOrderBy = ' ORDER BY '.$sOrderBy;
+ }
+
+ if ($sLimit != '') {
+ $sLimit = ' LIMIT '.$sLimit;
+ }
+
+ $sFields = ($this->_settings['select_all_mode']) ? '*' : $this->primaryKey;
+ $sql = 'SELECT ' . $sFields . ' FROM `' . $this->table . '`' . $sWhere
+ . $sGroupBy . $sOrderBy . $sLimit;
+ $this->db->query($sql);
+ $this->_lastSQL = $sql;
+ $this->_bAllMode = $this->_settings['select_all_mode'];
+
+ if ($this->db->num_rows() == 0) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Selects all entries from the database. Objects are loaded using their primary key.
+ *
+ * @param string $sDistinct Specifies if distinct will be added to the SQL
+ * statement ($sDistinct !== '' -> DISTINCT)
+ * @param string $sFrom Specifies the additional from clause (e.g.
+ * 'con_news_groups AS groups, con_news_groupmembers AS groupmembers').
+ * @param string $sWhere Specifies the where clause.
+ * @param string $sGroupBy Specifies the group by clause.
+ * @param string $sOrderBy Specifies the order by clause.
+ * @param string $sLimit Specifies the limit by clause.
+ * @return bool True on success, otherwhise false
+ * @author HerrB
+ */
+ public function flexSelect($sDistinct = '', $sFrom = '', $sWhere = '', $sGroupBy = '', $sOrderBy = '', $sLimit = '')
+ {
+ unset($this->objects);
+
+ if ($sDistinct != '') {
+ $sDistinct = 'DISTINCT ';
+ }
+
+ if ($sFrom != '') {
+ $sFrom = ', '.$sFrom;
+ }
+
+ if ($sWhere != '') {
+ $sWhere = ' WHERE '.$sWhere;
+ }
+
+ if ($sGroupBy != '') {
+ $sGroupBy = ' GROUP BY '.$sGroupBy;
+ }
+
+ if ($sOrderBy != '') {
+ $sOrderBy = ' ORDER BY '.$sOrderBy;
+ }
+
+ if ($sLimit != '') {
+ $sLimit = ' LIMIT '.$sLimit;
+ }
+
+ $sql = 'SELECT ' . $sDistinct . strtolower(get_class($this)) . '.' . $this->primaryKey
+ . ' AS ' . $this->primaryKey . ' FROM `' . $this->table . '` AS ' . strtolower(get_class($this))
+ . $sFrom . $sWhere . $sGroupBy . $sOrderBy . $sLimit;
+
+ $this->db->query($sql);
+ $this->_lastSQL = $sql;
+ // @todo disable all mode in this method
+ $this->_bAllMode = false;
+
+ if ($this->db->num_rows() == 0) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Checks if a specific entry exists.
+ *
+ * @param mixed $mId The id to check for (could be numeric or string)
+ * @return bool True if object exists, false if not
+ */
+ public function exists($mId)
+ {
+ $oDb = $this->_getSecondDBInstance();
+ $sql = "SELECT `%s` FROM %s WHERE %s='%s'";
+ $oDb->query($sql, $this->primaryKey, $this->table, $this->primaryKey, $mId);
+ return ($oDb->next_record()) ? true : false;
+ }
+
+ /**
+ * Advances to the next item in the database.
+ *
+ * @return Item|bool The next object, or false if no more objects
+ */
+ public function next()
+ {
+ if ($this->db->next_record()) {
+ if ($this->_bAllMode) {
+ $aRs = $this->db->toArray(DB_ConLite::FETCH_BOTH);
+ return $this->loadItem($aRs);
+ } else {
+ return $this->loadItem($this->db->f($this->primaryKey));
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Fetches the resultset related to current loaded primary key as a object
+ *
+ * @param Item
+ */
+ public function fetchObject($sClassName)
+ {
+ $sKey = strtolower($sClassName);
+
+ if (!is_object($this->_collectionCache[$sKey])) {
+ $this->_collectionCache[$sKey] = new $sClassName;
+ }
+ $obj = $this->_collectionCache[$sKey];
+ return $obj->loadItem($this->db->f($obj->primaryKey));
+ }
+
+ /**
+ * Both arrays are optional. If both empty you will get an result using field stored in primaryKey
+ *
+ * $aFields = array with the fields to fetch. Notes:
+ * If the array contains keys, the key will be used as alias for the field. Example:
+ * array('id' => 'idcat') will put 'idcat' into field 'id'
+ *
+ * $aObjects = array with the objects to fetch. Notes:
+ * If the array contains keys, the key will be used as alias for the object. If you specify
+ * more than one object with the same key, the array will be multi-dimensional.
+ *
+ * @param array $aFields
+ * @param array $aObjects
+ * @return array
+ */
+ public function fetchTable(array $aFields = array(), array $aObjects = array()) {
+ $row = 1;
+ $aTable = array();
+
+ if(empty($aFields) && empty($aObjects)) {
+ $aFields = array($this->primaryKey);
+ }
+
+ $this->db->seek(0);
+
+ while ($this->db->next_record()) {
+ foreach ($aFields as $alias => $field) {
+ //if ($alias != '') {
+ if (is_string($alias)) {
+ $aTable[$row][$alias] = $this->db->f($field);
+ } else {
+ $aTable[$row][$field] = $this->db->f($field);
+ }
+ }
+
+ // Fetch objects
+ if(!empty($aObjects)) {
+ foreach ($aObjects as $alias => $object) {
+ if ($alias != '') {
+ if (isset($aTable[$row][$alias])) {
+ // Is set, check for array. If no array, create one
+ if (is_array($aTable[$row][$alias])) {
+ $aTable[$row][$alias][] = $this->fetchObject($object);
+ } else {
+ // $tmpObj = $aTable[$row][$alias];
+ $aTable[$row][$alias] = array();
+ $aTable[$row][$alias][] = $this->fetchObject($object);
+ }
+ } else {
+ $aTable[$row][$alias] = $this->fetchObject($object);
+ }
+ } else {
+ $aTable[$row][$object] = $this->fetchObject($object);
+ }
+ }
+ }
+ $row ++;
+ }
+
+ $this->db->seek(0);
+
+ return $aTable;
+ }
+
+ /**
+ * Returns an array of arrays
+ * @param array $aObjects With the correct order of the objects
+ * @return array Result
+ */
+ public function queryAndFetchStructured(array $aObjects)
+ {
+ $aOrder = array();
+ $aFetchObjects = array();
+ $aResult = array();
+
+ foreach ($aObjects as $object) {
+ $x = new $object;
+ $object = strtolower($object);
+ $aOrder[] = $object.'.'.$x->primaryKey.' ASC';
+ $aFetchObjects[] = $x;
+ }
+
+ $this->setOrder(implode(', ', $aOrder));
+ $this->query();
+
+ $this->db->seek(0);
+
+ while ($this->db->next_record()) {
+ $aResult = $this->_recursiveStructuredFetch($aFetchObjects, $aResult);
+ }
+
+ return $aResult;
+ }
+
+ protected function _recursiveStructuredFetch(array $aObjects, array $aResult)
+ {
+ $i = array_shift($aObjects);
+
+ $value = $this->db->f($i->primaryKey);
+
+ if (!is_null($value)) {
+ $aResult[$value]['class'] = strtolower(get_class($i));
+ $aResult[$value]['object'] = $i->loadItem($value);
+
+ if (count($aObjects) > 0) {
+ $aResult[$value]['items'] = $this->_recursiveStructuredFetch($aObjects, $aResult[$value]['items']);
+ }
+ }
+
+ return $aResult;
+ }
+
+ /**
+ * Returns the amount of returned items
+ * @return int Number of rows
+ */
+ public function count()
+ {
+ return ($this->db->num_rows());
+ }
+
+ /**
+ * Loads a single entry by it's id.
+ *
+ * @param string|int $id The primary key of the item to load.
+ * @return Item The loaded item
+ */
+ public function fetchById($id)
+ {
+ if (is_numeric($id)) {
+ $id = (int) $id;
+ } elseif (is_string($id)) {
+ $id = $this->escape($id);
+ }
+ return $this->loadItem($id);
+ }
+
+ /**
+ * Loads a single object from the database.
+ *
+ * @param mixed $mItem The primary key of the item to load or a recordset
+ * with itemdata (array) to inject to the item object.
+ * @return Item The newly created object
+ * @throws Contenido_ItemException If item class is not set
+ */
+ public function loadItem($mItem)
+ {
+ if (empty($this->_itemClass)) {
+ $sMsg = "ItemClass has to be set in the constructor of class "
+ . get_class($this) . ")";
+ throw new Contenido_ItemException($sMsg);
+ }
+
+ if (!is_object($this->_iteratorItem)) {
+ $this->_iteratorItem = new $this->_itemClass();
+ }
+
+ if (is_array($mItem)) {
+ $this->_iteratorItem->loadByRecordSet($mItem);
+ } else {
+ $this->_iteratorItem->loadByPrimaryKey($mItem);
+ }
+
+ return $this->_iteratorItem;
+ }
+
+ /**
+ * Creates a new item in the table and loads it afterwards.
+ *
+ * @param string $primaryKeyValue Optional parameter for direct input of primary key value
+ * @return Item The newly created object
+ */
+ public function create()
+ { /* @var $oDb DB_ConLite */
+ $oDb = $this->_getSecondDBInstance();
+ $iNextId = $oDb->nextid($this->table);
+ $sql = 'INSERT INTO `%s` (%s) VALUES (%d)';
+ $oDb->query($sql, $this->table, $this->primaryKey, $iNextId);
+ return $this->loadItem($iNextId);
+ }
+
+ /**
+ * Deletes an item in the table.
+ * Deletes also cached e entry and any existing properties.
+ *
+ * @param mixed $mId Id of entry to delete
+ * @return bool
+ */
+ public function delete($mId)
+ {
+ $result = $this->_delete($mId);
+
+ return $result;
+ }
+
+ /**
+ * Deletes all found items in the table matching the rules in the passed where clause.
+ * Deletes also cached e entries and any existing properties.
+ *
+ * @param string $sWhere The where clause of the SQL statement
+ * @return int Number of deleted entries
+ */
+ public function deleteByWhereClause($sWhere)
+ {
+ $oDb = $this->_getSecondDBInstance();
+
+ $aIds = array();
+ $numDeleted = 0;
+
+ // get all ids
+ $sql = 'SELECT ' . $this->primaryKey . ' AS pk FROM `' . $this->table . '` WHERE ' . $sWhere;
+ $oDb->query($sql);
+ while ($oDb->next_record()) {
+ $aIds[] = $oDb->f('pk');
+ }
+
+ // delete entries by their ids
+ foreach ($aIds as $id) {
+ if ($this->_delete($id)) {
+ $numDeleted++;
+ }
+ }
+
+ return $numDeleted;
+ }
+
+ /**
+ * Deletes all found items in the table matching the passed field and it's value.
+ * Deletes also cached e entries and any existing properties.
+ *
+ * @param string $sField The field name
+ * @param mixed $mValue The value of the field
+ * @return int Number of deleted entries
+ */
+ public function deleteBy($sField, $mValue)
+ {
+ $oDb = $this->_getSecondDBInstance();
+
+ $aIds = array();
+ $numDeleted = 0;
+
+ // get all ids
+ if (is_string($mValue)) {
+ $sql = "SELECT %s AS pk FROM `%s` WHERE `%s` = '%s'";
+ } else {
+ $sql = "SELECT %s AS pk FROM `%s` WHERE `%s` = %d";
+ }
+
+ $oDb->query($sql, $this->primaryKey, $this->table, $sField, $mValue);
+ while ($oDb->next_record()) {
+ $aIds[] = $oDb->f('pk');
+ }
+
+ // delete entries by their ids
+ foreach ($aIds as $id) {
+ if ($this->_delete($id)) {
+ $numDeleted++;
+ }
+ }
+
+ return $numDeleted;
+ }
+
+ /**
+ * Deletes an item in the table, deletes also existing cache entries and
+ * properties of the item.
+ *
+ * @param mixed $mId Id of entry to delete
+ * @return bool
+ */
+ protected function _delete($mId) {
+
+ // delete cache entry
+ self::$_oCache->removeItem($mId);
+
+ // delete the property values
+ $oProperties = $this->_getPropertiesCollectionInstance();
+ $oProperties->deleteProperties($this->primaryKey, $mId);
+
+ $oDb = $this->_getSecondDBInstance();
+
+ // delete db entry
+ $sql = "DELETE FROM `%s` WHERE %s = '%s'";
+ $oDb->query($sql, $this->table, $this->primaryKey, $mId);
+
+ return (($oDb->affected_rows() > 0)?true:false);
+ }
+
+ /**
+ * Fetches an array of fields from the database.
+ *
+ * Example:
+ * $i = $object->fetchArray('idartlang', array('idlang', 'name'));
+ *
+ * could result in:
+ * $i[5] = array('idlang' => 5, 'name' => 'My Article');
+ *
+ * Important: If you don't pass an array for fields, the function
+ * doesn't create an array.
+ * @param string $sKey Name of the field to use for the key
+ * @param mixed $mFields String or array
+ * @return array Resulting array
+ */
+ public function fetchArray($sKey, $mFields)
+ {
+ $aResult = array();
+
+ while ($item = $this->next()) {
+ if (is_array($mFields)) {
+ foreach ($mFields as $value) {
+ $aResult[$item->get($sKey)][$value] = $item->get($value);
+ }
+ } else {
+ $aResult[$item->get($sKey)] = $item->get($mFields);
+ }
+ }
+
+ return $aResult;
+ }
+
+}
+
+/**
+ * Class Item
+ * Abstract class for database based items.
+ *
+ * @author Timo A. Hummel
+ * @author Murat Purc
+ * @version 0.3
+ * @copyright four for business 2003
+ */
+abstract class Item extends Contenido_ItemBaseAbstract
+{
+ /**
+ * Storage of the source table to use for the user informations
+ * @var array
+ */
+ public $values;
+
+ /**
+ * Storage of the fields which were modified, where the keys are the
+ * fieldnames and the values just simple booleans.
+ * @var array
+ */
+ protected $modifiedValues;
+
+ /**
+ * Stores the old primary key, just in case somebody wants to change it
+ * @var string
+ */
+ protected $oldPrimaryKey;
+
+ /**
+ * List of funcion names of the filters used when data is stored to the db.
+ * @var array
+ */
+ protected $_arrInFilters = array('urlencode', 'clHtmlSpecialChars', 'addslashes');
+
+ /**
+ * List of funcion names of the filtersused when data is retrieved from the db
+ * @var array
+ */
+ protected $_arrOutFilters = array('stripslashes', 'htmldecode', 'urldecode');
+
+ /**
+ * Class name of meta object
+ * @var string
+ */
+ protected $_metaObject;
+
+ /**
+ * Constructor function
+ *
+ * @param string $sTable The table to use as information source
+ * @param string $sPrimaryKey The primary key to use
+ * @param int $iLifetime
+ */
+ public function __construct($sTable = '', $sPrimaryKey = '', $iLifetime = 10)
+ {
+ parent::__construct($sTable, $sPrimaryKey, get_parent_class($this), $iLifetime);
+ }
+
+ function __destruct() {
+ //print_r(self::$_oCache);
+ }
+
+ /**
+ * Loads an item by colum/field from the database.
+ *
+ * @param string $sField Specifies the field
+ * @param mixed $mValue Specifies the value
+ * @param bool $bSafe Use inFilter or not
+ * @return bool True if the load was successful
+ */
+ public function loadBy($sField, $mValue, $bSafe = true)
+ {
+ if ($bSafe) {
+ $mValue = $this->_inFilter($mValue);
+ }
+
+ // check, if cache contains a matching entry
+ $aRecordSet = null;
+ if ($sField === $this->primaryKey) {
+ $aRecordSet = self::$_oCache->getItem($this->table."_".$mValue);
+ } else {
+ $aRecordSet = self::$_oCache->getItemByProperty($this->table."_".$sField, $mValue);
+ }
+
+ if ($aRecordSet) {
+ // entry in cache found, load entry from cache
+ $this->loadByRecordSet($aRecordSet);
+ return true;
+ }
+
+ // SQL-Statement to select by field
+ $sql = sprintf("SELECT * FROM `%s` WHERE %s = '%s'",$this->table,$sField,$mValue);
+ //$sql = $this->db->prepare($sql, $this->table, $sField, $mValue);
+
+ // Query the database
+ $this->db->query($sql);
+
+ $this->_lastSQL = $sql;
+
+ if ($this->db->num_rows() > 1) {
+ $sMsg = "Tried to load a single line with field $sField and value $mValue from "
+ . $this->table . " but found more than one row";
+ cWarning(__FILE__, __LINE__, $sMsg);
+ }
+
+ // Advance to the next record, return false if nothing found
+ if (!$this->db->next_record()) {
+ return false;
+ }
+
+ $this->loadByRecordSet($this->db->toArray());
+ return true;
+ }
+
+ /**
+ * Loads an item by passed where clause from the database.
+ * This function is expensive, since it executes allways a query to the database
+ * to retrieve the primary key, even if the record set is aleady cached.
+ * NOTE: Passed value has to be escaped before. This will not be done by this function.
+ *
+ * @param string $sWhere The where clause like 'idart = 123 AND idlang = 1'
+ * @return bool True if the load was successful
+ */
+ protected function _loadByWhereClause($sWhere)
+ {
+ // SQL-Statement to select by whee clause
+ $sql = sprintf("SELECT %s AS pk FROM `%s` WHERE ",$this->primaryKey,$this->table) . (string) $sWhere;
+ //$sql = $this->db->prepare($sql, $this->primaryKey, $this->table);
+
+ // Query the database
+ $this->db->query($sql);
+
+ $this->_lastSQL = $sql;
+
+ if ($this->db->num_rows() > 1) {
+ $sMsg = "Tried to load a single line with where clause '" . $sWhere . "' from "
+ . $this->table . " but found more than one row";
+ cWarning(__FILE__, __LINE__, $sMsg);
+ }
+
+ // Advance to the next record, return false if nothing found
+ if (!$this->db->next_record()) {
+ return false;
+ }
+
+ $id = $this->db->f('pk');
+ return $this->loadByPrimaryKey($id);
+ }
+
+ /**
+ * Loads an item by ID from the database.
+ *
+ * @param string $mValue Specifies the primary key value
+ * @return bool True if the load was successful
+ */
+ public function loadByPrimaryKey($mValue)
+ {
+ $bSuccess = $this->loadBy($this->primaryKey, $mValue);
+
+ if (($bSuccess == true) && method_exists($this, '_onLoad')) {
+ $this->_onLoad();
+ }
+ return $bSuccess;
+ }
+
+ /**
+ * Loads an item by it's recordset.
+ *
+ * @param array $aRecordSet The recordset of the item
+ */
+ public function loadByRecordSet(array $aRecordSet)
+ {
+ $this->values = $aRecordSet;
+ $this->oldPrimaryKey = $this->values[$this->primaryKey];
+ $this->virgin = false;
+ self::$_oCache->addItem($this->table."_".$this->oldPrimaryKey, $this->values);
+ }
+
+ /**
+ * Checks if a the item is already loaded.
+ * @return boolean
+ */
+ public function isLoaded()
+ {
+ return ($this->virgin)?FALSE:TRUE;
+ }
+
+ /**
+ * Function which is called whenever an item is loaded.
+ * Inherited classes should override this function if desired.
+ *
+ * @return void
+ */
+ protected function _onLoad()
+ {
+ }
+
+ /**
+ * Gets the value of a specific field.
+ *
+ * @param string $sField Specifies the field to retrieve
+ * @return mixed Value of the field
+ */
+ public function getField($sField)
+ {
+ if ($this->virgin == true) {
+ $this->lasterror = 'No item loaded';
+ return false;
+ }
+ return $this->_outFilter($this->values[$sField]);
+ }
+
+ /**
+ * Wrapper for getField (less to type).
+ *
+ * @param string $sField Specifies the field to retrieve
+ * @return mixed Value of the field
+ */
+ public function get($sField)
+ {
+ return $this->getField($sField);
+ }
+
+ /**
+ * Sets the value of a specific field.
+ *
+ * @param string $sField Field name
+ * @param string $mValue Value to set
+ * @param bool $bSafe Flag to run defined inFilter on passed value
+ */
+ public function setField($sField, $mValue, $bSafe = true)
+ {
+ if ($this->virgin == true) {
+ $this->lasterror = 'No item loaded';
+ return false;
+ }
+
+ $this->modifiedValues[$sField] = true;
+
+ if ($sField == $this->primaryKey) {
+ $this->oldPrimaryKey = $this->values[$sField];
+ }
+
+ if ($bSafe == true) {
+ $this->values[$sField] = $this->_inFilter($mValue);
+ } else {
+ $this->values[$sField] = $mValue;
+ }
+ return true;
+ }
+
+ /**
+ * Shortcut to setField.
+ *
+ * @param string $sField Field name
+ * @param string $mValue Value to set
+ * @param bool $bSafe Flag to run defined inFilter on passed value
+ */
+ public function set($sField, $mValue, $bSafe = true)
+ {
+ return $this->setField($sField, $mValue, $bSafe);
+ }
+
+ /**
+ * Stores the loaded and modified item to the database.
+ *
+ * @return bool
+ */
+ public function store() {
+ if(!$this->isLoaded()) {
+ $this->lasterror = 'No item loaded';
+ return false;
+ }
+
+ $sql = 'UPDATE `' . $this->table . '` SET ';
+ $first = true;
+
+ if (!is_array($this->modifiedValues)) {
+ return true;
+ }
+
+ foreach ($this->modifiedValues as $key => $bValue) {
+ if ($first == true) {
+ $sql .= "`$key` = '" . $this->values[$key] . "'";
+ $first = false;
+ } else {
+ $sql .= ", `$key` = '" . $this->values[$key] . "'";
+ }
+ }
+
+ $sql .= " WHERE " . $this->primaryKey . " = '" . $this->oldPrimaryKey . "'";
+
+ $this->db->query($sql);
+
+ $this->_lastSQL = $sql;
+
+ if ($this->db->affected_rows() > 0) {
+ self::$_oCache->addItem($this->table."_".$this->oldPrimaryKey, $this->values);
+ }
+
+ return ($this->db->affected_rows() < 1) ? false : true;
+ }
+
+ /**
+ * Returns current item data as an assoziative array.
+ *
+ * @return array|false
+ */
+ public function toArray()
+ {
+ if ($this->virgin == true) {
+ $this->lasterror = 'No item loaded';
+ return false;
+ }
+
+ $aReturn = array();
+ foreach ($this->values as $field => $value) {
+ $aReturn[$field] = $this->getField($field);
+ }
+ return $aReturn;
+ }
+
+ /**
+ * Returns current item data as an object.
+ *
+ * @return stdClass|false
+ */
+ public function toObject()
+ {
+ $return = $this->toArray();
+ return (false !== $return) ? (object) $return : $return;
+ }
+
+ /**
+ * Sets a custom property.
+ *
+ * @param string $sType Specifies the type
+ * @param string $sName Specifies the name
+ * @param mixed $mValue Specifies the value
+ * @return bool
+ */
+ public function setProperty($sType, $sName, $mValue)
+ {
+ // If this object wasn't loaded before, return false
+ if ($this->virgin == true) {
+ $this->lasterror = 'No item loaded';
+ return false;
+ }
+
+ // Set the value
+ $oProperties = $this->_getPropertiesCollectionInstance();
+ $bResult = $oProperties->setValue(
+ $this->primaryKey, $this->get($this->primaryKey), $sType, $sName, $mValue
+ );
+ return $bResult;
+ }
+
+ /**
+ * Returns a custom property.
+ *
+ * @param string $sType Specifies the type
+ * @param string $sName Specifies the name
+ * @return mixed Value of the given property or false
+ */
+ public function getProperty($sType, $sName)
+ {
+ // If this object wasn't loaded before, return false
+ if ($this->virgin == true) {
+ $this->lasterror = 'No item loaded';
+ return false;
+ }
+
+ // Return the value
+ $oProperties = $this->_getPropertiesCollectionInstance();
+ $mValue = $oProperties->getValue(
+ $this->primaryKey, $this->get($this->primaryKey), $sType, $sName
+ );
+ return $mValue;
+ }
+
+ /**
+ * Deletes a custom property.
+ *
+ * @param string $sType Specifies the type
+ * @param string $sName Specifies the name
+ * @return bool
+ */
+ public function deleteProperty($sType, $sName)
+ {
+ // If this object wasn't loaded before, return false
+ if ($this->virgin == true) {
+ $this->lasterror = 'No item loaded';
+ return false;
+ }
+
+ // Delete the value
+ $oProperties = $this->_getPropertiesCollectionInstance();
+ $bResult = $oProperties->deleteValue(
+ $this->primaryKey, $this->get($this->primaryKey), $sType, $sName
+ );
+ return $bResult;
+ }
+
+ /**
+ * Deletes a custom property by its id.
+ *
+ * @param int $idprop Id of property
+ * @return bool
+ */
+ public function deletePropertyById($idprop)
+ {
+ $oProperties = $this->_getPropertiesCollectionInstance();
+ return $oProperties->delete($idprop);
+ }
+
+ /**
+ * Deletes the current item
+ *
+ * @return void
+ */
+ // Method doesn't work, remove in future versions
+ // function delete()
+ // {
+ // $this->_collectionInstance->delete($item->get($this->primaryKey));
+ //}
+
+ /**
+ * Define the filter functions used when data is being stored or retrieved
+ * from the database.
+ *
+ * Examples:
+ *
+ * $obj->setFilters(array('addslashes'), array('stripslashes'));
+ * $obj->setFilters(array('htmlencode', 'addslashes'), array('stripslashes', 'htmlencode'));
+ *
+ *
+ * @param array $aInFilters Array with function names
+ * @param array $aOutFilters Array with function names
+ *
+ * @return void
+ */
+ public function setFilters($aInFilters = array(), $aOutFilters = array())
+ {
+ $this->_arrInFilters = $aInFilters;
+ $this->_arrOutFilters = $aOutFilters;
+ }
+
+ /**
+ * Filters the passed data using the functions defines in the _arrInFilters array.
+ *
+ * @see setFilters
+ *
+ * @todo This method is used from public scope, but it should be protected
+ *
+ * @param mixed $mData Data to filter
+ * @return mixed Filtered data
+ */
+ public function _inFilter($mData) {
+ if(is_numeric($mData) || is_array($mData)) return $mData;
+
+ foreach ($this->_arrInFilters as $_function) {
+ if (function_exists($_function)) {
+ $mData = $_function($mData);
+ }
+ }
+ return $mData;
+ }
+
+ /**
+ * Filters the passed data using the functions defines in the _arrOutFilters array.
+ *
+ * @see setFilters
+ *
+ * @param mixed $mData Data to filter
+ * @return mixed Filtered data
+ */
+ protected function _outFilter($mData) {
+ if(is_numeric($mData)) return $mData;
+
+ foreach ($this->_arrOutFilters as $_function) {
+ if (function_exists($_function)) {
+ $mData = $_function($mData);
+ }
+ }
+ return $mData;
+ }
+
+ protected function _setMetaObject($sObjectName)
+ {
+ $this->_metaObject = $sObjectName;
+ }
+
+ public function getMetaObject()
+ {
+ global $_metaObjectCache;
+
+ if (!is_array($_metaObjectCache)) {
+ $_metaObjectCache = array();
+ }
+
+ $sClassName = $this->_metaObject;
+ $qclassname = strtolower($sClassName);
+
+ if (array_key_exists($qclassname, $_metaObjectCache)) {
+ if (is_object($_metaObjectCache[$qclassname])) {
+ if (strtolower(get_class($_metaObjectCache[$qclassname])) == $qclassname) {
+ $_metaObjectCache[$qclassname]->setPayloadObject($this);
+ return $_metaObjectCache[$qclassname];
+ }
+ }
+ }
+
+ if (class_exists($sClassName)) {
+ $_metaObjectCache[$qclassname] = new $sClassName ($this);
+ return $_metaObjectCache[$qclassname];
+ }
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.group.php b/conlite/classes/class.group.php
new file mode 100644
index 0000000..fd09d86
--- /dev/null
+++ b/conlite/classes/class.group.php
@@ -0,0 +1,459 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created 2003-05-20
+ * modified 2008-07-02, Frederic Schneider, add security fix
+ * modified 2011-02-05, Murat Purc, Cleanup/formatting, documentation, standardize
+ * getGroupProperties() and new function insert()
+ *
+ * $Id: class.group.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ * Class Groups
+ * Container class for all system groups
+ * @author Timo A. Hummel
+ * @version 1.0
+ * @copyright four for business AG 2003
+ */
+class Groups
+{
+
+ /**
+ * Storage of the source table to use for the group informations
+ * @var string Contains the source table
+ * @access private
+ */
+ var $table;
+
+ /**
+ * DB_ConLite instance
+ * @var DB_ConLite Contains the database object
+ * @access private
+ */
+ var $db;
+
+ /**
+ * Constructor Function
+ *
+ * @param string $table The table to use as information source
+ */
+ function Groups($table = '')
+ {
+ if ($table == '') {
+ global $cfg;
+ $this->table = $cfg['tab']['groups'];
+ } else {
+ $this->table = $table;
+ }
+
+ $this->db = new DB_ConLite();
+ }
+
+
+ /**
+ * Removes the specified group from the database
+ *
+ * @param string $groupid Specifies the group ID
+ * @return bool True if the delete was successful
+ */
+ function deleteGroupByID($groupid)
+ {
+ $sql = "DELETE FROM "
+ .$this->table.
+ " WHERE group_id = '".Contenido_Security::escapeDB($groupid, $this->db)."'";
+
+ $this->db->query($sql);
+ return ($this->db->affected_rows() == 0) ? false : true;
+ }
+
+
+ /**
+ * Removes the specified group from the database.
+ *
+ * @param string $groupid Specifies the groupname
+ * @return bool True if the delete was successful
+ */
+ function deleteGroupByGroupname($groupname)
+ {
+ $sql = "DELETE FROM "
+ .$this->table.
+ " WHERE groupname = '".Contenido_Security::escapeDB($groupname, $this->db)."'";
+
+ $this->db->query($sql);
+ return ($this->db->affected_rows() == 0) ? false : true;
+ }
+
+
+ /**
+ * Returns all groups which are accessible by the current group.
+ *
+ * @param array $perms
+ * @return array Array of group objects
+ */
+ function getAccessibleGroups($perms)
+ {
+ global $cfg;
+
+ $clientclass = new Client();
+
+ $allClients = $clientclass->getAvailableClients();
+
+ $db = new DB_ConLite();
+
+ foreach ($allClients as $key => $value) {
+ if (in_array("client[".$key."]", $perms) || in_array("admin[".$key."]", $perms)) {
+ $limit[] = 'perms LIKE "%client['.Contenido_Security::escapeDB($key, $db).']%"';
+ }
+
+ if (in_array("admin[".$key."]", $perms)) {
+ $limit[] = 'perms LIKE "%admin['.Contenido_Security::escapeDB($key, $db).']%"';
+ }
+ }
+
+ if (count($limit) > 0) {
+ $limitSQL = implode(' OR ', $limit);
+ }
+
+ if (in_array('sysadmin', $perms)) {
+ $limitSQL = '1';
+ }
+
+ $sql = "SELECT
+ group_id, groupname, description
+ FROM
+ ". $cfg['tab']['groups']
+ . " WHERE 1 AND " .$limitSQL;
+
+ $db->query($sql);
+
+ $groups = array();
+
+ while ($db->next_record()) {
+ $groups[$db->f('group_id')] = array(
+ 'groupname' => substr($db->f('groupname'), 4),
+ 'description' => $db->f('description'),
+ );
+ }
+
+ return ($groups);
+ }
+
+}
+
+/**
+ * Class Group
+ * Class for group information and management
+ * @author Timo A. Hummel
+ * @version 1.0
+ * @copyright four for business 2003
+ */
+class Group
+{
+
+ /**
+ * Storage of the source table to use for the group informations
+ * @var string Contains the source table
+ * @access private
+ */
+ var $table;
+
+ /**
+ * DB_ConLite instance
+ * @var object Contains the database object
+ * @access private
+ */
+ var $db;
+
+ /**
+ * Storage of the source table to use for the group informations
+ * @var array Contains the source table
+ * @access private
+ */
+ var $values;
+
+ /**
+ * Storage of the fields which were modified
+ * @var array Contains the field names which where modified
+ * @access private
+ */
+ var $modifiedValues;
+
+ /**
+ * Constructor Function.
+ *
+ * @param string $table The table to use as information source
+ */
+ function Group($table = '')
+ {
+ if ($table == '') {
+ global $cfg;
+ $this->table = $cfg['tab']['groups'];
+ } else {
+ $this->table = $table;
+ }
+
+ $this->db = new DB_ConLite();
+ }
+
+
+ /**
+ * Loads a group from the database by its groupname.
+ *
+ * @param string $groupname Specifies the groupname
+ * @return bool True if the load was successful
+ */
+ function loadGroupByGroupname($groupname)
+ {
+ // SQL-Statement to select by groupname
+ $sql = "SELECT * FROM ".
+ $this->table
+ ." WHERE groupname = '" .Contenido_Security::escapeDB($groupname, $this->db)."'";
+
+ // Query the database
+ $this->db->query($sql);
+
+ // Advance to the next record, return false if nothing found
+ if (!$this->db->next_record()) {
+ return false;
+ }
+
+ $this->values = $this->db->toArray();
+ }
+
+
+ /**
+ * Loads a group from the database by its groupID.
+ *
+ * @param string $groupid Specifies the groupID
+ * @return bool True if the load was successful
+ */
+ function loadGroupByGroupID($groupID)
+ {
+ // SQL-Statement to select by groupID
+ $sql = "SELECT * FROM ".
+ $this->table
+ ." WHERE group_id = '" .Contenido_Security::escapeDB($groupID, $this->db)."'";
+
+ // Query the database
+ $this->db->query($sql);
+
+ // Advance to the next record, return false if nothing found
+ if (!$this->db->next_record()) {
+ return false;
+ }
+
+ $this->values = $this->db->toArray();
+ }
+
+
+ /**
+ * Gets the value of a specific field.
+ *
+ * @param string $field Specifies the field to retrieve
+ * @return mixed Value of the field
+ */
+ function getField($field)
+ {
+ return ($this->values[$field]);
+ }
+
+
+ /**
+ * Sets the value of a specific field.
+ *
+ * @param string $field Specifies the field to set
+ * @param string $value Specifies the value to set
+ */
+ function setField($field, $value)
+ {
+ $this->modifiedValues[$field] = true;
+ $this->values[$field] = $value;
+ }
+
+
+ /**
+ * Stores the modified group object to the database.
+ *
+ * @return bool
+ */
+ function store()
+ {
+ $sql = "UPDATE " . $this->table ." SET ";
+ $first = true;
+
+ foreach ($this->modifiedValues as $key => $value) {
+ if ($first == true) {
+ $sql .= "$key = '" . $this->values[$key] ."'";
+ } else {
+ $sql .= ", $key = '" . $this->values[$key] ."'";
+ }
+ $first = false;
+ }
+
+ $sql .= " WHERE group_id = '" .Contenido_Security::escapeDB($this->values['group_id'], $this->db)."'";
+
+ $this->db->query($sql);
+
+ return ($this->db->affected_rows() < 1) ? false : true;
+ }
+
+ /**
+ * Inserts new group object to the database
+ *
+ * @return bool
+ */
+ function insert()
+ {
+ $sql = "INSERT INTO " . $this->table ." SET ";
+ $first = true;
+
+ foreach ($this->modifiedValues as $key => $value) {
+ if ($first == true) {
+ $sql .= "$key = '" . $this->values[$key] ."'";
+ } else {
+ $sql .= ", $key = '" . $this->values[$key] ."'";
+ }
+ $first = false;
+ }
+
+ return ($this->db->query($sql));
+ }
+
+
+ /**
+ * Returns the group property
+ *
+ * @param string $type Specifies the type (class, category etc) for the property to retrieve
+ * @param string $name Specifies the name of the property to retrieve
+ * @return string The value of the retrieved property
+ */
+ function getGroupProperty($type, $name)
+ {
+ global $cfg;
+
+ $sql = "SELECT value FROM " .$cfg['tab']['group_prop']."
+ WHERE group_id = '".Contenido_Security::escapeDB($this->values['group_id'], $this->db)."'
+ AND type = '".Contenido_Security::escapeDB($type, $this->db)."'
+ AND name = '".Contenido_Security::escapeDB($name, $this->db)."'";
+ $this->db->query($sql);
+
+ if ($this->db->next_record()) {
+ return $this->db->f('value');
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Retrieves all available properties of the group.
+ *
+ * @return array Returns assoziative properties array as follows:
+ * - $arr[idgroupprop][name]
+ * - $arr[idgroupprop][type]
+ * - $arr[idgroupprop][value]
+ */
+ function getGroupProperties()
+ {
+ global $cfg;
+
+ $aProps = array();
+
+ $sql = "SELECT idgroupprop, type, name, value FROM " .$cfg['tab']['group_prop']."
+ WHERE group_id = '".Contenido_Security::escapeDB($this->values['group_id'], $this->db)."'";
+ $this->db->query($sql);
+
+ if ($this->db->num_rows() == 0) {
+ return $aProps;
+ }
+
+ while ($this->db->next_record()) {
+ $aProps[$this->db->f('idgroupprop')] = array(
+ 'name' => $this->db->f('name'),
+ 'type' => $this->db->f('type'),
+ 'value' => $this->db->f('value'),
+ );
+ }
+
+ return $aProps;
+ }
+
+
+ /**
+ * Stores a property to the database.
+ *
+ * @param string $type Specifies the type (class, category etc) for the property to retrieve
+ * @param string $name Specifies the name of the property to retrieve
+ * @param string $value Specifies the value to insert
+ */
+ function setGroupProperty($type, $name, $value)
+ {
+ global $cfg;
+
+ // Check if such an entry already exists
+ if ($this->getGroupProperty($type, $name) !== false) {
+ $sql = "UPDATE ".$cfg['tab']['group_prop']."
+ SET value = '".Contenido_Security::escapeDB($value, $this->db)."'
+ WHERE group_id = '".Contenido_Security::escapeDB($this->values['group_id'], $this->db)."'
+ AND type = '".Contenido_Security::escapeDB($type, $this->db)."'
+ AND name = '".Contenido_Security::escapeDB($name, $this->db)."'";
+ $this->db->query($sql);
+ } else {
+ $sql = "INSERT INTO ".$cfg['tab']['group_prop']."
+ SET value = '".Contenido_Security::escapeDB($value, $this->db)."',
+ group_id = '".Contenido_Security::escapeDB($this->values['group_id'], $this->db)."',
+ type = '".Contenido_Security::escapeDB($type, $this->db)."',
+ name = '".Contenido_Security::escapeDB($name, $this->db)."',
+ idgroupprop = '".Contenido_Security::toInteger($this->db->nextid($cfg['tab']['group_prop']))."'";
+ $this->db->query($sql);
+ }
+ }
+
+
+ /**
+ * Deletes a group property from the table.
+ *
+ * @param string $type Specifies the type (class, category etc) for the property to retrieve
+ * @param string $name Specifies the name of the property to retrieve
+ */
+ function deleteGroupProperty($type, $name)
+ {
+ global $cfg;
+
+ // Check if such an entry already exists
+ $sql = "DELETE FROM ".$cfg['tab']['group_prop']."
+ WHERE group_id = '".Contenido_Security::escapeDB($this->values['group_id'], $this->db)."' AND
+ type = '".Contenido_Security::escapeDB($type, $this->db)."' AND
+ name = '".Contenido_Security::escapeDB($name, $this->db)."'";
+ $this->db->query($sql);
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.htmlelements.php b/conlite/classes/class.htmlelements.php
new file mode 100644
index 0000000..7b379e7
--- /dev/null
+++ b/conlite/classes/class.htmlelements.php
@@ -0,0 +1,2027 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ *
+ * $Id: class.htmlelements.php 365 2015-10-08 14:26:19Z oldperl $:
+ */
+/**
+ *
+ */
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ * HTML Form element class
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLFormElement extends cHTML {
+
+ /**
+ * Constructor. This is a generic form element, where
+ * specific elements should be inherited from this class.
+ *
+ * @param $name string Name of the element
+ * @param $id string ID of the element
+ * @param $disabled string Item disabled flag (non-empty to set disabled)
+ * @param $tabindex string Tab index for form elements
+ * @param $accesskey string Key to access the field
+ *
+ * @return none
+ */
+ public function __construct($name = "", $id = "", $disabled = "", $tabindex = "", $accesskey = "") {
+ parent::__construct();
+
+ $this->updateAttributes(array("name" => $name));
+
+ if (is_string($id) && !empty($id)) {
+ $this->updateAttributes(array("id" => $id));
+ }
+
+ $this->setClass("text_medium"); // TODO: Remove this...
+ $this->setDisabled($disabled);
+ $this->setTabindex($tabindex);
+ $this->setAccessKey($accesskey);
+ }
+
+ /**
+ * Sets the "disabled" attribute of an element. User Agents
+ * usually are showing the element as "greyed-out".
+ *
+ * Example:
+ * $obj->setDisabled("disabled");
+ * $obj->setDisabled("");
+ *
+ * The first example sets the disabled flag, the second one
+ * removes the disabled flag.
+ *
+ * @param $disabled string Sets the disabled-flag if non-empty
+ * @return none
+ */
+ function setDisabled($disabled) {
+ if (!empty($disabled)) {
+ $this->updateAttributes(array("disabled" => "disabled"));
+ } else {
+ $this->removeAttribute("disabled");
+ }
+ }
+
+ /**
+ * sets the tab index for this element. The tab
+ * index needs to be numeric, bigger than 0 and smaller than 32767.
+ *
+ * @param $tabindex int desired tab index
+ * @return none
+ */
+ function setTabindex($tabindex) {
+ if (is_numeric($tabindex) && $tabindex >= 0 && $tabindex <= 32767) {
+ $this->updateAttributes(array("tabindex" => $tabindex));
+ }
+ }
+
+ /**
+ * sets the access key for this element.
+ *
+ * @param $accesskey string The length of the access key. May be A-Z and 0-9.
+ * @return none
+ */
+ function setAccessKey($accesskey) {
+ if ((strlen($accesskey) == 1) && is_alphanumeric($accesskey)) {
+ $this->updateAttributes(array("accesskey" => $accesskey));
+ } else {
+ $this->removeAttribute("accesskey");
+ }
+ }
+
+}
+
+/**
+ * HTML Hidden Field
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLHiddenField extends cHTMLFormElement {
+
+ /**
+ * Constructor. Creates an HTML hidden field.
+ *
+ * @param $name string Name of the element
+ * @param $value string Title of the button
+ * @param $id string ID of the element
+ *
+ * @return none
+ */
+ function __construct($name, $value = "", $id = "") {
+ parent::__construct($name, $id);
+ $this->setContentlessTag();
+ $this->updateAttributes(array("type" => "hidden"));
+ $this->_tag = "input";
+
+ $this->setValue($value);
+ }
+
+ /**
+ * Sets the value for the field
+ *
+ * @param $value string Value of the field
+ * @return none
+ */
+ function setValue($value) {
+ $this->updateAttributes(array("value" => $value));
+ }
+
+ /**
+ * Renders the hidden field
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHtml() {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes);
+ }
+
+}
+
+/**
+ * HTML Button class
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLButton extends cHTMLFormElement {
+
+ /**
+ * Constructor. Creates an HTML button.
+ *
+ * Creates a submit button by default, can be changed
+ * using setMode.
+ *
+ * @param $name string Name of the element
+ * @param $title string Title of the button
+ * @param $id string ID of the element
+ * @param $disabled string Item disabled flag (non-empty to set disabled)
+ * @param $tabindex string Tab index for form elements
+ * @param $accesskey string Key to access the field
+ *
+ * @return none
+ */
+ function __construct($name, $title = "", $id = "", $disabled = false, $tabindex = null, $accesskey = "", $mode = "submit") {
+ parent::__construct($name, $id, $disabled, $tabindex, $accesskey);
+ $this->_tag = "input";
+ $this->setContentlessTag();
+ $this->setTitle($title);
+ $this->setMode($mode);
+ }
+
+ /**
+ * Sets the title (caption) for the button
+ *
+ * @param $title string The title to set
+ * @return none
+ */
+ function setTitle($title) {
+ $this->updateAttributes(array("value" => $title));
+ }
+
+ /**
+ * Sets the mode (submit or reset) for the button
+ *
+ * @param $mode string Either "submit", "reset" or "image".
+ * @return boolean Returns false if failed to set the mode
+ */
+ function setMode($mode) {
+
+ switch ($mode) {
+ case "submit" :
+ case "reset" :
+ $this->updateAttributes(array("type" => $mode));
+ break;
+ case "image" :
+ $this->updateAttributes(array("type" => $mode));
+ break;
+ case "button" :
+ $this->updateAttributes(array("type" => $mode));
+ break;
+ default :
+ return false;
+ }
+ }
+
+ /**
+ * Set the image src if mode type is "image"
+ *
+ * @param $mode string image path.
+ * @return void
+ */
+ function setImageSource($src) {
+ $this->updateAttributes(array("src" => $src));
+ }
+
+ /**
+ * Renders the button
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHtml() {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes);
+ }
+
+}
+
+/**
+ * HTML Textbox
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLTextbox extends cHTMLFormElement {
+
+ /**
+ * Constructor. Creates an HTML text box.
+ *
+ * If no additional parameters are specified, the
+ * default width is 20 units.
+ *
+ * @param $name string Name of the element
+ * @param $initvalue string Initial value of the box
+ * @param $width int width of the text box
+ * @param $maxlength int maximum input length of the box
+ * @param $id string ID of the element
+ * @param $disabled string Item disabled flag (non-empty to set disabled)
+ * @param $tabindex string Tab index for form elements
+ * @param $accesskey string Key to access the field
+ *
+ * @return none
+ */
+ public function __construct($name, $initvalue = "", $width = "", $maxlength = "", $id = "", $disabled = false, $tabindex = null, $accesskey = "") {
+ parent::__construct($name, $id, $disabled, $tabindex, $accesskey);
+
+ $this->_tag = "input";
+ $this->setContentlessTag();
+ $this->setValue($initvalue);
+
+ $this->setWidth($width);
+ $this->setMaxLength($maxlength);
+
+ $this->updateAttributes(array("type" => "text"));
+ }
+
+ /**
+ * sets the width of the text box.
+ *
+ * @param $width int width of the text box
+ *
+ * @return none
+ */
+ function setWidth($width) {
+ $width = intval($width);
+
+ if ($width <= 0) {
+ $width = 50;
+ }
+
+ $this->updateAttributes(array("size" => $width));
+ }
+
+ /**
+ * sets the maximum input length of the text box.
+ *
+ * @param $maxlen int maximum input length
+ *
+ * @return none
+ */
+ function setMaxLength($maxlen) {
+ $maxlen = intval($maxlen);
+
+ if ($maxlen <= 0) {
+ $this->removeAttribute("maxlength");
+ } else {
+ $this->updateAttributes(array("maxlength" => $maxlen));
+ }
+ }
+
+ /**
+ * sets the initial value of the text box.
+ *
+ * @param $value string Initial value
+ *
+ * @return none
+ */
+ function setValue($value) {
+ $this->updateAttributes(array("value" => $value));
+ }
+
+ /**
+ * Renders the textbox
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHtml() {
+ return parent::toHtml();
+ }
+
+}
+
+/**
+ * HTML Password Box
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLPasswordbox extends cHTMLFormElement {
+
+ /**
+ * Constructor. Creates an HTML password box.
+ *
+ * If no additional parameters are specified, the
+ * default width is 20 units.
+ *
+ * @param $name string Name of the element
+ * @param $initvalue string Initial value of the box
+ * @param $width int width of the text box
+ * @param $maxlength int maximum input length of the box
+ * @param $id string ID of the element
+ * @param $disabled string Item disabled flag (non-empty to set disabled)
+ * @param $tabindex string Tab index for form elements
+ * @param $accesskey string Key to access the field
+ *
+ * @return none
+ */
+ function __construct($name, $initvalue = "", $width = "", $maxlength = "", $id = "", $disabled = false, $tabindex = null, $accesskey = "") {
+ parent::__construct($name, $id, $disabled, $tabindex, $accesskey);
+ $this->_tag = "input";
+ $this->setValue($initvalue);
+
+ $this->setWidth($width);
+ $this->setMaxLength($maxlength);
+
+ $this->updateAttributes(array("type" => "password"));
+ }
+
+ /**
+ * sets the width of the text box.
+ *
+ * @param $width int width of the text box
+ *
+ * @return none
+ */
+ function setWidth($width) {
+ $width = intval($width);
+
+ if ($width <= 0) {
+ $width = 20;
+ }
+
+ $this->updateAttributes(array("size" => $width));
+ }
+
+ /**
+ * sets the maximum input length of the text box.
+ *
+ * @param $maxlen int maximum input length
+ *
+ * @return none
+ */
+ function setMaxLength($maxlen) {
+ $maxlen = intval($maxlen);
+
+ if ($maxlen <= 0) {
+ $this->removeAttribute("maxlength");
+ } else {
+ $this->updateAttributes(array("maxlength" => $maxlen));
+ }
+ }
+
+ /**
+ * sets the initial value of the text box.
+ *
+ * @param $value string Initial value
+ *
+ * @return none
+ */
+ function setValue($value) {
+ $this->updateAttributes(array("value" => $value));
+ }
+
+ /**
+ * Renders the textbox
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHtml() {
+ return parent::toHTML();
+ }
+
+}
+
+class cHTMLTextarea extends cHTMLFormElement {
+
+ var $_value;
+
+ /**
+ * Constructor. Creates an HTML text area.
+ *
+ * If no additional parameters are specified, the
+ * default width is 60 chars, and the height is 5 chars.
+ *
+ * @param $name string Name of the element
+ * @param $initvalue string Initial value of the textarea
+ * @param $width int width of the textarea
+ * @param $height int height of the textarea
+ * @param $id string ID of the element
+ * @param $disabled string Item disabled flag (non-empty to set disabled)
+ * @param $tabindex string Tab index for form elements
+ * @param $accesskey string Key to access the field
+ *
+ * @return none
+ */
+ function __construct($name, $initvalue = "", $width = "", $height = "", $id = "", $disabled = false, $tabindex = null, $accesskey = "") {
+ parent::__construct($name, $id, $disabled, $tabindex, $accesskey);
+ $this->_tag = "textarea";
+ $this->setValue($initvalue);
+ $this->setContentlessTag(false);
+ $this->setWidth($width);
+ $this->setHeight($height);
+ }
+
+ /**
+ * sets the width of the text box.
+ *
+ * @param $width int width of the text box
+ *
+ * @return none
+ */
+ function setWidth($width) {
+ $width = intval($width);
+
+ if ($width <= 0) {
+ $width = 50;
+ }
+
+ $this->updateAttributes(array("cols" => $width));
+ }
+
+ /**
+ * sets the maximum input length of the text box.
+ *
+ * @param $maxlen int maximum input length
+ *
+ * @return none
+ */
+ function setHeight($height) {
+ $height = intval($height);
+
+ if ($height <= 0) {
+ $height = 5;
+ }
+
+ $this->updateAttributes(array("rows" => $height));
+ }
+
+ /**
+ * sets the initial value of the text box.
+ *
+ * @param $value string Initial value
+ *
+ * @return none
+ */
+ function setValue($value) {
+ $this->_value = $value;
+ }
+
+ /**
+ * Renders the textbox
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHtml() {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes) . $this->_value . $this->fillCloseSkeleton();
+ }
+
+}
+
+/**
+ *
+ * @package Contenido cHTML
+ * @subpackage cHTMLElements
+ * @author Timo A. Hummel
+ * @author Ortwin Pinke
+ */
+class cHTMLLabel extends cHTML {
+
+ /**
+ * the text for label
+ *
+ * @var string $_sText
+ */
+ protected $_sText;
+
+ /**
+ * Creates an HTML label which can be linked
+ * to any form element (specified by their ID).
+ *
+ * A label can be used to link to elements. This is very useful
+ * since if a user clicks a label, the linked form element receives
+ * the focus (if supported by the user agent).
+ *
+ * @param string $sText Text for the label
+ * @param string $for Id of the form element the label belongs to
+ *
+ * @return void
+ */
+ public function __construct($sText, $sFor) {
+ parent::__construct();
+ $this->_tag = "label";
+ $this->setContentlessTag(false);
+ $this->updateAttributes(array("for" => $sFor));
+ $this->_sText = $sText;
+ }
+
+ /**
+ * setter for label text
+ *
+ * @param string $sText
+ */
+ public function setLabelText($sText) {
+ $this->_sText = $sText;
+ }
+
+ /**
+ * Renders the label
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHtml() {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes) . $this->_sText . $this->fillCloseSkeleton();
+ }
+
+}
+
+/**
+ * HTML Select Element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLSelectElement extends cHTMLFormElement {
+
+ /**
+ * All cHTMLOptionElements
+ * @var array
+ */
+ var $_options;
+
+ /**
+ * Constructor. Creates an HTML select field (aka "DropDown").
+ *
+ * @param $name string Name of the element
+ * @param $width int width of the select element
+ * @param $id string ID of the element
+ * @param $disabled string Item disabled flag (non-empty to set disabled)
+ * @param $tabindex string Tab index for form elements
+ * @param $accesskey string Key to access the field
+ *
+ * @return none
+ */
+ function __construct($name, $width = "", $id = "", $disabled = false, $tabindex = null, $accesskey = "") {
+ parent::__construct($name, $id, $disabled, $tabindex, $accesskey);
+ $this->_tag = "select";
+ $this->setContentlessTag(false);
+ }
+
+ /**
+ * Automatically creates and fills cHTMLOptionElements
+ *
+ * Array format:
+ * $stuff = array(
+ * array("value","title"),
+ * array("value","title"));
+ *
+ * or regular key => value arrays.
+ *
+ * @param $stuff array Array with all items
+ *
+ * @return none
+ */
+ function autoFill($stuff) {
+ if (is_array($stuff)) {
+ foreach ($stuff as $key => $row) {
+ if (is_array($row)) {
+ $option = new cHTMLOptionElement($row[1], $row[0]);
+ $this->addOptionElement($row[0], $option);
+ } else {
+ $option = new cHTMLOptionElement($row, $key);
+ $this->addOptionElement($key, $option);
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds an cHTMLOptionElement to the number of choices.
+ *
+ * @param $index string Index of the element
+ * @param $element object Filled cHTMLOptionElement to add
+ *
+ * @return none
+ */
+ function addOptionElement($index, $element) {
+ $this->_options[$index] = $element;
+ }
+
+ function setMultiselect() {
+ $this->updateAttributes(array("multiple" => "multiple"));
+ }
+
+ function setSize($size) {
+ $this->updateAttributes(array("size" => $size));
+ }
+
+ /**
+ * Sets a specific cHTMLOptionElement to the selected
+ * state.
+ *
+ * @param $lvalue string Specifies the "value" of the cHTMLOptionElement to set
+ *
+ * @return none
+ */
+ function setDefault($lvalue) {
+ $bSet = false;
+
+ if (is_array($this->_options)) {
+ foreach ($this->_options as $key => $value) {
+ if (strcmp($value->getAttribute("value"), $lvalue) == 0) {
+ $value->setSelected(true);
+ $this->_options[$key] = $value;
+ $bSet = true;
+ } else {
+ $value->setSelected(false);
+ $this->_options[$key] = $value;
+ }
+ }
+ }
+
+ if ($bSet == false) {
+ if (is_array($this->_options)) {
+ foreach ($this->_options as $key => $value) {
+ $value->setSelected(true);
+ $this->_options[$key] = $value;
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * Search for the selected elements
+ *
+ * @param none
+ *
+ * @return Selected "lvalue"
+ */
+ function getDefault() {
+ if (is_array($this->_options)) {
+ foreach ($this->_options as $key => $value) {
+ if ($value->isSelected()) {
+ return $key;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Sets specified elements as selected (and all others as unselected)
+ *
+ * @param array $aElements Array with "values" of the cHTMLOptionElement to set
+ *
+ * @return none
+ */
+ function setSelected($aElements) {
+ if (is_array($this->_options) && is_array($aElements)) {
+ foreach ($this->_options as $sKey => $oOption) {
+ if (in_array($oOption->getAttribute("value"), $aElements)) {
+ $oOption->setSelected(true);
+ $this->_options[$sKey] = $oOption;
+ } else {
+ $oOption->setSelected(false);
+ $this->_options[$sKey] = $oOption;
+ }
+ }
+ }
+ }
+
+ /**
+ * Renders the select box
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHtml() {
+
+ $attributes = $this->getAttributes(true);
+
+ $options = "";
+
+ if (is_array($this->_options)) {
+ foreach ($this->_options as $key => $value) {
+ $options .= $value->toHtml();
+ }
+ }
+
+ return ($this->fillSkeleton($attributes) . $options . $this->fillCloseSkeleton());
+ }
+
+}
+
+/**
+ * HTML Select Option Element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLOptionElement extends cHTMLFormElement {
+
+ /**
+ * Title to display
+ * @var string
+ * @access private
+ */
+ var $_title;
+
+ /**
+ * Constructor. Creates an HTML option element.
+ *
+ * @param $title string Displayed title of the element
+ * @param $value string Value of the option
+ * @param $selected boolean If true, element is selected
+ * @param $disabled boolean If true, element is disabled
+ *
+ * @return none
+ */
+ function __construct($title, $value, $selected = false, $disabled = false) {
+ cHTML::__construct();
+ $this->_tag = "option";
+ $this->_title = $title;
+
+ $this->updateAttributes(array("value" => $value));
+ $this->setContentlessTag(false);
+
+ $this->setSelected($selected);
+ $this->setDisabled($disabled);
+ }
+
+ /**
+ * sets the selected flag
+ *
+ * @param $selected boolean If true, adds the "selected" attribute
+ *
+ * @return none
+ */
+ function setSelected($selected) {
+ if ($selected == true) {
+ $this->updateAttributes(array("selected" => "selected"));
+ } else {
+ $this->removeAttribute("selected");
+ }
+ }
+
+ /**
+ * sets the selected flag
+ *
+ * @param $selected boolean If true, adds the "selected" attribute
+ *
+ * @return none
+ */
+ function isSelected() {
+ if ($this->getAttribute("selected") == "selected") {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * sets the disabled flag
+ *
+ * @param $disabled boolean If true, adds the "disabled" attribute
+ *
+ * @return none
+ */
+ function setDisabled($disabled) {
+ if ($disabled == true) {
+ $this->updateAttributes(array("disabled" => "disabled"));
+ } else {
+ $this->removeAttribute("disabled");
+ }
+ }
+
+ /**
+ * Renders the option element. Note:
+ * the cHTMLSelectElement renders the options by itself.
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHtml() {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes) . $this->_title . $this->fillCloseSkeleton();
+ }
+
+}
+
+/**
+ * HTML Radio Button
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLRadiobutton extends cHTMLFormElement {
+
+ /**
+ * Values for the check box
+ * @var string
+ * @access private
+ */
+ var $_value;
+
+ /**
+ * Constructor. Creates an HTML radio button element.
+ *
+ * @param $name string Name of the element
+ * @param $value string Value of the radio button
+ * @param $id string ID of the element
+ * @param $checked boolean Is element checked?
+ * @param $disabled string Item disabled flag (non-empty to set disabled)
+ * @param $tabindex string Tab index for form elements
+ * @param $accesskey string Key to access the field
+ *
+ * @return none
+ */
+ function __construct($name, $value, $id = "", $checked = false, $disabled = false, $tabindex = null, $accesskey = "") {
+ parent::__construct($name, $id, $disabled, $tabindex, $accesskey);
+ $this->_tag = "input";
+ $this->_value = $value;
+ $this->setContentlessTag();
+
+ $this->setChecked($checked);
+ $this->updateAttributes(array("type" => "radio"));
+ $this->updateAttributes(array("value" => $value));
+ }
+
+ /**
+ * Sets the checked flag.
+ *
+ * @param $checked boolean If true, the "checked" attribute will be assigned.
+ *
+ * @return none
+ */
+ function setChecked($checked) {
+ if ($checked == true) {
+ $this->updateAttributes(array("checked" => "checked"));
+ } else {
+ $this->removeAttribute("checked");
+ }
+ }
+
+ /**
+ * Sets a custom label text
+ *
+ * @param $text string Text to display
+ *
+ * @return none
+ */
+ function setLabelText($text) {
+ $this->_labelText = $text;
+ }
+
+ /**
+ * Renders the option element. Note:
+ *
+ * If this element has an ID, the value (which equals the text displayed)
+ * will be rendered as seperate HTML label, if not, it will be displayed
+ * as regular text. Displaying the value can be turned off via the parameter.
+ *
+ * @param $renderlabel boolean If true, renders a label
+ *
+ * @return string Rendered HTML
+ */
+ function toHtml($renderLabel = true) {
+ $attributes = $this->getAttributes(true);
+
+ if ($renderLabel == false) {
+ return $this->fillSkeleton($attributes);
+ }
+
+ $id = $this->getAttribute("id");
+
+ $renderedLabel = "";
+
+ if ($id != "") {
+ $label = new cHTMLLabel($this->_value, $this->getAttribute("id"));
+
+ if ($this->_labelText != "") {
+ $label->setLabelText($this->_labelText);
+ }
+
+ $renderedLabel = $label->toHtml();
+ } else {
+ $renderedLabel = $this->_value;
+ }
+
+ return $this->fillSkeleton($attributes) . $renderedLabel;
+ }
+
+}
+
+/**
+ * HTML Checkbox
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLCheckbox extends cHTMLFormElement {
+
+ var $_value;
+
+ /**
+ * Constructor. Creates an HTML checkbox element.
+ *
+ * @param $name string Name of the element
+ * @param $value string Value of the radio button
+ * @param $id string ID of the element
+ * @param $checked boolean Is element checked?
+ * @param $disabled string Item disabled flag (non-empty to set disabled)
+ * @param $tabindex string Tab index for form elements
+ * @param $accesskey string Key to access the field
+ *
+ * @return none
+ */
+ function __construct($name, $value, $id = "", $checked = false, $disabled = false, $tabindex = null, $accesskey = "") {
+
+ parent::__construct($name, $id, $disabled, $tabindex, $accesskey);
+ $this->_tag = "input";
+ $this->_value = $value;
+ $this->setContentlessTag();
+
+ $this->setChecked($checked);
+ $this->updateAttributes(array("type" => "checkbox"));
+ $this->updateAttributes(array("value" => $value));
+ }
+
+ /**
+ * Sets the checked flag.
+ *
+ * @param $checked boolean If true, the "checked" attribute will be assigned.
+ *
+ * @return none
+ */
+ function setChecked($checked) {
+ if ($checked == true) {
+ $this->updateAttributes(array("checked" => "checked"));
+ } else {
+ $this->removeAttribute("checked");
+ }
+ }
+
+ /**
+ * Sets a custom label text
+ *
+ * @param $text string Text to display
+ *
+ * @return none
+ */
+ function setLabelText($text) {
+ $this->_labelText = $text;
+ }
+
+ /**
+ * Renders the checkbox element. Note:
+ *
+ * If this element has an ID, the value (which equals the text displayed)
+ * will be rendered as seperate HTML label, if not, it will be displayed
+ * as regular text. Displaying the value can be turned off via the parameter.
+ *
+ * @param $renderlabel boolean If true, renders a label
+ *
+ * @return string Rendered HTML
+ */
+ function toHtml($renderlabel = true) {
+ $id = $this->getAttribute("id");
+ $renderedLabel = "";
+
+ if ($renderlabel == true) {
+ if ($id != "") {
+ $label = new cHTMLLabel($this->_value, $this->getAttribute("id"));
+
+ $label->setClass($this->getAttribute("class"));
+
+ if ($this->_labelText != "") {
+ $label->setLabelText($this->_labelText);
+ }
+
+ $renderedLabel = $label->toHtml();
+ } else {
+
+ $renderedLabel = $this->_value;
+
+ if ($this->_labelText != "") {
+ $label = new cHTMLLabel($this->_value, $this->getAttribute("id"));
+ $label->setLabelText($this->_labelText);
+ $renderedLabel = $label->toHtml();
+ }
+ }
+
+ return '' . parent::toHTML() . ' ' . $renderedLabel . '
';
+ } else {
+ return parent::toHTML();
+ }
+ }
+
+}
+
+/**
+ * HTML File upload box
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLUpload extends cHTMLFormElement {
+
+ /**
+ * Constructor. Creates an HTML upload box.
+ *
+ * If no additional parameters are specified, the
+ * default width is 20 units.
+ *
+ * @param $name string Name of the element
+ * @param $initvalue string Initial value of the box
+ * @param $width int width of the text box
+ * @param $maxlength int maximum input length of the box
+ * @param $id string ID of the element
+ * @param $disabled string Item disabled flag (non-empty to set disabled)
+ * @param $tabindex string Tab index for form elements
+ * @param $accesskey string Key to access the field
+ *
+ * @return none
+ */
+ function __construct($name, $width = "", $maxlength = "", $id = "", $disabled = false, $tabindex = null, $accesskey = "") {
+ parent::__construct($name, $id, $disabled, $tabindex, $accesskey);
+ $this->_tag = "input";
+ $this->setContentlessTag();
+
+ $this->setWidth($width);
+ $this->setMaxLength($maxlength);
+
+ $this->updateAttributes(array("type" => "file"));
+ }
+
+ /**
+ * sets the width of the text box.
+ *
+ * @param $width int width of the text box
+ *
+ * @return none
+ */
+ function setWidth($width) {
+ $width = intval($width);
+
+ if ($width <= 0) {
+ $width = 20;
+ }
+
+ $this->updateAttributes(array("size" => $width));
+ }
+
+ /**
+ * sets the maximum input length of the text box.
+ *
+ * @param $maxlen int maximum input length
+ *
+ * @return none
+ */
+ function setMaxLength($maxlen) {
+ $maxlen = intval($maxlen);
+
+ if ($maxlen <= 0) {
+ $this->removeAttribute("maxlength");
+ } else {
+ $this->updateAttributes(array("maxlength" => $maxlen));
+ }
+ }
+
+ /**
+ * Renders the textbox
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHtml() {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes);
+ }
+
+}
+
+/**
+ * HTML Link
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLLink extends cHTML {
+ /* Stores the link location */
+
+ var $_link;
+
+ /* Stores the content */
+ var $_content;
+
+ /* Stores the anchor */
+ var $_anchor;
+
+ /* Stores the custom entries */
+ var $_custom;
+
+ /**
+ * Constructor. Creates an HTML link.
+ *
+ * @param $href String with the location to link to
+ *
+ */
+ function __construct($href = "") {
+ global $sess;
+ parent::__construct();
+
+ $this->setLink($href);
+ $this->setContentlessTag(false);
+ $this->_tag = "a";
+
+ /* Check for backend */
+ if (is_object($sess)) {
+ if ($sess->classname == "Contenido_Session") {
+ $this->enableAutomaticParameterAppend();
+ }
+ }
+ }
+
+ function enableAutomaticParameterAppend() {
+ $this->setEvent("click", 'var doit = true; try { var i = get_registered_parameters() } catch (e) { doit = false; }; if (doit == true) { this.href += i; }');
+ }
+
+ function disableAutomaticParameterAppend() {
+ $this->unsetEvent("click");
+ }
+
+ /**
+ * setLink: Sets the link to a specific location
+ *
+ * @param $href String with the location to link to
+ *
+ */
+ function setLink($href) {
+ $this->_link = $href;
+ $this->_type = "link";
+
+ if (strpos($href, "javascript:") !== false) {
+ $this->disableAutomaticParameterAppend();
+ }
+ }
+
+ /**
+ * setTargetFrame: Sets the target frame
+ *
+ * @param $target string Target frame identifier
+ *
+ */
+ function setTargetFrame($target) {
+ $this->updateAttributes(array("target" => $target));
+ }
+
+ /**
+ * setLink: Sets a Contenido link (area, frame, action)
+ *
+ * @param $targetarea string Target backend area
+ * @param $targetframe string Target frame (1-4)
+ * @param $targetaction string Target action
+ */
+ function setCLink($targetarea, $targetframe, $targetaction = "") {
+ $this->_targetarea = $targetarea;
+ $this->_targetframe = $targetframe;
+ $this->_targetaction = $targetaction;
+ $this->_type = "clink";
+ }
+
+ /**
+ * setMultiLink: Sets a multilink
+ *
+ * @param $righttoparea string Area (right top)
+ * @param $righttopaction string Action (right top)
+ * @param $rightbottomarea string Area (right bottom)
+ * @param $rightbottomaction string Action (right bottom)
+ */
+ function setMultiLink($righttoparea, $righttopaction, $rightbottomarea, $rightbottomaction) {
+ $this->_targetarea = $righttoparea;
+ $this->_targetframe = 3;
+ $this->_targetaction = $righttopaction;
+ $this->_targetarea2 = $rightbottomarea;
+ $this->_targetframe2 = 4;
+ $this->_targetaction2 = $rightbottomaction;
+ $this->_type = "multilink";
+ }
+
+ /**
+ * setCustom: Sets a custom attribute to be appended to the link
+ *
+ * @param $key string Parameter name
+ * @param $value string Parameter value
+ */
+ function setCustom($key, $value) {
+ $this->_custom[$key] = $value;
+ }
+
+ function getHref() {
+ global $sess;
+
+ if (is_array($this->_custom)) {
+ $custom = "";
+
+ foreach ($this->_custom as $key => $value) {
+ $custom .= "&$key=$value";
+ }
+ }
+
+ if ($this->_anchor) {
+ $anchor = "#" . $this->_anchor;
+ } else {
+ $anchor = "";
+ }
+
+ switch ($this->_type) {
+ case "link" :
+ $custom = "";
+ if (is_array($this->_custom)) {
+ foreach ($this->_custom as $key => $value) {
+ if ($custom == "") {
+ $custom .= "?$key=$value";
+ } else {
+ $custom .= "&$key=$value";
+ }
+ }
+ }
+
+ return $this->_link . $custom . $anchor;
+ break;
+ case "clink" :
+ $this->disableAutomaticParameterAppend();
+ return 'main.php?area=' . $this->_targetarea . '&frame=' . $this->_targetframe . '&action=' . $this->_targetaction . $custom . "&contenido=" . $sess->id . $anchor;
+ break;
+ case "multilink" :
+ $this->disableAutomaticParameterAppend();
+ $tmp_mstr = 'javascript:conMultiLink(\'%s\',\'%s\',\'%s\',\'%s\');';
+ $mstr = sprintf($tmp_mstr, 'right_top', $sess->url("main.php?area=" . $this->_targetarea . "&frame=" . $this->_targetframe . "&action=" . $this->_targetaction . $custom), 'right_bottom', $sess->url("main.php?area=" . $this->_targetarea2 . "&frame=" . $this->_targetframe2 . "&action=" . $this->_targetaction2 . $custom));
+ return $mstr;
+ break;
+ }
+ }
+
+ /**
+ * setAnchor: Sets an anchor
+ *
+ * Only works for the link types Link and cLink.
+ *
+ * @param $content string Anchor name
+ *
+ */
+ function setAnchor($anchor) {
+ $this->_anchor = $anchor;
+ }
+
+ /**
+ * setContent: Sets the link's content
+ *
+ * @param $content string/object String with the content or an object to render.
+ *
+ */
+ function setContent($content) {
+ $this->_setContent($content);
+ }
+
+ /**
+ * Renders the link
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ $this->updateAttributes(array("href" => $this->getHref()));
+
+ return parent::toHTML();
+ }
+
+}
+
+/**
+ * DIV Element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLDiv extends cHTML {
+
+ /**
+ * Constructor. Creates an HTML Div element.
+ *
+ * @param $content mixed String or object with the contents
+ */
+ function __construct($content = "") {
+ parent::__construct();
+ $this->setContent($content);
+ $this->setContentlessTag(false);
+ $this->_tag = "div";
+ }
+
+ /**
+ * setContent: Sets the div's content
+ *
+ * @param $content string/object String with the content or an object to render.
+ */
+ function setContent($content) {
+ $this->_setContent($content);
+ }
+
+ /**
+ * Renders the DIV element
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ return parent::toHTML();
+ }
+
+}
+
+/**
+ * SPAN Element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLSpan extends cHTML {
+
+ /**
+ * Constructor. Creates an HTML Span element.
+ *
+ * @param $content mixed String or object with the contents
+ */
+ function __construct($content = "") {
+ parent::__construct();
+ $this->setContent($content);
+ $this->setContentlessTag(false);
+ $this->_tag = "span";
+ }
+
+ /**
+ * setContent: Sets the div's content
+ *
+ * @param $content string/object String with the content or an object to render.
+ */
+ function setContent($content) {
+ $this->_setContent($content);
+ }
+
+ /**
+ * Renders the SPAN element
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes) . $this->_content . $this->fillCloseSkeleton();
+ }
+
+}
+
+/**
+ * Image Element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLImage extends cHTML {
+
+ /**
+ * Image source
+ * @var string
+ * @access private
+ */
+ var $_src;
+
+ /**
+ * Image width
+ * @var int
+ * @access private
+ */
+ var $_width;
+
+ /**
+ * Image height
+ * @var int
+ * @access private
+ */
+ var $_height;
+
+ /**
+ * Constructor. Creates an HTML IMG element.
+ *
+ * @param $content mixed String or object with the contents
+ *
+ */
+ function __construct($src = NULL) {
+ parent::__construct();
+
+ $this->_tag = "img";
+ $this->setContentlessTag();
+
+ $this->setBorder(0);
+ $this->setSrc($src);
+ }
+
+ /**
+ * setSrc: Sets the image's source file
+ *
+ * @param $src string source location
+ *
+ */
+ function setSrc($src) {
+ if ($src === NULL) {
+ $this->_src = "images/spacer.gif";
+ } else {
+ $this->_src = $src;
+ }
+ }
+
+ /**
+ * setWidth: Sets the image's width
+ *
+ * @param $width int Image width
+ *
+ */
+ function setWidth($width) {
+ $this->_width = $width;
+ }
+
+ /**
+ * setHeight: Sets the image's height
+ *
+ * @param $height int Image height
+ *
+ */
+ function setHeight($height) {
+ $this->_height = $height;
+ }
+
+ /**
+ * setBorder: Sets the border size
+ *
+ * @param $border int Border size
+ *
+ */
+ function setBorder($border) {
+ $this->_border = $border;
+ }
+
+ function setAlignment($alignment) {
+ $this->updateAttributes(array("align" => $alignment));
+ }
+
+ /**
+ * applyDimensions: Apply dimensions from the source image
+ *
+ * @param none
+ *
+ */
+ function applyDimensions() {
+ global $cfg;
+
+ /* Try to open the image */
+ list ($width, $height) = @ getimagesize($cfg['path']['contenido'] . $this->_src);
+
+ if (!empty($width) && !empty($height)) {
+ $this->_width = $width;
+ $this->_height = $height;
+ }
+ }
+
+ /**
+ * Renders the IMG element
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ $this->updateAttributes(array("src" => $this->_src));
+
+ if (!empty($this->_width)) {
+ $this->updateAttributes(array("width" => $this->_width));
+ }
+
+ if (!empty($this->_height)) {
+ $this->updateAttributes(array("height" => $this->_height));
+ }
+
+ //$this->updateAttributes(array ("border" => $this->_border));
+
+ return parent::toHTML();
+ }
+
+}
+
+/**
+ * Table Element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLTable extends cHTML {
+
+ function __construct() {
+ parent::__construct();
+
+ $this->_tag = "table";
+ $this->setContentlessTag(false);
+ $this->setPadding(0);
+ $this->setSpacing(0);
+ $this->setBorder(0);
+ }
+
+ /**
+ * setContent: Sets the table's content
+ *
+ * @param $content string/object String with the content or an object to render.
+ *
+ */
+ function setContent($content) {
+ $this->_setContent($content);
+ }
+
+ /**
+ * setCellSpacing: Sets the spacing between cells
+ *
+ * @param $cellspacing Spacing
+ *
+ */
+ function setCellSpacing($cellspacing) {
+ $this->updateAttributes(array("cellspacing" => $cellspacing));
+ }
+
+ function setPadding($cellpadding) {
+ $this->setCellPadding($cellpadding);
+ }
+
+ function setSpacing($cellspacing) {
+ $this->setCellSpacing($cellspacing);
+ }
+
+ /**
+ * setCellPadding: Sets the padding between cells
+ *
+ * @param $cellpadding Padding
+ *
+ */
+ function setCellPadding($cellpadding) {
+ $this->updateAttributes(array("cellpadding" => $cellpadding));
+ }
+
+ /**
+ * setBorder: Sets the table's border
+ *
+ * @param border Border size
+ *
+ */
+ function setBorder($border) {
+ $this->updateAttributes(array("border" => $border));
+ }
+
+ /**
+ * setWidth: Sets the table width
+ *
+ * @param $width Width
+ *
+ */
+ function setWidth($width) {
+ $this->updateAttributes(array("width" => $width));
+ }
+
+ /**
+ * Renders the Table element
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ return parent::toHTML();
+ }
+
+}
+
+/**
+ * Table Body Element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLTableBody extends cHTML {
+
+ function __construct() {
+ parent::__construct();
+ $this->setContentlessTag(false);
+ $this->_tag = "tbody";
+ }
+
+ /**
+ * setContent: Sets the table body's content
+ *
+ * @param $content string/object String with the content or an object to render.
+ *
+ */
+ function setContent($content) {
+ $this->_setContent($content);
+ }
+
+ /**
+ * Renders the table body element
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ return parent::toHTML();
+ }
+
+}
+
+/**
+ * Table Row Element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLTableRow extends cHTML {
+
+ function __construct() {
+ parent::__construct();
+ $this->setContentlessTag(false);
+ $this->_tag = "tr";
+ }
+
+ /**
+ * setContent: Sets the table row's content
+ *
+ * @param $content string/object String with the content or an object to render.
+ *
+ */
+ function setContent($content) {
+ $this->_setContent($content);
+ }
+
+ /**
+ * Renders the table row element
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ return parent::toHTML();
+ }
+
+}
+
+/**
+ * Table Data Element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLTableData extends cHTML {
+
+ function __construct() {
+ parent::__construct();
+ $this->setContentlessTag(false);
+ $this->_tag = "td";
+ }
+
+ /**
+ * setWidth: Sets the table width
+ *
+ * @param $width Width
+ *
+ */
+ function setWidth($width) {
+ $this->updateAttributes(array("width" => $width));
+ }
+
+ function setHeight($height) {
+ $this->updateAttributes(array("height" => $height));
+ }
+
+ function setAlignment($alignment) {
+ $this->updateAttributes(array("align" => $alignment));
+ }
+
+ function setVerticalAlignment($alignment) {
+ $this->updateAttributes(array("valign" => $alignment));
+ }
+
+ function setBackgroundColor($color) {
+ $this->updateAttributes(array("bgcolor" => $color));
+ }
+
+ function setColspan($colspan) {
+ $this->updateAttributes(array("colspan" => $colspan));
+ }
+
+ /**
+ * setContent: Sets the table data's content
+ *
+ * @param $content string/object String with the content or an object to render.
+ *
+ */
+ function setContent($content) {
+ $this->_setContent($content);
+ }
+
+ /**
+ * Renders the table data element
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes) . $this->_content . $this->fillCloseSkeleton();
+ }
+
+}
+
+/**
+ * Table Head Element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLTableHead extends cHTML {
+
+ function __construct() {
+ parent::__construct();
+ $this->setContentlessTag(false);
+ $this->_tag = "th";
+ }
+
+ /**
+ * setContent: Sets the table head's content
+ *
+ * @param $content string/object String with the content or an object to render.
+ *
+ */
+ function setContent($content) {
+ $this->_setContent($content);
+ }
+
+ /**
+ * Renders the table head element
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes) . $this->_content . $this->fillCloseSkeleton();
+ }
+
+}
+
+/**
+ * Table Head Element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLTableHeader extends cHTML {
+
+ function __construct() {
+ parent::__construct();
+ $this->setContentlessTag(false);
+ $this->_tag = "thead";
+ }
+
+ /**
+ * setContent: Sets the table head's content
+ *
+ * @param $content string/object String with the content or an object to render.
+ *
+ */
+ function setContent($content) {
+ $this->_setContent($content);
+ }
+
+ /**
+ * Renders the table head element
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes) . $this->_content . $this->fillCloseSkeleton();
+ }
+
+}
+
+/**
+ * IFrame element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLIFrame extends cHTML {
+
+ function __construct() {
+ parent::__construct();
+ $this->setContentlessTag(false);
+ $this->_tag = "iframe";
+ }
+
+ /**
+ * setSrc: Sets this frame's source
+ *
+ * @param $content string/object String with the content or an object to render.
+ *
+ */
+ function setSrc($src) {
+ $this->updateAttributes(array("src" => $src));
+ }
+
+ /**
+ * setWidth: Sets this frame's width
+ *
+ * @param $width Width of the item
+ *
+ */
+ function setWidth($width) {
+ $this->updateAttributes(array("width" => $width));
+ }
+
+ /**
+ * setHeight: Sets this frame's height
+ *
+ * @param $height Height of the item
+ *
+ */
+ function setHeight($height) {
+ $this->updateAttributes(array("height" => $height));
+ }
+
+ /**
+ * setBorder: Sets wether this iframe should have a border or not
+ *
+ * @param $border If 1 or true, this frame will have a border
+ *
+ */
+ function setBorder($border) {
+ $this->updateAttributes(array("frameborder" => intval($border)));
+ }
+
+ /**
+ * Renders the table head element
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes) . $this->_content . $this->fillCloseSkeleton();
+ }
+
+}
+
+class cHTMLAlignmentTable extends cHTMLTable {
+
+ function __construct() {
+ parent::__construct();
+
+ $this->_data = func_get_args();
+ $this->setContentlessTag(false);
+ }
+
+ function render() {
+ $tr = new cHTMLTableRow;
+ $td = new cHTMLTableData;
+
+ $out = "";
+
+ foreach ($this->_data as $data) {
+ $td->setContent($data);
+ $out .= $td->render();
+ }
+
+ $tr->setContent($out);
+
+ $this->setContent($tr);
+
+ return $this->toHTML();
+ }
+
+}
+
+class cHTMLForm extends cHTML {
+
+ function __construct() {
+ parent::__construct();
+ $this->setContentlessTag(false);
+ $this->_tag = "form";
+ }
+
+ function setVar($var, $value) {
+ $this->_vars[$var] = $value;
+ }
+
+ /**
+ * setContent: Sets the form's content
+ *
+ * @param $content string/object String with the content or an object to render.
+ *
+ */
+ function setContent($content) {
+ $this->_setContent($content);
+ }
+
+ /**
+ * Renders the form element
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ $out = '';
+ foreach ($this->_vars as $var => $value) {
+ $f = new cHTMLHiddenField($var, $value);
+ $out .= $f->render();
+ }
+
+ $attributes = $this->getAttributes(true);
+
+ return $this->fillSkeleton($attributes) . $out . $this->_content . $this->fillCloseSkeleton();
+ }
+
+}
+
+/**
+ * Table Head Element
+ *
+ * @author Timo A. Hummel
+ */
+class cHTMLScript extends cHTML {
+
+ function __construct() {
+ parent::__construct();
+ $this->setContentlessTag(false);
+ $this->_tag = "script";
+ }
+
+ /**
+ * setContent: Sets the table head's content
+ *
+ * @param $content string/object String with the content or an object to render.
+ *
+ */
+ function setContent($content) {
+ $this->_setContent($content);
+ }
+
+ /**
+ * Renders the table head element
+ *
+ * @param none
+ * @return string Rendered HTML
+ */
+ function toHTML() {
+ $attributes = $this->getAttributes(true);
+ return $this->fillSkeleton($attributes) . $this->_content . $this->fillCloseSkeleton();
+ }
+
+}
+
+?>
diff --git a/conlite/classes/class.htmlparser.php b/conlite/classes/class.htmlparser.php
new file mode 100644
index 0000000..abba85e
--- /dev/null
+++ b/conlite/classes/class.htmlparser.php
@@ -0,0 +1,329 @@
+iHtmlText = $aHtmlText;
+ $this->iHtmlTextLength = strlen($aHtmlText);
+ }
+
+ /**
+ * Method parse.
+ * Parses the next node. Returns false only if
+ * the end of the HTML text has been reached.
+ * Updates values of iNode* fields.
+ */
+ function parse() {
+ $text = $this->skipToElement();
+ if ($text != "") {
+ $this->iNodeType = NODE_TYPE_TEXT;
+ $this->iNodeName = "Text";
+ $this->iNodeValue = $text;
+ return true;
+ }
+ return $this->readTag();
+ }
+
+ function clearAttributes() {
+ $this->iNodeAttributes = array();
+ }
+
+ function readTag() {
+ if ($this->currentChar() != "<") {
+ $this->iNodeType = NODE_TYPE_DONE;
+ return false;
+ }
+ $this->skipInTag ("<");
+ $this->clearAttributes();
+ $name = $this->skipToBlanksInTag();
+ $pos = strpos($name, "/");
+ if ($pos === 0) {
+ $this->iNodeType = NODE_TYPE_ENDELEMENT;
+ $this->iNodeName = substr ($name, 1);
+ $this->iNodeValue = "";
+ }
+ else {
+ if (!$this->isValidTagIdentifier ($name)) {
+ $comment = false;
+ if ($name == "!--") {
+ $rest = $this->skipToStringInTag ("-->");
+ if ($rest != "") {
+ $this->iNodeType = NODE_TYPE_COMMENT;
+ $this->iNodeName = "Comment";
+ $this->iNodeValue = "<" . $name . $rest;
+ $comment = true;
+ }
+ }
+ if (!$comment) {
+ $this->iNodeType = NODE_TYPE_TEXT;
+ $this->iNodeName = "Text";
+ $this->iNodeValue = "<" . $name;
+ }
+ return true;
+ }
+ else {
+ $this->iNodeType = NODE_TYPE_ELEMENT;
+ $this->iNodeValue = "";
+ $nameLength = strlen($name);
+ if ($nameLength > 0 && substr($name, $nameLength - 1, 1) == "/") {
+ $this->iNodeName = substr($name, 0, $nameLength - 1);
+ }
+ else {
+ $this->iNodeName = $name;
+ }
+ }
+ }
+ while ($this->skipBlanksInTag()) {
+ $attrName = $this->skipToBlanksOrEqualsInTag();
+ if ($attrName != "") {
+ $this->skipBlanksInTag();
+ if ($this->currentChar() == "=") {
+ $this->skipEqualsInTag();
+ $this->skipBlanksInTag();
+ $value = $this->readValueInTag();
+ $this->iNodeAttributes[strtolower($attrName)] = $value;
+ }
+ else {
+ $this->iNodeAttributes[strtolower($attrName)] = "";
+ }
+ }
+ }
+ $this->skipEndOfTag();
+ return true;
+ }
+
+ function isValidTagIdentifier ($name) {
+ return preg_match('/[A-Za-z0-9]+/', $name);
+ }
+
+ function skipBlanksInTag() {
+ return "" != ($this->skipInTag (array (" ", "\t", "\r", "\n" )));
+ }
+
+ function skipToBlanksOrEqualsInTag() {
+ return $this->skipToInTag (array (" ", "\t", "\r", "\n", "=" ));
+ }
+
+ function skipToBlanksInTag() {
+ return $this->skipToInTag (array (" ", "\t", "\r", "\n" ));
+ }
+
+ function skipEqualsInTag() {
+ return $this->skipInTag (array ( "=" ));
+ }
+
+ function readValueInTag() {
+ $ch = $this->currentChar();
+ $value = "";
+ if ($ch == "\"") {
+ $this->skipInTag (array ( "\"" ));
+ $value = $this->skipToInTag (array ( "\"" ));
+ $this->skipInTag (array ( "\"" ));
+ }
+ else if ($ch == "\'") {
+ $this->skipInTag (array ( "\'" ));
+ $value = $this->skipToInTag (array ( "\'" ));
+ $this->skipInTag (array ( "\'" ));
+ }
+ else {
+ $value = $this->skipToBlanksInTag();
+ }
+ return $value;
+ }
+
+ function currentChar() {
+ if ($this->iHtmlTextIndex >= $this->iHtmlTextLength) {
+ return -1;
+ }
+ return $this->iHtmlText{$this->iHtmlTextIndex};
+ }
+
+ function moveNext() {
+ if ($this->iHtmlTextIndex < $this->iHtmlTextLength) {
+ $this->iHtmlTextIndex++;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ function skipEndOfTag() {
+ $sb = "";
+ if (($ch = $this->currentChar()) !== -1) {
+ $match = ($ch == ">");
+ if (!$match) {
+ return $sb;
+ }
+ $sb .= $ch;
+ $this->moveNext();
+ }
+ return $sb;
+ }
+
+ function skipInTag ($chars) {
+ $sb = "";
+ while (($ch = $this->currentChar()) !== -1) {
+ if ($ch == ">") {
+ return $sb;
+ } else {
+ $match = false;
+ for ($idx = 0; $idx < count($chars); $idx++) {
+ if ($ch == $chars[$idx]) {
+ $match = true;
+ break;
+ }
+ }
+ if (!$match) {
+ return $sb;
+ }
+ $sb .= $ch;
+ $this->moveNext();
+ }
+ }
+ return $sb;
+ }
+
+ function skipToInTag ($chars) {
+ $sb = "";
+ while (($ch = $this->currentChar()) !== -1) {
+ $match = $ch == ">";
+ if (!$match) {
+ for ($idx = 0; $idx < count($chars); $idx++) {
+ if ($ch == $chars[$idx]) {
+ $match = true;
+ break;
+ }
+ }
+ }
+ if ($match) {
+ return $sb;
+ }
+ $sb .= $ch;
+ $this->moveNext();
+ }
+ return $sb;
+ }
+
+ function skipToElement() {
+ $sb = "";
+ while (($ch = $this->currentChar()) !== -1) {
+ if ($ch == "<") {
+ return $sb;
+ }
+ $sb .= $ch;
+ $this->moveNext();
+ }
+ return $sb;
+ }
+
+ /**
+ * Returns text between current position and $needle,
+ * inclusive, or "" if not found. The current index is moved to a point
+ * after the location of $needle, or not moved at all
+ * if nothing is found.
+ */
+ function skipToStringInTag ($needle) {
+ $pos = strpos ($this->iHtmlText, $needle, $this->iHtmlTextIndex);
+ if ($pos === false) {
+ return "";
+ }
+ $top = $pos + strlen($needle);
+ $retvalue = substr ($this->iHtmlText, $this->iHtmlTextIndex, $top - $this->iHtmlTextIndex);
+ $this->iHtmlTextIndex = $top;
+ return $retvalue;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.htmlvalidator.php b/conlite/classes/class.htmlvalidator.php
new file mode 100644
index 0000000..905bb42
--- /dev/null
+++ b/conlite/classes/class.htmlvalidator.php
@@ -0,0 +1,214 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-07-02, Frederic Schneider, add security fix
+ *
+ * $Id: class.htmlvalidator.php 312 2014-06-18 11:01:08Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class cHTMLValidator
+{
+
+ var $doubleTags;
+ var $htmlParser;
+ var $html;
+ var $nestingLevel;
+ var $iNodeName;
+ var $nestingNodes;
+ var $_existingTags;
+
+ function cHTMLValidator()
+ {
+ $this->doubleTags = array ("form", "head", "body", "html", "td", "tr", "table", "a", "tbody", "title", "container", "span", "div");
+
+ $this->nestingLevel = array ();
+ $this->missingNodes = array ();
+ $this->nestingNodes = array ();
+ $this->_existingTags = array ();
+
+ }
+
+ function cleanHTML($html)
+ {
+
+ // remove all php code from layout
+ $resultingHTML = preg_replace('/<\?(php)?((.)|(\s))*?\?>/i', '', $html);
+
+ /* We respect only \n, but we need to take care of windows (\n\r) and other systems (\r) */
+ $resultingHTML = str_replace("\r\n", "\n", $resultingHTML);
+ $resultingHTML = str_replace("\r", "\n", $resultingHTML);
+
+ return $resultingHTML;
+
+ }
+
+ function validate($html)
+ {
+ $nestingLevel = 0;
+
+ /* Clean up HTML first from any PHP scripts, and clean up line breaks */
+ $this->html = $this->cleanHTML($html);
+
+ $htmlParser = new HtmlParser($this->html);
+
+ while ($htmlParser->parse())
+ {
+ $this->_existingTags[] = $htmlParser->iNodeName;
+ /* Check if we found a double tag */
+ if (in_array($htmlParser->iNodeName, $this->doubleTags))
+ {
+ if (!array_key_exists($htmlParser->iNodeName, $this->nestingLevel))
+ {
+ $this->nestingLevel[$htmlParser->iNodeName] = 0;
+ }
+
+ if (!array_key_exists($htmlParser->iNodeName, $this->nestingNodes))
+ {
+ $this->nestingNodes[$htmlParser->iNodeName][intval($this->nestingLevel[$htmlParser->iNodeName])] = array ();
+ }
+
+ /* Check if it's a start tag */
+ if ($htmlParser->iNodeType == NODE_TYPE_ELEMENT)
+ {
+
+ /* Push the current element to the stack, remember ID and Name, if possible */
+ $nestingLevel ++;
+
+ $this->nestingNodes[$htmlParser->iNodeName][intval($this->nestingLevel[$htmlParser->iNodeName])]["name"] = $htmlParser->iNodeAttributes["name"];
+ $this->nestingNodes[$htmlParser->iNodeName][intval($this->nestingLevel[$htmlParser->iNodeName])]["id"] = $htmlParser->iNodeAttributes["id"];
+ $this->nestingNodes[$htmlParser->iNodeName][intval($this->nestingLevel[$htmlParser->iNodeName])]["level"] = $nestingLevel;
+ $this->nestingNodes[$htmlParser->iNodeName][intval($this->nestingLevel[$htmlParser->iNodeName])]["char"] = $htmlParser->iHtmlTextIndex;
+ $this->nestingLevel[$htmlParser->iNodeName]++;
+ }
+
+ if ($htmlParser->iNodeType == NODE_TYPE_ENDELEMENT)
+ {
+ /* Check if we've an element of this type on the stack */
+ if ($this->nestingLevel[$htmlParser->iNodeName] > 0)
+ {
+ unset ($this->nestingNodes[$htmlParser->iNodeName][$this->nestingLevel[$htmlParser->iNodeName]]);
+ $this->nestingLevel[$htmlParser->iNodeName]--;
+
+ if ($this->nestingNodes[$htmlParser->iNodeName][intval($this->nestingLevel[$htmlParser->iNodeName])]["level"] != $nestingLevel)
+ {
+ /* Todo: Check for the wrong nesting level */
+ }
+
+ $nestingLevel --;
+
+ }
+ }
+ }
+ }
+
+ /* missingNodes should be an empty array by default */
+ $this->missingNodes = array ();
+
+ /* Collect all missing nodes */
+ foreach ($this->nestingLevel as $key => $value)
+ {
+ /* One or more missing tags found */
+ if ($value > 0)
+ {
+ /* Step trough all missing tags */
+ for ($i = 0; $i < $value; $i ++)
+ {
+ $node = $this->nestingNodes[$key][$i];
+
+ list ($line, $char) = $this->getLineAndCharPos($node["char"]);
+ $this->missingNodes[] = array ("tag" => $key, "id" => $node["id"], "name" => $node["name"], "line" => $line, "char" => $char);
+
+ $this->missingTags[$line][$char] = true;
+ }
+ }
+ }
+
+ }
+
+ function tagExists($tag)
+ {
+ if (in_array($tag, $this->_existingTags))
+ {
+ return true;
+ } else
+ {
+ return false;
+ }
+ }
+
+ function returnErrorMap()
+ {
+ $html .= "";
+
+ $chunks = explode("\n", $this->html);
+
+ foreach ($chunks as $key => $value)
+ {
+ $html .= ($key +1)." ";
+
+ for ($i = 0; $i < strlen($value); $i ++)
+ {
+ $char = substr($value, $i, 1);
+
+ if (is_array($this->missingTags[$key +1]))
+ {
+ //echo ($key+1) . " ". $i." ";
+ if (array_key_exists($i +2, $this->missingTags[$key +1]))
+ {
+ $html .= "".clHtmlSpecialChars($char)." ";
+ } else
+ {
+ $html .= clHtmlSpecialChars($char);
+ }
+ } else
+ {
+ $html .= clHtmlSpecialChars($char);
+ }
+
+ }
+
+ $html .= " ";
+
+ }
+
+ return $html;
+ }
+
+ function getLineAndCharPos($charpos)
+ {
+ $mangled = substr($this->html, 0, $charpos);
+
+ $line = substr_count($mangled, "\n") + 1;
+ $char = $charpos -strrpos($mangled, "\n");
+
+ return array ($line, $char);
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.httpinputvalidator.php b/conlite/classes/class.httpinputvalidator.php
new file mode 100644
index 0000000..24cfa66
--- /dev/null
+++ b/conlite/classes/class.httpinputvalidator.php
@@ -0,0 +1,297 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * @TODO: Some features are the same as in Contenido_Security (see contenido/classes/class.security.php),
+ * merge them...
+ *
+ * {@internal
+ * created 2008-02-06
+ * modified 2008-06-10, I. van Peeren, initially set $this->bLog as $bLog in config file
+ * modified 2008-07-02, Frederic Schneider, add security fix
+ *
+ * $Id: class.httpinputvalidator.php 312 2014-06-18 11:01:08Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+#### FORMAT CONSTANTS ####
+define('CON_CHECK_INTEGER', '/^[0-9]*$/'); // integer value
+define('CON_CHECK_PRIMITIVESTRING', '/^[a-zA-Z0-9 -_]*$/'); // simple string
+define('CON_CHECK_STRING', '/^[\w0-9 -_]*$/'); // more complex string
+define('CON_CHECK_HASH32', '/^[a-zA-Z0-9]{32}$/'); // 32-character hash
+
+
+/**
+ * This class is the extended version of excelent
+ * code made by kummer.
+ *
+ * @version 1.0.1
+ * @see http://contenido.org/forum/viewtopic.php?p=113492#113492
+ */
+class HttpInputValidator {
+
+ /**
+ * Associative array with available POST parameter name as
+ * key and flag whether this parameter is "clean" or not.
+ *
+ * @var array
+ */
+ var $aPostVariables = array();
+
+ /**
+ * Path and filename of logfile
+ *
+ * @var string
+ */
+ var $sLogPath = '';
+
+ /**
+ * Flag whether to write log or not.
+ *
+ * @var boolean
+ */
+ var $bLog = false;
+
+ /**
+ * Path to config file.
+ *
+ * @var string
+ */
+ var $sConfigPath = '';
+
+ /**
+ * Array with all possible parameters and parameter formats.
+ * Structure has to be:
+ *
+ *
+ * $check['GET']['param1'] = VALIDATE_FORMAT;
+ * $check['POST']['param2'] = VALIDATE_FORMAT;
+ *
+ *
+ * Possible formats are defined as constants in top of these class file.
+ *
+ * @var array
+ */
+ var $aCheck = array();
+
+ /**
+ * Contains first invalid parameter name.
+ *
+ * @var string
+ */
+ var $sFailure = '';
+
+ /**
+ * Current mode
+ *
+ * @var string
+ */
+ var $sMode = 'training';
+
+ /**
+ * Constructor
+ *
+ * Configuration path $sConfigPath is mandatory and has to contain the complete
+ * path to configuration file with defined parameters.
+ *
+ * The class provides two modes: training and arcade.
+ * Training mode only logs violations - if log path is given into log file otherwise
+ * as comment into HTML output. Arcade mode is made for killing - every violation will
+ * cause an hard exit!
+ *
+ * @param string $sConfigPath
+ * @return HttpInputValidator
+ */
+ function HttpInputValidator($sConfigPath) {
+ // check config and logging path
+ if (!empty($sConfigPath) && file_exists($sConfigPath)) {
+ $this->sConfigPath = realpath($sConfigPath);
+ } else {
+ die ('Could not load HttpInputValidator configuration! (invalid path)');
+ }
+
+ // include configuration
+ require ($this->sConfigPath);
+
+ // if custom config exists, include it also here
+ if (file_exists(dirname($this->sConfigPath) . '/config.http_check.local.php')) {
+ require (dirname($this->sConfigPath) . '/config.http_check.local.php');
+ }
+
+ $this->bLog = $bLog;
+
+ if ($this->bLog === true) {
+ if (!empty($sLogPath) && is_writable(dirname($sLogPath))) {
+ $this->sLogPath = realpath($sLogPath);
+ } else {
+ die ('Could not log into not existing or empty log path!');
+ }
+ }
+
+ $this->aCheck = $aCheck;
+
+ // run GET check
+ if ($this->checkGetParams()) {
+ // logging is needed in both modes, training and arcade
+ $this->logHackTrial();
+
+ // stops here in case of arcade mode
+ if ($sMode == 'arcade') {
+ ob_end_clean();
+ die ('Parameter check failed! (' . $this->sFailure . ')');
+ }
+ }
+
+ // check POST params for further processings
+ $this->checkPostParams();
+ }
+
+ /**
+ * Checks all GET params and returns true in case of a violation, otherwise false.
+ *
+ * @return bool
+ */
+ function checkGetParams () {
+ $bResult = false;
+
+ foreach ($_GET as $sKey => $mValue) {
+ if (!$this->checkParameter('GET', $sKey, $mValue)) {
+ $this->sFailure = $sKey;
+ $bResult = true;
+ break;
+ }
+ }
+
+ return $bResult;
+ }
+
+ /**
+ * Fills status-array $aPostVariables. Is POST-param known and valid mapped value is true.
+ *
+ */
+ function checkPostParams () {
+ foreach ($_POST as $sKey => $mValue) {
+ $this->aPostVariables[$sKey] = ($this->checkParameter('POST', $sKey, $mValue)) ? (true) : (false);
+ }
+ }
+
+ /**
+ * This method checks parameter of type $sType (currently GET and POST
+ * are supported) and name $sKey has valid value $mValue. In this case or
+ * in case of unknown but empty params, the method will also return true.
+ *
+ * @param string $sType
+ * @param string $sKey
+ * @param mixed $mValue
+ * @return bool
+ */
+ function checkParameter ($sType, $sKey, $mValue) {
+ $bResult = false;
+
+ if (in_array(strtoupper($sType), array('GET', 'POST'))) {
+ if (!isset($this->aCheck[$sType][$sKey]) && (is_null($mValue) || empty($mValue))) {
+ // if unknown but empty the value is unaesthetic but ok
+ $bResult = true;
+ } elseif (isset($this->aCheck[$sType][$sKey])) {
+ // parameter is known, check it...
+ $bResult = preg_match($this->aCheck[$sType][$sKey], $mValue);
+ }
+ }
+
+ return $bResult;
+ }
+
+ /**
+ * Tries to log date, remote ip and the requested URI into log file.
+ */
+ function logHackTrial() {
+ if ($this->bLog === true && !empty($this->sLogPath)) {
+ if (($rLogFile = @fopen($this->sLogPath, 'a')) !== false) {
+ fwrite($rLogFile, date('Y-m-d H:i:s'));
+ fwrite($rLogFile, ' ');
+ fwrite($rLogFile, $_SERVER['REMOTE_ADDR'] . str_repeat(' ', 17 - strlen($_SERVER['REMOTE_ADDR'])));
+ fwrite($rLogFile, $_SERVER['QUERY_STRING']);
+ fwrite($rLogFile, "\n");
+ fclose($rLogFile);
+ }
+ } elseif ($this->sMode == 'training') {
+ echo "\n VIOLATION: URL contains invalid or undefined paramaters! URL: '" .
+ clHtmlEntities($_SERVER['QUERY_STRING']) . "' \n";
+ }
+ }
+
+ /**
+ * Print html comment or returns (depending on flag $bReturn) all POST params.
+ *
+ * @return string
+ */
+ function showPosts($bReturn = false) {
+ $sResult = '';
+
+ foreach ($_POST as $sKey => $sValue) {
+ $sResult .= $key . ": ";
+
+ if (is_null($this->isRegularPost($sKey))) {
+ $sResult .= "not defined";
+ } else
+ if ($this->isRegularPost($key) === false) {
+ $sResult .= "iregular";
+ } else {
+ $sResult .= "ok";
+ }
+ $sResult .= "\n";
+ }
+
+ if ($bReturn === false) {
+ $sResult = "\n\n\n\n";
+ echo $sResult;
+ } else {
+ return $sResult;
+ }
+ }
+
+ /**
+ * Checks POST param $sKey is unknown (result is null), known but invalid (result is false)
+ * or it is known and valid (result is true).
+ *
+ * @param string $sKey
+ * @return mixed
+ */
+ function isRegularPost($sKey) {
+ $mResult = null;
+
+ if (isset ($this->postVariable[$sKey])) {
+ $mResult = $this->postVariable[$sKey];
+ }
+
+ return $mResult;
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.input.helper.php b/conlite/classes/class.input.helper.php
new file mode 100644
index 0000000..4755fca
--- /dev/null
+++ b/conlite/classes/class.input.helper.php
@@ -0,0 +1,215 @@
+setDefault(self::$_aOptions['default']);
+ }
+
+ $sSelectScript = '';
+
+ // reset static options array
+ self::_setDefaultOptions();
+ return self::$_oSelectElement->render() . $sSelectScript;
+ }
+
+ static public function getFileSelect($sName) {
+ global $cCurrentModule;
+ if(is_null(self::$_aOptions)) {
+ self::_setDefaultOptions();
+ }
+ self::$_oSelectElement = new cHTMLSelectElement($sName);
+ if(empty(self::$_aOptions['file_select_dir'])) {
+ $sDir = cRegistry::getClientConfig(cRegistry::getClientId())['path']['frontend'].'templates';
+ } else {
+ $sDir = self::$_aOptions['file_select_dir'];
+ }
+
+ $aFiles = scanDirectory($sDir);
+ $aModFiles = array();
+
+ // add template files in mod dir if present
+ if(null !== cRegistry::getConfigValue('dceModEdit','use') && cRegistry::getConfigValue('dceModEdit','use') == TRUE) {
+ //echo "modul: ".$cCurrentModule;
+ $oModule = new cApiModule($cCurrentModule);
+ if($oModule->isLoaded() && $oModule->isLoadedFromFile('input')) {
+ $sModTplPath = $oModule->getModulePath()."template";
+ if(is_dir($sModTplPath)) {
+ $aModFiles = scanDirectory($sModTplPath);
+ //print_r($aModFiles);
+ $aFiles = array_merge($aFiles, $aModFiles);
+ }
+ }
+ }
+ //echo '';
+ //print_r($aFiles);
+
+ $oOption = new cHTMLOptionElement("--Please Choose--", 0);
+ self::$_oSelectElement->addOptionElement(0, $oOption);
+
+ foreach($aFiles as $iKey=>$sFilePath) {
+ $aParts = pathinfo($sFilePath);
+ if(!in_array($aParts['extension'], self::$_aOptions['file_extension'])) {
+ continue;
+ }
+ if($aParts['dirname'] == $sDir) {
+ $oOption = new cHTMLOptionElement($aParts['basename'], $aParts['basename']);
+ } else {
+ $oOption = new cHTMLOptionElement("Mod: ".$aParts['basename'], $aParts['basename']);
+ }
+ self::$_oSelectElement->addOptionElement($iKey+1, $oOption);
+ //print_r($aParts);
+ }
+ if (isset(self::$_aOptions['default'])) {
+ self::$_oSelectElement->setDefault(self::$_aOptions['default']);
+ }
+
+ $sSelectScript = '';
+
+ // reset static options array
+ self::_setDefaultOptions();
+ return self::$_oSelectElement->render().$sSelectScript;
+ }
+
+ static public function getOnOffButton($sName) {
+ global $cnumber;
+ $oDiv = new cHTMLDiv();
+ $oDiv->setID($oDiv->getID()."C".$cnumber);
+ $sInput = "";
+ $aValues = array(
+ 'false' => mi18n("OFF"),
+ 'true' => mi18n("ON")
+ );
+ $oInput = new cHTMLRadiobutton($sName, "not set");
+
+ foreach ($aValues as $sValue => $sLabel) {
+ $oInput->advanceID();
+ $oInput->setLabelText($sLabel);
+ $oInput->setAttribute("value", $sValue);
+ if (self::$_aOptions['default'] == $sValue) {
+ $oInput->setChecked(TRUE);
+ } else {
+ $oInput->setChecked(FALSE);
+ }
+
+ $sInput .= $oInput->render();
+ }
+ $sInput .= '';
+
+
+ $oDiv->setContent($sInput);
+ return $oDiv->render();
+ }
+
+ static public function setOptions(array $aOptions) {
+ self::_setDefaultOptions();
+ self::$_aOptions = array_merge(self::$_aOptions, $aOptions);
+ }
+
+ static protected function _addCategories() {
+
+ $oDB = new DB_ConLite();
+
+ $sSQL = "SELECT tblCat.idcat AS idcat, tblCatLang.name AS name, "
+ . "tblCatLang.visible AS visible, tblCatLang.public AS public, tblCatTree.level AS level "
+ . "FROM " . cRegistry::getConfigValue('tab', 'cat')
+ . " AS tblCat, " . cRegistry::getConfigValue('tab', 'cat_lang') . " AS tblCatLang, "
+ . cRegistry::getConfigValue('tab', 'cat_tree') . " AS tblCatTree"
+ . " WHERE tblCat.idclient = '" . Contenido_Security::escapeDB(cRegistry::getClientId(), $oDB) . "'"
+ . " AND tblCatLang.idlang = '" . Contenido_Security::escapeDB(cRegistry::getLanguageId(), $oDB) . "'"
+ . " AND tblCatLang.idcat = tblCat.idcat AND tblCatTree.idcat = tblCat.idcat ";
+
+ if (self::$_aOptions['max_level'] > 0) {
+ $sSQL .= "AND tblCatTree.level < '" . Contenido_Security::escapeDB(self::$_aOptions['max_level'], $oDB) . "' ";
+ }
+ $sSQL .= "ORDER BY tblCatTree.idtree";
+
+ $oDB->query($sSQL);
+
+ $iCount = (int) $oDB->num_rows();
+ if ($iCount > 0) {
+ $iCountOptions = count(self::$_oSelectElement->_options);
+
+ while ($oDB->next_record()) {
+ $sSpaces = "";
+ $sStyle = "";
+ $iID = $oDB->f("idcat");
+
+ for ($i = 0; $i < $oDB->f("level"); $i++) {
+ $sSpaces .= " ";
+ }
+
+ // Generate new option element
+ if ((self::$_aOptions['cat_visible'] && $oDB->f("visible") == 0) ||
+ (self::$_aOptions['cat_public'] && $oDB->f("public") == 0)) {
+ // If category has to be visible or public and it isn't, don't add value
+ $sValue = "";
+ } else if (self::$_aOptions['with_articles']) {
+ // If article will be added, set negative idcat as value
+ $sValue = "-" . $iID;
+ } else {
+ // Show only categories - and everything is fine...
+ $sValue = $iID;
+ }
+ $oOption = new cHTMLOptionElement($sSpaces . "> " . utf8_encode($oDB->f("name")), $sValue);
+ if ((self::$_aOptions['cat_visible'] && $oDB->f("visible") == 0) ||
+ (self::$_aOptions['cat_public'] && $oDB->f("public") == 0)) {
+ $oOption->setDisabled(true);
+ }
+ // Coloring option element, restricted shows grey color
+ $oOption->setStyle("background-color: #EFEFEF");
+ if (self::$_aOptions['colored'] && ($oDB->f("visible") == 0 || $oDB->f("public") == 0)) {
+ $oOption->setStyle("color: #666666;");
+ }
+
+ // Add option element to the list
+ self::$_oSelectElement->addOptionElement($iCountOptions, $oOption);
+ /*
+ if ($bWithArt) {
+ $iArticles = $this->addArticles($iID, $bColored, self::$_aOptions['art_online'], $sSpaces);
+ $iCount += $iArticles;
+ } */
+ $iCountOptions++;
+ }
+ }
+ return $iCount;
+ }
+
+ static private function _setDefaultOptions() {
+ self::$_aOptions = array(
+ 'max_level' => 0,
+ 'default' => NULL,
+ 'colored' => FALSE,
+ 'cat_visible' => TRUE,
+ 'cat_public' => TRUE,
+ 'with_articles' => FALSE,
+ 'art_online' => TRUE,
+ 'file_select_dir' => NULL,
+ 'file_extension' => array('html')
+ );
+ }
+
+}
diff --git a/conlite/classes/class.inuse.php b/conlite/classes/class.inuse.php
new file mode 100644
index 0000000..7c7366f
--- /dev/null
+++ b/conlite/classes/class.inuse.php
@@ -0,0 +1,294 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * $Id: class.inuse.php 89 2012-06-05 08:18:09Z oldperl $:
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ * Class InUse
+ * Class for In-Use management
+ * @author Timo A. Hummel
+ * @todo Check and probably recode of behaviour with usage of an area-user-pointer or -hook
+ * @version 0.1
+ * @copyright four for business 2003
+ */
+class InUseCollection extends ItemCollection
+{
+ /**
+ * Constructor Function
+ * @param none
+ */
+ public function __construct()
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["inuse"], "idinuse");
+ $this->_setItemClass("InUseItem");
+ }
+
+ /**
+ * Marks a specific object as "in use". Note that
+ * items are released when the session is destroyed.
+ *
+ * Currently, the following types are defined and approved
+ * as internal Contenido standard:
+ * article
+ * module
+ * layout
+ * template
+ *
+ * @param $type string Specifies the type to mark.
+ * @param $objectid mixed Specifies the object ID
+ * @param $session string Specifies the session for which the "in use" mark is valid
+ * @param $user string Specifies the user which requested the in-use flag
+ */
+ public function markInUse($type, $objectid, $session, $user)
+ {
+ $type = Contenido_Security::escapeDB($type, null);
+ $objectid = Contenido_Security::escapeDB($objectid, null);
+ $session = Contenido_Security::escapeDB($session, null);
+ $user = Contenido_Security::escapeDB($user, null);
+
+ $this->select("type = '".$type."' AND objectid = '".$objectid."'");
+
+ if (!$this->next()) {
+ $newitem = parent::create();
+ $newitem->set("type", $type);
+ $newitem->set("objectid", $objectid);
+ $newitem->set("session", $session);
+ $newitem->set("userid", $user);
+ $newitem->store();
+ }
+ }
+
+ /**
+ * Removes the "in use" mark from a specific object.
+ *
+ * @param $type string Specifies the type to de-mark.
+ * @param $objectid mixed Specifies the object ID
+ * @param $session string Specifies the session for which the "in use" mark is valid
+ */
+ public function removeMark($type, $objectid, $session)
+ {
+ $type = Contenido_Security::escapeDB($type, null);
+ $objectid = Contenido_Security::escapeDB($objectid, null);
+ $session = Contenido_Security::escapeDB($session, null);
+
+ $this->select("type = '".$type."' AND objectid = '".$objectid."' AND session = '".$session."'");
+
+ if ($obj = $this->next()) {
+ // Extract the ID
+ $id = $obj->get("idinuse");
+
+ // Let's save memory
+ unset($obj);
+
+ // Remove entry
+ $this->delete($id);
+ }
+ }
+
+ /**
+ * Removes all marks for a specific type and session
+ *
+ * @param $type string Specifies the type to de-mark.
+ * @param $session string Specifies the session for which the "in use" mark is valid
+ */
+ public function removeTypeMarks($type, $session)
+ {
+ $type = Contenido_Security::escapeDB($type, null);
+ $session = Contenido_Security::escapeDB($session, null);
+
+ $this->select("type = '".$type."' AND session = '".$session."'");
+
+ while ($obj = $this->next()) {
+ // Extract the ID
+ $id = $obj->get("idinuse");
+
+ // Let's save memory
+ unset($obj);
+
+ // Remove entry
+ $this->delete($id);
+ }
+ }
+
+ /**
+ * Removes the mark for a specific item
+ *
+ * @param $type string Specifies the type to de-mark.
+ * @param $itemid string Specifies the item
+ */
+ public function removeItemMarks($type, $itemid)
+ {
+ $type = Contenido_Security::escapeDB($type, null);
+ $itemid = Contenido_Security::escapeDB($itemid, null);
+
+ $this->select("type = '".$type."' AND objectid = '".$itemid."'");
+
+ while ($obj = $this->next()) {
+ // Extract the ID
+ $id = $obj->get("idinuse");
+
+ // Let's save memory
+ unset($obj);
+
+ // Remove entry
+ $this->delete($id);
+ }
+ }
+
+ /**
+ * Removes all in-use marks for a specific session.
+ *
+ * @param $session string Specifies the session for which the "in use" marks should be removed
+ */
+ public function removeSessionMarks($session)
+ {
+ $session = Contenido_Security::escapeDB($session, null);
+ $this->select("session = '".$session."'");
+
+ while ($obj = $this->next()) {
+ // Extract the ID
+ $id = $obj->get("idinuse");
+
+ // Let's save memory
+ unset($obj);
+
+ // Remove entry
+ $this->delete($id);
+ }
+ }
+
+ /**
+ * Checks if a specific item is marked
+ *
+ * @param $type string Specifies the type to de-mark.
+ * @param $objectid mixed Specifies the object ID
+ * @return int Returns false if it's not in use or returns the object if it is.
+ */
+ public function checkMark($type, $objectid) {
+ /* @var $sess Contenido_Session */
+ global $sess;
+
+ $type = Contenido_Security::escapeDB($type, null);
+ $objectid = Contenido_Security::escapeDB($objectid, null);
+
+ $this->select("type = '".$type."' AND objectid = '".$objectid."'");
+
+ if ($obj = $this->next()) {
+ if($obj->get('session') != $sess->id) {
+ return ($obj);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks and marks if not marked.
+ *
+ * Example: Check for "idmod", also return a lock message:
+ * list($inUse, $message) = $col->checkAndMark("idmod", $idmod, true, i18n("Module is in use by %s (%s)"));
+ *
+ * Example 2: Check for "idmod", don't return a lock message
+ * $inUse = $col->checkAndMark("idmod", $idmod);
+ *
+ * @param $type string Specifies the type to de-mark.
+ * @param $objectid mixed Specifies the object ID
+ * @param $returnWarning boolean If true, also returns an error message if in use
+ * @param $warningTemplate string String to fill with the template
+ * (%s as placeholder, first %s is the username, second is the real name)
+ * @param $allowOverride boolean True if the user can override the lock
+ * @param $location string Value to append to the override lock button
+ * @return mixed If returnWarning is false, returns a boolean value wether the object is locked. If
+ * returnWarning is true, returns a 2 item array (boolean inUse, string errormessage).
+ */
+ public function checkAndMark($type, $objectid, $returnWarning = false, $warningTemplate = "", $allowOverride = false, $location = "")
+ {
+ global $sess, $auth, $notification, $area, $frame, $perm;
+
+ if (($obj = $this->checkMark($type, $objectid)) === false) {
+ $this->markInUse($type, $objectid, $sess->id, $auth->auth["uid"]);
+ $inUse = false;
+ $disabled = "";
+ $noti = "";
+ } else {
+ if ($returnWarning == true) {
+ $vuser = new User();
+ $vuser->loadUserByUserID($obj->get("userid"));
+ $inUseUser = $vuser->getField("username");
+ $inUseUserRealName = $vuser->getField("realname");
+
+ $message = sprintf($warningTemplate, $inUseUser, $inUseUserRealName);
+
+ if ($allowOverride == true && ($auth->auth["uid"] == $obj->get("userid") || $perm->have_perm())) {
+ $alt = i18n("Click here if you want to override the lock");
+
+ $link = $sess->url($location."&overridetype=".$type."&overrideid=".$objectid);
+
+ $warnmessage = i18n("Do you really want to override the lock?");
+ $script = "javascript:if (window.confirm('".$warnmessage."') == true) { window.location.href = '".$link."';}";
+ $override = '['.i18n("Override lock").'] ['.i18n("Hide notification").'] ';
+ } else {
+ $override = "";
+ }
+
+ if (!is_object($notification)) {
+ $notification = new Contenido_Notification;
+ }
+
+ $noti = $notification->messageBox("warning", $message.$override, 0);
+ $inUse = true;
+ }
+ }
+
+ if ($returnWarning == true) {
+ return (array($inUse, $noti));
+ } else {
+ return $inUse;
+ }
+ }
+}
+
+
+/**
+ * Class InUseItem
+ * Class for a single in-use item
+ * @author Timo A. Hummel
+ * @version 0.1
+ * @copyright four for business 2003
+ */
+class InUseItem extends Item
+{
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false)
+ {
+ global $cfg;
+ parent::__construct($cfg["tab"]["inuse"], "idinuse");
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.iterator.php b/conlite/classes/class.iterator.php
new file mode 100644
index 0000000..01e3932
--- /dev/null
+++ b/conlite/classes/class.iterator.php
@@ -0,0 +1,123 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ *
+ * $Id: class.iterator.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ * cIterator: A class which represents the C/C++/JAVA Iterator support.
+ *
+ * Iterating items is a mechanism to "step" trough a list of defined items.
+ * Basically, the iterator is similar to an array, but provides easy functions
+ * to step trough the list.
+ *
+ * An instance of an iterator is usually created by a class returning multiple
+ * items and automatically filled using the $aItems parameter of the constructor,
+ * and then returned to the caller.
+ *
+ * The caller receives the iterator object and can step trough all items using
+ * the "next" method.
+ *
+ * @todo Add more stepping methods, as well as retrieving items
+ *
+ */
+class cIterator
+{
+ /**
+ * Holds the items which should be iterated
+ * @var array
+ */
+ var $_aIteratorItems;
+
+ /**
+ * Iterator constructor
+ *
+ * This function initializes the constructor, adds the passed items
+ * and moves the iterator to the first element.
+ *
+ * @param $aItems array Items to add
+ * @return none
+ */
+ function cIterator ($aItems)
+ {
+ if (is_array($aItems))
+ {
+ $this->_aIteratorItems = $aItems;
+ } else {
+ $this->_aIteratorItems = array();
+ }
+
+ $this->reset();
+ }
+
+ /**
+ * reset: Resets the iterator to the first element
+ *
+ * This function moves the iterator to the first element
+ *
+ * @return none
+ */
+ function reset ()
+ {
+ reset($this->_aIteratorItems);
+ }
+
+ /**
+ * next: Returns the next item in the iterator
+ *
+ * This function returns the item, or false if no
+ * items are left.
+ *
+ * @return mixed item or false if nothing was found
+ */
+ function next ()
+ {
+ $item = each($this->_aIteratorItems);
+
+ if ($item === false)
+ {
+ return false;
+ } else {
+ return $item["value"];
+ }
+ }
+
+ /**
+ * count: Returns the number of items in the iterator
+ *
+ * @return int Number of items
+ */
+ function count ()
+ {
+ return count($this->_aIteratorItems);
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.lang.php b/conlite/classes/class.lang.php
new file mode 100644
index 0000000..a94ebf1
--- /dev/null
+++ b/conlite/classes/class.lang.php
@@ -0,0 +1,92 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created 2003-05-20
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting
+ *
+ * $Id: class.lang.php 123 2012-08-30 11:11:09Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ * Class Language
+ * Class for language collections
+ * @author Timo A. Hummel
+ * @deprecated since version 2.0.0 use cApiLanguageCollection instead
+ * @version 0.1
+ * @copyright four for business 2003
+ */
+class Languages extends cApiLanguageCollection {
+ /**
+ * Constructor
+ * @param none
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function Languages()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+}
+
+/**
+ * Class Language
+ * Class for a single language item
+ * @author Timo A. Hummel
+ * @version 0.1
+ * @deprecated since CL version 2.0.0 use cApiLanguage instead
+ * @copyright four for business 2003
+ */
+class Language extends cApiLanguage {
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false)
+ {
+ if($mId === false) {
+ parent::__construct();
+ } else {
+ parent::__construct($mId);
+ }
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function Language($mId = false)
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct($mId);
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.layout.php b/conlite/classes/class.layout.php
new file mode 100644
index 0000000..61af16e
--- /dev/null
+++ b/conlite/classes/class.layout.php
@@ -0,0 +1,192 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2008-07-02, Frederic Schneider, change sql-escapes
+ * modified 2009-10-27, OliverL, replace toInteger() to escapeString() in function getLayoutID()
+ *
+ * modified 2010-08-17, Munkh-Ulzii Balidar,
+ * - changed the code compatible to php5
+ * - added new property aUsedTemplates and saved the information of used templates
+ * - added new method getUsedTemplates
+ *
+ * $Id: class.layout.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class Layout {
+
+ private $aUsedTemplates = array();
+
+ /**
+ * Constructor Function
+ * @param
+ */
+ public function __construct()
+ {
+ ;// empty
+ } // end function
+
+ /**
+ * getAvailableLayouts()
+ * Returns all layouts available in the system
+ * @return array Array with id and name entries
+ */
+ public function getAvailableLayouts()
+ {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ idlay,
+ name
+ FROM
+ ". $cfg["tab"]["lay"];
+
+ $db->query($sql);
+
+ $layouts = array();
+
+ while ($db->next_record())
+ {
+
+ $newentry["name"] = $db->f("name");
+
+ $layouts[$db->f("idlay")] = $newentry;
+
+ }
+
+ return ($layouts);
+ } // end function
+
+ /**
+ * getLayoutName()
+ * Returns the name for a given layoutid
+ * @return string String with the name for the layout
+ */
+ public function getLayoutName($layout)
+ {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ name
+ FROM
+ ". $cfg["tab"]["lay"] ."
+ WHERE
+ idlay = '".Contenido_Security::toInteger($layout)."'";
+ $db->query($sql);
+ $db->next_record();
+
+ return ($db->f("name"));
+
+ } // end function
+
+ /**
+ * getLayoutID()
+ * Returns the idlayout for a given layout name
+ * @param $layout String with the Layoutname
+ * @return int Integer with the ID for the layout
+ */
+ public function getLayoutID($layout)
+ {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ idlay
+ FROM
+ ". $cfg["tab"]["lay"] ."
+ WHERE
+ name = '".Contenido_Security::escapeString($layout)."'";
+
+ $db->query($sql);
+ $db->next_record();
+
+ return ($db->f("idlay"));
+
+ } // end function
+
+
+ /**
+ * layoutInUse()
+ * Checks if the layout is in use
+ * @return bool Specifies if the layout is in use
+ */
+ public function layoutInUse($layout, $bSetData = false)
+ {
+ global $cfg;
+
+ if (!is_numeric($layout))
+ {
+ $layout = $this->getLayoutID($layout);
+ }
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ idtpl, name
+ FROM
+ ". $cfg["tab"]["tpl"] ."
+ WHERE
+ idlay = '".Contenido_Security::toInteger($layout)."'";
+
+ $db->query($sql);
+
+ if ($db->nf() == 0) {
+ return false;
+ } else {
+ $i = 0;
+ // save the datas of used templates in array
+ if ($bSetData === true) {
+ while ($db->next_record()) {
+ $this->aUsedTemplates[$i]['tpl_name'] = $db->f('name');
+ $this->aUsedTemplates[$i]['tpl_id'] = (int)$db->f('idtpl');
+ $i++;
+ }
+ }
+
+ return true;
+ }
+ } // end function
+
+ /**
+ * Get the informations of used templates
+ * @return array template data
+ */
+ public function getUsedTemplates()
+ {
+ return $this->aUsedTemplates;
+ }
+
+} // end class
+
+?>
diff --git a/conlite/classes/class.metaobject.php b/conlite/classes/class.metaobject.php
new file mode 100644
index 0000000..50f5d02
--- /dev/null
+++ b/conlite/classes/class.metaobject.php
@@ -0,0 +1,390 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ *
+ * $Id: class.metaobject.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/* Introduction to metaobjects
+ *
+ * A metaobject is an object which combines pure API objects with presentation logic.
+ * An API object contains API functions for doing actions or data manipulation in general.
+ *
+ * A metaobject can define the following things:
+ *
+ * - Map data objects to widgets
+ * - Map data into groups
+ * - Map actions (from the API objects) to visible actions
+ * - Map data fields with flags (searchable, sortable)
+ *
+ */
+
+define("CMETAOBJECT_BASE", 1);
+define("CMETAOBJECT_PLUGIN", 2);
+
+class cMetaObject
+{
+
+ /**
+ * Type of this plugin
+ * @var int Contains the object type
+ * @access private
+ */
+ var $_objectType;
+
+ /**
+ * Object icon
+ * @var string Icon filename
+ * @access private
+ */
+ var $_iconFilename;
+
+ var $_objectInvalid;
+
+ var $_payloadObject;
+
+ function cMetaObject ($payload = false)
+ {
+ $this->_actions = array();
+ $this->_fields = array();
+ $this->_objectInvalid = false;
+
+ $this->setPayloadObject($payload);
+ }
+
+ /**
+ * setObjectType ($type)
+ *
+ * Sets the object type (either COBJECT_BASE or COBJECT_PLUGIN).
+ *
+ * @param int $type Constant with the object type
+ *
+ */
+ function setObjectType ($type)
+ {
+ if ($type != COBJECT_BASE &&
+ $type != COBJECT_PLUGIN)
+ {
+ cDie(__FILE__, __LINE__, "When calling setObjectType, please use either COBJECT_BASE or COBJECT_PLUGIN");
+ }
+
+ $this->_objectType = $type;
+ }
+
+ /**
+ * setIcon ($icon)
+ * Defines the icon for this object
+ * @param string $icon Icon path
+ * @return none
+ */
+ function setIcon ($icon = false)
+ {
+ $icon = Contenido_Security::escapeDB($icon, null);
+ $this->_iconFilename = $icon;
+ }
+
+ /**
+ * getIcon ($icon)
+ * Returns the icon for this object
+ * @param string $icon Icon path
+ * @return none
+ */
+ function getIcon ()
+ {
+ return $this->_iconFilename;
+ }
+
+ function setPayloadObject ($object)
+ {
+ if (is_object($object))
+ {
+ $this->_payloadObject = $object;
+ $this->defineActions();
+ } else {
+ if (class_exists($object))
+ {
+ $this->_payloadObject = new $object;
+ $this->defineActions();
+ }
+ }
+ }
+
+ function getName ()
+ {
+ return;
+ }
+
+ function getDescription ()
+ {
+ return;
+ }
+
+ function defineActions ()
+ {
+ }
+
+ function assignField ($field, $name, $editwidget, $parameters = array(), $group = "default", $readonly = false)
+ {
+ if (!array_key_exists("default", $parameters))
+ {
+ $parameters["default"] = $this->_payloadObject->get($field);
+ $parameters["_payload"] = $this->_payloadObject;
+ }
+
+ $this->_fields[$group][$field]["name"] = $name;
+ $this->_fields[$group][$field]["editwidget"] = $editwidget;
+ $this->_fields[$group][$field]["readonly"] = $readonly;
+ $this->_fields[$group][$field]["parameters"] = $parameters;
+ }
+
+ function setEditAction ($actionclass)
+ {
+ $args = func_num_args();
+
+ unset($this->_editAction);
+
+ $this->_editAction = $actionclass;
+ $this->_editParams = array();
+
+ for ($i=1; $i< $args; $i++)
+ {
+ $this->_editParams[$i] = func_get_arg($i);
+ }
+ }
+
+ function setCreateAction ($actionclass)
+ {
+ $args = func_num_args();
+
+ unset($this->_createAction);
+
+ $this->_createAction = $actionclass;
+ $this->_createParams = array();
+
+ for ($i=1; $i< $args; $i++)
+ {
+ $this->_createParams[$i] = func_get_arg($i);
+ }
+ }
+
+
+ function addAction ($actionclass)
+ {
+ $args = func_num_args();
+
+ $this->_actions[$actionclass] = array();
+
+ for ($i=1; $i< $args; $i++)
+ {
+ $this->_actions[$actionclass][$i] = func_get_arg($i);
+ }
+ }
+
+ function defineFields ()
+ {
+ }
+
+ function defineEditAction ()
+ {
+ }
+
+ function defineCreateAction ()
+ {
+ }
+
+ function processActions ()
+ {
+ $reload = false;
+
+ $actions = $this->getActions();
+
+ if (is_array($actions))
+ {
+ foreach ($actions as $action)
+ {
+ if ($_GET["action"] == $action->_namedAction)
+ {
+
+ /* Collect parameters */
+ foreach ($action->_wantParameters as $parameter)
+ {
+ /* Mangle parameter */
+ if (get_magic_quotes_gpc())
+ {
+ $parameters[$parameter] = stripslashes($_GET[$parameter]);
+ } else {
+ $parameters[$parameter] = $_GET[$parameter];
+ }
+ }
+
+ foreach ($action->_parameters as $parameter => $value)
+ {
+ if (get_magic_quotes_gpc())
+ {
+ $parameters[$parameter] = stripslashes($_GET[$parameter]);
+ } else {
+ $parameters[$parameter] = $_GET[$parameter];
+ }
+ }
+
+ if ($action->process($parameters) == true)
+ {
+ $reload = true;
+ }
+
+ if ($action->_objectInvalid)
+ {
+ $this->_objectInvalid = true;
+ }
+ }
+
+ }
+ }
+
+ return $reload;
+ }
+
+ function processEdit ()
+ {
+ $this->defineFields();
+ $modified = false;
+ foreach ($this->_fields as $group)
+ {
+
+ foreach ($group as $field => $params)
+ {
+ $vname = get_class($this)."_".$field;
+ if (array_key_exists($vname, $_GET))
+ {
+ if (get_magic_quotes_gpc())
+ {
+ $this->_payloadObject->set($field, stripslashes($_GET[$vname]));
+ } else {
+ $this->_payloadObject->set($field, $_GET[$vname]);
+ }
+ $modified = true;
+ }
+ }
+ }
+
+ if ($modified == true)
+ {
+ $this->_payloadObject->store();
+ }
+ }
+
+ function processCreate ()
+ {
+ if ($this->_actionsDefined == false)
+ {
+ $this->defineActions();
+ $this->_actionsDefined = true;
+ }
+
+ /* Get create action */
+ $createaction = $this->getAction($this->_createAction);
+
+ if ($createaction != false)
+ {
+ if ($_GET["action"] == $createaction->_namedAction)
+ {
+ return $createaction->process();
+ }
+ }
+
+ }
+
+ function getActions ()
+ {
+ if ($this->_actionsDefined == false)
+ {
+ $this->defineActions();
+ $this->_actionsDefined = true;
+ }
+
+ foreach ($this->_actions as $action => $params)
+ {
+ $i = $this->getAction($action);
+
+ if ($i !== false)
+ {
+ $actions[] = $i;
+ }
+ }
+ return ($actions);
+ }
+
+ function getAction ($action)
+ {
+ if (!array_key_exists($action, $this->_actions))
+ {
+ if ($this->_editAction == $action)
+ {
+ $params = $this->_editParams;
+ } else {
+ if ($this->_createAction == $action)
+ {
+ $params = $this->_createParams;
+ } else {
+ return false;
+ }
+ }
+ } else {
+ $params = $this->_actions[$action];
+ }
+
+ $myparams = array();
+ if (!is_array($params))
+ {
+ $params = array();
+ }
+
+ foreach ($params as $param)
+ {
+ switch (gettype($param))
+ {
+ case "string" : $myparams[] = '"'.addslashes($param).'"'; break;
+ case "boolean": if ($param == true)
+ {
+ $myparams[] = "true";
+ } else {
+ $myparams[] = "false";
+ }
+ break;
+ default: $myparams[] = $param;
+ }
+ }
+ $statement = '$action = new '.$action."(".implode(", ",$myparams).");";
+ eval($statement);
+
+ return ($action);
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.navigation.php b/conlite/classes/class.navigation.php
new file mode 100644
index 0000000..eedb3b6
--- /dev/null
+++ b/conlite/classes/class.navigation.php
@@ -0,0 +1,441 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2008-07-08 Thorsten Granz, added option to disable menu hover effect. clicking is now possible again
+ * modified 2009-12-17, Dominik Ziegler, added support for username fallback and fixed double quote
+ * modified 2009-12-16 Corrected rendering of multiple apostrophes in anchors
+ * modified 2010-01-15, Dominik Ziegler, added frontend url to client name
+ * modified 2011-01-28, Dominik Ziegler, added check for client existance for link to frontend [#CON-378]
+ *
+ * $Id: class.navigation.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+cInclude('includes', 'functions.api.string.php');
+cInclude('includes', 'functions.api.images.php');
+
+
+/**
+ * Backend navigaton class. Renders the header navigation document containing the navigtion structure.
+ *
+ * @category Contenido
+ * @package Backend
+ * @subpackage Navigation
+ */
+class Contenido_Navigation {
+
+ /**
+ * Flag to debug this vlass
+ * @var bool
+ */
+ var $debug = 0;
+
+ /**
+ * Array storing all data
+ * @var array
+ */
+ var $data = array();
+
+
+ /**
+ * Constructor. Loads the XML language file using XML_Doc.
+ */
+ function Contenido_Navigation() {
+ global $cfg, $belang;
+
+ $this->xml = new XML_Doc();
+ $this->plugxml = new XML_Doc();
+
+ // Load language file
+ if ($this->xml->load($cfg['path']['xml'] . $cfg['lang'][$belang]) == false) {
+ if ($this->xml->load($cfg['path']['xml'] . 'lang_en_US.xml') == false) {
+ die('Unable to load any XML language file');
+ }
+ }
+ }
+
+
+ /**
+ * Extracts caption from the XML language file including plugins extended multilang version.
+ *
+ * @param string $location The location of navigation item caption. Feasible values are
+ * - "{xmlFilePath};{XPath}": Path to XML File and the XPath value
+ * separated by semicolon. This type is used
+ * to extract caption from a plugin XML file.
+ * - "{XPath}": XPath value to extract caption from Contenido XML file
+ * @return string The found caption
+ */
+ function getName($location) {
+ global $cfg, $belang;
+
+ # If a ";" is found entry is from a plugin -> explode location, first is xml file path,
+ # second is xpath location in xml file
+ if (strstr($location, ';')) {
+
+ $locs = explode(';', $location);
+ $file = trim($locs[0]);
+ $xpath = trim($locs[1]);
+
+ $filepath = explode('/', $file);
+ $counter = count($filepath)-1;
+
+ if ($filepath[$counter] == '') {
+ unset($filepath[$counter]);
+ $counter--;
+ }
+
+ if(strstr($filepath[$counter], '.xml')) {
+ $filename = $filepath[$counter];
+ unset($filepath[$counter]);
+ $counter--;
+ }
+
+ $filepath[($counter+1)] = '';
+
+ $filepath = implode('/', $filepath);
+
+ if ($this->plugxml->load($cfg['path']['plugins'] . $filepath . $cfg['lang'][$belang]) == false) {
+ if (!isset($filename)) {
+ $filename = 'lang_en_US.xml';
+ }
+ if ($this->plugxml->load($cfg['path']['plugins'] . $filepath . $filename) == false) {
+ die("Unable to load $filepath XML language file");
+ }
+ }
+ $caption = $this->plugxml->valueOf($xpath);
+
+ } else {
+ $caption = $this->xml->valueOf($location);
+ }
+
+ return $caption;
+ }
+
+
+ /**
+ * Reads and fills the navigation structure data
+ *
+ * @return void
+ */
+ function _buildHeaderData() {
+ global $cfg, $perm, $belang;
+
+ $db = new DB_ConLite();
+ $db2 = new DB_ConLite();
+
+ # Load main items
+ $sql = "SELECT idnavm, location FROM ".$cfg['tab']['nav_main']." ORDER BY idnavm";
+
+ $db->query($sql);
+
+ # Loop result and build array
+ while ($db->next_record()) {
+
+ # Extract names from the XML document.
+ $main = $this->getName($db->f('location'));
+
+ # Build data array
+ $this->data[$db->f('idnavm')] = array($main);
+
+ $sql = "SELECT
+ a.location AS location, b.name AS area, b.relevant
+ FROM
+ ".$cfg['tab']['nav_sub']." AS a, ".$cfg['tab']['area']." AS b
+ WHERE
+ a.idnavm = '".$db->f('idnavm')."' AND
+ a.level = '0' AND
+ b.idarea = a.idarea AND
+ a.online = '1' AND
+ b.online = '1'
+ ORDER BY
+ a.idnavs";
+
+ $db2->query($sql);
+
+ while ($db2->next_record()) {
+ $area = $db2->f('area');
+ if ($perm->have_perm_area_action($area) || $db2->f('relevant') == 0){
+ # Extract names from the XML document.
+ $name = $this->getName($db2->f('location'));
+ $this->data[$db->f('idnavm')][] = array($name, $area);
+ }
+ }
+
+ }
+
+ # debugging information
+ if ($this->debug) {
+ echo '' . print_r($this->data, true) . ' ';
+ }
+ }
+
+
+ /**
+ * Function to build the Contenido header document for backend
+ *
+ * @param int $lang The language to use for header doc creation
+ */
+ function buildHeader($lang) {
+
+ global $cfg, $sess, $client, $auth, $cfgClient;
+
+ $this->_buildHeaderData();
+
+ $main = new Template();
+ $sub = new Template();
+
+ $cnt = 0;
+ $t_sub = '';
+ $numSubMenus = 0;
+
+ $properties = new PropertyCollection();
+ $clientImage = $properties->getValue('idclient', $client, 'backend', 'clientimage', false);
+
+ $sJsEvents = '';
+ foreach ($this->data as $id => $item) {
+ $sub->reset();
+ $genSubMenu = false;
+
+ foreach ($item as $key => $value) {
+ if (is_array($value)) {
+ $sub->set('s', 'SUBID', 'sub_'.$id);
+
+ // create sub menu link
+ $link = new cHTMLLink();
+ $link->disableAutomaticParameterAppend();
+ $link->setClass('sub');
+ $link->setID('sub_' . $value[1]);
+ $link->setLink($sess->url('frameset.php?area=' . $value[1]));
+ $link->setTargetFrame('content');
+ $link->setContent($value[0]);
+
+ if ($cfg['help'] == true) {
+ $sJsEvents .= "\n\t" . '$("#sub_' . $value[1] . '").click(function(){ $("#help").attr("data", "'.$value[1].'"); });';
+ }
+ $sub->set('d', 'CAPTION', $link->render());
+
+ $sub->next();
+ $genSubMenu = true;
+ }
+ }
+
+ if ($genSubMenu == true) {
+ $link = new cHTMLLink();
+ $link->setClass('main');
+ $link->setID('main_' . $id);
+ $link->setLink('javascript://');
+ $link->setAttribute('ident', 'sub_' . $id);
+ $link->setContent($item[0]);
+
+ $main->set('d', 'CAPTION', $link->render());
+ $main->next();
+
+ $numSubMenus++;
+
+ } else {
+ # first entry in array is a main menu item
+ }
+
+ # generate a sub menu item.
+ $t_sub .= $sub->generate($cfg['path']['templates'] . $cfg['templates']['submenu'], true);
+ $cnt ++;
+ }
+
+ if ($cfg['help'] == true) {
+ $sJsEvents .= "\n\t" . 'help.setArea("mycontenido");';
+ }
+
+ if ($numSubMenus == 0) {
+ $main->set('d', 'CAPTION', ' ');
+ $main->next();
+ }
+
+ $main->set('s', 'SUBMENUS', $t_sub);
+
+ // my contenido link
+ $oMyConLink = new cHTMLLink();
+ $oMyConLink->setClass('main');
+ $oMyConLink->setTargetFrame('content');
+ $oMyConLink->attachEventDefinition('help_mycontenido', 'onclick', 'help.setArea("mycontenido")');
+ $oMyConLink->setLink($sess->url("frameset.php?area=mycontenido&frame=4"));
+ $oMyConLink->setContent(' ');
+ $main->set('s', 'MYCONTENIDO', $oMyConLink->render());
+
+ // info link
+ $oInfoLink = new cHTMLLink();
+ $oInfoLink->setClass('main');
+ $oInfoLink->setTargetFrame('content');
+ $oInfoLink->attachEventDefinition('help_info', 'onclick', 'help.setArea("info")');
+ $oInfoLink->setLink($sess->url('frameset.php?area=info&frame=4'));
+ $oInfoLink->setContent(' ');
+ $main->set('s', 'INFO', $oInfoLink->render());
+
+ $main->set('s', 'LOGOUT', $sess->url('logout.php'));
+
+ if ($cfg['help'] == true) {
+ // help link
+ $oHelpLink = new cHTMLLink();
+ $oHelpLink->setID('help');
+ $oHelpLink->setClass('main');
+ $oHelpLink->setLink('javascript://');
+ $oHelpLink->setEvent('click', 'callHelp($(\'#help\').attr(\'data\'));');
+ $oHelpLink->setContent(' ');
+ $main->set('s', 'HELP', $oHelpLink->render());
+ } else {
+ $main->set('s', 'HELP', '');
+ }
+
+ $classuser = new User();
+ $classclient = new Client();
+
+ if (getEffectiveSetting('system', 'clickmenu') == 'true') {
+ // set click menu
+ $main->set('s', 'HEADER_MENU_OBJ', 'HeaderClickMenu');
+ $main->set('s', 'HEADER_MENU_OPTIONS', '{menuId: "main_0", subMenuId: "sub_0"}');
+ } else {
+ // set delay menu
+ $mouseOver = getEffectiveSetting('system', 'delaymenu_mouseover', 300);
+ $mouseOot = getEffectiveSetting('system', 'delaymenu_mouseout', 1000);
+ $main->set('s', 'HEADER_MENU_OBJ', 'HeaderDelayMenu');
+ $main->set('s', 'HEADER_MENU_OPTIONS', '{menuId: "main_0", subMenuId: "sub_0", mouseOverDelay: '.$mouseOver.', mouseOutDelay: '.$mouseOot.'}');
+ }
+
+ $main->set('s', 'ACTION', $sess->url('index.php'));
+ $main->set('s', 'LANG', $this->_renderLanguageSelect());
+ $main->set('s', 'WIDTH', '');
+
+ $sClientName = $classclient->getClientName($client);
+ if (strlen($sClientName) > 25) {
+ $sClientName = capiStrTrimHard($sClientName, 25);
+ }
+
+ $client = Contenido_Security::toInteger($client);
+ if ( $client == 0 ) {
+ $sClientNameTemplate = '' . i18n("Client") . ': %s';
+ $main->set('s', 'CHOSENCLIENT', sprintf($sClientNameTemplate, $sClientName));
+ } else {
+ $sClientNameTemplate = '' . i18n("Client") . ': %s ';
+
+ $sClientName = $classclient->getClientName($client).' ('.$client.')';
+ $sClientUrl = $cfgClient[$client]["path"]["htmlpath"];
+
+ if ($clientImage !== false && $clientImage != "" && file_exists($cfgClient[$client]['path']['frontend'].$clientImage)) {
+ $sClientImageTemplate = ' ';
+
+ $sThumbnailPath = capiImgScale($cfgClient[$client]['path']['frontend'].$clientImage, 80, 25, 0, 1);
+ $sClientImageTag = sprintf($sClientImageTemplate, $sThumbnailPath, $sClientName, $sClientName);
+
+ $main->set('s', 'CHOSENCLIENT', sprintf($sClientNameTemplate, $sClientUrl, $sClientImageTag));
+ } else {
+ $main->set('s', 'CHOSENCLIENT', sprintf($sClientNameTemplate, $sClientUrl, $sClientName));
+ }
+ }
+
+ $main->set('s', 'CHOSENUSER', "".i18n("User").": ".$classuser->getRealname($auth->auth["uid"], true));
+ $main->set('s', 'SID', $sess->id);
+ $main->set('s', 'MAINLOGINLINK', $sess->url("frameset.php?area=mycontenido&frame=4"));
+
+ // additional footer javascript
+ $footerJs = '';
+ if ($sJsEvents !== '') {
+ $footerJs = '$(document).ready(function(){' . $sJsEvents . '});';
+ }
+ $main->set('s', 'FOOTER_JS', $footerJs);
+
+ $main->generate($cfg['path']['templates'] . $cfg['templates']['header']);
+ }
+
+
+ /**
+ * Renders the language select box
+ *
+ * @todo recode and remove direct sql calls
+ *
+ * @return string
+ */
+ function _renderLanguageSelect()
+ {
+ global $cfg, $client, $lang;
+
+ $tpl = new Template();
+
+ $tpl->set('s', 'NAME', 'changelang');
+ $tpl->set('s', 'CLASS', 'text_medium');
+ $tpl->set('s', 'ID', 'cLanguageSelect');
+ $tpl->set('s', 'OPTIONS', 'onchange="changeContenidoLanguage(this.value)"');
+
+ $availableLanguages = new cApiLanguageCollection();
+
+ if (getEffectiveSetting('system', 'languageorder', 'name') == 'name') {
+ $availableLanguages->select('', '', 'name ASC');
+ } else {
+ $availableLanguages->select('', '', 'idlang ASC');
+ }
+
+ $db = new DB_ConLite();
+
+ if ($availableLanguages->count() > 0) {
+ while ($myLang = $availableLanguages->nextAccessible()) {
+ $key = $myLang->get('idlang');
+ $value = $myLang->get('name');
+
+ // I want to get rid of such silly constructs very soon :)
+
+ $sql = "SELECT idclient FROM ".$cfg['tab']['clients_lang']." WHERE
+ idlang = '".Contenido_Security::toInteger($key)."'";
+
+ $db->query($sql);
+
+ if ($db->next_record()) {
+ if ($db->f('idclient') == $client) {
+ if ($key == $lang) {
+ $tpl->set('d', 'SELECTED', 'selected');
+ } else {
+ $tpl->set('d', 'SELECTED', '');
+ }
+
+ if (strlen($value) > 20) {
+ $value = capiStrTrimHard($value, 20);
+ }
+
+ $tpl->set('d', 'VALUE', $key);
+ $tpl->set('d', 'CAPTION', $value.' ('.$key.')');
+ $tpl->next();
+ }
+ }
+ }
+ } else {
+ $tpl->set('d', 'VALUE', 0);
+ $tpl->set('d', 'CAPTION', i18n('-- No Language available --'));
+ $tpl->next();
+ }
+
+ return $tpl->generate($cfg['path']['templates'] . $cfg['templates']['generic_select'], true);
+ }
+}
diff --git a/conlite/classes/class.note.php b/conlite/classes/class.note.php
new file mode 100644
index 0000000..123784f
--- /dev/null
+++ b/conlite/classes/class.note.php
@@ -0,0 +1,404 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2011-03-14, Murat Purc, adapted to new GenericDB partly ported to PHP 5, formatting
+ *
+ * $Id: class.note.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class NoteCollection extends CommunicationCollection
+{
+ public function __construct()
+ {
+ parent::__construct();
+ $this->_setItemClass("NoteItem");
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ function NoteCollection()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+
+ /**
+ * select: Selects one or more items from the database
+ *
+ * This function only extends the where statement. See the
+ * original function for the parameters.
+ *
+ * @access public
+ * @see ItemCollection
+ */
+ public function select($where = "", $group_by = "", $order_by = "", $limit = "")
+ {
+ if ($where == "") {
+ $where = "comtype='note'";
+ } else {
+ $where .= " AND comtype='note'";
+ }
+
+ return parent::select($where, $group_by, $order_by, $limit);
+ }
+
+ /**
+ * create: Creates a new note item.
+ *
+ * @param $itemtype string Item type (usually the class name)
+ * @param $itemid mixed Item ID (usually the primary key)
+ * @param $idlang int Language-ID
+ * @param $message string Message to store
+ *
+ * @return object The new item
+ * @access public
+ */
+ public function create($itemtype, $itemid, $idlang, $message, $category = "")
+ {
+ $item = parent::create();
+
+ $item->set("subject", "Note Item");
+ $item->set("message", $message);
+ $item->set("comtype", "note");
+ $item->store();
+
+ $item->setProperty("note", "itemtype", $itemtype);
+ $item->setProperty("note", "itemid", $itemid);
+ $item->setProperty("note", "idlang", $idlang);
+
+ if ($category != "") {
+ $item->setProperty("note", "category", $category);
+ }
+
+ return $item;
+ }
+
+}
+
+class NoteItem extends CommunicationItem
+{
+
+}
+
+
+class NoteView extends cHTMLIFrame
+{
+ public function NoteView($sItemType, $sItemId)
+ {
+ global $sess, $cfg;
+ cHTMLIFrame::cHTMLIFrame();
+ $this->setSrc($sess->url("main.php?itemtype=$sItemType&itemid=$sItemId&area=note&frame=2"));
+ $this->setBorder(0);
+ $this->setStyleDefinition("border", "1px solid ".$cfg['color']['table_border']);
+ }
+}
+
+
+class NoteList extends cHTMLDiv
+{
+ public function NoteList($sItemType, $sItemId)
+ {
+ cHTMLDiv::cHTMLDiv();
+
+ $this->_sItemType = $sItemType;
+ $this->_sItemId = $sItemId;
+
+ $this->setStyleDefinition("width", "100%");
+ }
+
+ public function setDeleteable($bDeleteable)
+ {
+ $this->_bDeleteable = $bDeleteable;
+ }
+
+ public function toHTML()
+ {
+ global $cfg, $lang;
+
+ $sItemType = $this->_sItemType;
+ $sItemId = $this->_sItemId;
+
+ $this->setStyleDefinition("background", $cfg['color']['table_light']);
+
+ $oPropertyCollection = new PropertyCollection;
+ $oPropertyCollection->select("itemtype = 'idcommunication' AND type = 'note' AND name = 'idlang' AND value = '$lang'");
+
+ $items = array();
+
+ while ($oProperty = $oPropertyCollection->next()) {
+ $items[] = $oProperty->get("itemid");
+ }
+
+ $oNoteItems = new NoteCollection;
+
+ if (count($items) == 0) {
+ $items[] = 0;
+ }
+
+ $oNoteItems->select("idcommunication IN (".implode(", ", $items).')',"", "created DESC");
+
+ $i = array();
+ $dark = false;
+ while ($oNoteItem = $oNoteItems->next()) {
+ if ($oNoteItem->getProperty("note", "itemtype") == $sItemType && $oNoteItem->getProperty("note", "itemid") == $sItemId) {
+ $j = new NoteListItem($sItemType, $sItemId, $oNoteItem->get("idcommunication"));
+ $j->setAuthor($oNoteItem->get("author"));
+ $j->setDate($oNoteItem->get("created"));
+ $j->setMessage($oNoteItem->get("message"));
+ $j->setBackground($dark);
+ $j->setDeleteable($this->_bDeleteable);
+
+ $dark = !$dark;
+
+ $i[] = $j;
+ }
+ }
+
+ $this->setContent($i);
+
+ $result = parent::toHTML();
+
+ return ('');
+ }
+}
+
+
+class NoteListItem extends cHTMLDiv
+{
+ public function NoteListItem($sItemType, $sItemId, $iDeleteItem)
+ {
+ cHTMLDiv::cHTMLDiv();
+ $this->setStyleDefinition("padding", "2px");
+ $this->setBackground();
+ $this->setDeleteable(true);
+
+ $this->_iDeleteItem = $iDeleteItem;
+ $this->_sItemType = $sItemType;
+ $this->_sItemId = $sItemId;
+
+ }
+
+ public function setDeleteable($bDeleteable)
+ {
+ $this->_bDeleteable = $bDeleteable;
+ }
+
+ public function setBackground($dark = false)
+ {
+ global $cfg;
+
+ if ($dark) {
+ $this->setStyleDefinition("background", $cfg['color']['table_dark']);
+ } else {
+ $this->setStyleDefinition("background", $cfg['color']['table_light']);
+ }
+ }
+
+ public function setAuthor($sAuthor)
+ {
+ if (strlen($sAuthor) == 32) {
+ $result = getGroupOrUserName($sAuthor);
+
+ if ($result !== false) {
+ $sAuthor = $result;
+ }
+ }
+
+ $this->_sAuthor = $sAuthor;
+ }
+
+ public function setDate($iDate)
+ {
+ $dateformat = getEffectiveSetting("backend", "timeformat", "Y-m-d H:i:s");
+
+ if (is_string($iDate)) {
+ $iDate = strtotime($iDate);
+ }
+ $this->_sDate = date($dateformat, $iDate);
+ }
+
+ public function setMessage($sMessage)
+ {
+ $this->_sMessage = $sMessage;
+ }
+
+ public function render()
+ {
+ global $cfg, $sess;
+
+ $itemtype = $this->_sItemType;
+ $itemid = $this->_sItemId;
+ $deleteitem = $this->_iDeleteItem;
+
+ $table = '';
+ $table .= $this->_sAuthor;
+ $table .= ' ';
+ $table .= $this->_sDate;
+
+ if ($this->_bDeleteable == true) {
+ $oDeleteable = new cHTMLLink();
+ $oDeletePic = new cHTMLImage($cfg["path"]["contenido_fullhtml"]."/images/delete.gif");
+ $oDeleteable->setContent($oDeletePic);
+ $oDeleteable->setLink($sess->url("main.php?frame=2&area=note&itemtype=$itemtype&itemid=$itemid&action=note_delete&deleteitem=$deleteitem"));
+
+ $table .= ' '.$oDeleteable->render();
+ }
+ $table .= '
';
+
+ $oMessage = new cHTMLDiv;
+ $oMessage->setContent($this->_sMessage);
+ $oMessage->setStyle("padding-bottom: 8px;");
+
+ $this->setContent(array($table, ' ',$oMessage));
+
+ return parent::render();
+ }
+
+}
+
+class NoteLink extends cHTMLLink
+{
+ /**
+ * @var string Object type
+ * @access private
+ */
+ private $_sItemType;
+
+ /**
+ * @var string Object ID
+ * @access private
+ */
+ private $_sItemID;
+
+ /**
+ * @var boolean If true, shows the note history
+ * @access private
+ */
+ private $_bShowHistory;
+
+ /**
+ * @var boolean If true, history items can be deleted
+ * @access private
+ */
+ private $_bDeleteHistoryItems;
+
+ /**
+ * NoteLink: Creates a new note link item.
+ *
+ * This link is used to show the popup from any position within the system.
+ * The link contains the note image.
+ *
+ * @param $sItemType string Item type (usually the class name)
+ * @param $sItemId mixed Item ID (usually the primary key)
+ *
+ * @return none
+ * @access public
+ */
+ public function NoteLink($sItemType, $sItemID)
+ {
+ parent::cHTMLLink();
+
+ $img = new cHTMLImage("images/note.gif");
+ $img->setStyle("padding-left: 2px; padding-right: 2px;");
+
+ $img->setAlt(i18n("View notes / add note"));
+ $this->setLink("#");
+ $this->setContent($img->render());
+ $this->setAlt(i18n("View notes / add note"));
+
+ $this->_sItemType = $sItemType;
+ $this->_sItemID = $sItemID;
+ $this->_bShowHistory = false;
+ $this->_bDeleteHistoryItems = false;
+ }
+
+ /**
+ * enableHistory: Enables the display of all note items
+ *
+ * @return none
+ * @access public
+ */
+ public function enableHistory()
+ {
+ $this->_bShowHistory = true;
+ }
+
+ /**
+ * disableHistory: Disables the display of all note items
+ *
+ * @return none
+ * @access public
+ */
+ public function disableHistory()
+ {
+ $this->_bShowHistory = false;
+ }
+
+ /**
+ * enableHistoryDelete: Enables the delete function in the history view
+ *
+ * @return none
+ * @access public
+ */
+ public function enableHistoryDelete()
+ {
+ $this->_bDeleteHistoryItems = true;
+ }
+
+ /**
+ * disableHistoryDelete: Disables the delete function in the history view
+ *
+ * @return none
+ * @access public
+ */
+ public function disableHistoryDelete()
+ {
+ $this->_bDeleteHistoryItems = false;
+ }
+
+ /**
+ * render: Renders the resulting link
+ *
+ * @return none
+ * @access public
+ */
+ public function render($return = false)
+ {
+ global $sess;
+
+ $itemtype = $this->_sItemType;
+ $itemid = $this->_sItemID;
+
+ $this->setEvent("click", 'javascript:window.open('."'".$sess->url("main.php?area=note&frame=1&itemtype=$itemtype&itemid=$itemid")."', 'todo', 'resizable=yes, scrollbars=yes, height=360, width=550');");
+ return parent::render($return);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.notification.php b/conlite/classes/class.notification.php
new file mode 100644
index 0000000..97be523
--- /dev/null
+++ b/conlite/classes/class.notification.php
@@ -0,0 +1,236 @@
+
+ * // render a error directly
+ * $oNotification = new Contenido_Notification();
+ * $oNotification->displayNotification(
+ * Contenido_Notification::LEVEL_ERROR, 'Foobar does not exists'
+ * );
+ *
+ * // assign a notification to a variable
+ * $oNotification = new Contenido_Notification();
+ * $sNotification = $oNotification->displayNotification(
+ * Contenido_Notification::LEVEL_NOTIFICATION, 'Hey dude, you did it!'
+ * );
+ *
+ *
+ * Requirements:
+ * @con_php_req 5.0
+ *
+ *
+ * @package Contenido Backend classes
+ * @version 1.1.0
+ * @author Timo A. Hummel
+ * @copyright four for business AG
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-04-04, Timo Trautmann, added new colors and functions for direct output
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2011-05-19, Murat Purc, adapted to PHP 5, formatted and documented code
+ *
+ * $Id: class.notification.php 75 2012-05-25 10:51:00Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class Contenido_Notification
+{
+ /**
+ * Error message level
+ * @var string
+ */
+ const LEVEL_ERROR = 'error';
+
+ /**
+ * Warning message level
+ * @var string
+ */
+ const LEVEL_WARNING = 'warning';
+
+ /**
+ * Info message level
+ * @var string
+ */
+ const LEVEL_INFO = 'info';
+
+ /**
+ * Notification message level
+ * @var string
+ */
+ const LEVEL_NOTIFICATION = 'notification';
+
+ /**
+ * Colors configuration
+ * @var array
+ */
+ protected $_aColors;
+
+ /**
+ * HTML path to images
+ * @var string
+ */
+ protected $_sPathImages;
+
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ global $cfg;
+ $this->_aColors = $cfg['color'];
+ $this->_sPathImages = $cfg['path']['contenido_fullhtml'] . $cfg['path']['images'];
+ }
+
+ /**
+ * Generates message box and returns it back.
+ *
+ * @param string $sLevel Message level, one of Contenido_Notification::LEVEL_* constants
+ * @param string $sMessage The message to display
+ * @param int $iStyle Flag tp use styles for display or not (feasible 1 or 0)
+ * @return string
+ */
+ public function messageBox($sLevel, $sMessage, $iStyle = 1)
+ {
+ switch ($sLevel) {
+ case self::LEVEL_ERROR:
+ $sHead = i18n('Error');
+ $sHeadClass = 'alertbox_error';
+ $frameColor = $this->_aColors['notify_error'];
+ $sImgPath = $this->_sPathImages . 'icon_fatalerror.gif';
+ break;
+ case self::LEVEL_WARNING:
+ $sHead = i18n('Warning');
+ $sHeadClass = 'alertbox_warning';
+ $sBgColor = $this->_aColors['notify_warning'];
+ $sImgPath = $this->_sPathImages . 'icon_warning.gif';
+ break;
+ case self::LEVEL_INFO:
+ $sHead = i18n('Info');
+ $sHeadClass = 'alertbox_info';
+ $sMessage = '' . $sMessage . ' ';
+ $sBgColor = $this->_aColors['notify_info'];
+ $sImgPath = $this->_sPathImages . 'but_ok.gif';
+ break;
+ default:
+ $sHead = i18n('Notification');
+ $sHeadClass = 'alertbox_notification';
+ $sMessage = '' . $sMessage . ' ';
+ $sBgColor = $this->_aColors['notify'];
+ $sImgPath = $this->_sPathImages . 'but_ok.gif';
+ break;
+ }
+
+ if ($iStyle == 1) {
+ // Box on login page
+ $sMessageBox =
+ '' .
+ '
' . $sHead . ' ' .
+ '
' . $sMessage . '
' .
+ '
';
+ } else {
+ // Simple box
+ $sMessageBox =
+ '' .
+ '
' . $sHead . ' ' .
+ '
' . $sMessage . '
' .
+ '
';
+ }
+ return $sMessageBox;
+ }
+
+
+ /**
+ * Generates message box and returns it back, uses markup with table.
+ *
+ * @param string $sLevel Message level, one of Contenido_Notification::LEVEL_* constants
+ * @param string $sMessage The message to display
+ * @return string
+ */
+ public function returnNotification($sLevel, $sMessage)
+ {
+ switch ($sLevel) {
+ case self::LEVEL_ERROR:
+ $sBgColor = $this->_aColors['notify_error'];
+ $sImgPath = $this->_sPathImages . 'icon_fatalerror.gif';
+ break;
+ case self::LEVEL_WARNING:
+ $sBgColor = $this->_aColors['notify_warning'];
+ $sImgPath = $this->_sPathImages . 'icon_warning.gif';
+ break;
+ case self::LEVEL_INFO:
+ $sMessage = '' . $sMessage . ' ';
+ $sBgColor = $this->_aColors['notify_info'];
+ $sImgPath = $this->_sPathImages . 'but_ok.gif';
+ break;
+ default:
+ $sMessage = ''.$sMessage.' ';
+ $sBgColor = $this->_aColors['notify'];
+ $sImgPath = $this->_sPathImages . 'but_ok.gif';
+ break;
+ }
+
+ $oTable = new Table($sBgColor, 'solid', 0, 2, '#FFFFFF', '#FFFFFF', '#FFFFFF', true, false);
+
+ $sNoti = '';
+ $sNoti .= $oTable->start_table();
+ $sNoti .= $oTable->header_row();
+ $sNoti .= $oTable->borderless_cell('
');
+ $sNoti .= $oTable->borderless_cell(
+ '
' . $sMessage . ' ', 'left', 'middle'
+ );
+ $sNoti .= $oTable->end_row();
+ $sNoti .= $oTable->end_table();
+ $sNoti .= '
';
+
+ return $sNoti;
+ }
+
+
+ /**
+ * Displays small message box directly.
+ *
+ * @param string $sLevel Message level, one of Contenido_Notification::LEVEL_* constants
+ * @param string $sMessage The message to display
+ * @return void
+ */
+ public function displayNotification($sLevel, $sMessage)
+ {
+ echo $this->returnNotification($sLevel, $sMessage) . ' ';
+ }
+
+
+ /**
+ * Displays large message box directly.
+ *
+ * @param string $sLevel Message level, one of Contenido_Notification::LEVEL_* constants
+ * @param string $sMessage The message to display
+ * @param int $iStyle Flag tp use styles for display or not (feasible 1 or 0)
+ * @return void
+ */
+ public function displayMessageBox($sLevel, $sMessage, $iStyle = 1)
+ {
+ echo $this->messageBox($sLevel, $sMessage, $iStyle) . ' ';
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.output_compressor.php b/conlite/classes/class.output_compressor.php
new file mode 100644
index 0000000..61ea86a
--- /dev/null
+++ b/conlite/classes/class.output_compressor.php
@@ -0,0 +1,217 @@
+
+ * @license http://www.conlite.org/license/LIZENZ.txt
+ * @link http://www.conlite.org
+ * @since file available since ConLite release 2.0.0
+ *
+ * {@internal
+ * created 2012-12-15
+ *
+ * $Id: class.output_compressor.php 261 2013-04-13 09:57:24Z Mansveld $:
+ * }}
+ *
+ */
+
+/**
+ * Class for creating and outputing only one compressed file
+ */
+abstract class Output_Compressor {
+
+ /**
+ * Worker-Function generate()
+ *
+ * @param string $sCachePath - Path to the cache folder
+ * @param array string $asFiles - Files to include in the compressed output file
+ * @return string - Returns the name of the compressed file in the cache folder
+ * @access public
+ */
+ public function generate($sCachePath, $asFiles, $sFileExt, $sFrontendPath) {
+
+ # Check for input files
+ if ((!is_array($asFiles)) || (!count($asFiles))) {
+ return false;
+ }
+
+ $lastCacheTime = 0;
+ $lastChangeTime = 0;
+
+ # Generate a unique filename for the compressed file
+ $md5 = md5(implode('', $asFiles));
+
+ # Check if a file with this name exists in the cache folder
+ $found = self::findMatchingFilenames($sCachePath, strtolower($sFileExt), $md5);
+ if ($found !== false) {
+ # Matching files were found, check which one ist the latest one
+ for ($i = 0, $n = count($found); $i < $n; $i ++) {
+ $time = substr($found[$i], strlen($md5), 14);
+ if ($time > $lastCacheTime) {
+ $lastCacheTime = $time;
+ }
+ }
+ }
+
+ # Get the date and time of the last modified input file
+ for ($i = 0, $n = count($asFiles); $i < $n; $i ++) {
+ if (file_exists($asFiles[$i])) {
+ $time = date('YmdHis', filemtime($asFiles[$i]));
+ if ($time > $lastChangeTime) {
+ $lastChangeTime = $time;
+ }
+ }
+ }
+
+ if ($lastCacheTime == $lastChangeTime) {
+ # If the cache file has the date and time of the last changed file, just return it's name
+ return $md5 . $lastCacheTime . '.' . $sFileExt;
+ } else {
+ # Create new cache files
+ $content = '';
+
+ # Read the input files
+ for ($i = 0, $n = count($asFiles); $i < $n; $i ++) {
+ if (file_exists($asFiles[$i])) {
+ $cnt = file_get_contents($asFiles[$i]);
+ # Remove file include commands (those files were added to the array or HTML head section)
+ if (strrpos($asFiles[$i], '/') > 0) {
+ $path = substr($asFiles[$i], 0, (strrpos($asFiles[$i], '/') + 1));
+ } else {
+ $path = '';
+ }
+ $p1 = strpos(strtolower($cnt), '@import url(');
+ while ($p1 !== false) {
+ $p2 = strpos($cnt, ');', $p1);
+ $cnt = substr($cnt, 0, $p1) . substr($cnt, ($p2 + 2));
+ $p1 = strpos(strtolower($cnt), '@import url(');
+ }
+
+ $content .= $cnt . "\n";
+ }
+ }
+
+ # Compress the content
+ switch ($sFileExt) {
+ case 'css':
+ # Remove '/* ... */' comments
+ $content = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $content);
+
+ # Convert line breaks and tabs to a single space
+ $content = str_replace(array("\r\n", "\r", "\n", "\t"), ' ', $content);
+
+ # Convert multiple spaces to a single space
+ while (strpos($content, ' ') !== false) {
+ $content = str_replace(' ', ' ', $content);
+ }
+
+ # Remove preceding and trailing spaces
+ $content = trim($content);
+
+ # Correct paths starting with '../' to start with the client HTML path
+ $content = str_replace(array('../../', '../'), $sFrontendPath, $content);
+
+ break;
+ case 'js':
+ # Convert tabs to a single space
+ $content = str_replace("\t", ' ', $content);
+
+ # Convert multiple spaces to a single space
+ while (strpos($content, ' ') !== false) {
+ $content = str_replace(' ', ' ', $content);
+ }
+
+ # Remove blank lines
+ $content = str_replace(array("\r\n\r\n", "\r\r", "\n\n"), "\n", $content);
+
+ # Remove preceding and trailing spaces from each line and
+ $aCnt = explode("\n", $content);
+ for ($i = 0, $n = count($aCnt); $i < $n; $i ++) {
+ $aCnt[$i] = trim($aCnt[$i]);
+ }
+ $content = implode("\n", $aCnt);
+
+ # Remove remaining blank lines
+ while (strpos($content, "\n\n") !== false) {
+ $content = str_replace("\n\n", "\n", $content);
+ }
+
+ break;
+ }
+
+ # Save a new uncompressed cache file, use date and time of the last modified file in the filename
+ $fp = fopen($sCachePath . $md5 . $lastChangeTime . '.' . $sFileExt, 'w');
+ fwrite($fp, $content);
+ fclose($fp);
+
+ if (extension_loaded('zlib')) {
+ # Save a new compressed cache file, use date and time of the last modified file in the filename
+ $fp = fopen($sCachePath . $md5 . $lastChangeTime . '.' . $sFileExt . '.gz', 'w');
+ fwrite($fp, gzencode($content, 6, FORCE_GZIP));
+ fclose($fp);
+ }
+
+ # Delete all older versions of the cache file
+ for ($i = 0, $n = count($found); $i < $n; $i ++) {
+ @unlink($sCachePath . $found[$i]);
+ @unlink($sCachePath . $found[$i] . '.gz');
+ }
+
+ # Return the name of the new cache file
+ return $md5 . $lastChangeTime . '.' . $sFileExt;
+ }
+ }
+
+ /**
+ * Worker-Function output()
+ *
+ * @param string $sCachePath - Path to the cache folder
+ * @param string $sFilename - Name of the file to deliver
+ * @param string $sContentType - Content-Type of the file (eg 'css', 'html' or 'javascript')
+ */
+ public function output($sCachePath, $sFilename, $sContentType) {
+ header('Content-Type: text/' . $sContentType);
+ if ((strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) && (extension_loaded('zlib')) && (is_file($sCachePath . $sFilename . '.gz')) && (!ini_get('zlib.output_compression'))) {
+ header('Content-Length: ' . filesize($sCachePath . $sFilename . '.gz'));
+ header('Content-Encoding: gzip');
+ readfile($sCachePath . $sFilename . '.gz');
+ } else {
+ header('Content-Length: ' . filesize($sCachePath . $sFilename));
+ readfile($sCachePath . $sFilename);
+ }
+ }
+
+ /**
+ * private helper function findMatchingFilenames()
+ *
+ * @param string $sCachePath - Path to the cache folder
+ * @param string $sFileExt - filename extension (eg css)
+ * @param string $sFilenamePart - Beginning part of the filename
+ * @return - Returns an array of the matching files found or false
+ * @access private
+ */
+ private function findMatchingFilenames($sCachePath, $sFileExt, $sFilenamePart) {
+ $pattern = '[0123456789]';
+ # Find only files with 14 numerical characters in the filename (yyyymmddHHiiss)
+ $files = glob($sCachePath . $sFilenamePart . str_repeat($pattern, 14) . '.' . $sFileExt);
+ if (empty($files)) {
+ # No suiting filename was found
+ return false;
+ } else {
+ # Return the filenames of the found files
+ return array_map('basename', $files);
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.phpmailer.php b/conlite/classes/class.phpmailer.php
new file mode 100644
index 0000000..5c41166
--- /dev/null
+++ b/conlite/classes/class.phpmailer.php
@@ -0,0 +1,32 @@
+
\ No newline at end of file
diff --git a/conlite/classes/class.properties.php b/conlite/classes/class.properties.php
new file mode 100644
index 0000000..a8a7584
--- /dev/null
+++ b/conlite/classes/class.properties.php
@@ -0,0 +1,501 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created 2003-12-21
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2009-09-27, Dominik Ziegler, fixed wrong (un)escaping
+ * modified 2011-02-05, Murat Purc, cleanup, formatting and documentation.
+ * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting
+ *
+ * $Id: class.properties.php 2M 2016-07-22 10:48:29Z (local) $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+/* Custom properties
+ * -----------------
+ *
+ * Custom properties are properties which can be assigned to virtually any element
+ * in Contenido and underlaying websites.
+ *
+ *
+ * Table structure
+ * ---------------
+ *
+ * Field Size Description
+ * ----- ---- -----------
+ * idproperty int(10) idproperty (automatically handled by this class)
+ * itemtype varchar(32) Custom item type (e.g. idcat, idart, idartlang, custom)
+ * itemid varchar(32) ID of the item
+ * type varchar(32) Property type
+ * name varchar(32) Property name
+ * value text Property value
+ * author varchar(32) Author (md5-hash of the username)
+ * created datetime Created date and time
+ * modified datetime Modified date and time
+ * modifiedby varchar(32) Modified by (md5-hash of the username)
+ *
+ *
+ * Example:
+ * --------
+ * A module needs to store custom properties for categories. Modifying the database
+ * would be a bad thing, since the changes might get lost during an upgrade or
+ * reinstall.
+ *
+ * If the custom property for a category would be the path to a category image,
+ * we would fill a row as follows:
+ *
+ * itemtype: idcat
+ * itemid:
+ * type: category
+ * name: image
+ * value: images/category01.gif
+ *
+ * idproperty, author, created, modified and modifiedby are automatically handled by
+ * the class.
+ */
+
+
+class PropertyCollection extends ItemCollection
+{
+ public $client;
+
+ /**
+ * Constructor Function
+ * @param none
+ */
+ public function __construct()
+ {
+ global $cfg, $client;
+ $this->client = Contenido_Security::toInteger($client);
+ parent::__construct($cfg['tab']['properties'], 'idproperty');
+ $this->_setItemClass('PropertyItem');
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function PropertyCollection()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+
+ /**
+ * Creates a new property item.
+ *
+ * Example:
+ *
+ * $properties->create('idcat', 27, 'visual', 'image', 'images/tool.gif');
+ *
+ * @param mixed $itemtype Type of the item (example: idcat)
+ * @param mixed $itemid ID of the item (example: 31)
+ * @param mixed $type Type of the data to store (arbitary data)
+ * @param mixed $name Entry name
+ * @param mixed $value Value
+ * @param bool $bInternally Optionally default false (on internal call do not escape parameters again
+ * @return PropertyItem
+ */
+ public function create($itemtype, $itemid, $type, $name, $value, $bInternally = false)
+ {
+ global $cfg, $auth;
+
+ $item = parent::create();
+
+ if (!$bInternally) {
+ $itemtype = Contenido_Security::escapeDB($itemtype, null);
+ $itemid = Contenido_Security::escapeDB($itemid, null);
+ $value = Contenido_Security::escapeDB($value, null);
+ $type = Contenido_Security::escapeDB($type, null);
+ $name = Contenido_Security::escapeDB($name, null);
+ }
+
+ $item->set('idclient', $this->client);
+ $item->set('itemtype', $itemtype, false);
+ $item->set('itemid', $itemid, false);
+ $item->set('type', $type);
+ $item->set('name', $name);
+ $item->set('value', $value);
+
+ $item->set('created', date('Y-m-d H:i:s'), false);
+ $item->set('author', Contenido_Security::escapeDB($auth->auth['uid'], null));
+ $item->store();
+
+ return ($item);
+ }
+
+
+ /**
+ * Returns the value for a given item.
+ *
+ * Example:
+ *
+ * $file = $properties->getValue('idcat', 27, 'visual', 'image');
+ *
+ * @param mixed $itemtype Type of the item (example: idcat)
+ * @param mixed $itemid ID of the item (example: 31)
+ * @param mixed $type Type of the data to store (arbitary data)
+ * @param mixed $name Entry name
+ * @return mixed Value
+ */
+ public function getValue($itemtype, $itemid, $type, $name, $default = false)
+ {
+ $itemtype = Contenido_Security::escapeDB($itemtype, null);
+ $itemid = Contenido_Security::escapeDB($itemid, null);
+ $type = Contenido_Security::escapeDB($type, null);
+ $name = Contenido_Security::escapeDB($name, null);
+
+ if($mValue = cPropertyCache::getProp($itemtype, $itemid, $type, $name) !== FALSE) {
+ return $mValue;
+ }
+
+ if (isset($this->client)) {
+ $this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."' AND name = '".$name."'");
+ } else {
+ $this->select("itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."' AND name = '".$name."'");
+ }
+
+ if ($item = $this->next()) {
+ cPropertyCache::addProp($item);
+ return (Contenido_Security::unescapeDB($item->get('value')));
+ }
+
+ return $default;
+ }
+
+
+ /**
+ * Returns the value for a given item.
+ *
+ * Example:
+ *
+ * $file = $properties->getValuesByType('idcat', 27, 'visual');
+ *
+ * @param mixed $itemtype Type of the item (example: idcat)
+ * @param mixed $itemid ID of the item (example: 31)
+ * @param mixed $type Type of the data to store (arbitary data)
+ * @return array Value
+ **/
+ public function getValuesByType($itemtype, $itemid, $type)
+ {
+ $aResult = array();
+ $itemtype = Contenido_Security::escapeDB($itemtype, null);
+ $itemid = Contenido_Security::escapeDB($itemid, null);
+ $type = Contenido_Security::escapeDB($type, null);
+
+ if (isset($this->client)) {
+ $this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."'");
+ } else {
+ $this->select("itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."'");
+ }
+
+ while ($item = $this->next()) {
+ cPropertyCache::addProp($item);
+ $aResult[$item->get('name')] = Contenido_Security::unescapeDB($item->get('value'));
+ }
+
+ return $aResult;
+ }
+
+
+ /**
+ * Sets a property item. Handles creation and updating.
+ *
+ * Example:
+ *
+ * $properties->setValue('idcat', 27, 'visual', 'image', 'images/tool.gif');
+ *
+ * @param mixed $itemtype Type of the item (example: idcat)
+ * @param mixed $itemid ID of the item (example: 31)
+ * @param mixed $type Type of the data to store (arbitary data)
+ * @param mixed $name Entry name
+ * @param mixed $value Value
+ * @param int $idProp Id of database record (if set, update on this basis (possiblity to update name value and type))
+ */
+ public function setValue($itemtype, $itemid, $type, $name, $value, $idProp = 0)
+ {
+ $itemtype = Contenido_Security::escapeDB($itemtype, null);
+ $itemid = Contenido_Security::escapeDB($itemid, null);
+ $type = Contenido_Security::escapeDB($type, null);
+ $name = Contenido_Security::escapeDB($name, null);
+ $value = Contenido_Security::escapeDB($value, null);
+ $idProp = Contenido_Security::toInteger($idProp);
+
+ if ($idProp == 0) {
+ $this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."' AND name = '".$name."'");
+ } else {
+ $this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND idproperty = '".$idProp."'");
+ }
+
+ if ($item = $this->next()) {
+ $item->set('value', $value);
+ $item->set('name', $name);
+ $item->set('type', $type);
+ $item->store();
+ } else {
+ $this->create($itemtype, $itemid, $type, $name, $value, true);
+ }
+ }
+
+
+ /**
+ * Delete a property item.
+ *
+ * Example:
+ *
+ * $properties->deleteValue('idcat', 27, 'visual', 'image');
+ *
+ * @param mixed $itemtype Type of the item (example: idcat)
+ * @param mixed $itemid ID of the item (example: 31)
+ * @param mixed $type Type of the data to store (arbitary data)
+ * @param mixed $name Entry name
+ */
+ public function deleteValue($itemtype, $itemid, $type, $name)
+ {
+ $itemtype = Contenido_Security::escapeDB($itemtype, null);
+ $itemid = Contenido_Security::escapeDB($itemid, null);
+ $type = Contenido_Security::escapeDB($type, null);
+ $name = Contenido_Security::escapeDB($name, null);
+
+ if (isset($this->client)) {
+ $this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."' AND name = '".$name."'");
+ } else {
+ $this->select("itemtype = '".$itemtype."' AND itemid = '".$itemid."' AND type = '".$type."' AND name = '".$name."'");
+ }
+
+ if ($item = $this->next()) {
+ $this->delete($item->get('idproperty'));
+ }
+ }
+
+
+ /**
+ * Checks if values for a given item are available.
+ *
+ * @param mixed $itemtype Type of the item (example: idcat)
+ * @param mixed $itemid ID of the item (example: 31)
+ * @return array For each given item
+ */
+ public function getProperties($itemtype, $itemid)
+ {
+ $itemtype = Contenido_Security::escapeDB($itemtype, null);
+ $itemid = Contenido_Security::escapeDB($itemid, null);
+
+ if (isset($this->client)) {
+ $this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."'");
+ } else {
+ $this->select("itemtype = '".$itemtype."' AND itemid = '".$itemid."'");
+ }
+
+ $result[$itemid] = false;
+
+ while ($item = $this->next()) {
+ cPropertyCache::addProp($item);
+ // enable accessing property values per number and field name
+ $result[$item->get('itemid')][$item->get('idproperty')] = array(
+ 0=> $item->get('type'), 'type'=> $item->get('type'),
+ 1=> $item->get('name'), 'name'=> $item->get('name'),
+ 2=> $item->get('value'), 'value'=> $item->get('value')
+ );
+ }
+ return $result;
+ }
+
+
+ /**
+ * Returns all datasets selected by given field and value combination
+ *
+ * @param mixed $field Field to search in
+ * @param mixed $fieldValue Value to search for
+ * @param Contenido_Auth $auth Narrow result down to user in auth objext
+ * @return array For each given item
+ */
+ public function getAllValues($field, $fieldValue, $auth=NULL)
+ {
+ $authString = '';
+ if (!is_null($auth) && sizeof($auth) > 0) {
+ $authString .= " AND author = '" . $auth->auth["uid"] . "'";
+ }
+
+ if (isset($this->client)) {
+ $this->select("idclient = '" . $this->client . "' AND " . $field . " = '" . $fieldValue . "'" . $authString, '' ,'itemid');
+ } else {
+ $this->select($field . " = '" . $fieldValue . "'" . $authString);
+ }
+
+ $retValue = array();
+ while ($item = $this->next()) {
+ cPropertyCache::addProp($item);
+ $dbLine = array(
+ 'idproperty' => $item->get('idproperty'),
+ 'idclient' => $item->get('idclient'),
+ 'itemtype' => $item->get('itemtype'),
+ 'itemid' => $item->get('itemid'),
+ 'type' => $item->get('type'),
+ 'name' => $item->get('name'),
+ 'value' => $item->get('value'),
+ 'author' => $item->get('author'),
+ 'created' => $item->get('created'),
+ 'modified' => $item->get('modified'),
+ 'modifiedby' => $item->get('modifiedby')
+ );
+ $retValue[] = $dbLine;
+ }
+ return $retValue;
+ }
+
+
+ /**
+ * Delete all properties which match itemtype and itemid
+ *
+ * @param mixed $itemtype Type of the item (example: idcat)
+ * @param mixed $itemid ID of the item (example: 31)
+ */
+ public function deleteProperties($itemtype, $itemid)
+ {
+ $itemtype = Contenido_Security::escapeDB($itemtype, null);
+ $itemid = Contenido_Security::escapeDB($itemid, null);
+
+ if (isset($this->client)) {
+ $this->select("idclient = '".$this->client."' AND itemtype = '".$itemtype."' AND itemid = '".$itemid."'");
+ } else {
+ $this->select("itemtype = '".$itemtype."' AND itemid = '".$itemid."'");
+ }
+
+ $deleteProperties = array();
+
+ while ($item = $this->next()) {
+ $deleteProperties[] = $item->get('idproperty');
+ }
+
+ foreach($deleteProperties as $idproperty) {
+ cPropertyCache::deleteProp($idproperty);
+ $this->delete($idproperty);
+ }
+ }
+
+
+ public function changeClient($idclient)
+ {
+ $this->client = $idclient;
+ }
+}
+
+
+class PropertyItem extends Item
+{
+ /**
+ * maximumLength: Array which stores the maximum string length of each field
+ */
+ public $maximumLength;
+
+ /**
+ * Constructor Function
+ * @param mixed $mId Specifies the ID of item to load
+ */
+ public function __construct($mId = false)
+ {
+ global $cfg;
+ parent::__construct($cfg['tab']['properties'], 'idproperty');
+
+ // Initialize maximum lengths for each column
+ $this->maximumLength = array();
+ $this->maximumLength['itemtype'] = 64;
+ $this->maximumLength['itemid'] = 255;
+ $this->maximumLength['type'] = 96;
+ $this->maximumLength['name'] = 96;
+
+ if ($mId !== false) {
+ $this->loadByPrimaryKey($mId);
+ }
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function PropertyItem($mId = false)
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct($mId);
+ }
+
+ /**
+ * Stores changed PropertyItem
+ */
+ public function store()
+ {
+ global $auth;
+
+ $this->set('modified', date('Y-m-d H:i:s'), false);
+ $this->set('modifiedby', $auth->auth['uid']);
+
+ parent::store();
+ }
+
+ /**
+ * Sets value of a field
+ *
+ * @param string $field
+ * @param string $value
+ * @param bool $safe Flag to run filter on passed value
+ */
+ public function setField($field, $value, $safe)
+ {
+ if (array_key_exists($field, $this->maximumLength)) {
+ if (strlen($value) > $this->maximumLength[$field]) {
+ cWarning(__FILE__, __LINE__, "Tried to set field $field to value $value, but the field is too small. Truncated.");
+ }
+ }
+
+ parent::setField($field, $value, $safe);
+ }
+}
+
+class cPropertyCache {
+
+ public static $_aEntries;
+
+ public static function addProp($oEntry) {
+ $aData = $oEntry->toArray();
+ self::$_aEntries[$aData['idproperty']] = $aData;
+ }
+
+ public static function deleteProp($iId) {
+ if(isset(self::$_aEntries[$iId]) && is_array(self::$_aEntries[$iId])) {
+ unset(self::$_aEntries[$iId]);
+ }
+ }
+
+ public static function getProp($itemtype, $itemid, $type, $name) {
+ if(!is_array(self::$_aEntries)) {
+ self::$_aEntries = array();
+ }
+ foreach (self::$_aEntries as $id => $entry) {
+ if ($entry['itemtype'] == $itemtype && $entry['itemid'] == $itemid && $entry['type'] == $type && $entry['name'] == $name) {
+ return Contenido_Security::unescapeDB($entry['value']);
+ }
+ }
+ return FALSE;
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.purge.php b/conlite/classes/class.purge.php
new file mode 100644
index 0000000..443cab5
--- /dev/null
+++ b/conlite/classes/class.purge.php
@@ -0,0 +1,432 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.8.12
+ *
+ * $Id:
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ * class Purge
+ *
+ */
+
+class Purge {
+
+ /**
+ * @var DB_ConLite $oDb
+ */
+ private $oDb;
+
+ /**
+ * @var $cfg
+ */
+ private $cfg;
+
+ /**
+ * @var $cfgClient
+ */
+ private $cfgClient;
+
+ /**
+ * @var string $sDefaultCacheDir
+ */
+ private $sDefaultCacheDir = 'cache/';
+
+
+ /**
+ * @var string $sDefaultLogDir
+ */
+ private $sDefaultLogDir = 'logs/';
+
+ /**
+ * @var string $sDefaultVersionDir
+ */
+ private $sDefaultVersionDir = 'version/';
+
+ /**
+ * @var string $sDefaultCronjobDir
+ */
+ private $sDefaultCronjobDir = 'cronjobs/';
+
+ /**
+ * @var array $aLogFileTypes
+ */
+ private $aLogFileTypes;
+
+ /**
+ * @var array $aCronjobFileTypes
+ */
+ private $aCronjobFileTypes;
+
+ /**
+ * Constructor of class
+ *
+ * @param object $db
+ * @param array $cfg
+ * @param array $cfgClient
+ */
+ public function __construct(&$db, $cfg, $cfgClient) {
+ $this->oDb = $db;
+ $this->cfg = $cfg;
+ $this->cfgClient = $cfgClient;
+
+ $this->setLogFileTypes(array('txt'));
+ $this->setCronjobFileTypes(array('job'));
+ }
+
+ /**
+ * Reset the table con_code for a client
+ *
+ * @param int $iClientId
+ * @return boolean
+ */
+ public function resetClientConCode($iClientId) {
+ $sSql = "DELETE FROM " . $this->cfg['tab']['code'] .
+ " WHERE idclient = " . $iClientId;
+
+ $this->oDb->query($sSql);
+
+ return ($this->oDb->Error == '') ? true : false;
+ }
+
+ /**
+ * Reset the table con_cat_art for a client
+ *
+ * @param int $iClientId
+ * @return boolean
+ */
+ public function resetClientConCatArt ($iClientId) {
+ $sSql = " UPDATE " . $this->cfg['tab']['cat_art'] . " cca, " .
+ $this->cfg['tab']['cat'] . " cc, " .
+ $this->cfg['tab']['art'] . " ca " .
+ " SET cca.createcode=1 " .
+ " WHERE cc.idcat = cca.idcat " .
+ " AND ca.idart = cca.idart " .
+ " AND cc.idclient = " . $iClientId .
+ " AND ca.idclient =" . $iClientId;
+ $this->oDb->query($sSql);
+
+ return ($this->oDb->Error == '') ? true : false;
+ }
+
+ /**
+ * Reset the table con_inuse
+ *
+ * @return boolean
+ */
+ public function resetConInuse () {
+ $sSql = "DELETE FROM " . $this->cfg['tab']['inuse'];
+ $this->oDb->query($sSql);
+
+ return ($this->oDb->Error == '') ? true : false;
+ }
+
+ /**
+ * Reset the table con_phplib_active_sessions
+ *
+ * @return boolean
+ */
+ public function resetPHPLibActiveSession () {
+ $sSql = "DELETE FROM " . $this->cfg['tab']['phplib_active_sessions'];
+ $this->oDb->query($sSql);
+ return ($this->oDb->Error == '') ? true : false;
+ }
+
+ /**
+ * Reset the table con_inuse
+ *
+ * @return boolean
+ */
+ public function resetUnusedSession () {
+ $sSql = "DELETE FROM " . $this->cfg['tab']['inuse'];
+ $this->oDb->query($sSql);
+
+ return ($this->oDb->Error == '') ? true : false;
+ }
+
+ /**
+ * Clear the cache directory for a client
+ *
+ * @param int $sClientName
+ * @return boolean
+ */
+ public function clearClientCache ($iClientId, $sCacheDir = 'cache/') {
+ $sClientDir = $this->getClientDir($iClientId);
+
+ $sCacheDir = (trim($sCacheDir) == '' || trim($sCacheDir) == '/') ? $this->sDefaultCacheDir : $sCacheDir;
+
+ if (is_dir($sClientDir . $sCacheDir)) {
+ $sCachePath = $sClientDir . $sCacheDir;
+ return ($this->clearDir($sCachePath, $sCachePath) ? true : false);
+ }
+
+ return false;
+ }
+
+ /**
+ * Clear the cache directory for a client
+ *
+ * @param int $sClientName
+ * @return boolean
+ */
+ public function clearClientHistory ($iClientId, $bKeep, $iFileNumber, $sVersionDir = 'version/') {
+ $sClientDir = $this->getClientDir($iClientId);
+
+ $sCacheDir = (trim($sVersionDir) == '' || trim($sVersionDir) == '/') ? $this->sDefaultVersionDir : $sVersionDir;
+
+ if (is_dir($sClientDir . $sVersionDir)) {
+ $sVersionPath = $sClientDir . $sVersionDir;
+ $aTmpFile = array();
+ $this->clearDir($sVersionPath, $sVersionPath, $bKeep, $aTmpFile);
+ if (count($aTmpFile) > 0 )
+ foreach ($aTmpFile as $sKey => $aFiles) {
+ // sort the history files with filename
+ array_multisort($aTmpFile[$sKey]);
+
+ $iCount = count($aTmpFile[$sKey]);
+ // find the total number to delete
+ $iCountDelete = ($iCount <= $iFileNumber) ? 0 : ($iCount - $iFileNumber);
+ // delete the files
+ for ($i = 0; $i < $iCountDelete; $i++) {
+ if (file_exists($aTmpFile[$sKey][$i]) && is_writable($aTmpFile[$sKey][$i])) {
+ unlink($aTmpFile[$sKey][$i]);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Clear client log file
+ *
+ * @param int $iClientId
+ * @param string $sLogDir
+ * @return boolean
+ */
+ public function clearClientLog ($iClientId, $sLogDir = 'logs/') {
+ $sClientDir = $this->getClientDir($iClientId);
+
+ $sLogDir = (trim($sLogDir) == '' || trim($sLogDir) == '/') ? $this->sDefaultLogDir : $sLogDir;
+
+ if (is_dir($sClientDir . $sLogDir)) {
+ return $this->emptyFile($sClientDir . $sLogDir, $this->aLogFileTypes);
+ }
+
+ return false;
+ }
+
+ /**
+ * Clear contenido log files
+ *
+ * @param string $sLogDir
+ * @return boolean
+ */
+ public function clearConLog ($sLogDir = 'logs/') {
+ $sLogDir = (trim($sLogDir) == '' || trim($sLogDir) == '/') ? $this->sDefaultLogDir : $sLogDir;
+
+ if (is_dir($sLogDir)) {
+ return $this->emptyFile($sLogDir, $this->aLogFileTypes);
+ }
+
+ return false;
+ }
+
+ /**
+ * Clear contenido log files
+ *
+ * @param string $sLogDir
+ * @return boolean
+ */
+ public function clearConCronjob ($sCronjobDir = 'cronjobs/') {
+ $sCronjobDir = (trim($sCronjobDir) == '' || trim($sCronjobDir) == '/') ? $this->sDefaultCronjobDir : $sCronjobDir;
+
+ if (is_dir($sCronjobDir)) {
+ return $this->emptyFile($sCronjobDir, $this->aCronjobFileTypes);
+ }
+
+ return false;
+ }
+
+ /**
+ * Clear the cache directory for a client
+ *
+ * @param int $sClientName
+ * @return boolean
+ */
+ public function clearConCache ($sCacheDir = 'cache/') {
+
+ $sCacheDir = (trim($sCacheDir) == '' || trim($sCacheDir) == '/') ? $this->sDefaultCacheDir : $sCacheDir;
+
+ if (is_dir($sCacheDir)) {
+ return ($this->clearDir($sCacheDir, $sCacheDir) ? true : false);
+ }
+
+ return false;
+ }
+
+ /**
+ * Delete all files and sub directories in a directory
+ *
+ * @param string $sDirPath
+ * @param string $sTmpDirPath - root directory not deleted
+ * @param boolean $bKeep
+ * @param array $aTmpFileList - files are temporarily saved
+ * @return boolean
+ */
+ public function clearDir ($sDirPath, $sTmpDirPath, $bKeep = false, &$aTmpFileList = array()) {
+ if (is_dir($sDirPath) && ($handle = opendir($sDirPath))) {
+ $sTmp = str_replace(array('/', '..'), '', $sDirPath);
+ while (false !== ($file = readdir($handle))) {
+ if ($file != "." && $file != "..") {
+ $sFilePath = $sDirPath . '/' . $file;
+ $sFilePath = str_replace('//', '/', $sFilePath);
+ if (is_dir($sFilePath)) {
+ $this->clearDir($sFilePath, $sTmpDirPath, $bKeep, $aTmpFileList);
+ } else {
+ if ($bKeep === false ) {
+ unlink($sFilePath);
+ } else {
+ $aTmpFileList[$sTmp][] = $sFilePath;
+ }
+
+ }
+ }
+ }
+ if (str_replace(array('/', '..'), '', $sDirPath) != str_replace(array('/', '..'), '', $sTmpDirPath) && $bKeep === false)
+ rmdir($sDirPath);
+
+ closedir($handle);
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Empty a file content
+ *
+ * @param string $sFilePath
+ * @return boolean
+ */
+ public function emptyFile($sDirPath, $aTypes) {
+ $iCount = 0;
+ $iCountCleared = 0;
+ if (is_dir($sDirPath) && ($handle = opendir($sDirPath))) {
+ while (false !== ($file = readdir($handle))) {
+ $sFileExt = trim(end(explode('.', $file)));
+
+ if ($file != "." && $file != ".." && in_array($sFileExt, $aTypes)) {
+ $sFilePath = $sDirPath . '/' . $file;
+
+ if (file_exists($sFilePath) && is_writable($sFilePath)) {
+ $iCount++;
+
+ //chmod($sFilePath, 0777);
+ if (fclose(fopen($sFilePath, 'w+')))
+ $iCountCleared++;
+ }
+ }
+ }
+
+ // true if all files are cleaned
+ return ($iCount == $iCountCleared) ? true : false;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get frontend directory name for a client
+ *
+ * @param int $iClientId
+ * @return string $sClientDir
+ */
+ public function getClientDir($iClientId) {
+ $sClientDir = str_replace($this->cfg['path']['frontend'], '..', $this->cfgClient[$iClientId]['path']['frontend']);
+
+ return $sClientDir;
+ }
+
+ /**
+ * Set log file types
+ *
+ * @param array $aTypes
+ */
+ public function setLogFileTypes( $aTypes) {
+ if (count($aTypes) > 0) {
+ foreach($aTypes as $sType) {
+ $this->aLogFileTypes[] = $sType;
+ }
+ }
+ }
+
+ /**
+ * Set cronjob file types
+ *
+ * @param array $aTypes
+ */
+ public function setCronjobFileTypes($aTypes) {
+ if (count($aTypes) > 0) {
+ foreach($aTypes as $sType) {
+ $this->aCronjobFileTypes[] = $sType;
+ }
+ }
+ }
+
+ /**
+ * updates con_sequence for all tables in db
+ * which are know in CL
+ *
+ * @author Ortwin Pinke
+ * @since 4.8.17 CL
+ *
+ * @return boolean
+ */
+ public function updateConSequence() {
+
+ $aDbTables = array();
+ $sSql = 'SHOW TABLES';
+ $this->oDb->query($sSql);
+
+ while($this->oDb->next_record()) {
+ $aTmp = $this->oDb->toArray();
+ $aDbTables[] = $aTmp[0];
+ }
+
+ $iLoop = 0;
+ //only use tables which are listet in tab-cfg
+ foreach ($this->cfg['tab'] as $sTable) {
+ if(in_array($sTable, $aDbTables)) {
+ dbUpdateSequence($this->cfg['tab']['sequence'], $sTable, $this->oDb);
+ if($this->oDb->Errno > 0) {
+ return false;
+ }
+
+ $iLoop++;
+ }
+ }
+ return true;
+ // not working with tables not listed in tab-cfg
+ // return ($iLoop == count($aDbTables))?true:false;
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.request.password.php b/conlite/classes/class.request.password.php
new file mode 100644
index 0000000..4cd1665
--- /dev/null
+++ b/conlite/classes/class.request.password.php
@@ -0,0 +1,404 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since 2008-03-20
+ *
+ * {@internal
+ * created 2008-03-20
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2010-05-27, Oliver Lohkemper, check if user activ in handleNewPassword()
+ * modified 2011-02-26, Ortwin Pinke, added temporary pw request behaviour, so user may login with old and/or requested pw
+ *
+ * $Id: class.request.password.php 340 2015-08-20 13:31:29Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+/**
+ *
+ * Description: Class for handling passwort recovery
+ *
+ * @author Timo Trautmann
+ * @copyright four for business AG
+ *
+ */
+class RequestPassword {
+ /**
+ * The contenido database object
+ *
+ * @var object
+ * @access private
+ */
+ var $oDb;
+
+ /**
+ * The contenido configuration array
+ *
+ * @var array
+ * @access private
+ */
+ var $aCfg;
+
+ /**
+ * The contenido template object
+ *
+ * @var object
+ * @access private
+ */
+ var $oTpl;
+
+ /*################################################################*/
+
+ /**
+ * Username of user which requests password
+ *
+ * @var string
+ * @access private
+ */
+ var $sUsername;
+
+ /**
+ * E-mail address of user which requests password
+ *
+ * @var string
+ * @access private
+ */
+ var $sEmail;
+
+ /*################################################################*/
+
+ /**
+ * Time in minutes after which user is allowed to request a new password
+ *
+ * @var integer
+ * @access private
+ */
+ var $iReloadTime;
+
+ /**
+ * Length of new passwort, which is generated automatically
+ *
+ * @var integer
+ * @access private
+ */
+ var $iPassLength;
+
+ /*################################################################*/
+
+ /**
+ * Definies if passwort request is enabled or disabled.
+ * Default: This feature is enabled
+ *
+ * @var boolean
+ * @access private
+ */
+ var $bIsEnabled;
+
+ /**
+ * E-mail address of the sender
+ *
+ * @var string
+ * @access private
+ */
+ var $sSendermail;
+
+ /**
+ * Name of the sender
+ *
+ * @var string
+ * @access private
+ */
+ var $sSendername;
+
+ /**
+ * Host of mailserver, which sends new password via mail
+ *
+ * @var string
+ * @access private
+ */
+ var $sMailhost;
+
+ /*################################################################*/
+ /*################################################################*/
+
+ /**
+ * Constructor of RequestPassword initializes class variables
+ *
+ * @param object $oDb - The contenido database object
+ * @param array $aCfg - The contenido configuration array
+ * @access public
+ */
+ function RequestPassword ($oDb, $aCfg) {
+ //generate new dbobject, if it does not exist
+ if (!is_object($oDb)) {
+ $this->oDb = new DB_ConLite();
+ } else {
+ $this->oDb = $oDb;
+ }
+
+ //init class variables
+ $this->aCfg = $aCfg;
+ $this->oTpl = new Template();
+ $this->sUsername = '';
+ $this->sEmail = '';
+
+ //set reload to 30 minutes
+ $this->iReloadTime = 30;
+
+ //set pass length to 14 chars
+ $this->iPassLength = 14;
+
+ //get systemproperty, which definies if password request is enabled (true) or disabled (false) : default to enabled
+ $sEnable = getSystemProperty('pw_request', 'enable');
+ if ($sEnable == 'false') {
+ $this->bIsEnabled = false;
+ } else {
+ $this->bIsEnabled = true;
+ }
+
+ //get systemproperty for senders mail and validate mailadress, if not set use standard sender
+ $sSendermail = getSystemProperty('system', 'mail_sender');
+ if (preg_match("/^.+@.+\.([A-Za-z0-9\-_]{1,20})$/", $sSendermail)) {
+ $this->sSendermail = $sSendermail;
+ } else {
+ $this->sSendermail = 'noreply@contenido-passwordservice.de';
+ }
+
+ //get systemproperty for senders name, if not set use Contenido Backend
+ $sSendername = getSystemProperty('system', 'mail_sender_name');
+ if ($sSendername != '') {
+ $this->sSendername = $sSendername;
+ } else {
+ $this->sSendername = 'Contenido Backend';
+ }
+
+ //get systemproperty for location of mailserver, if not set use localhost
+ $sMailhost = getSystemProperty('system', 'mail_host');
+ if ($sMailhost != '') {
+ $this->sMailhost = $sMailhost;
+ } else {
+ $this->sMailhost = 'localhost';
+ }
+ }
+
+ /**
+ * Function displays form for password request and sets new password, if password is submitted this function
+ * also starts the passwort change an sending process
+ *
+ * @access public
+ */
+ function renderForm () {
+ //if feature is not enabled, do nothing
+ if (!$this->bIsEnabled) {
+ return;
+ }
+
+ $sMessage = '';
+
+ //if form is sumbitted call function handleNewPassword() and set submitted username to class variable $sUsername
+ if (isset($_POST['action']) && $_POST['action'] == 'request_pw') {
+ //avoid SQL-Injection, first check if submitted vars are escaped automatically
+ $this->sUsername = $_POST['request_username'];
+
+ $sMessage = $this->handleNewPassword();
+ //if form is submitted, show corresponding password request layer
+ $this->oTpl->set('s', 'JS_CALL', 'showRequestLayer();');
+ } else {
+ //by default request layer is invisible so da nothing
+ $this->oTpl->set('s', 'JS_CALL', '');
+ }
+
+ //generate new form
+ $oForm = new UI_Form('request_pw', 'index.php', 'post');
+ $sRequestUsername = (isset($_POST['request_username']))?stripslashes($_POST['request_username']):'';
+ //generate input for username
+ $oInputUsername = new cHTMLTextbox('request_username', $sRequestUsername, '', '', 'request_username');
+ $oInputUsername->setStyle('width:215px;');
+
+ //set request action and current language
+ $oForm->setVar('action', 'request_pw');
+ $oForm->setVar('belang', $GLOBALS['belang']);
+
+ //generate submitbutton and fill the form
+ $oForm->add('submit', ' ');
+ $oForm->add('request_username', $oInputUsername->render());
+ $this->oTpl->set('s', 'FORM', $oForm->render());
+ $this->oTpl->set('s', 'MESSAGE', $sMessage);
+ $this->oTpl->set('s', 'LABEL', i18n('Please enter your login').':');
+
+ $oButtonHide = new cHTMLImage($this->aCfg["path"]["contenido_fullhtml"]
+ .$this->aCfg["path"]["images"]
+ ."but_cancel_off.gif");
+ $oButtonHide->setStyle("border: none;");
+ $oButtonHide->setAlt(i18n("Hide request"));
+
+ $this->oTpl->set('s', 'BTN_HIDE', $oButtonHide->render());
+
+ //if handleNewPassword() returns a message, display it
+ $this->oTpl->generate($this->aCfg['path']['contenido']
+ .$this->aCfg['path']['templates']
+ .$this->aCfg['templates']['request_password']);
+ }
+
+ /**
+ * Function checks password request for errors an delegate request to setNewPassword() if there is no error
+ *
+ * @access private
+ * @param string - contains message for displaying (errors or success message)
+ */
+ function handleNewPassword () {
+ //notification message, which is returned to caller
+ $sMessage = '';
+ $this->sUsername = stripslashes($this->sUsername);
+
+ //check if requested username exists, also get email and timestamp when user last requests a new password (last_pw_request)
+ $sSql = "SELECT username, last_pw_request, email FROM ".$this->aCfg["tab"]["phplib_auth_user_md5"]."
+ WHERE username = '".$this->oDb->escape($this->sUsername)."'
+ AND ( valid_from <= NOW() OR valid_from = '0000-00-00')
+ AND ( valid_to >= NOW() OR valid_to = '0000-00-00' )";
+
+ $this->oDb->query($sSql);
+ if ($this->oDb->next_record() && md5($this->sUsername) == md5($this->oDb->f('username'))) {
+ //by default user is allowed to request new password
+ $bIsAllowed = true;
+ $sLast_pw_request = $this->oDb->f('last_pw_request');
+ //store users mail adress to class variable
+ $this->sEmail = $this->oDb->f('email');
+
+ //check if there is a correct last request date
+ if (preg_match('/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/', $sLast_pw_request, $aMatches)) {
+ $iLastRequest = mktime($aMatches[4], $aMatches[5], $aMatches[6], $aMatches[2], $aMatches[3], $aMatches[1]);
+ $iNow = time();
+
+ //check if this last request is longer ago then timelimit.
+ if ($iNow-$iLastRequest < (60*$this->iReloadTime)) {
+ //user is not allowed to request new password, he has to wait
+ $bIsAllowed = false;
+ $sMessage = sprintf(i18n('Password requests are allowed every %s minutes.'), $this->iReloadTime);
+ }
+ }
+
+ //check if syntax of users mail adress is correct and there is no standard mailadress like admin_kunde@IhreSite.de or sysadmin@IhreSite.de
+ if ((!preg_match("/^.+@.+\.([A-Za-z0-9\-_]{1,20})$/", $this->sEmail) || $this->sEmail == 'sysadmin@IhreSite.de' || $this->sEmail == 'admin_kunde@IhreSite.de') && $bIsAllowed) {
+ $bIsAllowed = false;
+ //$sMessage = i18n('The requested user has no valid e-mail address. Submitting new password is not possible. Please contact your system- administrator for further support.');
+ $sMessage = i18n('No matching data found. Please contact your systemadministrator.');
+ }
+
+ //if there are no errors, call function setNewPassword(), else wait a while, then return error message
+ if ($bIsAllowed) {
+ $this->setNewPassword();
+ $sMessage = i18n('New password was submitted to your e-mail address.');
+ } else {
+ sleep(5);
+ }
+ } else {
+ //slepp a while, then return error message
+ //$sMessage = i18n('This user does not exist.');
+ $sMessage = i18n('No matching data found. Please contact your systemadministrator.');
+ sleep(5);
+ }
+ return $sMessage;
+ }
+
+ /**
+ * Function sets new password for user and sets last request time to now
+ *
+ * @access private
+ */
+ function setNewPassword () {
+ //generate new password, using generatePassword()
+ $sPassword = $this->generatePassword();
+
+ //update database entry, set new password and last_pw_request time
+ $sSql = "UPDATE ".$this->aCfg["tab"]["phplib_auth_user_md5"]."
+ SET last_pw_request = '".date('Y-m-d H:i:s')."',
+ tmp_pw_request = '".md5($sPassword)."'
+ WHERE username = '".$this->sUsername."'";
+ $this->oDb->query($sSql);
+
+ //call function submitMail(), which sends new password to user
+ $this->submitMail($sPassword);
+ }
+
+ /**
+ * Function submits new password to users mail adress
+ *
+ * @access private
+ * @param string $sPassword - the new password
+ */
+ function submitMail ($sPassword) {
+ $sPassword = (string) $sPassword;
+
+ //get translation for mailbody and insert username and new password
+ $sMailBody = sprintf(i18n("Dear Contenidouser %s,\n\nYour password to log in Content Management System Contenido is: %s\n\nBest regards\n\nYour Contenido sysadmin"), $this->sUsername, $sPassword);
+
+ //use php mailer class for submitting mail
+ $oMail = new PHPMailer();
+ //set host of mailserver
+ $oMail->Host = $this->sMailhost;
+ //it is not a html mail
+ $oMail->IsHTML(0);
+ //set senders e-mail adress
+ $oMail->From = $this->sSendermail;
+ //set senders name
+ $oMail->FromName = $this->sSendername;
+
+ //set users e mail adress as recipient
+ $oMail->AddAddress($this->sEmail, "");
+ //set mail subject
+ $oMail->Subject = stripslashes (i18n('Your new password for Contenido Backend'));
+ //append mail body
+ $oMail->Body = $sMailBody;
+ //wrap after 1000 chars
+ $oMail->WordWrap = 1000;
+ //activate mail and send it
+ $oMail->IsMail();
+ $oMail->Send();
+ }
+
+ /**
+ * Function generates new password
+ *
+ * @access private
+ * @return string - the new password
+ */
+ function generatePassword () {
+ //possible chars which were used in password
+ $sChars = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghjkmnopqrstuvwxyz123456789";
+
+ $sPw = "";
+
+ //for each character of password choose one from $sChars randomly
+ for ($i = 0; $i < $this->iPassLength; $i++) {
+ $sPw.= $sChars[rand(0, strlen($sChars))];
+ }
+
+ return $sPw;
+ }
+}
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.search.php b/conlite/classes/class.search.php
new file mode 100644
index 0000000..f76739e
--- /dev/null
+++ b/conlite/classes/class.search.php
@@ -0,0 +1,1548 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created 2004-01-15
+ * modified 2008-06-30, Frederic Schneider, add security fix
+ * modified 2008-07-11, Dominik Ziegler, marked class search_helper as deprecated
+ * modified 2008-11-12, Andreas Lindner, add special treatment for iso-8859-2
+ * modified 2011-02-08, Murat Purc, removed PHP 4.3 related code, cleanup and formatting, created SearchBaseAbstract class
+ *
+ * $Id: class.search.php 312 2014-06-18 11:01:08Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+/**
+ * Abstract base search class. Provides general properties and functions
+ * for child implementations.
+ *
+ * @author Murat Purc
+ */
+abstract class SearchBaseAbstract
+{
+ /**
+ * Contenido database object
+ * @var DB_ConLite
+ */
+ protected $oDB;
+
+ /**
+ * Contenido configuration data
+ * @var array
+ */
+ protected $cfg;
+
+ /**
+ * Language id of a client
+ * @var int
+ */
+ protected $lang;
+
+ /**
+ * Client id
+ * @var int
+ */
+ protected $client;
+
+ /**
+ * Flag to enable debug
+ * @var bool
+ */
+ protected $bDebug;
+
+ /**
+ * Initialises some properties
+ *
+ * @param DB_ConLite $oDB Optional database instance
+ * @param bool $bDebug Optional, flag to enable debugging
+ */
+ protected function __construct($oDB = null, $bDebug = false)
+ {
+ global $cfg, $lang, $client;
+
+ $this->cfg = $cfg;
+ $this->lang = $lang;
+ $this->client = $client;
+
+ $this->setDebug((bool) $bDebug);
+
+ if ($oDB == null) {
+ $this->db = new DB_ConLite();
+ } elseif (is_object($oDB)) {
+ $this->db = $oDB;
+ }
+ }
+
+ /**
+ * Setter for debug
+ *
+ * @param bool $bDebug
+ */
+ public function setDebug($bDebug)
+ {
+ $this->bDebug = (bool) $bDebug;
+ }
+
+ /**
+ * Main debug function, prints dumps parameter if debugging is enabled
+ *
+ * @param string $msg Some text
+ * @param mixed $var The variable to dump
+ */
+ protected function _debug($msg, $var)
+ {
+ if (!$this->bDebug) {
+ return;
+ }
+ $dump = '' . $msg . ': ';
+ if (is_array($var) || is_object($var)) {
+ $dump .= print_r($var, true);
+ } else {
+ $dump .= $var;
+ }
+ $dump .= ' ' . "\n";
+ echo $dump;
+ }
+}
+
+
+/**
+ * Contenido API - Index Object
+ *
+ * This object creates an index of an article
+ *
+ * Create object with
+ * $oIndex = new Index($db); # where $db is the global Contenido database object.
+ * Start indexing with
+ * $oIndex->start($idart, $aContent);
+ * where $aContent is the complete content of an article specified by its content types.
+ * It looks like
+ * Array (
+ * [CMS_HTMLHEAD] => Array (
+ * [1] => Herzlich Willkommen...
+ * [2] => ...auf Ihrer Website!
+ * )
+ * [CMS_HTML] => Array (
+ * [1] => Die Inhalte auf dieser Website ...
+ *
+ * The index for keyword 'willkommen' would look like '&12=1(CMS_HTMLHEAD-1)' which means the keyword 'willkommen' occurs 1 times in article with articleId 12 and content type CMS_HTMLHEAD[1].
+ *
+ * TODO: The basic idea of the indexing process is to take the complete content of an article and to generate normalized index terms
+ * from the content and to store a specific index structure in the relation 'con_keywords'.
+ * To take the complete content is not very flexible. It would be better to differentiate by specific content types or by any content.
+ * The &, =, () and - seperated string is not easy to parse to compute the search result set.
+ * It would be a better idea (and a lot of work) to extend the relation 'con_keywords' to store keywords by articleId (or content source identifier) and content type.
+ * The functions removeSpecialChars, setStopwords, setContentTypes and setCmsOptions should be sourced out into a new helper-class.
+ * Keep in mind that class Search and SearchResult uses an instance of object Index.
+ * Consider character tables in relation 'con_chartable'.
+ */
+
+cInclude('includes', 'functions.encoding.php');
+
+class Index extends SearchBaseAbstract
+{
+ /**
+ * the content of the cms-types of an article
+ * @var array
+ */
+ var $keycode = array();
+
+ /**
+ * the list of keywords of an article
+ * @var array
+ */
+ var $keywords = array();
+
+ /**
+ * the words, which should not be indexed
+ * @var array
+ */
+ var $stopwords = array();
+
+ /**
+ * the keywords of an article stored in the DB
+ * @var array
+ */
+ var $keywords_old = array();
+
+ /**
+ * the keywords to be deleted
+ * @var array
+ */
+ var $keywords_del = array();
+
+ /**
+ * 'auto' or 'self'
+ * The field 'auto' in table con_keywords is used for automatic indexing.
+ * The value is a string like "&12=2(CMS_HTMLHEAD-1,CMS_HTML-1)", which means a keyword occurs 2 times in article with $idart 12
+ * and can be found in CMS_HTMLHEAD[1] and CMS_HTML[1].
+ * The field 'self' can be used in the article properties to index the article manually.
+ * @var string
+ */
+ var $place;
+
+ /**
+ * array of cms types
+ * @var array
+ */
+ var $cms_options = array();
+
+ /**
+ * array of all available cms types
+ *
+ * htmlhead - HTML Headline
+ * html - HTML Text
+ * head - Headline (no HTML)
+ * text - Text (no HTML)
+ * img - Upload id of the element
+ * imgdescr - Image description
+ * link - Link (URL)
+ * linktarget - Linktarget (_self, _blank, _top ...)
+ * linkdescr - Linkdescription
+ * swf - Upload id of the element
+ * etc.
+ *
+ * @var array
+ */
+ var $cms_type = array();
+
+ /**
+ * the suffix of all available cms types
+ * @var array
+ */
+ var $cms_type_suffix = array();
+
+ /**
+ * Constructor, set object properties
+ * @param DB_ConLite $oDB Contenido Database object
+ * @return void
+ */
+ function Index($oDB = null)
+ {
+ parent::__construct($oDB);
+
+ $this->setContentTypes();
+ }
+
+ /**
+ * Start indexing the article.
+ *
+ * @param int $idart Article Id
+ * @param array $aContent The complete content of an article specified by its content types.
+ * It looks like
+ * Array (
+ * [CMS_HTMLHEAD] => Array (
+ * [1] => Herzlich Willkommen...
+ * [2] => ...auf Ihrer Website!
+ * )
+ * [CMS_HTML] => Array (
+ * [1] => Die Inhalte auf dieser Website ...
+ *
+ * @param string $place The field where to store the index information in db.
+ * @param array $cms_options One can specify explicitly cms types which should not be indexed.
+ * @param array $aStopwords Array with words which should not be indexed.
+ * @return void
+ */
+ function start($idart, $aContent, $place = 'auto', $cms_options = array(), $aStopwords = array())
+ {
+ if (!is_int((int)$idart) || $idart < 0) {
+ return null;
+ } else {
+ $this->idart = $idart;
+ }
+
+ $this->place = $place;
+ $this->keycode = $aContent;
+ $this->setStopwords($aStopwords);
+ $this->setCmsOptions($cms_options);
+
+ $this->createKeywords();
+ $this->getKeywords();
+ $this->saveKeywords();
+
+ $new_keys = array_keys($this->keywords);
+ $old_keys = array_keys($this->keywords_old);
+
+ $this->keywords_del = array_diff($old_keys, $new_keys);
+
+ if (count($this->keywords_del) > 0) {
+ $this->deleteKeywords();
+ }
+ }
+
+ /**
+ * for each cms-type create index structure.
+ * it looks like
+ * Array (
+ * [die] => CMS_HTML-1
+ * [inhalte] => CMS_HTML-1
+ * [auf] => CMS_HTML-1 CMS_HTMLHEAD-2
+ * [dieser] => CMS_HTML-1
+ * [website] => CMS_HTML-1 CMS_HTML-1 CMS_HTMLHEAD-2
+ * )
+ *
+ * @param none
+ * @return void
+ */
+ function createKeywords()
+ {
+ $tmp_keys = array();
+ $replace = array(' ', '&', '<', '>', '"', ''');
+
+ // Only create keycodes, if some are available
+ if (is_array($this->keycode)) {
+ foreach($this->keycode as $idtype => $data) {
+ if ($this->checkCmsType($idtype)) {
+ foreach($data as $typeid => $code) {
+ $this->_debug('code', $code);
+
+ $code = stripslashes($code); // remove backslash
+ $code = str_ireplace(array(' ', ' '), "\n", $code); // replace HTML line breaks with newlines
+ $code = strip_tags($code); // remove html tags
+ if (strlen($code) > 0) {
+ $code = clHtmlEntityDecode($code);
+ }
+ $this->_debug('code', $code);
+
+ $tmp_keys = preg_split('/[\s,]+/', trim($code)); // split content by any number of commas or space characters
+ $this->_debug('tmp_keys', $tmp_keys);
+
+ foreach ($tmp_keys as $value) {
+ $value = strtolower($value); // index terms are stored with lower case
+
+ if (!in_array($value, $this->stopwords)) {
+ // eliminate stopwords
+ $value = $this->removeSpecialChars($value);
+
+ if (strlen($value) > 1) {
+ // do not index single characters
+ $this->keywords[$value] = $this->keywords[$value] . $idtype . '-' . $typeid . ' ';
+ }
+ }
+ }
+ }
+ }
+
+ unset($tmp_keys);
+ }
+ }
+
+ $this->_debug('keywords', $this->keywords);
+ }
+
+ /**
+ * generate index_string from index structure and save keywords
+ * The index_string looks like "&12=2(CMS_HTMLHEAD-1,CMS_HTML-1)"
+ * @return void
+ */
+ function saveKeywords()
+ {
+ $tmp_count = array();
+
+ foreach ($this->keywords as $keyword => $count) {
+ $tmp_count = preg_split('/[\s]/', trim($count));
+ $this->_debug('tmp_count', $tmp_count);
+
+ $occurrence = count($tmp_count);
+ $tmp_count = array_unique($tmp_count);
+ $cms_types = implode(',', $tmp_count);
+ $index_string = '&' . $this->idart . '=' . $occurrence . '(' . $cms_types . ')';
+
+ if (!array_key_exists($keyword, $this->keywords_old)) {
+ // if keyword is new, save index information
+
+ $nextid = $this->db->nextid($this->cfg['tab']['keywords']);
+
+ $sql = "INSERT INTO ".$this->cfg['tab']['keywords']."
+ (keyword, ".$this->place.", idlang, idkeyword)
+ VALUES
+ ('".Contenido_Security::escapeDB($keyword, $this->db)."', '".Contenido_Security::escapeDB($index_string, $this->db)."', ".Contenido_Security::toInteger($this->lang).", ".Contenido_Security::toInteger($nextid).")";
+ } else {
+ // if keyword allready exists, create new index_string
+ if (preg_match("/&$this->idart=/", $this->keywords_old[$keyword])) {
+ $index_string = preg_replace("/&$this->idart=[0-9]+\([\w-,]+\)/", $index_string, $this->keywords_old[$keyword]);
+ } else {
+ $index_string = $this->keywords_old[$keyword] . $index_string;
+ }
+
+ $sql = "UPDATE ".$this->cfg['tab']['keywords']."
+ SET ".$this->place." = '".$index_string."'
+ WHERE idlang='".Contenido_Security::toInteger($this->lang)."' AND keyword='".Contenido_Security::escapeDB($keyword, $this->db)."'";
+ }
+ $this->_debug('sql', $sql);
+
+ $this->db->query($sql);
+ }
+ }
+
+ /**
+ * if keywords don't occur in the article anymore, update index_string and delete keyword if necessary
+ * @param none
+ * @return void
+ */
+ function deleteKeywords()
+ {
+ foreach ($this->keywords_del as $key_del) {
+ $index_string = preg_replace("/&$this->idart=[0-9]+\([\w-,]+\)/", "", $this->keywords_old[$key_del]);
+
+ if (strlen($index_string) == 0) {
+ // keyword is not referenced by any article
+ $sql = "DELETE FROM ".$this->cfg['tab']['keywords']."
+ WHERE idlang='".Contenido_Security::toInteger($this->lang)."' AND keyword='".Contenido_Security::escapeDB($key_del, $this->db)."'";
+ } else {
+ $sql = "UPDATE ".$this->cfg['tab']['keywords']."
+ SET ".$this->place." = '".$index_string."'
+ WHERE idlang='".Contenido_Security::toInteger($this->lang)."' AND keyword='".Contenido_Security::escapeDB($key_del, $this->db)."'";
+ }
+ $this->_debug('sql', $sql);
+ $this->db->query($sql);
+ }
+ }
+
+ /**
+ * get the keywords of an article
+ * @param none
+ * @return void
+ */
+ function getKeywords()
+ {
+ $keys = implode("','", array_keys($this->keywords));
+
+ $sql = "SELECT
+ keyword, auto, self
+ FROM
+ ".$this->cfg['tab']['keywords']."
+ WHERE
+ idlang=".Contenido_Security::toInteger($this->lang)." AND
+ (keyword IN ('".$keys."') OR ".$this->place." REGEXP '&".Contenido_Security::toInteger($this->idart)."=')";
+
+ $this->_debug('sql', $sql);
+
+ $this->db->query($sql);
+
+ $place = $this->place;
+
+ while ($this->db->next_record()) {
+ $this->keywords_old[$this->db->f('keyword')] = $this->db->f($place);
+ }
+ }
+
+ /**
+ * remove special characters from index term
+ * @param $key Keyword
+ * @return $key
+ */
+ function removeSpecialChars($key)
+ {
+ $aSpecialChars = array(
+ "-", "_", "'", ".", "!", "\"", "#", "$", "%", "&", "(", ")", "*", "+", ",", "/",
+ ":", ";", "<", "=", ">", "?", "@", "[", "\\", "]", "^", "`", "{", "|", "}", "~"
+ );
+
+ for ($i = 127; $i < 192; $i++) {
+ array_push($aSpecialChars, chr($i)); // some other special characters
+ }
+
+ // TODO: The transformation of accented characters must depend on the selected encoding of the language of
+ // a client and should not be treated in this method.
+ // modified 2007-10-01, H. Librenz - added as hotfix for encoding problems (doesn't find any words with
+ // umlaut vowels in it since you turn on UTF-8 as language encoding)
+ $sEncoding = getEncodingByLanguage($this->db, $this->lang, $this->cfg);
+
+ if (strtolower($sEncoding) != 'iso-8859-2') {
+ $key = clHtmlEntities($key, NULL, $sEncoding);
+ } else {
+ $key = htmlentities_iso88592($key);
+ }
+
+ $aUmlautMap = array (
+ 'Ü' => 'ue',
+ 'ü' => 'ue',
+ 'Ä' => 'ae',
+ 'ä' => 'ae',
+ 'Ö' => 'oe',
+ 'ö' => 'oe',
+ 'ß' => 'ss'
+ );
+
+ foreach ($aUmlautMap as $sUmlaut => $sMapped) {
+ $key = str_replace($sUmlaut, $sMapped, $key);
+ }
+
+ $key = clHtmlEntityDecode($key);
+ $key = str_replace($aSpecialChars, '', $key);
+
+ return $key;
+ }
+
+ /**
+ * @modified 2008-04-17, Timo Trautmann - reverse function to removeSpecialChars
+ * (important for syntaxhighlighting searchterm in searchresults)
+ * adds umlauts to search term
+ * @param $key Keyword
+ * @return $key
+ */
+ function addSpecialUmlauts($key)
+ {
+ $key = clHtmlEntities($key, null, getEncodingByLanguage($this->db, $this->lang, $this->cfg));
+ $aUmlautMap = array (
+ 'ue' => 'Ü',
+ 'ue' => 'ü',
+ 'ae' => 'Ä',
+ 'ae' => 'ä',
+ 'oe' => 'Ö',
+ 'oe' => 'ö',
+ 'ss' => 'ß'
+ );
+
+ foreach ($aUmlautMap as $sUmlaut => $sMapped) {
+ $key = str_replace($sUmlaut, $sMapped, $key);
+ }
+
+ $key = clHtmlEntityDecode($key);
+ return $key;
+ }
+
+ /**
+ * set the array of stopwords which should not be indexed
+ * @param array $aStopwords
+ * @return void
+ */
+ function setStopwords ($aStopwords)
+ {
+ if (is_array($aStopwords) && count($aStopwords) > 0) {
+ $this->stopwords = $aStopwords;
+ }
+ }
+
+ /**
+ * set the cms types
+ * @param none
+ * @return void
+ */
+ function setContentTypes()
+ {
+ $sql = "SELECT type, idtype FROM ".$this->cfg['tab']['type'] . ' ';
+ $this->_debug('sql', $sql);
+ $this->db->query($sql);
+ while ($this->db->next_record()) {
+ $this->cms_type[$this->db->f('type')] = $this->db->f('idtype');
+ $this->cms_type_suffix[$this->db->f('idtype')] = substr($this->db->f('type'), 4, strlen($this->db->f('type')));
+ }
+ }
+
+ /**
+ * set the cms_options array of cms types which should be treated special
+ * @param none
+ * @return void
+ */
+ function setCmsOptions($cms_options)
+ {
+ if (is_array($cms_options) && count($cms_options) > 0) {
+ foreach($cms_options as $opt) {
+ $opt = strtoupper($opt);
+
+ if (strlen($opt) > 0) {
+ if (!stristr($opt, 'cms_')) {
+ if (in_array($opt, $this->cms_type_suffix)) {
+ $this->cms_options[$opt] = 'CMS_' . $opt;
+ }
+ } else {
+ if (array_key_exists($opt, $this->cms_type)) {
+ $this->cms_options[$opt] = $opt;
+ }
+ }
+ }
+ }
+ } else {
+ $this->cms_options = array();
+ }
+ }
+
+ /**
+ * check if the current cms type is in the cms_options array
+ * @param $idtype
+ *
+ * @return bolean
+ */
+ function checkCmsType($idtype)
+ {
+ $idtype = strtoupper($idtype);
+ return (in_array($idtype, $this->cms_options)) ? false : true;
+ }
+
+}
+
+
+/**
+ * Contenido API - Search Object
+ *
+ * This object starts a indexed fulltext search
+ *
+ * TODO:
+ * The way to set the search options could be done much more better!
+ * The computation of the set of searchable articles should not be treated in this class.
+ * It is better to compute the array of searchable articles from the outside and to pass the array of searchable articles as parameter.
+ * Avoid foreach loops.
+ *
+ * Use object with
+ *
+ * $options = array('db' => 'regexp', // use db function regexp
+ * 'combine' => 'or'); // combine searchwords with or
+ *
+ * The range of searchable articles is by default the complete content which is online and not protected.
+ *
+ * With option 'searchable_articles' you can define your own set of searchable articles.
+ * If parameter 'searchable_articles' is set the options 'cat_tree', 'categories', 'articles', 'exclude', 'artspecs',
+ * 'protected', 'dontshowofflinearticles' don't have any effect.
+ *
+ * $options = array('db' => 'regexp', // use db function regexp
+ * 'combine' => 'or', // combine searchwords with or
+ * 'searchable_articles' => array(5, 6, 9, 13));
+ *
+ * One can define the range of searchable articles by setting the parameter 'exclude' to false which means the range of categories
+ * defined by parameter 'cat_tree' or 'categories' and the range of articles defined by parameter 'articles' is included.
+ *
+ * $options = array('db' => 'regexp', // use db function regexp
+ * 'combine' => 'or', // combine searchwords with or
+ * 'exclude' => false, // => searchrange specified in 'cat_tree', 'categories' and 'articles' is included
+ * 'cat_tree' => array(12), // tree with root 12 included
+ * 'categories' => array(100,111), // categories 100, 111 included
+ * 'articles' => array(33), // article 33 included
+ * 'artspecs' => array(2, 3), // array of article specifications => search only articles with these artspecs
+ * 'res_per_page' => 2, // results per page
+ * 'protected' => true); // => do not search articles or articles in categories which are offline or protected
+ * 'dontshowofflinearticles' => false); // => search offline articles or articles in categories which are offline
+ *
+ * You can build the complement of the range of searchable articles by setting the parameter 'exclude' to true which means the range of categories
+ * defined by parameter 'cat_tree' or 'categories' and the range of articles defined by parameter 'articles' is excluded from search.
+ *
+ * $options = array('db' => 'regexp', // use db function regexp
+ * 'combine' => 'or', // combine searchwords with or
+ * 'exclude' => true, // => searchrange specified in 'cat_tree', 'categories' and 'articles' is excluded
+ * 'cat_tree' => array(12), // tree with root 12 excluded
+ * 'categories' => array(100,111), // categories 100, 111 excluded
+ * 'articles' => array(33), // article 33 excluded
+ * 'artspecs' => array(2, 3), // array of article specifications => search only articles with these artspecs
+ * 'res_per_page' => 2, // results per page
+ * 'protected' => true); // => do not search articles or articles in categories which are offline or protected
+ * 'dontshowofflinearticles' => false); // => search offline articles or articles in categories which are offline
+ *
+ * $search = new Search($options);
+ *
+ * $cms_options = array("htmlhead", "html", "head", "text", "imgdescr", "link", "linkdescr");
+ * search only in these cms-types
+ * $search->setCmsOptions($cms_options);
+ *
+ * $search_result = $search->searchIndex($searchword, $searchwordex); // start search
+ *
+ * The search result structure has following form
+ * Array (
+ * [20] => Array (
+ * [CMS_HTML] => Array (
+ * [0] => 1
+ * [1] => 1
+ * [2] => 1
+ * )
+ * [keyword] => Array (
+ * [0] => content
+ * [1] => contenido
+ * [2] => wwwcontenidoorg
+ * )
+ * [search] => Array (
+ * [0] => con
+ * [1] => con
+ * [2] => con
+ * )
+ * [occurence] => Array (
+ * [0] => 1
+ * [1] => 5
+ * [2] => 1
+ * )
+ * [similarity] => 60
+ * )
+ * )
+ *
+ * The keys of the array are the article ID's found by search.
+ *
+ * Searching 'con' matches keywords 'content', 'contenido' and 'wwwcontenidoorg' in article with ID 20 in content type CMS_HTML[1].
+ * The search term occurs 7 times.
+ * The maximum similarity between searchterm and matching keyword is 60%.
+ *
+ * with $oSearchResults = new SearchResult($search_result, 10);
+ * one can rank and display the results
+ *
+ * @version 1.0.1
+ *
+ * @author Willi Man
+ * @copyright four for business AG
+ */
+
+class Search extends SearchBaseAbstract
+{
+
+ /**
+ * Instance of class Index
+ * @var object
+ */
+ var $index;
+
+ /**
+ * array of available cms types
+ * @var array
+ */
+ var $cms_type = array();
+
+ /**
+ * suffix of available cms types
+ * @var array
+ */
+ var $cms_type_suffix = array();
+
+ /**
+ * the search words
+ * @var array
+ */
+ var $search_words = array();
+
+ /**
+ * the words which should be excluded from search
+ * @var array
+ */
+ var $search_words_exclude = array();
+
+ /**
+ * type of db search
+ * like => 'sql like', regexp => 'sql regexp'
+ * @var string
+ */
+ var $search_option;
+
+ /**
+ * logical combination of searchwords (and, or)
+ * @var string
+ */
+ var $search_combination;
+
+ /**
+ * array of searchable articles
+ * @var array
+ */
+ var $searchable_arts = array();
+
+ /**
+ * article specifications
+ * @var array
+ */
+ var $article_specs = array();
+
+ /**
+ * If $protected = true => do not search articles which are offline or articles in catgeories which are offline (protected)
+ * @var boolean
+ */
+ var $protected;
+
+ /**
+ * If $dontshowofflinearticles = false => search offline articles or articles in categories which are offline
+ * @var boolean
+ */
+ var $dontshowofflinearticles;
+
+ /**
+ * If $exclude = true => the specified search range is excluded from search, otherwise included
+ * @var boolean
+ */
+ var $exclude;
+
+ /**
+ * Array of article id's with information about cms-types, occurence of keyword/searchword, similarity ...
+ * @var array
+ */
+ var $search_result = array();
+
+ /**
+ * Constructor
+ *
+ * @param array $options
+ * $options['db'] 'regexp' => DB search with REGEXP; 'like' => DB search with LIKE; 'exact' => exact match;
+ * $options['combine'] 'and', 'or' Combination of search words with AND, OR
+ * $options['exclude'] 'true' => searchrange specified in 'cat_tree', 'categories' and 'articles' is excluded; 'false' => searchrange specified in 'cat_tree', 'categories' and 'articles' is included
+ * $options['cat_tree'] e.g. array(8) => The complete tree with root 8 is in/excluded from search
+ * $options['categories'] e.g. array(10, 12) => Categories 10, 12 in/excluded
+ * $options['articles'] e.g. array(23) => Article 33 in/excluded
+ * $options['artspecs'] => e.g. array(2, 3) => search only articles with certain article specifications
+ * $options['protected'] 'true' => do not search articles which are offline (locked) or articles in catgeories which are offline (protected)
+ * $options['dontshowofflinearticles'] 'false' => search offline articles or articles in categories which are offline
+ * $options['searchable_articles'] array of article ID's which should be searchable
+ * @param DB_ConLite $oDB Optional database instance
+ * @return void
+ */
+ function Search($options, $oDB = null)
+ {
+ parent::__construct($oDB);
+
+ $this->index = new Index($oDB);
+
+ $this->cms_type = $this->index->cms_type;
+ $this->cms_type_suffix = $this->index->cms_type_suffix;
+
+ $this->search_option = (array_key_exists('db', $options)) ? strtolower($options['db']) : 'regexp';
+ $this->search_combination = (array_key_exists('combine', $options)) ? strtolower($options['combine']) : 'or';
+ $this->protected = (array_key_exists('protected', $options)) ? $options['protected'] : true;
+ $this->dontshowofflinearticles = (array_key_exists('dontshowofflinearticles', $options)) ? $options['dontshowofflinearticles'] : false;
+ $this->exclude = (array_key_exists('exclude', $options)) ? $options['exclude'] : true;
+ $this->article_specs = (array_key_exists('artspecs', $options) && is_array($options['artspecs'])) ? $options['artspecs'] : array();
+ $this->index->setCmsOptions($this->cms_type_suffix);
+
+ if (array_key_exists('searchable_articles', $options) && is_array($options['searchable_articles'])) {
+ $this->searchable_arts = $options['searchable_articles'];
+ } else {
+ $this->searchable_arts = $this->getSearchableArticles($options);
+ }
+
+ $this->intMinimumSimilarity = 50; # minimum similarity between searchword and keyword in percent
+ }
+
+ /**
+ * indexed fulltext search
+ * @param string $searchwords The search words
+ * @param string $searchwords_exclude The words, which should be excluded from search
+ * @return void
+ */
+ function searchIndex($searchwords, $searchwords_exclude = '')
+ {
+ if (strlen(trim($searchwords)) > 0) {
+ $this->search_words = $this->stripWords($searchwords);
+ } else {
+ return false;
+ }
+
+ if (strlen(trim($searchwords_exclude)) > 0) {
+ $this->search_words_exclude = $this->stripWords($searchwords_exclude);
+ }
+
+ $tmp_searchwords = array();
+ foreach ($this->search_words as $word) {
+ if ($this->search_option == 'like') {
+ $word = "'%" . $word . "%'";
+ } elseif ($this->search_option == 'exact') {
+ $word = "'" . $word . "'";
+ }
+ array_push($tmp_searchwords, $word);
+ }
+
+ if (count($this->search_words_exclude) > 0) {
+ foreach($this->search_words_exclude as $word) {
+ if ($this->search_option == 'like') {
+ $word = "'%" . $word . "%'";
+ } elseif ($this->search_option == 'exact') {
+ $word = "'" . $word . "'";
+ }
+ array_push($tmp_searchwords, $word);
+ array_push($this->search_words, $word);
+ }
+ }
+
+ if(count($tmp_searchwords) == 0) return false;
+
+ if ($this->search_option == 'regexp') {
+ // regexp search
+ $kwSql = "keyword REGEXP '" . implode('|', $tmp_searchwords) . "'";
+ } elseif ($this->search_option == 'like') {
+ // like search
+ $search_like = implode(" OR keyword LIKE ", Contenido_Security::escapeDB($tmp_searchwords, $this->db));
+ $kwSql = "keyword LIKE '" . $search_like;
+ } elseif ($this->search_option == 'exact') {
+ // exact match
+ $search_exact = implode(" OR keyword = ", Contenido_Security::escapeDB($tmp_searchwords, $this->db));
+ $kwSql = "keyword LIKE '" . $search_exact;
+ }
+
+ $sql = "SELECT keyword, auto FROM " . $this->cfg['tab']['keywords']
+ . " WHERE idlang=" . Contenido_Security::toInteger($this->lang) . " AND " . $kwSql . " ";
+ $this->_debug('sql', $sql);
+ $this->db->query($sql);
+
+ while ($this->db->next_record()) {
+
+ $tmp_index_string = preg_split('/&/', $this->db->f('auto'), -1, PREG_SPLIT_NO_EMPTY);
+
+ $this->_debug('index', $this->db->f('auto'));
+
+ $tmp_index = array();
+ foreach ($tmp_index_string as $string) {
+ $tmp_string = preg_replace('/[=\(\)]/', ' ', $string);
+ $tmp_index[] = preg_split('/\s/', $tmp_string, -1, PREG_SPLIT_NO_EMPTY);
+ }
+ $this->_debug('tmp_index', $tmp_index);
+
+ foreach ($tmp_index as $string) {
+ $artid = $string[0];
+
+ // filter nonsearchable articles
+ if (in_array($artid, $this->searchable_arts)) {
+
+ $cms_place = $string[2];
+ $keyword = $this->db->f('keyword');
+ $percent = 0;
+ $similarity = 0;
+ foreach ($this->search_words as $word) {
+ similar_text($word, $keyword, $percent); // computes similarity between searchword and keyword in percent
+ if ($percent > $similarity) {
+ $similarity = $percent;
+ $searchword = $word;
+ }
+ }
+
+ $tmp_cmstype = preg_split('/[,]/', $cms_place, -1, PREG_SPLIT_NO_EMPTY);
+ $this->_debug('tmp_cmstype', $tmp_cmstype);
+
+ $tmp_cmstype2 = array();
+ foreach ($tmp_cmstype as $type) {
+ $tmp_cmstype2[] = preg_split('/-/', $type, -1, PREG_SPLIT_NO_EMPTY);
+ }
+ $this->_debug('tmp_cmstype2', $tmp_cmstype2);
+
+ foreach ($tmp_cmstype2 as $type) {
+ if (!$this->index->checkCmsType($type[0])) {
+ // search for specified cms-types
+ if ($similarity >= $this->intMinimumSimilarity) {
+ // include article into searchresult set only if
+ // similarity between searchword and keyword is big enough
+ $this->search_result[$artid][$type[0]][] = $type[1];
+ $this->search_result[$artid]['keyword'][] = $this->db->f('keyword');
+ $this->search_result[$artid]['search'][] = $searchword;
+ $this->search_result[$artid]['occurence'][] = $string[1];
+ $this->search_result[$artid]['debug_similarity'][] = $percent;
+ if ($similarity > $this->search_result[$artid]['similarity']) {
+ $this->search_result[$artid]['similarity'] = $similarity;
+ }
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ if ($this->search_combination == 'and') {
+ // all search words must appear in the article
+ foreach ($this->search_result as $article => $val) {
+ if (!count(array_diff($this->search_words, $val['search'])) == 0) {
+ //$this->rank_structure[$article] = $rank[$article];
+ unset($this->search_result[$article]);
+ }
+ }
+ }
+
+ if (count($this->search_words_exclude) > 0) {
+ // search words to be excluded must not appear in article
+ foreach ($this->search_result as $article => $val) {
+ if (!count(array_intersect($this->search_words_exclude, $val['search'])) == 0) {
+ //$this->rank_structure[$article] = $rank[$article];
+ unset($this->search_result[$article]);
+ }
+ }
+ }
+
+ $this->_debug('$this->search_result', $this->search_result);
+ $this->_debug('$this->searchable_arts', $this->searchable_arts);
+
+ return $this->search_result;
+ }
+
+ /**
+ * @param $cms_options The cms-types (htmlhead, html, ...) which should explicitly be searched
+ * @return void
+ */
+ function setCmsOptions($cms_options)
+ {
+ if (is_array($cms_options) && count($cms_options) > 0) {
+ $this->index->setCmsOptions($cms_options);
+ }
+ }
+
+ /**
+ * @param $searchwords The search-words
+ * @return Array of stripped search-words
+ */
+ function stripWords($searchwords)
+ {
+ $tmp_words = array();
+ $searchwords = stripslashes($searchwords); // remove backslash
+ $searchwords = strip_tags($searchwords); // remove html tags
+
+ $tmp_words = preg_split('/[\s,]+/', trim($searchwords)); // split the phrase by any number of commas or space characters
+
+ $tmp_searchwords = array();
+
+ foreach ($tmp_words as $word) {
+ $word = strtolower($word);
+ $word = $this->index->removeSpecialChars(trim($word));
+ if (strlen($word) > 1) {
+ array_push($tmp_searchwords, $word);
+ }
+ }
+
+ return array_unique($tmp_searchwords);
+ }
+
+ /**
+ * Returns the category tree array.
+ *
+ * @param int $cat_start Root of a category tree
+ * @return array Category Tree
+ * @todo This is not the job for search, should be oursourced...
+ */
+ function getSubTree($cat_start)
+ {
+ $sql = "SELECT
+ B.idcat, B.parentid
+ FROM
+ ".$this->cfg['tab']['cat_tree']." AS A,
+ ".$this->cfg['tab']['cat']." AS B,
+ ".$this->cfg['tab']['cat_lang']." AS C
+ WHERE
+ A.idcat = B.idcat AND
+ B.idcat = C.idcat AND
+ C.idlang = '".Contenido_Security::toInteger($this->lang)."' AND
+ B.idclient = '".Contenido_Security::toInteger($this->client)."'
+ ORDER BY
+ idtree";
+ $this->_debug('sql', $sql);
+ $this->db->query($sql);
+
+ $aSubCats = array();
+ $i = false;
+
+ while ($this->db->next_record()) {
+ if ($this->db->f('parentid') < $cat_start) {
+ // ending part of tree
+ $i = false;
+ }
+
+ if ($this->db->f('idcat') == $cat_start) {
+ // starting part of tree
+ $i = true;
+ }
+
+ if ($i == true) {
+ $aSubCats[] = $this->db->f('idcat');
+ }
+ }
+ return $aSubCats;
+ }
+
+ /**
+ * Returns list of searchable article ids.
+ *
+ * @param array $search_range
+ * @return array Articles in specified search range
+ */
+ function getSearchableArticles($search_range)
+ {
+
+ $cat_range = array();
+ if (array_key_exists('cat_tree', $search_range) && is_array($search_range['cat_tree'])) {
+ if (count($search_range['cat_tree']) > 0) {
+ foreach($search_range['cat_tree'] as $cat) {
+ $cat_range = array_merge($cat_range, $this->getSubTree($cat));
+ }
+ }
+ }
+
+ if (array_key_exists('categories', $search_range) && is_array($search_range['categories'])) {
+ if (count($search_range['categories']) > 0) {
+ $cat_range = array_merge($cat_range, $search_range['categories']);
+ }
+ }
+
+ $cat_range = array_unique($cat_range);
+ $sCatRange = implode("','", $cat_range);
+
+ if (array_key_exists('articles', $search_range) && is_array($search_range['articles'])) {
+ if (count($search_range['articles']) > 0) {
+ $sArtRange = implode("','", $search_range['articles']);
+ } else {
+ $sArtRange = '';
+ }
+ }
+
+ $id_arts = array();
+
+ if ($this->protected == true) {
+ $protected = " C.public = '1' AND C.visible = '1' AND B.online = '1' ";
+ } else {
+ if ($this->dontshowofflinearticles == true) {
+ $protected = " C.visible = '1' AND B.online = '1' ";
+ } else {
+ $protected = " 1 ";
+ }
+ }
+
+ if ($this->exclude == true) {
+ // exclude searchrange
+ $sSearchRange = " A.idcat NOT IN ('".$sCatRange."') AND B.idart NOT IN ('".$sArtRange."') AND ";
+ } else {
+ // include searchrange
+ if (strlen($sArtRange) > 0) {
+ $sSearchRange = " A.idcat IN ('".$sCatRange."') AND B.idart IN ('".$sArtRange."') AND ";
+ } else {
+ $sSearchRange = " A.idcat IN ('".$sCatRange."') AND ";
+ }
+ }
+
+ if (count($this->article_specs) > 0) {
+ $sArtSpecs = " B.artspec IN ('".implode("','", $this->article_specs)."') AND ";
+ } else {
+ $sArtSpecs = '';
+ }
+
+ $sql = "SELECT
+ A.idart
+ FROM
+ ".$this->cfg["tab"]["cat_art"]." as A,
+ ".$this->cfg["tab"]["art_lang"]." as B,
+ ".$this->cfg["tab"]["cat_lang"]." as C
+ WHERE
+ ".$sSearchRange."
+ B.idlang = '".Contenido_Security::toInteger($this->lang)."' AND
+ C.idlang = '".Contenido_Security::toInteger($this->lang)."' AND
+ A.idart = B.idart AND
+ A.idcat = C.idcat AND
+ ".$sArtSpecs."
+ ".$protected." ";
+ $this->_debug('sql', $sql);
+ $this->db->query($sql);
+ while ($this->db->next_record()) {
+ $id_arts[] = $this->db->f('idart');
+ }
+ return $id_arts;
+ }
+
+ /**
+ * Fetch all article specifications which are online,
+ *
+ * @return array Array of article specification Ids
+ */
+ function getArticleSpecifications()
+ {
+ $sql = "SELECT
+ idartspec
+ FROM
+ ".$this->cfg['tab']['art_spec']."
+ WHERE
+ client = ".Contenido_Security::toInteger($this->client)." AND
+ lang = ".Contenido_Security::toInteger($this->lang)." AND
+ online = 1 ";
+ $this->_debug('sql', $sql);
+ $this->db->query($sql);
+ $aArtspec = array();
+ while ($this->db->next_record()) {
+ $aArtspec[] = $this->db->f('idartspec');
+ }
+ return $aArtspec;
+ }
+
+ /**
+ * Set article specification
+ * @param int $iArtspecID
+ * @return void
+ */
+ function setArticleSpecification($iArtspecID)
+ {
+ array_push($this->article_specs, $iArtspecID);
+ }
+
+ /**
+ * Add all article specifications matching name of article specification (client dependent but language independent)
+ * @param string $sArtSpecName
+ * @return void
+ */
+ function addArticleSpecificationsByName($sArtSpecName)
+ {
+ if (!isset($sArtSpecName) || strlen($sArtSpecName) == 0) {
+ return false;
+ }
+
+ $sql = "SELECT
+ idartspec
+ FROM
+ ".$this->cfg['tab']['art_spec']."
+ WHERE
+ client = ".Contenido_Security::toInteger($this->client)." AND
+ artspec = '".Contenido_Security::escapeDB($sArtSpecName, $this->db)."' ";
+ $this->_debug('sql', $sql);
+ $this->db->query($sql);
+ while ($this->db->next_record()) {
+ array_push($this->article_specs, $this->db->f('idartspec'));
+ }
+ }
+
+}
+
+
+/**
+ * Contenido API - SearchResult Object
+ *
+ * This object ranks and displays the result of the indexed fulltext search.
+ * If you are not comfortable with this API feel free to use your own methods to display the search results.
+ * The search result is basically an array with article ID's.
+ *
+ * If $search_result = $search->searchIndex($searchword, $searchwordex);
+ *
+ * use object with
+ *
+ * $oSearchResults = new SearchResult($search_result, 10);
+ *
+ * $oSearchResults->setReplacement('', ' '); // html-tags to emphasize the located searchwords
+ *
+ * $num_res = $oSearchResults->getNumberOfResults();
+ * $num_pages = $oSearchResults->getNumberOfPages();
+ * $res_page = $oSearchResults->getSearchResultPage(1); // first result page
+ * foreach ($res_page as $key => $val) {
+ * $headline = $oSearchResults->getSearchContent($key, 'HTMLHEAD');
+ * $first_headline = $headline[0];
+ * $text = $oSearchResults->getSearchContent($key, 'HTML');
+ * $first_text = $text[0];
+ * $similarity = $oSearchResults->getSimilarity($key);
+ * $iOccurrence = $oSearchResults->getOccurrence($key);
+ * }
+ *
+ * @version 1.0.0
+ *
+ * @author Willi Man
+ * @copyright four for business AG
+ *
+ */
+
+class SearchResult extends SearchBaseAbstract
+{
+ /**
+ * Instance of class Index
+ * @var object
+ */
+ var $index;
+
+ /**
+ * Number of results
+ * @var int
+ */
+ var $results;
+
+ /**
+ * Number of result pages
+ * @var int
+ */
+ var $pages;
+
+ /**
+ * Current result page
+ * @var int
+ */
+ var $result_page;
+
+ /**
+ * Results per page to display
+ * @var int
+ */
+ var $result_per_page;
+
+ /**
+ * Array of html-tags to emphasize the searchwords
+ * @var array
+ */
+ var $replacement = array();
+
+ /**
+ * Array of article id's with ranking information
+ * @var array
+ */
+ var $rank_structure = array();
+
+ /**
+ * Array of result-pages with array's of article id's
+ * @var array
+ */
+ var $ordered_search_result = array();
+
+ /**
+ * Array of article id's with information about cms-types, occurence of keyword/searchword, similarity ...
+ * @var array
+ */
+ var $search_result = array();
+
+ /**
+ * Compute ranking factor for each search result and order the search results by ranking factor
+ * NOTE: The ranking factor is the sum of occurences of matching searchterms weighted by similarity (in %) between searchword
+ * and matching word in the article.
+ * TODO: One can think of more sophisticated ranking strategies. One could use the content type information for example
+ * because a matching word in the headline (CMS_HEADLINE[1]) could be weighted more than a matching word in the text (CMS_HTML[1]).
+ *
+ * @param array $search_result List of article ids
+ * @param int $result_per_page Number of items per page
+ * @param DB_ConLite $oDB Optional db instance
+ * @param bool $bDebug Optional flag to enable debugging
+ */
+ function SearchResult($search_result, $result_per_page, $oDB = null, $bDebug = false)
+ {
+ parent::__construct($oDB, $bDebug);
+
+ $this->index = new Index($oDB);
+
+ $this->search_result = $search_result;
+ $this->_debug('$this->search_result', $this->search_result);
+
+ $this->result_per_page = $result_per_page;
+ $this->results = count($this->search_result);
+
+ # compute ranking factor for each search result
+ foreach ($this->search_result as $article => $val) {
+ $this->rank_structure[$article] = $this->getOccurrence($article) * ( $this->getSimilarity($article) / 100);
+ }
+ $this->_debug('$this->rank_structure', $this->rank_structure);
+
+ $this->setOrderedSearchResult($this->rank_structure, $this->result_per_page);
+ $this->pages = count($this->ordered_search_result);
+ $this->_debug('$this->ordered_search_result', $this->ordered_search_result);
+ }
+
+ /**
+ * @param $ranked_search
+ * @param $result_per_page
+ * @return void
+ */
+ function setOrderedSearchResult($ranked_search, $result_per_page)
+ {
+ asort($ranked_search);
+
+ $sorted_rank = array_reverse($ranked_search, true);
+
+ if (isset($result_per_page) && $result_per_page > 0) {
+ $split_result = array();
+ $split_result = array_chunk($sorted_rank, $result_per_page, true);
+ $this->ordered_search_result = $split_result;
+ } else {
+ $this->ordered_search_result[] = $sorted_rank;
+ }
+ }
+
+ /**
+ * @param $cms_type
+ * @param $art_id Id of an article
+ * @return Content of an article, specified by it's content type
+ */
+ function getContent($art_id, $cms_type, $id = 0)
+ {
+ $article = new Article($art_id, $this->client, $this->lang);
+ return $article->getContent($cms_type, $id);
+ }
+
+ /**
+ * @param $cms_type Content type
+ * @param $art_id Id of an article
+ * @return Content of an article in search result, specified by its type
+ */
+ function getSearchContent($art_id, $cms_type, $cms_nr = NULL)
+ {
+ $cms_type = strtoupper($cms_type);
+ if (strlen($cms_type) > 0) {
+ if (!stristr($cms_type, 'cms_')) {
+ if (in_array($cms_type, $this->index->cms_type_suffix)) {
+ $cms_type = 'CMS_' . $cms_type;
+ }
+ } else {
+ if (!array_key_exists($cms_type, $this->index->cms_type)) {
+ return array();
+ }
+ }
+ }
+
+ $article = new Article($art_id, $this->client, $this->lang);
+ $content = array();
+ if (isset($this->search_result[$art_id][$cms_type])) {
+ // if searchword occurs in cms_type
+ $search_words = $this->search_result[$art_id]['search'];
+ $search_words = array_unique($search_words);
+
+ $id_type = $this->search_result[$art_id][$cms_type];
+ $id_type = array_unique($id_type);
+
+ if (isset($cms_nr) && is_numeric($cms_nr)) {
+ // get content of cms_type[cms_nr]
+ //build consistent escaped string(Timo Trautmann) 2008-04-17
+ $cms_content = clHtmlEntities(clHtmlEntityDecode(strip_tags($article->getContent($cms_type, $cms_nr))));
+ if (count($this->replacement) == 2) {
+ foreach($search_words as $word) {
+ //build consistent escaped string, replace ae ue .. with original html entities (Timo Trautmann) 2008-04-17
+ $word = clHtmlEntities(clHtmlEntityDecode($this->index->addSpecialUmlauts($word)));
+ $match = array();
+ preg_match("/$word/i", $cms_content, $match);
+ if (isset($match[0])) {
+ $pattern = $match[0];
+ $replacement = $this->replacement[0].$pattern.$this->replacement[1];
+ $cms_content = preg_replace("/$pattern/i", $replacement, $cms_content); // emphasize located searchwords
+ }
+ }
+ }
+ $content[] = htmlspecialchars_decode($cms_content);
+ } else {
+ // get content of cms_type[$id], where $id are the cms_type numbers found in search
+ foreach ($id_type as $id) {
+ $cms_content = strip_tags($article->getContent($cms_type, $id));
+
+ if (count($this->replacement) == 2) {
+ foreach($search_words as $word) {
+ preg_match("/$word/i", $cms_content, $match);
+ if (isset($match[0])) {
+ $pattern = $match[0];
+ $replacement = $this->replacement[0].$pattern.$this->replacement[1];
+ $cms_content = preg_replace("/$pattern/i", $replacement, $cms_content); // emphasize located searchwords
+ }
+ }
+ }
+ $content[] = $cms_content;
+ }
+ }
+
+ } else {
+ // searchword was not found in cms_type
+ if (isset($cms_nr) && is_numeric($cms_nr)) {
+ $content[] = strip_tags($article->getContent($cms_type, $cms_nr));
+ } else {
+ $art_content = $article->getContent($cms_type);
+ if (count($art_content) > 0) {
+ foreach ($art_content as $val) {
+ $content[] = strip_tags($val);
+ }
+ }
+ }
+ }
+ return $content;
+ }
+
+ /**
+ * Returns articles in page.
+ *
+ * @param int $page_id
+ * @return array Artices in page $page_id
+ */
+ function getSearchResultPage($page_id)
+ {
+ $this->result_page = $page_id;
+ $result_page = $this->ordered_search_result[$page_id - 1];
+ return $result_page;
+ }
+
+ /**
+ * Returns number of result pages
+ * @return int
+ */
+ function getNumberOfPages()
+ {
+ return $this->pages;
+ }
+
+ /**
+ * Returns number of results
+ * @return int
+ */
+ function getNumberOfResults()
+ {
+ return $this->results;
+ }
+
+ /**
+ * @param $art_id Id of an article
+ * @return Similarity between searchword and matching word in article
+ */
+ function getSimilarity($art_id)
+ {
+ return $this->search_result[$art_id]['similarity'];
+ }
+
+ /**
+ * @param $art_id Id of an article
+ * @return Number of matching searchwords found in article
+ */
+ function getOccurrence($art_id)
+ {
+ $aOccurence = $this->search_result[$art_id]['occurence'];
+ $iSumOfOccurence = 0;
+ for ($i = 0; $i < count($aOccurence); $i++) {
+ $iSumOfOccurence += $aOccurence[$i];
+ }
+
+ return $iSumOfOccurence;
+ }
+
+ /**
+ * @param string $rep1 The opening html-tag to emphasize the searchword e.g. ''
+ * @param string $rep2 The closing html-tag e.g. ' '
+ * @return void
+ */
+ function setReplacement($rep1, $rep2)
+ {
+ if (strlen(trim($rep1)) > 0 && strlen(trim($rep2)) > 0) {
+ array_push($this->replacement, $rep1);
+ array_push($this->replacement, $rep2);
+ }
+ }
+
+ /**
+ * @param $artid
+ * @return Category Id
+ * @todo Is not job of search, should be outsourced!
+ */
+ function getArtCat($artid)
+ {
+ $sql = "SELECT idcat FROM ".$this->cfg['tab']['cat_art']."
+ WHERE idart = ".Contenido_Security::toInteger($artid)." ";
+ $this->db->query($sql);
+ if ($this->db->next_record()) {
+ return $this->db->f('idcat');
+ }
+ }
+
+}
+
+/**
+ * @deprecated
+ * @since 2008-07-11
+ *
+ */
+class Search_helper {
+
+ var $oDb = NULL;
+
+ function search_helper ($oDb, $lang, $client) {
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.security.php b/conlite/classes/class.security.php
new file mode 100644
index 0000000..db01960
--- /dev/null
+++ b/conlite/classes/class.security.php
@@ -0,0 +1,503 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release 4.8.7
+ *
+ * @TODO: Some features are the same as in HttpInputValidator (see contenido/classes/class.httpinputvalidator.php),
+ * merge them...
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+/**
+ * Contenido Security exception class
+ */
+class Contenido_Security_Exception extends Exception
+{
+ /**
+ * Logging flag. Set to true for logging invalid calls.
+ * @access protected
+ * @static
+ * @var boolean
+ */
+ protected static $_logging = false;
+
+ /**
+ * @see Exception::__construct()
+ */
+ public function __construct($sMessage, $sParamName)
+ {
+ parent::__construct($sMessage);
+
+ // check if logging is enabled
+ if ( self::$_logging == true ) {
+ $sLogFile = realpath( dirname(__FILE__) . '/../logs/') . '/security.txt';
+
+ $sFileContent = '---------' . PHP_EOL;
+ $sFileContent .= "Invalid call caused by parameter '" . $sParamName . "' at " . date("c") . PHP_EOL;
+ $sFileContent .= "Original value was '" . $_REQUEST[$sParamName] . "'" . PHP_EOL;
+ $sFileContent .= "URL: " . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] . " (Protocol: " . $_SERVER['SERVER_PROTOCOL'] . ")" . PHP_EOL;
+
+ file_put_contents($sLogFile, $sFileContent, FILE_APPEND);
+ }
+
+ // strictly die here
+ die( $sMessage );
+ exit;
+ }
+}
+
+
+/**
+ * Contenido Security class
+ */
+class Contenido_Security
+{
+ /**
+ * Accepted backend languages
+ * @var array
+ */
+ protected static $_acceptedBelangValues = array('de_DE', 'en_US', 'fr_FR', 'it_IT', 'nl_NL');
+
+ /**
+ * Request paramaters, which must be numeric
+ * @var array
+ */
+ protected static $_mustbeNumericParameters = array(
+ 'client', 'changeclient', 'lang', 'changelang', 'idcat', 'idcatlang', 'idart', 'idartlang',
+ 'idcatart'
+ );
+
+ /**
+ * Request paramaters, which are strictly forbidden
+ * @var array
+ */
+ protected static $_forbiddenParameters = array('cfg', 'cfgClient', 'contenido_path', '_PHPLIB', 'db', 'sess');
+
+
+ /**
+ * Returns accepted backend language values
+ *
+ * @return array
+ */
+ public static function getAcceptedBelangValues()
+ {
+ return self::$_acceptedBelangValues;
+ }
+
+
+ /**
+ * Returns must be numeric request parameters
+ *
+ * @return array
+ */
+ public static function getMustbeNumericParameters()
+ {
+ return self::$_mustbeNumericParameters;
+ }
+
+
+ /**
+ * Returns forbidden request parameters
+ *
+ * @return array
+ */
+ public static function getForbiddenParameters()
+ {
+ return self::$_forbiddenParameters;
+ }
+
+ /**
+ * Escapes string using contenido urlencoding method and escapes string for inserting
+ * @static
+ *
+ * @param string $sString Input string
+ * @param DB_ConLite $oDb Contenido database object
+ * @return string Filtered string
+ */
+ public static function filter($sString, $oDb)
+ {
+ $sString = self::toString($sString);
+ if (defined('CONTENIDO_STRIPSLASHES')) {
+ $sString = stripslashes($sString);
+ }
+ return self::escapeDB(clHtmlSpecialChars(urlencode($sString)), $oDb, false);
+ }
+
+ /**
+ * Reverts effect of method filter()
+ * @static
+ *
+ * @param string $sString Input string
+ * @return string Unfiltered string
+ */
+ public static function unFilter($sString)
+ {
+ $sString = self::toString($sString);
+ return urldecode(htmldecode(self::unEscapeDB($sString)));
+ }
+
+ /**
+ * Check: Has the variable an boolean value?
+ * @static
+ *
+ * @param string $sVar Input string
+ * @return boolean Check state
+ */
+ public static function isBoolean($sVar)
+ {
+ $sTempVar = $sVar;
+ $sTemp2Var = self::toBoolean($sVar);
+ return ($sTempVar === $sTemp2Var);
+ }
+
+ /**
+ * Check: Is the variable an integer?
+ * @static
+ *
+ * @param string $sVar Input string
+ * @return boolean Check state
+ */
+ public static function isInteger($sVar)
+ {
+ return (preg_match('/^[0-9]+$/', $sVar));
+ }
+
+ /**
+ * Check: Is the variable an string?
+ * @static
+ *
+ * @param string $sVar Input string
+ * @return boolean Check state
+ */
+ public static function isString($sVar)
+ {
+ return (is_string($sVar));
+ }
+
+ /**
+ * Check: Is the variable formatted as MySQL DATE 'YYYY-MM-DD'
+ * @static
+ *
+ * @author Ortwin Pinke
+ * @since ConLite 0.1.0
+ *
+ * @param string $sVar given date/string
+ * @param boolean $bCheckValid additional use of checkdate for validation
+ * @return boolean true|false
+ */
+ public static function isMySQLDate($sVar, $bCheckValid = false) {
+ $sVar = trim($sVar);
+ $bFormatOk = preg_match("/^\d{4}-\d{2}-\d{2}$/", $sVar);
+ if($bCheckValid && $bFormatOk) {
+ $aDateParts = explode("-", $sVar);
+ return checkdate($aDateParts[1], $aDateParts[2], $aDateParts[0]);
+ } elseif($bFormatOk) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check: Is the variable formatted as MySQL DATETIME 'YYYY-MM-DD HH:MM:SS'
+ * @static
+ *
+ * @author Ortwin Pinke
+ * @since ConLite 0.1.0
+ *
+ * @param string $Var given datetime/string
+ * @param boolean $bCheckValid additional use of checkdate for validation
+ * @return boolean true|false
+ */
+ public static function isMySQLDateTime($sVar, $bCheckValid = false) {
+ $sVar = trim($sVar);
+ $bFormatOk = preg_match("/^\d{4}-\d{2}-\d{2} [0-2][0-3]:[0-5][0-9]:[0-5][0-9]$/", $sVar);
+ if($bCheckValid && $bFormatOk) {
+ $aDateTimeParts = explode(" ", $sVar);
+ $aDateParts = explode("-", $aDateTimeParts[0]);
+ return checkdate($aDateParts[1], $aDateParts[2], $aDateParts[0]);
+ } elseif($bFormatOk) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Convert an string to an boolean
+ * @static
+ *
+ * @deprecated since ConLite 0.1.0, this function will be deleted in future versions, use buildin PHP-functions
+ *
+ * @param string $sString Input string
+ * @return boolean Type casted input string
+ */
+ public static function toBoolean($sString)
+ {
+ return (bool) $sString;
+ }
+
+ /**
+ * Convert an string to an integer
+ * @static
+ *
+ * @deprecated since ConLite 0.1.0, this function will be deleted in future versions, use buildin PHP-functions
+ *
+ * @param string $sString Input string
+ * @return integer Type casted input string
+ */
+ public static function toInteger($sString)
+ {
+ return (int) $sString;
+ }
+
+ /**
+ * Convert an string
+ * @static
+ *
+ * @param string $sString Input string
+ * @param boolean $bHTML If true check with strip_tags and stripslashes
+ * @param string $sAllowableTags Allowable tags if $bHTML is true
+ * @return string Converted string
+ */
+ public static function toString($sString, $bHTML = false, $sAllowableTags = '')
+ {
+ $sString = (string) $sString;
+ if ($bHTML == true) {
+ $sString = strip_tags(stripslashes($sString), $sAllowableTags);
+ }
+ return $sString;
+ }
+
+ /**
+ * Checks some Contenido core related request parameters against XSS
+ *
+ * @access public
+ * @return bool|void True on success otherwhise nothing.
+ * @throws Contenido_Security_Exception if one of the checks fails
+ */
+ public static function checkRequests()
+ {
+ // Check backend language
+ self::checkRequestBelang();
+
+ // Check for forbidden parameters
+ self::checkRequestForbiddenParameter();
+
+ // Check for parameters who must be numeric
+ self::checkRequestMustbeNumericParameter();
+
+ // Check session id
+ self::checkRequestSession();
+
+ return true;
+ }
+
+ /**
+ * Checks backend language parameter in request.
+ *
+ * @return bool|void True on success otherwhise nothing.
+ * @throws Contenido_Security_Exception if existing backend language parameter is not valid
+ */
+ public static function checkRequestBelang()
+ {
+ if (isset($_REQUEST['belang'])) {
+ $_REQUEST['belang'] = strval($_REQUEST['belang']);
+ if (!in_array($_REQUEST['belang'], self::$_acceptedBelangValues)) {
+ throw new Contenido_Security_Exception('Please use a valid language!', 'belang');
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks for forbidden parameters in request.
+ *
+ * @return bool|void True on success otherwhise nothing.
+ * @throws Contenido_Security_Exception if the request contains one of forbidden parameters.
+ */
+ public static function checkRequestForbiddenParameter()
+ {
+ foreach (self::$_forbiddenParameters as $param) {
+ if (isset($_REQUEST[$param])) {
+ throw new Contenido_Security_Exception('Invalid call!', $param);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks for parameters in request who must be numeric.
+ *
+ * Contrary to other request checks, this method don't throws a exception. It just insures that
+ * incomming values are really numeric, by type casting them to an integer.
+ *
+ * @return bool Just true
+ */
+ public static function checkRequestMustbeNumericParameter()
+ {
+ foreach (self::$_mustbeNumericParameters as $sParamName) {
+ if ( isset($_REQUEST[$sParamName]) ) {
+ $sValue = $_REQUEST[$sParamName];
+ if ( strlen($sValue) > 0 && self::isInteger($sValue) == false ) {
+ throw new Contenido_Security_Exception('Invalid call', $sParamName);
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks/Validates existing contenido session request parameter.
+ *
+ * @return bool|void True on success otherwhise nothing.
+ * @throws Contenido_Security_Exception if contenido parameter in request don't matches the required format
+ */
+ public static function checkRequestSession()
+ {
+ if (isset($_REQUEST['contenido']) && !preg_match('/^[0-9a-f]{32}$/', $_REQUEST['contenido'])) {
+ if ($_REQUEST['contenido'] != '') {
+ throw new Contenido_Security_Exception('Invalid call', 'contenido');
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks also contenido-var (session) to ascii, but works as a wrapper to checkRequestSession().
+ *
+ * @access public
+ * @return true
+ * @throws Contenido_Security_Exception if contenido parameter in request don't matches the required format
+ * @deprecated Use checkRequestSession() instead due to better naming conventions
+ * @TODO: Should be removed, but later in few years...
+ */
+ public static function checkSession()
+ {
+ return self::checkRequestSession();
+ }
+
+ /**
+ * Checks some global variables at frontend like $lang, $client, $changelang, $changeclient,
+ * $tmpchangelang.
+ *
+ * Validates client and language related variables and takes care that their content is
+ * really a numeric value.
+ *
+ * Logic in this function is taken over from front_content.php (v 4.8.12, line 164 - 192).
+ *
+ * @TODO: Need a solution for used globals
+ *
+ * @return void
+ */
+ public static function checkFrontendGlobals()
+ {
+ global $tmpchangelang, $savedlang, $lang, $changelang, $load_lang, $changeclient, $client, $load_client;
+
+ if (isset($tmpchangelang) && is_numeric($tmpchangelang) && $tmpchangelang > 0) {
+ // savelang is needed to set language before closing the page, see
+ // {frontend_clientdir}/front_content.php before page_close()
+ $savedlang = $lang;
+ $lang = $tmpchangelang;
+ }
+
+ // Check basic incomming data
+ if (isset($changeclient) && !is_numeric($changeclient)) {
+ unset($changeclient);
+ }
+ if (isset($client) && !is_numeric($client)) {
+ unset($client);
+ }
+ if (isset($changelang) && !is_numeric($changelang)) {
+ unset($changelang);
+ }
+ if (isset($lang) && !is_numeric($lang)) {
+ unset($lang);
+ }
+
+ // Change client
+ if (isset($changeclient)){
+ $client = $changeclient;
+ unset($lang);
+ unset($load_lang);
+ }
+
+ // Change language
+ if (isset($changelang)) {
+ $lang = $changelang;
+ }
+
+ // Initialize client
+ if (!isset($client)) {
+ // load_client defined in {frontend_clientdir}/config.php
+ $client = $load_client;
+ }
+ }
+
+ /**
+ * Escaped an query-string with mysql_real_escape_string
+ * @static
+ *
+ * @param string $sString Input string
+ * @param DB_ConLite $oDB Contenido database object
+ * @param boolean $bUndoAddSlashes Flag for undo addslashes (optional, default: true)
+ * @return string Converted string
+ */
+ public static function escapeDB($sString, $oDB = null, $bUndoAddSlashes = true)
+ {
+ if (!is_object($oDB)) {
+ return self::escapeString($sString);
+ } else {
+ if (defined('CONTENIDO_STRIPSLASHES') && $bUndoAddSlashes == true) {
+ $sString = stripslashes($sString);
+ }
+ return $oDB->Escape($sString);
+ }
+ }
+
+ /**
+ * Escaped an query-string with addslashes
+ * @static
+ *
+ * @param string $sString Input string
+ * @return string Converted string
+ */
+ public static function escapeString($sString)
+ {
+ $sString = (string) $sString;
+ if (defined('CONTENIDO_STRIPSLASHES')) {
+ $sString = stripslashes($sString);
+ }
+ return addslashes($sString);
+ }
+
+ /**
+ * Un-quote string quoted with escapeDB()
+ * @static
+ *
+ * @param string $sString Input string
+ * @return string Converted string
+ */
+ public static function unescapeDB($sString)
+ {
+ return stripslashes($sString);
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.smtp.php b/conlite/classes/class.smtp.php
new file mode 100644
index 0000000..6900671
--- /dev/null
+++ b/conlite/classes/class.smtp.php
@@ -0,0 +1,1065 @@
+smtp_conn = 0;
+ $this->error = null;
+ $this->helo_rply = null;
+
+ $this->do_debug = 0;
+ }
+
+ /*************************************************************
+ * CONNECTION FUNCTIONS *
+ ***********************************************************/
+
+ /**
+ * Connect to the server specified on the port specified.
+ * If the port is not specified use the default SMTP_PORT.
+ * If tval is specified then a connection will try and be
+ * established with the server for that number of seconds.
+ * If tval is not specified the default is 30 seconds to
+ * try on the connection.
+ *
+ * SMTP CODE SUCCESS: 220
+ * SMTP CODE FAILURE: 421
+ * @access public
+ * @return bool
+ */
+ function Connect($host,$port=0,$tval=30) {
+ # set the error val to null so there is no confusion
+ $this->error = null;
+
+ # make sure we are __not__ connected
+ if($this->connected()) {
+ # ok we are connected! what should we do?
+ # for now we will just give an error saying we
+ # are already connected
+ $this->error =
+ array("error" => "Already connected to a server");
+ return false;
+ }
+
+ if(empty($port)) {
+ $port = $this->SMTP_PORT;
+ }
+
+ #connect to the smtp server
+ $this->smtp_conn = fsockopen($host, # the host of the server
+ $port, # the port to use
+ $errno, # error number if any
+ $errstr, # error message if any
+ $tval); # give up after ? secs
+ # verify we connected properly
+ if(empty($this->smtp_conn)) {
+ $this->error = array("error" => "Failed to connect to server",
+ "errno" => $errno,
+ "errstr" => $errstr);
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": $errstr ($errno)" . $this->CRLF;
+ }
+ return false;
+ }
+
+ # sometimes the SMTP server takes a little longer to respond
+ # so we will give it a longer timeout for the first read
+ // Windows still does not have support for this timeout function
+ if(substr(PHP_OS, 0, 3) != "WIN")
+ socket_set_timeout($this->smtp_conn, $tval, 0);
+
+ # get any announcement stuff
+ $announce = $this->get_lines();
+
+ # set the timeout of any socket functions at 1/10 of a second
+ //if(function_exists("socket_set_timeout"))
+ // socket_set_timeout($this->smtp_conn, 0, 100000);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;
+ }
+
+ return true;
+ }
+
+ /**
+ * Performs SMTP authentication. Must be run after running the
+ * Hello() method. Returns true if successfully authenticated.
+ * @access public
+ * @return bool
+ */
+ function Authenticate($username, $password) {
+ // Start authentication
+ fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($code != 334) {
+ $this->error =
+ array("error" => "AUTH not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ // Send encoded username
+ fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($code != 334) {
+ $this->error =
+ array("error" => "Username not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ // Send encoded password
+ fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($code != 235) {
+ $this->error =
+ array("error" => "Password not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if connected to a server otherwise false
+ * @access private
+ * @return bool
+ */
+ function Connected() {
+ if(!empty($this->smtp_conn)) {
+ $sock_status = socket_get_status($this->smtp_conn);
+ if($sock_status["eof"]) {
+ # hmm this is an odd situation... the socket is
+ # valid but we aren't connected anymore
+ if($this->do_debug >= 1) {
+ echo "SMTP -> NOTICE:" . $this->CRLF .
+ "EOF caught while checking if connected";
+ }
+ $this->Close();
+ return false;
+ }
+ return true; # everything looks good
+ }
+ return false;
+ }
+
+ /**
+ * Closes the socket and cleans up the state of the class.
+ * It is not considered good to use this function without
+ * first trying to use QUIT.
+ * @access public
+ * @return void
+ */
+ function Close() {
+ $this->error = null; # so there is no confusion
+ $this->helo_rply = null;
+ if(!empty($this->smtp_conn)) {
+ # close the connection and cleanup
+ fclose($this->smtp_conn);
+ $this->smtp_conn = 0;
+ }
+ }
+
+
+ /***************************************************************
+ * SMTP COMMANDS *
+ *************************************************************/
+
+ /**
+ * Issues a data command and sends the msg_data to the server
+ * finializing the mail transaction. $msg_data is the message
+ * that is to be send with the headers. Each header needs to be
+ * on a single line followed by a with the message headers
+ * and the message body being seperated by and additional .
+ *
+ * Implements rfc 821: DATA
+ *
+ * SMTP CODE INTERMEDIATE: 354
+ * [data]
+ * .
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE FAILURE: 552,554,451,452
+ * SMTP CODE FAILURE: 451,554
+ * SMTP CODE ERROR : 500,501,503,421
+ * @access public
+ * @return bool
+ */
+ function Data($msg_data) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Data() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"DATA" . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 354) {
+ $this->error =
+ array("error" => "DATA command not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ # the server is ready to accept data!
+ # according to rfc 821 we should not send more than 1000
+ # including the CRLF
+ # characters on a single line so we will break the data up
+ # into lines by \r and/or \n then if needed we will break
+ # each of those into smaller lines to fit within the limit.
+ # in addition we will be looking for lines that start with
+ # a period '.' and append and additional period '.' to that
+ # line. NOTE: this does not count towards are limit.
+
+ # normalize the line breaks so we know the explode works
+ $msg_data = str_replace("\r\n","\n",$msg_data);
+ $msg_data = str_replace("\r","\n",$msg_data);
+ $lines = explode("\n",$msg_data);
+
+ # we need to find a good way to determine is headers are
+ # in the msg_data or if it is a straight msg body
+ # currently I'm assuming rfc 822 definitions of msg headers
+ # and if the first field of the first line (':' sperated)
+ # does not contain a space then it _should_ be a header
+ # and we can process all lines before a blank "" line as
+ # headers.
+ $field = substr($lines[0],0,strpos($lines[0],":"));
+ $in_headers = false;
+ if(!empty($field) && !strstr($field," ")) {
+ $in_headers = true;
+ }
+
+ $max_line_length = 998; # used below; set here for ease in change
+
+ while(list(,$line) = @each($lines)) {
+ $lines_out = null;
+ if($line == "" && $in_headers) {
+ $in_headers = false;
+ }
+ # ok we need to break this line up into several
+ # smaller lines
+ while(strlen($line) > $max_line_length) {
+ $pos = strrpos(substr($line,0,$max_line_length)," ");
+
+ # Patch to fix DOS attack
+ if(!$pos) {
+ $pos = $max_line_length - 1;
+ }
+
+ $lines_out[] = substr($line,0,$pos);
+ $line = substr($line,$pos + 1);
+ # if we are processing headers we need to
+ # add a LWSP-char to the front of the new line
+ # rfc 822 on long msg headers
+ if($in_headers) {
+ $line = "\t" . $line;
+ }
+ }
+ $lines_out[] = $line;
+
+ # now send the lines to the server
+ while(list(,$line_out) = @each($lines_out)) {
+ if(strlen($line_out) > 0)
+ {
+ if(substr($line_out, 0, 1) == ".") {
+ $line_out = "." . $line_out;
+ }
+ }
+ fputs($this->smtp_conn,$line_out . $this->CRLF);
+ }
+ }
+
+ # ok all the message data has been sent so lets get this
+ # over with aleady
+ fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "DATA not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Expand takes the name and asks the server to list all the
+ * people who are members of the _list_. Expand will return
+ * back and array of the result or false if an error occurs.
+ * Each value in the array returned has the format of:
+ * [ ]
+ * The definition of is defined in rfc 821
+ *
+ * Implements rfc 821: EXPN
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE FAILURE: 550
+ * SMTP CODE ERROR : 500,501,502,504,421
+ * @access public
+ * @return string array
+ */
+ function Expand($name) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Expand() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "EXPN not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ # parse the reply and place in our array to return to user
+ $entries = explode($this->CRLF,$rply);
+ while(list(,$l) = @each($entries)) {
+ $list[] = substr($l,4);
+ }
+
+ return $list;
+ }
+
+ /**
+ * Sends the HELO command to the smtp server.
+ * This makes sure that we and the server are in
+ * the same known state.
+ *
+ * Implements from rfc 821: HELO
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE ERROR : 500, 501, 504, 421
+ * @access public
+ * @return bool
+ */
+ function Hello($host="") {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Hello() without being connected");
+ return false;
+ }
+
+ # if a hostname for the HELO wasn't specified determine
+ # a suitable one to send
+ if(empty($host)) {
+ # we need to determine some sort of appopiate default
+ # to send to the server
+ $host = "localhost";
+ }
+
+ // Send extended hello first (RFC 2821)
+ if(!$this->SendHello("EHLO", $host))
+ {
+ if(!$this->SendHello("HELO", $host))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sends a HELO/EHLO command.
+ * @access private
+ * @return bool
+ */
+ function SendHello($hello, $host) {
+ fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => $hello . " not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ $this->helo_rply = $rply;
+
+ return true;
+ }
+
+ /**
+ * Gets help information on the keyword specified. If the keyword
+ * is not specified then returns generic help, ussually contianing
+ * A list of keywords that help is available on. This function
+ * returns the results back to the user. It is up to the user to
+ * handle the returned data. If an error occurs then false is
+ * returned with $this->error set appropiately.
+ *
+ * Implements rfc 821: HELP [ ]
+ *
+ * SMTP CODE SUCCESS: 211,214
+ * SMTP CODE ERROR : 500,501,502,504,421
+ * @access public
+ * @return string
+ */
+ function Help($keyword="") {
+ $this->error = null; # to avoid confusion
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Help() without being connected");
+ return false;
+ }
+
+ $extra = "";
+ if(!empty($keyword)) {
+ $extra = " " . $keyword;
+ }
+
+ fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 211 && $code != 214) {
+ $this->error =
+ array("error" => "HELP not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ return $rply;
+ }
+
+ /**
+ * Starts a mail transaction from the email address specified in
+ * $from. Returns true if successful or false otherwise. If True
+ * the mail transaction is started and then one or more Recipient
+ * commands may be called followed by a Data command.
+ *
+ * Implements rfc 821: MAIL FROM:
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE SUCCESS: 552,451,452
+ * SMTP CODE SUCCESS: 500,501,421
+ * @access public
+ * @return bool
+ */
+ function Mail($from) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Mail() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "MAIL not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Sends the command NOOP to the SMTP server.
+ *
+ * Implements from rfc 821: NOOP
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE ERROR : 500, 421
+ * @access public
+ * @return bool
+ */
+ function Noop() {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Noop() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"NOOP" . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "NOOP not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Sends the quit command to the server and then closes the socket
+ * if there is no error or the $close_on_error argument is true.
+ *
+ * Implements from rfc 821: QUIT
+ *
+ * SMTP CODE SUCCESS: 221
+ * SMTP CODE ERROR : 500
+ * @access public
+ * @return bool
+ */
+ function Quit($close_on_error=true) {
+ $this->error = null; # so there is no confusion
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Quit() without being connected");
+ return false;
+ }
+
+ # send the quit command to the server
+ fputs($this->smtp_conn,"quit" . $this->CRLF);
+
+ # get any good-bye messages
+ $byemsg = $this->get_lines();
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;
+ }
+
+ $rval = true;
+ $e = null;
+
+ $code = substr($byemsg,0,3);
+ if($code != 221) {
+ # use e as a tmp var cause Close will overwrite $this->error
+ $e = array("error" => "SMTP server rejected quit command",
+ "smtp_code" => $code,
+ "smtp_rply" => substr($byemsg,4));
+ $rval = false;
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $e["error"] . ": " .
+ $byemsg . $this->CRLF;
+ }
+ }
+
+ if(empty($e) || $close_on_error) {
+ $this->Close();
+ }
+
+ return $rval;
+ }
+
+ /**
+ * Sends the command RCPT to the SMTP server with the TO: argument of $to.
+ * Returns true if the recipient was accepted false if it was rejected.
+ *
+ * Implements from rfc 821: RCPT TO:
+ *
+ * SMTP CODE SUCCESS: 250,251
+ * SMTP CODE FAILURE: 550,551,552,553,450,451,452
+ * SMTP CODE ERROR : 500,501,503,421
+ * @access public
+ * @return bool
+ */
+ function Recipient($to) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Recipient() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250 && $code != 251) {
+ $this->error =
+ array("error" => "RCPT not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Sends the RSET command to abort and transaction that is
+ * currently in progress. Returns true if successful false
+ * otherwise.
+ *
+ * Implements rfc 821: RSET
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE ERROR : 500,501,504,421
+ * @access public
+ * @return bool
+ */
+ function Reset() {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Reset() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"RSET" . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "RSET failed",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Starts a mail transaction from the email address specified in
+ * $from. Returns true if successful or false otherwise. If True
+ * the mail transaction is started and then one or more Recipient
+ * commands may be called followed by a Data command. This command
+ * will send the message to the users terminal if they are logged
+ * in.
+ *
+ * Implements rfc 821: SEND FROM:
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE SUCCESS: 552,451,452
+ * SMTP CODE SUCCESS: 500,501,502,421
+ * @access public
+ * @return bool
+ */
+ function Send($from) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Send() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "SEND not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Starts a mail transaction from the email address specified in
+ * $from. Returns true if successful or false otherwise. If True
+ * the mail transaction is started and then one or more Recipient
+ * commands may be called followed by a Data command. This command
+ * will send the message to the users terminal if they are logged
+ * in and send them an email.
+ *
+ * Implements rfc 821: SAML FROM:
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE SUCCESS: 552,451,452
+ * SMTP CODE SUCCESS: 500,501,502,421
+ * @access public
+ * @return bool
+ */
+ function SendAndMail($from) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called SendAndMail() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "SAML not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Starts a mail transaction from the email address specified in
+ * $from. Returns true if successful or false otherwise. If True
+ * the mail transaction is started and then one or more Recipient
+ * commands may be called followed by a Data command. This command
+ * will send the message to the users terminal if they are logged
+ * in or mail it to them if they are not.
+ *
+ * Implements rfc 821: SOML FROM:
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE SUCCESS: 552,451,452
+ * SMTP CODE SUCCESS: 500,501,502,421
+ * @access public
+ * @return bool
+ */
+ function SendOrMail($from) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called SendOrMail() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250) {
+ $this->error =
+ array("error" => "SOML not accepted from server",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * This is an optional command for SMTP that this class does not
+ * support. This method is here to make the RFC821 Definition
+ * complete for this class and __may__ be implimented in the future
+ *
+ * Implements from rfc 821: TURN
+ *
+ * SMTP CODE SUCCESS: 250
+ * SMTP CODE FAILURE: 502
+ * SMTP CODE ERROR : 500, 503
+ * @access public
+ * @return bool
+ */
+ function Turn() {
+ $this->error = array("error" => "This method, TURN, of the SMTP ".
+ "is not implemented");
+ if($this->do_debug >= 1) {
+ echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;
+ }
+ return false;
+ }
+
+ /**
+ * Verifies that the name is recognized by the server.
+ * Returns false if the name could not be verified otherwise
+ * the response from the server is returned.
+ *
+ * Implements rfc 821: VRFY
+ *
+ * SMTP CODE SUCCESS: 250,251
+ * SMTP CODE FAILURE: 550,551,553
+ * SMTP CODE ERROR : 500,501,502,421
+ * @access public
+ * @return int
+ */
+ function Verify($name) {
+ $this->error = null; # so no confusion is caused
+
+ if(!$this->connected()) {
+ $this->error = array(
+ "error" => "Called Verify() without being connected");
+ return false;
+ }
+
+ fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);
+
+ $rply = $this->get_lines();
+ $code = substr($rply,0,3);
+
+ if($this->do_debug >= 2) {
+ echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
+ }
+
+ if($code != 250 && $code != 251) {
+ $this->error =
+ array("error" => "VRFY failed on name '$name'",
+ "smtp_code" => $code,
+ "smtp_msg" => substr($rply,4));
+ if($this->do_debug >= 1) {
+ echo "SMTP -> ERROR: " . $this->error["error"] .
+ ": " . $rply . $this->CRLF;
+ }
+ return false;
+ }
+ return $rply;
+ }
+
+ /*******************************************************************
+ * INTERNAL FUNCTIONS *
+ ******************************************************************/
+
+ /**
+ * Read in as many lines as possible
+ * either before eof or socket timeout occurs on the operation.
+ * With SMTP we can tell if we have more lines to read if the
+ * 4th character is '-' symbol. If it is a space then we don't
+ * need to read anything else.
+ * @access private
+ * @return string
+ */
+ function get_lines() {
+ $data = "";
+ while($str = fgets($this->smtp_conn,515)) {
+ if($this->do_debug >= 4) {
+ echo "SMTP -> get_lines(): \$data was \"$data\"" .
+ $this->CRLF;
+ echo "SMTP -> get_lines(): \$str is \"$str\"" .
+ $this->CRLF;
+ }
+ $data .= $str;
+ if($this->do_debug >= 4) {
+ echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;
+ }
+ # if the 4th character is a space then we are done reading
+ # so just break the loop
+ if(substr($str,3,1) == " ") { break; }
+ }
+ return $data;
+ }
+
+}
+
+
+ ?>
diff --git a/conlite/classes/class.structure.php b/conlite/classes/class.structure.php
new file mode 100644
index 0000000..ac9e8d5
--- /dev/null
+++ b/conlite/classes/class.structure.php
@@ -0,0 +1,97 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created 2003
+ * modified 2008-06-30, Frederic Schneider, add security fix
+ *
+ * $Id: class.structure.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class Structure {
+
+ /**
+ * Constructor Function
+ * @param
+ */
+ function Structure() {
+ // empty
+ } // end function
+
+ /**
+ * getStructureName()
+ * Returns a name for the given structure
+ * @return string Returns the name of the given structure
+ */
+ function getStructureName( $structure, $idlang) {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ name
+ FROM
+ ". $cfg["tab"]["cat_lang"] ."
+ WHERE
+ idlang = '".Contenido_Security::toInteger($idlang)."' AND
+ idcat = '".Contenido_Security::toInteger($structure)."'";
+
+ $db->query($sql);
+ $db->next_record();
+
+ return ($db->f("name"));
+
+ } // end function
+
+ /**
+ * getStructureIDForCatArt()
+ * Returns a name for the given structure
+ * @return string Returns the name of the given structure
+ *
+ */
+ function getStructureIDForCatArt ( $idcatart)
+ {
+ global $cfg;
+
+ $db = new DB_ConLite;
+
+ $sql = "SELECT
+ idcat
+ FROM
+ ". $cfg["tab"]["cat_art"] ."
+ WHERE
+ idcatart = '".Contenido_Security::toInteger($idcatart)."'";
+ $db->query($sql);
+ $db->next_record();
+
+ return ($db->f("idcat"));
+
+ } // End function
+
+} // end class
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.table.php b/conlite/classes/class.table.php
new file mode 100644
index 0000000..e425fd6
--- /dev/null
+++ b/conlite/classes/class.table.php
@@ -0,0 +1,378 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Frederic Schneider, add security fix
+ * modified 2008-07-03, Timo.Trautmann, added linebreaks for readable source code
+ *
+ * $Id: class.table.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class Table {
+
+ /**
+ * Table border color
+ * @var string
+ */
+ var $border_color = '';
+
+ /**
+ * Table border style
+ * @var string
+ */
+ var $border_style = '';
+
+ /**
+ * Table cell spacing
+ * @var string
+ */
+ var $cell_spacing = '';
+
+
+ /**
+ * Table cell padding
+ * @var string
+ */
+ var $cell_padding = '';
+
+
+ /**
+ * Table header color
+ * @var string
+ */
+ var $header_color = '';
+
+
+ /**
+ * Table light row color
+ * @var string
+ */
+ var $light_color = '';
+
+
+ /**
+ * Table dark row color
+ * @var string
+ */
+ var $dark_color = '';
+
+
+ /**
+ * Internal dark/light row counter
+ * @var bool
+ */
+ var $dark_row = 0;
+
+ /**
+ * Internal table width counter
+ * @var int
+ */
+
+ var $table_cols = 0;
+
+ /**
+ * Internal first cell checker
+ * @var bool
+ */
+ var $first_cell = 0;
+
+ /**
+ * Internal full border checker
+ * @var bool
+ */
+ var $fullborder = false;
+
+ /**
+ * Directly output table if true
+ *
+ */
+ var $directoutput = true;
+
+ /**
+ * Constructor
+ */
+ function Table($m_bordercolor = "#EEEEEE", $m_borderstyle = "solid", $m_cellspacing = "0", $m_cellpadding="2", $m_header_color = "#222222", $m_light_color = "#AAAAAA", $m_dark_color = "#777777", $m_fullborder = false, $m_directoutput = true) {
+ $this->border_color = $m_bordercolor;
+ $this->border_style = $m_borderstyle;
+ $this->cellspacing = $m_cellspacing;
+ $this->cellpadding = $m_cellpadding;
+ $this->header_color = $m_header_color;
+ $this->dark_color = $m_dark_color;
+ $this->light_color = $m_light_color;
+ $this->fullborder = $m_fullborder;
+ $this->directoutput = $m_directoutput;
+
+ } # end function
+
+ /**
+ * Begins the new table
+ * @param none
+ * @return void
+ */
+ function start_table() {
+
+ if (!$this->fullborder)
+ {
+ $starttable = '';
+ } else {
+ $starttable = '';
+ }
+
+ if ($this->directoutput)
+ {
+ echo $starttable."\n";
+ } else {
+ return $starttable."\n";
+ }
+
+
+ } # end function
+
+
+
+ /**
+ * Outputs a header row
+ * @param none
+ * @return void
+ */
+ function header_row($additional="") {
+
+ $headerrow = '';
+
+ if ($this->directoutput)
+ {
+ echo $headerrow."\n";
+ } else {
+ return $headerrow."\n";
+ }
+ } # end function
+
+
+
+ /**
+ * Outputs a regular row
+ * @param none
+ * @return void
+ */
+ function row($id = '') {
+ if ($this->dark_row)
+ {
+ $bgColor = $this->light_color;
+ } else {
+ $bgColor = $this->dark_color;
+ }
+
+ $this->dark_row = !$this->dark_row;
+
+ $row = ' ';
+
+ if ($this->directoutput)
+ {
+ echo $row."\n";
+ } else {
+ return $row."\n";
+ }
+
+ } # end function
+
+
+
+ /**
+ * Outputs a header cell
+ * @param $content The content which will fill the cell
+ * @param $align The horizontal alignment of the cell, default "center"
+ * @param $valign The vertical alignment of the cell, default "top"
+ * @return void
+ */
+ function header_cell($content, $align="center", $valign="top", $additional="", $borderTop = 1){
+
+ $header_cell = '' . $content . ' ';
+
+ if ($this->first_cell)
+ {
+ $this->table_cols = 0;
+ $this->first_cell = false;
+ }
+
+ $this->table_cols++;
+
+ if ($this->directoutput)
+ {
+ echo $header_cell."\n";
+ } else {
+ return $header_cell."\n";
+ }
+
+ } # end function
+
+
+
+ /**
+ * Outputs a regular cell
+ * @param $content The content which will fill the cell
+ * @param $align The horizontal alignment of the cell, default "center"
+ * @param $valign The vertical alignment of the cell, default "top"
+ * @param $additional Additional flags for the table
+ */
+ function cell($content, $align="center", $valign="top", $additional = "", $bSetStyle = true){
+
+ if (strlen($content) == 0)
+ {
+ $content = " ";
+ }
+ $cell = ''.$content.' ';
+
+ if ($this->first_cell)
+ {
+ $this->table_cols = 0;
+ $this->first_cell = false;
+ }
+
+ $this->table_cols++;
+
+ if ($this->directoutput)
+ {
+ echo $cell."\n";
+ } else {
+ return $cell."\n";
+ }
+
+ } # end function
+
+ /**
+ * Outputs a borderless cell
+ * @param $content The content which will fill the cell
+ * @param $align The horizontal alignment of the cell, default "center"
+ * @param $valign The vertical alignment of the cell, default "top"
+ * @param $additional Additional flags for the table
+ */
+ function borderless_cell($content, $align="center", $valign="top", $additional = ""){
+
+ if (strlen($content) == 0)
+ {
+ $content = " ";
+ }
+ $borderless_cell = '' . $content . ' ';
+
+ if ($this->first_cell)
+ {
+ $this->table_cols = 0;
+ $this->first_cell = false;
+ }
+
+ $this->table_cols++;
+
+ if ($this->directoutput)
+ {
+ echo $borderless_cell."\n";
+ } else {
+ return $borderless_cell."\n";
+ }
+
+ } # end function
+
+
+ /**
+ * Outputs a sum cell
+ * @param $content The content which will fill the cell
+ * @param $align The horizontal alignment of the cell, default "center"
+ * @param $valign The vertical alignment of the cell, default "top"
+ */
+ function sumcell($content, $align="center", $valign="top"){
+
+ if (strlen($content) == 0)
+ {
+ $content = " ";
+ }
+ $sumcell = '' . $content . ' ';
+
+ if ($this->directoutput)
+ {
+ echo $sumcell."\n";
+ } else {
+ return $sumcell."\n";
+ }
+
+ } # end function
+
+
+ /**
+ * Ends a row
+ * @param none
+ * @return void
+ */
+
+ function end_row()
+ {
+ $end_row = ' ';
+
+ $this->first_cell = true;
+
+ if ($this->directoutput)
+ {
+ echo $end_row."\n";
+ } else {
+ return $end_row."\n";
+ }
+
+ }
+
+
+ /**
+ * Ends a table
+ * @param none
+ * @return void
+ */
+ function end_table(){
+ $end_table = '
';
+
+ if ($this->directoutput)
+ {
+ echo $end_table."\n";
+ } else {
+ return $end_table."\n";
+ }
+ } # end function
+
+} # end class Table
+
+?>
diff --git a/conlite/classes/class.template.php b/conlite/classes/class.template.php
new file mode 100644
index 0000000..bb04024
--- /dev/null
+++ b/conlite/classes/class.template.php
@@ -0,0 +1,29 @@
+
+ * @copyright c) 2012, conlite.org
+ * @license http://www.gnu.de/documents/gpl.en.html GPL v3 (english version)
+ * @license http://www.gnu.de/documents/gpl.de.html GPL v3 (deutsche Version)
+ * @link http://www.conlite.org ConLite.org
+ *
+ * $Id: class.template.php 195 2012-12-19 06:09:48Z oldperl $
+ */
+
+// security check
+defined('CON_FRAMEWORK') or die('Illegal call');
+$cErrorType = (version_compare(PHP_VERSION, '5.3.0') >= 0)?E_USER_DEPRECATED:E_USER_NOTICE;
+trigger_error("Include of ".__FILE__." is deprecated since CL 2.0. Please use autoloader or include file in folder classes/template.", $cErrorType);
+cInclude("classes", "template/class.template.php");
+?>
diff --git a/conlite/classes/class.templateconfig.php b/conlite/classes/class.templateconfig.php
new file mode 100644
index 0000000..2cf65dc
--- /dev/null
+++ b/conlite/classes/class.templateconfig.php
@@ -0,0 +1,325 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Frederic Schneider, add security fix
+ * modified 2009-12-16, Dominik Ziegler, fixed sql table name
+ *
+ * $Id: class.templateconfig.php 306 2014-03-13 23:03:26Z oldperl $:
+ * }}
+ *
+ */
+
+/**
+ * Object of a contenido template configuration
+ *
+ * Class to get template configurations for the current article or the current category
+ *
+ * Example (article configuration):
+ *
+ * $tplCfg = new templateConfig($idart); //get template configuration for current article
+ * $exampleAr = $tplCfg->getData(20); //get all informations for container 20 for this template
+ *
+ * Example (category configuration):
+ * $tplCfg = new templateConfig(); //leave empty cause you only want a category configuration
+ * $tplCfg->getDataForIdcat ($idcat);
+ * $exampleAr = $tplCfg->getData(20); //get all informations for container 20 for this template
+ *
+ * $exampleAr:
+ * $exampleAr[0] => ""
+ *
+ * "0" specifies the CMS_VALUE set in modules
+ * "" contains the configuration data
+ *
+ * @author Marco Jahn
+ * @version 1.0
+ * @copyright four for business 2003
+ * @package Contenido_API
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+class TemplateConfig
+{
+ /**
+ * stores configuration data
+ * @var array
+ */
+ var $data = array();
+
+ /**
+ * database object
+ * @var object
+ */
+ var $db;
+
+ /**
+ * global config variables
+ * @var array
+ */
+ var $cfg;
+
+ /**
+ * language id
+ * @var int
+ */
+ var $lang;
+
+ /**
+ * client id
+ * @var int
+ */
+ var $client;
+
+ /**
+ * constructor
+ *
+ * @return void
+ */
+ function templateConfig($idart = 0)
+ {
+ global $cfg, $lang, $client;
+
+ $this->db = new DB_ConLite;
+
+ $this->cfg = &$cfg;
+ $this->lang = &$lang;
+ $this->client = &$client;
+ $this->idart = $idart;
+
+ if ($idart != 0)
+ {
+ $idtplcfg = $this->_getTplCfgByArtId($idart);
+ $this->data = $this->_getContainersByTplCfg($idtplcfg);
+ }
+ }
+
+ /**
+ * reset data array
+ *
+ * @return void
+ */
+ function resetData()
+ {
+ unset($this->data);
+ }
+
+ /**
+ * get cms_values
+ * returns false if no configuration was found
+ *
+ * @param integer $idcontainer id for the container which settings should be returned
+ *
+ * @return array array with the settings for each cms_value of the specified container
+ */
+ function getData ($idcontainer)
+ {
+ if ($this->data[$idcontainer])
+ {
+ $tmpVar = explode("&",trim($this->data[$idcontainer],"&"));
+ foreach ($tmpVar as $string)
+ {
+ $tmpData = explode("=", $string);
+ $tmpArray[$tmpData[0]] = urldecode($tmpData[1]);
+ }
+ return $tmpArray;
+ }
+ return false;
+ }
+
+ /**
+ * get data
+ */
+ function getDataForIdcat ($idcat)
+ {
+ $idtplcfg = $this->_getTplCfgByCatId($idcat);
+ $this->data = $this->_getContainersByTplCfg($idtplcfg);
+ }
+
+ /**
+ * get values from template pre configuration
+ * returns false if no pre configuration values were found
+ *
+ * @param integer $idart id of the article
+ * @param integer $containerid id for the container of which the settings should be returned
+ *
+ * @return array containing pre configuration values
+ */
+
+ function getPreConfigurationValues ($idart,$containerid) {
+
+ global $cfg;
+
+ $idtplcfg = $this->_getTplCfgByArtId($idart);
+ if ((!$idtplcfg) || ($idtplcfg==0)) {
+ $idcat = $this->_getIdCatByIdArt($idart);
+ $idtplcfg = $this->_getTplCfgByCatId($idcat);
+ }
+
+ if ($idtplcfg) {
+ #Article or cat is assigned to a template
+ $sql = "SELECT * FROM ".$cfg["tab"]["tpl_conf"]." WHERE idtplcfg = '".Contenido_Security::toInteger($idtplcfg)."'";
+ $this->db->query($sql);
+ if ($this->db->next_record()) {
+ $idtpl = $this->db->f("idtpl");
+ $sql = "SELECT * FROM ".$cfg["tab"]["tpl"]." WHERE idtpl = '".Contenido_Security::toInteger($idtpl)."'";
+ $this->db->query($sql);
+ if ($this->db->next_record()) {
+ $idtplcfg = $this->db->f("idtplcfg");
+ $this->_getContainersByTplCfg($idtplcfg);
+ $arrData = $this->getData ($containerid);
+ return $arrData;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * get template config id by article id
+ * returns false if the article has no configuration
+ *
+ * returns the template configuration for the current article
+ * if the article has not a template configuration it will return the configuration
+ * for the current category
+ *
+ * @param integer $idart id of the article which configuration should be get
+ *
+ * @return string returns the template configuration
+ */
+ function _getTplCfgByArtId($idart)
+ {
+ $sql = "
+ SELECT
+ idtplcfg
+ FROM ".$this->cfg['tab']['art_lang']."
+ WHERE
+ idart='".Contenido_Security::toInteger($idart)."'
+ AND
+ idlang='".Contenido_Security::toInteger($this->lang)."'";
+
+ //query
+ $this->db->query($sql);
+
+ if (!$this->db->next_record())
+ {
+ return false;
+ }
+
+ if ($this->db->f("idtplcfg") != 0)
+ {
+ return $this->db->f("idtplcfg");
+ }
+ else
+ {
+ $idcat = $this->_getIdCatByIdArt($idart);
+ return $this->_getTplCfgByCatId($idcat);
+ }
+
+ }
+
+ /**
+ * get category id by article id
+ *
+ * returns false if the specified article doesn't belong to a category
+ *
+ * @param integer $idart id of the current article
+ *
+ * @return int returns the idcat for the current article
+ */
+
+ function _getIdCatByIdArt($idart)
+ {
+ $sql = "SELECT idcat FROM ".$this->cfg['tab']['cat_art']." WHERE idart='".Contenido_Security::toInteger($idart)."' ORDER BY idcat ASC LIMIT 1";
+ $this->db->query($sql);
+ if ($this->db->next_record())
+ {
+ return $this->db->f("idcat");
+ }
+ return false;
+ }
+
+ /**
+ * get template config id by category id
+ * returns false if the category specified has not a template configuration
+ *
+ * @param integer $idcat id of the category which template config should be read out
+ *
+ * @return string template configuration for the selected category
+ */
+ function _getTplCfgByCatId ($idcat)
+ {
+ $sql = "SELECT idtplcfg FROM ".$this->cfg['tab']['cat_lang']." WHERE idcat='".Contenido_Security::toInteger($idcat)."'
+ AND idlang='".Contenido_Security::toInteger($this->lang)."'";
+ $this->db->query($sql);
+ if ($this->db->next_record())
+ {
+ return $this->db->f("idtplcfg");
+ }
+ return false;
+ }
+
+ /**
+ * get containers for a specified template configuration
+ * returns false if no configuratin was found
+ *
+ * @param integer $idtplcfg id of the template
+ *
+ * @return array array with all containers and their values
+ */
+ function _getContainersByTplCfg($idtplcfg)
+ {
+ $sql = "
+ SELECT
+ number, container
+ FROM ".$this->cfg['tab']['container_conf']."
+ WHERE idtplcfg='".Contenido_Security::toInteger($idtplcfg)."'
+ ORDER BY
+ number ASC";
+ $this->db->query($sql);
+
+ if ($this->db->nf() == 0)
+ { //nothing found
+ return false;
+ }
+ else
+ {
+ //get all results
+ while ($this->db->next_record())
+ {
+ $this->data[$this->db->f("number")] = $this->db->f("container");
+ }
+
+ //return data array
+ return $this->data;
+ }
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.todo.php b/conlite/classes/class.todo.php
new file mode 100644
index 0000000..402641f
--- /dev/null
+++ b/conlite/classes/class.todo.php
@@ -0,0 +1,165 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created unknown
+ * modified 2008-06-30, Frederic Schneider, add security fix
+ * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting
+ *
+ * $Id: class.todo.php 78 2012-05-25 11:35:10Z oldperl $:
+ * }}
+ *
+ */
+
+if (!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class TODOCollection extends CommunicationCollection
+{
+ public function __construct()
+ {
+ parent::__construct();
+ $this->_setItemClass("TODOItem");
+ }
+
+ /** @deprecated [2011-03-15] Old constructor function for downwards compatibility */
+ public function TODOCollection()
+ {
+ cWarning(__FILE__, __LINE__, "Deprecated method call, use __construct()");
+ $this->__construct();
+ }
+
+ public function select($where = "", $group_by = "", $order_by = "", $limit = "")
+ {
+ if ($where == "") {
+ $where = "comtype='todo'";
+ } else {
+ $where .= " AND comtype='todo'";
+ }
+
+ return parent::select($where, $group_by, $order_by, $limit);
+ }
+
+ /**
+ * Creates a new communication item
+ */
+ public function create($itemtype, $itemid, $reminderdate, $subject, $content, $notimail, $notibackend, $recipient)
+ {
+ $item = parent::create();
+
+ $item->set("subject", $subject);
+ $item->set("message", $content);
+ $item->set("comtype", "todo");
+ $item->set("recipient", $recipient);
+ $item->store();
+
+ if ($notimail === true) {
+ $notimail = 1;
+ }
+
+ // Is the date passed as string?
+ if (!is_numeric($reminderdate)) {
+ // Convert to timestamp
+ $reminderdate = strtotime($reminderdate);
+ }
+
+ $item->setProperty("todo", "reminderdate", $reminderdate);
+ $item->setProperty("todo", "itemtype", $itemtype);
+ $item->setProperty("todo", "itemid", $itemid);
+ $item->setProperty("todo", "emailnoti", $notimail);
+ $item->setProperty("todo", "backendnoti", $notibackend);
+ $item->setProperty("todo", "status", "new");
+ $item->setProperty("todo", "priority", "medium");
+ $item->setProperty("todo", "progress", "0");
+
+ return $item;
+ }
+
+ public function getStatusTypes()
+ {
+ $statusTypes = array(
+ "new" => i18n("New"),
+ "progress" => i18n("In progress"),
+ "done" => i18n("Done"),
+ "waiting" => i18n("Waiting for action"),
+ "deferred" => i18n("Deferred")
+ );
+ return ($statusTypes);
+ }
+
+ public function getPriorityTypes()
+ {
+ $priorityTypes = array(
+ "low" => i18n("Low"),
+ "medium" => i18n("Medium"),
+ "high" => i18n("High"),
+ "immediately" => i18n("Immediately")
+ );
+ return ($priorityTypes);
+ }
+}
+
+
+class TODOItem extends CommunicationItem
+{
+ public function setProperty ($type, $name, $value)
+ {
+ if ($type == "todo" && $name == "emailnoti") {
+ if ($value) {
+ parent::setProperty("todo", "emailnoti-sent", false);
+ $value = true;
+ } else {
+ $value = false;
+ }
+ }
+
+ parent::setProperty($type, $name, $value);
+ }
+
+}
+
+
+class TODOLink extends cHTMLLink
+{
+ public function __construct($itemtype, $itemid, $subject, $message)
+ {
+ global $sess;
+ parent::__construct();
+
+ $subject = urlencode($subject);
+ $message = urlencode($message);
+
+ $this->setEvent("click", 'javascript:window.open('."'".$sess->url("main.php?subject=$subject&message=$message&area=todo&frame=1&itemtype=$itemtype&itemid=$itemid")."', 'todo', 'scrollbars=yes, resizable=yes, height=350, width=550');");
+ $this->setEvent("mouseover", "this.style.cursor='pointer'");
+
+ $img = new cHTMLImage("images/but_setreminder.gif");
+ $img->setStyle("padding-left: 2px; padding-right: 2px;");
+
+ $img->setAlt(i18n("Set reminder / add to todo list"));
+ $this->setLink("#");
+ $this->setContent($img->render());
+ $this->setAlt(i18n("Set reminder / add to todo list"));
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.treeitem.php b/conlite/classes/class.treeitem.php
new file mode 100644
index 0000000..da0856a
--- /dev/null
+++ b/conlite/classes/class.treeitem.php
@@ -0,0 +1,482 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created 2003-05-20
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ *
+ * $Id: class.treeitem.php 2 2011-07-20 12:00:48Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+/**
+ * Class TreeItem
+ * Class to create tree-based items
+ *
+ * The treeitem class allows you to logically store
+ * tree-based structures.
+ *
+ * Example:
+ *
+ * Let's have a tree with 3 nodes. It's important that
+ * we always have a "root" key.
+ *
+ * $root = new TreeItem("root", 1);
+ * $item1 = new TreeItem("node1",2);
+ * $item2 = new TreeItem("node2",3);
+ * $item3 = new TreeItem("node3",4);
+ *
+ * $root->addItem($item1);
+ * $root->addItem($item2);
+ * $root->addItem($item3);
+ *
+ * This represents the tree we described above.
+ *
+ * If you know the ID of the item you want to add
+ * to, there's no need to have a specific item handy,
+ * but rather you can use the "addItemToID" function.
+ */
+class TreeItem
+{
+
+ /**
+ * Sub Items for this tree item
+ * @var array
+ */
+ var $subitems;
+
+ /**
+ * Determinates if this tree item is collapsed
+ * @var boolean
+ */
+ var $collapsed;
+
+ /**
+ * ID for this item
+ * @var string
+ */
+ var $id;
+
+ /**
+ * Name for this item
+ * @var string
+ */
+ var $name;
+
+ /**
+ * Icon for the collapsed item
+ * @var string
+ */
+ var $collapsed_icon;
+
+ /**
+ * Icon for the expanded item
+ * @var string
+ */
+ var $expanded_icon;
+
+ /**
+ * Icon for last node in a branch
+ * @var string
+ */
+ var $lastnode_icon;
+
+ /**
+ * Contains the level of this item
+ * @var integer
+ */
+ var $level;
+
+ /**
+ * Contains custom entries
+ * @var array
+ */
+ var $custom;
+
+ /**
+ * Contains the parent of this item
+ * @var array
+ */
+ var $parent;
+
+ /**
+ * Constructor Function
+ * Creates a new, independant tree item.
+ * @param string $name The name of that item
+ * @param string $id The unique ID of that item
+ * @param boolean $collapsed Is this item collapsed by default
+ */
+ function TreeItem($name ="", $id="", $collapsed = false)
+ {
+ $this->name = $name;
+ $this->id = $id;
+ $this->collapsed = $collapsed;
+ $this->subitems = array();
+ $this->collapsed_icon = 'images/but_plus.gif';
+ $this->expanded_icon = 'images/but_minus.gif';
+ $this->lastnode_icon = 'images/but_lastnode.gif';
+ $this->parent = -1;
+ }
+
+
+ /**
+ * addItem
+ * Adds a new subitem to this item.
+ * @param object $item the item to add
+ */
+ function addItem(&$item)
+ {
+ $this->subitems[count($this->subitems)] = &$item;
+ $item->parent = $this->id;
+ }
+
+ /**
+ * addItemToID
+ * Adds a new subitem to a specific item with an ID.
+ * Traverses all subitems to find the correct item.
+ * @param object $item the item to add
+ * @param string $id the ID to add the item to
+ */
+ function addItemToID($item, $id)
+ {
+ if ($this->id == $id)
+ {
+ $this->subitems[count($this->subitems)] = &$item;
+ $item->parent = $this->id;
+ } else {
+ foreach (array_keys($this->subitems) as $key)
+ {
+ $this->subitems[$key]->addItemToID($item, $id);
+ }
+ }
+ }
+
+ /**
+ * getItemByID
+ * Retrieves a specific item by its ID. Note that this
+ * function traverses all subitems to find the correct item.
+ * @param string $id the ID to find
+ * @return object The item, or false if nothing was found
+ */
+ function &getItemByID($id)
+ {
+ if ($this->id == $id)
+ {
+ return ($this);
+ } else {
+ foreach (array_keys($this->subitems) as $key)
+ {
+ $retObj = &$this->subitems[$key]->getItemByID($id);
+ if ($retObj->id == $id)
+ {
+ return ($retObj);
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * removeItem
+ * Removes an item with a specific ID.
+ * @param string $id the ID to find
+ */
+ function removeItem ($id)
+ {
+ foreach (array_keys($this->subitems) as $key)
+ {
+ if ($this->subitems[$key]->id == $id)
+ {
+ unset($this->subitems[$key]);
+ }
+ }
+ }
+
+ /**
+ * isCustomAttributeSet
+ * checks if a specific custom attribute is set
+ * @param string $item the attribute name to find
+ */
+ function isCustomAttributeSet ($item)
+ {
+ if (array_key_exists($item, $this->custom))
+ {
+ return true;
+ } else {
+ foreach (array_keys($this->subitems) as $key)
+ {
+ if ($this->subitems[$key]->isCustomAttributeSet($item))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+
+ /**
+ * markExpanded
+ * Marks an item as expanded. Traverses all subitems
+ * to find the ID. Note that only the item with $id is
+ * expanded, but not its childs.
+ * @param string $id the ID to expand, or an array with all id's
+ */
+ function markExpanded ($id)
+ {
+ if (is_array($id))
+ {
+ if (in_array($this->id, $id))
+ {
+ $this->collapsed = false;
+ }
+
+ foreach (array_keys($this->subitems) as $key)
+ {
+ $this->subitems[$key]->markExpanded($id);
+ }
+ } else {
+ if ($this->id == $id)
+ {
+ $this->collapsed = false;
+ return true;
+ } else {
+ foreach (array_keys($this->subitems) as $key)
+ {
+ $this->subitems[$key]->markExpanded($id);
+ }
+ }
+ }
+ }
+
+ /**
+ * expandAll
+ * Expands all items, starting from the $start item.
+ * @param string $start the ID to start expanding from
+ */
+ function expandAll ($start = -2)
+ {
+ if ($start != $this->id)
+ {
+ $this->collapsed = false;
+ }
+
+ foreach (array_keys($this->subitems) as $key)
+ {
+ $this->subitems[$key]->expandAll();
+ }
+ }
+
+ /**
+ * collapseAll
+ * Collapses all items, starting from the $start item.
+ * @param string $start the ID to start collapsing from
+ */
+ function collapseAll ($start = -2)
+ {
+ if ($start != $this->id)
+ {
+ $this->collapsed = true;
+ }
+
+ foreach (array_keys($this->subitems) as $key)
+ {
+ $this->subitems[$key]->collapseAll();
+ }
+ }
+
+ /**
+ * markCollapsed
+ * Marks an item as collpased. Traverses all subitems
+ * to find the ID. Note that only the item with $id is
+ * collapsed, but not its childs.
+ * @param string $id the ID to collapse
+ */
+ function markCollapsed($id)
+ {
+ if ($this->id == $id)
+ {
+ $this->collapsed = true;
+
+ } else {
+ foreach (array_keys($this->subitems) as $key)
+ {
+ $this->subitems[$key]->markCollapsed($id);
+ }
+ }
+ }
+
+ /**
+ * traverse
+ * traverses the tree starting from this item, and returning
+ * all objects as $objects.
+ * @param object $objects all found objects
+ * @param integer $level Level to start on
+ */
+ function traverse (&$objects, $level = 0)
+ {
+ $objects[count($objects)] = &$this;
+ $this->level = $level;
+
+ if ($this->collapsed == false)
+ {
+ foreach (array_keys($this->subitems) as $key)
+ {
+ $this->subitems[$key]->traverse($objects, $level + 1);
+ }
+ }
+ }
+
+ /**
+ * Starts iterating at root node and flattens the tree into an array
+ */
+ function getFlatTree($item, &$flat_tree)
+ {
+ foreach ($item->subitems as $curItem)
+ {
+ $curItem->custom['vertline']=array();
+ $flat_tree[] = $curItem;
+ $this->getFlatTree($curItem, $flat_tree);
+ }
+ }
+
+ function hasCollapsedNode($item_id)
+ {
+ $parentNodeList=array();
+ $this->getTreeParentNodes($parentNodeList, $item_id);
+ $collapsedList=array();
+ $this->getRealCollapsedList($collapsedList);
+
+ if(sizeof(array_intersect($parentNodeList, $collapsedList)) > 0)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ /**
+ * Returns a list of the id of all parent nodes of the given node
+ **/
+ function getTreeParentNodes(&$parentNodes, $id)
+ {
+ $curItem = $this->getItemByID($id);
+ $parentId = $curItem->parent;
+
+ if($parentId && $parentId != -1)
+ {
+ $parentNodes[] = $parentId;
+ $this->getTreeParentNodes($parentNodes, $parentId);
+ }
+ }
+
+ /**
+ * Returns a list of the id of all parent nodes of the given node
+ * Not using the nodes of hierarchical tree, but flat tree !!
+ **/
+ function getParentNodes(&$parentNodes, $stop_id)
+ {
+ $flat_tree = array();
+ $this->getFlatTree($this, $flat_tree);
+
+ foreach($flat_tree as $key => $value)
+ {
+ if($value->id != $stop_id)
+ {
+ $parentNodes[] = $value->id;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ /**
+ * getCollapsedList thinks if a node has no subnodes it is collapsed
+ * I don't think so
+ **/
+ function getRealCollapsedList(&$list)
+ {
+ $this->getCollapsedList($list);
+ $cleared_list=array();
+
+ // remove all nodes that have no subnodes
+ foreach($list as $key)
+ {
+ $item=$this->getItemByID($key);
+ if(sizeof($item->subitems) > 0)
+ {
+ $cleared_list[]=$key;
+ }
+ }
+ }
+
+ /**
+ * getCollapsedList
+ * Returns all items (as ID array) which are collapsed.
+ * @param array $list Contains the list with all collapsed items
+ */
+ function getCollapsedList(&$list)
+ {
+ if ($this->collapsed == true)
+ {
+ $list[] = $this->id;
+ }
+
+ foreach (array_keys($this->subitems) as $key)
+ {
+ $this->subitems[$key]->getCollapsedList($list);
+ }
+ }
+
+ /**
+ * getExpandedList
+ * Returns all items (as ID array) which are expanded.
+ * @param array $list Contains the list with all expanded items
+ */
+ function getExpandedList(&$list)
+ {
+ if ($this->collapsed == false && !in_array($this->id, $list))
+ {
+ $list[] = $this->id;
+ }
+
+ foreach (array_keys($this->subitems) as $key)
+ {
+ $this->subitems[$key]->getExpandedList($list);
+ }
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/conlite/classes/class.ui.php b/conlite/classes/class.ui.php
new file mode 100644
index 0000000..d34cbd2
--- /dev/null
+++ b/conlite/classes/class.ui.php
@@ -0,0 +1,1595 @@
+
+ * @license http://www.contenido.org/license/LIZENZ.txt
+ * @link http://www.4fb.de
+ * @link http://www.contenido.org
+ * @since file available since contenido release <= 4.6
+ *
+ * {@internal
+ * created 2003-05-20
+ * modified 2008-06-30, Dominik Ziegler, add security fix
+ * modified 2010-12-13, Ortwin Pinke, count up object id's in cScrollList while rendering
+ *
+ * $Id: class.ui.php 75 2012-05-25 10:51:00Z oldperl $:
+ * }}
+ *
+ */
+
+if(!defined('CON_FRAMEWORK')) {
+ die('Illegal call');
+}
+
+
+class UI_Left_Top
+{
+ var $link;
+ var $javascripts;
+
+ function UI_Left_Top ()
+ {
+ }
+
+ function setLink ($link)
+ {
+ $this->link = $link;
+ }
+
+ function setJS ($type, $script)
+ {
+ $this->javascripts[$type] = $script;
+ }
+
+ function render()
+ {
+ global $sess, $cfg;
+
+ $tpl = new Template;
+
+ $tpl->reset();
+ $tpl->set('s', 'SESSID', $sess->id);
+
+ $scripts = "";
+
+ if (is_array($this->javascripts))
+ {
+ foreach ($this->javascripts as $script)
+ {
+ $scripts .= '';
+ }
+ }
+
+ if (is_object($this->link))
+ {
+ $tpl->set('s', 'LINK', $this->link->render() . $this->additional);
+ } else {
+ $tpl->set('s', 'LINK', '');
+ }
+
+ $tpl->set('s', 'JAVASCRIPTS', $scripts);
+ $tpl->set('s', 'CAPTION', $this->caption);
+ $tpl->generate($cfg['path']['contenido'] . $cfg['path']['templates'] . $cfg['templates']['generic_left_top']);
+
+
+ }
+
+ function setAdditionalContent ($content)
+ {
+ $this->additional = $content;
+ }
+
+}
+
+class UI_Menu
+{
+ var $link;
+ var $title;
+ var $caption;
+ var $javascripts;
+ var $type;
+ var $image;
+ var $alt;
+ var $actions;
+ var $padding;
+ var $imagewidth;
+ var $extra;
+ var $border;
+ var $show;
+ var $bgColor;
+
+ function UI_Menu ()
+ {
+ $this->padding = 2;
+ $this->border = 0;
+ $this->rowmark = true;
+ }
+
+ function setTitle ($item, $title)
+ {
+ $this->title[$item] = $title;
+ }
+
+ function setRowmark ($rowmark = true)
+ {
+ $this->rowmark = $rowmark;
+ }
+
+ function setImage ($item, $image, $maxwidth = 0)
+ {
+ $this->image[$item] = $image;
+ $this->imagewidth[$item] = $maxwidth;
+ $this->show[$item] = $show;
+ }
+
+ function setExtra ($item, $extra)
+ {
+ $this->extra[$item] = $extra;
+ }
+
+ function setLink ($item, $link)
+ {
+ $this->link[$item] = $link;
+ }
+
+ function setActions ($item, $key, $action)
+ {
+ $this->actions[$item][$key] = $action;
+ }
+
+ function setPadding ($padding)
+ {
+ $this->padding = $padding;
+ }
+
+ function setBorder ($border)
+ {
+ $this->border = $border;
+ }
+
+ function setBgColor($item, $bgColor)
+ {
+ $this->bgColor[$item] = $bgColor;
+
+ }
+
+ function render($print = true)
+ {
+ global $sess, $cfg;
+
+ $tpl = new Template;
+
+ $tpl->reset();
+ $tpl->set('s', 'SID', $sess->id);
+
+ $scripts = "";
+
+ if (is_array($this->javascripts))
+ {
+
+ foreach ($this->javascripts as $script)
+ {
+ $scripts .= '';
+ }
+ }
+
+ #echo ' Debug (B.A.): ' . $scripts;
+ $tpl->set('s', 'JSACTIONS', $scripts);
+ $tpl->set('s', 'CELLPADDING', $this->padding);
+ $tpl->set('s', 'BORDER', $this->border);
+ $tpl->set('s', 'BORDERCOLOR', $cfg['color']['table_border']);
+
+
+ if (is_array($this->link)) {
+
+ $dark = false;
+
+ foreach ($this->link as $key => $value) {
+ if ($value != NULL)
+ {
+ if ($this->imagewidth[$key] != 0)
+ {
+ $value->setContent(' ');
+ $img = $value->render();
+ }
+ else
+ {
+ $value->setContent(' ');
+ $img = $value->render();
+ }
+ $value->setContent($this->title[$key]);
+ $link = $value->render();
+ } else {
+ $link = $this->title[$key];
+
+ if ($this->image[$key] != "")
+ {
+ if ($this->imagewidth[$key] != 0)
+ {
+ $img = ' ';
+ } else {
+ $img = ' ';
+ }
+ } else {
+ $img = " ";
+ }
+ }
+
+ if(isset($this->bgColor[$key])) {
+ $bgColor = $this->bgColor[$key];
+ } else {
+ $dark = !$dark;
+ if ($dark) {
+ $bgColor = $cfg["color"]["table_dark"];
+ } else {
+ $bgColor = $cfg["color"]["table_light"];
+ }
+
+ if (isset($_GET['idworkflow']) && $_GET['idworkflow'] == $value) {
+ //$mlist->setExtra($iMenu, 'id="marked" ');
+ $bgColor = $cfg["color"]["table_light_active"];
+ }
+
+ if ($this->extra[$key] == 'id="marked" ') {
+ $bgColor = $cfg["color"]["table_light_active"];
+ }
+ }
+
+ $tpl->set('d', 'NAME', $link);
+
+ if ($this->image[$key] == "")
+ {
+ $tpl->set('d', 'ICON', '');
+ }
+ else
+ {
+ $tpl->set('d', 'ICON', $img);
+ }
+
+ if ($this->extra[$key] != "" || $this->rowmark == true)
+ {
+ $extraadd = "";
+
+ if ($this->rowmark == true)
+ {
+ $extraadd = 'onmouseover="row.over(this)" onmouseout="row.out(this)" onclick="row.click(this)"';
+ #echo ' Debug(B.A): ' . $extraadd;
+ }
+ $tpl->set('d', 'EXTRA', $this->extra[$key] . $extraadd);
+ } else {
+ $tpl->set('d', 'EXTRA', '');
+ }
+
+ $fullactions = "";
+ if (is_array($this->actions[$key]))
+ {
+
+ $fullactions = '';
+
+ foreach ($this->actions[$key] as $key => $singleaction)
+ {
+ $fullactions .= ''.$singleaction.' ';
+ }
+
+ $fullactions .= '
';
+ }
+
+ $tpl->set('d', 'ACTIONS', $fullactions);
+ $tpl->set('d', 'BGCOLOR', $bgColor);
+ $tpl->next();
+ }
+
+ }
+ $rendered = $tpl->generate($cfg['path']['contenido'] . $cfg['path']['templates'] . $cfg['templates']['generic_menu'],true);
+
+ if ($print == true)
+ {
+ echo $rendered;
+ } else {
+ return $rendered;
+ }
+ }
+
+}
+
+class UI_Table_Form
+{
+ var $items;
+ var $captions;
+ var $id;
+ var $rownames;
+ var $itemType;
+
+ var $formname;
+ var $formmethod;
+ var $formaction;
+ var $formvars;
+
+ var $tableid;
+ var $tablebordercolor;
+
+ var $header;
+ var $cancelLink;
+ var $submitjs;
+
+ var $accesskey;
+ var $width;
+
+
+ function UI_Table_Form ($name, $action = "", $method = "post")
+ {
+ global $sess, $cfg;
+
+ $this->formname = $name;
+
+ if ($action == "")
+ {
+ $this->formaction = "main.php";
+ } else {
+ $this->formaction = $action;
+ }
+
+ $this->formmethod = $method;
+
+ $this->tableid = "";
+ $this->tablebordercolor = $cfg['color']['table_border'];
+ $this->setAccessKey('s');
+ $this->custom = array();
+
+ $this->setActionButton("submit", $cfg['path']['contenido_fullhtml']."images/but_ok.gif", i18n("Save changes"), "s");
+
+ }
+
+ function setWidth ($width)
+ {
+ $this->width = $width;
+ }
+
+ function setVar ($name, $value)
+ {
+ $this->formvars[$name] = $value;
+ }
+
+ function add ($caption, $field, $rowname = "", $style = "")
+ {
+ $n = "";
+
+ if (is_array($field))
+ {
+
+ foreach ($field as $value)
+ {
+ if (is_object($value) && method_exists($value, "render"))
+ {
+ $n .= $value->render();
+ } else {
+ $n .= $value;
+ }
+ }
+
+ $field = $n;
+ }
+ if (is_object($field) && method_exists($field, "render"))
+ {
+ $n = $field->render();
+ $field = $n;
+ }
+ if ($field == "")
+ {
+ $field = " ";
+ }
+
+ if ($caption == "")
+ {
+ $caption = " ";
+ }
+
+ $this->id++;
+ $this->items[$this->id] = $field;
+ $this->captions[$this->id] = $caption;
+
+ if ($rowname == "")
+ {
+ $rowname = $this->id;
+ }
+
+ $this->rownames[$this->id] = $rowname;
+
+ $this->styles[$this->id] = $style;
+ }
+
+ function addCancel ($link)
+ {
+ $this->cancelLink = $link;
+ }
+
+ function addHeader ($header)
+ {
+ $this->header = $header;
+ }
+
+ function addSubHeader ($header)
+ {
+ $this->id++;
+ $this->items[$this->id] = '';
+ $this->captions[$this->id] = $header;
+ $this->itemType[$this->id] = 'subheader';
+ }
+
+ function setSubmitJS ($js)
+ {
+ $this->submitjs = $js;
+ }
+
+ function setAccessKey ($key)
+ {
+ $this->accessKey = $key;
+ }
+
+ function setActionEvent ($id, $event)
+ {
+ $this->custom[$id]["event"] = $event;
+ }
+
+ function setActionButton ($id, $image, $description = "", $accesskey = false, $action = false)
+ {
+ $this->custom[$id]["image"] = $image;
+ $this->custom[$id]["type"] = "actionsetter";
+ $this->custom[$id]["action"] = $action;
+ $this->custom[$id]["description"] = $description;
+ $this->custom[$id]["accesskey"] = $accesskey;
+ $this->custom[$id]["event"] = "";
+ }
+
+ function setConfirm ($id, $title, $description)
+ {
+ $this->custom[$id]["confirmtitle"] = $title;
+ $this->custom[$id]["confirmdescription"] = $description;
+ }
+
+ function unsetActionButton ($id)
+ {
+ unset($this->custom[$id]);
+ }
+
+ function render ($return = true)
+ {
+ global $sess, $cfg;
+
+ $tpl = new Template;
+
+ $extra = "";
+
+ if ($this->submitjs != "")
+ {
+ $fextra = 'onsubmit="'.$this->submitjs.'"';
+ } else {
+ $fextra = "";
+ }
+
+ $form = '