WP Super Minify - Version 1.5

Version Description

Download this release

Release Info

Developer dipakcg
Plugin Icon 128x128 WP Super Minify
Version 1.5
Comparing to
See all releases

Code changes from version 1.4 to 1.5

includes/min/builder/_index.js CHANGED
@@ -12,7 +12,7 @@ var MUB = {
12
  $.ajax({
13
  url : '../f=' + testUri + '&' + (new Date()).getTime(),
14
  success : function (data) {
15
- if (data === '1') {
16
  MUB._minRoot = '/min/';
17
  $('span.minRoot').html('/min/');
18
  } else
@@ -26,8 +26,8 @@ var MUB = {
26
  */
27
  newLi : function () {
28
  return '<li id="li' + MUB._uid + '">http://' + location.host + '/<input type=text size=20>' +
29
- ' <button title="Remove">x</button> <button title="Include Earlier">&uarr;</button>' +
30
- ' <button title="Include Later">&darr;</button> <span></span></li>';
31
  },
32
  /**
33
  * Add new empty source LI and attach handlers to buttons
@@ -36,13 +36,13 @@ var MUB = {
36
  $('#sources').append(MUB.newLi());
37
  var li = $('#li' + MUB._uid)[0];
38
  $('button[title=Remove]', li).click(function () {
39
- $('#results').hide();
40
  var hadValue = !!$('input', li)[0].value;
41
  $(li).remove();
42
  });
43
  $('button[title$=Earlier]', li).click(function () {
44
  $(li).prev('li').find('input').each(function () {
45
- $('#results').hide();
46
  // this = previous li input
47
  var tmp = this.value;
48
  this.value = $('input', li).val();
@@ -52,7 +52,7 @@ var MUB = {
52
  });
53
  $('button[title$=Later]', li).click(function () {
54
  $(li).next('li').find('input').each(function () {
55
- $('#results').hide();
56
  // this = next li input
57
  var tmp = this.value;
58
  this.value = $('input', li).val();
@@ -77,9 +77,9 @@ var MUB = {
77
  url : url,
78
  complete : function (xhr, stat) {
79
  if ('success' === stat)
80
- $('span', li).html('&#x2713;');
81
  else {
82
- $('span', li).html('<button><b>404! </b> recheck</button>')
83
  .find('button').click(function () {
84
  MUB.liUpdateTestLink.call(li);
85
  });
@@ -184,16 +184,16 @@ var MUB = {
184
  markup = '<link type="text/css" rel="stylesheet" href="' + uriH + '" />';
185
  }
186
  $('#uriHtml').val(markup);
187
- $('#results').show();
188
  },
189
  /**
190
  * Handler for the "Add file +" button
191
  */
192
  addButtonClick : function () {
193
- $('#results').hide();
194
  MUB.addLi();
195
  MUB.updateAllTestLinks();
196
- $('#update').show().click(MUB.update);
197
  $('#sources li:last input')[0].focus();
198
  },
199
  /**
@@ -201,7 +201,7 @@ var MUB = {
201
  */
202
  init : function () {
203
  $('#jsDidntLoad').remove();
204
- $('#app').show();
205
  $('#sources').html('');
206
  $('#add button').click(MUB.addButtonClick);
207
  // make easier to copy text out of
@@ -213,7 +213,7 @@ var MUB = {
213
  $('a.ext').attr({target:'_blank'});
214
  if (location.hash) {
215
  // make links out of URIs from bookmarklet
216
- $('#getBm').hide();
217
  var i = 0, found = location.hash.substr(1).split(','), l = found.length;
218
  $('#bmUris').html('<p><strong>Found by bookmarklet:</strong> /</p>');
219
  var $p = $('#bmUris p');
@@ -227,7 +227,7 @@ var MUB = {
227
  MUB.addButtonClick();
228
  $('#sources li:last input').val(this.innerHTML);
229
  MUB.liUpdateTestLink.call($('#sources li:last')[0]);
230
- $('#results').hide();
231
  return false;
232
  }).attr({title:'Add file +'});
233
  } else {
12
  $.ajax({
13
  url : '../f=' + testUri + '&' + (new Date()).getTime(),
14
  success : function (data) {
15
+ if (data === '1' || data === '1;') {
16
  MUB._minRoot = '/min/';
17
  $('span.minRoot').html('/min/');
18
  } else
26
  */
27
  newLi : function () {
28
  return '<li id="li' + MUB._uid + '">http://' + location.host + '/<input type=text size=20>' +
29
+ ' <button class="btn btn-danger btn-sm" title="Remove">x</button> <button class="btn btn-default btn-sm" title="Include Earlier">&uarr;</button>' +
30
+ ' <button class="btn btn-default btn-sm" title="Include Later">&darr;</button> <span></span></li>';
31
  },
32
  /**
33
  * Add new empty source LI and attach handlers to buttons
36
  $('#sources').append(MUB.newLi());
37
  var li = $('#li' + MUB._uid)[0];
38
  $('button[title=Remove]', li).click(function () {
39
+ $('#results').addClass('hide');
40
  var hadValue = !!$('input', li)[0].value;
41
  $(li).remove();
42
  });
43
  $('button[title$=Earlier]', li).click(function () {
44
  $(li).prev('li').find('input').each(function () {
45
+ $('#results').addClass('hide');
46
  // this = previous li input
47
  var tmp = this.value;
48
  this.value = $('input', li).val();
52
  });
53
  $('button[title$=Later]', li).click(function () {
54
  $(li).next('li').find('input').each(function () {
55
+ $('#results').addClass('hide');
56
  // this = next li input
57
  var tmp = this.value;
58
  this.value = $('input', li).val();
77
  url : url,
78
  complete : function (xhr, stat) {
79
  if ('success' === stat)
80
+ $('span', li).html('<a href="#" class="btn btn-success btn-sm disabled">&#x2713;</a>');
81
  else {
82
+ $('span', li).html('<button class="btn btn-warning btn-sm"><b>404! </b> recheck</button>')
83
  .find('button').click(function () {
84
  MUB.liUpdateTestLink.call(li);
85
  });
184
  markup = '<link type="text/css" rel="stylesheet" href="' + uriH + '" />';
185
  }
186
  $('#uriHtml').val(markup);
187
+ $('#results').removeClass('hide');
188
  },
189
  /**
190
  * Handler for the "Add file +" button
191
  */
192
  addButtonClick : function () {
193
+ $('#results').addClass('hide');
194
  MUB.addLi();
195
  MUB.updateAllTestLinks();
196
+ $('#update').removeClass('hide').click(MUB.update);
197
  $('#sources li:last input')[0].focus();
198
  },
199
  /**
201
  */
202
  init : function () {
203
  $('#jsDidntLoad').remove();
204
+ $('#app').removeClass('hide');
205
  $('#sources').html('');
206
  $('#add button').click(MUB.addButtonClick);
207
  // make easier to copy text out of
213
  $('a.ext').attr({target:'_blank'});
214
  if (location.hash) {
215
  // make links out of URIs from bookmarklet
216
+ $('#getBm').addClass('hide');
217
  var i = 0, found = location.hash.substr(1).split(','), l = found.length;
218
  $('#bmUris').html('<p><strong>Found by bookmarklet:</strong> /</p>');
219
  var $p = $('#bmUris p');
227
  MUB.addButtonClick();
228
  $('#sources li:last input').val(this.innerHTML);
229
  MUB.liUpdateTestLink.call($('#sources li:last')[0]);
230
+ $('#results').addClass('hide');
231
  return false;
232
  }).attr({title:'Add file +'});
233
  } else {
includes/min/builder/index.php CHANGED
@@ -49,6 +49,7 @@ ob_start();
49
  <!DOCTYPE html>
50
  <title>Minify URI Builder</title>
51
  <meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
 
52
  <style>
53
  body {margin:1em 60px;}
54
  h1, h2, h3 {margin-left:-25px; position:relative;}
@@ -111,7 +112,7 @@ and click [Update].</p>
111
 
112
  <div id=bmUris></div>
113
 
114
- <p><button id=update class=hide>Update</button></p>
115
 
116
  <div id=results class=hide>
117
 
49
  <!DOCTYPE html>
50
  <title>Minify URI Builder</title>
51
  <meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
52
+ <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
53
  <style>
54
  body {margin:1em 60px;}
55
  h1, h2, h3 {margin-left:-25px; position:relative;}
112
 
113
  <div id=bmUris></div>
114
 
115
+ <p><button class="btn btn-primary" id=update class=hide>Update</button></p>
116
 
117
  <div id=results class=hide>
118
 
includes/min/builder/ocCheck.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
  /**
3
  * AJAX checks for zlib.output_compression
4
  *
@@ -11,7 +11,7 @@ $_oc = ini_get('zlib.output_compression');
11
  require dirname(__FILE__) . '/../config.php';
12
  if (! $min_enableBuilder) {
13
  header('Location: /');
14
- exit();
15
  }
16
 
17
  if (isset($_GET['hello'])) {
@@ -26,8 +26,8 @@ if (isset($_GET['hello'])) {
26
  'content' => 'World!'
27
  ,'method' => 'deflate'
28
  ));
29
- $he->encode();
30
- $he->sendAll();
31
 
32
  } else {
33
  // echo status "0" or "1"
1
+ <?php
2
  /**
3
  * AJAX checks for zlib.output_compression
4
  *
11
  require dirname(__FILE__) . '/../config.php';
12
  if (! $min_enableBuilder) {
13
  header('Location: /');
14
+ exit;
15
  }
16
 
17
  if (isset($_GET['hello'])) {
26
  'content' => 'World!'
27
  ,'method' => 'deflate'
28
  ));
29
+ $he->encode();
30
+ $he->sendAll();
31
 
32
  } else {
33
  // echo status "0" or "1"
includes/min/builder/test.php CHANGED
@@ -1,5 +1,5 @@
1
  <?php
2
- exit();
3
  /* currently unused.
4
 
5
  // capture PHP's default setting (may get overridden in config
@@ -8,7 +8,7 @@ $_oc = ini_get('zlib.output_compression');
8
  // allow access only if builder is enabled
9
  require dirname(__FILE__) . '/../config.php';
10
  if (! $min_enableBuilder) {
11
- exit();
12
  }
13
 
14
  if (isset($_GET['oc'])) {
1
  <?php
2
+ exit;
3
  /* currently unused.
4
 
5
  // capture PHP's default setting (may get overridden in config
8
  // allow access only if builder is enabled
9
  require dirname(__FILE__) . '/../config.php';
10
  if (! $min_enableBuilder) {
11
+ exit;
12
  }
13
 
14
  if (isset($_GET['oc'])) {
includes/min/config.php CHANGED
@@ -12,6 +12,13 @@
12
  */
13
  $min_enableBuilder = false;
14
 
 
 
 
 
 
 
 
15
  /**
16
  * If non-empty, the Builder will be protected with HTTP Digest auth.
17
  * The username is "admin".
@@ -52,11 +59,20 @@ $min_allowDebugFlag = false;
52
  //$min_cachePath = 'c:\\WINDOWS\\Temp';
53
  //$min_cachePath = '/tmp';
54
  //$min_cachePath = preg_replace('/^\\d+;/', '', session_save_path());
 
 
 
 
 
 
 
 
 
55
  /**
56
  * To use APC/Memcache/ZendPlatform for cache storage, require the class and
57
  * set $min_cachePath to an instance. Example below:
58
  */
59
- //require dirname(__FILE__) . '/lib/Minify/Cache/APC.php';
60
  //$min_cachePath = new Minify_Cache_APC();
61
 
62
 
@@ -105,6 +121,12 @@ $min_serveOptions['bubbleCssImports'] = false;
105
  $min_serveOptions['maxAge'] = 1800;
106
 
107
 
 
 
 
 
 
 
108
  /**
109
  * To use Google's Closure Compiler API to minify Javascript (falling back to JSMin
110
  * on failure), uncomment the following line:
@@ -173,12 +195,5 @@ $min_symlinks = array();
173
  $min_uploaderHoursBehind = 0;
174
 
175
 
176
- /**
177
- * Path to Minify's lib folder. If you happen to move it, change
178
- * this accordingly.
179
- */
180
- $min_libPath = dirname(__FILE__) . '/lib';
181
-
182
-
183
  // try to disable output_compression (may not have an effect)
184
  ini_set('zlib.output_compression', '0');
12
  */
13
  $min_enableBuilder = false;
14
 
15
+
16
+ /**
17
+ * Concatenate but do not minify the files. This can be used for testing.
18
+ */
19
+ $min_concatOnly = false;
20
+
21
+
22
  /**
23
  * If non-empty, the Builder will be protected with HTTP Digest auth.
24
  * The username is "admin".
59
  //$min_cachePath = 'c:\\WINDOWS\\Temp';
60
  //$min_cachePath = '/tmp';
61
  //$min_cachePath = preg_replace('/^\\d+;/', '', session_save_path());
62
+
63
+
64
+ /**
65
+ * Path to Minify's lib folder. If you happen to move it, change
66
+ * this accordingly.
67
+ */
68
+ $min_libPath = dirname(__FILE__) . '/lib';
69
+
70
+
71
  /**
72
  * To use APC/Memcache/ZendPlatform for cache storage, require the class and
73
  * set $min_cachePath to an instance. Example below:
74
  */
75
+ //require "$min_libPath/Minify/Cache/APC.php";
76
  //$min_cachePath = new Minify_Cache_APC();
77
 
78
 
121
  $min_serveOptions['maxAge'] = 1800;
122
 
123
 
124
+ /**
125
+ * To use CSSmin (Túbal Martín's port of the YUI CSS compressor), uncomment the following line:
126
+ */
127
+ //$min_serveOptions['minifiers']['text/css'] = array('Minify_CSSmin', 'minify');
128
+
129
+
130
  /**
131
  * To use Google's Closure Compiler API to minify Javascript (falling back to JSMin
132
  * on failure), uncomment the following line:
195
  $min_uploaderHoursBehind = 0;
196
 
197
 
 
 
 
 
 
 
 
198
  // try to disable output_compression (may not have an effect)
199
  ini_set('zlib.output_compression', '0');
includes/min/index.php CHANGED
@@ -9,11 +9,23 @@
9
 
10
  define('MINIFY_MIN_DIR', dirname(__FILE__));
11
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  // load config
13
- require MINIFY_MIN_DIR . '/config.php';
14
 
15
  if (isset($_GET['test'])) {
16
- include MINIFY_MIN_DIR . '/config-test.php';
17
  }
18
 
19
  require "$min_libPath/Minify/Loader.php";
@@ -40,6 +52,10 @@ if ($min_allowDebugFlag) {
40
  $min_serveOptions['debug'] = Minify_DebugDetector::shouldDebugRequest($_COOKIE, $_GET, $_SERVER['REQUEST_URI']);
41
  }
42
 
 
 
 
 
43
  if ($min_errorLogger) {
44
  if (true === $min_errorLogger) {
45
  $min_errorLogger = FirePHP::getInstance(true);
@@ -48,25 +64,29 @@ if ($min_errorLogger) {
48
  }
49
 
50
  // check for URI versioning
51
- if (preg_match('/&\\d/', $_SERVER['QUERY_STRING'])) {
52
  $min_serveOptions['maxAge'] = 31536000;
53
  }
 
 
54
  if (isset($_GET['g'])) {
55
  // well need groups config
56
- $min_serveOptions['minApp']['groups'] = (require MINIFY_MIN_DIR . '/groupsConfig.php');
57
  }
58
- if (isset($_GET['f']) || isset($_GET['g'])) {
59
- // serve!
60
 
 
 
61
  if (! isset($min_serveController)) {
62
  $min_serveController = new Minify_Controller_MinApp();
63
- }
 
64
  Minify::serve($min_serveController, $min_serveOptions);
 
65
 
66
  } elseif ($min_enableBuilder) {
67
  header('Location: builder/');
68
- exit();
69
  } else {
70
- header("Location: /");
71
- exit();
72
- }
9
 
10
  define('MINIFY_MIN_DIR', dirname(__FILE__));
11
 
12
+ // set config path defaults
13
+ $min_configPaths = array(
14
+ 'base' => MINIFY_MIN_DIR . '/config.php',
15
+ 'test' => MINIFY_MIN_DIR . '/config-test.php',
16
+ 'groups' => MINIFY_MIN_DIR . '/groupsConfig.php'
17
+ );
18
+
19
+ // check for custom config paths
20
+ if (!empty($min_customConfigPaths) && is_array($min_customConfigPaths)) {
21
+ $min_configPaths = array_merge($min_configPaths, $min_customConfigPaths);
22
+ }
23
+
24
  // load config
25
+ require $min_configPaths['base'];
26
 
27
  if (isset($_GET['test'])) {
28
+ include $min_configPaths['test'];
29
  }
30
 
31
  require "$min_libPath/Minify/Loader.php";
52
  $min_serveOptions['debug'] = Minify_DebugDetector::shouldDebugRequest($_COOKIE, $_GET, $_SERVER['REQUEST_URI']);
53
  }
54
 
55
+ if (!empty($min_concatOnly)) {
56
+ $min_serveOptions['concatOnly'] = true;
57
+ }
58
+
59
  if ($min_errorLogger) {
60
  if (true === $min_errorLogger) {
61
  $min_errorLogger = FirePHP::getInstance(true);
64
  }
65
 
66
  // check for URI versioning
67
+ if (preg_match('/&\\d/', $_SERVER['QUERY_STRING']) || isset($_GET['v'])) {
68
  $min_serveOptions['maxAge'] = 31536000;
69
  }
70
+
71
+ // need groups config?
72
  if (isset($_GET['g'])) {
73
  // well need groups config
74
+ $min_serveOptions['minApp']['groups'] = (require $min_configPaths['groups']);
75
  }
 
 
76
 
77
+ // serve or redirect
78
+ if (isset($_GET['f']) || isset($_GET['g'])) {
79
  if (! isset($min_serveController)) {
80
  $min_serveController = new Minify_Controller_MinApp();
81
+ }
82
+
83
  Minify::serve($min_serveController, $min_serveOptions);
84
+
85
 
86
  } elseif ($min_enableBuilder) {
87
  header('Location: builder/');
88
+ exit;
89
  } else {
90
+ header('Location: /');
91
+ exit;
92
+ }
includes/min/lib/CSSmin.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
 
3
  /*!
4
- * cssmin.php rev ebaf67b 12/06/2013
5
  * Author: Tubal Martin - http://tubalmartin.me/
6
  * Repo: https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port
7
  *
8
- * This is a PHP port of the CSS minification tool distributed with YUICompressor,
9
  * itself a port of the cssmin utility by Isaac Schlueter - http://foohack.com/
10
  * Permission is hereby granted to use the PHP version under the same
11
  * conditions as the YUICompressor.
@@ -92,7 +92,7 @@ class CSSmin
92
  // preserve strings so their content doesn't get accidentally minified
93
  $css = preg_replace_callback('/(?:"(?:[^\\\\"]|\\\\.|\\\\)*")|'."(?:'(?:[^\\\\']|\\\\.|\\\\)*')/S", array($this, 'replace_string'), $css);
94
 
95
- // Let's divide css code in chunks of 25.000 chars aprox.
96
  // Reason: PHP's PCRE functions like preg_replace have a "backtrack limit"
97
  // of 100.000 chars by default (php < 5.3.7) so if we're dealing with really
98
  // long strings and a (sub)pattern matches a number of chars greater than
@@ -101,19 +101,19 @@ class CSSmin
101
  $charset = '';
102
  $charset_regexp = '/(@charset)( [^;]+;)/i';
103
  $css_chunks = array();
104
- $css_chunk_length = 25000; // aprox size, not exact
105
  $start_index = 0;
106
  $i = $css_chunk_length; // save initial iterations
107
  $l = strlen($css);
108
 
109
 
110
- // if the number of characters is 25000 or less, do not chunk
111
  if ($l <= $css_chunk_length) {
112
  $css_chunks[] = $css;
113
  } else {
114
  // chunk css code securely
115
  while ($i < $l) {
116
- $i += 50; // save iterations. 500 checks for a closing curly brace }
117
  if ($l - $start_index <= $css_chunk_length || $i >= $l) {
118
  $css_chunks[] = $this->str_slice($css, $start_index);
119
  break;
@@ -264,6 +264,9 @@ class CSSmin
264
  // Normalize all whitespace strings to single spaces. Easier to work with that way.
265
  $css = preg_replace('/\s+/', ' ', $css);
266
 
 
 
 
267
  // Shorten & preserve calculations calc(...) since spaces are important
268
  $css = preg_replace_callback('/calc(\(((?:[^\(\)]+|(?1))*)\))/i', array($this, 'replace_calc'), $css);
269
 
@@ -288,8 +291,8 @@ class CSSmin
288
  // Remove the spaces before the things that should not have spaces before them.
289
  // But, be careful not to turn "p :link {...}" into "p:link{...}"
290
  // Swap out any pseudo-class colons with the token, and then swap back.
291
- $css = preg_replace_callback('/(?:^|\})(?:(?:[^\{\:])+\:)+(?:[^\{]*\{)/', array($this, 'replace_colon'), $css);
292
-
293
  // Remove spaces before the things that should not have spaces before them.
294
  $css = preg_replace('/\s+([\!\{\}\;\:\>\+\(\)\]\~\=,])/', '$1', $css);
295
 
@@ -317,7 +320,7 @@ class CSSmin
317
  // lower case some common function that can be values
318
  // NOTE: rgb() isn't useful as we replace with #hex later, as well as and() is already done for us
319
  $css = preg_replace_callback('/([:,\( ]\s*)(attr|color-stop|from|rgba|to|url|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?(?:calc|max|min|(?:repeating-)?(?:linear|radial)-gradient)|-webkit-gradient)/iS', array($this, 'lowercase_common_functions_values'), $css);
320
-
321
  // Put the space back in some cases, to support stuff like
322
  // @media screen and (-webkit-min-device-pixel-ratio:0){
323
  $css = preg_replace('/\band\(/i', 'and (', $css);
@@ -333,8 +336,13 @@ class CSSmin
333
  // to avoid issues on Symbian S60 3.x browsers.
334
  $css = preg_replace('/(\*[a-z0-9\-]+\s*\:[^;\}]+)(\})/', '$1;$2', $css);
335
 
336
- // Replace 0 length units 0(px,em,%) with 0.
337
- $css = preg_replace('/(^|[^0-9])(?:0?\.)?0(?:em|ex|ch|rem|vw|vh|vm|vmin|cm|mm|in|px|pt|pc|%|deg|g?rad|m?s|k?hz)/iS', '${1}0', $css);
 
 
 
 
 
338
 
339
  // Replace 0 0; or 0 0 0; or 0 0 0 0; with 0.
340
  $css = preg_replace('/\:0(?: 0){1,3}(;|\}| \!)/', ':0$1', $css);
@@ -373,6 +381,16 @@ class CSSmin
373
  // Add "/" back to fix Opera -o-device-pixel-ratio query
374
  $css = preg_replace('/'. self::QUERY_FRACTION .'/', '/', $css);
375
 
 
 
 
 
 
 
 
 
 
 
376
  // Some source control tools don't like it when files containing lines longer
377
  // than, say 8000 characters, are checked in. The linebreak option is used in
378
  // that case to split long lines after a specific column.
@@ -388,18 +406,8 @@ class CSSmin
388
  }
389
  }
390
 
391
- // Replace multiple semi-colons in a row by a single one
392
- // See SF bug #1980989
393
- $css = preg_replace('/;;+/', ';', $css);
394
-
395
- // Restore new lines for /*! important comments
396
- $css = preg_replace('/'. self::NL .'/', "\n", $css);
397
-
398
- // Lowercase all uppercase properties
399
- $css = preg_replace_callback('/(\{|\;)([A-Z\-]+)(\:)/', array($this, 'lowercase_properties'), $css);
400
-
401
- // restore preserved comments and strings
402
- for ($i = 0, $max = count($this->preserved_tokens); $i < $max; $i++) {
403
  $css = preg_replace('/' . self::TOKEN . $i . '___/', $this->preserved_tokens[$i], $css, 1);
404
  }
405
 
@@ -582,6 +590,17 @@ class CSSmin
582
  return 'calc('. self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . ')';
583
  }
584
 
 
 
 
 
 
 
 
 
 
 
 
585
  private function rgb_to_hex($matches)
586
  {
587
  // Support for percentage values rgb(100%, 0%, 45%);
@@ -638,22 +657,22 @@ class CSSmin
638
  return ':first-'. strtolower($matches[1]) .' '. $matches[2];
639
  }
640
 
641
- private function lowercase_directives($matches)
642
  {
643
  return '@'. strtolower($matches[1]);
644
  }
645
 
646
- private function lowercase_pseudo_elements($matches)
647
  {
648
  return ':'. strtolower($matches[1]);
649
  }
650
 
651
- private function lowercase_common_functions($matches)
652
  {
653
  return ':'. strtolower($matches[1]) .'(';
654
  }
655
 
656
- private function lowercase_common_functions_values($matches)
657
  {
658
  return $matches[1] . strtolower($matches[2]);
659
  }
1
  <?php
2
 
3
  /*!
4
+ * cssmin.php v2.4.8-4
5
  * Author: Tubal Martin - http://tubalmartin.me/
6
  * Repo: https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port
7
  *
8
+ * This is a PHP port of the CSS minification tool distributed with YUICompressor,
9
  * itself a port of the cssmin utility by Isaac Schlueter - http://foohack.com/
10
  * Permission is hereby granted to use the PHP version under the same
11
  * conditions as the YUICompressor.
92
  // preserve strings so their content doesn't get accidentally minified
93
  $css = preg_replace_callback('/(?:"(?:[^\\\\"]|\\\\.|\\\\)*")|'."(?:'(?:[^\\\\']|\\\\.|\\\\)*')/S", array($this, 'replace_string'), $css);
94
 
95
+ // Let's divide css code in chunks of 5.000 chars aprox.
96
  // Reason: PHP's PCRE functions like preg_replace have a "backtrack limit"
97
  // of 100.000 chars by default (php < 5.3.7) so if we're dealing with really
98
  // long strings and a (sub)pattern matches a number of chars greater than
101
  $charset = '';
102
  $charset_regexp = '/(@charset)( [^;]+;)/i';
103
  $css_chunks = array();
104
+ $css_chunk_length = 5000; // aprox size, not exact
105
  $start_index = 0;
106
  $i = $css_chunk_length; // save initial iterations
107
  $l = strlen($css);
108
 
109
 
110
+ // if the number of characters is 5000 or less, do not chunk
111
  if ($l <= $css_chunk_length) {
112
  $css_chunks[] = $css;
113
  } else {
114
  // chunk css code securely
115
  while ($i < $l) {
116
+ $i += 50; // save iterations
117
  if ($l - $start_index <= $css_chunk_length || $i >= $l) {
118
  $css_chunks[] = $this->str_slice($css, $start_index);
119
  break;
264
  // Normalize all whitespace strings to single spaces. Easier to work with that way.
265
  $css = preg_replace('/\s+/', ' ', $css);
266
 
267
+ // Fix IE7 issue on matrix filters which browser accept whitespaces between Matrix parameters
268
+ $css = preg_replace_callback('/\s*filter\:\s*progid:DXImageTransform\.Microsoft\.Matrix\(([^\)]+)\)/', array($this, 'preserve_old_IE_specific_matrix_definition'), $css);
269
+
270
  // Shorten & preserve calculations calc(...) since spaces are important
271
  $css = preg_replace_callback('/calc(\(((?:[^\(\)]+|(?1))*)\))/i', array($this, 'replace_calc'), $css);
272
 
291
  // Remove the spaces before the things that should not have spaces before them.
292
  // But, be careful not to turn "p :link {...}" into "p:link{...}"
293
  // Swap out any pseudo-class colons with the token, and then swap back.
294
+ $css = preg_replace_callback('/(?:^|\})[^\{]*\s+\:/', array($this, 'replace_colon'), $css);
295
+
296
  // Remove spaces before the things that should not have spaces before them.
297
  $css = preg_replace('/\s+([\!\{\}\;\:\>\+\(\)\]\~\=,])/', '$1', $css);
298
 
320
  // lower case some common function that can be values
321
  // NOTE: rgb() isn't useful as we replace with #hex later, as well as and() is already done for us
322
  $css = preg_replace_callback('/([:,\( ]\s*)(attr|color-stop|from|rgba|to|url|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?(?:calc|max|min|(?:repeating-)?(?:linear|radial)-gradient)|-webkit-gradient)/iS', array($this, 'lowercase_common_functions_values'), $css);
323
+
324
  // Put the space back in some cases, to support stuff like
325
  // @media screen and (-webkit-min-device-pixel-ratio:0){
326
  $css = preg_replace('/\band\(/i', 'and (', $css);
336
  // to avoid issues on Symbian S60 3.x browsers.
337
  $css = preg_replace('/(\*[a-z0-9\-]+\s*\:[^;\}]+)(\})/', '$1;$2', $css);
338
 
339
+ // Replace 0 <length> and 0 <percentage> values with 0.
340
+ // <length> data type: https://developer.mozilla.org/en-US/docs/Web/CSS/length
341
+ // <percentage> data type: https://developer.mozilla.org/en-US/docs/Web/CSS/percentage
342
+ $css = preg_replace('/([^\\\\]\:|\s)0(?:em|ex|ch|rem|vw|vh|vm|vmin|cm|mm|in|px|pt|pc|%)/iS', '${1}0', $css);
343
+
344
+ // 0% step in a keyframe? restore the % unit
345
+ $css = preg_replace_callback('/(@[a-z\-]*?keyframes[^\{]+\{)(.*?)(\}\})/iS', array($this, 'replace_keyframe_zero'), $css);
346
 
347
  // Replace 0 0; or 0 0 0; or 0 0 0 0; with 0.
348
  $css = preg_replace('/\:0(?: 0){1,3}(;|\}| \!)/', ':0$1', $css);
381
  // Add "/" back to fix Opera -o-device-pixel-ratio query
382
  $css = preg_replace('/'. self::QUERY_FRACTION .'/', '/', $css);
383
 
384
+ // Replace multiple semi-colons in a row by a single one
385
+ // See SF bug #1980989
386
+ $css = preg_replace('/;;+/', ';', $css);
387
+
388
+ // Restore new lines for /*! important comments
389
+ $css = preg_replace('/'. self::NL .'/', "\n", $css);
390
+
391
+ // Lowercase all uppercase properties
392
+ $css = preg_replace_callback('/(\{|\;)([A-Z\-]+)(\:)/', array($this, 'lowercase_properties'), $css);
393
+
394
  // Some source control tools don't like it when files containing lines longer
395
  // than, say 8000 characters, are checked in. The linebreak option is used in
396
  // that case to split long lines after a specific column.
406
  }
407
  }
408
 
409
+ // restore preserved comments and strings in reverse order
410
+ for ($i = count($this->preserved_tokens) - 1; $i >= 0; $i--) {
 
 
 
 
 
 
 
 
 
 
411
  $css = preg_replace('/' . self::TOKEN . $i . '___/', $this->preserved_tokens[$i], $css, 1);
412
  }
413
 
590
  return 'calc('. self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . ')';
591
  }
592
 
593
+ private function preserve_old_IE_specific_matrix_definition($matches)
594
+ {
595
+ $this->preserved_tokens[] = $matches[1];
596
+ return 'filter:progid:DXImageTransform.Microsoft.Matrix(' . self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . ')';
597
+ }
598
+
599
+ private function replace_keyframe_zero($matches)
600
+ {
601
+ return $matches[1] . preg_replace('/0(\{|,[^\)\{]+\{)/', '0%$1', $matches[2]) . $matches[3];
602
+ }
603
+
604
  private function rgb_to_hex($matches)
605
  {
606
  // Support for percentage values rgb(100%, 0%, 45%);
657
  return ':first-'. strtolower($matches[1]) .' '. $matches[2];
658
  }
659
 
660
+ private function lowercase_directives($matches)
661
  {
662
  return '@'. strtolower($matches[1]);
663
  }
664
 
665
+ private function lowercase_pseudo_elements($matches)
666
  {
667
  return ':'. strtolower($matches[1]);
668
  }
669
 
670
+ private function lowercase_common_functions($matches)
671
  {
672
  return ':'. strtolower($matches[1]) .'(';
673
  }
674
 
675
+ private function lowercase_common_functions_values($matches)
676
  {
677
  return $matches[1] . strtolower($matches[2]);
678
  }
includes/min/lib/DooDigestAuth.php CHANGED
@@ -23,6 +23,8 @@
23
  * @version $Id: DooDigestAuth.php 1000 2009-07-7 18:27:22
24
  * @package doo.auth
25
  * @since 1.0
 
 
26
  */
27
  class DooDigestAuth{
28
 
23
  * @version $Id: DooDigestAuth.php 1000 2009-07-7 18:27:22
24
  * @package doo.auth
25
  * @since 1.0
26
+ *
27
+ * @deprecated 2.3 This will be removed in Minify 3.0
28
  */
29
  class DooDigestAuth{
30
 
includes/min/lib/FirePHP.php CHANGED
@@ -1,47 +1,57 @@
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-2008, 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-2008 Christoph Dorn
40
- * @author Christoph Dorn <christoph@christophdorn.com>
41
- * @license http://www.opensource.org/licenses/bsd-license.php
42
- * @package FirePHP
43
  */
44
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  /**
47
  * Sends the given data to the FirePHP Firefox Extension.
@@ -50,1321 +60,1784 @@
50
  *
51
  * For more information see: http://www.firephp.org/
52
  *
53
- * @copyright Copyright (C) 2007-2008 Christoph Dorn
54
- * @author Christoph Dorn <christoph@christophdorn.com>
55
- * @license http://www.opensource.org/licenses/bsd-license.php
56
- * @package FirePHP
 
 
57
  */
58
  class FirePHP {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
- /**
61
- * FirePHP version
62
- *
63
- * @var string
64
- */
65
- const VERSION = '0.2.0';
66
-
67
- /**
68
- * Firebug LOG level
69
- *
70
- * Logs a message to firebug console.
71
- *
72
- * @var string
73
- */
74
- const LOG = 'LOG';
75
-
76
- /**
77
- * Firebug INFO level
78
- *
79
- * Logs a message to firebug console and displays an info icon before the message.
80
- *
81
- * @var string
82
- */
83
- const INFO = 'INFO';
84
-
85
- /**
86
- * Firebug WARN level
87
- *
88
- * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise.
89
- *
90
- * @var string
91
- */
92
- const WARN = 'WARN';
93
-
94
- /**
95
- * Firebug ERROR level
96
- *
97
- * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count.
98
- *
99
- * @var string
100
- */
101
- const ERROR = 'ERROR';
102
-
103
- /**
104
- * Dumps a variable to firebug's server panel
105
- *
106
- * @var string
107
- */
108
- const DUMP = 'DUMP';
109
-
110
- /**
111
- * Displays a stack trace in firebug console
112
- *
113
- * @var string
114
- */
115
- const TRACE = 'TRACE';
116
-
117
- /**
118
- * Displays an exception in firebug console
119
- *
120
- * Increments the firebug error count.
121
- *
122
- * @var string
123
- */
124
- const EXCEPTION = 'EXCEPTION';
125
-
126
- /**
127
- * Displays an table in firebug console
128
- *
129
- * @var string
130
- */
131
- const TABLE = 'TABLE';
132
-
133
- /**
134
- * Starts a group in firebug console
135
- *
136
- * @var string
137
- */
138
- const GROUP_START = 'GROUP_START';
139
-
140
- /**
141
- * Ends a group in firebug console
142
- *
143
- * @var string
144
- */
145
- const GROUP_END = 'GROUP_END';
146
-
147
- /**
148
- * Singleton instance of FirePHP
149
- *
150
- * @var FirePHP
151
- */
152
- protected static $instance = null;
153
-
154
- /**
155
- * Wildfire protocol message index
156
- *
157
- * @var int
158
- */
159
- protected $messageIndex = 1;
160
 
161
- /**
162
- * Options for the library
163
- *
164
- * @var array
165
- */
166
- protected $options = array();
167
-
168
- /**
169
- * Filters used to exclude object members when encoding
170
- *
171
- * @var array
172
- */
173
- protected $objectFilters = array();
174
-
175
- /**
176
- * A stack of objects used to detect recursion during object encoding
177
- *
178
- * @var object
179
- */
180
- protected $objectStack = array();
181
-
182
- /**
183
- * Flag to enable/disable logging
184
- *
185
- * @var boolean
186
- */
187
- protected $enabled = true;
188
-
189
- /**
190
- * The object constructor
191
- */
192
- function __construct() {
193
- $this->options['maxObjectDepth'] = 10;
194
- $this->options['maxArrayDepth'] = 20;
195
- $this->options['useNativeJsonEncode'] = true;
196
- $this->options['includeLineNumbers'] = true;
197
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
- /**
200
- * When the object gets serialized only include specific object members.
201
- *
202
- * @return array
203
- */
204
- public function __sleep() {
205
- return array('options','objectFilters','enabled');
206
- }
207
 
208
- /**
209
- * Gets singleton instance of FirePHP
210
- *
211
- * @param boolean $AutoCreate
212
- * @return FirePHP
213
- */
214
- public static function getInstance($AutoCreate=false) {
215
- if($AutoCreate===true && !self::$instance) {
216
- self::init();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  }
218
- return self::$instance;
219
- }
220
-
221
- /**
222
- * Creates FirePHP object and stores it for singleton access
223
- *
224
- * @return FirePHP
225
- */
226
- public static function init() {
227
- return self::$instance = new self();
228
- }
229
-
230
- /**
231
- * Enable and disable logging to Firebug
232
- *
233
- * @param boolean $Enabled TRUE to enable, FALSE to disable
234
- * @return void
235
- */
236
- public function setEnabled($Enabled) {
237
- $this->enabled = $Enabled;
238
- }
239
-
240
- /**
241
- * Check if logging is enabled
242
- *
243
- * @return boolean TRUE if enabled
244
- */
245
- public function getEnabled() {
246
- return $this->enabled;
247
- }
248
-
249
- /**
250
- * Specify a filter to be used when encoding an object
251
- *
252
- * Filters are used to exclude object members.
253
- *
254
- * @param string $Class The class name of the object
255
- * @param array $Filter An array or members to exclude
256
- * @return void
257
- */
258
- public function setObjectFilter($Class, $Filter) {
259
- $this->objectFilters[$Class] = $Filter;
260
- }
261
-
262
- /**
263
- * Set some options for the library
264
- *
265
- * Options:
266
- * - maxObjectDepth: The maximum depth to traverse objects (default: 10)
267
- * - maxArrayDepth: The maximum depth to traverse arrays (default: 20)
268
- * - useNativeJsonEncode: If true will use json_encode() (default: true)
269
- * - includeLineNumbers: If true will include line numbers and filenames (default: true)
270
- *
271
- * @param array $Options The options to be set
272
- * @return void
273
- */
274
- public function setOptions($Options) {
275
- $this->options = array_merge($this->options,$Options);
276
- }
277
-
278
- /**
279
- * Register FirePHP as your error handler
280
- *
281
- * Will throw exceptions for each php error.
282
- */
283
- public function registerErrorHandler()
284
- {
285
- //NOTE: The following errors will not be caught by this error handler:
286
- // E_ERROR, E_PARSE, E_CORE_ERROR,
287
- // E_CORE_WARNING, E_COMPILE_ERROR,
288
- // E_COMPILE_WARNING, E_STRICT
289
 
290
- set_error_handler(array($this,'errorHandler'));
291
- }
292
-
293
- /**
294
- * FirePHP's error handler
295
- *
296
- * Throws exception for each php error that will occur.
297
- *
298
- * @param int $errno
299
- * @param string $errstr
300
- * @param string $errfile
301
- * @param int $errline
302
- * @param array $errcontext
303
- */
304
- public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
305
- {
306
- // Don't throw exception if error reporting is switched off
307
- if (error_reporting() == 0) {
308
- return;
309
  }
310
- // Only throw exceptions for errors we are asking for
311
- if (error_reporting() & $errno) {
312
- throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
 
 
 
 
 
 
313
  }
314
- }
315
-
316
- /**
317
- * Register FirePHP as your exception handler
318
- */
319
- public function registerExceptionHandler()
320
- {
321
- set_exception_handler(array($this,'exceptionHandler'));
322
- }
323
-
324
- /**
325
- * FirePHP's exception handler
326
- *
327
- * Logs all exceptions to your firebug console and then stops the script.
328
- *
329
- * @param Exception $Exception
330
- * @throws Exception
331
- */
332
- function exceptionHandler($Exception) {
333
- $this->fb($Exception);
334
- }
335
-
336
- /**
337
- * Set custom processor url for FirePHP
338
- *
339
- * @param string $URL
340
- */
341
- public function setProcessorUrl($URL)
342
- {
343
- $this->setHeader('X-FirePHP-ProcessorURL', $URL);
344
- }
345
-
346
- /**
347
- * Set custom renderer url for FirePHP
348
- *
349
- * @param string $URL
350
- */
351
- public function setRendererUrl($URL)
352
- {
353
- $this->setHeader('X-FirePHP-RendererURL', $URL);
354
- }
355
-
356
- /**
357
- * Start a group for following messages
358
- *
359
- * @param string $Name
360
- * @return true
361
- * @throws Exception
362
- */
363
- public function group($Name) {
364
- return $this->fb(null, $Name, FirePHP::GROUP_START);
365
- }
366
-
367
- /**
368
- * Ends a group you have started before
369
- *
370
- * @return true
371
- * @throws Exception
372
- */
373
- public function groupEnd() {
374
- return $this->fb(null, null, FirePHP::GROUP_END);
375
- }
376
-
377
- /**
378
- * Log object with label to firebug console
379
- *
380
- * @see FirePHP::LOG
381
- * @param mixes $Object
382
- * @param string $Label
383
- * @return true
384
- * @throws Exception
385
- */
386
- public function log($Object, $Label=null) {
387
- return $this->fb($Object, $Label, FirePHP::LOG);
388
- }
389
-
390
- /**
391
- * Log object with label to firebug console
392
- *
393
- * @see FirePHP::INFO
394
- * @param mixes $Object
395
- * @param string $Label
396
- * @return true
397
- * @throws Exception
398
- */
399
- public function info($Object, $Label=null) {
400
- return $this->fb($Object, $Label, FirePHP::INFO);
401
- }
402
-
403
- /**
404
- * Log object with label to firebug console
405
- *
406
- * @see FirePHP::WARN
407
- * @param mixes $Object
408
- * @param string $Label
409
- * @return true
410
- * @throws Exception
411
- */
412
- public function warn($Object, $Label=null) {
413
- return $this->fb($Object, $Label, FirePHP::WARN);
414
- }
415
-
416
- /**
417
- * Log object with label to firebug console
418
- *
419
- * @see FirePHP::ERROR
420
- * @param mixes $Object
421
- * @param string $Label
422
- * @return true
423
- * @throws Exception
424
- */
425
- public function error($Object, $Label=null) {
426
- return $this->fb($Object, $Label, FirePHP::ERROR);
427
- }
428
-
429
- /**
430
- * Dumps key and variable to firebug server panel
431
- *
432
- * @see FirePHP::DUMP
433
- * @param string $Key
434
- * @param mixed $Variable
435
- * @return true
436
- * @throws Exception
437
- */
438
- public function dump($Key, $Variable) {
439
- return $this->fb($Variable, $Key, FirePHP::DUMP);
440
- }
441
-
442
- /**
443
- * Log a trace in the firebug console
444
- *
445
- * @see FirePHP::TRACE
446
- * @param string $Label
447
- * @return true
448
- * @throws Exception
449
- */
450
- public function trace($Label) {
451
- return $this->fb($Label, FirePHP::TRACE);
452
- }
453
-
454
- /**
455
- * Log a table in the firebug console
456
- *
457
- * @see FirePHP::TABLE
458
- * @param string $Label
459
- * @param string $Table
460
- * @return true
461
- * @throws Exception
462
- */
463
- public function table($Label, $Table) {
464
- return $this->fb($Table, $Label, FirePHP::TABLE);
465
- }
466
-
467
- /**
468
- * Check if FirePHP is installed on client
469
- *
470
- * @return boolean
471
- */
472
- public function detectClientExtension() {
473
- /* Check if FirePHP is installed on client */
474
- if(!@preg_match_all('/\sFirePHP\/([\.|\d]*)\s?/si',$this->getUserAgent(),$m) ||
475
- !version_compare($m[1][0],'0.0.6','>=')) {
476
- return false;
477
  }
478
- return true;
479
- }
480
-
481
- /**
482
- * Log varible to Firebug
483
- *
484
- * @see http://www.firephp.org/Wiki/Reference/Fb
485
- * @param mixed $Object The variable to be logged
486
- * @return true Return TRUE if message was added to headers, FALSE otherwise
487
- * @throws Exception
488
- */
489
- public function fb($Object) {
490
 
491
- if(!$this->enabled) {
492
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
493
  }
494
 
495
- if (headers_sent($filename, $linenum)) {
496
- 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.');
 
 
 
 
 
 
 
 
497
  }
498
 
499
- $Type = null;
500
- $Label = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
501
 
502
- if(func_num_args()==1) {
503
- } else
504
- if(func_num_args()==2) {
505
- switch(func_get_arg(1)) {
506
- case self::LOG:
507
- case self::INFO:
508
- case self::WARN:
509
- case self::ERROR:
510
- case self::DUMP:
511
- case self::TRACE:
512
- case self::EXCEPTION:
513
- case self::TABLE:
514
- case self::GROUP_START:
515
- case self::GROUP_END:
516
- $Type = func_get_arg(1);
517
- break;
518
- default:
519
- $Label = func_get_arg(1);
520
- break;
521
- }
522
- } else
523
- if(func_num_args()==3) {
524
- $Type = func_get_arg(2);
525
- $Label = func_get_arg(1);
526
- } else {
527
- throw $this->newException('Wrong number of arguments to fb() function!');
528
  }
529
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
530
 
531
- if(!$this->detectClientExtension()) {
532
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533
  }
534
 
535
- $meta = array();
536
- $skipFinalObjectEncode = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
537
 
538
- if($Object instanceof Exception) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
 
540
- $meta['file'] = $this->_escapeTraceFile($Object->getFile());
541
- $meta['line'] = $Object->getLine();
542
-
543
- $trace = $Object->getTrace();
544
- if($Object instanceof ErrorException
545
- && isset($trace[0]['function'])
546
- && $trace[0]['function']=='errorHandler'
547
- && isset($trace[0]['class'])
548
- && $trace[0]['class']=='FirePHP') {
549
-
550
- $severity = false;
551
- switch($Object->getSeverity()) {
552
- case E_WARNING: $severity = 'E_WARNING'; break;
553
- case E_NOTICE: $severity = 'E_NOTICE'; break;
554
- case E_USER_ERROR: $severity = 'E_USER_ERROR'; break;
555
- case E_USER_WARNING: $severity = 'E_USER_WARNING'; break;
556
- case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break;
557
- case E_STRICT: $severity = 'E_STRICT'; break;
558
- case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break;
559
- case E_DEPRECATED: $severity = 'E_DEPRECATED'; break;
560
- case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break;
561
  }
562
-
563
- $Object = array('Class'=>get_class($Object),
564
- 'Message'=>$severity.': '.$Object->getMessage(),
565
- 'File'=>$this->_escapeTraceFile($Object->getFile()),
566
- 'Line'=>$Object->getLine(),
567
- 'Type'=>'trigger',
568
- 'Trace'=>$this->_escapeTrace(array_splice($trace,2)));
569
- $skipFinalObjectEncode = true;
570
- } else {
571
- $Object = array('Class'=>get_class($Object),
572
- 'Message'=>$Object->getMessage(),
573
- 'File'=>$this->_escapeTraceFile($Object->getFile()),
574
- 'Line'=>$Object->getLine(),
575
- 'Type'=>'throw',
576
- 'Trace'=>$this->_escapeTrace($trace));
577
- $skipFinalObjectEncode = true;
578
- }
579
- $Type = self::EXCEPTION;
580
-
581
- } else
582
- if($Type==self::TRACE) {
583
-
584
- $trace = debug_backtrace();
585
- if(!$trace) return false;
586
- for( $i=0 ; $i<sizeof($trace) ; $i++ ) {
587
-
588
- if(isset($trace[$i]['class'])
589
- && isset($trace[$i]['file'])
590
- && ($trace[$i]['class']=='FirePHP'
591
- || $trace[$i]['class']=='FB')
592
- && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
593
- || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
594
- /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
595
- } else
596
- if(isset($trace[$i]['class'])
597
- && isset($trace[$i+1]['file'])
598
- && $trace[$i]['class']=='FirePHP'
599
- && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
600
- /* Skip fb() */
601
  } else
602
- if($trace[$i]['function']=='fb'
603
- || $trace[$i]['function']=='trace'
604
- || $trace[$i]['function']=='send') {
605
- $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'',
606
- 'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'',
607
- 'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'',
608
- 'Message'=>$trace[$i]['args'][0],
609
- 'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'',
610
- 'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'',
611
- 'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'',
612
- 'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1)));
613
-
614
- $skipFinalObjectEncode = true;
615
- $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
616
- $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
617
- break;
 
 
 
 
 
 
618
  }
619
- }
620
 
621
- } else
622
- if($Type==self::TABLE) {
623
-
624
- if(isset($Object[0]) && is_string($Object[0])) {
625
- $Object[1] = $this->encodeTable($Object[1]);
626
- } else {
627
- $Object = $this->encodeTable($Object);
628
- }
629
 
630
- $skipFinalObjectEncode = true;
631
-
632
- } else {
633
- if($Type===null) {
634
- $Type = self::LOG;
635
- }
636
- }
637
-
638
- if($this->options['includeLineNumbers']) {
639
- if(!isset($meta['file']) || !isset($meta['line'])) {
640
 
641
- $trace = debug_backtrace();
642
- for( $i=0 ; $trace && $i<sizeof($trace) ; $i++ ) {
643
-
644
- if(isset($trace[$i]['class'])
645
- && isset($trace[$i]['file'])
646
- && ($trace[$i]['class']=='FirePHP'
647
- || $trace[$i]['class']=='FB')
648
- && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php'
649
- || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.class.php')) {
650
- /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
651
- } else
652
- if(isset($trace[$i]['class'])
653
- && isset($trace[$i+1]['file'])
654
- && $trace[$i]['class']=='FirePHP'
655
- && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') {
656
- /* Skip fb() */
657
- } else
658
- if(isset($trace[$i]['file'])
659
- && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') {
660
- /* Skip FB::fb() */
661
- } else {
662
- $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'';
663
- $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:'';
664
- break;
665
- }
666
- }
667
 
668
- }
669
- } else {
670
- unset($meta['file']);
671
- unset($meta['line']);
672
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
 
674
- $this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
675
- $this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION);
676
-
677
- $structure_index = 1;
678
- if($Type==self::DUMP) {
679
- $structure_index = 2;
680
- $this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');
681
- } else {
682
- $this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
683
- }
684
-
685
- if($Type==self::DUMP) {
686
- $msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}';
687
- } else {
688
- $msg_meta = array('Type'=>$Type);
689
- if($Label!==null) {
690
- $msg_meta['Label'] = $Label;
691
- }
692
- if(isset($meta['file'])) {
693
- $msg_meta['File'] = $meta['file'];
694
- }
695
- if(isset($meta['line'])) {
696
- $msg_meta['Line'] = $meta['line'];
697
- }
698
- $msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']';
699
- }
700
-
701
- $parts = explode("\n",chunk_split($msg, 5000, "\n"));
 
 
 
 
 
702
 
703
- for( $i=0 ; $i<count($parts) ; $i++) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
704
 
705
- $part = $parts[$i];
706
- if ($part) {
707
-
708
- if(count($parts)>2) {
709
- // Message needs to be split into multiple parts
710
- $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
711
- (($i==0)?strlen($msg):'')
712
- . '|' . $part . '|'
713
- . (($i<count($parts)-2)?'\\':''));
 
 
 
714
  } else {
715
- $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex,
716
- strlen($part) . '|' . $part . '|');
717
  }
718
-
719
- $this->messageIndex++;
720
-
721
- if ($this->messageIndex > 99999) {
722
- throw new Exception('Maximum number (99,999) of messages reached!');
 
 
 
 
 
 
 
723
  }
724
  }
725
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
726
 
727
- $this->setHeader('X-Wf-1-Index',$this->messageIndex-1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
728
 
729
- return true;
730
- }
731
-
732
- /**
733
- * Standardizes path for windows systems.
734
- *
735
- * @param string $Path
736
- * @return string
737
- */
738
- protected function _standardizePath($Path) {
739
- return preg_replace('/\\\\+/','/',$Path);
740
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
741
 
742
- /**
743
- * Escape trace path for windows systems
744
- *
745
- * @param array $Trace
746
- * @return array
747
- */
748
- protected function _escapeTrace($Trace) {
749
- if(!$Trace) return $Trace;
750
- for( $i=0 ; $i<sizeof($Trace) ; $i++ ) {
751
- if(isset($Trace[$i]['file'])) {
752
- $Trace[$i]['file'] = $this->_escapeTraceFile($Trace[$i]['file']);
753
- }
754
- if(isset($Trace[$i]['args'])) {
755
- $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']);
756
- }
757
  }
758
- return $Trace;
759
- }
760
 
761
- /**
762
- * Escape file information of trace for windows systems
763
- *
764
- * @param string $File
765
- * @return string
766
- */
767
- protected function _escapeTraceFile($File) {
768
- /* Check if we have a windows filepath */
769
- if(strpos($File,'\\')) {
770
- /* First strip down to single \ */
771
-
772
- $file = preg_replace('/\\\\+/','\\',$File);
773
-
774
- return $file;
 
 
 
 
775
  }
776
- return $File;
777
- }
778
-
779
- /**
780
- * Send header
781
- *
782
- * @param string $Name
783
- * @param string_type $Value
784
- */
785
- protected function setHeader($Name, $Value) {
786
- return header($Name.': '.$Value);
787
- }
788
-
789
- /**
790
- * Get user agent
791
- *
792
- * @return string|false
793
- */
794
- protected function getUserAgent() {
795
- if(!isset($_SERVER['HTTP_USER_AGENT'])) return false;
796
- return $_SERVER['HTTP_USER_AGENT'];
797
- }
798
-
799
- /**
800
- * Returns a new exception
801
- *
802
- * @param string $Message
803
- * @return Exception
804
- */
805
- protected function newException($Message) {
806
- return new Exception($Message);
807
- }
808
 
809
- /**
810
- * Encode an object into a JSON string
811
- *
812
- * Uses PHP's jeson_encode() if available
813
- *
814
- * @param object $Object The object to be encoded
815
- * @return string The JSON string
816
- */
817
- protected function jsonEncode($Object, $skipObjectEncode=false)
818
- {
819
- if(!$skipObjectEncode) {
820
- $Object = $this->encodeObject($Object);
 
 
 
 
 
821
  }
822
-
823
- if(function_exists('json_encode')
824
- && $this->options['useNativeJsonEncode']!=false) {
825
 
826
- return json_encode($Object);
827
- } else {
828
- return $this->json_encode($Object);
 
 
 
 
 
 
829
  }
830
- }
831
-
832
- /**
833
- * Encodes a table by encoding each row and column with encodeObject()
834
- *
835
- * @param array $Table The table to be encoded
836
- * @return array
837
- */
838
- protected function encodeTable($Table) {
839
- if(!$Table) return $Table;
840
- for( $i=0 ; $i<count($Table) ; $i++ ) {
841
- if(is_array($Table[$i])) {
842
- for( $j=0 ; $j<count($Table[$i]) ; $j++ ) {
843
- $Table[$i][$j] = $this->encodeObject($Table[$i][$j]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
844
  }
845
- }
 
 
 
 
 
 
 
 
 
 
 
846
  }
847
- return $Table;
848
- }
849
 
850
- /**
851
- * Encodes an object including members with
852
- * protected and private visibility
853
- *
854
- * @param Object $Object The object to be encoded
855
- * @param int $Depth The current traversal depth
856
- * @return array All members of the object
857
- */
858
- protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1)
859
- {
860
- $return = array();
 
 
 
 
 
 
861
 
862
- if (is_object($Object)) {
863
-
864
- if ($ObjectDepth > $this->options['maxObjectDepth']) {
865
- return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **';
866
  }
 
 
 
 
 
 
 
 
 
 
 
867
 
868
- foreach ($this->objectStack as $refVal) {
869
- if ($refVal === $Object) {
870
- return '** Recursion ('.get_class($Object).') **';
 
 
 
 
 
 
 
 
871
  }
872
  }
873
- array_push($this->objectStack, $Object);
874
-
875
- $return['__className'] = $class = get_class($Object);
876
 
877
- $reflectionClass = new ReflectionClass($class);
878
- $properties = array();
879
- foreach( $reflectionClass->getProperties() as $property) {
880
- $properties[$property->getName()] = $property;
 
 
 
 
 
 
 
 
 
 
 
881
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
882
 
883
- $members = (array)$Object;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
884
 
885
- foreach( $properties as $raw_name => $property ) {
886
-
887
- $name = $raw_name;
888
- if($property->isStatic()) {
889
- $name = 'static:'.$name;
890
- }
891
- if($property->isPublic()) {
892
- $name = 'public:'.$name;
893
- } else
894
- if($property->isPrivate()) {
895
- $name = 'private:'.$name;
896
- $raw_name = "\0".$class."\0".$raw_name;
897
- } else
898
- if($property->isProtected()) {
899
- $name = 'protected:'.$name;
900
- $raw_name = "\0".'*'."\0".$raw_name;
901
- }
902
-
903
- if(!(isset($this->objectFilters[$class])
904
- && is_array($this->objectFilters[$class])
905
- && in_array($raw_name,$this->objectFilters[$class]))) {
906
 
907
- if(array_key_exists($raw_name,$members)
908
- && !$property->isStatic()) {
909
-
910
- $return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
911
 
912
- } else {
913
- if(method_exists($property,'setAccessible')) {
914
- $property->setAccessible(true);
915
- $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1);
916
- } else
917
- if($property->isPublic()) {
918
- $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1);
919
- } else {
920
- $return[$name] = '** Need PHP 5.3 to get value **';
921
- }
922
  }
923
- } else {
924
- $return[$name] = '** Excluded by Filter **';
925
- }
926
- }
927
-
928
- // Include all members that are not defined in the class
929
- // but exist in the object
930
- foreach( $members as $raw_name => $value ) {
931
 
932
- $name = $raw_name;
933
-
934
- if ($name{0} == "\0") {
935
- $parts = explode("\0", $name);
936
- $name = $parts[2];
937
- }
938
-
939
- if(!isset($properties[$name])) {
940
- $name = 'undeclared:'.$name;
941
-
942
- if(!(isset($this->objectFilters[$class])
943
- && is_array($this->objectFilters[$class])
944
- && in_array($raw_name,$this->objectFilters[$class]))) {
945
-
946
- $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1);
 
 
 
 
 
 
 
 
 
 
 
 
947
  } else {
948
- $return[$name] = '** Excluded by Filter **';
949
  }
950
- }
951
  }
952
-
953
- array_pop($this->objectStack);
954
-
955
- } elseif (is_array($Object)) {
956
 
957
- if ($ArrayDepth > $this->options['maxArrayDepth']) {
958
- return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **';
 
 
 
 
 
 
 
 
 
 
 
959
  }
960
-
961
- foreach ($Object as $key => $val) {
962
-
963
- // Encoding the $GLOBALS PHP array causes an infinite loop
964
- // if the recursion is not reset here as it contains
965
- // a reference to itself. This is the only way I have come up
966
- // with to stop infinite recursion in this case.
967
- if($key=='GLOBALS'
968
- && is_array($val)
969
- && array_key_exists('GLOBALS',$val)) {
970
- $val['GLOBALS'] = '** Recursion (GLOBALS) **';
971
- }
972
-
973
- $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1);
974
- }
975
- } else {
976
- if(self::is_utf8($Object)) {
977
- return $Object;
978
- } else {
979
- return utf8_encode($Object);
980
- }
981
- }
982
- return $return;
983
- }
984
-
985
- /**
986
- * Returns true if $string is valid UTF-8 and false otherwise.
987
- *
988
- * @param mixed $str String to be tested
989
- * @return boolean
990
- */
991
- protected static function is_utf8($str) {
992
- $c=0; $b=0;
993
- $bits=0;
994
- $len=strlen($str);
995
- for($i=0; $i<$len; $i++){
996
- $c=ord($str[$i]);
997
- if($c > 128){
998
- if(($c >= 254)) return false;
999
- elseif($c >= 252) $bits=6;
1000
- elseif($c >= 248) $bits=5;
1001
- elseif($c >= 240) $bits=4;
1002
- elseif($c >= 224) $bits=3;
1003
- elseif($c >= 192) $bits=2;
1004
- else return false;
1005
- if(($i+$bits) > $len) return false;
1006
- while($bits > 1){
1007
- $i++;
1008
- $b=ord($str[$i]);
1009
- if($b < 128 || $b > 191) return false;
1010
- $bits--;
1011
  }
1012
  }
1013
- }
1014
- return true;
1015
- }
1016
-
1017
- /**
1018
- * Converts to and from JSON format.
1019
- *
1020
- * JSON (JavaScript Object Notation) is a lightweight data-interchange
1021
- * format. It is easy for humans to read and write. It is easy for machines
1022
- * to parse and generate. It is based on a subset of the JavaScript
1023
- * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
1024
- * This feature can also be found in Python. JSON is a text format that is
1025
- * completely language independent but uses conventions that are familiar
1026
- * to programmers of the C-family of languages, including C, C++, C#, Java,
1027
- * JavaScript, Perl, TCL, and many others. These properties make JSON an
1028
- * ideal data-interchange language.
1029
- *
1030
- * This package provides a simple encoder and decoder for JSON notation. It
1031
- * is intended for use with client-side Javascript applications that make
1032
- * use of HTTPRequest to perform server communication functions - data can
1033
- * be encoded into JSON notation for use in a client-side javascript, or
1034
- * decoded from incoming Javascript requests. JSON format is native to
1035
- * Javascript, and can be directly eval()'ed with no further parsing
1036
- * overhead
1037
- *
1038
- * All strings should be in ASCII or UTF-8 format!
1039
- *
1040
- * LICENSE: Redistribution and use in source and binary forms, with or
1041
- * without modification, are permitted provided that the following
1042
- * conditions are met: Redistributions of source code must retain the
1043
- * above copyright notice, this list of conditions and the following
1044
- * disclaimer. Redistributions in binary form must reproduce the above
1045
- * copyright notice, this list of conditions and the following disclaimer
1046
- * in the documentation and/or other materials provided with the
1047
- * distribution.
1048
- *
1049
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1050
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1051
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
1052
- * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
1053
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
1054
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
1055
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1056
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
1057
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1058
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1059
- * DAMAGE.
1060
- *
1061
- * @category
1062
- * @package Services_JSON
1063
- * @author Michal Migurski <mike-json@teczno.com>
1064
- * @author Matt Knapp <mdknapp[at]gmail[dot]com>
1065
- * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
1066
- * @author Christoph Dorn <christoph@christophdorn.com>
1067
- * @copyright 2005 Michal Migurski
1068
- * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
1069
- * @license http://www.opensource.org/licenses/bsd-license.php
1070
- * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
1071
- */
1072
 
1073
 
1074
- /**
1075
- * Keep a list of objects as we descend into the array so we can detect recursion.
1076
- */
1077
- private $json_objectStack = array();
1078
-
1079
-
1080
- /**
1081
- * convert a string from one UTF-8 char to one UTF-16 char
1082
- *
1083
- * Normally should be handled by mb_convert_encoding, but
1084
- * provides a slower PHP-only method for installations
1085
- * that lack the multibye string extension.
1086
- *
1087
- * @param string $utf8 UTF-8 character
1088
- * @return string UTF-16 character
1089
- * @access private
1090
- */
1091
- private function json_utf82utf16($utf8)
1092
- {
1093
- // oh please oh please oh please oh please oh please
1094
- if(function_exists('mb_convert_encoding')) {
1095
- return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
1096
- }
1097
-
1098
- switch(strlen($utf8)) {
1099
- case 1:
1100
- // this case should never be reached, because we are in ASCII range
1101
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1102
- return $utf8;
1103
-
1104
- case 2:
1105
- // return a UTF-16 character from a 2-byte UTF-8 char
1106
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1107
- return chr(0x07 & (ord($utf8{0}) >> 2))
1108
- . chr((0xC0 & (ord($utf8{0}) << 6))
1109
  | (0x3F & ord($utf8{1})));
1110
 
1111
- case 3:
1112
- // return a UTF-16 character from a 3-byte UTF-8 char
1113
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1114
- return chr((0xF0 & (ord($utf8{0}) << 4))
1115
  | (0x0F & (ord($utf8{1}) >> 2)))
1116
- . chr((0xC0 & (ord($utf8{1}) << 6))
1117
  | (0x7F & ord($utf8{2})));
1118
- }
1119
-
1120
- // ignoring UTF-32 for now, sorry
1121
- return '';
1122
- }
1123
-
1124
- /**
1125
- * encodes an arbitrary variable into JSON format
1126
- *
1127
- * @param mixed $var any number, boolean, string, array, or object to be encoded.
1128
- * see argument 1 to Services_JSON() above for array-parsing behavior.
1129
- * if var is a strng, note that encode() always expects it
1130
- * to be in ASCII or UTF-8 format!
1131
- *
1132
- * @return mixed JSON string representation of input var or an error if a problem occurs
1133
- * @access public
1134
- */
1135
- private function json_encode($var)
1136
- {
1137
-
1138
- if(is_object($var)) {
1139
- if(in_array($var,$this->json_objectStack)) {
1140
- return '"** Recursion **"';
1141
- }
1142
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1143
 
1144
- switch (gettype($var)) {
1145
- case 'boolean':
1146
- return $var ? 'true' : 'false';
1147
-
1148
- case 'NULL':
1149
- return 'null';
1150
-
1151
- case 'integer':
1152
- return (int) $var;
1153
-
1154
- case 'double':
1155
- case 'float':
1156
- return (float) $var;
1157
-
1158
- case 'string':
1159
- // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
1160
- $ascii = '';
1161
- $strlen_var = strlen($var);
1162
-
1163
- /*
1164
- * Iterate over every character in the string,
1165
- * escaping with a slash or encoding to UTF-8 where necessary
1166
- */
1167
- for ($c = 0; $c < $strlen_var; ++$c) {
1168
-
1169
- $ord_var_c = ord($var{$c});
1170
-
1171
- switch (true) {
1172
- case $ord_var_c == 0x08:
1173
- $ascii .= '\b';
1174
- break;
1175
- case $ord_var_c == 0x09:
1176
- $ascii .= '\t';
1177
- break;
1178
- case $ord_var_c == 0x0A:
1179
- $ascii .= '\n';
1180
- break;
1181
- case $ord_var_c == 0x0C:
1182
- $ascii .= '\f';
1183
- break;
1184
- case $ord_var_c == 0x0D:
1185
- $ascii .= '\r';
1186
- break;
1187
-
1188
- case $ord_var_c == 0x22:
1189
- case $ord_var_c == 0x2F:
1190
- case $ord_var_c == 0x5C:
1191
- // double quote, slash, slosh
1192
- $ascii .= '\\'.$var{$c};
1193
- break;
1194
-
1195
- case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
1196
- // characters U-00000000 - U-0000007F (same as ASCII)
1197
- $ascii .= $var{$c};
1198
- break;
1199
-
1200
- case (($ord_var_c & 0xE0) == 0xC0):
1201
- // characters U-00000080 - U-000007FF, mask 110XXXXX
1202
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1203
- $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
1204
- $c += 1;
1205
- $utf16 = $this->json_utf82utf16($char);
1206
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
1207
- break;
1208
-
1209
- case (($ord_var_c & 0xF0) == 0xE0):
1210
- // characters U-00000800 - U-0000FFFF, mask 1110XXXX
1211
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1212
- $char = pack('C*', $ord_var_c,
1213
- ord($var{$c + 1}),
1214
- ord($var{$c + 2}));
1215
- $c += 2;
1216
- $utf16 = $this->json_utf82utf16($char);
1217
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
1218
- break;
1219
-
1220
- case (($ord_var_c & 0xF8) == 0xF0):
1221
- // characters U-00010000 - U-001FFFFF, mask 11110XXX
1222
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1223
- $char = pack('C*', $ord_var_c,
1224
- ord($var{$c + 1}),
1225
- ord($var{$c + 2}),
1226
- ord($var{$c + 3}));
1227
- $c += 3;
1228
- $utf16 = $this->json_utf82utf16($char);
1229
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
1230
- break;
1231
-
1232
- case (($ord_var_c & 0xFC) == 0xF8):
1233
- // characters U-00200000 - U-03FFFFFF, mask 111110XX
1234
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1235
- $char = pack('C*', $ord_var_c,
1236
- ord($var{$c + 1}),
1237
- ord($var{$c + 2}),
1238
- ord($var{$c + 3}),
1239
- ord($var{$c + 4}));
1240
- $c += 4;
1241
- $utf16 = $this->json_utf82utf16($char);
1242
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
1243
- break;
1244
-
1245
- case (($ord_var_c & 0xFE) == 0xFC):
1246
- // characters U-04000000 - U-7FFFFFFF, mask 1111110X
1247
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1248
- $char = pack('C*', $ord_var_c,
1249
- ord($var{$c + 1}),
1250
- ord($var{$c + 2}),
1251
- ord($var{$c + 3}),
1252
- ord($var{$c + 4}),
1253
- ord($var{$c + 5}));
1254
- $c += 5;
1255
- $utf16 = $this->json_utf82utf16($char);
1256
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
1257
- break;
1258
- }
1259
- }
1260
-
1261
- return '"'.$ascii.'"';
1262
-
1263
- case 'array':
1264
- /*
1265
- * As per JSON spec if any array key is not an integer
1266
- * we must treat the the whole array as an object. We
1267
- * also try to catch a sparsely populated associative
1268
- * array with numeric keys here because some JS engines
1269
- * will create an array with empty indexes up to
1270
- * max_index which can cause memory issues and because
1271
- * the keys, which may be relevant, will be remapped
1272
- * otherwise.
1273
- *
1274
- * As per the ECMA and JSON specification an object may
1275
- * have any string as a property. Unfortunately due to
1276
- * a hole in the ECMA specification if the key is a
1277
- * ECMA reserved word or starts with a digit the
1278
- * parameter is only accessible using ECMAScript's
1279
- * bracket notation.
1280
- */
1281
-
1282
- // treat as a JSON object
1283
- if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
1284
 
1285
- $this->json_objectStack[] = $var;
1286
 
1287
- $properties = array_map(array($this, 'json_name_value'),
1288
- array_keys($var),
1289
- array_values($var));
1290
 
1291
- array_pop($this->json_objectStack);
1292
 
1293
- foreach($properties as $property) {
1294
- if($property instanceof Exception) {
1295
- return $property;
1296
- }
1297
- }
1298
 
1299
- return '{' . join(',', $properties) . '}';
1300
- }
1301
 
1302
- $this->json_objectStack[] = $var;
1303
 
1304
- // treat it like a regular array
1305
- $elements = array_map(array($this, 'json_encode'), $var);
1306
 
1307
- array_pop($this->json_objectStack);
1308
 
1309
- foreach($elements as $element) {
1310
- if($element instanceof Exception) {
1311
- return $element;
1312
- }
1313
- }
1314
 
1315
- return '[' . join(',', $elements) . ']';
1316
 
1317
- case 'object':
1318
- $vars = self::encodeObject($var);
1319
 
1320
- $this->json_objectStack[] = $var;
1321
 
1322
- $properties = array_map(array($this, 'json_name_value'),
1323
- array_keys($vars),
1324
- array_values($vars));
1325
 
1326
- array_pop($this->json_objectStack);
1327
 
1328
- foreach($properties as $property) {
1329
- if($property instanceof Exception) {
1330
- return $property;
1331
- }
1332
- }
1333
 
1334
- return '{' . join(',', $properties) . '}';
1335
-
1336
- default:
1337
- return null;
1338
- }
1339
- }
1340
-
1341
- /**
1342
- * array-walking function for use in generating JSON-formatted name-value pairs
1343
- *
1344
- * @param string $name name of key to use
1345
- * @param mixed $value reference to an array element to be encoded
1346
- *
1347
- * @return string JSON-formatted name-value pair, like '"name":value'
1348
- * @access private
1349
- */
1350
- private function json_name_value($name, $value)
1351
- {
1352
- // Encoding the $GLOBALS PHP array causes an infinite loop
1353
- // if the recursion is not reset here as it contains
1354
- // a reference to itself. This is the only way I have come up
1355
- // with to stop infinite recursion in this case.
1356
- if($name=='GLOBALS'
1357
- && is_array($value)
1358
- && array_key_exists('GLOBALS',$value)) {
1359
- $value['GLOBALS'] = '** Recursion **';
1360
- }
1361
 
1362
- $encoded_value = $this->json_encode($value);
1363
 
1364
- if($encoded_value instanceof Exception) {
1365
- return $encoded_value;
1366
- }
1367
 
1368
- return $this->json_encode(strval($name)) . ':' . $encoded_value;
1369
- }
1370
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
+ // Authors:
3
+ // - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2007, New BSD License
4
+ // - qbbr, Sokolov Innokenty <sokolov.innokenty@gmail.com>, Copyright 2011, New BSD License
5
+ // - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2011, MIT License
6
+
7
  /**
8
  * *** BEGIN LICENSE BLOCK *****
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  *
10
+ * [MIT License](http://www.opensource.org/licenses/mit-license.php)
 
 
11
  *
12
+ * Copyright (c) 2007+ [Christoph Dorn](http://www.christophdorn.com/)
 
 
13
  *
14
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ * of this software and associated documentation files (the "Software"), to deal
16
+ * in the Software without restriction, including without limitation the rights
17
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ * copies of the Software, and to permit persons to whom the Software is
19
+ * furnished to do so, subject to the following conditions:
20
+ *
21
+ * The above copyright notice and this permission notice shall be included in
22
+ * all copies or substantial portions of the Software.
23
+ *
24
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30
+ * THE SOFTWARE.
31
  *
32
  * ***** END LICENSE BLOCK *****
33
  *
34
+ * @copyright Copyright (C) 2007+ Christoph Dorn
35
+ * @author Christoph Dorn <christoph@christophdorn.com>
36
+ * @license [MIT License](http://www.opensource.org/licenses/mit-license.php)
37
+ * @package FirePHPCore
38
  */
39
+
40
+ /**
41
+ * @see http://code.google.com/p/firephp/issues/detail?id=112
42
+ */
43
+ if (!defined('E_STRICT')) {
44
+ define('E_STRICT', 2048);
45
+ }
46
+ if (!defined('E_RECOVERABLE_ERROR')) {
47
+ define('E_RECOVERABLE_ERROR', 4096);
48
+ }
49
+ if (!defined('E_DEPRECATED')) {
50
+ define('E_DEPRECATED', 8192);
51
+ }
52
+ if (!defined('E_USER_DEPRECATED')) {
53
+ define('E_USER_DEPRECATED', 16384);
54
+ }
55
 
56
  /**
57
  * Sends the given data to the FirePHP Firefox Extension.
60
  *
61
  * For more information see: http://www.firephp.org/
62
  *
63
+ * @copyright Copyright (C) 2007+ Christoph Dorn
64
+ * @author Christoph Dorn <christoph@christophdorn.com>
65
+ * @license [MIT License](http://www.opensource.org/licenses/mit-license.php)
66
+ * @package FirePHPCore
67
+ *
68
+ * @deprecated 2.3 This will be removed in Minify 3.0
69
  */
70
  class FirePHP {
71
+
72
+ /**
73
+ * FirePHP version
74
+ *
75
+ * @var string
76
+ */
77
+ const VERSION = '0.3'; // @pinf replace '0.3' with '%%VERSION%%'
78
+
79
+ /**
80
+ * Firebug LOG level
81
+ *
82
+ * Logs a message to firebug console.
83
+ *
84
+ * @var string
85
+ */
86
+ const LOG = 'LOG';
87
 
88
+ /**
89
+ * Firebug INFO level
90
+ *
91
+ * Logs a message to firebug console and displays an info icon before the message.
92
+ *
93
+ * @var string
94
+ */
95
+ const INFO = 'INFO';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
+ /**
98
+ * Firebug WARN level
99
+ *
100
+ * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise.
101
+ *
102
+ * @var string
103
+ */
104
+ const WARN = 'WARN';
105
+
106
+ /**
107
+ * Firebug ERROR level
108
+ *
109
+ * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count.
110
+ *
111
+ * @var string
112
+ */
113
+ const ERROR = 'ERROR';
114
+
115
+ /**
116
+ * Dumps a variable to firebug's server panel
117
+ *
118
+ * @var string
119
+ */
120
+ const DUMP = 'DUMP';
121
+
122
+ /**
123
+ * Displays a stack trace in firebug console
124
+ *
125
+ * @var string
126
+ */
127
+ const TRACE = 'TRACE';
128
+
129
+ /**
130
+ * Displays an exception in firebug console
131
+ *
132
+ * Increments the firebug error count.
133
+ *
134
+ * @var string
135
+ */
136
+ const EXCEPTION = 'EXCEPTION';
137
+
138
+ /**
139
+ * Displays an table in firebug console
140
+ *
141
+ * @var string
142
+ */
143
+ const TABLE = 'TABLE';
144
+
145
+ /**
146
+ * Starts a group in firebug console
147
+ *
148
+ * @var string
149
+ */
150
+ const GROUP_START = 'GROUP_START';
151
+
152
+ /**
153
+ * Ends a group in firebug console
154
+ *
155
+ * @var string
156
+ */
157
+ const GROUP_END = 'GROUP_END';
158
+
159
+ /**
160
+ * Singleton instance of FirePHP
161
+ *
162
+ * @var FirePHP
163
+ */
164
+ protected static $instance = null;
165
+
166
+ /**
167
+ * Flag whether we are logging from within the exception handler
168
+ *
169
+ * @var boolean
170
+ */
171
+ protected $inExceptionHandler = false;
172
 
173
+ /**
174
+ * Flag whether to throw PHP errors that have been converted to ErrorExceptions
175
+ *
176
+ * @var boolean
177
+ */
178
+ protected $throwErrorExceptions = true;
 
 
179
 
180
+ /**
181
+ * Flag whether to convert PHP assertion errors to Exceptions
182
+ *
183
+ * @var boolean
184
+ */
185
+ protected $convertAssertionErrorsToExceptions = true;
186
+
187
+ /**
188
+ * Flag whether to throw PHP assertion errors that have been converted to Exceptions
189
+ *
190
+ * @var boolean
191
+ */
192
+ protected $throwAssertionExceptions = false;
193
+
194
+ /**
195
+ * Wildfire protocol message index
196
+ *
197
+ * @var integer
198
+ */
199
+ protected $messageIndex = 1;
200
+
201
+ /**
202
+ * Options for the library
203
+ *
204
+ * @var array
205
+ */
206
+ protected $options = array('maxDepth' => 10,
207
+ 'maxObjectDepth' => 5,
208
+ 'maxArrayDepth' => 5,
209
+ 'useNativeJsonEncode' => true,
210
+ 'includeLineNumbers' => true);
211
+
212
+ /**
213
+ * Filters used to exclude object members when encoding
214
+ *
215
+ * @var array
216
+ */
217
+ protected $objectFilters = array(
218
+ 'firephp' => array('objectStack', 'instance', 'json_objectStack'),
219
+ 'firephp_test_class' => array('objectStack', 'instance', 'json_objectStack')
220
+ );
221
+
222
+ /**
223
+ * A stack of objects used to detect recursion during object encoding
224
+ *
225
+ * @var object
226
+ */
227
+ protected $objectStack = array();
228
+
229
+ /**
230
+ * Flag to enable/disable logging
231
+ *
232
+ * @var boolean
233
+ */
234
+ protected $enabled = true;
235
+
236
+ /**
237
+ * The insight console to log to if applicable
238
+ *
239
+ * @var object
240
+ */
241
+ protected $logToInsightConsole = null;
242
+
243
+ /**
244
+ * When the object gets serialized only include specific object members.
245
+ *
246
+ * @return array
247
+ */
248
+ public function __sleep()
249
+ {
250
+ return array('options', 'objectFilters', 'enabled');
251
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
 
253
+ /**
254
+ * Gets singleton instance of FirePHP
255
+ *
256
+ * @param boolean $autoCreate
257
+ * @return FirePHP
258
+ */
259
+ public static function getInstance($autoCreate = false)
260
+ {
261
+ if ($autoCreate === true && !self::$instance) {
262
+ self::init();
263
+ }
264
+ return self::$instance;
 
 
 
 
 
 
 
265
  }
266
+
267
+ /**
268
+ * Creates FirePHP object and stores it for singleton access
269
+ *
270
+ * @return FirePHP
271
+ */
272
+ public static function init()
273
+ {
274
+ return self::setInstance(new self());
275
  }
276
+
277
+ /**
278
+ * Set the instance of the FirePHP singleton
279
+ *
280
+ * @param FirePHP $instance The FirePHP object instance
281
+ * @return FirePHP
282
+ */
283
+ public static function setInstance($instance)
284
+ {
285
+ return self::$instance = $instance;
286
+ }
287
+
288
+ /**
289
+ * Set an Insight console to direct all logging calls to
290
+ *
291
+ * @param object $console The console object to log to
292
+ * @return void
293
+ */
294
+ public function setLogToInsightConsole($console)
295
+ {
296
+ if (is_string($console)) {
297
+ if (get_class($this) != 'FirePHP_Insight' && !is_subclass_of($this, 'FirePHP_Insight')) {
298
+ throw new Exception('FirePHP instance not an instance or subclass of FirePHP_Insight!');
299
+ }
300
+ $this->logToInsightConsole = $this->to('request')->console($console);
301
+ } else {
302
+ $this->logToInsightConsole = $console;
303
+ }
304
+ }
305
+
306
+ /**
307
+ * Enable and disable logging to Firebug
308
+ *
309
+ * @param boolean $enabled TRUE to enable, FALSE to disable
310
+ * @return void
311
+ */
312
+ public function setEnabled($enabled)
313
+ {
314
+ $this->enabled = $enabled;
315
+ }
316
+
317
+ /**
318
+ * Check if logging is enabled
319
+ *
320
+ * @return boolean TRUE if enabled
321
+ */
322
+ public function getEnabled()
323
+ {
324
+ return $this->enabled;
325
+ }
326
+
327
+ /**
328
+ * Specify a filter to be used when encoding an object
329
+ *
330
+ * Filters are used to exclude object members.
331
+ *
332
+ * @param string $class The class name of the object
333
+ * @param array $filter An array of members to exclude
334
+ * @return void
335
+ */
336
+ public function setObjectFilter($class, $filter)
337
+ {
338
+ $this->objectFilters[strtolower($class)] = $filter;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
  }
 
 
 
 
 
 
 
 
 
 
 
 
340
 
341
+ /**
342
+ * Set some options for the library
343
+ *
344
+ * Options:
345
+ * - maxDepth: The maximum depth to traverse (default: 10)
346
+ * - maxObjectDepth: The maximum depth to traverse objects (default: 5)
347
+ * - maxArrayDepth: The maximum depth to traverse arrays (default: 5)
348
+ * - useNativeJsonEncode: If true will use json_encode() (default: true)
349
+ * - includeLineNumbers: If true will include line numbers and filenames (default: true)
350
+ *
351
+ * @param array $options The options to be set
352
+ * @return void
353
+ */
354
+ public function setOptions($options)
355
+ {
356
+ $this->options = array_merge($this->options, $options);
357
+ }
358
+
359
+ /**
360
+ * Get options from the library
361
+ *
362
+ * @return array The currently set options
363
+ */
364
+ public function getOptions()
365
+ {
366
+ return $this->options;
367
+ }
368
+
369
+ /**
370
+ * Set an option for the library
371
+ *
372
+ * @param string $name
373
+ * @param mixed $value
374
+ * @return void
375
+ * @throws Exception
376
+ */
377
+ public function setOption($name, $value)
378
+ {
379
+ if (!isset($this->options[$name])) {
380
+ throw $this->newException('Unknown option: ' . $name);
381
+ }
382
+ $this->options[$name] = $value;
383
+ }
384
+
385
+ /**
386
+ * Get an option from the library
387
+ *
388
+ * @param string $name
389
+ * @return mixed
390
+ * @throws Exception
391
+ */
392
+ public function getOption($name)
393
+ {
394
+ if (!isset($this->options[$name])) {
395
+ throw $this->newException('Unknown option: ' . $name);
396
+ }
397
+ return $this->options[$name];
398
+ }
399
+
400
+ /**
401
+ * Register FirePHP as your error handler
402
+ *
403
+ * Will throw exceptions for each php error.
404
+ *
405
+ * @return mixed Returns a string containing the previously defined error handler (if any)
406
+ */
407
+ public function registerErrorHandler($throwErrorExceptions = false)
408
+ {
409
+ //NOTE: The following errors will not be caught by this error handler:
410
+ // E_ERROR, E_PARSE, E_CORE_ERROR,
411
+ // E_CORE_WARNING, E_COMPILE_ERROR,
412
+ // E_COMPILE_WARNING, E_STRICT
413
+
414
+ $this->throwErrorExceptions = $throwErrorExceptions;
415
+
416
+ return set_error_handler(array($this, 'errorHandler'));
417
+ }
418
+
419
+ /**
420
+ * FirePHP's error handler
421
+ *
422
+ * Throws exception for each php error that will occur.
423
+ *
424
+ * @param integer $errno
425
+ * @param string $errstr
426
+ * @param string $errfile
427
+ * @param integer $errline
428
+ * @param array $errcontext
429
+ */
430
+ public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
431
+ {
432
+ // Don't throw exception if error reporting is switched off
433
+ if (error_reporting() == 0) {
434
+ return;
435
+ }
436
+ // Only throw exceptions for errors we are asking for
437
+ if (error_reporting() & $errno) {
438
+
439
+ $exception = new ErrorException($errstr, 0, $errno, $errfile, $errline);
440
+ if ($this->throwErrorExceptions) {
441
+ throw $exception;
442
+ } else {
443
+ $this->fb($exception);
444
+ }
445
+ }
446
  }
447
 
448
+ /**
449
+ * Register FirePHP as your exception handler
450
+ *
451
+ * @return mixed Returns the name of the previously defined exception handler,
452
+ * or NULL on error.
453
+ * If no previous handler was defined, NULL is also returned.
454
+ */
455
+ public function registerExceptionHandler()
456
+ {
457
+ return set_exception_handler(array($this, 'exceptionHandler'));
458
  }
459
 
460
+ /**
461
+ * FirePHP's exception handler
462
+ *
463
+ * Logs all exceptions to your firebug console and then stops the script.
464
+ *
465
+ * @param Exception $exception
466
+ * @throws Exception
467
+ */
468
+ function exceptionHandler($exception)
469
+ {
470
+ $this->inExceptionHandler = true;
471
+
472
+ header('HTTP/1.1 500 Internal Server Error');
473
+
474
+ try {
475
+ $this->fb($exception);
476
+ } catch (Exception $e) {
477
+ echo 'We had an exception: ' . $e;
478
+ }
479
+
480
+ $this->inExceptionHandler = false;
481
+ }
482
 
483
+ /**
484
+ * Register FirePHP driver as your assert callback
485
+ *
486
+ * @param boolean $convertAssertionErrorsToExceptions
487
+ * @param boolean $throwAssertionExceptions
488
+ * @return mixed Returns the original setting or FALSE on errors
489
+ */
490
+ public function registerAssertionHandler($convertAssertionErrorsToExceptions = true, $throwAssertionExceptions = false)
491
+ {
492
+ $this->convertAssertionErrorsToExceptions = $convertAssertionErrorsToExceptions;
493
+ $this->throwAssertionExceptions = $throwAssertionExceptions;
494
+
495
+ if ($throwAssertionExceptions && !$convertAssertionErrorsToExceptions) {
496
+ throw $this->newException('Cannot throw assertion exceptions as assertion errors are not being converted to exceptions!');
497
+ }
498
+
499
+ return assert_options(ASSERT_CALLBACK, array($this, 'assertionHandler'));
 
 
 
 
 
 
 
 
 
500
  }
501
 
502
+ /**
503
+ * FirePHP's assertion handler
504
+ *
505
+ * Logs all assertions to your firebug console and then stops the script.
506
+ *
507
+ * @param string $file File source of assertion
508
+ * @param integer $line Line source of assertion
509
+ * @param mixed $code Assertion code
510
+ */
511
+ public function assertionHandler($file, $line, $code)
512
+ {
513
+ if ($this->convertAssertionErrorsToExceptions) {
514
+
515
+ $exception = new ErrorException('Assertion Failed - Code[ ' . $code . ' ]', 0, null, $file, $line);
516
+
517
+ if ($this->throwAssertionExceptions) {
518
+ throw $exception;
519
+ } else {
520
+ $this->fb($exception);
521
+ }
522
+
523
+ } else {
524
+ $this->fb($code, 'Assertion Failed', FirePHP::ERROR, array('File' => $file, 'Line' => $line));
525
+ }
526
+ }
527
 
528
+ /**
529
+ * Start a group for following messages.
530
+ *
531
+ * Options:
532
+ * Collapsed: [true|false]
533
+ * Color: [#RRGGBB|ColorName]
534
+ *
535
+ * @param string $name
536
+ * @param array $options OPTIONAL Instructions on how to log the group
537
+ * @return true
538
+ * @throws Exception
539
+ */
540
+ public function group($name, $options = null)
541
+ {
542
+
543
+ if ( !isset($name) ) {
544
+ throw $this->newException('You must specify a label for the group!');
545
+ }
546
+
547
+ if ($options) {
548
+ if (!is_array($options)) {
549
+ throw $this->newException('Options must be defined as an array!');
550
+ }
551
+ if (array_key_exists('Collapsed', $options)) {
552
+ $options['Collapsed'] = ($options['Collapsed']) ? 'true' : 'false';
553
+ }
554
+ }
555
+
556
+ return $this->fb(null, $name, FirePHP::GROUP_START, $options);
557
  }
558
 
559
+ /**
560
+ * Ends a group you have started before
561
+ *
562
+ * @return true
563
+ * @throws Exception
564
+ */
565
+ public function groupEnd()
566
+ {
567
+ return $this->fb(null, null, FirePHP::GROUP_END);
568
+ }
569
+
570
+ /**
571
+ * Log object with label to firebug console
572
+ *
573
+ * @see FirePHP::LOG
574
+ * @param mixes $object
575
+ * @param string $label
576
+ * @return true
577
+ * @throws Exception
578
+ */
579
+ public function log($object, $label = null, $options = array())
580
+ {
581
+ return $this->fb($object, $label, FirePHP::LOG, $options);
582
+ }
583
+
584
+ /**
585
+ * Log object with label to firebug console
586
+ *
587
+ * @see FirePHP::INFO
588
+ * @param mixes $object
589
+ * @param string $label
590
+ * @return true
591
+ * @throws Exception
592
+ */
593
+ public function info($object, $label = null, $options = array())
594
+ {
595
+ return $this->fb($object, $label, FirePHP::INFO, $options);
596
+ }
597
+
598
+ /**
599
+ * Log object with label to firebug console
600
+ *
601
+ * @see FirePHP::WARN
602
+ * @param mixes $object
603
+ * @param string $label
604
+ * @return true
605
+ * @throws Exception
606
+ */
607
+ public function warn($object, $label = null, $options = array())
608
+ {
609
+ return $this->fb($object, $label, FirePHP::WARN, $options);
610
+ }
611
+
612
+ /**
613
+ * Log object with label to firebug console
614
+ *
615
+ * @see FirePHP::ERROR
616
+ * @param mixes $object
617
+ * @param string $label
618
+ * @return true
619
+ * @throws Exception
620
+ */
621
+ public function error($object, $label = null, $options = array())
622
+ {
623
+ return $this->fb($object, $label, FirePHP::ERROR, $options);
624
+ }
625
+
626
+ /**
627
+ * Dumps key and variable to firebug server panel
628
+ *
629
+ * @see FirePHP::DUMP
630
+ * @param string $key
631
+ * @param mixed $variable
632
+ * @return true
633
+ * @throws Exception
634
+ */
635
+ public function dump($key, $variable, $options = array())
636
+ {
637
+ if (!is_string($key)) {
638
+ throw $this->newException('Key passed to dump() is not a string');
639
+ }
640
+ if (strlen($key) > 100) {
641
+ throw $this->newException('Key passed to dump() is longer than 100 characters');
642
+ }
643
+ if (!preg_match_all('/^[a-zA-Z0-9-_\.:]*$/', $key, $m)) {
644
+ throw $this->newException('Key passed to dump() contains invalid characters [a-zA-Z0-9-_\.:]');
645
+ }
646
+ return $this->fb($variable, $key, FirePHP::DUMP, $options);
647
+ }
648
 
649
+ /**
650
+ * Log a trace in the firebug console
651
+ *
652
+ * @see FirePHP::TRACE
653
+ * @param string $label
654
+ * @return true
655
+ * @throws Exception
656
+ */
657
+ public function trace($label)
658
+ {
659
+ return $this->fb($label, FirePHP::TRACE);
660
+ }
661
+
662
+ /**
663
+ * Log a table in the firebug console
664
+ *
665
+ * @see FirePHP::TABLE
666
+ * @param string $label
667
+ * @param string $table
668
+ * @return true
669
+ * @throws Exception
670
+ */
671
+ public function table($label, $table, $options = array())
672
+ {
673
+ return $this->fb($table, $label, FirePHP::TABLE, $options);
674
+ }
675
 
676
+ /**
677
+ * Insight API wrapper
678
+ *
679
+ * @see Insight_Helper::to()
680
+ */
681
+ public static function to()
682
+ {
683
+ $instance = self::getInstance();
684
+ if (!method_exists($instance, '_to')) {
685
+ throw new Exception('FirePHP::to() implementation not loaded');
 
 
 
 
 
 
 
 
 
 
 
686
  }
687
+ $args = func_get_args();
688
+ return call_user_func_array(array($instance, '_to'), $args);
689
+ }
690
+
691
+ /**
692
+ * Insight API wrapper
693
+ *
694
+ * @see Insight_Helper::plugin()
695
+ */
696
+ public static function plugin()
697
+ {
698
+ $instance = self::getInstance();
699
+ if (!method_exists($instance, '_plugin')) {
700
+ throw new Exception('FirePHP::plugin() implementation not loaded');
701
+ }
702
+ $args = func_get_args();
703
+ return call_user_func_array(array($instance, '_plugin'), $args);
704
+ }
705
+
706
+ /**
707
+ * Check if FirePHP is installed on client
708
+ *
709
+ * @return boolean
710
+ */
711
+ public function detectClientExtension()
712
+ {
713
+ // Check if FirePHP is installed on client via User-Agent header
714
+ if (@preg_match_all('/\sFirePHP\/([\.\d]*)\s?/si', $this->getUserAgent(), $m) &&
715
+ version_compare($m[1][0], '0.0.6', '>=')) {
716
+ return true;
 
 
 
 
 
 
 
 
 
717
  } else
718
+ // Check if FirePHP is installed on client via X-FirePHP-Version header
719
+ if (@preg_match_all('/^([\.\d]*)$/si', $this->getRequestHeader('X-FirePHP-Version'), $m) &&
720
+ version_compare($m[1][0], '0.0.6', '>=')) {
721
+ return true;
722
+ }
723
+ return false;
724
+ }
725
+
726
+ /**
727
+ * Log varible to Firebug
728
+ *
729
+ * @see http://www.firephp.org/Wiki/Reference/Fb
730
+ * @param mixed $object The variable to be logged
731
+ * @return boolean Return TRUE if message was added to headers, FALSE otherwise
732
+ * @throws Exception
733
+ */
734
+ public function fb($object)
735
+ {
736
+ if ($this instanceof FirePHP_Insight && method_exists($this, '_logUpgradeClientMessage')) {
737
+ if (!FirePHP_Insight::$upgradeClientMessageLogged) { // avoid infinite recursion as _logUpgradeClientMessage() logs a message
738
+ $this->_logUpgradeClientMessage();
739
+ }
740
  }
 
741
 
742
+ static $insightGroupStack = array();
 
 
 
 
 
 
 
743
 
744
+ if (!$this->getEnabled()) {
745
+ return false;
746
+ }
 
 
 
 
 
 
 
747
 
748
+ if ($this->headersSent($filename, $linenum)) {
749
+ // If we are logging from within the exception handler we cannot throw another exception
750
+ if ($this->inExceptionHandler) {
751
+ // Simply echo the error out to the page
752
+ 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>';
753
+ } else {
754
+ 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.');
755
+ }
756
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
757
 
758
+ $type = null;
759
+ $label = null;
760
+ $options = array();
761
+
762
+ if (func_num_args() == 1) {
763
+ } else if (func_num_args() == 2) {
764
+ switch (func_get_arg(1)) {
765
+ case self::LOG:
766
+ case self::INFO:
767
+ case self::WARN:
768
+ case self::ERROR:
769
+ case self::DUMP:
770
+ case self::TRACE:
771
+ case self::EXCEPTION:
772
+ case self::TABLE:
773
+ case self::GROUP_START:
774
+ case self::GROUP_END:
775
+ $type = func_get_arg(1);
776
+ break;
777
+ default:
778
+ $label = func_get_arg(1);
779
+ break;
780
+ }
781
+ } else if (func_num_args() == 3) {
782
+ $type = func_get_arg(2);
783
+ $label = func_get_arg(1);
784
+ } else if (func_num_args() == 4) {
785
+ $type = func_get_arg(2);
786
+ $label = func_get_arg(1);
787
+ $options = func_get_arg(3);
788
+ } else {
789
+ throw $this->newException('Wrong number of arguments to fb() function!');
790
+ }
791
 
792
+ // Get folder name where firephp is located.
793
+ $parentFolder = basename(dirname(__FILE__));
794
+ $parentFolderLength = strlen( $parentFolder );
795
+ $fbLength = 7 + $parentFolderLength;
796
+ $fireClassLength = 18 + $parentFolderLength;
797
+
798
+ if ($this->logToInsightConsole !== null && (get_class($this) == 'FirePHP_Insight' || is_subclass_of($this, 'FirePHP_Insight'))) {
799
+ $trace = debug_backtrace();
800
+ if (!$trace) return false;
801
+ for ($i = 0; $i < sizeof($trace); $i++) {
802
+ if (isset($trace[$i]['class'])) {
803
+ if ($trace[$i]['class'] == 'FirePHP' || $trace[$i]['class'] == 'FB') {
804
+ continue;
805
+ }
806
+ }
807
+ if (isset($trace[$i]['file'])) {
808
+ $path = $this->_standardizePath($trace[$i]['file']);
809
+ if (substr($path, -1*$fbLength, $fbLength) == $parentFolder.'/fb.php' || substr($path, -1*$fireClassLength, $fireClassLength) == $parentFolder.'/FirePHP.class.php') {
810
+ continue;
811
+ }
812
+ }
813
+ if (isset($trace[$i]['function']) && $trace[$i]['function'] == 'fb' &&
814
+ isset($trace[$i - 1]['file']) && substr($this->_standardizePath($trace[$i - 1]['file']), -1*$fbLength, $fbLength) == $parentFolder.'/fb.php') {
815
+ continue;
816
+ }
817
+ if (isset($trace[$i]['class']) && $trace[$i]['class'] == 'FB' &&
818
+ isset($trace[$i - 1]['file']) && substr($this->_standardizePath($trace[$i - 1]['file']), -1*$fbLength, $fbLength) == $parentFolder.'/fb.php') {
819
+ continue;
820
+ }
821
+ break;
822
+ }
823
+ // adjust trace offset
824
+ $msg = $this->logToInsightConsole->option('encoder.trace.offsetAdjustment', $i);
825
 
826
+ if ($object instanceof Exception) {
827
+ $type = self::EXCEPTION;
828
+ }
829
+ if ($label && $type != self::TABLE && $type != self::GROUP_START) {
830
+ $msg = $msg->label($label);
831
+ }
832
+ switch ($type) {
833
+ case self::DUMP:
834
+ case self::LOG:
835
+ return $msg->log($object);
836
+ case self::INFO:
837
+ return $msg->info($object);
838
+ case self::WARN:
839
+ return $msg->warn($object);
840
+ case self::ERROR:
841
+ return $msg->error($object);
842
+ case self::TRACE:
843
+ return $msg->trace($object);
844
+ case self::EXCEPTION:
845
+ return $this->plugin('error')->handleException($object, $msg);
846
+ case self::TABLE:
847
+ if (isset($object[0]) && !is_string($object[0]) && $label) {
848
+ $object = array($label, $object);
849
+ }
850
+ return $msg->table($object[0], array_slice($object[1], 1), $object[1][0]);
851
+ case self::GROUP_START:
852
+ $insightGroupStack[] = $msg->group(md5($label))->open();
853
+ return $msg->log($label);
854
+ case self::GROUP_END:
855
+ if (count($insightGroupStack) == 0) {
856
+ throw new Error('Too many groupEnd() as opposed to group() calls!');
857
+ }
858
+ $group = array_pop($insightGroupStack);
859
+ return $group->close();
860
+ default:
861
+ return $msg->log($object);
862
+ }
863
+ }
864
+
865
+ if (!$this->detectClientExtension()) {
866
+ return false;
867
+ }
868
+
869
+ $meta = array();
870
+ $skipFinalObjectEncode = false;
871
+
872
+ if ($object instanceof Exception) {
873
+
874
+ $meta['file'] = $this->_escapeTraceFile($object->getFile());
875
+ $meta['line'] = $object->getLine();
876
+
877
+ $trace = $object->getTrace();
878
+ if ($object instanceof ErrorException
879
+ && isset($trace[0]['function'])
880
+ && $trace[0]['function'] == 'errorHandler'
881
+ && isset($trace[0]['class'])
882
+ && $trace[0]['class'] == 'FirePHP') {
883
+
884
+ $severity = false;
885
+ switch ($object->getSeverity()) {
886
+ case E_WARNING:
887
+ $severity = 'E_WARNING';
888
+ break;
889
+
890
+ case E_NOTICE:
891
+ $severity = 'E_NOTICE';
892
+ break;
893
+
894
+ case E_USER_ERROR:
895
+ $severity = 'E_USER_ERROR';
896
+ break;
897
+
898
+ case E_USER_WARNING:
899
+ $severity = 'E_USER_WARNING';
900
+ break;
901
+
902
+ case E_USER_NOTICE:
903
+ $severity = 'E_USER_NOTICE';
904
+ break;
905
+
906
+ case E_STRICT:
907
+ $severity = 'E_STRICT';
908
+ break;
909
+
910
+ case E_RECOVERABLE_ERROR:
911
+ $severity = 'E_RECOVERABLE_ERROR';
912
+ break;
913
+
914
+ case E_DEPRECATED:
915
+ $severity = 'E_DEPRECATED';
916
+ break;
917
+
918
+ case E_USER_DEPRECATED:
919
+ $severity = 'E_USER_DEPRECATED';
920
+ break;
921
+ }
922
+
923
+ $object = array('Class' => get_class($object),
924
+ 'Message' => $severity . ': ' . $object->getMessage(),
925
+ 'File' => $this->_escapeTraceFile($object->getFile()),
926
+ 'Line' => $object->getLine(),
927
+ 'Type' => 'trigger',
928
+ 'Trace' => $this->_escapeTrace(array_splice($trace, 2)));
929
+ $skipFinalObjectEncode = true;
930
+ } else {
931
+ $object = array('Class' => get_class($object),
932
+ 'Message' => $object->getMessage(),
933
+ 'File' => $this->_escapeTraceFile($object->getFile()),
934
+ 'Line' => $object->getLine(),
935
+ 'Type' => 'throw',
936
+ 'Trace' => $this->_escapeTrace($trace));
937
+ $skipFinalObjectEncode = true;
938
+ }
939
+ $type = self::EXCEPTION;
940
+
941
+ } else if ($type == self::TRACE) {
942
+
943
+ $trace = debug_backtrace();
944
+ if (!$trace) return false;
945
+ for ($i = 0; $i < sizeof($trace); $i++) {
946
+
947
+ if (isset($trace[$i]['class'])
948
+ && isset($trace[$i]['file'])
949
+ && ($trace[$i]['class'] == 'FirePHP'
950
+ || $trace[$i]['class'] == 'FB')
951
+ && (substr($this->_standardizePath($trace[$i]['file']), -1*$fbLength, $fbLength) == $parentFolder.'/fb.php'
952
+ || substr($this->_standardizePath($trace[$i]['file']), -1*$fireClassLength, $fireClassLength) == $parentFolder.'/FirePHP.class.php')) {
953
+ /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
954
+ } else
955
+ if (isset($trace[$i]['class'])
956
+ && isset($trace[$i+1]['file'])
957
+ && $trace[$i]['class'] == 'FirePHP'
958
+ && substr($this->_standardizePath($trace[$i + 1]['file']), -1*$fbLength, $fbLength) == $parentFolder.'/fb.php') {
959
+ /* Skip fb() */
960
+ } else
961
+ if ($trace[$i]['function'] == 'fb'
962
+ || $trace[$i]['function'] == 'trace'
963
+ || $trace[$i]['function'] == 'send') {
964
+
965
+ $object = array('Class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : '',
966
+ 'Type' => isset($trace[$i]['type']) ? $trace[$i]['type'] : '',
967
+ 'Function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : '',
968
+ 'Message' => $trace[$i]['args'][0],
969
+ 'File' => isset($trace[$i]['file']) ? $this->_escapeTraceFile($trace[$i]['file']) : '',
970
+ 'Line' => isset($trace[$i]['line']) ? $trace[$i]['line'] : '',
971
+ 'Args' => isset($trace[$i]['args']) ? $this->encodeObject($trace[$i]['args']) : '',
972
+ 'Trace' => $this->_escapeTrace(array_splice($trace, $i + 1)));
973
 
974
+ $skipFinalObjectEncode = true;
975
+ $meta['file'] = isset($trace[$i]['file']) ? $this->_escapeTraceFile($trace[$i]['file']) : '';
976
+ $meta['line'] = isset($trace[$i]['line']) ? $trace[$i]['line'] : '';
977
+ break;
978
+ }
979
+ }
980
+
981
+ } else
982
+ if ($type == self::TABLE) {
983
+
984
+ if (isset($object[0]) && is_string($object[0])) {
985
+ $object[1] = $this->encodeTable($object[1]);
986
  } else {
987
+ $object = $this->encodeTable($object);
 
988
  }
989
+
990
+ $skipFinalObjectEncode = true;
991
+
992
+ } else if ($type == self::GROUP_START) {
993
+
994
+ if (!$label) {
995
+ throw $this->newException('You must specify a label for the group!');
996
+ }
997
+
998
+ } else {
999
+ if ($type === null) {
1000
+ $type = self::LOG;
1001
  }
1002
  }
1003
+
1004
+ if ($this->options['includeLineNumbers']) {
1005
+ if (!isset($meta['file']) || !isset($meta['line'])) {
1006
+
1007
+ $trace = debug_backtrace();
1008
+ for ($i = 0; $trace && $i < sizeof($trace); $i++) {
1009
+
1010
+ if (isset($trace[$i]['class'])
1011
+ && isset($trace[$i]['file'])
1012
+ && ($trace[$i]['class'] == 'FirePHP'
1013
+ || $trace[$i]['class'] == 'FB')
1014
+ && (substr($this->_standardizePath($trace[$i]['file']), -1*$fbLength, $fbLength) == $parentFolder.'/fb.php'
1015
+ || substr($this->_standardizePath($trace[$i]['file']), -1*$fireClassLength, $fireClassLength) == $parentFolder.'/FirePHP.class.php')) {
1016
+ /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */
1017
+ } else
1018
+ if (isset($trace[$i]['class'])
1019
+ && isset($trace[$i + 1]['file'])
1020
+ && $trace[$i]['class'] == 'FirePHP'
1021
+ && substr($this->_standardizePath($trace[$i + 1]['file']), -1*$fbLength, $fbLength) == $parentFolder.'/fb.php') {
1022
+ /* Skip fb() */
1023
+ } else
1024
+ if (isset($trace[$i]['file'])
1025
+ && substr($this->_standardizePath($trace[$i]['file']), -1*$fbLength, $fbLength) == $parentFolder.'/fb.php') {
1026
+ /* Skip FB::fb() */
1027
+ } else {
1028
+ $meta['file'] = isset($trace[$i]['file']) ? $this->_escapeTraceFile($trace[$i]['file']) : '';
1029
+ $meta['line'] = isset($trace[$i]['line']) ? $trace[$i]['line'] : '';
1030
+ break;
1031
+ }
1032
+ }
1033
+ }
1034
+ } else {
1035
+ unset($meta['file']);
1036
+ unset($meta['line']);
1037
+ }
1038
 
1039
+ $this->setHeader('X-Wf-Protocol-1', 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
1040
+ $this->setHeader('X-Wf-1-Plugin-1', 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/' . self::VERSION);
1041
+
1042
+ $structureIndex = 1;
1043
+ if ($type == self::DUMP) {
1044
+ $structureIndex = 2;
1045
+ $this->setHeader('X-Wf-1-Structure-2', 'http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');
1046
+ } else {
1047
+ $this->setHeader('X-Wf-1-Structure-1', 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
1048
+ }
1049
+
1050
+ if ($type == self::DUMP) {
1051
+ $msg = '{"' . $label . '":' . $this->jsonEncode($object, $skipFinalObjectEncode) . '}';
1052
+ } else {
1053
+ $msgMeta = $options;
1054
+ $msgMeta['Type'] = $type;
1055
+ if ($label !== null) {
1056
+ $msgMeta['Label'] = $label;
1057
+ }
1058
+ if (isset($meta['file']) && !isset($msgMeta['File'])) {
1059
+ $msgMeta['File'] = $meta['file'];
1060
+ }
1061
+ if (isset($meta['line']) && !isset($msgMeta['Line'])) {
1062
+ $msgMeta['Line'] = $meta['line'];
1063
+ }
1064
+ $msg = '[' . $this->jsonEncode($msgMeta) . ',' . $this->jsonEncode($object, $skipFinalObjectEncode) . ']';
1065
+ }
1066
+
1067
+ $parts = explode("\n", chunk_split($msg, 5000, "\n"));
1068
 
1069
+ for ($i = 0; $i < count($parts); $i++) {
1070
+
1071
+ $part = $parts[$i];
1072
+ if ($part) {
1073
+
1074
+ if (count($parts) > 2) {
1075
+ // Message needs to be split into multiple parts
1076
+ $this->setHeader('X-Wf-1-' . $structureIndex . '-' . '1-' . $this->messageIndex,
1077
+ (($i == 0) ? strlen($msg) : '')
1078
+ . '|' . $part . '|'
1079
+ . (($i < count($parts) - 2) ? '\\' : ''));
1080
+ } else {
1081
+ $this->setHeader('X-Wf-1-' . $structureIndex . '-' . '1-' . $this->messageIndex,
1082
+ strlen($part) . '|' . $part . '|');
1083
+ }
1084
+
1085
+ $this->messageIndex++;
1086
+
1087
+ if ($this->messageIndex > 99999) {
1088
+ throw $this->newException('Maximum number (99,999) of messages reached!');
1089
+ }
1090
+ }
1091
+ }
1092
+
1093
+ $this->setHeader('X-Wf-1-Index', $this->messageIndex - 1);
1094
+
1095
+ return true;
1096
+ }
1097
 
1098
+ /**
1099
+ * Standardizes path for windows systems.
1100
+ *
1101
+ * @param string $path
1102
+ * @return string
1103
+ */
1104
+ protected function _standardizePath($path)
1105
+ {
1106
+ return preg_replace('/\\\\+/', '/', $path);
 
 
 
 
 
 
1107
  }
 
 
1108
 
1109
+ /**
1110
+ * Escape trace path for windows systems
1111
+ *
1112
+ * @param array $trace
1113
+ * @return array
1114
+ */
1115
+ protected function _escapeTrace($trace)
1116
+ {
1117
+ if (!$trace) return $trace;
1118
+ for ($i = 0; $i < sizeof($trace); $i++) {
1119
+ if (isset($trace[$i]['file'])) {
1120
+ $trace[$i]['file'] = $this->_escapeTraceFile($trace[$i]['file']);
1121
+ }
1122
+ if (isset($trace[$i]['args'])) {
1123
+ $trace[$i]['args'] = $this->encodeObject($trace[$i]['args']);
1124
+ }
1125
+ }
1126
+ return $trace;
1127
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1128
 
1129
+ /**
1130
+ * Escape file information of trace for windows systems
1131
+ *
1132
+ * @param string $file
1133
+ * @return string
1134
+ */
1135
+ protected function _escapeTraceFile($file)
1136
+ {
1137
+ /* Check if we have a windows filepath */
1138
+ if (strpos($file, '\\')) {
1139
+ /* First strip down to single \ */
1140
+
1141
+ $file = preg_replace('/\\\\+/', '\\', $file);
1142
+
1143
+ return $file;
1144
+ }
1145
+ return $file;
1146
  }
 
 
 
1147
 
1148
+ /**
1149
+ * Check if headers have already been sent
1150
+ *
1151
+ * @param string $filename
1152
+ * @param integer $linenum
1153
+ */
1154
+ protected function headersSent(&$filename, &$linenum)
1155
+ {
1156
+ return headers_sent($filename, $linenum);
1157
  }
1158
+
1159
+ /**
1160
+ * Send header
1161
+ *
1162
+ * @param string $name
1163
+ * @param string $value
1164
+ */
1165
+ protected function setHeader($name, $value)
1166
+ {
1167
+ return header($name . ': ' . $value);
1168
+ }
1169
+
1170
+ /**
1171
+ * Get user agent
1172
+ *
1173
+ * @return string|false
1174
+ */
1175
+ protected function getUserAgent()
1176
+ {
1177
+ if (!isset($_SERVER['HTTP_USER_AGENT'])) return false;
1178
+ return $_SERVER['HTTP_USER_AGENT'];
1179
+ }
1180
+
1181
+ /**
1182
+ * Get all request headers
1183
+ *
1184
+ * @return array
1185
+ */
1186
+ public static function getAllRequestHeaders()
1187
+ {
1188
+ static $_cachedHeaders = false;
1189
+ if ($_cachedHeaders !== false) {
1190
+ return $_cachedHeaders;
1191
+ }
1192
+ $headers = array();
1193
+ if (function_exists('getallheaders')) {
1194
+ foreach (getallheaders() as $name => $value) {
1195
+ $headers[strtolower($name)] = $value;
1196
+ }
1197
+ } else {
1198
+ foreach ($_SERVER as $name => $value) {
1199
+ if (substr($name, 0, 5) == 'HTTP_') {
1200
+ $headers[strtolower(str_replace(' ', '-', str_replace('_', ' ', substr($name, 5))))] = $value;
1201
+ }
1202
+ }
1203
+ }
1204
+ return $_cachedHeaders = $headers;
1205
+ }
1206
+
1207
+ /**
1208
+ * Get a request header
1209
+ *
1210
+ * @return string|false
1211
+ */
1212
+ protected function getRequestHeader($name)
1213
+ {
1214
+ $headers = self::getAllRequestHeaders();
1215
+ if (isset($headers[strtolower($name)])) {
1216
+ return $headers[strtolower($name)];
1217
  }
1218
+ return false;
1219
+ }
1220
+
1221
+ /**
1222
+ * Returns a new exception
1223
+ *
1224
+ * @param string $message
1225
+ * @return Exception
1226
+ */
1227
+ protected function newException($message)
1228
+ {
1229
+ return new Exception($message);
1230
  }
 
 
1231
 
1232
+ /**
1233
+ * Encode an object into a JSON string
1234
+ *
1235
+ * Uses PHP's jeson_encode() if available
1236
+ *
1237
+ * @param object $object The object to be encoded
1238
+ * @param boolean $skipObjectEncode
1239
+ * @return string The JSON string
1240
+ */
1241
+ public function jsonEncode($object, $skipObjectEncode = false)
1242
+ {
1243
+ if (!$skipObjectEncode) {
1244
+ $object = $this->encodeObject($object);
1245
+ }
1246
+
1247
+ if (function_exists('json_encode')
1248
+ && $this->options['useNativeJsonEncode'] != false) {
1249
 
1250
+ return json_encode($object);
1251
+ } else {
1252
+ return $this->json_encode($object);
 
1253
  }
1254
+ }
1255
+
1256
+ /**
1257
+ * Encodes a table by encoding each row and column with encodeObject()
1258
+ *
1259
+ * @param array $table The table to be encoded
1260
+ * @return array
1261
+ */
1262
+ protected function encodeTable($table)
1263
+ {
1264
+ if (!$table) return $table;
1265
 
1266
+ $newTable = array();
1267
+ foreach ($table as $row) {
1268
+
1269
+ if (is_array($row)) {
1270
+ $newRow = array();
1271
+
1272
+ foreach ($row as $item) {
1273
+ $newRow[] = $this->encodeObject($item);
1274
+ }
1275
+
1276
+ $newTable[] = $newRow;
1277
  }
1278
  }
 
 
 
1279
 
1280
+ return $newTable;
1281
+ }
1282
+
1283
+ /**
1284
+ * Encodes an object including members with
1285
+ * protected and private visibility
1286
+ *
1287
+ * @param object $object The object to be encoded
1288
+ * @param integer $Depth The current traversal depth
1289
+ * @return array All members of the object
1290
+ */
1291
+ protected function encodeObject($object, $objectDepth = 1, $arrayDepth = 1, $maxDepth = 1)
1292
+ {
1293
+ if ($maxDepth > $this->options['maxDepth']) {
1294
+ return '** Max Depth (' . $this->options['maxDepth'] . ') **';
1295
  }
1296
+
1297
+ $return = array();
1298
+
1299
+ //#2801 is_resource reports false for closed resources https://bugs.php.net/bug.php?id=28016
1300
+ if (is_resource($object) || gettype($object) === "unknown type") {
1301
+
1302
+ return '** ' . (string) $object . ' **';
1303
+
1304
+ } else if (is_object($object)) {
1305
+
1306
+ if ($objectDepth > $this->options['maxObjectDepth']) {
1307
+ return '** Max Object Depth (' . $this->options['maxObjectDepth'] . ') **';
1308
+ }
1309
 
1310
+ foreach ($this->objectStack as $refVal) {
1311
+ if ($refVal === $object) {
1312
+ return '** Recursion (' . get_class($object) . ') **';
1313
+ }
1314
+ }
1315
+ array_push($this->objectStack, $object);
1316
+
1317
+ $return['__className'] = $class = get_class($object);
1318
+ $classLower = strtolower($class);
1319
+
1320
+ $reflectionClass = new ReflectionClass($class);
1321
+ $properties = array();
1322
+ foreach ($reflectionClass->getProperties() as $property) {
1323
+ $properties[$property->getName()] = $property;
1324
+ }
1325
+
1326
+ $members = (array)$object;
1327
+
1328
+ foreach ($properties as $plainName => $property) {
1329
+
1330
+ $name = $rawName = $plainName;
1331
+ if ($property->isStatic()) {
1332
+ $name = 'static:' . $name;
1333
+ }
1334
+ if ($property->isPublic()) {
1335
+ $name = 'public:' . $name;
1336
+ } else if ($property->isPrivate()) {
1337
+ $name = 'private:' . $name;
1338
+ $rawName = "\0" . $class . "\0" . $rawName;
1339
+ } else if ($property->isProtected()) {
1340
+ $name = 'protected:' . $name;
1341
+ $rawName = "\0" . '*' . "\0" . $rawName;
1342
+ }
1343
+
1344
+ if (!(isset($this->objectFilters[$classLower])
1345
+ && is_array($this->objectFilters[$classLower])
1346
+ && in_array($plainName, $this->objectFilters[$classLower]))) {
1347
+
1348
+ if (array_key_exists($rawName, $members) && !$property->isStatic()) {
1349
+ $return[$name] = $this->encodeObject($members[$rawName], $objectDepth + 1, 1, $maxDepth + 1);
1350
+ } else {
1351
+ if (method_exists($property, 'setAccessible')) {
1352
+ $property->setAccessible(true);
1353
+ $return[$name] = $this->encodeObject($property->getValue($object), $objectDepth + 1, 1, $maxDepth + 1);
1354
+ } else
1355
+ if ($property->isPublic()) {
1356
+ $return[$name] = $this->encodeObject($property->getValue($object), $objectDepth + 1, 1, $maxDepth + 1);
1357
+ } else {
1358
+ $return[$name] = '** Need PHP 5.3 to get value **';
1359
+ }
1360
+ }
1361
+ } else {
1362
+ $return[$name] = '** Excluded by Filter **';
1363
+ }
1364
+ }
1365
 
1366
+ // Include all members that are not defined in the class
1367
+ // but exist in the object
1368
+ foreach ($members as $rawName => $value) {
1369
+
1370
+ $name = $rawName;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1371
 
1372
+ if ($name{0} == "\0") {
1373
+ $parts = explode("\0", $name);
1374
+ $name = $parts[2];
1375
+ }
1376
+
1377
+ $plainName = $name;
1378
+
1379
+ if (!isset($properties[$name])) {
1380
+ $name = 'undeclared:' . $name;
1381
+
1382
+ if (!(isset($this->objectFilters[$classLower])
1383
+ && is_array($this->objectFilters[$classLower])
1384
+ && in_array($plainName, $this->objectFilters[$classLower]))) {
1385
+
1386
+ $return[$name] = $this->encodeObject($value, $objectDepth + 1, 1, $maxDepth + 1);
1387
+ } else {
1388
+ $return[$name] = '** Excluded by Filter **';
1389
+ }
1390
+ }
1391
+ }
1392
 
1393
+ array_pop($this->objectStack);
1394
+
1395
+ } elseif (is_array($object)) {
1396
+
1397
+ if ($arrayDepth > $this->options['maxArrayDepth']) {
1398
+ return '** Max Array Depth (' . $this->options['maxArrayDepth'] . ') **';
 
 
 
 
1399
  }
 
 
 
 
 
 
 
 
1400
 
1401
+ foreach ($object as $key => $val) {
1402
+
1403
+ // Encoding the $GLOBALS PHP array causes an infinite loop
1404
+ // if the recursion is not reset here as it contains
1405
+ // a reference to itself. This is the only way I have come up
1406
+ // with to stop infinite recursion in this case.
1407
+ if ($key == 'GLOBALS'
1408
+ && is_array($val)
1409
+ && array_key_exists('GLOBALS', $val)) {
1410
+ $val['GLOBALS'] = '** Recursion (GLOBALS) **';
1411
+ }
1412
+
1413
+ if (!$this->is_utf8($key)) {
1414
+ $key = utf8_encode($key);
1415
+ }
1416
+
1417
+ $return[$key] = $this->encodeObject($val, 1, $arrayDepth + 1, $maxDepth + 1);
1418
+ }
1419
+ } elseif ( is_bool($object) ) {
1420
+ return $object;
1421
+ } elseif ( is_null($object) ) {
1422
+ return $object;
1423
+ } elseif ( is_numeric($object) ) {
1424
+ return $object;
1425
+ } else {
1426
+ if ($this->is_utf8($object)) {
1427
+ return $object;
1428
  } else {
1429
+ return utf8_encode($object);
1430
  }
 
1431
  }
1432
+ return $return;
1433
+ }
 
 
1434
 
1435
+ /**
1436
+ * Returns true if $string is valid UTF-8 and false otherwise.
1437
+ *
1438
+ * @param mixed $str String to be tested
1439
+ * @return boolean
1440
+ */
1441
+ protected function is_utf8($str)
1442
+ {
1443
+ if (function_exists('mb_detect_encoding')) {
1444
+ return (
1445
+ mb_detect_encoding($str, 'UTF-8', true) == 'UTF-8' &&
1446
+ ($str === null || $this->jsonEncode($str, true) !== 'null')
1447
+ );
1448
  }
1449
+ $c = 0;
1450
+ $b = 0;
1451
+ $bits = 0;
1452
+ $len = strlen($str);
1453
+ for ($i = 0; $i < $len; $i++) {
1454
+ $c = ord($str[$i]);
1455
+ if ($c > 128) {
1456
+ if (($c >= 254)) return false;
1457
+ elseif ($c >= 252) $bits = 6;
1458
+ elseif ($c >= 248) $bits = 5;
1459
+ elseif ($c >= 240) $bits = 4;
1460
+ elseif ($c >= 224) $bits = 3;
1461
+ elseif ($c >= 192) $bits = 2;
1462
+ else return false;
1463
+ if (($i + $bits) > $len) return false;
1464
+ while($bits > 1) {
1465
+ $i++;
1466
+ $b = ord($str[$i]);
1467
+ if ($b < 128 || $b > 191) return false;
1468
+ $bits--;
1469
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1470
  }
1471
  }
1472
+ return ($str === null || $this->jsonEncode($str, true) !== 'null');
1473
+ }
1474
+
1475
+ /**
1476
+ * Converts to and from JSON format.
1477
+ *
1478
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
1479
+ * format. It is easy for humans to read and write. It is easy for machines
1480
+ * to parse and generate. It is based on a subset of the JavaScript
1481
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
1482
+ * This feature can also be found in Python. JSON is a text format that is
1483
+ * completely language independent but uses conventions that are familiar
1484
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
1485
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
1486
+ * ideal data-interchange language.
1487
+ *
1488
+ * This package provides a simple encoder and decoder for JSON notation. It
1489
+ * is intended for use with client-side Javascript applications that make
1490
+ * use of HTTPRequest to perform server communication functions - data can
1491
+ * be encoded into JSON notation for use in a client-side javascript, or
1492
+ * decoded from incoming Javascript requests. JSON format is native to
1493
+ * Javascript, and can be directly eval()'ed with no further parsing
1494
+ * overhead
1495
+ *
1496
+ * All strings should be in ASCII or UTF-8 format!
1497
+ *
1498
+ * LICENSE: Redistribution and use in source and binary forms, with or
1499
+ * without modification, are permitted provided that the following
1500
+ * conditions are met: Redistributions of source code must retain the
1501
+ * above copyright notice, this list of conditions and the following
1502
+ * disclaimer. Redistributions in binary form must reproduce the above
1503
+ * copyright notice, this list of conditions and the following disclaimer
1504
+ * in the documentation and/or other materials provided with the
1505
+ * distribution.
1506
+ *
1507
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1508
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1509
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
1510
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
1511
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
1512
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
1513
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1514
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
1515
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1516
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1517
+ * DAMAGE.
1518
+ *
1519
+ * @category
1520
+ * @package Services_JSON
1521
+ * @author Michal Migurski <mike-json@teczno.com>
1522
+ * @author Matt Knapp <mdknapp[at]gmail[dot]com>
1523
+ * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
1524
+ * @author Christoph Dorn <christoph@christophdorn.com>
1525
+ * @copyright 2005 Michal Migurski
1526
+ * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
1527
+ * @license http://www.opensource.org/licenses/bsd-license.php
1528
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
1529
+ */
 
1530
 
1531
 
1532
+ /**
1533
+ * Keep a list of objects as we descend into the array so we can detect recursion.
1534
+ */
1535
+ private $json_objectStack = array();
1536
+
1537
+
1538
+ /**
1539
+ * convert a string from one UTF-8 char to one UTF-16 char
1540
+ *
1541
+ * Normally should be handled by mb_convert_encoding, but
1542
+ * provides a slower PHP-only method for installations
1543
+ * that lack the multibye string extension.
1544
+ *
1545
+ * @param string $utf8 UTF-8 character
1546
+ * @return string UTF-16 character
1547
+ * @access private
1548
+ */
1549
+ private function json_utf82utf16($utf8)
1550
+ {
1551
+ // oh please oh please oh please oh please oh please
1552
+ if (function_exists('mb_convert_encoding')) {
1553
+ return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
1554
+ }
1555
+
1556
+ switch (strlen($utf8)) {
1557
+ case 1:
1558
+ // this case should never be reached, because we are in ASCII range
1559
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1560
+ return $utf8;
1561
+
1562
+ case 2:
1563
+ // return a UTF-16 character from a 2-byte UTF-8 char
1564
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1565
+ return chr(0x07 & (ord($utf8{0}) >> 2))
1566
+ . chr((0xC0 & (ord($utf8{0}) << 6))
1567
  | (0x3F & ord($utf8{1})));
1568
 
1569
+ case 3:
1570
+ // return a UTF-16 character from a 3-byte UTF-8 char
1571
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1572
+ return chr((0xF0 & (ord($utf8{0}) << 4))
1573
  | (0x0F & (ord($utf8{1}) >> 2)))
1574
+ . chr((0xC0 & (ord($utf8{1}) << 6))
1575
  | (0x7F & ord($utf8{2})));
1576
+ }
1577
+
1578
+ // ignoring UTF-32 for now, sorry
1579
+ return '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1580
  }
1581
+
1582
+ /**
1583
+ * encodes an arbitrary variable into JSON format
1584
+ *
1585
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
1586
+ * see argument 1 to Services_JSON() above for array-parsing behavior.
1587
+ * if var is a strng, note that encode() always expects it
1588
+ * to be in ASCII or UTF-8 format!
1589
+ *
1590
+ * @return mixed JSON string representation of input var or an error if a problem occurs
1591
+ * @access public
1592
+ */
1593
+ private function json_encode($var)
1594
+ {
1595
+ if (is_object($var)) {
1596
+ if (in_array($var, $this->json_objectStack)) {
1597
+ return '"** Recursion **"';
1598
+ }
1599
+ }
1600
 
1601
+ switch (gettype($var)) {
1602
+ case 'boolean':
1603
+ return $var ? 'true' : 'false';
1604
+
1605
+ case 'NULL':
1606
+ return 'null';
1607
+
1608
+ case 'integer':
1609
+ return (int) $var;
1610
+
1611
+ case 'double':
1612
+ case 'float':
1613
+ return (float) $var;
1614
+
1615
+ case 'string':
1616
+ // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
1617
+ $ascii = '';
1618
+ $strlen_var = strlen($var);
1619
+
1620
+ /*
1621
+ * Iterate over every character in the string,
1622
+ * escaping with a slash or encoding to UTF-8 where necessary
1623
+ */
1624
+ for ($c = 0; $c < $strlen_var; ++$c) {
1625
+
1626
+ $ord_var_c = ord($var{$c});
1627
+
1628
+ switch (true) {
1629
+ case $ord_var_c == 0x08:
1630
+ $ascii .= '\b';
1631
+ break;
1632
+ case $ord_var_c == 0x09:
1633
+ $ascii .= '\t';
1634
+ break;
1635
+ case $ord_var_c == 0x0A:
1636
+ $ascii .= '\n';
1637
+ break;
1638
+ case $ord_var_c == 0x0C:
1639
+ $ascii .= '\f';
1640
+ break;
1641
+ case $ord_var_c == 0x0D:
1642
+ $ascii .= '\r';
1643
+ break;
1644
+
1645
+ case $ord_var_c == 0x22:
1646
+ case $ord_var_c == 0x2F:
1647
+ case $ord_var_c == 0x5C:
1648
+ // double quote, slash, slosh
1649
+ $ascii .= '\\' . $var{$c};
1650
+ break;
1651
+
1652
+ case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
1653
+ // characters U-00000000 - U-0000007F (same as ASCII)
1654
+ $ascii .= $var{$c};
1655
+ break;
1656
+
1657
+ case (($ord_var_c & 0xE0) == 0xC0):
1658
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
1659
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1660
+ $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
1661
+ $c += 1;
1662
+ $utf16 = $this->json_utf82utf16($char);
1663
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1664
+ break;
1665
+
1666
+ case (($ord_var_c & 0xF0) == 0xE0):
1667
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
1668
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1669
+ $char = pack('C*', $ord_var_c,
1670
+ ord($var{$c + 1}),
1671
+ ord($var{$c + 2}));
1672
+ $c += 2;
1673
+ $utf16 = $this->json_utf82utf16($char);
1674
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1675
+ break;
1676
+
1677
+ case (($ord_var_c & 0xF8) == 0xF0):
1678
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
1679
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1680
+ $char = pack('C*', $ord_var_c,
1681
+ ord($var{$c + 1}),
1682
+ ord($var{$c + 2}),
1683
+ ord($var{$c + 3}));
1684
+ $c += 3;
1685
+ $utf16 = $this->json_utf82utf16($char);
1686
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1687
+ break;
1688
+
1689
+ case (($ord_var_c & 0xFC) == 0xF8):
1690
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
1691
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1692
+ $char = pack('C*', $ord_var_c,
1693
+ ord($var{$c + 1}),
1694
+ ord($var{$c + 2}),
1695
+ ord($var{$c + 3}),
1696
+ ord($var{$c + 4}));
1697
+ $c += 4;
1698
+ $utf16 = $this->json_utf82utf16($char);
1699
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1700
+ break;
1701
+
1702
+ case (($ord_var_c & 0xFE) == 0xFC):
1703
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
1704
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
1705
+ $char = pack('C*', $ord_var_c,
1706
+ ord($var{$c + 1}),
1707
+ ord($var{$c + 2}),
1708
+ ord($var{$c + 3}),
1709
+ ord($var{$c + 4}),
1710
+ ord($var{$c + 5}));
1711
+ $c += 5;
1712
+ $utf16 = $this->json_utf82utf16($char);
1713
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
1714
+ break;
1715
+ }
1716
+ }
1717
+
1718
+ return '"' . $ascii . '"';
1719
+
1720
+ case 'array':
1721
+ /*
1722
+ * As per JSON spec if any array key is not an integer
1723
+ * we must treat the the whole array as an object. We
1724
+ * also try to catch a sparsely populated associative
1725
+ * array with numeric keys here because some JS engines
1726
+ * will create an array with empty indexes up to
1727
+ * max_index which can cause memory issues and because
1728
+ * the keys, which may be relevant, will be remapped
1729
+ * otherwise.
1730
+ *
1731
+ * As per the ECMA and JSON specification an object may
1732
+ * have any string as a property. Unfortunately due to
1733
+ * a hole in the ECMA specification if the key is a
1734
+ * ECMA reserved word or starts with a digit the
1735
+ * parameter is only accessible using ECMAScript's
1736
+ * bracket notation.
1737
+ */
1738
+
1739
+ // treat as a JSON object
1740
+ if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
1741
 
1742
+ $this->json_objectStack[] = $var;
1743
 
1744
+ $properties = array_map(array($this, 'json_name_value'),
1745
+ array_keys($var),
1746
+ array_values($var));
1747
 
1748
+ array_pop($this->json_objectStack);
1749
 
1750
+ foreach ($properties as $property) {
1751
+ if ($property instanceof Exception) {
1752
+ return $property;
1753
+ }
1754
+ }
1755
 
1756
+ return '{' . join(',', $properties) . '}';
1757
+ }
1758
 
1759
+ $this->json_objectStack[] = $var;
1760
 
1761
+ // treat it like a regular array
1762
+ $elements = array_map(array($this, 'json_encode'), $var);
1763
 
1764
+ array_pop($this->json_objectStack);
1765
 
1766
+ foreach ($elements as $element) {
1767
+ if ($element instanceof Exception) {
1768
+ return $element;
1769
+ }
1770
+ }
1771
 
1772
+ return '[' . join(',', $elements) . ']';
1773
 
1774
+ case 'object':
1775
+ $vars = self::encodeObject($var);
1776
 
1777
+ $this->json_objectStack[] = $var;
1778
 
1779
+ $properties = array_map(array($this, 'json_name_value'),
1780
+ array_keys($vars),
1781
+ array_values($vars));
1782
 
1783
+ array_pop($this->json_objectStack);
1784
 
1785
+ foreach ($properties as $property) {
1786
+ if ($property instanceof Exception) {
1787
+ return $property;
1788
+ }
1789
+ }
1790
 
1791
+ return '{' . join(',', $properties) . '}';
1792
+
1793
+ default:
1794
+ return null;
1795
+ }
1796
+ }
1797
+
1798
+ /**
1799
+ * array-walking function for use in generating JSON-formatted name-value pairs
1800
+ *
1801
+ * @param string $name name of key to use
1802
+ * @param mixed $value reference to an array element to be encoded
1803
+ *
1804
+ * @return string JSON-formatted name-value pair, like '"name":value'
1805
+ * @access private
1806
+ */
1807
+ private function json_name_value($name, $value)
1808
+ {
1809
+ // Encoding the $GLOBALS PHP array causes an infinite loop
1810
+ // if the recursion is not reset here as it contains
1811
+ // a reference to itself. This is the only way I have come up
1812
+ // with to stop infinite recursion in this case.
1813
+ if ($name == 'GLOBALS'
1814
+ && is_array($value)
1815
+ && array_key_exists('GLOBALS', $value)) {
1816
+ $value['GLOBALS'] = '** Recursion **';
1817
+ }
1818
 
1819
+ $encodedValue = $this->json_encode($value);
1820
 
1821
+ if ($encodedValue instanceof Exception) {
1822
+ return $encodedValue;
1823
+ }
1824
 
1825
+ return $this->json_encode(strval($name)) . ':' . $encodedValue;
1826
+ }
1827
+
1828
+ /**
1829
+ * @deprecated
1830
+ */
1831
+ public function setProcessorUrl($URL)
1832
+ {
1833
+ trigger_error('The FirePHP::setProcessorUrl() method is no longer supported', E_USER_DEPRECATED);
1834
+ }
1835
+
1836
+ /**
1837
+ * @deprecated
1838
+ */
1839
+ public function setRendererUrl($URL)
1840
+ {
1841
+ trigger_error('The FirePHP::setRendererUrl() method is no longer supported', E_USER_DEPRECATED);
1842
+ }
1843
+ }
includes/min/lib/JSMin.php CHANGED
@@ -108,6 +108,11 @@ class JSMin {
108
  $mbIntEnc = mb_internal_encoding();
109
  mb_internal_encoding('8bit');
110
  }
 
 
 
 
 
111
  $this->input = str_replace("\r\n", "\n", $this->input);
112
  $this->inputLength = strlen($this->input);
113
 
@@ -200,8 +205,9 @@ class JSMin {
200
  break;
201
  }
202
  if ($this->isEOF($this->a)) {
 
203
  throw new JSMin_UnterminatedStringException(
204
- "JSMin: Unterminated String at byte {$this->inputIndex}: {$str}");
205
  }
206
  $str .= $this->a;
207
  if ($this->a === '\\') {
@@ -251,8 +257,9 @@ class JSMin {
251
  $this->a = $this->get();
252
  $pattern .= $this->a;
253
  } elseif ($this->isEOF($this->a)) {
 
254
  throw new JSMin_UnterminatedRegExpException(
255
- "JSMin: Unterminated RegExp at byte {$this->inputIndex}: {$pattern}");
256
  }
257
  $this->output .= $this->a;
258
  $this->lastByteOut = $this->a;
@@ -269,27 +276,39 @@ class JSMin {
269
  protected function isRegexpLiteral()
270
  {
271
  if (false !== strpos("(,=:[!&|?+-~*{;", $this->a)) {
272
- // we obviously aren't dividing
273
  return true;
274
  }
 
 
 
275
  if ($this->a === ' ' || $this->a === "\n") {
276
- $length = strlen($this->output);
277
  if ($length < 2) { // weird edge case
278
  return true;
279
  }
280
- // you can't divide a keyword
281
- if (preg_match('/(?:case|else|in|return|typeof)$/', $this->output, $m)) {
282
- if ($this->output === $m[0]) { // odd but could happen
283
- return true;
284
- }
285
- // make sure it's a keyword, not end of an identifier
286
- $charBeforeKeyword = substr($this->output, $length - strlen($m[0]) - 1, 1);
287
- if (! $this->isAlphaNum($charBeforeKeyword)) {
288
- return true;
289
- }
290
- }
291
  }
292
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  }
294
 
295
  /**
108
  $mbIntEnc = mb_internal_encoding();
109
  mb_internal_encoding('8bit');
110
  }
111
+
112
+ if (isset($this->input[0]) && $this->input[0] === "\xef") {
113
+ $this->input = substr($this->input, 3);
114
+ }
115
+
116
  $this->input = str_replace("\r\n", "\n", $this->input);
117
  $this->inputLength = strlen($this->input);
118
 
205
  break;
206
  }
207
  if ($this->isEOF($this->a)) {
208
+ $byte = $this->inputIndex - 1;
209
  throw new JSMin_UnterminatedStringException(
210
+ "JSMin: Unterminated String at byte {$byte}: {$str}");
211
  }
212
  $str .= $this->a;
213
  if ($this->a === '\\') {
257
  $this->a = $this->get();
258
  $pattern .= $this->a;
259
  } elseif ($this->isEOF($this->a)) {
260
+ $byte = $this->inputIndex - 1;
261
  throw new JSMin_UnterminatedRegExpException(
262
+ "JSMin: Unterminated RegExp at byte {$byte}: {$pattern}");
263
  }
264
  $this->output .= $this->a;
265
  $this->lastByteOut = $this->a;
276
  protected function isRegexpLiteral()
277
  {
278
  if (false !== strpos("(,=:[!&|?+-~*{;", $this->a)) {
279
+ // we can't divide after these tokens
280
  return true;
281
  }
282
+
283
+ // check if first non-ws token is "/" (see starts-regex.js)
284
+ $length = strlen($this->output);
285
  if ($this->a === ' ' || $this->a === "\n") {
 
286
  if ($length < 2) { // weird edge case
287
  return true;
288
  }
 
 
 
 
 
 
 
 
 
 
 
289
  }
290
+
291
+ // if the "/" follows a keyword, it must be a regexp, otherwise it's best to assume division
292
+
293
+ $subject = $this->output . trim($this->a);
294
+ if (!preg_match('/(?:case|else|in|return|typeof)$/', $subject, $m)) {
295
+ // not a keyword
296
+ return false;
297
+ }
298
+
299
+ // can't be sure it's a keyword yet (see not-regexp.js)
300
+ $charBeforeKeyword = substr($subject, 0 - strlen($m[0]) - 1, 1);
301
+ if ($this->isAlphaNum($charBeforeKeyword)) {
302
+ // this is really an identifier ending in a keyword, e.g. "xreturn"
303
+ return false;
304
+ }
305
+
306
+ // it's a regexp. Remove unneeded whitespace after keyword
307
+ if ($this->a === ' ' || $this->a === "\n") {
308
+ $this->a = '';
309
+ }
310
+
311
+ return true;
312
  }
313
 
314
  /**
includes/min/lib/JSMinPlus.php CHANGED
@@ -170,7 +170,9 @@ define('KEYWORD_VOID', 'void');
170
  define('KEYWORD_WHILE', 'while');
171
  define('KEYWORD_WITH', 'with');
172
 
173
-
 
 
174
  class JSMinPlus
175
  {
176
  private $parser;
@@ -197,6 +199,8 @@ class JSMinPlus
197
 
198
  public static function minify($js, $filename='')
199
  {
 
 
200
  static $instance;
201
 
202
  // this is a singleton
170
  define('KEYWORD_WHILE', 'while');
171
  define('KEYWORD_WITH', 'with');
172
 
173
+ /**
174
+ * @deprecated 2.3 This will be removed in Minify 3.0
175
+ */
176
  class JSMinPlus
177
  {
178
  private $parser;
199
 
200
  public static function minify($js, $filename='')
201
  {
202
+ trigger_error(__CLASS__ . ' is deprecated. This will be removed in Minify 3.0', E_USER_DEPRECATED);
203
+
204
  static $instance;
205
 
206
  // this is a singleton
includes/min/lib/Minify.php CHANGED
@@ -24,7 +24,7 @@
24
  */
25
  class Minify {
26
 
27
- const VERSION = '2.1.7';
28
  const TYPE_CSS = 'text/css';
29
  const TYPE_HTML = 'text/html';
30
  // there is some debate over the ideal JS Content-Type, but this is the
@@ -124,6 +124,9 @@ class Minify {
124
  * 'debug' : set to true to minify all sources with the 'Lines' controller, which
125
  * eases the debugging of combined files. This also prevents 304 responses.
126
  * @see Minify_Lines::minify()
 
 
 
127
  *
128
  * 'minifiers' : to override Minify's default choice of minifier function for
129
  * a particular content-type, specify your callback under the key of the
@@ -251,11 +254,21 @@ class Minify {
251
  $headers = $cg->getHeaders();
252
  unset($cg);
253
  }
254
-
255
- if (self::$_options['contentType'] === self::TYPE_CSS
256
- && self::$_options['rewriteCssUris']) {
257
- foreach($controller->sources as $key => $source) {
258
- if ($source->filepath
 
 
 
 
 
 
 
 
 
 
259
  && !isset($source->minifyOptions['currentDir'])
260
  && !isset($source->minifyOptions['prependRelativePath'])
261
  ) {
@@ -435,7 +448,7 @@ class Minify {
435
  header('Content-Type: text/html; charset=utf-8');
436
  echo "<h1>$h1</h1>";
437
  echo "<p>Please see <a href='$url'>$url</a>.</p>";
438
- exit();
439
  }
440
 
441
  /**
@@ -493,7 +506,7 @@ class Minify {
493
  // get next source
494
  $source = null;
495
  if ($i < $l) {
496
- $source = self::$_controller->sources[$i];
497
  /* @var Minify_Source $source */
498
  $sourceContent = $source->getContent();
499
 
@@ -565,7 +578,7 @@ class Minify {
565
  {
566
  $name = preg_replace('/[^a-zA-Z0-9\\.=_,]/', '', self::$_controller->selectionId);
567
  $name = preg_replace('/\\.+/', '.', $name);
568
- $name = substr($name, 0, 200 - 34 - strlen($prefix));
569
  $md5 = md5(serialize(array(
570
  Minify_Source::getDigest(self::$_controller->sources)
571
  ,self::$_options['minifiers']
24
  */
25
  class Minify {
26
 
27
+ const VERSION = '2.2.0';
28
  const TYPE_CSS = 'text/css';
29
  const TYPE_HTML = 'text/html';
30
  // there is some debate over the ideal JS Content-Type, but this is the
124
  * 'debug' : set to true to minify all sources with the 'Lines' controller, which
125
  * eases the debugging of combined files. This also prevents 304 responses.
126
  * @see Minify_Lines::minify()
127
+ *
128
+ * 'concatOnly' : set to true to disable minification and simply concatenate the files.
129
+ * For JS, no minifier will be used. For CSS, only URI rewriting is still performed.
130
  *
131
  * 'minifiers' : to override Minify's default choice of minifier function for
132
  * a particular content-type, specify your callback under the key of the
254
  $headers = $cg->getHeaders();
255
  unset($cg);
256
  }
257
+
258
+ if (self::$_options['concatOnly']) {
259
+ foreach ($controller->sources as $key => $source) {
260
+ if (self::$_options['contentType'] === self::TYPE_JS) {
261
+ $source->minifier = "";
262
+ } elseif (self::$_options['contentType'] === self::TYPE_CSS) {
263
+ $source->minifier = array('Minify_CSS', 'minify');
264
+ $source->minifyOptions['compress'] = false;
265
+ }
266
+ }
267
+ }
268
+
269
+ if (self::$_options['contentType'] === self::TYPE_CSS && self::$_options['rewriteCssUris']) {
270
+ foreach ($controller->sources as $key => $source) {
271
+ if ($source->filepath
272
  && !isset($source->minifyOptions['currentDir'])
273
  && !isset($source->minifyOptions['prependRelativePath'])
274
  ) {
448
  header('Content-Type: text/html; charset=utf-8');
449
  echo "<h1>$h1</h1>";
450
  echo "<p>Please see <a href='$url'>$url</a>.</p>";
451
+ exit;
452
  }
453
 
454
  /**
506
  // get next source
507
  $source = null;
508
  if ($i < $l) {
509
+ $source = self::$_controller->sources[$i];
510
  /* @var Minify_Source $source */
511
  $sourceContent = $source->getContent();
512
 
578
  {
579
  $name = preg_replace('/[^a-zA-Z0-9\\.=_,]/', '', self::$_controller->selectionId);
580
  $name = preg_replace('/\\.+/', '.', $name);
581
+ $name = substr($name, 0, 100 - 34 - strlen($prefix));
582
  $md5 = md5(serialize(array(
583
  Minify_Source::getDigest(self::$_controller->sources)
584
  ,self::$_options['minifiers']
includes/min/lib/Minify/CSS/UriRewriter.php CHANGED
@@ -66,16 +66,20 @@ class Minify_CSS_UriRewriter {
66
  self::$debugText .= "\n";
67
 
68
  $css = self::_trimUrls($css);
69
-
 
 
70
  // rewrite
71
  $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
72
  ,array(self::$className, '_processUriCB'), $css);
73
- $css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
74
  ,array(self::$className, '_processUriCB'), $css);
75
 
 
 
76
  return $css;
77
  }
78
-
79
  /**
80
  * In CSS content, prepend a path to relative URIs
81
  *
@@ -90,13 +94,17 @@ class Minify_CSS_UriRewriter {
90
  self::$_prependPath = $path;
91
 
92
  $css = self::_trimUrls($css);
 
 
93
 
94
  // append
95
  $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
96
  ,array(self::$className, '_processUriCB'), $css);
97
- $css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
98
  ,array(self::$className, '_processUriCB'), $css);
99
 
 
 
100
  self::$_prependPath = null;
101
  return $css;
102
  }
@@ -282,11 +290,8 @@ class Minify_CSS_UriRewriter {
282
  ? $m[1]
283
  : substr($m[1], 1, strlen($m[1]) - 2);
284
  }
285
- // analyze URI
286
- if ('/' !== $uri[0] // root-relative
287
- && false === strpos($uri, '//') // protocol (non-data)
288
- && 0 !== strpos($uri, 'data:') // data protocol
289
- ) {
290
  // URI is file-relative: rewrite depending on options
291
  if (self::$_prependPath === null) {
292
  $uri = self::rewriteRelative($uri, self::$_currentDir, self::$_docRoot, self::$_symlinks);
@@ -307,4 +312,30 @@ class Minify_CSS_UriRewriter {
307
  ? "@import {$quoteChar}{$uri}{$quoteChar}"
308
  : "url({$quoteChar}{$uri}{$quoteChar})";
309
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  }
66
  self::$debugText .= "\n";
67
 
68
  $css = self::_trimUrls($css);
69
+
70
+ $css = self::_owlifySvgPaths($css);
71
+
72
  // rewrite
73
  $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
74
  ,array(self::$className, '_processUriCB'), $css);
75
+ $css = preg_replace_callback('/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/'
76
  ,array(self::$className, '_processUriCB'), $css);
77
 
78
+ $css = self::_unOwlify($css);
79
+
80
  return $css;
81
  }
82
+
83
  /**
84
  * In CSS content, prepend a path to relative URIs
85
  *
94
  self::$_prependPath = $path;
95
 
96
  $css = self::_trimUrls($css);
97
+
98
+ $css = self::_owlifySvgPaths($css);
99
 
100
  // append
101
  $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
102
  ,array(self::$className, '_processUriCB'), $css);
103
+ $css = preg_replace_callback('/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/'
104
  ,array(self::$className, '_processUriCB'), $css);
105
 
106
+ $css = self::_unOwlify($css);
107
+
108
  self::$_prependPath = null;
109
  return $css;
110
  }
290
  ? $m[1]
291
  : substr($m[1], 1, strlen($m[1]) - 2);
292
  }
293
+ // if not root/scheme relative and not starts with scheme
294
+ if (!preg_match('~^(/|[a-z]+\:)~', $uri)) {
 
 
 
295
  // URI is file-relative: rewrite depending on options
296
  if (self::$_prependPath === null) {
297
  $uri = self::rewriteRelative($uri, self::$_currentDir, self::$_docRoot, self::$_symlinks);
312
  ? "@import {$quoteChar}{$uri}{$quoteChar}"
313
  : "url({$quoteChar}{$uri}{$quoteChar})";
314
  }
315
+
316
+ /**
317
+ * Mungs some inline SVG URL declarations so they won't be touched
318
+ *
319
+ * @link https://github.com/mrclay/minify/issues/517
320
+ * @see _unOwlify
321
+ *
322
+ * @param string $css
323
+ * @return string
324
+ */
325
+ private static function _owlifySvgPaths($css) {
326
+ return preg_replace('~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)url(\(\s*#\w+\s*\))~', '$1owl$2', $css);
327
+
328
+ }
329
+
330
+ /**
331
+ * Undo work of _owlify
332
+ *
333
+ * @see _owlifySvgPaths
334
+ *
335
+ * @param string $css
336
+ * @return string
337
+ */
338
+ private static function _unOwlify($css) {
339
+ return preg_replace('~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)owl~', '$1url', $css);
340
+ }
341
  }
includes/min/lib/Minify/Cache/File.php CHANGED
@@ -98,6 +98,9 @@ class Minify_Cache_File {
98
  {
99
  if ($this->_locking) {
100
  $fp = fopen($this->_path . '/' . $id, 'rb');
 
 
 
101
  flock($fp, LOCK_SH);
102
  $ret = stream_get_contents($fp);
103
  flock($fp, LOCK_UN);
98
  {
99
  if ($this->_locking) {
100
  $fp = fopen($this->_path . '/' . $id, 'rb');
101
+ if (!$fp) {
102
+ return false;
103
+ }
104
  flock($fp, LOCK_SH);
105
  $ret = stream_get_contents($fp);
106
  flock($fp, LOCK_UN);
includes/min/lib/Minify/ClosureCompiler.php CHANGED
@@ -33,6 +33,11 @@
33
  */
34
  class Minify_ClosureCompiler {
35
 
 
 
 
 
 
36
  /**
37
  * Filepath of the Closure Compiler jar file. This must be set before
38
  * calling minifyJs().
@@ -65,18 +70,28 @@ class Minify_ClosureCompiler {
65
  * @see https://code.google.com/p/closure-compiler/source/browse/trunk/README
66
  *
67
  * @return string
 
 
68
  */
69
  public static function minify($js, $options = array())
70
  {
71
  self::_prepare();
72
  if (! ($tmpFile = tempnam(self::$tempDir, 'cc_'))) {
73
- throw new Exception('Minify_ClosureCompiler : could not create temp file.');
74
  }
75
  file_put_contents($tmpFile, $js);
76
- exec(self::_getCmd($options, $tmpFile), $output, $result_code);
 
77
  unlink($tmpFile);
78
  if ($result_code != 0) {
79
- throw new Exception('Minify_ClosureCompiler : Closure Compiler execution failed.');
 
 
 
 
 
 
 
80
  }
81
  return implode("\n", $output);
82
  }
@@ -85,17 +100,18 @@ class Minify_ClosureCompiler {
85
  {
86
  $o = array_merge(
87
  array(
88
- 'charset' => 'utf-8',
89
- 'compilation_level' => 'SIMPLE_OPTIMIZATIONS',
90
  ),
91
  $userOptions
92
  );
 
93
  $cmd = self::$javaExecutable . ' -jar ' . escapeshellarg(self::$jarFile)
94
- . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $o['charset'])
95
- ? " --charset {$o['charset']}"
96
  : '');
97
 
98
- foreach (array('compilation_level') as $opt) {
99
  if ($o[$opt]) {
100
  $cmd .= " --{$opt} ". escapeshellarg($o[$opt]);
101
  }
@@ -106,18 +122,18 @@ class Minify_ClosureCompiler {
106
  private static function _prepare()
107
  {
108
  if (! is_file(self::$jarFile)) {
109
- throw new Exception('Minify_ClosureCompiler : $jarFile('.self::$jarFile.') is not a valid file.');
110
  }
111
  if (! is_readable(self::$jarFile)) {
112
- throw new Exception('Minify_ClosureCompiler : $jarFile('.self::$jarFile.') is not readable.');
113
  }
114
  if (! is_dir(self::$tempDir)) {
115
- throw new Exception('Minify_ClosureCompiler : $tempDir('.self::$tempDir.') is not a valid direcotry.');
116
  }
117
  if (! is_writable(self::$tempDir)) {
118
- throw new Exception('Minify_ClosureCompiler : $tempDir('.self::$tempDir.') is not writable.');
119
  }
120
  }
121
  }
122
 
123
- /* vim:ts=4:sw=4:et */
33
  */
34
  class Minify_ClosureCompiler {
35
 
36
+ const OPTION_CHARSET = 'charset';
37
+ const OPTION_COMPILATION_LEVEL = 'compilation_level';
38
+
39
+ public static $isDebug = false;
40
+
41
  /**
42
  * Filepath of the Closure Compiler jar file. This must be set before
43
  * calling minifyJs().
70
  * @see https://code.google.com/p/closure-compiler/source/browse/trunk/README
71
  *
72
  * @return string
73
+ *
74
+ * @throws Minify_ClosureCompiler_Exception
75
  */
76
  public static function minify($js, $options = array())
77
  {
78
  self::_prepare();
79
  if (! ($tmpFile = tempnam(self::$tempDir, 'cc_'))) {
80
+ throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : could not create temp file in "'.self::$tempDir.'".');
81
  }
82
  file_put_contents($tmpFile, $js);
83
+ $cmd = self::_getCmd($options, $tmpFile);
84
+ exec($cmd, $output, $result_code);
85
  unlink($tmpFile);
86
  if ($result_code != 0) {
87
+ $message = 'Minify_ClosureCompiler : Closure Compiler execution failed.';
88
+ if (self::$isDebug) {
89
+ exec($cmd . ' 2>&1', $error);
90
+ if ($error) {
91
+ $message .= "\nReason:\n" . join("\n", $error);
92
+ }
93
+ }
94
+ throw new Minify_ClosureCompiler_Exception($message);
95
  }
96
  return implode("\n", $output);
97
  }
100
  {
101
  $o = array_merge(
102
  array(
103
+ self::OPTION_CHARSET => 'utf-8',
104
+ self::OPTION_COMPILATION_LEVEL => 'SIMPLE_OPTIMIZATIONS',
105
  ),
106
  $userOptions
107
  );
108
+ $charsetOption = $o[self::OPTION_CHARSET];
109
  $cmd = self::$javaExecutable . ' -jar ' . escapeshellarg(self::$jarFile)
110
+ . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $charsetOption)
111
+ ? " --charset {$charsetOption}"
112
  : '');
113
 
114
+ foreach (array(self::OPTION_COMPILATION_LEVEL) as $opt) {
115
  if ($o[$opt]) {
116
  $cmd .= " --{$opt} ". escapeshellarg($o[$opt]);
117
  }
122
  private static function _prepare()
123
  {
124
  if (! is_file(self::$jarFile)) {
125
+ throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : $jarFile('.self::$jarFile.') is not a valid file.');
126
  }
127
  if (! is_readable(self::$jarFile)) {
128
+ throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : $jarFile('.self::$jarFile.') is not readable.');
129
  }
130
  if (! is_dir(self::$tempDir)) {
131
+ throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : $tempDir('.self::$tempDir.') is not a valid direcotry.');
132
  }
133
  if (! is_writable(self::$tempDir)) {
134
+ throw new Minify_ClosureCompiler_Exception('Minify_ClosureCompiler : $tempDir('.self::$tempDir.') is not writable.');
135
  }
136
  }
137
  }
138
 
139
+ class Minify_ClosureCompiler_Exception extends Exception {}
includes/min/lib/Minify/Controller/Base.php CHANGED
@@ -51,6 +51,7 @@ abstract class Minify_Controller_Base {
51
  ,'bubbleCssImports' => false
52
  ,'quiet' => false // serve() will send headers and output
53
  ,'debug' => false
 
54
 
55
  // if you override these, the response codes MUST be directly after
56
  // the first space.
@@ -125,7 +126,9 @@ abstract class Minify_Controller_Base {
125
  return true;
126
  }
127
  }
128
- throw new Exception("File '$file' is outside \$allowDirs. If the path is"
 
 
129
  . " resolved via an alias/symlink, look into the \$min_symlinks option."
130
  . " E.g. \$min_symlinks['/" . dirname($uri) . "'] = '" . dirname($file) . "';");
131
  }
@@ -145,9 +148,7 @@ abstract class Minify_Controller_Base {
145
  /**
146
  * instances of Minify_Source, which provide content and any individual minification needs.
147
  *
148
- * @var array
149
- *
150
- * @see Minify_Source
151
  */
152
  public $sources = array();
153
 
51
  ,'bubbleCssImports' => false
52
  ,'quiet' => false // serve() will send headers and output
53
  ,'debug' => false
54
+ ,'concatOnly' => false
55
 
56
  // if you override these, the response codes MUST be directly after
57
  // the first space.
126
  return true;
127
  }
128
  }
129
+
130
+ $allowDirs = implode(';', array_values($allowDirs));
131
+ throw new Exception("File '$file' is outside \$allowDirs ($allowDirs). If the path is"
132
  . " resolved via an alias/symlink, look into the \$min_symlinks option."
133
  . " E.g. \$min_symlinks['/" . dirname($uri) . "'] = '" . dirname($file) . "';");
134
  }
148
  /**
149
  * instances of Minify_Source, which provide content and any individual minification needs.
150
  *
151
+ * @var Minify_Source[]
 
 
152
  */
153
  public $sources = array();
154
 
includes/min/lib/Minify/Controller/MinApp.php CHANGED
@@ -49,7 +49,6 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
49
  $this->log("Duplicate group key found.");
50
  return $options;
51
  }
52
- $keys = explode(',', $_GET['g']);
53
  foreach ($keys as $key) {
54
  if (! isset($cOptions['groups'][$key])) {
55
  $this->log("A group configuration for \"{$key}\" was not found");
49
  $this->log("Duplicate group key found.");
50
  return $options;
51
  }
 
52
  foreach ($keys as $key) {
53
  if (! isset($cOptions['groups'][$key])) {
54
  $this->log("A group configuration for \"{$key}\" was not found");
includes/min/lib/Minify/HTML.php CHANGED
@@ -63,8 +63,6 @@ class Minify_HTML {
63
  *
64
  * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
65
  * unset, minify will sniff for an XHTML doctype.
66
- *
67
- * @return null
68
  */
69
  public function __construct($html, $options = array())
70
  {
@@ -133,7 +131,7 @@ class Minify_HTML {
133
 
134
  // remove ws around block/undisplayed elements
135
  $this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body'
136
- .'|caption|center|cite|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
137
  .'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta'
138
  .'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
139
  .'|ul)\\b[^>]*>)/i', '$1', $this->_html);
63
  *
64
  * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
65
  * unset, minify will sniff for an XHTML doctype.
 
 
66
  */
67
  public function __construct($html, $options = array())
68
  {
131
 
132
  // remove ws around block/undisplayed elements
133
  $this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body'
134
+ .'|caption|center|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
135
  .'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta'
136
  .'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
137
  .'|ul)\\b[^>]*>)/i', '$1', $this->_html);
includes/min/lib/Minify/JS/ClosureCompiler.php CHANGED
@@ -14,13 +14,68 @@
14
  * @todo can use a stream wrapper to unit test this?
15
  */
16
  class Minify_JS_ClosureCompiler {
17
- const URL = 'http://closure-compiler.appspot.com/compile';
18
 
19
  /**
20
- * Minify Javascript code via HTTP request to the Closure Compiler API
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  *
22
  * @param string $js input code
23
- * @param array $options unused at this point
 
24
  * @return string
25
  */
26
  public static function minify($js, array $options = array())
@@ -30,53 +85,91 @@ class Minify_JS_ClosureCompiler {
30
  }
31
 
32
  /**
 
33
  *
34
- * @param array $options
35
  *
36
- * fallbackFunc : default array($this, 'fallback');
 
 
 
 
 
 
 
37
  */
38
  public function __construct(array $options = array())
39
  {
40
- $this->_fallbackFunc = isset($options['fallbackMinifier'])
41
- ? $options['fallbackMinifier']
42
- : array($this, '_fallback');
 
 
 
 
 
 
 
 
 
43
  }
44
 
 
 
 
 
 
 
 
45
  public function min($js)
46
  {
47
- $postBody = $this->_buildPostBody($js);
48
- $bytes = (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2))
49
- ? mb_strlen($postBody, '8bit')
50
- : strlen($postBody);
51
- if ($bytes > 200000) {
52
- throw new Minify_JS_ClosureCompiler_Exception(
53
- 'POST content larger than 200000 bytes'
54
- );
 
 
 
55
  }
56
- $response = $this->_getResponse($postBody);
 
 
57
  if (preg_match('/^Error\(\d\d?\):/', $response)) {
58
- if (is_callable($this->_fallbackFunc)) {
 
59
  $response = "/* Received errors from Closure Compiler API:\n$response"
60
  . "\n(Using fallback minifier)\n*/\n";
61
- $response .= call_user_func($this->_fallbackFunc, $js);
62
  } else {
63
  throw new Minify_JS_ClosureCompiler_Exception($response);
64
  }
65
  }
 
66
  if ($response === '') {
67
- $errors = $this->_getResponse($this->_buildPostBody($js, true));
68
  throw new Minify_JS_ClosureCompiler_Exception($errors);
69
  }
 
70
  return $response;
71
  }
72
 
73
- protected $_fallbackFunc = null;
74
-
75
- protected function _getResponse($postBody)
 
 
 
 
 
76
  {
77
  $allowUrlFopen = preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen'));
 
78
  if ($allowUrlFopen) {
79
- $contents = file_get_contents(self::URL, false, stream_context_create(array(
80
  'http' => array(
81
  'method' => 'POST',
82
  'header' => "Content-type: application/x-www-form-urlencoded\r\nConnection: close\r\n",
@@ -86,7 +179,7 @@ class Minify_JS_ClosureCompiler {
86
  )
87
  )));
88
  } elseif (defined('CURLOPT_POST')) {
89
- $ch = curl_init(self::URL);
90
  curl_setopt($ch, CURLOPT_POST, true);
91
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
92
  curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
@@ -100,32 +193,37 @@ class Minify_JS_ClosureCompiler {
100
  "Could not make HTTP request: allow_url_open is false and cURL not available"
101
  );
102
  }
 
103
  if (false === $contents) {
104
  throw new Minify_JS_ClosureCompiler_Exception(
105
  "No HTTP response from server"
106
  );
107
  }
108
- return trim($contents);
109
- }
110
 
111
- protected function _buildPostBody($js, $returnErrors = false)
112
- {
113
- return http_build_query(array(
114
- 'js_code' => $js,
115
- 'output_info' => ($returnErrors ? 'errors' : 'compiled_code'),
116
- 'output_format' => 'text',
117
- 'compilation_level' => 'SIMPLE_OPTIMIZATIONS'
118
- ), null, '&');
119
  }
120
 
121
  /**
122
- * Default fallback function if CC API fails
123
- * @param string $js
 
 
124
  * @return string
125
  */
126
- protected function _fallback($js)
127
  {
128
- return JSMin::minify($js);
 
 
 
 
 
 
 
 
 
 
 
129
  }
130
  }
131
 
14
  * @todo can use a stream wrapper to unit test this?
15
  */
16
  class Minify_JS_ClosureCompiler {
 
17
 
18
  /**
19
+ * @var string The option key for the maximum POST byte size
20
+ */
21
+ const OPTION_MAX_BYTES = 'maxBytes';
22
+
23
+ /**
24
+ * @var string The option key for additional params. @see __construct
25
+ */
26
+ const OPTION_ADDITIONAL_OPTIONS = 'additionalParams';
27
+
28
+ /**
29
+ * @var string The option key for the fallback Minifier
30
+ */
31
+ const OPTION_FALLBACK_FUNCTION = 'fallbackFunc';
32
+
33
+ /**
34
+ * @var string The option key for the service URL
35
+ */
36
+ const OPTION_COMPILER_URL = 'compilerUrl';
37
+
38
+ /**
39
+ * @var int The default maximum POST byte size according to https://developers.google.com/closure/compiler/docs/api-ref
40
+ */
41
+ const DEFAULT_MAX_BYTES = 200000;
42
+
43
+ /**
44
+ * @var string[] $DEFAULT_OPTIONS The default options to pass to the compiler service
45
+ *
46
+ * @note This would be a constant if PHP allowed it
47
+ */
48
+ private static $DEFAULT_OPTIONS = array(
49
+ 'output_format' => 'text',
50
+ 'compilation_level' => 'SIMPLE_OPTIMIZATIONS'
51
+ );
52
+
53
+ /**
54
+ * @var string $url URL of compiler server. defaults to Google's
55
+ */
56
+ protected $serviceUrl = 'http://closure-compiler.appspot.com/compile';
57
+
58
+ /**
59
+ * @var int $maxBytes The maximum JS size that can be sent to the compiler server in bytes
60
+ */
61
+ protected $maxBytes = self::DEFAULT_MAX_BYTES;
62
+
63
+ /**
64
+ * @var string[] $additionalOptions Additional options to pass to the compiler service
65
+ */
66
+ protected $additionalOptions = array();
67
+
68
+ /**
69
+ * @var callable Function to minify JS if service fails. Default is JSMin
70
+ */
71
+ protected $fallbackMinifier = array('JSMin', 'minify');
72
+
73
+ /**
74
+ * Minify JavaScript code via HTTP request to a Closure Compiler API
75
  *
76
  * @param string $js input code
77
+ * @param array $options Options passed to __construct(). @see __construct
78
+ *
79
  * @return string
80
  */
81
  public static function minify($js, array $options = array())
85
  }
86
 
87
  /**
88
+ * @param array $options Options with keys available below:
89
  *
90
+ * fallbackFunc : (callable) function to minify if service unavailable. Default is JSMin.
91
  *
92
+ * compilerUrl : (string) URL to closure compiler server
93
+ *
94
+ * maxBytes : (int) The maximum amount of bytes to be sent as js_code in the POST request.
95
+ * Defaults to 200000.
96
+ *
97
+ * additionalParams : (string[]) Additional parameters to pass to the compiler server. Can be anything named
98
+ * in https://developers.google.com/closure/compiler/docs/api-ref except for js_code and
99
+ * output_info
100
  */
101
  public function __construct(array $options = array())
102
  {
103
+ if (isset($options[self::OPTION_FALLBACK_FUNCTION])) {
104
+ $this->fallbackMinifier = $options[self::OPTION_FALLBACK_FUNCTION];
105
+ }
106
+ if (isset($options[self::OPTION_COMPILER_URL])) {
107
+ $this->serviceUrl = $options[self::OPTION_COMPILER_URL];
108
+ }
109
+ if (isset($options[self::OPTION_ADDITIONAL_OPTIONS]) && is_array($options[self::OPTION_ADDITIONAL_OPTIONS])) {
110
+ $this->additionalOptions = $options[self::OPTION_ADDITIONAL_OPTIONS];
111
+ }
112
+ if (isset($options[self::OPTION_MAX_BYTES])) {
113
+ $this->maxBytes = (int) $options[self::OPTION_MAX_BYTES];
114
+ }
115
  }
116
 
117
+ /**
118
+ * Call the service to perform the minification
119
+ *
120
+ * @param string $js JavaScript code
121
+ * @return string
122
+ * @throws Minify_JS_ClosureCompiler_Exception
123
+ */
124
  public function min($js)
125
  {
126
+ $postBody = $this->buildPostBody($js);
127
+
128
+ if ($this->maxBytes > 0) {
129
+ $bytes = (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2))
130
+ ? mb_strlen($postBody, '8bit')
131
+ : strlen($postBody);
132
+ if ($bytes > $this->maxBytes) {
133
+ throw new Minify_JS_ClosureCompiler_Exception(
134
+ 'POST content larger than ' . $this->maxBytes . ' bytes'
135
+ );
136
+ }
137
  }
138
+
139
+ $response = $this->getResponse($postBody);
140
+
141
  if (preg_match('/^Error\(\d\d?\):/', $response)) {
142
+ if (is_callable($this->fallbackMinifier)) {
143
+ // use fallback
144
  $response = "/* Received errors from Closure Compiler API:\n$response"
145
  . "\n(Using fallback minifier)\n*/\n";
146
+ $response .= call_user_func($this->fallbackMinifier, $js);
147
  } else {
148
  throw new Minify_JS_ClosureCompiler_Exception($response);
149
  }
150
  }
151
+
152
  if ($response === '') {
153
+ $errors = $this->getResponse($this->buildPostBody($js, true));
154
  throw new Minify_JS_ClosureCompiler_Exception($errors);
155
  }
156
+
157
  return $response;
158
  }
159
 
160
+ /**
161
+ * Get the response for a given POST body
162
+ *
163
+ * @param string $postBody
164
+ * @return string
165
+ * @throws Minify_JS_ClosureCompiler_Exception
166
+ */
167
+ protected function getResponse($postBody)
168
  {
169
  $allowUrlFopen = preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen'));
170
+
171
  if ($allowUrlFopen) {
172
+ $contents = file_get_contents($this->serviceUrl, false, stream_context_create(array(
173
  'http' => array(
174
  'method' => 'POST',
175
  'header' => "Content-type: application/x-www-form-urlencoded\r\nConnection: close\r\n",
179
  )
180
  )));
181
  } elseif (defined('CURLOPT_POST')) {
182
+ $ch = curl_init($this->serviceUrl);
183
  curl_setopt($ch, CURLOPT_POST, true);
184
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
185
  curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
193
  "Could not make HTTP request: allow_url_open is false and cURL not available"
194
  );
195
  }
196
+
197
  if (false === $contents) {
198
  throw new Minify_JS_ClosureCompiler_Exception(
199
  "No HTTP response from server"
200
  );
201
  }
 
 
202
 
203
+ return trim($contents);
 
 
 
 
 
 
 
204
  }
205
 
206
  /**
207
+ * Build a POST request body
208
+ *
209
+ * @param string $js JavaScript code
210
+ * @param bool $returnErrors
211
  * @return string
212
  */
213
+ protected function buildPostBody($js, $returnErrors = false)
214
  {
215
+ return http_build_query(
216
+ array_merge(
217
+ self::$DEFAULT_OPTIONS,
218
+ $this->additionalOptions,
219
+ array(
220
+ 'js_code' => $js,
221
+ 'output_info' => ($returnErrors ? 'errors' : 'compiled_code')
222
+ )
223
+ ),
224
+ null,
225
+ '&'
226
+ );
227
  }
228
  }
229
 
includes/min/lib/Minify/Loader.php CHANGED
@@ -9,6 +9,8 @@
9
  *
10
  * @package Minify
11
  * @author Stephen Clay <steve@mrclay.org>
 
 
12
  */
13
  class Minify_Loader {
14
  public function loadClass($class)
@@ -20,6 +22,9 @@ class Minify_Loader {
20
  }
21
  }
22
 
 
 
 
23
  static public function register()
24
  {
25
  $inst = new self();
9
  *
10
  * @package Minify
11
  * @author Stephen Clay <steve@mrclay.org>
12
+ *
13
+ * @deprecated 2.3 This will be removed in Minify 3.0
14
  */
15
  class Minify_Loader {
16
  public function loadClass($class)
22
  }
23
  }
24
 
25
+ /**
26
+ * @deprecated 2.3 This will be removed in Minify 3.0
27
+ */
28
  static public function register()
29
  {
30
  $inst = new self();
includes/min/lib/Minify/Logger.php CHANGED
@@ -10,7 +10,7 @@
10
  * @package Minify
11
  * @author Stephen Clay <steve@mrclay.org>
12
  *
13
- * @todo lose this singleton! pass log object in Minify::serve and distribute to others
14
  */
15
  class Minify_Logger {
16
 
10
  * @package Minify
11
  * @author Stephen Clay <steve@mrclay.org>
12
  *
13
+ * @deprecated 2.3 This will be removed in Minify 3.0
14
  */
15
  class Minify_Logger {
16
 
includes/min/lib/Minify/YUICompressor.php CHANGED
@@ -90,7 +90,7 @@ class Minify_YUICompressor {
90
  {
91
  self::_prepare();
92
  if (! ($tmpFile = tempnam(self::$tempDir, 'yuic_'))) {
93
- throw new Exception('Minify_YUICompressor : could not create temp file.');
94
  }
95
  file_put_contents($tmpFile, $content);
96
  exec(self::_getCmd($options, $type, $tmpFile), $output, $result_code);
90
  {
91
  self::_prepare();
92
  if (! ($tmpFile = tempnam(self::$tempDir, 'yuic_'))) {
93
+ throw new Exception('Minify_YUICompressor : could not create temp file in "'.self::$tempDir.'".');
94
  }
95
  file_put_contents($tmpFile, $content);
96
  exec(self::_getCmd($options, $type, $tmpFile), $output, $result_code);
includes/min/quick-test.css CHANGED
@@ -3,7 +3,7 @@
3
  * http://example.org/min/f=min/quick-test.css
4
  */
5
 
6
- @import url( /more.css );
7
 
8
  body, td, th {
9
  font-family: Verdana , "Bitstream Vera Sans" , Arial Narrow, sans-serif ;
3
  * http://example.org/min/f=min/quick-test.css
4
  */
5
 
6
+ @import url( more.css );
7
 
8
  body, td, th {
9
  font-family: Verdana , "Bitstream Vera Sans" , Arial Narrow, sans-serif ;
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: minify, compress, combine, html, css, javascript, js, performance, load, s
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3S8BRPLWLNQ38
5
  Requires at least: 3.5
6
  Tested up to: 4.7
7
- Stable tag: 1.4
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -45,6 +45,9 @@ Pretty much, yeah.
45
  1. Admin Settings
46
 
47
  == Changelog ==
 
 
 
48
  = 1.4, October 1, 2016 =
49
  * Fixed css conflict with WP Performance Score Booster.
50
  * Improved Settings page.
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3S8BRPLWLNQ38
5
  Requires at least: 3.5
6
  Tested up to: 4.7
7
+ Stable tag: 1.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
45
  1. Admin Settings
46
 
47
  == Changelog ==
48
+ = 1.5, December 30, 2016 =
49
+ * Updated min library to it's latest version
50
+
51
  = 1.4, October 1, 2016 =
52
  * Fixed css conflict with WP Performance Score Booster.
53
  * Improved Settings page.
wp-super-minify.php CHANGED
@@ -3,9 +3,9 @@
3
  Plugin Name: WP Super Minify
4
  Plugin URI: https://github.com/dipakcg/wp-super-minify
5
  Description: Minifies, caches and combine inline JavaScript and CSS files to improve page load time.
6
- Version: 1.4
7
  Author: Dipak C. Gajjar
8
- Author URI: http://dipakgajjar.com
9
  */
10
 
11
  // Define plugin version for future releases
@@ -13,7 +13,7 @@ if (!defined('WPSMY_PLUGIN_VERSION')) {
13
  define('WPSMY_PLUGIN_VERSION', 'wpsmy_plugin_version');
14
  }
15
  if (!defined('WPSMY_PLUGIN_VERSION_NUM')) {
16
- define('WPSMY_PLUGIN_VERSION_NUM', '1.4');
17
  }
18
  update_option(WPSMY_PLUGIN_VERSION, WPSMY_PLUGIN_VERSION_NUM);
19
 
3
  Plugin Name: WP Super Minify
4
  Plugin URI: https://github.com/dipakcg/wp-super-minify
5
  Description: Minifies, caches and combine inline JavaScript and CSS files to improve page load time.
6
+ Version: 1.5
7
  Author: Dipak C. Gajjar
8
+ Author URI: https://dipakgajjar.com
9
  */
10
 
11
  // Define plugin version for future releases
13
  define('WPSMY_PLUGIN_VERSION', 'wpsmy_plugin_version');
14
  }
15
  if (!defined('WPSMY_PLUGIN_VERSION_NUM')) {
16
+ define('WPSMY_PLUGIN_VERSION_NUM', '1.5');
17
  }
18
  update_option(WPSMY_PLUGIN_VERSION, WPSMY_PLUGIN_VERSION_NUM);
19