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

/**
* Set this to let grommunio.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", TMP_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_SOURCE);

// 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("grommunio_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 grommunio_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+");
	$datetime = date("d-M-Y H:i:s");
	if($resource) {
		fwrite($file, ("[" . $datetime . "] " . $title. " - " . var_export(get_resource_type($variable), true) . "\r\n"));
	} else {
		fwrite($file, ("[" . $datetime . "] " . $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 grommunio.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 = date("YmdHiS").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+");
	$datetime = date("d-M-Y H:i:s");
	fwrite($file, ("[" . $datetime . "] Restrictions - " . var_export($variable, true) . "\r\n"));
}

/**
 * This function is used to convert all constants of restriction into a human readable strings
 */
if (!function_exists('simplify_restriction')) {
	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;
	}
}
?>
