mirror of
				https://git.code.sf.net/p/seeddms/code
				synced 2025-10-28 19:51:25 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			2068 lines
		
	
	
		
			63 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			2068 lines
		
	
	
		
			63 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | ||
| //    MyDMS. Document Management System
 | ||
| //    Copyright (C) 2002-2005  Markus Westphal
 | ||
| //    Copyright (C) 2006-2008 Malcolm Cowe
 | ||
| //    Copyright (C) 2010 Matteo Lucarelli
 | ||
| //
 | ||
| //    This program is free software; you can redistribute it and/or modify
 | ||
| //    it under the terms of the GNU General Public License as published by
 | ||
| //    the Free Software Foundation; either version 2 of the License, or
 | ||
| //    (at your option) any later version.
 | ||
| //
 | ||
| //    This program is distributed in the hope that it will be useful,
 | ||
| //    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||
| //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | ||
| //    GNU General Public License for more details.
 | ||
| //
 | ||
| //    You should have received a copy of the GNU General Public License
 | ||
| //    along with this program; if not, write to the Free Software
 | ||
| //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | ||
| 
 | ||
| /* Date picker needs a different syntax for date formats using
 | ||
|  * yyyy for %Y
 | ||
|  * yy for %y
 | ||
|  * mm for %m
 | ||
|  * dd for %d
 | ||
|  * This functions returns the converted format
 | ||
|  */
 | ||
| function getConvertDateFormat($dateformat) { /* {{{ */
 | ||
| 	global $settings;
 | ||
| 	if(!$dateformat)
 | ||
| 		$dateformat = $settings->_dateformat;
 | ||
| 	if($dateformat) {
 | ||
| 		return str_replace(['y', 'Y', 'm', 'M', 'F', 'd', 'l', 'D'], ['yy', 'yyyy', 'mm', 'M', 'MM', 'dd', 'DD', 'D'], $settings->_dateformat);
 | ||
| 	} else
 | ||
| 		return 'yyyy-mm-dd';
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Return a human readable date string
 | ||
|  *
 | ||
|  * This function formats a timestamp according to the date format
 | ||
|  * settings. If no timestamp is passed the current date is used.
 | ||
|  * If null or an empty string is passed, then an empty string
 | ||
|  * is returned. If $timestamp is numeric it will be taken as a unix
 | ||
|  * timestamp. If $timestamp is a string it will be parѕed with strtotime().
 | ||
|  */
 | ||
| function getReadableDate($timestamp=0) { /* {{{ */
 | ||
| 	global $settings;
 | ||
| 	if($timestamp === 0)
 | ||
| 		$timestamp = time();
 | ||
| 	elseif($timestamp && is_numeric($timestamp))
 | ||
| 		;
 | ||
| 	elseif($timestamp && is_string($timestamp))
 | ||
| 		$timestamp = strtotime($timestamp);
 | ||
| 	elseif(!is_numeric($timestamp))
 | ||
| 		return '';
 | ||
| 	if($settings->_dateformat)
 | ||
| 		return date($settings->_dateformat, $timestamp);
 | ||
| 	else
 | ||
| 		return date("Y-m-d", $timestamp);
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Return a human readable date and time string
 | ||
|  *
 | ||
|  * See note for getReadableDate()
 | ||
|  */
 | ||
| function getLongReadableDate($timestamp=0) { /* {{{ */
 | ||
| 	global $settings;
 | ||
| 	if($timestamp === 0)
 | ||
| 		$timestamp = time();
 | ||
| 	elseif($timestamp && is_numeric($timestamp))
 | ||
| 		;
 | ||
| 	elseif($timestamp && is_string($timestamp))
 | ||
| 		$timestamp = strtotime($timestamp);
 | ||
| 	elseif(!is_numeric($timestamp))
 | ||
| 		return '';
 | ||
| 	if($settings->_datetimeformat)
 | ||
| 		return date($settings->_datetimeformat, $timestamp);
 | ||
| 	else
 | ||
| 		return date("Y-m-d H:i:s", $timestamp);
 | ||
| } /* }}} */
 | ||
| 
 | ||
| function getPeriodOfTime($timestamp) { /* {{{ */
 | ||
| 	if(!is_numeric($timestamp))
 | ||
| 		$timestamp = strtotime($timestamp);
 | ||
| 
 | ||
| 	$time = time() - $timestamp; // to get the time since that moment
 | ||
| 	$time = ($time<1)? 1 : $time;
 | ||
| 	$tokens = array (
 | ||
| 		31536000 => 'abbr_year',
 | ||
| 		2592000 => 'abbr_month',
 | ||
| 		604800 => 'abbr_week',
 | ||
| 		86400 => 'abbr_day',
 | ||
| 		3600 => 'abbr_hour',
 | ||
| 		60 => 'abbr_minute',
 | ||
| 		1 => 'abbr_second'
 | ||
| 	);
 | ||
| 
 | ||
| 	foreach ($tokens as $unit => $text) {
 | ||
| 		if ($time < $unit) continue;
 | ||
| 		$numberOfUnits = floor($time / $unit);
 | ||
| 		return $numberOfUnits.' '.(($numberOfUnits>1) ? getMLText($text):getMLText($text));
 | ||
| 	}
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /*
 | ||
|  * Converts a date string into a timestamp
 | ||
|  *
 | ||
|  * @param $date string date in format understood by strftime
 | ||
|  * @return integer/boolean unix timestamp or false in case of an error
 | ||
|  */
 | ||
| function makeTsFromDate($date) { /* {{{ */
 | ||
| 	return strtotime($date);
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /*
 | ||
|  * Converts a date/time string into a timestamp
 | ||
|  *
 | ||
|  * @param $date string date in form Y-m-d H:i:s
 | ||
|  * @return integer/boolean unix timestamp or false in case of an error
 | ||
|  */
 | ||
| function makeTsFromLongDate($date) { /* {{{ */
 | ||
| 	return strtotime($date);
 | ||
| 	$tmp = explode(' ', $date);
 | ||
| 	if(count($tmp) != 2)
 | ||
| 		return false;
 | ||
| 	$tarr = explode(':', $tmp[1]);
 | ||
| 	$darr = explode('-', $tmp[0]);
 | ||
| 	if(count($tarr) != 3 || count($darr) != 3)
 | ||
| 		return false;
 | ||
| 	$ts = mktime($tarr[0], $tarr[1], $tarr[2], $darr[1], $darr[2], $darr[0]);
 | ||
| 	return $ts;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| function getReadableDuration($secs) { /* {{{ */
 | ||
| 	$s = "";
 | ||
| 	foreach ( getReadableDurationArray($secs) as $k => $v ) {
 | ||
| 		if ( $v ) $s .= $v." ".($v==1? substr($k,0,-1) : $k).", ";
 | ||
| 	}
 | ||
| 
 | ||
| 	return substr($s, 0, -2);
 | ||
| } /* }}} */
 | ||
| 
 | ||
| function getReadableDurationArray($secs) { /* {{{ */
 | ||
| 	$units = array(
 | ||
| 		getMLText("weeks")   => 7*24*3600,
 | ||
| 		getMLText("days")    =>   24*3600,
 | ||
| 		getMLText("hours")   =>      3600,
 | ||
| 		getMLText("minutes") =>        60,
 | ||
| 		getMLText("seconds") =>         1,
 | ||
| 	);
 | ||
| 
 | ||
| 	foreach ( $units as &$unit ) {
 | ||
| 		$quot  = intval($secs / $unit);
 | ||
| 		$secs -= $quot * $unit;
 | ||
| 		$unit  = $quot;
 | ||
| 	}
 | ||
| 
 | ||
| 	return $units;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Return the timestamp after a period of time
 | ||
|  *
 | ||
|  * The period is relative to $start. $r sets if the returned
 | ||
|  * time stamp is the start, end or current seconds of day.
 | ||
|  * getTsByPeriod('today', 's') returns 00:00:00 of today
 | ||
|  * getTsByPeriod('tomorrow', 'e') returns 23:59:59 of tommorrow
 | ||
|  * The parameter $start can be any timestamp from where the
 | ||
|  * period starts
 | ||
|  * getTsByPeriod('today', 's', time()+7*86400) is equivalent to
 | ||
|  * getTsByPeriod('1w', 's')
 | ||
|  */
 | ||
| function getTsByPeriod($period, $r='', $start=0) { /* {{{ */
 | ||
| 	if(!$start)
 | ||
| 		$start = time();
 | ||
| 	$sofd = time() - strtotime('today'); // seconds elapsed today
 | ||
| 	switch($r) {
 | ||
| 	case 's': // start of day
 | ||
| 		$o = $sofd;
 | ||
| 		break;
 | ||
| 	case 'e': // end of day
 | ||
| 		$o = $sofd-86400+1;
 | ||
| 		break;
 | ||
| 	default: // same sec as current time
 | ||
| 		$o = 0;
 | ||
| 	}
 | ||
| 	switch($period) {
 | ||
| 	case "never":
 | ||
| 		$expiration = 0;
 | ||
| 		break;
 | ||
| 	case "1h":
 | ||
| 		$expiration = $start+3600;
 | ||
| 		break;
 | ||
| 	case "2h":
 | ||
| 		$expiration = $start+7200;
 | ||
| 		break;
 | ||
| 	case "24h":
 | ||
| 		$expiration = $start+86400;
 | ||
| 		break;
 | ||
| 	case "today":
 | ||
| 		$expiration = $start - $o;
 | ||
| 		break;
 | ||
| 	case "1d":
 | ||
| 		$expiration = $start-$o+86400;
 | ||
| 		break;
 | ||
| 	case "tomorrow":
 | ||
| 		$expiration = $start - $o + 86400;
 | ||
| 		break;
 | ||
| 	case "1w":
 | ||
| 		$expiration = $start-$o+7*86400;
 | ||
| 		break;
 | ||
| 	case "1m":
 | ||
| 		$tmp = explode('-', date('Y-m-d', $start));
 | ||
| 		$expiration = mktime(0,0,0, $tmp[1]+1, $tmp[2], $tmp[0])+$sofd-$o;
 | ||
| 		break;
 | ||
| 	case "1y":
 | ||
| 		$tmp = explode('-', date('Y-m-d', $start));
 | ||
| 		$expiration = mktime(0,0,0, $tmp[1], $tmp[2], $tmp[0]+1)+$sofd-$o;
 | ||
| 		break;
 | ||
| 	case "2y":
 | ||
| 		$tmp = explode('-', date('Y-m-d', $start));
 | ||
| 		$expiration = mktime(0,0,0, $tmp[1], $tmp[2], $tmp[0]+2)+$sofd-$o;
 | ||
| 		break;
 | ||
| 	case "3y":
 | ||
| 		$tmp = explode('-', date('Y-m-d', $start));
 | ||
| 		$expiration = mktime(0,0,0, $tmp[1], $tmp[2], $tmp[0]+3)+$sofd-$o;
 | ||
| 		break;
 | ||
| 	default:
 | ||
| 		$expiration = false;
 | ||
| 	}
 | ||
| 	return $expiration;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /* Deprecated, do not use anymore, but keep it for upgrading
 | ||
|  * older versions
 | ||
|  */
 | ||
| function mydmsDecodeString($string) { /* {{{ */
 | ||
| 
 | ||
| 	$string = (string)$string;
 | ||
| 
 | ||
| 	$string = str_replace("&", "&", $string);
 | ||
| 	$string = str_replace("%", "%", $string); // percent
 | ||
| 	$string = str_replace(""", "\"", $string); // double quote
 | ||
| 	$string = str_replace("/*", "/*", $string); // start of comment
 | ||
| 	$string = str_replace("*/", "*/", $string); // end of comment
 | ||
| 	$string = str_replace("<", "<", $string);
 | ||
| 	$string = str_replace(">", ">", $string);
 | ||
| 	$string = str_replace("=", "=", $string);
 | ||
| 	$string = str_replace(")", ")", $string);
 | ||
| 	$string = str_replace("(", "(", $string);
 | ||
| 	$string = str_replace("'", "'", $string);
 | ||
| 	$string = str_replace("+", "+", $string);
 | ||
| 
 | ||
| 	return $string;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| function createVersionigFile($document) { /* {{{ */
 | ||
| 	global $settings, $dms;
 | ||
| 
 | ||
| 	// if directory has been removed recreate it
 | ||
| 	if (!file_exists($dms->contentDir . $document->getDir()))
 | ||
| 		if (!SeedDMS_Core_File::makeDir($dms->contentDir . $document->getDir())) return false;
 | ||
| 
 | ||
| 	$handle = fopen($dms->contentDir . $document->getDir() .$settings-> _versioningFileName , "wb");
 | ||
| 
 | ||
| 	if (is_bool($handle)&&!$handle) return false;
 | ||
| 
 | ||
| 	$tmp = $document->getName()." (ID ".$document->getID().")\n\n";
 | ||
| 	fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	$owner = $document->getOwner();
 | ||
| 	$tmp = getMLText("owner")." = ".$owner->getFullName()." <".$owner->getEmail().">\n";
 | ||
| 	fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	$tmp = getMLText("creation_date")." = ".getLongReadableDate($document->getDate())."\n";
 | ||
| 	fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	$latestContent = $document->getLatestContent();
 | ||
| 	$tmp = "\n### ".getMLText("current_version")." ###\n\n";
 | ||
| 	fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	$tmp = getMLText("version")." = ".$latestContent->getVersion()."\n";
 | ||
| 	fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	$tmp = getMLText("file")." = ".$latestContent->getOriginalFileName()." (".$latestContent->getMimeType().")\n";
 | ||
| 	fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	$tmp = getMLText("comment")." = ". $latestContent->getComment()."\n";
 | ||
| 	fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	$status = $latestContent->getStatus();
 | ||
| 	$tmp = getMLText("status")." = ".getOverallStatusText($status["status"])."\n";
 | ||
| 	fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	$reviewStatus = $latestContent->getReviewStatus();
 | ||
| 	$tmp = "\n### ".getMLText("reviewers")." ###\n";
 | ||
| 	fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	foreach ($reviewStatus as $r) {
 | ||
| 
 | ||
| 		switch ($r["type"]) {
 | ||
| 			case 0: // Reviewer is an individual.
 | ||
| 				$required = $dms->getUser($r["required"]);
 | ||
| 				if (!is_object($required)) $reqName = getMLText("unknown_user")." = ".$r["required"];
 | ||
| 				else $reqName =  getMLText("user")." = ".$required->getFullName();
 | ||
| 				break;
 | ||
| 			case 1: // Reviewer is a group.
 | ||
| 				$required = $dms->getGroup($r["required"]);
 | ||
| 				if (!is_object($required)) $reqName = getMLText("unknown_group")." = ".$r["required"];
 | ||
| 				else $reqName = getMLText("group")." = ".$required->getName();
 | ||
| 				break;
 | ||
| 		}
 | ||
| 
 | ||
| 		$tmp = "\n".$reqName."\n";
 | ||
| 		fwrite($handle, $tmp);
 | ||
| 
 | ||
| 		$tmp = getMLText("status")." = ".getReviewStatusText($r["status"])."\n";
 | ||
| 		fwrite($handle, $tmp);
 | ||
| 
 | ||
| 		$tmp = getMLText("comment")." = ". $r["comment"]."\n";
 | ||
| 		fwrite($handle, $tmp);
 | ||
| 
 | ||
| 		$tmp = getMLText("last_update")." = ".$r["date"]."\n";
 | ||
| 		fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	}
 | ||
| 
 | ||
| 
 | ||
| 	$approvalStatus = $latestContent->getApprovalStatus();
 | ||
| 	$tmp = "\n### ".getMLText("approvers")." ###\n";
 | ||
| 	fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	foreach ($approvalStatus as $r) {
 | ||
| 
 | ||
| 		switch ($r["type"]) {
 | ||
| 			case 0: // Reviewer is an individual.
 | ||
| 				$required = $dms->getUser($r["required"]);
 | ||
| 				if (!is_object($required)) $reqName = getMLText("unknown_user")." = ".$r["required"];
 | ||
| 				else $reqName =  getMLText("user")." = ".$required->getFullName();
 | ||
| 				break;
 | ||
| 			case 1: // Reviewer is a group.
 | ||
| 				$required = $dms->getGroup($r["required"]);
 | ||
| 				if (!is_object($required)) $reqName = getMLText("unknown_group")." = ".$r["required"];
 | ||
| 				else $reqName = getMLText("group")." = ".$required->getName();
 | ||
| 				break;
 | ||
| 		}
 | ||
| 
 | ||
| 		$tmp = "\n".$reqName."\n";
 | ||
| 		fwrite($handle, $tmp);
 | ||
| 
 | ||
| 		$tmp = getMLText("status")." = ".getApprovalStatusText($r["status"])."\n";
 | ||
| 		fwrite($handle, $tmp);
 | ||
| 
 | ||
| 		$tmp = getMLText("comment")." = ". $r["comment"]."\n";
 | ||
| 		fwrite($handle, $tmp);
 | ||
| 
 | ||
| 		$tmp = getMLText("last_update")." = ".$r["date"]."\n";
 | ||
| 		fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	}
 | ||
| 
 | ||
| 	$versions = $document->getContent();
 | ||
| 	$tmp = "\n### ".getMLText("previous_versions")." ###\n";
 | ||
| 	fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	for ($i = count($versions)-2; $i >= 0; $i--){
 | ||
| 
 | ||
| 		$version = $versions[$i];
 | ||
| 		$status = $version->getStatus();
 | ||
| 
 | ||
| 		$tmp = "\n".getMLText("version")." = ".$version->getVersion()."\n";
 | ||
| 		fwrite($handle, $tmp);
 | ||
| 
 | ||
| 		$tmp = getMLText("file")." = ".$version->getOriginalFileName()." (".$version->getMimeType().")\n";
 | ||
| 		fwrite($handle, $tmp);
 | ||
| 
 | ||
| 		$tmp = getMLText("comment")." = ". $version->getComment()."\n";
 | ||
| 		fwrite($handle, $tmp);
 | ||
| 
 | ||
| 		$status = $latestContent->getStatus();
 | ||
| 		$tmp = getMLText("status")." = ".getOverallStatusText($status["status"])."\n";
 | ||
| 		fwrite($handle, $tmp);
 | ||
| 
 | ||
| 	}
 | ||
| 
 | ||
| 	fclose($handle);
 | ||
| 	return true;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Calculate disk space of file or directory
 | ||
|  *
 | ||
|  * original funcion by shalless at rubix dot net dot au (php.net)
 | ||
|  * stat() replace by filesize() to make it work on all platforms.
 | ||
|  *
 | ||
|  * @param string $dir directory or filename
 | ||
|  * @return integer number of bytes
 | ||
|  */
 | ||
| function dskspace($dir) { /* {{{ */
 | ||
| 	$space = 0;
 | ||
| 	if(is_file($dir)) {
 | ||
| 		$space = filesize($dir);
 | ||
| 	} elseif (is_dir($dir)) {
 | ||
| 		if($dh = opendir($dir)) {
 | ||
| 			while (($file = readdir($dh)) !== false)
 | ||
| 				if ($file != "." and $file != "..")
 | ||
| 					$space += dskspace($dir."/".$file);
 | ||
| 			closedir($dh);
 | ||
| 		}
 | ||
| 	}
 | ||
| 	return $space;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Replacement of PHP's basename function
 | ||
|  *
 | ||
|  * Because basename is locale dependent and strips off non ascii chars
 | ||
|  * from the beginning of filename, it cannot be used in a environment
 | ||
|  * where locale is set to e.g. 'C'
 | ||
|  */
 | ||
| function utf8_basename($path, $suffix='') { /* {{{ */
 | ||
| 	$rpos = strrpos($path, DIRECTORY_SEPARATOR);
 | ||
| 	if($rpos === false)
 | ||
| 		return $path;
 | ||
| 	$file = substr($path, $rpos+1);
 | ||
| 
 | ||
| 	$suflen = strlen($suffix);
 | ||
| 	if($suflen && (substr($file, -$suflen) == $suffix)){
 | ||
| 			$file = substr($file, 0, -$suflen);
 | ||
| 	}
 | ||
| 
 | ||
| 	return $file;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Return a valid file name
 | ||
|  *
 | ||
|  * This function returns a valid file name for the given document content
 | ||
|  * or an arbitrary string. If a document content is given the name of
 | ||
|  * the document will be used. The extension of the file name will be
 | ||
|  * either taken from the document name or the original file. If the two
 | ||
|  * differ the extension from the original file name will be used.
 | ||
|  *
 | ||
|  * @param object|string $content document content or an arbitrary string
 | ||
|  * @return string valid file name
 | ||
|  */
 | ||
| function getFilenameByDocname($content) { /* {{{ */
 | ||
| 	if(is_string($content)) {
 | ||
| 		$filename = $content;
 | ||
| 	} else {
 | ||
| 		$document = $content->getDocument();
 | ||
| 		$ext = pathinfo($document->getName(), PATHINFO_EXTENSION);
 | ||
| 		$oext = pathinfo($content->getOriginalFileName(), PATHINFO_EXTENSION);
 | ||
| 		if($ext == $oext)
 | ||
| 			$filename = $document->getName();
 | ||
| 		else {
 | ||
| 			$filename = $document->getName().'.'.$oext;
 | ||
| 		}
 | ||
| 	}
 | ||
| 	return mb_ereg_replace("([^\w\s\d\-_~,;\[\]\(\).])", '', $filename);
 | ||
| } /* }}} */
 | ||
| 
 | ||
| function getLogger($prefix='', $mask=PEAR_LOG_INFO) { /* {{{ */
 | ||
| 	global $settings;
 | ||
| 
 | ||
| 	if($settings->_logFileEnable) {
 | ||
| 		if ($settings->_logFileRotation=="h") $logname=date("YmdH", time());
 | ||
| 		else if ($settings->_logFileRotation=="d") $logname=date("Ymd", time());
 | ||
| 		else $logname=date("Ym", time());
 | ||
| 		$logname = $settings->_contentDir."log/".$prefix.$logname.".log";
 | ||
| 		if(!file_exists($settings->_contentDir.'log'))
 | ||
| 			@mkdir($settings->_contentDir.'log');
 | ||
| 		if(file_exists($settings->_contentDir.'log') && is_dir($settings->_contentDir.'log')) {
 | ||
| 			$logger = Log::factory('file', $logname);
 | ||
| 			$logger->setMask(Log::MAX($mask));
 | ||
| 		} else
 | ||
| 			$logger = null;
 | ||
| 	} else {
 | ||
| 		$logger = null;
 | ||
| 	}
 | ||
| 	return $logger;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Log a message
 | ||
|  *
 | ||
|  * This function is still here for convienice and because it is
 | ||
|  * used at so many places.
 | ||
|  *
 | ||
|  * @param string $msg
 | ||
|  * @param int $priority can be one of PEAR_LOG_EMERG, PEAR_LOG_ALERT,
 | ||
|  *            PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
 | ||
|  *						PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
 | ||
|  */
 | ||
| function add_log_line($msg="", $priority=null) { /* {{{ */
 | ||
| 	global $logger, $user;
 | ||
| 
 | ||
| 	if(!$logger) return;
 | ||
| 
 | ||
| 	$ip = "-";
 | ||
| 	if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
 | ||
| 		$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
 | ||
| 	elseif(!empty($_SERVER['REMOTE_ADDR']))
 | ||
| 		$ip = $_SERVER['REMOTE_ADDR'];
 | ||
| 	if(!empty($_SERVER["REQUEST_URI"]))
 | ||
| 		$scriptname = basename($_SERVER["REQUEST_URI"]).' ';
 | ||
| 	else
 | ||
| 		$scriptname = basename($_SERVER["SCRIPT_NAME"]).' ';
 | ||
| 	if($user)
 | ||
| 		$logger->log($user->getLogin()." (".$ip.") ".$scriptname.($msg ? $msg : ''), $priority);
 | ||
| 	else
 | ||
| 		$logger->log("-- (".$ip.") ".$scriptname.($msg ? $msg : ''), $priority);
 | ||
| } /* }}} */
 | ||
| 
 | ||
| function _add_log_line($msg="") { /* {{{ */
 | ||
| 	global $settings,$user;
 | ||
| 
 | ||
| 	if ($settings->_logFileEnable!=TRUE) return;
 | ||
| 
 | ||
| 	if ($settings->_logFileRotation=="h") $logname=date("YmdH", time());
 | ||
| 	else if ($settings->_logFileRotation=="d") $logname=date("Ymd", time());
 | ||
| 	else $logname=date("Ym", time());
 | ||
| 
 | ||
| 	if($h = fopen($settings->_contentDir.$logname.".log", "a")) {
 | ||
| 		fwrite($h,date("Y/m/d H:i", time())." ".$user->getLogin()." (".$_SERVER['REMOTE_ADDR'].") ".basename($_SERVER["REQUEST_URI"]).$msg."\n");
 | ||
| 		fclose($h);
 | ||
| 	}
 | ||
| } /* }}} */
 | ||
| 
 | ||
| function getFolderPathHTML($folder, $tagAll=false, $document=null) { /* {{{ */
 | ||
| 	$path = $folder->getPath();
 | ||
| 	$txtpath = "";
 | ||
| 	for ($i = 0; $i < count($path); $i++) {
 | ||
| 		if ($i +1 < count($path)) {
 | ||
| 			$txtpath .= "<a href=\"../out/out.ViewFolder.php?folderid=".$path[$i]->getID()."&showtree=".showtree()."\">".
 | ||
| 				htmlspecialchars($path[$i]->getName())."</a> / ";
 | ||
| 		}
 | ||
| 		else {
 | ||
| 			$txtpath .= ($tagAll ? "<a href=\"../out/out.ViewFolder.php?folderid=".$path[$i]->getID()."&showtree=".showtree()."\">".
 | ||
| 									 htmlspecialchars($path[$i]->getName())."</a>" : htmlspecialchars($path[$i]->getName()));
 | ||
| 		}
 | ||
| 	}
 | ||
| 	if($document)
 | ||
| 		$txtpath .= " / <a href=\"../out/out.ViewDocument.php?documentid=".$document->getId()."\">".htmlspecialchars($document->getName())."</a>";
 | ||
| 
 | ||
| 	return $txtpath;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| function showtree() { /* {{{ */
 | ||
| 	global $settings;
 | ||
| 
 | ||
| 	if (isset($_GET["showtree"])) return intval($_GET["showtree"]);
 | ||
| 	else if ($settings->_expandFolderTree==0) return 0;
 | ||
| 
 | ||
| 	return 1;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Create a unique key which is used for form validation to prevent
 | ||
|  * CSRF attacks. The key is added to a any form that has to be secured
 | ||
|  * as a hidden field. Once the form is submitted the key is compared
 | ||
|  * to the current key in the session and the request is only executed
 | ||
|  * if both are equal. The key is derived from the session id, a configurable
 | ||
|  * encryption key and form identifierer.
 | ||
|  *
 | ||
|  * @param string $formid individual form identifier
 | ||
|  * @return string session key
 | ||
|  */
 | ||
| function createFormKey($formid='') { /* {{{ */
 | ||
| 	global $settings, $session;
 | ||
| 
 | ||
| 	if($session && $id = $session->getId()) {
 | ||
| 		return md5($id.$settings->_encryptionKey.$formid);
 | ||
| 	} else {
 | ||
| 		return md5($settings->_encryptionKey.$formid);
 | ||
| 	}
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Create a hidden field with the name 'formtoken' and set its value
 | ||
|  * to the key returned by createFormKey()
 | ||
|  *
 | ||
|  * @param string $formid individual form identifier
 | ||
|  * @return string input field for html formular
 | ||
|  */
 | ||
| function createHiddenFieldWithKey($formid='') { /* {{{ */
 | ||
| 	return '<input type="hidden" name="formtoken" value="'.createFormKey($formid).'" />';
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Check if the form key in the POST or GET request variable 'formtoken'
 | ||
|  * has the value of key returned by createFormKey(). Request to modify
 | ||
|  * data in the DMS should always use POST because it is harder to run
 | ||
|  * CSRF attacks using POST than GET.
 | ||
|  *
 | ||
|  * @param string $formid individual form identifier
 | ||
|  * @param string $method defines if the form data is pass via GET or
 | ||
|  * POST (default)
 | ||
|  * @return boolean true if key matches otherwise false
 | ||
|  */
 | ||
| function checkFormKey($formid='', $method='POST') { /* {{{ */
 | ||
| 	switch($method) {
 | ||
| 		case 'GET':
 | ||
| 			if(isset($_GET['formtoken']) && $_GET['formtoken'] == createFormKey($formid))
 | ||
| 				return true;
 | ||
| 			break;
 | ||
| 		default:
 | ||
| 			if(isset($_POST['formtoken']) && $_POST['formtoken'] == createFormKey($formid))
 | ||
| 				return true;
 | ||
| 	}
 | ||
| 
 | ||
| 	return false;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Check disk usage of currently logged in user
 | ||
|  *
 | ||
|  * @return boolean/integer true if no quota is set, number of bytes until
 | ||
|  *         quota is reached. Negative values indicate a disk usage above quota.
 | ||
|  */
 | ||
| function checkQuota($user) { /* {{{ */
 | ||
| 	global $settings, $dms;
 | ||
| 
 | ||
| 	/* check if quota is turn off system wide */
 | ||
| 	if($settings->_quota == 0)
 | ||
| 		return true;
 | ||
| 
 | ||
| 	$quota = 0;
 | ||
| 	$uquota = $user->getQuota();
 | ||
| 	if($uquota > 0)
 | ||
| 		$quota = $uquota;
 | ||
| 	elseif($settings->_quota > 0) {
 | ||
| 		$quota = $settings->_quota;
 | ||
| 	}
 | ||
| 
 | ||
| 	if($quota == 0)
 | ||
| 		return true;
 | ||
| 
 | ||
| 	return ($quota - $user->getUsedDiskSpace());
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Encrypt any data with a key
 | ||
|  *
 | ||
|  * @param string $key
 | ||
|  * @param string $value plain text data
 | ||
|  * @return string encrypted data
 | ||
|  */
 | ||
| function encryptData($key, $value) { /* {{{ */
 | ||
| 	if(function_exists('openssl_cipher_iv_length')) {
 | ||
| 		$nonceSize = openssl_cipher_iv_length('aes-256-ctr');
 | ||
| 		$nonce = openssl_random_pseudo_bytes($nonceSize);
 | ||
| 
 | ||
| 		$ciphertext = openssl_encrypt(
 | ||
| 			$value,
 | ||
| 			'aes-256-ctr',
 | ||
| 			$key,
 | ||
| 			OPENSSL_RAW_DATA,
 | ||
| 			$nonce
 | ||
| 		);
 | ||
| 
 | ||
| 		// Now let's pack the IV and the ciphertext together
 | ||
| 		// Naively, we can just concatenate
 | ||
| 		return $nonce.$ciphertext;
 | ||
| 	} else {	
 | ||
| 		$text = $value;
 | ||
| 		$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
 | ||
| 		$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
 | ||
| 		$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv);
 | ||
| 		return $crypttext;
 | ||
| 	}
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Decrypt data previously encrypted by encrypt
 | ||
|  *
 | ||
|  * @param string $key
 | ||
|  * @param string $value encrypted data
 | ||
|  * @return string plain text data
 | ||
|  */
 | ||
| function decryptData($key, $value) { /* {{{ */
 | ||
| 	if(function_exists('openssl_cipher_iv_length')) {
 | ||
| 		$nonceSize = openssl_cipher_iv_length('aes-256-ctr');
 | ||
| 		$nonce = mb_substr($value, 0, $nonceSize, '8bit');
 | ||
| 		$ciphertext = mb_substr($value, $nonceSize, null, '8bit');
 | ||
| 		
 | ||
| 		$plaintext = openssl_decrypt(
 | ||
| 			$ciphertext,
 | ||
| 			'aes-256-ctr',
 | ||
| 			$key,
 | ||
| 			OPENSSL_RAW_DATA,
 | ||
| 			$nonce
 | ||
| 		);
 | ||
| 		return $plaintext;
 | ||
| 	} else {
 | ||
| 		$crypttext = $value;
 | ||
| 		$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
 | ||
| 		$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
 | ||
| 		$decrypttext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $crypttext, MCRYPT_MODE_ECB, $iv);
 | ||
| 		return trim($decrypttext);
 | ||
| 	}
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Return file extension for a give mimetype
 | ||
|  *
 | ||
|  * @param string $mimetype Mime-Type
 | ||
|  * @return string file extension including leading dot
 | ||
|  */
 | ||
| function get_extension($mimetype) { /* {{{ */
 | ||
| 	if(empty($mimetype)) return false;
 | ||
| 	switch($mimetype) {
 | ||
| 		case 'image/bmp': return '.bmp';
 | ||
| 		case 'image/x-ms-bmp': return '.bmp';
 | ||
| 		case 'image/cis-cod': return '.cod';
 | ||
| 		case 'image/gif': return '.gif';
 | ||
| 		case 'image/ief': return '.ief';
 | ||
| 		case 'image/jpeg': return '.jpg';
 | ||
| 		case 'image/jpg': return '.jpg';
 | ||
| 		case 'image/pipeg': return '.jfif';
 | ||
| 		case 'image/tiff': return '.tif';
 | ||
| 		case 'image/x-cmu-raster': return '.ras';
 | ||
| 		case 'image/x-cmx': return '.cmx';
 | ||
| 		case 'image/x-icon': return '.ico';
 | ||
| 		case 'image/x-portable-anymap': return '.pnm';
 | ||
| 		case 'image/x-portable-bitmap': return '.pbm';
 | ||
| 		case 'image/x-portable-graymap': return '.pgm';
 | ||
| 		case 'image/x-portable-pixmap': return '.ppm';
 | ||
| 		case 'image/x-rgb': return '.rgb';
 | ||
| 		case 'image/x-xbitmap': return '.xbm';
 | ||
| 		case 'image/x-xpixmap': return '.xpm';
 | ||
| 		case 'image/x-xwindowdump': return '.xwd';
 | ||
| 		case 'image/png': return '.png';
 | ||
| 		case 'image/x-jps': return '.jps';
 | ||
| 		case 'image/x-freehand': return '.fh';
 | ||
| 		case 'image/svg+xml': return '.svg';
 | ||
| 		case 'audio/mp3': return '.mp3';
 | ||
| 		case 'audio/mpeg': return '.mpeg';
 | ||
| 		case 'audio/ogg': return '.ogg';
 | ||
| 		case 'video/mp4': return '.mp4';
 | ||
| 		case 'video/webm': return '.webm';
 | ||
| 		case 'application/zip': return '.zip';
 | ||
| 		case 'application/x-gzip': return '.gz';
 | ||
| 		case 'application/x-rar': return '.rar';
 | ||
| 		case 'application/x-7z-compressed': return '.7z';
 | ||
| 		case 'application/x-compressed-tar': return '.tgz';
 | ||
| 		case 'application/x-tar': return '.tar';
 | ||
| 		case 'application/x-xopp': return '.xopp';
 | ||
| 		case 'application/pdf': return '.pdf';
 | ||
| 		case 'application/dxf': return '.dxf';
 | ||
| 		case 'application/msword': return '.doc';
 | ||
| 		case 'application/vnd.ms-powerpoint': return '.ppt';
 | ||
| 		case 'application/vnd.ms-excel': return '.xls';
 | ||
| 		case 'application/postscript': return '.ps';
 | ||
| 		case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': return '.docx';
 | ||
| 		case 'application/vnd.openxmlformats-officedocument.presentationml.presentation': return '.pptx';
 | ||
| 		case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': return '.xlsx';
 | ||
| 		case 'application/vnd.oasis.opendocument.text': return '.odt';
 | ||
| 		case 'application/vnd.oasis.opendocument.spreadsheet': return '.ods';
 | ||
| 		case 'application/vnd.oasis.opendocument.presentation': return '.odp';
 | ||
| 		case 'application/vnd.apple.pages': return '.pages';
 | ||
| 		case 'application/vnd.apple.numbers': return '.numbers';
 | ||
| 		case 'application/vnd.apple.keynote': return '.keynote';
 | ||
| 		case 'application/vnd.wordperfect': return '.wpd';
 | ||
| 		case 'application/vnd.ms-works': return '.wps';
 | ||
| 		case 'text/plain': return '.txt';
 | ||
| 		case 'text/csv': return '.csv';
 | ||
| 		case 'text/rtf': return '.rtf';
 | ||
| 		case 'text/xml': return '.xml';
 | ||
| 		case 'text/x-php': return '.php';
 | ||
| 		case 'text/x-tex': return '.tex';
 | ||
| 		case 'message/rfc822': return '.eml';
 | ||
| 		default: return false;
 | ||
| 	}
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Adds a missing directory separator (or any other char) to a string
 | ||
|  *
 | ||
|  * This function is used for making sure a directory name has a
 | ||
|  * trailing directory separator. It can also be used to add
 | ||
|  * any other char at the end of a string, e.g. an URL which must
 | ||
|  * end in '/' (DIRECTORY_SEPARATOR wouldn't be right in that case,
 | ||
|  * because it is '\' on Windows)
 | ||
|  */
 | ||
| function addDirSep($str, $chr=DIRECTORY_SEPARATOR) { /* {{{ */
 | ||
| 	if(trim($str) == '')
 | ||
| 		return '';
 | ||
| 	if(substr(trim($str), -1, 1) != $chr)
 | ||
| 		return trim($str).$chr;
 | ||
| 	else
 | ||
| 		return trim($str);
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Formats comments for aknowledge of reception.
 | ||
|  *
 | ||
|  * Only use in documentListRow()
 | ||
|  */
 | ||
| function formatComment($an) { /* {{{ */
 | ||
| 	$t = array();
 | ||
| 	foreach($an as $a)
 | ||
| 		$t[] = $a['n']." × ".$a['c'];
 | ||
| 	return $t;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /*
 | ||
|  * Determines if a command exists on the current environment
 | ||
|  *
 | ||
|  * @param string $command The command to check
 | ||
|  * @return bool True if the command has been found ; otherwise, false.
 | ||
|  */
 | ||
| function commandExists ($command) { /* {{{ */
 | ||
| 	$whereIsCommand = (PHP_OS == 'WINNT') ? 'where' : 'command -v';
 | ||
| 
 | ||
| 	$process = proc_open(
 | ||
| 		"$whereIsCommand $command",
 | ||
| 		array(
 | ||
| 			0 => array("pipe", "r"), //STDIN
 | ||
| 			1 => array("pipe", "w"), //STDOUT
 | ||
| 			2 => array("pipe", "w"), //STDERR
 | ||
| 		),
 | ||
| 		$pipes
 | ||
| 	);
 | ||
| 	if ($process !== false) {
 | ||
| 		$stdout = stream_get_contents($pipes[1]);
 | ||
| 		$stderr = stream_get_contents($pipes[2]);
 | ||
| 		fclose($pipes[1]);
 | ||
| 		fclose($pipes[2]);
 | ||
| 		proc_close($process);
 | ||
| 
 | ||
| 		return $stdout != '';
 | ||
| 	}
 | ||
| 
 | ||
| 	return false;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Send a file from disk to the browser
 | ||
|  *
 | ||
|  * This function uses either readfile() or the xѕendfile apache module if
 | ||
|  * it is installed.
 | ||
|  *
 | ||
|  * @param string $filename
 | ||
|  */
 | ||
| function sendFile($filename) { /* {{{ */
 | ||
| 	global $settings;
 | ||
| 	if($settings->_enableXsendfile && function_exists('apache_get_modules') && in_array('mod_xsendfile',apache_get_modules())) {
 | ||
| 		header("X-Sendfile: ".$filename);
 | ||
| 	} else {
 | ||
| 
 | ||
| 		$size = filesize($filename);
 | ||
| 		if (isset($_SERVER['HTTP_RANGE'])) {
 | ||
| 			$fp = @fopen($filename, 'rb');
 | ||
| 			$length = $size;           // Content length
 | ||
| 			$start  = 0;               // Start byte
 | ||
| 			$end    = $size - 1;       // End byte
 | ||
| 
 | ||
| //			header("Accept-Ranges: 0-$length");
 | ||
| 			header("Accept-Ranges: bytes");
 | ||
| 
 | ||
| 			$c_start = $start;
 | ||
| 			$c_end   = $end;
 | ||
| 
 | ||
| 			list($unit, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
 | ||
| 			if (trim($unit) !== 'bytes') {
 | ||
| 					header('HTTP/1.1 416 Requested Range Not Satisfiable');
 | ||
| 					header("Content-Range: bytes $start-$end/$size");
 | ||
| 					exit;
 | ||
| 			}
 | ||
| 			if (strpos($range, ',') !== false) {
 | ||
| 					header('HTTP/1.1 416 Requested Range Not Satisfiable');
 | ||
| 					header("Content-Range: bytes $start-$end/$size");
 | ||
| 					exit;
 | ||
| 			}
 | ||
| 			if ($range == '-') {
 | ||
| 					$c_start = $size - substr($range, 1);
 | ||
| 			} else {
 | ||
| 					$range  = explode('-', $range);
 | ||
| 					$c_start = $range[0];
 | ||
| 					$c_end   = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size;
 | ||
| 			}
 | ||
| 			$c_end = ($c_end > $end) ? $end : $c_end;
 | ||
| 			if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) {
 | ||
| 					header('HTTP/1.1 416 Requested Range Not Satisfiable');
 | ||
| 					header("Content-Range: bytes $start-$end/$size");
 | ||
| 					exit;
 | ||
| 			}
 | ||
| 			$start  = $c_start;
 | ||
| 			$end    = $c_end;
 | ||
| 			$length = $end - $start + 1;
 | ||
| 			fseek($fp, $start);
 | ||
| 			header('HTTP/1.1 206 Partial Content');
 | ||
| 			header("Content-Range: bytes $start-$end/$size");
 | ||
| 			header("Content-Length: " . $length);
 | ||
| 
 | ||
| 			$buffer = 1024 * 8;
 | ||
| 			while(!feof($fp) && ($p = ftell($fp)) <= $end) {
 | ||
| 				if ($p + $buffer > $end) {
 | ||
| 					$buffer = $end - $p + 1;
 | ||
| 				}
 | ||
| 				set_time_limit(0);
 | ||
| 				echo fread($fp, $buffer);
 | ||
| 				flush();
 | ||
| 			}
 | ||
| 
 | ||
| 			fclose($fp);
 | ||
| 		} else {
 | ||
| 			header("Content-Length: " . $size);
 | ||
| 			/* Make sure output buffering is off */
 | ||
| 			if (ob_get_level()) {
 | ||
| 				ob_end_clean();
 | ||
| 			}
 | ||
| 			readfile($filename);
 | ||
| 		}
 | ||
| 	}
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Return protocol and host of url
 | ||
|  *
 | ||
|  * @return string
 | ||
|  */
 | ||
| function getBaseUrl() { /* {{{ */
 | ||
| 	global $settings;
 | ||
| 
 | ||
| 	if(!empty($settings->_baseUrl))
 | ||
| 		return $settings->_baseUrl;
 | ||
| 
 | ||
| 	if(isset($_SERVER['HTTP_X_FORWARDED_HOST']))
 | ||
| 		$host = $_SERVER['HTTP_X_FORWARDED_HOST'];
 | ||
| 	else
 | ||
| 		$host = $_SERVER['HTTP_HOST'];
 | ||
| 	if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']))
 | ||
| 		$ssl = $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https';
 | ||
| 	else
 | ||
| 		$ssl = (isset($_SERVER['HTTPS']) && (strcmp($_SERVER['HTTPS'],'off')!=0));
 | ||
| 
 | ||
| 	return "http".($ssl ? "s" : "")."://".$host;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| function getToken($length){ /* {{{ */
 | ||
| 	$token = "";
 | ||
| 	$codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 | ||
| 	$codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
 | ||
| 	$codeAlphabet.= "0123456789";
 | ||
| 	$max = strlen($codeAlphabet);
 | ||
| 
 | ||
| 	for ($i=0; $i < $length; $i++) {
 | ||
| 		$token .= $codeAlphabet[random_int(0, $max-1)];
 | ||
| 	}
 | ||
| 
 | ||
| 	return $token;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| function isAjax() { /* {{{ */
 | ||
| 	if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
 | ||
| 		return true;
 | ||
| 	else	
 | ||
| 		return false;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Hash a password
 | ||
|  *
 | ||
|  * @param string $password
 | ||
|  * @return string hashed password
 | ||
|  */
 | ||
| function seed_pass_hash($password) { /* {{{ */
 | ||
| 	return md5($password);
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Verify a password
 | ||
|  *
 | ||
|  * @param string $password
 | ||
|  * @return string hashed password
 | ||
|  */
 | ||
| function seed_pass_verify($password, $hash) { /* {{{ */
 | ||
| 	return $hash === md5($password);
 | ||
| } /* }}} */
 | ||
| 
 | ||
| function resolveTask($task) { /* {{{ */
 | ||
| 	global $dms, $user, $settings, $logger, $fulltextservice, $notifier, $conversionmgr;
 | ||
| 
 | ||
| 	if(is_object($task))
 | ||
| 		return $task;
 | ||
| 	if(is_string($task)) {
 | ||
| 		if(class_exists($task)) {
 | ||
| 			$task = new $task($dms, $user, $settings, $logger, $fulltextservice, $notifier, $conversionmgr);
 | ||
| 		}
 | ||
| 	}
 | ||
| 	return $task;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Return nonce for CSP
 | ||
|  *
 | ||
|  * @return string
 | ||
|  */
 | ||
| function createNonce() { /* {{{ */
 | ||
| 	$length = 16;
 | ||
| 	$usable = true;
 | ||
| 	$bytes = openssl_random_pseudo_bytes($length, $usable);
 | ||
| 	if ($usable === false) {
 | ||
| 			// weak
 | ||
| 			// @TODO do something?
 | ||
| 	}
 | ||
| 	return base64_encode($bytes);
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Create a real uniqid for cryptographic purposes
 | ||
|  *
 | ||
|  * @ return string
 | ||
|  */
 | ||
| function uniqidReal($lenght = 13) {
 | ||
| 	// uniqid gives 13 chars, but you could adjust it to your needs.
 | ||
| 	if (function_exists("random_bytes")) {
 | ||
| 		$bytes = random_bytes(ceil($lenght / 2));
 | ||
| 	} elseif (function_exists("openssl_random_pseudo_bytes")) {
 | ||
| 		$bytes = openssl_random_pseudo_bytes(ceil($lenght / 2));
 | ||
| 	} else {
 | ||
| 		throw new Exception("no cryptographically secure random function available");
 | ||
| 	}
 | ||
| 	return substr(bin2hex($bytes), 0, $lenght);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * Compare function for sorting users by login
 | ||
|  *
 | ||
|  * Use this for usort()
 | ||
|  *
 | ||
|  * <code>
 | ||
|  * $users = $dms->getAllUsers();
 | ||
|  * usort($users, 'cmp_user_login');
 | ||
|  * </code>
 | ||
|  */
 | ||
| function cmp_user_login($a, $b) { /* {{{ */
 | ||
| 	$as = strtolower($a->getLogin());
 | ||
| 	$bs = strtolower($b->getLogin());
 | ||
| 	if ($as == $bs) {
 | ||
| 		return 0;
 | ||
| 	}
 | ||
| 	return ($as < $bs) ? -1 : 1;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Compare function for sorting users by name
 | ||
|  *
 | ||
|  * Use this for usort()
 | ||
|  *
 | ||
|  * <code>
 | ||
|  * $users = $dms->getAllUsers();
 | ||
|  * usort($users, 'cmp_user_fullname');
 | ||
|  * </code>
 | ||
|  */
 | ||
| function cmp_user_fullname($a, $b) { /* {{{ */
 | ||
| 	$as = strtolower($a->getFullName());
 | ||
| 	$bs = strtolower($b->getFullName());
 | ||
| 	if ($as == $bs) {
 | ||
| 		return 0;
 | ||
| 	}
 | ||
| 	return ($as < $bs) ? -1 : 1;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Returns the mandatory reviewers
 | ||
|  *
 | ||
|  * This function checks if the reviewers have at least read access
 | ||
|  * on the folder containing the document. It also checks if the
 | ||
|  * mandatory reviewer is an admin or the uploading user and if
 | ||
|  * those are allowed to review/approve a document.
 | ||
|  * Mandatory groups will only be added if they are not empty
 | ||
|  *
 | ||
|  * @param $folder folder where document is located
 | ||
|  * @param $document document which is updated, null when adding a new document
 | ||
|  * @param $user user creating the new version or document
 | ||
|  * @return array containing the elements 'i' and 'g'. Each is a list of user/group ids
 | ||
|  */
 | ||
| function getMandatoryReviewers($folder, $document, $user) { /* {{{ */
 | ||
| 	global $settings;
 | ||
| 
 | ||
| 	/* Get mandatory reviewers of user */
 | ||
| 	$res = $user->getMandatoryReviewers();
 | ||
| 	$revi = $revg = [];
 | ||
| 	foreach ($res as $r){
 | ||
| 		if ($r['reviewerUserID']!=0){
 | ||
| 			$revi[] = $r['reviewerUserID'];
 | ||
| 		} elseif ($r['reviewerGroupID']!=0){
 | ||
| 			$revg[] = $r['reviewerGroupID'];
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	/* Add managers of groups as mandatory reviewers */
 | ||
| 	if(!empty($settings->_addManagerAsReviewer)) {
 | ||
| 		$groups = $user->getGroups();
 | ||
| 		foreach($groups as $group) {
 | ||
| 			$managers = $group->getManagers();
 | ||
| 			foreach($managers as $manager) {
 | ||
| 				/* Do not add myself, if I'm the manager of the group */
 | ||
| 				if($manager->getId() != $user->getId())
 | ||
| 					$revi[] = $manager->getId();
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	/* Add global reviewers as mandatory reviewers */
 | ||
| 	if(!empty($settings->_globalReviewer)) {
 | ||
| 		$revi = array_merge($revi, $settings->_globalReviewer);
 | ||
| 	}
 | ||
| 
 | ||
| 	/* Add global group reviewers as mandatory reviewers */
 | ||
| 	if(!empty($settings->_globalGroupReviewer)) {
 | ||
| 		$revg = array_merge($revg, $settings->_globalGroupReviewer);
 | ||
| 	}
 | ||
| 
 | ||
| 	/* Check if reviewers are allowed to review */
 | ||
| 	$revi = array_unique($revi);
 | ||
| 	$revg = array_unique($revg);
 | ||
| 	$reviewers["i"] = []; // users
 | ||
| 	$reviewers["g"] = []; // groups
 | ||
| 	$reviewers["ni"] = []; // users being filtered out
 | ||
| 	$reviewers["ng"] = []; // groups being filtered out
 | ||
| 	$dms = $user->getDMS();
 | ||
| 	foreach($revi as $uid) {
 | ||
| 		if($u = $dms->getUser($uid)) {
 | ||
| 			/* need at least read access on parent folder */
 | ||
| 			if($document)
 | ||
| 				$accessmode = $document->getAccessMode($u);
 | ||
| 			else
 | ||
| 				$accessmode = $folder->getAccessMode($u);
 | ||
| 			if($accessmode < M_READ)
 | ||
| 				$reviewers["ni"][] = $u->getId();
 | ||
| 			/* admins as reviewers must be enabled */
 | ||
| 			elseif(!$settings->_enableAdminRevApp && $u->isAdmin())
 | ||
| 				$reviewers["ni"][] = $u->getId();
 | ||
| 			/* the owner of the document as a reviewer must be enabled */
 | ||
| 			elseif(!$settings->_enableOwnerRevApp && $document && $document->getOwner()->getId() == $u->getId())
 | ||
| 				$reviewers["ni"][] = $u->getId();
 | ||
| 			/* the updloader as a reviewer must be enabled */
 | ||
| 			elseif(!$settings->_enableSelfRevApp && $u->getId() == $user->getId())
 | ||
| 				$reviewers["ni"][] = $u->getId();
 | ||
| 			else
 | ||
| 				$reviewers["i"][] = $u->getId();
 | ||
| 		}
 | ||
| 	}
 | ||
| 	foreach($revg as $gid) {
 | ||
| 		if($g = $dms->getGroup($gid)) {
 | ||
| 			if($document)
 | ||
| 				$accessmode = $document->getGroupAccessMode($u);
 | ||
| 			else
 | ||
| 				$accessmode = $folder->getGroupAccessMode($u);
 | ||
| 			if($accessmode < M_READ || !$g->getUsers())
 | ||
| 				$reviewers["ng"][] = $g->getId();
 | ||
| 			else
 | ||
| 				$reviewers["g"][] = $g->getId();
 | ||
| 		}
 | ||
| 	}
 | ||
| 		
 | ||
| 	return $reviewers;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Returns the mandatory approvers
 | ||
|  *
 | ||
|  * This function checks if the approvers have at least read access
 | ||
|  * on the folder containing the document. It also checks if the
 | ||
|  * mandatory approver is an admin or the uploading user and if
 | ||
|  * those are allowed to review/approve a document.
 | ||
|  * Mandatory groups will only be added if they are not empty
 | ||
|  *
 | ||
|  * @param $folder folder where document is located
 | ||
|  * @param $document document which is updated, null when adding a new document
 | ||
|  * @param $user user creating the new version or document
 | ||
|  * @return array containing the elements 'i' and 'g'. Each is a list of user/group ids
 | ||
|  */
 | ||
| function getMandatoryApprovers($folder, $document, $user) { /* {{{ */
 | ||
| 	global $settings;
 | ||
| 
 | ||
| 	/* Get mandatory approvers of user */
 | ||
| 	$res = $user->getMandatoryApprovers();
 | ||
| 	$appi = $appg = [];
 | ||
| 	foreach ($res as $r){
 | ||
| 		if ($r['approverUserID']!=0){
 | ||
| 			$appi[] = $r['approverUserID'];
 | ||
| 		} elseif ($r['approverGroupID']!=0){
 | ||
| 			$appg[] = $r['approverGroupID'];
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	/* Add managers of groups as mandatory approvers */
 | ||
| 	if(!empty($settings->_addManagerAsApprover)) {
 | ||
| 		$groups = $user->getGroups();
 | ||
| 		foreach($groups as $group) {
 | ||
| 			$managers = $group->getManagers();
 | ||
| 			foreach($managers as $manager) {
 | ||
| 				/* Do not add myself, if I'm the manager of the group */
 | ||
| 				if($manager->getId() != $user->getId())
 | ||
| 					$appi[] = $manager->getId();
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	/* Add global approvers as mandatory approvers */
 | ||
| 	if(!empty($settings->_globalApprover)) {
 | ||
| 		$appi = array_merge($appi, $settings->_globalApprover);
 | ||
| 	}
 | ||
| 
 | ||
| 	/* Add global group approvers as mandatory approvers */
 | ||
| 	if(!empty($settings->_globalGroupApprover)) {
 | ||
| 		$appg = array_merge($appg, $settings->_globalGroupApprover);
 | ||
| 	}
 | ||
| 
 | ||
| 	/* Check if approvers are allowed to approve */
 | ||
| 	$appi = array_unique($appi);
 | ||
| 	$appg = array_unique($appg);
 | ||
| 	$approvers["i"] = []; // users
 | ||
| 	$approvers["g"] = []; // groups
 | ||
| 	$approvers["ni"] = []; // users being filtered out
 | ||
| 	$approvers["ng"] = []; // groups being filtered out
 | ||
| 	$dms = $user->getDMS();
 | ||
| 	foreach($appi as $uid) {
 | ||
| 		if($u = $dms->getUser($uid)) {
 | ||
| 			/* need at least read access on parent folder */
 | ||
| 			if($document)
 | ||
| 				$accessmode = $document->getAccessMode($u);
 | ||
| 			else
 | ||
| 				$accessmode = $folder->getAccessMode($u);
 | ||
| 			if($accessmode < M_READ)
 | ||
| 				$approvers["ni"][] = $u->getId();
 | ||
| 			/* admins as approvers must be enabled */
 | ||
| 			elseif(!$settings->_enableAdminRevApp && $u->isAdmin())
 | ||
| 				$approvers["ni"][] = $u->getId();
 | ||
| 			/* the owner of the document as a approver must be enabled */
 | ||
| 			elseif(!$settings->_enableOwnerRevApp && $document && $document->getOwner()->getId() == $u->getId())
 | ||
| 				$approvers["ni"][] = $u->getId();
 | ||
| 			/* the updloader as a approver must be enabled */
 | ||
| 			elseif(!$settings->_enableSelfRevApp && $u->getId() == $user->getId())
 | ||
| 				$approvers["ni"][] = $u->getId();
 | ||
| 			else
 | ||
| 				$approvers["i"][] = $u->getId();
 | ||
| 		}
 | ||
| 	}
 | ||
| 	foreach($appg as $gid) {
 | ||
| 		if($g = $dms->getGroup($gid)) {
 | ||
| 			if($document)
 | ||
| 				$accessmode = $document->getGroupAccessMode($u);
 | ||
| 			else
 | ||
| 				$accessmode = $folder->getGroupAccessMode($u);
 | ||
| 			if($accessmode < M_READ || !$g->getUsers())
 | ||
| 				$approvers["ng"][] = $g->getId();
 | ||
| 			else
 | ||
| 				$approvers["g"][] = $g->getId();
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	return $approvers;
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Class with various utility methods
 | ||
|  *
 | ||
|  * This class will sooner or later comprise the functions above
 | ||
|  *
 | ||
|  */
 | ||
| class SeedDMS_Utils { /* {{{ */
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Recursively remove a directory on disc
 | ||
| 	 *
 | ||
| 	 * @param string $dir name of directory
 | ||
| 	 */
 | ||
| 	static public function rrmdir($dir) { /* {{{ */
 | ||
| 		if (is_dir($dir)) {
 | ||
| 			$objects = scandir($dir);
 | ||
| 			foreach ($objects as $object) {
 | ||
| 				if ($object != "." && $object != "..") {
 | ||
| 					if (filetype($dir."/".$object) == "dir") self::rrmdir($dir."/".$object); else unlink($dir."/".$object);
 | ||
| 				}
 | ||
| 			}
 | ||
| 			reset($objects);
 | ||
| 			rmdir($dir);
 | ||
| 		}
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Class for creating encrypted api keys
 | ||
|  *
 | ||
|  * <code>
 | ||
|  * <?php
 | ||
|  * $CSRF = new SeedDMS_CSRF($settings->_encryptionKey);
 | ||
|  * $kkk = $CSRF->create_api_key();
 | ||
|  * echo $kkk;
 | ||
|  * echo $CSRF->check_api_key($kkk) ? 'valid' : 'invalid';
 | ||
|  * ?>
 | ||
|  * </code>
 | ||
|  */
 | ||
| class SeedDMS_CSRF { /* {{{ */
 | ||
| 
 | ||
| 	protected $secret;
 | ||
| 
 | ||
| 	public function __construct($secret) { /* {{{ */
 | ||
| 		$this->secret = $secret;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function create_api_key() { /* {{{ */
 | ||
| 		return base64_encode($this->encrypt(time().'|'.$_SERVER['REMOTE_ADDR'])); // !change if you dont want IP check
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function check_api_key($key, $timeout = 5) { /* {{{ */
 | ||
| 		if (empty($key)) exit('Invalid Key');
 | ||
| 
 | ||
| 		$keys = explode('|', $this->decrypt(base64_decode($key)));
 | ||
| 
 | ||
| 		return (
 | ||
| 			isset($key, $keys[0], $keys[1]) && 
 | ||
| 			$keys[0] >= (time() - $timeout) && 
 | ||
| 			$keys[1] == $_SERVER['REMOTE_ADDR'] // !change if you dont want IP check
 | ||
| 		);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function encrypt($string, $key = 'PrivateKey', $method = 'AES-256-CBC') { /* {{{ */
 | ||
| 		// hash
 | ||
| 		$key = hash('sha256', $key);
 | ||
| 		// create iv - encrypt method AES-256-CBC expects 16 bytes
 | ||
| 		$iv = substr(hash('sha256', $this->secret), 0, 16);
 | ||
| 		// encrypt
 | ||
| 		$output = openssl_encrypt($string, $method, $key, 0, $iv);
 | ||
| 		// encode
 | ||
| 		return base64_encode($output);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function decrypt($string, $key = 'PrivateKey', $method = 'AES-256-CBC') { /* {{{ */
 | ||
| 		// hash
 | ||
| 		$key = hash('sha256', $key);
 | ||
| 		// create iv - encrypt method AES-256-CBC expects 16 bytes
 | ||
| 		$iv = substr(hash('sha256', $this->secret), 0, 16);
 | ||
| 		// decode
 | ||
| 		$string = base64_decode($string);
 | ||
| 		// decrypt
 | ||
| 		return openssl_decrypt($string, $method, $key, 0, $iv);
 | ||
| 	} /* }}} */
 | ||
| } /* }}} */
 | ||
| 
 | ||
| /**
 | ||
|  * Class to represent a jwt token
 | ||
|  *
 | ||
|  *
 | ||
|  * @category   DMS
 | ||
|  * @package    SeedDMS
 | ||
|  * @author     Uwe Steinmann <uwe@steinmann.cx>
 | ||
|  * @copyright  2016 Uwe Steinmann
 | ||
|  * @version    Release: @package_version@
 | ||
|  */
 | ||
| class SeedDMS_JwtToken { /* {{{ */
 | ||
| 	protected $jwtsecret;
 | ||
| 
 | ||
| 	public function __construct($jwtsecret = '') { /* {{{ */
 | ||
| 		$this->jwtsecret = $jwtsecret;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function jwtEncode($payload) { /* {{{ */
 | ||
| 		$header = [
 | ||
| 				"alg" => "HS256",
 | ||
| 				"typ" => "JWT"
 | ||
| 		];
 | ||
| 		$encHeader = self::base64UrlEncode(json_encode($header));
 | ||
| 		$encPayload = self::base64UrlEncode(json_encode($payload));
 | ||
| 		$hash = self::base64UrlEncode(self::calculateHash($encHeader, $encPayload));
 | ||
| 
 | ||
| 		return "$encHeader.$encPayload.$hash";
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function jwtDecode($token) { /* {{{ */
 | ||
| 		if (!$this->jwtsecret) return "";
 | ||
| 
 | ||
| 		$split = explode(".", $token);
 | ||
| 		if (count($split) != 3) return "";
 | ||
| 
 | ||
| 		$hash = self::base64UrlEncode(self::calculateHash($split[0], $split[1]));
 | ||
| 
 | ||
| 		if (strcmp($hash, $split[2]) != 0) return "";
 | ||
| 		return self::base64UrlDecode($split[1]);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	protected function calculateHash($encHeader, $encPayload) { /* {{{ */
 | ||
| 		return hash_hmac("sha256", "$encHeader.$encPayload", $this->jwtsecret, true);
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	protected function base64UrlEncode($str) { /* {{{ */
 | ||
| 		return str_replace("/", "_", str_replace("+", "-", trim(base64_encode($str), "=")));
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	protected function base64UrlDecode($payload) { /* {{{ */
 | ||
| 		$b64 = str_replace("_", "/", str_replace("-", "+", $payload));
 | ||
| 		switch (strlen($b64) % 4) {
 | ||
| 			case 2:
 | ||
| 				$b64 = $b64 . "=="; break;
 | ||
| 			case 3:
 | ||
| 				$b64 = $b64 . "="; break;
 | ||
| 		}
 | ||
| 		return base64_decode($b64);
 | ||
| 	} /* }}} */
 | ||
| } /* }}} */
 | ||
| 
 | ||
| class SeedDMS_FolderTree { /* {{{ */
 | ||
| 
 | ||
| 	public function __construct($folder, $callback) { /* {{{ */
 | ||
| 		$iter = new \SeedDMS\Core\RecursiveFolderIterator($folder);
 | ||
| 		$iter2 = new RecursiveIteratorIterator($iter, RecursiveIteratorIterator::SELF_FIRST);
 | ||
| 		foreach($iter2 as $ff) {
 | ||
| 			call_user_func($callback, $ff, $iter2->getDepth()+1);
 | ||
| //      echo $ff->getID().': '.$ff->getFolderPathPlain().'-'.$ff->getName()."<br />";
 | ||
| 		}
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| } /* }}} */
 | ||
| 
 | ||
| class SeedDMS_Search { /* {{{ */
 | ||
| 	protected $dms;
 | ||
| 
 | ||
| 	protected $user;
 | ||
| 
 | ||
| 	protected $fulltextservice;
 | ||
| 
 | ||
| 	protected $settings;
 | ||
| 
 | ||
| 	public $searchparams;
 | ||
| 
 | ||
| 	protected $dcount;
 | ||
| 
 | ||
| 	protected $fcount;
 | ||
| 
 | ||
| 	protected $totalPages;
 | ||
| 
 | ||
| 	protected $entries;
 | ||
| 
 | ||
| 	protected $terms;
 | ||
| 
 | ||
| 	protected $searchTime;
 | ||
| 
 | ||
| 	public function __construct($dms, $user, $fulltextservice, $settings) {
 | ||
| 		$this->dms = $dms;
 | ||
| 		$this->user = $user;
 | ||
| 		$this->fulltextservice = $fulltextservice;
 | ||
| 		$this->settings = $settings;
 | ||
| 		$this->searchparams = [];
 | ||
| 		$this->dcount = 0;
 | ||
| 		$this->fcount = 0;
 | ||
| 		$this->totalPages = 0;
 | ||
| 		$this->entries = array();
 | ||
| 		$this->terms = array();
 | ||
| 		$this->searchTime = 0;
 | ||
| 	}
 | ||
| 
 | ||
| 	protected function getTime() { /* {{{ */
 | ||
| 		if (function_exists('microtime')) {
 | ||
| 			$tm = microtime();
 | ||
| 			$tm = explode(' ', $tm);
 | ||
| 			return (float) sprintf('%f', $tm[1] + $tm[0]);
 | ||
| 		}
 | ||
| 		return time();
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function createSearchFromQuery($get) { /* {{{ */
 | ||
| 
 | ||
| 		/* Creation date {{{ */
 | ||
| 		$createstartts = null;
 | ||
| 		$createstartdate = null;
 | ||
| 		$createendts = null;
 | ||
| 		$createenddate = null;
 | ||
| 		$created['from'] = null;
 | ||
| 		$created['to'] = null;
 | ||
| 		if(!empty($get["created"]["from"])) {
 | ||
| 			$createstartts = makeTsFromDate($get["created"]["from"]);
 | ||
| 			$createstartdate = array('year'=>(int)date('Y', $createstartts), 'month'=>(int)date('m', $createstartts), 'day'=>(int)date('d', $createstartts), 'hour'=>0, 'minute'=>0, 'second'=>0);
 | ||
| 			if (!checkdate($createstartdate['month'], $createstartdate['day'], $createstartdate['year'])) {
 | ||
| 				UI::exitError(getMLText("search"),getMLText("invalid_create_date_end"));
 | ||
| 			}
 | ||
| 			$created['from'] = $createstartts;
 | ||
| 		}
 | ||
| 		if(!empty($get["created"]["to"])) {
 | ||
| 			$createendts = makeTsFromDate($get["created"]["to"]);
 | ||
| 			$createenddate = array('year'=>(int)date('Y', $createendts), 'month'=>(int)date('m', $createendts), 'day'=>(int)date('d', $createendts), 'hour'=>23, 'minute'=>59, 'second'=>59);
 | ||
| 			if (!checkdate($createenddate['month'], $createenddate['day'], $createenddate['year'])) {
 | ||
| 				UI::exitError(getMLText("search"),getMLText("invalid_create_date_end"));
 | ||
| 			}
 | ||
| 			$created['to'] = $createendts;
 | ||
| 		}
 | ||
| 		$this->searchparams['created'] = $created;
 | ||
| 		/* }}} */
 | ||
| 
 | ||
| 		/* Modification date {{{ */
 | ||
| 		$modifystartts = null;
 | ||
| 		$modifystartdate = null;
 | ||
| 		$modifyendts = null;
 | ||
| 		$modifyenddate = null;
 | ||
| 		$modified['from'] = null;
 | ||
| 		$modified['to'] = null;
 | ||
| 		if(!empty($get["modified"]["from"])) {
 | ||
| 			$modifystartts = makeTsFromDate($get["modified"]["from"]);
 | ||
| 			$modifystartdate = array('year'=>(int)date('Y', $modifystartts), 'month'=>(int)date('m', $modifystartts), 'day'=>(int)date('d', $modifystartts), 'hour'=>0, 'minute'=>0, 'second'=>0);
 | ||
| 			if (!checkdate($modifystartdate['month'], $modifystartdate['day'], $modifystartdate['year'])) {
 | ||
| 				UI::exitError(getMLText("search"),getMLText("invalid_modification_date_end"));
 | ||
| 			}
 | ||
| 			$modified['from'] = $modifystartts;
 | ||
| 		}
 | ||
| 		if(!empty($get["modified"]["to"])) {
 | ||
| 			$modifyendts = makeTsFromDate($get["modified"]["to"]);
 | ||
| 			$modifyenddate = array('year'=>(int)date('Y', $modifyendts), 'month'=>(int)date('m', $modifyendts), 'day'=>(int)date('d', $modifyendts), 'hour'=>23, 'minute'=>59, 'second'=>59);
 | ||
| 			if (!checkdate($modifyenddate['month'], $modifyenddate['day'], $modifyenddate['year'])) {
 | ||
| 				UI::exitError(getMLText("search"),getMLText("invalid_modification_date_end"));
 | ||
| 			}
 | ||
| 			$modified['to'] = $modifyendts;
 | ||
| 		}
 | ||
| 		$this->searchparams['modified'] = $modified;
 | ||
| 		/* }}} */
 | ||
| 
 | ||
| 		/* Filesize {{{ */
 | ||
| 		$filesizestart = 0;
 | ||
| 		$filesizeend = 0;
 | ||
| 		$filesize['from'] = null;
 | ||
| 		$filesize['to'] = null;
 | ||
| 		if(!empty($get["filesize"]["from"])) {
 | ||
| 			$filesizestart = $get["filesize"]["from"];
 | ||
| 			$filesize['from'] = $get["filesize"]["from"];
 | ||
| 		}
 | ||
| 		if(!empty($get["filesize"]["to"])) {
 | ||
| 			$filesizeend = $get["filesize"]["to"];
 | ||
| 			$filesize['to'] = $get["filesize"]["to"];
 | ||
| 		}
 | ||
| 		$this->searchparams['filesize'] = $filesize;
 | ||
| 		/* }}} */
 | ||
| 
 | ||
| 		// Check to see if the search has been restricted to a particular
 | ||
| 		// document owner.
 | ||
| 		// $get['owner'] can be a name of an array of names or ids {{{
 | ||
| 		$owner = [];
 | ||
| 		$ownernames = []; // Needed by fulltext search
 | ||
| 		$ownerobjs = []; // Needed by database search
 | ||
| 		if(!empty($get["owner"])) {
 | ||
| 			$owner = $get['owner'];
 | ||
| 			if (!is_array($get['owner'])) {
 | ||
| 				if(is_numeric($get['owner']))
 | ||
| 					$o = $dms->getUser($get['owner']);
 | ||
| 				else
 | ||
| 					$o = $dms->getUserByLogin($get['owner']);
 | ||
| 				if($o) {
 | ||
| 					$ownernames[] = $o->getLogin();
 | ||
| 					$ownerobjs[] = $o;
 | ||
| 				}
 | ||
| 			} else {
 | ||
| 				foreach($get["owner"] as $l) {
 | ||
| 					if($l) {
 | ||
| 						if(is_numeric($l))
 | ||
| 							$o = $dms->getUser($l);
 | ||
| 						else
 | ||
| 							$o = $dms->getUserByLogin($l);
 | ||
| 						if($o) {
 | ||
| 							$ownernames[] = $o->getLogin();
 | ||
| 							$ownerobjs[] = $o;
 | ||
| 						}
 | ||
| 					}
 | ||
| 				}
 | ||
| 			}
 | ||
| 		}
 | ||
| 		$this->searchparams['ownernames'] = $ownernames;
 | ||
| 		$this->searchparams['ownerobjs'] = $ownerobjs;
 | ||
| 		/* }}} */
 | ||
| 
 | ||
| 		// category {{{
 | ||
| 		$categories = array();
 | ||
| 		$categorynames = array();
 | ||
| 		$category = array();
 | ||
| 		if(isset($get['category']) && $get['category']) {
 | ||
| 			$category = $get['category'];
 | ||
| 			foreach($get['category'] as $catid) {
 | ||
| 				if($catid) {
 | ||
| 					if(is_numeric($catid)) {
 | ||
| 						if($cat = $dms->getDocumentCategory($catid)) {
 | ||
| 							$categories[] = $cat;
 | ||
| 							$categorynames[] = $cat->getName();
 | ||
| 						}
 | ||
| 					} else {
 | ||
| 						$categorynames[] = $catid;
 | ||
| 					}
 | ||
| 				}
 | ||
| 			}
 | ||
| 		}
 | ||
| 		$this->searchparams['categorynames'] = $categorynames;
 | ||
| 		$this->searchparams['categories'] = $categories;
 | ||
| 		/* }}} */
 | ||
| 
 | ||
| 		if (isset($get["orderby"]) && is_string($get["orderby"])) {
 | ||
| 			$orderby = $get["orderby"];
 | ||
| 		} else {
 | ||
| 			$orderby = "";
 | ||
| 		}
 | ||
| 		$this->searchparams['orderby'] = $orderby;
 | ||
| 
 | ||
| 		$limit = (isset($get["limit"]) && is_numeric($get["limit"])) ? (int) $get['limit'] : 20;
 | ||
| 		$this->searchparams['limit'] = $limit;
 | ||
| 		$fullsearch = ((!isset($get["fullsearch"]) && $this->settings->_defaultSearchMethod == 'fulltext') || !empty($get["fullsearch"])) && $this->settings->_enableFullSearch;
 | ||
| 		$this->searchparams['fullsearch'] = $fullsearch;
 | ||
| 		$facetsearch = !empty($get["facetsearch"]) && $this->settings->_enableFullSearch;
 | ||
| 		$this->searchparams['facetsearch'] = $facetsearch;
 | ||
| 
 | ||
| 		if (isset($get["query"]) && is_string($get["query"])) {
 | ||
| 			$query = $get["query"];
 | ||
| 		} else {
 | ||
| 			$query = "";
 | ||
| 		}
 | ||
| 		$this->searchparams['query'] = $query;
 | ||
| 
 | ||
| 		// Check to see if the search has been restricted to a particular
 | ||
| 		// mimetype. {{{
 | ||
| 		$mimetype = [];
 | ||
| 		if (isset($get["mimetype"])) {
 | ||
| 			if (!is_array($get['mimetype'])) {
 | ||
| 				if(!empty($get['mimetype']))
 | ||
| 					$mimetype[] = $get['mimetype'];
 | ||
| 			} else {
 | ||
| 				foreach($get["mimetype"] as $l) {
 | ||
| 					if($l)
 | ||
| 						$mimetype[] = $l;
 | ||
| 				}
 | ||
| 			}
 | ||
| 		}
 | ||
| 		$this->searchparams['mimetype'] = $mimetype;
 | ||
| 		/* }}} */
 | ||
| 
 | ||
| 		// status
 | ||
| 		$status = isset($get['status']) ? $get['status'] : array();
 | ||
| 		$this->searchparams['status'] = $status;
 | ||
| 
 | ||
| 		// Get the page number to display. If the result set contains more than
 | ||
| 		// 25 entries, it is displayed across multiple pages.
 | ||
| 		//
 | ||
| 		// This requires that a page number variable be used to track which page the
 | ||
| 		// user is interested in, and an extra clause on the select statement.
 | ||
| 		//
 | ||
| 		// Default page to display is always one.
 | ||
| 		$pageNumber=1;
 | ||
| 		if (isset($get["pg"])) {
 | ||
| 			if (is_numeric($get["pg"]) && $get["pg"]>0) {
 | ||
| 				$pageNumber = (int) $get["pg"];
 | ||
| 			}
 | ||
| 			elseif (!strcasecmp($get["pg"], "all")) {
 | ||
| 				$pageNumber = "all";
 | ||
| 			}
 | ||
| 		}
 | ||
| 		$this->searchparams['pageNumber'] = $pageNumber;
 | ||
| 
 | ||
| 		if($fullsearch) {
 | ||
| 			// Search in Fulltext {{{
 | ||
| 
 | ||
| 			// record_type
 | ||
| 			if(isset($get['record_type']))
 | ||
| 				$record_type = $get['record_type'];
 | ||
| 			else
 | ||
| 				$record_type = array();
 | ||
| 			$this->searchparams['record_type'] = $record_type;
 | ||
| 
 | ||
| 			if (isset($get["attributes"]))
 | ||
| 				$attributes = $get["attributes"];
 | ||
| 			else
 | ||
| 				$attributes = array();
 | ||
| 
 | ||
| 			foreach($attributes as $an=>&$av) {
 | ||
| 				if(substr($an, 0, 5) == 'attr_') {
 | ||
| 					$tmp = explode('_', $an);
 | ||
| 					if($attrdef = $dms->getAttributeDefinition($tmp[1])) {
 | ||
| 						switch($attrdef->getType()) {
 | ||
| 						/* Turn dates into timestamps */
 | ||
| 						case SeedDMS_Core_AttributeDefinition::type_date:
 | ||
| 							foreach(['from', 'to'] as $kk)
 | ||
| 								if(!empty($av[$kk])) {
 | ||
| 									if(!is_numeric($av[$kk])) {
 | ||
| 										$av[$kk] = makeTsFromDate($av[$kk]);
 | ||
| 									}
 | ||
| 								}
 | ||
| 							break;
 | ||
| 						}
 | ||
| 					}
 | ||
| 				}
 | ||
| 			}
 | ||
| 			$this->searchparams['attributes'] = $attributes;
 | ||
| 
 | ||
| 			/* Create $order array for fulltext search */
 | ||
| 			$order = ['by'=>'', 'dir'=>''];
 | ||
| 			switch($orderby) {
 | ||
| 			case 'dd':
 | ||
| 				$order = ['by'=>'created', 'dir'=>'desc'];
 | ||
| 				break;
 | ||
| 			case 'd':
 | ||
| 				$order = ['by'=>'created', 'dir'=>'asc'];
 | ||
| 				break;
 | ||
| 			case 'nd':
 | ||
| 				$order = ['by'=>'title', 'dir'=>'desc'];
 | ||
| 				break;
 | ||
| 			case 'n':
 | ||
| 				$order = ['by'=>'title', 'dir'=>'asc'];
 | ||
| 				break;
 | ||
| 			case 'id':
 | ||
| 				$order = ['by'=>'id', 'dir'=>'desc'];
 | ||
| 				break;
 | ||
| 			case 'i':
 | ||
| 				$order = ['by'=>'id', 'dir'=>'asc'];
 | ||
| 				break;
 | ||
| 			default:
 | ||
| 				$order = ['by'=>'', 'dir'=>''];
 | ||
| 			}
 | ||
| 			$this->searchparams['order'] = $order;
 | ||
| 
 | ||
| 			// Check to see if the search has been restricted to a particular sub-tree in
 | ||
| 			// the folder hierarchy.
 | ||
| 			$startFolder = null;
 | ||
| 			if (isset($get["folderfullsearchid"]) && is_numeric($get["folderfullsearchid"]) && $get["folderfullsearchid"]>0) {
 | ||
| 				$targetid = $get["folderfullsearchid"];
 | ||
| 				$startFolder = $this->dms->getFolder($targetid);
 | ||
| 				if (!is_object($startFolder)) {
 | ||
| 					UI::exitError(getMLText("search"),getMLText("invalid_folder_id"));
 | ||
| 				}
 | ||
| 			}
 | ||
| 			$this->searchparams['startFolder'] = $startFolder;
 | ||
| 
 | ||
| 			$rootFolder = $this->dms->getFolder($this->settings->_rootFolderID);
 | ||
| 			$this->searchparams['rootFolder'] = $rootFolder;
 | ||
| 
 | ||
| 			// }}}
 | ||
| 		} else {
 | ||
| 			// Search in Database {{{
 | ||
| 
 | ||
| 			/* Select if only documents (0x01), only folders (0x02) or both (0x03)
 | ||
| 			 * are found
 | ||
| 			 */
 | ||
| 			$resultmode = 0x03;
 | ||
| 			if (isset($get["resultmode"]) && is_numeric($get["resultmode"])) {
 | ||
| 					$resultmode = $get['resultmode'];
 | ||
| 			}
 | ||
| 			$this->searchparams['resultmode'] = $resultmode;
 | ||
| 
 | ||
| 			$mode = "AND";
 | ||
| 			if (isset($get["mode"]) && is_numeric($get["mode"]) && $get["mode"]==0) {
 | ||
| 					$mode = "OR";
 | ||
| 			}
 | ||
| 			$this->searchparams['mode'] = $mode;
 | ||
| 
 | ||
| 			$searchin = array();
 | ||
| 			if (isset($get['searchin']) && is_array($get["searchin"])) {
 | ||
| 				foreach ($get["searchin"] as $si) {
 | ||
| 					if (isset($si) && is_numeric($si)) {
 | ||
| 						switch ($si) {
 | ||
| 							case 1: // keywords
 | ||
| 							case 2: // name
 | ||
| 							case 3: // comment
 | ||
| 							case 4: // attributes
 | ||
| 							case 5: // id
 | ||
| 								$searchin[$si] = $si;
 | ||
| 								break;
 | ||
| 						}
 | ||
| 					}
 | ||
| 				}
 | ||
| 			}
 | ||
| 
 | ||
| 			// if none is checkd search all
 | ||
| 			if (count($searchin)==0) $searchin=array(1, 2, 3, 4, 5);
 | ||
| 			$this->searchparams['searchin'] = $searchin;
 | ||
| 
 | ||
| 			// Check to see if the search has been restricted to a particular sub-tree in
 | ||
| 			// the folder hierarchy.
 | ||
| 			if (isset($get["targetid"]) && is_numeric($get["targetid"]) && $get["targetid"]>0) {
 | ||
| 				$targetid = $get["targetid"];
 | ||
| 				$startFolder = $this->dms->getFolder($targetid);
 | ||
| 			}
 | ||
| 			else {
 | ||
| 				$startFolder = $this->dms->getRootFolder();
 | ||
| 			}
 | ||
| 			if (!is_object($startFolder)) {
 | ||
| 				UI::exitError(getMLText("search"),getMLText("invalid_folder_id"));
 | ||
| 			}
 | ||
| 			$this->searchparams['startFolder'] = $startFolder;
 | ||
| 
 | ||
| 			/* Revision date {{{ */
 | ||
| 			$revisionstartts = null;
 | ||
| 			$revisionstartdate = array();
 | ||
| 			$revisionendts = null;
 | ||
| 			$revisionenddate = array();
 | ||
| 			$revised['from'] = null;
 | ||
| 			$revised['to'] = null;
 | ||
| 			if(!empty($get["revisiondatestart"])) {
 | ||
| 				$revisionstartts = makeTsFromDate($get["revisiondatestart"]);
 | ||
| 				$revisionstartdate = array('year'=>(int)date('Y', $revisionstartts), 'month'=>(int)date('m', $revisionstartts), 'day'=>(int)date('d', $revisionstartts), 'hour'=>0, 'minute'=>0, 'second'=>0);
 | ||
| 				if (!checkdate($revisionstartdate['month'], $revisionstartdate['day'], $revisionstartdate['year'])) {
 | ||
| 					UI::exitError(getMLText("search"),getMLText("invalid_revision_date_start"));
 | ||
| 				}
 | ||
| 				$revised['from'] = $revisionstartts;
 | ||
| 			}
 | ||
| 			if(!empty($get["revisiondateend"])) {
 | ||
| 				$revisionendts = makeTsFromDate($get["revisiondateend"]);
 | ||
| 				$revisionenddate = array('year'=>(int)date('Y', $revisionendts), 'month'=>(int)date('m', $revisionendts), 'day'=>(int)date('d', $revisionendts), 'hour'=>23, 'minute'=>59, 'second'=>59);
 | ||
| 				if (!checkdate($revisionenddate['month'], $revisionenddate['day'], $revisionenddate['year'])) {
 | ||
| 					UI::exitError(getMLText("search"),getMLText("invalid_revision_date_end"));
 | ||
| 				}
 | ||
| 				$revised['to'] = $revisionendts;
 | ||
| 			}
 | ||
| 			/* }}} */
 | ||
| 
 | ||
| 			/* Status date {{{ */
 | ||
| 			$statusstartdate = array();
 | ||
| 			$statusenddate = array();
 | ||
| 			if(!empty($get["statusdatestart"])) {
 | ||
| 				$statusstartts = makeTsFromDate($get["statusdatestart"]);
 | ||
| 				$statusstartdate = array('year'=>(int)date('Y', $statusstartts), 'month'=>(int)date('m', $statusstartts), 'day'=>(int)date('d', $statusstartts), 'hour'=>0, 'minute'=>0, 'second'=>0);
 | ||
| 			}
 | ||
| 			$this->searchparams['statusstartdate'] = $statusstartdate;
 | ||
| 			if ($statusstartdate && !checkdate($statusstartdate['month'], $statusstartdate['day'], $statusstartdate['year'])) {
 | ||
| 				UI::exitError(getMLText("search"),getMLText("invalid_status_date_start"));
 | ||
| 			}
 | ||
| 
 | ||
| 			if(!empty($get["statusdateend"])) {
 | ||
| 				$statusendts = makeTsFromDate($get["statusdateend"]);
 | ||
| 				$statusenddate = array('year'=>(int)date('Y', $statusendts), 'month'=>(int)date('m', $statusendts), 'day'=>(int)date('d', $statusendts), 'hour'=>23, 'minute'=>59, 'second'=>59);
 | ||
| 			}
 | ||
| 			if ($statusenddate && !checkdate($statusenddate['month'], $statusenddate['day'], $statusenddate['year'])) {
 | ||
| 				UI::exitError(getMLText("search"),getMLText("invalid_status_date_end"));
 | ||
| 			}
 | ||
| 			$this->searchparams['statusenddate'] = $statusenddate;
 | ||
| 			/* }}} */
 | ||
| 
 | ||
| 			/* Expiration date {{{ */
 | ||
| 			$expstartdate = array();
 | ||
| 			$expenddate = array();
 | ||
| 			if(!empty($get["expirationstart"])) {
 | ||
| 				$expstartts = makeTsFromDate($get["expirationstart"]);
 | ||
| 				$expstartdate = array('year'=>(int)date('Y', $expstartts), 'month'=>(int)date('m', $expstartts), 'day'=>(int)date('d', $expstartts), 'hour'=>0, 'minute'=>0, 'second'=>0);
 | ||
| 				if (!checkdate($expstartdate['month'], $expstartdate['day'], $expstartdate['year'])) {
 | ||
| 					UI::exitError(getMLText("search"),getMLText("invalid_expiration_date_start"));
 | ||
| 				}
 | ||
| 			}
 | ||
| 			if(!empty($get["expirationend"])) {
 | ||
| 				$expendts = makeTsFromDate($get["expirationend"]);
 | ||
| 				$expenddate = array('year'=>(int)date('Y', $expendts), 'month'=>(int)date('m', $expendts), 'day'=>(int)date('d', $expendts), 'hour'=>23, 'minute'=>59, 'second'=>59);
 | ||
| 				if (!checkdate($expenddate['month'], $expenddate['day'], $expenddate['year'])) {
 | ||
| 					UI::exitError(getMLText("search"),getMLText("invalid_expiration_date_end"));
 | ||
| 				}
 | ||
| 			}
 | ||
| 			/* }}} */
 | ||
| 
 | ||
| 			$reception = array();
 | ||
| 			if (isset($get["reception"])){
 | ||
| 				$reception = $get["reception"];
 | ||
| 			}
 | ||
| 
 | ||
| 			/* Do not search for folders if result shall be filtered by status.
 | ||
| 			 * If this is not done, unexplainable results will be delivered.
 | ||
| 			 * e.g. a search for expired documents of a given user will list
 | ||
| 			 * also all folders of that user because the status doesn't apply
 | ||
| 			 * to folders.
 | ||
| 			 */
 | ||
| 		//	if($status)
 | ||
| 		//		$resultmode = 0x01;
 | ||
| 
 | ||
| 			if (isset($get["attributes"]))
 | ||
| 				$attributes = $get["attributes"];
 | ||
| 			else
 | ||
| 				$attributes = array();
 | ||
| 
 | ||
| 			foreach($attributes as $attrdefid=>$attribute) {
 | ||
| 				$attrdef = $this->dms->getAttributeDefinition($attrdefid);
 | ||
| 				if($attribute) {
 | ||
| 					if($attrdef->getType() == SeedDMS_Core_AttributeDefinition::type_date) {
 | ||
| 						if(is_array($attribute)) {
 | ||
| 							if(!empty($attributes[$attrdefid]['from']))
 | ||
| 								$attributes[$attrdefid]['from'] = date('Y-m-d', makeTsFromDate($attribute['from']));
 | ||
| 							if(!empty($attributes[$attrdefid]['to']))
 | ||
| 								$attributes[$attrdefid]['to'] = date('Y-m-d', makeTsFromDate($attribute['to']));
 | ||
| 						} else {
 | ||
| 							$attributes[$attrdefid] = date('Y-m-d', makeTsFromDate($attribute));
 | ||
| 						}
 | ||
| 					}
 | ||
| 				}
 | ||
| 			}
 | ||
| 			$this->searchparams['attributes'] = $attributes;
 | ||
| 
 | ||
| 		// }}}
 | ||
| 		}
 | ||
| 		return $this->searchparams;
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function setSearchParam($name, $value) {
 | ||
| 		$this->searchparams[$name] = $value;
 | ||
| 	}
 | ||
| 
 | ||
| 	public function search() { /* {{{ */
 | ||
| 		if($this->searchparams['fullsearch']) {
 | ||
| 			if($this->settings->_fullSearchEngine == 'lucene') {
 | ||
| 				Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('utf-8');
 | ||
| 			}
 | ||
| 
 | ||
| 			$startTime = $this->getTime();
 | ||
| 			$total = 0;
 | ||
| 			$index = $this->fulltextservice->Indexer();
 | ||
| 			if($index) {
 | ||
| 				if(!empty($this->settings->_suggestTerms) && !empty($get['query'])) {
 | ||
| 					$st = preg_split("/[\s,]+/", trim($get['query']));
 | ||
| 					if($lastterm = end($st))
 | ||
| 						$this->terms = $index->terms($lastterm, $this->settings->_suggestTerms);
 | ||
| 				}
 | ||
| 				$limit = $this->searchparams['limit'];
 | ||
| 				$lucenesearch = $this->fulltextservice->Search();
 | ||
| 				$searchresult = $lucenesearch->search($this->searchparams['query'],
 | ||
| 					array(
 | ||
| 						'record_type'=>$this->searchparams['record_type'],
 | ||
| 						'owner'=>$this->searchparams['ownernames'],
 | ||
| 						'status'=>$this->searchparams['status'],
 | ||
| 						'category'=>$this->searchparams['categorynames'],
 | ||
| 						'user'=>$this->user->isAdmin() ? [] : [$this->user->getLogin()],
 | ||
| 						'mimetype'=>$this->searchparams['mimetype'],
 | ||
| 						'startFolder'=>$this->searchparams['startFolder'],
 | ||
| 						'rootFolder'=>$this->searchparams['rootFolder'],
 | ||
| 						'created_start'=>$this->searchparams['created']['from'],
 | ||
| 						'created_end'=>$this->searchparams['created']['to'],
 | ||
| 						'modified_start'=>$this->searchparams['modified']['from'],
 | ||
| 						'modified_end'=>$this->searchparams['modified']['to'],
 | ||
| 						'filesize_start'=>$this->searchparams['filesize']['from'],
 | ||
| 						'filesize_end'=>$this->searchparams['filesize']['to'],
 | ||
| 						'attributes'=>$this->searchparams['attributes']
 | ||
| 					), ($this->searchparams['pageNumber'] == 'all' ? array() : array('limit'=>$limit, 'offset'=>$limit * ($this->searchparams['pageNumber']-1))), $this->searchparams['order']);
 | ||
| 				if($searchresult !== false) {
 | ||
| 					$entries = array();
 | ||
| 					$facets = $searchresult['facets'];
 | ||
| 					$stats = $searchresult['stats'] ?? null;
 | ||
| 					$dcount = 0;
 | ||
| 					$fcount = 0;
 | ||
| 					if($searchresult['hits']) {
 | ||
| 						foreach($searchresult['hits'] as $hit) {
 | ||
| 							if($hit['document_id'][0] == 'D') {
 | ||
| 								if($tmp = $this->dms->getDocument(substr($hit['document_id'], 1))) {
 | ||
| 	//								if($tmp->getAccessMode($user) >= M_READ) {
 | ||
| 										$tmp->verifyLastestContentExpriry();
 | ||
| 										$entries[] = $tmp;
 | ||
| 										$dcount++;
 | ||
| 	//								}
 | ||
| 								}
 | ||
| 							} elseif($hit['document_id'][0] == 'F') {
 | ||
| 								if($tmp = $this->dms->getFolder(substr($hit['document_id'], 1))) {
 | ||
| 	//								if($tmp->getAccessMode($user) >= M_READ) {
 | ||
| 										$entries[] = $tmp;
 | ||
| 										$fcount++;
 | ||
| 	//								}
 | ||
| 								}
 | ||
| 							}
 | ||
| 						}
 | ||
| 						if(isset($facets['record_type'])) {
 | ||
| 							$fcount = isset($facets['record_type']['folder']) ? $facets['record_type']['folder'] : 0;
 | ||
| 							$dcount = isset($facets['record_type']['document']) ? $facets['record_type']['document'] : 0 ;
 | ||
| 						}
 | ||
| 					}
 | ||
| 					$this->fcount = $fcount;
 | ||
| 					$this->dcount = $dcount;
 | ||
| 					$this->stats = $stats;
 | ||
| 					$this->entries = $entries;
 | ||
| 					$this->facets = $facets;
 | ||
| 					$totalPages = 0;
 | ||
| 					if($limit > 0) {
 | ||
| 						if($searchresult['count'] > $limit) {
 | ||
| 							$totalPages = (int) ($searchresult['count']/$limit);
 | ||
| 							if($searchresult['count']%$limit)
 | ||
| 								$totalPages++;
 | ||
| 						} else {
 | ||
| 							$totalPages = 1;
 | ||
| 						}
 | ||
| 					}
 | ||
| 					$this->total = $searchresult['count'];
 | ||
| 					$this->totalPages = $totalPages;
 | ||
| 				}
 | ||
| 				$searchTime = $this->getTime() - $startTime;
 | ||
| 				$this->searchTime = round($searchTime, 2);
 | ||
| 			}
 | ||
| 		} else {
 | ||
| 			// ---------------- Start searching -----------------------------------------
 | ||
| 			$startTime = $this->getTime();
 | ||
| 			$resArr = $this->dms->search(array(
 | ||
| 				'query'=>$query,
 | ||
| 				'limit'=>0,
 | ||
| 				'offset'=>0,
 | ||
| 				'logicalmode'=>$mode,
 | ||
| 				'searchin'=>$searchin,
 | ||
| 				'startFolder'=>$startFolder,
 | ||
| 				'owner'=>$ownerobjs,
 | ||
| 				'status'=>$status,
 | ||
| 				'mimetype'=>$mimetype,
 | ||
| 				'creationstartdate'=>$created['from'],
 | ||
| 				'creationenddate'=>$created['to'],
 | ||
| 				'modificationstartdate'=>$modified['from'],
 | ||
| 				'modificationenddate'=>$modified['to'],
 | ||
| 				'filesizestart'=>$filesize['from'],
 | ||
| 				'filesizeend'=>$filesize['to'],
 | ||
| 				'categories'=>$categories,
 | ||
| 				'attributes'=>$attributes,
 | ||
| 				'mode'=>$resultmode,
 | ||
| 				'expirationstartdate'=>$expstartdate ? $expstartdate : array(),
 | ||
| 				'expirationenddate'=>$expenddate ? $expenddate : array(),
 | ||
| 				'revisionstartdate'=>$revisionstartdate ? $revisionstartdate : array(),
 | ||
| 				'revisionenddate'=>$revisionenddate ? $revisionenddate : array(),
 | ||
| 				'reception'=>$reception,
 | ||
| 				'statusstartdate'=>$statusstartdate ? $statusstartdate : array(),
 | ||
| 				'statusenddate'=>$statusenddate ? $statusenddate : array(),
 | ||
| 				'orderby'=>$orderby
 | ||
| 			));
 | ||
| 			$this->total = $resArr['totalDocs'] + $resArr['totalFolders'];
 | ||
| 			$searchTime = $this->getTime() - $startTime;
 | ||
| 			$this->searchTime = round($searchTime, 2);
 | ||
| 
 | ||
| 			$entries = array();
 | ||
| 			$fcount = 0;
 | ||
| 			if($resArr['folders']) {
 | ||
| 				foreach ($resArr['folders'] as $entry) {
 | ||
| 					if ($entry->getAccessMode($user) >= M_READ) {
 | ||
| 						$entries[] = $entry;
 | ||
| 						$fcount++;
 | ||
| 					}
 | ||
| 				}
 | ||
| 			}
 | ||
| 			$this->fcount = $fcount;
 | ||
| 			$dcount = 0;
 | ||
| 			if($resArr['docs']) {
 | ||
| 				foreach ($resArr['docs'] as $entry) {
 | ||
| 					if ($entry->getAccessMode($user) >= M_READ) {
 | ||
| 						if($entry->getLatestContent()) {
 | ||
| 							$entry->verifyLastestContentExpriry();
 | ||
| 							$entries[] = $entry;
 | ||
| 							$dcount++;
 | ||
| 						}
 | ||
| 					}
 | ||
| 				}
 | ||
| 			}
 | ||
| 			$this->dcount = $dcount;
 | ||
| 			$totalPages = (int) (count($entries)/$limit);
 | ||
| 			if(count($entries)%$limit)
 | ||
| 				$totalPages++;
 | ||
| 			if($pageNumber != 'all')
 | ||
| 				$this->entries = array_slice($entries, ($pageNumber-1)*$limit, $limit);
 | ||
| 			$this->totalPages = $totalPages;
 | ||
| 			$this->facets = array();
 | ||
| 			$this->stats = array();
 | ||
| 		}
 | ||
| 	} /* }}} */
 | ||
| 
 | ||
| 	public function getFolderCount() {
 | ||
| 		return $this->fcount;
 | ||
| 	}
 | ||
| 
 | ||
| 	public function getDocumentCount() {
 | ||
| 		return $this->dcount;
 | ||
| 	}
 | ||
| 
 | ||
| 	public function getTotal() {
 | ||
| 		return $this->total;
 | ||
| 	}
 | ||
| } /* }}} */
 | 
