<?php
/**
* This file is only used for debugging purpose, this file isn't needed in
* the release version.
*/

/**
* Set this to let kopano.php exports the JSON
* but please note that you must create the DEBUG_JSONOUT_DIR directory and that
* it is writable by PHP
*/
define("DEBUG_JSONOUT", true);
define("DEBUG_JSONOUT_DIR", "debug_xml/");
define("DEBUG_JSONOUT_GZIP", false);
define("DEBUG_PLUGINS", true);
define("DEBUG_PLUGINS_DISABLE_CACHE", false);

// dump file, must be writable
define("DEBUG_DUMP_FILE", BASE_PATH . 'debug.txt');

// The different value types for the DEBUG_LOADER config option
// This can be any of the following values:
//      LOAD_RELEASE
//              Load the concatenated & compressed files
//      LOAD_DEBUG
//              Load the concatenated files
//      LOAD_SOURCE
//              Load the original source files (for developers)
define("DEBUG_LOADER", LOAD_RELEASE);

// log php errors into apache log
ini_set("log_errors", true);

// end config


//	This PHP error handler, only dumps the error to our dump file, including mapi_last_hresult
error_reporting(E_ALL | E_STRICT);
set_error_handler("kopano_error_handler");

/**
* Custom error handler, here we check to see if it is a MAPI error and dump all info
* to the dump file, and finally we redirect the error back to PHP
*/
function kopano_error_handler($errno, $errstr, $errfile, $errline, $errorContext)
{
	$error = array("msg"=>$errstr, "file"=>$errfile.":".$errline);

	dump($error, "ERROR", true);

	$filterOutErrors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE, E_WARNING, E_NOTICE);

	if(!in_array($errno, $filterOutErrors))
		throw new ZarafaErrorException($errstr, $errno, $errfile, $errline, $errorContext);
}

/**
* This function "dumps" the contents of $variable to debug.txt (and when requested also a backtrace)
*/
function dump($variable, $title="", $backtrace=false, $resource=false)
{
	$file = fopen(DEBUG_DUMP_FILE, "a+");
	$date = strftime("%d-%b-%Y");
	$time = strftime("%H:%M:%S");
	if($resource) {
		fwrite($file, ("[" . $date . " " . $time . "] " . $title. " - " . var_export(get_resource_type($variable), true) . "\r\n"));
	} else {
		fwrite($file, ("[" . $date . " " . $time . "] " . $title. " - " . var_export($variable, true) . "\r\n"));
	}

	if ($backtrace){
		dump(_debug_backtrace(false));
	}
}

// use this function when you want to dump an array of MAPI properties
function dump_props($variable,$title=""){
	global $_debug_propList;
	if ($_debug_propList===false){
		// caching
		foreach(get_defined_constants() as $key=>$value){
			if (substr($key,0,3)=='PR_'){
				$_debug_propList[$key] = $value;
			}
		}
	}

	foreach($variable as $key=>$value){
		$prop = array_keys($_debug_propList,$key);
		if (count($prop)>0){
			foreach($prop as $k=>$v){
				$variable["0x".str_pad(strtoupper(dechex($key)),8, '0', STR_PAD_LEFT).' '.$v] = $value;
			}
		}else{
			$variable["0x".str_pad(strtoupper(dechex($key)),8, '0', STR_PAD_LEFT)] = $value;
		}
		unset($variable[$key]);
	}
	dump($variable,$title);
}
$_debug_propList = false;

/**
 * This function is used for the in/output by kopano.php to store the JSON to disk
 */
function dump_json($json, $prefix){
	global $debug_json_id;

	if (DEBUG_JSONOUT && is_dir(DEBUG_JSONOUT_DIR)) {
		if (!isset($debug_json_id) || empty($debug_json_id)) {
			$debug_json_id = strftime("%Y%m%d%H%M%S").uniqid("_");
		}

		$data = json_decode($json, true);
		$data = var_export($data, true);

		$fh = fopen(DEBUG_JSONOUT_DIR . $prefix . "_" . $debug_json_id . ".json" . (DEBUG_JSONOUT_GZIP ? ".gz" : ""), "w");
		fwrite($fh, (DEBUG_JSONOUT_GZIP ? gzencode($data) : $data));
		fclose($fh);
	}
}

/**
* internal function to generate a backtrace
*/
function _debug_backtrace($html=true){
  $output = $html?"<br/>\n":"\n";
  foreach(debug_backtrace() as $t){
    if (isset($t['file']) && $t['file']!=__FILE__){
      $output .= $html?'<strong>@</strong> ':'@ ';
      if(isset($t['file'])) {
        $output .= basename($t['file']) . ':' . $t['line'];
      } else {
       $output .= '[PHP inner-code]';
      }
      $output .= ' - ';
      if(isset($t['class'])) $output .= $t['class'] . $t['type'];
      $output .= $t['function'];
      if(isset($t['args']) && sizeof($t['args']) > 0) {
        $output .= '(...)';
      } else {
        $output .= '()';
      }
      $output .= $html?"<br/>\n":"\n";
    }
  }
  return $output;
}

/**
* This function is used for dumping client side restrictions in user readable form
*/
function dump_restriction($restriction) {
	$variable = simplify_restriction($restriction);

	$file = fopen(DEBUG_DUMP_FILE, "a+");
	$date = strftime("%d-%b-%Y");
	$time = strftime("%H:%M:%S");
	fwrite($file, ("[" . $date . " " . $time . "] Restrictions - " . var_export($variable, true) . "\r\n"));
}

/**
 * This function is used to covert all constants of restriction into a human readable strings
 */
function simplify_restriction($restriction) {
	if (!is_array($restriction)){
		return $restriction;
	}

	switch($restriction[0]){
		case RES_AND:
			$restriction[0] = "RES_AND";
			if(isset($restriction[1][0]) && is_array($restriction[1][0])) {
				foreach($restriction[1] as &$res) {
					$res = simplify_restriction($res);
				}
				unset($res);
			} else if(isset($restriction[1]) && $restriction[1]) {
				$restriction[1] = simplify_restriction($restriction[1]);
			}
			break;
		case RES_OR:
			$restriction[0] = "RES_OR";
			if(isset($restriction[1][0]) && is_array($restriction[1][0])) {
				foreach($restriction[1] as &$res) {
					$res = simplify_restriction($res);
				}
				unset($res);
			} else if(isset($restriction[1]) && $restriction[1]) {
				$restriction[1] = simplify_restriction($restriction[1]);
			}
			break;
		case RES_NOT:
			$restriction[0] = "RES_NOT";
			$restriction[1][0] = simplify_restriction($restriction[1][0]);
			break;
		case RES_COMMENT:
			$restriction[0] = "RES_COMMENT";
			$res = simplify_restriction($restriction[1][RESTRICTION]);
			$props = $restriction[1][PROPS];

			foreach($props as &$prop) {
				$propTag = $prop[ULPROPTAG];
				$propValue = $prop[VALUE];

				unset($prop);

				$prop["ULPROPTAG"] = is_string($propTag) ? $propTag : Conversion::property2json($propTag);
				$prop["VALUE"] = is_array($propValue) ? $propValue[$propTag] : $propValue;
			}
			unset($prop);

			unset($restriction[1]);

			$restriction[1]["RESTRICTION"] = $res;
			$restriction[1]["PROPS"] = $props;
			break;
		case RES_PROPERTY:
			$restriction[0] = "RES_PROPERTY";
			$propTag = $restriction[1][ULPROPTAG];
			$propValue = $restriction[1][VALUE];
			$relOp = $restriction[1][RELOP];

			unset($restriction[1]);

			// relop flags
			$relOpFlags = "";
			if($relOp == RELOP_LT) {
				$relOpFlags = "RELOP_LT";
			} else if($relOp == RELOP_LE) {
				$relOpFlags = "RELOP_LE";
			} else if($relOp == RELOP_GT) {
				$relOpFlags = "RELOP_GT";
			} else if($relOp == RELOP_GE) {
				$relOpFlags = "RELOP_GE";
			} else if($relOp == RELOP_EQ) {
				$relOpFlags = "RELOP_EQ";
			} else if($relOp == RELOP_NE) {
				$relOpFlags = "RELOP_NE";
			} else if($relOp == RELOP_RE) {
				$relOpFlags = "RELOP_RE";
			}

			$restriction[1]["RELOP"] = $relOpFlags;
			$restriction[1]["ULPROPTAG"] = is_string($propTag) ? $propTag : Conversion::property2json($propTag);
			$restriction[1]["VALUE"] = is_array($propValue) ? $propValue[$propTag] : $propValue;
			break;
		case RES_CONTENT:
			$restriction[0] = "RES_CONTENT";
			$propTag = $restriction[1][ULPROPTAG];
			$propValue = $restriction[1][VALUE];
			$fuzzyLevel = $restriction[1][FUZZYLEVEL];

			unset($restriction[1]);

			// fuzzy level flags
			$levels = array();

			if (($fuzzyLevel & FL_SUBSTRING) == FL_SUBSTRING)
				$levels[] = "FL_SUBSTRING";
			elseif (($fuzzyLevel & FL_PREFIX) == FL_PREFIX)
				$levels[] = "FL_PREFIX";
			else
				$levels[] = "FL_FULLSTRING";
						
			if (($fuzzyLevel & FL_IGNORECASE) == FL_IGNORECASE)
				$levels[] = "FL_IGNORECASE";
						
			if (($fuzzyLevel & FL_IGNORENONSPACE) == FL_IGNORENONSPACE)
				$levels[] = "FL_IGNORENONSPACE";
			
			if (($fuzzyLevel & FL_LOOSE) == FL_LOOSE)
				$levels[] = "FL_LOOSE";
			
			$fuzzyLevelFlags = implode(" | ", $levels);

			$restriction[1]["FUZZYLEVEL"] = $fuzzyLevelFlags;
			$restriction[1]["ULPROPTAG"] = is_string($propTag) ? $propTag : Conversion::property2json($propTag);
			$restriction[1]["VALUE"] = is_array($propValue) ? $propValue[$propTag] : $propValue;
			break;
		case RES_COMPAREPROPS:
			$propTag1 = $restriction[1][ULPROPTAG1];
			$propTag2 = $restriction[1][ULPROPTAG2];

			unset($restriction[1]);

			$restriction[1]["ULPROPTAG1"] = is_string($propTag1) ? $proptag1 : Conversion::property2json($proptag1);
			$restriction[1]["ULPROPTAG2"] = is_string($propTag2) ? $propTag2 : Conversion::property2json($propTag2);
			break;
		case RES_BITMASK:
			$restriction[0] = "RES_BITMASK";
			$propTag = $restriction[1][ULPROPTAG];
			$maskType = $restriction[1][ULTYPE];
			$maskValue = $restriction[1][ULMASK];

			unset($restriction[1]);

			// relop flags
			$maskTypeFlags = "";
			if($maskType == BMR_EQZ) {
				$maskTypeFlags = "BMR_EQZ";
			} else if($maskType == BMR_NEZ) {
				$maskTypeFlags = "BMR_NEZ";
			}

			$restriction[1]["ULPROPTAG"] = is_string($propTag) ? $propTag : Conversion::property2json($propTag);
			$restriction[1]["ULTYPE"] = $maskTypeFlags;
			$restriction[1]["ULMASK"] = $maskValue;
			break;
		case RES_SIZE:
			$restriction[0] = "RES_SIZE";
			$propTag = $restriction[1][ULPROPTAG];
			$propValue = $restriction[1][CB];
			$relOp = $restriction[1][RELOP];

			unset($restriction[1]);

			// relop flags
			$relOpFlags = "";
			if($relOp == RELOP_LT) {
				$relOpFlags = "RELOP_LT";
			} else if($relOp == RELOP_LE) {
				$relOpFlags = "RELOP_LE";
			} else if($relOp == RELOP_GT) {
				$relOpFlags = "RELOP_GT";
			} else if($relOp == RELOP_GE) {
				$relOpFlags = "RELOP_GE";
			} else if($relOp == RELOP_EQ) {
				$relOpFlags = "RELOP_EQ";
			} else if($relOp == RELOP_NE) {
				$relOpFlags = "RELOP_NE";
			} else if($relOp == RELOP_RE) {
				$relOpFlags = "RELOP_RE";
			}

			$restriction[1]["ULPROPTAG"] = is_string($propTag) ? $propTag : Conversion::property2json($propTag);
			$restriction[1]["RELOP"] = $relOpFlags;
			$restriction[1]["CB"] = $propValue;
			break;
		case RES_EXIST:
			$propTag = $restriction[1][ULPROPTAG];

			unset($restriction[1]);

			$restriction[1]["ULPROPTAG"] = is_string($propTag) ? $propTag : Conversion::property2json($propTag);
			break;
		case RES_SUBRESTRICTION:
			$propTag = $restriction[1][ULPROPTAG];
			$res = simplify_restriction($restriction[1][RESTRICTION]);

			unset($restriction[1]);

			$restriction[1]["ULPROPTAG"] = is_string($propTag) ? $propTag : Conversion::property2json($propTag);
			$restriction[1]["RESTRICTION"] = $res;
			break;
	}

	return $restriction;
}
?>
