summaryrefslogtreecommitdiff
path: root/debug.class
blob: e33a339673ac9df8273b7cd4c4f62262e0e71883 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
<?php
/*
**	$Id$
**
**	debug.class - Debug Functionality for ITools
**
**	ITools - the Internet Tools Library
**
**	Copyright (C) 1995-2003 by the ITools Authors.
**	This program is free software; you can redistribute it and/or
**	modify it under the terms of either the GNU General Public License
**	or the GNU Lesser General Public License, as published by the Free
**	Software Foundation. See http://www.gnu.org/licenses/ for details.
*/

/**
 * Debug functions
 */
class it_debug
{
	var $level;
	var $email;
	var $subject;
	var $from;

/**
 * Constructor
 * @param $level Debug level. All debug() calls with a level <= $level are shown.
 * @param $email E-mail address for mail() and internal_error() functions.
 * @param $subject Subject of e-mail messages
 * @see ::debug(), ::mail(), ::internal_error()
 */
function it_debug($level=0, $email="itools@gna.ch", $subject=null)
{
	$this->level = isset($GLOBALS['debug_level']) ? $GLOBALS['debug_level'] : $level;
	$this->email = $email;
	$this->subject = isset($subject) ? $subject : 'ITools error ('.$_SERVER['HTTP_HOST'].') on '.getenv('HOSTNAME');
	$this->from = 'From: "it_debug '.getenv('HOSTNAME').'" <itools@'.$_SERVER['SERVER_NAME'].'>';
}


/**
 * Output a message if the global debug level is higher or the same as $level
 * @param $text Message to display
 * @param $level Debug level
 */
function debug($text, $level = 0)
{
	if ($this->level >= $level)
	{
		echo (isset($_SERVER['REMOTE_ADDR']) ? nl2br("$level $text\n") : "$level $text")."\n";
		flush();
	}
}


/**
 * Send an e-mail to this debug object's maintainer
 * @param $text Text of mail message
 * @param $level Debug level - Mail is only sent if this is <= the global debug level
 */
function mail($text, $level = 0)
{
	if ($this->level >= $level)
	{
		if ($this->email)
			mail($this->email, $this->subject, $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']."\n".$_SERVER['SCRIPT_FILENAME']."\n\n".$text, $this->from);
		else
			error_log("missing debug email addr: " . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . " " . substr($text,0,200));
	}
}


/**
 * Display error message or maintenance page and terminate processing. Mail message and vardump to maintainer
 * @param $text Message to display
 * @return This function never returns
 */
function internal_error($text)
{
	$text = "Host: ".getenv('HOSTNAME')."\nPage: //{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}\nFile: {$_SERVER['SCRIPT_FILENAME']}\n\n$text\n\n";

	if ($this->email)
		mail($this->email, $this->subject, $text.'$_REQUEST: '.print_r($_REQUEST, true). "\nStack:\n" . print_r(debug_backtrace(), true), $this->from);
	else
		error_log("missing debug email addr: " . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . " " . substr($text,0,200));

	/* If we have a maintenance display page show this instead of error */
	if (file_exists($_SERVER['DOCUMENT_ROOT'].'/maintenance.html'))
	{
		header("Location: http://{$_SERVER['HTTP_HOST']}/maintenance.html");
		exit;
	}
	else
		fail("<pre>Internal Error:\n\n$text");
}


/**
 * Function to return dump of all it's parameters,
 * normally used through D(), ED(), EDX() in support.pinc
 * @param Varargs of mixed stuff to dump
 * @return String representation of dump
 */
function dump()
{
	$stack = debug_backtrace();
	$line = $stack[2]['line'];
	$file = $stack[2]['file'];

	if (!$_SERVER['REMOTE_ADDR'] && preg_match('/class/', $file))
		$line--;

	if (ereg('(csv|txt|gif|jpg)', $_SERVER['PHP_SELF']) || !ereg('Mozilla', $_SERVER['HTTP_USER_AGENT']))
		$plain = 1;
	else if ($_SERVER['REMOTE_ADDR'])
	{
		$blue = "<span style='color:#00c'>";
		$noblue = "</span>";
	}
	else if (getenv('USER') != 'cschneid') # ;)
	{
		$blue = "\033[34m";
		$noblue = "\033[m";
		$red = "\033[31m";
		$nored = "\033[m";
	}

	if (!isset($GLOBALS['it_debug::dump source'][$file]))
		$GLOBALS['it_debug::dump source'][$file] = file($file);

	$src = $GLOBALS['it_debug::dump source'][$file][$line-1];

	$paramlist = preg_match('/(D|ED|EDC|EDX)\s*\(\s*([^)]+)/i', $src, $parts) ? $parts[2] : "";
	$argnames = preg_split('/\s*,\s*/', $paramlist);

	foreach (func_get_args() as $arg)
	{
		$var = array_shift($argnames);
		if ($arg==='_ignoreme')
			continue;

		$item = gettype($arg) == 'resource' ? trim(print_r($arg, true)) : trim(var_export($arg, true));
		$item = preg_replace("#(=>?)\s*\n\s*(array|class)#", '$1 $2', $item); # array( and class on same line as key
		$item = preg_replace('#array \(\s+([^({,;]+),\s+\)#', 'array( $1 )', $item); # 1-element arrays on 1 line
		$item = preg_replace('#class (\S+) \{\s+([^({,;]+;)?\s+\}#', 'class $1 { $2 }', $item); # 1-element objects on 1 line
		#$item = preg_replace('#\{\s*var \$attr#', '{ var $attr', $item); # move $attr on same line
		$item = preg_replace("#\\(\s*\n\s*\\)#", "()", $item);	   # empty arrays on 1 line
		#$item = preg_replace('#\s+var \$_(.|\n)*?;\s*\n#', "", $item);
		$item = "$red$item$nored";

		if (isset($_SERVER['REMOTE_ADDR']) && !$plain)
			$item = htmlspecialchars($item);

		if (ereg('^[\'"]', $var))
			$r .= "$item ";
		else {
			$var = "$blue$var=$noblue";
			$r .= preg_match("/\n/", $item) ? "\n$var$item\n" : "$var$item ";
		}
	}

	if ($GLOBALS['debug_indent'])
		$r = str_repeat("  ", count(debug_backtrace())-3) . $r;

	if (isset($_SERVER['REMOTE_ADDR']) && !$plain)
		 return "<pre style='color:#c00; text-align:left; background-color:white; margin:0'>$r</pre>\n";
	else
		 return "$r\n";
}

function backtrace()
{
	foreach (array_slice(debug_backtrace(), 1) as $call)
		$line .= basename($call['file']) . ":" . $call['line'] . " ";
	return $line;
}

}
?>