ITM_Logger - Version 0.1.0

Version Notes

ChromePHP and FirePHP support.

Download this release

Release Info

Developer Jens Averkamp
Extension ITM_Logger
Version 0.1.0
Comparing to
See all releases


Version 0.1.0

app/code/community/Itm/Logger/Helper/Data.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by ITM design GmbH
4
+ *
5
+ * @file Data.php
6
+ * @author Jens Averkamp <j.averkamp@itm-systems.com>
7
+ * @copyright Itm design GmbH
8
+ * @link http://www.itm-design.com
9
+ *
10
+ * Date: 01.10.12 16:38
11
+ */
12
+ require_once 'lib/Itm/ChromePhp/ChromePhp.php';
13
+
14
+ class Itm_Logger_Helper_Data extends Mage_Core_Helper_Abstract implements Itm_Logger_Model_Logger
15
+ {
16
+ const ITM_LOGGER_CONFIG_ENABLE = 'itm/logger/enabled';
17
+ const ITM_LOGGER_CONFIG_ONLY_DEV = 'itm/logger/onlydev';
18
+
19
+ protected $logger = array();
20
+ protected $logger_classes = array(
21
+ 'logger/chromePhp',
22
+ 'logger/firePhp',
23
+ );
24
+
25
+ public function __construct()
26
+ {
27
+ if(!$this->canLog())
28
+ return;
29
+
30
+ foreach($this->logger_classes as $logger)
31
+ {
32
+ $logger = Mage::getModel($logger);
33
+ if($logger instanceof Itm_Logger_Model_Logger && $logger->canLog())
34
+ $this->logger[] = $logger;
35
+ }
36
+ }
37
+
38
+ public function log($message)
39
+ {
40
+ foreach($this->logger as $logger)
41
+ {
42
+ $logger->log($message);
43
+ }
44
+ }
45
+
46
+ public function info($message)
47
+ {
48
+ foreach($this->logger as $logger)
49
+ {
50
+ $logger->info($message);
51
+ }
52
+ }
53
+
54
+ public function warn($message)
55
+ {
56
+ foreach($this->logger as $logger)
57
+ {
58
+ $logger->warn($message);
59
+ }
60
+ }
61
+
62
+ public function error($message)
63
+ {
64
+ foreach($this->logger as $logger)
65
+ {
66
+ $logger->error($message);
67
+ }
68
+ }
69
+
70
+ public function canLog()
71
+ {
72
+ // Nur Loggen wenn die Extension "eingeschaltet ist"
73
+ if(!Mage::getStoreConfig(self::ITM_LOGGER_CONFIG_ENABLE))
74
+ return false;
75
+
76
+ // Nur Loggen wenn Magento sich im Dev Mode befindet
77
+ if(Mage::getStoreConfig(self::ITM_LOGGER_CONFIG_ONLY_DEV) && !Mage::getIsDeveloperMode())
78
+ return false;
79
+
80
+
81
+ return true;
82
+ }
83
+ }
app/code/community/Itm/Logger/Model/ChromePhp.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by ITM design GmbH
4
+ *
5
+ * @file ChromePhp.php
6
+ * @author Jens Averkamp <j.averkamp@itm-systems.com>
7
+ * @copyright Itm design GmbH
8
+ * @link http://www.itm-design.com
9
+ *
10
+ * Date: 02.10.12 09:44
11
+ */
12
+ require_once 'lib/Itm/ChromePhp/ChromePhp.php';
13
+
14
+ class Itm_Logger_Model_ChromePhp implements Itm_Logger_Model_Logger
15
+ {
16
+
17
+ protected $logger = null;
18
+ const ITM_LOGGER_CONFIG_CHROMEPHP = 'itm/logger/chromephp';
19
+
20
+
21
+ public function __construct()
22
+ {
23
+ $this->logger = ChromePhp::getInstance();
24
+ }
25
+
26
+ public function log($message)
27
+ {
28
+ if($this->canLog())
29
+ $this->logger->log($message);
30
+
31
+ return $this;
32
+ }
33
+
34
+ public function info($message)
35
+ {
36
+ if($this->canLog())
37
+ $this->logger->info($message);
38
+
39
+ return $this;
40
+ }
41
+
42
+ public function warn($message)
43
+ {
44
+ if($this->canLog())
45
+ $this->logger->warn($message);
46
+
47
+ return $this;
48
+ }
49
+
50
+ public function error($message)
51
+ {
52
+ if($this->canLog())
53
+ $this->logger->error($message);
54
+
55
+ return $this;
56
+ }
57
+
58
+ public function canLog()
59
+ {
60
+ if(!Mage::getStoreConfig(self::ITM_LOGGER_CONFIG_CHROMEPHP))
61
+ return false;
62
+
63
+ return true;
64
+ }
65
+ }
app/code/community/Itm/Logger/Model/FirePhp.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by ITM design GmbH
4
+ *
5
+ * @file FireBug.php
6
+ * @author Jens Averkamp <j.averkamp@itm-systems.com>
7
+ * @copyright Itm design GmbH
8
+ * @link http://www.itm-design.com
9
+ *
10
+ * Date: 02.10.12 09:34
11
+ */
12
+ require_once 'lib/Itm/FirePhp/FirePHP.class.php';
13
+
14
+ class Itm_Logger_Model_FirePhp implements Itm_Logger_Model_Logger
15
+ {
16
+ protected $logger = null;
17
+ protected $writter = null;
18
+
19
+ const Itm_LOGGER_CONFIG_FIREPHP = 'itm/logger/firephp';
20
+
21
+ public function __construct()
22
+ {
23
+ $this->logger = FirePHP::getInstance(true);
24
+ }
25
+
26
+ public function log($message)
27
+ {
28
+ if($this->canLog())
29
+ $this->logger->log($message);
30
+
31
+ return $this;
32
+ }
33
+
34
+ public function info($message)
35
+ {
36
+ if($this->canLog())
37
+ $this->logger->info($message);
38
+
39
+ return $this;
40
+ }
41
+
42
+ public function warn($message)
43
+ {
44
+ if($this->canLog())
45
+ $this->logger->warn($message);
46
+
47
+ return $this;
48
+ }
49
+
50
+ public function error($message)
51
+ {
52
+ if($this->canLog())
53
+ $this->logger->error($message);
54
+
55
+ return $this;
56
+ }
57
+
58
+ public function canLog()
59
+ {
60
+ if(!Mage::getStoreConfig(self::Itm_LOGGER_CONFIG_FIREPHP))
61
+ return false;
62
+
63
+ return true;
64
+ }
65
+ }
app/code/community/Itm/Logger/Model/Logger.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by ITM design GmbH
4
+ *
5
+ * @file Logger.php
6
+ * @author Jens Averkamp <j.averkamp@itm-systems.com>
7
+ * @copyright Itm design GmbH
8
+ * @link http://www.itm-design.com
9
+ *
10
+ * Date: 02.10.12 09:36
11
+ */
12
+ interface Itm_Logger_Model_Logger
13
+ {
14
+ public function log($message);
15
+ public function info($message);
16
+ public function warn($message);
17
+ public function error($message);
18
+ public function canLog();
19
+ }
app/code/community/Itm/Logger/etc/adminhtml.xml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <config>
2
+ <acl>
3
+ <resources>
4
+ <all>
5
+ <title>Allow Everything</title>
6
+ </all>
7
+ <admin>
8
+ <children>
9
+ <system>
10
+ <children>
11
+ <config>
12
+ <children>
13
+ <itm translate="title">
14
+ <title>ITM Design</title>
15
+ <sort_order>100</sort_order>
16
+ </itm>
17
+ </children>
18
+ </config>
19
+ </children>
20
+ </system>
21
+ </children>
22
+ </admin>
23
+ </resources>
24
+ </acl>
25
+ </config>
app/code/community/Itm/Logger/etc/config.xml ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" ?>
2
+
3
+ <config>
4
+ <modules>
5
+ <Itm_Logger>
6
+ <version>0.1.0</version>
7
+ </Itm_Logger>
8
+ </modules>
9
+ <global>
10
+ <helpers>
11
+ <logger>
12
+ <class>Itm_Logger_Helper</class>
13
+ </logger>
14
+ </helpers>
15
+ <models>
16
+ <logger>
17
+ <class>Itm_Logger_Model</class>
18
+ </logger>
19
+ </models>
20
+ </global>
21
+ <default>
22
+ <itm>
23
+ <logger>
24
+ <enabled>0</enabled>
25
+ <onlydev>1</onlydev>
26
+ <firephp>1</firephp>
27
+ <chromephp>1</chromephp>
28
+ </logger>
29
+ </itm>
30
+ </default>
31
+ </config>
app/code/community/Itm/Logger/etc/system.xml ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <config>
2
+ <sections>
3
+ <itm translate="label">
4
+ <label>ITM Extensions</label>
5
+ <tab>general</tab>
6
+ <frontend_type>text</frontend_type>
7
+ <sort_order>1000</sort_order>
8
+ <show_in_default>1</show_in_default>
9
+ <show_in_website>0</show_in_website>
10
+ <show_in_store>0</show_in_store>
11
+ <groups>
12
+ <logger translate="label">
13
+ <label>Develop Log</label>
14
+ <frontend_type>text</frontend_type>
15
+ <sort_order>100</sort_order>
16
+ <show_in_default>1</show_in_default>
17
+ <show_in_website>0</show_in_website>
18
+ <show_in_store>0</show_in_store>
19
+ <fields>
20
+ <enabled translate="label comment">
21
+ <label>Enabled</label>
22
+ <comment />
23
+ <frontend_type>select</frontend_type>
24
+ <source_model>adminhtml/system_config_source_yesno</source_model>
25
+ <sort_order>10</sort_order>
26
+ <show_in_default>1</show_in_default>
27
+ <show_in_website>0</show_in_website>
28
+ <show_in_store>0</show_in_store>
29
+ </enabled>
30
+ <onlydev translate="label comment tooltip">
31
+ <label>Only Dev-Mode</label>
32
+ <comment>Enable Extension only in Magento Dev-Mode</comment>
33
+ <tooltip>Set this option to false, if you have no access to htaccess file!</tooltip>
34
+ <frontend_type>select</frontend_type>
35
+ <source_model>adminhtml/system_config_source_yesno</source_model>
36
+ <sort_order>20</sort_order>
37
+ <show_in_default>1</show_in_default>
38
+ <show_in_website>0</show_in_website>
39
+ <show_in_store>0</show_in_store>
40
+ </onlydev>
41
+ <firephp translate="label comment">
42
+ <label>Enable FirePHP</label>
43
+ <comment>Enable FirePHP for logging?</comment>
44
+ <frontend_type>select</frontend_type>
45
+ <source_model>adminhtml/system_config_source_yesno</source_model>
46
+ <sort_order>30</sort_order>
47
+ <show_in_default>1</show_in_default>
48
+ <show_in_website>0</show_in_website>
49
+ <show_in_store>0</show_in_store>
50
+ </firephp>
51
+ <chromephp translate="label comment">
52
+ <label>Enable ChromePhp</label>
53
+ <comment>Enable ChromePhp for logging?</comment>
54
+ <frontend_type>select</frontend_type>
55
+ <source_model>adminhtml/system_config_source_yesno</source_model>
56
+ <sort_order>40</sort_order>
57
+ <show_in_default>1</show_in_default>
58
+ <show_in_website>0</show_in_website>
59
+ <show_in_store>0</show_in_store>
60
+ </chromephp>
61
+ </fields>
62
+ </logger>
63
+ </groups>
64
+ </itm>
65
+ </sections>
66
+ </config>
app/etc/modules/Itm_Logger.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Itm_Logger>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ </Itm_Logger>
8
+ </modules>
9
+ </config>
lib/Itm/ChromePhp/ChromePhp.php ADDED
@@ -0,0 +1,437 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2012 Craig Campbell
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /**
19
+ * Server Side Chrome PHP debugger class
20
+ *
21
+ * @package ChromePhp
22
+ * @author Craig Campbell <iamcraigcampbell@gmail.com>
23
+ */
24
+ class ChromePhp
25
+ {
26
+ /**
27
+ * @var string
28
+ */
29
+ const VERSION = '3.0';
30
+
31
+ /**
32
+ * @var string
33
+ */
34
+ const HEADER_NAME = 'X-ChromePhp-Data';
35
+
36
+ /**
37
+ * @var string
38
+ */
39
+ const BACKTRACE_LEVEL = 'backtrace_level';
40
+
41
+ /**
42
+ * @var string
43
+ */
44
+ const LOG = 'log';
45
+
46
+ /**
47
+ * @var string
48
+ */
49
+ const WARN = 'warn';
50
+
51
+ /**
52
+ * @var string
53
+ */
54
+ const ERROR = 'error';
55
+
56
+ /**
57
+ * @var string
58
+ */
59
+ const GROUP = 'group';
60
+
61
+ /**
62
+ * @var string
63
+ */
64
+ const INFO = 'info';
65
+
66
+ /**
67
+ * @var string
68
+ */
69
+ const GROUP_END = 'groupEnd';
70
+
71
+ /**
72
+ * @var string
73
+ */
74
+ const GROUP_COLLAPSED = 'groupCollapsed';
75
+
76
+ /**
77
+ * @var string
78
+ */
79
+ protected $_php_version;
80
+
81
+ /**
82
+ * @var int
83
+ */
84
+ protected $_timestamp;
85
+
86
+ /**
87
+ * @var array
88
+ */
89
+ protected $_json = array(
90
+ 'version' => self::VERSION,
91
+ 'columns' => array('label', 'log', 'backtrace', 'type'),
92
+ 'rows' => array()
93
+ );
94
+
95
+ /**
96
+ * @var array
97
+ */
98
+ protected $_backtraces = array();
99
+
100
+ /**
101
+ * @var bool
102
+ */
103
+ protected $_error_triggered = false;
104
+
105
+ /**
106
+ * @var array
107
+ */
108
+ protected $_settings = array(
109
+ self::BACKTRACE_LEVEL => 1
110
+ );
111
+
112
+ /**
113
+ * @var ChromePhp
114
+ */
115
+ protected static $_instance;
116
+
117
+ /**
118
+ * Prevent recursion when working with objects referring to each other
119
+ *
120
+ * @var array
121
+ */
122
+ protected $_processed = array();
123
+
124
+ /**
125
+ * constructor
126
+ */
127
+ private function __construct()
128
+ {
129
+ $this->_php_version = phpversion();
130
+ $this->_timestamp = $this->_php_version >= 5.1 ? $_SERVER['REQUEST_TIME'] : time();
131
+ $this->_json['request_uri'] = $_SERVER['REQUEST_URI'];
132
+ }
133
+
134
+ /**
135
+ * gets instance of this class
136
+ *
137
+ * @return ChromePhp
138
+ */
139
+ public static function getInstance()
140
+ {
141
+ if (self::$_instance === null) {
142
+ self::$_instance = new ChromePhp();
143
+ }
144
+ return self::$_instance;
145
+ }
146
+
147
+ /**
148
+ * logs a variable to the console
149
+ *
150
+ * @param string label
151
+ * @param mixed value
152
+ * @param string severity ChromePhp::LOG || ChromePhp::WARN || ChromePhp::ERROR
153
+ * @return void
154
+ */
155
+ public static function log()
156
+ {
157
+ $args = func_get_args();
158
+ $severity = count($args) == 3 ? array_pop($args) : '';
159
+
160
+ // save precious bytes
161
+ if ($severity == self::LOG) {
162
+ $severity = '';
163
+ }
164
+
165
+ return self::_log($args + array('type' => $severity));
166
+ }
167
+
168
+ /**
169
+ * logs a warning to the console
170
+ *
171
+ * @param string label
172
+ * @param mixed value
173
+ * @return void
174
+ */
175
+ public static function warn()
176
+ {
177
+ return self::_log(func_get_args() + array('type' => self::WARN));
178
+ }
179
+
180
+ /**
181
+ * logs an error to the console
182
+ *
183
+ * @param string label
184
+ * @param mixed value
185
+ * @return void
186
+ */
187
+ public static function error()
188
+ {
189
+ return self::_log(func_get_args() + array('type' => self::ERROR));
190
+ }
191
+
192
+ /**
193
+ * sends a group log
194
+ *
195
+ * @param string value
196
+ */
197
+ public static function group()
198
+ {
199
+ return self::_log(func_get_args() + array('type' => self::GROUP));
200
+ }
201
+
202
+ /**
203
+ * sends an info log
204
+ *
205
+ * @param string value
206
+ */
207
+ public static function info()
208
+ {
209
+ return self::_log(func_get_args() + array('type' => self::INFO));
210
+ }
211
+
212
+ /**
213
+ * sends a collapsed group log
214
+ *
215
+ * @param string value
216
+ */
217
+ public static function groupCollapsed()
218
+ {
219
+ return self::_log(func_get_args() + array('type' => self::GROUP_COLLAPSED));
220
+ }
221
+
222
+ /**
223
+ * ends a group log
224
+ *
225
+ * @param string value
226
+ */
227
+ public static function groupEnd()
228
+ {
229
+ return self::_log(func_get_args() + array('type' => self::GROUP_END));
230
+ }
231
+
232
+ /**
233
+ * internal logging call
234
+ *
235
+ * @param string $type
236
+ * @return void
237
+ */
238
+ protected static function _log(array $args)
239
+ {
240
+ $type = $args['type'];
241
+ unset($args['type']);
242
+
243
+ // nothing passed in, don't do anything
244
+ if (count($args) == 0 && $type != self::GROUP_END) {
245
+ return;
246
+ }
247
+
248
+ // default to single
249
+ $label = null;
250
+ $value = isset($args[0]) ? $args[0] : '';
251
+
252
+ $logger = self::getInstance();
253
+
254
+ // if there are two values passed in then the first one is the label
255
+ if (count($args) == 2) {
256
+ $label = $args[0];
257
+ $value = $args[1];
258
+ }
259
+
260
+ $logger->_processed = array();
261
+ $value = $logger->_convert($value);
262
+
263
+ $backtrace = debug_backtrace(false);
264
+ $level = $logger->getSetting(self::BACKTRACE_LEVEL);
265
+
266
+ $backtrace_message = 'unknown';
267
+ if (isset($backtrace[$level]['file']) && isset($backtrace[$level]['line'])) {
268
+ $backtrace_message = $backtrace[$level]['file'] . ' : ' . $backtrace[$level]['line'];
269
+ }
270
+
271
+ $logger->_addRow($label, $value, $backtrace_message, $type);
272
+ }
273
+
274
+ /**
275
+ * converts an object to a better format for logging
276
+ *
277
+ * @param Object
278
+ * @return array
279
+ */
280
+ protected function _convert($object)
281
+ {
282
+ // if this isn't an object then just return it
283
+ if (!is_object($object)) {
284
+ return $object;
285
+ }
286
+
287
+ //Mark this object as processed so we don't convert it twice and it
288
+ //Also avoid recursion when objects refer to each other
289
+ $this->_processed[] = $object;
290
+
291
+ $object_as_array = array();
292
+
293
+ // first add the class name
294
+ $object_as_array['___class_name'] = get_class($object);
295
+
296
+ // loop through object vars
297
+ $object_vars = get_object_vars($object);
298
+ foreach ($object_vars as $key => $value) {
299
+
300
+ // same instance as parent object
301
+ if ($value === $object || in_array($value, $this->_processed, true)) {
302
+ $value = 'recursion - parent object [' . get_class($value) . ']';
303
+ }
304
+ $object_as_array[$key] = $this->_convert($value);
305
+ }
306
+
307
+ $reflection = new ReflectionClass($object);
308
+
309
+ // loop through the properties and add those
310
+ foreach ($reflection->getProperties() as $property) {
311
+
312
+ // if one of these properties was already added above then ignore it
313
+ if (array_key_exists($property->getName(), $object_vars)) {
314
+ continue;
315
+ }
316
+ $type = $this->_getPropertyKey($property);
317
+
318
+ if ($this->_php_version >= 5.3) {
319
+ $property->setAccessible(true);
320
+ }
321
+
322
+ try {
323
+ $value = $property->getValue($object);
324
+ } catch (ReflectionException $e) {
325
+ $value = 'only PHP 5.3 can access private/protected properties';
326
+ }
327
+
328
+ // same instance as parent object
329
+ if ($value === $object || in_array($value, $this->_processed, true)) {
330
+ $value = 'recursion - parent object [' . get_class($value) . ']';
331
+ }
332
+
333
+ $object_as_array[$type] = $this->_convert($value);
334
+ }
335
+ return $object_as_array;
336
+ }
337
+
338
+ /**
339
+ * takes a reflection property and returns a nicely formatted key of the property name
340
+ *
341
+ * @param ReflectionProperty
342
+ * @return string
343
+ */
344
+ protected function _getPropertyKey(ReflectionProperty $property)
345
+ {
346
+ $static = $property->isStatic() ? ' static' : '';
347
+ if ($property->isPublic()) {
348
+ return 'public' . $static . ' ' . $property->getName();
349
+ }
350
+
351
+ if ($property->isProtected()) {
352
+ return 'protected' . $static . ' ' . $property->getName();
353
+ }
354
+
355
+ if ($property->isPrivate()) {
356
+ return 'private' . $static . ' ' . $property->getName();
357
+ }
358
+ }
359
+
360
+ /**
361
+ * adds a value to the data array
362
+ *
363
+ * @var mixed
364
+ * @return void
365
+ */
366
+ protected function _addRow($label, $log, $backtrace, $type)
367
+ {
368
+ // if this is logged on the same line for example in a loop, set it to null to save space
369
+ if (in_array($backtrace, $this->_backtraces)) {
370
+ $backtrace = null;
371
+ }
372
+
373
+ if ($backtrace !== null) {
374
+ $this->_backtraces[] = $backtrace;
375
+ }
376
+
377
+ $row = array($label, $log, $backtrace, $type);
378
+
379
+ $this->_json['rows'][] = $row;
380
+ $this->_writeHeader($this->_json);
381
+ }
382
+
383
+ protected function _writeHeader($data)
384
+ {
385
+ header(self::HEADER_NAME . ': ' . $this->_encode($data));
386
+ }
387
+
388
+ /**
389
+ * encodes the data to be sent along with the request
390
+ *
391
+ * @param array $data
392
+ * @return string
393
+ */
394
+ protected function _encode($data)
395
+ {
396
+ return base64_encode(utf8_encode(json_encode($data)));
397
+ }
398
+
399
+ /**
400
+ * adds a setting
401
+ *
402
+ * @param string key
403
+ * @param mixed value
404
+ * @return void
405
+ */
406
+ public function addSetting($key, $value)
407
+ {
408
+ $this->_settings[$key] = $value;
409
+ }
410
+
411
+ /**
412
+ * add ability to set multiple settings in one call
413
+ *
414
+ * @param array $settings
415
+ * @return void
416
+ */
417
+ public function addSettings(array $settings)
418
+ {
419
+ foreach ($settings as $key => $value) {
420
+ $this->addSetting($key, $value);
421
+ }
422
+ }
423
+
424
+ /**
425
+ * gets a setting
426
+ *
427
+ * @param string key
428
+ * @return mixed
429
+ */
430
+ public function getSetting($key)
431
+ {
432
+ if (!isset($this->_settings[$key])) {
433
+ return null;
434
+ }
435
+ return $this->_settings[$key];
436
+ }
437
+ }
lib/Itm/ChromePhp/README ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version 3.0
2
+ This class requires PHP 5 or later.
3
+
4
+ ChromePhp is a PHP class to go along with the ChromePhp Google Chrome extension.
5
+
6
+ This class allows you to log variables to the Chrome console.
7
+
8
+ INSTALLATION
9
+ 1. Download the Chrome extension from: https://chrome.google.com/extensions/detail/noaneddfkdjfnfdakjjmocngnfkfehhd
10
+ 2. Put ChromePhp.php somewhere in your PHP include path
11
+ 3. Click the extension icon on the browser to enable it for the current site
12
+ 3. include 'ChromePhp.php';
13
+ 4. ChromePhp::log('hello world');
14
+
15
+ More information can be found here:
16
+ http://www.chromephp.com
lib/Itm/FirePhp/FirePHP.class.php ADDED
@@ -0,0 +1,1784 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * *** BEGIN LICENSE BLOCK *****
4
+ *
5
+ * This file is part of FirePHP (http://www.firephp.org/).
6
+ *
7
+ * Software License Agreement (New BSD License)
8
+ *
9
+ * Copyright (c) 2006-2010, Christoph Dorn
10
+ * All rights reserved.
11
+ *
12
+ * Redistribution and use in source and binary forms, with or without modification,
13
+ * are permitted provided that the following conditions are met:
14
+ *
15
+ * * Redistributions of source code must retain the above copyright notice,
16
+ * this list of conditions and the following disclaimer.
17
+ *
18
+ * * Redistributions in binary form must reproduce the above copyright notice,
19
+ * this list of conditions and the following disclaimer in the documentation
20
+ * and/or other materials provided with the distribution.
21
+ *
22
+ * * Neither the name of Christoph Dorn nor the names of its
23
+ * contributors may be used to endorse or promote products derived from this
24
+ * software without specific prior written permission.
25
+ *
26
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
27
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
30
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
33
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+ *
37
+ * ***** END LICENSE BLOCK *****
38
+ *
39
+ * @copyright Copyright (C) 2007-2009 Christoph Dorn
40
+ * @author Christoph Dorn <christoph@christophdorn.com>
41
+ * @license http://www.opensource.org/licenses/bsd-license.php
42
+ * @package FirePHPCore
43
+ */
44
+
45
+ /**
46
+ * @see http://code.google.com/p/firephp/issues/detail?id=112
47
+ */
48
+ if (!defined('E_STRICT')) {
49
+ define('E_STRICT', 2048);
50
+ }
51
+ if (!defined('E_RECOVERABLE_ERROR')) {
52
+ define('E_RECOVERABLE_ERROR', 4096);
53
+ }
54
+ if (!defined('E_DEPRECATED')) {
55
+ define('E_DEPRECATED', 8192);
56
+ }
57
+ if (!defined('E_USER_DEPRECATED')) {
58
+ define('E_USER_DEPRECATED', 16384);
59
+ }
60
+
61
+ /**
62
+ * Sends the given data to the FirePHP Firefox Extension.
63
+ * The data can be displayed in the Firebug Console or in the
64
+ * "Server" request tab.
65
+ *
66
+ * For more information see: http://www.firephp.org/
67
+ *
68
+ * @copyright Copyright (C) 2007-2009 Christoph Dorn
69
+ * @author Christoph Dorn <christoph@christophdorn.com>
70
+ * @license http://www.opensource.org/licenses/bsd-license.php
71
+ * @package FirePHPCore
72
+ */
73
+ class FirePHP {
74
+
75
+ /**
76
+ * FirePHP version
77
+ *
78
+ * @var string
79
+ */
80
+ const VERSION = '0.3'; // @pinf replace '0.3' with '%%package.version%%'
81
+
82
+ /**
83
+ * Firebug LOG level
84
+ *
85
+ * Logs a message to firebug console.
86
+ *
87
+ * @var string
88
+ */
89
+ const LOG = 'LOG';
90
+
91
+ /**
92
+ * Firebug INFO level
93
+ *
94
+ * Logs a message to firebug console and displays an info icon before the message.
95
+ *
96
+ * @var string
97
+ */
98
+ const INFO = 'INFO';
99
+
100
+ /**
101
+ * Firebug WARN level
102
+ *
103
+ * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise.
104
+ *
105
+ * @var string
106
+ */
107
+ const WARN = 'WARN';
108
+
109
+ /**
110
+ * Firebug ERROR level
111
+ *
112
+ * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count.
113
+ *
114
+ * @var string
115
+ */
116
+ const ERROR = 'ERROR';
117
+
118
+ /**
119
+ * Dumps a variable to firebug's server panel
120
+ *
121
+ * @var string
122
+ */
123
+ const DUMP = 'DUMP';
124
+
125
+ /**
126
+ * Displays a stack trace in firebug console
127
+ *
128
+ * @var string
129
+ */
130
+ const TRACE = 'TRACE';
131
+
132
+ /**
133
+ * Displays an exception in firebug console
134
+ *
135
+ * Increments the firebug error count.
136
+ *
137
+ * @var string
138
+ */
139
+ const EXCEPTION = 'EXCEPTION';
140
+
141
+ /**
142
+ * Displays an table in firebug console
143
+ *
144
+ * @var string
145
+ */
146
+ const TABLE = 'TABLE';
147
+
148
+ /**
149
+ * Starts a group in firebug console
150
+ *
151
+ * @var string
152
+ */
153
+ const GROUP_START = 'GROUP_START';
154
+
155
+ /**
156
+ * Ends a group in firebug console
157
+ *
158
+ * @var string
159
+ */
160
+ const GROUP_END = 'GROUP_END';
161
+
162
+ /**
163
+ * Singleton instance of FirePHP
164
+ *
165
+ * @var FirePHP
166
+ */
167
+ protected static $instance = null;
168
+
169
+ /**
170
+ * Flag whether we are logging from within the exception handler
171
+ *
172
+ * @var boolean
173
+ */
174
+ protected $inExceptionHandler = false;
175
+
176
+ /**
177
+ * Flag whether to throw PHP errors that have been converted to ErrorExceptions
178
+ *
179
+ * @var boolean
180
+ */
181
+ protected $throwErrorExceptions = true;
182
+
183
+ /**
184
+ * Flag whether to convert PHP assertion errors to Exceptions
185
+ *
186
+ * @var boolean
187
+ */
188
+ protected $convertAssertionErrorsToExceptions = true;
189
+
190
+ /**
191
+ * Flag whether to throw PHP assertion errors that have been converted to Exceptions
192
+ *
193
+ * @var boolean
194
+ */
195
+ protected $throwAssertionExceptions = false;
196
+
197
+ /**
198
+ * Wildfire protocol message index
199
+ *
200
+ * @var int
201
+ */
202
+ protected $messageIndex = 1;
203
+
204
+ /**
205
+ * Options for the library
206
+ *
207
+ * @var array
208
+ */
209
+ protected $options = array('maxDepth' => 10,
210
+ 'maxObjectDepth' => 5,
211
+ 'maxArrayDepth' => 5,
212
+ 'useNativeJsonEncode' => true,
213
+ 'includeLineNumbers' => true);
214
+
215
+ /**
216
+ * Filters used to exclude object members when encoding
217
+ *
218
+ * @var array
219
+ */
220
+ protected $objectFilters = array(
221
+ 'firephp' => array('objectStack', 'instance', 'json_objectStack'),
222
+ 'firephp_test_class' => array('objectStack', 'instance', 'json_objectStack')
223
+ );
224
+
225
+ /**
226
+ * A stack of objects used to detect recursion during object encoding
227
+ *
228
+ * @var object
229
+ */
230
+ protected $objectStack = array();
231
+
232
+ /**
233
+ * Flag to enable/disable logging
234
+ *
235
+ * @var boolean
236
+ */
237
+ protected $enabled = true;
238
+
239
+ /**
240
+ * The insight console to log to if applicable
241
+ *
242
+ * @var object
243
+ */
244
+ protected $logToInsightConsole = null;
245
+
246
+ /**
247
+ * When the object gets serialized only include specific object members.
248
+ *
249
+ * @return array
250
+ */
251
+ public function __sleep()
252
+ {
253
+ return array('options','objectFilters','enabled');
254
+ }
255
+
256
+ /**
257
+ * Gets singleton instance of FirePHP
258
+ *
259
+ * @param boolean $AutoCreate
260
+ * @return FirePHP
261
+ */
262
+ public static function getInstance($AutoCreate = false)
263
+ {
264
+ if ($AutoCreate===true && !self::$instance) {
265
+ self::init();
266
+ }
267
+ return self::$instance;
268
+ }
269
+
270
+ /**
271
+ * Creates FirePHP object and stores it for singleton access
272
+ *
273
+ * @return FirePHP
274
+ */
275
+ public static function init()
276
+ {
277
+ return self::setInstance(new self());
278
+ }
279
+
280
+ /**
281
+ * Set the instance of the FirePHP singleton
282
+ *
283
+ * @param FirePHP $instance The FirePHP object instance
284
+ * @return FirePHP
285
+ */
286
+ public static function setInstance($instance)
287
+ {
288
+ return self::$instance = $instance;
289
+ }
290
+
291
+ /**
292
+ * Set an Insight console to direct all logging calls to
293
+ *
294
+ * @param object $console The console object to log to
295
+ * @return void
296
+ */
297
+ public function setLogToInsightConsole($console)
298
+ {
299
+ if(is_string($console)) {
300
+ if(get_class($this)!='FirePHP_Insight' && !is_subclass_of($this, 'FirePHP_Insight')) {
301
+ throw new Exception('FirePHP instance not an instance or subclass of FirePHP_Insight!');
302
+ }
303
+ $this->logToInsightConsole = $this->to('request')->console($console);
304
+ } else {
305
+ $this->logToInsightConsole = $console;
306
+ }
307
+ }
308
+
309
+ /**
310
+ * Enable and disable logging to Firebug
311
+ *
312
+ * @param boolean $Enabled TRUE to enable, FALSE to disable
313
+ * @return void
314
+ */
315
+ public function setEnabled($Enabled)
316
+ {
317
+ $this->enabled = $Enabled;
318
+ }
319
+
320
+ /**
321
+ * Check if logging is enabled
322
+ *
323
+ * @return boolean TRUE if enabled
324
+ */
325
+ public function getEnabled()
326
+ {
327
+ return $this->enabled;
328
+ }
329
+
330
+ /**
331
+ * Specify a filter to be used when encoding an object
332
+ *
333
+ * Filters are used to exclude object members.
334
+ *
335
+ * @param string $Class The class name of the object
336
+ * @param array $Filter An array of members to exclude
337
+ * @return void
338
+ */
339
+ public function setObjectFilter($Class, $Filter)
340
+ {
341
+ $this->objectFilters[strtolower($Class)] = $Filter;
342
+ }
343
+
344
+ /**
345
+ * Set some options for the library
346
+ *
347
+ * Options:
348
+ * - maxDepth: The maximum depth to traverse (default: 10)
349
+ * - maxObjectDepth: The maximum depth to traverse objects (default: 5)
350
+ * - maxArrayDepth: The maximum depth to traverse arrays (default: 5)
351
+ * - useNativeJsonEncode: If true will use json_encode() (default: true)
352
+ * - includeLineNumbers: If true will include line numbers and filenames (default: true)
353
+ *
354
+ * @param array $Options The options to be set
355
+ * @return void
356
+ */
357
+ public function setOptions($Options)
358
+ {
359
+ $this->options = array_merge($this->options,$Options);
360
+ }
361
+
362
+ /**
363
+ * Get options from the library
364
+ *
365
+ * @return array The currently set options
366
+ */
367
+ public function getOptions()
368
+ {
369
+ return $this->options;
370
+ }
371
+
372
+ /**
373
+ * Set an option for the library
374
+ *
375
+ * @param string $Name
376
+ * @param mixed $Value
377
+ * @throws Exception
378
+ * @return void
379
+ */
380
+ public function setOption($Name, $Value)
381
+ {
382
+ if (!isset($this->options[$Name])) {
383
+ throw $this->newException('Unknown option: ' . $Name);
384
+ }
385
+ $this->options[$Name] = $Value;
386
+ }
387
+
388
+ /**
389
+ * Get an option from the library
390
+ *
391
+ * @param string $Name
392
+ * @throws Exception
393
+ * @return mixed
394
+ */
395
+ public function getOption($Name)
396
+ {
397
+ if (!isset($this->options[$Name])) {
398
+ throw $this->newException('Unknown option: ' . $Name);
399
+ }
400
+ return $this->options[$Name];
401
+ }
402
+
403
+ /**
404
+ * Register FirePHP as your error handler
405
+ *
406
+ * Will throw exceptions for each php error.
407
+ *
408
+ * @return mixed Returns a string containing the previously defined error handler (if any)
409
+ */
410
+ public function registerErrorHandler($throwErrorExceptions = false)
411
+ {
412
+ //NOTE: The following errors will not be caught by this error handler:
413
+ // E_ERROR, E_PARSE, E_CORE_ERROR,
414
+ // E_CORE_WARNING, E_COMPILE_ERROR,
415
+ // E_COMPILE_WARNING, E_STRICT
416
+
417
+ $this->throwErrorExceptions = $throwErrorExceptions;
418
+
419
+ return set_error_handler(array($this,'errorHandler'));
420
+ }
421
+
422
+ /**
423
+ * FirePHP's error handler
424
+ *
425
+ * Throws exception for each php error that will occur.
426
+ *
427
+ * @param int $errno
428
+ * @param string $errstr
429
+ * @param string $errfile
430
+ * @param int $errline
431
+ * @param array $errcontext
432
+ */
433
+ public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
434
+ {
435
+ // Don't throw exception if error reporting is switched off
436
+ if (error_reporting() == 0) {
437
+ return;
438
+ }
439
+ // Only throw exceptions for errors we are asking for
440
+ if (error_reporting() & $errno) {
441
+
442
+ $exception = new ErrorException($errstr, 0, $errno, $errfile, $errline);
443
+ if ($this->throwErrorExceptions) {
444
+ throw $exception;
445
+ } else {
446
+ $this->fb($exception);
447
+ }
448
+ }
449
+ }
450
+
451
+ /**
452
+ * Register FirePHP as your exception handler
453
+ *
454
+ * @return mixed Returns the name of the previously defined exception handler,
455
+ * or NULL on error.
456
+ * If no previous handler was defined, NULL is also returned.
457
+ */
458
+ public function registerExceptionHandler()
459
+ {
460
+ return set_exception_handler(array($this,'exceptionHandler'));
461
+ }
462
+
463
+ /**
464
+ * FirePHP's exception handler
465
+ *
466
+ * Logs all exceptions to your firebug console and then stops the script.
467
+ *
468
+ * @param Exception $Exception
469
+ * @throws Exception
470
+ */
471
+ function exceptionHandler($Exception)
472
+ {
473
+
474
+ $this->inExceptionHandler = true;
475
+
476
+ header('HTTP/1.1 500 Internal Server Error');
477
+
478
+ try {
479
+ $this->fb($Exception);
480
+ } catch (Exception $e) {
481
+ echo 'We had an exception: ' . $e;
482
+ }
483
+ $this->inExceptionHandler = false;
484
+ }
485
+
486
+ /**
487
+ * Register FirePHP driver as your assert callback
488
+ *
489
+ * @param boolean $convertAssertionErrorsToExceptions
490
+ * @param boolean $throwAssertionExceptions
491
+ * @return mixed Returns the original setting or FALSE on errors
492
+ */
493
+ public function registerAssertionHandler($convertAssertionErrorsToExceptions = true, $throwAssertionExceptions = false)
494
+ {
495
+ $this->convertAssertionErrorsToExceptions = $convertAssertionErrorsToExceptions;
496
+ $this->throwAssertionExceptions = $throwAssertionExceptions;
497
+
498
+ if ($throwAssertionExceptions && !$convertAssertionErrorsToExceptions) {
499
+ throw $this->newException('Cannot throw assertion exceptions as assertion errors are not being converted to exceptions!');
500
+ }
501
+
502
+ return assert_options(ASSERT_CALLBACK, array($this, 'assertionHandler'));
503
+ }
504
+
505
+ /**
506
+ * FirePHP's assertion handler
507
+ *
508
+ * Logs all assertions to your firebug console and then stops the script.
509
+ *
510
+ * @param string $file File source of assertion
511
+ * @param int $line Line source of assertion
512
+ * @param mixed $code Assertion code
513
+ */
514
+ public function assertionHandler($file, $line, $code)
515
+ {
516
+ if ($this->convertAssertionErrorsToExceptions) {
517
+
518
+ $exception = new ErrorException('Assertion Failed - Code[ '.$code.' ]', 0, null, $file, $line);
519
+
520
+ if ($this->throwAssertionExceptions) {
521
+ throw $exception;
522
+ } else {
523
+ $this->fb($exception);
524
+ }
525
+
526
+ } else {
527
+ $this->fb($code, 'Assertion Failed', FirePHP::ERROR, array('File'=>$file,'Line'=>$line));
528
+ }
529
+ }
530
+
531
+ /**
532
+ * Start a group for following messages.
533
+ *
534
+ * Options:
535
+ * Collapsed: [true|false]
536
+ * Color: [#RRGGBB|ColorName]
537
+ *
538
+ * @param string $Name
539
+ * @param array $Options OPTIONAL Instructions on how to log the group
540
+ * @return true
541
+ * @throws Exception
542
+ */
543
+ public function group($Name, $Options = null)
544
+ {
545
+
546
+ if (!$Name) {
547
+ throw $this->newException('You must specify a label for the group!');
548
+ }
549
+
550
+ if ($Options) {
551
+ if (!is_array($Options)) {
552
+ throw $this->newException('Options must be defined as an array!');
553
+ }
554
+ if (array_key_exists('Collapsed', $Options)) {
555
+ $Options['Collapsed'] = ($Options['Collapsed'])?'true':'false';
556
+ }
557
+ }
558
+
559
+ return $this->fb(null, $Name, FirePHP::GROUP_START, $Options);
560
+ }
561
+
562
+ /**
563
+ * Ends a group you have started before
564
+ *
565
+ * @return true
566
+ * @throws Exception
567
+ */
568
+ public function groupEnd()
569
+ {
570
+ return $this->fb(null, null, FirePHP::GROUP_END);
571
+ }
572
+
573
+ /**
574
+ * Log object with label to firebug console
575
+ *
576
+ * @see FirePHP::LOG
577
+ * @param mixes $Object
578
+ * @param string $Label
579
+ * @return true
580
+ * @throws Exception
581
+ */
582
+ public function log($Object, $Label = null, $Options = array())
583
+ {
584
+ return $this->fb($Object, $Label, FirePHP::LOG, $Options);
585
+ }
586
+
587
+ /**
588
+ * Log object with label to firebug console
589
+ *
590
+ * @see FirePHP::INFO
591
+ * @param mixes $Object
592
+ * @param string $Label
593
+ * @return true
594
+ * @throws Exception
595
+ */
596
+ public function info($Object, $Label = null, $Options = array())
597
+ {
598
+ return $this->fb($Object, $Label, FirePHP::INFO, $Options);
599
+ }
600
+
601
+ /**
602
+ * Log object with label to firebug console
603
+ *
604
+ * @see FirePHP::WARN
605
+ * @param mixes $Object
606
+ * @param string $Label
607
+ * @return true
608
+ * @throws Exception
609
+ */
610
+ public function warn($Object, $Label = null, $Options = array())
611
+ {
612
+ return $this->fb($Object, $Label, FirePHP::WARN, $Options);
613
+ }
614
+
615
+ /**
616
+ * Log object with label to firebug console
617
+ *
618
+ * @see FirePHP::ERROR
619
+ * @param mixes $Object
620
+ * @param string $Label
621
+ * @return true
622
+ * @throws Exception
623
+ */
624
+ public function error($Object, $Label = null, $Options = array())
625
+ {
626
+ return $this->fb($Object, $Label, FirePHP::ERROR, $Options);
627
+ }
628
+
629
+ /**
630
+ * Dumps key and variable to firebug server panel
631
+ *
632
+ * @see FirePHP::DUMP
633
+ * @param string $Key
634
+ * @param mixed $Variable
635
+ * @return true
636
+ * @throws Exception
637
+ */
638
+ public function dump($Key, $Variable, $Options = array())
639
+ {
640
+ if (!is_string($Key)) {
641
+ throw $this->newException('Key passed to dump() is not a string');
642
+ }
643
+ if (strlen($Key)>100) {
644
+ throw $this->newException('Key passed to dump() is longer than 100 characters');
645
+ }
646
+ if (!preg_match_all('/^[a-zA-Z0-9-_\.:]*$/', $Key, $m)) {
647
+ throw $this->newException('Key passed to dump() contains invalid characters [a-zA-Z0-9-_\.:]');
648
+ }
649
+ return $this->fb($Variable, $Key, FirePHP::DUMP, $Options);
650
+ }
651
+
652
+ /**
653
+ * Log a trace in the firebug console
654
+ *
655
+ * @see FirePHP::TRACE
656
+ * @param string $Label
657
+ * @return true
658
+ * @throws Exception
659
+ */
660
+ public function trace($Label)
661
+ {
662
+ return $this->fb($Label, FirePHP::TRACE);
663
+ }
664
+
665
+ /**
666
+ * Log a table in the firebug console
667
+ *
668
+ * @see FirePHP::TABLE
669
+ * @param string $Label
670
+ * @param string $Table
671
+ * @return true
672
+ * @throws Exception
673
+ */
674
+ public function table($Label, $Table, $Options = array())
675
+ {
676
+ return $this->fb($Table, $Label, FirePHP::TABLE, $Options);
677
+ }
678
+
679
+ /**
680
+ * Insight API wrapper
681
+ *
682
+ * @see Insight_Helper::to()
683
+ */
684
+ public static function to()
685
+ {
686
+ $instance = self::getInstance();
687
+ if (!method_exists($instance, "_to")) {
688
+ throw new Exception("FirePHP::to() implementation not loaded");
689
+ }
690
+ $args = func_get_args();
691
+ return call_user_func_array(array($instance, '_to'), $args);
692
+ }
693
+
694
+ /**
695
+ * Insight API wrapper
696
+ *
697
+ * @see Insight_Helper::plugin()
698
+ */
699
+ public static function plugin()
700
+ {
701
+ $instance = self::getInstance();
702
+ if (!method_exists($instance, "_plugin")) {
703
+ throw new Exception("FirePHP::plugin() implementation not loaded");
704
+ }
705
+ $args = func_get_args();
706
+ return call_user_func_array(array($instance, '_plugin'), $args);
707
+ }
708
+
709
+ /**
710
+ * Check if FirePHP is installed on client
711
+ *
712
+ * @return boolean
713
+ */
714
+ public function detectClientExtension()
715
+ {
716
+ // Check if FirePHP is installed on client via User-Agent header
717
+ if (@preg_match_all('/\sFirePHP\/([\.\d]*)\s?/si',$this->getUserAgent(),$m) &&
718
+ version_compare($m[1][0],'0.0.6','>=')) {
719
+ return true;
720
+ } else
721
+ // Check if FirePHP is installed on client via X-FirePHP-Version header
722
+ if (@preg_match_all('/^([\.\d]*)$/si',$this->getRequestHeader("X-FirePHP-Version"),$m) &&
723
+ version_compare($m[1][0],'0.0.6','>=')) {
724
+ return true;
725
+ }
726
+ return false;
727
+ }
728
+
729
+ /**
730
+ * Log varible to Firebug
731
+ *
732
+ * @see http://www.firephp.org/Wiki/Reference/Fb
733
+ * @param mixed $Object The variable to be logged
734
+ * @return true Return TRUE if message was added to headers, FALSE otherwise
735
+ * @throws Exception
736
+ */
737
+ public function fb($Object)
738
+ {
739
+ if($this instanceof FirePHP_Insight && method_exists($this, '_logUpgradeClientMessage')) {
740
+ if(!FirePHP_Insight::$upgradeClientMessageLogged) { // avoid infinite recursion as _logUpgradeClientMessage() logs a message
741
+ $this->_logUpgradeClientMessage();
742
+ }
743
+ }
744
+
745
+ static $insightGroupStack = array();
746
+
747
+ if (!$this->getEnabled()) {
748
+ return false;
749
+ }
750
+
751
+ if ($this->headersSent($filename, $linenum)) {
752
+ // If we are logging from within the exception handler we cannot throw another exception
753
+ if ($this->inExceptionHandler) {
754
+ // Simply echo the error out to the page
755
+ echo '<div style="border: 2px solid red; font-family: Arial; font-size: 12px; background-color: lightgray; padding: 5px;"><span style="color: red; font-weight: bold;">FirePHP ERROR:</span> Headers already sent in <b>'.$filename.'</b> on line <b>'.$linenum.'</b>. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.</div>';
756
+ } else {
757
+ throw $this->newException('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.');
758
+ }
759
+ }
760
+
761
+ $Type = null;
762
+ $Label = null;
763
+ $Options = array();
764
+
765
+ if (func_num_args()==1) {
766
+ } else
767
+ if (func_num_args()==2) {
768
+ switch(func_get_arg(1)) {
769
+ case self::LOG:
770
+ case self::INFO:
771
+ case self::WARN:
772
+ case self::ERROR:
773
+ case self::DUMP:
774
+ case self::TRACE:
775
+ case self::EXCEPTION:
776
+ case self::TABLE:
777
+ case self::GROUP_START:
778
+ case self::GROUP_END:
779
+ $Type = func_get_arg(1);
780
+ break;
781
+ default:
782
+ $Label = func_get_arg(1);
783
+ break;
784
+ }
785
+ } else
786
+ if (func_num_args()==3) {
787
+ $Type = func_get_arg(2);
788
+ $Label = func_get_arg(1);
789
+ } else
790
+ if (func_num_args()==4) {
791
+ $Type = func_get_arg(2);
792
+ $Label = func_get_arg(1);
793
+ $Options = func_get_arg(3);
794
+ } else {
795
+ throw $this->newException('Wrong number of arguments to fb() function!');
796
+ }
797
+
798
+ if($this->logToInsightConsole!==null && (get_class($this)=='FirePHP_Insight' || is_subclass_of($this, 'FirePHP_Insight'))) {
799
+ $msg = $this->logToInsightConsole;
800
+ if ($Object instanceof Exception) {
801
+ $Type = self::EXCEPTION;
802
+ }
803
+ if($Label && $Type!=self::TABLE && $Type!=self::GROUP_START) {
804
+ $msg = $msg->label($Label);
805
+ }
806
+ switch($Type) {
807
+ case self::DUMP:
808
+ case self::LOG:
809
+ return $msg->log($Object);
810
+ case self::INFO:
811
+ return $msg->info($Object);
812
+ case self::WARN:
813
+ return $msg->warn($Object);
814
+ case self::ERROR:
815
+ return $msg->error($Object);
816
+ case self::TRACE:
817
+ return $msg->trace($Object);
818
+ case self::EXCEPTION:
819
+ return $this->plugin('engine')->handleException($Object, $msg);
820
+ case self::TABLE:
821
+ if (isset($Object[0]) && !is_string($Object[0]) && $Label) {
822
+ $Object = array($Label, $Object);
823
+ }
824
+ return $msg->table($Object[0], array_slice($Object[1],1), $Object[1][0]);
825
+ case self::GROUP_START:
826
+ $insightGroupStack[] = $msg->group(md5($Label))->open();
827
+ return $msg->log($Label);
828
+ case self::GROUP_END:
829
+ if(count($insightGroupStack)==0) {
830
+ throw new Error('Too many groupEnd() as opposed to group() calls!');
831
+ }
832
+ $group = array_pop($insightGroupStack);
833
+ return $group->close();
834
+ default:
835
+ return $msg->log($Object);
836
+ }
837
+ }
838
+
839
+ if (!$this->detectClientExtension()) {
840
+ return false;
841
+ }
842
+
843
+ $meta = array();
844
+ $skipFinalObjectEncode = false;
845
+
846
+ if ($Object instanceof Exception) {
847
+
848
+ $meta['file'] = $this->_escapeTraceFile($Object->getFile());
849
+ $meta['line'] = $Object->getLine();
850
+
851
+ $trace = $Object->getTrace();
852
+ if ($Object instanceof ErrorException
853
+ && isset($trace[0]['function'])
854
+ && $trace[0]['function']=='errorHandler'
855
+ && isset($trace[0]['class'])
856
+ && $trace[0]['class']=='FirePHP') {
857
+
858
+ $severity = false;
859
+ switch($Object->getSeverity()) {
860
+ case E_WARNING: $severity = 'E_WARNING'; break;
861
+ case E_NOTICE: $severity = 'E_NOTICE'; break;
862
+ case E_USER_ERROR: $severity = 'E_USER_ERROR'; break;
863
+ case E_USER_WARNING: $severity = 'E_USER_WARNING'; break;
864
+ case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break;
865
+ case E_STRICT: $severity = 'E_STRICT'; break;
866
+ case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break;
867
+ case E_DEPRECATED: $severity = 'E_DEPRECATED'; break;
868
+ case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break;
869
+ }
870
+
871
+ $Object = array('Class'=>get_class($Object),
872
+ 'Message'=>$severity.': '.$Object->getMessage(),
873
+ 'File'=>$this->_escapeTraceFile($Object->getFile()),
874
+ 'Line'=>$Object->getLine(),
875
+ 'Type'=>'trigger',
876
+ 'Trace'=>$this->_escapeTrace(array_splice($trace,2)));
877
+ $skipFinalObjectEncode = true;
878
+ } else {
879
+ $Object = array('Class'=>get_class($Object),
880
+ 'Message'=>$Object->getMessage(),
881
+ 'File'=>$this->_escapeTraceFile($Object->getFile()),
882
+ 'Line'=>$Object->getLine(),
883
+ 'Type'=>'throw',
884
+ 'Trace'=>$this->_escapeTrace($trace));
885
+ $skipFinalObjectEncode = true;
886
+ }
887
+ $Type = self::EXCEPTION;
888
+
889
+ } else
890
+ if ($Type==self::TRACE) {
891
+
892
+ $trace = debug_backtrace();
893
+ if (!$trace) return false;
894
+ for( $i=0 ; $i<sizeof($trace) ; $i++ ) {
895
+
896
+ if (isset($trace[$i]['class'])
897
+ && isset($trace[$i]['file'])
898
+ && ($trace[$i]['class']=='FirePHP'
899
+ || $trace[$i]['class']=='FB')
900
+ && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
901
+ || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
902
+ /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
903
+ } else
904
+ if (isset($trace[$i]['class'])
905
+ && isset($trace[$i+1]['file'])
906
+ && $trace[$i]['class']=='FirePHP'
907
+ && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
908
+ /* Skip fb() */
909
+ } else
910
+ if ($trace[$i]['function']=='fb'
911
+ || $trace[$i]['function']=='trace'
912
+ || $trace[$i]['function']=='send') {
913
+
914
+ $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'',
915
+ 'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'',
916
+ 'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'',
917
+ 'Message'=>$trace[$i]['args'][0],
918
+ 'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'',
919
+ 'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'',
920
+ 'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'',
921
+ 'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1)));
922
+
923
+ $skipFinalObjectEncode = true;
924
+ $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
925
+ $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
926
+ break;
927
+ }
928
+ }
929
+
930
+ } else
931
+ if ($Type==self::TABLE) {
932
+
933
+ if (isset($Object[0]) && is_string($Object[0])) {
934
+ $Object[1] = $this->encodeTable($Object[1]);
935
+ } else {
936
+ $Object = $this->encodeTable($Object);
937
+ }
938
+
939
+ $skipFinalObjectEncode = true;
940
+
941
+ } else
942
+ if ($Type==self::GROUP_START) {
943
+
944
+ if (!$Label) {
945
+ throw $this->newException('You must specify a label for the group!');
946
+ }
947
+
948
+ } else {
949
+ if ($Type===null) {
950
+ $Type = self::LOG;
951
+ }
952
+ }
953
+
954
+ if ($this->options['includeLineNumbers']) {
955
+ if (!isset($meta['file']) || !isset($meta['line'])) {
956
+
957
+ $trace = debug_backtrace();
958
+ for( $i=0 ; $trace && $i<sizeof($trace) ; $i++ ) {
959
+
960
+ if (isset($trace[$i]['class'])
961
+ && isset($trace[$i]['file'])
962
+ && ($trace[$i]['class']=='FirePHP'
963
+ || $trace[$i]['class']=='FB')
964
+ && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
965
+ || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
966
+ /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
967
+ } else
968
+ if (isset($trace[$i]['class'])
969
+ && isset($trace[$i+1]['file'])
970
+ && $trace[$i]['class']=='FirePHP'
971
+ && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
972
+ /* Skip fb() */
973
+ } else
974
+ if (isset($trace[$i]['file'])
975
+ && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') {
976
+ /* Skip FB::fb() */
977
+ } else {
978
+ $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
979
+ $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
980
+ break;
981
+ }
982
+ }
983
+ }
984
+ } else {
985
+ unset($meta['file']);
986
+ unset($meta['line']);
987
+ }
988
+
989
+ $this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
990
+ $this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION);
991
+
992
+ $structure_index = 1;
993
+ if ($Type==self::DUMP) {
994
+ $structure_index = 2;
995
+ $this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');
996
+ } else {
997
+ $this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
998
+ }
999
+
1000
+ if ($Type==self::DUMP) {
1001
+ $msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}';
1002
+ } else {
1003
+ $msg_meta = $Options;
1004
+ $msg_meta['Type'] = $Type;
1005
+ if ($Label!==null) {
1006
+ $msg_meta['Label'] = $Label;
1007
+ }
1008
+ if (isset($meta['file']) && !isset($msg_meta['File'])) {
1009
+ $msg_meta['File'] = $meta['file'];
1010
+ }
1011
+ if (isset($meta['line']) && !isset($msg_meta['Line'])) {
1012
+ $msg_meta['Line'] = $meta['line'];
1013
+ }
1014
+ $msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']';
1015
+ }
1016
+
1017
+ $parts = explode("\n",chunk_split($msg, 5000, "\n"));
1018
+
1019
+ for( $i=0 ; $i<count($parts) ; $i++) {
1020
+
1021
+ $part = $parts[$i];
1022
+ if ($part) {
1023
+
1024
+ if (count($parts)>2) {
1025
+ // Message needs to be split into multiple parts
1026
+ $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
1027
+ (($i==0)?strlen($msg):'')
1028
+ . '|' . $part . '|'
1029
+ . (($i<count($parts)-2)?'\\':''));
1030
+ } else {
1031
+ $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
1032
+ strlen($part) . '|' . $part . '|');
1033
+ }
1034
+
1035
+ $this->messageIndex++;
1036
+
1037
+ if ($this->messageIndex > 99999) {
1038
+ throw $this->newException('Maximum number (99,999) of messages reached!');
1039
+ }
1040
+ }
1041
+ }
1042
+
1043
+ $this->setHeader('X-Wf-1-Index',$this->messageIndex-1);
1044
+
1045
+ return true;
1046
+ }
1047
+
1048
+ /**
1049
+ * Standardizes path for windows systems.
1050
+ *
1051
+ * @param string $Path
1052
+ * @return string
1053
+ */
1054
+ protected function _standardizePath($Path)
1055
+ {
1056
+ return preg_replace('/\\\\+/','/',$Path);
1057
+ }
1058
+
1059
+ /**
1060
+ * Escape trace path for windows systems
1061
+ *
1062
+ * @param array $Trace
1063
+ * @return array
1064
+ */
1065
+ protected function _escapeTrace($Trace)
1066
+ {
1067
+ if (!$Trace) return $Trace;
1068
+ for( $i=0 ; $i<sizeof($Trace) ; $i++ ) {
1069
+ if (isset($Trace[$i]['file'])) {
1070
+ $Trace[$i]['file'] = $this->_escapeTraceFile($Trace[$i]['file']);
1071
+ }
1072
+ if (isset($Trace[$i]['args'])) {
1073
+ $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']);
1074
+ }
1075
+ }
1076
+ return $Trace;
1077
+ }
1078
+
1079
+ /**
1080
+ * Escape file information of trace for windows systems
1081
+ *
1082
+ * @param string $File
1083
+ * @return string
1084
+ */
1085
+ protected function _escapeTraceFile($File)
1086
+ {
1087
+ /* Check if we have a windows filepath */
1088
+ if (strpos($File,'\\')) {
1089
+ /* First strip down to single \ */
1090
+
1091
+ $file = preg_replace('/\\\\+/','\\',$File);
1092
+
1093
+ return $file;
1094
+ }
1095
+ return $File;
1096
+ }
1097
+
1098
+ /**
1099
+ * Check if headers have already been sent
1100
+ *
1101
+ * @param string $Filename
1102
+ * @param integer $Linenum
1103
+ */
1104
+ protected function headersSent(&$Filename, &$Linenum)
1105
+ {
1106
+ return headers_sent($Filename, $Linenum);
1107
+ }
1108
+
1109
+ /**
1110
+ * Send header
1111
+ *
1112
+ * @param string $Name
1113
+ * @param string $Value
1114
+ */
1115
+ protected function setHeader($Name, $Value)
1116
+ {
1117
+ return header($Name.': '.$Value);
1118
+ }
1119
+
1120
+ /**
1121
+ * Get user agent
1122
+ *
1123
+ * @return string|false
1124
+ */
1125
+ protected function getUserAgent()
1126
+ {
1127
+ if (!isset($_SERVER['HTTP_USER_AGENT'])) return false;
1128
+ return $_SERVER['HTTP_USER_AGENT'];
1129
+ }
1130
+
1131
+ /**
1132
+ * Get all request headers
1133
+ *
1134
+ * @return array
1135
+ */
1136
+ public static function getAllRequestHeaders() {
1137
+ static $_cached_headers = false;
1138
+ if($_cached_headers!==false) {
1139
+ return $_cached_headers;
1140
+ }
1141
+ $headers = array();
1142
+ if(function_exists('getallheaders')) {
1143
+ foreach( getallheaders() as $name => $value ) {
1144
+ $headers[strtolower($name)] = $value;
1145
+ }
1146
+ } else {
1147
+ foreach($_SERVER as $name => $value) {
1148
+ if(substr($name, 0, 5) == 'HTTP_') {
1149
+ $headers[strtolower(str_replace(' ', '-', str_replace('_', ' ', substr($name, 5))))] = $value;
1150
+ }
1151
+ }
1152
+ }
1153
+ return $_cached_headers = $headers;
1154
+ }
1155
+
1156
+ /**
1157
+ * Get a request header
1158
+ *
1159
+ * @return string|false
1160
+ */
1161
+ protected function getRequestHeader($Name)
1162
+ {
1163
+ $headers = self::getAllRequestHeaders();
1164
+ if (isset($headers[strtolower($Name)])) {
1165
+ return $headers[strtolower($Name)];
1166
+ }
1167
+ return false;
1168
+ }
1169
+
1170
+ /**
1171
+ * Returns a new exception
1172
+ *
1173
+ * @param string $Message
1174
+ * @return Exception
1175
+ */
1176
+ protected function newException($Message)
1177
+ {
1178
+ return new Exception($Message);
1179
+ }
1180
+
1181
+ /**
1182
+ * Encode an object into a JSON string
1183
+ *
1184
+ * Uses PHP's jeson_encode() if available
1185
+ *
1186
+ * @param object $Object The object to be encoded
1187
+ * @return string The JSON string
1188
+ */
1189
+ public function jsonEncode($Object, $skipObjectEncode = false)
1190
+ {
1191
+ if (!$skipObjectEncode) {
1192
+ $Object = $this->encodeObject($Object);
1193
+ }
1194
+
1195
+ if (function_exists('json_encode')
1196
+ && $this->options['useNativeJsonEncode']!=false) {
1197
+
1198
+ return json_encode($Object);
1199
+ } else {
1200
+ return $this->json_encode($Object);
1201
+ }
1202
+ }
1203
+
1204
+ /**
1205
+ * Encodes a table by encoding each row and column with encodeObject()
1206
+ *
1207
+ * @param array $Table The table to be encoded
1208
+ * @return array
1209
+ */
1210
+ protected function encodeTable($Table)
1211
+ {
1212
+
1213
+ if (!$Table) return $Table;
1214
+
1215
+ $new_table = array();
1216
+ foreach($Table as $row) {
1217
+
1218
+ if (is_array($row)) {
1219
+ $new_row = array();
1220
+
1221
+ foreach($row as $item) {
1222
+ $new_row[] = $this->encodeObject($item);
1223
+ }
1224
+
1225
+ $new_table[] = $new_row;
1226
+ }
1227
+ }
1228
+
1229
+ return $new_table;
1230
+ }
1231
+
1232
+ /**
1233
+ * Encodes an object including members with
1234
+ * protected and private visibility
1235
+ *
1236
+ * @param Object $Object The object to be encoded
1237
+ * @param int $Depth The current traversal depth
1238
+ * @return array All members of the object
1239
+ */
1240
+ protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1, $MaxDepth = 1)
1241
+ {
1242
+ if ($MaxDepth > $this->options['maxDepth']) {
1243
+ return '** Max Depth ('.$this->options['maxDepth'].') **';
1244
+ }
1245
+
1246
+ $return = array();
1247
+
1248
+ if (is_resource($Object)) {
1249
+
1250
+ return '** '.(string)$Object.' **';
1251
+
1252
+ } else
1253
+ if (is_object($Object)) {
1254
+
1255
+ if ($ObjectDepth > $this->options['maxObjectDepth']) {
1256
+ return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **';
1257
+ }
1258
+
1259
+ foreach ($this->objectStack as $refVal) {
1260
+ if ($refVal === $Object) {
1261
+ return '** Recursion ('.get_class($Object).') **';
1262
+ }
1263
+ }
1264
+ array_push($this->objectStack, $Object);
1265
+
1266
+ $return['__className'] = $class = get_class($Object);
1267
+ $class_lower = strtolower($class);
1268
+
1269
+ $reflectionClass = new ReflectionClass($class);
1270
+ $properties = array();
1271
+ foreach( $reflectionClass->getProperties() as $property) {
1272
+ $properties[$property->getName()] = $property;
1273
+ }
1274
+
1275
+ $members = (array)$Object;
1276
+
1277
+ foreach( $properties as $plain_name => $property ) {
1278
+
1279
+ $name = $raw_name = $plain_name;
1280
+ if ($property->isStatic()) {
1281
+ $name = 'static:'.$name;
1282
+ }
1283
+ if ($property->isPublic()) {
1284
+ $name = 'public:'.$name;
1285
+ } else
1286
+ if ($property->isPrivate()) {
1287
+ $name = 'private:'.$name;
1288
+ $raw_name = "\0".$class."\0".$raw_name;
1289
+ } else
1290
+ if ($property->isProtected()) {
1291
+ $name = 'protected:'.$name;
1292
+ $raw_name = "\0".'*'."\0".$raw_name;
1293
+ }
1294
+
1295
+ if (!(isset($this->objectFilters[$class_lower])
1296
+ && is_array($this->objectFilters[$class_lower])
1297
+ && in_array($plain_name,$this->objectFilters[$class_lower]))) {
1298
+
1299
+ if (array_key_exists($raw_name,$members)
1300
+ && !$property->isStatic()) {
1301
+
1302
+ $return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1, $MaxDepth + 1);
1303
+
1304
+ } else {
1305
+ if (method_exists($property,'setAccessible')) {
1306
+ $property->setAccessible(true);
1307
+ $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1, $MaxDepth + 1);
1308
+ } else
1309
+ if ($property->isPublic()) {
1310
+ $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1, $MaxDepth + 1);
1311
+ } else {
1312
+ $return[$name] = '** Need PHP 5.3 to get value **';
1313
+ }
1314
+ }
1315
+ } else {
1316
+ $return[$name] = '** Excluded by Filter **';
1317
+ }
1318
+ }
1319
+
1320
+ // Include all members that are not defined in the class
1321
+ // but exist in the object
1322
+ foreach( $members as $raw_name => $value ) {
1323
+
1324
+ $name = $raw_name;
1325
+
1326
+ if ($name{0} == "\0") {
1327
+ $parts = explode("\0", $name);
1328
+ $name = $parts[2];
1329
+ }
1330
+
1331
+ $plain_name = $name;
1332
+
1333
+ if (!isset($properties[$name])) {
1334
+ $name = 'undeclared:'.$name;
1335
+
1336
+ if (!(isset($this->objectFilters[$class_lower])
1337
+ && is_array($this->objectFilters[$class_lower])
1338
+ && in_array($plain_name,$this->objectFilters[$class_lower]))) {
1339
+
1340
+ $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1, $MaxDepth + 1);
1341
+ } else {
1342
+ $return[$name] = '** Excluded by Filter **';
1343
+ }
1344
+ }
1345
+ }
1346
+
1347
+ array_pop($this->objectStack);
1348
+
1349
+ } elseif (is_array($Object)) {
1350
+
1351
+ if ($ArrayDepth > $this->options['maxArrayDepth']) {
1352
+ return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **';
1353
+ }
1354
+
1355
+ foreach ($Object as $key => $val) {
1356
+
1357
+ // Encoding the $GLOBALS PHP array causes an infinite loop
1358
+ // if the recursion is not reset here as it contains
1359
+ // a reference to itself. This is the only way I have come up
1360
+ // with to stop infinite recursion in this case.
1361
+ if ($key=='GLOBALS'
1362
+ && is_array($val)
1363
+ && array_key_exists('GLOBALS',$val)) {
1364
+ $val['GLOBALS'] = '** Recursion (GLOBALS) **';
1365
+ }
1366
+
1367
+ $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1, $MaxDepth + 1);
1368
+ }
1369
+ } else {
1370
+ if (self::is_utf8($Object)) {
1371
+ return $Object;
1372
+ } else {
1373
+ return utf8_encode($Object);
1374
+ }
1375
+ }
1376
+ return $return;
1377
+ }
1378
+
1379
+ /**
1380
+ * Returns true if $string is valid UTF-8 and false otherwise.
1381
+ *
1382
+ * @param mixed $str String to be tested
1383
+ * @return boolean
1384
+ */
1385
+ protected static function is_utf8($str)
1386
+ {
1387
+ if(function_exists('mb_detect_encoding')) {
1388
+ return (mb_detect_encoding($str) == 'UTF-8');
1389
+ }
1390
+ $c=0; $b=0;
1391
+ $bits=0;
1392
+ $len=strlen($str);
1393
+ for($i=0; $i<$len; $i++){
1394
+ $c=ord($str[$i]);
1395
+ if ($c > 128){
1396
+ if (($c >= 254)) return false;
1397
+ elseif ($c >= 252) $bits=6;
1398
+ elseif ($c >= 248) $bits=5;
1399
+ elseif ($c >= 240) $bits=4;
1400
+ elseif ($c >= 224) $bits=3;
1401
+ elseif ($c >= 192) $bits=2;
1402
+ else return false;
1403
+ if (($i+$bits) > $len) return false;
1404
+ while($bits > 1){
1405
+ $i++;
1406
+ $b=ord($str[$i]);
1407
+ if ($b < 128 || $b > 191) return false;
1408
+ $bits--;
1409
+ }
1410
+ }
1411
+ }
1412
+ return true;
1413
+ }
1414
+
1415
+ /**
1416
+ * Converts to and from JSON format.
1417
+ *
1418
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
1419
+ * format. It is easy for humans to read and write. It is easy for machines
1420
+ * to parse and generate. It is based on a subset of the JavaScript
1421
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
1422
+ * This feature can also be found in Python. JSON is a text format that is
1423
+ * completely language independent but uses conventions that are familiar
1424
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
1425
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
1426
+ * ideal data-interchange language.
1427
+ *
1428
+ * This package provides a simple encoder and decoder for JSON notation. It
1429
+ * is intended for use with client-side Javascript applications that make
1430
+ * use of HTTPRequest to perform server communication functions - data can
1431
+ * be encoded into JSON notation for use in a client-side javascript, or
1432
+ * decoded from incoming Javascript requests. JSON format is native to
1433
+ * Javascript, and can be directly eval()'ed with no further parsing
1434
+ * overhead
1435
+ *
1436
+ * All strings should be in ASCII or UTF-8 format!
1437
+ *
1438
+ * LICENSE: Redistribution and use in source and binary forms, with or
1439
+ * without modification, are permitted provided that the following
1440
+ * conditions are met: Redistributions of source code must retain the
1441
+ * above copyright notice, this list of conditions and the following
1442
+ * disclaimer. Redistributions in binary form must reproduce the above
1443
+ * copyright notice, this list of conditions and the following disclaimer
1444
+ * in the documentation and/or other materials provided with the
1445
+ * distribution.
1446
+ *
1447
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1448
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1449
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
1450
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
1451
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
1452
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
1453
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1454
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
1455
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1456
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1457
+ * DAMAGE.
1458
+ *
1459
+ * @category
1460
+ * @package Services_JSON
1461
+ * @author Michal Migurski <mike-json@teczno.com>
1462
+ * @author Matt Knapp <mdknapp[at]gmail[dot]com>
1463
+ * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
1464
+ * @author Christoph Dorn <christoph@christophdorn.com>
1465
+ * @copyright 2005 Michal Migurski
1466
+ * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
1467
+ * @license http://www.opensource.org/licenses/bsd-license.php
1468
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
1469
+ */
1470
+
1471
+
1472
+ /**
1473
+ * Keep a list of objects as we descend into the array so we can detect recursion.
1474
+ */
1475
+ private $json_objectStack = array();
1476
+
1477
+
1478
+ /**
1479
+ * convert a string from one UTF-8 char to one UTF-16 char
1480
+ *
1481
+ * Normally should be handled by mb_convert_encoding, but
1482
+ * provides a slower PHP-only method for installations
1483
+ * that lack the multibye string extension.
1484
+ *
1485
+ * @param string $utf8 UTF-8 character
1486
+ * @return string UTF-16 character
1487
+ * @access private
1488
+ */
1489
+ private function json_utf82utf16($utf8)
1490
+ {
1491
+ // oh please oh please oh please oh please oh please
1492
+ if (function_exists('mb_convert_encoding')) {
1493
+ return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
1494
+ }
1495
+
1496
+ switch(strlen($utf8)) {
1497
+ case 1:
1498
+ // this case should never be reached, because we are in ASCII range
1499
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1500
+ return $utf8;
1501
+
1502
+ case 2:
1503
+ // return a UTF-16 character from a 2-byte UTF-8 char
1504
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1505
+ return chr(0x07 & (ord($utf8{0}) >> 2))
1506
+ . chr((0xC0 & (ord($utf8{0}) << 6))
1507
+ | (0x3F & ord($utf8{1})));
1508
+
1509
+ case 3:
1510
+ // return a UTF-16 character from a 3-byte UTF-8 char
1511
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1512
+ return chr((0xF0 & (ord($utf8{0}) << 4))
1513
+ | (0x0F & (ord($utf8{1}) >> 2)))
1514
+ . chr((0xC0 & (ord($utf8{1}) << 6))
1515
+ | (0x7F & ord($utf8{2})));
1516
+ }
1517
+
1518
+ // ignoring UTF-32 for now, sorry
1519
+ return '';
1520
+ }
1521
+
1522
+ /**
1523
+ * encodes an arbitrary variable into JSON format
1524
+ *
1525
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
1526
+ * see argument 1 to Services_JSON() above for array-parsing behavior.
1527
+ * if var is a strng, note that encode() always expects it
1528
+ * to be in ASCII or UTF-8 format!
1529
+ *
1530
+ * @return mixed JSON string representation of input var or an error if a problem occurs
1531
+ * @access public
1532
+ */
1533
+ private function json_encode($var)
1534
+ {
1535
+
1536
+ if (is_object($var)) {
1537
+ if (in_array($var,$this->json_objectStack)) {
1538
+ return '"** Recursion **"';
1539
+ }
1540
+ }
1541
+
1542
+ switch (gettype($var)) {
1543
+ case 'boolean':
1544
+ return $var ? 'true' : 'false';
1545
+
1546
+ case 'NULL':
1547
+ return 'null';
1548
+
1549
+ case 'integer':
1550
+ return (int) $var;
1551
+
1552
+ case 'double':
1553
+ case 'float':
1554
+ return (float) $var;
1555
+
1556
+ case 'string':
1557
+ // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
1558
+ $ascii = '';
1559
+ $strlen_var = strlen($var);
1560
+
1561
+ /*
1562
+ * Iterate over every character in the string,
1563
+ * escaping with a slash or encoding to UTF-8 where necessary
1564
+ */
1565
+ for ($c = 0; $c < $strlen_var; ++$c) {
1566
+
1567
+ $ord_var_c = ord($var{$c});
1568
+
1569
+ switch (true) {
1570
+ case $ord_var_c == 0x08:
1571
+ $ascii .= '\b';
1572
+ break;
1573
+ case $ord_var_c == 0x09:
1574
+ $ascii .= '\t';
1575
+ break;
1576
+ case $ord_var_c == 0x0A:
1577
+ $ascii .= '\n';
1578
+ break;
1579
+ case $ord_var_c == 0x0C:
1580
+ $ascii .= '\f';
1581
+ break;
1582
+ case $ord_var_c == 0x0D:
1583
+ $ascii .= '\r';
1584
+ break;
1585
+
1586
+ case $ord_var_c == 0x22:
1587
+ case $ord_var_c == 0x2F:
1588
+ case $ord_var_c == 0x5C:
1589
+ // double quote, slash, slosh
1590
+ $ascii .= '\\'.$var{$c};
1591
+ break;
1592
+
1593
+ case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
1594
+ // characters U-00000000 - U-0000007F (same as ASCII)
1595
+ $ascii .= $var{$c};
1596
+ break;
1597
+
1598
+ case (($ord_var_c & 0xE0) == 0xC0):
1599
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
1600
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1601
+ $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
1602
+ $c += 1;
1603
+ $utf16 = $this->json_utf82utf16($char);
1604
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1605
+ break;
1606
+
1607
+ case (($ord_var_c & 0xF0) == 0xE0):
1608
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
1609
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1610
+ $char = pack('C*', $ord_var_c,
1611
+ ord($var{$c + 1}),
1612
+ ord($var{$c + 2}));
1613
+ $c += 2;
1614
+ $utf16 = $this->json_utf82utf16($char);
1615
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1616
+ break;
1617
+
1618
+ case (($ord_var_c & 0xF8) == 0xF0):
1619
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
1620
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1621
+ $char = pack('C*', $ord_var_c,
1622
+ ord($var{$c + 1}),
1623
+ ord($var{$c + 2}),
1624
+ ord($var{$c + 3}));
1625
+ $c += 3;
1626
+ $utf16 = $this->json_utf82utf16($char);
1627
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1628
+ break;
1629
+
1630
+ case (($ord_var_c & 0xFC) == 0xF8):
1631
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
1632
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1633
+ $char = pack('C*', $ord_var_c,
1634
+ ord($var{$c + 1}),
1635
+ ord($var{$c + 2}),
1636
+ ord($var{$c + 3}),
1637
+ ord($var{$c + 4}));
1638
+ $c += 4;
1639
+ $utf16 = $this->json_utf82utf16($char);
1640
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1641
+ break;
1642
+
1643
+ case (($ord_var_c & 0xFE) == 0xFC):
1644
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
1645
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1646
+ $char = pack('C*', $ord_var_c,
1647
+ ord($var{$c + 1}),
1648
+ ord($var{$c + 2}),
1649
+ ord($var{$c + 3}),
1650
+ ord($var{$c + 4}),
1651
+ ord($var{$c + 5}));
1652
+ $c += 5;
1653
+ $utf16 = $this->json_utf82utf16($char);
1654
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1655
+ break;
1656
+ }
1657
+ }
1658
+
1659
+ return '"'.$ascii.'"';
1660
+
1661
+ case 'array':
1662
+ /*
1663
+ * As per JSON spec if any array key is not an integer
1664
+ * we must treat the the whole array as an object. We
1665
+ * also try to catch a sparsely populated associative
1666
+ * array with numeric keys here because some JS engines
1667
+ * will create an array with empty indexes up to
1668
+ * max_index which can cause memory issues and because
1669
+ * the keys, which may be relevant, will be remapped
1670
+ * otherwise.
1671
+ *
1672
+ * As per the ECMA and JSON specification an object may
1673
+ * have any string as a property. Unfortunately due to
1674
+ * a hole in the ECMA specification if the key is a
1675
+ * ECMA reserved word or starts with a digit the
1676
+ * parameter is only accessible using ECMAScript's
1677
+ * bracket notation.
1678
+ */
1679
+
1680
+ // treat as a JSON object
1681
+ if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
1682
+
1683
+ $this->json_objectStack[] = $var;
1684
+
1685
+ $properties = array_map(array($this, 'json_name_value'),
1686
+ array_keys($var),
1687
+ array_values($var));
1688
+
1689
+ array_pop($this->json_objectStack);
1690
+
1691
+ foreach($properties as $property) {
1692
+ if ($property instanceof Exception) {
1693
+ return $property;
1694
+ }
1695
+ }
1696
+
1697
+ return '{' . join(',', $properties) . '}';
1698
+ }
1699
+
1700
+ $this->json_objectStack[] = $var;
1701
+
1702
+ // treat it like a regular array
1703
+ $elements = array_map(array($this, 'json_encode'), $var);
1704
+
1705
+ array_pop($this->json_objectStack);
1706
+
1707
+ foreach($elements as $element) {
1708
+ if ($element instanceof Exception) {
1709
+ return $element;
1710
+ }
1711
+ }
1712
+
1713
+ return '[' . join(',', $elements) . ']';
1714
+
1715
+ case 'object':
1716
+ $vars = self::encodeObject($var);
1717
+
1718
+ $this->json_objectStack[] = $var;
1719
+
1720
+ $properties = array_map(array($this, 'json_name_value'),
1721
+ array_keys($vars),
1722
+ array_values($vars));
1723
+
1724
+ array_pop($this->json_objectStack);
1725
+
1726
+ foreach($properties as $property) {
1727
+ if ($property instanceof Exception) {
1728
+ return $property;
1729
+ }
1730
+ }
1731
+
1732
+ return '{' . join(',', $properties) . '}';
1733
+
1734
+ default:
1735
+ return null;
1736
+ }
1737
+ }
1738
+
1739
+ /**
1740
+ * array-walking function for use in generating JSON-formatted name-value pairs
1741
+ *
1742
+ * @param string $name name of key to use
1743
+ * @param mixed $value reference to an array element to be encoded
1744
+ *
1745
+ * @return string JSON-formatted name-value pair, like '"name":value'
1746
+ * @access private
1747
+ */
1748
+ private function json_name_value($name, $value)
1749
+ {
1750
+ // Encoding the $GLOBALS PHP array causes an infinite loop
1751
+ // if the recursion is not reset here as it contains
1752
+ // a reference to itself. This is the only way I have come up
1753
+ // with to stop infinite recursion in this case.
1754
+ if ($name=='GLOBALS'
1755
+ && is_array($value)
1756
+ && array_key_exists('GLOBALS',$value)) {
1757
+ $value['GLOBALS'] = '** Recursion **';
1758
+ }
1759
+
1760
+ $encoded_value = $this->json_encode($value);
1761
+
1762
+ if ($encoded_value instanceof Exception) {
1763
+ return $encoded_value;
1764
+ }
1765
+
1766
+ return $this->json_encode(strval($name)) . ':' . $encoded_value;
1767
+ }
1768
+
1769
+ /**
1770
+ * @deprecated
1771
+ */
1772
+ public function setProcessorUrl($URL)
1773
+ {
1774
+ trigger_error("The FirePHP::setProcessorUrl() method is no longer supported", E_USER_DEPRECATED);
1775
+ }
1776
+
1777
+ /**
1778
+ * @deprecated
1779
+ */
1780
+ public function setRendererUrl($URL)
1781
+ {
1782
+ trigger_error("The FirePHP::setRendererUrl() method is no longer supported", E_USER_DEPRECATED);
1783
+ }
1784
+ }
lib/Itm/FirePhp/FirePHP.class.php4 ADDED
@@ -0,0 +1,1332 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * *** BEGIN LICENSE BLOCK *****
4
+ *
5
+ * This file is part of FirePHP (http://www.firephp.org/).
6
+ *
7
+ * Software License Agreement (New BSD License)
8
+ *
9
+ * Copyright (c) 2006-2010, Christoph Dorn
10
+ * All rights reserved.
11
+ *
12
+ * Redistribution and use in source and binary forms, with or without modification,
13
+ * are permitted provided that the following conditions are met:
14
+ *
15
+ * * Redistributions of source code must retain the above copyright notice,
16
+ * this list of conditions and the following disclaimer.
17
+ *
18
+ * * Redistributions in binary form must reproduce the above copyright notice,
19
+ * this list of conditions and the following disclaimer in the documentation
20
+ * and/or other materials provided with the distribution.
21
+ *
22
+ * * Neither the name of Christoph Dorn nor the names of its
23
+ * contributors may be used to endorse or promote products derived from this
24
+ * software without specific prior written permission.
25
+ *
26
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
27
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
30
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
33
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+ *
37
+ * ***** END LICENSE BLOCK *****
38
+ *
39
+ * This verion of FirePHPCore is for use with PHP4. If you do not require PHP4
40
+ * compatibility, it is suggested you use FirePHPCore.class.php instead.
41
+ *
42
+ * @copyright Copyright (C) 2007-2009 Christoph Dorn
43
+ * @author Christoph Dorn <christoph@christophdorn.com>
44
+ * @author Michael Day <manveru.alma@gmail.com>
45
+ * @license http://www.opensource.org/licenses/bsd-license.php
46
+ * @package FirePHPCore
47
+ */
48
+
49
+ /**
50
+ * FirePHP version
51
+ *
52
+ * @var string
53
+ */
54
+ define('FirePHP_VERSION', '0.3'); // @pinf replace '0.3' with '%%package.version%%'
55
+
56
+ /**
57
+ * Firebug LOG level
58
+ *
59
+ * Logs a message to firebug console
60
+ *
61
+ * @var string
62
+ */
63
+ define('FirePHP_LOG', 'LOG');
64
+
65
+ /**
66
+ * Firebug INFO level
67
+ *
68
+ * Logs a message to firebug console and displays an info icon before the message
69
+ *
70
+ * @var string
71
+ */
72
+ define('FirePHP_INFO', 'INFO');
73
+
74
+ /**
75
+ * Firebug WARN level
76
+ *
77
+ * Logs a message to firebug console, displays a warning icon before the message and colors the line turquoise
78
+ *
79
+ * @var string
80
+ */
81
+ define('FirePHP_WARN', 'WARN');
82
+
83
+ /**
84
+ * Firebug ERROR level
85
+ *
86
+ * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count.
87
+ *
88
+ * @var string
89
+ */
90
+ define('FirePHP_ERROR', 'ERROR');
91
+
92
+ /**
93
+ * Dumps a variable to firebug's server panel
94
+ *
95
+ * @var string
96
+ */
97
+ define('FirePHP_DUMP', 'DUMP');
98
+
99
+ /**
100
+ * Displays a stack trace in firebug console
101
+ *
102
+ * @var string
103
+ */
104
+ define('FirePHP_TRACE', 'TRACE');
105
+
106
+ /**
107
+ * Displays a table in firebug console
108
+ *
109
+ * @var string
110
+ */
111
+ define('FirePHP_TABLE', 'TABLE');
112
+
113
+ /**
114
+ * Starts a group in firebug console
115
+ *
116
+ * @var string
117
+ */
118
+ define('FirePHP_GROUP_START', 'GROUP_START');
119
+
120
+ /**
121
+ * Ends a group in firebug console
122
+ *
123
+ * @var string
124
+ */
125
+ define('FirePHP_GROUP_END', 'GROUP_END');
126
+
127
+ /**
128
+ * Sends the given data to the FirePHP Firefox Extension.
129
+ * The data can be displayed in the Firebug Console or in the
130
+ * "Server" request tab.
131
+ *
132
+ * For more information see: http://www.firephp.org/
133
+ *
134
+ * @copyright Copyright (C) 2007-2009 Christoph Dorn
135
+ * @author Christoph Dorn <christoph@christophdorn.com>
136
+ * @author Michael Day <manveru.alma@gmail.com>
137
+ * @license http://www.opensource.org/licenses/bsd-license.php
138
+ * @package FirePHPCore
139
+ */
140
+ class FirePHP {
141
+ /**
142
+ * Wildfire protocol message index
143
+ *
144
+ * @var int
145
+ */
146
+ var $messageIndex = 1;
147
+
148
+ /**
149
+ * Options for the library
150
+ *
151
+ * @var array
152
+ */
153
+ var $options = array('maxObjectDepth' => 5,
154
+ 'maxArrayDepth' => 5,
155
+ 'useNativeJsonEncode' => true,
156
+ 'includeLineNumbers' => true);
157
+
158
+ /**
159
+ * Filters used to exclude object members when encoding
160
+ *
161
+ * @var array
162
+ */
163
+ var $objectFilters = array();
164
+
165
+ /**
166
+ * A stack of objects used to detect recursion during object encoding
167
+ *
168
+ * @var object
169
+ */
170
+ var $objectStack = array();
171
+
172
+ /**
173
+ * Flag to enable/disable logging
174
+ *
175
+ * @var boolean
176
+ */
177
+ var $enabled = true;
178
+
179
+ /**
180
+ * The object constructor
181
+ */
182
+ function FirePHP() {
183
+ }
184
+
185
+
186
+ /**
187
+ * When the object gets serialized only include specific object members.
188
+ *
189
+ * @return array
190
+ */
191
+ function __sleep() {
192
+ return array('options','objectFilters','enabled');
193
+ }
194
+
195
+ /**
196
+ * Gets singleton instance of FirePHP
197
+ *
198
+ * @param boolean $AutoCreate
199
+ * @return FirePHP
200
+ */
201
+ function &getInstance($AutoCreate=false) {
202
+ global $FirePHP_Instance;
203
+
204
+ if($AutoCreate===true && !$FirePHP_Instance) {
205
+ $FirePHP_Instance = new FirePHP();
206
+ }
207
+
208
+ return $FirePHP_Instance;
209
+ }
210
+
211
+ /**
212
+ * Enable and disable logging to Firebug
213
+ *
214
+ * @param boolean $Enabled TRUE to enable, FALSE to disable
215
+ * @return void
216
+ */
217
+ function setEnabled($Enabled) {
218
+ $this->enabled = $Enabled;
219
+ }
220
+
221
+ /**
222
+ * Check if logging is enabled
223
+ *
224
+ * @return boolean TRUE if enabled
225
+ */
226
+ function getEnabled() {
227
+ return $this->enabled;
228
+ }
229
+
230
+ /**
231
+ * Specify a filter to be used when encoding an object
232
+ *
233
+ * Filters are used to exclude object members.
234
+ *
235
+ * @param string $Class The class name of the object
236
+ * @param array $Filter An array of members to exclude
237
+ * @return void
238
+ */
239
+ function setObjectFilter($Class, $Filter) {
240
+ $this->objectFilters[strtolower($Class)] = $Filter;
241
+ }
242
+
243
+ /**
244
+ * Set some options for the library
245
+ *
246
+ * Options:
247
+ * - maxObjectDepth: The maximum depth to traverse objects (default: 5)
248
+ * - maxArrayDepth: The maximum depth to traverse arrays (default: 5)
249
+ * - useNativeJsonEncode: If true will use json_encode() (default: true)
250
+ * - includeLineNumbers: If true will include line numbers and filenames (default: true)
251
+ *
252
+ * @param array $Options The options to be set
253
+ * @return void
254
+ */
255
+ function setOptions($Options) {
256
+ $this->options = array_merge($this->options,$Options);
257
+ }
258
+
259
+ /**
260
+ * Get options from the library
261
+ *
262
+ * @return array The currently set options
263
+ */
264
+ function getOptions() {
265
+ return $this->options;
266
+ }
267
+
268
+ /**
269
+ * Register FirePHP as your error handler
270
+ *
271
+ * Will use FirePHP to log each php error.
272
+ *
273
+ * @return mixed Returns a string containing the previously defined error handler (if any)
274
+ */
275
+ function registerErrorHandler()
276
+ {
277
+ //NOTE: The following errors will not be caught by this error handler:
278
+ // E_ERROR, E_PARSE, E_CORE_ERROR,
279
+ // E_CORE_WARNING, E_COMPILE_ERROR,
280
+ // E_COMPILE_WARNING, E_STRICT
281
+
282
+ return set_error_handler(array($this,'errorHandler'));
283
+ }
284
+
285
+ /**
286
+ * FirePHP's error handler
287
+ *
288
+ * Logs each php error that will occur.
289
+ *
290
+ * @param int $errno
291
+ * @param string $errstr
292
+ * @param string $errfile
293
+ * @param int $errline
294
+ * @param array $errcontext
295
+ */
296
+ function errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
297
+ {
298
+ global $FirePHP_Instance;
299
+ // Don't log error if error reporting is switched off
300
+ if (error_reporting() == 0) {
301
+ return;
302
+ }
303
+ // Only log error for errors we are asking for
304
+ if (error_reporting() & $errno) {
305
+ $FirePHP_Instance->group($errstr);
306
+ $FirePHP_Instance->error("{$errfile}, line $errline");
307
+ $FirePHP_Instance->groupEnd();
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Register FirePHP driver as your assert callback
313
+ *
314
+ * @return mixed Returns the original setting
315
+ */
316
+ function registerAssertionHandler()
317
+ {
318
+ return assert_options(ASSERT_CALLBACK, array($this, 'assertionHandler'));
319
+ }
320
+
321
+ /**
322
+ * FirePHP's assertion handler
323
+ *
324
+ * Logs all assertions to your firebug console and then stops the script.
325
+ *
326
+ * @param string $file File source of assertion
327
+ * @param int $line Line source of assertion
328
+ * @param mixed $code Assertion code
329
+ */
330
+ function assertionHandler($file, $line, $code)
331
+ {
332
+ $this->fb($code, 'Assertion Failed', FirePHP_ERROR, array('File'=>$file,'Line'=>$line));
333
+ }
334
+
335
+ /**
336
+ * Set custom processor url for FirePHP
337
+ *
338
+ * @param string $URL
339
+ */
340
+ function setProcessorUrl($URL)
341
+ {
342
+ $this->setHeader('X-FirePHP-ProcessorURL', $URL);
343
+ }
344
+
345
+ /**
346
+ * Set custom renderer url for FirePHP
347
+ *
348
+ * @param string $URL
349
+ */
350
+ function setRendererUrl($URL)
351
+ {
352
+ $this->setHeader('X-FirePHP-RendererURL', $URL);
353
+ }
354
+
355
+ /**
356
+ * Start a group for following messages.
357
+ *
358
+ * Options:
359
+ * Collapsed: [true|false]
360
+ * Color: [#RRGGBB|ColorName]
361
+ *
362
+ * @param string $Name
363
+ * @param array $Options OPTIONAL Instructions on how to log the group
364
+ * @return true
365
+ * @throws Exception
366
+ */
367
+ function group($Name, $Options=null) {
368
+
369
+ if(!$Name) {
370
+ trigger_error('You must specify a label for the group!');
371
+ }
372
+
373
+ if($Options) {
374
+ if(!is_array($Options)) {
375
+ trigger_error('Options must be defined as an array!');
376
+ }
377
+ if(array_key_exists('Collapsed', $Options)) {
378
+ $Options['Collapsed'] = ($Options['Collapsed'])?'true':'false';
379
+ }
380
+ }
381
+
382
+ return $this->fb(null, $Name, FirePHP_GROUP_START, $Options);
383
+ }
384
+
385
+ /**
386
+ * Ends a group you have started before
387
+ *
388
+ * @return true
389
+ * @throws Exception
390
+ */
391
+ function groupEnd() {
392
+ return $this->fb(null, null, FirePHP_GROUP_END);
393
+ }
394
+
395
+ /**
396
+ * Log object with label to firebug console
397
+ *
398
+ * @see FirePHP::LOG
399
+ * @param mixes $Object
400
+ * @param string $Label
401
+ * @return true
402
+ * @throws Exception
403
+ */
404
+ function log($Object, $Label=null) {
405
+ return $this->fb($Object, $Label, FirePHP_LOG);
406
+ }
407
+
408
+ /**
409
+ * Log object with label to firebug console
410
+ *
411
+ * @see FirePHP::INFO
412
+ * @param mixes $Object
413
+ * @param string $Label
414
+ * @return true
415
+ * @throws Exception
416
+ */
417
+ function info($Object, $Label=null) {
418
+ return $this->fb($Object, $Label, FirePHP_INFO);
419
+ }
420
+
421
+ /**
422
+ * Log object with label to firebug console
423
+ *
424
+ * @see FirePHP::WARN
425
+ * @param mixes $Object
426
+ * @param string $Label
427
+ * @return true
428
+ * @throws Exception
429
+ */
430
+ function warn($Object, $Label=null) {
431
+ return $this->fb($Object, $Label, FirePHP_WARN);
432
+ }
433
+
434
+ /**
435
+ * Log object with label to firebug console
436
+ *
437
+ * @see FirePHP::ERROR
438
+ * @param mixes $Object
439
+ * @param string $Label
440
+ * @return true
441
+ * @throws Exception
442
+ */
443
+ function error($Object, $Label=null) {
444
+ return $this->fb($Object, $Label, FirePHP_ERROR);
445
+ }
446
+
447
+ /**
448
+ * Dumps key and variable to firebug server panel
449
+ *
450
+ * @see FirePHP::DUMP
451
+ * @param string $Key
452
+ * @param mixed $Variable
453
+ * @return true
454
+ * @throws Exception
455
+ */
456
+ function dump($Key, $Variable) {
457
+ return $this->fb($Variable, $Key, FirePHP_DUMP);
458
+ }
459
+
460
+ /**
461
+ * Log a trace in the firebug console
462
+ *
463
+ * @see FirePHP::TRACE
464
+ * @param string $Label
465
+ * @return true
466
+ * @throws Exception
467
+ */
468
+ function trace($Label) {
469
+ return $this->fb($Label, FirePHP_TRACE);
470
+ }
471
+
472
+ /**
473
+ * Log a table in the firebug console
474
+ *
475
+ * @see FirePHP::TABLE
476
+ * @param string $Label
477
+ * @param string $Table
478
+ * @return true
479
+ * @throws Exception
480
+ */
481
+ function table($Label, $Table) {
482
+ return $this->fb($Table, $Label, FirePHP_TABLE);
483
+ }
484
+
485
+ /**
486
+ * Check if FirePHP is installed on client
487
+ *
488
+ * @return boolean
489
+ */
490
+ function detectClientExtension() {
491
+ // Check if FirePHP is installed on client via User-Agent header
492
+ if(@preg_match_all('/\sFirePHP\/([\.\d]*)\s?/si',$this->getUserAgent(),$m) &&
493
+ version_compare($m[1][0],'0.0.6','>=')) {
494
+ return true;
495
+ } else
496
+ // Check if FirePHP is installed on client via X-FirePHP-Version header
497
+ if(@preg_match_all('/^([\.\d]*)$/si',$this->getRequestHeader("X-FirePHP-Version"),$m) &&
498
+ version_compare($m[1][0],'0.0.6','>=')) {
499
+ return true;
500
+ }
501
+ return false;
502
+ }
503
+
504
+ /**
505
+ * Log varible to Firebug
506
+ *
507
+ * @see http://www.firephp.org/Wiki/Reference/Fb
508
+ * @param mixed $Object The variable to be logged
509
+ * @return true Return TRUE if message was added to headers, FALSE otherwise
510
+ * @throws Exception
511
+ */
512
+ function fb($Object) {
513
+
514
+ if(!$this->enabled) {
515
+ return false;
516
+ }
517
+
518
+ if (headers_sent($filename, $linenum)) {
519
+ trigger_error('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.');
520
+ }
521
+
522
+ $Type = null;
523
+ $Label = null;
524
+ $Options = array();
525
+
526
+ if(func_num_args()==1) {
527
+ } else
528
+ if(func_num_args()==2) {
529
+ switch(func_get_arg(1)) {
530
+ case FirePHP_LOG:
531
+ case FirePHP_INFO:
532
+ case FirePHP_WARN:
533
+ case FirePHP_ERROR:
534
+ case FirePHP_DUMP:
535
+ case FirePHP_TRACE:
536
+ case FirePHP_TABLE:
537
+ case FirePHP_GROUP_START:
538
+ case FirePHP_GROUP_END:
539
+ $Type = func_get_arg(1);
540
+ break;
541
+ default:
542
+ $Label = func_get_arg(1);
543
+ break;
544
+ }
545
+ } else
546
+ if(func_num_args()==3) {
547
+ $Type = func_get_arg(2);
548
+ $Label = func_get_arg(1);
549
+ } else
550
+ if(func_num_args()==4) {
551
+ $Type = func_get_arg(2);
552
+ $Label = func_get_arg(1);
553
+ $Options = func_get_arg(3);
554
+ } else {
555
+ trigger_error('Wrong number of arguments to fb() function!');
556
+ }
557
+
558
+
559
+ if(!$this->detectClientExtension()) {
560
+ return false;
561
+ }
562
+
563
+ $meta = array();
564
+ $skipFinalObjectEncode = false;
565
+
566
+ if($Type==FirePHP_TRACE) {
567
+
568
+ $trace = debug_backtrace();
569
+ if(!$trace) return false;
570
+ for( $i=0 ; $i<sizeof($trace) ; $i++ ) {
571
+
572
+ if(isset($trace[$i]['class'])
573
+ && isset($trace[$i]['file'])
574
+ && ($trace[$i]['class']=='FirePHP'
575
+ || $trace[$i]['class']=='FB')
576
+ && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
577
+ || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
578
+ /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
579
+ } else
580
+ if(isset($trace[$i]['class'])
581
+ && isset($trace[$i+1]['file'])
582
+ && $trace[$i]['class']=='FirePHP'
583
+ && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
584
+ /* Skip fb() */
585
+ } else
586
+ if($trace[$i]['function']=='fb'
587
+ || $trace[$i]['function']=='trace'
588
+ || $trace[$i]['function']=='send') {
589
+ $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'',
590
+ 'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'',
591
+ 'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'',
592
+ 'Message'=>$trace[$i]['args'][0],
593
+ 'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'',
594
+ 'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'',
595
+ 'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'',
596
+ 'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1)));
597
+
598
+ $skipFinalObjectEncode = true;
599
+ $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
600
+ $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
601
+ break;
602
+ }
603
+ }
604
+
605
+ } else
606
+ if($Type==FirePHP_TABLE) {
607
+
608
+ if(isset($Object[0]) && is_string($Object[0])) {
609
+ $Object[1] = $this->encodeTable($Object[1]);
610
+ } else {
611
+ $Object = $this->encodeTable($Object);
612
+ }
613
+
614
+ $skipFinalObjectEncode = true;
615
+
616
+ } else
617
+ if($Type==FirePHP_GROUP_START) {
618
+
619
+ if(!$Label) {
620
+ trigger_error('You must specify a label for the group!');
621
+ }
622
+ } else {
623
+ if($Type===null) {
624
+ $Type = FirePHP_LOG;
625
+ }
626
+ }
627
+
628
+ if($this->options['includeLineNumbers']) {
629
+ if(!isset($meta['file']) || !isset($meta['line'])) {
630
+
631
+ $trace = debug_backtrace();
632
+ for( $i=0 ; $trace && $i<sizeof($trace) ; $i++ ) {
633
+
634
+ if(isset($trace[$i]['class'])
635
+ && isset($trace[$i]['file'])
636
+ && ($trace[$i]['class']=='FirePHP'
637
+ || $trace[$i]['class']=='FB')
638
+ && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
639
+ || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
640
+ /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
641
+ } else
642
+ if(isset($trace[$i]['class'])
643
+ && isset($trace[$i+1]['file'])
644
+ && $trace[$i]['class']=='FirePHP'
645
+ && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
646
+ /* Skip fb() */
647
+ } else
648
+ if(isset($trace[$i]['file'])
649
+ && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') {
650
+ /* Skip FB::fb() */
651
+ } else {
652
+ $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
653
+ $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
654
+ break;
655
+ }
656
+ }
657
+
658
+ }
659
+ } else {
660
+ unset($meta['file']);
661
+ unset($meta['line']);
662
+ }
663
+
664
+ $this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
665
+ $this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.FirePHP_VERSION);
666
+
667
+ $structure_index = 1;
668
+ if($Type==FirePHP_DUMP) {
669
+ $structure_index = 2;
670
+ $this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');
671
+ } else {
672
+ $this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
673
+ }
674
+
675
+ if($Type==FirePHP_DUMP) {
676
+ $msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}';
677
+ } else {
678
+ $msg_meta = $Options;
679
+ $msg_meta['Type'] = $Type;
680
+ if($Label!==null) {
681
+ $msg_meta['Label'] = $Label;
682
+ }
683
+ if(isset($meta['file']) && !isset($msg_meta['File'])) {
684
+ $msg_meta['File'] = $meta['file'];
685
+ }
686
+ if(isset($meta['line']) && !isset($msg_meta['Line'])) {
687
+ $msg_meta['Line'] = $meta['line'];
688
+ }
689
+ $msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']';
690
+ }
691
+
692
+ $parts = explode("\n",chunk_split($msg, 5000, "\n"));
693
+
694
+ for( $i=0 ; $i<count($parts) ; $i++) {
695
+
696
+ $part = $parts[$i];
697
+ if ($part) {
698
+
699
+ if(count($parts)>2) {
700
+ // Message needs to be split into multiple parts
701
+ $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
702
+ (($i==0)?strlen($msg):'')
703
+ . '|' . $part . '|'
704
+ . (($i<count($parts)-2)?'\\':''));
705
+ } else {
706
+ $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
707
+ strlen($part) . '|' . $part . '|');
708
+ }
709
+
710
+ $this->messageIndex++;
711
+
712
+ if ($this->messageIndex > 99999) {
713
+ trigger_error('Maximum number (99,999) of messages reached!');
714
+ }
715
+ }
716
+ }
717
+
718
+ $this->setHeader('X-Wf-1-Index',$this->messageIndex-1);
719
+
720
+ return true;
721
+ }
722
+
723
+
724
+ /**
725
+ * Standardizes path for windows systems.
726
+ *
727
+ * @param string $Path
728
+ * @return string
729
+ */
730
+ function _standardizePath($Path) {
731
+ return preg_replace('/\\\\+/','/',$Path);
732
+ }
733
+
734
+ /**
735
+ * Escape trace path for windows systems
736
+ *
737
+ * @param array $Trace
738
+ * @return array
739
+ */
740
+ function _escapeTrace($Trace) {
741
+ if(!$Trace) return $Trace;
742
+ for( $i=0 ; $i<sizeof($Trace) ; $i++ ) {
743
+ if(isset($Trace[$i]['file'])) {
744
+ $Trace[$i]['file'] = $this->_escapeTraceFile($Trace[$i]['file']);
745
+ }
746
+ if(isset($Trace[$i]['args'])) {
747
+ $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']);
748
+ }
749
+ }
750
+ return $Trace;
751
+ }
752
+
753
+ /**
754
+ * Escape file information of trace for windows systems
755
+ *
756
+ * @param string $File
757
+ * @return string
758
+ */
759
+ function _escapeTraceFile($File) {
760
+ /* Check if we have a windows filepath */
761
+ if(strpos($File,'\\')) {
762
+ /* First strip down to single \ */
763
+
764
+ $file = preg_replace('/\\\\+/','\\',$File);
765
+
766
+ return $file;
767
+ }
768
+ return $File;
769
+ }
770
+
771
+ /**
772
+ * Send header
773
+ *
774
+ * @param string $Name
775
+ * @param string_type $Value
776
+ */
777
+ function setHeader($Name, $Value) {
778
+ return header($Name.': '.$Value);
779
+ }
780
+
781
+ /**
782
+ * Get user agent
783
+ *
784
+ * @return string|false
785
+ */
786
+ function getUserAgent() {
787
+ if(!isset($_SERVER['HTTP_USER_AGENT'])) return false;
788
+ return $_SERVER['HTTP_USER_AGENT'];
789
+ }
790
+
791
+ /**
792
+ * Get all request headers
793
+ *
794
+ * @return array
795
+ */
796
+ function getAllRequestHeaders() {
797
+ $headers = array();
798
+ if(function_exists('getallheaders')) {
799
+ foreach( getallheaders() as $name => $value ) {
800
+ $headers[strtolower($name)] = $value;
801
+ }
802
+ } else {
803
+ foreach($_SERVER as $name => $value) {
804
+ if(substr($name, 0, 5) == 'HTTP_') {
805
+ $headers[strtolower(str_replace(' ', '-', str_replace('_', ' ', substr($name, 5))))] = $value;
806
+ }
807
+ }
808
+ }
809
+ return $headers;
810
+ }
811
+
812
+ /**
813
+ * Get a request header
814
+ *
815
+ * @return string|false
816
+ */
817
+ function getRequestHeader($Name)
818
+ {
819
+ $headers = $this->getAllRequestHeaders();
820
+ if (isset($headers[strtolower($Name)])) {
821
+ return $headers[strtolower($Name)];
822
+ }
823
+ return false;
824
+ }
825
+
826
+ /**
827
+ * Encode an object into a JSON string
828
+ *
829
+ * Uses PHP's jeson_encode() if available
830
+ *
831
+ * @param object $Object The object to be encoded
832
+ * @return string The JSON string
833
+ */
834
+ function jsonEncode($Object, $skipObjectEncode=false)
835
+ {
836
+ if(!$skipObjectEncode) {
837
+ $Object = $this->encodeObject($Object);
838
+ }
839
+
840
+ if(function_exists('json_encode')
841
+ && $this->options['useNativeJsonEncode']!=false) {
842
+
843
+ return json_encode($Object);
844
+ } else {
845
+ return $this->json_encode($Object);
846
+ }
847
+ }
848
+
849
+ /**
850
+ * Encodes a table by encoding each row and column with encodeObject()
851
+ *
852
+ * @param array $Table The table to be encoded
853
+ * @return array
854
+ */
855
+ function encodeTable($Table) {
856
+
857
+ if(!$Table) return $Table;
858
+
859
+ $new_table = array();
860
+ foreach($Table as $row) {
861
+
862
+ if(is_array($row)) {
863
+ $new_row = array();
864
+
865
+ foreach($row as $item) {
866
+ $new_row[] = $this->encodeObject($item);
867
+ }
868
+
869
+ $new_table[] = $new_row;
870
+ }
871
+ }
872
+
873
+ return $new_table;
874
+ }
875
+
876
+ /**
877
+ * Encodes an object
878
+ *
879
+ * @param Object $Object The object to be encoded
880
+ * @param int $Depth The current traversal depth
881
+ * @return array All members of the object
882
+ */
883
+ function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1)
884
+ {
885
+ $return = array();
886
+
887
+ if (is_resource($Object)) {
888
+
889
+ return '** '.(string)$Object.' **';
890
+
891
+ } else
892
+ if (is_object($Object)) {
893
+
894
+ if ($ObjectDepth > $this->options['maxObjectDepth']) {
895
+ return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **';
896
+ }
897
+
898
+ foreach ($this->objectStack as $refVal) {
899
+ if ($refVal === $Object) {
900
+ return '** Recursion ('.get_class($Object).') **';
901
+ }
902
+ }
903
+ array_push($this->objectStack, $Object);
904
+
905
+ $return['__className'] = $class = get_class($Object);
906
+ $class_lower = strtolower($class);
907
+
908
+ $members = (array)$Object;
909
+
910
+ // Include all members that are not defined in the class
911
+ // but exist in the object
912
+ foreach( $members as $raw_name => $value ) {
913
+
914
+ $name = $raw_name;
915
+
916
+ if ($name{0} == "\0") {
917
+ $parts = explode("\0", $name);
918
+ $name = $parts[2];
919
+ }
920
+
921
+ if(!isset($properties[$name])) {
922
+ $name = 'undeclared:'.$name;
923
+
924
+ if(!(isset($this->objectFilters[$class_lower])
925
+ && is_array($this->objectFilters[$class_lower])
926
+ && in_array($raw_name,$this->objectFilters[$class_lower]))) {
927
+
928
+ $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1);
929
+ } else {
930
+ $return[$name] = '** Excluded by Filter **';
931
+ }
932
+ }
933
+ }
934
+
935
+ array_pop($this->objectStack);
936
+
937
+ } elseif (is_array($Object)) {
938
+
939
+ if ($ArrayDepth > $this->options['maxArrayDepth']) {
940
+ return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **';
941
+ }
942
+
943
+ foreach ($Object as $key => $val) {
944
+
945
+ // Encoding the $GLOBALS PHP array causes an infinite loop
946
+ // if the recursion is not reset here as it contains
947
+ // a reference to itself. This is the only way I have come up
948
+ // with to stop infinite recursion in this case.
949
+ if($key=='GLOBALS'
950
+ && is_array($val)
951
+ && array_key_exists('GLOBALS',$val)) {
952
+ $val['GLOBALS'] = '** Recursion (GLOBALS) **';
953
+ }
954
+
955
+ $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1);
956
+ }
957
+ } else {
958
+ if($this->is_utf8($Object)) {
959
+ return $Object;
960
+ } else {
961
+ return utf8_encode($Object);
962
+ }
963
+ }
964
+ return $return;
965
+
966
+ }
967
+
968
+ /**
969
+ * Returns true if $string is valid UTF-8 and false otherwise.
970
+ *
971
+ * @param mixed $str String to be tested
972
+ * @return boolean
973
+ */
974
+ function is_utf8($str) {
975
+ $c=0; $b=0;
976
+ $bits=0;
977
+ $len=strlen($str);
978
+ for($i=0; $i<$len; $i++){
979
+ $c=ord($str[$i]);
980
+ if($c > 128){
981
+ if(($c >= 254)) return false;
982
+ elseif($c >= 252) $bits=6;
983
+ elseif($c >= 248) $bits=5;
984
+ elseif($c >= 240) $bits=4;
985
+ elseif($c >= 224) $bits=3;
986
+ elseif($c >= 192) $bits=2;
987
+ else return false;
988
+ if(($i+$bits) > $len) return false;
989
+ while($bits > 1){
990
+ $i++;
991
+ $b=ord($str[$i]);
992
+ if($b < 128 || $b > 191) return false;
993
+ $bits--;
994
+ }
995
+ }
996
+ }
997
+ return true;
998
+ }
999
+
1000
+ /**
1001
+ * Converts to and from JSON format.
1002
+ *
1003
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
1004
+ * format. It is easy for humans to read and write. It is easy for machines
1005
+ * to parse and generate. It is based on a subset of the JavaScript
1006
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
1007
+ * This feature can also be found in Python. JSON is a text format that is
1008
+ * completely language independent but uses conventions that are familiar
1009
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
1010
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
1011
+ * ideal data-interchange language.
1012
+ *
1013
+ * This package provides a simple encoder and decoder for JSON notation. It
1014
+ * is intended for use with client-side Javascript applications that make
1015
+ * use of HTTPRequest to perform server communication functions - data can
1016
+ * be encoded into JSON notation for use in a client-side javascript, or
1017
+ * decoded from incoming Javascript requests. JSON format is native to
1018
+ * Javascript, and can be directly eval()'ed with no further parsing
1019
+ * overhead
1020
+ *
1021
+ * All strings should be in ASCII or UTF-8 format!
1022
+ *
1023
+ * LICENSE: Redistribution and use in source and binary forms, with or
1024
+ * without modification, are permitted provided that the following
1025
+ * conditions are met: Redistributions of source code must retain the
1026
+ * above copyright notice, this list of conditions and the following
1027
+ * disclaimer. Redistributions in binary form must reproduce the above
1028
+ * copyright notice, this list of conditions and the following disclaimer
1029
+ * in the documentation and/or other materials provided with the
1030
+ * distribution.
1031
+ *
1032
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1033
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1034
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
1035
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
1036
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
1037
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
1038
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1039
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
1040
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1041
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1042
+ * DAMAGE.
1043
+ *
1044
+ * @category
1045
+ * @package Services_JSON
1046
+ * @author Michal Migurski <mike-json@teczno.com>
1047
+ * @author Matt Knapp <mdknapp[at]gmail[dot]com>
1048
+ * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
1049
+ * @author Christoph Dorn <christoph@christophdorn.com>
1050
+ * @copyright 2005 Michal Migurski
1051
+ * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
1052
+ * @license http://www.opensource.org/licenses/bsd-license.php
1053
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
1054
+ */
1055
+
1056
+
1057
+ /**
1058
+ * Keep a list of objects as we descend into the array so we can detect recursion.
1059
+ */
1060
+ var $json_objectStack = array();
1061
+
1062
+
1063
+ /**
1064
+ * convert a string from one UTF-8 char to one UTF-16 char
1065
+ *
1066
+ * Normally should be handled by mb_convert_encoding, but
1067
+ * provides a slower PHP-only method for installations
1068
+ * that lack the multibye string extension.
1069
+ *
1070
+ * @param string $utf8 UTF-8 character
1071
+ * @return string UTF-16 character
1072
+ * @access private
1073
+ */
1074
+ function json_utf82utf16($utf8)
1075
+ {
1076
+ // oh please oh please oh please oh please oh please
1077
+ if(function_exists('mb_convert_encoding')) {
1078
+ return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
1079
+ }
1080
+
1081
+ switch(strlen($utf8)) {
1082
+ case 1:
1083
+ // this case should never be reached, because we are in ASCII range
1084
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1085
+ return $utf8;
1086
+
1087
+ case 2:
1088
+ // return a UTF-16 character from a 2-byte UTF-8 char
1089
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1090
+ return chr(0x07 & (ord($utf8{0}) >> 2))
1091
+ . chr((0xC0 & (ord($utf8{0}) << 6))
1092
+ | (0x3F & ord($utf8{1})));
1093
+
1094
+ case 3:
1095
+ // return a UTF-16 character from a 3-byte UTF-8 char
1096
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1097
+ return chr((0xF0 & (ord($utf8{0}) << 4))
1098
+ | (0x0F & (ord($utf8{1}) >> 2)))
1099
+ . chr((0xC0 & (ord($utf8{1}) << 6))
1100
+ | (0x7F & ord($utf8{2})));
1101
+ }
1102
+
1103
+ // ignoring UTF-32 for now, sorry
1104
+ return '';
1105
+ }
1106
+
1107
+ /**
1108
+ * encodes an arbitrary variable into JSON format
1109
+ *
1110
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
1111
+ * see argument 1 to Services_JSON() above for array-parsing behavior.
1112
+ * if var is a strng, note that encode() always expects it
1113
+ * to be in ASCII or UTF-8 format!
1114
+ *
1115
+ * @return mixed JSON string representation of input var or an error if a problem occurs
1116
+ * @access public
1117
+ */
1118
+ function json_encode($var)
1119
+ {
1120
+
1121
+ if(is_object($var)) {
1122
+ if(in_array($var,$this->json_objectStack)) {
1123
+ return '"** Recursion **"';
1124
+ }
1125
+ }
1126
+
1127
+ switch (gettype($var)) {
1128
+ case 'boolean':
1129
+ return $var ? 'true' : 'false';
1130
+
1131
+ case 'NULL':
1132
+ return 'null';
1133
+
1134
+ case 'integer':
1135
+ return (int) $var;
1136
+
1137
+ case 'double':
1138
+ case 'float':
1139
+ return (float) $var;
1140
+
1141
+ case 'string':
1142
+ // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
1143
+ $ascii = '';
1144
+ $strlen_var = strlen($var);
1145
+
1146
+ /*
1147
+ * Iterate over every character in the string,
1148
+ * escaping with a slash or encoding to UTF-8 where necessary
1149
+ */
1150
+ for ($c = 0; $c < $strlen_var; ++$c) {
1151
+
1152
+ $ord_var_c = ord($var{$c});
1153
+
1154
+ switch (true) {
1155
+ case $ord_var_c == 0x08:
1156
+ $ascii .= '\b';
1157
+ break;
1158
+ case $ord_var_c == 0x09:
1159
+ $ascii .= '\t';
1160
+ break;
1161
+ case $ord_var_c == 0x0A:
1162
+ $ascii .= '\n';
1163
+ break;
1164
+ case $ord_var_c == 0x0C:
1165
+ $ascii .= '\f';
1166
+ break;
1167
+ case $ord_var_c == 0x0D:
1168
+ $ascii .= '\r';
1169
+ break;
1170
+
1171
+ case $ord_var_c == 0x22:
1172
+ case $ord_var_c == 0x2F:
1173
+ case $ord_var_c == 0x5C:
1174
+ // double quote, slash, slosh
1175
+ $ascii .= '\\'.$var{$c};
1176
+ break;
1177
+
1178
+ case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
1179
+ // characters U-00000000 - U-0000007F (same as ASCII)
1180
+ $ascii .= $var{$c};
1181
+ break;
1182
+
1183
+ case (($ord_var_c & 0xE0) == 0xC0):
1184
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
1185
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1186
+ $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
1187
+ $c += 1;
1188
+ $utf16 = $this->json_utf82utf16($char);
1189
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1190
+ break;
1191
+
1192
+ case (($ord_var_c & 0xF0) == 0xE0):
1193
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
1194
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1195
+ $char = pack('C*', $ord_var_c,
1196
+ ord($var{$c + 1}),
1197
+ ord($var{$c + 2}));
1198
+ $c += 2;
1199
+ $utf16 = $this->json_utf82utf16($char);
1200
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1201
+ break;
1202
+
1203
+ case (($ord_var_c & 0xF8) == 0xF0):
1204
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
1205
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1206
+ $char = pack('C*', $ord_var_c,
1207
+ ord($var{$c + 1}),
1208
+ ord($var{$c + 2}),
1209
+ ord($var{$c + 3}));
1210
+ $c += 3;
1211
+ $utf16 = $this->json_utf82utf16($char);
1212
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1213
+ break;
1214
+
1215
+ case (($ord_var_c & 0xFC) == 0xF8):
1216
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
1217
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1218
+ $char = pack('C*', $ord_var_c,
1219
+ ord($var{$c + 1}),
1220
+ ord($var{$c + 2}),
1221
+ ord($var{$c + 3}),
1222
+ ord($var{$c + 4}));
1223
+ $c += 4;
1224
+ $utf16 = $this->json_utf82utf16($char);
1225
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1226
+ break;
1227
+
1228
+ case (($ord_var_c & 0xFE) == 0xFC):
1229
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
1230
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1231
+ $char = pack('C*', $ord_var_c,
1232
+ ord($var{$c + 1}),
1233
+ ord($var{$c + 2}),
1234
+ ord($var{$c + 3}),
1235
+ ord($var{$c + 4}),
1236
+ ord($var{$c + 5}));
1237
+ $c += 5;
1238
+ $utf16 = $this->json_utf82utf16($char);
1239
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1240
+ break;
1241
+ }
1242
+ }
1243
+
1244
+ return '"'.$ascii.'"';
1245
+
1246
+ case 'array':
1247
+ /*
1248
+ * As per JSON spec if any array key is not an integer
1249
+ * we must treat the the whole array as an object. We
1250
+ * also try to catch a sparsely populated associative
1251
+ * array with numeric keys here because some JS engines
1252
+ * will create an array with empty indexes up to
1253
+ * max_index which can cause memory issues and because
1254
+ * the keys, which may be relevant, will be remapped
1255
+ * otherwise.
1256
+ *
1257
+ * As per the ECMA and JSON specification an object may
1258
+ * have any string as a property. Unfortunately due to
1259
+ * a hole in the ECMA specification if the key is a
1260
+ * ECMA reserved word or starts with a digit the
1261
+ * parameter is only accessible using ECMAScript's
1262
+ * bracket notation.
1263
+ */
1264
+
1265
+ // treat as a JSON object
1266
+ if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
1267
+
1268
+ $this->json_objectStack[] = $var;
1269
+
1270
+ $properties = array_map(array($this, 'json_name_value'),
1271
+ array_keys($var),
1272
+ array_values($var));
1273
+
1274
+ array_pop($this->json_objectStack);
1275
+
1276
+ return '{' . join(',', $properties) . '}';
1277
+ }
1278
+
1279
+ $this->json_objectStack[] = $var;
1280
+
1281
+ // treat it like a regular array
1282
+ $elements = array_map(array($this, 'json_encode'), $var);
1283
+
1284
+ array_pop($this->json_objectStack);
1285
+
1286
+ return '[' . join(',', $elements) . ']';
1287
+
1288
+ case 'object':
1289
+ $vars = FirePHP::encodeObject($var);
1290
+
1291
+ $this->json_objectStack[] = $var;
1292
+
1293
+ $properties = array_map(array($this, 'json_name_value'),
1294
+ array_keys($vars),
1295
+ array_values($vars));
1296
+
1297
+ array_pop($this->json_objectStack);
1298
+
1299
+ return '{' . join(',', $properties) . '}';
1300
+
1301
+ default:
1302
+ return null;
1303
+ }
1304
+ }
1305
+
1306
+ /**
1307
+ * array-walking function for use in generating JSON-formatted name-value pairs
1308
+ *
1309
+ * @param string $name name of key to use
1310
+ * @param mixed $value reference to an array element to be encoded
1311
+ *
1312
+ * @return string JSON-formatted name-value pair, like '"name":value'
1313
+ * @access private
1314
+ */
1315
+ function json_name_value($name, $value)
1316
+ {
1317
+ // Encoding the $GLOBALS PHP array causes an infinite loop
1318
+ // if the recursion is not reset here as it contains
1319
+ // a reference to itself. This is the only way I have come up
1320
+ // with to stop infinite recursion in this case.
1321
+ if($name=='GLOBALS'
1322
+ && is_array($value)
1323
+ && array_key_exists('GLOBALS',$value)) {
1324
+ $value['GLOBALS'] = '** Recursion **';
1325
+ }
1326
+
1327
+ $encoded_value = $this->json_encode($value);
1328
+
1329
+ return $this->json_encode(strval($name)) . ':' . $encoded_value;
1330
+ }
1331
+ }
1332
+
lib/Itm/FirePhp/LICENSE ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Software License Agreement (New BSD License)
2
+
3
+ Copyright (c) 2006-2009, Christoph Dorn
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without modification,
7
+ are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ * Neither the name of Christoph Dorn nor the names of its
17
+ contributors may be used to endorse or promote products derived from this
18
+ software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
24
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
lib/Itm/FirePhp/fb.php ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* ***** BEGIN LICENSE BLOCK *****
4
+ *
5
+ * This file is part of FirePHP (http://www.firephp.org/).
6
+ *
7
+ * Software License Agreement (New BSD License)
8
+ *
9
+ * Copyright (c) 2006-2010, Christoph Dorn
10
+ * All rights reserved.
11
+ *
12
+ * Redistribution and use in source and binary forms, with or without modification,
13
+ * are permitted provided that the following conditions are met:
14
+ *
15
+ * * Redistributions of source code must retain the above copyright notice,
16
+ * this list of conditions and the following disclaimer.
17
+ *
18
+ * * Redistributions in binary form must reproduce the above copyright notice,
19
+ * this list of conditions and the following disclaimer in the documentation
20
+ * and/or other materials provided with the distribution.
21
+ *
22
+ * * Neither the name of Christoph Dorn nor the names of its
23
+ * contributors may be used to endorse or promote products derived from this
24
+ * software without specific prior written permission.
25
+ *
26
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
27
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
30
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
33
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+ *
37
+ * ***** END LICENSE BLOCK *****
38
+ *
39
+ * @copyright Copyright (C) 2007-2009 Christoph Dorn
40
+ * @author Christoph Dorn <christoph@christophdorn.com>
41
+ * @license http://www.opensource.org/licenses/bsd-license.php
42
+ * @package FirePHPCore
43
+ */
44
+
45
+ if(!class_exists('FirePHP')) {
46
+ require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'FirePHP.class.php';
47
+ }
48
+
49
+ /**
50
+ * Sends the given data to the FirePHP Firefox Extension.
51
+ * The data can be displayed in the Firebug Console or in the
52
+ * "Server" request tab.
53
+ *
54
+ * @see http://www.firephp.org/Wiki/Reference/Fb
55
+ * @param mixed $Object
56
+ * @return true
57
+ * @throws Exception
58
+ */
59
+ function fb()
60
+ {
61
+ $instance = FirePHP::getInstance(true);
62
+
63
+ $args = func_get_args();
64
+ return call_user_func_array(array($instance,'fb'),$args);
65
+ }
66
+
67
+
68
+ class FB
69
+ {
70
+ /**
71
+ * Enable and disable logging to Firebug
72
+ *
73
+ * @see FirePHP->setEnabled()
74
+ * @param boolean $Enabled TRUE to enable, FALSE to disable
75
+ * @return void
76
+ */
77
+ public static function setEnabled($Enabled)
78
+ {
79
+ $instance = FirePHP::getInstance(true);
80
+ $instance->setEnabled($Enabled);
81
+ }
82
+
83
+ /**
84
+ * Check if logging is enabled
85
+ *
86
+ * @see FirePHP->getEnabled()
87
+ * @return boolean TRUE if enabled
88
+ */
89
+ public static function getEnabled()
90
+ {
91
+ $instance = FirePHP::getInstance(true);
92
+ return $instance->getEnabled();
93
+ }
94
+
95
+ /**
96
+ * Specify a filter to be used when encoding an object
97
+ *
98
+ * Filters are used to exclude object members.
99
+ *
100
+ * @see FirePHP->setObjectFilter()
101
+ * @param string $Class The class name of the object
102
+ * @param array $Filter An array or members to exclude
103
+ * @return void
104
+ */
105
+ public static function setObjectFilter($Class, $Filter)
106
+ {
107
+ $instance = FirePHP::getInstance(true);
108
+ $instance->setObjectFilter($Class, $Filter);
109
+ }
110
+
111
+ /**
112
+ * Set some options for the library
113
+ *
114
+ * @see FirePHP->setOptions()
115
+ * @param array $Options The options to be set
116
+ * @return void
117
+ */
118
+ public static function setOptions($Options)
119
+ {
120
+ $instance = FirePHP::getInstance(true);
121
+ $instance->setOptions($Options);
122
+ }
123
+
124
+ /**
125
+ * Get options for the library
126
+ *
127
+ * @see FirePHP->getOptions()
128
+ * @return array The options
129
+ */
130
+ public static function getOptions()
131
+ {
132
+ $instance = FirePHP::getInstance(true);
133
+ return $instance->getOptions();
134
+ }
135
+
136
+ /**
137
+ * Log object to firebug
138
+ *
139
+ * @see http://www.firephp.org/Wiki/Reference/Fb
140
+ * @param mixed $Object
141
+ * @return true
142
+ * @throws Exception
143
+ */
144
+ public static function send()
145
+ {
146
+ $instance = FirePHP::getInstance(true);
147
+ $args = func_get_args();
148
+ return call_user_func_array(array($instance,'fb'),$args);
149
+ }
150
+
151
+ /**
152
+ * Start a group for following messages
153
+ *
154
+ * Options:
155
+ * Collapsed: [true|false]
156
+ * Color: [#RRGGBB|ColorName]
157
+ *
158
+ * @param string $Name
159
+ * @param array $Options OPTIONAL Instructions on how to log the group
160
+ * @return true
161
+ */
162
+ public static function group($Name, $Options=null)
163
+ {
164
+ $instance = FirePHP::getInstance(true);
165
+ return $instance->group($Name, $Options);
166
+ }
167
+
168
+ /**
169
+ * Ends a group you have started before
170
+ *
171
+ * @return true
172
+ * @throws Exception
173
+ */
174
+ public static function groupEnd()
175
+ {
176
+ return self::send(null, null, FirePHP::GROUP_END);
177
+ }
178
+
179
+ /**
180
+ * Log object with label to firebug console
181
+ *
182
+ * @see FirePHP::LOG
183
+ * @param mixes $Object
184
+ * @param string $Label
185
+ * @return true
186
+ * @throws Exception
187
+ */
188
+ public static function log($Object, $Label=null)
189
+ {
190
+ return self::send($Object, $Label, FirePHP::LOG);
191
+ }
192
+
193
+ /**
194
+ * Log object with label to firebug console
195
+ *
196
+ * @see FirePHP::INFO
197
+ * @param mixes $Object
198
+ * @param string $Label
199
+ * @return true
200
+ * @throws Exception
201
+ */
202
+ public static function info($Object, $Label=null)
203
+ {
204
+ return self::send($Object, $Label, FirePHP::INFO);
205
+ }
206
+
207
+ /**
208
+ * Log object with label to firebug console
209
+ *
210
+ * @see FirePHP::WARN
211
+ * @param mixes $Object
212
+ * @param string $Label
213
+ * @return true
214
+ * @throws Exception
215
+ */
216
+ public static function warn($Object, $Label=null)
217
+ {
218
+ return self::send($Object, $Label, FirePHP::WARN);
219
+ }
220
+
221
+ /**
222
+ * Log object with label to firebug console
223
+ *
224
+ * @see FirePHP::ERROR
225
+ * @param mixes $Object
226
+ * @param string $Label
227
+ * @return true
228
+ * @throws Exception
229
+ */
230
+ public static function error($Object, $Label=null)
231
+ {
232
+ return self::send($Object, $Label, FirePHP::ERROR);
233
+ }
234
+
235
+ /**
236
+ * Dumps key and variable to firebug server panel
237
+ *
238
+ * @see FirePHP::DUMP
239
+ * @param string $Key
240
+ * @param mixed $Variable
241
+ * @return true
242
+ * @throws Exception
243
+ */
244
+ public static function dump($Key, $Variable)
245
+ {
246
+ return self::send($Variable, $Key, FirePHP::DUMP);
247
+ }
248
+
249
+ /**
250
+ * Log a trace in the firebug console
251
+ *
252
+ * @see FirePHP::TRACE
253
+ * @param string $Label
254
+ * @return true
255
+ * @throws Exception
256
+ */
257
+ public static function trace($Label)
258
+ {
259
+ return self::send($Label, FirePHP::TRACE);
260
+ }
261
+
262
+ /**
263
+ * Log a table in the firebug console
264
+ *
265
+ * @see FirePHP::TABLE
266
+ * @param string $Label
267
+ * @param string $Table
268
+ * @return true
269
+ * @throws Exception
270
+ */
271
+ public static function table($Label, $Table)
272
+ {
273
+ return self::send($Table, $Label, FirePHP::TABLE);
274
+ }
275
+
276
+ }
lib/Itm/FirePhp/fb.php4 ADDED
@@ -0,0 +1,251 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* ***** BEGIN LICENSE BLOCK *****
4
+ *
5
+ * This file is part of FirePHP (http://www.firephp.org/).
6
+ *
7
+ * Software License Agreement (New BSD License)
8
+ *
9
+ * Copyright (c) 2006-2010, Christoph Dorn
10
+ * All rights reserved.
11
+ *
12
+ * Redistribution and use in source and binary forms, with or without modification,
13
+ * are permitted provided that the following conditions are met:
14
+ *
15
+ * * Redistributions of source code must retain the above copyright notice,
16
+ * this list of conditions and the following disclaimer.
17
+ *
18
+ * * Redistributions in binary form must reproduce the above copyright notice,
19
+ * this list of conditions and the following disclaimer in the documentation
20
+ * and/or other materials provided with the distribution.
21
+ *
22
+ * * Neither the name of Christoph Dorn nor the names of its
23
+ * contributors may be used to endorse or promote products derived from this
24
+ * software without specific prior written permission.
25
+ *
26
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
27
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
30
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
33
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+ *
37
+ * ***** END LICENSE BLOCK *****
38
+ *
39
+ * @copyright Copyright (C) 2007-2009 Christoph Dorn
40
+ * @author Christoph Dorn <christoph@christophdorn.com>
41
+ * @author Michael Day <manveru.alma@gmail.com>
42
+ * @license http://www.opensource.org/licenses/bsd-license.php
43
+ * @package FirePHPCore
44
+ */
45
+
46
+ require_once dirname(__FILE__).'/FirePHP.class.php4';
47
+
48
+ /**
49
+ * Sends the given data to the FirePHP Firefox Extension.
50
+ * The data can be displayed in the Firebug Console or in the
51
+ * "Server" request tab.
52
+ *
53
+ * @see http://www.firephp.org/Wiki/Reference/Fb
54
+ * @param mixed $Object
55
+ * @return true
56
+ * @throws Exception
57
+ */
58
+ function fb()
59
+ {
60
+ $instance =& FirePHP::getInstance(true);
61
+
62
+ $args = func_get_args();
63
+ return call_user_func_array(array(&$instance,'fb'),$args);
64
+ }
65
+
66
+
67
+ class FB
68
+ {
69
+ /**
70
+ * Enable and disable logging to Firebug
71
+ *
72
+ * @see FirePHP->setEnabled()
73
+ * @param boolean $Enabled TRUE to enable, FALSE to disable
74
+ * @return void
75
+ */
76
+ function setEnabled($Enabled) {
77
+ $instance =& FirePHP::getInstance(true);
78
+ $instance->setEnabled($Enabled);
79
+ }
80
+
81
+ /**
82
+ * Check if logging is enabled
83
+ *
84
+ * @see FirePHP->getEnabled()
85
+ * @return boolean TRUE if enabled
86
+ */
87
+ function getEnabled() {
88
+ $instance =& FirePHP::getInstance(true);
89
+ return $instance->getEnabled();
90
+ }
91
+
92
+ /**
93
+ * Specify a filter to be used when encoding an object
94
+ *
95
+ * Filters are used to exclude object members.
96
+ *
97
+ * @see FirePHP->setObjectFilter()
98
+ * @param string $Class The class name of the object
99
+ * @param array $Filter An array or members to exclude
100
+ * @return void
101
+ */
102
+ function setObjectFilter($Class, $Filter) {
103
+ $instance =& FirePHP::getInstance(true);
104
+ $instance->setObjectFilter($Class, $Filter);
105
+ }
106
+
107
+ /**
108
+ * Set some options for the library
109
+ *
110
+ * @see FirePHP->setOptions()
111
+ * @param array $Options The options to be set
112
+ * @return void
113
+ */
114
+ function setOptions($Options) {
115
+ $instance =& FirePHP::getInstance(true);
116
+ $instance->setOptions($Options);
117
+ }
118
+
119
+ /**
120
+ * Get options for the library
121
+ *
122
+ * @see FirePHP->getOptions()
123
+ * @return array The options
124
+ */
125
+ function getOptions() {
126
+ $instance =& FirePHP::getInstance(true);
127
+ return $instance->getOptions();
128
+ }
129
+
130
+ /**
131
+ * Log object to firebug
132
+ *
133
+ * @see http://www.firephp.org/Wiki/Reference/Fb
134
+ * @param mixed $Object
135
+ * @return true
136
+ */
137
+ function send()
138
+ {
139
+ $instance =& FirePHP::getInstance(true);
140
+ $args = func_get_args();
141
+ return call_user_func_array(array(&$instance,'fb'),$args);
142
+ }
143
+
144
+ /**
145
+ * Start a group for following messages
146
+ *
147
+ * Options:
148
+ * Collapsed: [true|false]
149
+ * Color: [#RRGGBB|ColorName]
150
+ *
151
+ * @param string $Name
152
+ * @param array $Options OPTIONAL Instructions on how to log the group
153
+ * @return true
154
+ */
155
+ function group($Name, $Options=null) {
156
+ $instance =& FirePHP::getInstance(true);
157
+ return $instance->group($Name, $Options);
158
+ }
159
+
160
+ /**
161
+ * Ends a group you have started before
162
+ *
163
+ * @return true
164
+ */
165
+ function groupEnd() {
166
+ return FB::send(null, null, FirePHP_GROUP_END);
167
+ }
168
+
169
+ /**
170
+ * Log object with label to firebug console
171
+ *
172
+ * @see FirePHP::LOG
173
+ * @param mixes $Object
174
+ * @param string $Label
175
+ * @return true
176
+ */
177
+ function log($Object, $Label=null) {
178
+ return FB::send($Object, $Label, FirePHP_LOG);
179
+ }
180
+
181
+ /**
182
+ * Log object with label to firebug console
183
+ *
184
+ * @see FirePHP::INFO
185
+ * @param mixes $Object
186
+ * @param string $Label
187
+ * @return true
188
+ */
189
+ function info($Object, $Label=null) {
190
+ return FB::send($Object, $Label, FirePHP_INFO);
191
+ }
192
+
193
+ /**
194
+ * Log object with label to firebug console
195
+ *
196
+ * @see FirePHP::WARN
197
+ * @param mixes $Object
198
+ * @param string $Label
199
+ * @return true
200
+ */
201
+ function warn($Object, $Label=null) {
202
+ return FB::send($Object, $Label, FirePHP_WARN);
203
+ }
204
+
205
+ /**
206
+ * Log object with label to firebug console
207
+ *
208
+ * @see FirePHP::ERROR
209
+ * @param mixes $Object
210
+ * @param string $Label
211
+ * @return true
212
+ */
213
+ function error($Object, $Label=null) {
214
+ return FB::send($Object, $Label, FirePHP_ERROR);
215
+ }
216
+
217
+ /**
218
+ * Dumps key and variable to firebug server panel
219
+ *
220
+ * @see FirePHP::DUMP
221
+ * @param string $Key
222
+ * @param mixed $Variable
223
+ * @return true
224
+ */
225
+ function dump($Key, $Variable) {
226
+ return FB::send($Variable, $Key, FirePHP_DUMP);
227
+ }
228
+
229
+ /**
230
+ * Log a trace in the firebug console
231
+ *
232
+ * @see FirePHP::TRACE
233
+ * @param string $Label
234
+ * @return true
235
+ */
236
+ function trace($Label) {
237
+ return FB::send($Label, FirePHP_TRACE);
238
+ }
239
+
240
+ /**
241
+ * Log a table in the firebug console
242
+ *
243
+ * @see FirePHP::TABLE
244
+ * @param string $Label
245
+ * @param string $Table
246
+ * @return true
247
+ */
248
+ function table($Label, $Table) {
249
+ return FB::send($Table, $Label, FirePHP_TABLE);
250
+ }
251
+ }
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>ITM_Logger</name>
4
+ <version>0.1.0</version>
5
+ <stability>stable</stability>
6
+ <license>BSD</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>This Extension enable the logging with ChromePHP and FirePHP.</summary>
10
+ <description>This Extension enable the logging with ChromePHP and FirePHP.</description>
11
+ <notes>ChromePHP and FirePHP support.</notes>
12
+ <authors><author><name>Jens Averkamp</name><user>Zeichen32</user><email>j.averkamp@itm-systems.com</email></author></authors>
13
+ <date>2012-10-02</date>
14
+ <time>10:11:26</time>
15
+ <contents><target name="magelib"><dir name="Itm"><dir name="ChromePhp"><file name="ChromePhp.php" hash="6cfd158a43f93c23d622ff101d85d84f"/><file name="README" hash="248a6810348f421e8088e5f15ffdcd95"/></dir><dir name="FirePhp"><file name="FirePHP.class.php" hash="48f5cd9953b22b2520dad0052bb63dfe"/><file name="FirePHP.class.php4" hash="7e3eedc65af89b608c61b8f245339abf"/><file name="LICENSE" hash="6069b4312400e0217c832242b0556b9e"/><file name="fb.php" hash="818b76e245f7c3f370ceba0bec1a53e3"/><file name="fb.php4" hash="2762f10e406c61531ead128394e135ff"/></dir></dir></target><target name="magecommunity"><dir name="Itm"><dir name="Logger"><dir name="Helper"><file name="Data.php" hash="11d6def9f9f4523de0dc683f46c1b286"/></dir><dir name="Model"><file name="ChromePhp.php" hash="50eeba1f5c4cc4f8cac5d3b3771fa189"/><file name="FirePhp.php" hash="4eccd43537ecfca912641ee58f5deaac"/><file name="Logger.php" hash="5805fb3bdcf8ca70475b4d88f5b1911d"/></dir><dir name="etc"><file name="adminhtml.xml" hash="26ea0d8b148585fa65447f5a8f0782c3"/><file name="config.xml" hash="ba204344abb4b29602f090d4ca210b35"/><file name="system.xml" hash="84788fd26e10e51f193d6617e9f09d48"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Itm_Logger.xml" hash="53d7caa96559b6177fd2f263d3c8c36c"/></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
18
+ </package>