Easy Table of Contents - Version 2.0.9

Version Description

Requires WordPress >

Download this release

Release Info

Developer shazahm1@hotmail.com
Plugin Icon 128x128 Easy Table of Contents
Version 2.0.9
Comparing to
See all releases

Code changes from version 2.0.8 to 2.0.9

README.txt CHANGED
@@ -5,7 +5,7 @@ Tags: table of contents, toc
5
  Requires at least: 5.2
6
  Tested up to: 5.4
7
  Requires PHP: 5.6.20
8
- Stable tag: 2.0.8
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -89,6 +89,14 @@ Easy Table Contents is a fork of the excellent [Table of Contents Plus](https://
89
 
90
  == Changelog ==
91
 
 
 
 
 
 
 
 
 
92
  = 2.0.8 04/03/2020 =
93
  * TWEAK: Convert `<br />` tags in headings to a space.
94
  * TWEAK: Add additional widget classes.
@@ -388,3 +396,6 @@ Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
388
 
389
  = 2.0.8 =
390
  Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
 
 
 
5
  Requires at least: 5.2
6
  Tested up to: 5.4
7
  Requires PHP: 5.6.20
8
+ Stable tag: 2.0.9
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
89
 
90
  == Changelog ==
91
 
92
+ = 2.0.9 04/08/2020 =
93
+ * TWEAK: AMP/Caching plugins seems to break anchors with colons and periods even though they are valid characters for the id attribute in HTML5.
94
+ * TWEAK: Replace multiple underscores with a single underscore.
95
+ * DEV: Update the UWS library which fixes the deprecation notice for PHP 7.4.
96
+ * DEV: Add phpcs.xml.dist.
97
+ * DEV: Strict type checks.
98
+ * DEV: Inline doc updates.
99
+
100
  = 2.0.8 04/03/2020 =
101
  * TWEAK: Convert `<br />` tags in headings to a space.
102
  * TWEAK: Add additional widget classes.
396
 
397
  = 2.0.8 =
398
  Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
399
+
400
+ = 2.0.9 =
401
+ Requires WordPress >= 5.0 and PHP version >= 5.6.20 (>= 7.1 is recommended).
easy-table-of-contents.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Easy Table of Contents
4
  * Plugin URI: http://connections-pro.com/
5
  * Description: Adds a user friendly and fully automatic way to create and display a table of contents generated from the page content.
6
- * Version: 2.0.8
7
  * Author: Steven A. Zahm
8
  * Author URI: http://connections-pro.com/
9
  * Text Domain: easy-table-of-contents
@@ -26,7 +26,7 @@
26
  * @package Easy Table of Contents
27
  * @category Plugin
28
  * @author Steven A. Zahm
29
- * @version 2.0.8
30
  */
31
 
32
  use function Easy_Plugins\Table_Of_Contents\String\mb_find_replace;
@@ -47,7 +47,7 @@ if ( ! class_exists( 'ezTOC' ) ) {
47
  * @since 1.0
48
  * @var string
49
  */
50
- const VERSION = '2.0.8';
51
 
52
  /**
53
  * Stores the instance of this class.
@@ -250,7 +250,7 @@ if ( ! class_exists( 'ezTOC' ) ) {
250
 
251
  if ( ezTOC_Option::get( 'show_heading_text' ) && ezTOC_Option::get( 'visibility' ) ) {
252
 
253
- $width = ezTOC_Option::get( 'width' ) != 'custom' ? ezTOC_Option::get( 'width' ) : ezTOC_Option::get( 'width_custom' ) . ezTOC_Option::get( 'width_custom_units' );
254
 
255
  $js_vars['visibility_hide_by_default'] = ezTOC_Option::get( 'visibility_hide_by_default' ) ? true : false;
256
 
@@ -289,20 +289,20 @@ if ( ! class_exists( 'ezTOC' ) ) {
289
  $css .= 'div#ez-toc-container p.ez-toc-title {font-weight: ' . ezTOC_Option::get( 'title_font_weight', 500 ) . ';}';
290
  $css .= 'div#ez-toc-container ul li {font-size: ' . ezTOC_Option::get( 'font_size' ) . ezTOC_Option::get( 'font_size_units' ) . ';}';
291
 
292
- if ( ezTOC_Option::get( 'theme' ) == 'custom' || ezTOC_Option::get( 'width' ) != 'auto' ) {
293
 
294
  $css .= 'div#ez-toc-container {';
295
 
296
- if ( ezTOC_Option::get( 'theme' ) == 'custom' ) {
297
 
298
  $css .= 'background: ' . ezTOC_Option::get( 'custom_background_colour' ) . ';border: 1px solid ' . ezTOC_Option::get( 'custom_border_colour' ) . ';';
299
  }
300
 
301
- if ( 'auto' != ezTOC_Option::get( 'width' ) ) {
302
 
303
  $css .= 'width: ';
304
 
305
- if ( 'custom' != ezTOC_Option::get( 'width' ) ) {
306
 
307
  $css .= ezTOC_Option::get( 'width' );
308
 
@@ -317,7 +317,7 @@ if ( ! class_exists( 'ezTOC' ) ) {
317
  $css .= '}';
318
  }
319
 
320
- if ( 'custom' == ezTOC_Option::get( 'theme' ) ) {
321
 
322
  $css .= 'div#ez-toc-container p.ez-toc-title {color: ' . ezTOC_Option::get( 'custom_title_colour' ) . ';}';
323
  //$css .= 'div#ez-toc-container p.ez-toc-title a,div#ez-toc-container ul.ez-toc-list a {color: ' . ezTOC_Option::get( 'custom_link_colour' ) . ';}';
@@ -397,8 +397,8 @@ if ( ! class_exists( 'ezTOC' ) ) {
397
 
398
  $type = get_post_type( $post->ID );
399
 
400
- $enabled = in_array( $type, ezTOC_Option::get( 'enabled_post_types', array() ) );
401
- $insert = in_array( $type, ezTOC_Option::get( 'auto_insert_post_types', array() ) );
402
 
403
  if ( $insert || $enabled ) {
404
 
3
  * Plugin Name: Easy Table of Contents
4
  * Plugin URI: http://connections-pro.com/
5
  * Description: Adds a user friendly and fully automatic way to create and display a table of contents generated from the page content.
6
+ * Version: 2.0.9
7
  * Author: Steven A. Zahm
8
  * Author URI: http://connections-pro.com/
9
  * Text Domain: easy-table-of-contents
26
  * @package Easy Table of Contents
27
  * @category Plugin
28
  * @author Steven A. Zahm
29
+ * @version 2.0.9
30
  */
31
 
32
  use function Easy_Plugins\Table_Of_Contents\String\mb_find_replace;
47
  * @since 1.0
48
  * @var string
49
  */
50
+ const VERSION = '2.0.9';
51
 
52
  /**
53
  * Stores the instance of this class.
250
 
251
  if ( ezTOC_Option::get( 'show_heading_text' ) && ezTOC_Option::get( 'visibility' ) ) {
252
 
253
+ $width = ezTOC_Option::get( 'width' ) !== 'custom' ? ezTOC_Option::get( 'width' ) : ezTOC_Option::get( 'width_custom' ) . ezTOC_Option::get( 'width_custom_units' );
254
 
255
  $js_vars['visibility_hide_by_default'] = ezTOC_Option::get( 'visibility_hide_by_default' ) ? true : false;
256
 
289
  $css .= 'div#ez-toc-container p.ez-toc-title {font-weight: ' . ezTOC_Option::get( 'title_font_weight', 500 ) . ';}';
290
  $css .= 'div#ez-toc-container ul li {font-size: ' . ezTOC_Option::get( 'font_size' ) . ezTOC_Option::get( 'font_size_units' ) . ';}';
291
 
292
+ if ( ezTOC_Option::get( 'theme' ) === 'custom' || ezTOC_Option::get( 'width' ) != 'auto' ) {
293
 
294
  $css .= 'div#ez-toc-container {';
295
 
296
+ if ( ezTOC_Option::get( 'theme' ) === 'custom' ) {
297
 
298
  $css .= 'background: ' . ezTOC_Option::get( 'custom_background_colour' ) . ';border: 1px solid ' . ezTOC_Option::get( 'custom_border_colour' ) . ';';
299
  }
300
 
301
+ if ( 'auto' !== ezTOC_Option::get( 'width' ) ) {
302
 
303
  $css .= 'width: ';
304
 
305
+ if ( 'custom' !== ezTOC_Option::get( 'width' ) ) {
306
 
307
  $css .= ezTOC_Option::get( 'width' );
308
 
317
  $css .= '}';
318
  }
319
 
320
+ if ( 'custom' === ezTOC_Option::get( 'theme' ) ) {
321
 
322
  $css .= 'div#ez-toc-container p.ez-toc-title {color: ' . ezTOC_Option::get( 'custom_title_colour' ) . ';}';
323
  //$css .= 'div#ez-toc-container p.ez-toc-title a,div#ez-toc-container ul.ez-toc-list a {color: ' . ezTOC_Option::get( 'custom_link_colour' ) . ';}';
397
 
398
  $type = get_post_type( $post->ID );
399
 
400
+ $enabled = in_array( $type, ezTOC_Option::get( 'enabled_post_types', array() ), true );
401
+ $insert = in_array( $type, ezTOC_Option::get( 'auto_insert_post_types', array() ), true );
402
 
403
  if ( $insert || $enabled ) {
404
 
includes/class.post.php CHANGED
@@ -799,10 +799,17 @@ class ezTOC_Post {
799
  //$return = preg_replace( '/[^a-zA-Z0-9 \-_]*/', '', $return );
800
  $return = preg_replace( '/[\x00-\x1F\x7F\-_]*/u', '', $return );
801
 
802
- // convert spaces to _
 
 
 
 
803
  $return = preg_replace( '/\s+/', '_', $return );
804
 
805
- // remove trailing - and _
 
 
 
806
  $return = rtrim( $return, '-_' );
807
 
808
  /*
799
  //$return = preg_replace( '/[^a-zA-Z0-9 \-_]*/', '', $return );
800
  $return = preg_replace( '/[\x00-\x1F\x7F\-_]*/u', '', $return );
801
 
802
+ // AMP/Caching plugins seems to break URL with the following characters, so lets replace them.
803
+ $return = str_replace( array( ':' ), '_', $return );
804
+ $return = str_replace( array( '.' ), ' ', $return );
805
+
806
+ // Convert space characters to an `_` (underscore).
807
  $return = preg_replace( '/\s+/', '_', $return );
808
 
809
+ // Replace multiple `_` (underscore) with a single `_` (underscore).
810
+ $return = preg_replace( '/_+/', '_', $return );
811
+
812
+ // Remove trailing `-` (hyphen) and `_` (underscore).
813
  $return = rtrim( $return, '-_' );
814
 
815
  /*
includes/inc.plugin-compatibility.php CHANGED
@@ -326,6 +326,22 @@ add_filter(
326
  }
327
  );
328
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
  class ezTOC_Elementor {
330
 
331
  /**
326
  }
327
  );
328
 
329
+ /**
330
+ * Remove the Contextual Related Posts node from the post content before extracting headings.
331
+ *
332
+ * @link https://wordpress.org/plugins/contextual-related-posts/
333
+ * @since 2.0.9
334
+ */
335
+ add_filter(
336
+ 'ez_toc_exclude_by_selector',
337
+ function( $selectors ) {
338
+
339
+ $selectors['contextual-related-posts'] = '.crp_related';
340
+
341
+ return $selectors;
342
+ }
343
+ );
344
+
345
  class ezTOC_Elementor {
346
 
347
  /**
includes/vendor/ultimate-web-scraper/crc32_stream.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  // CRC32 stream class.
3
- // (C) 2016 CubicleSoft. All Rights Reserved.
4
  //
5
  // Direct port from the CubicleSoft C++ implementation.
6
 
@@ -45,8 +45,8 @@
45
  $y = strlen($data);
46
  for ($x < 0; $x < $y; $x++)
47
  {
48
- if ($this->datareflect) $this->currcrc = $this->SHL32($this->currcrc, 8) ^ $this->crctable[$this->SHR32($this->currcrc, 24) ^ self::$revlookup[ord($data{$x})]];
49
- else $this->currcrc = $this->SHL32($this->currcrc, 8) ^ $this->crctable[$this->SHR32($this->currcrc, 24) ^ ord($data{$x})];
50
  }
51
 
52
  return true;
1
  <?php
2
  // CRC32 stream class.
3
+ // (C) 2020 CubicleSoft. All Rights Reserved.
4
  //
5
  // Direct port from the CubicleSoft C++ implementation.
6
 
45
  $y = strlen($data);
46
  for ($x < 0; $x < $y; $x++)
47
  {
48
+ if ($this->datareflect) $this->currcrc = $this->SHL32($this->currcrc, 8) ^ $this->crctable[$this->SHR32($this->currcrc, 24) ^ self::$revlookup[ord($data[$x])]];
49
+ else $this->currcrc = $this->SHL32($this->currcrc, 8) ^ $this->crctable[$this->SHR32($this->currcrc, 24) ^ ord($data[$x])];
50
  }
51
 
52
  return true;
includes/vendor/ultimate-web-scraper/deflate_stream.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  // Deflate stream class. Default is RFC1951 (raw deflate). Supports RFC1950 (ZLIB) and RFC1952 (gzip).
3
- // (C) 2016 CubicleSoft. All Rights Reserved.
4
 
5
  class DeflateStream
6
  {
@@ -140,7 +140,7 @@
140
  $y = strlen($data);
141
  for ($x = 0; $x < $y; $x++)
142
  {
143
- $this->options["a"] = ($this->options["a"] + ord($data{$x})) % 65521;
144
  $this->options["b"] = ($this->options["b"] + $this->options["a"]) % 65521;
145
  }
146
  }
@@ -225,7 +225,7 @@
225
  $zlibtest = unpack("n", substr($this->indata, 0, 2));
226
 
227
  if (substr($this->indata, 0, 3) === "\x1F\x8B\x08") $this->options["type"] = "gzip";
228
- else if ((ord($this->indata{0}) & 0x0F) == 8 && ((ord($this->indata{0}) & 0xF0) >> 4) < 8 && $zlibtest[1] % 31 == 0) $this->options["type"] = "zlib";
229
  else $this->options["type"] = "raw";
230
  }
231
  else if ($final) $this->options["type"] = "raw";
@@ -238,7 +238,7 @@
238
  if (strlen($this->indata) >= 10)
239
  {
240
  $idcm = substr($this->indata, 0, 3);
241
- $flg = ord($this->indata{3});
242
 
243
  if ($idcm !== "\x1F\x8B\x08") $this->options["type"] = "ignore";
244
  else
@@ -300,8 +300,8 @@
300
  {
301
  if (strlen($this->indata) >= 2)
302
  {
303
- $cmf = ord($this->indata{0});
304
- $flg = ord($this->indata{1});
305
  $cm = $cmf & 0x0F;
306
  $cinfo = ($cmf & 0xF0) >> 4;
307
 
1
  <?php
2
  // Deflate stream class. Default is RFC1951 (raw deflate). Supports RFC1950 (ZLIB) and RFC1952 (gzip).
3
+ // (C) 2020 CubicleSoft. All Rights Reserved.
4
 
5
  class DeflateStream
6
  {
140
  $y = strlen($data);
141
  for ($x = 0; $x < $y; $x++)
142
  {
143
+ $this->options["a"] = ($this->options["a"] + ord($data[$x])) % 65521;
144
  $this->options["b"] = ($this->options["b"] + $this->options["a"]) % 65521;
145
  }
146
  }
225
  $zlibtest = unpack("n", substr($this->indata, 0, 2));
226
 
227
  if (substr($this->indata, 0, 3) === "\x1F\x8B\x08") $this->options["type"] = "gzip";
228
+ else if ((ord($this->indata[0]) & 0x0F) == 8 && ((ord($this->indata[0]) & 0xF0) >> 4) < 8 && $zlibtest[1] % 31 == 0) $this->options["type"] = "zlib";
229
  else $this->options["type"] = "raw";
230
  }
231
  else if ($final) $this->options["type"] = "raw";
238
  if (strlen($this->indata) >= 10)
239
  {
240
  $idcm = substr($this->indata, 0, 3);
241
+ $flg = ord($this->indata[3]);
242
 
243
  if ($idcm !== "\x1F\x8B\x08") $this->options["type"] = "ignore";
244
  else
300
  {
301
  if (strlen($this->indata) >= 2)
302
  {
303
+ $cmf = ord($this->indata[0]);
304
+ $flg = ord($this->indata[1]);
305
  $cm = $cmf & 0x0F;
306
  $cinfo = ($cmf & 0xF0) >> 4;
307
 
includes/vendor/ultimate-web-scraper/http.php CHANGED
@@ -265,13 +265,14 @@
265
 
266
  public static function GetSafeSSLOpts($cafile = true, $cipherstype = "intermediate")
267
  {
268
- // Result array last updated May 3, 2017.
269
  $result = array(
270
  "ciphers" => self::GetSSLCiphers($cipherstype),
271
  "disable_compression" => true,
272
  "allow_self_signed" => false,
273
  "verify_peer" => true,
274
- "verify_depth" => 5
 
275
  );
276
 
277
  if ($cafile === true) $result["auto_cainfo"] = true;
@@ -452,6 +453,18 @@
452
  else if (file_exists(str_replace("\\", "/", dirname(__FILE__)) . "/cacert.pem")) $options[$key]["cafile"] = str_replace("\\", "/", dirname(__FILE__)) . "/cacert.pem";
453
  }
454
 
 
 
 
 
 
 
 
 
 
 
 
 
455
  if (isset($options[$key]["auto_cn_match"]))
456
  {
457
  unset($options[$key]["auto_cn_match"]);
@@ -722,7 +735,7 @@
722
  if ($state[$prefix . "data"] !== "")
723
  {
724
  // Serious bug in PHP core for non-blocking SSL sockets: https://bugs.php.net/bug.php?id=72333
725
- if ($state["secure"] && $state["async"])
726
  {
727
  // This is a huge hack that has a pretty good chance of blocking on the socket.
728
  // Peeling off up to just 4KB at a time helps to minimize that possibility. It's better than guaranteed failure of the socket though.
@@ -850,6 +863,8 @@
850
  if ($state["async"] && function_exists("stream_socket_client") && (($state["useproxy"] && $state["proxysecure"]) || (!$state["useproxy"] && $state["secure"]))) $state["state"] = "connecting_enable_crypto";
851
  else $state["state"] = "connection_ready";
852
 
 
 
853
  break;
854
  }
855
  case "connecting_enable_crypto":
@@ -861,6 +876,8 @@
861
  if ($result === false) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("A stream_socket_enable_crypto() failure occurred. Most likely cause: Connection failure or incompatible crypto setup."), "errorcode" => "stream_socket_enable_crypto_failed"));
862
  else if ($result === true) $state["state"] = "connection_ready";
863
 
 
 
864
  break;
865
  }
866
  case "connection_ready":
@@ -910,6 +927,8 @@
910
  $state["state"] = "send_data";
911
  }
912
 
 
 
913
  break;
914
  }
915
  case "proxy_connect_send":
@@ -928,9 +947,12 @@
928
  $options2["debug_callback_opts"] = $state["options"]["debug_callback_opts"];
929
  }
930
  $state["proxyresponse"] = self::InitResponseState($state["fp"], $state["debug"], $options2, $state["startts"], $state["timeout"], $state["result"], false, $state["nextread"]);
 
931
 
932
  $state["state"] = "proxy_connect_response";
933
 
 
 
934
  break;
935
  }
936
  case "proxy_connect_response":
@@ -950,6 +972,8 @@
950
  if ($state["secure"]) $state["state"] = "proxy_connect_enable_crypto";
951
  else $state["state"] = "send_data";
952
 
 
 
953
  break;
954
  }
955
  case "proxy_connect_enable_crypto":
@@ -977,6 +1001,8 @@
977
 
978
  // Secure connection established.
979
  $state["state"] = "send_data";
 
 
980
  }
981
 
982
  break;
@@ -1100,7 +1126,12 @@
1100
  // All done sending data.
1101
  if ($state["data"] === "")
1102
  {
1103
- if ($state["client"]) $state["state"] = "receive_switch";
 
 
 
 
 
1104
  else
1105
  {
1106
  $state["result"]["endts"] = microtime(true);
@@ -1130,6 +1161,8 @@
1130
 
1131
  $state["state"] = "done";
1132
 
 
 
1133
  break;
1134
  }
1135
  }
@@ -1171,6 +1204,8 @@
1171
  $state["result"]["headers"] = array();
1172
  $state["lastheader"] = "";
1173
 
 
 
1174
  break;
1175
  }
1176
  case "request_line":
@@ -1217,6 +1252,8 @@
1217
  $state["result"]["headers"] = array();
1218
  $state["lastheader"] = "";
1219
 
 
 
1220
  break;
1221
  }
1222
  case "headers":
@@ -1253,13 +1290,23 @@
1253
  }
1254
 
1255
  // Additional headers (optional) are the last bit of data in a chunked response.
1256
- if ($state["state"] === "body_chunked_headers") $state["state"] = "body_finalize";
 
 
 
 
 
1257
  else
1258
  {
1259
  $state["result"]["body"] = "";
1260
 
1261
  // Handle 100 Continue below OR WebSocket among other things by letting the caller handle reading the body.
1262
- if ($state["result"]["response"]["code"] == 100 || $state["result"]["response"]["code"] == 101) $state["state"] = "done";
 
 
 
 
 
1263
  else
1264
  {
1265
  // Determine if decoding the content is possible and necessary.
@@ -1282,11 +1329,13 @@
1282
  else
1283
  {
1284
  $state["sizeleft"] = (isset($state["result"]["headers"]["Content-Length"]) ? (double)preg_replace('/[^0-9]/', "", $state["result"]["headers"]["Content-Length"][0]) : false);
1285
- $state["state"] = ($state["sizeleft"] !== false || $state["client"] ? "body_content" : "done");
1286
  }
1287
 
 
 
1288
  // Let servers have a chance to alter limits before processing the input body.
1289
- if (!$state["client"] && $state["state"] !== "done") return array("success" => false, "error" => self::HTTPTranslate("Intermission for adjustments to limits."), "errorcode" => "no_data");
1290
  }
1291
  }
1292
  }
@@ -1324,6 +1373,8 @@
1324
  $state["sizeleft"] = $size2;
1325
  $state["state"] = "body_chunked_data";
1326
 
 
 
1327
  break;
1328
  }
1329
  case "body_chunked_data":
@@ -1338,6 +1389,8 @@
1338
  $state["state"] = "body_chunked_headers";
1339
  }
1340
 
 
 
1341
  break;
1342
  }
1343
  case "body_chunked_skipline":
@@ -1352,6 +1405,8 @@
1352
 
1353
  $state["state"] = "body_chunked_size";
1354
 
 
 
1355
  break;
1356
  }
1357
  case "body_content":
@@ -1361,6 +1416,8 @@
1361
 
1362
  $state["state"] = "body_finalize";
1363
 
 
 
1364
  break;
1365
  }
1366
  case "body_finalize":
@@ -1376,6 +1433,8 @@
1376
 
1377
  $state["state"] = "done";
1378
 
 
 
1379
  break;
1380
  }
1381
  }
@@ -1388,6 +1447,8 @@
1388
  $state["result"]["response"] = false;
1389
  $state["result"]["headers"] = false;
1390
  $state["result"]["body"] = false;
 
 
1391
  }
1392
  }
1393
 
@@ -1730,7 +1791,12 @@
1730
  }
1731
  else if ($secure)
1732
  {
1733
- if (!isset($options["sslopts"]) || !is_array($options["sslopts"])) $options["sslopts"] = self::GetSafeSSLOpts();
 
 
 
 
 
1734
  self::ProcessSSLOptions($options, "sslopts", $host);
1735
  foreach ($options["sslopts"] as $key => $val) @stream_context_set_option($context, "ssl", $key, $val);
1736
  }
265
 
266
  public static function GetSafeSSLOpts($cafile = true, $cipherstype = "intermediate")
267
  {
268
+ // Result array last updated Feb 15, 2020.
269
  $result = array(
270
  "ciphers" => self::GetSSLCiphers($cipherstype),
271
  "disable_compression" => true,
272
  "allow_self_signed" => false,
273
  "verify_peer" => true,
274
+ "verify_depth" => 5,
275
+ "SNI_enabled" => true
276
  );
277
 
278
  if ($cafile === true) $result["auto_cainfo"] = true;
453
  else if (file_exists(str_replace("\\", "/", dirname(__FILE__)) . "/cacert.pem")) $options[$key]["cafile"] = str_replace("\\", "/", dirname(__FILE__)) . "/cacert.pem";
454
  }
455
 
456
+ if (isset($options[$key]["auto_peer_name"]))
457
+ {
458
+ unset($options[$key]["auto_peer_name"]);
459
+
460
+ if (!isset($options["headers"]["Host"])) $options[$key]["peer_name"] = $host;
461
+ else
462
+ {
463
+ $info = self::ExtractURL("https://" . $options["headers"]["Host"]);
464
+ $options[$key]["peer_name"] = $info["host"];
465
+ }
466
+ }
467
+
468
  if (isset($options[$key]["auto_cn_match"]))
469
  {
470
  unset($options[$key]["auto_cn_match"]);
735
  if ($state[$prefix . "data"] !== "")
736
  {
737
  // Serious bug in PHP core for non-blocking SSL sockets: https://bugs.php.net/bug.php?id=72333
738
+ if ($state["secure"] && $state["async"] && version_compare(PHP_VERSION, "7.1.4") <= 0)
739
  {
740
  // This is a huge hack that has a pretty good chance of blocking on the socket.
741
  // Peeling off up to just 4KB at a time helps to minimize that possibility. It's better than guaranteed failure of the socket though.
863
  if ($state["async"] && function_exists("stream_socket_client") && (($state["useproxy"] && $state["proxysecure"]) || (!$state["useproxy"] && $state["secure"]))) $state["state"] = "connecting_enable_crypto";
864
  else $state["state"] = "connection_ready";
865
 
866
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
867
+
868
  break;
869
  }
870
  case "connecting_enable_crypto":
876
  if ($result === false) return self::CleanupErrorState($state, array("success" => false, "error" => self::HTTPTranslate("A stream_socket_enable_crypto() failure occurred. Most likely cause: Connection failure or incompatible crypto setup."), "errorcode" => "stream_socket_enable_crypto_failed"));
877
  else if ($result === true) $state["state"] = "connection_ready";
878
 
879
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
880
+
881
  break;
882
  }
883
  case "connection_ready":
927
  $state["state"] = "send_data";
928
  }
929
 
930
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
931
+
932
  break;
933
  }
934
  case "proxy_connect_send":
947
  $options2["debug_callback_opts"] = $state["options"]["debug_callback_opts"];
948
  }
949
  $state["proxyresponse"] = self::InitResponseState($state["fp"], $state["debug"], $options2, $state["startts"], $state["timeout"], $state["result"], false, $state["nextread"]);
950
+ $state["proxyresponse"]["proxyconnect"] = true;
951
 
952
  $state["state"] = "proxy_connect_response";
953
 
954
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
955
+
956
  break;
957
  }
958
  case "proxy_connect_response":
972
  if ($state["secure"]) $state["state"] = "proxy_connect_enable_crypto";
973
  else $state["state"] = "send_data";
974
 
975
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
976
+
977
  break;
978
  }
979
  case "proxy_connect_enable_crypto":
1001
 
1002
  // Secure connection established.
1003
  $state["state"] = "send_data";
1004
+
1005
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1006
  }
1007
 
1008
  break;
1126
  // All done sending data.
1127
  if ($state["data"] === "")
1128
  {
1129
+ if ($state["client"])
1130
+ {
1131
+ $state["state"] = "receive_switch";
1132
+
1133
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1134
+ }
1135
  else
1136
  {
1137
  $state["result"]["endts"] = microtime(true);
1161
 
1162
  $state["state"] = "done";
1163
 
1164
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1165
+
1166
  break;
1167
  }
1168
  }
1204
  $state["result"]["headers"] = array();
1205
  $state["lastheader"] = "";
1206
 
1207
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1208
+
1209
  break;
1210
  }
1211
  case "request_line":
1252
  $state["result"]["headers"] = array();
1253
  $state["lastheader"] = "";
1254
 
1255
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1256
+
1257
  break;
1258
  }
1259
  case "headers":
1290
  }
1291
 
1292
  // Additional headers (optional) are the last bit of data in a chunked response.
1293
+ if ($state["state"] === "body_chunked_headers")
1294
+ {
1295
+ $state["state"] = "body_finalize";
1296
+
1297
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1298
+ }
1299
  else
1300
  {
1301
  $state["result"]["body"] = "";
1302
 
1303
  // Handle 100 Continue below OR WebSocket among other things by letting the caller handle reading the body.
1304
+ if ($state["result"]["response"]["code"] == 100 || $state["result"]["response"]["code"] == 101)
1305
+ {
1306
+ $state["state"] = "done";
1307
+
1308
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1309
+ }
1310
  else
1311
  {
1312
  // Determine if decoding the content is possible and necessary.
1329
  else
1330
  {
1331
  $state["sizeleft"] = (isset($state["result"]["headers"]["Content-Length"]) ? (double)preg_replace('/[^0-9]/', "", $state["result"]["headers"]["Content-Length"][0]) : false);
1332
+ $state["state"] = (!isset($state["proxyconnect"]) && ($state["sizeleft"] !== false || $state["client"]) ? "body_content" : "done");
1333
  }
1334
 
1335
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1336
+
1337
  // Let servers have a chance to alter limits before processing the input body.
1338
+ if (!$state["client"] && $state["state"] !== "done") return array("success" => false, "error" => self::HTTPTranslate("Intermission for adjustments to limits."), "errorcode" => "no_data");
1339
  }
1340
  }
1341
  }
1373
  $state["sizeleft"] = $size2;
1374
  $state["state"] = "body_chunked_data";
1375
 
1376
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1377
+
1378
  break;
1379
  }
1380
  case "body_chunked_data":
1389
  $state["state"] = "body_chunked_headers";
1390
  }
1391
 
1392
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1393
+
1394
  break;
1395
  }
1396
  case "body_chunked_skipline":
1405
 
1406
  $state["state"] = "body_chunked_size";
1407
 
1408
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1409
+
1410
  break;
1411
  }
1412
  case "body_content":
1416
 
1417
  $state["state"] = "body_finalize";
1418
 
1419
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1420
+
1421
  break;
1422
  }
1423
  case "body_finalize":
1433
 
1434
  $state["state"] = "done";
1435
 
1436
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1437
+
1438
  break;
1439
  }
1440
  }
1447
  $state["result"]["response"] = false;
1448
  $state["result"]["headers"] = false;
1449
  $state["result"]["body"] = false;
1450
+
1451
+ if (isset($state["options"]["debug_callback"]) && is_callable($state["options"]["debug_callback"])) call_user_func_array($state["options"]["debug_callback"], array("nextstate", $state["state"], &$state["options"]["debug_callback_opts"]));
1452
  }
1453
  }
1454
 
1791
  }
1792
  else if ($secure)
1793
  {
1794
+ if (!isset($options["sslopts"]) || !is_array($options["sslopts"]))
1795
+ {
1796
+ $options["sslopts"] = self::GetSafeSSLOpts();
1797
+ $options["sslopts"]["auto_peer_name"] = true;
1798
+ }
1799
+
1800
  self::ProcessSSLOptions($options, "sslopts", $host);
1801
  foreach ($options["sslopts"] as $key => $val) @stream_context_set_option($context, "ssl", $key, $val);
1802
  }
includes/vendor/ultimate-web-scraper/tag_filter.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  // CubicleSoft PHP Tag Filter class. Can repair broken HTML.
3
- // (C) 2018 CubicleSoft. All Rights Reserved.
4
 
5
  class TagFilterStream
6
  {
@@ -70,7 +70,7 @@
70
  $startpos = $cx + 1;
71
  for ($x = $startpos; $x < $cy; $x++)
72
  {
73
- $val = ord($content{$x});
74
  if (($val >= $a && $val <= $z) || ($val >= $a2 && $val <= $z2))
75
  {
76
  if ($x > $cx + 1) $prefix = ltrim(substr($content, $cx + 1, $x - $cx - 1));
@@ -83,7 +83,7 @@
83
  if ($prefix === "") $open = true;
84
  else
85
  {
86
- if ($prefix{0} === "!")
87
  {
88
  // !DOCTYPE vs. comment.
89
  if (substr($prefix, 0, 3) !== "!--")
@@ -126,13 +126,13 @@
126
  continue;
127
  }
128
  }
129
- else if ($prefix{0} === "/")
130
  {
131
  // Close tag.
132
  $prefix = "/";
133
  $open = false;
134
  }
135
- else if ($prefix{0} === "<")
136
  {
137
  // Stray less than. Encode and reset.
138
  $content2 = "&lt;";
@@ -171,7 +171,7 @@
171
  $cx = $startpos;
172
  for (; $cx < $cy; $cx++)
173
  {
174
- $val = ord($content{$cx});
175
  if ($val > 127) $parse = true;
176
  else if (!(($val >= $a && $val <= $z) || ($val >= $a2 && $val <= $z2) || ($cx > $startpos && (($val >= $zero && $val <= $nine) || $val == $hyphen || $val == $underscore || $val == $period)) || ($this->options["allow_namespaces"] && $val == $colon))) break;
177
  }
@@ -241,7 +241,7 @@
241
  // Find attribute key/property.
242
  for ($x = $cx; $x < $cy; $x++)
243
  {
244
- if ($content{$x} === ">" || $content{$x} === "<")
245
  {
246
  $cx = $x;
247
 
@@ -249,7 +249,7 @@
249
 
250
  break;
251
  }
252
- else if ($content{$x} === "/")
253
  {
254
  $pos = strpos($content, ">", $x + 1);
255
  if ($pos !== false && trim(substr($content, $x + 1, $pos - $x - 1)) === "")
@@ -262,10 +262,10 @@
262
  break;
263
  }
264
  }
265
- else if ($content{$x} === "\"" || $content{$x} === "'" || $content{$x} === "`")
266
  {
267
- $pos = strpos($content, $content{$x}, $x + 1);
268
- if ($pos === false) $content .= $content{$x};
269
  else if (isset($this->options["untouched_tag_attr_keys"][$tagname]))
270
  {
271
  $keyname = substr($content, $x, $pos - $x + 1);
@@ -298,7 +298,7 @@
298
  }
299
  else
300
  {
301
- $val = ord($content{$x});
302
  if (($val >= $a && $val <= $z) || ($val >= $a2 && $val <= $z2))
303
  {
304
  $cx = $x;
@@ -306,8 +306,8 @@
306
 
307
  for (; $cx < $cy; $cx++)
308
  {
309
- if ($content{$cx} === " " || $content{$cx} === "=" || $content{$cx} === "\"" || $content{$cx} === "'" || $content{$cx} === "`" || $content{$cx} === ">" || $content{$cx} === "<" || $content{$cx} === "/" || $content{$cx} === "\0" || $content{$cx} === "\r" || $content{$cx} === "\n" || $content{$cx} === "\t") break;
310
- else if (ord($content{$cx}) > 127) $parse = true;
311
  }
312
 
313
  $keyname = substr($content, $x, $cx - $x);
@@ -342,7 +342,7 @@
342
  // Find the equals sign OR the start of the next attribute/property.
343
  for ($x = $cx; $x < $cy; $x++)
344
  {
345
- if ($content{$x} === ">" || $content{$x} === "<")
346
  {
347
  $cx = $x;
348
 
@@ -352,7 +352,7 @@
352
 
353
  break;
354
  }
355
- else if ($content{$x} === "=")
356
  {
357
  $cx = $x + 1;
358
 
@@ -360,7 +360,7 @@
360
 
361
  break;
362
  }
363
- else if ($content{$x} === "\"" || $content{$x} === "'")
364
  {
365
  $cx = $x;
366
 
@@ -372,7 +372,7 @@
372
  }
373
  else
374
  {
375
- $val = ord($content{$x});
376
  if (($val >= $a && $val <= $z) || ($val >= $a2 && $val <= $z2) || ($val >= $zero && $val <= $nine))
377
  {
378
  $cx = $x;
@@ -399,7 +399,7 @@
399
  {
400
  for ($x = $cx; $x < $cy; $x++)
401
  {
402
- if ($content{$x} === ">" || $content{$x} === "<")
403
  {
404
  $cx = $x;
405
 
@@ -409,10 +409,10 @@
409
 
410
  break;
411
  }
412
- else if ($content{$x} === "\"" || $content{$x} === "'" || $content{$x} === "`")
413
  {
414
- $pos = strpos($content, $content{$x}, $x + 1);
415
- if ($pos === false) $content .= $content{$x};
416
  else
417
  {
418
  $value = substr($content, $x + 1, $pos - $x - 1);
@@ -423,13 +423,13 @@
423
 
424
  break;
425
  }
426
- else if ($content{$x} !== "\0" && $content{$x} !== "\r" && $content{$x} !== "\n" && $content{$x} !== "\t" && $content{$x} !== " ")
427
  {
428
  $cx = $x;
429
 
430
  for (; $cx < $cy; $cx++)
431
  {
432
- if ($content{$cx} === "\0" || $content{$cx} === "\r" || $content{$cx} === "\n" || $content{$cx} === "\t" || $content{$cx} === " " || $content{$cx} === "<" || $content{$cx} === ">")
433
  {
434
  break;
435
  }
@@ -474,20 +474,20 @@
474
  $vx = $pos + 2;
475
  if ($vx < $vy)
476
  {
477
- if ($value{$vx} == "x" || $value{$vx} == "X")
478
  {
479
  $vx++;
480
  if ($vx < $vy)
481
  {
482
  for ($x = $vx; $x < $vy; $x++)
483
  {
484
- $val = ord($value{$x});
485
  if (!(($val >= $a && $val <= $f) || ($val >= $a2 && $val <= $f2) || ($val >= $zero && $val <= $nine))) break;
486
  }
487
 
488
  $num = hexdec(substr($value, $vx, $x - $vx));
489
  $vx = $x;
490
- if ($vx < $vy && $value{$vx} == ";") $vx++;
491
 
492
  $value2 .= self::UTF8Chr($num);
493
  }
@@ -496,13 +496,13 @@
496
  {
497
  for ($x = $vx; $x < $vy; $x++)
498
  {
499
- $val = ord($value{$x});
500
  if (!($val >= $zero && $val <= $nine)) break;
501
  }
502
 
503
  $num = (int)substr($value, $vx, $x - $vx);
504
  $vx = $x;
505
- if ($vx < $vy && $value{$vx} == ";") $vx++;
506
 
507
  $value2 .= self::UTF8Chr($num);
508
  }
@@ -518,7 +518,7 @@
518
  {
519
  for ($x = $vx; $x < $vy; $x++)
520
  {
521
- $val = ord($value{$x});
522
  if (!(($val >= $a && $val <= $f) || ($val >= $a2 && $val <= $f2) || ($val >= $zero && $val <= $nine))) break;
523
  }
524
 
@@ -580,7 +580,7 @@
580
 
581
  unset($attrs[""]);
582
 
583
- if ($cx < $cy && $content{$cx} === ">") $cx++;
584
 
585
  if (isset($this->options["tag_name_map"][$prefix . $tagname])) $outtagname = $tagname = $this->options["tag_name_map"][$prefix . $tagname];
586
 
@@ -899,19 +899,19 @@
899
  $y = strlen($data);
900
  while ($x < $y)
901
  {
902
- $tempchr = ord($data{$x});
903
  if (($tempchr >= 0x20 && $tempchr <= 0x7E) || $tempchr == 0x09 || $tempchr == 0x0A || $tempchr == 0x0D) $x++;
904
  else if ($tempchr < 0xC2) return false;
905
  else
906
  {
907
  $left = $y - $x;
908
- if ($left > 1) $tempchr2 = ord($data{$x + 1});
909
  else return false;
910
 
911
  if (($tempchr >= 0xC2 && $tempchr <= 0xDF) && ($tempchr2 >= 0x80 && $tempchr2 <= 0xBF)) $x += 2;
912
  else
913
  {
914
- if ($left > 2) $tempchr3 = ord($data{$x + 2});
915
  else return false;
916
 
917
  if ($tempchr3 < 0x80 || $tempchr3 > 0xBF) return false;
@@ -921,7 +921,7 @@
921
  else if ($tempchr == 0xED && ($tempchr2 >= 0x80 && $tempchr2 <= 0x9F)) $x += 3;
922
  else
923
  {
924
- if ($left > 3) $tempchr4 = ord($data{$x + 3});
925
  else return false;
926
 
927
  if ($tempchr4 < 0x80 || $tempchr4 > 0xBF) return false;
@@ -2642,7 +2642,7 @@
2642
  {
2643
  if ($cx >= $cy) break;
2644
 
2645
- switch ($query{$cx})
2646
  {
2647
  case "#":
2648
  {
@@ -2683,14 +2683,14 @@
2683
  $cx++;
2684
 
2685
  // Find a non-whitespace character.
2686
- while ($cx < $cy && ($query{$cx} == " " || $query{$cx} == "\t" || $query{$cx} == "\r" || $query{$cx} == "\n" || $query{$cx} == "\f")) $cx++;
2687
 
2688
  break;
2689
  }
2690
  case ":":
2691
  {
2692
  $cx++;
2693
- if ($cx >= $cy || $query{$cx} != ":") $token["type"] = "pseudo-class";
2694
  else
2695
  {
2696
  $token["type"] = "pseudo-element";
@@ -2771,9 +2771,9 @@
2771
  $token[$state2] = $ident;
2772
 
2773
  // Find a non-whitespace character.
2774
- while ($cx < $cy && ($query{$cx} == " " || $query{$cx} == "\t" || $query{$cx} == "\r" || $query{$cx} == "\n" || $query{$cx} == "\f")) $cx++;
2775
 
2776
- if ($cx >= $cy || $query{$cx} == "]")
2777
  {
2778
  $token["cmp"] = false;
2779
  $tokens[] = $token;
@@ -2782,28 +2782,28 @@
2782
  }
2783
  else
2784
  {
2785
- if ($query{$cx} == "=")
2786
  {
2787
  $token["cmp"] = "=";
2788
  $cx++;
2789
  }
2790
- else if ($cx + 1 < $cy && ($query{$cx} == "^" || $query{$cx} == "$" || $query{$cx} == "*" || $query{$cx} == "~" || $query{$cx} == "|") && $query{$cx + 1} == "=")
2791
  {
2792
  $token["cmp"] = substr($query, $cx, 2);
2793
  $cx += 2;
2794
  }
2795
  else
2796
  {
2797
- return array("success" => false, "error" => "Unknown or invalid attribute comparison operator '" . $query{$cx} . "' detected at position " . $cx . ".", "errorcode" => "invalid_attr_compare", "selector" => $query, "startpos" => $currcx, "pos" => $cx, "state" => $currstate, "tokens" => self::ReorderSelectorTokens(array_slice($tokens, 0, $lastor), $splitrules), "splitrules" => $splitrules);
2798
  }
2799
 
2800
  // Find a non-whitespace character.
2801
- while ($cx < $cy && ($query{$cx} == " " || $query{$cx} == "\t" || $query{$cx} == "\r" || $query{$cx} == "\n" || $query{$cx} == "\f")) $cx++;
2802
 
2803
- if ($cx < $cy && ($query{$cx} == "\"" || $query{$cx} == "'"))
2804
  {
2805
  $state = "string";
2806
- $endchr = ord($query{$cx});
2807
  $cx++;
2808
  }
2809
  else
@@ -2823,12 +2823,12 @@
2823
  $token[$state2] = $ident;
2824
 
2825
  // Find a non-whitespace character.
2826
- while ($cx < $cy && ($query{$cx} == " " || $query{$cx} == "\t" || $query{$cx} == "\r" || $query{$cx} == "\n" || $query{$cx} == "\f")) $cx++;
2827
 
2828
  $tokens[] = $token;
2829
  $state = ($token["not"] ? "negate_close" : "next_selector");
2830
 
2831
- if ($cx < $cy && $query{$cx} == "]") $cx++;
2832
  }
2833
 
2834
  break;
@@ -2844,7 +2844,7 @@
2844
  if ($token["type"] == "pseudo-class" && $ident == "not")
2845
  {
2846
  if ($token["not"]) return array("success" => false, "error" => "Invalid :not() embedded inside another :not() detected at position " . $cx . ".", "errorcode" => "invalid_not", "selector" => $query, "startpos" => $currcx, "pos" => $cx, "state" => $currstate, "tokens" => self::ReorderSelectorTokens(array_slice($tokens, 0, $lastor), $splitrules), "splitrules" => $splitrules);
2847
- if ($cx >= $cy || $query{$cx} != "(") return array("success" => false, "error" => "Missing '(' detected at position " . $cx . ".", "errorcode" => "invalid_not", "selector" => $query, "startpos" => $currcx, "pos" => $cx, "state" => $currstate, "tokens" => self::ReorderSelectorTokens(array_slice($tokens, 0, $lastor), $splitrules), "splitrules" => $splitrules);
2848
 
2849
  unset($token["type"]);
2850
  $token["not"] = true;
@@ -2853,13 +2853,13 @@
2853
  $cx++;
2854
 
2855
  // Find a non-whitespace character.
2856
- while ($cx < $cy && ($query{$cx} == " " || $query{$cx} == "\t" || $query{$cx} == "\r" || $query{$cx} == "\n" || $query{$cx} == "\f")) $cx++;
2857
  }
2858
  else
2859
  {
2860
  $token["pseudo"] = $ident;
2861
 
2862
- if ($cx < $cy && $query{$cx} == "(")
2863
  {
2864
  $token["expression"] = "";
2865
  $ident = "";
@@ -2883,9 +2883,9 @@
2883
  case "negate_close":
2884
  {
2885
  // Find a non-whitespace character.
2886
- while ($cx < $cy && ($query{$cx} == " " || $query{$cx} == "\t" || $query{$cx} == "\r" || $query{$cx} == "\n" || $query{$cx} == "\f")) $cx++;
2887
 
2888
- if ($cx < $cy && $query{$cx} != ")") return array("success" => false, "error" => "Invalid :not() close character '" . $query{$cx} . "' detected at position " . $cx . ".", "errorcode" => "invalid_negate_close", "selector" => $query, "startpos" => $currcx, "pos" => $cx, "state" => $currstate, "tokens" => self::ReorderSelectorTokens(array_slice($tokens, 0, $lastor), $splitrules), "splitrules" => $splitrules);
2889
 
2890
  $cx++;
2891
  $state = "next_selector";
@@ -2897,11 +2897,11 @@
2897
  $token["expression"] .= $ident;
2898
 
2899
  // Find a non-whitespace character.
2900
- while ($cx < $cy && ($query{$cx} == " " || $query{$cx} == "\t" || $query{$cx} == "\r" || $query{$cx} == "\n" || $query{$cx} == "\f")) $cx++;
2901
 
2902
  if ($cx >= $cy) break;
2903
 
2904
- if ($query{$cx} == ")")
2905
  {
2906
  if (substr($token["pseudo"], 0, 4) === "nth-")
2907
  {
@@ -2944,20 +2944,20 @@
2944
  $state = ($token["not"] ? "negate_close" : "next_selector");
2945
  $cx++;
2946
  }
2947
- else if ($query{$cx} == "+" || $query{$cx} == "-")
2948
  {
2949
- $ident = $query{$cx};
2950
  $cx++;
2951
  }
2952
- else if ($query{$cx} == "\"" || $query{$cx} == "'")
2953
  {
2954
  $state = "string";
2955
- $endchr = ord($query{$cx});
2956
  $cx++;
2957
  }
2958
  else
2959
  {
2960
- $val = ord($query{$cx});
2961
 
2962
  $state = ($val >= $zero && $val <= $nine ? "ident_name" : "ident");
2963
  $allownamespace = false;
@@ -2979,7 +2979,7 @@
2979
 
2980
  for (; $cx < $cy; $cx++)
2981
  {
2982
- $val = ord($query{$cx});
2983
 
2984
  if ($val == $endchr)
2985
  {
@@ -2994,14 +2994,14 @@
2994
  else
2995
  {
2996
  $cx++;
2997
- $val = ord($query{$cx});
2998
 
2999
  if (($val >= $a && $val <= $f) || ($val >= $a2 && $val <= $f2) || ($val >= $zero && $val <= $nine))
3000
  {
3001
  // Unicode (e.g. \0020)
3002
  for ($x = $cx + 1; $x < $cy; $x++)
3003
  {
3004
- $val = ord($query{$x});
3005
  if (!(($val >= $a && $val <= $f) || ($val >= $a2 && $val <= $f2) || ($val >= $zero && $val <= $nine))) break;
3006
  }
3007
 
@@ -3011,18 +3011,18 @@
3011
  $ident .= TagFilterStream::UTF8Chr($num);
3012
 
3013
  // Skip one optional \r\n OR a single whitespace char.
3014
- if ($cx + 2 < $cy && $query{$cx + 1} == "\r" && $query{$cx + 2} == "\n") $cx += 2;
3015
- else if ($cx + 1 < $cy && ($query{$cx + 1} == " " || $query{$cx + 1} == "\r" || $query{$cx + 1} == "\n" || $query{$cx + 1} == "\t" || $query{$cx + 1} == "\f")) $cx++;
3016
  }
3017
  else
3018
  {
3019
- $ident .= $query{$cx};
3020
  }
3021
  }
3022
  }
3023
  else
3024
  {
3025
- $ident .= $query{$cx};
3026
  }
3027
  }
3028
 
@@ -3037,7 +3037,7 @@
3037
 
3038
  if ($cx >= $cy) break;
3039
 
3040
- if ($query{$cx} != "-") $ident = "";
3041
  else
3042
  {
3043
  $ident = "-";
@@ -3054,13 +3054,13 @@
3054
  $startcx = $cx;
3055
  for (; $cx < $cy; $cx++)
3056
  {
3057
- $val = ord($query{$cx});
3058
 
3059
  if ($val != $period && ($val < $zero || $val > $nine)) $allowperiod = false;
3060
 
3061
  if (($val >= $a && $val <= $z) || ($val >= $a2 && $val <= $z2) || $val == $underscore || $val > 127)
3062
  {
3063
- $ident .= $query{$cx};
3064
  }
3065
  else if ($allowperiod && $val == $period)
3066
  {
@@ -3071,11 +3071,11 @@
3071
  else if ($val == $hyphen || ($val >= $zero && $val <= $nine))
3072
  {
3073
  // Only allowed AFTER the first character.
3074
- if (!$range) return array("success" => false, "error" => "Invalid identifier character '" . $query{$cx} . "' detected at position " . $cx . ".", "errorcode" => "invalid_ident", "selector" => $query, "startpos" => $currcx, "pos" => $cx, "state" => $currstate, "tokens" => self::ReorderSelectorTokens(array_slice($tokens, 0, $lastor), $splitrules), "splitrules" => $splitrules);
3075
 
3076
  $allowperiod = false;
3077
 
3078
- $ident .= $query{$cx};
3079
  }
3080
  else if ($val == $backslash)
3081
  {
@@ -3084,14 +3084,14 @@
3084
  else
3085
  {
3086
  $cx++;
3087
- $val = ord($query{$cx});
3088
 
3089
  if (($val >= $a && $val <= $f) || ($val >= $a2 && $val <= $f2) || ($val >= $zero && $val <= $nine))
3090
  {
3091
  // Unicode (e.g. \0020)
3092
  for ($x = $cx + 1; $x < $cy; $x++)
3093
  {
3094
- $val = ord($query{$x});
3095
  if (!(($val >= $a && $val <= $f) || ($val >= $a2 && $val <= $f2) || ($val >= $zero && $val <= $nine))) break;
3096
  }
3097
 
@@ -3101,16 +3101,16 @@
3101
  $ident .= TagFilterStream::UTF8Chr($num);
3102
 
3103
  // Skip one optional \r\n OR a single whitespace char.
3104
- if ($cx + 2 < $cy && $query{$cx + 1} == "\r" && $query{$cx + 2} == "\n") $cx += 2;
3105
- else if ($cx + 1 < $cy && ($query{$cx + 1} == " " || $query{$cx + 1} == "\r" || $query{$cx + 1} == "\n" || $query{$cx + 1} == "\t" || $query{$cx + 1} == "\f")) $cx++;
3106
  }
3107
  else if ($val != $cr && $val != $nl && $val != $ff)
3108
  {
3109
- $ident .= $query{$cx};
3110
  }
3111
  }
3112
  }
3113
- else if ($allownamespace && $val == $pipe && ($cx + 1 >= $cy || $query{$cx + 1} != "="))
3114
  {
3115
  // Handle namespaces (rare).
3116
  if ($ident != "")
@@ -3124,7 +3124,7 @@
3124
  else if ($val == $asterisk)
3125
  {
3126
  // Handle wildcard (*) characters.
3127
- if ($allownamespace && $cx + 1 < $cy && $query{$cx + 1} == "|")
3128
  {
3129
  // Wildcard namespace (*|).
3130
  $namespace = "*";
@@ -3166,11 +3166,11 @@
3166
  $token = array("type" => "combine");
3167
 
3168
  // Find a non-whitespace character.
3169
- while ($cx < $cy && ($query{$cx} == " " || $query{$cx} == "\t" || $query{$cx} == "\r" || $query{$cx} == "\n" || $query{$cx} == "\f")) $cx++;
3170
 
3171
  if ($cx < $cy)
3172
  {
3173
- switch ($query{$cx})
3174
  {
3175
  case ",":
3176
  {
@@ -3214,7 +3214,7 @@
3214
  $tokens[] = $token;
3215
 
3216
  // Find a non-whitespace character.
3217
- while ($cx < $cy && ($query{$cx} == " " || $query{$cx} == "\t" || $query{$cx} == "\r" || $query{$cx} == "\n" || $query{$cx} == "\f")) $cx++;
3218
  }
3219
 
3220
  $state = "next_selector";
@@ -3257,4 +3257,4 @@
3257
  return false;
3258
  }
3259
  }
3260
- ?>
1
  <?php
2
  // CubicleSoft PHP Tag Filter class. Can repair broken HTML.
3
+ // (C) 2020 CubicleSoft. All Rights Reserved.
4
 
5
  class TagFilterStream
6
  {
70
  $startpos = $cx + 1;
71
  for ($x = $startpos; $x < $cy; $x++)
72
  {
73
+ $val = ord($content[$x]);
74
  if (($val >= $a && $val <= $z) || ($val >= $a2 && $val <= $z2))
75
  {
76
  if ($x > $cx + 1) $prefix = ltrim(substr($content, $cx + 1, $x - $cx - 1));
83
  if ($prefix === "") $open = true;
84
  else
85
  {
86
+ if ($prefix[0] === "!")
87
  {
88
  // !DOCTYPE vs. comment.
89
  if (substr($prefix, 0, 3) !== "!--")
126
  continue;
127
  }
128
  }
129
+ else if ($prefix[0] === "/")
130
  {
131
  // Close tag.
132
  $prefix = "/";
133
  $open = false;
134
  }
135
+ else if ($prefix[0] === "<")
136
  {
137
  // Stray less than. Encode and reset.
138
  $content2 = "&lt;";
171
  $cx = $startpos;
172
  for (; $cx < $cy; $cx++)
173
  {
174
+ $val = ord($content[$cx]);
175
  if ($val > 127) $parse = true;
176
  else if (!(($val >= $a && $val <= $z) || ($val >= $a2 && $val <= $z2) || ($cx > $startpos && (($val >= $zero && $val <= $nine) || $val == $hyphen || $val == $underscore || $val == $period)) || ($this->options["allow_namespaces"] && $val == $colon))) break;
177
  }
241
  // Find attribute key/property.
242
  for ($x = $cx; $x < $cy; $x++)
243
  {
244
+ if ($content[$x] === ">" || $content[$x] === "<")
245
  {
246
  $cx = $x;
247
 
249
 
250
  break;
251
  }
252
+ else if ($content[$x] === "/")
253
  {
254
  $pos = strpos($content, ">", $x + 1);
255
  if ($pos !== false && trim(substr($content, $x + 1, $pos - $x - 1)) === "")
262
  break;
263
  }
264
  }
265
+ else if ($content[$x] === "\"" || $content[$x] === "'" || $content[$x] === "`")
266
  {
267
+ $pos = strpos($content, $content[$x], $x + 1);
268
+ if ($pos === false) $content .= $content[$x];
269
  else if (isset($this->options["untouched_tag_attr_keys"][$tagname]))
270
  {
271
  $keyname = substr($content, $x, $pos - $x + 1);
298
  }
299
  else
300
  {
301
+ $val = ord($content[$x]);
302
  if (($val >= $a && $val <= $z) || ($val >= $a2 && $val <= $z2))
303
  {
304
  $cx = $x;
306
 
307
  for (; $cx < $cy; $cx++)
308
  {
309
+ if ($content[$cx] === " " || $content[$cx] === "=" || $content[$cx] === "\"" || $content[$cx] === "'" || $content[$cx] === "`" || $content[$cx] === ">" || $content[$cx] === "<" || $content[$cx] === "/" || $content[$cx] === "\0" || $content[$cx] === "\r" || $content[$cx] === "\n" || $content[$cx] === "\t") break;
310
+ else if (ord($content[$cx]) > 127) $parse = true;
311
  }
312
 
313
  $keyname = substr($content, $x, $cx - $x);
342
  // Find the equals sign OR the start of the next attribute/property.
343
  for ($x = $cx; $x < $cy; $x++)
344
  {
345
+ if ($content[$x] === ">" || $content[$x] === "<")
346
  {
347
  $cx = $x;
348
 
352
 
353
  break;
354
  }
355
+ else if ($content[$x] === "=")
356
  {
357
  $cx = $x + 1;
358
 
360
 
361
  break;
362
  }
363
+ else if ($content[$x] === "\"" || $content[$x] === "'")
364
  {
365
  $cx = $x;
366
 
372
  }
373
  else
374
  {
375
+ $val = ord($content[$x]);
376
  if (($val >= $a && $val <= $z) || ($val >= $a2 && $val <= $z2) || ($val >= $zero && $val <= $nine))
377
  {
378
  $cx = $x;
399
  {
400
  for ($x = $cx; $x < $cy; $x++)
401
  {
402
+ if ($content[$x] === ">" || $content[$x] === "<")
403
  {
404
  $cx = $x;
405
 
409
 
410
  break;
411
  }
412
+ else if ($content[$x] === "\"" || $content[$x] === "'" || $content[$x] === "`")
413
  {
414
+ $pos = strpos($content, $content[$x], $x + 1);
415
+ if ($pos === false) $content .= $content[$x];
416
  else
417
  {
418
  $value = substr($content, $x + 1, $pos - $x - 1);
423
 
424
  break;
425
  }
426
+ else if ($content[$x] !== "\0" && $content[$x] !== "\r" && $content[$x] !== "\n" && $content[$x] !== "\t" && $content[$x] !== " ")
427
  {
428
  $cx = $x;
429
 
430
  for (; $cx < $cy; $cx++)
431
  {
432
+ if ($content[$cx] === "\0" || $content[$cx] === "\r" || $content[$cx] === "\n" || $content[$cx] === "\t" || $content[$cx] === " " || $content[$cx] === "<" || $content[$cx] === ">")
433
  {
434
  break;
435
  }
474
  $vx = $pos + 2;
475
  if ($vx < $vy)
476
  {
477
+ if ($value[$vx] == "x" || $value[$vx] == "X")
478
  {
479
  $vx++;
480
  if ($vx < $vy)
481
  {
482
  for ($x = $vx; $x < $vy; $x++)
483
  {
484
+ $val = ord($value[$x]);
485
  if (!(($val >= $a && $val <= $f) || ($val >= $a2 && $val <= $f2) || ($val >= $zero && $val <= $nine))) break;
486
  }
487
 
488
  $num = hexdec(substr($value, $vx, $x - $vx));
489
  $vx = $x;
490
+ if ($vx < $vy && $value[$vx] == ";") $vx++;
491
 
492
  $value2 .= self::UTF8Chr($num);
493
  }
496
  {
497
  for ($x = $vx; $x < $vy; $x++)
498
  {
499
+ $val = ord($value[$x]);
500
  if (!($val >= $zero && $val <= $nine)) break;
501
  }
502
 
503
  $num = (int)substr($value, $vx, $x - $vx);
504
  $vx = $x;
505
+ if ($vx < $vy && $value[$vx] == ";") $vx++;
506
 
507
  $value2 .= self::UTF8Chr($num);
508
  }
518
  {
519
  for ($x = $vx; $x < $vy; $x++)
520
  {
521
+ $val = ord($value[$x]);
522
  if (!(($val >= $a && $val <= $f) || ($val >= $a2 && $val <= $f2) || ($val >= $zero && $val <= $nine))) break;
523
  }
524
 
580
 
581
  unset($attrs[""]);
582
 
583
+ if ($cx < $cy && $content[$cx] === ">") $cx++;
584
 
585
  if (isset($this->options["tag_name_map"][$prefix . $tagname])) $outtagname = $tagname = $this->options["tag_name_map"][$prefix . $tagname];
586
 
899
  $y = strlen($data);
900
  while ($x < $y)
901
  {
902
+ $tempchr = ord($data[$x]);
903
  if (($tempchr >= 0x20 && $tempchr <= 0x7E) || $tempchr == 0x09 || $tempchr == 0x0A || $tempchr == 0x0D) $x++;
904
  else if ($tempchr < 0xC2) return false;
905
  else
906
  {
907
  $left = $y - $x;
908
+ if ($left > 1) $tempchr2 = ord($data[$x + 1]);
909
  else return false;
910
 
911
  if (($tempchr >= 0xC2 && $tempchr <= 0xDF) && ($tempchr2 >= 0x80 && $tempchr2 <= 0xBF)) $x += 2;
912
  else
913
  {
914
+ if ($left > 2) $tempchr3 = ord($data[$x + 2]);
915
  else return false;
916
 
917
  if ($tempchr3 < 0x80 || $tempchr3 > 0xBF) return false;
921
  else if ($tempchr == 0xED && ($tempchr2 >= 0x80 && $tempchr2 <= 0x9F)) $x += 3;
922
  else
923
  {
924
+ if ($left > 3) $tempchr4 = ord($data[$x + 3]);
925
  else return false;
926
 
927
  if ($tempchr4 < 0x80 || $tempchr4 > 0xBF) return false;
2642
  {
2643
  if ($cx >= $cy) break;
2644
 
2645
+ switch ($query[$cx])
2646
  {
2647
  case "#":
2648
  {
2683
  $cx++;
2684
 
2685
  // Find a non-whitespace character.
2686
+ while ($cx < $cy && ($query[$cx] == " " || $query[$cx] == "\t" || $query[$cx] == "\r" || $query[$cx] == "\n" || $query[$cx] == "\f")) $cx++;
2687
 
2688
  break;
2689
  }
2690
  case ":":
2691
  {
2692
  $cx++;
2693
+ if ($cx >= $cy || $query[$cx] != ":") $token["type"] = "pseudo-class";
2694
  else
2695
  {
2696
  $token["type"] = "pseudo-element";
2771
  $token[$state2] = $ident;
2772
 
2773
  // Find a non-whitespace character.
2774
+ while ($cx < $cy && ($query[$cx] == " " || $query[$cx] == "\t" || $query[$cx] == "\r" || $query[$cx] == "\n" || $query[$cx] == "\f")) $cx++;
2775
 
2776
+ if ($cx >= $cy || $query[$cx] == "]")
2777
  {
2778
  $token["cmp"] = false;
2779
  $tokens[] = $token;
2782
  }
2783
  else
2784
  {
2785
+ if ($query[$cx] == "=")
2786
  {
2787
  $token["cmp"] = "=";
2788
  $cx++;
2789
  }
2790
+ else if ($cx + 1 < $cy && ($query[$cx] == "^" || $query[$cx] == "$" || $query[$cx] == "*" || $query[$cx] == "~" || $query[$cx] == "|") && $query[$cx + 1] == "=")
2791
  {
2792
  $token["cmp"] = substr($query, $cx, 2);
2793
  $cx += 2;
2794
  }
2795
  else
2796
  {
2797
+ return array("success" => false, "error" => "Unknown or invalid attribute comparison operator '" . $query[$cx] . "' detected at position " . $cx . ".", "errorcode" => "invalid_attr_compare", "selector" => $query, "startpos" => $currcx, "pos" => $cx, "state" => $currstate, "tokens" => self::ReorderSelectorTokens(array_slice($tokens, 0, $lastor), $splitrules), "splitrules" => $splitrules);
2798
  }
2799
 
2800
  // Find a non-whitespace character.
2801
+ while ($cx < $cy && ($query[$cx] == " " || $query[$cx] == "\t" || $query[$cx] == "\r" || $query[$cx] == "\n" || $query[$cx] == "\f")) $cx++;
2802
 
2803
+ if ($cx < $cy && ($query[$cx] == "\"" || $query[$cx] == "'"))
2804
  {
2805
  $state = "string";
2806
+ $endchr = ord($query[$cx]);
2807
  $cx++;
2808
  }
2809
  else
2823
  $token[$state2] = $ident;
2824
 
2825
  // Find a non-whitespace character.
2826
+ while ($cx < $cy && ($query[$cx] == " " || $query[$cx] == "\t" || $query[$cx] == "\r" || $query[$cx] == "\n" || $query[$cx] == "\f")) $cx++;
2827
 
2828
  $tokens[] = $token;
2829
  $state = ($token["not"] ? "negate_close" : "next_selector");
2830
 
2831
+ if ($cx < $cy && $query[$cx] == "]") $cx++;
2832
  }
2833
 
2834
  break;
2844
  if ($token["type"] == "pseudo-class" && $ident == "not")
2845
  {
2846
  if ($token["not"]) return array("success" => false, "error" => "Invalid :not() embedded inside another :not() detected at position " . $cx . ".", "errorcode" => "invalid_not", "selector" => $query, "startpos" => $currcx, "pos" => $cx, "state" => $currstate, "tokens" => self::ReorderSelectorTokens(array_slice($tokens, 0, $lastor), $splitrules), "splitrules" => $splitrules);
2847
+ if ($cx >= $cy || $query[$cx] != "(") return array("success" => false, "error" => "Missing '(' detected at position " . $cx . ".", "errorcode" => "invalid_not", "selector" => $query, "startpos" => $currcx, "pos" => $cx, "state" => $currstate, "tokens" => self::ReorderSelectorTokens(array_slice($tokens, 0, $lastor), $splitrules), "splitrules" => $splitrules);
2848
 
2849
  unset($token["type"]);
2850
  $token["not"] = true;
2853
  $cx++;
2854
 
2855
  // Find a non-whitespace character.
2856
+ while ($cx < $cy && ($query[$cx] == " " || $query[$cx] == "\t" || $query[$cx] == "\r" || $query[$cx] == "\n" || $query[$cx] == "\f")) $cx++;
2857
  }
2858
  else
2859
  {
2860
  $token["pseudo"] = $ident;
2861
 
2862
+ if ($cx < $cy && $query[$cx] == "(")
2863
  {
2864
  $token["expression"] = "";
2865
  $ident = "";
2883
  case "negate_close":
2884
  {
2885
  // Find a non-whitespace character.
2886
+ while ($cx < $cy && ($query[$cx] == " " || $query[$cx] == "\t" || $query[$cx] == "\r" || $query[$cx] == "\n" || $query[$cx] == "\f")) $cx++;
2887
 
2888
+ if ($cx < $cy && $query[$cx] != ")") return array("success" => false, "error" => "Invalid :not() close character '" . $query[$cx] . "' detected at position " . $cx . ".", "errorcode" => "invalid_negate_close", "selector" => $query, "startpos" => $currcx, "pos" => $cx, "state" => $currstate, "tokens" => self::ReorderSelectorTokens(array_slice($tokens, 0, $lastor), $splitrules), "splitrules" => $splitrules);
2889
 
2890
  $cx++;
2891
  $state = "next_selector";
2897
  $token["expression"] .= $ident;
2898
 
2899
  // Find a non-whitespace character.
2900
+ while ($cx < $cy && ($query[$cx] == " " || $query[$cx] == "\t" || $query[$cx] == "\r" || $query[$cx] == "\n" || $query[$cx] == "\f")) $cx++;
2901
 
2902
  if ($cx >= $cy) break;
2903
 
2904
+ if ($query[$cx] == ")")
2905
  {
2906
  if (substr($token["pseudo"], 0, 4) === "nth-")
2907
  {
2944
  $state = ($token["not"] ? "negate_close" : "next_selector");
2945
  $cx++;
2946
  }
2947
+ else if ($query[$cx] == "+" || $query[$cx] == "-")
2948
  {
2949
+ $ident = $query[$cx];
2950
  $cx++;
2951
  }
2952
+ else if ($query[$cx] == "\"" || $query[$cx] == "'")
2953
  {
2954
  $state = "string";
2955
+ $endchr = ord($query[$cx]);
2956
  $cx++;
2957
  }
2958
  else
2959
  {
2960
+ $val = ord($query[$cx]);
2961
 
2962
  $state = ($val >= $zero && $val <= $nine ? "ident_name" : "ident");
2963
  $allownamespace = false;
2979
 
2980
  for (; $cx < $cy; $cx++)
2981
  {
2982
+ $val = ord($query[$cx]);
2983
 
2984
  if ($val == $endchr)
2985
  {
2994
  else
2995
  {
2996
  $cx++;
2997
+ $val = ord($query[$cx]);
2998
 
2999
  if (($val >= $a && $val <= $f) || ($val >= $a2 && $val <= $f2) || ($val >= $zero && $val <= $nine))
3000
  {
3001
  // Unicode (e.g. \0020)
3002
  for ($x = $cx + 1; $x < $cy; $x++)
3003
  {
3004
+ $val = ord($query[$x]);
3005
  if (!(($val >= $a && $val <= $f) || ($val >= $a2 && $val <= $f2) || ($val >= $zero && $val <= $nine))) break;
3006
  }
3007
 
3011
  $ident .= TagFilterStream::UTF8Chr($num);
3012
 
3013
  // Skip one optional \r\n OR a single whitespace char.
3014
+ if ($cx + 2 < $cy && $query[$cx + 1] == "\r" && $query[$cx + 2] == "\n") $cx += 2;
3015
+ else if ($cx + 1 < $cy && ($query[$cx + 1] == " " || $query[$cx + 1] == "\r" || $query[$cx + 1] == "\n" || $query[$cx + 1] == "\t" || $query[$cx + 1] == "\f")) $cx++;
3016
  }
3017
  else
3018
  {
3019
+ $ident .= $query[$cx];
3020
  }
3021
  }
3022
  }
3023
  else
3024
  {
3025
+ $ident .= $query[$cx];
3026
  }
3027
  }
3028
 
3037
 
3038
  if ($cx >= $cy) break;
3039
 
3040
+ if ($query[$cx] != "-") $ident = "";
3041
  else
3042
  {
3043
  $ident = "-";
3054
  $startcx = $cx;
3055
  for (; $cx < $cy; $cx++)
3056
  {
3057
+ $val = ord($query[$cx]);
3058
 
3059
  if ($val != $period && ($val < $zero || $val > $nine)) $allowperiod = false;
3060
 
3061
  if (($val >= $a && $val <= $z) || ($val >= $a2 && $val <= $z2) || $val == $underscore || $val > 127)
3062
  {
3063
+ $ident .= $query[$cx];
3064
  }
3065
  else if ($allowperiod && $val == $period)
3066
  {
3071
  else if ($val == $hyphen || ($val >= $zero && $val <= $nine))
3072
  {
3073
  // Only allowed AFTER the first character.
3074
+ if (!$range) return array("success" => false, "error" => "Invalid identifier character '" . $query[$cx] . "' detected at position " . $cx . ".", "errorcode" => "invalid_ident", "selector" => $query, "startpos" => $currcx, "pos" => $cx, "state" => $currstate, "tokens" => self::ReorderSelectorTokens(array_slice($tokens, 0, $lastor), $splitrules), "splitrules" => $splitrules);
3075
 
3076
  $allowperiod = false;
3077
 
3078
+ $ident .= $query[$cx];
3079
  }
3080
  else if ($val == $backslash)
3081
  {
3084
  else
3085
  {
3086
  $cx++;
3087
+ $val = ord($query[$cx]);
3088
 
3089
  if (($val >= $a && $val <= $f) || ($val >= $a2 && $val <= $f2) || ($val >= $zero && $val <= $nine))
3090
  {
3091
  // Unicode (e.g. \0020)
3092
  for ($x = $cx + 1; $x < $cy; $x++)
3093
  {
3094
+ $val = ord($query[$x]);
3095
  if (!(($val >= $a && $val <= $f) || ($val >= $a2 && $val <= $f2) || ($val >= $zero && $val <= $nine))) break;
3096
  }
3097
 
3101
  $ident .= TagFilterStream::UTF8Chr($num);
3102
 
3103
  // Skip one optional \r\n OR a single whitespace char.
3104
+ if ($cx + 2 < $cy && $query[$cx + 1] == "\r" && $query[$cx + 2] == "\n") $cx += 2;
3105
+ else if ($cx + 1 < $cy && ($query[$cx + 1] == " " || $query[$cx + 1] == "\r" || $query[$cx + 1] == "\n" || $query[$cx + 1] == "\t" || $query[$cx + 1] == "\f")) $cx++;
3106
  }
3107
  else if ($val != $cr && $val != $nl && $val != $ff)
3108
  {
3109
+ $ident .= $query[$cx];
3110
  }
3111
  }
3112
  }
3113
+ else if ($allownamespace && $val == $pipe && ($cx + 1 >= $cy || $query[$cx + 1] != "="))
3114
  {
3115
  // Handle namespaces (rare).
3116
  if ($ident != "")
3124
  else if ($val == $asterisk)
3125
  {
3126
  // Handle wildcard (*) characters.
3127
+ if ($allownamespace && $cx + 1 < $cy && $query[$cx + 1] == "|")
3128
  {
3129
  // Wildcard namespace (*|).
3130
  $namespace = "*";
3166
  $token = array("type" => "combine");
3167
 
3168
  // Find a non-whitespace character.
3169
+ while ($cx < $cy && ($query[$cx] == " " || $query[$cx] == "\t" || $query[$cx] == "\r" || $query[$cx] == "\n" || $query[$cx] == "\f")) $cx++;
3170
 
3171
  if ($cx < $cy)
3172
  {
3173
+ switch ($query[$cx])
3174
  {
3175
  case ",":
3176
  {
3214
  $tokens[] = $token;
3215
 
3216
  // Find a non-whitespace character.
3217
+ while ($cx < $cy && ($query[$cx] == " " || $query[$cx] == "\t" || $query[$cx] == "\r" || $query[$cx] == "\n" || $query[$cx] == "\f")) $cx++;
3218
  }
3219
 
3220
  $state = "next_selector";
3257
  return false;
3258
  }
3259
  }
3260
+ ?>
includes/vendor/ultimate-web-scraper/websocket.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  // CubicleSoft PHP WebSocket class.
3
- // (C) 2017 CubicleSoft. All Rights Reserved.
4
 
5
  // Implements RFC 6455 (WebSocket protocol).
6
  // Requires the CubicleSoft PHP HTTP/HTTPS class.
@@ -463,14 +463,14 @@
463
  {
464
  if (strlen($this->readdata) < 2) return false;
465
 
466
- $chr = ord($this->readdata{0});
467
  $fin = (($chr & 0x80) ? true : false);
468
  $rsv1 = (($chr & 0x40) ? true : false);
469
  $rsv2 = (($chr & 0x20) ? true : false);
470
  $rsv3 = (($chr & 0x10) ? true : false);
471
  $opcode = $chr & 0x0F;
472
 
473
- $chr = ord($this->readdata{1});
474
  $mask = (($chr & 0x80) ? true : false);
475
  $length = $chr & 0x7F;
476
  if ($length == 126) $start = 4;
@@ -500,7 +500,7 @@
500
  // Decode the payload.
501
  for ($x = 0; $x < $length; $x++)
502
  {
503
- $payload{$x} = chr(ord($payload{$x}) ^ ord($maskingkey{$x % 4}));
504
  }
505
  }
506
 
@@ -565,7 +565,7 @@
565
  $y = strlen($payload);
566
  for ($x = 0; $x < $y; $x++)
567
  {
568
- $payload{$x} = chr(ord($payload{$x}) ^ ord($maskingkey{$x % 4}));
569
  }
570
  }
571
 
@@ -598,7 +598,7 @@
598
  $result = 0;
599
  for ($x = 0; $x < 8; $x++)
600
  {
601
- $result = ($result * 256) + ord($data{$x});
602
  }
603
 
604
  return $result;
1
  <?php
2
  // CubicleSoft PHP WebSocket class.
3
+ // (C) 2020 CubicleSoft. All Rights Reserved.
4
 
5
  // Implements RFC 6455 (WebSocket protocol).
6
  // Requires the CubicleSoft PHP HTTP/HTTPS class.
463
  {
464
  if (strlen($this->readdata) < 2) return false;
465
 
466
+ $chr = ord($this->readdata[0]);
467
  $fin = (($chr & 0x80) ? true : false);
468
  $rsv1 = (($chr & 0x40) ? true : false);
469
  $rsv2 = (($chr & 0x20) ? true : false);
470
  $rsv3 = (($chr & 0x10) ? true : false);
471
  $opcode = $chr & 0x0F;
472
 
473
+ $chr = ord($this->readdata[1]);
474
  $mask = (($chr & 0x80) ? true : false);
475
  $length = $chr & 0x7F;
476
  if ($length == 126) $start = 4;
500
  // Decode the payload.
501
  for ($x = 0; $x < $length; $x++)
502
  {
503
+ $payload[$x] = chr(ord($payload[$x]) ^ ord($maskingkey[$x % 4]));
504
  }
505
  }
506
 
565
  $y = strlen($payload);
566
  for ($x = 0; $x < $y; $x++)
567
  {
568
+ $payload[$x] = chr(ord($payload[$x]) ^ ord($maskingkey[$x % 4]));
569
  }
570
  }
571
 
598
  $result = 0;
599
  for ($x = 0; $x < 8; $x++)
600
  {
601
+ $result = ($result * 256) + ord($data[$x]);
602
  }
603
 
604
  return $result;