WordPress Page Builder – Beaver Builder - Version 2.4.2.5

Version Description

Download this release

Release Info

Developer pross
Plugin Icon 128x128 WordPress Page Builder – Beaver Builder
Version 2.4.2.5
Comparing to
See all releases

Code changes from version 2.4.2.4 to 2.4.2.5

changelog.txt CHANGED
@@ -1,3 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
1
  <h4>2.4.2.4 - 06/15/2021</h4>
2
  <strong>Hot Fix</strong>
3
  <ul>
1
+ <h4>2.4.2.5 - 07/21/2021</h4>
2
+ <strong>Hot Fix</strong>
3
+ <ul>
4
+ <li>Fix responsive editing while inline CSS is enabled</li>
5
+ <li>Accordion Module: Fix spacing issue in HTML when collapse is disabled</li>
6
+ <li>Subscribe Module: Fix conflict with WooCommerce Mailer Lite</li>
7
+ <li>Subscribe Module: Fix integration with Campaign Monitor when using PHP 8</li>
8
+ <li>Subscribe Module: Update MailPoet integration for their new API</li>
9
+ <li>Fix notice for block preload path when using WP 5.8</li>
10
+ </ul>
11
+
12
  <h4>2.4.2.4 - 06/15/2021</h4>
13
  <strong>Hot Fix</strong>
14
  <ul>
classes/class-fl-builder-loader.php CHANGED
@@ -48,7 +48,7 @@ if ( ! class_exists( 'FLBuilderLoader' ) ) {
48
  * @return void
49
  */
50
  static private function define_constants() {
51
- define( 'FL_BUILDER_VERSION', '2.4.2.4' );
52
  define( 'FL_BUILDER_FILE', trailingslashit( dirname( dirname( __FILE__ ) ) ) . 'fl-builder.php' );
53
  define( 'FL_BUILDER_DIR', plugin_dir_path( FL_BUILDER_FILE ) );
54
  define( 'FL_BUILDER_URL', plugins_url( '/', FL_BUILDER_FILE ) );
48
  * @return void
49
  */
50
  static private function define_constants() {
51
+ define( 'FL_BUILDER_VERSION', '2.4.2.5' );
52
  define( 'FL_BUILDER_FILE', trailingslashit( dirname( dirname( __FILE__ ) ) ) . 'fl-builder.php' );
53
  define( 'FL_BUILDER_DIR', plugin_dir_path( FL_BUILDER_FILE ) );
54
  define( 'FL_BUILDER_URL', plugins_url( '/', FL_BUILDER_FILE ) );
classes/class-fl-builder-service-mailpoet.php CHANGED
@@ -178,7 +178,6 @@ final class FLBuilderServiceMailPoet extends FLBuilderService {
178
 
179
  // MailPoet 3.0
180
  } elseif ( defined( 'MAILPOET_INITIALIZED' ) && true === MAILPOET_INITIALIZED ) {
181
- $subscriber = new MailPoet\Models\Subscriber();
182
 
183
  if ( $names && isset( $names[0] ) ) {
184
  $user['first_name'] = $names[0];
@@ -187,16 +186,28 @@ final class FLBuilderServiceMailPoet extends FLBuilderService {
187
  $user['last_name'] = $names[1];
188
  }
189
 
190
- $subscribed = $subscriber::subscribe( $user, array( $settings->list_id ) );
191
- $errors = $subscribed->getErrors();
192
-
193
- if ( false !== $errors ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  /* translators: %s: error */
195
- $response['error'] = sprintf( __( 'There was an error subscribing to MailPoet. %s', 'fl-builder' ), $errors[0] );
196
  }
197
  }
198
  }
199
-
200
  return $response;
201
  }
202
  }
178
 
179
  // MailPoet 3.0
180
  } elseif ( defined( 'MAILPOET_INITIALIZED' ) && true === MAILPOET_INITIALIZED ) {
 
181
 
182
  if ( $names && isset( $names[0] ) ) {
183
  $user['first_name'] = $names[0];
186
  $user['last_name'] = $names[1];
187
  }
188
 
189
+ $error = false;
190
+
191
+ // old api
192
+ if ( ! class_exists( \MailPoet\API\API::class ) ) {
193
+ $subscriber = new MailPoet\Models\Subscriber();
194
+ $subscribed = $subscriber::subscribe( $user, array( $settings->list_id ) );
195
+ $errors = method_exists( $subscribed, 'getErrors' ) ? $subscribed->getErrors() : false;
196
+ $error = false !== $errors ? $errors[0] : '';
197
+ } else {
198
+ $mailpoet_api = \MailPoet\API\API::MP( 'v1' );
199
+ try {
200
+ $result = $mailpoet_api->addSubscriber( $user, array( $settings->list_id ) );
201
+ } catch ( \Exception $e ) {
202
+ $error = $e->getMessage();
203
+ }
204
+ }
205
+ if ( false !== $error ) {
206
  /* translators: %s: error */
207
+ $response['error'] = sprintf( __( 'There was an error subscribing to MailPoet. %s', 'fl-builder' ), $error );
208
  }
209
  }
210
  }
 
211
  return $response;
212
  }
213
  }
classes/class-fl-builder-wp-blocks-layout.php CHANGED
@@ -12,12 +12,17 @@ final class FLBuilderWPBlocksLayout {
12
  * @return void
13
  */
14
  static public function init() {
 
15
  // Actions
16
  add_action( 'current_screen', __CLASS__ . '::init_template' );
17
  add_action( 'pre_post_update', __CLASS__ . '::disable_builder_on_post_update', 10, 2 );
18
 
19
  // Filters
20
- add_action( 'block_editor_preload_paths', __CLASS__ . '::update_legacy_post', 10, 2 );
 
 
 
 
21
  add_filter( 'fl_builder_editor_content', __CLASS__ . '::filter_editor_content' );
22
  add_filter( 'fl_builder_migrated_post_content', __CLASS__ . '::filter_migrated_post_content' );
23
  }
@@ -61,20 +66,24 @@ final class FLBuilderWPBlocksLayout {
61
  * Updates posts being edited in the admin that we're built
62
  * using Beaver Builder before WordPress blocks existed.
63
  *
64
- * We do this on the `block_editor_preload_paths` filter because
65
  * that is the earliest we can hook into updating the post before
66
  * it is preloaded by the REST API.
67
  *
68
  * @since 2.1
69
  * @param array $paths
70
- * @param object $post
71
  * @return array
72
  */
73
- static public function update_legacy_post( $paths, $post ) {
 
 
 
 
 
74
  if ( is_object( $post ) ) {
75
  $enabled = FLBuilderModel::is_builder_enabled( $post->ID );
76
  $blocks = preg_match( '/<!-- wp:(.*) \/?-->/', $post->post_content );
77
-
78
  if ( $enabled && ! $blocks ) {
79
  $block = '<!-- wp:fl-builder/layout -->';
80
  $block .= self::remove_broken_p_tags( $post->post_content );
12
  * @return void
13
  */
14
  static public function init() {
15
+ global $wp_version;
16
  // Actions
17
  add_action( 'current_screen', __CLASS__ . '::init_template' );
18
  add_action( 'pre_post_update', __CLASS__ . '::disable_builder_on_post_update', 10, 2 );
19
 
20
  // Filters
21
+ if ( version_compare( $wp_version, '5.8', '<' ) ) {
22
+ add_filter( 'block_editor_preload_paths', __CLASS__ . '::update_legacy_post', 10, 2 );
23
+ } else {
24
+ add_filter( 'block_editor_rest_api_preload_paths', __CLASS__ . '::update_legacy_post', 10, 2 );
25
+ }
26
  add_filter( 'fl_builder_editor_content', __CLASS__ . '::filter_editor_content' );
27
  add_filter( 'fl_builder_migrated_post_content', __CLASS__ . '::filter_migrated_post_content' );
28
  }
66
  * Updates posts being edited in the admin that we're built
67
  * using Beaver Builder before WordPress blocks existed.
68
  *
69
+ * We do this on the `block_editor_rest_api_preload_paths` filter because
70
  * that is the earliest we can hook into updating the post before
71
  * it is preloaded by the REST API.
72
  *
73
  * @since 2.1
74
  * @param array $paths
75
+ * @param object $editor_context
76
  * @return array
77
  */
78
+ static public function update_legacy_post( $paths, $editor_context ) {
79
+ if ( isset( $editor_context->ID ) ) {
80
+ $post = $editor_context;
81
+ } else {
82
+ $post = $editor_context->post;
83
+ }
84
  if ( is_object( $post ) ) {
85
  $enabled = FLBuilderModel::is_builder_enabled( $post->ID );
86
  $blocks = preg_match( '/<!-- wp:(.*) \/?-->/', $post->post_content );
 
87
  if ( $enabled && ! $blocks ) {
88
  $block = '<!-- wp:fl-builder/layout -->';
89
  $block .= self::remove_broken_p_tags( $post->post_content );
fl-builder.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Beaver Builder Plugin (Lite Version)
4
  * Plugin URI: https://www.wpbeaverbuilder.com/?utm_medium=bb&utm_source=plugins-admin-page&utm_campaign=plugins-admin-uri
5
  * Description: A drag and drop frontend WordPress page builder plugin that works with almost any theme!
6
- * Version: 2.4.2.4
7
  * Author: The Beaver Builder Team
8
  * Author URI: https://www.wpbeaverbuilder.com/?utm_medium=bb&utm_source=plugins-admin-page&utm_campaign=plugins-admin-author
9
  * Copyright: (c) 2014 Beaver Builder
3
  * Plugin Name: Beaver Builder Plugin (Lite Version)
4
  * Plugin URI: https://www.wpbeaverbuilder.com/?utm_medium=bb&utm_source=plugins-admin-page&utm_campaign=plugins-admin-uri
5
  * Description: A drag and drop frontend WordPress page builder plugin that works with almost any theme!
6
+ * Version: 2.4.2.5
7
  * Author: The Beaver Builder Team
8
  * Author URI: https://www.wpbeaverbuilder.com/?utm_medium=bb&utm_source=plugins-admin-page&utm_campaign=plugins-admin-author
9
  * Copyright: (c) 2014 Beaver Builder
includes/updater-config.php CHANGED
@@ -3,7 +3,7 @@
3
  if ( class_exists( 'FLUpdater' ) ) {
4
  FLUpdater::add_product(array(
5
  'name' => 'Beaver Builder Plugin (Lite Version)',
6
- 'version' => '2.4.2.4',
7
  'slug' => 'bb-plugin',
8
  'type' => 'plugin',
9
  ));
3
  if ( class_exists( 'FLUpdater' ) ) {
4
  FLUpdater::add_product(array(
5
  'name' => 'Beaver Builder Plugin (Lite Version)',
6
+ 'version' => '2.4.2.5',
7
  'slug' => 'bb-plugin',
8
  'type' => 'plugin',
9
  ));
includes/vendor/campaign-monitor/class/services_json.php CHANGED
@@ -1,5 +1,5 @@
1
  <?php
2
-
3
  /**
4
  * Converts to and from JSON format.
5
  *
@@ -50,7 +50,7 @@
50
  * @author Matt Knapp <mdknapp[at]gmail[dot]com>
51
  * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
52
  * @copyright 2005 Michal Migurski
53
- * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
54
  * @license http://www.opensource.org/licenses/bsd-license.php
55
  * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
56
  */
@@ -90,6 +90,11 @@ define('SERVICES_JSON_LOOSE_TYPE', 16);
90
  */
91
  define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
92
 
 
 
 
 
 
93
  /**
94
  * Converts to and from JSON format.
95
  *
@@ -128,11 +133,23 @@ class Services_JSON
128
  * By default, a deeply-nested resource will
129
  * bubble up with an error, so all return values
130
  * from encode() should be checked with isError()
 
 
 
 
 
131
  */
132
  function __construct($use = 0)
133
  {
134
  $this->use = $use;
 
 
 
135
  }
 
 
 
 
136
 
137
  /**
138
  * convert a string from one UTF-16 char to one UTF-8 char
@@ -148,11 +165,11 @@ class Services_JSON
148
  function utf162utf8($utf16)
149
  {
150
  // oh please oh please oh please oh please oh please
151
- if(function_exists('mb_convert_encoding')) {
152
  return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
153
  }
154
 
155
- $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
156
 
157
  switch(true) {
158
  case ((0x7F & $bytes) == $bytes):
@@ -192,11 +209,11 @@ class Services_JSON
192
  function utf82utf16($utf8)
193
  {
194
  // oh please oh please oh please oh please oh please
195
- if(function_exists('mb_convert_encoding')) {
196
  return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
197
  }
198
 
199
- switch(strlen($utf8)) {
200
  case 1:
201
  // this case should never be reached, because we are in ASCII range
202
  // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
@@ -205,17 +222,17 @@ class Services_JSON
205
  case 2:
206
  // return a UTF-16 character from a 2-byte UTF-8 char
207
  // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
208
- return chr(0x07 & (ord($utf8{0}) >> 2))
209
- . chr((0xC0 & (ord($utf8{0}) << 6))
210
- | (0x3F & ord($utf8{1})));
211
 
212
  case 3:
213
  // return a UTF-16 character from a 3-byte UTF-8 char
214
  // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
215
- return chr((0xF0 & (ord($utf8{0}) << 4))
216
- | (0x0F & (ord($utf8{1}) >> 2)))
217
- . chr((0xC0 & (ord($utf8{1}) << 6))
218
- | (0x7F & ord($utf8{2})));
219
  }
220
 
221
  // ignoring UTF-32 for now, sorry
@@ -223,7 +240,7 @@ class Services_JSON
223
  }
224
 
225
  /**
226
- * encodes an arbitrary variable into JSON format
227
  *
228
  * @param mixed $var any number, boolean, string, array, or object to be encoded.
229
  * see argument 1 to Services_JSON() above for array-parsing behavior.
@@ -235,6 +252,44 @@ class Services_JSON
235
  */
236
  function encode($var)
237
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  switch (gettype($var)) {
239
  case 'boolean':
240
  return $var ? 'true' : 'false';
@@ -247,12 +302,12 @@ class Services_JSON
247
 
248
  case 'double':
249
  case 'float':
250
- return (float) $var;
251
 
252
  case 'string':
253
  // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
254
  $ascii = '';
255
- $strlen_var = strlen($var);
256
 
257
  /*
258
  * Iterate over every character in the string,
@@ -260,7 +315,7 @@ class Services_JSON
260
  */
261
  for ($c = 0; $c < $strlen_var; ++$c) {
262
 
263
- $ord_var_c = ord($var{$c});
264
 
265
  switch (true) {
266
  case $ord_var_c == 0x08:
@@ -283,41 +338,57 @@ class Services_JSON
283
  case $ord_var_c == 0x2F:
284
  case $ord_var_c == 0x5C:
285
  // double quote, slash, slosh
286
- $ascii .= '\\'.$var{$c};
287
  break;
288
 
289
  case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
290
  // characters U-00000000 - U-0000007F (same as ASCII)
291
- $ascii .= $var{$c};
292
  break;
293
 
294
  case (($ord_var_c & 0xE0) == 0xC0):
295
  // characters U-00000080 - U-000007FF, mask 110XXXXX
296
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
297
- $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
 
 
 
 
 
 
298
  $c += 1;
299
  $utf16 = $this->utf82utf16($char);
300
  $ascii .= sprintf('\u%04s', bin2hex($utf16));
301
  break;
302
 
303
  case (($ord_var_c & 0xF0) == 0xE0):
 
 
 
 
 
304
  // characters U-00000800 - U-0000FFFF, mask 1110XXXX
305
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
306
  $char = pack('C*', $ord_var_c,
307
- ord($var{$c + 1}),
308
- ord($var{$c + 2}));
309
  $c += 2;
310
  $utf16 = $this->utf82utf16($char);
311
  $ascii .= sprintf('\u%04s', bin2hex($utf16));
312
  break;
313
 
314
  case (($ord_var_c & 0xF8) == 0xF0):
 
 
 
 
 
315
  // characters U-00010000 - U-001FFFFF, mask 11110XXX
316
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
317
  $char = pack('C*', $ord_var_c,
318
- ord($var{$c + 1}),
319
- ord($var{$c + 2}),
320
- ord($var{$c + 3}));
321
  $c += 3;
322
  $utf16 = $this->utf82utf16($char);
323
  $ascii .= sprintf('\u%04s', bin2hex($utf16));
@@ -326,33 +397,42 @@ class Services_JSON
326
  case (($ord_var_c & 0xFC) == 0xF8):
327
  // characters U-00200000 - U-03FFFFFF, mask 111110XX
328
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 
 
 
 
 
329
  $char = pack('C*', $ord_var_c,
330
- ord($var{$c + 1}),
331
- ord($var{$c + 2}),
332
- ord($var{$c + 3}),
333
- ord($var{$c + 4}));
334
  $c += 4;
335
  $utf16 = $this->utf82utf16($char);
336
  $ascii .= sprintf('\u%04s', bin2hex($utf16));
337
  break;
338
 
339
  case (($ord_var_c & 0xFE) == 0xFC):
 
 
 
 
 
340
  // characters U-04000000 - U-7FFFFFFF, mask 1111110X
341
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
342
  $char = pack('C*', $ord_var_c,
343
- ord($var{$c + 1}),
344
- ord($var{$c + 2}),
345
- ord($var{$c + 3}),
346
- ord($var{$c + 4}),
347
- ord($var{$c + 5}));
348
  $c += 5;
349
  $utf16 = $this->utf82utf16($char);
350
  $ascii .= sprintf('\u%04s', bin2hex($utf16));
351
  break;
352
  }
353
  }
354
-
355
- return '"'.$ascii.'"';
356
 
357
  case 'array':
358
  /*
@@ -380,7 +460,7 @@ class Services_JSON
380
  array_values($var));
381
 
382
  foreach($properties as $property) {
383
- if($this->isError($property)) {
384
  return $property;
385
  }
386
  }
@@ -389,10 +469,10 @@ class Services_JSON
389
  }
390
 
391
  // treat it like a regular array
392
- $elements = array_map(array($this, 'encode'), $var);
393
 
394
  foreach($elements as $element) {
395
- if($this->isError($element)) {
396
  return $element;
397
  }
398
  }
@@ -400,6 +480,25 @@ class Services_JSON
400
  return '[' . join(',', $elements) . ']';
401
 
402
  case 'object':
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403
  $vars = get_object_vars($var);
404
 
405
  $properties = array_map(array($this, 'name_value'),
@@ -407,7 +506,7 @@ class Services_JSON
407
  array_values($vars));
408
 
409
  foreach($properties as $property) {
410
- if($this->isError($property)) {
411
  return $property;
412
  }
413
  }
@@ -432,13 +531,13 @@ class Services_JSON
432
  */
433
  function name_value($name, $value)
434
  {
435
- $encoded_value = $this->encode($value);
436
 
437
- if($this->isError($encoded_value)) {
438
  return $encoded_value;
439
  }
440
 
441
- return $this->encode(strval($name)) . ':' . $encoded_value;
442
  }
443
 
444
  /**
@@ -511,15 +610,15 @@ class Services_JSON
511
 
512
  } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
513
  // STRINGS RETURNED IN UTF-8 FORMAT
514
- $delim = substr($str, 0, 1);
515
- $chrs = substr($str, 1, -1);
516
  $utf8 = '';
517
- $strlen_chrs = strlen($chrs);
518
 
519
  for ($c = 0; $c < $strlen_chrs; ++$c) {
520
 
521
- $substr_chrs_c_2 = substr($chrs, $c, 2);
522
- $ord_chrs_c = ord($chrs{$c});
523
 
524
  switch (true) {
525
  case $substr_chrs_c_2 == '\b':
@@ -549,54 +648,54 @@ class Services_JSON
549
  case $substr_chrs_c_2 == '\\/':
550
  if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
551
  ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
552
- $utf8 .= $chrs{++$c};
553
  }
554
  break;
555
 
556
- case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
557
  // single, escaped unicode character
558
- $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
559
- . chr(hexdec(substr($chrs, ($c + 4), 2)));
560
  $utf8 .= $this->utf162utf8($utf16);
561
  $c += 5;
562
  break;
563
 
564
  case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
565
- $utf8 .= $chrs{$c};
566
  break;
567
 
568
  case ($ord_chrs_c & 0xE0) == 0xC0:
569
  // characters U-00000080 - U-000007FF, mask 110XXXXX
570
  //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
571
- $utf8 .= substr($chrs, $c, 2);
572
  ++$c;
573
  break;
574
 
575
  case ($ord_chrs_c & 0xF0) == 0xE0:
576
  // characters U-00000800 - U-0000FFFF, mask 1110XXXX
577
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
578
- $utf8 .= substr($chrs, $c, 3);
579
  $c += 2;
580
  break;
581
 
582
  case ($ord_chrs_c & 0xF8) == 0xF0:
583
  // characters U-00010000 - U-001FFFFF, mask 11110XXX
584
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
585
- $utf8 .= substr($chrs, $c, 4);
586
  $c += 3;
587
  break;
588
 
589
  case ($ord_chrs_c & 0xFC) == 0xF8:
590
  // characters U-00200000 - U-03FFFFFF, mask 111110XX
591
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
592
- $utf8 .= substr($chrs, $c, 5);
593
  $c += 4;
594
  break;
595
 
596
  case ($ord_chrs_c & 0xFE) == 0xFC:
597
  // characters U-04000000 - U-7FFFFFFF, mask 1111110X
598
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
599
- $utf8 .= substr($chrs, $c, 6);
600
  $c += 5;
601
  break;
602
 
@@ -609,7 +708,7 @@ class Services_JSON
609
  } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
610
  // array, or object notation
611
 
612
- if ($str{0} == '[') {
613
  $stk = array(SERVICES_JSON_IN_ARR);
614
  $arr = array();
615
  } else {
@@ -626,7 +725,7 @@ class Services_JSON
626
  'where' => 0,
627
  'delim' => false));
628
 
629
- $chrs = substr($str, 1, -1);
630
  $chrs = $this->reduce_string($chrs);
631
 
632
  if ($chrs == '') {
@@ -639,21 +738,21 @@ class Services_JSON
639
  }
640
  }
641
 
642
- //print("\nparsing {$chrs}\n");
643
 
644
- $strlen_chrs = strlen($chrs);
645
 
646
  for ($c = 0; $c <= $strlen_chrs; ++$c) {
647
 
648
  $top = end($stk);
649
- $substr_chrs_c_2 = substr($chrs, $c, 2);
650
 
651
- if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
652
  // found a comma that is not inside a string, array, etc.,
653
  // OR we've reached the end of the character list
654
- $slice = substr($chrs, $top['where'], ($c - $top['where']));
655
  array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
656
- //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
657
 
658
  if (reset($stk) == SERVICES_JSON_IN_ARR) {
659
  // we are in an array, so just push an element onto the stack
@@ -665,21 +764,20 @@ class Services_JSON
665
  // element in an associative array,
666
  // for now
667
  $parts = array();
668
-
669
- if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
670
- // "name":value pair
671
- $key = $this->decode($parts[1]);
672
- $val = $this->decode($parts[2]);
673
 
 
 
 
 
674
  if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
675
  $obj[$key] = $val;
676
  } else {
677
  $obj->$key = $val;
678
  }
679
- } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
680
  // name:value pair, where name is unquoted
681
  $key = $parts[1];
682
- $val = $this->decode($parts[2]);
683
 
684
  if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
685
  $obj[$key] = $val;
@@ -690,41 +788,41 @@ class Services_JSON
690
 
691
  }
692
 
693
- } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
694
  // found a quote, and we are not inside a string
695
- array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
696
  //print("Found start of string at {$c}\n");
697
 
698
- } elseif (($chrs{$c} == $top['delim']) &&
699
  ($top['what'] == SERVICES_JSON_IN_STR) &&
700
- ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
701
  // found a quote, we're in a string, and it's not escaped
702
  // we know that it's not escaped becase there is _not_ an
703
  // odd number of backslashes at the end of the string so far
704
  array_pop($stk);
705
- //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
706
 
707
- } elseif (($chrs{$c} == '[') &&
708
  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
709
  // found a left-bracket, and we are in an array, object, or slice
710
  array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
711
  //print("Found start of array at {$c}\n");
712
 
713
- } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
714
  // found a right-bracket, and we're in an array
715
  array_pop($stk);
716
- //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
717
 
718
- } elseif (($chrs{$c} == '{') &&
719
  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
720
  // found a left-brace, and we are in an array, object, or slice
721
  array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
722
  //print("Found start of object at {$c}\n");
723
 
724
- } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
725
  // found a right-brace, and we're in an object
726
  array_pop($stk);
727
- //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
728
 
729
  } elseif (($substr_chrs_c_2 == '/*') &&
730
  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
@@ -741,7 +839,7 @@ class Services_JSON
741
  for ($i = $top['where']; $i <= $c; ++$i)
742
  $chrs = substr_replace($chrs, ' ', $i, 1);
743
 
744
- //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
745
 
746
  }
747
 
@@ -758,25 +856,78 @@ class Services_JSON
758
  }
759
  }
760
  }
761
-
 
 
 
762
  function isError($data, $code = null)
763
  {
764
- if (is_object($data) && (get_class($data) == 'services_json_error' ||
 
 
765
  is_subclass_of($data, 'services_json_error'))) {
766
  return true;
767
  }
768
 
769
  return false;
770
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
771
  }
772
 
773
- class Services_JSON_Error
774
- {
775
- function __construct($message = 'unknown error', $code = null,
776
- $mode = null, $options = null, $userinfo = null)
777
  {
 
 
 
 
 
 
 
 
778
 
 
 
 
 
 
 
 
 
 
 
779
  }
 
780
  }
781
-
782
- ?>
1
  <?php
2
+ /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
  /**
4
  * Converts to and from JSON format.
5
  *
50
  * @author Matt Knapp <mdknapp[at]gmail[dot]com>
51
  * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
52
  * @copyright 2005 Michal Migurski
53
+ * @version CVS: $Id: JSON.php 305040 2010-11-02 23:19:03Z alan_k $
54
  * @license http://www.opensource.org/licenses/bsd-license.php
55
  * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
56
  */
90
  */
91
  define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
92
 
93
+ /**
94
+ * Behavior switch for Services_JSON::decode()
95
+ */
96
+ define('SERVICES_JSON_USE_TO_JSON', 64);
97
+
98
  /**
99
  * Converts to and from JSON format.
100
  *
133
  * By default, a deeply-nested resource will
134
  * bubble up with an error, so all return values
135
  * from encode() should be checked with isError()
136
+ * - SERVICES_JSON_USE_TO_JSON: call toJSON when serializing objects
137
+ * It serializes the return value from the toJSON call rather
138
+ * than the object it'self, toJSON can return associative arrays,
139
+ * strings or numbers, if you return an object, make sure it does
140
+ * not have a toJSON method, otherwise an error will occur.
141
  */
142
  function __construct($use = 0)
143
  {
144
  $this->use = $use;
145
+ $this->_mb_strlen = function_exists('mb_strlen');
146
+ $this->_mb_convert_encoding = function_exists('mb_convert_encoding');
147
+ $this->_mb_substr = function_exists('mb_substr');
148
  }
149
+ // private - cache the mbstring lookup results..
150
+ var $_mb_strlen = false;
151
+ var $_mb_substr = false;
152
+ var $_mb_convert_encoding = false;
153
 
154
  /**
155
  * convert a string from one UTF-16 char to one UTF-8 char
165
  function utf162utf8($utf16)
166
  {
167
  // oh please oh please oh please oh please oh please
168
+ if($this->_mb_convert_encoding) {
169
  return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
170
  }
171
 
172
+ $bytes = (ord($utf16[0]) << 8) | ord($utf16[1]);
173
 
174
  switch(true) {
175
  case ((0x7F & $bytes) == $bytes):
209
  function utf82utf16($utf8)
210
  {
211
  // oh please oh please oh please oh please oh please
212
+ if($this->_mb_convert_encoding) {
213
  return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
214
  }
215
 
216
+ switch($this->strlen8($utf8)) {
217
  case 1:
218
  // this case should never be reached, because we are in ASCII range
219
  // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
222
  case 2:
223
  // return a UTF-16 character from a 2-byte UTF-8 char
224
  // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
225
+ return chr(0x07 & (ord($utf8[0]) >> 2))
226
+ . chr((0xC0 & (ord($utf8[0]) << 6))
227
+ | (0x3F & ord($utf8[1])));
228
 
229
  case 3:
230
  // return a UTF-16 character from a 3-byte UTF-8 char
231
  // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
232
+ return chr((0xF0 & (ord($utf8[0]) << 4))
233
+ | (0x0F & (ord($utf8[1]) >> 2)))
234
+ . chr((0xC0 & (ord($utf8[1]) << 6))
235
+ | (0x7F & ord($utf8[2])));
236
  }
237
 
238
  // ignoring UTF-32 for now, sorry
240
  }
241
 
242
  /**
243
+ * encodes an arbitrary variable into JSON format (and sends JSON Header)
244
  *
245
  * @param mixed $var any number, boolean, string, array, or object to be encoded.
246
  * see argument 1 to Services_JSON() above for array-parsing behavior.
252
  */
253
  function encode($var)
254
  {
255
+ header('Content-type: application/json');
256
+ return $this->encodeUnsafe($var);
257
+ }
258
+ /**
259
+ * encodes an arbitrary variable into JSON format without JSON Header - warning - may allow XSS!!!!)
260
+ *
261
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
262
+ * see argument 1 to Services_JSON() above for array-parsing behavior.
263
+ * if var is a strng, note that encode() always expects it
264
+ * to be in ASCII or UTF-8 format!
265
+ *
266
+ * @return mixed JSON string representation of input var or an error if a problem occurs
267
+ * @access public
268
+ */
269
+ function encodeUnsafe($var)
270
+ {
271
+ // see bug #16908 - regarding numeric locale printing
272
+ $lc = setlocale(LC_NUMERIC, 0);
273
+ setlocale(LC_NUMERIC, 'C');
274
+ $ret = $this->_encode($var);
275
+ setlocale(LC_NUMERIC, $lc);
276
+ return $ret;
277
+
278
+ }
279
+ /**
280
+ * PRIVATE CODE that does the work of encodes an arbitrary variable into JSON format
281
+ *
282
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
283
+ * see argument 1 to Services_JSON() above for array-parsing behavior.
284
+ * if var is a strng, note that encode() always expects it
285
+ * to be in ASCII or UTF-8 format!
286
+ *
287
+ * @return mixed JSON string representation of input var or an error if a problem occurs
288
+ * @access public
289
+ */
290
+ function _encode($var)
291
+ {
292
+
293
  switch (gettype($var)) {
294
  case 'boolean':
295
  return $var ? 'true' : 'false';
302
 
303
  case 'double':
304
  case 'float':
305
+ return (float) $var;
306
 
307
  case 'string':
308
  // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
309
  $ascii = '';
310
+ $strlen_var = $this->strlen8($var);
311
 
312
  /*
313
  * Iterate over every character in the string,
315
  */
316
  for ($c = 0; $c < $strlen_var; ++$c) {
317
 
318
+ $ord_var_c = ord($var[$c]);
319
 
320
  switch (true) {
321
  case $ord_var_c == 0x08:
338
  case $ord_var_c == 0x2F:
339
  case $ord_var_c == 0x5C:
340
  // double quote, slash, slosh
341
+ $ascii .= '\\'.$var[$c];
342
  break;
343
 
344
  case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
345
  // characters U-00000000 - U-0000007F (same as ASCII)
346
+ $ascii .= $var[$c];
347
  break;
348
 
349
  case (($ord_var_c & 0xE0) == 0xC0):
350
  // characters U-00000080 - U-000007FF, mask 110XXXXX
351
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
352
+ if ($c+1 >= $strlen_var) {
353
+ $c += 1;
354
+ $ascii .= '?';
355
+ break;
356
+ }
357
+
358
+ $char = pack('C*', $ord_var_c, ord($var[$c + 1]));
359
  $c += 1;
360
  $utf16 = $this->utf82utf16($char);
361
  $ascii .= sprintf('\u%04s', bin2hex($utf16));
362
  break;
363
 
364
  case (($ord_var_c & 0xF0) == 0xE0):
365
+ if ($c+2 >= $strlen_var) {
366
+ $c += 2;
367
+ $ascii .= '?';
368
+ break;
369
+ }
370
  // characters U-00000800 - U-0000FFFF, mask 1110XXXX
371
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
372
  $char = pack('C*', $ord_var_c,
373
+ @ord($var[$c + 1]),
374
+ @ord($var[$c + 2]));
375
  $c += 2;
376
  $utf16 = $this->utf82utf16($char);
377
  $ascii .= sprintf('\u%04s', bin2hex($utf16));
378
  break;
379
 
380
  case (($ord_var_c & 0xF8) == 0xF0):
381
+ if ($c+3 >= $strlen_var) {
382
+ $c += 3;
383
+ $ascii .= '?';
384
+ break;
385
+ }
386
  // characters U-00010000 - U-001FFFFF, mask 11110XXX
387
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
388
  $char = pack('C*', $ord_var_c,
389
+ ord($var[$c + 1]),
390
+ ord($var[$c + 2]),
391
+ ord($var[$c + 3]));
392
  $c += 3;
393
  $utf16 = $this->utf82utf16($char);
394
  $ascii .= sprintf('\u%04s', bin2hex($utf16));
397
  case (($ord_var_c & 0xFC) == 0xF8):
398
  // characters U-00200000 - U-03FFFFFF, mask 111110XX
399
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
400
+ if ($c+4 >= $strlen_var) {
401
+ $c += 4;
402
+ $ascii .= '?';
403
+ break;
404
+ }
405
  $char = pack('C*', $ord_var_c,
406
+ ord($var[$c + 1]),
407
+ ord($var[$c + 2]),
408
+ ord($var[$c + 3]),
409
+ ord($var[$c + 4]));
410
  $c += 4;
411
  $utf16 = $this->utf82utf16($char);
412
  $ascii .= sprintf('\u%04s', bin2hex($utf16));
413
  break;
414
 
415
  case (($ord_var_c & 0xFE) == 0xFC):
416
+ if ($c+5 >= $strlen_var) {
417
+ $c += 5;
418
+ $ascii .= '?';
419
+ break;
420
+ }
421
  // characters U-04000000 - U-7FFFFFFF, mask 1111110X
422
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
423
  $char = pack('C*', $ord_var_c,
424
+ ord($var[$c + 1]),
425
+ ord($var[$c + 2]),
426
+ ord($var[$c + 3]),
427
+ ord($var[$c + 4]),
428
+ ord($var[$c + 5]));
429
  $c += 5;
430
  $utf16 = $this->utf82utf16($char);
431
  $ascii .= sprintf('\u%04s', bin2hex($utf16));
432
  break;
433
  }
434
  }
435
+ return '"'.$ascii.'"';
 
436
 
437
  case 'array':
438
  /*
460
  array_values($var));
461
 
462
  foreach($properties as $property) {
463
+ if(Services_JSON::isError($property)) {
464
  return $property;
465
  }
466
  }
469
  }
470
 
471
  // treat it like a regular array
472
+ $elements = array_map(array($this, '_encode'), $var);
473
 
474
  foreach($elements as $element) {
475
+ if(Services_JSON::isError($element)) {
476
  return $element;
477
  }
478
  }
480
  return '[' . join(',', $elements) . ']';
481
 
482
  case 'object':
483
+
484
+ // support toJSON methods.
485
+ if (($this->use & SERVICES_JSON_USE_TO_JSON) && method_exists($var, 'toJSON')) {
486
+ // this may end up allowing unlimited recursion
487
+ // so we check the return value to make sure it's not got the same method.
488
+ $recode = $var->toJSON();
489
+
490
+ if (method_exists($recode, 'toJSON')) {
491
+
492
+ return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
493
+ ? 'null'
494
+ : new Services_JSON_Error(class_name($var).
495
+ " toJSON returned an object with a toJSON method.");
496
+
497
+ }
498
+
499
+ return $this->_encode( $recode );
500
+ }
501
+
502
  $vars = get_object_vars($var);
503
 
504
  $properties = array_map(array($this, 'name_value'),
506
  array_values($vars));
507
 
508
  foreach($properties as $property) {
509
+ if(Services_JSON::isError($property)) {
510
  return $property;
511
  }
512
  }
531
  */
532
  function name_value($name, $value)
533
  {
534
+ $encoded_value = $this->_encode($value);
535
 
536
+ if(Services_JSON::isError($encoded_value)) {
537
  return $encoded_value;
538
  }
539
 
540
+ return $this->_encode(strval($name)) . ':' . $encoded_value;
541
  }
542
 
543
  /**
610
 
611
  } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
612
  // STRINGS RETURNED IN UTF-8 FORMAT
613
+ $delim = $this->substr8($str, 0, 1);
614
+ $chrs = $this->substr8($str, 1, -1);
615
  $utf8 = '';
616
+ $strlen_chrs = $this->strlen8($chrs);
617
 
618
  for ($c = 0; $c < $strlen_chrs; ++$c) {
619
 
620
+ $substr_chrs_c_2 = $this->substr8($chrs, $c, 2);
621
+ $ord_chrs_c = ord($chrs[$c]);
622
 
623
  switch (true) {
624
  case $substr_chrs_c_2 == '\b':
648
  case $substr_chrs_c_2 == '\\/':
649
  if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
650
  ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
651
+ $utf8 .= $chrs[++$c];
652
  }
653
  break;
654
 
655
+ case preg_match('/\\\u[0-9A-F]{4}/i', $this->substr8($chrs, $c, 6)):
656
  // single, escaped unicode character
657
+ $utf16 = chr(hexdec($this->substr8($chrs, ($c + 2), 2)))
658
+ . chr(hexdec($this->substr8($chrs, ($c + 4), 2)));
659
  $utf8 .= $this->utf162utf8($utf16);
660
  $c += 5;
661
  break;
662
 
663
  case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
664
+ $utf8 .= $chrs[$c];
665
  break;
666
 
667
  case ($ord_chrs_c & 0xE0) == 0xC0:
668
  // characters U-00000080 - U-000007FF, mask 110XXXXX
669
  //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
670
+ $utf8 .= $this->substr8($chrs, $c, 2);
671
  ++$c;
672
  break;
673
 
674
  case ($ord_chrs_c & 0xF0) == 0xE0:
675
  // characters U-00000800 - U-0000FFFF, mask 1110XXXX
676
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
677
+ $utf8 .= $this->substr8($chrs, $c, 3);
678
  $c += 2;
679
  break;
680
 
681
  case ($ord_chrs_c & 0xF8) == 0xF0:
682
  // characters U-00010000 - U-001FFFFF, mask 11110XXX
683
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
684
+ $utf8 .= $this->substr8($chrs, $c, 4);
685
  $c += 3;
686
  break;
687
 
688
  case ($ord_chrs_c & 0xFC) == 0xF8:
689
  // characters U-00200000 - U-03FFFFFF, mask 111110XX
690
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
691
+ $utf8 .= $this->substr8($chrs, $c, 5);
692
  $c += 4;
693
  break;
694
 
695
  case ($ord_chrs_c & 0xFE) == 0xFC:
696
  // characters U-04000000 - U-7FFFFFFF, mask 1111110X
697
  // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
698
+ $utf8 .= $this->substr8($chrs, $c, 6);
699
  $c += 5;
700
  break;
701
 
708
  } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
709
  // array, or object notation
710
 
711
+ if ($str[0] == '[') {
712
  $stk = array(SERVICES_JSON_IN_ARR);
713
  $arr = array();
714
  } else {
725
  'where' => 0,
726
  'delim' => false));
727
 
728
+ $chrs = $this->substr8($str, 1, -1);
729
  $chrs = $this->reduce_string($chrs);
730
 
731
  if ($chrs == '') {
738
  }
739
  }
740
 
741
+ //print("\nparsing [$chrs]\n");
742
 
743
+ $strlen_chrs = $this->strlen8($chrs);
744
 
745
  for ($c = 0; $c <= $strlen_chrs; ++$c) {
746
 
747
  $top = end($stk);
748
+ $substr_chrs_c_2 = $this->substr8($chrs, $c, 2);
749
 
750
+ if (($c == $strlen_chrs) || (($chrs[$c] == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
751
  // found a comma that is not inside a string, array, etc.,
752
  // OR we've reached the end of the character list
753
+ $slice = $this->substr8($chrs, $top['where'], ($c - $top['where']));
754
  array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
755
+ //print("Found split at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n");
756
 
757
  if (reset($stk) == SERVICES_JSON_IN_ARR) {
758
  // we are in an array, so just push an element onto the stack
764
  // element in an associative array,
765
  // for now
766
  $parts = array();
 
 
 
 
 
767
 
768
+ if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:/Uis', $slice, $parts)) {
769
+ // "name":value pair
770
+ $key = $this->decode($parts[1]);
771
+ $val = $this->decode(trim(substr($slice, strlen($parts[0])), ", \t\n\r\0\x0B"));
772
  if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
773
  $obj[$key] = $val;
774
  } else {
775
  $obj->$key = $val;
776
  }
777
+ } elseif (preg_match('/^\s*(\w+)\s*:/Uis', $slice, $parts)) {
778
  // name:value pair, where name is unquoted
779
  $key = $parts[1];
780
+ $val = $this->decode(trim(substr($slice, strlen($parts[0])), ", \t\n\r\0\x0B"));
781
 
782
  if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
783
  $obj[$key] = $val;
788
 
789
  }
790
 
791
+ } elseif ((($chrs[$c] == '"') || ($chrs[$c] == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
792
  // found a quote, and we are not inside a string
793
+ array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs[$c]));
794
  //print("Found start of string at {$c}\n");
795
 
796
+ } elseif (($chrs[$c] == $top['delim']) &&
797
  ($top['what'] == SERVICES_JSON_IN_STR) &&
798
+ (($this->strlen8($this->substr8($chrs, 0, $c)) - $this->strlen8(rtrim($this->substr8($chrs, 0, $c), '\\'))) % 2 != 1)) {
799
  // found a quote, we're in a string, and it's not escaped
800
  // we know that it's not escaped becase there is _not_ an
801
  // odd number of backslashes at the end of the string so far
802
  array_pop($stk);
803
+ //print("Found end of string at {$c}: ".$this->substr8($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
804
 
805
+ } elseif (($chrs[$c] == '[') &&
806
  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
807
  // found a left-bracket, and we are in an array, object, or slice
808
  array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
809
  //print("Found start of array at {$c}\n");
810
 
811
+ } elseif (($chrs[$c] == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
812
  // found a right-bracket, and we're in an array
813
  array_pop($stk);
814
+ //print("Found end of array at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n");
815
 
816
+ } elseif (($chrs[$c] == '{') &&
817
  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
818
  // found a left-brace, and we are in an array, object, or slice
819
  array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
820
  //print("Found start of object at {$c}\n");
821
 
822
+ } elseif (($chrs[$c] == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
823
  // found a right-brace, and we're in an object
824
  array_pop($stk);
825
+ //print("Found end of object at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n");
826
 
827
  } elseif (($substr_chrs_c_2 == '/*') &&
828
  in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
839
  for ($i = $top['where']; $i <= $c; ++$i)
840
  $chrs = substr_replace($chrs, ' ', $i, 1);
841
 
842
+ //print("Found end of comment at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n");
843
 
844
  }
845
 
856
  }
857
  }
858
  }
859
+
860
+ /**
861
+ * @todo Ultimately, this should just call PEAR::isError()
862
+ */
863
  function isError($data, $code = null)
864
  {
865
+ if (class_exists('pear')) {
866
+ return PEAR::isError($data, $code);
867
+ } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
868
  is_subclass_of($data, 'services_json_error'))) {
869
  return true;
870
  }
871
 
872
  return false;
873
  }
874
+
875
+ /**
876
+ * Calculates length of string in bytes
877
+ * @param string
878
+ * @return integer length
879
+ */
880
+ function strlen8( $str )
881
+ {
882
+ if ( $this->_mb_strlen ) {
883
+ return mb_strlen( $str, "8bit" );
884
+ }
885
+ return strlen( $str );
886
+ }
887
+
888
+ /**
889
+ * Returns part of a string, interpreting $start and $length as number of bytes.
890
+ * @param string
891
+ * @param integer start
892
+ * @param integer length
893
+ * @return integer length
894
+ */
895
+ function substr8( $string, $start, $length=false )
896
+ {
897
+ if ( $length === false ) {
898
+ $length = $this->strlen8( $string ) - $start;
899
+ }
900
+ if ( $this->_mb_substr ) {
901
+ return mb_substr( $string, $start, $length, "8bit" );
902
+ }
903
+ return substr( $string, $start, $length );
904
+ }
905
+
906
  }
907
 
908
+ if (class_exists('PEAR_Error')) {
909
+
910
+ class Services_JSON_Error extends PEAR_Error
 
911
  {
912
+ function __construct($message = 'unknown error', $code = null,
913
+ $mode = null, $options = null, $userinfo = null)
914
+ {
915
+ parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
916
+ }
917
+ }
918
+
919
+ } else {
920
 
921
+ /**
922
+ * @todo Ultimately, this class shall be descended from PEAR_Error
923
+ */
924
+ class Services_JSON_Error
925
+ {
926
+ function __construct($message = 'unknown error', $code = null,
927
+ $mode = null, $options = null, $userinfo = null)
928
+ {
929
+
930
+ }
931
  }
932
+
933
  }
 
 
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Contributors: justinbusa, RobbyMcCullough, billyyoung, hinampaksh, diegoliv, webmandesign, eugenealegiojo, helgatheviking, ozancanakli, brentjettgmailcom, jproffitt71, brainstormforce, ideaboxcreations, laubsterboy, nikolayyordanov, codente, pross, pedromendonca
3
  Tags: page builder, beaver builder, landing page, front-end builder, drag and drop editor
4
  Requires at least: 4.6
5
- Tested up to: 5.7
6
  Requires PHP: 5.6
7
  Stable tag: trunk
8
  License: GPL2+
2
  Contributors: justinbusa, RobbyMcCullough, billyyoung, hinampaksh, diegoliv, webmandesign, eugenealegiojo, helgatheviking, ozancanakli, brentjettgmailcom, jproffitt71, brainstormforce, ideaboxcreations, laubsterboy, nikolayyordanov, codente, pross, pedromendonca
3
  Tags: page builder, beaver builder, landing page, front-end builder, drag and drop editor
4
  Requires at least: 4.6
5
+ Tested up to: 5.8
6
  Requires PHP: 5.6
7
  Stable tag: trunk
8
  License: GPL2+