1<?php
2//=======================================================================
3// File:        JPGRAPH_ERRHANDLER.PHP
4// Description: Error handler class together with handling of localized
5//              error messages. All localized error messages are stored
6//              in a separate file under the "lang/" subdirectory.
7// Created:     2006-09-24
8// Ver:         $Id: jpgraph_errhandler.inc.php 1920 2009-12-08 10:02:26Z ljp $
9//
10// Copyright 2006 (c) Aditus Consulting. All rights reserved.
11//========================================================================
12
13if( !defined('DEFAULT_ERR_LOCALE') ) {
14    define('DEFAULT_ERR_LOCALE','en');
15}
16
17if( !defined('USE_IMAGE_ERROR_HANDLER') ) {
18    define('USE_IMAGE_ERROR_HANDLER',true);
19}
20
21GLOBAL $__jpg_err_locale ;
22$__jpg_err_locale = DEFAULT_ERR_LOCALE;
23
24class ErrMsgText {
25    private $lt=NULL;
26    function __construct() {
27        GLOBAL $__jpg_err_locale;
28        $file = 'lang/'.$__jpg_err_locale.'.inc.php';
29
30        // If the chosen locale doesn't exist try english
31        if( !file_exists(dirname(__FILE__).'/'.$file) ) {
32            $__jpg_err_locale = 'en';
33        }
34
35        $file = 'lang/'.$__jpg_err_locale.'.inc.php';
36        if( !file_exists(dirname(__FILE__).'/'.$file) ) {
37            die('Chosen locale file ("'.$file.'") for error messages does not exist or is not readable for the PHP process. Please make sure that the file exists and that the file permissions are such that the PHP process is allowed to read this file.');
38        }
39        require($file);
40        $this->lt = $_jpg_messages;
41    }
42
43    function Get($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) {
44        GLOBAL $__jpg_err_locale;
45        if( !isset($this->lt[$errnbr]) ) {
46            return 'Internal error: The specified error message ('.$errnbr.') does not exist in the chosen locale ('.$__jpg_err_locale.')';
47        }
48        $ea = $this->lt[$errnbr];
49        $j=0;
50        if( $a1 !== null ) {
51            $argv[$j++] = $a1;
52            if( $a2 !== null ) {
53                $argv[$j++] = $a2;
54                if( $a3 !== null ) {
55                    $argv[$j++] = $a3;
56                    if( $a4 !== null ) {
57                        $argv[$j++] = $a4;
58                        if( $a5 !== null ) {
59                            $argv[$j++] = $a5;
60                        }
61                    }
62                }
63            }
64        }
65        $numargs = $j;
66        if( $ea[1] != $numargs ) {
67            // Error message argument count do not match.
68            // Just return the error message without arguments.
69            return $ea[0];
70        }
71        switch( $numargs ) {
72            case 1:
73                $msg = sprintf($ea[0],$argv[0]);
74                break;
75            case 2:
76                $msg = sprintf($ea[0],$argv[0],$argv[1]);
77                break;
78            case 3:
79                $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2]);
80                break;
81            case 4:
82                $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3]);
83                break;
84            case 5:
85                $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3],$argv[4]);
86                break;
87            case 0:
88            default:
89                $msg = sprintf($ea[0]);
90                break;
91        }
92        return $msg;
93    }
94}
95
96//
97// A wrapper class that is used to access the specified error object
98// (to hide the global error parameter and avoid having a GLOBAL directive
99// in all methods.
100//
101class JpGraphError {
102    private static $__iImgFlg = true;
103    private static $__iLogFile = '';
104    private static $__iTitle = 'JpGraph Error: ';
105    public static function Raise($aMsg,$aHalt=true){
106        throw new JpGraphException($aMsg);
107    }
108    public static function SetErrLocale($aLoc) {
109        GLOBAL $__jpg_err_locale ;
110        $__jpg_err_locale = $aLoc;
111    }
112    public static function RaiseL($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) {
113        throw new JpGraphExceptionL($errnbr,$a1,$a2,$a3,$a4,$a5);
114    }
115    public static function SetImageFlag($aFlg=true) {
116    	self::$__iImgFlg = $aFlg;
117    }
118    public static function GetImageFlag() {
119    	return self::$__iImgFlg;
120    }
121    public static function SetLogFile($aFile) {
122    	self::$__iLogFile = $aFile;
123    }
124    public static function GetLogFile() {
125    	return self::$__iLogFile;
126    }
127    public static function SetTitle($aTitle) {
128    	self::$__iTitle = $aTitle;
129    }
130    public static function GetTitle() {
131    	return self::$__iTitle;
132    }
133}
134
135class JpGraphException extends Exception {
136    // Redefine the exception so message isn't optional
137    public function __construct($message, $code = 0) {
138        // make sure everything is assigned properly
139        parent::__construct($message, $code);
140    }
141    // custom string representation of object
142    public function _toString() {
143        return __CLASS__ . ": [{$this->code}]: {$this->message} at " . basename($this->getFile()) . ":" . $this->getLine() . "\n" . $this->getTraceAsString() . "\n";
144    }
145    // custom representation of error as an image
146    public function Stroke() {
147    	if( JpGraphError::GetImageFlag() ) {
148        	$errobj = new JpGraphErrObjectImg();
149        	$errobj->SetTitle(JpGraphError::GetTitle());
150    	}
151    	else {
152    		$errobj = new JpGraphErrObject();
153        	$errobj->SetTitle(JpGraphError::GetTitle());
154    		$errobj->SetStrokeDest(JpGraphError::GetLogFile());
155    	}
156        $errobj->Raise($this->getMessage());
157    }
158    static public function defaultHandler(Throwable $exception) {
159        global $__jpg_OldHandler;
160        if( $exception instanceof JpGraphException ) {
161            $exception->Stroke();
162        }
163        else {
164            // Restore old handler
165            if( $__jpg_OldHandler !== NULL ) {
166                set_exception_handler($__jpg_OldHandler);
167            }
168            throw $exception;
169        }
170    }
171}
172
173class JpGraphExceptionL extends JpGraphException {
174   // Redefine the exception so message isn't optional
175    public function __construct($errcode,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) {
176        // make sure everything is assigned properly
177        $errtxt = new ErrMsgText();
178        JpGraphError::SetTitle('JpGraph Error: '.$errcode);
179        parent::__construct($errtxt->Get($errcode,$a1,$a2,$a3,$a4,$a5), 0);
180    }
181}
182
183// Setup the default handler
184global $__jpg_OldHandler;
185$__jpg_OldHandler = set_exception_handler(array('JpGraphException','defaultHandler'));
186
187//
188// First of all set up a default error handler
189//
190
191//=============================================================
192// The default trivial text error handler.
193//=============================================================
194class JpGraphErrObject {
195
196    protected $iTitle = "JpGraph error: ";
197    protected $iDest = false;
198
199
200    function __construct() {
201        // Empty. Reserved for future use
202    }
203
204    function SetTitle($aTitle) {
205        $this->iTitle = $aTitle;
206    }
207
208    function SetStrokeDest($aDest) {
209        $this->iDest = $aDest;
210    }
211
212    // If aHalt is true then execution can't continue. Typical used for fatal errors
213    function Raise($aMsg,$aHalt=false) {
214        if( $this->iDest != '' ) {
215        	if( $this->iDest == 'syslog' ) {
216        		error_log($this->iTitle.$aMsg);
217        	}
218        	else {
219        		$str = '['.date('r').'] '.$this->iTitle.$aMsg."\n";
220        		$f = @fopen($this->iDest,'a');
221    	        if( $f ) {
222        	        @fwrite($f,$str);
223            	    @fclose($f);
224            	}
225        	}
226        }
227        else {
228        	$aMsg = $this->iTitle.$aMsg;
229        	// Check SAPI and if we are called from the command line
230        	// send the error to STDERR instead
231        	if( PHP_SAPI == 'cli' ) {
232        		fwrite(STDERR,$aMsg);
233        	}
234        	else {
235            	echo $aMsg;
236        	}
237        }
238        if( $aHalt )
239        	exit(1);
240    }
241}
242
243//==============================================================
244// An image based error handler
245//==============================================================
246class JpGraphErrObjectImg extends JpGraphErrObject {
247
248    function __construct() {
249        parent::__construct();
250        // Empty. Reserved for future use
251    }
252
253    function Raise($aMsg,$aHalt=true) {
254        $img_iconerror =
255     'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaV'.
256     'BMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'.
257     'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpY'.
258     'iYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'.
259     'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'.
260     'IAAAsSAdLdfvwAAAAHdElNRQfTBgISOCqusfs5AAABLUlEQVR4'.
261     '2tWV3XKCMBBGWfkranCIVClKLd/7P2Q3QsgCxjDTq+6FE2cPH+'.
262     'xJ0Ogn2lQbsT+Wrs+buAZAV4W5T6Bs0YXBBwpKgEuIu+JERAX6'.
263     'wM2rHjmDdEITmsQEEmWADgZm6rAjhXsoMGY9B/NZBwJzBvn+e3'.
264     'wHntCAJdGu9SviwIwoZVDxPB9+Rc0TSEbQr0j3SA1gwdSn6Db0'.
265     '6Tm1KfV6yzWGQO7zdpvyKLKBDmRFjzeB3LYgK7r6A/noDAfjtS'.
266     'IXaIzbJSv6WgUebTMV4EoRB8a2mQiQjgtF91HdKDKZ1gtFtQjk'.
267     'YcWaR5OKOhkYt+ZsTFdJRfPAApOpQYJTNHvCRSJR6SJngQadfc'.
268     'vd69OLMddVOPCGVnmrFD8bVYd3JXfxXPtLR/+mtv59/ALWiiMx'.
269     'qL72fwAAAABJRU5ErkJggg==' ;
270
271
272        if( function_exists("imagetypes") ) {
273            $supported = imagetypes();
274        } else {
275            $supported = 0;
276        }
277
278        if( !function_exists('imagecreatefromstring') ) {
279            $supported = 0;
280        }
281
282        if( ob_get_length() || headers_sent() || !($supported & IMG_PNG) ) {
283            // Special case for headers already sent or that the installation doesn't support
284            // the PNG format (which the error icon is encoded in).
285            // Dont return an image since it can't be displayed
286            die($this->iTitle.' '.$aMsg);
287        }
288
289        $aMsg = wordwrap($aMsg,55);
290        $lines = substr_count($aMsg,"\n");
291
292        // Create the error icon GD
293        $erricon = Image::CreateFromString(base64_decode($img_iconerror));
294
295        // Create an image that contains the error text.
296        $w=400;
297        $h=100 + 15*max(0,$lines-3);
298
299        $img = new Image($w,$h);
300
301
302        // Drop shadow
303        $img->SetColor("gray");
304        $img->FilledRectangle(5,5,$w-1,$h-1,10);
305        $img->SetColor("gray:0.7");
306        $img->FilledRectangle(5,5,$w-3,$h-3,10);
307
308        // Window background
309        $img->SetColor("lightblue");
310        $img->FilledRectangle(1,1,$w-5,$h-5);
311        $img->CopyCanvasH($img->img,$erricon,5,30,0,0,40,40);
312
313        // Window border
314        $img->SetColor("black");
315        $img->Rectangle(1,1,$w-5,$h-5);
316        $img->Rectangle(0,0,$w-4,$h-4);
317
318        // Window top row
319        $img->SetColor("darkred");
320        for($y=3; $y < 18; $y += 2 )
321        $img->Line(1,$y,$w-6,$y);
322
323        // "White shadow"
324        $img->SetColor("white");
325
326        // Left window edge
327        $img->Line(2,2,2,$h-5);
328        $img->Line(2,2,$w-6,2);
329
330        // "Gray button shadow"
331        $img->SetColor("darkgray");
332
333        // Gray window shadow
334        $img->Line(2,$h-6,$w-5,$h-6);
335        $img->Line(3,$h-7,$w-5,$h-7);
336
337        // Window title
338        $m = floor($w/2-5);
339        $l = 110;
340        $img->SetColor("lightgray:1.3");
341        $img->FilledRectangle($m-$l,2,$m+$l,16);
342
343        // Stroke text
344        $img->SetColor("darkred");
345        $img->SetFont(FF_FONT2,FS_BOLD);
346        $img->StrokeText($m-90,15,$this->iTitle);
347        $img->SetColor("black");
348        $img->SetFont(FF_FONT1,FS_NORMAL);
349        $txt = new Text($aMsg,52,25);
350        $txt->SetFont(FF_FONT1);
351        $txt->Align("left","top");
352        $txt->Stroke($img);
353        if ($this->iDest) {
354            $img->Stream($this->iDest);
355        } else {
356            $img->Headers();
357            $img->Stream();
358        }
359        if( $aHalt )
360            die();
361    }
362}
363
364
365
366if( ! USE_IMAGE_ERROR_HANDLER ) {
367	JpGraphError::SetImageFlag(false);
368}
369?>
370