Defender Security – Malware Scanner, Login Security & Firewall - Version 2.1.4

Version Description

  • Fix: Mask Login cause issue when visiting /wp-admin/network/sites.php
Download this release

Release Info

Developer hoang1213
Plugin Icon 128x128 Defender Security – Malware Scanner, Login Security & Firewall
Version 2.1.4
Comparing to
See all releases

Code changes from version 2.1.2 to 2.1.4

Files changed (93) hide show
  1. app/behavior/utils.php +2 -2
  2. app/controller/requirement.php +1 -1
  3. app/module/advanced-tools/component/auth-api.php +0 -1
  4. app/module/advanced-tools/component/mask-api.php +48 -6
  5. app/module/advanced-tools/controller/main.php +4 -4
  6. app/module/advanced-tools/controller/mask-login.php +5 -7
  7. app/module/advanced-tools/view/2factor-otp-email-edit-from.php +2 -2
  8. app/module/advanced-tools/view/layouts/layout.php +10 -9
  9. app/module/advanced-tools/view/login/disabled.php +7 -7
  10. app/module/advanced-tools/view/main-free.php +2 -2
  11. app/module/advanced-tools/view/main.php +5 -5
  12. app/module/advanced-tools/view/mask-login/enabled.php +2 -2
  13. app/module/hardener/component/change-admin.php +4 -0
  14. app/module/hardener/component/db-prefix.php +8 -1
  15. app/module/hardener/component/disable-file-editor.php +4 -0
  16. app/module/hardener/component/disable-trackback.php +6 -2
  17. app/module/hardener/component/disable-xml-rpc.php +4 -0
  18. app/module/hardener/component/hide-error.php +4 -0
  19. app/module/hardener/component/login-duration.php +18 -6
  20. app/module/hardener/component/php-version.php +7 -0
  21. app/module/hardener/component/prevent-php.php +4 -0
  22. app/module/hardener/component/protect-information.php +4 -0
  23. app/module/hardener/component/security-key.php +4 -0
  24. app/module/hardener/component/wp-version.php +4 -0
  25. app/module/hardener/controller/main.php +49 -5
  26. app/module/hardener/rule.php +9 -3
  27. app/module/hardener/view/email/notification.php +366 -0
  28. app/module/hardener/view/layouts/layout.php +26 -15
  29. app/module/hardener/view/rules/db-prefix.php +13 -12
  30. app/module/hardener/view/rules/hide-error.php +21 -19
  31. app/module/hardener/view/rules/prevent-php-executed.php +21 -5
  32. app/module/hardener/view/rules/protect-information.php +20 -4
  33. app/module/hardener/view/rules/wp-version.php +12 -10
  34. app/module/ip-lockout/component/login-protection-api.php +5 -5
  35. app/module/ip-lockout/controller/main.php +3 -2
  36. app/module/ip-lockout/view/blacklist/enabled.php +8 -5
  37. app/module/ip-lockout/view/detect-404/enabled.php +1 -4
  38. app/module/ip-lockout/view/layouts/layout.php +5 -4
  39. app/module/ip-lockout/view/locked.php +4 -2
  40. app/module/ip-lockout/view/login-lockouts/enabled.php +0 -3
  41. app/module/ip-lockout/view/notification/enabled.php +4 -4
  42. app/module/ip-lockout/view/notification/report.php +2 -2
  43. app/module/scan/behavior/scan.php +0 -266
  44. app/module/scan/component/result-table.php +17 -11
  45. app/module/scan/component/scan-api.php +3 -1
  46. app/module/scan/component/token-utils.php +301 -10
  47. app/module/scan/controller/main.php +18 -6
  48. app/module/scan/js/prism.css +183 -0
  49. app/module/scan/js/prism.js +1350 -0
  50. app/module/scan/js/script.js +13 -24
  51. app/module/scan/model/settings.php +2 -1
  52. app/module/scan/view/automation.php +1 -1
  53. app/module/scan/view/ignored.php +1 -1
  54. app/module/scan/view/issues.php +2 -2
  55. app/module/scan/view/layouts/layout.php +19 -6
  56. app/module/scan/view/notification.php +27 -1
  57. app/module/scan/view/setting-free.php +1 -1
  58. app/module/scan/view/setting.php +7 -7
  59. app/module/setting/view/accessibility.php +1 -1
  60. app/module/setting/view/general.php +1 -1
  61. app/module/setting/view/layouts/layout.php +19 -12
  62. app/view/activator.php +4 -2
  63. app/view/dashboard.php +32 -5
  64. assets/css/styles.css +33 -73
  65. assets/css/styles.css.map +0 -7
  66. assets/email-assets/img/Blue-Copy.png +0 -0
  67. assets/email-assets/img/Blue-Copy@2x.png +0 -0
  68. assets/email-assets/img/Defender-widerec.png +0 -0
  69. assets/email-assets/img/Defender-widerec@2x.png +0 -0
  70. assets/email-assets/img/Warning.png +0 -0
  71. assets/email-assets/img/Warning@2x.png +0 -0
  72. readme.txt +27 -2
  73. vendor/hammer/base/db-model.php +1 -1
  74. vendor/hammer/wp/model.php +1 -2
  75. vendor/php_codesniffer-3.4.0/CONTRIBUTING.md +13 -0
  76. vendor/php_codesniffer-3.4.0/CodeSniffer.conf.dist +9 -0
  77. vendor/php_codesniffer-3.4.0/README.md +107 -0
  78. vendor/php_codesniffer-3.4.0/composer.json +40 -0
  79. vendor/php_codesniffer-3.4.0/licence.txt +24 -0
  80. vendor/php_codesniffer-3.4.0/phpcs.xml.dist +145 -0
  81. vendor/php_codesniffer-3.4.0/phpcs.xsd +108 -0
  82. vendor/php_codesniffer-3.4.0/src/Exceptions/DeepExitException.php +18 -0
  83. vendor/php_codesniffer-3.4.0/src/Exceptions/RuntimeException.php +15 -0
  84. vendor/php_codesniffer-3.4.0/src/Exceptions/TokenizerException.php +15 -0
  85. vendor/php_codesniffer-3.4.0/src/Tokenizers/CSS.php +534 -0
  86. vendor/php_codesniffer-3.4.0/src/Tokenizers/Comment.php +277 -0
  87. vendor/php_codesniffer-3.4.0/src/Tokenizers/JS.php +1264 -0
  88. vendor/php_codesniffer-3.4.0/src/Tokenizers/PHP.php +2014 -0
  89. vendor/php_codesniffer-3.4.0/src/Tokenizers/Tokenizer.php +1614 -0
  90. vendor/php_codesniffer-3.4.0/src/Util/Standards.php +137 -0
  91. vendor/php_codesniffer-3.4.0/src/Util/Tokens.php +644 -0
  92. vendor/phpqrcode/qrvect.php +1 -1
  93. wp-defender.php +3 -3
app/behavior/utils.php CHANGED
@@ -685,11 +685,11 @@ class Utils extends Behavior {
685
  public function checkRequirement( &$result = null ) {
686
  $meet = true;
687
 
688
- if ( version_compare( $this->getPHPVersion(), '5.3', '>=' ) == false ) {
689
  $meet = false;
690
  $result['php'] = array(
691
  'status' => $this->getPHPVersion(),
692
- 'message' => __( "Please upgrade to 5.3 or later", "defender-security" )
693
  );
694
  }
695
 
685
  public function checkRequirement( &$result = null ) {
686
  $meet = true;
687
 
688
+ if ( version_compare( $this->getPHPVersion(), '5.6', '>=' ) == false ) {
689
  $meet = false;
690
  $result['php'] = array(
691
  'status' => $this->getPHPVersion(),
692
+ 'message' => __( "Please upgrade to 5.6 or later", "defender-security" )
693
  );
694
  }
695
 
app/controller/requirement.php CHANGED
@@ -49,7 +49,7 @@ class WD_Requirement {
49
  <tr>
50
  <td><?php _e( "PHP version", "defender-security" ) ?></td>
51
  <td>
52
- <span class="def-tag tag-yellow"><?php echo phpversion() ?></span>&nbsp;&nbsp;<?php _e( "Please upgrade to 5.3 or later.", "defender-security" ) ?>
53
  </td>
54
  </tr>
55
  </tbody>
49
  <tr>
50
  <td><?php _e( "PHP version", "defender-security" ) ?></td>
51
  <td>
52
+ <?php _e( "Please upgrade to 5.6 or later.", "defender-security" ) ?>
53
  </td>
54
  </tr>
55
  </tbody>
app/module/advanced-tools/component/auth-api.php CHANGED
@@ -70,7 +70,6 @@ class Auth_API extends Component {
70
  $secret = $base32->decode( $secret );
71
  //timestep fixed at 30
72
  if ( is_null( $counter ) ) {
73
-
74
  $counter = time();
75
  }
76
  $input = floor( $counter / 30 );
70
  $secret = $base32->decode( $secret );
71
  //timestep fixed at 30
72
  if ( is_null( $counter ) ) {
 
73
  $counter = time();
74
  }
75
  $input = floor( $counter / 30 );
app/module/advanced-tools/component/mask-api.php CHANGED
@@ -25,8 +25,8 @@ class Mask_Api extends Component {
25
  $requestUri = $_SERVER['REQUEST_URI'];
26
  }
27
  //
28
- $requestUri = '/' . ltrim( $requestUri, '/' );
29
- $prefix = parse_url( self::site_url(), PHP_URL_PATH );;
30
  $requestPath = parse_url( $requestUri, PHP_URL_PATH );
31
  //clean it a bit
32
  if ( Utils::instance()->isActivatedSingle() == false
@@ -42,8 +42,11 @@ class Mask_Api extends Component {
42
  $requestPath = substr( $requestPath, strlen( $path ) );
43
  $requestPath = '/' . ltrim( $requestPath, '/' );
44
  }
 
 
 
45
  }
46
- if ( strpos( $requestPath, $prefix ) === 0 ) {
47
  $requestPath = substr( $requestPath, strlen( $prefix ) );
48
  }
49
  $requestPath = untrailingslashit( $requestPath );
@@ -104,13 +107,52 @@ class Mask_Api extends Component {
104
  return $url;
105
  }
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  /**
108
  * @return string
109
  */
110
  public static function getRedirectUrl() {
111
  $settings = Mask_Settings::instance();
112
 
113
- return untrailingslashit( network_site_url() ) . '/' . ltrim( $settings->redirectTrafficUrl, '/' );
114
  }
115
 
116
  /**
@@ -119,7 +161,7 @@ class Mask_Api extends Component {
119
  public static function getNewLoginUrl( $domain = null ) {
120
  $settings = Mask_Settings::instance();
121
  if ( $domain == null ) {
122
- $domain = site_url();
123
  }
124
 
125
  return untrailingslashit( $domain . '/' . ltrim( $settings->maskUrl, '/' ) );
@@ -145,7 +187,7 @@ class Mask_Api extends Component {
145
  }
146
  //if context is login, we will check for exists page
147
  if ( $context == 'login' ) {
148
- if ( in_array( $slug, array( 'admin', 'backend', 'wp-login', 'wp-login.php' ) ) ) {
149
  return new \WP_Error( Error_Code::VALIDATE, __( "A page already exists at this URL, please pick a unique page for your new login area.", "defender-security" ) );
150
  }
151
 
25
  $requestUri = $_SERVER['REQUEST_URI'];
26
  }
27
  //
28
+ $requestUri = '/' . ltrim( $requestUri, '/' );
29
+ $prefix = parse_url( self::site_url(), PHP_URL_PATH );
30
  $requestPath = parse_url( $requestUri, PHP_URL_PATH );
31
  //clean it a bit
32
  if ( Utils::instance()->isActivatedSingle() == false
42
  $requestPath = substr( $requestPath, strlen( $path ) );
43
  $requestPath = '/' . ltrim( $requestPath, '/' );
44
  }
45
+ } elseif ( self::get_home_url() != self::site_url() && strpos( $requestPath, (string) $prefix . '/' ) !== 0 ) {
46
+ //this case when a wp install inside a sub folder and domain changed into that subfolder
47
+ $prefix = parse_url( self::get_home_url(), PHP_URL_PATH );
48
  }
49
+ if ( strlen( $prefix ) && strpos( $requestPath, (string) $prefix ) === 0 ) {
50
  $requestPath = substr( $requestPath, strlen( $prefix ) );
51
  }
52
  $requestPath = untrailingslashit( $requestPath );
107
  return $url;
108
  }
109
 
110
+ /**
111
+ * clone from get_home_url function without the filter
112
+ *
113
+ * @param null $blog_id
114
+ * @param string $path
115
+ * @param null $scheme
116
+ *
117
+ * @return mixed|void
118
+ */
119
+ private static function get_home_url( $blog_id = null, $path = '', $scheme = null ) {
120
+ global $pagenow;
121
+
122
+ $orig_scheme = $scheme;
123
+
124
+ if ( empty( $blog_id ) || ! is_multisite() ) {
125
+ $url = get_option( 'home' );
126
+ } else {
127
+ switch_to_blog( $blog_id );
128
+ $url = get_option( 'home' );
129
+ restore_current_blog();
130
+ }
131
+
132
+ if ( ! in_array( $scheme, array( 'http', 'https', 'relative' ) ) ) {
133
+ if ( is_ssl() && ! is_admin() && 'wp-login.php' !== $pagenow ) {
134
+ $scheme = 'https';
135
+ } else {
136
+ $scheme = parse_url( $url, PHP_URL_SCHEME );
137
+ }
138
+ }
139
+
140
+ $url = set_url_scheme( $url, $scheme );
141
+
142
+ if ( $path && is_string( $path ) ) {
143
+ $url .= '/' . ltrim( $path, '/' );
144
+ }
145
+
146
+ return $url;
147
+ }
148
+
149
  /**
150
  * @return string
151
  */
152
  public static function getRedirectUrl() {
153
  $settings = Mask_Settings::instance();
154
 
155
+ return untrailingslashit( get_home_url( get_current_blog_id() ) ) . '/' . ltrim( $settings->redirectTrafficUrl, '/' );
156
  }
157
 
158
  /**
161
  public static function getNewLoginUrl( $domain = null ) {
162
  $settings = Mask_Settings::instance();
163
  if ( $domain == null ) {
164
+ $domain = self::site_url();
165
  }
166
 
167
  return untrailingslashit( $domain . '/' . ltrim( $settings->maskUrl, '/' ) );
187
  }
188
  //if context is login, we will check for exists page
189
  if ( $context == 'login' ) {
190
+ if ( in_array( $slug, array( 'admin', 'backend', 'wp-login', 'wp-login.php', 'login' ) ) ) {
191
  return new \WP_Error( Error_Code::VALIDATE, __( "A page already exists at this URL, please pick a unique page for your new login area.", "defender-security" ) );
192
  }
193
 
app/module/advanced-tools/controller/main.php CHANGED
@@ -113,7 +113,7 @@ class Main extends Controller {
113
 
114
  $screen = get_current_screen();
115
  if ( $screen->id != 'profile' ) {
116
- wp_redirect( admin_url( 'profile.php' ) . '#show2AuthActivator' );
117
  exit;
118
  }
119
  }
@@ -404,7 +404,7 @@ class Main extends Controller {
404
  wp_set_current_user( $user->ID, $user->user_login );
405
  wp_set_auth_cookie( $user->ID, true );
406
  $redirect = apply_filters( 'login_redirect', $redirect, isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '', $user );
407
- wp_redirect( $redirect );
408
  exit;
409
  } else {
410
  $backupCode = get_user_meta( $user->ID, 'defenderBackupCode', true );
@@ -414,7 +414,7 @@ class Main extends Controller {
414
  wp_set_current_user( $user->ID, $user->user_login );
415
  wp_set_auth_cookie( $user->ID, true );
416
  $redirect = apply_filters( 'login_redirect', $redirect, isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '', $user );
417
- wp_redirect( $redirect );
418
  exit;
419
  } else {
420
  $params['error'] = new \WP_Error( 'opt_fail', __( "Whoops, the passcode you entered was incorrect or expired.", "defender-security" ) );
@@ -595,7 +595,7 @@ class Main extends Controller {
595
  }
596
  $email_settings['email_subject'] = $subject;
597
  $email_settings['email_sender'] = $sender;
598
- $email_settings['email_body'] = $body;
599
 
600
  $setting = Auth_Settings::instance();
601
  $setting->import( $email_settings );
113
 
114
  $screen = get_current_screen();
115
  if ( $screen->id != 'profile' ) {
116
+ wp_safe_redirect( admin_url( 'profile.php' ) . '#show2AuthActivator' );
117
  exit;
118
  }
119
  }
404
  wp_set_current_user( $user->ID, $user->user_login );
405
  wp_set_auth_cookie( $user->ID, true );
406
  $redirect = apply_filters( 'login_redirect', $redirect, isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '', $user );
407
+ wp_safe_redirect( $redirect );
408
  exit;
409
  } else {
410
  $backupCode = get_user_meta( $user->ID, 'defenderBackupCode', true );
414
  wp_set_current_user( $user->ID, $user->user_login );
415
  wp_set_auth_cookie( $user->ID, true );
416
  $redirect = apply_filters( 'login_redirect', $redirect, isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '', $user );
417
+ wp_safe_redirect( $redirect );
418
  exit;
419
  } else {
420
  $params['error'] = new \WP_Error( 'opt_fail', __( "Whoops, the passcode you entered was incorrect or expired.", "defender-security" ) );
595
  }
596
  $email_settings['email_subject'] = $subject;
597
  $email_settings['email_sender'] = $sender;
598
+ $email_settings['email_body'] = wp_kses_post( $body );
599
 
600
  $setting = Auth_Settings::instance();
601
  $setting->import( $email_settings );
app/module/advanced-tools/controller/mask-login.php CHANGED
@@ -46,9 +46,7 @@ class Mask_Login extends Controller {
46
  remove_action( 'template_redirect', 'wp_redirect_admin_locations' );
47
  //if prosite is activate and useremail is not defined, we need to update the
48
  //email to match the new login URL
49
- if ( is_plugin_active_for_network( 'pro-sites/pro-sites.php' ) ) {
50
- $this->add_filter( 'update_welcome_email', 'updateWelcomeEmailPrositeCase', 10, 6 );
51
- }
52
  } else {
53
  if ( $isJetpackSSO ) {
54
  wp_defender()->global['compatibility'][] = __( "We’ve detected a conflict with Jetpack’s Wordpress.com Log In feature. Please disable it and return to this page to continue setup.", "defender-security" );
@@ -88,8 +86,8 @@ class Mask_Login extends Controller {
88
  * @return mixed
89
  */
90
  public function updateWelcomeEmailPrositeCase( $welcome_email, $blog_id, $user_id, $password, $title, $meta ) {
91
- $url = get_blogaddress_by_id( $blog_id );
92
- $welcome_email = str_replace( $url . 'wp-login.php', Mask_Api::getNewLoginUrl( rtrim( '/', $url ) ), $welcome_email );
93
 
94
  return $welcome_email;
95
  }
@@ -134,7 +132,7 @@ class Mask_Login extends Controller {
134
  * @return string
135
  */
136
  private function alterLoginUrl( $currentUrl, $scheme = null ) {
137
- if ( strpos( $currentUrl, 'wp-login.php' ) !== false ) {
138
  //this is URL go to old wp-login.php
139
  $parts = parse_url( $currentUrl );
140
  if ( isset( $parts['query'] ) ) {
@@ -217,7 +215,7 @@ class Mask_Login extends Controller {
217
  }
218
 
219
  private function _showLoginPage() {
220
- global $error, $interim_login, $action, $user_login;
221
  require_once ABSPATH . 'wp-login.php';
222
  die;
223
  }
46
  remove_action( 'template_redirect', 'wp_redirect_admin_locations' );
47
  //if prosite is activate and useremail is not defined, we need to update the
48
  //email to match the new login URL
49
+ $this->add_filter( 'update_welcome_email', 'updateWelcomeEmailPrositeCase', 9999, 6 );
 
 
50
  } else {
51
  if ( $isJetpackSSO ) {
52
  wp_defender()->global['compatibility'][] = __( "We’ve detected a conflict with Jetpack’s Wordpress.com Log In feature. Please disable it and return to this page to continue setup.", "defender-security" );
86
  * @return mixed
87
  */
88
  public function updateWelcomeEmailPrositeCase( $welcome_email, $blog_id, $user_id, $password, $title, $meta ) {
89
+ $url = get_blogaddress_by_id( $blog_id );
90
+ $welcome_email = str_replace( $url . 'wp-login.php', Mask_Api::getNewLoginUrl( rtrim( $url, '/' ) ), $welcome_email );
91
 
92
  return $welcome_email;
93
  }
132
  * @return string
133
  */
134
  private function alterLoginUrl( $currentUrl, $scheme = null ) {
135
+ if ( stristr( $currentUrl, 'wp-login.php' ) !== false ) {
136
  //this is URL go to old wp-login.php
137
  $parts = parse_url( $currentUrl );
138
  if ( isset( $parts['query'] ) ) {
215
  }
216
 
217
  private function _showLoginPage() {
218
+ global $error, $interim_login, $action, $user_login, $user, $redirect_to;
219
  require_once ABSPATH . 'wp-login.php';
220
  die;
221
  }
app/module/advanced-tools/view/2factor-otp-email-edit-from.php CHANGED
@@ -20,7 +20,7 @@ $body = ! empty( $settings->email_body ) ? $settings->email_body : $settings-
20
  </div>
21
  </div>
22
  <form method="post">
23
- <?php wp_nonce_field( 'twoFactorOPTEmail' ) ?>
24
  <div class="sui-box-body">
25
  <p id="dialogDescription">
26
  <?php _e( "This email sends a temporary passcode when the user can’t access their phone.", "defender-security" ) ?>
@@ -50,7 +50,7 @@ $body = ! empty( $settings->email_body ) ? $settings->email_body : $settings-
50
  <?php _e( "Body", "defender-security" ) ?>
51
  </label>
52
  <textarea class="sui-form-control" name="body" rows="8"
53
- id="email_body"><?php echo $body; ?></textarea>
54
  </div>
55
  </div>
56
  <div class="sui-row">
20
  </div>
21
  </div>
22
  <form method="post">
23
+ <?php wp_nonce_field( 'twoFactorOPTEmail' ) ?>
24
  <div class="sui-box-body">
25
  <p id="dialogDescription">
26
  <?php _e( "This email sends a temporary passcode when the user can’t access their phone.", "defender-security" ) ?>
50
  <?php _e( "Body", "defender-security" ) ?>
51
  </label>
52
  <textarea class="sui-form-control" name="body" rows="8"
53
+ id="email_body"><?php echo stripslashes( $body ); ?></textarea>
54
  </div>
55
  </div>
56
  <div class="sui-row">
app/module/advanced-tools/view/layouts/layout.php CHANGED
@@ -8,7 +8,8 @@
8
  <?php if ( wp_defender()->hideDocLinks === false ): ?>
9
  <div class="sui-actions-right">
10
  <div class="sui-actions-right">
11
- <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/#advanced-tools" target="_blank" class="sui-button sui-button-ghost">
 
12
  <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
13
  </a>
14
  </div>
@@ -39,13 +40,13 @@
39
  <?php echo $contents ?>
40
  </div>
41
  </div>
42
- <?php if ( wp_defender()->changeFooter && ! empty( wp_defender()->footerText ) ): ?>
43
  <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
44
- <?php else: ?>
45
  <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
46
- <?php endif; ?>
47
- <?php if ( wp_defender()->hideDocLinks == false ): ?>
48
- <?php if ( wp_defender()->isFree ): ?>
49
  <ul class="sui-footer-nav">
50
  <li><a href="https://profiles.wordpress.org/wpmudev#content-plugins" target="_blank">Free
51
  Plugins</a>
@@ -59,7 +60,7 @@
59
  </li>
60
  <li><a href="https://incsub.com/privacy-policy/" target="_blank">Privacy Policy</a></li>
61
  </ul>
62
- <?php else: ?>
63
  <ul class="sui-footer-nav">
64
  <li><a href="https://premium.wpmudev.org/hub/" target="_blank">The Hub</a></li>
65
  <li><a href="https://premium.wpmudev.org/projects/category/plugins/" target="_blank">Plugins</a>
@@ -72,7 +73,7 @@
72
  </li>
73
  <li><a href="https://incsub.com/privacy-policy/" target="_blank">Privacy Policy</a></li>
74
  </ul>
75
- <?php endif; ?>
76
  <ul class="sui-footer-social">
77
  <li><a href="https://www.facebook.com/wpmudev" target="_blank">
78
  <i class="sui-icon-social-facebook" aria-hidden="true"></i>
@@ -87,6 +88,6 @@
87
  <span class="sui-screen-reader-text">Instagram</span>
88
  </a></li>
89
  </ul>
90
- <?php endif; ?>
91
  </div>
92
  </div>
8
  <?php if ( wp_defender()->hideDocLinks === false ): ?>
9
  <div class="sui-actions-right">
10
  <div class="sui-actions-right">
11
+ <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/#advanced-tools"
12
+ target="_blank" class="sui-button sui-button-ghost">
13
  <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
14
  </a>
15
  </div>
40
  <?php echo $contents ?>
41
  </div>
42
  </div>
43
+ <?php if ( wp_defender()->changeFooter ): ?>
44
  <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
45
+ <?php else: ?>
46
  <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
47
+ <?php endif; ?>
48
+ <?php if ( wp_defender()->hideDocLinks == false ): ?>
49
+ <?php if ( wp_defender()->isFree ): ?>
50
  <ul class="sui-footer-nav">
51
  <li><a href="https://profiles.wordpress.org/wpmudev#content-plugins" target="_blank">Free
52
  Plugins</a>
60
  </li>
61
  <li><a href="https://incsub.com/privacy-policy/" target="_blank">Privacy Policy</a></li>
62
  </ul>
63
+ <?php else: ?>
64
  <ul class="sui-footer-nav">
65
  <li><a href="https://premium.wpmudev.org/hub/" target="_blank">The Hub</a></li>
66
  <li><a href="https://premium.wpmudev.org/projects/category/plugins/" target="_blank">Plugins</a>
73
  </li>
74
  <li><a href="https://incsub.com/privacy-policy/" target="_blank">Privacy Policy</a></li>
75
  </ul>
76
+ <?php endif; ?>
77
  <ul class="sui-footer-social">
78
  <li><a href="https://www.facebook.com/wpmudev" target="_blank">
79
  <i class="sui-icon-social-facebook" aria-hidden="true"></i>
88
  <span class="sui-screen-reader-text">Instagram</span>
89
  </a></li>
90
  </ul>
91
+ <?php endif; ?>
92
  </div>
93
  </div>
app/module/advanced-tools/view/login/disabled.php CHANGED
@@ -52,10 +52,7 @@
52
  <div class="line"></div>
53
  <p><strong><?php _e( "2. Scan the barcode", "defender-security" ) ?></strong></p>
54
  <p><?php _e( "Open the Google Authenticator app you just downloaded, tap the “+” symbol and then use your phone’s camera to scan the barcode below.", "defender-security" ) ?></p>
55
- <!-- <img class="barcode"-->
56
- <!-- src="-->
57
- <?php //echo \WP_Defender\Module\Advanced_Tools\Component\Auth_API::generateQRCode( urlencode( get_bloginfo( 'name' ) ) . ':' . $email, $secretKey, 149, 149, urlencode( get_bloginfo( 'name' ) ) ) ?><!--"/>-->
58
- <?php echo \WP_Defender\Module\Advanced_Tools\Component\Auth_API::generateQRCode( urlencode( get_bloginfo( 'name' ) ) , $email, $secretKey, 149, 149, urlencode( get_bloginfo( 'name' ) ) ) ?>
59
  <div class="line"></div>
60
  <p><strong><?php _e( "3. Enter passcode", "defender-security" ) ?></strong></p>
61
  <p>
@@ -75,6 +72,8 @@
75
  </tr>
76
  </tbody>
77
  </table>
 
 
78
  <script type="text/javascript">
79
  jQuery(function ($) {
80
  $('#def2qr').hide();
@@ -144,8 +143,9 @@
144
  </script>
145
  <?php if ( $settings->forceAuth ): ?>
146
  <script type="text/javascript">
147
- if (!window.location.hash) {
148
- window.location.hash = '#show2AuthActivator';
149
- }
150
  </script>
151
  <?php endif; ?>
 
52
  <div class="line"></div>
53
  <p><strong><?php _e( "2. Scan the barcode", "defender-security" ) ?></strong></p>
54
  <p><?php _e( "Open the Google Authenticator app you just downloaded, tap the “+” symbol and then use your phone’s camera to scan the barcode below.", "defender-security" ) ?></p>
55
+ <?php echo \WP_Defender\Module\Advanced_Tools\Component\Auth_API::generateQRCode( urlencode( get_bloginfo( 'name' ) ), $email, $secretKey, 149, 149, urlencode( get_bloginfo( 'name' ) ) ) ?>
 
 
 
56
  <div class="line"></div>
57
  <p><strong><?php _e( "3. Enter passcode", "defender-security" ) ?></strong></p>
58
  <p>
72
  </tr>
73
  </tbody>
74
  </table>
75
+ <script type="text/javascript"
76
+ src="<?php echo wp_defender()->getPluginUrl() . 'app/module/advanced-tools/js/qrcode.min.js' ?>"></script>
77
  <script type="text/javascript">
78
  jQuery(function ($) {
79
  $('#def2qr').hide();
143
  </script>
144
  <?php if ( $settings->forceAuth ): ?>
145
  <script type="text/javascript">
146
+ jQuery(function ($) {
147
+ $('html, body').animate({scrollTop: $("#show2AuthActivator").offset().top}, 1000);
148
+ });
149
  </script>
150
  <?php endif; ?>
151
+
app/module/advanced-tools/view/main-free.php CHANGED
@@ -89,8 +89,8 @@
89
  </div>
90
  <div class="sui-box-settings-col-2">
91
  <div class="sui-form-field">
 
92
  <label class="sui-toggle">
93
- <input type="hidden" name="lostPhone" value="0"/>
94
  <input role="presentation" type="checkbox" name="lostPhone" class="toggle-checkbox"
95
  id="lostPhone" value="1"
96
  <?php checked( true, $settings->lostPhone ) ?>/>
@@ -113,8 +113,8 @@
113
  </div>
114
  <div class="sui-box-settings-col-2">
115
  <div class="sui-form-field">
 
116
  <label class="sui-toggle">
117
- <input type="hidden" name="forceAuth" value="0"/>
118
  <input role="presentation" type="checkbox" name="forceAuth" class="toggle-checkbox"
119
  id="forceAuth" value="1"
120
  <?php checked( true, $settings->forceAuth ) ?>/>
89
  </div>
90
  <div class="sui-box-settings-col-2">
91
  <div class="sui-form-field">
92
+ <input type="hidden" name="lostPhone" value="0"/>
93
  <label class="sui-toggle">
 
94
  <input role="presentation" type="checkbox" name="lostPhone" class="toggle-checkbox"
95
  id="lostPhone" value="1"
96
  <?php checked( true, $settings->lostPhone ) ?>/>
113
  </div>
114
  <div class="sui-box-settings-col-2">
115
  <div class="sui-form-field">
116
+ <input type="hidden" name="forceAuth" value="0"/>
117
  <label class="sui-toggle">
 
118
  <input role="presentation" type="checkbox" name="forceAuth" class="toggle-checkbox"
119
  id="forceAuth" value="1"
120
  <?php checked( true, $settings->forceAuth ) ?>/>
app/module/advanced-tools/view/main.php CHANGED
@@ -87,8 +87,8 @@
87
  </div>
88
  <div class="sui-box-settings-col-2">
89
  <div class="sui-form-field">
 
90
  <label class="sui-toggle">
91
- <input type="hidden" name="lostPhone" value="0"/>
92
  <input role="presentation" type="checkbox" name="lostPhone" class="toggle-checkbox"
93
  id="lostPhone" value="1"
94
  <?php checked( true, $settings->lostPhone ) ?>/>
@@ -111,8 +111,8 @@
111
  </div>
112
  <div class="sui-box-settings-col-2">
113
  <div class="sui-form-field">
 
114
  <label class="sui-toggle">
115
- <input type="hidden" name="forceAuth" value="0"/>
116
  <input role="presentation" type="checkbox" name="forceAuth" class="toggle-checkbox"
117
  id="forceAuth" value="1"
118
  <?php checked( true, $settings->forceAuth ) ?>/>
@@ -163,8 +163,8 @@
163
  </span>
164
  </div>
165
  <div class="sui-box-settings-col-2">
 
166
  <label class="sui-toggle">
167
- <input type="hidden" name="customGraphic" value="0"/>
168
  <input role="presentation" type="checkbox" name="customGraphic" class="toggle-checkbox"
169
  id="customGraphic" value="1"
170
  <?php checked( true, $settings->customGraphic ) ?>/>
@@ -238,7 +238,7 @@
238
  <?php _e( "App Download", "defender-security" ) ?>
239
  </span>
240
  <span class="sui-description">
241
- <?php _e( 'Need the app? Here’s links to the official Google Authenticator apps.', "defender-security" ); ?>
242
  </span>
243
  </div>
244
  <div class="sui-box-settings-col-2">
@@ -256,7 +256,7 @@
256
  <?php _e( "Active Users", "defender-security" ) ?>
257
  </span>
258
  <span class="sui-description">
259
- <?php _e( "Here’s a quick link to see which of your users have enabled two-factor verification.", "defender-security" ) ?>
260
  </span>
261
  </div>
262
  <div class="sui-box-settings-col-2">
87
  </div>
88
  <div class="sui-box-settings-col-2">
89
  <div class="sui-form-field">
90
+ <input type="hidden" name="lostPhone" value="0"/>
91
  <label class="sui-toggle">
 
92
  <input role="presentation" type="checkbox" name="lostPhone" class="toggle-checkbox"
93
  id="lostPhone" value="1"
94
  <?php checked( true, $settings->lostPhone ) ?>/>
111
  </div>
112
  <div class="sui-box-settings-col-2">
113
  <div class="sui-form-field">
114
+ <input type="hidden" name="forceAuth" value="0"/>
115
  <label class="sui-toggle">
 
116
  <input role="presentation" type="checkbox" name="forceAuth" class="toggle-checkbox"
117
  id="forceAuth" value="1"
118
  <?php checked( true, $settings->forceAuth ) ?>/>
163
  </span>
164
  </div>
165
  <div class="sui-box-settings-col-2">
166
+ <input type="hidden" name="customGraphic" value="0"/>
167
  <label class="sui-toggle">
 
168
  <input role="presentation" type="checkbox" name="customGraphic" class="toggle-checkbox"
169
  id="customGraphic" value="1"
170
  <?php checked( true, $settings->customGraphic ) ?>/>
238
  <?php _e( "App Download", "defender-security" ) ?>
239
  </span>
240
  <span class="sui-description">
241
+ <?php _e( 'Need the app? Here’s links to the official Google Authenticator iOS and Android apps.', "defender-security" ); ?>
242
  </span>
243
  </div>
244
  <div class="sui-box-settings-col-2">
256
  <?php _e( "Active Users", "defender-security" ) ?>
257
  </span>
258
  <span class="sui-description">
259
+ <?php _e( "Here’s a quick link to see which of your users have enabled two-factor authentication.", "defender-security" ) ?>
260
  </span>
261
  </div>
262
  <div class="sui-box-settings-col-2">
app/module/advanced-tools/view/mask-login/enabled.php CHANGED
@@ -66,14 +66,14 @@
66
  </div>
67
 
68
  <div class="sui-box-settings-col-2">
 
69
  <label class="sui-toggle">
70
- <input type="hidden" name="redirectTraffic" value="0"/>
71
  <input role="presentation" type="checkbox" name="redirectTraffic" class="toggle-checkbox"
72
  id="redirectTraffic" value="1"
73
  <?php checked( true, $settings->redirectTraffic ) ?>/>
74
  <span class="sui-toggle-slider"></span>
75
  </label>
76
- <label for="lostPhone" class="sui-toggle-label">
77
  <?php _e( "Enable 404 redirection", "defender-security" ) ?>
78
  </label>
79
  <div id="redirectTrafficContainer" class="sui-border-frame sui-toggle-content"
66
  </div>
67
 
68
  <div class="sui-box-settings-col-2">
69
+ <input type="hidden" name="redirectTraffic" value="0"/>
70
  <label class="sui-toggle">
 
71
  <input role="presentation" type="checkbox" name="redirectTraffic" class="toggle-checkbox"
72
  id="redirectTraffic" value="1"
73
  <?php checked( true, $settings->redirectTraffic ) ?>/>
74
  <span class="sui-toggle-slider"></span>
75
  </label>
76
+ <label for="redirectTraffic" class="sui-toggle-label">
77
  <?php _e( "Enable 404 redirection", "defender-security" ) ?>
78
  </label>
79
  <div id="redirectTrafficContainer" class="sui-border-frame sui-toggle-content"
app/module/hardener/component/change-admin.php CHANGED
@@ -17,6 +17,10 @@ class Change_Admin extends Rule {
17
  $this->renderPartial( 'rules/change-admin' );
18
  }
19
 
 
 
 
 
20
  public function check() {
21
  return $this->getService()->check();
22
  }
17
  $this->renderPartial( 'rules/change-admin' );
18
  }
19
 
20
+ public function getSubDescription() {
21
+ return __( "You have a user account with the admin username.", "defender-security" );
22
+ }
23
+
24
  public function check() {
25
  return $this->getService()->check();
26
  }
app/module/hardener/component/db-prefix.php CHANGED
@@ -22,6 +22,13 @@ class DB_Prefix extends Rule {
22
  return $this->getService()->check();
23
  }
24
 
 
 
 
 
 
 
 
25
  function addHooks() {
26
  $this->add_action( 'processingHardener' . self::$slug, 'process' );
27
  $this->add_action( 'processRevert' . self::$slug, 'revert' );
@@ -60,7 +67,7 @@ class DB_Prefix extends Rule {
60
  wp_send_json_error( array(
61
  'message' => $ret->get_error_message()
62
  ) );
63
- } ;
64
  }
65
 
66
  /**
22
  return $this->getService()->check();
23
  }
24
 
25
+ /**
26
+ * @return mixed
27
+ */
28
+ function getSubDescription() {
29
+ return __( "Your database prefix is the default wp_ prefix.", "defender-security" );
30
+ }
31
+
32
  function addHooks() {
33
  $this->add_action( 'processingHardener' . self::$slug, 'process' );
34
  $this->add_action( 'processRevert' . self::$slug, 'revert' );
67
  wp_send_json_error( array(
68
  'message' => $ret->get_error_message()
69
  ) );
70
+ };
71
  }
72
 
73
  /**
app/module/hardener/component/disable-file-editor.php CHANGED
@@ -16,6 +16,10 @@ class Disable_File_Editor extends Rule {
16
  $this->renderPartial( 'rules/disable-file-editor' );
17
  }
18
 
 
 
 
 
19
  function check() {
20
  return $this->getService()->check();
21
  }
16
  $this->renderPartial( 'rules/disable-file-editor' );
17
  }
18
 
19
+ function getSubDescription() {
20
+ return __( "The file editor is currently enabled.", "defender-security" );
21
+ }
22
+
23
  function check() {
24
  return $this->getService()->check();
25
  }
app/module/hardener/component/disable-trackback.php CHANGED
@@ -17,6 +17,10 @@ class Disable_Trackback extends Rule {
17
  $this->renderPartial( 'rules/disable-trackback' );
18
  }
19
 
 
 
 
 
20
  /**
21
  * @return bool
22
  */
@@ -66,8 +70,8 @@ class Disable_Trackback extends Rule {
66
  if ( ! $this->verifyNonce() ) {
67
  return;
68
  }
69
- $process_posts = HTTP_Helper::retrieve_post( 'updatePosts' );
70
- $this->getService()->process_posts = $process_posts;
71
 
72
  $ret = $this->getService()->process();
73
  if ( ! is_wp_error( $ret ) ) {
17
  $this->renderPartial( 'rules/disable-trackback' );
18
  }
19
 
20
+ function getSubDescription() {
21
+ return __( "Trackbacks and pingbacks are currently enabled.", "defender-security" );
22
+ }
23
+
24
  /**
25
  * @return bool
26
  */
70
  if ( ! $this->verifyNonce() ) {
71
  return;
72
  }
73
+ $process_posts = HTTP_Helper::retrieve_post( 'updatePosts' );
74
+ $this->getService()->process_posts = $process_posts;
75
 
76
  $ret = $this->getService()->process();
77
  if ( ! is_wp_error( $ret ) ) {
app/module/hardener/component/disable-xml-rpc.php CHANGED
@@ -17,6 +17,10 @@ class Disable_Xml_Rpc extends Rule {
17
  $this->renderPartial( 'rules/disable-xml-rpc' );
18
  }
19
 
 
 
 
 
20
  /**
21
  * @return bool
22
  */
17
  $this->renderPartial( 'rules/disable-xml-rpc' );
18
  }
19
 
20
+ function getSubDescription() {
21
+ return __( "XML-RPC is currently enabled.", "defender-security" );
22
+ }
23
+
24
  /**
25
  * @return bool
26
  */
app/module/hardener/component/hide-error.php CHANGED
@@ -29,6 +29,10 @@ class Hide_Error extends Rule {
29
  return $stat;
30
  }
31
 
 
 
 
 
32
  public function getTitle() {
33
  return __( "Hide error reporting", "defender-security" );
34
  }
29
  return $stat;
30
  }
31
 
32
+ function getSubDescription() {
33
+ return __( "Error debugging is currently allowed.", "defender-security" );
34
+ }
35
+
36
  public function getTitle() {
37
  return __( "Hide error reporting", "defender-security" );
38
  }
app/module/hardener/component/login-duration.php CHANGED
@@ -32,6 +32,12 @@ class Login_Duration extends Rule {
32
  $this->renderPartial( 'rules/login-duration' );
33
  }
34
 
 
 
 
 
 
 
35
  /**
36
  * @return string
37
  */
@@ -53,7 +59,7 @@ class Login_Duration extends Rule {
53
  if ( $this->check() ) {
54
  $this->add_filter( 'auth_cookie_expiration', 'cookie_duration', 10, 3 );
55
  $this->add_filter( 'login_message', 'login_message' );
56
- $this->add_action( 'wp_loaded', 'check_login' );
57
  }
58
 
59
  }
@@ -113,6 +119,8 @@ class Login_Duration extends Rule {
113
 
114
  /**
115
  * Check login of users
 
 
116
  */
117
  function check_login() {
118
  $defender_logout = HTTP_Helper::retrieve_get( 'defender_logout', false );
@@ -212,13 +220,17 @@ class Login_Duration extends Rule {
212
  * @return Integer $duration
213
  */
214
  function cookie_duration( $duration, $user_id, $remember ) {
215
- if ( $remember ) {
216
- $duration = $this->getService()->getDuration( true );
 
 
 
 
 
217
  }
218
 
 
219
  return $duration;
220
  }
221
 
222
- }
223
-
224
- ?>
32
  $this->renderPartial( 'rules/login-duration' );
33
  }
34
 
35
+ function getSubDescription() {
36
+ $days = $this->getService()->getDuration();
37
+
38
+ return sprintf( __( "Your current login duration is the default %d days.", "defender-security" ), $days );
39
+ }
40
+
41
  /**
42
  * @return string
43
  */
59
  if ( $this->check() ) {
60
  $this->add_filter( 'auth_cookie_expiration', 'cookie_duration', 10, 3 );
61
  $this->add_filter( 'login_message', 'login_message' );
62
+ //$this->add_action( 'wp_loaded', 'check_login' );
63
  }
64
 
65
  }
119
 
120
  /**
121
  * Check login of users
122
+ * @deprecated since 2.1.3
123
+ * We just need to alter the cookies time so wordpress will do the rest
124
  */
125
  function check_login() {
126
  $defender_logout = HTTP_Helper::retrieve_get( 'defender_logout', false );
220
  * @return Integer $duration
221
  */
222
  function cookie_duration( $duration, $user_id, $remember ) {
223
+ $dur = $this->getService()->getDuration( true );
224
+ if ( $dur < 2 ) {
225
+ //duration set smaller than 2 days, use the custom for both remember & non remeber
226
+ return $dur;
227
+ } elseif ( $remember ) {
228
+ //this case only
229
+ return $dur;
230
  }
231
 
232
+ //return default
233
  return $duration;
234
  }
235
 
236
+ }
 
 
app/module/hardener/component/php-version.php CHANGED
@@ -5,6 +5,7 @@
5
 
6
  namespace WP_Defender\Module\Hardener\Component;
7
 
 
8
  use WP_Defender\Module\Hardener\Rule;
9
 
10
  class PHP_Version extends Rule {
@@ -15,6 +16,12 @@ class PHP_Version extends Rule {
15
  $this->renderPartial( 'rules/php-version' );
16
  }
17
 
 
 
 
 
 
 
18
  /**
19
  * @return bool
20
  */
5
 
6
  namespace WP_Defender\Module\Hardener\Component;
7
 
8
+ use WP_Defender\Module\Hardener\Model\Settings;
9
  use WP_Defender\Module\Hardener\Rule;
10
 
11
  class PHP_Version extends Rule {
16
  $this->renderPartial( 'rules/php-version' );
17
  }
18
 
19
+ function getSubDescription() {
20
+ $settings = Settings::instance();
21
+
22
+ return sprintf( __( "PHP versions older than %s are no longer supported. For security and stability we strongly recommend you upgrade your PHP version to version %s or newer as soon as possible. ", "defender-security" ), $settings->min_php_version, $settings->min_php_version );
23
+ }
24
+
25
  /**
26
  * @return bool
27
  */
app/module/hardener/component/prevent-php.php CHANGED
@@ -22,6 +22,10 @@ class Prevent_Php extends Rule {
22
  $this->renderPartial( 'rules/prevent-php-executed' );
23
  }
24
 
 
 
 
 
25
  /**
26
  * @return bool|false|mixed|null
27
  */
22
  $this->renderPartial( 'rules/prevent-php-executed' );
23
  }
24
 
25
+ function getSubDescription() {
26
+ return __( "PHP execution is currently allowed in all directories.", "defender-security" );
27
+ }
28
+
29
  /**
30
  * @return bool|false|mixed|null
31
  */
app/module/hardener/component/protect-information.php CHANGED
@@ -17,6 +17,10 @@ class Protect_Information extends Rule {
17
  $this->renderPartial( 'rules/protect-information' );
18
  }
19
 
 
 
 
 
20
  /**
21
  * @return bool|false|mixed|null
22
  */
17
  $this->renderPartial( 'rules/protect-information' );
18
  }
19
 
20
+ function getSubDescription() {
21
+ return __( "You don't have information disclosure protection active.", "defender-security" );
22
+ }
23
+
24
  /**
25
  * @return bool|false|mixed|null
26
  */
app/module/hardener/component/security-key.php CHANGED
@@ -34,6 +34,10 @@ class Security_Key extends Rule {
34
  ) );
35
  }
36
 
 
 
 
 
37
  /**
38
  * @return string
39
  */
34
  ) );
35
  }
36
 
37
+ function getSubDescription() {
38
+ return sprintf( __( "Your current security keys are %s days old. Time to update them!", "defender-security" ), $this->check() );
39
+ }
40
+
41
  /**
42
  * @return string
43
  */
app/module/hardener/component/wp-version.php CHANGED
@@ -22,6 +22,10 @@ class WP_Version extends Rule {
22
  return $this->getService()->check();
23
  }
24
 
 
 
 
 
25
  function revert() {
26
  // TODO: Implement revert() method.
27
  }
22
  return $this->getService()->check();
23
  }
24
 
25
+ function getSubDescription() {
26
+ return sprintf( __( "Your current WordPress version is out of date, which means you could be missing out on the latest security patches in v%s", "defender-security" ), $this->getService()->getLatestVersion() );
27
+ }
28
+
29
  function revert() {
30
  // TODO: Implement revert() method.
31
  }
app/module/hardener/controller/main.php CHANGED
@@ -47,11 +47,14 @@ class Main extends Controller {
47
  $this->add_ajax_action( 'restoreHardener', 'restoreHardener' );
48
  $this->add_ajax_action( 'updateHardener', 'updateHardener' );
49
  $this->add_ajax_action( 'saveTweaksSettings', 'saveTweaksSettings' );
50
- // if ( ! wp_next_scheduled( 'tweaksSendNotification' ) ) {
51
- // wp_schedule_event( time(), 'twicedaily', 'tweaksSendNotification' );
52
- // }
53
 
54
  $this->add_action( 'tweaksSendNotification', 'tweaksSendNotification' );
 
 
 
55
 
56
  $view = HTTP_Helper::retrieve_get( 'view' );
57
  $id = isset( $_REQUEST['id'] ) ? $_REQUEST['id'] : 0;
@@ -99,13 +102,22 @@ class Main extends Controller {
99
  //no honey no email
100
  return;
101
  }
 
 
 
 
 
 
102
 
 
 
 
103
  if ( $settings->last_sent == null ) {
104
  //this is the case user install this and never check the page
105
  //send report
106
  foreach ( $settings->receipts as $receipt ) {
107
  $email = $receipt['email'];
108
- wp_mail( $email, 'update tweak subject', 'update tweak content' );
109
  }
110
  $settings->last_sent = time();
111
  $settings->save();
@@ -118,13 +130,45 @@ class Main extends Controller {
118
 
119
  foreach ( $settings->receipts as $receipt ) {
120
  $email = $receipt['email'];
121
- wp_mail( $email, 'update tweak subject', 'update tweak content' );
122
  }
123
  $settings->last_sent = time();
124
  $settings->save();
125
  }
126
  }
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  public function saveTweaksSettings() {
129
  if ( ! $this->checkPermission() ) {
130
  return;
47
  $this->add_ajax_action( 'restoreHardener', 'restoreHardener' );
48
  $this->add_ajax_action( 'updateHardener', 'updateHardener' );
49
  $this->add_ajax_action( 'saveTweaksSettings', 'saveTweaksSettings' );
50
+ if ( ! wp_next_scheduled( 'tweaksSendNotification' ) ) {
51
+ wp_schedule_event( time(), 'twicedaily', 'tweaksSendNotification' );
52
+ }
53
 
54
  $this->add_action( 'tweaksSendNotification', 'tweaksSendNotification' );
55
+ if ( isset( $_GET['email'] ) ) {
56
+ $this->tweaksSendNotification();
57
+ }
58
 
59
  $view = HTTP_Helper::retrieve_get( 'view' );
60
  $id = isset( $_REQUEST['id'] ) ? $_REQUEST['id'] : 0;
102
  //no honey no email
103
  return;
104
  }
105
+ $no_reply_email = "noreply@" . parse_url( get_site_url(), PHP_URL_HOST );
106
+ $no_reply_email = apply_filters( 'wd_scan_noreply_email', $no_reply_email );
107
+ $headers = array(
108
+ 'From: Defender <' . $no_reply_email . '>',
109
+ 'Content-Type: text/html; charset=UTF-8'
110
+ );
111
 
112
+ $subject = _n( 'Security Tweak Report for %s. %s tweak needs attention.', 'Security Tweak Report for %s. %s tweaks needs attention.', count( $tweaks ), "defender-security" );
113
+ $subject = sprintf( $subject, network_site_url(), count( $tweaks ) );
114
+
115
  if ( $settings->last_sent == null ) {
116
  //this is the case user install this and never check the page
117
  //send report
118
  foreach ( $settings->receipts as $receipt ) {
119
  $email = $receipt['email'];
120
+ wp_mail( $email, $subject, $this->prepareEmailContent( $receipt['first_name'] ), $headers );
121
  }
122
  $settings->last_sent = time();
123
  $settings->save();
130
 
131
  foreach ( $settings->receipts as $receipt ) {
132
  $email = $receipt['email'];
133
+ wp_mail( $email, $subject, $this->prepareEmailContent( $receipt['first_name'] ), $headers );
134
  }
135
  $settings->last_sent = time();
136
  $settings->save();
137
  }
138
  }
139
 
140
+ private function prepareEmailContent( $firstName ) {
141
+ $issues = "";
142
+ foreach ( Hardener\Model\Settings::instance()->getIssues() as $issue ) {
143
+ $issue = '<tr style="border:none;padding:0;text-align:left;vertical-align:top">
144
+ <td class="wpmudev-table__row--label"
145
+ style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;border-radius:0 0 0 4px;border-top:.5px solid #d8d8d8;color:#333;font-family:\'Open Sans\',Helvetica,Arial,sans-serif;font-size:16px;font-weight:600;hyphens:auto;line-height:20px;margin:0;padding:10px 15px;text-align:left;vertical-align:top;word-wrap:break-word">
146
+ <img class="wpmudev-table__icon"
147
+ src="' . wp_defender()->getPluginUrl() . 'assets/email-assets/img/Warning@2x.png"
148
+ alt="Hero Image"
149
+ style="-ms-interpolation-mode:bicubic;clear:both;display:inline-block;margin-right:10px;max-width:100%;outline:0;text-decoration:none;vertical-align:middle;width:18px">
150
+ ' . $issue->getTitle() . '
151
+ <span style="color: #888888;font-family: \'Open Sans\';padding-left: 32px;font-size: 13px;font-weight:300;letter-spacing: -0.25px;line-height: 22px;display: block">
152
+ ' . $issue->getSubDescription() . '
153
+ </span>
154
+ </td>
155
+ <td class="wpmudev-table__row--warning text-right"
156
+ style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;border-radius:0 0 4px 0;border-top:.5px solid #d8d8d8;color:#FACD25;font-family:\'Open Sans\',Helvetica,Arial,sans-serif;font-size:12px;font-weight:400;hyphens:auto;line-height:20px;margin:0;padding:10px 15px;text-align:right;vertical-align:top;word-wrap:break-word">
157
+ </td>
158
+ </tr>';
159
+ $issues .= $issue;
160
+ }
161
+ $contents = $this->renderPartial( 'email/notification', array(
162
+ 'userName' => $firstName,
163
+ 'siteUrl' => network_site_url(),
164
+ 'viewUrl' => network_admin_url( 'admin.php?page=wdf-hardener' ),
165
+ 'issues' => $issues,
166
+ 'count' => count( Hardener\Model\Settings::instance()->getIssues() )
167
+ ), false );
168
+
169
+ return $contents;
170
+ }
171
+
172
  public function saveTweaksSettings() {
173
  if ( ! $this->checkPermission() ) {
174
  return;
app/module/hardener/rule.php CHANGED
@@ -28,6 +28,12 @@ abstract class Rule extends Component {
28
  */
29
  abstract function getDescription();
30
 
 
 
 
 
 
 
31
  /**
32
  * @return mixed
33
  */
@@ -130,15 +136,15 @@ abstract class Rule extends Component {
130
  <div class="sui-accordion-item-header">
131
  <div class="sui-accordion-item-title">
132
  <i aria-hidden="true" class="sui-icon-eye-hide"></i>
133
- <?php echo $this->getTitle(); ?>
134
  <div class="sui-actions-right">
135
  <form method="post" class="float-r hardener-frm rule-process">
136
- <?php $this->createNonceField(); ?>
137
  <input type="hidden" name="action" value="restoreHardener"/>
138
  <input type="hidden" name="slug" value="<?php echo static::$slug ?>"/>
139
  <button type="submit" class="sui-button sui-button-ghost">
140
  <i class="sui-icon-update" aria-hidden="true"></i>
141
- <?php _e( "Restore", "defender-security" ) ?>
142
  </button>
143
  </form>
144
  </div>
28
  */
29
  abstract function getDescription();
30
 
31
+ /**
32
+ * Return this rule reason
33
+ * @return mixed
34
+ */
35
+ abstract function getSubDescription();
36
+
37
  /**
38
  * @return mixed
39
  */
136
  <div class="sui-accordion-item-header">
137
  <div class="sui-accordion-item-title">
138
  <i aria-hidden="true" class="sui-icon-eye-hide"></i>
139
+ <?php echo $this->getTitle(); ?>
140
  <div class="sui-actions-right">
141
  <form method="post" class="float-r hardener-frm rule-process">
142
+ <?php $this->createNonceField(); ?>
143
  <input type="hidden" name="action" value="restoreHardener"/>
144
  <input type="hidden" name="slug" value="<?php echo static::$slug ?>"/>
145
  <button type="submit" class="sui-button sui-button-ghost">
146
  <i class="sui-icon-update" aria-hidden="true"></i>
147
+ <?php _e( "Restore", "defender-security" ) ?>
148
  </button>
149
  </form>
150
  </div>
app/module/hardener/view/email/notification.php ADDED
@@ -0,0 +1,366 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" style="background:#f3f3f3!important">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6
+ <meta name="viewport" content="width=device-width"><!-- Import Open Sans Webfont -->
7
+ <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,400i,600,600i,700,700i" rel="stylesheet">
8
+ <title></title>
9
+ <style>@media only screen {
10
+ html {
11
+ min-height: 100%;
12
+ background: #f3f3f3
13
+ }
14
+ }
15
+
16
+ @media only screen and (max-width: 615px) {
17
+ .small-float-center {
18
+ margin: 0 auto !important;
19
+ float: none !important;
20
+ text-align: center !important
21
+ }
22
+ }
23
+
24
+ @media only screen and (max-width: 615px) {
25
+ table.body img {
26
+ width: auto;
27
+ height: auto
28
+ }
29
+
30
+ table.body center {
31
+ min-width: 0 !important
32
+ }
33
+
34
+ table.body .container {
35
+ width: 95% !important
36
+ }
37
+
38
+ table.body .columns {
39
+ height: auto !important;
40
+ -moz-box-sizing: border-box;
41
+ -webkit-box-sizing: border-box;
42
+ box-sizing: border-box;
43
+ padding-left: 15px !important;
44
+ padding-right: 15px !important
45
+ }
46
+
47
+ th.small-12 {
48
+ display: inline-block !important;
49
+ width: 100% !important
50
+ }
51
+
52
+ table.menu {
53
+ width: 100% !important
54
+ }
55
+
56
+ table.menu td, table.menu th {
57
+ width: auto !important;
58
+ display: inline-block !important
59
+ }
60
+
61
+ table.menu.vertical td, table.menu.vertical th {
62
+ display: block !important
63
+ }
64
+
65
+ table.menu[align=center] {
66
+ width: auto !important
67
+ }
68
+ }</style>
69
+ <style type="text/css">@media only screen and (min-width: 615px) {
70
+ h1 {
71
+ padding-top: 40px !important
72
+ }
73
+
74
+ table.body .column.first, table.body .columns.first {
75
+ padding-left: 60px !important
76
+ }
77
+
78
+ table.body .column.last, table.body .columns.last {
79
+ padding-right: 60px !important
80
+ }
81
+
82
+ .article-block .article-block__heading {
83
+ font-size: 15px !important;
84
+ line-height: 20px !important;
85
+ Margin: 20px 0 20px -15px !important;
86
+ font-weight: 400 !important
87
+ }
88
+
89
+ .article-block .article-block__img {
90
+ height: 90px !important;
91
+ width: 130px !important
92
+ }
93
+ }
94
+
95
+ @media only screen and (min-width: 450px) {
96
+ span.whip-issue-tag {
97
+ position: relative !important;
98
+ left: 0 !important;
99
+ transform: translateX(0) !important;
100
+ display: inline-block !important
101
+ }
102
+ }
103
+
104
+ @media only screen and (max-width: 450px) {
105
+ h1.whip-orange:first-of-type {
106
+ padding-top: 55px !important
107
+ }
108
+ }
109
+
110
+ @media only screen {
111
+ table.button:hover table td {
112
+ background: #0092CA !important
113
+ }
114
+
115
+ table.button.secondary:hover table td {
116
+ background: #6F6F6F !important
117
+ }
118
+
119
+ table.button.success:hover table td {
120
+ background: #01A383 !important
121
+ }
122
+
123
+ table.button.warning:hover table td {
124
+ background: #E1B40C !important
125
+ }
126
+
127
+ table.button.alert:hover table td {
128
+ background: #D33F27 !important
129
+ }
130
+ }</style>
131
+ </head>
132
+ <body style="-moz-box-sizing:border-box;-ms-text-size-adjust:100%;-webkit-box-sizing:border-box;-webkit-text-size-adjust:100%;Margin:0;background:#f3f3f3!important;box-sizing:border-box;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;min-width:100%;padding:0;text-align:left;width:100%!important">
133
+ <table class="body"
134
+ style="Margin:0;background:#f3f3f3!important;border-collapse:collapse;border-spacing:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;height:100%;line-height:25px;margin:0;padding:0;text-align:left;vertical-align:top;width:100%">
135
+ <tr style="padding:0;text-align:left;vertical-align:top">
136
+ <td class="center" align="center" valign="top"
137
+ style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
138
+ <center data-parsed style="min-width:600px;width:100%">
139
+ <table align="center" class="container view-in-browser float-center"
140
+ style="Margin:0 auto;background:0 0;border-collapse:collapse;border-spacing:0;float:none;height:50px;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:600px">
141
+ <tbody>
142
+ <tr style="padding:0;text-align:left;vertical-align:top">
143
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
144
+ <div class="text-right" style="text-align:right"><a href="https://premium.wpmudev.org"
145
+ style="Margin:0;color:#888;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:12px;font-weight:400;line-height:50px;margin:0;margin-right:10px;padding:0;text-align:right;text-decoration:none">View
146
+ in browser</a></div>
147
+ </td>
148
+ </tr>
149
+ </tbody>
150
+ </table>
151
+ <table align="center" class="container main-content float-center"
152
+ style="Margin:0 auto;background:#fff;border-collapse:collapse;border-radius:4px;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:600px">
153
+ <tbody>
154
+ <tr style="padding:0;text-align:left;vertical-align:top">
155
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;padding-bottom:55px!important;text-align:left;vertical-align:top;word-wrap:break-word">
156
+ <div class="hero-image" style="height:150px"><img
157
+ src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-assets/img/Defender-widerec@2x.png"
158
+ alt="Hero Image"
159
+ style="-ms-interpolation-mode:bicubic;border-radius:4px 4px 0 0;clear:both;display:block;height:100%;max-width:100%;object-fit:cover;outline:0;text-decoration:none;width:auto">
160
+ </div>
161
+ <table class="row"
162
+ style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
163
+ <tbody>
164
+ <tr style="padding:0;text-align:left;vertical-align:top">
165
+ <th class="small-12 large-12 columns first last"
166
+ style="Margin:0 auto;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-bottom:15px;padding-left:15px;padding-right:15px;text-align:left;width:585px">
167
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
168
+ <tr style="padding:0;text-align:left;vertical-align:top">
169
+ <th style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0;text-align:left">
170
+ <h1 style="-webkit-font-smoothing:antialiased;Margin:0;Margin-bottom:10px;color:inherit;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:22px;font-smoothing:antialiased;font-weight:600;line-height:25px;margin:0;margin-bottom:30px;padding:0;padding-top:30px;text-align:left;word-wrap:normal">
171
+ <?php printf( __( "Security tweak report for %s", "defender-security" ), $siteUrl ) ?>
172
+ </h1>
173
+ <p style="-webkit-font-smoothing:antialiased;Margin:0;Margin-bottom:10px;color:#333;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-smoothing:antialiased;font-weight:400;line-height:25px;margin:0;margin-bottom:30px;padding:0;text-align:left">
174
+ <?php printf( __( "Hi %s,", "defender-security" ), $userName ) ?>
175
+ </p>
176
+ <p style="-webkit-font-smoothing:antialiased;Margin:0;Margin-bottom:10px;color:#333;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-smoothing:antialiased;font-weight:400;line-height:25px;margin:0;margin-bottom:30px;padding:0;text-align:left">
177
+ <?php printf( __( "You have %d unresolved security tweaks on %s. We recommend you action what you can to prevent any issues, and ignore anything you don't want to fix up.", "defender-security" ), $count, $siteUrl ) ?>
178
+ </p>
179
+ </th>
180
+ <th class="expander"
181
+ style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
182
+ </tr>
183
+ </table>
184
+ </th>
185
+ </tr>
186
+ </tbody>
187
+ </table>
188
+ <table class="row"
189
+ style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
190
+ <tbody>
191
+ <tr style="padding:0;text-align:left;vertical-align:top">
192
+ <th class="small-12 large-12 columns first last"
193
+ style="Margin:0 auto;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-bottom:15px;padding-left:15px;padding-right:15px;text-align:left;width:585px">
194
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
195
+ <tr style="padding:0;text-align:left;vertical-align:top">
196
+ <th style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0;text-align:left">
197
+ <table class="wpmudev-table"
198
+ style="border-collapse:separate;border-radius:4px;border-spacing:0;margin-bottom:10px;padding:0;text-align:left;vertical-align:top;width:100%">
199
+ <tbody>
200
+ <?php echo $issues ?>
201
+ </tbody>
202
+ </table>
203
+ </th>
204
+ <th class="expander"
205
+ style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
206
+ </tr>
207
+ </table>
208
+ </th>
209
+ </tr>
210
+ </tbody>
211
+ </table>
212
+ <table class="row"
213
+ style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
214
+ <tbody>
215
+ <tr style="padding:0;text-align:left;vertical-align:top">
216
+ <th class="small-12 large-12 columns first last"
217
+ style="Margin:0 auto;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-bottom:15px;padding-left:15px;padding-right:15px;text-align:left;width:585px">
218
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
219
+ <tr style="padding:0;text-align:left;vertical-align:top">
220
+ <th style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0;text-align:left">
221
+ <table class="button btn-center"
222
+ style="Margin:0 auto 30px!important;border-collapse:collapse;border-spacing:0;margin:0 0 30px 0;padding:0;text-align:left;vertical-align:top;width:auto">
223
+ <tr style="padding:0;text-align:left;vertical-align:top">
224
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
225
+ <table style="border-collapse:collapse;border-radius:4px;border-spacing:0;overflow:hidden;padding:0;text-align:left;vertical-align:top;width:100%">
226
+ <tr style="padding:0;text-align:left;vertical-align:top">
227
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:#17ABE3;border:none;border-collapse:collapse!important;color:#fff;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;text-align:center;vertical-align:top;word-wrap:break-word">
228
+ <a href="<?php echo $viewUrl ?>"
229
+ style="Margin:0;border:0 solid #17ABE3;border-radius:4px;color:#fff;display:inline-block;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:15px;font-weight:400;line-height:25px;margin:0;min-width:275px;padding:8px 16px 8px 16px;text-align:center;text-decoration:none;text-transform:uppercase">
230
+ <?php _e( "View All", "defender-security" ) ?>
231
+ </a></td>
232
+ </tr>
233
+ </table>
234
+ </td>
235
+ </tr>
236
+ </table>
237
+ </th>
238
+ <th class="expander"
239
+ style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
240
+ </tr>
241
+ </table>
242
+ </th>
243
+ </tr>
244
+ </tbody>
245
+ </table>
246
+ <table class="row cheers"
247
+ style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
248
+ <tbody>
249
+ <tr style="padding:0;text-align:left;vertical-align:top">
250
+ <th class="small-12 large-12 columns first last"
251
+ style="Margin:0 auto;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-bottom:15px;padding-left:15px;padding-right:15px;text-align:left;width:585px">
252
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
253
+ <tr style="padding:0;text-align:left;vertical-align:top">
254
+ <th style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0;text-align:left">
255
+ <p style="-webkit-font-smoothing:antialiased;Margin:0;Margin-bottom:10px;color:#333;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:15px;font-smoothing:antialiased;font-weight:400;line-height:25px;margin:0;margin-bottom:30px;padding:0;text-align:left">
256
+ <?php _e( "Stay safe,", "defender-security" ) ?>
257
+ </p>
258
+ <p style="-webkit-font-smoothing:antialiased;Margin:0;color:#333;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:15px;font-smoothing:antialiased;font-weight:400;line-height:25px;margin:0;padding:0;text-align:left">
259
+ <?php _e( "Defender,", "defender-security" ) ?>
260
+ </p>
261
+ <p style="-webkit-font-smoothing:antialiased;Margin:0;color:#333;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:15px;font-smoothing:antialiased;font-weight:400;line-height:25px;margin:0;margin-bottom:30px;padding:0;text-align:left">
262
+ <?php _e( "WPMU DEV Security Hero", "defender-security" ) ?></p>
263
+ <th class="expander"
264
+ style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
265
+ </tr>
266
+ </table>
267
+ </th>
268
+ </tr>
269
+ </tbody>
270
+ </table>
271
+ </td>
272
+ </tr>
273
+ </tbody>
274
+ </table>
275
+ <table align="center" class="container footer float-center"
276
+ style="Margin:0 auto;background:0 0;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;text-align:center;vertical-align:top;width:600px">
277
+ <tbody>
278
+ <tr style="padding:0;text-align:left;vertical-align:top">
279
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
280
+ <table class="row"
281
+ style="border-collapse:collapse;border-spacing:0;display:table;padding:0;position:relative;text-align:left;vertical-align:top;width:100%">
282
+ <tbody>
283
+ <tr style="padding:0;text-align:left;vertical-align:top">
284
+ <th class="small-12 large-12 columns first last"
285
+ style="Margin:0 auto;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-bottom:15px;padding-left:15px;padding-right:15px;text-align:left;width:585px">
286
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
287
+ <tr style="padding:0;text-align:left;vertical-align:top">
288
+ <th style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0;text-align:left">
289
+ <center data-parsed style="min-width:555px;width:100%"><img
290
+ class="footer__logo float-center"
291
+ src="<?php echo wp_defender()->getPluginUrl() ?>assets/email-assets/img/Blue-Copy@2x.png"
292
+ alt="WPMUDEV Logo"
293
+ align="center"
294
+ style="-ms-interpolation-mode:bicubic;Margin:0 auto;clear:both;display:block;float:none;height:23px;margin:0 auto;max-width:100%;outline:0;padding-bottom:26px;padding-top:40px;text-align:center;text-decoration:none;width:auto">
295
+ </center>
296
+ <center data-parsed style="min-width:555px;width:100%"><span
297
+ class="text-center footer__italic float-center"
298
+ align="center"
299
+ style="color:#666;display:block;font-size:14px;font-style:italic;line-height:20px;text-align:center;width:100%">Everything You Need For WordPress.</span>
300
+ <span class="text-center footer__italic float-center"
301
+ align="center"
302
+ style="color:#666;display:block;font-size:14px;font-style:italic;line-height:20px;text-align:center;width:100%">One place, one low price, unlimited sites.</span>
303
+ </center>
304
+ <center data-parsed style="min-width:555px;width:100%"><span
305
+ class="text-center footer__address float-center"
306
+ align="center"
307
+ style="color:#AAA;display:block;font-size:10px;line-height:30px;padding-top:30px;text-align:center;width:100%">INCSUB PO BOX 163, ALBERT PARK, VICTORIA.3206 AUSTRALIA</span>
308
+ </center>
309
+ <center data-parsed style="min-width:555px;width:100%">
310
+ <table align="center"
311
+ class="menu text-center footer__menu float-center"
312
+ style="Margin:0 auto;border-collapse:collapse;border-spacing:0;float:none;margin:0 auto;padding:0;padding-bottom:100px;text-align:center;vertical-align:top;width:auto!important">
313
+ <tr style="padding:0;text-align:left;vertical-align:top">
314
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;hyphens:auto;line-height:25px;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
315
+ <table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
316
+ <tr style="padding:0;text-align:left;vertical-align:top">
317
+ <th class="menu-item float-center"
318
+ style="Margin:0 auto;color:#000;float:none;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-right:10px;text-align:center">
319
+ <a href="#"
320
+ style="Margin:0;color:#888;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:14px;font-weight:400;line-height:30px;margin:0;padding:0;text-align:center;text-decoration:underline">Manage
321
+ your email preferences</a></th>
322
+ <th class="menu-item float-center"
323
+ style="Margin:0 auto;color:#000;float:none;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0 auto;padding:0;padding-right:10px;text-align:center">
324
+ <a href="#"
325
+ style="Margin:0;color:#888;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:14px;font-weight:400;line-height:30px;margin:0;padding:0;text-align:center;text-decoration:underline">Unsubscribe</a>
326
+ </th>
327
+ </tr>
328
+ </table>
329
+ </td>
330
+ </tr>
331
+ </table>
332
+ </center>
333
+ <table class="spacer"
334
+ style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%">
335
+ <tbody>
336
+ <tr style="padding:0;text-align:left;vertical-align:top">
337
+ <td height="96px"
338
+ style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:96px;font-weight:400;hyphens:auto;line-height:96px;margin:0;mso-line-height-rule:exactly;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
339
+ &#xA0;
340
+ </td>
341
+ </tr>
342
+ </tbody>
343
+ </table>
344
+ </th>
345
+ <th class="expander"
346
+ style="Margin:0;color:#000;font-family:'Open Sans',Helvetica,Arial,sans-serif;font-size:18px;font-weight:400;line-height:25px;margin:0;padding:0!important;text-align:left;visibility:hidden;width:0"></th>
347
+ </tr>
348
+ </table>
349
+ </th>
350
+ </tr>
351
+ </tbody>
352
+ </table>
353
+ </td>
354
+ </tr>
355
+ </tbody>
356
+ </table>
357
+ </center>
358
+ </td>
359
+ </tr>
360
+ </table><!-- prevent Gmail on iOS font size manipulation -->
361
+ <div style="display:none;white-space:nowrap;font:15px courier;line-height:0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
362
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
363
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
364
+ </div>
365
+ </body>
366
+ </html>
app/module/hardener/view/layouts/layout.php CHANGED
@@ -2,11 +2,12 @@
2
  $countAll = $controller->getCount( 'issues' );
3
  $resolved = $controller->getCount( 'fixed' );
4
  $ignore = $controller->getCount( 'ignore' );
5
- $tooltip = '';
6
  $class = '';
7
- if ( $countAll > 0 ) {
8
- $tooltip = 'data-tooltip="' . esc_attr( sprintf( __( 'You have %d security tweak(s) needing attention.', "defender-security" ), $countAll ) ) . '"';
9
- $class = 'sui-tooltip';
 
10
  }
11
  $inlineHeroImage = strlen( wp_defender()->heroImage ) > 0 ? 'background-image: url(\'' . wp_defender()->heroImage . '\')' : null;
12
  ?>
@@ -17,15 +18,16 @@ $inlineHeroImage = strlen( wp_defender()->heroImage ) > 0 ? 'background-image: u
17
  <h1 class="sui-header-title">
18
  <?php _e( "Security Tweaks", "defender-security" ) ?>
19
  </h1>
20
- <?php if ( wp_defender()->hideDocLinks === false ): ?>
21
  <div class="sui-actions-right">
22
  <div class="sui-actions-right">
23
- <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/" target="_blank" class="sui-button sui-button-ghost">
 
24
  <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
25
  </a>
26
  </div>
27
  </div>
28
- <?php endif; ?>
29
  </div>
30
  <div class="sui-box sui-summary sui-summary-sm <?php echo \WP_Defender\Behavior\Utils::instance()->getSummaryClass() ?>">
31
  <div class="sui-summary-image-space"
@@ -36,11 +38,17 @@ $inlineHeroImage = strlen( wp_defender()->heroImage ) > 0 ? 'background-image: u
36
 
37
  <div class="sui-summary-details issues">
38
 
39
- <span class="sui-summary-large <?php echo $class ?> count-issues" <?php echo $tooltip ?> ><?php echo $countAll ?></span>
40
  <?php if ( $countAll > 0 ): ?>
 
 
41
  <i aria-hidden="true" class="sui-icon-info sui-warning"></i>
 
42
  <?php else: ?>
 
 
43
  <i class="sui-icon-check-tick sui-success" aria-hidden="true"></i>
 
44
  <?php endif; ?>
45
  <span class="sui-summary-sub"><?php _e( "Security issues", "defender-security" ) ?></span>
46
  </div>
@@ -89,10 +97,11 @@ $inlineHeroImage = strlen( wp_defender()->heroImage ) > 0 ? 'background-image: u
89
  <?php _e( "Ignored", "defender-security" ) ?></a>
90
  <span class="sui-tag count-ignored <?php echo $ignore ? '' : 'wd-hide' ?>"><?php echo $ignore ?></span>
91
  </li>
92
- <!-- <li class="sui-vertical-tab --><?php //echo $controller->isView( 'notification' ) ? 'current' : null ?><!--">-->
93
- <!-- <a href="--><?php //echo network_admin_url( 'admin.php?page=wdf-hardener&view=notification' ) ?><!--">-->
94
- <!-- --><?php //_e( "Notification", "defender-security" ) ?><!--</a>-->
95
- <!-- </li>-->
 
96
  </ul>
97
  <div class="sui-sidenav-hide-lg">
98
  <select class="sui-mobile-nav" style="display: none;">
@@ -102,8 +111,10 @@ $inlineHeroImage = strlen( wp_defender()->heroImage ) > 0 ? 'background-image: u
102
  value="<?php echo network_admin_url( 'admin.php?page=wdf-hardener&view=resolved' ) ?>"><?php _e( "Resolved", "defender-security" ) ?></option>
103
  <option <?php selected( 'ignored', \Hammer\Helper\HTTP_Helper::retrieve_get( 'view' ) ) ?>
104
  value="<?php echo network_admin_url( 'admin.php?page=wdf-hardener&view=ignored' ) ?>"><?php _e( "Ignored", "defender-security" ) ?></option>
105
- <!-- <option --><?php //selected( 'notification', \Hammer\Helper\HTTP_Helper::retrieve_get( 'view' ) ) ?>
106
- <!-- value="--><?php //echo network_admin_url( 'admin.php?page=wdf-hardener&view=notification' ) ?><!--">--><?php //_e( "Notification", "defender-security" ) ?><!--</option>-->
 
 
107
  </select>
108
  </div>
109
  </div>
@@ -112,7 +123,7 @@ $inlineHeroImage = strlen( wp_defender()->heroImage ) > 0 ? 'background-image: u
112
  </div>
113
  </div>
114
  </div>
115
- <?php if ( wp_defender()->changeFooter && ! empty( wp_defender()->footerText ) ): ?>
116
  <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
117
  <?php else: ?>
118
  <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
2
  $countAll = $controller->getCount( 'issues' );
3
  $resolved = $controller->getCount( 'fixed' );
4
  $ignore = $controller->getCount( 'ignore' );
5
+ $tooltips = __( "You don't have any outstanding security issues, nice work!", "defender-security" );
6
  $class = '';
7
+ if ( $countAll == 1 ) {
8
+ $tooltips = __( "You have one security tweak left to do. We recommend you action it, or ignore it if it's irrelevant.", "defender-security" );
9
+ } elseif ( $countAll > 1 ) {
10
+ $tooltips = sprintf( __( "You have %s security tweaks left to do. We recommend you take a look and action fixes, or ignore the issues if they are harmless." ), $countAll );
11
  }
12
  $inlineHeroImage = strlen( wp_defender()->heroImage ) > 0 ? 'background-image: url(\'' . wp_defender()->heroImage . '\')' : null;
13
  ?>
18
  <h1 class="sui-header-title">
19
  <?php _e( "Security Tweaks", "defender-security" ) ?>
20
  </h1>
21
+ <?php if ( wp_defender()->hideDocLinks === false ): ?>
22
  <div class="sui-actions-right">
23
  <div class="sui-actions-right">
24
+ <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/#security-tweaks" target="_blank"
25
+ class="sui-button sui-button-ghost">
26
  <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
27
  </a>
28
  </div>
29
  </div>
30
+ <?php endif; ?>
31
  </div>
32
  <div class="sui-box sui-summary sui-summary-sm <?php echo \WP_Defender\Behavior\Utils::instance()->getSummaryClass() ?>">
33
  <div class="sui-summary-image-space"
38
 
39
  <div class="sui-summary-details issues">
40
 
41
+ <span class="sui-summary-large count-issues"><?php echo $countAll ?></span>
42
  <?php if ( $countAll > 0 ): ?>
43
+ <span class="sui-tooltip sui-tooltip-top-left sui-tooltip-constrained"
44
+ data-tooltip="<?php echo $tooltips ?>">
45
  <i aria-hidden="true" class="sui-icon-info sui-warning"></i>
46
+ </span>
47
  <?php else: ?>
48
+ <span class="sui-tooltip sui-tooltip-top-left sui-tooltip-constrained"
49
+ data-tooltip="<?php echo $tooltips ?>">
50
  <i class="sui-icon-check-tick sui-success" aria-hidden="true"></i>
51
+ </span>
52
  <?php endif; ?>
53
  <span class="sui-summary-sub"><?php _e( "Security issues", "defender-security" ) ?></span>
54
  </div>
97
  <?php _e( "Ignored", "defender-security" ) ?></a>
98
  <span class="sui-tag count-ignored <?php echo $ignore ? '' : 'wd-hide' ?>"><?php echo $ignore ?></span>
99
  </li>
100
+ <li class="sui-vertical-tab <?php echo $controller->isView( 'notification' ) ? 'current' : null ?>">
101
+ <a href="<?php echo network_admin_url( 'admin.php?page=wdf-hardener&view=notification' ) ?>">
102
+ <?php _e( "Notification", "defender-security" ) ?>
103
+ </a>
104
+ </li>
105
  </ul>
106
  <div class="sui-sidenav-hide-lg">
107
  <select class="sui-mobile-nav" style="display: none;">
111
  value="<?php echo network_admin_url( 'admin.php?page=wdf-hardener&view=resolved' ) ?>"><?php _e( "Resolved", "defender-security" ) ?></option>
112
  <option <?php selected( 'ignored', \Hammer\Helper\HTTP_Helper::retrieve_get( 'view' ) ) ?>
113
  value="<?php echo network_admin_url( 'admin.php?page=wdf-hardener&view=ignored' ) ?>"><?php _e( "Ignored", "defender-security" ) ?></option>
114
+ <option <?php selected( 'notification', \Hammer\Helper\HTTP_Helper::retrieve_get( 'view' ) ) ?>
115
+ value="<?php echo network_admin_url( 'admin.php?page=wdf-hardener&view=notification' ) ?>">
116
+ <?php _e( "Notification", "defender-security" ) ?>
117
+ </option>
118
  </select>
119
  </div>
120
  </div>
123
  </div>
124
  </div>
125
  </div>
126
+ <?php if ( wp_defender()->changeFooter ): ?>
127
  <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
128
  <?php else: ?>
129
  <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
app/module/hardener/view/rules/db-prefix.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  $checked = $controller->check();
3
  global $wpdb;
4
- $prefix = uniqid();
5
  ?>
6
  <div id="db_prefix" class="sui-accordion-item <?php echo $controller->getCssClass() ?>">
7
  <div class="sui-accordion-item-header">
@@ -20,10 +20,10 @@ $prefix = uniqid();
20
  <div class="sui-box">
21
  <div class="sui-box-body">
22
  <strong>
23
- <?php _e( "Overview", "defender-security" ) ?>
24
  </strong>
25
  <p>
26
- <?php _e( "When you first install WordPress on a new database, the default settings start with wp_ as the prefix to anything that gets stored in the tables. This makes it easier for hackers to perform SQL injection attacks if they find a code vulnerability. ", "defender-security" ) ?>
27
  </p>
28
  <?php if ( $checked ): ?>
29
  <div class="sui-notice sui-notice-success">
@@ -50,21 +50,22 @@ $prefix = uniqid();
50
  <div class="sui-border-frame">
51
  <div class="sui-form-field ">
52
  <label class="sui-label"><?php _e( "New database prefix", "defender-security" ) ?></label>
53
- <input type="text" value="<?php echo $prefix ?>" name="dbprefix" id="dbprefix" class="sui-form-control"/>
 
54
  </div>
55
  </div>
56
  <?php endif; ?>
57
  </div>
58
  <div class="sui-box-footer">
59
  <?php if ( $checked ): ?>
60
- <!-- <form method="post" class="hardener-frm rule-process">-->
61
- <!-- --><?php //$controller->createNonceField(); ?>
62
- <!-- <input type="hidden" name="action" value="processRevert"/>-->
63
- <!-- <input type="hidden" name="slug" value="--><?php //echo $controller::$slug ?><!--"/>-->
64
- <!-- <button class="sui-button" type="submit">-->
65
- <!-- <i class="sui-icon-undo" aria-hidden="true"></i>-->
66
- <!-- --><?php //_e( "Revert", "defender-security" ) ?><!--</button>-->
67
- <!-- </form>-->
68
  <?php else: ?>
69
  <div class="sui-actions-left">
70
  <?php $controller->showIgnoreForm() ?>
1
  <?php
2
  $checked = $controller->check();
3
  global $wpdb;
4
+ $prefix = 'wp_' . uniqid();
5
  ?>
6
  <div id="db_prefix" class="sui-accordion-item <?php echo $controller->getCssClass() ?>">
7
  <div class="sui-accordion-item-header">
20
  <div class="sui-box">
21
  <div class="sui-box-body">
22
  <strong>
23
+ <?php _e( "Overview", "defender-security" ) ?>
24
  </strong>
25
  <p>
26
+ <?php _e( "When you first install WordPress on a new database, the default settings start with wp_ as the prefix to anything that gets stored in the tables. This makes it easier for hackers to perform SQL injection attacks if they find a code vulnerability. ", "defender-security" ) ?>
27
  </p>
28
  <?php if ( $checked ): ?>
29
  <div class="sui-notice sui-notice-success">
50
  <div class="sui-border-frame">
51
  <div class="sui-form-field ">
52
  <label class="sui-label"><?php _e( "New database prefix", "defender-security" ) ?></label>
53
+ <input type="text" value="<?php echo $prefix ?>" name="dbprefix" id="dbprefix"
54
+ class="sui-form-control"/>
55
  </div>
56
  </div>
57
  <?php endif; ?>
58
  </div>
59
  <div class="sui-box-footer">
60
  <?php if ( $checked ): ?>
61
+ <!-- <form method="post" class="hardener-frm rule-process">-->
62
+ <!-- --><?php //$controller->createNonceField(); ?>
63
+ <!-- <input type="hidden" name="action" value="processRevert"/>-->
64
+ <!-- <input type="hidden" name="slug" value="--><?php //echo $controller::$slug ?><!--"/>-->
65
+ <!-- <button class="sui-button" type="submit">-->
66
+ <!-- <i class="sui-icon-undo" aria-hidden="true"></i>-->
67
+ <!-- --><?php //_e( "Revert", "defender-security" ) ?><!--</button>-->
68
+ <!-- </form>-->
69
  <?php else: ?>
70
  <div class="sui-actions-left">
71
  <?php $controller->showIgnoreForm() ?>
app/module/hardener/view/rules/hide-error.php CHANGED
@@ -57,27 +57,29 @@ $checked = $controller->check();
57
  </p>
58
  <?php endif; ?>
59
  </div>
60
- <?php if ( WP_DEBUG == true && ( ! defined( 'WP_DEBUG_DISPLAY' ) || WP_DEBUG_DISPLAY != false ) ): ?>
61
- <div class="sui-box-footer">
62
- <div class="sui-actions-left">
63
- <?php $controller->showIgnoreForm() ?>
64
- </div>
65
- <div class="sui-actions-right">
66
- <form method="post" class="hardener-frm rule-process hardener-frm-process-xml-rpc">
67
- <?php $controller->createNonceField(); ?>
68
- <input type="hidden" name="action" value="processHardener"/>
69
- <input type="hidden" name="slug" value="<?php echo $controller::$slug ?>"/>
70
- <button class="sui-button sui-button-blue" type="submit">
71
- <?php _e( "Disable error debugging", "defender-security" ) ?></button>
72
- </form>
 
 
73
  </div>
74
- </div>
75
- <?php else: ?>
76
- <div class="sui-box-footer">
77
- <div class="sui-actions-left">
78
- <?php $controller->showIgnoreForm() ?>
79
  </div>
80
- </div>
81
  <?php endif; ?>
82
  </div>
83
  </div>
57
  </p>
58
  <?php endif; ?>
59
  </div>
60
+ <?php if ( !$checked ): ?>
61
+ <?php if ( WP_DEBUG == true && ( ! defined( 'WP_DEBUG_DISPLAY' ) || WP_DEBUG_DISPLAY != false ) ): ?>
62
+ <div class="sui-box-footer">
63
+ <div class="sui-actions-left">
64
+ <?php $controller->showIgnoreForm() ?>
65
+ </div>
66
+ <div class="sui-actions-right">
67
+ <form method="post" class="hardener-frm rule-process hardener-frm-process-xml-rpc">
68
+ <?php $controller->createNonceField(); ?>
69
+ <input type="hidden" name="action" value="processHardener"/>
70
+ <input type="hidden" name="slug" value="<?php echo $controller::$slug ?>"/>
71
+ <button class="sui-button sui-button-blue" type="submit">
72
+ <?php _e( "Disable error debugging", "defender-security" ) ?></button>
73
+ </form>
74
+ </div>
75
  </div>
76
+ <?php else: ?>
77
+ <div class="sui-box-footer">
78
+ <div class="sui-actions-left">
79
+ <?php $controller->showIgnoreForm() ?>
80
+ </div>
81
  </div>
82
+ <?php endif; ?>
83
  <?php endif; ?>
84
  </div>
85
  </div>
app/module/hardener/view/rules/prevent-php-executed.php CHANGED
@@ -48,7 +48,7 @@ $checked = $controller->check();
48
  <?php if ( $checked ): ?>
49
  <div class="sui-notice sui-notice-success">
50
  <p>
51
- <?php _e( "You've automatically disabled PHP execution..", "defender-security" ) ?>
52
  </p>
53
  </div>
54
  <?php else: ?>
@@ -105,11 +105,27 @@ $checked = $controller->check();
105
  </div>
106
  <?php endif; ?>
107
  </div>
108
- <div class="sui-box-footer">
109
- <div class="sui-actions-left">
110
- <?php $controller->showIgnoreForm() ?>
 
 
111
  </div>
112
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  </div>
114
  </div>
115
  </div>
48
  <?php if ( $checked ): ?>
49
  <div class="sui-notice sui-notice-success">
50
  <p>
51
+ <?php _e( "You've automatically disabled PHP execution..", "defender-security" ) ?>
52
  </p>
53
  </div>
54
  <?php else: ?>
105
  </div>
106
  <?php endif; ?>
107
  </div>
108
+ <?php if ( ! $checked ): ?>
109
+ <div class="sui-box-footer">
110
+ <div class="sui-actions-left">
111
+ <?php $controller->showIgnoreForm() ?>
112
+ </div>
113
  </div>
114
+ <?php else: ?>
115
+ <?php if ( $setting->active_server == 'apache' || $setting->active_server == 'lite_speed' ): ?>
116
+ <div class="sui-box-footer">
117
+ <div class="sui-actions-left">
118
+ <form method="post" class="hardener-frm rule-process">
119
+ <?php $controller->createNonceField(); ?>
120
+ <input type="hidden" name="action" value="processRevert"/>
121
+ <input type="hidden" name="slug" value="<?php echo $controller::$slug ?>"/>
122
+ <button class="sui-button sui-button-gray"
123
+ type="submit"><?php _e( "Revert", "defender-security" ) ?></button>
124
+ </form>
125
+ </div>
126
+ </div>
127
+ <?php endif; ?>
128
+ <?php endif; ?>
129
  </div>
130
  </div>
131
  </div>
app/module/hardener/view/rules/protect-information.php CHANGED
@@ -95,11 +95,27 @@ if ( $is_nginx ) {
95
  </div>
96
  <?php endif; ?>
97
  </div>
98
- <div class="sui-box-footer">
99
- <div class="sui-actions-left">
100
- <?php $controller->showIgnoreForm() ?>
 
 
101
  </div>
102
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  </div>
104
  </div>
105
  </div>
95
  </div>
96
  <?php endif; ?>
97
  </div>
98
+ <?php if ( ! $checked ): ?>
99
+ <div class="sui-box-footer">
100
+ <div class="sui-actions-left">
101
+ <?php $controller->showIgnoreForm() ?>
102
+ </div>
103
  </div>
104
+ <?php else: ?>
105
+ <?php if ( $setting->active_server == 'apache' || $setting->active_server == 'lite_speed' ): ?>
106
+ <div class="sui-box-footer">
107
+ <div class="sui-actions-left">
108
+ <form method="post" class="hardener-frm rule-process">
109
+ <?php $controller->createNonceField(); ?>
110
+ <input type="hidden" name="action" value="processRevert"/>
111
+ <input type="hidden" name="slug" value="<?php echo $controller::$slug ?>"/>
112
+ <button class="sui-button sui-button-gray"
113
+ type="submit"><?php _e( "Revert", "defender-security" ) ?></button>
114
+ </form>
115
+ </div>
116
+ </div>
117
+ <?php endif; ?>
118
+ <?php endif; ?>
119
  </div>
120
  </div>
121
  </div>
app/module/hardener/view/rules/wp-version.php CHANGED
@@ -56,17 +56,19 @@ $checked = $controller->check();
56
  </p>
57
  <?php endif; ?>
58
  </div>
59
- <div class="sui-box-footer">
60
- <div class="sui-actions-left">
61
- <?php $controller->showIgnoreForm() ?>
62
- </div>
63
- <div class="sui-actions-right">
64
- <a href="<?php echo network_admin_url( 'update-core.php' ) ?>"
65
- class="sui-button sui-button-ghost">
66
- <?php esc_html_e( "Update WordPress", "defender-security" ) ?>
67
- </a>
 
 
68
  </div>
69
- </div>
70
  </div>
71
  </div>
72
  </div>
56
  </p>
57
  <?php endif; ?>
58
  </div>
59
+ <?php if ( ! $checked ): ?>
60
+ <div class="sui-box-footer">
61
+ <div class="sui-actions-left">
62
+ <?php $controller->showIgnoreForm() ?>
63
+ </div>
64
+ <div class="sui-actions-right">
65
+ <a href="<?php echo network_admin_url( 'update-core.php' ) ?>"
66
+ class="sui-button sui-button-ghost">
67
+ <?php esc_html_e( "Update WordPress", "defender-security" ) ?>
68
+ </a>
69
+ </div>
70
  </div>
71
+ <?php endif; ?>
72
  </div>
73
  </div>
74
  </div>
app/module/ip-lockout/component/login-protection-api.php CHANGED
@@ -56,7 +56,7 @@ class Login_Protection_Api extends Component {
56
  $model->attempt = $attempt;
57
  if ( $model->attempt >= $settings->login_protection_login_attempt || $force == true ) {
58
  $model->status = IP_Model::STATUS_BLOCKED;
59
- $model->release_time = strtotime( '+ ' . $settings->login_protection_lockout_duration . ' seconds' );
60
  if ( $blacklist && $force ) {
61
  $model->lockout_message = esc_html__( "You have been locked out by the administrator for attempting to login with a banned username", "defender-security" );
62
  } else {
@@ -143,7 +143,7 @@ class Login_Protection_Api extends Component {
143
  if ( count( $logs ) >= $settings->detect_404_threshold ) {
144
  //we need to check the extension
145
  $model->status = IP_Model::STATUS_BLOCKED;
146
- $model->release_time = strtotime( '+ ' . $settings->detect_404_lockout_duration . ' seconds' );
147
  $model->lockout_message = $settings->detect_404_lockout_message;
148
  $model->lock_time_404 = time();
149
  $model->save();
@@ -168,8 +168,8 @@ class Login_Protection_Api extends Component {
168
  /**
169
  * @param null $time - unix timestamp
170
  *
171
- * @deprecated
172
  * @return int
 
173
  */
174
  public static function get404Lockouts( $time = null ) {
175
  $logs = Log_Model::count( array(
@@ -186,8 +186,8 @@ class Login_Protection_Api extends Component {
186
  /**
187
  * @param null $time - unix timestamp
188
  *
189
- * @deprecated
190
  * @return int
 
191
  */
192
  public static function getLoginLockouts( $time = null ) {
193
  $logs = Log_Model::count( array(
@@ -204,8 +204,8 @@ class Login_Protection_Api extends Component {
204
  /**
205
  * @param null $time - unix timestamp
206
  *
207
- * @deprecated
208
  * @return int
 
209
  */
210
  public static function getAllLockouts( $time = null ) {
211
  $logs = Log_Model::count( array(
56
  $model->attempt = $attempt;
57
  if ( $model->attempt >= $settings->login_protection_login_attempt || $force == true ) {
58
  $model->status = IP_Model::STATUS_BLOCKED;
59
+ $model->release_time = strtotime( '+ ' . $settings->login_protection_lockout_duration . ' ' . $settings->login_protection_lockout_duration_unit );
60
  if ( $blacklist && $force ) {
61
  $model->lockout_message = esc_html__( "You have been locked out by the administrator for attempting to login with a banned username", "defender-security" );
62
  } else {
143
  if ( count( $logs ) >= $settings->detect_404_threshold ) {
144
  //we need to check the extension
145
  $model->status = IP_Model::STATUS_BLOCKED;
146
+ $model->release_time = strtotime( '+ ' . $settings->detect_404_lockout_duration . ' ' . $settings->detect_404_lockout_duration_unit );
147
  $model->lockout_message = $settings->detect_404_lockout_message;
148
  $model->lock_time_404 = time();
149
  $model->save();
168
  /**
169
  * @param null $time - unix timestamp
170
  *
 
171
  * @return int
172
+ * @deprecated
173
  */
174
  public static function get404Lockouts( $time = null ) {
175
  $logs = Log_Model::count( array(
186
  /**
187
  * @param null $time - unix timestamp
188
  *
 
189
  * @return int
190
+ * @deprecated
191
  */
192
  public static function getLoginLockouts( $time = null ) {
193
  $logs = Log_Model::count( array(
204
  /**
205
  * @param null $time - unix timestamp
206
  *
 
207
  * @return int
208
+ * @deprecated
209
  */
210
  public static function getAllLockouts( $time = null ) {
211
  $logs = Log_Model::count( array(
app/module/ip-lockout/controller/main.php CHANGED
@@ -310,6 +310,7 @@ class Main extends Controller {
310
  * Determine if an ip get lockout or not
311
  */
312
  public function maybeLockouts() {
 
313
  $settings = Settings::instance();
314
  $isTest = HTTP_Helper::retrieve_get( 'def-lockout-demo', false ) == 1;
315
  if ( $isTest ) {
@@ -618,7 +619,7 @@ class Main extends Controller {
618
  $ext = trim( $ext );
619
  $model = new Log_Model();
620
  $model->ip = $this->getUserIp();
621
- $model->user_agent = $_SERVER['HTTP_USER_AGENT'];
622
  $model->log = esc_url( $uri );
623
  $model->date = time();
624
  if ( strlen( $ext ) > 0 && in_array( $ext, $settings->get404Ignorelist() ) ) {
@@ -667,7 +668,7 @@ class Main extends Controller {
667
  public function recordFailLogin( $username ) {
668
  $model = new Log_Model();
669
  $model->ip = $this->getUserIp();
670
- $model->user_agent = $_SERVER['HTTP_USER_AGENT'];
671
  $model->log = sprintf( esc_html__( "Failed login attempt with username %s", "defender-security" ), $username );
672
  $model->date = time();
673
  $model->type = 'auth_fail';
310
  * Determine if an ip get lockout or not
311
  */
312
  public function maybeLockouts() {
313
+ do_action('wd_before_lockout');
314
  $settings = Settings::instance();
315
  $isTest = HTTP_Helper::retrieve_get( 'def-lockout-demo', false ) == 1;
316
  if ( $isTest ) {
619
  $ext = trim( $ext );
620
  $model = new Log_Model();
621
  $model->ip = $this->getUserIp();
622
+ $model->user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null;
623
  $model->log = esc_url( $uri );
624
  $model->date = time();
625
  if ( strlen( $ext ) > 0 && in_array( $ext, $settings->get404Ignorelist() ) ) {
668
  public function recordFailLogin( $username ) {
669
  $model = new Log_Model();
670
  $model->ip = $this->getUserIp();
671
+ $model->user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null;
672
  $model->log = sprintf( esc_html__( "Failed login attempt with username %s", "defender-security" ), $username );
673
  $model->date = time();
674
  $model->type = 'auth_fail';
app/module/ip-lockout/view/blacklist/enabled.php CHANGED
@@ -15,30 +15,33 @@
15
  <?php _e( "IP Addresses", "defender-security" ) ?>
16
  </span>
17
  <span class="sui-description">
18
- <?php _e( "Add IP addresses you want to permanently ban from, or always allow access to your website.", "defender-security" ) ?>
19
  </span>
20
  </div>
21
  <div class="sui-box-settings-col-2">
22
  <strong><?php _e( "Blacklist", "defender-security" ) ?></strong>
23
  <p class="sui-description">
24
- <?php _e( "Any IPs addresses you list here will be completely blocked from accessing your website, including admins.", "defender-security" ) ?>
25
  </p>
26
  <div class="sui-border-frame">
27
  <label class="sui-label"><?php _e( "Banned IPs", "defender-security" ) ?></label>
28
  <textarea class="sui-form-control"
29
  id="ip_blacklist" name="ip_blacklist"
30
- placeholder="<?php esc_attr_e( "Add blacklisted IPs here, one per line", "defender-security" ) ?>"
31
  rows="8"><?php echo $settings->ip_blacklist ?></textarea>
32
  <span class="sui-description">
33
  <?php _e( "Both IPv4 and IPv6 are supported. IP ranges are also accepted in format xxx.xxx.xxx.xxx-xxx.xxx.xxx.xxx.", "defender-security" ) ?>
34
  </span>
35
  </div>
36
  <strong><?php _e( "Whitelist", "defender-security" ) ?></strong>
 
 
 
37
  <div class="sui-border-frame">
38
  <label class="sui-label"><?php _e( "Allowed IPs", "defender-security" ) ?></label>
39
  <textarea class="sui-form-control"
40
  id="ip_whitelist" name="ip_whitelist"
41
- placeholder="<?php esc_attr_e( "Add whitelisted IPs here, one per line", "defender-security" ) ?>"
42
  rows="8"><?php echo $settings->ip_whitelist ?></textarea>
43
  <span class="sui-description">
44
  <?php _e( "One IP address per line. Both IPv4 and IPv6 are supported. IP ranges are also accepted in format xxx.xxx.xxx.xxx-xxx.xxx.xxx.xxx.", "defender-security" ) ?>
@@ -87,7 +90,7 @@
87
  <?php else: ?>
88
  <strong><?php _e( "Blacklist", "defender-security" ) ?></strong>
89
  <p class="sui-description no-margin-bottom">
90
- <?php _e( "Any countries you select will not being able to access any area of your website.", "defender-security" ) ?>
91
  </p>
92
  <div class="sui-border-frame">
93
  <div class="sui-control-with-icon">
15
  <?php _e( "IP Addresses", "defender-security" ) ?>
16
  </span>
17
  <span class="sui-description">
18
+ <?php _e( "Add IP addresses you want to permanently ban from, or always allow access to your website. ", "defender-security" ) ?>
19
  </span>
20
  </div>
21
  <div class="sui-box-settings-col-2">
22
  <strong><?php _e( "Blacklist", "defender-security" ) ?></strong>
23
  <p class="sui-description">
24
+ <?php _e( "Any IP addresses you list here will be completely blocked from accessing your website, including admins.", "defender-security" ) ?>
25
  </p>
26
  <div class="sui-border-frame">
27
  <label class="sui-label"><?php _e( "Banned IPs", "defender-security" ) ?></label>
28
  <textarea class="sui-form-control"
29
  id="ip_blacklist" name="ip_blacklist"
30
+ placeholder="<?php esc_attr_e( "Add IP addresses here, one per line", "defender-security" ) ?>"
31
  rows="8"><?php echo $settings->ip_blacklist ?></textarea>
32
  <span class="sui-description">
33
  <?php _e( "Both IPv4 and IPv6 are supported. IP ranges are also accepted in format xxx.xxx.xxx.xxx-xxx.xxx.xxx.xxx.", "defender-security" ) ?>
34
  </span>
35
  </div>
36
  <strong><?php _e( "Whitelist", "defender-security" ) ?></strong>
37
+ <p class="sui-description">
38
+ <?php _e( "Any IP addresses you list here will be exempt any existing or new ban rules outlined in login protection, 404 detection or IP ban lists.", "defender-security" ) ?>
39
+ </p>
40
  <div class="sui-border-frame">
41
  <label class="sui-label"><?php _e( "Allowed IPs", "defender-security" ) ?></label>
42
  <textarea class="sui-form-control"
43
  id="ip_whitelist" name="ip_whitelist"
44
+ placeholder="<?php esc_attr_e( "Add IP addresses here, one per line", "defender-security" ) ?>"
45
  rows="8"><?php echo $settings->ip_whitelist ?></textarea>
46
  <span class="sui-description">
47
  <?php _e( "One IP address per line. Both IPv4 and IPv6 are supported. IP ranges are also accepted in format xxx.xxx.xxx.xxx-xxx.xxx.xxx.xxx.", "defender-security" ) ?>
90
  <?php else: ?>
91
  <strong><?php _e( "Blacklist", "defender-security" ) ?></strong>
92
  <p class="sui-description no-margin-bottom">
93
+ <?php _e( "Any countries you select will not be able to access any area of your website.", "defender-security" ) ?>
94
  </p>
95
  <div class="sui-border-frame">
96
  <div class="sui-control-with-icon">
app/module/ip-lockout/view/detect-404/enabled.php CHANGED
@@ -61,9 +61,6 @@
61
  </div>
62
  <div data-panes>
63
  <div class="sui-tab-boxed <?php echo $settings->detect_404_lockout_ban == 0 ? 'active' : null ?>">
64
- <p class="sui-description">
65
- <?php _e( "Choose a timeframe to temporarily lock out blocked the IP for.", "defender-security" ) ?>
66
- </p>
67
  <div class="sui-row">
68
  <div class="sui-col-md-3">
69
  <input value="<?php echo $settings->detect_404_lockout_duration ?>" size="8"
@@ -157,8 +154,8 @@
157
  </div>
158
  <div class="sui-box-settings-col-2">
159
  <div class="sui-form-field">
 
160
  <label class="sui-toggle">
161
- <input type="hidden" name="detect_404_logged" value="0"/>
162
  <input id="detect_404_logged" <?php checked( 1, $settings->detect_404_logged ) ?>
163
  type="checkbox"
164
  name="detect_404_logged" value="1">
61
  </div>
62
  <div data-panes>
63
  <div class="sui-tab-boxed <?php echo $settings->detect_404_lockout_ban == 0 ? 'active' : null ?>">
 
 
 
64
  <div class="sui-row">
65
  <div class="sui-col-md-3">
66
  <input value="<?php echo $settings->detect_404_lockout_duration ?>" size="8"
154
  </div>
155
  <div class="sui-box-settings-col-2">
156
  <div class="sui-form-field">
157
+ <input type="hidden" name="detect_404_logged" value="0"/>
158
  <label class="sui-toggle">
 
159
  <input id="detect_404_logged" <?php checked( 1, $settings->detect_404_logged ) ?>
160
  type="checkbox"
161
  name="detect_404_logged" value="1">
app/module/ip-lockout/view/layouts/layout.php CHANGED
@@ -3,15 +3,16 @@
3
  <div class="iplockout">
4
  <div class="sui-header">
5
  <h1 class="sui-header-title"><?php _e( "IP Lockout", "defender-security" ) ?></h1>
6
- <?php if ( wp_defender()->hideDocLinks === false ): ?>
7
  <div class="sui-actions-right">
8
  <div class="sui-actions-right">
9
- <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/#ip-lockouts" target="_blank" class="sui-button sui-button-ghost">
 
10
  <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
11
  </a>
12
  </div>
13
  </div>
14
- <?php endif; ?>
15
  </div>
16
  <div class="sui-box sui-summary <?php echo \WP_Defender\Behavior\Utils::instance()->getSummaryClass() ?>"
17
  id="lockoutSummary">
@@ -92,7 +93,7 @@
92
  <?php echo $contents ?>
93
  </div>
94
  </div>
95
- <?php if ( wp_defender()->changeFooter && ! empty( wp_defender()->footerText ) ): ?>
96
  <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
97
  <?php else: ?>
98
  <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
3
  <div class="iplockout">
4
  <div class="sui-header">
5
  <h1 class="sui-header-title"><?php _e( "IP Lockout", "defender-security" ) ?></h1>
6
+ <?php if ( wp_defender()->hideDocLinks === false ): ?>
7
  <div class="sui-actions-right">
8
  <div class="sui-actions-right">
9
+ <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/#ip-lockouts"
10
+ target="_blank" class="sui-button sui-button-ghost">
11
  <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
12
  </a>
13
  </div>
14
  </div>
15
+ <?php endif; ?>
16
  </div>
17
  <div class="sui-box sui-summary <?php echo \WP_Defender\Behavior\Utils::instance()->getSummaryClass() ?>"
18
  id="lockoutSummary">
93
  <?php echo $contents ?>
94
  </div>
95
  </div>
96
+ <?php if ( wp_defender()->changeFooter ): ?>
97
  <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
98
  <?php else: ?>
99
  <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
app/module/ip-lockout/view/locked.php CHANGED
@@ -67,8 +67,10 @@
67
  <body>
68
  <div class="wp-defender">
69
  <div class="container">
70
- <div class="image">
71
- </div>
 
 
72
  <p><?php echo $message ?></p>
73
  </div>
74
  <div class="powered"><?php esc_html_e( "Powered by", "defender-security" ) ?>
67
  <body>
68
  <div class="wp-defender">
69
  <div class="container">
70
+ <?php if ( strlen( wp_defender()->heroImage ) == 0 ): ?>
71
+ <div class="image">
72
+ </div>
73
+ <?php endif; ?>
74
  <p><?php echo $message ?></p>
75
  </div>
76
  <div class="powered"><?php esc_html_e( "Powered by", "defender-security" ) ?>
app/module/ip-lockout/view/login-lockouts/enabled.php CHANGED
@@ -67,9 +67,6 @@
67
  </div>
68
  <div data-panes>
69
  <div class="sui-tab-boxed <?php echo $settings->login_protection_lockout_ban == 0 ? 'active' : null ?>">
70
- <p class="sui-description">
71
- <?php _e( "Choose a timeframe to temporarily lock out blocked the IP for.", "defender-security" ) ?>
72
- </p>
73
  <div class="sui-row">
74
  <div class="sui-col-md-3">
75
  <input value="<?php echo $settings->login_protection_lockout_duration ?>"
67
  </div>
68
  <div data-panes>
69
  <div class="sui-tab-boxed <?php echo $settings->login_protection_lockout_ban == 0 ? 'active' : null ?>">
 
 
 
70
  <div class="sui-row">
71
  <div class="sui-col-md-3">
72
  <input value="<?php echo $settings->login_protection_lockout_duration ?>"
app/module/ip-lockout/view/notification/enabled.php CHANGED
@@ -16,8 +16,8 @@
16
 
17
  <div class="sui-box-settings-col-2">
18
  <div class="sui-form-field">
 
19
  <label class="sui-toggle">
20
- <input type="hidden" name="login_lockout_notification" value="0"/>
21
  <input role="presentation" type="checkbox" name="login_lockout_notification"
22
  class="toggle-checkbox"
23
  id="login_lockout_notification" value="1"
@@ -32,8 +32,8 @@
32
  </p>
33
  </div>
34
  <div class="sui-form-field">
 
35
  <label class="sui-toggle">
36
- <input type="hidden" name="ip_lockout_notification" value="0"/>
37
  <input role="presentation" type="checkbox" name="ip_lockout_notification"
38
  class="toggle-checkbox"
39
  id="ip_lockout_notification" value="1"
@@ -74,15 +74,15 @@
74
  </div>
75
 
76
  <div class="sui-box-settings-col-2">
 
77
  <label class="sui-toggle">
78
- <input type="hidden" name="cooldown_enabled" value="0"/>
79
  <input role="presentation" type="checkbox" name="cooldown_enabled"
80
  class="toggle-checkbox"
81
  id="cooldown_enabled" value="1"
82
  <?php checked( true, $settings->cooldown_enabled ) ?>/>
83
  <span class="sui-toggle-slider"></span>
84
  </label>
85
- <label for="ip_lockout_notification" class="sui-toggle-label">
86
  <?php esc_html_e( "Limit email notifications for repeat lockouts", "defender-security" ) ?>
87
  </label>
88
  <div class="sui-border-frame sui-toggle-content">
16
 
17
  <div class="sui-box-settings-col-2">
18
  <div class="sui-form-field">
19
+ <input type="hidden" name="login_lockout_notification" value="0"/>
20
  <label class="sui-toggle">
 
21
  <input role="presentation" type="checkbox" name="login_lockout_notification"
22
  class="toggle-checkbox"
23
  id="login_lockout_notification" value="1"
32
  </p>
33
  </div>
34
  <div class="sui-form-field">
35
+ <input type="hidden" name="ip_lockout_notification" value="0"/>
36
  <label class="sui-toggle">
 
37
  <input role="presentation" type="checkbox" name="ip_lockout_notification"
38
  class="toggle-checkbox"
39
  id="ip_lockout_notification" value="1"
74
  </div>
75
 
76
  <div class="sui-box-settings-col-2">
77
+ <input type="hidden" name="cooldown_enabled" value="0"/>
78
  <label class="sui-toggle">
 
79
  <input role="presentation" type="checkbox" name="cooldown_enabled"
80
  class="toggle-checkbox"
81
  id="cooldown_enabled" value="1"
82
  <?php checked( true, $settings->cooldown_enabled ) ?>/>
83
  <span class="sui-toggle-slider"></span>
84
  </label>
85
+ <label for="cooldown_enabled" class="sui-toggle-label">
86
  <?php esc_html_e( "Limit email notifications for repeat lockouts", "defender-security" ) ?>
87
  </label>
88
  <div class="sui-border-frame sui-toggle-content">
app/module/ip-lockout/view/notification/report.php CHANGED
@@ -18,15 +18,15 @@
18
 
19
  <div class="sui-box-settings-col-2">
20
  <div class="sui-form-field">
 
21
  <label class="sui-toggle">
22
- <input type="hidden" name="report" value="0"/>
23
  <input role="presentation" type="checkbox" name="report"
24
  class="toggle-checkbox"
25
  id="report" value="1"
26
  <?php checked( true, $settings->report ) ?>/>
27
  <span class="sui-toggle-slider"></span>
28
  </label>
29
- <label for="login_lockout_notification" class="sui-toggle-label">
30
  <?php esc_html_e( "Send regular email report", "defender-security" ) ?>
31
  </label>
32
  <div class="sui-border-frame sui-toggle-content">
18
 
19
  <div class="sui-box-settings-col-2">
20
  <div class="sui-form-field">
21
+ <input type="hidden" name="report" value="0"/>
22
  <label class="sui-toggle">
 
23
  <input role="presentation" type="checkbox" name="report"
24
  class="toggle-checkbox"
25
  id="report" value="1"
26
  <?php checked( true, $settings->report ) ?>/>
27
  <span class="sui-toggle-slider"></span>
28
  </label>
29
+ <label for="report" class="sui-toggle-label">
30
  <?php esc_html_e( "Send regular email report", "defender-security" ) ?>
31
  </label>
32
  <div class="sui-border-frame sui-toggle-content">
app/module/scan/behavior/scan.php DELETED
@@ -1,266 +0,0 @@
1
- <?php
2
- /**
3
- * Author: Hoang Ngo
4
- */
5
-
6
- namespace WP_Defender\Module\Scan\Behavior;
7
-
8
- use Hammer\Base\Behavior;
9
- use WP_Defender\Behavior\Utils;
10
- use WP_Defender\Module\Scan\Component\Scan_Api;
11
- use WP_Defender\Module\Scan\Model\Result_Item;
12
- use WP_Defender\Module\Scan\Model\Settings;
13
-
14
- class Scan extends Behavior {
15
- private $lastScan;
16
- private $activeScan;
17
- private $settled = false;
18
- private $countAll;
19
-
20
- private function pullStatus() {
21
- if ( $this->settled == false ) {
22
- $this->activeScan = Scan_Api::getActiveScan();
23
- $this->lastScan = Scan_Api::getLastScan();
24
- $this->countAll = is_object( $this->lastScan ) ? $this->lastScan->countAll( Result_Item::STATUS_ISSUE ) : 0;
25
- $this->settled = true;
26
- }
27
- }
28
-
29
- public function renderScanWidget() {
30
- $this->pullStatus();
31
-
32
- ?>
33
- <div class="sui-box">
34
- <div class="sui-box-header">
35
- <h3 class="sui-box-title">
36
- <i class="sui-icon-layers" aria-hidden="true"></i>
37
- <?php _e("File Scanning") ?>
38
- </h3>
39
- <?php if($this->countAll > 0):?>
40
- <div class="sui-actions-left">
41
- <span class="sui-tag sui-tag-error">
42
- <?php echo $this->countAll; ?>
43
- </span>
44
- </div>
45
- <?php endif; ?>
46
- </div>
47
- <?php
48
- $activeScan = $this->activeScan;
49
- $lastScan = $this->lastScan;
50
- if ( ! is_object( $activeScan ) && ! is_object( $lastScan ) ) {
51
- echo $this->_renderNewScan();
52
- } elseif ( is_object( $activeScan ) && $activeScan->status != \WP_Defender\Module\Scan\Model\Scan::STATUS_ERROR ) {
53
- echo $this->_renderScanning( $activeScan );
54
- } elseif ( is_object( $activeScan ) && $activeScan->status == \WP_Defender\Module\Scan\Model\Scan::STATUS_ERROR ) {
55
-
56
- } else {
57
- echo $this->_renderResult( $lastScan );
58
- }
59
- ?>
60
- <!-- <div class="sui-box-body">-->
61
- <!-- --><?php
62
- // $activeScan = $this->activeScan;
63
- // $lastScan = $this->lastScan;
64
- // if ( ! is_object( $activeScan ) && ! is_object( $lastScan ) ) {
65
- // echo $this->_renderNewScan();
66
- // } elseif ( is_object( $activeScan ) && $activeScan->status != \WP_Defender\Module\Scan\Model\Scan::STATUS_ERROR ) {
67
- // echo $this->_renderScanning( $activeScan );
68
- // } elseif ( is_object( $activeScan ) && $activeScan->status == \WP_Defender\Module\Scan\Model\Scan::STATUS_ERROR ) {
69
- //
70
- // } else {
71
- // echo $this->_renderResult( $lastScan );
72
- // }
73
- // ?>
74
- <!-- </div>-->
75
- </div>
76
- <?php
77
- }
78
-
79
- public function renderScanStatusText() {
80
- $this->pullStatus();
81
- $activeScan = $this->activeScan;
82
- $lastScan = $this->lastScan;
83
- if ( ! is_object( $activeScan ) && ! is_object( $lastScan ) ) {
84
- ?>
85
- <form id="start-a-scan" method="post" class="scan-frm">
86
- <?php
87
- wp_nonce_field( 'startAScan' );
88
- ?>
89
- <input type="hidden" name="action" value="startAScan"/>
90
- <button type="submit"
91
- class="button button-small"><?php _e( "RUN SCAN", "defender-security" ) ?></button>
92
- </form>
93
- <?php
94
- } elseif ( is_object( $activeScan ) && $activeScan->status != \WP_Defender\Module\Scan\Model\Scan::STATUS_ERROR ) {
95
- ?>
96
- <img src="<?php echo wp_defender()->getPluginUrl() ?>assets/img/loading.gif" width="18"
97
- height="18"/> <?php _e( "Scanning…", "defender-security" ) ?>
98
- <?php
99
- } elseif ( is_object( $activeScan ) && $activeScan->status == \WP_Defender\Module\Scan\Model\Scan::STATUS_ERROR ) {
100
- echo $this->activeScan->statusText;
101
- } else {
102
- ?>
103
- <?php
104
- if ( $this->countAll == 0 ): ?>
105
- <span class="def-tag tag-success">
106
- <?php else:
107
- ?>
108
- <span class="def-tag tag-error">
109
- <?php endif;
110
- echo $this->countAll;
111
- ?>
112
- </span>
113
- <?php
114
- }
115
- }
116
-
117
- private function _renderResult(\WP_Defender\Module\Scan\Model\Scan $model){
118
- ob_start();
119
- ?>
120
- <div class="sui-box-body no-padding-bottom">
121
- <p>
122
- <?php _e( "Scan your website for file changes, vulnerabilities and injected code and get and get notified about anything suspicious.", "defender-security" ) ?>
123
- </p>
124
- <?php
125
- if ( $this->countAll == 0 ) {
126
- ?>
127
- <div class="sui-notice sui-notice-success">
128
- <p><?php _e( "Your code is clean, the skies are clear.", "defender-security" ) ?></p>
129
- </div>
130
- <?php
131
- } else {
132
- ?>
133
- <div class="sui-field-list sui-flushed no-border">
134
- <div class="sui-field-list-body">
135
- <div class="sui-field-list-item">
136
- <label class="sui-field-list-item-label">
137
- <?php _e( "WordPress Core", "defender-security" ) ?>
138
- </label>
139
- <?php echo $model->getCount( 'core' ) == 0 ? ' <i class="sui-icon-check" aria-hidden="true"></i>' : '<span class="sui-tag sui-tag-error">' . $model->getCount( 'core' ) . '</span>' ?>
140
- </div>
141
- <div class="sui-field-list-item">
142
- <label class="sui-field-list-item-label">
143
- <?php _e( "Plugins & Themes", "defender-security" ) ?>
144
- </label>
145
- <?php if ( Utils::instance()->getAPIKey() ): ?>
146
- <?php echo $model->getCount( 'vuln' ) == 0 ? ' <i class="sui-icon-check" aria-hidden="true"></i>' : '<span class="sui-tag sui-tag-error">' . $model->getCount( 'vuln' ) . '</span>' ?>
147
- <?php else: ?>
148
- <a href="<?php echo Utils::instance()->campaignURL('defender_dash_filescan_pro_tag') ?>" target="_blank" class="sui-button sui-button-purple"
149
- data-tooltip="<?php esc_attr_e( "Try Defender Pro free today", "defender-security" ) ?>">
150
- <?php _e( "Pro Feature", "defender-security" ) ?>
151
- </a>
152
- <?php endif; ?>
153
- </div>
154
- <div class="sui-field-list-item">
155
- <label class="sui-field-list-item-label">
156
- <?php _e( "Suspicious Code", "defender-security" ) ?>
157
- </label>
158
- <?php if ( Utils::instance()->getAPIKey() ): ?>
159
- <?php echo $model->getCount( 'content' ) == 0 ? ' <i class="sui-icon-check" aria-hidden="true"></i>' : '<span class="sui-tag sui-tag-error">' . $model->getCount( 'content' ) . '</span>' ?>
160
- <?php else: ?>
161
- <a href="<?php echo Utils::instance()->campaignURL('defender_dash_filescan_pro_tag') ?>" target="_blank" class="sui-button sui-button-purple"
162
- tooltip="<?php esc_attr_e( "Try Defender Pro free today", "defender-security" ) ?>">
163
- <?php _e( "Pro Feature", "defender-security" ) ?>
164
- </a>
165
- <?php endif; ?>
166
- </div>
167
- </div>
168
- </div>
169
- <?php
170
- }
171
- ?>
172
- </div>
173
-
174
- <div class="sui-box-footer">
175
- <div class="sui-actions-left">
176
- <a href="<?php echo network_admin_url( 'admin.php?page=wdf-scan' ) ?>"
177
- class="sui-button sui-button-ghost">
178
- <?php _e( "View Report", "defender-security" ) ?>
179
- </a>
180
- </div>
181
- <?php if(!wp_defender()->isFree): ?>
182
- <div class="sui-actions-right">
183
- <?php
184
- if ( !empty( Settings::instance()->notification ) ) {
185
- switch ( Settings::instance()->frequency ) {
186
- case '1':
187
- _e( "Automatic scans are running daily", "defender-security" );
188
- break;
189
- case '7':
190
- _e( "Automatic scans are running weekly", "defender-security" );
191
- break;
192
- case '30':
193
- _e( "Automatic scans are running monthly", "defender-security" );
194
- break;
195
- }
196
- }
197
- ?>
198
- </div>
199
- <?php endif; ?>
200
- </div>
201
- <?php
202
- return ob_get_clean();
203
- }
204
-
205
- private function _renderNewScan() {
206
- ob_start();
207
- ?>
208
- <div class="sui-box-body">
209
- <p>
210
- <?php _e( "Scan your website for file changes, vulnerabilities and injected code and get
211
- notified about anything suspicious.", "defender-security" ) ?>
212
- </p>
213
- <form id="start-a-scan" method="post" class="scan-frm">
214
- <?php
215
- wp_nonce_field( 'startAScan' );
216
- ?>
217
- <input type="hidden" name="action" value="startAScan"/>
218
- <button type="submit" class="sui-button sui-button-blue"><?php _e( "Run Scan", "defender-security" ) ?></button>
219
- </form>
220
- </div>
221
- <?php
222
- return ob_get_clean();
223
- }
224
-
225
- private function _renderScanning( $model ) {
226
- ob_start();
227
- $percent = Scan_Api::getScanProgress();
228
- ?>
229
- <div class="wdf-scanning"></div>
230
- <div class="sui-box-body">
231
- <p>
232
- <?php _e( "Defender is scanning your files for malicious code. This will take a few minutes depending on the size of your website.", "defender-security" ) ?>
233
- </p>
234
- <div class="sui-progress-block sui-progress-can-close">
235
- <div class="sui-progress">
236
- <div class="sui-progress-text sui-icon-loader sui-loading">
237
- <span><?php echo $percent ?>%</span>
238
- </div>
239
- <div class="sui-progress-bar">
240
- <span style="width: <?php echo $percent ?>%"></span>
241
- </div>
242
- <form method="post" class="scan-frm">
243
- <input type="hidden" name="action" value="cancelScan"/>
244
- <?php wp_nonce_field( 'cancelScan', '_wpnonce', true ) ?>
245
- <button class="sui-button-icon" type="submit">
246
- <i class="sui-icon-close"></i>
247
- </button>
248
- </form>
249
- </div>
250
- </div>
251
- <div class="sui-progress-state">
252
- <span class="sui-progress-state-text">
253
- <?php echo $model->statusText ?>
254
- </span>
255
- </div>
256
- </div>
257
- <form method="post" id="process-scan" class="scan-frm">
258
- <input type="hidden" name="action" value="processScan"/>
259
- <?php
260
- wp_nonce_field( 'processScan' );
261
- ?>
262
- </form>
263
- <?php
264
- return ob_get_clean();
265
- }
266
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/module/scan/component/result-table.php CHANGED
@@ -103,25 +103,29 @@ class Result_Table extends \WP_List_Table {
103
  function prepare_items() {
104
  $model = Scan_Api::getLastScan();
105
  $itemsPerPage = 40;
106
- $totalItems = $model->countAll( $this->type );
107
 
108
- $this->set_pagination_args( array(
109
- 'total_items' => $totalItems,
110
- 'total_pages' => ceil( $totalItems / $itemsPerPage ),
111
- 'per_page' => $itemsPerPage
112
- ) );
113
  $offset = ( $this->get_pagenum() - 1 ) * $itemsPerPage;
114
  $this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() );
115
  $issueType = HTTP_Helper::retrieve_get( 'type', null );
116
  if ( ! in_array( $issueType, array(
117
  'core',
118
  'vuln',
119
- 'code'
120
  ) ) ) {
121
  $issueType = null;
122
  }
123
 
124
  $this->items = $model->getItems( $offset . ',' . $itemsPerPage, $this->type, $issueType );
 
 
 
 
 
 
 
 
 
 
125
  }
126
 
127
  /**
@@ -203,8 +207,8 @@ class Result_Table extends \WP_List_Table {
203
  <input type="hidden" name="action" value="scanBulkAction"/>
204
  <?php wp_nonce_field( 'scanBulkAction' ) ?>
205
  <div class="bulk-action-bar">
206
- <label class="sui-checkbox apply-all">
207
- <input type="checkbox" id="apply-all"/>
208
  <span aria-hidden="true"></span>
209
  </label>
210
  <select name="bulk" class="sui-select-sm bulk-action">
@@ -239,10 +243,11 @@ class Result_Table extends \WP_List_Table {
239
  /**
240
  * Generates content for a single row of the table
241
  *
 
 
242
  * @since 3.1.0
243
  * @access public
244
  *
245
- * @param object $item The current item
246
  */
247
  public function single_row( $item ) {
248
  echo '<tr id="mid-' . $item->id . '" class="sui-accordion-item sui-error">';
@@ -320,9 +325,10 @@ class Result_Table extends \WP_List_Table {
320
  /**
321
  * Generates the columns for a single row of the table
322
  *
 
 
323
  * @since 3.1.0
324
  *
325
- * @param object $item The current item
326
  */
327
  protected function single_row_columns( $item ) {
328
  list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
103
  function prepare_items() {
104
  $model = Scan_Api::getLastScan();
105
  $itemsPerPage = 40;
 
106
 
 
 
 
 
 
107
  $offset = ( $this->get_pagenum() - 1 ) * $itemsPerPage;
108
  $this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() );
109
  $issueType = HTTP_Helper::retrieve_get( 'type', null );
110
  if ( ! in_array( $issueType, array(
111
  'core',
112
  'vuln',
113
+ 'content'
114
  ) ) ) {
115
  $issueType = null;
116
  }
117
 
118
  $this->items = $model->getItems( $offset . ',' . $itemsPerPage, $this->type, $issueType );
119
+ $totalItems = Result_Item::count( [
120
+ 'type' => $issueType,
121
+ 'status' => $this->type
122
+ ] );
123
+
124
+ $this->set_pagination_args( array(
125
+ 'total_items' => $totalItems,
126
+ 'total_pages' => ceil( $totalItems / $itemsPerPage ),
127
+ 'per_page' => $itemsPerPage
128
+ ) );
129
  }
130
 
131
  /**
207
  <input type="hidden" name="action" value="scanBulkAction"/>
208
  <?php wp_nonce_field( 'scanBulkAction' ) ?>
209
  <div class="bulk-action-bar">
210
+ <label class="sui-checkbox">
211
+ <input type="checkbox" class="apply-all"/>
212
  <span aria-hidden="true"></span>
213
  </label>
214
  <select name="bulk" class="sui-select-sm bulk-action">
243
  /**
244
  * Generates content for a single row of the table
245
  *
246
+ * @param object $item The current item
247
+ *
248
  * @since 3.1.0
249
  * @access public
250
  *
 
251
  */
252
  public function single_row( $item ) {
253
  echo '<tr id="mid-' . $item->id . '" class="sui-accordion-item sui-error">';
325
  /**
326
  * Generates the columns for a single row of the table
327
  *
328
+ * @param object $item The current item
329
+ *
330
  * @since 3.1.0
331
  *
 
332
  */
333
  protected function single_row_columns( $item ) {
334
  list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
app/module/scan/component/scan-api.php CHANGED
@@ -25,6 +25,8 @@ class Scan_Api extends Component {
25
 
26
  private static $ignoreList = false;
27
 
 
 
28
  /**
29
  * @return Scan|\WP_Error
30
  */
@@ -139,7 +141,7 @@ class Scan_Api extends Component {
139
  $files = File_Helper::findFiles( WP_CONTENT_DIR, true, false, array(), array(
140
  'ext' => array( 'php' )
141
  ), true, $settings->max_filesize, true );
142
- // $files = File_Helper::findFiles( ABSPATH . 'wp-content/trash/sample', true, false, array(), array(
143
  // 'ext' => array( 'php' )
144
  // ), true, $settings->max_filesize );
145
  //include wp-config.php here
25
 
26
  private static $ignoreList = false;
27
 
28
+ public static $scanResults = array();
29
+
30
  /**
31
  * @return Scan|\WP_Error
32
  */
141
  $files = File_Helper::findFiles( WP_CONTENT_DIR, true, false, array(), array(
142
  'ext' => array( 'php' )
143
  ), true, $settings->max_filesize, true );
144
+ // $files = File_Helper::findFiles( ABSPATH . 'wp-content/randomly/a', true, false, array(), array(
145
  // 'ext' => array( 'php' )
146
  // ), true, $settings->max_filesize );
147
  //include wp-config.php here
app/module/scan/component/token-utils.php CHANGED
@@ -13,6 +13,7 @@ class Token_Utils extends Component {
13
  * @var array
14
  */
15
  static $tokens = array();
 
16
 
17
  /**
18
  * @param $token
@@ -31,6 +32,45 @@ class Token_Utils extends Component {
31
  return false;
32
  }
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  /**
35
  * @param $token
36
  * @param $from
@@ -47,7 +87,7 @@ class Token_Utils extends Component {
47
  $token = array( $token );
48
  }
49
 
50
- for ( $i = $from; $i < $end; $i ++ ) {
51
  if ( ! isset( self::$tokens[ $i ] ) ) {
52
  return false;
53
  }
@@ -80,6 +120,21 @@ class Token_Utils extends Component {
80
  return $str;
81
  }
82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  /**
84
  * @param $start
85
  * @param $end
@@ -89,18 +144,46 @@ class Token_Utils extends Component {
89
  public static function findParams( $start, $end ) {
90
  $params = array();
91
  for ( $i = $start; $i < $end; $i ++ ) {
92
- $params[] = self::$tokens[ $i ];
93
  }
94
 
95
  return $params;
96
  }
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  /**
99
  * @param $token
100
  *
101
  * @return bool
102
  */
103
- public static function isUserInput( $token ) {
 
 
104
  if ( $token['code'] == T_VARIABLE
105
  && preg_match( '/\$\{?_(GET|POST|REQUEST|COOKIE|SERVER|FILES|ENV)/', $token['content'] ) ) {
106
  return true;
@@ -109,6 +192,166 @@ class Token_Utils extends Component {
109
  return false;
110
  }
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  //Borrow from https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/Utils.php
113
  //Point to RIPs and SO https://stackoverflow.com/questions/3115559/exploitable-php-functions
114
  public static function getCallbackFunctions() {
@@ -116,10 +359,10 @@ class Token_Utils extends Component {
116
  'ob_start',
117
  'array_diff_uassoc',
118
  'array_diff_ukey',
119
- 'array_filter',
120
  'array_intersect_uassoc',
121
  'array_intersect_ukey',
122
- 'array_map',
123
  'array_reduce',
124
  'array_udiff_assoc',
125
  'array_udiff_uassoc',
@@ -130,9 +373,6 @@ class Token_Utils extends Component {
130
  'array_walk_recursive',
131
  'array_walk',
132
  'assert_options',
133
- 'uasort',
134
- 'uksort',
135
- 'usort',
136
  'preg_replace_callback',
137
  'spl_autoload_register',
138
  'iterator_apply',
@@ -166,11 +406,15 @@ class Token_Utils extends Component {
166
  * @return array
167
  */
168
  public static function getsuspiciousFunctions() {
169
- return array_merge( self::getCryptoFunctions(), array(
 
 
 
 
170
  'assert',
171
  'eval',
172
  'gzinflate'
173
- ) );
174
  }
175
 
176
  /**
@@ -330,4 +574,51 @@ class Token_Utils extends Component {
330
  'crc32',
331
  );
332
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  }
13
  * @var array
14
  */
15
  static $tokens = array();
16
+ static $code;
17
 
18
  /**
19
  * @param $token
32
  return false;
33
  }
34
 
35
+ /**
36
+ * Find the first token it met, can skip things dont need
37
+ *
38
+ * @param $from
39
+ * @param null $end
40
+ * @param array $skips
41
+ *
42
+ * @return bool|mixed
43
+ */
44
+ public static function findFirstPrevious( $from, $end = 0, $skips = array() ) {
45
+ for ( $i = $from; $i >= $end; $i -- ) {
46
+ if ( isset( self::$tokens[ $i ] ) && ! in_array( self::$tokens[ $i ]['code'], $skips ) ) {
47
+ return $i;
48
+ }
49
+ }
50
+
51
+ return false;
52
+ }
53
+
54
+ /**
55
+ * @param $from
56
+ * @param null $end
57
+ * @param array $skips
58
+ *
59
+ * @return bool
60
+ */
61
+ public static function findFirstNext( $from, $end = null, $skips = array() ) {
62
+ if ( $end == null ) {
63
+ $end = count( self::$tokens ) - 1;
64
+ }
65
+ for ( $i = $from; $i <= $end; $i ++ ) {
66
+ if ( isset( self::$tokens[ $i ] ) && ! in_array( self::$tokens[ $i ]['code'], $skips ) ) {
67
+ return $i;
68
+ }
69
+ }
70
+
71
+ return false;
72
+ }
73
+
74
  /**
75
  * @param $token
76
  * @param $from
87
  $token = array( $token );
88
  }
89
 
90
+ for ( $i = $from; $i <= $end; $i ++ ) {
91
  if ( ! isset( self::$tokens[ $i ] ) ) {
92
  return false;
93
  }
120
  return $str;
121
  }
122
 
123
+ /**
124
+ * @param $start
125
+ * @param $end
126
+ *
127
+ * @return string
128
+ */
129
+ public static function getTokensAsStringByIndex( $start, $end ) {
130
+ $str = '';
131
+ for ( $i = $start; $i < $end; $i ++ ) {
132
+ $str .= self::$tokens[ $i ]['content'];
133
+ }
134
+
135
+ return $str;
136
+ }
137
+
138
  /**
139
  * @param $start
140
  * @param $end
144
  public static function findParams( $start, $end ) {
145
  $params = array();
146
  for ( $i = $start; $i < $end; $i ++ ) {
147
+ $params[ $i ] = self::$tokens[ $i ];
148
  }
149
 
150
  return $params;
151
  }
152
 
153
+ public static function prepareParams() {
154
+ $results = array();
155
+ foreach ( self::$tokens as $index => $token ) {
156
+ if ( $token['code'] == T_VARIABLE ) {
157
+ $next = self::findFirstNext( $index + 1, null, array( T_WHITESPACE ) );
158
+ //this should be the =
159
+ $params = array();
160
+ if ( self::$tokens[ $next ]['code'] == T_EQUAL ) {
161
+ //capture this
162
+ $end = self::findNext( T_SEMICOLON, $index + 2 );
163
+ $params = self::findParams( $index + 2, $end );
164
+
165
+ } elseif ( self::$tokens[ $next ]['code'] == T_OPEN_PARENTHESIS ) {
166
+ //a variable function
167
+ }
168
+
169
+ $results[] = array(
170
+ 'variable' => $token['content'],
171
+ 'args' => $params
172
+ );
173
+ }
174
+ }
175
+
176
+ return $results;
177
+ }
178
+
179
  /**
180
  * @param $token
181
  *
182
  * @return bool
183
  */
184
+ public static function isUserInput(
185
+ $token
186
+ ) {
187
  if ( $token['code'] == T_VARIABLE
188
  && preg_match( '/\$\{?_(GET|POST|REQUEST|COOKIE|SERVER|FILES|ENV)/', $token['content'] ) ) {
189
  return true;
192
  return false;
193
  }
194
 
195
+ /**
196
+ * Borrow from https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/Utils.php
197
+ * @return array
198
+ */
199
+ public static function getFilesystemFunctions() {
200
+ return array(
201
+ // From http://www.php.net/manual/en/book.filesystem.php
202
+ 'chgrp',
203
+ 'chown',
204
+ 'clearstatcache',
205
+ 'copy',
206
+ 'delete',
207
+ 'disk_free_space',
208
+ 'disk_total_space',
209
+ 'diskfreespace',
210
+ 'fclose',
211
+ 'feof',
212
+ 'fflush',
213
+ 'fgetc',
214
+ 'fgetcsv',
215
+ 'fgets',
216
+ 'fgetss',
217
+ 'file_get_contents',
218
+ 'file_put_contents',
219
+ 'file',
220
+ 'fileatime',
221
+ 'filectime',
222
+ 'filegroup',
223
+ 'fileinode',
224
+ 'filemtime',
225
+ 'fileowner',
226
+ 'fileperms',
227
+ 'filesize',
228
+ 'filetype',
229
+ 'flock',
230
+ 'fopen',
231
+ 'fpassthru',
232
+ 'fputcsv',
233
+ 'fputs',
234
+ 'ftruncate',
235
+ 'fwrite',
236
+ 'glob',
237
+ 'is_executable',
238
+ 'is_readable',
239
+ 'is_uploaded_file',
240
+ 'is_writable',
241
+ 'is_writeable',
242
+ 'lchgrp',
243
+ 'lchown',
244
+ 'link',
245
+ 'linkinfo',
246
+ 'lstat',
247
+ 'mkdir',
248
+ 'move_uploaded_file',
249
+ 'parse_ini_file',
250
+ 'parse_ini_string',
251
+ 'readfile',
252
+ 'readlink',
253
+ 'realpath_cache_get',
254
+ 'realpath_cache_size',
255
+ //'realpath',
256
+ 'rename',
257
+ 'rewind',
258
+ 'rmdir',
259
+ 'set_file_buffer',
260
+ 'stat',
261
+ 'symlink',
262
+ 'tempnam',
263
+ 'tmpfile',
264
+ 'touch',
265
+ 'umask',
266
+ 'unlink',
267
+ // From http://www.php.net/manual/en/ref.dir.php except function that use directory handle as parameter
268
+ 'chdir',
269
+ 'chroot',
270
+ 'dir',
271
+ 'opendir',
272
+ 'scandir',
273
+ // From http://ca2.php.net/manual/en/function.mime-content-type.php
274
+ 'finfo_open',
275
+ // From http://ca2.php.net/manual/en/book.xattr.php
276
+ 'xattr_get',
277
+ 'xattr_list',
278
+ 'xattr_remove',
279
+ 'xattr_set',
280
+ 'xattr_supported',
281
+ // From http://www.php.net/manual/en/function.readgzfile.php
282
+ 'readgzfile',
283
+ 'gzopen',
284
+ 'gzfile',
285
+ // From http://www.php.net/manual/en/ref.image.php
286
+ 'getimagesize',
287
+ 'imagecreatefromgd2',
288
+ 'imagecreatefromgd2part',
289
+ 'imagecreatefromgd',
290
+ 'imagecreatefromgif',
291
+ 'imagecreatefromjpeg',
292
+ 'imagecreatefrompng',
293
+ 'imagecreatefromwbmp',
294
+ 'imagecreatefromwebp',
295
+ 'imagecreatefromxbm',
296
+ 'imagecreatefromxpm',
297
+ 'imagepsloadfont',
298
+ 'jpeg2wbmp',
299
+ 'png2wbmp',
300
+ // 2nd params only, maybe make it standalone and check just the second param?
301
+ 'image2wbmp',
302
+ 'imagegd2',
303
+ 'imagegd',
304
+ 'imagegif',
305
+ 'imagejpeg',
306
+ 'imagepng',
307
+ 'imagewbmp',
308
+ 'imagewebp',
309
+ 'imagexbm',
310
+ // From http://www.php.net/manual/en/ref.exif.php
311
+ 'exif_imagetype',
312
+ 'exif_read_data',
313
+ 'exif_thumbnail',
314
+ 'read_exif_data',
315
+ // From http://www.php.net/manual/en/ref.hash.php
316
+ 'hash_file',
317
+ 'hash_hmac_file',
318
+ 'hash_update_file',
319
+ // From http://www.php.net/manual/en/ref.misc.php
320
+ 'highlight_file',
321
+ 'php_check_syntax',
322
+ 'php_strip_whitespace',
323
+ 'show_source',
324
+ // Various functions that open/read files
325
+ 'get_meta_tags',
326
+ 'hash_file',
327
+ 'hash_hmac_file',
328
+ 'hash_update_file',
329
+ 'md5_file',
330
+ 'sha1_file',
331
+ 'bzopen',
332
+ //Curl Functions
333
+ 'curl_exec',
334
+ 'curl_multi_exec',
335
+ );
336
+ }
337
+
338
+ //Borrow from https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/Utils.php
339
+ public static function getSystemexecFunctions() {
340
+ return array(
341
+ 'exec',
342
+ 'passthru',
343
+ 'proc_open',
344
+ 'popen',
345
+ 'shell_exec',
346
+ 'system',
347
+ 'pcntl_exec'
348
+ );
349
+ }
350
+
351
+ public static function getInclutions() {
352
+ return array( 'include', 'include_once', 'require', 'require_once' );
353
+ }
354
+
355
  //Borrow from https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/Utils.php
356
  //Point to RIPs and SO https://stackoverflow.com/questions/3115559/exploitable-php-functions
357
  public static function getCallbackFunctions() {
359
  'ob_start',
360
  'array_diff_uassoc',
361
  'array_diff_ukey',
362
+ //'array_filter',
363
  'array_intersect_uassoc',
364
  'array_intersect_ukey',
365
+ //'array_map',
366
  'array_reduce',
367
  'array_udiff_assoc',
368
  'array_udiff_uassoc',
373
  'array_walk_recursive',
374
  'array_walk',
375
  'assert_options',
 
 
 
376
  'preg_replace_callback',
377
  'spl_autoload_register',
378
  'iterator_apply',
406
  * @return array
407
  */
408
  public static function getsuspiciousFunctions() {
409
+ return array_merge( self::getDangeriousFunction(), self::getFilesystemFunctions() );
410
+ }
411
+
412
+ public static function getDangeriousFunction() {
413
+ return array(
414
  'assert',
415
  'eval',
416
  'gzinflate'
417
+ );
418
  }
419
 
420
  /**
574
  'crc32',
575
  );
576
  }
577
+
578
+ /**
579
+ * @return array
580
+ */
581
+ public static function getSanitizeFunctions() {
582
+ return array(
583
+ 'sanitize_email',
584
+ 'sanitize_file_name',
585
+ 'sanitize_html_class',
586
+ 'sanitize_key',
587
+ 'sanitize_meta',
588
+ 'sanitize_mime_type',
589
+ 'sanitize_option',
590
+ 'sanitize_sql_orderby',
591
+ 'sanitize_text_field',
592
+ 'sanitize_textarea_field',
593
+ 'sanitize_title',
594
+ 'sanitize_title_for_query',
595
+ 'sanitize_title_with_dashes',
596
+ 'sanitize_user',
597
+ 'intval',
598
+ 'floatval'
599
+ );
600
+ }
601
+
602
+ public static function getOutputFunctions() {
603
+ return array(
604
+ 'echo',
605
+ 'print'
606
+ );
607
+ }
608
+
609
+ public static function getEscapeFunction() {
610
+ return array(
611
+ 'esc_html',
612
+ 'esc_html_',
613
+ 'esc_html_e',
614
+ 'esc_html_x',
615
+ 'esc_url',
616
+ 'esc_js',
617
+ 'esc_attr',
618
+ 'esc_attr_',
619
+ 'esc_attr_e',
620
+ 'esc_attr_x',
621
+ 'esc_textarea'
622
+ );
623
+ }
624
  }
app/module/scan/controller/main.php CHANGED
@@ -491,7 +491,7 @@ class Main extends \WP_Defender\Controller {
491
  //from dashboard
492
  $data['url'] = network_admin_url( 'admin.php?page=wp-defender' );
493
  }
494
- $this->sendEmailReport( true );
495
  $this->submitStatsToDev();
496
  wp_send_json_success( $data );
497
  } else {
@@ -559,10 +559,10 @@ class Main extends \WP_Defender\Controller {
559
  wp_enqueue_style( 'wpmudev-sui' );
560
 
561
  wp_enqueue_script( 'defender' );
562
- wp_enqueue_script( 'highlight.js', wp_defender()->getPluginUrl() . 'app/module/scan/js/highlight.pack.js' );
563
- wp_enqueue_script( 'highlight-linenumbers.js', wp_defender()->getPluginUrl() . 'app/module/scan/js/highlightjs-line-numbers.js' );
564
  wp_enqueue_style( 'defender' );
565
  wp_enqueue_script( 'scan', wp_defender()->getPluginUrl() . 'app/module/scan/js/script.js' );
 
566
  wp_localize_script( 'scan', 'scan', $data );
567
  } else {
568
  wp_enqueue_script( 'scan', wp_defender()->getPluginUrl() . 'app/module/scan/js/script.js' );
@@ -770,26 +770,38 @@ class Main extends \WP_Defender\Controller {
770
 
771
  public function sendEmailReport( $force = false ) {
772
  $settings = Settings::instance();
773
- if ( $settings->notification == false && $force != true ) {
774
- return false;
775
- }
776
 
777
  $model = Scan_Api::getLastScan();
778
  if ( ! is_object( $model ) ) {
779
  return;
780
  }
 
 
 
 
 
781
  $count = $model->countAll( Result_Item::STATUS_ISSUE );
782
 
783
  //Check one instead of validating both conditions
784
  if ( $model->logs == 'report' ) {
 
 
 
 
785
  if ( $settings->always_send == false && $count == 0 ) {
786
  return;
787
  }
 
788
  $recipients = $settings->receipts;
789
  } else {
 
 
 
 
790
  if ( $settings->alwaysSendNotification == false && $count == 0 ) {
791
  return;
792
  }
 
793
  $recipients = $settings->receiptsNotification;
794
  }
795
 
491
  //from dashboard
492
  $data['url'] = network_admin_url( 'admin.php?page=wp-defender' );
493
  }
494
+ $this->sendEmailReport();
495
  $this->submitStatsToDev();
496
  wp_send_json_success( $data );
497
  } else {
559
  wp_enqueue_style( 'wpmudev-sui' );
560
 
561
  wp_enqueue_script( 'defender' );
562
+ wp_enqueue_script( 'prism', wp_defender()->getPluginUrl() . 'app/module/scan/js/prism.js' );
 
563
  wp_enqueue_style( 'defender' );
564
  wp_enqueue_script( 'scan', wp_defender()->getPluginUrl() . 'app/module/scan/js/script.js' );
565
+ wp_enqueue_style( 'prism', wp_defender()->getPluginUrl() . 'app/module/scan/js/prism.css' );
566
  wp_localize_script( 'scan', 'scan', $data );
567
  } else {
568
  wp_enqueue_script( 'scan', wp_defender()->getPluginUrl() . 'app/module/scan/js/script.js' );
770
 
771
  public function sendEmailReport( $force = false ) {
772
  $settings = Settings::instance();
 
 
 
773
 
774
  $model = Scan_Api::getLastScan();
775
  if ( ! is_object( $model ) ) {
776
  return;
777
  }
778
+
779
+ if ( $settings->notification == false && $force != true ) {
780
+ return false;
781
+ }
782
+
783
  $count = $model->countAll( Result_Item::STATUS_ISSUE );
784
 
785
  //Check one instead of validating both conditions
786
  if ( $model->logs == 'report' ) {
787
+ if ( $settings->report == false ) {
788
+ return;
789
+ }
790
+
791
  if ( $settings->always_send == false && $count == 0 ) {
792
  return;
793
  }
794
+
795
  $recipients = $settings->receipts;
796
  } else {
797
+ if ( $settings->notification == false ) {
798
+ return;
799
+ }
800
+
801
  if ( $settings->alwaysSendNotification == false && $count == 0 ) {
802
  return;
803
  }
804
+
805
  $recipients = $settings->receiptsNotification;
806
  }
807
 
app/module/scan/js/prism.css ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* PrismJS 1.16.0
2
+ https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+markup-templating+php&plugins=line-numbers+keep-markup */
3
+ /**
4
+ * prism.js default theme for JavaScript, CSS and HTML
5
+ * Based on dabblet (http://dabblet.com)
6
+ * @author Lea Verou
7
+ */
8
+
9
+ code[class*="language-"],
10
+ pre[class*="language-"] {
11
+ color: black;
12
+ background: none;
13
+ text-shadow: 0 1px white;
14
+ font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
15
+ font-size: 1em;
16
+ text-align: left;
17
+ white-space: pre;
18
+ word-spacing: normal;
19
+ word-break: normal;
20
+ word-wrap: normal;
21
+ line-height: 1.5;
22
+
23
+ -moz-tab-size: 4;
24
+ -o-tab-size: 4;
25
+ tab-size: 4;
26
+
27
+ -webkit-hyphens: none;
28
+ -moz-hyphens: none;
29
+ -ms-hyphens: none;
30
+ hyphens: none;
31
+ }
32
+
33
+ pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
34
+ code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
35
+ text-shadow: none;
36
+ background: #b3d4fc;
37
+ }
38
+
39
+ pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
40
+ code[class*="language-"]::selection, code[class*="language-"] ::selection {
41
+ text-shadow: none;
42
+ background: #b3d4fc;
43
+ }
44
+
45
+ @media print {
46
+ code[class*="language-"],
47
+ pre[class*="language-"] {
48
+ text-shadow: none;
49
+ }
50
+ }
51
+
52
+ /* Code blocks */
53
+ pre[class*="language-"] {
54
+ padding: 1em;
55
+ margin: .5em 0;
56
+ overflow: auto;
57
+ }
58
+
59
+ :not(pre) > code[class*="language-"],
60
+ pre[class*="language-"] {
61
+ background: #f5f2f0;
62
+ }
63
+
64
+ /* Inline code */
65
+ :not(pre) > code[class*="language-"] {
66
+ padding: .1em;
67
+ border-radius: .3em;
68
+ white-space: normal;
69
+ }
70
+
71
+ .token.comment,
72
+ .token.prolog,
73
+ .token.doctype,
74
+ .token.cdata {
75
+ color: slategray;
76
+ }
77
+
78
+ .token.punctuation {
79
+ color: #999;
80
+ }
81
+
82
+ .namespace {
83
+ opacity: .7;
84
+ }
85
+
86
+ .token.property,
87
+ .token.tag,
88
+ .token.boolean,
89
+ .token.number,
90
+ .token.constant,
91
+ .token.symbol,
92
+ .token.deleted {
93
+ color: #905;
94
+ }
95
+
96
+ .token.selector,
97
+ .token.attr-name,
98
+ .token.string,
99
+ .token.char,
100
+ .token.builtin,
101
+ .token.inserted {
102
+ color: #690;
103
+ }
104
+
105
+ .token.operator,
106
+ .token.entity,
107
+ .token.url,
108
+ .language-css .token.string,
109
+ .style .token.string {
110
+ color: #9a6e3a;
111
+ background: hsla(0, 0%, 100%, .5);
112
+ }
113
+
114
+ .token.atrule,
115
+ .token.attr-value,
116
+ .token.keyword {
117
+ color: #07a;
118
+ }
119
+
120
+ .token.function,
121
+ .token.class-name {
122
+ color: #DD4A68;
123
+ }
124
+
125
+ .token.regex,
126
+ .token.important,
127
+ .token.variable {
128
+ color: #e90;
129
+ }
130
+
131
+ .token.important,
132
+ .token.bold {
133
+ font-weight: bold;
134
+ }
135
+ .token.italic {
136
+ font-style: italic;
137
+ }
138
+
139
+ .token.entity {
140
+ cursor: help;
141
+ }
142
+
143
+ pre[class*="language-"].line-numbers {
144
+ position: relative;
145
+ padding-left: 3.8em !important;
146
+ counter-reset: linenumber;
147
+ }
148
+
149
+ pre[class*="language-"].line-numbers > code {
150
+ position: relative;
151
+ white-space: inherit;
152
+ }
153
+
154
+ .line-numbers .line-numbers-rows {
155
+ position: absolute;
156
+ pointer-events: none;
157
+ top: 0;
158
+ font-size: 100%;
159
+ left: -3.8em;
160
+ width: 3em; /* works for line-numbers below 1000 lines */
161
+ letter-spacing: -1px;
162
+ border-right: 1px solid #999;
163
+
164
+ -webkit-user-select: none;
165
+ -moz-user-select: none;
166
+ -ms-user-select: none;
167
+ user-select: none;
168
+
169
+ }
170
+
171
+ .line-numbers-rows > span {
172
+ pointer-events: none;
173
+ display: block;
174
+ counter-increment: linenumber;
175
+ }
176
+
177
+ .line-numbers-rows > span:before {
178
+ content: counter(linenumber);
179
+ color: #999;
180
+ display: block;
181
+ padding-right: 0.8em;
182
+ text-align: right;
183
+ }
app/module/scan/js/prism.js ADDED
@@ -0,0 +1,1350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* PrismJS 1.16.0
2
+ https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+markup-templating+php&plugins=line-numbers+keep-markup */
3
+ var _self = (typeof window !== 'undefined')
4
+ ? window // if in browser
5
+ : (
6
+ (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)
7
+ ? self // if in worker
8
+ : {} // if in node js
9
+ );
10
+
11
+ /**
12
+ * Prism: Lightweight, robust, elegant syntax highlighting
13
+ * MIT license http://www.opensource.org/licenses/mit-license.php/
14
+ * @author Lea Verou http://lea.verou.me
15
+ */
16
+
17
+ var Prism = (function (_self){
18
+
19
+ // Private helper vars
20
+ var lang = /\blang(?:uage)?-([\w-]+)\b/i;
21
+ var uniqueId = 0;
22
+
23
+ var _ = {
24
+ manual: _self.Prism && _self.Prism.manual,
25
+ disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,
26
+ util: {
27
+ encode: function (tokens) {
28
+ if (tokens instanceof Token) {
29
+ return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias);
30
+ } else if (Array.isArray(tokens)) {
31
+ return tokens.map(_.util.encode);
32
+ } else {
33
+ return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
34
+ }
35
+ },
36
+
37
+ type: function (o) {
38
+ return Object.prototype.toString.call(o).slice(8, -1);
39
+ },
40
+
41
+ objId: function (obj) {
42
+ if (!obj['__id']) {
43
+ Object.defineProperty(obj, '__id', { value: ++uniqueId });
44
+ }
45
+ return obj['__id'];
46
+ },
47
+
48
+ // Deep clone a language definition (e.g. to extend it)
49
+ clone: function deepClone(o, visited) {
50
+ var clone, id, type = _.util.type(o);
51
+ visited = visited || {};
52
+
53
+ switch (type) {
54
+ case 'Object':
55
+ id = _.util.objId(o);
56
+ if (visited[id]) {
57
+ return visited[id];
58
+ }
59
+ clone = {};
60
+ visited[id] = clone;
61
+
62
+ for (var key in o) {
63
+ if (o.hasOwnProperty(key)) {
64
+ clone[key] = deepClone(o[key], visited);
65
+ }
66
+ }
67
+
68
+ return clone;
69
+
70
+ case 'Array':
71
+ id = _.util.objId(o);
72
+ if (visited[id]) {
73
+ return visited[id];
74
+ }
75
+ clone = [];
76
+ visited[id] = clone;
77
+
78
+ o.forEach(function (v, i) {
79
+ clone[i] = deepClone(v, visited);
80
+ });
81
+
82
+ return clone;
83
+
84
+ default:
85
+ return o;
86
+ }
87
+ }
88
+ },
89
+
90
+ languages: {
91
+ extend: function (id, redef) {
92
+ var lang = _.util.clone(_.languages[id]);
93
+
94
+ for (var key in redef) {
95
+ lang[key] = redef[key];
96
+ }
97
+
98
+ return lang;
99
+ },
100
+
101
+ /**
102
+ * Insert a token before another token in a language literal
103
+ * As this needs to recreate the object (we cannot actually insert before keys in object literals),
104
+ * we cannot just provide an object, we need an object and a key.
105
+ * @param inside The key (or language id) of the parent
106
+ * @param before The key to insert before.
107
+ * @param insert Object with the key/value pairs to insert
108
+ * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted.
109
+ */
110
+ insertBefore: function (inside, before, insert, root) {
111
+ root = root || _.languages;
112
+ var grammar = root[inside];
113
+ var ret = {};
114
+
115
+ for (var token in grammar) {
116
+ if (grammar.hasOwnProperty(token)) {
117
+
118
+ if (token == before) {
119
+ for (var newToken in insert) {
120
+ if (insert.hasOwnProperty(newToken)) {
121
+ ret[newToken] = insert[newToken];
122
+ }
123
+ }
124
+ }
125
+
126
+ // Do not insert token which also occur in insert. See #1525
127
+ if (!insert.hasOwnProperty(token)) {
128
+ ret[token] = grammar[token];
129
+ }
130
+ }
131
+ }
132
+
133
+ var old = root[inside];
134
+ root[inside] = ret;
135
+
136
+ // Update references in other language definitions
137
+ _.languages.DFS(_.languages, function(key, value) {
138
+ if (value === old && key != inside) {
139
+ this[key] = ret;
140
+ }
141
+ });
142
+
143
+ return ret;
144
+ },
145
+
146
+ // Traverse a language definition with Depth First Search
147
+ DFS: function DFS(o, callback, type, visited) {
148
+ visited = visited || {};
149
+
150
+ var objId = _.util.objId;
151
+
152
+ for (var i in o) {
153
+ if (o.hasOwnProperty(i)) {
154
+ callback.call(o, i, o[i], type || i);
155
+
156
+ var property = o[i],
157
+ propertyType = _.util.type(property);
158
+
159
+ if (propertyType === 'Object' && !visited[objId(property)]) {
160
+ visited[objId(property)] = true;
161
+ DFS(property, callback, null, visited);
162
+ }
163
+ else if (propertyType === 'Array' && !visited[objId(property)]) {
164
+ visited[objId(property)] = true;
165
+ DFS(property, callback, i, visited);
166
+ }
167
+ }
168
+ }
169
+ }
170
+ },
171
+ plugins: {},
172
+
173
+ highlightAll: function(async, callback) {
174
+ _.highlightAllUnder(document, async, callback);
175
+ },
176
+
177
+ highlightAllUnder: function(container, async, callback) {
178
+ var env = {
179
+ callback: callback,
180
+ selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
181
+ };
182
+
183
+ _.hooks.run("before-highlightall", env);
184
+
185
+ var elements = env.elements || container.querySelectorAll(env.selector);
186
+
187
+ for (var i=0, element; element = elements[i++];) {
188
+ _.highlightElement(element, async === true, env.callback);
189
+ }
190
+ },
191
+
192
+ highlightElement: function(element, async, callback) {
193
+ // Find language
194
+ var language, grammar, parent = element;
195
+
196
+ while (parent && !lang.test(parent.className)) {
197
+ parent = parent.parentNode;
198
+ }
199
+
200
+ if (parent) {
201
+ language = (parent.className.match(lang) || [,''])[1].toLowerCase();
202
+ grammar = _.languages[language];
203
+ }
204
+
205
+ // Set language on the element, if not present
206
+ element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
207
+
208
+ if (element.parentNode) {
209
+ // Set language on the parent, for styling
210
+ parent = element.parentNode;
211
+
212
+ if (/pre/i.test(parent.nodeName)) {
213
+ parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
214
+ }
215
+ }
216
+
217
+ var code = element.textContent;
218
+
219
+ var env = {
220
+ element: element,
221
+ language: language,
222
+ grammar: grammar,
223
+ code: code
224
+ };
225
+
226
+ var insertHighlightedCode = function (highlightedCode) {
227
+ env.highlightedCode = highlightedCode;
228
+
229
+ _.hooks.run('before-insert', env);
230
+
231
+ env.element.innerHTML = env.highlightedCode;
232
+
233
+ _.hooks.run('after-highlight', env);
234
+ _.hooks.run('complete', env);
235
+ callback && callback.call(env.element);
236
+ }
237
+
238
+ _.hooks.run('before-sanity-check', env);
239
+
240
+ if (!env.code) {
241
+ _.hooks.run('complete', env);
242
+ return;
243
+ }
244
+
245
+ _.hooks.run('before-highlight', env);
246
+
247
+ if (!env.grammar) {
248
+ insertHighlightedCode(_.util.encode(env.code));
249
+ return;
250
+ }
251
+
252
+ if (async && _self.Worker) {
253
+ var worker = new Worker(_.filename);
254
+
255
+ worker.onmessage = function(evt) {
256
+ insertHighlightedCode(evt.data);
257
+ };
258
+
259
+ worker.postMessage(JSON.stringify({
260
+ language: env.language,
261
+ code: env.code,
262
+ immediateClose: true
263
+ }));
264
+ }
265
+ else {
266
+ insertHighlightedCode(_.highlight(env.code, env.grammar, env.language));
267
+ }
268
+ },
269
+
270
+ highlight: function (text, grammar, language) {
271
+ var env = {
272
+ code: text,
273
+ grammar: grammar,
274
+ language: language
275
+ };
276
+ _.hooks.run('before-tokenize', env);
277
+ env.tokens = _.tokenize(env.code, env.grammar);
278
+ _.hooks.run('after-tokenize', env);
279
+ return Token.stringify(_.util.encode(env.tokens), env.language);
280
+ },
281
+
282
+ matchGrammar: function (text, strarr, grammar, index, startPos, oneshot, target) {
283
+ for (var token in grammar) {
284
+ if(!grammar.hasOwnProperty(token) || !grammar[token]) {
285
+ continue;
286
+ }
287
+
288
+ if (token == target) {
289
+ return;
290
+ }
291
+
292
+ var patterns = grammar[token];
293
+ patterns = (_.util.type(patterns) === "Array") ? patterns : [patterns];
294
+
295
+ for (var j = 0; j < patterns.length; ++j) {
296
+ var pattern = patterns[j],
297
+ inside = pattern.inside,
298
+ lookbehind = !!pattern.lookbehind,
299
+ greedy = !!pattern.greedy,
300
+ lookbehindLength = 0,
301
+ alias = pattern.alias;
302
+
303
+ if (greedy && !pattern.pattern.global) {
304
+ // Without the global flag, lastIndex won't work
305
+ var flags = pattern.pattern.toString().match(/[imuy]*$/)[0];
306
+ pattern.pattern = RegExp(pattern.pattern.source, flags + "g");
307
+ }
308
+
309
+ pattern = pattern.pattern || pattern;
310
+
311
+ // Don’t cache length as it changes during the loop
312
+ for (var i = index, pos = startPos; i < strarr.length; pos += strarr[i].length, ++i) {
313
+
314
+ var str = strarr[i];
315
+
316
+ if (strarr.length > text.length) {
317
+ // Something went terribly wrong, ABORT, ABORT!
318
+ return;
319
+ }
320
+
321
+ if (str instanceof Token) {
322
+ continue;
323
+ }
324
+
325
+ if (greedy && i != strarr.length - 1) {
326
+ pattern.lastIndex = pos;
327
+ var match = pattern.exec(text);
328
+ if (!match) {
329
+ break;
330
+ }
331
+
332
+ var from = match.index + (lookbehind ? match[1].length : 0),
333
+ to = match.index + match[0].length,
334
+ k = i,
335
+ p = pos;
336
+
337
+ for (var len = strarr.length; k < len && (p < to || (!strarr[k].type && !strarr[k - 1].greedy)); ++k) {
338
+ p += strarr[k].length;
339
+ // Move the index i to the element in strarr that is closest to from
340
+ if (from >= p) {
341
+ ++i;
342
+ pos = p;
343
+ }
344
+ }
345
+
346
+ // If strarr[i] is a Token, then the match starts inside another Token, which is invalid
347
+ if (strarr[i] instanceof Token) {
348
+ continue;
349
+ }
350
+
351
+ // Number of tokens to delete and replace with the new match
352
+ delNum = k - i;
353
+ str = text.slice(pos, p);
354
+ match.index -= pos;
355
+ } else {
356
+ pattern.lastIndex = 0;
357
+
358
+ var match = pattern.exec(str),
359
+ delNum = 1;
360
+ }
361
+
362
+ if (!match) {
363
+ if (oneshot) {
364
+ break;
365
+ }
366
+
367
+ continue;
368
+ }
369
+
370
+ if(lookbehind) {
371
+ lookbehindLength = match[1] ? match[1].length : 0;
372
+ }
373
+
374
+ var from = match.index + lookbehindLength,
375
+ match = match[0].slice(lookbehindLength),
376
+ to = from + match.length,
377
+ before = str.slice(0, from),
378
+ after = str.slice(to);
379
+
380
+ var args = [i, delNum];
381
+
382
+ if (before) {
383
+ ++i;
384
+ pos += before.length;
385
+ args.push(before);
386
+ }
387
+
388
+ var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias, match, greedy);
389
+
390
+ args.push(wrapped);
391
+
392
+ if (after) {
393
+ args.push(after);
394
+ }
395
+
396
+ Array.prototype.splice.apply(strarr, args);
397
+
398
+ if (delNum != 1)
399
+ _.matchGrammar(text, strarr, grammar, i, pos, true, token);
400
+
401
+ if (oneshot)
402
+ break;
403
+ }
404
+ }
405
+ }
406
+ },
407
+
408
+ tokenize: function(text, grammar) {
409
+ var strarr = [text];
410
+
411
+ var rest = grammar.rest;
412
+
413
+ if (rest) {
414
+ for (var token in rest) {
415
+ grammar[token] = rest[token];
416
+ }
417
+
418
+ delete grammar.rest;
419
+ }
420
+
421
+ _.matchGrammar(text, strarr, grammar, 0, 0, false);
422
+
423
+ return strarr;
424
+ },
425
+
426
+ hooks: {
427
+ all: {},
428
+
429
+ add: function (name, callback) {
430
+ var hooks = _.hooks.all;
431
+
432
+ hooks[name] = hooks[name] || [];
433
+
434
+ hooks[name].push(callback);
435
+ },
436
+
437
+ run: function (name, env) {
438
+ var callbacks = _.hooks.all[name];
439
+
440
+ if (!callbacks || !callbacks.length) {
441
+ return;
442
+ }
443
+
444
+ for (var i=0, callback; callback = callbacks[i++];) {
445
+ callback(env);
446
+ }
447
+ }
448
+ },
449
+
450
+ Token: Token
451
+ };
452
+
453
+ _self.Prism = _;
454
+
455
+ function Token(type, content, alias, matchedStr, greedy) {
456
+ this.type = type;
457
+ this.content = content;
458
+ this.alias = alias;
459
+ // Copy of the full string this token was created from
460
+ this.length = (matchedStr || "").length|0;
461
+ this.greedy = !!greedy;
462
+ }
463
+
464
+ Token.stringify = function(o, language) {
465
+ if (typeof o == 'string') {
466
+ return o;
467
+ }
468
+
469
+ if (Array.isArray(o)) {
470
+ return o.map(function(element) {
471
+ return Token.stringify(element, language);
472
+ }).join('');
473
+ }
474
+
475
+ var env = {
476
+ type: o.type,
477
+ content: Token.stringify(o.content, language),
478
+ tag: 'span',
479
+ classes: ['token', o.type],
480
+ attributes: {},
481
+ language: language
482
+ };
483
+
484
+ if (o.alias) {
485
+ var aliases = Array.isArray(o.alias) ? o.alias : [o.alias];
486
+ Array.prototype.push.apply(env.classes, aliases);
487
+ }
488
+
489
+ _.hooks.run('wrap', env);
490
+
491
+ var attributes = Object.keys(env.attributes).map(function(name) {
492
+ return name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
493
+ }).join(' ');
494
+
495
+ return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + (attributes ? ' ' + attributes : '') + '>' + env.content + '</' + env.tag + '>';
496
+ };
497
+
498
+ if (!_self.document) {
499
+ if (!_self.addEventListener) {
500
+ // in Node.js
501
+ return _;
502
+ }
503
+
504
+ if (!_.disableWorkerMessageHandler) {
505
+ // In worker
506
+ _self.addEventListener('message', function (evt) {
507
+ var message = JSON.parse(evt.data),
508
+ lang = message.language,
509
+ code = message.code,
510
+ immediateClose = message.immediateClose;
511
+
512
+ _self.postMessage(_.highlight(code, _.languages[lang], lang));
513
+ if (immediateClose) {
514
+ _self.close();
515
+ }
516
+ }, false);
517
+ }
518
+
519
+ return _;
520
+ }
521
+
522
+ //Get current script and highlight
523
+ var script = document.currentScript || [].slice.call(document.getElementsByTagName("script")).pop();
524
+
525
+ if (script) {
526
+ _.filename = script.src;
527
+
528
+ if (!_.manual && !script.hasAttribute('data-manual')) {
529
+ if(document.readyState !== "loading") {
530
+ if (window.requestAnimationFrame) {
531
+ window.requestAnimationFrame(_.highlightAll);
532
+ } else {
533
+ window.setTimeout(_.highlightAll, 16);
534
+ }
535
+ }
536
+ else {
537
+ document.addEventListener('DOMContentLoaded', _.highlightAll);
538
+ }
539
+ }
540
+ }
541
+
542
+ return _;
543
+
544
+ })(_self);
545
+
546
+ if (typeof module !== 'undefined' && module.exports) {
547
+ module.exports = Prism;
548
+ }
549
+
550
+ // hack for components to work correctly in node.js
551
+ if (typeof global !== 'undefined') {
552
+ global.Prism = Prism;
553
+ }
554
+ ;
555
+ Prism.languages.markup = {
556
+ 'comment': /<!--[\s\S]*?-->/,
557
+ 'prolog': /<\?[\s\S]+?\?>/,
558
+ 'doctype': /<!DOCTYPE[\s\S]+?>/i,
559
+ 'cdata': /<!\[CDATA\[[\s\S]*?]]>/i,
560
+ 'tag': {
561
+ pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,
562
+ greedy: true,
563
+ inside: {
564
+ 'tag': {
565
+ pattern: /^<\/?[^\s>\/]+/i,
566
+ inside: {
567
+ 'punctuation': /^<\/?/,
568
+ 'namespace': /^[^\s>\/:]+:/
569
+ }
570
+ },
571
+ 'attr-value': {
572
+ pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,
573
+ inside: {
574
+ 'punctuation': [
575
+ /^=/,
576
+ {
577
+ pattern: /^(\s*)["']|["']$/,
578
+ lookbehind: true
579
+ }
580
+ ]
581
+ }
582
+ },
583
+ 'punctuation': /\/?>/,
584
+ 'attr-name': {
585
+ pattern: /[^\s>\/]+/,
586
+ inside: {
587
+ 'namespace': /^[^\s>\/:]+:/
588
+ }
589
+ }
590
+
591
+ }
592
+ },
593
+ 'entity': /&#?[\da-z]{1,8};/i
594
+ };
595
+
596
+ Prism.languages.markup['tag'].inside['attr-value'].inside['entity'] =
597
+ Prism.languages.markup['entity'];
598
+
599
+ // Plugin to make entity title show the real entity, idea by Roman Komarov
600
+ Prism.hooks.add('wrap', function(env) {
601
+
602
+ if (env.type === 'entity') {
603
+ env.attributes['title'] = env.content.replace(/&amp;/, '&');
604
+ }
605
+ });
606
+
607
+ Object.defineProperty(Prism.languages.markup.tag, 'addInlined', {
608
+ /**
609
+ * Adds an inlined language to markup.
610
+ *
611
+ * An example of an inlined language is CSS with `<style>` tags.
612
+ *
613
+ * @param {string} tagName The name of the tag that contains the inlined language. This name will be treated as
614
+ * case insensitive.
615
+ * @param {string} lang The language key.
616
+ * @example
617
+ * addInlined('style', 'css');
618
+ */
619
+ value: function addInlined(tagName, lang) {
620
+ var includedCdataInside = {};
621
+ includedCdataInside['language-' + lang] = {
622
+ pattern: /(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,
623
+ lookbehind: true,
624
+ inside: Prism.languages[lang]
625
+ };
626
+ includedCdataInside['cdata'] = /^<!\[CDATA\[|\]\]>$/i;
627
+
628
+ var inside = {
629
+ 'included-cdata': {
630
+ pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
631
+ inside: includedCdataInside
632
+ }
633
+ };
634
+ inside['language-' + lang] = {
635
+ pattern: /[\s\S]+/,
636
+ inside: Prism.languages[lang]
637
+ };
638
+
639
+ var def = {};
640
+ def[tagName] = {
641
+ pattern: RegExp(/(<__[\s\S]*?>)(?:<!\[CDATA\[[\s\S]*?\]\]>\s*|[\s\S])*?(?=<\/__>)/.source.replace(/__/g, tagName), 'i'),
642
+ lookbehind: true,
643
+ greedy: true,
644
+ inside: inside
645
+ };
646
+
647
+ Prism.languages.insertBefore('markup', 'cdata', def);
648
+ }
649
+ });
650
+
651
+ Prism.languages.xml = Prism.languages.extend('markup', {});
652
+ Prism.languages.html = Prism.languages.markup;
653
+ Prism.languages.mathml = Prism.languages.markup;
654
+ Prism.languages.svg = Prism.languages.markup;
655
+
656
+ (function (Prism) {
657
+
658
+ var string = /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;
659
+
660
+ Prism.languages.css = {
661
+ 'comment': /\/\*[\s\S]*?\*\//,
662
+ 'atrule': {
663
+ pattern: /@[\w-]+?[\s\S]*?(?:;|(?=\s*\{))/i,
664
+ inside: {
665
+ 'rule': /@[\w-]+/
666
+ // See rest below
667
+ }
668
+ },
669
+ 'url': RegExp('url\\((?:' + string.source + '|.*?)\\)', 'i'),
670
+ 'selector': RegExp('[^{}\\s](?:[^{};"\']|' + string.source + ')*?(?=\\s*\\{)'),
671
+ 'string': {
672
+ pattern: string,
673
+ greedy: true
674
+ },
675
+ 'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,
676
+ 'important': /!important\b/i,
677
+ 'function': /[-a-z0-9]+(?=\()/i,
678
+ 'punctuation': /[(){};:,]/
679
+ };
680
+
681
+ Prism.languages.css['atrule'].inside.rest = Prism.languages.css;
682
+
683
+ var markup = Prism.languages.markup;
684
+ if (markup) {
685
+ markup.tag.addInlined('style', 'css');
686
+
687
+ Prism.languages.insertBefore('inside', 'attr-value', {
688
+ 'style-attr': {
689
+ pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,
690
+ inside: {
691
+ 'attr-name': {
692
+ pattern: /^\s*style/i,
693
+ inside: markup.tag.inside
694
+ },
695
+ 'punctuation': /^\s*=\s*['"]|['"]\s*$/,
696
+ 'attr-value': {
697
+ pattern: /.+/i,
698
+ inside: Prism.languages.css
699
+ }
700
+ },
701
+ alias: 'language-css'
702
+ }
703
+ }, markup.tag);
704
+ }
705
+
706
+ }(Prism));
707
+
708
+ Prism.languages.clike = {
709
+ 'comment': [
710
+ {
711
+ pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
712
+ lookbehind: true
713
+ },
714
+ {
715
+ pattern: /(^|[^\\:])\/\/.*/,
716
+ lookbehind: true,
717
+ greedy: true
718
+ }
719
+ ],
720
+ 'string': {
721
+ pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
722
+ greedy: true
723
+ },
724
+ 'class-name': {
725
+ pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,
726
+ lookbehind: true,
727
+ inside: {
728
+ punctuation: /[.\\]/
729
+ }
730
+ },
731
+ 'keyword': /\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,
732
+ 'boolean': /\b(?:true|false)\b/,
733
+ 'function': /\w+(?=\()/,
734
+ 'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,
735
+ 'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,
736
+ 'punctuation': /[{}[\];(),.:]/
737
+ };
738
+
739
+ Prism.languages.javascript = Prism.languages.extend('clike', {
740
+ 'class-name': [
741
+ Prism.languages.clike['class-name'],
742
+ {
743
+ pattern: /(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,
744
+ lookbehind: true
745
+ }
746
+ ],
747
+ 'keyword': [
748
+ {
749
+ pattern: /((?:^|})\s*)(?:catch|finally)\b/,
750
+ lookbehind: true
751
+ },
752
+ {
753
+ pattern: /(^|[^.])\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
754
+ lookbehind: true
755
+ },
756
+ ],
757
+ 'number': /\b(?:(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+)n?|\d+n|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,
758
+ // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
759
+ 'function': /[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,
760
+ 'operator': /-[-=]?|\+[+=]?|!=?=?|<<?=?|>>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/
761
+ });
762
+
763
+ Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/;
764
+
765
+ Prism.languages.insertBefore('javascript', 'keyword', {
766
+ 'regex': {
767
+ pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/,
768
+ lookbehind: true,
769
+ greedy: true
770
+ },
771
+ // This must be declared before keyword because we use "function" inside the look-forward
772
+ 'function-variable': {
773
+ pattern: /[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,
774
+ alias: 'function'
775
+ },
776
+ 'parameter': [
777
+ {
778
+ pattern: /(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,
779
+ lookbehind: true,
780
+ inside: Prism.languages.javascript
781
+ },
782
+ {
783
+ pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,
784
+ inside: Prism.languages.javascript
785
+ },
786
+ {
787
+ pattern: /(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,
788
+ lookbehind: true,
789
+ inside: Prism.languages.javascript
790
+ },
791
+ {
792
+ pattern: /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,
793
+ lookbehind: true,
794
+ inside: Prism.languages.javascript
795
+ }
796
+ ],
797
+ 'constant': /\b[A-Z](?:[A-Z_]|\dx?)*\b/
798
+ });
799
+
800
+ Prism.languages.insertBefore('javascript', 'string', {
801
+ 'template-string': {
802
+ pattern: /`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,
803
+ greedy: true,
804
+ inside: {
805
+ 'interpolation': {
806
+ pattern: /\${[^}]+}/,
807
+ inside: {
808
+ 'interpolation-punctuation': {
809
+ pattern: /^\${|}$/,
810
+ alias: 'punctuation'
811
+ },
812
+ rest: Prism.languages.javascript
813
+ }
814
+ },
815
+ 'string': /[\s\S]+/
816
+ }
817
+ }
818
+ });
819
+
820
+ if (Prism.languages.markup) {
821
+ Prism.languages.markup.tag.addInlined('script', 'javascript');
822
+ }
823
+
824
+ Prism.languages.js = Prism.languages.javascript;
825
+
826
+ (function (Prism) {
827
+
828
+ /**
829
+ * Returns the placeholder for the given language id and index.
830
+ *
831
+ * @param {string} language
832
+ * @param {string|number} index
833
+ * @returns {string}
834
+ */
835
+ function getPlaceholder(language, index) {
836
+ return '___' + language.toUpperCase() + index + '___';
837
+ }
838
+
839
+ Object.defineProperties(Prism.languages['markup-templating'] = {}, {
840
+ buildPlaceholders: {
841
+ /**
842
+ * Tokenize all inline templating expressions matching `placeholderPattern`.
843
+ *
844
+ * If `replaceFilter` is provided, only matches of `placeholderPattern` for which `replaceFilter` returns
845
+ * `true` will be replaced.
846
+ *
847
+ * @param {object} env The environment of the `before-tokenize` hook.
848
+ * @param {string} language The language id.
849
+ * @param {RegExp} placeholderPattern The matches of this pattern will be replaced by placeholders.
850
+ * @param {(match: string) => boolean} [replaceFilter]
851
+ */
852
+ value: function (env, language, placeholderPattern, replaceFilter) {
853
+ if (env.language !== language) {
854
+ return;
855
+ }
856
+
857
+ var tokenStack = env.tokenStack = [];
858
+
859
+ env.code = env.code.replace(placeholderPattern, function (match) {
860
+ if (typeof replaceFilter === 'function' && !replaceFilter(match)) {
861
+ return match;
862
+ }
863
+ var i = tokenStack.length;
864
+ var placeholder;
865
+
866
+ // Check for existing strings
867
+ while (env.code.indexOf(placeholder = getPlaceholder(language, i)) !== -1)
868
+ ++i;
869
+
870
+ // Create a sparse array
871
+ tokenStack[i] = match;
872
+
873
+ return placeholder;
874
+ });
875
+
876
+ // Switch the grammar to markup
877
+ env.grammar = Prism.languages.markup;
878
+ }
879
+ },
880
+ tokenizePlaceholders: {
881
+ /**
882
+ * Replace placeholders with proper tokens after tokenizing.
883
+ *
884
+ * @param {object} env The environment of the `after-tokenize` hook.
885
+ * @param {string} language The language id.
886
+ */
887
+ value: function (env, language) {
888
+ if (env.language !== language || !env.tokenStack) {
889
+ return;
890
+ }
891
+
892
+ // Switch the grammar back
893
+ env.grammar = Prism.languages[language];
894
+
895
+ var j = 0;
896
+ var keys = Object.keys(env.tokenStack);
897
+
898
+ function walkTokens(tokens) {
899
+ for (var i = 0; i < tokens.length; i++) {
900
+ // all placeholders are replaced already
901
+ if (j >= keys.length) {
902
+ break;
903
+ }
904
+
905
+ var token = tokens[i];
906
+ if (typeof token === 'string' || (token.content && typeof token.content === 'string')) {
907
+ var k = keys[j];
908
+ var t = env.tokenStack[k];
909
+ var s = typeof token === 'string' ? token : token.content;
910
+ var placeholder = getPlaceholder(language, k);
911
+
912
+ var index = s.indexOf(placeholder);
913
+ if (index > -1) {
914
+ ++j;
915
+
916
+ var before = s.substring(0, index);
917
+ var middle = new Prism.Token(language, Prism.tokenize(t, env.grammar), 'language-' + language, t);
918
+ var after = s.substring(index + placeholder.length);
919
+
920
+ var replacement = [];
921
+ if (before) {
922
+ replacement.push.apply(replacement, walkTokens([before]));
923
+ }
924
+ replacement.push(middle);
925
+ if (after) {
926
+ replacement.push.apply(replacement, walkTokens([after]));
927
+ }
928
+
929
+ if (typeof token === 'string') {
930
+ tokens.splice.apply(tokens, [i, 1].concat(replacement));
931
+ } else {
932
+ token.content = replacement;
933
+ }
934
+ }
935
+ } else if (token.content /* && typeof token.content !== 'string' */) {
936
+ walkTokens(token.content);
937
+ }
938
+ }
939
+
940
+ return tokens;
941
+ }
942
+
943
+ walkTokens(env.tokens);
944
+ }
945
+ }
946
+ });
947
+
948
+ }(Prism));
949
+
950
+ /**
951
+ * Original by Aaron Harun: http://aahacreative.com/2012/07/31/php-syntax-highlighting-prism/
952
+ * Modified by Miles Johnson: http://milesj.me
953
+ *
954
+ * Supports the following:
955
+ * - Extends clike syntax
956
+ * - Support for PHP 5.3+ (namespaces, traits, generators, etc)
957
+ * - Smarter constant and function matching
958
+ *
959
+ * Adds the following new token classes:
960
+ * constant, delimiter, variable, function, package
961
+ */
962
+ (function (Prism) {
963
+ Prism.languages.php = Prism.languages.extend('clike', {
964
+ 'keyword': /\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|new|or|parent|print|private|protected|public|require|require_once|return|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,
965
+ 'boolean': {
966
+ pattern: /\b(?:false|true)\b/i,
967
+ alias: 'constant'
968
+ },
969
+ 'constant': [
970
+ /\b[A-Z_][A-Z0-9_]*\b/,
971
+ /\b(?:null)\b/i,
972
+ ],
973
+ 'comment': {
974
+ pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,
975
+ lookbehind: true
976
+ }
977
+ });
978
+
979
+ Prism.languages.insertBefore('php', 'string', {
980
+ 'shell-comment': {
981
+ pattern: /(^|[^\\])#.*/,
982
+ lookbehind: true,
983
+ alias: 'comment'
984
+ }
985
+ });
986
+
987
+ Prism.languages.insertBefore('php', 'comment', {
988
+ 'delimiter': {
989
+ pattern: /\?>$|^<\?(?:php(?=\s)|=)?/i,
990
+ alias: 'important'
991
+ }
992
+ });
993
+
994
+ Prism.languages.insertBefore('php', 'keyword', {
995
+ 'variable': /\$+(?:\w+\b|(?={))/i,
996
+ 'package': {
997
+ pattern: /(\\|namespace\s+|use\s+)[\w\\]+/,
998
+ lookbehind: true,
999
+ inside: {
1000
+ punctuation: /\\/
1001
+ }
1002
+ }
1003
+ });
1004
+
1005
+ // Must be defined after the function pattern
1006
+ Prism.languages.insertBefore('php', 'operator', {
1007
+ 'property': {
1008
+ pattern: /(->)[\w]+/,
1009
+ lookbehind: true
1010
+ }
1011
+ });
1012
+
1013
+ var string_interpolation = {
1014
+ pattern: /{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/,
1015
+ lookbehind: true,
1016
+ inside: {
1017
+ rest: Prism.languages.php
1018
+ }
1019
+ };
1020
+
1021
+ Prism.languages.insertBefore('php', 'string', {
1022
+ 'nowdoc-string': {
1023
+ pattern: /<<<'([^']+)'(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;/,
1024
+ greedy: true,
1025
+ alias: 'string',
1026
+ inside: {
1027
+ 'delimiter': {
1028
+ pattern: /^<<<'[^']+'|[a-z_]\w*;$/i,
1029
+ alias: 'symbol',
1030
+ inside: {
1031
+ 'punctuation': /^<<<'?|[';]$/
1032
+ }
1033
+ }
1034
+ }
1035
+ },
1036
+ 'heredoc-string': {
1037
+ pattern: /<<<(?:"([^"]+)"(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;|([a-z_]\w*)(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\2;)/i,
1038
+ greedy: true,
1039
+ alias: 'string',
1040
+ inside: {
1041
+ 'delimiter': {
1042
+ pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,
1043
+ alias: 'symbol',
1044
+ inside: {
1045
+ 'punctuation': /^<<<"?|[";]$/
1046
+ }
1047
+ },
1048
+ 'interpolation': string_interpolation // See below
1049
+ }
1050
+ },
1051
+ 'single-quoted-string': {
1052
+ pattern: /'(?:\\[\s\S]|[^\\'])*'/,
1053
+ greedy: true,
1054
+ alias: 'string'
1055
+ },
1056
+ 'double-quoted-string': {
1057
+ pattern: /"(?:\\[\s\S]|[^\\"])*"/,
1058
+ greedy: true,
1059
+ alias: 'string',
1060
+ inside: {
1061
+ 'interpolation': string_interpolation // See below
1062
+ }
1063
+ }
1064
+ });
1065
+ // The different types of PHP strings "replace" the C-like standard string
1066
+ delete Prism.languages.php['string'];
1067
+
1068
+ Prism.hooks.add('before-tokenize', function(env) {
1069
+ if (!/<\?/.test(env.code)) {
1070
+ return;
1071
+ }
1072
+
1073
+ var phpPattern = /<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#)(?:[^?\n\r]|\?(?!>))*|\/\*[\s\S]*?(?:\*\/|$))*?(?:\?>|$)/ig;
1074
+ Prism.languages['markup-templating'].buildPlaceholders(env, 'php', phpPattern);
1075
+ });
1076
+
1077
+ Prism.hooks.add('after-tokenize', function(env) {
1078
+ Prism.languages['markup-templating'].tokenizePlaceholders(env, 'php');
1079
+ });
1080
+
1081
+ }(Prism));
1082
+
1083
+ (function () {
1084
+
1085
+ if (typeof self === 'undefined' || !self.Prism || !self.document) {
1086
+ return;
1087
+ }
1088
+
1089
+ /**
1090
+ * Plugin name which is used as a class name for <pre> which is activating the plugin
1091
+ * @type {String}
1092
+ */
1093
+ var PLUGIN_NAME = 'line-numbers';
1094
+
1095
+ /**
1096
+ * Regular expression used for determining line breaks
1097
+ * @type {RegExp}
1098
+ */
1099
+ var NEW_LINE_EXP = /\n(?!$)/g;
1100
+
1101
+ /**
1102
+ * Resizes line numbers spans according to height of line of code
1103
+ * @param {Element} element <pre> element
1104
+ */
1105
+ var _resizeElement = function (element) {
1106
+ var codeStyles = getStyles(element);
1107
+ var whiteSpace = codeStyles['white-space'];
1108
+
1109
+ if (whiteSpace === 'pre-wrap' || whiteSpace === 'pre-line') {
1110
+ var codeElement = element.querySelector('code');
1111
+ var lineNumbersWrapper = element.querySelector('.line-numbers-rows');
1112
+ var lineNumberSizer = element.querySelector('.line-numbers-sizer');
1113
+ var codeLines = codeElement.textContent.split(NEW_LINE_EXP);
1114
+
1115
+ if (!lineNumberSizer) {
1116
+ lineNumberSizer = document.createElement('span');
1117
+ lineNumberSizer.className = 'line-numbers-sizer';
1118
+
1119
+ codeElement.appendChild(lineNumberSizer);
1120
+ }
1121
+
1122
+ lineNumberSizer.style.display = 'block';
1123
+
1124
+ codeLines.forEach(function (line, lineNumber) {
1125
+ lineNumberSizer.textContent = line || '\n';
1126
+ var lineSize = lineNumberSizer.getBoundingClientRect().height;
1127
+ lineNumbersWrapper.children[lineNumber].style.height = lineSize + 'px';
1128
+ });
1129
+
1130
+ lineNumberSizer.textContent = '';
1131
+ lineNumberSizer.style.display = 'none';
1132
+ }
1133
+ };
1134
+
1135
+ /**
1136
+ * Returns style declarations for the element
1137
+ * @param {Element} element
1138
+ */
1139
+ var getStyles = function (element) {
1140
+ if (!element) {
1141
+ return null;
1142
+ }
1143
+
1144
+ return window.getComputedStyle ? getComputedStyle(element) : (element.currentStyle || null);
1145
+ };
1146
+
1147
+ window.addEventListener('resize', function () {
1148
+ Array.prototype.forEach.call(document.querySelectorAll('pre.' + PLUGIN_NAME), _resizeElement);
1149
+ });
1150
+
1151
+ Prism.hooks.add('complete', function (env) {
1152
+ if (!env.code) {
1153
+ return;
1154
+ }
1155
+
1156
+ var code = env.element;
1157
+ var pre = code.parentNode;
1158
+
1159
+ // works only for <code> wrapped inside <pre> (not inline)
1160
+ if (!pre || !/pre/i.test(pre.nodeName)) {
1161
+ return;
1162
+ }
1163
+
1164
+ // Abort if line numbers already exists
1165
+ if (code.querySelector('.line-numbers-rows')) {
1166
+ return;
1167
+ }
1168
+
1169
+ var addLineNumbers = false;
1170
+ var lineNumbersRegex = /(?:^|\s)line-numbers(?:\s|$)/;
1171
+
1172
+ for (var element = code; element; element = element.parentNode) {
1173
+ if (lineNumbersRegex.test(element.className)) {
1174
+ addLineNumbers = true;
1175
+ break;
1176
+ }
1177
+ }
1178
+
1179
+ // only add line numbers if <code> or one of its ancestors has the `line-numbers` class
1180
+ if (!addLineNumbers) {
1181
+ return;
1182
+ }
1183
+
1184
+ // Remove the class 'line-numbers' from the <code>
1185
+ code.className = code.className.replace(lineNumbersRegex, ' ');
1186
+ // Add the class 'line-numbers' to the <pre>
1187
+ if (!lineNumbersRegex.test(pre.className)) {
1188
+ pre.className += ' line-numbers';
1189
+ }
1190
+
1191
+ var match = env.code.match(NEW_LINE_EXP);
1192
+ var linesNum = match ? match.length + 1 : 1;
1193
+ var lineNumbersWrapper;
1194
+
1195
+ var lines = new Array(linesNum + 1).join('<span></span>');
1196
+
1197
+ lineNumbersWrapper = document.createElement('span');
1198
+ lineNumbersWrapper.setAttribute('aria-hidden', 'true');
1199
+ lineNumbersWrapper.className = 'line-numbers-rows';
1200
+ lineNumbersWrapper.innerHTML = lines;
1201
+
1202
+ if (pre.hasAttribute('data-start')) {
1203
+ pre.style.counterReset = 'linenumber ' + (parseInt(pre.getAttribute('data-start'), 10) - 1);
1204
+ }
1205
+
1206
+ env.element.appendChild(lineNumbersWrapper);
1207
+
1208
+ _resizeElement(pre);
1209
+
1210
+ Prism.hooks.run('line-numbers', env);
1211
+ });
1212
+
1213
+ Prism.hooks.add('line-numbers', function (env) {
1214
+ env.plugins = env.plugins || {};
1215
+ env.plugins.lineNumbers = true;
1216
+ });
1217
+
1218
+ /**
1219
+ * Global exports
1220
+ */
1221
+ Prism.plugins.lineNumbers = {
1222
+ /**
1223
+ * Get node for provided line number
1224
+ * @param {Element} element pre element
1225
+ * @param {Number} number line number
1226
+ * @return {Element|undefined}
1227
+ */
1228
+ getLine: function (element, number) {
1229
+ if (element.tagName !== 'PRE' || !element.classList.contains(PLUGIN_NAME)) {
1230
+ return;
1231
+ }
1232
+
1233
+ var lineNumberRows = element.querySelector('.line-numbers-rows');
1234
+ var lineNumberStart = parseInt(element.getAttribute('data-start'), 10) || 1;
1235
+ var lineNumberEnd = lineNumberStart + (lineNumberRows.children.length - 1);
1236
+
1237
+ if (number < lineNumberStart) {
1238
+ number = lineNumberStart;
1239
+ }
1240
+ if (number > lineNumberEnd) {
1241
+ number = lineNumberEnd;
1242
+ }
1243
+
1244
+ var lineIndex = number - lineNumberStart;
1245
+
1246
+ return lineNumberRows.children[lineIndex];
1247
+ }
1248
+ };
1249
+
1250
+ }());
1251
+
1252
+ (function (self, document) {
1253
+
1254
+ if (typeof self === 'undefined' || !self.Prism || !self.document || !document.createRange) {
1255
+ return;
1256
+ }
1257
+
1258
+ Prism.plugins.KeepMarkup = true;
1259
+
1260
+ Prism.hooks.add('before-highlight', function (env) {
1261
+ if (!env.element.children.length) {
1262
+ return;
1263
+ }
1264
+
1265
+ var pos = 0;
1266
+ var data = [];
1267
+ var f = function (elt, baseNode) {
1268
+ var o = {};
1269
+ if (!baseNode) {
1270
+ // Clone the original tag to keep all attributes
1271
+ o.clone = elt.cloneNode(false);
1272
+ o.posOpen = pos;
1273
+ data.push(o);
1274
+ }
1275
+ for (var i = 0, l = elt.childNodes.length; i < l; i++) {
1276
+ var child = elt.childNodes[i];
1277
+ if (child.nodeType === 1) { // element
1278
+ f(child);
1279
+ } else if(child.nodeType === 3) { // text
1280
+ pos += child.data.length;
1281
+ }
1282
+ }
1283
+ if (!baseNode) {
1284
+ o.posClose = pos;
1285
+ }
1286
+ };
1287
+ f(env.element, true);
1288
+
1289
+ if (data && data.length) {
1290
+ // data is an array of all existing tags
1291
+ env.keepMarkup = data;
1292
+ }
1293
+ });
1294
+
1295
+ Prism.hooks.add('after-highlight', function (env) {
1296
+ if(env.keepMarkup && env.keepMarkup.length) {
1297
+
1298
+ var walk = function (elt, nodeState) {
1299
+ for (var i = 0, l = elt.childNodes.length; i < l; i++) {
1300
+
1301
+ var child = elt.childNodes[i];
1302
+
1303
+ if (child.nodeType === 1) { // element
1304
+ if (!walk(child, nodeState)) {
1305
+ return false;
1306
+ }
1307
+
1308
+ } else if (child.nodeType === 3) { // text
1309
+ if(!nodeState.nodeStart && nodeState.pos + child.data.length > nodeState.node.posOpen) {
1310
+ // We found the start position
1311
+ nodeState.nodeStart = child;
1312
+ nodeState.nodeStartPos = nodeState.node.posOpen - nodeState.pos;
1313
+ }
1314
+ if(nodeState.nodeStart && nodeState.pos + child.data.length >= nodeState.node.posClose) {
1315
+ // We found the end position
1316
+ nodeState.nodeEnd = child;
1317
+ nodeState.nodeEndPos = nodeState.node.posClose - nodeState.pos;
1318
+ }
1319
+
1320
+ nodeState.pos += child.data.length;
1321
+ }
1322
+
1323
+ if (nodeState.nodeStart && nodeState.nodeEnd) {
1324
+ // Select the range and wrap it with the clone
1325
+ var range = document.createRange();
1326
+ range.setStart(nodeState.nodeStart, nodeState.nodeStartPos);
1327
+ range.setEnd(nodeState.nodeEnd, nodeState.nodeEndPos);
1328
+ nodeState.node.clone.appendChild(range.extractContents());
1329
+ range.insertNode(nodeState.node.clone);
1330
+ range.detach();
1331
+
1332
+ // Process is over
1333
+ return false;
1334
+ }
1335
+ }
1336
+ return true;
1337
+ };
1338
+
1339
+ // For each tag, we walk the DOM to reinsert it
1340
+ env.keepMarkup.forEach(function (node) {
1341
+ walk(env.element, {
1342
+ node: node,
1343
+ pos: 0
1344
+ });
1345
+ });
1346
+ // Store new highlightedCode for later hooks calls
1347
+ env.highlightedCode = env.element.innerHTML;
1348
+ }
1349
+ });
1350
+ }(self, document));
app/module/scan/js/script.js CHANGED
@@ -135,11 +135,8 @@ jQuery(function ($) {
135
  current_issue = null;
136
  var parent = form.closest('.source-code');
137
  parent.html(data.data.html);
138
-
139
- // hljs.highlightBlock(parent.find('pre code'));
140
  parent.find('pre code').each(function (i, block) {
141
- hljs.highlightBlock(block);
142
- hljs.lineNumbersBlock(block);
143
  });
144
  } else {
145
  Defender.showNotification('error', data.data.message);
@@ -190,7 +187,7 @@ jQuery(function ($) {
190
  }).change();
191
 
192
  //bulk
193
- $('#apply-all').click(function () {
194
  $('.scan-chk').prop('checked', $(this).prop('checked'));
195
  });
196
  $('select[name="bulk"]').change(function () {
@@ -261,10 +258,10 @@ WDScan.formHandler = function () {
261
  }
262
 
263
  WDScan.formatCode = function () {
264
- jQuery('pre code').each(function (i, block) {
265
- hljs.highlightBlock(block);
266
- hljs.lineNumbersBlock(block);
267
- });
268
  }
269
 
270
  //Refresh file issues counts
@@ -292,22 +289,14 @@ WDScan.initAppear = function () {
292
  }
293
 
294
  WDScan.showNextIssue = function () {
295
- jQuery('body').on('click', '#next_issue', function () {
 
 
296
  var parent = jQuery(this).closest('.sui-box').find('.inner-sourcecode').first();
297
- var issues = parent.find('del');
298
- if (issues.size() == 0) {
299
- return;
300
- }
301
- if (current_issue === null) {
302
- current_issue = 0;
303
- } else {
304
- current_issue = current_issue + 1;
305
- if (issues[current_issue] === undefined) {
306
- current_issue = 0;
307
- }
308
- }
309
- var pos = jQuery(issues[current_issue]).position();
310
- parent.scrollTop(pos.top);
311
  })
312
  }
313
 
135
  current_issue = null;
136
  var parent = form.closest('.source-code');
137
  parent.html(data.data.html);
 
 
138
  parent.find('pre code').each(function (i, block) {
139
+ Prism.highlightElement(block);
 
140
  });
141
  } else {
142
  Defender.showNotification('error', data.data.message);
187
  }).change();
188
 
189
  //bulk
190
+ $('.apply-all').click(function () {
191
  $('.scan-chk').prop('checked', $(this).prop('checked'));
192
  });
193
  $('select[name="bulk"]').change(function () {
258
  }
259
 
260
  WDScan.formatCode = function () {
261
+ // jQuery('pre code').each(function (i, block) {
262
+ // hljs.highlightBlock(block);
263
+ // hljs.lineNumbersBlock(block);
264
+ // });
265
  }
266
 
267
  //Refresh file issues counts
289
  }
290
 
291
  WDScan.showNextIssue = function () {
292
+ jQuery('body').on('click', '.nav-issue', function (e) {
293
+ e.preventDefault();
294
+ var line = jQuery(this).data('line');
295
  var parent = jQuery(this).closest('.sui-box').find('.inner-sourcecode').first();
296
+ var curr = jQuery(Prism.plugins.lineNumbers.getLine(parent.get(0), line));
297
+ curr.get(0).scrollIntoView({
298
+ block: 'center'
299
+ });
 
 
 
 
 
 
 
 
 
 
300
  })
301
  }
302
 
app/module/scan/model/settings.php CHANGED
@@ -11,6 +11,7 @@ use Hammer\Queue\Queue;
11
  use WP_Defender\Behavior\Utils;
12
  use WP_Defender\Module\Scan\Behavior\Core_Scan;
13
  use WP_Defender\Module\Scan\Behavior\Pro\Content_Scan;
 
14
  use WP_Defender\Module\Scan\Behavior\Pro\MD5_Scan;
15
  use WP_Defender\Module\Scan\Behavior\Pro\Vuln_Scan;
16
  use WP_Defender\Module\Scan\Component\Scan_Api;
@@ -141,7 +142,7 @@ Stay safe,
141
  WP Defender
142
  Official WPMU DEV Superhero', "defender-security" );
143
  //call parent to load stored
144
- if ( is_admin() || is_network_admin() && current_user_can( 'manage_options' ) ) {
145
  $user = wp_get_current_user();
146
  if ( is_object( $user ) ) {
147
  $this->receipts[] = array(
11
  use WP_Defender\Behavior\Utils;
12
  use WP_Defender\Module\Scan\Behavior\Core_Scan;
13
  use WP_Defender\Module\Scan\Behavior\Pro\Content_Scan;
14
+ use WP_Defender\Module\Scan\Behavior\Pro\Content_Scan2;
15
  use WP_Defender\Module\Scan\Behavior\Pro\MD5_Scan;
16
  use WP_Defender\Module\Scan\Behavior\Pro\Vuln_Scan;
17
  use WP_Defender\Module\Scan\Component\Scan_Api;
142
  WP Defender
143
  Official WPMU DEV Superhero', "defender-security" );
144
  //call parent to load stored
145
+ if ( ( is_admin() || is_network_admin() ) && current_user_can( 'manage_options' ) ) {
146
  $user = wp_get_current_user();
147
  if ( is_object( $user ) ) {
148
  $this->receipts[] = array(
app/module/scan/view/automation.php CHANGED
@@ -30,8 +30,8 @@
30
  <p class="sui-p-small">
31
  <?php _e( "By default, we will only notify the recipients below when there is an issue from your file scan. Enable this option to send emails even when no issues are detected. ", "defender-security" ) ?>
32
  </p>
 
33
  <label class="sui-toggle">
34
- <input type="hidden" name="always_send" value="0"/>
35
  <input role="presentation" type="checkbox" name="always_send"
36
  class="toggle-checkbox"
37
  id="always_send" value="1"
30
  <p class="sui-p-small">
31
  <?php _e( "By default, we will only notify the recipients below when there is an issue from your file scan. Enable this option to send emails even when no issues are detected. ", "defender-security" ) ?>
32
  </p>
33
+ <input type="hidden" name="always_send" value="0"/>
34
  <label class="sui-toggle">
 
35
  <input role="presentation" type="checkbox" name="always_send"
36
  class="toggle-checkbox"
37
  id="always_send" value="1"
app/module/scan/view/ignored.php CHANGED
@@ -17,7 +17,7 @@
17
  } else {
18
  ?>
19
  <div class="sui-notice sui-notice-info">
20
- <p> <?php _e( "You haven't ignored any suspicious files yet. Ignored files appear here and can be restored at any times.", "defender-security" ) ?> </p>
21
  </div>
22
  <?php
23
  }
17
  } else {
18
  ?>
19
  <div class="sui-notice sui-notice-info">
20
+ <p> <?php _e( "You haven't chosen to ignore any suspicious files yet. Ignored files appear here and can be restored at any time", "defender-security" ) ?> </p>
21
  </div>
22
  <?php
23
  }
app/module/scan/view/issues.php CHANGED
@@ -26,8 +26,8 @@ $table->prepare_items();
26
  <?php selected( 'vuln', \Hammer\Helper\HTTP_Helper::retrieve_get( 'type' ) ) ?>
27
  value="vuln"><?php _e( "Plugins/Themes Vulnerability", "defender-security" ) ?></option>
28
  <option
29
- <?php selected( 'code', \Hammer\Helper\HTTP_Helper::retrieve_get( 'type' ) ) ?>
30
- value="code"><?php _e( "Suspicious code", "defender-security" ) ?></option>
31
  </select>
32
  </div>
33
  </div>
26
  <?php selected( 'vuln', \Hammer\Helper\HTTP_Helper::retrieve_get( 'type' ) ) ?>
27
  value="vuln"><?php _e( "Plugins/Themes Vulnerability", "defender-security" ) ?></option>
28
  <option
29
+ <?php selected( 'content', \Hammer\Helper\HTTP_Helper::retrieve_get( 'type' ) ) ?>
30
+ value="content"><?php _e( "Suspicious code", "defender-security" ) ?></option>
31
  </select>
32
  </div>
33
  </div>
app/module/scan/view/layouts/layout.php CHANGED
@@ -2,6 +2,12 @@
2
  $core = $model->getCount( 'core' );
3
  $vuln = $model->getCount( 'vuln' );
4
  $content = $model->getCount( 'content' );
 
 
 
 
 
 
5
  ?>
6
  <div class="sui-wrap <?php echo \WP_Defender\Behavior\Utils::instance()->maybeHighContrast() ?>">
7
  <div id="wp-defender" class="wp-defender">
@@ -21,25 +27,32 @@ $content = $model->getCount( 'content' );
21
  </button>
22
  </form>
23
  </div>
24
- <?php if ( wp_defender()->hideDocLinks === false ): ?>
25
  <div class="sui-actions-right">
26
  <div class="sui-actions-right">
27
- <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/" target="_blank" class="sui-button sui-button-ghost">
 
28
  <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
29
  </a>
30
  </div>
31
  </div>
32
- <?php endif; ?>
33
  </div>
34
- <div class="sui-box sui-summary <?php echo \WP_Defender\Behavior\Utils::instance()->getSummaryClass()?>">
35
  <div class="sui-summary-image-space" aria-hidden="true"></div>
36
  <div class="sui-summary-segment">
37
  <div class="sui-summary-details">
38
  <span class="sui-summary-large issues"><?php echo $countAll ?></span>
39
  <?php if ( $countAll > 0 ): ?>
40
- <i aria-hidden="true" class="sui-icon-info sui-error"></i>
 
 
 
41
  <?php else: ?>
 
 
42
  <i class="sui-icon-check-tick sui-success" aria-hidden="true"></i>
 
43
  <?php endif; ?>
44
  <span class="sui-summary-sub"><?php _e( "File scanning issues", "defender-security" ) ?></span>
45
 
@@ -110,7 +123,7 @@ $content = $model->getCount( 'content' );
110
  <?php echo $contents ?>
111
  </div>
112
  </div>
113
- <?php if ( wp_defender()->changeFooter && ! empty( wp_defender()->footerText ) ): ?>
114
  <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
115
  <?php else: ?>
116
  <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
2
  $core = $model->getCount( 'core' );
3
  $vuln = $model->getCount( 'vuln' );
4
  $content = $model->getCount( 'content' );
5
+ $tooltips = __( "You don't have any outstanding security issues, nice work!", "defender-security" );
6
+ if ( $countAll == 1 ) {
7
+ $tooltips = __( "We've detected a potential security risk in your file system. We recommend you take a look and action a fix, or ignore the file if it's harmless.", "defender-security" );
8
+ } elseif ( $countAll > 1 ) {
9
+ $tooltips = sprintf( __( "You have %s potential security risks in your file system. We recommend you take a look and action fixes, or ignore the issues if they are harmless." ), $countAll );
10
+ }
11
  ?>
12
  <div class="sui-wrap <?php echo \WP_Defender\Behavior\Utils::instance()->maybeHighContrast() ?>">
13
  <div id="wp-defender" class="wp-defender">
27
  </button>
28
  </form>
29
  </div>
30
+ <?php if ( wp_defender()->hideDocLinks === false ): ?>
31
  <div class="sui-actions-right">
32
  <div class="sui-actions-right">
33
+ <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/#security-scans" target="_blank"
34
+ class="sui-button sui-button-ghost">
35
  <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
36
  </a>
37
  </div>
38
  </div>
39
+ <?php endif; ?>
40
  </div>
41
+ <div class="sui-box sui-summary <?php echo \WP_Defender\Behavior\Utils::instance()->getSummaryClass() ?>">
42
  <div class="sui-summary-image-space" aria-hidden="true"></div>
43
  <div class="sui-summary-segment">
44
  <div class="sui-summary-details">
45
  <span class="sui-summary-large issues"><?php echo $countAll ?></span>
46
  <?php if ( $countAll > 0 ): ?>
47
+ <span class="sui-tooltip sui-tooltip-top-left sui-tooltip-constrained"
48
+ data-tooltip="<?php echo $tooltips ?>">
49
+ <i aria-hidden="true" class="sui-icon-info sui-warning"></i>
50
+ </span>
51
  <?php else: ?>
52
+ <span class="sui-tooltip sui-tooltip-top-left sui-tooltip-constrained"
53
+ data-tooltip="<?php echo $tooltips ?>">
54
  <i class="sui-icon-check-tick sui-success" aria-hidden="true"></i>
55
+ </span>
56
  <?php endif; ?>
57
  <span class="sui-summary-sub"><?php _e( "File scanning issues", "defender-security" ) ?></span>
58
 
123
  <?php echo $contents ?>
124
  </div>
125
  </div>
126
+ <?php if ( wp_defender()->changeFooter ): ?>
127
  <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
128
  <?php else: ?>
129
  <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
app/module/scan/view/notification.php CHANGED
@@ -32,8 +32,8 @@
32
  <p class="sui-p-small">
33
  <?php _e( "By default, we will only notify the recipients below when there is an issue from your file scan. Enable this option to send emails even when no issues are detected. ", "defender-security" ) ?>
34
  </p>
 
35
  <label class="sui-toggle">
36
- <input type="hidden" name="always_send" value="0"/>
37
  <input role="presentation" type="checkbox" name="alwaysSendNotification"
38
  class="toggle-checkbox"
39
  id="alwaysSendNotification" value="1"
@@ -118,6 +118,19 @@
118
  <div class="sui-row">
119
  <div class="sui-col">
120
  <div class="sui-form-field">
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  <textarea rows="12" class="sui-form-control"
122
  name="email_all_ok"><?php echo $setting->email_all_ok ?></textarea>
123
  </div>
@@ -178,6 +191,19 @@
178
  <div class="sui-row">
179
  <div class="sui-col">
180
  <div class="sui-form-field">
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  <textarea rows="12" class="sui-form-control"
182
  name="email_has_issue"><?php echo $setting->email_has_issue ?></textarea>
183
  </div>
32
  <p class="sui-p-small">
33
  <?php _e( "By default, we will only notify the recipients below when there is an issue from your file scan. Enable this option to send emails even when no issues are detected. ", "defender-security" ) ?>
34
  </p>
35
+ <input type="hidden" name="always_send" value="0"/>
36
  <label class="sui-toggle">
 
37
  <input role="presentation" type="checkbox" name="alwaysSendNotification"
38
  class="toggle-checkbox"
39
  id="alwaysSendNotification" value="1"
118
  <div class="sui-row">
119
  <div class="sui-col">
120
  <div class="sui-form-field">
121
+ <label class="sui-label">
122
+ <?php _e( "Subject", "defender-security" ) ?>
123
+ </label>
124
+ <input type="text" class="sui-form-control" name="email_subject" value="<?php echo $setting->email_subject ?>">
125
+ </div>
126
+ </div>
127
+ </div>
128
+ <div class="sui-row">
129
+ <div class="sui-col">
130
+ <div class="sui-form-field">
131
+ <label class="sui-label">
132
+ <?php _e( "Body", "defender-security" ) ?>
133
+ </label>
134
  <textarea rows="12" class="sui-form-control"
135
  name="email_all_ok"><?php echo $setting->email_all_ok ?></textarea>
136
  </div>
191
  <div class="sui-row">
192
  <div class="sui-col">
193
  <div class="sui-form-field">
194
+ <label class="sui-label">
195
+ <?php _e( "Subject", "defender-security" ) ?>
196
+ </label>
197
+ <input type="text" class="sui-form-control" name="email_subject" value="<?php echo $setting->email_subject ?>">
198
+ </div>
199
+ </div>
200
+ </div>
201
+ <div class="sui-row">
202
+ <div class="sui-col">
203
+ <div class="sui-form-field">
204
+ <label class="sui-label">
205
+ <?php _e( "Subject", "defender-security" ) ?>
206
+ </label>
207
  <textarea rows="12" class="sui-form-control"
208
  name="email_has_issue"><?php echo $setting->email_has_issue ?></textarea>
209
  </div>
app/module/scan/view/setting-free.php CHANGED
@@ -16,8 +16,8 @@
16
 
17
  <div class="sui-box-settings-col-2">
18
  <div class="sui-form-field">
 
19
  <label class="sui-toggle">
20
- <input type="hidden" name="scan_core" value="0"/>
21
  <input role="presentation" type="checkbox" name="scan_core" class="toggle-checkbox"
22
  id="core-scan" value="1"
23
  <?php checked( true, $setting->scan_core ) ?>/>
16
 
17
  <div class="sui-box-settings-col-2">
18
  <div class="sui-form-field">
19
+ <input type="hidden" name="scan_core" value="0"/>
20
  <label class="sui-toggle">
 
21
  <input role="presentation" type="checkbox" name="scan_core" class="toggle-checkbox"
22
  id="core-scan" value="1"
23
  <?php checked( true, $setting->scan_core ) ?>/>
app/module/scan/view/setting.php CHANGED
@@ -16,9 +16,9 @@
16
 
17
  <div class="sui-box-settings-col-2">
18
  <div class="sui-form-field">
 
19
  <label class="sui-toggle">
20
- <input type="hidden" name="scan_core" value="0"/>
21
- <input role="presentation" type="checkbox" name="scan_core" class="toggle-checkbox"
22
  id="core-scan" value="1"
23
  <?php checked( true, $setting->scan_core ) ?>/>
24
  <span class="sui-toggle-slider"></span>
@@ -31,11 +31,11 @@
31
  </p>
32
  </div>
33
  <div class="sui-form-field">
 
34
  <label class="sui-toggle">
35
- <input type="hidden" name="scan_vuln" value="0"/>
36
- <input role="presentation" type="checkbox" class="toggle-checkbox" name="scan_vuln"
37
  value="1"
38
- id="scan-vuln" <?php checked( true, $setting->scan_vuln ) ?>/>
39
  <span class="sui-toggle-slider"></span>
40
  </label>
41
  <label for="scan_vuln" class="sui-toggle-label">
@@ -46,11 +46,11 @@
46
  </p>
47
  </div>
48
  <div class="sui-form-field">
 
49
  <label class="sui-toggle">
50
- <input type="hidden" name="scan_content" value="0"/>
51
  <input role="presentation" type="checkbox" class="toggle-checkbox" name="scan_content"
52
  value="1"
53
- id="scan-content" <?php checked( true, $setting->scan_content ) ?>/>
54
  <span class="sui-toggle-slider"></span>
55
  </label>
56
  <label for="scan_content" class="sui-toggle-label">
16
 
17
  <div class="sui-box-settings-col-2">
18
  <div class="sui-form-field">
19
+ <input type="hidden" name="scan_core" value="0"/>
20
  <label class="sui-toggle">
21
+ <input type="checkbox" name="scan_core" class="toggle-checkbox"
 
22
  id="core-scan" value="1"
23
  <?php checked( true, $setting->scan_core ) ?>/>
24
  <span class="sui-toggle-slider"></span>
31
  </p>
32
  </div>
33
  <div class="sui-form-field">
34
+ <input type="hidden" name="scan_vuln" value="0"/>
35
  <label class="sui-toggle">
36
+ <input type="checkbox" class="toggle-checkbox" name="scan_vuln"
 
37
  value="1"
38
+ id="scan_vuln" <?php checked( true, $setting->scan_vuln ) ?>/>
39
  <span class="sui-toggle-slider"></span>
40
  </label>
41
  <label for="scan_vuln" class="sui-toggle-label">
46
  </p>
47
  </div>
48
  <div class="sui-form-field">
49
+ <input type="hidden" name="scan_content" value="0"/>
50
  <label class="sui-toggle">
 
51
  <input role="presentation" type="checkbox" class="toggle-checkbox" name="scan_content"
52
  value="1"
53
+ id="scan_content" <?php checked( true, $setting->scan_content ) ?>/>
54
  <span class="sui-toggle-slider"></span>
55
  </label>
56
  <label for="scan_content" class="sui-toggle-label">
app/module/setting/view/accessibility.php CHANGED
@@ -19,9 +19,9 @@
19
  </span>
20
  </div>
21
  <div class="sui-box-settings-col-2">
 
22
  <div class="sui-form-field">
23
  <label class="sui-toggle">
24
- <input type="hidden" name="high_contrast_mode" value="0"/>
25
  <input role="presentation" type="checkbox" name="high_contrast_mode" class="toggle-checkbox"
26
  id="high_contrast_mode" <?php checked( 1, $settings->high_contrast_mode ) ?> value="1"
27
  />
19
  </span>
20
  </div>
21
  <div class="sui-box-settings-col-2">
22
+ <input type="hidden" name="high_contrast_mode" value="0"/>
23
  <div class="sui-form-field">
24
  <label class="sui-toggle">
 
25
  <input role="presentation" type="checkbox" name="high_contrast_mode" class="toggle-checkbox"
26
  id="high_contrast_mode" <?php checked( 1, $settings->high_contrast_mode ) ?> value="1"
27
  />
app/module/setting/view/general.php CHANGED
@@ -43,8 +43,8 @@
43
 
44
  <div class="sui-box-settings-col-2">
45
  <div class="sui-form-field">
 
46
  <label class="sui-toggle">
47
- <input type="hidden" name="usage_tracking" value="0"/>
48
  <input role="presentation" type="checkbox" name="usage_tracking" class="toggle-checkbox"
49
  id="usage_tracking" <?php checked( 1, $settings->usage_tracking ) ?> value="1"
50
  />
43
 
44
  <div class="sui-box-settings-col-2">
45
  <div class="sui-form-field">
46
+ <input type="hidden" name="usage_tracking" value="0"/>
47
  <label class="sui-toggle">
 
48
  <input role="presentation" type="checkbox" name="usage_tracking" class="toggle-checkbox"
49
  id="usage_tracking" <?php checked( 1, $settings->usage_tracking ) ?> value="1"
50
  />
app/module/setting/view/layouts/layout.php CHANGED
@@ -5,15 +5,16 @@
5
  <h1 class="sui-header-title">
6
  <?php _e( "Settings", "defender-security" ) ?>
7
  </h1>
8
- <?php if ( wp_defender()->hideDocLinks === false ): ?>
9
  <div class="sui-actions-right">
10
  <div class="sui-actions-right">
11
- <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/" target="_blank" class="sui-button sui-button-ghost">
 
12
  <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
13
  </a>
14
  </div>
15
  </div>
16
- <?php endif; ?>
17
  </div>
18
  <div class="sui-row-with-sidenav">
19
  <div class="sui-sidenav">
@@ -37,7 +38,13 @@
37
  <div class="sui-sidenav-hide-lg">
38
  <select class="sui-mobile-nav" style="display: none;">
39
  <option <?php selected( '', \Hammer\Helper\HTTP_Helper::retrieve_get( 'view' ) ) ?>
40
- value="<?php echo network_admin_url( 'admin.php?page=wdf-advanced-tools' ) ?>">
 
 
 
 
 
 
41
  <?php _e( "Accessibility", "defender-security" ) ?></option>
42
  </select>
43
  </div>
@@ -90,13 +97,13 @@
90
  </div>
91
 
92
  </div>
93
- <?php if ( wp_defender()->changeFooter && ! empty( wp_defender()->footerText ) ): ?>
94
  <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
95
- <?php else: ?>
96
  <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
97
- <?php endif; ?>
98
- <?php if ( wp_defender()->hideDocLinks == false ): ?>
99
- <?php if ( wp_defender()->isFree ): ?>
100
  <ul class="sui-footer-nav">
101
  <li><a href="https://profiles.wordpress.org/wpmudev#content-plugins" target="_blank">Free
102
  Plugins</a>
@@ -110,7 +117,7 @@
110
  </li>
111
  <li><a href="https://incsub.com/privacy-policy/" target="_blank">Privacy Policy</a></li>
112
  </ul>
113
- <?php else: ?>
114
  <ul class="sui-footer-nav">
115
  <li><a href="https://premium.wpmudev.org/hub/" target="_blank">The Hub</a></li>
116
  <li><a href="https://premium.wpmudev.org/projects/category/plugins/" target="_blank">Plugins</a>
@@ -123,7 +130,7 @@
123
  </li>
124
  <li><a href="https://incsub.com/privacy-policy/" target="_blank">Privacy Policy</a></li>
125
  </ul>
126
- <?php endif; ?>
127
  <ul class="sui-footer-social">
128
  <li><a href="https://www.facebook.com/wpmudev" target="_blank">
129
  <i class="sui-icon-social-facebook" aria-hidden="true"></i>
@@ -138,6 +145,6 @@
138
  <span class="sui-screen-reader-text">Instagram</span>
139
  </a></li>
140
  </ul>
141
- <?php endif; ?>
142
  </div>
143
  </div>
5
  <h1 class="sui-header-title">
6
  <?php _e( "Settings", "defender-security" ) ?>
7
  </h1>
8
+ <?php if ( wp_defender()->hideDocLinks === false ): ?>
9
  <div class="sui-actions-right">
10
  <div class="sui-actions-right">
11
+ <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/" target="_blank"
12
+ class="sui-button sui-button-ghost">
13
  <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
14
  </a>
15
  </div>
16
  </div>
17
+ <?php endif; ?>
18
  </div>
19
  <div class="sui-row-with-sidenav">
20
  <div class="sui-sidenav">
38
  <div class="sui-sidenav-hide-lg">
39
  <select class="sui-mobile-nav" style="display: none;">
40
  <option <?php selected( '', \Hammer\Helper\HTTP_Helper::retrieve_get( 'view' ) ) ?>
41
+ value="<?php echo network_admin_url( 'admin.php?page=wdf-setting' ) ?>">
42
+ <?php _e( "General", "defender-security" ) ?></option>
43
+ <option <?php selected( 'data', \Hammer\Helper\HTTP_Helper::retrieve_get( 'view' ) ) ?>
44
+ value="<?php echo network_admin_url( 'admin.php?page=wdf-setting&view=data' ) ?>">
45
+ <?php _e( "Data & Settings", "defender-security" ) ?></option>
46
+ <option <?php selected( 'accessibility', \Hammer\Helper\HTTP_Helper::retrieve_get( 'view' ) ) ?>
47
+ value="<?php echo network_admin_url( 'admin.php?page=wdf-setting&view=accessibility' ) ?>">
48
  <?php _e( "Accessibility", "defender-security" ) ?></option>
49
  </select>
50
  </div>
97
  </div>
98
 
99
  </div>
100
+ <?php if ( wp_defender()->changeFooter ): ?>
101
  <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
102
+ <?php else: ?>
103
  <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
104
+ <?php endif; ?>
105
+ <?php if ( wp_defender()->hideDocLinks == false ): ?>
106
+ <?php if ( wp_defender()->isFree ): ?>
107
  <ul class="sui-footer-nav">
108
  <li><a href="https://profiles.wordpress.org/wpmudev#content-plugins" target="_blank">Free
109
  Plugins</a>
117
  </li>
118
  <li><a href="https://incsub.com/privacy-policy/" target="_blank">Privacy Policy</a></li>
119
  </ul>
120
+ <?php else: ?>
121
  <ul class="sui-footer-nav">
122
  <li><a href="https://premium.wpmudev.org/hub/" target="_blank">The Hub</a></li>
123
  <li><a href="https://premium.wpmudev.org/projects/category/plugins/" target="_blank">Plugins</a>
130
  </li>
131
  <li><a href="https://incsub.com/privacy-policy/" target="_blank">Privacy Policy</a></li>
132
  </ul>
133
+ <?php endif; ?>
134
  <ul class="sui-footer-social">
135
  <li><a href="https://www.facebook.com/wpmudev" target="_blank">
136
  <i class="sui-icon-social-facebook" aria-hidden="true"></i>
145
  <span class="sui-screen-reader-text">Instagram</span>
146
  </a></li>
147
  </ul>
148
+ <?php endif; ?>
149
  </div>
150
  </div>
app/view/activator.php CHANGED
@@ -132,8 +132,10 @@
132
  </div>
133
  </div>
134
  </form>
135
- <img src="<?php echo wp_defender()->getPluginUrl() . '/assets/img/defender-activator.svg' ?>"
136
- class="sui-image sui-image-center"/>
 
 
137
  </div>
138
  <div class="sui-box activate-progress wd-hide">
139
  <div class="sui-box-body">
132
  </div>
133
  </div>
134
  </form>
135
+ <?php if ( strlen( wp_defender()->heroImage ) == 0 ): ?>
136
+ <img src="<?php echo wp_defender()->getPluginUrl() . '/assets/img/defender-activator.svg' ?>"
137
+ class="sui-image sui-image-center"/>
138
+ <?php endif; ?>
139
  </div>
140
  <div class="sui-box activate-progress wd-hide">
141
  <div class="sui-box-body">
app/view/dashboard.php CHANGED
@@ -9,15 +9,16 @@ $countAll = $hCount + $sCount;
9
  <h1 class="sui-header-title">
10
  <?php _e( "Dashboard", "defender-security" ) ?>
11
  </h1>
12
- <?php if ( wp_defender()->hideDocLinks === false ): ?>
13
  <div class="sui-actions-right">
14
  <div class="sui-actions-right">
15
- <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/" target="_blank" class="sui-button sui-button-ghost">
 
16
  <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
17
  </a>
18
  </div>
19
  </div>
20
- <?php endif; ?>
21
  </div>
22
  <div class="sui-box sui-summary <?php echo \WP_Defender\Behavior\Utils::instance()->getSummaryClass() ?>">
23
  <div class="sui-summary-image-space" aria-hidden="true"></div>
@@ -25,9 +26,35 @@ $countAll = $hCount + $sCount;
25
  <div class="sui-summary-details">
26
  <span class="sui-summary-large"><?php echo $countAll ?></span>
27
  <?php if ( $countAll > 0 ): ?>
28
- <i aria-hidden="true" class="sui-icon-info sui-error"></i>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  <?php else: ?>
 
 
30
  <i class="sui-icon-check-tick sui-success" aria-hidden="true"></i>
 
31
  <?php endif; ?>
32
  <span class="sui-summary-sub"><?php _e( "Security issues", "defender-security" ) ?></span>
33
  </div>
@@ -174,7 +201,7 @@ $countAll = $hCount + $sCount;
174
 
175
  </div>
176
  <?php endif; ?>
177
- <?php if ( wp_defender()->changeFooter && ! empty( wp_defender()->footerText ) ): ?>
178
  <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
179
  <?php else: ?>
180
  <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
9
  <h1 class="sui-header-title">
10
  <?php _e( "Dashboard", "defender-security" ) ?>
11
  </h1>
12
+ <?php if ( wp_defender()->hideDocLinks === false ): ?>
13
  <div class="sui-actions-right">
14
  <div class="sui-actions-right">
15
+ <a href="https://premium.wpmudev.org/docs/wpmu-dev-plugins/defender/" target="_blank"
16
+ class="sui-button sui-button-ghost">
17
  <i class="sui-icon-academy"></i> <?php _e( "View Documentation", "defender-security" ) ?>
18
  </a>
19
  </div>
20
  </div>
21
+ <?php endif; ?>
22
  </div>
23
  <div class="sui-box sui-summary <?php echo \WP_Defender\Behavior\Utils::instance()->getSummaryClass() ?>">
24
  <div class="sui-summary-image-space" aria-hidden="true"></div>
26
  <div class="sui-summary-details">
27
  <span class="sui-summary-large"><?php echo $countAll ?></span>
28
  <?php if ( $countAll > 0 ): ?>
29
+ <?php
30
+ $tooltips = "";
31
+ if ( $hCount == 1 && $sCount == 0 ) {
32
+ $tooltips = __( "You have one security tweak left to do. We recommend you action it, or ignore it if it's irrelevant.", "defender-security" );
33
+ } elseif ( $hCount == 0 && $sCount == 1 ) {
34
+ $tooltips = __( "We've detected a potential security risk in your file system. We recommend you take a look and action a fix, or ignore the file if it's harmless.", "defender-security" );
35
+ } elseif ( $hCount == 1 && $sCount == 1 ) {
36
+ $tooltips = __( "You have one security tweak left to do, and one potential security risk in your file system. We recommend you take a look and action fixes, or ignore the issues if they are harmless.", "defender-security" );
37
+ } elseif ( $hCount == 1 && $sCount > 1 ) {
38
+ $tooltips = sprintf( __( "You have one security tweak left to do, and %s potential security risks in your file system. We recommend you take a look and action fixes, or ignore the issues if they are harmless", "defender-security" ), $sCount );
39
+ } elseif ( $hCount > 1 && $sCount == 1 ) {
40
+ $tooltips = sprintf( __( "You have %s security tweaks left to do, and one potential security risk in your file system. We recommend you take a look and action fixes, or ignore the issues if they are harmless.", "defender-security" ), $hCount );
41
+ } elseif ( $hCount > 1 && $sCount > 1 ) {
42
+ $tooltips = sprintf( __( "You have %s security tweaks left to do, and %s potential security risks in your file system. We recommend you take a look and action fixes, or ignore the issues if they are harmless.", "defender-security" ), $hCount, $sCount );
43
+ } elseif ( $hCount > 1 && $sCount == 0 ) {
44
+ $tooltips = sprintf( __( "You have %d security tweaks left to do. We recommend you action it, or ignore it if it's irrelevant.", "defender-security" ), $hCount );
45
+ } elseif ( $hCount == 0 && $sCount > 1 ) {
46
+ $tooltips = sprintf( __( "We've detected %d potential security risks in your file system. We recommend you take a look and action a fix, or ignore the file if it's harmless.", "defender-security" ), $sCount );
47
+ }
48
+ ?>
49
+ <span class="sui-tooltip sui-tooltip-top-left sui-tooltip-constrained"
50
+ data-tooltip="<?php echo $tooltips ?>">
51
+ <i aria-hidden="true" class="sui-icon-info sui-warning"></i>
52
+ </span>
53
  <?php else: ?>
54
+ <span class="sui-tooltip sui-tooltip-top-left sui-tooltip-constrained"
55
+ data-tooltip="<?php esc_attr_e( "You don't have any outstanding security issues, nice work!", "defender-security" ) ?>">
56
  <i class="sui-icon-check-tick sui-success" aria-hidden="true"></i>
57
+ </span>
58
  <?php endif; ?>
59
  <span class="sui-summary-sub"><?php _e( "Security issues", "defender-security" ) ?></span>
60
  </div>
201
 
202
  </div>
203
  <?php endif; ?>
204
+ <?php if ( wp_defender()->changeFooter ): ?>
205
  <div class="sui-footer"><?php echo wp_defender()->footerText ?></div>
206
  <?php else: ?>
207
  <div class="sui-footer">Made with <i class="sui-icon-heart"></i> by WPMU DEV</div>
assets/css/styles.css CHANGED
@@ -230,9 +230,18 @@
230
  .wp-defender .hardener .sui-summary:not(.sui-unbranded) .sui-summary-image-space {
231
  display: block;
232
  }
 
 
 
233
  .wp-defender .hardener .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-summary-details {
234
  padding-left: 30px !important;
235
  }
 
 
 
 
 
 
236
  .wp-defender .hardener .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-list i {
237
  font-size: 16px;
238
  }
@@ -275,9 +284,18 @@
275
  .wp-defender .wdf-scanning .sui-summary:not(.sui-unbranded) .sui-summary-image-space {
276
  display: block;
277
  }
 
 
 
278
  .wp-defender .wdf-scanning .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-summary-details {
279
  padding-left: 30px !important;
280
  }
 
 
 
 
 
 
281
  .wp-defender .wdf-scanning .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-list i {
282
  font-size: 16px;
283
  }
@@ -301,79 +319,6 @@
301
  .wp-defender .wdf-scanning .issue-content .sui-box-body div {
302
  margin-bottom: 30px;
303
  }
304
- .wp-defender .wdf-scanning .issue-content .hljs {
305
- display: block;
306
- overflow-x: auto;
307
- padding: 0.5em;
308
- color: black;
309
- background-color: #FAFAFA;
310
- }
311
- .wp-defender .wdf-scanning .issue-content .hljs del {
312
- background: #FFA5A8;
313
- }
314
- .wp-defender .wdf-scanning .issue-content .hljs ins {
315
- background: #D1F1EA;
316
- text-decoration: none;
317
- }
318
- .wp-defender .wdf-scanning .issue-content .hljs-comment,
319
- .wp-defender .wdf-scanning .issue-content .hljs-quote,
320
- .wp-defender .wdf-scanning .issue-content .hljs-variable {
321
- color: #008000;
322
- }
323
- .wp-defender .wdf-scanning .issue-content .hljs-keyword,
324
- .wp-defender .wdf-scanning .issue-content .hljs-selector-tag,
325
- .wp-defender .wdf-scanning .issue-content .hljs-built_in,
326
- .wp-defender .wdf-scanning .issue-content .hljs-name,
327
- .wp-defender .wdf-scanning .issue-content .hljs-tag {
328
- color: #00f;
329
- }
330
- .wp-defender .wdf-scanning .issue-content .hljs-string,
331
- .wp-defender .wdf-scanning .issue-content .hljs-title,
332
- .wp-defender .wdf-scanning .issue-content .hljs-section,
333
- .wp-defender .wdf-scanning .issue-content .hljs-attribute,
334
- .wp-defender .wdf-scanning .issue-content .hljs-literal,
335
- .wp-defender .wdf-scanning .issue-content .hljs-template-tag,
336
- .wp-defender .wdf-scanning .issue-content .hljs-template-variable,
337
- .wp-defender .wdf-scanning .issue-content .hljs-type,
338
- .wp-defender .wdf-scanning .issue-content .hljs-addition {
339
- color: #a31515;
340
- }
341
- .wp-defender .wdf-scanning .issue-content .hljs-deletion,
342
- .wp-defender .wdf-scanning .issue-content .hljs-selector-attr,
343
- .wp-defender .wdf-scanning .issue-content .hljs-selector-pseudo,
344
- .wp-defender .wdf-scanning .issue-content .hljs-meta {
345
- color: #2b91af;
346
- }
347
- .wp-defender .wdf-scanning .issue-content .hljs-doctag {
348
- color: #808080;
349
- }
350
- .wp-defender .wdf-scanning .issue-content .hljs-attr {
351
- color: #f00;
352
- }
353
- .wp-defender .wdf-scanning .issue-content .hljs-symbol,
354
- .wp-defender .wdf-scanning .issue-content .hljs-bullet,
355
- .wp-defender .wdf-scanning .issue-content .hljs-link {
356
- color: #00b0e8;
357
- }
358
- .wp-defender .wdf-scanning .issue-content .hljs-emphasis {
359
- font-style: italic;
360
- }
361
- .wp-defender .wdf-scanning .issue-content .hljs-strong {
362
- font-weight: bold;
363
- }
364
- .wp-defender .wdf-scanning .issue-content .hljs-line-numbers {
365
- border-right: 1px solid #ccc;
366
- color: #999;
367
- -webkit-touch-callout: none;
368
- -webkit-user-select: none;
369
- -khtml-user-select: none;
370
- -moz-user-select: none;
371
- -ms-user-select: none;
372
- user-select: none;
373
- background-color: #F2F2F2;
374
- width: 40px;
375
- text-align: center;
376
- }
377
  .wp-defender .wdf-scanning .issue-content pre {
378
  border: 1px solid #E6E6E6;
379
  padding: 0;
@@ -384,6 +329,7 @@
384
  .wp-defender .wdf-scanning .issue-content pre code {
385
  border: none;
386
  border-radius: 0;
 
387
  }
388
  .wp-defender .wdf-scanning .sui-box-settings-row.sui-upsell-row {
389
  border-bottom: 1px solid #E6E6E6 !important;
@@ -532,9 +478,18 @@
532
  .wp-defender .def-dashboard .sui-summary:not(.sui-unbranded) .sui-summary-image-space {
533
  display: block;
534
  }
 
 
 
535
  .wp-defender .def-dashboard .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-summary-details {
536
  padding-left: 30px !important;
537
  }
 
 
 
 
 
 
538
  .wp-defender .def-dashboard .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-list i {
539
  font-size: 16px;
540
  }
@@ -640,3 +595,8 @@
640
  .wd-calendar .applyBtn, .wd-calendar .cancelBtn {
641
  display: none;
642
  }
 
 
 
 
 
230
  .wp-defender .hardener .sui-summary:not(.sui-unbranded) .sui-summary-image-space {
231
  display: block;
232
  }
233
+ .wp-defender .hardener .sui-summary:not(.sui-unbranded) .sui-summary-segment {
234
+ overflow: visible;
235
+ }
236
  .wp-defender .hardener .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-summary-details {
237
  padding-left: 30px !important;
238
  }
239
+ .wp-defender .hardener .sui-summary:not(.sui-unbranded) .sui-summary-segment span.sui-tooltip {
240
+ top: -22px;
241
+ }
242
+ .wp-defender .hardener .sui-summary:not(.sui-unbranded) .sui-summary-segment span.sui-tooltip i {
243
+ top: 0;
244
+ }
245
  .wp-defender .hardener .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-list i {
246
  font-size: 16px;
247
  }
284
  .wp-defender .wdf-scanning .sui-summary:not(.sui-unbranded) .sui-summary-image-space {
285
  display: block;
286
  }
287
+ .wp-defender .wdf-scanning .sui-summary:not(.sui-unbranded) .sui-summary-segment {
288
+ overflow: visible;
289
+ }
290
  .wp-defender .wdf-scanning .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-summary-details {
291
  padding-left: 30px !important;
292
  }
293
+ .wp-defender .wdf-scanning .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-summary-details span.sui-tooltip {
294
+ top: -22px;
295
+ }
296
+ .wp-defender .wdf-scanning .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-summary-details span.sui-tooltip i {
297
+ top: 0;
298
+ }
299
  .wp-defender .wdf-scanning .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-list i {
300
  font-size: 16px;
301
  }
319
  .wp-defender .wdf-scanning .issue-content .sui-box-body div {
320
  margin-bottom: 30px;
321
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
  .wp-defender .wdf-scanning .issue-content pre {
323
  border: 1px solid #E6E6E6;
324
  padding: 0;
329
  .wp-defender .wdf-scanning .issue-content pre code {
330
  border: none;
331
  border-radius: 0;
332
+ overflow: visible;
333
  }
334
  .wp-defender .wdf-scanning .sui-box-settings-row.sui-upsell-row {
335
  border-bottom: 1px solid #E6E6E6 !important;
478
  .wp-defender .def-dashboard .sui-summary:not(.sui-unbranded) .sui-summary-image-space {
479
  display: block;
480
  }
481
+ .wp-defender .def-dashboard .sui-summary:not(.sui-unbranded) .sui-summary-segment {
482
+ overflow: visible;
483
+ }
484
  .wp-defender .def-dashboard .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-summary-details {
485
  padding-left: 30px !important;
486
  }
487
+ .wp-defender .def-dashboard .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-summary-details span.sui-tooltip {
488
+ top: -22px;
489
+ }
490
+ .wp-defender .def-dashboard .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-summary-details span.sui-tooltip i {
491
+ top: 0;
492
+ }
493
  .wp-defender .def-dashboard .sui-summary:not(.sui-unbranded) .sui-summary-segment .sui-list i {
494
  font-size: 16px;
495
  }
595
  .wd-calendar .applyBtn, .wd-calendar .cancelBtn {
596
  display: none;
597
  }
598
+
599
+ .sui-color-accessible .wp-defender .iplockout #iplockout-table tbody tr td .badge {
600
+ color: white;
601
+ background: black;
602
+ }
assets/css/styles.css.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "mappings": ";;IA4HI,SAAS,EAAE,YAAY;;IAEvB,SAAS,EAAE,cAAc;AC9H7B,wBAAkB;EAChB,OAAO,EAAE,IAAI;EACb,SAAS,EAAE,IAAI;AAGjB,6CAAuC;EACrC,aAAa,EAAE,IAAI;AAGrB,iDAA2C;EACzC,YAAY,EAAE,CAAC;AAGjB,kDAA4C;EAC1C,aAAa,EAAE,CAAC;AAIhB,uBAAQ;EACN,UAAU,EAAE,UAAU;AAI1B,kCAA4B;EAAE,yBAAyB;EACrD,KAAK,EAAE,OAAO;AAGhB,wBAAkB;EAAE,6BAA6B;EAC/C,KAAK,EAAE,OAAO;EACd,OAAO,EAAE,CAAC;AAGZ,yBAAmB;EACjB,KAAK,EAAE,OAAO;EACd,OAAO,EAAE,CAAC;AAGZ,6BAAuB;EAAE,6BAA6B;EACpD,KAAK,EAAE,OAAO;AAGhB,sGAA2E;EACzE,UAAU,EAAE,OAAO;EACnB,MAAM,EAAE,iBAAiB;EACzB,KAAK,ECxCG,IAAI;EDyCZ,WAAW,EAAE,GAAG;EAChB,cAAc,EAAE,QAAQ;AAG1B,wBAAkB;EAChB,UAAU,EAAE,OAAO;EAEnB,yCAAiB;IACf,UAAU,EAAE,IAAI;EAGhB,2DAAY;IACV,KAAK,ECrDD,IAAI;IDsDR,WAAW,EAAE,GAAG;EAGhB,qDAAG;IACD,KAAK,EC1DH,IAAI;ID2DN,WAAW,EAAE,GAAG;AAMxB,qEAAwD;EACtD,MAAM,EAAE,iBAAiB;EACzB,6FAAY;IACV,KAAK,ECpEC,IAAI;IDqEV,WAAW,EAAE,GAAG;AAIpB,+DAAkD;EAShD,UAAU,EAAE,OAAO;EARnB,uFAAY;IACV,KAAK,EC3EC,IAAI;ID4EV,WAAW,EAAE,GAAG;IAChB,UAAU,EAAE,OAAO;EAErB,iGAAiB;IACf,UAAU,EAAE,IAAI;AAKpB,yFAAqE;EACnE,MAAM,EAAE,iBAAiB;AAG3B,yFAAqE;EACnE,MAAM,EAAE,iBAAiB;EACzB,UAAU,EAAE,OAAO;AAGrB,0KAAsJ;EACpJ,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,CAAC;AAGZ,+IAA2H;EACzH,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,IAAI;EAChB,OAAO,EAAE,CAAC;AAGZ,2JAAuI;EACrI,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,IAAI;EAChB,OAAO,EAAE,CAAC;AAGZ,8HAAwH;EACtH,gBAAgB,EC1GL,OAAO;ED2GlB,KAAK,EC1GO,IAAI;AD6GlB,wBAAkB;EAChB,KAAK,EC5GO,OAAO;ED6GnB,UAAU,EAAE,uBAA4B;AAG1C;oIAC8H;EAC5H,gBAAgB,EAAE,OAAO;AAG3B,8DAAiD;EAC/C,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,kBAAuB;AAGrC,yHAA8F;EAC5F,UAAU,ECnHE,OAAO;EDoHnB,KAAK,EAAE,OAAO;EACd,MAAM,EAAE,WAAW;EACnB,WAAW,EAAE,IAAI;AAGnB,2BAAqB;EACnB,IAAI,EAAE,gCAAgC;EACtC,OAAO,EAAE,QAAQ;AAGnB,yBAAmB;EACjB,KAAK,ECrIK,OAAO;EDsIjB,gBAAgB,EAAE,IAAI;EACtB,UAAU,EAAE,uBAAyB;EACrC,WAAW,EAAE,GAAG;EAChB,qBAAqB,EAAE,IAAI;EAC3B,kBAAkB,EAAE,IAAI;EACxB,aAAa,EAAE,IAAI;AAGrB,kGAA8E;EAC5E,UAAU,EAAE,kBAAoB;EAChC,KAAK,EAAE,IAAI;AAGb,gBAAU;EACR,UAAU,EAAE,CAAC;EACb,aAAa,EAAE,IAAI;EAEjB,kCAAa;IACX,OAAO,EAAE,MAAM;IACf,sCAAI;MACF,YAAY,EAAE,GAAG;MACjB,OAAO,EAAE,YAAY;MACrB,cAAc,EAAE,MAAM;EAG1B,iCAAY;IACV,OAAO,EAAE,MAAM;AAKrB,qBAAe;EACb,WAAW,ECnLK,8BAA8B;EDoL9C,iCAAY;IACV,WAAW,EAAE,IAAI;IACjB,KAAK,ECpLC,IAAI;IDqLV,SAAS,EAAE,IAAI;IACf,WAAW,ECzLF,kBAAkB;ID0L3B,cAAc,EAAE,UAAU;EAE5B,kCAAa;IACX,KAAK,ECzLM,IAAI;ID0Lf,SAAS,EAAE,IAAI;IACf,oCAAE;MACA,cAAc,EAAE,GAAG;AAKzB,eAAS;EACP,QAAQ,EAAE,QAAQ;EAClB,0BAAW;IACT,QAAQ,EAAE,QAAQ;IAClB,6BAAG;MACD,KAAK,ECvMD,IAAI;MDwMR,OAAO,EAAE,YAAY;MACrB,SAAS,EAAE,IAAI;MACf,QAAQ,EAAE,OAAO;IAEnB,qCAAW;MACT,YAAY,EAAE,IAAI;MAClB,cAAc,EAAE,MAAM;IAExB,mCAAS;MACP,WAAW,EAAE,IAAI;MACjB,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,IAAI;IAEX,kCAAQ;MACN,UAAU,EAAE,GAAG;IAGjB,kCAAQ;MACN,WAAW,EAAE,GAAG;MAChB,KAAK,EAAE,KAAK;MACZ,WAAW,EAAE,IAAI;MACjB,UAAU,EAAE,IAAI;IAElB,gCAAM;MAMJ,KAAK,EAAE,KAAK;MALZ,uCAAO;QACL,WAAW,EAAE,IAAI;QACjB,KAAK,EAAE,IAAI;QACX,YAAY,EAAE,IAAI;MAGpB,kDAAkB;QAChB,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,YAAY;QACrB,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,KAAK;QAChB,UAAU,EAAE,GAAG;IAGnB,mCAAQ;MACN,YAAY,EAAE,IAAI;EAGtB,4BAAa;IACX,KAAK,ECjPG,IAAI;IDkPZ,mCAAO;MACL,KAAK,ECrPD,IAAI;AD0Pd,cAAQ;EACN,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,4BAAc;IACZ,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;EAEd,kCAAoB;IAClB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,GAAG;IACR,UAAU,EAAE,IAAI;EAElB,6DAA+C;IAC7C,WAAW,EAAE,IAAI;EAEnB,8DAAgD;IAC9C,IAAI,EAAE,IAAI;EAEZ,uDAAyC;IACvC,UAAU,EAAE,OAAO;EAErB,mCAAqB;IACnB,UAAU,EAAE,OAAO;AAKrB,6BAAW;EACT,KAAK,EAAE,IAAI;AAKb,qBAAK;EACH,gBAAgB,EAAE,8BAA8B;EAChD,iBAAiB,EAAE,SAAS;EAC5B,mBAAmB,EAAE,QAAQ;EAC7B,cAAc,EAAE,gBAAgB;AAKlC,yBAAK;EACH,gBAAgB,EAAE,8BAA8B;EAChD,iBAAiB,EAAE,SAAS;EAC5B,mBAAmB,EAAE,QAAQ;EAC7B,cAAc,EAAE,gBAAgB;EAChC,qEAAsE;IALxE,yBAAK;MAMF,gBAAgB,EAAC,8BAClB;AAIJ,mBAAa;EACX,gBAAgB,EAAE,KAAK;EACvB,UAAU,EAAE,IAAI;EAChB,OAAO,EAAE,IAAI;EACb,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,iBAAsB;EAC9B,yCAAsB;IACpB,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,8BAA8B;IAC3C,6DAAoB;MAClB,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,IAAI;MACT,IAAI,EAAE,IAAI;MACV,MAAM,EAAE,OAAO;IAEjB,6DAAoB;MAClB,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,IAAI;MACT,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,OAAO;IAEjB,8DAAqB;MACnB,UAAU,EAAE,MAAM;EAGtB,2CAAwB;IACtB,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,cAAc;IAC1B,WAAW,EAAE,IAAI;IACjB,8FAAO;MACL,OAAO,EAAE,GAAG;MACZ,kGAAE;QACA,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;IAGhB,8CAAG;MACD,UAAU,EAAE,MAAM;EAGtB,wCAAqB;IACnB,UAAU,EAAE,OAAO;IACnB,0CAAE;MACA,KAAK,EAAE,IAAI;EAIf,8CAA2B;IACzB,UAAU,EAAE,OAAO;IACnB,gDAAE;MACA,KAAK,EAAE,IAAI;EAIf,6DAAsB;IACpB,OAAO,EAAE,IAAI;AAIjB,QAAE;EACA,KAAK,EAAE,OAAO;AAGhB,8BAAiB;EACf,KAAK,EAAE,OAAO;AAId,yBAAM;EACJ,UAAU,EAAE,sBAAqB;AAEnC,wBAAK;EAYH,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,SAAS;EACjB,KAAK,EAAE,IAAI;EACX,IAAI,EAAE,CAAC;EACP,SAAS,EAAE,KAAK;EAChB,OAAO,EAAE,IAAI;EAhBb,+BAAO;IAIL,MAAM,EAAE,sBAAsB;IAC9B,OAAO,EAAE,MAAM;IAJf,sCAAO;MACL,OAAO,EAAE,MAAM;IAIjB,kCAAG;MACD,KAAK,ECjYH,IAAI;MDkYN,SAAS,EAAE,IAAI;AAUrB,+BAAY;EACV,OAAO,EAAE,IAAI;AAKf,8BAAK;EACH,MAAM,EAAE,SAAS;ADpNnB,2DAAsE;ECyNtE,mBAAa;IACX,KAAK,EAAE,IAAI;IACX,IAAI,EAAE,IAAI;ADnOZ,oCAA4C;ECwO5C,mBAAa;IACX,KAAK,EAAE,IAAI;IACX,IAAI,EAAE,CAAC;IACP,+BAAY;MACV,OAAO,EAAE,IAAI;AAKnB,6BAAuB;EACrB,cAAc,EAAE,eAAe;EAC/B,WAAW,EAAE,MAAM;AAGrB,sBAAgB;EACd,cAAc,EAAE,IAAI;EACpB,IAAI,EAAE,gCAAgC;AEnbxC,sBAAgB;EACd,gBAAgB,EAAE,6BAA6B;EAC/C,iBAAiB,EAAE,SAAS;EAC5B,mBAAmB,EAAE,SAAS;AAGhC,mBAAa;EACX,gBAAgB,EAAE,mCAAmC;EACrD,iBAAiB,EAAE,SAAS;EAC5B,mBAAmB,EAAE,SAAS;EAC9B,cAAc,EAAE,KAAK;EACrB,QAAQ,EAAE,MAAM;EAChB,wBAAK;IACH,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,mBAAmB;IAC3B,OAAO,EAAE,MAAM;EAEjB,iCAAc;IACZ,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;EAEb,yBAAM;IACJ,UAAU,EAAE,IAAI;AAIpB,mCAA6B;EAC3B,gBAAgB,EAAE,+BAA+B;EAE/C,qDAAI;IACF,KAAK,EAAE,GAAG;AAKhB,wBAAkB;EAChB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,CAAC;EACN,IAAI,EAAE,KAAK;EACX,OAAO,EAAE,GAAG;EACZ,OAAO,EAAE,GAAG;EACZ,UAAU,EAAE,OAAO;AAGrB,iBAAU;EACR,UAAU,EAAE,eAAe;AAG7B,oBAAc;EACZ,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,CAAC;EACN,IAAI,EAAE,CAAC;EACP,OAAO,EAAE,GAAG;EACZ,OAAO,EAAE,GAAG;EACZ,UAAU,EAAE,OAAO;AAGrB,kCAA4B;EAC1B,gBAAgB,EAAE,0BAA0B;EAC5C,iBAAiB,EAAE,SAAS;EAC5B,mBAAmB,EAAE,QAAQ;EAC7B,cAAc,EAAE,GAAG;AAGrB,iCAA2B;EACzB,cAAc,EAAE,KAAK;EACrB,gBAAgB,EAAE,8BAA8B;EAChD,eAAe,EAAE,GAAG;EACpB,iBAAiB,EAAE,SAAS;EAC5B,mBAAmB,EAAE,QAAQ;AAI7B,mCAAK;EACH,gBAAgB,EAAE,mCAAmC;EACrD,iBAAiB,EAAE,SAAS;EAC5B,mBAAmB,EAAE,OAAO;EAC5B,cAAc,EAAE,gBAAgB;EAChC,iDAAc;IACZ,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IHqGf,oCAA4C;MGxG1C,iDAAc;QAKV,MAAM,EAAE,CAAC;AAMjB,2BAAqB;EAcnB,QAAQ,EAAE,QAAQ;EAblB,oEAAa;IACX,OAAO,EAAE,CAAC;EAEZ,+BAAI;IACF,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;IACP,OAAO,EAAE,CAAC;IACV,UAAU,EAAE,KAAK;IACjB,OAAO,EAAE,GAAG;EAGd,uCAAY;IACV,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,CAAC;IACV,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,IAAI;IACT,KAAK,EAAE,CAAC;AAIZ,oBAAc;EACZ,QAAQ,EAAE,MAAM;EAChB,WAAW,EAAE,EAAE;EACf,wBAAI;IACF,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAAE,GAAG;IACV,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,SAAS;IAClB,aAAa,EAAE,GAAG;IAClB,gBAAgB,EDtFV,OAAO;ICuFb,SAAS,EAAE,IAAI;IACf,KAAK,ED7HC,IAAI;IC8HV,WAAW,EAAE,IAAI;IHyDnB,oCAA4C;MGlE5C,wBAAI;QAWA,KAAK,EAAE,GAAG;EAGd,+BAAW;IACT,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,YAAY;IACrB,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,sBAAsB;IAC9B,cAAc,EAAE,MAAM;EAExB,+BAAW;IACT,kBAAkB,EDvGZ,OAAO;ICwGb,QAAQ,EAAE,QAAQ;IAClB,IAAI,EAAE,KAAK;IACX,GAAG,EAAE,GAAG;EAEV,sBAAE;IACA,KAAK,EDlJC,IAAI;ICmJV,eAAe,EAAE,SAAS;IAC1B,MAAM,EAAE,OAAO;IACf,WAAW,EAAE,GAAG;;ACjJpB,UASC;EARC,WAAW,EAAE,eAAe;EAC5B,GAAG,EAAE,yBAAyB;EAC9B,GAAG,EAAE,uMAG2C;EAChD,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,MAAM;AAGpB,YAAa;EACX,cAAc,EAAE,QAAQ;EACxB,WAAW,EFpBA,kBAAkB;EEqB7B,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,GAAG;EAChB,WAAW,EAAE,IAAI;EACjB,MAAM,EAAE,eAAe;EACvB,sBAAsB,EAAE,sBAAsB;ECmChD;;;;IAIE;EDrCA,kBAAM;IACJ,eAAe,EAAE,QAAQ;EC5B7B,kBAAM;IACJ,cAAc,EAAE,IAAI;EAGtB,mBAAO;IACL,aAAa,EAAE,IAAI;EAGrB,wBAAY;IACV,MAAM,EAAE,YAAY;EAGtB,iBAAK;IACH,aAAa,EAAE,iBAAsB;EAGvC,kBAAM;IACJ,SAAS,EAAE,IAAI;IACf,KAAK,EHZI,IAAI;IGab,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,CAAC;IACV,WAAW,EAAE,IAAI;EAGnB,mBAAO;IACL,KAAK,EAAE,IAAI;EAGb,yBAAa;IACX,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,CAAC;IACT,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,MAAM;EAGpB,qBAAS;IACP,OAAO,EAAE,eAAe;EAG1B,wBAAY;IACV,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,gBAAgB,EAAE,IAAI;IACtB,OAAO,EAAE,GAAG;IACZ,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;IACP,OAAO,EAAE,GAAG;IACZ,0BAAE;MACA,SAAS,EAAE,IAAI;MACf,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,GAAG;MACR,IAAI,EAAE,GAAG;MACT,UAAU,EAAE,KAAK;MACjB,WAAW,EAAE,KAAK;EAStB,kBAAM;IACJ,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,KAAK;IACjB,KAAK,EAAE,KAAK;IACZ,sBAAI;MACF,UAAU,EAAE,OAAO;IAErB,sBAAI;MACF,UAAU,EAAE,OAAO;MACnB,eAAe,EAAE,IAAI;EAIzB;;6BAEe;IACb,KAAK,EAAE,OAAO;EAGhB;;;;wBAIU;IACR,KAAK,EAAE,IAAI;EAGb;;;;;;;;6BAQe;IACb,KAAK,EAAE,OAAO;EAGhB;;;yBAGW;IACT,KAAK,EAAE,OAAO;EAGhB,yBAAa;IACX,KAAK,EAAE,OAAO;EAGhB,uBAAW;IACT,KAAK,EAAE,IAAI;EAGb;;yBAEW;IACT,KAAK,EAAE,OAAO;EAGhB,2BAAe;IACb,UAAU,EAAE,MAAM;EAGpB,yBAAa;IACX,WAAW,EAAE,IAAI;EAGnB,+BAAmB;IACjB,UAAU,EAAE,KAAK;IACjB,YAAY,EAAE,cAAc;IAC5B,KAAK,EAAE,IAAI;IACX,qBAAqB,EAAE,IAAI;IAC3B,mBAAmB,EAAE,IAAI;IACzB,kBAAkB,EAAE,IAAI;IACxB,gBAAgB,EAAE,IAAI;IACtB,eAAe,EAAE,IAAI;IACrB,WAAW,EAAE,IAAI;EAGnB,gBAAI;IACF,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,CAAC;IACV,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,MAAM;;;IL5BhB,SAAS,EAAE,YAAY;;IAEvB,SAAS,EAAE,cAAc;EMzH3B,sBAAe;IACb,OAAO,EAAE,KAAW;ENqLtB,oCAA4C;IMpL5C,6BAAsB;MAElB,OAAO,EAAE,gBAAsB;ENsLnC,oCAAsC;IMrLtC,6BAAsB;MAElB,OAAO,EAAE,gBAAsB;ENuLnC,2DAAsE;IMtLtE,kCAA2B;MAEvB,OAAO,EAAE,gBAAsB;ENwLnC,oCAA6C;IMvL7C,4BAAqB;MAEjB,OAAO,EAAE,gBAAsB;ENyLnC,oCAAuC;IMxLvC,8BAAuB;MAEnB,OAAO,EAAE,gBAAsB;EN0LnC,4DAA0E;IMzL1E,mCAA4B;MAExB,OAAO,EAAE,gBAAsB;EN2LnC,qCAA0C;IM1L1C,iCAA0B;MAEtB,OAAO,EAAE,gBAAsB;EAtBnC,qBAAe;IACb,OAAO,EAAE,IAAW;ENqLtB,oCAA4C;IMpL5C,4BAAsB;MAElB,OAAO,EAAE,eAAsB;ENsLnC,oCAAsC;IMrLtC,4BAAsB;MAElB,OAAO,EAAE,eAAsB;ENuLnC,2DAAsE;IMtLtE,iCAA2B;MAEvB,OAAO,EAAE,eAAsB;ENwLnC,oCAA6C;IMvL7C,2BAAqB;MAEjB,OAAO,EAAE,eAAsB;ENyLnC,oCAAuC;IMxLvC,6BAAuB;MAEnB,OAAO,EAAE,eAAsB;EN0LnC,4DAA0E;IMzL1E,kCAA4B;MAExB,OAAO,EAAE,eAAsB;EN2LnC,qCAA0C;IM1L1C,gCAA0B;MAEtB,OAAO,EAAE,eAAsB;EAtBnC,uBAAe;IACb,OAAO,EAAE,MAAW;ENqLtB,oCAA4C;IMpL5C,8BAAsB;MAElB,OAAO,EAAE,iBAAsB;ENsLnC,oCAAsC;IMrLtC,8BAAsB;MAElB,OAAO,EAAE,iBAAsB;ENuLnC,2DAAsE;IMtLtE,mCAA2B;MAEvB,OAAO,EAAE,iBAAsB;ENwLnC,oCAA6C;IMvL7C,6BAAqB;MAEjB,OAAO,EAAE,iBAAsB;ENyLnC,oCAAuC;IMxLvC,+BAAuB;MAEnB,OAAO,EAAE,iBAAsB;EN0LnC,4DAA0E;IMzL1E,oCAA4B;MAExB,OAAO,EAAE,iBAAsB;EN2LnC,qCAA0C;IM1L1C,kCAA0B;MAEtB,OAAO,EAAE,iBAAsB;EAtBnC,6BAAe;IACb,OAAO,EAAE,YAAW;ENqLtB,oCAA4C;IMpL5C,oCAAsB;MAElB,OAAO,EAAE,uBAAsB;ENsLnC,oCAAsC;IMrLtC,oCAAsB;MAElB,OAAO,EAAE,uBAAsB;ENuLnC,2DAAsE;IMtLtE,yCAA2B;MAEvB,OAAO,EAAE,uBAAsB;ENwLnC,oCAA6C;IMvL7C,mCAAqB;MAEjB,OAAO,EAAE,uBAAsB;ENyLnC,oCAAuC;IMxLvC,qCAAuB;MAEnB,OAAO,EAAE,uBAAsB;EN0LnC,4DAA0E;IMzL1E,0CAA4B;MAExB,OAAO,EAAE,uBAAsB;EN2LnC,qCAA0C;IM1L1C,wCAA0B;MAEtB,OAAO,EAAE,uBAAsB;EAtBnC,4BAAe;IACb,OAAO,EAAE,WAAW;ENqLtB,oCAA4C;IMpL5C,mCAAsB;MAElB,OAAO,EAAE,sBAAsB;ENsLnC,oCAAsC;IMrLtC,mCAAsB;MAElB,OAAO,EAAE,sBAAsB;ENuLnC,2DAAsE;IMtLtE,wCAA2B;MAEvB,OAAO,EAAE,sBAAsB;ENwLnC,oCAA6C;IMvL7C,kCAAqB;MAEjB,OAAO,EAAE,sBAAsB;ENyLnC,oCAAuC;IMxLvC,oCAAuB;MAEnB,OAAO,EAAE,sBAAsB;EN0LnC,4DAA0E;IMzL1E,yCAA4B;MAExB,OAAO,EAAE,sBAAsB;EN2LnC,qCAA0C;IM1L1C,uCAA0B;MAEtB,OAAO,EAAE,sBAAsB;ENTnC,+BAAO;IACL,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,KAAK;EMalB,4BAAe;IACb,KAAK,EAAE,IAAI;EAEb,6BAAgB;IACd,KAAK,EAAE,KAAK;EAId,wBAAW;IACT,QAAQ,EAAE,iBAAiB;EAI7B,wBAAW;IN8FT,MAAM,EADU,CAAC;IAEjB,IAAI,EAFY,CAAC;IAGjB,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAJW,CAAC;IAKjB,GAAG,EALa,CAAC;EMxFnB,+BAAkB;IAChB,UAAU,EAAE,MAAM;EAEpB,2BAAc;IACZ,UAAU,EAAE,IAAI;EAElB,4BAAe;IACb,UAAU,EAAE,KAAK;EAInB,uBAAU;IACR,OAAO,EAAE,eAAe;EN2HxB,oCAA4C;IMzH9C,8BAAiB;MAEb,OAAO,EAAE,eAAe;EN2H1B,oCAAsC;IMzHxC,8BAAiB;MAEb,OAAO,EAAE,eAAe;EN2H1B,2DAAsE;IMzHxE,mCAAsB;MAElB,OAAO,EAAE,eAAe;EN2H1B,oCAA6C;IMzH/C,6BAAgB;MAEZ,OAAO,EAAE,eAAe;EN2H1B,oCAAuC;IMzHzC,+BAAkB;MAEd,OAAO,EAAE,eAAe;EN2H1B,4DAA0E;IMzH5E,oCAAuB;MAEnB,OAAO,EAAE,eAAe;EN2H1B,qCAA0C;IMzH5C,kCAAqB;MAEjB,OAAO,EAAE,eAAe;EAI5B,yBAAY;IACV,cAAc,EAAE,IAAI;EAEtB,2BAAc;IACZ,MAAM,EAAE,YAAY;EAEtB,4BAAe;IACb,OAAO,EAAE,YAAY;EAEvB,6BAAgB;IN6Dd,qBAAqB,EAAE,IAAI;IAC3B,mBAAmB,EAAE,IAAI;IACzB,gBAAgB,EAAE,IAAI;IACtB,eAAe,EAAE,IAAI;IACrB,WAAW,EAAE,IAAI;EO1KnB,oBAAO;IACL,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,CAAC;IACb,SAAS,EAAE,CAAC;IACZ,WAAW,EAAE,CAAC;IACd,OAAO,EAAE,IAAI;IACb,mDAAgC;MAC9B,IAAI,EAAE,IAAI;IACZ,iDAA8B;MAC5B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,IAAI;IACb,2DAAwC;MACtC,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,GAAG;IACZ,uDAAoC;MAClC,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,QAAQ;IACjB,iDAA8B;MAC5B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,GAAG;IACZ,sDAAmC;MACjC,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,QAAQ;IACjB,wDAAqC;MACnC,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,GAAG;IACZ,kEAA+C;MAC7C,WAAW,EAAE,GAAG;IAClB,8DAA2C;MACzC,WAAW,EAAE,QAAQ;IACvB,wDAAqC;MACnC,WAAW,EAAE,GAAG;IAClB,6DAA0C;MACxC,WAAW,EAAE,QAAQ;IACvB,+DAA4C;MAC1C,WAAW,EAAE,GAAG;IAEhB,8CAA+B;MAC7B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,aAAgB;IACzB,qDAAsC;MACpC,WAAW,EAAE,aAAgB;IAJ/B,8CAA+B;MAC7B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,cAAgB;IACzB,qDAAsC;MACpC,WAAW,EAAE,cAAgB;IAJ/B,8CAA+B;MAC7B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,GAAgB;IACzB,qDAAsC;MACpC,WAAW,EAAE,GAAgB;IAJ/B,8CAA+B;MAC7B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,cAAgB;IACzB,qDAAsC;MACpC,WAAW,EAAE,cAAgB;IAJ/B,8CAA+B;MAC7B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,cAAgB;IACzB,qDAAsC;MACpC,WAAW,EAAE,cAAgB;IAJ/B,8CAA+B;MAC7B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,GAAgB;IACzB,qDAAsC;MACpC,WAAW,EAAE,GAAgB;IAJ/B,8CAA+B;MAC7B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,cAAgB;IACzB,qDAAsC;MACpC,WAAW,EAAE,cAAgB;IAJ/B,8CAA+B;MAC7B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,cAAgB;IACzB,qDAAsC;MACpC,WAAW,EAAE,cAAgB;IAJ/B,8CAA+B;MAC7B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,GAAgB;IACzB,qDAAsC;MACpC,WAAW,EAAE,GAAgB;IAJ/B,+CAA+B;MAC7B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,cAAgB;IACzB,sDAAsC;MACpC,WAAW,EAAE,cAAgB;IAJ/B,+CAA+B;MAC7B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,cAAgB;IACzB,sDAAsC;MACpC,WAAW,EAAE,cAAgB;IAJ/B,+CAA+B;MAC7B,IAAI,EAAE,IAAI;MACV,KAAK,EAAE,IAAgB;IACzB,sDAAsC;MACpC,WAAW,EAAE,IAAgB;IPkJjC,oCAA4C;MOhJ1C,qCAAkB;QAChB,IAAI,EAAE,IAAI;MACZ,mCAAgB;QACd,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAI;MACb,6CAA0B;QACxB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAG;MACZ,yCAAsB;QACpB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,QAAQ;MACjB,mCAAgB;QACd,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAG;MACZ,wCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,QAAQ;MACjB,0CAAuB;QACrB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAG;MACZ,oDAAiC;QAC/B,WAAW,EAAE,GAAG;MAClB,gDAA6B;QAC3B,WAAW,EAAE,QAAQ;MACvB,0CAAuB;QACrB,WAAW,EAAE,GAAG;MAClB,+CAA4B;QAC1B,WAAW,EAAE,QAAQ;MACvB,iDAA8B;QAC5B,WAAW,EAAE,GAAG;MAEhB,gCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,aAAgB;MACzB,uCAAwB;QACtB,WAAW,EAAE,aAAgB;MAJ/B,gCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,uCAAwB;QACtB,WAAW,EAAE,cAAgB;MAJ/B,gCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAgB;MACzB,uCAAwB;QACtB,WAAW,EAAE,GAAgB;MAJ/B,gCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,uCAAwB;QACtB,WAAW,EAAE,cAAgB;MAJ/B,gCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,uCAAwB;QACtB,WAAW,EAAE,cAAgB;MAJ/B,gCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAgB;MACzB,uCAAwB;QACtB,WAAW,EAAE,GAAgB;MAJ/B,gCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,uCAAwB;QACtB,WAAW,EAAE,cAAgB;MAJ/B,gCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,uCAAwB;QACtB,WAAW,EAAE,cAAgB;MAJ/B,gCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAgB;MACzB,uCAAwB;QACtB,WAAW,EAAE,GAAgB;MAJ/B,iCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,wCAAwB;QACtB,WAAW,EAAE,cAAgB;MAJ/B,iCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,wCAAwB;QACtB,WAAW,EAAE,cAAgB;MAJ/B,iCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAgB;MACzB,wCAAwB;QACtB,WAAW,EAAE,IAAgB;IPiHnC,oCAAsC;MO/GpC,qEAAY;QAEV,IAAI,EAAE,IAAI;MACZ,iEAAU;QAER,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAI;MACb,qFAAoB;QAElB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAG;MACZ,6EAAgB;QAEd,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,QAAQ;MACjB,iEAAU;QAER,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAG;MACZ,2EAAe;QAEb,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,QAAQ;MACjB,+EAAiB;QAEf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAG;MACZ,mGAA2B;QAEzB,WAAW,EAAE,GAAG;MAClB,2FAAuB;QAErB,WAAW,EAAE,QAAQ;MACvB,+EAAiB;QAEf,WAAW,EAAE,GAAG;MAClB,yFAAsB;QAEpB,WAAW,EAAE,QAAQ;MACvB,6FAAwB;QAEtB,WAAW,EAAE,GAAG;MAEhB,2DAAW;QAET,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,aAAgB;MACzB,yEAAkB;QAEhB,WAAW,EAAE,aAAgB;MAN/B,2DAAW;QAET,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,yEAAkB;QAEhB,WAAW,EAAE,cAAgB;MAN/B,2DAAW;QAET,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAgB;MACzB,yEAAkB;QAEhB,WAAW,EAAE,GAAgB;MAN/B,2DAAW;QAET,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,yEAAkB;QAEhB,WAAW,EAAE,cAAgB;MAN/B,2DAAW;QAET,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,yEAAkB;QAEhB,WAAW,EAAE,cAAgB;MAN/B,2DAAW;QAET,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAgB;MACzB,yEAAkB;QAEhB,WAAW,EAAE,GAAgB;MAN/B,2DAAW;QAET,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,yEAAkB;QAEhB,WAAW,EAAE,cAAgB;MAN/B,2DAAW;QAET,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,yEAAkB;QAEhB,WAAW,EAAE,cAAgB;MAN/B,2DAAW;QAET,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAgB;MACzB,yEAAkB;QAEhB,WAAW,EAAE,GAAgB;MAN/B,6DAAW;QAET,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,2EAAkB;QAEhB,WAAW,EAAE,cAAgB;MAN/B,6DAAW;QAET,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,2EAAkB;QAEhB,WAAW,EAAE,cAAgB;MAN/B,6DAAW;QAET,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAgB;MACzB,2EAAkB;QAEhB,WAAW,EAAE,IAAgB;IP0EnC,oCAAuC;MOxErC,sCAAmB;QACjB,IAAI,EAAE,IAAI;MACZ,oCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAI;MACb,8CAA2B;QACzB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAG;MACZ,0CAAuB;QACrB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,QAAQ;MACjB,oCAAiB;QACf,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAG;MACZ,yCAAsB;QACpB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,QAAQ;MACjB,2CAAwB;QACtB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAG;MACZ,qDAAkC;QAChC,WAAW,EAAE,GAAG;MAClB,iDAA8B;QAC5B,WAAW,EAAE,QAAQ;MACvB,2CAAwB;QACtB,WAAW,EAAE,GAAG;MAClB,gDAA6B;QAC3B,WAAW,EAAE,QAAQ;MACvB,kDAA+B;QAC7B,WAAW,EAAE,GAAG;MAEhB,iCAAkB;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,aAAgB;MACzB,wCAAyB;QACvB,WAAW,EAAE,aAAgB;MAJ/B,iCAAkB;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,wCAAyB;QACvB,WAAW,EAAE,cAAgB;MAJ/B,iCAAkB;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAgB;MACzB,wCAAyB;QACvB,WAAW,EAAE,GAAgB;MAJ/B,iCAAkB;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,wCAAyB;QACvB,WAAW,EAAE,cAAgB;MAJ/B,iCAAkB;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,wCAAyB;QACvB,WAAW,EAAE,cAAgB;MAJ/B,iCAAkB;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAgB;MACzB,wCAAyB;QACvB,WAAW,EAAE,GAAgB;MAJ/B,iCAAkB;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,wCAAyB;QACvB,WAAW,EAAE,cAAgB;MAJ/B,iCAAkB;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,wCAAyB;QACvB,WAAW,EAAE,cAAgB;MAJ/B,iCAAkB;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAgB;MACzB,wCAAyB;QACvB,WAAW,EAAE,GAAgB;MAJ/B,kCAAkB;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,yCAAyB;QACvB,WAAW,EAAE,cAAgB;MAJ/B,kCAAkB;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,yCAAyB;QACvB,WAAW,EAAE,cAAgB;MAJ/B,kCAAkB;QAChB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAgB;MACzB,yCAAyB;QACvB,WAAW,EAAE,IAAgB;IP6CnC,qCAA0C;MO3CxC,yCAAsB;QACpB,IAAI,EAAE,IAAI;MACZ,uCAAoB;QAClB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAI;MACb,iDAA8B;QAC5B,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAG;MACZ,6CAA0B;QACxB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,QAAQ;MACjB,uCAAoB;QAClB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAG;MACZ,4CAAyB;QACvB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,QAAQ;MACjB,8CAA2B;QACzB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAG;MACZ,wDAAqC;QACnC,WAAW,EAAE,GAAG;MAClB,oDAAiC;QAC/B,WAAW,EAAE,QAAQ;MACvB,8CAA2B;QACzB,WAAW,EAAE,GAAG;MAClB,mDAAgC;QAC9B,WAAW,EAAE,QAAQ;MACvB,qDAAkC;QAChC,WAAW,EAAE,GAAG;MAEhB,oCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,aAAgB;MACzB,2CAA4B;QAC1B,WAAW,EAAE,aAAgB;MAJ/B,oCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,2CAA4B;QAC1B,WAAW,EAAE,cAAgB;MAJ/B,oCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAgB;MACzB,2CAA4B;QAC1B,WAAW,EAAE,GAAgB;MAJ/B,oCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,2CAA4B;QAC1B,WAAW,EAAE,cAAgB;MAJ/B,oCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,2CAA4B;QAC1B,WAAW,EAAE,cAAgB;MAJ/B,oCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAgB;MACzB,2CAA4B;QAC1B,WAAW,EAAE,GAAgB;MAJ/B,oCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,2CAA4B;QAC1B,WAAW,EAAE,cAAgB;MAJ/B,oCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,2CAA4B;QAC1B,WAAW,EAAE,cAAgB;MAJ/B,oCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,GAAgB;MACzB,2CAA4B;QAC1B,WAAW,EAAE,GAAgB;MAJ/B,qCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,4CAA4B;QAC1B,WAAW,EAAE,cAAgB;MAJ/B,qCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAgB;MACzB,4CAA4B;QAC1B,WAAW,EAAE,cAAgB;MAJ/B,qCAAqB;QACnB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAgB;MACzB,4CAA4B;QAC1B,WAAW,EAAE,IAAgB;EAErC,qBAAQ;IACN,WAAW,EAAE,KAAK;IAClB,YAAY,EAAE,KAAK;IACnB,UAAU,EAAE,KAAK;IACjB,gCAAY;MACV,aAAa,EAAE,KAAK;IACtB,sCAAkB;MAChB,aAAa,EAAE,IAAI;IAErB,iCAAa;MACX,eAAe,EAAE,MAAM;IACzB,gCAAY;MACV,WAAW,EAAE,CAAC;MACd,YAAY,EAAE,CAAC;MACf,UAAU,EAAE,CAAC;MACb,2CAAY;QACV,aAAa,EAAE,CAAC;MAClB,iDAAkB;QAChB,aAAa,EAAE,IAAI;MACrB,0CAAW;QACT,MAAM,EAAE,CAAC;QACT,OAAO,EAAE,CAAC;IPnCd,oCAAsC;MOoCtC,6BAAS;QAGL,SAAS,EAAE,IAAI;QACf,uCAAW;UACT,SAAS,EAAE,QAAQ;UACnB,OAAO,EAAE,IAAI;UACb,KAAK,EAAE,QAAQ;UACf,iDAAW;YACT,WAAW,EAAE,CAAC;IACtB,+BAAW;MACT,OAAO,EAAE,IAAI;IACf,kCAAc;MACZ,SAAS,EAAE,IAAI;IACjB,kCAAc;MACZ,WAAW,EAAE,MAAM;IPnDrB,oCAAsC;MOsDpC,sCAAkB;QAChB,OAAO,EAAE,IAAI;IP3CjB,oCAAuC;MO8CrC,gCAAY;QACV,OAAO,EAAE,IAAI;EC1PnB,cAAE;IACA,aAAa,EAAE,CAAC;EAGlB,8BAAkB;IAChB,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;IACjB,WAAW,ENLK,8BAA8B;IMM9C,UAAU,EAAE,IAAI;IAChB,KAAK,ENLG,IAAI;IMMZ,cAAc,EAAE,SAAS;IACzB,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;IACjB,mCAAK;MACH,KAAK,ENVG,IAAI;MMWZ,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,GAAG;MAChB,WAAW,ENlBF,kBAAkB;MMmB3B,KAAK,EAAE,KAAK;MACZ,cAAc,EAAE,IAAI;MACpB,2CAAQ;QACN,WAAW,EAAE,IAAI;MAEnB,wCAAK;QACH,OAAO,EAAE,MAAM;EAKrB,yBAAa;IACX,gBAAgB,EAAE,0BAA0B;IAC5C,iBAAiB,EAAE,SAAS;IAC5B,mBAAmB,EAAE,OAAO;IAC5B,uCAAc;MACZ,cAAc,EAAE,MAAM;MACtB,QAAQ,EAAE,QAAQ;MAClB,6CAAM;QACJ,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,GAAG;QACR,SAAS,EAAE,gBAAgB;QAC3B,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,GAAG;QACV,KAAK,EAAE,KAAK;QACZ,UAAU,EAAE,IAAI;QAChB,gDAAG;UACD,UAAU,EAAE,IAAI;UAChB,OAAO,EAAE,YAAY;UACrB,KAAK,EAAE,IAAI;UACX,SAAS,EAAE,IAAI;UACf,KAAK,EN/CH,IAAI;UMgDN,MAAM,EAAE,CAAC;UACT,KAAK,EAAE,IAAI;UACX,QAAQ,EAAE,QAAQ;UAClB,cAAc,EAAE,GAAG;QAErB,gDAAG;UACD,KAAK,ENtDH,IAAI;UMuDN,SAAS,EAAE,IAAI;UACf,UAAU,EAAE,IAAI;UAChB,WAAW,EAAE,IAAI;UACjB,OAAO,EAAE,YAAY;QAEvB,+CAAE;UACA,SAAS,EAAE,IAAI;UACf,GAAG,EAAE,GAAG;UACR,WAAW,EAAE,CAAC;QAEhB,2EAA8B;UAC5B,IAAI,EAAE,IAAI;UACV,YAAY,EAAE,IAAI;UAClB,UAAU,EAAE,qDAAqD;QAEnE,oDAAO;UACL,OAAO,EAAE,KAAK;MAGlB,4CAAK;QACH,SAAS,EAAE,IAAI;QACf,KAAK,ENzEA,IAAI;QM0ET,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,KAAK;IAGlB,mCAAU;MACR,MAAM,EAAE,gBAAgB;MAEtB,+HAA0B;QACxB,WAAW,EAAE,CAAC;MAIhB,6HAA0B;QACxB,cAAc,EAAE,CAAC;EAMzB,qBAAS;IACP,qBAAqB,EAAE,IAAI;IAC3B,kBAAkB,EAAE,IAAI;IACxB,aAAa,EAAE,IAAI;IACnB,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,QAAQ;IACjB,KAAK,EAAE,IAAI;IACX,cAAc,EAAE,SAAS;EAG3B,iCAAqB;IACnB,UAAU,ENhFE,OAAO;IMiFnB,KAAK,EN5GG,IAAI;EM+Gd,gCAAoB;IAClB,gBAAgB,ENxFN,OAAO;IMyFjB,KAAK,ENjHG,IAAI;EMoHd,kCAAsB;IACpB,UAAU,EN1FE,OAAO;IM2FnB,KAAK,ENlHG,OAAO;EMqHjB,gCAAoB;IAClB,UAAU,ENtGF,OAAO;IMuGf,KAAK,ENjGI,OAAO;EMoGlB,iCAAqB;IACnB,UAAU,EAAE,OAAO;IACnB,KAAK,EAAE,IAAI;EAGb,+BAAmB;IACjB,UAAU,EN3GH,OAAO;IM4Gd,KAAK,EAAE,IAAI;EAGb,yBAAa;IACX,KAAK,ENjHK,OAAO;EMoHnB,yBAAa;IACX,KAAK,ENnHI,OAAO;EMsHlB,uBAAW;IACT,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,YAAY;EAGvB,qCAAyB;IACvB,UAAU,EAAE,4CAA4C;IACxD,KAAK,EAAE,IAAI;IACX,eAAe,EAAE,OAAO;EAG1B,iCAAqB;IACnB,UAAU,EAAE,2CAA2C;IACvD,eAAe,EAAE,OAAO;EAG1B,sCAA0B;IACxB,UAAU,EAAE,4CAA4C;IACxD,eAAe,EAAE,OAAO;EAG1B,oCAAwB;IACtB,UAAU,EAAE,6CAA6C;IACzD,eAAe,EAAE,OAAO;EAG1B,kCAAsB;IACpB,UAAU,EAAE,wCAAwC;IACpD,eAAe,EAAE,OAAO;EAG1B,mCAAuB;IACrB,UAAU,EAAE,4CAA4C;IACxD,eAAe,EAAE,OAAO;EAG1B,2BAAe;IACb,gBAAgB,ENxJP,OAAO;IMyJhB,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,MAAM;IACf,QAAQ,EAAE,QAAQ;IAClB,UAAU,EAAE,MAAM;IAClB,qBAAqB,EAAE,GAAG;IAC1B,kBAAkB,EAAE,GAAG;IACvB,aAAa,EAAE,GAAG;IAClB,aAAa,EAAE,IAAI;IACnB,kCAAO;MACL,OAAO,EAAE,KAAK;MACd,WAAW,ENnMG,8BAA8B;MMoM5C,WAAW,EAAE,IAAI;MACjB,UAAU,EAAE,IAAI;MAChB,SAAS,EAAE,IAAI;MACf,cAAc,EAAE,SAAS;IAE3B,+BAAI;MACF,KAAK,ENtMG,IAAI;MMuMZ,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;IAEd,mCAAQ;MACN,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,CAAC;MACN,KAAK,EAAE,CAAC;MACR,KAAK,ENrMG,OAAO;MMsMf,WAAW,EAAE,IAAI;MACjB,WAAW,ENpNG,8BAA8B;MMqN5C,aAAa,EAAE,GAAG;MAClB,WAAW,EAAE,GAAG;MAChB,cAAc,EAAE,SAAS;MACzB,SAAS,EAAE,IAAI;IAEjB,sCAAW;MACT,cAAc,EAAE,GAAG;MACnB,YAAY,EAAE,GAAG;IAEnB,6CAAkB;MAChB,SAAS,EAAE,IAAI;IAEjB,6BAAE;MACA,OAAO,EAAE,YAAY;MACrB,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;EAIhB,iCAAqB;IACnB,gBAAgB,EAAE,OAAO;IACzB,MAAM,EAAE,OAAO;EAGjB;gDACkC;IAChC,OAAO,EAAE,EAAE;IACX,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,CAAC;IACN,KAAK,EAAE,CAAC;IACR,YAAY,EAAE,WAAW;IACzB,YAAY,EAAE,KAAK;IACnB,uBAAuB,EAAE,GAAG;EAG9B,+CAAmC;IACjC,YAAY,EAAE,IAAI;IAClB,kBAAkB,EAAE,OAAO;IAC3B,gBAAgB,EAAE,OAAO;EAG3B,8CAAkC;IAChC,kBAAkB,EAAE,OAAO;IAC3B,gBAAgB,EAAE,OAAO;EAG3B,+DAAmD;IACjD,kBAAkB,ENjPN,OAAO;IMkPnB,gBAAgB,ENlPJ,OAAO;EMqPrB,8DAAkD;IAChD,kBAAkB,ENtPN,OAAO;IMuPnB,gBAAgB,ENvPJ,OAAO;EM2PnB,oDAAQ;IACN,KAAK,EN3QG,IAAI;IM4QZ,SAAS,EAAE,IAAI;IACf,MAAM,EAAE,OAAO;IACf,6DAAS;MACP,SAAS,EAAE,IAAI;MACf,KAAK,ENhRC,IAAI;MMiRV,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;EAKlB,kBAAM;IACJ,KAAK,EAAE,IAAI;IACX,UAAU,ENzPA,OAAO;IM0PjB,KAAK,EN5RG,IAAI;IM6RZ,qBAAqB,EAAE,GAAG;IAC1B,kBAAkB,EAAE,GAAG;IACvB,aAAa,EAAE,GAAG;IAClB,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,IAAI;IACjB,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,UAAU;IACtB,UAAU,EAAE,SAAS;IACrB,iCAAe;MACb,KAAK,ENvSC,IAAI;MMwSV,eAAe,EAAE,SAAS;MAC1B,MAAM,EAAE,OAAO;IAGf,gCAAS;MACP,OAAO,EAAE,MAAM;MACf,UAAU,EAAE,IAAI;IAGpB,+BAAa;MACX,UAAU,EAAE,cAAc;MAC1B,OAAO,EAAE,gBAAgB;MACzB,MAAM,EAAE,OAAO;EAInB,6BAAiB;IACf,UAAU,EAAE,KAAK;IACjB,MAAM,EAAE,iBAAsB;EAGhC,2BAAe;IACb,OAAO,EAAE,mBAAmB;IAC5B,6BAAE;MACA,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,IAAI;MACT,IAAI,EAAE,IAAI;EAId,4BAAgB;IACd,UAAU,ENlSF,OAAO;IMmSf,qCAAS;MACP,KAAK,EAAE,kBAAsB;EAIjC,8BAAkB;IAChB,gBAAgB,EN1SN,OAAO;EM6SnB,4BAAgB;IACd,gBAAgB,EN5SR,OAAO;EM+SjB,6BAAiB;IACf,UAAU,ENjUD,OAAO;IMkUhB,sCAAS;MACP,KAAK,EAAE,kBAAkB;EAI7B,6BAAiB;IACf,UAAU,EN1TD,OAAO;IM2ThB,sCAAS;MACP,KAAK,EAAE,kBAAoB;EAI/B,6BAAiB;IACf,YAAY,EAAE,IAAI;IAClB,cAAc,EAAE,CAAC;IACjB,UAAU,EAAE,IAAI;IAChB,+BAAE;MACA,IAAI,EAAE,CAAC;MACP,KAAK,EAAE,IAAI;MACX,WAAW,EAAE,SAAS;MACtB,mBAAmB,EAAE,SAAS;EAIlC,+BAAmB;IACjB,MAAM,EAAE,cAAc;EAItB,sCAAO;IACL,WAAW,EAAE,IAAI;IACjB,KAAK,ENtXC,IAAI;IMuXV,WAAW,EN1XF,kBAAkB;IM2X3B,SAAS,EAAE,IAAI;EAEjB,qCAAM;IACJ,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,CAAC;IACV,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,IAAI;EAInB,6BAAiB;IACf,OAAO,EAAE,SAAS;EAGpB,sCAA0B;IACxB,YAAY,EAAE,IAAI;IAClB,wCAAE;MACA,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,IAAI;MACT,IAAI,EAAE,IAAI;EAId,yBAAa;IACX,eAAe,EAAE,IAAI;IACrB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,CAAC;IACV,4BAAG;MACD,aAAa,EAAE,IAAI;IAErB,8BAAK;MACH,OAAO,EAAE,QAAQ;MACjB,OAAO,EAAE,KAAK;MACd,WAAW,EAAE,IAAI;MACjB,KAAK,ENxZG,IAAI;MMyZZ,mCAAK;QACH,SAAS,EAAE,IAAI;QACf,KAAK,EN1ZA,IAAI;QM2ZT,KAAK,EAAE,KAAK;QACZ,YAAY,EAAE,IAAI;MAEpB,2CAAa;QACX,WAAW,EAAE,IAAI;QACjB,YAAY,EAAE,GAAG;QACjB,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,IAAI;QACT,KAAK,ENtaD,IAAI;IMyaZ,wEAAqB;MACnB,MAAM,EAAE,OAAO;MACf,UAAU,EAAE,mBAAkB;MAC9B,KAAK,EN5aC,IAAI;MM6aV,qBAAqB,EAAE,IAAI;MAC3B,kBAAkB,EAAE,IAAI;MACxB,aAAa,EAAE,IAAI;MACnB,WAAW,EAAE,GAAG;IAElB,kCAAS;MACP,WAAW,EAAE,GAAG;EAKlB,qBAAI;IACF,WAAW,EAAE,CAAC;EAEhB,oCAAmB;IACjB,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,YAAY;IACrB,YAAY,EAAE,IAAI;EAEpB,0CAAyB;IACvB,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,KAAK;IACd,YAAY,EAAE,IAAI;IAClB,UAAU,EAAE,IAAI;EAGlB,0BAAS;IACP,cAAc,EAAE,IAAI;IACpB,WAAW,EAAE,IAAI;IACjB,aAAa,EAAE,CAAC;IAChB,QAAQ,EAAE,QAAQ;IA2DlB,UAAU,EAAE,0BAA+B;IA1D3C,kCAAQ;MAIN,aAAa,EAAE,IAAI;MAHnB,0CAAQ;QACN,cAAc,EAAE,GAAG;MAGrB,yCAAO;QACL,KAAK,ENldH,IAAI;MModR,2GAAsC;QACpC,OAAO,EAAE,YAAY;QACrB,WAAW,EAAE,CAAC;QACd,WAAW,EAAE,GAAG;QAChB,KAAK,ENxdH,IAAI;QMydN,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE,CAAC;MAEX,8FAAyB;QACvB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,IAAI;QACf,KAAK,EN5dF,IAAI;QM6dP,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE,MAAM;QACd,4GAAO;UACL,KAAK,ENheJ,IAAI;UMieL,WAAW,EAAE,GAAG;MAGpB,8CAAY;QACV,OAAO,EAAE,MAAM;MAEjB,iDAAe;QACb,WAAW,EAAE,IAAI;MAEnB,6CAAW;QACT,OAAO,EAAE,MAAM;QACf,cAAc,EAAE,GAAG;MAErB,+CAAa;QACX,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,IAAI;QACf,KAAK,ENlfD,IAAI;QMmfR,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE,MAAM;QACd,UAAU,EAAE,SAAS;QACrB,sDAAO;UACL,KAAK,ENvfH,IAAI;UMwfN,WAAW,EAAE,GAAG;IAKpB,8CAAM;MACJ,KAAK,ENhgBH,IAAI;MMigBN,OAAO,EAAE,CAAC;MACV,WAAW,EAAE,IAAI;MACjB,WAAW,EAAE,GAAG;EAKtB,uBAAM;IACJ,UAAU,EAAE,IAAI;EAElB,2CAA0B;IACxB,aAAa,EAAE,CAAC;EAElB,sCAAqB;IACnB,YAAY,EAAE,IAAI;EAMlB,4CAAW;IACT,KAAK,EAAE,IAAI;IACX,0DAAc;MACZ,aAAa,EAAE,WAAW;MAC1B,YAAY,EAAE,IAAI;EAIxB,wBAAG;IACD,eAAe,EAAE,IAAI;IACrB,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,CAAC;IACV,2BAAG;MACD,QAAQ,EAAE,MAAM;MAChB,aAAa,EAAE,IAAI;MACnB,+BAAI;QACF,qBAAqB,EAAE,IAAI;QAC3B,kBAAkB,EAAE,IAAI;QACxB,aAAa,EAAE,IAAI;QACnB,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,YAAY,EAAE,IAAI;QAClB,OAAO,EAAE,YAAY;QACrB,cAAc,EAAE,MAAM;MAExB,qCAAU;QACR,YAAY,EAAE,IAAI;QAClB,OAAO,EAAE,YAAY;EAKzB,gCAAK;IACH,OAAO,EAAE,YAAY;IACrB,KAAK,EAAE,GAAG;IACV,sCAAM;MACJ,YAAY,EAAE,CAAC;MACf,+BAA+B,EAAE,GAAG;MACpC,kCAAkC,EAAE,GAAG;MACvC,2BAA2B,EAAE,GAAG;MAChC,8BAA8B,EAAE,GAAG;MACnC,uBAAuB,EAAE,GAAG;MAC5B,0BAA0B,EAAE,GAAG;EAGnC,kCAAO;IACL,KAAK,EAAE,GAAG;IACV,OAAO,EAAE,YAAY;IACrB,8BAA8B,EAAE,GAAG;IACnC,iCAAiC,EAAE,GAAG;IACtC,0BAA0B,EAAE,GAAG;IAC/B,6BAA6B,EAAE,GAAG;IAClC,sBAAsB,EAAE,GAAG;IAC3B,yBAAyB,EAAE,GAAG;IAC9B,KAAK,EAAE,KAAK;EAKlB,mCAAuB;IACrB,MAAM,EAAE,iBAAsB;IAC9B,qBAAqB,EAAE,GAAG;IAC1B,kBAAkB,EAAE,GAAG;IACvB,aAAa,EAAE,GAAG;IAClB,UAAU,EAAE,IAAI;EAGlB,sBAAU;IACR,aAAa,EAAE,IAAI;IACnB,mCAAa;MACX,QAAQ,EAAE,QAAQ;MAClB,KAAK,EAAE,GAAG;MACV,KAAK,EAAE,IAAI;MACX,yCAAM;QACJ,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,GAAG;QACR,UAAU,EAAE,KAAK;QACjB,IAAI,EAAE,CAAC;MAET,qDAAkB;QAChB,OAAO,EAAE,YAAY;QACrB,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,IAAI;QACX,YAAY,EAAE,CAAC;QACf,uBAAuB,EAAE,CAAC;QAC1B,0BAA0B,EAAE,CAAC;QAC7B,QAAQ,EAAE,OAAO;QACjB,sEAAiB;UACf,MAAM,EAAE,IAAI;QAEd,4EAAuB;UACrB,MAAM,EAAE,IAAI;MAGhB,2CAAQ;QACN,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,CAAC;QACd,WAAW,EAAE,CAAC;QACd,sBAAsB,EAAE,CAAC;QACzB,yBAAyB,EAAE,CAAC;EAKlC,iBAAK;IACH,KAAK,EAAE,KAAK;IACZ,sBAAK;MACH,YAAY,EAAE,IAAI;MAClB,SAAS,EAAE,IAAI;MACf,KAAK,EN/nBE,IAAI;IMkoBX,uCAAQ;MACN,MAAM,EAAE,CAAC;MACT,UAAU,EAAE,IAAI;MAChB,MAAM,EAAE,iBAAsB;IAEhC,0EAA2C;MACzC,YAAY,EAAE,CAAC;IAEjB,mDAAoB;MAClB,YAAY,EAAE,CAAC;EAMnB,6CAAmB;IACjB,YAAY,EAAE,CAAC;IACf,YAAY,EAAE,CAAC;IACf,uBAAuB,EAAE,CAAC;IAC1B,0BAA0B,EAAE,CAAC;EAE/B,+CAAqB;IACnB,YAAY,EAAE,CAAC;IACf,uBAAuB,EAAE,CAAC;IAC1B,0BAA0B,EAAE,CAAC;IAC7B,WAAW,EAAE,CAAC;IACd,sBAAsB,EAAE,CAAC;IACzB,yBAAyB,EAAE,CAAC;IAC5B,WAAW,EAAE,IAAI;EAEnB,8CAAoB;IAClB,WAAW,EAAE,CAAC;IACd,sBAAsB,EAAE,CAAC;IACzB,yBAAyB,EAAE,CAAC;IAC5B,WAAW,EAAE,IAAI;EAQrB,2BAAe;IACb,QAAQ,EAAE,KAAK;IACf,GAAG,EAAE,CAAC;IACN,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,YAAY,EAAE,IAAI;IAClB,WAAW,EAAE,IAAI;IACjB,wBAAwB;IACxB,KAAK,EAAE,GAAG;IACV,KAAK,ENxrBG,IAAI;IMyrBZ,OAAO,EAAE,MAAM;IACf,yBAAyB,EAAE,GAAG;IAC9B,0BAA0B,EAAE,GAAG;IAC/B,kBAAkB,EAAE,mCAAmC;IACvD,eAAe,EAAE,mCAAmC;IACpD,UAAU,EAAE,mCAAmC;IAC/C,cAAc,EAAE,MAAM;IACtB,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,WAAW;IACvB,MAAM,EAAE,OAAO;EAGjB,uCAA2B;IACzB,UAAU,ENjrBD,OAAO;EMorBlB,8CAAkC;IAChC,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE,gBAAgB;IAC7B,SAAS,EAAE,IAAI;IACf,cAAc,EAAE,MAAM;IACtB,YAAY,EAAE,GAAG;IACjB,KAAK,ENtrBE,OAAO;EMyrBhB,oCAAwB;IACtB,UAAU,EN/rBF,OAAO;EMksBjB,2CAA+B;IAC7B,OAAO,EAAE,KAAK;IACd,WAAW,EAAE,oBAAoB;IACjC,SAAS,EAAE,IAAI;IACf,YAAY,EAAE,GAAG;IACjB,cAAc,EAAE,MAAM;IACtB,KAAK,ENlsBI,OAAO;EMqsBlB,0BAAc;IACZ,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,MAAM;EAGpB,yBAAa;IACX,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;IACjB,MAAM,EAAE,KAAK;EAOf,8BAAkB;IAChB,OAAO,EAAE,YAAY;IACrB,WAAW,EAAE,eAAe;IAC5B,UAAU,EAAE,MAAM;IAClB,WAAW,EAAE,MAAM;IACnB,WAAW,EAAE,CAAC;IACd,sBAAsB,EAAE,WAAW;IACnC,uBAAuB,EAAE,SAAS;IAClC,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,IAAI;EAGjB,yCAA6B;IAC3B,OAAO,EAAE,OAAO;IAChB,KAAK,ENnuBE,OAAO;EMsuBhB,wCAA4B;IAC1B,OAAO,EAAE,OAAO;EAGlB,6CAAiC;IAC/B,OAAO,EAAE,OAAO;IAChB,KAAK,EN7uBK,OAAO;EMgvBnB,wCAA4B;IAC1B,OAAO,EAAE,OAAO;IAChB,KAAK,ENhvBI,OAAO;EMmvBlB,2CAA+B;IAC7B,OAAO,EAAE,OAAO;IAChB,KAAK,ENvvBK,OAAO;IMwvBjB,OAAO,EAAE,CAAC;EAGZ,wCAA4B;IAC1B,KAAK,EN9wBM,OAAO;EMixBpB,uCAA2B;IACzB,KAAK,EN/vBE,OAAO;EMkwBhB,wCAA4B;IAC1B,KAAK,EAAE,OAAO;EAGhB,qBAAS;IACP,SAAS,EAAE,KAAK;IAChB,MAAM,EAAE,MAAM;EAGhB,mBAAO;IACL,KAAK,EAAE,IAAI;IAET,yBAAG;MACD,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,IAAI;MACjB,WAAW,EAAE,GAAG;MAChB,OAAO,EAAE,kBAAkB;MAC3B,KAAK,EN5yBD,IAAI;MM6yBR,UAAU,EAAE,IAAI;MAChB,aAAa,EAAE,iBAAiB;IAGlC,yBAAG;MACD,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,IAAI;MACjB,KAAK,ENpzBD,IAAI;MMqzBR,OAAO,EAAE,SAAS;MAClB,UAAU,EAAE,IAAI;MAChB,aAAa,EAAE,iBAAiB;IAElC,4EAA+B;MAC7B,YAAY,EAAE,CAAC;IAKf,sFAAO;MACL,aAAa,EAAE,IAAI;MACnB,cAAc,EAAE,CAAC;EAMzB,yBAAa;IACX,KAAK,ENr0BI,IAAI;IMs0Bb,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,IAAI;EAGnB,8BAAkB;IAChB,OAAO,EAAE,YAAY;ECj1BnB,sDAAU;IACR,MAAM,EAAE,QAAQ;IAChB,wDAAE;MACA,KAAK,EPCD,IAAI;MOAR,MAAM,EAAE,OAAO;MACf,OAAO,EAAE,KAAK;MACd,KAAK,EAAE,IAAI;IAEb,kEAAY;MACV,OAAO,EAAE,KAAK;MACd,MAAM,EAAE,OAAO;MACf,oEAAE;QACA,cAAc,EAAE,GAAG;QACnB,YAAY,EAAE,GAAG;QACjB,gBAAgB,EAAE,2CAA2C;QAC7D,iBAAiB,EAAE,SAAS;QAC5B,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,YAAY;MAEvB,2EAAS;QACP,OAAO,EAAE,EAAE;ECtBnB,iCAAW;IACT,KAAK,EAAE,GAAG;EAEZ,qCAAe;IACb,KAAK,EAAE,GAAG;EAEZ,mCAAa;IACX,gBAAgB,EAAE,8BAA8B;EAGhD,mCAAM;IACJ,UAAU,ERsBL,OAAO;IQrBZ,WAAW,EAAE,iBAAoB;IACjC,OAAO,EAAE,mBAAmB;IAC5B,WAAW,EAAE,IAAI;IACjB,MAAM,EAAE,OAAO;IACf,+CAAY;MACV,OAAO,EAAE,aAAa;MACtB,MAAM,EAAE,OAAO;MAcf,aAAa,EAAE,iBAAsB;MACrC,QAAQ,EAAE,QAAQ;MAdlB,iDAAE;QACA,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,YAAY;QACrB,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,CAAC;QACP,GAAG,EAAE,GAAG;MAEV,8DAAe;QACb,GAAG,EAAE,GAAG;IAKZ,qDAAkB;MAChB,WAAW,EAAE,oBAAoB;MACjC,KAAK,EAAE,IAAI;MACX,UAAU,EAAE,MAAM;MAClB,WAAW,EAAE,MAAM;MACnB,YAAY,EAAE,MAAM;MACpB,cAAc,EAAE,IAAI;MACpB,WAAW,EAAE,CAAC;MACd,SAAS,EAAE,IAAI;MACf,sBAAsB,EAAE,WAAW;MACnC,uBAAuB,EAAE,SAAS;MAClC,OAAO,EAAE,KAAK;MACd,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,GAAG;MACR,KAAK,EAAE,CAAC;IAEV,iDAAc;MACZ,UAAU,EAAE,IAAI;MAChB,UAAU,EAAE,IAAI;MAChB,OAAO,EAAE,gBAAgB;MACzB,qBAAqB,EAAE,GAAG;MAC1B,kBAAkB,EAAE,GAAG;MACvB,aAAa,EAAE,GAAG;MAClB,QAAQ,EAAE,MAAM;MAChB,UAAU,EAAE,eAAe;MAC3B,oDAAG;QACD,WAAW,EAAE,IAAI;QACjB,KAAK,ER3DL,IAAI;QQ4DJ,WAAW,ER/DR,kBAAkB;QQgErB,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,MAAM;QACd,SAAS,EAAE,IAAI;QACf,cAAc,EAAE,IAAI;MAGpB,kEAAY;QACV,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,KAAK;QACd,aAAa,EAAE,IAAI;QACnB,UAAU,EAAE,IAAI;MAElB,6DAAO;QACL,WAAW,EAAE,CAAC;IAKlB,2DAAK;MAUH,OAAO,EAAE,YAAY;MACrB,WAAW,EAAE,IAAI;MAVjB,6EAAkB;QAChB,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,YAAY;QACrB,cAAc,EAAE,MAAM;QACtB,MAAM,EAAE,MAAM;MAEhB,mEAAQ;QACN,cAAc,EAAE,MAAM;IAQ1B,uDAAO;MACL,KAAK,ERjGL,IAAI;MQkGJ,WAAW,ERrGR,kBAAkB;MQsGrB,OAAO,EAAE,KAAK;MACd,WAAW,EAAE,IAAI;MACjB,aAAa,EAAE,IAAI;MACnB,SAAS,EAAE,IAAI;MACf,cAAc,EAAE,IAAI;IAGxB,mDAAgB;MACd,QAAQ,EAAE,QAAQ;MAClB,mEAAgB;QACd,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,IAAI;EAIhB,0CAAa;IACX,OAAO,EAAE,gBAAgB;IACzB,UAAU,EAAE,IAAI;IAChB,aAAa,EAAE,iBAAsB;IACrC,sDAAY;MACV,aAAa,EAAE,CAAC;MAChB,OAAO,EAAE,gBAAgB;MACzB,wDAAE;QACA,GAAG,EAAE,IAAI;MAEX,qEAAe;QACb,GAAG,EAAE,IAAI;IAGb,4DAAkB;MAChB,OAAO,EAAE,KAAK;MACd,GAAG,EAAE,IAAI;IAEX,wDAAc;MACZ,OAAO,EAAE,IAAI;EAMjB,0DAAe;IACb,UAAU,EAAE,qDAAqD;IACjE,cAAc,EAAE,GAAG;IACnB,YAAY,EAAE,GAAG;EAEnB,iEAAsB;IACpB,OAAO,EAAE,EAAE;EAIf,+CAAyB;IACvB,UAAU,EAAE,iBAAsB;EAEpC,wCAAkB;IAChB,UAAU,EAAE,qBAAqB;EAGjC,yCAAM;IACJ,WAAW,EAAE,iBAAmB;EAKlC,2CAAM;IACJ,WAAW,EAAE,iBAAsB;EAIjC,gEAAE;IACA,GAAG,EAAE,IAAI;EAGb,oEAAkB;IAChB,OAAO,EAAE,EAAE;EAMb,sCAAE;IACA,aAAa,EAAE,CAAC;IAChB,yDAAmB;MACjB,YAAY,EAAE,IAAI;ECzL5B,2BAAe;IACb,QAAQ,EAAE,MAAM;IAChB,KAAK,EAAE,IAAI;IACX,+CAAoB;MAClB,KAAK,EAAE,IAAI;MACX,KAAK,EAAE,IAAI;MACX,mDAAI;QACF,OAAO,EAAE,YAAY;QACrB,cAAc,EAAE,GAAG;QACnB,YAAY,EAAE,IAAI;MAEpB,oDAAK;QACH,WAAW,EAAE,IAAI;QACjB,WAAW,ETXC,8BAA8B;QSY1C,SAAS,EAAE,IAAI;IAGnB,8CAAmB;MACjB,UAAU,EAAE,OAAO;MACnB,qBAAqB,EAAE,GAAG;MAC1B,kBAAkB,EAAE,GAAG;MACvB,aAAa,EAAE,GAAG;MAClB,MAAM,EAAE,IAAI;MACZ,QAAQ,EAAE,MAAM;MAChB,KAAK,EAAE,IAAI;MACX,UAAU,EAAE,IAAI;MAChB,QAAQ,EAAE,QAAQ;MAClB,mDAAK;QACH,UAAU,ETlBH,OAAO;QSmBd,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;QACP,kBAAkB,EAAE,wBAAwB;QAC5C,eAAe,EAAE,wBAAwB;QACzC,UAAU,EAAE,wBAAwB;EAMxC,+EAAa;IACX,gBAAgB,EAAE,iCAAiC;IACnD,2GAAc;MACZ,YAAY,EAAE,IAAI;MAClB,aAAa,EAAE,CAAC;MAChB,mHAAI;QACF,KAAK,EAAE,GAAG;EAKd,yFAAa;IACX,KAAK,EAAE,GAAG;EAEZ,iGAAiB;IACf,KAAK,EAAE,GAAG;EAId,6GAA4B;IAC1B,KAAK,EAAE,IAAI;EAGb,iEAAM;IACJ,KAAK,EAAE,IAAI;IACX,aAAa,EAAE,IAAI;IACnB,eAAe,EAAE,QAAQ;IACzB,gJAAO;MACL,aAAa,EAAE,iBAAsB;IAGrC,mFAAG;MACD,WAAW,ETzEN,kBAAkB;MS0EvB,UAAU,EAAE,IAAI;MAChB,WAAW,EAAE,IAAI;MACjB,KAAK,ETzEH,IAAI;MS0EN,cAAc,EAAE,GAAG;MACnB,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,IAAI;MACjB,WAAW,EAAE,MAAM;IAKnB,yFAAG;MACD,OAAO,EAAE,cAAc;MACvB,6FAAE;QACA,KAAK,ETnFL,IAAI;QSoFJ,aAAa,EAAE,CAAC;QAChB,WAAW,EAAE,IAAI;MAGnB,yHAAgB;QACd,WAAW,EAAE,KAAK;QAClB,KAAK,EAAE,IAAI;IAGf,sNAAwB;MACtB,KAAK,EAAE,IAAI;MACX,cAAc,EAAE,MAAM;IAExB,gOAA6B;MAC3B,KAAK,ETpGL,IAAI;MSqGJ,WAAW,EAAE,IAAI;MACjB,KAAK,EAAE,GAAG;MACV,aAAa,EAAE,IAAI;MACnB,oPAAK;QACH,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,IAAI;QACf,KAAK,ETxGN,IAAI;IS2GP,6VAAkD;MAChD,SAAS,EAAE,IAAI;MACf,cAAc,EAAE,MAAM;IAExB,sOAAgC;MAC9B,UAAU,EAAE,MAAM;MAClB,KAAK,EAAE,IAAI;MACX,8OAAE;QACA,UAAU,EAAE,WAAW;QACvB,OAAO,EAAE,SAAS;MAEpB,sQAAQ;QACN,UAAU,ETxFV,OAAO;MS0FT,0QAAS;QACP,UAAU,ETlGR,OAAO;ESwGnB,+EAAa;IACX,gBAAgB,EAAE,mCAAmC;IACrD,iBAAiB,EAAE,SAAS;IAC5B,mBAAmB,EAAE,OAAO;IAC5B,cAAc,EAAE,KAAK;IACrB,QAAQ,EAAE,QAAQ;IAClB,2GAAc;MACZ,QAAQ,EAAE,QAAQ;MAClB,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,IAAI;MACjB,MAAM,EAAE,IAAI;MACZ,IAAI,EAAE,KAAK;MACX,mHAAI;QACF,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,IAAI;EAIjB,+EAAa;IACX,aAAa,EAAE,CAAC;IAChB,cAAc,EAAE,CAAC;IACjB,kNAA0B;MACxB,OAAO,EAAE,KAAK;MACd,SAAS,EAAE,IAAI;IAEjB,yGAAa;MACX,KAAK,ET3JC,IAAI;MS4JV,UAAU,EAAE,IAAI;IAElB,uGAAY;MACV,KAAK,EAAE,KAAK;MACZ,WAAW,EAAE,IAAI;EAInB,+EAAE;IACA,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;EAEnB,iFAAG;IACD,MAAM,EAAE,gBAAgB;IACxB,qGAAU;MACR,OAAO,EAAE,GAAG;MACZ,YAAY,EAAE,GAAG;IAEnB,uFAAG;MACD,KAAK,ET9KF,IAAI;MS+KP,aAAa,EAAE,GAAG;MAClB,WAAW,EAAE,IAAI;MACjB,SAAS,EAAE,IAAI;MACf,WAAW,ETxLN,kBAAkB;MSyLvB,WAAW,EAAE,MAAM;EAIzB,+EAAa;IACX,SAAS,EAAE,IAAI;IACf,yFAAK;MACH,OAAO,EAAE,YAAY;MACrB,KAAK,EAAE,GAAG;MACV,KAAK,EAAE,IAAI;EAGf,iGAAsB;IACpB,SAAS,EAAE,GAAG;EAIZ,qFAAE;IACA,aAAa,EAAE,CAAC;IAChB,2HAAmB;MACjB,YAAY,EAAE,IAAI;IAEpB,+GAAa;MACX,KAAK,EAAE,KAAK;EC/MlB,wCAAa;IACX,KAAK,EAAE,GAAG;EAEZ,4CAAiB;IACf,KAAK,EAAE,GAAG;EAGd,mCAAa;IACX,gBAAgB,EAAE,6BAA6B;IAC/C,iBAAiB,EAAE,SAAS;IAC5B,mBAAmB,EAAE,SAAS;IAC9B,4CAAS;MACP,UAAU,EAAE,KAAK;MAEf,gEAAM;QACJ,KAAK,EAAE,GAAG;MAGd,kDAAM;QACJ,QAAQ,EAAE,QAAQ;QAClB,yEAAuB;UACrB,KAAK,EAAE,GAAG;UACV,QAAQ,EAAE,QAAQ;UAClB,GAAG,EAAE,GAAG;UACR,SAAS,EAAE,gBAAgB;EAMjC,6CAAa;IACX,KAAK,EAAE,GAAG;IACV,YAAY,EAAE,CAAC;EAGnB,+BAAS;IACP,gBAAgB,EAAE,mCAAmC;IACrD,iBAAiB,EAAE,SAAS;IAC5B,mBAAmB,EAAE,OAAO;IAE1B,iDAAI;MACF,KAAK,EAAE,GAAG;MACV,SAAS,EAAE,IAAI;MACf,gBAAgB,EAAE,OAAO;MACzB,KAAK,EV1CH,IAAI;MU2CN,WAAW,EAAE,IAAI;EAIvB,mCAAa;IACX,MAAM,EAAE,qBAAqB;IAC7B,2CAAQ;MACN,KAAK,EAAE,IAAI;MACX,8FAAO;QACL,aAAa,EAAE,iBAAsB;QACrC,cAAc,EAAE,IAAI;MAGpB,oDAAG;QACD,UAAU,EAAE,IAAI;QAChB,WAAW,EAAE,IAAI;QACjB,SAAS,EAAE,IAAI;QACf,KAAK,EV5DL,IAAI;QU6DJ,OAAO,EAAE,gBAAgB;QACzB,WAAW,EAAE,IAAI;QACjB,WAAW,EAAE,MAAM;QACnB,sDAAE;UACA,OAAO,EAAE,CAAC;UACV,MAAM,EAAE,CAAC;UACT,KAAK,EVnEP,IAAI;MUyEJ,6DAAK;QACH,OAAO,EAAE,SAAS;QAClB,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,IAAI;QACjB,cAAc,EAAE,GAAG;QACnB,sEAAS;UACP,SAAS,EAAE,IAAI;UACf,OAAO,EAAE,KAAK;UACd,WAAW,EAAE,IAAI;MAGrB,yEAAiB;QACf,KAAK,EAAE,GAAG;QACV,OAAO,EAAE,SAAS;MAEpB,gFAAwB;QACtB,OAAO,EAAE,EAAE;QACX,UAAU,EAAE,sCAAsC;QAClD,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,eAAe,EAAE,OAAO;QACxB,OAAO,EAAE,YAAY;QACrB,cAAc,EAAE,GAAG;QACnB,YAAY,EAAE,IAAI;MAEpB,0EAAkB;QAChB,WAAW,EAAE,MAAM;MAErB,0EAAkB;QAChB,WAAW,EAAE,MAAM;MAErB,wEAAgB;QACd,UAAU,EAAE,KAAK;QACjB,OAAO,EAAE,SAAS;QAClB,4EAAI;UACF,KAAK,EV1GP,IAAI;UU2GF,SAAS,EAAE,IAAI;UACf,cAAc,EAAE,MAAM;UACtB,8EAAE;YACA,SAAS,EAAE,IAAI;MAKvB,gEAAa;QACX,MAAM,EAAE,OAAO;MAGf,qFAAsB;QACpB,KAAK,EVjGR,OAAO;MUqGN,oFAAsB;QACpB,KAAK,EVvGL,OAAO;MU0GX,mEAAgB;QAkCd,UAAU,EVlIR,OAAO;QUiGT,4FAAyB;UACvB,UAAU,EAAE,IAAI;UAChB,KAAK,EAAE,IAAI;UACX,OAAO,EAAE,KAAK;UACd,UAAU,EAAE,iBAAsB;UAClC,MAAM,EAAE,IAAI;UACZ,WAAW,EAAE,CAAC;UACd,cAAc,EAAE,CAAC;QAEnB,oFAAiB;UACf,UAAU,EAAE,IAAI;UAChB,WAAW,EAAE,CAAC;UAEZ,wGAAO;YACL,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,IAAI;YACjB,WAAW,EAAE,IAAI;UAEnB,mGAAE;YACA,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,IAAI;YACjB,KAAK,EVrJV,IAAI;UUuJD,uGAAM;YACJ,KAAK,EAAE,IAAI;YACX,sNAAO;cACL,MAAM,EAAE,IAAI;cACZ,KAAK,EAAE,GAAG;cACV,OAAO,EAAE,CAAC;MAOpB,6DAAU;QACR,UAAU,EVrIR,OAAO;QUsIT,gEAAG;UACD,aAAa,EAAE,IAAI;EAO3B,6CAAS;IACP,cAAc,EAAE,SAAS;IACzB,OAAO,EAAE,KAAK;IACd,aAAa,EAAE,IAAI;IACnB,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;EAGnB,6CAAS;IACP,aAAa,EAAE,IAAI;IACnB,aAAa,EAAE,IAAI;IACnB,qDAAQ;MACN,cAAc,EAAE,CAAC;MACjB,2DAAM;QACJ,aAAa,EAAE,CAAC;MAElB,oEAAe;QACb,KAAK,EAAE,KAAK;EAKhB,mDAAO;IACL,KAAK,EAAE,IAAI;IACX,YAAY,EAAE,IAAI;IAClB,yDAAM;MACJ,OAAO,EAAE,YAAY;MACrB,OAAO,EAAE,CAAC;EC7MhB,yCAAa;IACX,KAAK,EAAE,GAAG;EAEZ,6CAAiB;IACf,KAAK,EAAE,GAAG;EAIZ,sDAAO;IACL,OAAO,EAAE,MAAM;EAEjB,mEAAoB;IAClB,MAAM,EAAE,eAAe;EAG3B,6BAAM;IACJ,KAAK,EAAE,IAAI;IACX,aAAa,EAAE,IAAI;IACnB,kEAAO;MACL,aAAa,EAAE,iBAAsB;IAGrC,kDAAe;MACb,YAAY,EAAE,IAAI;IAEpB,iDAAc;MACZ,aAAa,EAAE,IAAI;IAErB,sCAAG;MACD,WAAW,EX7BD,8BAA8B;MW8BxC,UAAU,EAAE,IAAI;MAChB,WAAW,EAAE,IAAI;MACjB,KAAK,EX9BH,IAAI;MW+BN,OAAO,EAAE,GAAG;MACZ,cAAc,EAAE,IAAI;MACpB,wCAAE;QACA,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,CAAC;QACT,KAAK,EXpCL,IAAI;IW0CN,0DAAG;MACD,OAAO,EAAE,KAAK;MACd,SAAS,EAAE,IAAI;IAEjB,sEAAe;MACb,KAAK,EAAE,GAAG;MACV,YAAY,EAAE,IAAI;MAClB,aAAa,EAAE,IAAI;MACnB,UAAU,EAAE,uBAAuB;MACnC,KAAK,EXnDL,IAAI;MWoDJ,6FAAuB;QACrB,YAAY,EAAE,IAAI;MAEpB,6EAAO;QACL,UAAU,EXpBV,OAAO;QWqBP,qBAAqB,EAAE,GAAG;QAC1B,kBAAkB,EAAE,GAAG;QACvB,aAAa,EAAE,GAAG;QAClB,SAAS,EAAE,IAAI;QACf,KAAK,EX7DP,IAAI;QW8DF,WAAW,EXhEL,8BAA8B;QWiEpC,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,QAAQ;QACjB,YAAY,EAAE,IAAI;QAClB,cAAc,EAAE,SAAS;IAG7B,qEAAc;MACZ,aAAa,EAAE,IAAI;IAErB,0DAAG;MACD,OAAO,EAAE,MAAM;MACf,MAAM,EAAE,OAAO;IAEjB,iEAAU;MACR,UAAU,EAAE,MAAM;IAIpB,6KAAsB;MACpB,UAAU,EX7DT,OAAO;IWgEZ,8DAA2B;MACzB,UAAU,EAAE,OAAO;MACnB,iEAAG;QACD,aAAa,EAAE,eAAe;IAGlC,iDAAc;MACZ,UAAU,EAAE,OAAO;MACnB,oDAAG;QACD,OAAO,EAAE,SAAS;QAClB,UAAU,EAAE,uBAAuB;QACnC,UAAU,EAAE,IAAI;QAChB,sDAAE;UACA,aAAa,EAAE,GAAG;UAClB,SAAS,EAAE,IAAI;UACf,WAAW,EAAE,IAAI;UACjB,6DAAO;YACL,WAAW,EAAE,GAAG;YAChB,KAAK,EXvGT,IAAI;QW0GJ,+DAAW;UACT,OAAO,EAAE,YAAY;UACrB,YAAY,EAAE,IAAI;UAClB,aAAa,EAAE,GAAG;EAM5B,4CAAqB;IACnB,OAAO,EAAE,MAAM;IACf,qDAAS;MACP,aAAa,EAAE,IAAI;MACnB,aAAa,EAAE,IAAI;MACnB,UAAU,EAAE,IAAI;MAChB,6DAAQ;QACN,cAAc,EAAE,CAAC;QACjB,mEAAM;UACJ,aAAa,EAAE,CAAC;QAElB,oEAAO;UACL,OAAO,EAAE,KAAK;UACd,SAAS,EAAE,IAAI;UACf,WAAW,EAAE,IAAI;UACjB,KAAK,EX/HJ,IAAI;EWqIX,8CAAa;IACX,YAAY,EAAE,CAAC;IACf,KAAK,EAAE,GAAG;IACV,gDAAE;MACA,WAAW,EAAE,IAAI;EAKrB,iDAAO;IACL,KAAK,EX/IA,IAAI;EWiJX,mDAAS;IACP,aAAa,EAAE,CAAC;IAChB,aAAa,EAAE,CAAC;IAChB,cAAc,EAAE,CAAC;IACjB,2DAAQ;MAKN,cAAc,EAAE,CAAC;MAJjB,iEAAM;QACJ,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,CAAC;EC9JlB,kCAAI;IACF,YAAY,EAAE,GAAG;IACjB,wCAAM;MACJ,KAAK,EAAE,IAAI;MACX,aAAa,EAAE,IAAI;IAErB,8CAAY;MACV,aAAa,EAAE,iBAAiB;MAChC,yBAAyB,EAAE,CAAC;MAC5B,0BAA0B,EAAE,CAAC;MAC7B,aAAa,EAAE,CAAC;IAGlB,sDAAoB;MAClB,KAAK,EAAE,OAAO;MACd,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,IAAI;MACjB,aAAa,EAAE,IAAI;IAErB,wCAAM;MACJ,KAAK,EAAE,OAAO;MACd,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,GAAG;MAChB,WAAW,EAAE,IAAI;MACjB,OAAO,EAAE,CAAC;MACV,WAAW,EZzBJ,kBAAkB;MY0BzB,6CAAK;QACH,WAAW,EAAE,GAAG;EC1BpB,8CAAa;IACX,KAAK,EAAE,GAAG;EAEZ,kDAAiB;IACf,KAAK,EAAE,GAAG;EAGd,0DAA8B;IAC5B,UAAU,EAAE,qDAAqD;IACjE,IAAI,EAAE,IAAI;IACV,YAAY,EAAE,IAAI;EAEpB,wCAAY;IACV,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAAE,CAAC;EAEV,wDAA4B;IAC1B,IAAI,EAAE,CAAC;EAGT,qCAAS;IACP,UAAU,EAAE,IAAI;IAChB,4CAAO;MACL,KAAK,EAAE,OAAO;MACd,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,GAAG;MAChB,WAAW,EAAE,IAAI;IAEnB,0CAAK;MACH,OAAO,EAAE,KAAK;MACd,KAAK,EAAE,OAAO;MACd,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,IAAI;MACjB,aAAa,EAAE,IAAI;IAInB,gDAAK;MACH,KAAK,EAAE,IAAI;MACX,aAAa,EAAE,CAAC;IAKlB,yDAAE;MACA,OAAO,EAAE,GAAG;MACZ,KAAK,EAAE,OAAO;MACd,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,IAAI;MACjB,WAAW,EAAE,IAAI;MACjB,eAAe,EAAE,IAAI;MACrB,cAAc,EAAE,SAAS;IAE3B,+DAAQ;MACN,OAAO,EAAE,CAAC;EC1DlB,wBAAY;IACV,OAAO,EAAE,IAAI;EhBkMb,2DAAsE;IgB9LtE,yBAAa;MACX,gBAAgB,EAAE,eAAe;MACjC,uCAAc;QAKZ,QAAQ,EAAE,MAAM;QAJhB,2CAAI;UACF,KAAK,EAAE,eAAe;UACtB,UAAU,EAAE,MAAM;IAKxB,yBAAa;MACX,cAAc,EAAE,gBAAgB;IAGhC,6CAAmB;MACjB,KAAK,EAAE,KAAK;IAEd,+CAAqB;MACnB,uBAAuB,EAAE,GAAG;MAC5B,0BAA0B,EAAE,GAAG;MAC/B,WAAW,EAAE,CAAC;MACd,sBAAsB,EAAE,CAAC;MACzB,yBAAyB,EAAE,CAAC;IAE9B,8CAAoB;MAClB,sBAAsB,EAAE,GAAG;MAC3B,yBAAyB,EAAE,GAAG;MAC9B,KAAK,EAAE,IAAI;IAIb,qCAAU;MACR,KAAK,EAAE,IAAI;MACX,aAAa,EAAE,CAAC;EhBqJpB,oCAA4C;IgB/I5C,wBAAY;MACV,OAAO,EAAE,IAAI;IAEf,yBAAa;MACX,gBAAgB,EAAE,eAAe;MACjC,qCAAY;QACV,MAAM,EAAE,CAAC;MAGT,6CAAM;QACJ,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,MAAM;QAClB,aAAa,EAAE,IAAI;QACnB,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,CAAC;QACN,SAAS,EAAE,IAAI;IAQb,8DAAI;MACF,KAAK,EAAE,IAAI;IAIb,yEAAuB;MACrB,KAAK,EAAE,IAAI;MACX,GAAG,EAAE,CAAC;MACN,SAAS,EAAE,IAAI;MACf,QAAQ,EAAE,QAAQ;IAO5B,4EAAsC;MACpC,KAAK,EAAE,eAAe;MACtB,OAAO,EAAE,YAAY;MACrB,OAAO,EAAE,gBAAgB;IAKrB,iDAAI;MACF,KAAK,EAAE,IAAI;IAKnB,yBAAa;MACX,cAAc,EAAE,gBAAgB;IAGhC,6CAAmB;MACjB,GAAG,EAAE,GAAG;MACR,QAAQ,EAAE,QAAQ;IAEpB,+CAAqB;MACnB,uBAAuB,EAAE,GAAG;MAC5B,0BAA0B,EAAE,GAAG;MAC/B,WAAW,EAAE,CAAC;MACd,sBAAsB,EAAE,CAAC;MACzB,yBAAyB,EAAE,CAAC;MAC5B,YAAY,EAAE,IAAI;IAEpB,8CAAoB;MAClB,sBAAsB,EAAE,GAAG;MAC3B,yBAAyB,EAAE,GAAG;IAIhC,wCAAc;MACZ,UAAU,EAAE,IAAI;IAGpB,2BAAe;MACb,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,IAAI;MACjB,OAAO,EAAE,SAAS;MAClB,KAAK,EAAE,IAAI;MACX,aAAa,EAAE,CAAC;MAChB,UAAU,EAAE,MAAM;IAEpB,6FAAoE;MAClE,OAAO,EAAE,EAAE;;AZtFf,qBAAsB;EACpB,SAAS,EAAE,IAAI;EACf,MAAM,EAAE,CAAC",
4
- "sources": ["../scss/mixins.sass","../scss/override.scss","../scss/vars.scss","../scss/sale.scss","../scss/main.scss","../scss/misc.scss","../scss/helpers.sass","../scss/grid.sass","../scss/components.scss","../scss/dashboard.scss","../scss/hardener.scss","../scss/scan.scss","../scss/audit.scss","../scss/ip-lockout.scss","../scss/register-modal.scss","../scss/auth.scss","../scss/mobile.scss"],
5
- "names": [],
6
- "file": "styles.css"
7
- }
 
 
 
 
 
 
 
assets/email-assets/img/Blue-Copy.png ADDED
Binary file
assets/email-assets/img/Blue-Copy@2x.png ADDED
Binary file
assets/email-assets/img/Defender-widerec.png ADDED
Binary file
assets/email-assets/img/Defender-widerec@2x.png ADDED
Binary file
assets/email-assets/img/Warning.png ADDED
Binary file
assets/email-assets/img/Warning@2x.png ADDED
Binary file
readme.txt CHANGED
@@ -1,13 +1,13 @@
1
  === Defender Security, Monitoring, and Hack Protection ===
2
  Plugin Name: Defender Security, Monitoring, and Hack Protection
3
- Version: 2.1.2
4
  Author: WPMU DEV
5
  Author URI: http://premium.wpmudev.org/
6
  Contributors: WPMUDEV
7
  Tags: Security, Security Tweaks, Hardening, IP lockout, Monitoring, Blacklist, Site Protection, Hacked, Security Scan
8
  Requires at least: 4.6
9
  Tested up to: 5.1.1
10
- Stable tag: 2.1.2
11
  License: GPL v2 - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
12
 
13
  Protect WordPress from hackers with security tweaks, code scans, 2-Step Verification, IP lockouts, and monitoring.
@@ -122,6 +122,31 @@ Hackers and bot attacks are not the only threat to your site. No matter what se
122
 
123
  == Changelog ==
124
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  = 2.1.2 =
126
  - Feature: Defender Pro now supports the WPMU DEV Dashboard’s white label feature.
127
  - Feature: You can now perform a factory reset of Defender’s settings via the Settings screen, as well as control what happens to data when the plugin is uninstalled.
1
  === Defender Security, Monitoring, and Hack Protection ===
2
  Plugin Name: Defender Security, Monitoring, and Hack Protection
3
+ Version: 2.1.4
4
  Author: WPMU DEV
5
  Author URI: http://premium.wpmudev.org/
6
  Contributors: WPMUDEV
7
  Tags: Security, Security Tweaks, Hardening, IP lockout, Monitoring, Blacklist, Site Protection, Hacked, Security Scan
8
  Requires at least: 4.6
9
  Tested up to: 5.1.1
10
+ Stable tag: 2.1.4
11
  License: GPL v2 - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
12
 
13
  Protect WordPress from hackers with security tweaks, code scans, 2-Step Verification, IP lockouts, and monitoring.
122
 
123
  == Changelog ==
124
 
125
+ = 2.1.4 =
126
+ - Fix: Mask Login cause issue when visiting /wp-admin/network/sites.php
127
+
128
+ = 2.1.3 =
129
+ - Feature: Security tweaks will send reminder when no tweaks were actioned after activation
130
+ - Improvement: Scanning will be more catchy, especially with code using eval function, however that can lead to more false positive, please consider to check with our support before delete the file.
131
+ - Fix: Bring back the tooltips system
132
+ - Fix: Audit filter links doesn't reflect the right results if open in new tab
133
+ - Fix: Filtering issue type in scanning now show correct results.
134
+ - Fix: Scanning notification keep sending when the setting turn to "off"
135
+ - Fix: User IP in IP Lockout->Blacklist now show the correct IP.
136
+ - Fix: Bring back the subject customization field in Scanning email config.
137
+ - Fix: Manage Login Duration wont make user to login twice anymore.
138
+ - Fix: Audit filtering by user now working properly
139
+ - Fix: We change the Audit logging items' color from red to more neutral.
140
+ - Fix: Ad Widget won't be show in vulnerability list by accident anymore
141
+ - Fix: Bottom bulk selector in Scanning page now work properly
142
+ - Fix: Deprecate warning from the function strpos() in php 7.3
143
+ - Fix: Sync issues with HUB will be more consistent.
144
+ - Fix: Mask login doesn't work properly if Wordpress get installed in a sub-folder
145
+ - Fix: Conflict with Avada theme which making scanning stuck
146
+ - Fix: Gracefully handle error when php dom extension does not install
147
+ - Fix: Prevent factory reset revert database prefix into wp_ even though it was not set by Defender.
148
+ - Fix: Prevent slashes added in email template
- Fix: Minor grammar and UX improvements.
149
+
150
  = 2.1.2 =
151
  - Feature: Defender Pro now supports the WPMU DEV Dashboard’s white label feature.
152
  - Feature: You can now perform a factory reset of Defender’s settings via the Settings screen, as well as control what happens to data when the plugin is uninstalled.
vendor/hammer/base/db-model.php CHANGED
@@ -284,7 +284,7 @@ class DB_Model extends Model {
284
  ), array_merge( array( $sql ), $attribute ) );
285
  $condition[] = $sql;
286
  }
287
- } elseif ( strpos( '%', $attribute ) === 0 ) {
288
  $condition[] = $wpdb->prepare( $key . ' LIKE %s', $attribute );
289
  } else {
290
  $condition[] = $wpdb->prepare( $key . ' = %s', $attribute );
284
  ), array_merge( array( $sql ), $attribute ) );
285
  $condition[] = $sql;
286
  }
287
+ } elseif ( strlen( $attribute ) && strpos( '%', (string) $attribute ) === 0 ) {
288
  $condition[] = $wpdb->prepare( $key . ' LIKE %s', $attribute );
289
  } else {
290
  $condition[] = $wpdb->prepare( $key . ' = %s', $attribute );
vendor/hammer/wp/model.php CHANGED
@@ -141,7 +141,6 @@ abstract class Model extends \Hammer\Base\Model {
141
  if ( ! empty( $limit ) ) {
142
  $sql .= ' LIMIT ' . $limit;
143
  }
144
-
145
  $ids = self::getWPDB()->get_col( $sql );
146
 
147
  foreach ( $ids as $id ) {
@@ -219,6 +218,7 @@ abstract class Model extends \Hammer\Base\Model {
219
  $fields = static::buildFields();
220
  $join = static::buildJoins();
221
  $where = static::buildWhere( $attributes );
 
222
  $sql = "SELECT " . implode( ',', $fields ) . " FROM " . static::getWPDB()->posts . ' AS t0';
223
  $sql = $sql . ' ' . implode( ' ', $join ) . ' ' . implode( ' AND ', $where );
224
  $sql = $sql . ' GROUP BY ID';
@@ -371,7 +371,6 @@ abstract class Model extends \Hammer\Base\Model {
371
  $sql = $wpdb->prepare( $sql, $value['value'] );
372
  } elseif ( ! empty( $value ) ) {
373
  $sql = 't' . $pos . "." . $field . " IN (" . implode( ', ', array_fill( 0, count( $value ), '%s' ) ) . ")";
374
-
375
  $sql = call_user_func_array( array( $wpdb, 'prepare' ), array_merge( array( $sql ), $value ) );
376
  } else {
377
  //this case the in array is empty,
141
  if ( ! empty( $limit ) ) {
142
  $sql .= ' LIMIT ' . $limit;
143
  }
 
144
  $ids = self::getWPDB()->get_col( $sql );
145
 
146
  foreach ( $ids as $id ) {
218
  $fields = static::buildFields();
219
  $join = static::buildJoins();
220
  $where = static::buildWhere( $attributes );
221
+
222
  $sql = "SELECT " . implode( ',', $fields ) . " FROM " . static::getWPDB()->posts . ' AS t0';
223
  $sql = $sql . ' ' . implode( ' ', $join ) . ' ' . implode( ' AND ', $where );
224
  $sql = $sql . ' GROUP BY ID';
371
  $sql = $wpdb->prepare( $sql, $value['value'] );
372
  } elseif ( ! empty( $value ) ) {
373
  $sql = 't' . $pos . "." . $field . " IN (" . implode( ', ', array_fill( 0, count( $value ), '%s' ) ) . ")";
 
374
  $sql = call_user_func_array( array( $wpdb, 'prepare' ), array_merge( array( $sql ), $value ) );
375
  } else {
376
  //this case the in array is empty,
vendor/php_codesniffer-3.4.0/CONTRIBUTING.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Contributing
2
+ -------------
3
+
4
+ Before you contribute code to PHP\_CodeSniffer, please make sure it conforms to the PHPCS coding standard and that the PHP\_CodeSniffer unit tests still pass. The easiest way to contribute is to work on a checkout of the repository, or your own fork, rather than an installed PEAR version. If you do this, you can run the following commands to check if everything is ready to submit:
5
+
6
+ cd PHP_CodeSniffer
7
+ php bin/phpcs
8
+
9
+ Which should display no coding standard errors. And then:
10
+
11
+ phpunit
12
+
13
+ Which should give you no failures or errors. You can ignore any skipped tests as these are for external tools.
vendor/php_codesniffer-3.4.0/CodeSniffer.conf.dist ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $phpCodeSnifferConfig = array (
3
+ 'default_standard' => 'PSR2',
4
+ 'report_format' => 'summary',
5
+ 'show_warnings' => '0',
6
+ 'show_progress' => '1',
7
+ 'report_width' => '120',
8
+ )
9
+ ?>
vendor/php_codesniffer-3.4.0/README.md ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## About
2
+
3
+ PHP\_CodeSniffer is a set of two PHP scripts; the main `phpcs` script that tokenizes PHP, JavaScript and CSS files to detect violations of a defined coding standard, and a second `phpcbf` script to automatically correct coding standard violations. PHP\_CodeSniffer is an essential development tool that ensures your code remains clean and consistent.
4
+
5
+ [![Build Status](https://travis-ci.org/squizlabs/PHP_CodeSniffer.svg?branch=phpcs-fixer)](https://travis-ci.org/squizlabs/PHP_CodeSniffer) [![Code consistency](http://squizlabs.github.io/PHP_CodeSniffer/analysis/squizlabs/PHP_CodeSniffer/grade.svg)](http://squizlabs.github.io/PHP_CodeSniffer/analysis/squizlabs/PHP_CodeSniffer) [![Join the chat at https://gitter.im/squizlabs/PHP_CodeSniffer](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/squizlabs/PHP_CodeSniffer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6
+
7
+ ## Requirements
8
+
9
+ PHP\_CodeSniffer requires PHP version 5.4.0 or greater, although individual sniffs may have additional requirements such as external applications and scripts. See the [Configuration Options manual page](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options) for a list of these requirements.
10
+
11
+ ## Installation
12
+
13
+ The easiest way to get started with PHP\_CodeSniffer is to download the Phar files for each of the commands:
14
+ ```
15
+ # Download using curl
16
+ curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar
17
+ curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcbf.phar
18
+
19
+ # Or download using wget
20
+ wget https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar
21
+ wget https://squizlabs.github.io/PHP_CodeSniffer/phpcbf.phar
22
+
23
+ # Then test the downloaded PHARs
24
+ php phpcs.phar -h
25
+ php phpcbf.phar -h
26
+ ```
27
+
28
+ ### Composer
29
+ If you use Composer, you can install PHP_CodeSniffer system-wide with the following command:
30
+
31
+ composer global require "squizlabs/php_codesniffer=*"
32
+
33
+ Make sure you have the composer bin dir in your PATH. The default value is `~/.composer/vendor/bin/`, but you can check the value that you need to use by running `composer global config bin-dir --absolute`.
34
+
35
+ Or alternatively, include a dependency for `squizlabs/php_codesniffer` in your `composer.json` file. For example:
36
+
37
+ ```json
38
+ {
39
+ "require-dev": {
40
+ "squizlabs/php_codesniffer": "3.*"
41
+ }
42
+ }
43
+ ```
44
+
45
+ You will then be able to run PHP_CodeSniffer from the vendor bin directory:
46
+
47
+ ./vendor/bin/phpcs -h
48
+ ./vendor/bin/phpcbf -h
49
+
50
+ ### Phive
51
+ If you use Phive, you can install PHP_CodeSniffer as a project tool using the following commands:
52
+
53
+ phive install phpcs
54
+ phive install phpcbf
55
+
56
+ You will then be able to run PHP_CodeSniffer from the tools directory:
57
+
58
+ ./tools/phpcs -h
59
+ ./tools/phpcbf -h
60
+
61
+ ### PEAR
62
+ If you use PEAR, you can install PHP\_CodeSniffer using the PEAR installer. This will make the `phpcs` and `phpcbf` commands immediately available for use. To install PHP\_CodeSniffer using the PEAR installer, first ensure you have [installed PEAR](http://pear.php.net/manual/en/installation.getting.php) and then run the following command:
63
+
64
+ pear install PHP_CodeSniffer
65
+
66
+ ### Git Clone
67
+ You can also download the PHP\_CodeSniffer source and run the `phpcs` and `phpcbf` commands directly from the Git clone:
68
+
69
+ git clone https://github.com/squizlabs/PHP_CodeSniffer.git
70
+ cd PHP_CodeSniffer
71
+ php bin/phpcs -h
72
+ php bin/phpcbf -h
73
+
74
+ ## Documentation
75
+
76
+ The documentation for PHP\_CodeSniffer is available on the [Github wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki).
77
+
78
+ ## Issues
79
+
80
+ Bug reports and feature requests can be submitted on the [Github Issue Tracker](https://github.com/squizlabs/PHP_CodeSniffer/issues).
81
+
82
+ ## Contributing
83
+
84
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for information.
85
+
86
+ ## Versioning
87
+
88
+ PHP_CodeSniffer uses a `MAJOR.MINOR.PATCH` version number format.
89
+
90
+ The `MAJOR` version is incremented when:
91
+ - backwards-incompatible changes are made to how the `phpcs` or `phpcbf` commands are used, or
92
+ - backwards-incompatible changes are made to the `ruleset.xml` format, or
93
+ - backwards-incompatible changes are made to the API used by sniff developers, or
94
+ - custom PHP_CodeSniffer token types are removed
95
+
96
+ The `MINOR` version is incremented when:
97
+ - new backwards-compatible features are added to the `phpcs` and `phpcbf` commands, or
98
+ - backwards-compatible changes are made to the `ruleset.xml` format, or
99
+ - backwards-compatible changes are made to the API used by sniff developers, or
100
+ - new sniffs are added to an included standard
101
+
102
+ > NOTE: Backwards-compatible changes to the API used by sniff develpers will allow an existing sniff to continue running without producing fatal errors but may not result in the sniff reporting the same errors as it did previously without changes being required.
103
+
104
+ The `PATCH` version is incremented when:
105
+ - backwards-compatible bug fixes are made
106
+
107
+ > NOTE: As PHP_CodeSniffer exists to report and fix issues, most bugs are the result of coding standard errors being incorrectly reported or coding standard errors not being reported when they should be. This means that the messages produced by PHP_CodeSniffer, and the fixes it makes, are likely to be different between PATCH versions.
vendor/php_codesniffer-3.4.0/composer.json ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "squizlabs/php_codesniffer",
3
+ "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
4
+ "type": "library",
5
+ "keywords": [
6
+ "phpcs",
7
+ "standards"
8
+ ],
9
+ "homepage": "http://www.squizlabs.com/php-codesniffer",
10
+ "license": "BSD-3-Clause",
11
+ "authors": [
12
+ {
13
+ "name": "Greg Sherwood",
14
+ "role": "lead"
15
+ }
16
+ ],
17
+ "support": {
18
+ "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
19
+ "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki",
20
+ "source": "https://github.com/squizlabs/PHP_CodeSniffer"
21
+ },
22
+ "extra": {
23
+ "branch-alias": {
24
+ "dev-master": "3.x-dev"
25
+ }
26
+ },
27
+ "require": {
28
+ "php": ">=5.4.0",
29
+ "ext-tokenizer": "*",
30
+ "ext-xmlwriter": "*",
31
+ "ext-simplexml": "*"
32
+ },
33
+ "require-dev": {
34
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
35
+ },
36
+ "bin": [
37
+ "bin/phpcs",
38
+ "bin/phpcbf"
39
+ ]
40
+ }
vendor/php_codesniffer-3.4.0/licence.txt ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2012, Squiz Pty Ltd (ABN 77 084 670 600)
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+ * Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ * Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+ * Neither the name of Squiz Pty Ltd nor the
12
+ names of its contributors may be used to endorse or promote products
13
+ derived from this software without specific prior written permission.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
vendor/php_codesniffer-3.4.0/phpcs.xml.dist ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="PHP_CodeSniffer" xsi:noNamespaceSchemaLocation="phpcs.xsd">
3
+ <description>The coding standard for PHP_CodeSniffer itself.</description>
4
+
5
+ <file>autoload.php</file>
6
+ <file>bin</file>
7
+ <file>scripts</file>
8
+ <file>src</file>
9
+ <file>tests</file>
10
+
11
+ <exclude-pattern>*/Standards/*/Tests/*\.(inc|css|js)</exclude-pattern>
12
+
13
+ <arg name="basepath" value="."/>
14
+ <arg name="colors"/>
15
+ <arg name="parallel" value="75"/>
16
+ <arg value="np"/>
17
+
18
+ <!-- Don't hide tokenizer exceptions -->
19
+ <rule ref="Internal.Tokenizer.Exception">
20
+ <type>error</type>
21
+ </rule>
22
+
23
+ <!-- Include the whole PEAR standard -->
24
+ <rule ref="PEAR">
25
+ <exclude name="PEAR.NamingConventions.ValidFunctionName"/>
26
+ <exclude name="PEAR.NamingConventions.ValidVariableName"/>
27
+ <exclude name="PEAR.Commenting.ClassComment"/>
28
+ <exclude name="PEAR.Commenting.FileComment.MissingCategoryTag"/>
29
+ <exclude name="PEAR.Commenting.FileComment.MissingPackageTag"/>
30
+ <exclude name="PEAR.Commenting.FileComment.MissingLinkTag"/>
31
+ <exclude name="PEAR.Commenting.FileComment.MissingVersion"/>
32
+ <exclude name="PEAR.Commenting.InlineComment"/>
33
+ </rule>
34
+
35
+ <!-- Include some sniffs from other standards that don't conflict with PEAR -->
36
+ <rule ref="Squiz.Arrays.ArrayBracketSpacing"/>
37
+ <rule ref="Squiz.Arrays.ArrayDeclaration"/>
38
+ <rule ref="Squiz.Commenting.ClosingDeclarationComment"/>
39
+ <rule ref="Squiz.ControlStructures.ControlSignature"/>
40
+ <rule ref="Squiz.ControlStructures.ElseIfDeclaration"/>
41
+ <rule ref="Squiz.Commenting.BlockComment"/>
42
+ <rule ref="Squiz.Commenting.DocCommentAlignment"/>
43
+ <rule ref="Squiz.Commenting.EmptyCatchComment"/>
44
+ <rule ref="Squiz.Commenting.InlineComment"/>
45
+ <rule ref="Squiz.Commenting.LongConditionClosingComment"/>
46
+ <rule ref="Squiz.Commenting.PostStatementComment"/>
47
+ <rule ref="Squiz.Commenting.VariableComment"/>
48
+ <rule ref="Squiz.Formatting.OperatorBracket"/>
49
+ <rule ref="Squiz.Functions.FunctionDeclarationArgumentSpacing"/>
50
+ <rule ref="Squiz.Operators.ComparisonOperatorUsage"/>
51
+ <rule ref="Squiz.PHP.DisallowInlineIf"/>
52
+ <rule ref="Squiz.Scope.MethodScope"/>
53
+ <rule ref="Squiz.Strings.ConcatenationSpacing"/>
54
+ <rule ref="Squiz.WhiteSpace.ControlStructureSpacing"/>
55
+ <rule ref="Squiz.WhiteSpace.FunctionClosingBraceSpace"/>
56
+ <rule ref="Squiz.WhiteSpace.FunctionSpacing"/>
57
+ <rule ref="Squiz.WhiteSpace.OperatorSpacing"/>
58
+ <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/>
59
+ <rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
60
+ <rule ref="Generic.Commenting.Todo"/>
61
+ <rule ref="Generic.ControlStructures.InlineControlStructure"/>
62
+ <rule ref="Generic.Formatting.DisallowMultipleStatements"/>
63
+ <rule ref="Generic.Formatting.SpaceAfterCast"/>
64
+ <rule ref="Generic.NamingConventions.ConstructorName"/>
65
+ <rule ref="Generic.PHP.DeprecatedFunctions"/>
66
+ <rule ref="Generic.PHP.LowerCaseKeyword"/>
67
+ <rule ref="Generic.Strings.UnnecessaryStringConcat"/>
68
+ <rule ref="Generic.WhiteSpace.IncrementDecrementSpacing"/>
69
+ <rule ref="PSR2.Classes.PropertyDeclaration"/>
70
+ <rule ref="PSR2.Methods.MethodDeclaration"/>
71
+ <rule ref="PSR2.Files.EndFileNewline"/>
72
+ <rule ref="Zend.Files.ClosingTag"/>
73
+
74
+ <!-- PEAR uses warnings for inline control structures, so switch back to errors -->
75
+ <rule ref="Generic.ControlStructures.InlineControlStructure">
76
+ <properties>
77
+ <property name="error" value="true"/>
78
+ </properties>
79
+ </rule>
80
+
81
+ <!-- We use custom indent rules for arrays -->
82
+ <rule ref="Generic.Arrays.ArrayIndent"/>
83
+ <rule ref="Squiz.Arrays.ArrayDeclaration.KeyNotAligned">
84
+ <severity>0</severity>
85
+ </rule>
86
+ <rule ref="Squiz.Arrays.ArrayDeclaration.ValueNotAligned">
87
+ <severity>0</severity>
88
+ </rule>
89
+ <rule ref="Squiz.Arrays.ArrayDeclaration.CloseBraceNotAligned">
90
+ <severity>0</severity>
91
+ </rule>
92
+ <rule ref="Squiz.Arrays.ArrayDeclaration.CloseBraceNewLine">
93
+ <severity>0</severity>
94
+ </rule>
95
+
96
+ <!-- Check var names, but we don't want leading underscores for private vars -->
97
+ <rule ref="Squiz.NamingConventions.ValidVariableName"/>
98
+ <rule ref="Squiz.NamingConventions.ValidVariableName.PrivateNoUnderscore">
99
+ <severity>0</severity>
100
+ </rule>
101
+
102
+ <!-- Only one argument per line in multi-line function calls -->
103
+ <rule ref="PEAR.Functions.FunctionCallSignature">
104
+ <properties>
105
+ <property name="allowMultipleArguments" value="false"/>
106
+ </properties>
107
+ </rule>
108
+
109
+ <!-- Have 12 chars padding maximum and always show as errors -->
110
+ <rule ref="Generic.Formatting.MultipleStatementAlignment">
111
+ <properties>
112
+ <property name="maxPadding" value="12"/>
113
+ <property name="error" value="true"/>
114
+ </properties>
115
+ </rule>
116
+
117
+ <!-- Ban some functions -->
118
+ <rule ref="Generic.PHP.ForbiddenFunctions">
119
+ <properties>
120
+ <property name="forbiddenFunctions" type="array">
121
+ <element key="sizeof" value="count"/>
122
+ <element key="delete" value="unset"/>
123
+ <element key="print" value="echo"/>
124
+ <element key="is_null" value="null"/>
125
+ <element key="create_function" value="null"/>
126
+ </property>
127
+ </properties>
128
+ </rule>
129
+
130
+ <!-- Private methods MUST not be prefixed with an underscore -->
131
+ <rule ref="PSR2.Methods.MethodDeclaration.Underscore">
132
+ <type>error</type>
133
+ </rule>
134
+
135
+ <!-- Private properties MUST not be prefixed with an underscore -->
136
+ <rule ref="PSR2.Classes.PropertyDeclaration.Underscore">
137
+ <type>error</type>
138
+ </rule>
139
+
140
+ <!-- The testing bootstrap file uses string concats to stop IDEs seeing the class aliases -->
141
+ <rule ref="Generic.Strings.UnnecessaryStringConcat">
142
+ <exclude-pattern>tests/bootstrap.php</exclude-pattern>
143
+ </rule>
144
+
145
+ </ruleset>
vendor/php_codesniffer-3.4.0/phpcs.xsd ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified">
3
+
4
+ <xs:element name="ruleset">
5
+ <xs:complexType>
6
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
7
+ <xs:element name="description" type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
8
+ <xs:element name="config" maxOccurs="unbounded" minOccurs="0">
9
+ <xs:complexType>
10
+ <xs:attribute name="name" type="xs:string" use="required"></xs:attribute>
11
+ <xs:attribute name="value" type="xs:string" use="required"></xs:attribute>
12
+ </xs:complexType>
13
+ </xs:element>
14
+ <xs:element name="file" type="xs:string" maxOccurs="unbounded" minOccurs="0"></xs:element>
15
+ <xs:element name="exclude-pattern" type="patternType" maxOccurs="unbounded" minOccurs="0"></xs:element>
16
+ <xs:element name="arg" maxOccurs="unbounded" minOccurs="0">
17
+ <xs:complexType>
18
+ <xs:attribute name="name" type="xs:string"></xs:attribute>
19
+ <xs:attribute name="value" type="xs:string"></xs:attribute>
20
+ </xs:complexType>
21
+ </xs:element>
22
+ <xs:element name="ini" maxOccurs="unbounded" minOccurs="0">
23
+ <xs:complexType>
24
+ <xs:attribute name="name" type="xs:string" use="required"></xs:attribute>
25
+ <xs:attribute name="value" type="xs:string" use="required"></xs:attribute>
26
+ </xs:complexType>
27
+ </xs:element>
28
+ <xs:element name="autoload" type="xs:string" maxOccurs="unbounded" minOccurs="0"></xs:element>
29
+ <xs:element name="rule" type="ruleType" maxOccurs="unbounded" minOccurs="0"></xs:element>
30
+ </xs:choice>
31
+ <xs:attribute name="name" type="xs:string"></xs:attribute>
32
+ <xs:attribute name="namespace" type="xs:string"></xs:attribute>
33
+ </xs:complexType>
34
+ </xs:element>
35
+
36
+ <xs:complexType name="ruleType">
37
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
38
+ <xs:element name="exclude" maxOccurs="unbounded" minOccurs="0">
39
+ <xs:complexType>
40
+ <xs:attribute name="name" type="xs:string" use="required"></xs:attribute>
41
+ </xs:complexType>
42
+ </xs:element>
43
+ <xs:element name="message" type="xs:string" maxOccurs="1" minOccurs="0"></xs:element>
44
+ <xs:element name="severity" type="xs:integer" maxOccurs="1" minOccurs="0"></xs:element>
45
+ <xs:element name="type" maxOccurs="1" minOccurs="0">
46
+ <xs:simpleType>
47
+ <xs:restriction base="xs:string">
48
+ <xs:enumeration value="error"></xs:enumeration>
49
+ <xs:enumeration value="warning"></xs:enumeration>
50
+ </xs:restriction>
51
+ </xs:simpleType>
52
+ </xs:element>
53
+ <xs:element name="exclude-pattern" type="patternType" maxOccurs="unbounded" minOccurs="0"></xs:element>
54
+ <xs:element name="include-pattern" type="patternType" maxOccurs="unbounded" minOccurs="0"></xs:element>
55
+ <xs:element name="properties" type="propertiesType" maxOccurs="1" minOccurs="0"></xs:element>
56
+ </xs:choice>
57
+ <xs:attribute name="ref" type="xs:string" use="required"></xs:attribute>
58
+ </xs:complexType>
59
+
60
+ <xs:complexType name="patternType">
61
+ <xs:simpleContent>
62
+ <xs:extension base="xs:string">
63
+ <xs:attribute name="type">
64
+ <xs:simpleType>
65
+ <xs:restriction base="xs:string">
66
+ <xs:enumeration value="relative"></xs:enumeration>
67
+ </xs:restriction>
68
+ </xs:simpleType>
69
+ </xs:attribute>
70
+ </xs:extension>
71
+ </xs:simpleContent>
72
+ </xs:complexType>
73
+
74
+ <xs:complexType name="propertiesType">
75
+ <xs:sequence>
76
+ <xs:element name="property" maxOccurs="unbounded" minOccurs="1">
77
+ <xs:complexType>
78
+ <xs:sequence>
79
+ <xs:element name="element" maxOccurs="unbounded" minOccurs="0">
80
+ <xs:complexType>
81
+ <xs:attribute name="key" type="xs:string"></xs:attribute>
82
+ <xs:attribute name="value" type="xs:string" use="required"></xs:attribute>
83
+ </xs:complexType>
84
+ </xs:element>
85
+ </xs:sequence>
86
+ <xs:attribute name="type">
87
+ <xs:simpleType>
88
+ <xs:restriction base="xs:string">
89
+ <xs:enumeration value="array"></xs:enumeration>
90
+ </xs:restriction>
91
+ </xs:simpleType>
92
+ </xs:attribute>
93
+ <xs:attribute name="name" type="xs:string" use="required"></xs:attribute>
94
+ <xs:attribute name="value" type="xs:string"></xs:attribute>
95
+ <xs:attribute name="extend">
96
+ <xs:simpleType>
97
+ <xs:restriction base="xs:string">
98
+ <xs:enumeration value="true"/>
99
+ <xs:enumeration value="false"/>
100
+ </xs:restriction>
101
+ </xs:simpleType>
102
+ </xs:attribute>
103
+ </xs:complexType>
104
+ </xs:element>
105
+ </xs:sequence>
106
+ </xs:complexType>
107
+
108
+ </xs:schema>
vendor/php_codesniffer-3.4.0/src/Exceptions/DeepExitException.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An exception thrown by PHP_CodeSniffer when it wants to exit from somewhere not in the main runner.
4
+ *
5
+ * Allows the runner to return an exit code instead of putting exit codes elsewhere
6
+ * in the source code.
7
+ *
8
+ * @author Greg Sherwood <gsherwood@squiz.net>
9
+ * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
10
+ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
11
+ */
12
+
13
+ namespace PHP_CodeSniffer\Exceptions;
14
+
15
+ class DeepExitException extends \Exception
16
+ {
17
+
18
+ }//end class
vendor/php_codesniffer-3.4.0/src/Exceptions/RuntimeException.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An exception thrown by PHP_CodeSniffer when it encounters an unrecoverable error.
4
+ *
5
+ * @author Greg Sherwood <gsherwood@squiz.net>
6
+ * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
+ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
+ */
9
+
10
+ namespace PHP_CodeSniffer\Exceptions;
11
+
12
+ class RuntimeException extends \Exception
13
+ {
14
+
15
+ }//end class
vendor/php_codesniffer-3.4.0/src/Exceptions/TokenizerException.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An exception thrown by PHP_CodeSniffer when it encounters an unrecoverable tokenizer error.
4
+ *
5
+ * @author Greg Sherwood <gsherwood@squiz.net>
6
+ * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
+ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
+ */
9
+
10
+ namespace PHP_CodeSniffer\Exceptions;
11
+
12
+ class TokenizerException extends \Exception
13
+ {
14
+
15
+ }//end class
vendor/php_codesniffer-3.4.0/src/Tokenizers/CSS.php ADDED
@@ -0,0 +1,534 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Tokenizes CSS code.
4
+ *
5
+ * @author Greg Sherwood <gsherwood@squiz.net>
6
+ * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
+ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
+ */
9
+
10
+ namespace PHP_CodeSniffer\Tokenizers;
11
+
12
+ use PHP_CodeSniffer\Util;
13
+ use PHP_CodeSniffer\Config;
14
+ use PHP_CodeSniffer\Exceptions\TokenizerException;
15
+
16
+ class CSS extends PHP
17
+ {
18
+
19
+
20
+ /**
21
+ * Initialise the tokenizer.
22
+ *
23
+ * Pre-checks the content to see if it looks minified.
24
+ *
25
+ * @param string $content The content to tokenize,
26
+ * @param \PHP_CodeSniffer\Config $config The config data for the run.
27
+ * @param string $eolChar The EOL char used in the content.
28
+ *
29
+ * @return void
30
+ * @throws TokenizerException If the file appears to be minified.
31
+ */
32
+ public function __construct($content, Config $config, $eolChar='\n')
33
+ {
34
+ if ($this->isMinifiedContent($content, $eolChar) === true) {
35
+ throw new TokenizerException('File appears to be minified and cannot be processed');
36
+ }
37
+
38
+ return parent::__construct($content, $config, $eolChar);
39
+
40
+ }//end __construct()
41
+
42
+
43
+ /**
44
+ * Creates an array of tokens when given some CSS code.
45
+ *
46
+ * Uses the PHP tokenizer to do all the tricky work
47
+ *
48
+ * @param string $string The string to tokenize.
49
+ *
50
+ * @return array
51
+ */
52
+ public function tokenize($string)
53
+ {
54
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
55
+ echo "\t*** START CSS TOKENIZING 1ST PASS ***".PHP_EOL;
56
+ }
57
+
58
+ // If the content doesn't have an EOL char on the end, add one so
59
+ // the open and close tags we add are parsed correctly.
60
+ $eolAdded = false;
61
+ if (substr($string, (strlen($this->eolChar) * -1)) !== $this->eolChar) {
62
+ $string .= $this->eolChar;
63
+ $eolAdded = true;
64
+ }
65
+
66
+ $string = str_replace('<?php', '^PHPCS_CSS_T_OPEN_TAG^', $string);
67
+ $string = str_replace('?>', '^PHPCS_CSS_T_CLOSE_TAG^', $string);
68
+ $tokens = parent::tokenize('<?php '.$string.'?>');
69
+
70
+ $finalTokens = [];
71
+ $finalTokens[0] = [
72
+ 'code' => T_OPEN_TAG,
73
+ 'type' => 'T_OPEN_TAG',
74
+ 'content' => '',
75
+ ];
76
+
77
+ $newStackPtr = 1;
78
+ $numTokens = count($tokens);
79
+ $multiLineComment = false;
80
+ for ($stackPtr = 1; $stackPtr < $numTokens; $stackPtr++) {
81
+ $token = $tokens[$stackPtr];
82
+
83
+ // CSS files don't have lists, breaks etc, so convert these to
84
+ // standard strings early so they can be converted into T_STYLE
85
+ // tokens and joined with other strings if needed.
86
+ if ($token['code'] === T_BREAK
87
+ || $token['code'] === T_LIST
88
+ || $token['code'] === T_DEFAULT
89
+ || $token['code'] === T_SWITCH
90
+ || $token['code'] === T_FOR
91
+ || $token['code'] === T_FOREACH
92
+ || $token['code'] === T_WHILE
93
+ || $token['code'] === T_DEC
94
+ || $token['code'] === T_NEW
95
+ ) {
96
+ $token['type'] = 'T_STRING';
97
+ $token['code'] = T_STRING;
98
+ }
99
+
100
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
101
+ $type = $token['type'];
102
+ $content = Util\Common::prepareForOutput($token['content']);
103
+ echo "\tProcess token $stackPtr: $type => $content".PHP_EOL;
104
+ }
105
+
106
+ if ($token['code'] === T_BITWISE_XOR
107
+ && $tokens[($stackPtr + 1)]['content'] === 'PHPCS_CSS_T_OPEN_TAG'
108
+ ) {
109
+ $content = '<?php';
110
+ for ($stackPtr += 3; $stackPtr < $numTokens; $stackPtr++) {
111
+ if ($tokens[$stackPtr]['code'] === T_BITWISE_XOR
112
+ && $tokens[($stackPtr + 1)]['content'] === 'PHPCS_CSS_T_CLOSE_TAG'
113
+ ) {
114
+ // Add the end tag and ignore the * we put at the end.
115
+ $content .= '?>';
116
+ $stackPtr += 2;
117
+ break;
118
+ } else {
119
+ $content .= $tokens[$stackPtr]['content'];
120
+ }
121
+ }
122
+
123
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
124
+ echo "\t\t=> Found embedded PHP code: ";
125
+ $cleanContent = Util\Common::prepareForOutput($content);
126
+ echo $cleanContent.PHP_EOL;
127
+ }
128
+
129
+ $finalTokens[$newStackPtr] = [
130
+ 'type' => 'T_EMBEDDED_PHP',
131
+ 'code' => T_EMBEDDED_PHP,
132
+ 'content' => $content,
133
+ ];
134
+
135
+ $newStackPtr++;
136
+ continue;
137
+ }//end if
138
+
139
+ if ($token['code'] === T_GOTO_LABEL) {
140
+ // Convert these back to T_STRING followed by T_COLON so we can
141
+ // more easily process style definitions.
142
+ $finalTokens[$newStackPtr] = [
143
+ 'type' => 'T_STRING',
144
+ 'code' => T_STRING,
145
+ 'content' => substr($token['content'], 0, -1),
146
+ ];
147
+ $newStackPtr++;
148
+ $finalTokens[$newStackPtr] = [
149
+ 'type' => 'T_COLON',
150
+ 'code' => T_COLON,
151
+ 'content' => ':',
152
+ ];
153
+ $newStackPtr++;
154
+ continue;
155
+ }
156
+
157
+ if ($token['code'] === T_FUNCTION) {
158
+ // There are no functions in CSS, so convert this to a string.
159
+ $finalTokens[$newStackPtr] = [
160
+ 'type' => 'T_STRING',
161
+ 'code' => T_STRING,
162
+ 'content' => $token['content'],
163
+ ];
164
+
165
+ $newStackPtr++;
166
+ continue;
167
+ }
168
+
169
+ if ($token['code'] === T_COMMENT
170
+ && substr($token['content'], 0, 2) === '/*'
171
+ ) {
172
+ // Multi-line comment. Record it so we can ignore other
173
+ // comment tags until we get out of this one.
174
+ $multiLineComment = true;
175
+ }
176
+
177
+ if ($token['code'] === T_COMMENT
178
+ && $multiLineComment === false
179
+ && (substr($token['content'], 0, 2) === '//'
180
+ || $token['content']{0} === '#')
181
+ ) {
182
+ $content = ltrim($token['content'], '#/');
183
+
184
+ // Guard against PHP7+ syntax errors by stripping
185
+ // leading zeros so the content doesn't look like an invalid int.
186
+ $leadingZero = false;
187
+ if ($content{0} === '0') {
188
+ $content = '1'.$content;
189
+ $leadingZero = true;
190
+ }
191
+
192
+ $commentTokens = parent::tokenize('<?php '.$content.'?>');
193
+
194
+ // The first and last tokens are the open/close tags.
195
+ array_shift($commentTokens);
196
+ array_pop($commentTokens);
197
+
198
+ if ($leadingZero === true) {
199
+ $commentTokens[0]['content'] = substr($commentTokens[0]['content'], 1);
200
+ $content = substr($content, 1);
201
+ }
202
+
203
+ if ($token['content']{0} === '#') {
204
+ // The # character is not a comment in CSS files, so
205
+ // determine what it means in this context.
206
+ $firstContent = $commentTokens[0]['content'];
207
+
208
+ // If the first content is just a number, it is probably a
209
+ // colour like 8FB7DB, which PHP splits into 8 and FB7DB.
210
+ if (($commentTokens[0]['code'] === T_LNUMBER
211
+ || $commentTokens[0]['code'] === T_DNUMBER)
212
+ && $commentTokens[1]['code'] === T_STRING
213
+ ) {
214
+ $firstContent .= $commentTokens[1]['content'];
215
+ array_shift($commentTokens);
216
+ }
217
+
218
+ // If the first content looks like a colour and not a class
219
+ // definition, join the tokens together.
220
+ if (preg_match('/^[ABCDEF0-9]+$/i', $firstContent) === 1
221
+ && $commentTokens[1]['content'] !== '-'
222
+ ) {
223
+ array_shift($commentTokens);
224
+ // Work out what we trimmed off above and remember to re-add it.
225
+ $trimmed = substr($token['content'], 0, (strlen($token['content']) - strlen($content)));
226
+ $finalTokens[$newStackPtr] = [
227
+ 'type' => 'T_COLOUR',
228
+ 'code' => T_COLOUR,
229
+ 'content' => $trimmed.$firstContent,
230
+ ];
231
+ } else {
232
+ $finalTokens[$newStackPtr] = [
233
+ 'type' => 'T_HASH',
234
+ 'code' => T_HASH,
235
+ 'content' => '#',
236
+ ];
237
+ }
238
+ } else {
239
+ $finalTokens[$newStackPtr] = [
240
+ 'type' => 'T_STRING',
241
+ 'code' => T_STRING,
242
+ 'content' => '//',
243
+ ];
244
+ }//end if
245
+
246
+ $newStackPtr++;
247
+
248
+ array_splice($tokens, $stackPtr, 1, $commentTokens);
249
+ $numTokens = count($tokens);
250
+ $stackPtr--;
251
+ continue;
252
+ }//end if
253
+
254
+ if ($token['code'] === T_COMMENT
255
+ && substr($token['content'], -2) === '*/'
256
+ ) {
257
+ // Multi-line comment is done.
258
+ $multiLineComment = false;
259
+ }
260
+
261
+ $finalTokens[$newStackPtr] = $token;
262
+ $newStackPtr++;
263
+ }//end for
264
+
265
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
266
+ echo "\t*** END CSS TOKENIZING 1ST PASS ***".PHP_EOL;
267
+ echo "\t*** START CSS TOKENIZING 2ND PASS ***".PHP_EOL;
268
+ }
269
+
270
+ // A flag to indicate if we are inside a style definition,
271
+ // which is defined using curly braces.
272
+ $inStyleDef = false;
273
+
274
+ // A flag to indicate if an At-rule like "@media" is used, which will result
275
+ // in nested curly brackets.
276
+ $asperandStart = false;
277
+
278
+ $numTokens = count($finalTokens);
279
+ for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) {
280
+ $token = $finalTokens[$stackPtr];
281
+
282
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
283
+ $type = $token['type'];
284
+ $content = Util\Common::prepareForOutput($token['content']);
285
+ echo "\tProcess token $stackPtr: $type => $content".PHP_EOL;
286
+ }
287
+
288
+ switch ($token['code']) {
289
+ case T_OPEN_CURLY_BRACKET:
290
+ // Opening curly brackets for an At-rule do not start a style
291
+ // definition. We also reset the asperand flag here because the next
292
+ // opening curly bracket could be indeed the start of a style
293
+ // definition.
294
+ if ($asperandStart === true) {
295
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
296
+ if ($inStyleDef === true) {
297
+ echo "\t\t* style definition closed *".PHP_EOL;
298
+ }
299
+
300
+ if ($asperandStart === true) {
301
+ echo "\t\t* at-rule definition closed *".PHP_EOL;
302
+ }
303
+ }
304
+
305
+ $inStyleDef = false;
306
+ $asperandStart = false;
307
+ } else {
308
+ $inStyleDef = true;
309
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
310
+ echo "\t\t* style definition opened *".PHP_EOL;
311
+ }
312
+ }
313
+ break;
314
+ case T_CLOSE_CURLY_BRACKET:
315
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
316
+ if ($inStyleDef === true) {
317
+ echo "\t\t* style definition closed *".PHP_EOL;
318
+ }
319
+
320
+ if ($asperandStart === true) {
321
+ echo "\t\t* at-rule definition closed *".PHP_EOL;
322
+ }
323
+ }
324
+
325
+ $inStyleDef = false;
326
+ $asperandStart = false;
327
+ break;
328
+ case T_MINUS:
329
+ // Minus signs are often used instead of spaces inside
330
+ // class names, IDs and styles.
331
+ if ($finalTokens[($stackPtr + 1)]['code'] === T_STRING) {
332
+ if ($finalTokens[($stackPtr - 1)]['code'] === T_STRING) {
333
+ $newContent = $finalTokens[($stackPtr - 1)]['content'].'-'.$finalTokens[($stackPtr + 1)]['content'];
334
+
335
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
336
+ echo "\t\t* token is a string joiner; ignoring this and previous token".PHP_EOL;
337
+ $old = Util\Common::prepareForOutput($finalTokens[($stackPtr + 1)]['content']);
338
+ $new = Util\Common::prepareForOutput($newContent);
339
+ echo "\t\t=> token ".($stackPtr + 1)." content changed from \"$old\" to \"$new\"".PHP_EOL;
340
+ }
341
+
342
+ $finalTokens[($stackPtr + 1)]['content'] = $newContent;
343
+ unset($finalTokens[$stackPtr]);
344
+ unset($finalTokens[($stackPtr - 1)]);
345
+ } else {
346
+ $newContent = '-'.$finalTokens[($stackPtr + 1)]['content'];
347
+
348
+ $finalTokens[($stackPtr + 1)]['content'] = $newContent;
349
+ unset($finalTokens[$stackPtr]);
350
+ }
351
+ } else if ($finalTokens[($stackPtr + 1)]['code'] === T_LNUMBER) {
352
+ // They can also be used to provide negative numbers.
353
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
354
+ echo "\t\t* token is part of a negative number; adding content to next token and ignoring *".PHP_EOL;
355
+ $content = Util\Common::prepareForOutput($finalTokens[($stackPtr + 1)]['content']);
356
+ echo "\t\t=> token ".($stackPtr + 1)." content changed from \"$content\" to \"-$content\"".PHP_EOL;
357
+ }
358
+
359
+ $finalTokens[($stackPtr + 1)]['content'] = '-'.$finalTokens[($stackPtr + 1)]['content'];
360
+ unset($finalTokens[$stackPtr]);
361
+ }//end if
362
+ break;
363
+ case T_COLON:
364
+ // Only interested in colons that are defining styles.
365
+ if ($inStyleDef === false) {
366
+ break;
367
+ }
368
+
369
+ for ($x = ($stackPtr - 1); $x >= 0; $x--) {
370
+ if (isset(Util\Tokens::$emptyTokens[$finalTokens[$x]['code']]) === false) {
371
+ break;
372
+ }
373
+ }
374
+
375
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
376
+ $type = $finalTokens[$x]['type'];
377
+ echo "\t\t=> token $x changed from $type to T_STYLE".PHP_EOL;
378
+ }
379
+
380
+ $finalTokens[$x]['type'] = 'T_STYLE';
381
+ $finalTokens[$x]['code'] = T_STYLE;
382
+ break;
383
+ case T_STRING:
384
+ if (strtolower($token['content']) === 'url') {
385
+ // Find the next content.
386
+ for ($x = ($stackPtr + 1); $x < $numTokens; $x++) {
387
+ if (isset(Util\Tokens::$emptyTokens[$finalTokens[$x]['code']]) === false) {
388
+ break;
389
+ }
390
+ }
391
+
392
+ // Needs to be in the format "url(" for it to be a URL.
393
+ if ($finalTokens[$x]['code'] !== T_OPEN_PARENTHESIS) {
394
+ continue 2;
395
+ }
396
+
397
+ // Make sure the content isn't empty.
398
+ for ($y = ($x + 1); $y < $numTokens; $y++) {
399
+ if (isset(Util\Tokens::$emptyTokens[$finalTokens[$y]['code']]) === false) {
400
+ break;
401
+ }
402
+ }
403
+
404
+ if ($finalTokens[$y]['code'] === T_CLOSE_PARENTHESIS) {
405
+ continue 2;
406
+ }
407
+
408
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
409
+ for ($i = ($stackPtr + 1); $i <= $y; $i++) {
410
+ $type = $finalTokens[$i]['type'];
411
+ $content = Util\Common::prepareForOutput($finalTokens[$i]['content']);
412
+ echo "\tProcess token $i: $type => $content".PHP_EOL;
413
+ }
414
+
415
+ echo "\t\t* token starts a URL *".PHP_EOL;
416
+ }
417
+
418
+ // Join all the content together inside the url() statement.
419
+ $newContent = '';
420
+ for ($i = ($x + 2); $i < $numTokens; $i++) {
421
+ if ($finalTokens[$i]['code'] === T_CLOSE_PARENTHESIS) {
422
+ break;
423
+ }
424
+
425
+ $newContent .= $finalTokens[$i]['content'];
426
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
427
+ $content = Util\Common::prepareForOutput($finalTokens[$i]['content']);
428
+ echo "\t\t=> token $i added to URL string and ignored: $content".PHP_EOL;
429
+ }
430
+
431
+ unset($finalTokens[$i]);
432
+ }
433
+
434
+ $stackPtr = $i;
435
+
436
+ // If the content inside the "url()" is in double quotes
437
+ // there will only be one token and so we don't have to do
438
+ // anything except change its type. If it is not empty,
439
+ // we need to do some token merging.
440
+ $finalTokens[($x + 1)]['type'] = 'T_URL';
441
+ $finalTokens[($x + 1)]['code'] = T_URL;
442
+
443
+ if ($newContent !== '') {
444
+ $finalTokens[($x + 1)]['content'] .= $newContent;
445
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
446
+ $content = Util\Common::prepareForOutput($finalTokens[($x + 1)]['content']);
447
+ echo "\t\t=> token content changed to: $content".PHP_EOL;
448
+ }
449
+ }
450
+ } else if ($finalTokens[$stackPtr]['content'][0] === '-'
451
+ && $finalTokens[($stackPtr + 1)]['code'] === T_STRING
452
+ ) {
453
+ if (isset($finalTokens[($stackPtr - 1)]) === true
454
+ && $finalTokens[($stackPtr - 1)]['code'] === T_STRING
455
+ ) {
456
+ $newContent = $finalTokens[($stackPtr - 1)]['content'].$finalTokens[$stackPtr]['content'].$finalTokens[($stackPtr + 1)]['content'];
457
+
458
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
459
+ echo "\t\t* token is a string joiner; ignoring this and previous token".PHP_EOL;
460
+ $old = Util\Common::prepareForOutput($finalTokens[($stackPtr + 1)]['content']);
461
+ $new = Util\Common::prepareForOutput($newContent);
462
+ echo "\t\t=> token ".($stackPtr + 1)." content changed from \"$old\" to \"$new\"".PHP_EOL;
463
+ }
464
+
465
+ $finalTokens[($stackPtr + 1)]['content'] = $newContent;
466
+ unset($finalTokens[$stackPtr]);
467
+ unset($finalTokens[($stackPtr - 1)]);
468
+ } else {
469
+ $newContent = $finalTokens[$stackPtr]['content'].$finalTokens[($stackPtr + 1)]['content'];
470
+
471
+ $finalTokens[($stackPtr + 1)]['content'] = $newContent;
472
+ unset($finalTokens[$stackPtr]);
473
+ }
474
+ }//end if
475
+ break;
476
+ case T_ASPERAND:
477
+ $asperandStart = true;
478
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
479
+ echo "\t\t* at-rule definition opened *".PHP_EOL;
480
+ }
481
+ break;
482
+ default:
483
+ // Nothing special to be done with this token.
484
+ break;
485
+ }//end switch
486
+ }//end for
487
+
488
+ // Reset the array keys to avoid gaps.
489
+ $finalTokens = array_values($finalTokens);
490
+ $numTokens = count($finalTokens);
491
+
492
+ // Blank out the content of the end tag.
493
+ $finalTokens[($numTokens - 1)]['content'] = '';
494
+
495
+ if ($eolAdded === true) {
496
+ // Strip off the extra EOL char we added for tokenizing.
497
+ $finalTokens[($numTokens - 2)]['content'] = substr(
498
+ $finalTokens[($numTokens - 2)]['content'],
499
+ 0,
500
+ (strlen($this->eolChar) * -1)
501
+ );
502
+
503
+ if ($finalTokens[($numTokens - 2)]['content'] === '') {
504
+ unset($finalTokens[($numTokens - 2)]);
505
+ $finalTokens = array_values($finalTokens);
506
+ $numTokens = count($finalTokens);
507
+ }
508
+ }
509
+
510
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
511
+ echo "\t*** END CSS TOKENIZING 2ND PASS ***".PHP_EOL;
512
+ }
513
+
514
+ return $finalTokens;
515
+
516
+ }//end tokenize()
517
+
518
+
519
+ /**
520
+ * Performs additional processing after main tokenizing.
521
+ *
522
+ * @return void
523
+ */
524
+ public function processAdditional()
525
+ {
526
+ /*
527
+ We override this method because we don't want the PHP version to
528
+ run during CSS processing because it is wasted processing time.
529
+ */
530
+
531
+ }//end processAdditional()
532
+
533
+
534
+ }//end class
vendor/php_codesniffer-3.4.0/src/Tokenizers/Comment.php ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Tokenizes doc block comments.
4
+ *
5
+ * @author Greg Sherwood <gsherwood@squiz.net>
6
+ * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
+ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
+ */
9
+
10
+ namespace PHP_CodeSniffer\Tokenizers;
11
+
12
+ use PHP_CodeSniffer\Util;
13
+
14
+ class Comment
15
+ {
16
+
17
+
18
+ /**
19
+ * Creates an array of tokens when given some PHP code.
20
+ *
21
+ * Starts by using token_get_all() but does a lot of extra processing
22
+ * to insert information about the context of the token.
23
+ *
24
+ * @param string $string The string to tokenize.
25
+ * @param string $eolChar The EOL character to use for splitting strings.
26
+ * @param int $stackPtr The position of the first token in the file.
27
+ *
28
+ * @return array
29
+ */
30
+ public function tokenizeString($string, $eolChar, $stackPtr)
31
+ {
32
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
33
+ echo "\t\t*** START COMMENT TOKENIZING ***".PHP_EOL;
34
+ }
35
+
36
+ $tokens = [];
37
+ $numChars = strlen($string);
38
+
39
+ /*
40
+ Doc block comments start with /*, but typically contain an
41
+ extra star when they are used for function and class comments.
42
+ */
43
+
44
+ $char = ($numChars - strlen(ltrim($string, '/*')));
45
+ $openTag = substr($string, 0, $char);
46
+ $string = ltrim($string, '/*');
47
+
48
+ $tokens[$stackPtr] = [
49
+ 'content' => $openTag,
50
+ 'code' => T_DOC_COMMENT_OPEN_TAG,
51
+ 'type' => 'T_DOC_COMMENT_OPEN_TAG',
52
+ 'comment_tags' => [],
53
+ ];
54
+
55
+ $openPtr = $stackPtr;
56
+ $stackPtr++;
57
+
58
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
59
+ $content = Util\Common::prepareForOutput($openTag);
60
+ echo "\t\tCreate comment token: T_DOC_COMMENT_OPEN_TAG => $content".PHP_EOL;
61
+ }
62
+
63
+ /*
64
+ Strip off the close tag so it doesn't interfere with any
65
+ of our comment line processing. The token will be added to the
66
+ stack just before we return it.
67
+ */
68
+
69
+ $closeTag = [
70
+ 'content' => substr($string, strlen(rtrim($string, '/*'))),
71
+ 'code' => T_DOC_COMMENT_CLOSE_TAG,
72
+ 'type' => 'T_DOC_COMMENT_CLOSE_TAG',
73
+ 'comment_opener' => $openPtr,
74
+ ];
75
+
76
+ if ($closeTag['content'] === false) {
77
+ $closeTag['content'] = '';
78
+ }
79
+
80
+ $string = rtrim($string, '/*');
81
+
82
+ /*
83
+ Process each line of the comment.
84
+ */
85
+
86
+ $lines = explode($eolChar, $string);
87
+ $numLines = count($lines);
88
+ foreach ($lines as $lineNum => $string) {
89
+ if ($lineNum !== ($numLines - 1)) {
90
+ $string .= $eolChar;
91
+ }
92
+
93
+ $char = 0;
94
+ $numChars = strlen($string);
95
+
96
+ // We've started a new line, so process the indent.
97
+ $space = $this->collectWhitespace($string, $char, $numChars);
98
+ if ($space !== null) {
99
+ $tokens[$stackPtr] = $space;
100
+ $stackPtr++;
101
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
102
+ $content = Util\Common::prepareForOutput($space['content']);
103
+ echo "\t\tCreate comment token: T_DOC_COMMENT_WHITESPACE => $content".PHP_EOL;
104
+ }
105
+
106
+ $char += strlen($space['content']);
107
+ if ($char === $numChars) {
108
+ break;
109
+ }
110
+ }
111
+
112
+ if ($string === '') {
113
+ continue;
114
+ }
115
+
116
+ if ($lineNum > 0 && $string[$char] === '*') {
117
+ // This is a function or class doc block line.
118
+ $char++;
119
+ $tokens[$stackPtr] = [
120
+ 'content' => '*',
121
+ 'code' => T_DOC_COMMENT_STAR,
122
+ 'type' => 'T_DOC_COMMENT_STAR',
123
+ ];
124
+
125
+ $stackPtr++;
126
+
127
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
128
+ echo "\t\tCreate comment token: T_DOC_COMMENT_STAR => *".PHP_EOL;
129
+ }
130
+ }
131
+
132
+ // Now we are ready to process the actual content of the line.
133
+ $lineTokens = $this->processLine($string, $eolChar, $char, $numChars);
134
+ foreach ($lineTokens as $lineToken) {
135
+ $tokens[$stackPtr] = $lineToken;
136
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
137
+ $content = Util\Common::prepareForOutput($lineToken['content']);
138
+ $type = $lineToken['type'];
139
+ echo "\t\tCreate comment token: $type => $content".PHP_EOL;
140
+ }
141
+
142
+ if ($lineToken['code'] === T_DOC_COMMENT_TAG) {
143
+ $tokens[$openPtr]['comment_tags'][] = $stackPtr;
144
+ }
145
+
146
+ $stackPtr++;
147
+ }
148
+ }//end foreach
149
+
150
+ $tokens[$stackPtr] = $closeTag;
151
+ $tokens[$openPtr]['comment_closer'] = $stackPtr;
152
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
153
+ $content = Util\Common::prepareForOutput($closeTag['content']);
154
+ echo "\t\tCreate comment token: T_DOC_COMMENT_CLOSE_TAG => $content".PHP_EOL;
155
+ }
156
+
157
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
158
+ echo "\t\t*** END COMMENT TOKENIZING ***".PHP_EOL;
159
+ }
160
+
161
+ return $tokens;
162
+
163
+ }//end tokenizeString()
164
+
165
+
166
+ /**
167
+ * Process a single line of a comment.
168
+ *
169
+ * @param string $string The comment string being tokenized.
170
+ * @param string $eolChar The EOL character to use for splitting strings.
171
+ * @param int $start The position in the string to start processing.
172
+ * @param int $end The position in the string to end processing.
173
+ *
174
+ * @return array
175
+ */
176
+ private function processLine($string, $eolChar, $start, $end)
177
+ {
178
+ $tokens = [];
179
+
180
+ // Collect content padding.
181
+ $space = $this->collectWhitespace($string, $start, $end);
182
+ if ($space !== null) {
183
+ $tokens[] = $space;
184
+ $start += strlen($space['content']);
185
+ }
186
+
187
+ if (isset($string[$start]) === false) {
188
+ return $tokens;
189
+ }
190
+
191
+ if ($string[$start] === '@') {
192
+ // The content up until the first whitespace is the tag name.
193
+ $matches = [];
194
+ preg_match('/@[^\s]+/', $string, $matches, 0, $start);
195
+ if (isset($matches[0]) === true
196
+ && substr(strtolower($matches[0]), 0, 7) !== '@phpcs:'
197
+ ) {
198
+ $tagName = $matches[0];
199
+ $start += strlen($tagName);
200
+ $tokens[] = [
201
+ 'content' => $tagName,
202
+ 'code' => T_DOC_COMMENT_TAG,
203
+ 'type' => 'T_DOC_COMMENT_TAG',
204
+ ];
205
+
206
+ // Then there will be some whitespace.
207
+ $space = $this->collectWhitespace($string, $start, $end);
208
+ if ($space !== null) {
209
+ $tokens[] = $space;
210
+ $start += strlen($space['content']);
211
+ }
212
+ }
213
+ }//end if
214
+
215
+ // Process the rest of the line.
216
+ $eol = strpos($string, $eolChar, $start);
217
+ if ($eol === false) {
218
+ $eol = $end;
219
+ }
220
+
221
+ if ($eol > $start) {
222
+ $tokens[] = [
223
+ 'content' => substr($string, $start, ($eol - $start)),
224
+ 'code' => T_DOC_COMMENT_STRING,
225
+ 'type' => 'T_DOC_COMMENT_STRING',
226
+ ];
227
+ }
228
+
229
+ if ($eol !== $end) {
230
+ $tokens[] = [
231
+ 'content' => substr($string, $eol, strlen($eolChar)),
232
+ 'code' => T_DOC_COMMENT_WHITESPACE,
233
+ 'type' => 'T_DOC_COMMENT_WHITESPACE',
234
+ ];
235
+ }
236
+
237
+ return $tokens;
238
+
239
+ }//end processLine()
240
+
241
+
242
+ /**
243
+ * Collect consecutive whitespace into a single token.
244
+ *
245
+ * @param string $string The comment string being tokenized.
246
+ * @param int $start The position in the string to start processing.
247
+ * @param int $end The position in the string to end processing.
248
+ *
249
+ * @return array|null
250
+ */
251
+ private function collectWhitespace($string, $start, $end)
252
+ {
253
+ $space = '';
254
+ for ($start; $start < $end; $start++) {
255
+ if ($string[$start] !== ' ' && $string[$start] !== "\t") {
256
+ break;
257
+ }
258
+
259
+ $space .= $string[$start];
260
+ }
261
+
262
+ if ($space === '') {
263
+ return null;
264
+ }
265
+
266
+ $token = [
267
+ 'content' => $space,
268
+ 'code' => T_DOC_COMMENT_WHITESPACE,
269
+ 'type' => 'T_DOC_COMMENT_WHITESPACE',
270
+ ];
271
+
272
+ return $token;
273
+
274
+ }//end collectWhitespace()
275
+
276
+
277
+ }//end class
vendor/php_codesniffer-3.4.0/src/Tokenizers/JS.php ADDED
@@ -0,0 +1,1264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Tokenizes JS code.
4
+ *
5
+ * @author Greg Sherwood <gsherwood@squiz.net>
6
+ * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
+ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
+ */
9
+
10
+ namespace PHP_CodeSniffer\Tokenizers;
11
+
12
+ use PHP_CodeSniffer\Util;
13
+ use PHP_CodeSniffer\Exceptions\TokenizerException;
14
+ use PHP_CodeSniffer\Config;
15
+
16
+ class JS extends Tokenizer
17
+ {
18
+
19
+
20
+ /**
21
+ * A list of tokens that are allowed to open a scope.
22
+ *
23
+ * This array also contains information about what kind of token the scope
24
+ * opener uses to open and close the scope, if the token strictly requires
25
+ * an opener, if the token can share a scope closer, and who it can be shared
26
+ * with. An example of a token that shares a scope closer is a CASE scope.
27
+ *
28
+ * @var array
29
+ */
30
+ public $scopeOpeners = [
31
+ T_IF => [
32
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
33
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
34
+ 'strict' => false,
35
+ 'shared' => false,
36
+ 'with' => [],
37
+ ],
38
+ T_TRY => [
39
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
40
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
41
+ 'strict' => true,
42
+ 'shared' => false,
43
+ 'with' => [],
44
+ ],
45
+ T_CATCH => [
46
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
47
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
48
+ 'strict' => true,
49
+ 'shared' => false,
50
+ 'with' => [],
51
+ ],
52
+ T_ELSE => [
53
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
54
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
55
+ 'strict' => false,
56
+ 'shared' => false,
57
+ 'with' => [],
58
+ ],
59
+ T_FOR => [
60
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
61
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
62
+ 'strict' => false,
63
+ 'shared' => false,
64
+ 'with' => [],
65
+ ],
66
+ T_CLASS => [
67
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
68
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
69
+ 'strict' => true,
70
+ 'shared' => false,
71
+ 'with' => [],
72
+ ],
73
+ T_FUNCTION => [
74
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
75
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
76
+ 'strict' => false,
77
+ 'shared' => false,
78
+ 'with' => [],
79
+ ],
80
+ T_WHILE => [
81
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
82
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
83
+ 'strict' => false,
84
+ 'shared' => false,
85
+ 'with' => [],
86
+ ],
87
+ T_DO => [
88
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
89
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
90
+ 'strict' => true,
91
+ 'shared' => false,
92
+ 'with' => [],
93
+ ],
94
+ T_SWITCH => [
95
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
96
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
97
+ 'strict' => true,
98
+ 'shared' => false,
99
+ 'with' => [],
100
+ ],
101
+ T_CASE => [
102
+ 'start' => [T_COLON => T_COLON],
103
+ 'end' => [
104
+ T_BREAK => T_BREAK,
105
+ T_RETURN => T_RETURN,
106
+ T_CONTINUE => T_CONTINUE,
107
+ T_THROW => T_THROW,
108
+ ],
109
+ 'strict' => true,
110
+ 'shared' => true,
111
+ 'with' => [
112
+ T_DEFAULT => T_DEFAULT,
113
+ T_CASE => T_CASE,
114
+ T_SWITCH => T_SWITCH,
115
+ ],
116
+ ],
117
+ T_DEFAULT => [
118
+ 'start' => [T_COLON => T_COLON],
119
+ 'end' => [
120
+ T_BREAK => T_BREAK,
121
+ T_RETURN => T_RETURN,
122
+ T_CONTINUE => T_CONTINUE,
123
+ T_THROW => T_THROW,
124
+ ],
125
+ 'strict' => true,
126
+ 'shared' => true,
127
+ 'with' => [
128
+ T_CASE => T_CASE,
129
+ T_SWITCH => T_SWITCH,
130
+ ],
131
+ ],
132
+ ];
133
+
134
+ /**
135
+ * A list of tokens that end the scope.
136
+ *
137
+ * This array is just a unique collection of the end tokens
138
+ * from the _scopeOpeners array. The data is duplicated here to
139
+ * save time during parsing of the file.
140
+ *
141
+ * @var array
142
+ */
143
+ public $endScopeTokens = [
144
+ T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
145
+ T_BREAK => T_BREAK,
146
+ ];
147
+
148
+ /**
149
+ * A list of special JS tokens and their types.
150
+ *
151
+ * @var array
152
+ */
153
+ protected $tokenValues = [
154
+ 'class' => 'T_CLASS',
155
+ 'function' => 'T_FUNCTION',
156
+ 'prototype' => 'T_PROTOTYPE',
157
+ 'try' => 'T_TRY',
158
+ 'catch' => 'T_CATCH',
159
+ 'return' => 'T_RETURN',
160
+ 'throw' => 'T_THROW',
161
+ 'break' => 'T_BREAK',
162
+ 'switch' => 'T_SWITCH',
163
+ 'continue' => 'T_CONTINUE',
164
+ 'if' => 'T_IF',
165
+ 'else' => 'T_ELSE',
166
+ 'do' => 'T_DO',
167
+ 'while' => 'T_WHILE',
168
+ 'for' => 'T_FOR',
169
+ 'var' => 'T_VAR',
170
+ 'case' => 'T_CASE',
171
+ 'default' => 'T_DEFAULT',
172
+ 'true' => 'T_TRUE',
173
+ 'false' => 'T_FALSE',
174
+ 'null' => 'T_NULL',
175
+ 'this' => 'T_THIS',
176
+ 'typeof' => 'T_TYPEOF',
177
+ '(' => 'T_OPEN_PARENTHESIS',
178
+ ')' => 'T_CLOSE_PARENTHESIS',
179
+ '{' => 'T_OPEN_CURLY_BRACKET',
180
+ '}' => 'T_CLOSE_CURLY_BRACKET',
181
+ '[' => 'T_OPEN_SQUARE_BRACKET',
182
+ ']' => 'T_CLOSE_SQUARE_BRACKET',
183
+ '?' => 'T_INLINE_THEN',
184
+ '.' => 'T_OBJECT_OPERATOR',
185
+ '+' => 'T_PLUS',
186
+ '-' => 'T_MINUS',
187
+ '*' => 'T_MULTIPLY',
188
+ '%' => 'T_MODULUS',
189
+ '/' => 'T_DIVIDE',
190
+ '^' => 'T_LOGICAL_XOR',
191
+ ',' => 'T_COMMA',
192
+ ';' => 'T_SEMICOLON',
193
+ ':' => 'T_COLON',
194
+ '<' => 'T_LESS_THAN',
195
+ '>' => 'T_GREATER_THAN',
196
+ '<<' => 'T_SL',
197
+ '>>' => 'T_SR',
198
+ '>>>' => 'T_ZSR',
199
+ '<<=' => 'T_SL_EQUAL',
200
+ '>>=' => 'T_SR_EQUAL',
201
+ '>>>=' => 'T_ZSR_EQUAL',
202
+ '<=' => 'T_IS_SMALLER_OR_EQUAL',
203
+ '>=' => 'T_IS_GREATER_OR_EQUAL',
204
+ '=>' => 'T_DOUBLE_ARROW',
205
+ '!' => 'T_BOOLEAN_NOT',
206
+ '||' => 'T_BOOLEAN_OR',
207
+ '&&' => 'T_BOOLEAN_AND',
208
+ '|' => 'T_BITWISE_OR',
209
+ '&' => 'T_BITWISE_AND',
210
+ '!=' => 'T_IS_NOT_EQUAL',
211
+ '!==' => 'T_IS_NOT_IDENTICAL',
212
+ '=' => 'T_EQUAL',
213
+ '==' => 'T_IS_EQUAL',
214
+ '===' => 'T_IS_IDENTICAL',
215
+ '-=' => 'T_MINUS_EQUAL',
216
+ '+=' => 'T_PLUS_EQUAL',
217
+ '*=' => 'T_MUL_EQUAL',
218
+ '/=' => 'T_DIV_EQUAL',
219
+ '%=' => 'T_MOD_EQUAL',
220
+ '++' => 'T_INC',
221
+ '--' => 'T_DEC',
222
+ '//' => 'T_COMMENT',
223
+ '/*' => 'T_COMMENT',
224
+ '/**' => 'T_DOC_COMMENT',
225
+ '*/' => 'T_COMMENT',
226
+ ];
227
+
228
+ /**
229
+ * A list string delimiters.
230
+ *
231
+ * @var array
232
+ */
233
+ protected $stringTokens = [
234
+ '\'' => '\'',
235
+ '"' => '"',
236
+ ];
237
+
238
+ /**
239
+ * A list tokens that start and end comments.
240
+ *
241
+ * @var array
242
+ */
243
+ protected $commentTokens = [
244
+ '//' => null,
245
+ '/*' => '*/',
246
+ '/**' => '*/',
247
+ ];
248
+
249
+
250
+ /**
251
+ * Initialise the tokenizer.
252
+ *
253
+ * Pre-checks the content to see if it looks minified.
254
+ *
255
+ * @param string $content The content to tokenize,
256
+ * @param \PHP_CodeSniffer\Config $config The config data for the run.
257
+ * @param string $eolChar The EOL char used in the content.
258
+ *
259
+ * @return void
260
+ * @throws TokenizerException If the file appears to be minified.
261
+ */
262
+ public function __construct($content, Config $config, $eolChar='\n')
263
+ {
264
+ if ($this->isMinifiedContent($content, $eolChar) === true) {
265
+ throw new TokenizerException('File appears to be minified and cannot be processed');
266
+ }
267
+
268
+ return parent::__construct($content, $config, $eolChar);
269
+
270
+ }//end __construct()
271
+
272
+
273
+ /**
274
+ * Creates an array of tokens when given some JS code.
275
+ *
276
+ * @param string $string The string to tokenize.
277
+ *
278
+ * @return array
279
+ */
280
+ public function tokenize($string)
281
+ {
282
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
283
+ echo "\t*** START JS TOKENIZING ***".PHP_EOL;
284
+ }
285
+
286
+ $maxTokenLength = 0;
287
+ foreach ($this->tokenValues as $token => $values) {
288
+ if (strlen($token) > $maxTokenLength) {
289
+ $maxTokenLength = strlen($token);
290
+ }
291
+ }
292
+
293
+ $tokens = [];
294
+ $inString = '';
295
+ $stringChar = null;
296
+ $inComment = '';
297
+ $buffer = '';
298
+ $preStringBuffer = '';
299
+ $cleanBuffer = false;
300
+
301
+ $commentTokenizer = new Comment();
302
+
303
+ $tokens[] = [
304
+ 'code' => T_OPEN_TAG,
305
+ 'type' => 'T_OPEN_TAG',
306
+ 'content' => '',
307
+ ];
308
+
309
+ // Convert newlines to single characters for ease of
310
+ // processing. We will change them back later.
311
+ $string = str_replace($this->eolChar, "\n", $string);
312
+
313
+ $chars = str_split($string);
314
+ $numChars = count($chars);
315
+ for ($i = 0; $i < $numChars; $i++) {
316
+ $char = $chars[$i];
317
+
318
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
319
+ $content = Util\Common::prepareForOutput($char);
320
+ $bufferContent = Util\Common::prepareForOutput($buffer);
321
+
322
+ if ($inString !== '') {
323
+ echo "\t";
324
+ }
325
+
326
+ if ($inComment !== '') {
327
+ echo "\t";
328
+ }
329
+
330
+ echo "\tProcess char $i => $content (buffer: $bufferContent)".PHP_EOL;
331
+ }//end if
332
+
333
+ if ($inString === '' && $inComment === '' && $buffer !== '') {
334
+ // If the buffer only has whitespace and we are about to
335
+ // add a character, store the whitespace first.
336
+ if (trim($char) !== '' && trim($buffer) === '') {
337
+ $tokens[] = [
338
+ 'code' => T_WHITESPACE,
339
+ 'type' => 'T_WHITESPACE',
340
+ 'content' => str_replace("\n", $this->eolChar, $buffer),
341
+ ];
342
+
343
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
344
+ $content = Util\Common::prepareForOutput($buffer);
345
+ echo "\t=> Added token T_WHITESPACE ($content)".PHP_EOL;
346
+ }
347
+
348
+ $buffer = '';
349
+ }
350
+
351
+ // If the buffer is not whitespace and we are about to
352
+ // add a whitespace character, store the content first.
353
+ if ($inString === ''
354
+ && $inComment === ''
355
+ && trim($char) === ''
356
+ && trim($buffer) !== ''
357
+ ) {
358
+ $tokens[] = [
359
+ 'code' => T_STRING,
360
+ 'type' => 'T_STRING',
361
+ 'content' => str_replace("\n", $this->eolChar, $buffer),
362
+ ];
363
+
364
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
365
+ $content = Util\Common::prepareForOutput($buffer);
366
+ echo "\t=> Added token T_STRING ($content)".PHP_EOL;
367
+ }
368
+
369
+ $buffer = '';
370
+ }
371
+ }//end if
372
+
373
+ // Process strings.
374
+ if ($inComment === '' && isset($this->stringTokens[$char]) === true) {
375
+ if ($inString === $char) {
376
+ // This could be the end of the string, but make sure it
377
+ // is not escaped first.
378
+ $escapes = 0;
379
+ for ($x = ($i - 1); $x >= 0; $x--) {
380
+ if ($chars[$x] !== '\\') {
381
+ break;
382
+ }
383
+
384
+ $escapes++;
385
+ }
386
+
387
+ if ($escapes === 0 || ($escapes % 2) === 0) {
388
+ // There is an even number escape chars,
389
+ // so this is not escaped, it is the end of the string.
390
+ $tokens[] = [
391
+ 'code' => T_CONSTANT_ENCAPSED_STRING,
392
+ 'type' => 'T_CONSTANT_ENCAPSED_STRING',
393
+ 'content' => str_replace("\n", $this->eolChar, $buffer).$char,
394
+ ];
395
+
396
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
397
+ echo "\t\t* found end of string *".PHP_EOL;
398
+ $content = Util\Common::prepareForOutput($buffer.$char);
399
+ echo "\t=> Added token T_CONSTANT_ENCAPSED_STRING ($content)".PHP_EOL;
400
+ }
401
+
402
+ $buffer = '';
403
+ $preStringBuffer = '';
404
+ $inString = '';
405
+ $stringChar = null;
406
+ continue;
407
+ }//end if
408
+ } else if ($inString === '') {
409
+ $inString = $char;
410
+ $stringChar = $i;
411
+ $preStringBuffer = $buffer;
412
+
413
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
414
+ echo "\t\t* looking for string closer *".PHP_EOL;
415
+ }
416
+ }//end if
417
+ }//end if
418
+
419
+ if ($inString !== '' && $char === "\n") {
420
+ // Unless this newline character is escaped, the string did not
421
+ // end before the end of the line, which means it probably
422
+ // wasn't a string at all (maybe a regex).
423
+ if ($chars[($i - 1)] !== '\\') {
424
+ $i = $stringChar;
425
+ $buffer = $preStringBuffer;
426
+ $preStringBuffer = '';
427
+ $inString = '';
428
+ $stringChar = null;
429
+ $char = $chars[$i];
430
+
431
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
432
+ echo "\t\t* found newline before end of string, bailing *".PHP_EOL;
433
+ }
434
+ }
435
+ }
436
+
437
+ $buffer .= $char;
438
+
439
+ // We don't look for special tokens inside strings,
440
+ // so if we are in a string, we can continue here now
441
+ // that the current char is in the buffer.
442
+ if ($inString !== '') {
443
+ continue;
444
+ }
445
+
446
+ // Special case for T_DIVIDE which can actually be
447
+ // the start of a regular expression.
448
+ if ($buffer === $char && $char === '/' && $chars[($i + 1)] !== '*') {
449
+ $regex = $this->getRegexToken(
450
+ $i,
451
+ $string,
452
+ $chars,
453
+ $tokens,
454
+ $this->eolChar
455
+ );
456
+
457
+ if ($regex !== null) {
458
+ $tokens[] = [
459
+ 'code' => T_REGULAR_EXPRESSION,
460
+ 'type' => 'T_REGULAR_EXPRESSION',
461
+ 'content' => $regex['content'],
462
+ ];
463
+
464
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
465
+ $content = Util\Common::prepareForOutput($regex['content']);
466
+ echo "\t=> Added token T_REGULAR_EXPRESSION ($content)".PHP_EOL;
467
+ }
468
+
469
+ $i = $regex['end'];
470
+ $buffer = '';
471
+ $cleanBuffer = false;
472
+ continue;
473
+ }//end if
474
+ }//end if
475
+
476
+ // Check for known tokens, but ignore tokens found that are not at
477
+ // the end of a string, like FOR and this.FORmat.
478
+ if (isset($this->tokenValues[strtolower($buffer)]) === true
479
+ && (preg_match('|[a-zA-z0-9_]|', $char) === 0
480
+ || isset($chars[($i + 1)]) === false
481
+ || preg_match('|[a-zA-z0-9_]|', $chars[($i + 1)]) === 0)
482
+ ) {
483
+ $matchedToken = false;
484
+ $lookAheadLength = ($maxTokenLength - strlen($buffer));
485
+
486
+ if ($lookAheadLength > 0) {
487
+ // The buffer contains a token type, but we need
488
+ // to look ahead at the next chars to see if this is
489
+ // actually part of a larger token. For example,
490
+ // FOR and FOREACH.
491
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
492
+ echo "\t\t* buffer possibly contains token, looking ahead $lookAheadLength chars *".PHP_EOL;
493
+ }
494
+
495
+ $charBuffer = $buffer;
496
+ for ($x = 1; $x <= $lookAheadLength; $x++) {
497
+ if (isset($chars[($i + $x)]) === false) {
498
+ break;
499
+ }
500
+
501
+ $charBuffer .= $chars[($i + $x)];
502
+
503
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
504
+ $content = Util\Common::prepareForOutput($charBuffer);
505
+ echo "\t\t=> Looking ahead $x chars => $content".PHP_EOL;
506
+ }
507
+
508
+ if (isset($this->tokenValues[strtolower($charBuffer)]) === true) {
509
+ // We've found something larger that matches
510
+ // so we can ignore this char. Except for 1 very specific
511
+ // case where a comment like /**/ needs to tokenize as
512
+ // T_COMMENT and not T_DOC_COMMENT.
513
+ $oldType = $this->tokenValues[strtolower($buffer)];
514
+ $newType = $this->tokenValues[strtolower($charBuffer)];
515
+ if ($oldType === 'T_COMMENT'
516
+ && $newType === 'T_DOC_COMMENT'
517
+ && $chars[($i + $x + 1)] === '/'
518
+ ) {
519
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
520
+ echo "\t\t* look ahead ignored T_DOC_COMMENT, continuing *".PHP_EOL;
521
+ }
522
+ } else {
523
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
524
+ echo "\t\t* look ahead found more specific token ($newType), ignoring $i *".PHP_EOL;
525
+ }
526
+
527
+ $matchedToken = true;
528
+ break;
529
+ }
530
+ }//end if
531
+ }//end for
532
+ }//end if
533
+
534
+ if ($matchedToken === false) {
535
+ if (PHP_CODESNIFFER_VERBOSITY > 1 && $lookAheadLength > 0) {
536
+ echo "\t\t* look ahead found nothing *".PHP_EOL;
537
+ }
538
+
539
+ $value = $this->tokenValues[strtolower($buffer)];
540
+
541
+ if ($value === 'T_FUNCTION' && $buffer !== 'function') {
542
+ // The function keyword needs to be all lowercase or else
543
+ // it is just a function called "Function".
544
+ $value = 'T_STRING';
545
+ }
546
+
547
+ $tokens[] = [
548
+ 'code' => constant($value),
549
+ 'type' => $value,
550
+ 'content' => $buffer,
551
+ ];
552
+
553
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
554
+ $content = Util\Common::prepareForOutput($buffer);
555
+ echo "\t=> Added token $value ($content)".PHP_EOL;
556
+ }
557
+
558
+ $cleanBuffer = true;
559
+ }//end if
560
+ } else if (isset($this->tokenValues[strtolower($char)]) === true) {
561
+ // No matter what token we end up using, we don't
562
+ // need the content in the buffer any more because we have
563
+ // found a valid token.
564
+ $newContent = substr(str_replace("\n", $this->eolChar, $buffer), 0, -1);
565
+ if ($newContent !== '') {
566
+ $tokens[] = [
567
+ 'code' => T_STRING,
568
+ 'type' => 'T_STRING',
569
+ 'content' => $newContent,
570
+ ];
571
+
572
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
573
+ $content = Util\Common::prepareForOutput(substr($buffer, 0, -1));
574
+ echo "\t=> Added token T_STRING ($content)".PHP_EOL;
575
+ }
576
+ }
577
+
578
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
579
+ echo "\t\t* char is token, looking ahead ".($maxTokenLength - 1).' chars *'.PHP_EOL;
580
+ }
581
+
582
+ // The char is a token type, but we need to look ahead at the
583
+ // next chars to see if this is actually part of a larger token.
584
+ // For example, = and ===.
585
+ $charBuffer = $char;
586
+ $matchedToken = false;
587
+ for ($x = 1; $x <= $maxTokenLength; $x++) {
588
+ if (isset($chars[($i + $x)]) === false) {
589
+ break;
590
+ }
591
+
592
+ $charBuffer .= $chars[($i + $x)];
593
+
594
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
595
+ $content = Util\Common::prepareForOutput($charBuffer);
596
+ echo "\t\t=> Looking ahead $x chars => $content".PHP_EOL;
597
+ }
598
+
599
+ if (isset($this->tokenValues[strtolower($charBuffer)]) === true) {
600
+ // We've found something larger that matches
601
+ // so we can ignore this char.
602
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
603
+ $type = $this->tokenValues[strtolower($charBuffer)];
604
+ echo "\t\t* look ahead found more specific token ($type), ignoring $i *".PHP_EOL;
605
+ }
606
+
607
+ $matchedToken = true;
608
+ break;
609
+ }
610
+ }//end for
611
+
612
+ if ($matchedToken === false) {
613
+ $value = $this->tokenValues[strtolower($char)];
614
+ $tokens[] = [
615
+ 'code' => constant($value),
616
+ 'type' => $value,
617
+ 'content' => $char,
618
+ ];
619
+
620
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
621
+ echo "\t\t* look ahead found nothing *".PHP_EOL;
622
+ $content = Util\Common::prepareForOutput($char);
623
+ echo "\t=> Added token $value ($content)".PHP_EOL;
624
+ }
625
+
626
+ $cleanBuffer = true;
627
+ } else {
628
+ $buffer = $char;
629
+ }//end if
630
+ }//end if
631
+
632
+ // Keep track of content inside comments.
633
+ if ($inComment === ''
634
+ && array_key_exists($buffer, $this->commentTokens) === true
635
+ ) {
636
+ // This is not really a comment if the content
637
+ // looks like \// (i.e., it is escaped).
638
+ if (isset($chars[($i - 2)]) === true && $chars[($i - 2)] === '\\') {
639
+ $lastToken = array_pop($tokens);
640
+ $lastContent = $lastToken['content'];
641
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
642
+ $value = $this->tokenValues[strtolower($lastContent)];
643
+ $content = Util\Common::prepareForOutput($lastContent);
644
+ echo "\t=> Removed token $value ($content)".PHP_EOL;
645
+ }
646
+
647
+ $lastChars = str_split($lastContent);
648
+ $lastNumChars = count($lastChars);
649
+ for ($x = 0; $x < $lastNumChars; $x++) {
650
+ $lastChar = $lastChars[$x];
651
+ $value = $this->tokenValues[strtolower($lastChar)];
652
+ $tokens[] = [
653
+ 'code' => constant($value),
654
+ 'type' => $value,
655
+ 'content' => $lastChar,
656
+ ];
657
+
658
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
659
+ $content = Util\Common::prepareForOutput($lastChar);
660
+ echo "\t=> Added token $value ($content)".PHP_EOL;
661
+ }
662
+ }
663
+ } else {
664
+ // We have started a comment.
665
+ $inComment = $buffer;
666
+
667
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
668
+ echo "\t\t* looking for end of comment *".PHP_EOL;
669
+ }
670
+ }//end if
671
+ } else if ($inComment !== '') {
672
+ if ($this->commentTokens[$inComment] === null) {
673
+ // Comment ends at the next newline.
674
+ if (strpos($buffer, "\n") !== false) {
675
+ $inComment = '';
676
+ }
677
+ } else {
678
+ if ($this->commentTokens[$inComment] === $buffer) {
679
+ $inComment = '';
680
+ }
681
+ }
682
+
683
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
684
+ if ($inComment === '') {
685
+ echo "\t\t* found end of comment *".PHP_EOL;
686
+ }
687
+ }
688
+
689
+ if ($inComment === '' && $cleanBuffer === false) {
690
+ $tokens[] = [
691
+ 'code' => T_STRING,
692
+ 'type' => 'T_STRING',
693
+ 'content' => str_replace("\n", $this->eolChar, $buffer),
694
+ ];
695
+
696
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
697
+ $content = Util\Common::prepareForOutput($buffer);
698
+ echo "\t=> Added token T_STRING ($content)".PHP_EOL;
699
+ }
700
+
701
+ $buffer = '';
702
+ }
703
+ }//end if
704
+
705
+ if ($cleanBuffer === true) {
706
+ $buffer = '';
707
+ $cleanBuffer = false;
708
+ }
709
+ }//end for
710
+
711
+ if (empty($buffer) === false) {
712
+ if ($inString !== '') {
713
+ // The string did not end before the end of the file,
714
+ // which means there was probably a syntax error somewhere.
715
+ $tokens[] = [
716
+ 'code' => T_STRING,
717
+ 'type' => 'T_STRING',
718
+ 'content' => str_replace("\n", $this->eolChar, $buffer),
719
+ ];
720
+
721
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
722
+ $content = Util\Common::prepareForOutput($buffer);
723
+ echo "\t=> Added token T_STRING ($content)".PHP_EOL;
724
+ }
725
+ } else {
726
+ // Buffer contains whitespace from the end of the file.
727
+ $tokens[] = [
728
+ 'code' => T_WHITESPACE,
729
+ 'type' => 'T_WHITESPACE',
730
+ 'content' => str_replace("\n", $this->eolChar, $buffer),
731
+ ];
732
+
733
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
734
+ $content = Util\Common::prepareForOutput($buffer);
735
+ echo "\t=> Added token T_WHITESPACE ($content)".PHP_EOL;
736
+ }
737
+ }//end if
738
+ }//end if
739
+
740
+ $tokens[] = [
741
+ 'code' => T_CLOSE_TAG,
742
+ 'type' => 'T_CLOSE_TAG',
743
+ 'content' => '',
744
+ ];
745
+
746
+ /*
747
+ Now that we have done some basic tokenizing, we need to
748
+ modify the tokens to join some together and split some apart
749
+ so they match what the PHP tokenizer does.
750
+ */
751
+
752
+ $finalTokens = [];
753
+ $newStackPtr = 0;
754
+ $numTokens = count($tokens);
755
+ for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) {
756
+ $token = $tokens[$stackPtr];
757
+
758
+ /*
759
+ Look for comments and join the tokens together.
760
+ */
761
+
762
+ if ($token['code'] === T_COMMENT || $token['code'] === T_DOC_COMMENT) {
763
+ $newContent = '';
764
+ $tokenContent = $token['content'];
765
+
766
+ $endContent = null;
767
+ if (isset($this->commentTokens[$tokenContent]) === true) {
768
+ $endContent = $this->commentTokens[$tokenContent];
769
+ }
770
+
771
+ while ($tokenContent !== $endContent) {
772
+ if ($endContent === null
773
+ && strpos($tokenContent, $this->eolChar) !== false
774
+ ) {
775
+ // A null end token means the comment ends at the end of
776
+ // the line so we look for newlines and split the token.
777
+ $tokens[$stackPtr]['content'] = substr(
778
+ $tokenContent,
779
+ (strpos($tokenContent, $this->eolChar) + strlen($this->eolChar))
780
+ );
781
+
782
+ $tokenContent = substr(
783
+ $tokenContent,
784
+ 0,
785
+ (strpos($tokenContent, $this->eolChar) + strlen($this->eolChar))
786
+ );
787
+
788
+ // If the substr failed, skip the token as the content
789
+ // will now be blank.
790
+ if ($tokens[$stackPtr]['content'] !== false
791
+ && $tokens[$stackPtr]['content'] !== ''
792
+ ) {
793
+ $stackPtr--;
794
+ }
795
+
796
+ break;
797
+ }//end if
798
+
799
+ $stackPtr++;
800
+ $newContent .= $tokenContent;
801
+ if (isset($tokens[$stackPtr]) === false) {
802
+ break;
803
+ }
804
+
805
+ $tokenContent = $tokens[$stackPtr]['content'];
806
+ }//end while
807
+
808
+ if ($token['code'] === T_DOC_COMMENT) {
809
+ $commentTokens = $commentTokenizer->tokenizeString($newContent.$tokenContent, $this->eolChar, $newStackPtr);
810
+ foreach ($commentTokens as $commentToken) {
811
+ $finalTokens[$newStackPtr] = $commentToken;
812
+ $newStackPtr++;
813
+ }
814
+
815
+ continue;
816
+ } else {
817
+ // Save the new content in the current token so
818
+ // the code below can chop it up on newlines.
819
+ $token['content'] = $newContent.$tokenContent;
820
+ }
821
+ }//end if
822
+
823
+ /*
824
+ If this token has newlines in its content, split each line up
825
+ and create a new token for each line. We do this so it's easier
826
+ to ascertain where errors occur on a line.
827
+ Note that $token[1] is the token's content.
828
+ */
829
+
830
+ if (strpos($token['content'], $this->eolChar) !== false) {
831
+ $tokenLines = explode($this->eolChar, $token['content']);
832
+ $numLines = count($tokenLines);
833
+
834
+ for ($i = 0; $i < $numLines; $i++) {
835
+ $newToken['content'] = $tokenLines[$i];
836
+ if ($i === ($numLines - 1)) {
837
+ if ($tokenLines[$i] === '') {
838
+ break;
839
+ }
840
+ } else {
841
+ $newToken['content'] .= $this->eolChar;
842
+ }
843
+
844
+ $newToken['type'] = $token['type'];
845
+ $newToken['code'] = $token['code'];
846
+ $finalTokens[$newStackPtr] = $newToken;
847
+ $newStackPtr++;
848
+ }
849
+ } else {
850
+ $finalTokens[$newStackPtr] = $token;
851
+ $newStackPtr++;
852
+ }//end if
853
+
854
+ // Convert numbers, including decimals.
855
+ if ($token['code'] === T_STRING
856
+ || $token['code'] === T_OBJECT_OPERATOR
857
+ ) {
858
+ $newContent = '';
859
+ $oldStackPtr = $stackPtr;
860
+ while (preg_match('|^[0-9\.]+$|', $tokens[$stackPtr]['content']) !== 0) {
861
+ $newContent .= $tokens[$stackPtr]['content'];
862
+ $stackPtr++;
863
+ }
864
+
865
+ if ($newContent !== '' && $newContent !== '.') {
866
+ $finalTokens[($newStackPtr - 1)]['content'] = $newContent;
867
+ if (ctype_digit($newContent) === true) {
868
+ $finalTokens[($newStackPtr - 1)]['code'] = constant('T_LNUMBER');
869
+ $finalTokens[($newStackPtr - 1)]['type'] = 'T_LNUMBER';
870
+ } else {
871
+ $finalTokens[($newStackPtr - 1)]['code'] = constant('T_DNUMBER');
872
+ $finalTokens[($newStackPtr - 1)]['type'] = 'T_DNUMBER';
873
+ }
874
+
875
+ $stackPtr--;
876
+ continue;
877
+ } else {
878
+ $stackPtr = $oldStackPtr;
879
+ }
880
+ }//end if
881
+
882
+ // Convert the token after an object operator into a string, in most cases.
883
+ if ($token['code'] === T_OBJECT_OPERATOR) {
884
+ for ($i = ($stackPtr + 1); $i < $numTokens; $i++) {
885
+ if (isset(Util\Tokens::$emptyTokens[$tokens[$i]['code']]) === true) {
886
+ continue;
887
+ }
888
+
889
+ if ($tokens[$i]['code'] !== T_PROTOTYPE
890
+ && $tokens[$i]['code'] !== T_LNUMBER
891
+ && $tokens[$i]['code'] !== T_DNUMBER
892
+ ) {
893
+ $tokens[$i]['code'] = T_STRING;
894
+ $tokens[$i]['type'] = 'T_STRING';
895
+ }
896
+
897
+ break;
898
+ }
899
+ }
900
+ }//end for
901
+
902
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
903
+ echo "\t*** END TOKENIZING ***".PHP_EOL;
904
+ }
905
+
906
+ return $finalTokens;
907
+
908
+ }//end tokenize()
909
+
910
+
911
+ /**
912
+ * Tokenizes a regular expression if one is found.
913
+ *
914
+ * If a regular expression is not found, NULL is returned.
915
+ *
916
+ * @param string $char The index of the possible regex start character.
917
+ * @param string $string The complete content of the string being tokenized.
918
+ * @param string $chars An array of characters being tokenized.
919
+ * @param string $tokens The current array of tokens found in the string.
920
+ *
921
+ * @return void
922
+ */
923
+ public function getRegexToken($char, $string, $chars, $tokens)
924
+ {
925
+ $beforeTokens = [
926
+ T_EQUAL => true,
927
+ T_IS_NOT_EQUAL => true,
928
+ T_IS_IDENTICAL => true,
929
+ T_IS_NOT_IDENTICAL => true,
930
+ T_OPEN_PARENTHESIS => true,
931
+ T_OPEN_SQUARE_BRACKET => true,
932
+ T_RETURN => true,
933
+ T_BOOLEAN_OR => true,
934
+ T_BOOLEAN_AND => true,
935
+ T_BOOLEAN_NOT => true,
936
+ T_BITWISE_OR => true,
937
+ T_BITWISE_AND => true,
938
+ T_COMMA => true,
939
+ T_COLON => true,
940
+ T_TYPEOF => true,
941
+ T_INLINE_THEN => true,
942
+ T_INLINE_ELSE => true,
943
+ ];
944
+
945
+ $afterTokens = [
946
+ ',' => true,
947
+ ')' => true,
948
+ ']' => true,
949
+ ';' => true,
950
+ ' ' => true,
951
+ '.' => true,
952
+ ':' => true,
953
+ $this->eolChar => true,
954
+ ];
955
+
956
+ // Find the last non-whitespace token that was added
957
+ // to the tokens array.
958
+ $numTokens = count($tokens);
959
+ for ($prev = ($numTokens - 1); $prev >= 0; $prev--) {
960
+ if (isset(Util\Tokens::$emptyTokens[$tokens[$prev]['code']]) === false) {
961
+ break;
962
+ }
963
+ }
964
+
965
+ if (isset($beforeTokens[$tokens[$prev]['code']]) === false) {
966
+ return null;
967
+ }
968
+
969
+ // This is probably a regular expression, so look for the end of it.
970
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
971
+ echo "\t* token possibly starts a regular expression *".PHP_EOL;
972
+ }
973
+
974
+ $numChars = count($chars);
975
+ for ($next = ($char + 1); $next < $numChars; $next++) {
976
+ if ($chars[$next] === '/') {
977
+ // Just make sure this is not escaped first.
978
+ if ($chars[($next - 1)] !== '\\') {
979
+ // In the simple form: /.../ so we found the end.
980
+ break;
981
+ } else if ($chars[($next - 2)] === '\\') {
982
+ // In the form: /...\\/ so we found the end.
983
+ break;
984
+ }
985
+ } else {
986
+ $possibleEolChar = substr($string, $next, strlen($this->eolChar));
987
+ if ($possibleEolChar === $this->eolChar) {
988
+ // This is the last token on the line and regular
989
+ // expressions need to be defined on a single line,
990
+ // so this is not a regular expression.
991
+ break;
992
+ }
993
+ }
994
+ }
995
+
996
+ if ($chars[$next] !== '/') {
997
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
998
+ echo "\t* could not find end of regular expression *".PHP_EOL;
999
+ }
1000
+
1001
+ return null;
1002
+ }
1003
+
1004
+ while (preg_match('|[a-zA-Z]|', $chars[($next + 1)]) !== 0) {
1005
+ // The token directly after the end of the regex can
1006
+ // be modifiers like global and case insensitive
1007
+ // (.e.g, /pattern/gi).
1008
+ $next++;
1009
+ }
1010
+
1011
+ $regexEnd = $next;
1012
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1013
+ echo "\t* found end of regular expression at token $regexEnd *".PHP_EOL;
1014
+ }
1015
+
1016
+ for ($next += 1; $next < $numChars; $next++) {
1017
+ if ($chars[$next] !== ' ') {
1018
+ break;
1019
+ } else {
1020
+ $possibleEolChar = substr($string, $next, strlen($this->eolChar));
1021
+ if ($possibleEolChar === $this->eolChar) {
1022
+ // This is the last token on the line.
1023
+ break;
1024
+ }
1025
+ }
1026
+ }
1027
+
1028
+ if (isset($afterTokens[$chars[$next]]) === false) {
1029
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1030
+ echo "\t* tokens after regular expression do not look correct *".PHP_EOL;
1031
+ }
1032
+
1033
+ return null;
1034
+ }
1035
+
1036
+ // This is a regular expression, so join all the tokens together.
1037
+ $content = '';
1038
+ for ($x = $char; $x <= $regexEnd; $x++) {
1039
+ $content .= $chars[$x];
1040
+ }
1041
+
1042
+ $token = [
1043
+ 'start' => $char,
1044
+ 'end' => $regexEnd,
1045
+ 'content' => $content,
1046
+ ];
1047
+
1048
+ return $token;
1049
+
1050
+ }//end getRegexToken()
1051
+
1052
+
1053
+ /**
1054
+ * Performs additional processing after main tokenizing.
1055
+ *
1056
+ * This additional processing looks for properties, closures, labels and objects.
1057
+ *
1058
+ * @return void
1059
+ */
1060
+ public function processAdditional()
1061
+ {
1062
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1063
+ echo "\t*** START ADDITIONAL JS PROCESSING ***".PHP_EOL;
1064
+ }
1065
+
1066
+ $numTokens = count($this->tokens);
1067
+ $classStack = [];
1068
+
1069
+ for ($i = 0; $i < $numTokens; $i++) {
1070
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1071
+ $type = $this->tokens[$i]['type'];
1072
+ $content = Util\Common::prepareForOutput($this->tokens[$i]['content']);
1073
+
1074
+ echo str_repeat("\t", count($classStack));
1075
+ echo "\tProcess token $i: $type => $content".PHP_EOL;
1076
+ }
1077
+
1078
+ // Looking for functions that are actually closures.
1079
+ if ($this->tokens[$i]['code'] === T_FUNCTION && isset($this->tokens[$i]['scope_opener']) === true) {
1080
+ for ($x = ($i + 1); $x < $numTokens; $x++) {
1081
+ if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) {
1082
+ break;
1083
+ }
1084
+ }
1085
+
1086
+ if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) {
1087
+ $this->tokens[$i]['code'] = T_CLOSURE;
1088
+ $this->tokens[$i]['type'] = 'T_CLOSURE';
1089
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1090
+ $line = $this->tokens[$i]['line'];
1091
+ echo str_repeat("\t", count($classStack));
1092
+ echo "\t* token $i on line $line changed from T_FUNCTION to T_CLOSURE *".PHP_EOL;
1093
+ }
1094
+
1095
+ for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) {
1096
+ if (isset($this->tokens[$x]['conditions'][$i]) === false) {
1097
+ continue;
1098
+ }
1099
+
1100
+ $this->tokens[$x]['conditions'][$i] = T_CLOSURE;
1101
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1102
+ $type = $this->tokens[$x]['type'];
1103
+ echo str_repeat("\t", count($classStack));
1104
+ echo "\t\t* cleaned $x ($type) *".PHP_EOL;
1105
+ }
1106
+ }
1107
+ }//end if
1108
+
1109
+ continue;
1110
+ } else if ($this->tokens[$i]['code'] === T_OPEN_CURLY_BRACKET
1111
+ && isset($this->tokens[$i]['scope_condition']) === false
1112
+ && isset($this->tokens[$i]['bracket_closer']) === true
1113
+ ) {
1114
+ $condition = end($this->tokens[$i]['conditions']);
1115
+ reset($this->tokens[$i]['conditions']);
1116
+ if ($condition === T_CLASS) {
1117
+ // Possibly an ES6 method. To be classified as one, the previous
1118
+ // non-empty tokens need to be a set of parenthesis, and then a string
1119
+ // (the method name).
1120
+ for ($parenCloser = ($i - 1); $parenCloser > 0; $parenCloser--) {
1121
+ if (isset(Util\Tokens::$emptyTokens[$this->tokens[$parenCloser]['code']]) === false) {
1122
+ break;
1123
+ }
1124
+ }
1125
+
1126
+ if ($this->tokens[$parenCloser]['code'] === T_CLOSE_PARENTHESIS) {
1127
+ $parenOpener = $this->tokens[$parenCloser]['parenthesis_opener'];
1128
+ for ($name = ($parenOpener - 1); $name > 0; $name--) {
1129
+ if (isset(Util\Tokens::$emptyTokens[$this->tokens[$name]['code']]) === false) {
1130
+ break;
1131
+ }
1132
+ }
1133
+
1134
+ if ($this->tokens[$name]['code'] === T_STRING) {
1135
+ // We found a method name.
1136
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1137
+ $line = $this->tokens[$name]['line'];
1138
+ echo str_repeat("\t", count($classStack));
1139
+ echo "\t* token $name on line $line changed from T_STRING to T_FUNCTION *".PHP_EOL;
1140
+ }
1141
+
1142
+ $closer = $this->tokens[$i]['bracket_closer'];
1143
+
1144
+ $this->tokens[$name]['code'] = T_FUNCTION;
1145
+ $this->tokens[$name]['type'] = 'T_FUNCTION';
1146
+
1147
+ foreach ([$name, $i, $closer] as $token) {
1148
+ $this->tokens[$token]['scope_condition'] = $name;
1149
+ $this->tokens[$token]['scope_opener'] = $i;
1150
+ $this->tokens[$token]['scope_closer'] = $closer;
1151
+ $this->tokens[$token]['parenthesis_opener'] = $parenOpener;
1152
+ $this->tokens[$token]['parenthesis_closer'] = $parenCloser;
1153
+ $this->tokens[$token]['parenthesis_owner'] = $name;
1154
+ }
1155
+
1156
+ $this->tokens[$parenOpener]['parenthesis_owner'] = $name;
1157
+ $this->tokens[$parenCloser]['parenthesis_owner'] = $name;
1158
+
1159
+ for ($x = ($i + 1); $x < $closer; $x++) {
1160
+ $this->tokens[$x]['conditions'][$name] = T_FUNCTION;
1161
+ ksort($this->tokens[$x]['conditions'], SORT_NUMERIC);
1162
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1163
+ $type = $this->tokens[$x]['type'];
1164
+ echo str_repeat("\t", count($classStack));
1165
+ echo "\t\t* added T_FUNCTION condition to $x ($type) *".PHP_EOL;
1166
+ }
1167
+ }
1168
+
1169
+ continue;
1170
+ }//end if
1171
+ }//end if
1172
+ }//end if
1173
+
1174
+ $classStack[] = $i;
1175
+
1176
+ $closer = $this->tokens[$i]['bracket_closer'];
1177
+ $this->tokens[$i]['code'] = T_OBJECT;
1178
+ $this->tokens[$i]['type'] = 'T_OBJECT';
1179
+ $this->tokens[$closer]['code'] = T_CLOSE_OBJECT;
1180
+ $this->tokens[$closer]['type'] = 'T_CLOSE_OBJECT';
1181
+
1182
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1183
+ echo str_repeat("\t", count($classStack));
1184
+ echo "\t* token $i converted from T_OPEN_CURLY_BRACKET to T_OBJECT *".PHP_EOL;
1185
+ echo str_repeat("\t", count($classStack));
1186
+ echo "\t* token $closer converted from T_CLOSE_CURLY_BRACKET to T_CLOSE_OBJECT *".PHP_EOL;
1187
+ }
1188
+
1189
+ for ($x = ($i + 1); $x < $closer; $x++) {
1190
+ $this->tokens[$x]['conditions'][$i] = T_OBJECT;
1191
+ ksort($this->tokens[$x]['conditions'], SORT_NUMERIC);
1192
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1193
+ $type = $this->tokens[$x]['type'];
1194
+ echo str_repeat("\t", count($classStack));
1195
+ echo "\t\t* added T_OBJECT condition to $x ($type) *".PHP_EOL;
1196
+ }
1197
+ }
1198
+ } else if ($this->tokens[$i]['code'] === T_CLOSE_OBJECT) {
1199
+ $opener = array_pop($classStack);
1200
+ } else if ($this->tokens[$i]['code'] === T_COLON) {
1201
+ // If it is a scope opener, it belongs to a
1202
+ // DEFAULT or CASE statement.
1203
+ if (isset($this->tokens[$i]['scope_condition']) === true) {
1204
+ continue;
1205
+ }
1206
+
1207
+ // Make sure this is not part of an inline IF statement.
1208
+ for ($x = ($i - 1); $x >= 0; $x--) {
1209
+ if ($this->tokens[$x]['code'] === T_INLINE_THEN) {
1210
+ $this->tokens[$i]['code'] = T_INLINE_ELSE;
1211
+ $this->tokens[$i]['type'] = 'T_INLINE_ELSE';
1212
+
1213
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1214
+ echo str_repeat("\t", count($classStack));
1215
+ echo "\t* token $i converted from T_COLON to T_INLINE_THEN *".PHP_EOL;
1216
+ }
1217
+
1218
+ continue(2);
1219
+ } else if ($this->tokens[$x]['line'] < $this->tokens[$i]['line']) {
1220
+ break;
1221
+ }
1222
+ }
1223
+
1224
+ // The string to the left of the colon is either a property or label.
1225
+ for ($label = ($i - 1); $label >= 0; $label--) {
1226
+ if (isset(Util\Tokens::$emptyTokens[$this->tokens[$label]['code']]) === false) {
1227
+ break;
1228
+ }
1229
+ }
1230
+
1231
+ if ($this->tokens[$label]['code'] !== T_STRING
1232
+ && $this->tokens[$label]['code'] !== T_CONSTANT_ENCAPSED_STRING
1233
+ ) {
1234
+ continue;
1235
+ }
1236
+
1237
+ if (empty($classStack) === false) {
1238
+ $this->tokens[$label]['code'] = T_PROPERTY;
1239
+ $this->tokens[$label]['type'] = 'T_PROPERTY';
1240
+
1241
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1242
+ echo str_repeat("\t", count($classStack));
1243
+ echo "\t* token $label converted from T_STRING to T_PROPERTY *".PHP_EOL;
1244
+ }
1245
+ } else {
1246
+ $this->tokens[$label]['code'] = T_LABEL;
1247
+ $this->tokens[$label]['type'] = 'T_LABEL';
1248
+
1249
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1250
+ echo str_repeat("\t", count($classStack));
1251
+ echo "\t* token $label converted from T_STRING to T_LABEL *".PHP_EOL;
1252
+ }
1253
+ }//end if
1254
+ }//end if
1255
+ }//end for
1256
+
1257
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1258
+ echo "\t*** END ADDITIONAL JS PROCESSING ***".PHP_EOL;
1259
+ }
1260
+
1261
+ }//end processAdditional()
1262
+
1263
+
1264
+ }//end class
vendor/php_codesniffer-3.4.0/src/Tokenizers/PHP.php ADDED
@@ -0,0 +1,2014 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Tokenizes PHP code.
4
+ *
5
+ * @author Greg Sherwood <gsherwood@squiz.net>
6
+ * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
+ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
+ */
9
+
10
+ namespace PHP_CodeSniffer\Tokenizers;
11
+
12
+ use PHP_CodeSniffer\Util;
13
+
14
+ class PHP extends Tokenizer
15
+ {
16
+
17
+
18
+ /**
19
+ * A list of tokens that are allowed to open a scope.
20
+ *
21
+ * This array also contains information about what kind of token the scope
22
+ * opener uses to open and close the scope, if the token strictly requires
23
+ * an opener, if the token can share a scope closer, and who it can be shared
24
+ * with. An example of a token that shares a scope closer is a CASE scope.
25
+ *
26
+ * @var array
27
+ */
28
+ public $scopeOpeners = [
29
+ T_IF => [
30
+ 'start' => [
31
+ T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
32
+ T_COLON => T_COLON,
33
+ ],
34
+ 'end' => [
35
+ T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
36
+ T_ENDIF => T_ENDIF,
37
+ T_ELSE => T_ELSE,
38
+ T_ELSEIF => T_ELSEIF,
39
+ ],
40
+ 'strict' => false,
41
+ 'shared' => false,
42
+ 'with' => [
43
+ T_ELSE => T_ELSE,
44
+ T_ELSEIF => T_ELSEIF,
45
+ ],
46
+ ],
47
+ T_TRY => [
48
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
49
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
50
+ 'strict' => true,
51
+ 'shared' => false,
52
+ 'with' => [],
53
+ ],
54
+ T_CATCH => [
55
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
56
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
57
+ 'strict' => true,
58
+ 'shared' => false,
59
+ 'with' => [],
60
+ ],
61
+ T_FINALLY => [
62
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
63
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
64
+ 'strict' => true,
65
+ 'shared' => false,
66
+ 'with' => [],
67
+ ],
68
+ T_ELSE => [
69
+ 'start' => [
70
+ T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
71
+ T_COLON => T_COLON,
72
+ ],
73
+ 'end' => [
74
+ T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
75
+ T_ENDIF => T_ENDIF,
76
+ ],
77
+ 'strict' => false,
78
+ 'shared' => false,
79
+ 'with' => [
80
+ T_IF => T_IF,
81
+ T_ELSEIF => T_ELSEIF,
82
+ ],
83
+ ],
84
+ T_ELSEIF => [
85
+ 'start' => [
86
+ T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
87
+ T_COLON => T_COLON,
88
+ ],
89
+ 'end' => [
90
+ T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
91
+ T_ENDIF => T_ENDIF,
92
+ T_ELSE => T_ELSE,
93
+ T_ELSEIF => T_ELSEIF,
94
+ ],
95
+ 'strict' => false,
96
+ 'shared' => false,
97
+ 'with' => [
98
+ T_IF => T_IF,
99
+ T_ELSE => T_ELSE,
100
+ ],
101
+ ],
102
+ T_FOR => [
103
+ 'start' => [
104
+ T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
105
+ T_COLON => T_COLON,
106
+ ],
107
+ 'end' => [
108
+ T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
109
+ T_ENDFOR => T_ENDFOR,
110
+ ],
111
+ 'strict' => false,
112
+ 'shared' => false,
113
+ 'with' => [],
114
+ ],
115
+ T_FOREACH => [
116
+ 'start' => [
117
+ T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
118
+ T_COLON => T_COLON,
119
+ ],
120
+ 'end' => [
121
+ T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
122
+ T_ENDFOREACH => T_ENDFOREACH,
123
+ ],
124
+ 'strict' => false,
125
+ 'shared' => false,
126
+ 'with' => [],
127
+ ],
128
+ T_INTERFACE => [
129
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
130
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
131
+ 'strict' => true,
132
+ 'shared' => false,
133
+ 'with' => [],
134
+ ],
135
+ T_FUNCTION => [
136
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
137
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
138
+ 'strict' => true,
139
+ 'shared' => false,
140
+ 'with' => [],
141
+ ],
142
+ T_CLASS => [
143
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
144
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
145
+ 'strict' => true,
146
+ 'shared' => false,
147
+ 'with' => [],
148
+ ],
149
+ T_TRAIT => [
150
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
151
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
152
+ 'strict' => true,
153
+ 'shared' => false,
154
+ 'with' => [],
155
+ ],
156
+ T_USE => [
157
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
158
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
159
+ 'strict' => false,
160
+ 'shared' => false,
161
+ 'with' => [],
162
+ ],
163
+ T_DECLARE => [
164
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
165
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
166
+ 'strict' => false,
167
+ 'shared' => false,
168
+ 'with' => [],
169
+ ],
170
+ T_NAMESPACE => [
171
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
172
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
173
+ 'strict' => false,
174
+ 'shared' => false,
175
+ 'with' => [],
176
+ ],
177
+ T_WHILE => [
178
+ 'start' => [
179
+ T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
180
+ T_COLON => T_COLON,
181
+ ],
182
+ 'end' => [
183
+ T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
184
+ T_ENDWHILE => T_ENDWHILE,
185
+ ],
186
+ 'strict' => false,
187
+ 'shared' => false,
188
+ 'with' => [],
189
+ ],
190
+ T_DO => [
191
+ 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET],
192
+ 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET],
193
+ 'strict' => true,
194
+ 'shared' => false,
195
+ 'with' => [],
196
+ ],
197
+ T_SWITCH => [
198
+ 'start' => [
199
+ T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
200
+ T_COLON => T_COLON,
201
+ ],
202
+ 'end' => [
203
+ T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
204
+ T_ENDSWITCH => T_ENDSWITCH,
205
+ ],
206
+ 'strict' => true,
207
+ 'shared' => false,
208
+ 'with' => [],
209
+ ],
210
+ T_CASE => [
211
+ 'start' => [
212
+ T_COLON => T_COLON,
213
+ T_SEMICOLON => T_SEMICOLON,
214
+ ],
215
+ 'end' => [
216
+ T_BREAK => T_BREAK,
217
+ T_RETURN => T_RETURN,
218
+ T_CONTINUE => T_CONTINUE,
219
+ T_THROW => T_THROW,
220
+ T_EXIT => T_EXIT,
221
+ ],
222
+ 'strict' => true,
223
+ 'shared' => true,
224
+ 'with' => [
225
+ T_DEFAULT => T_DEFAULT,
226
+ T_CASE => T_CASE,
227
+ T_SWITCH => T_SWITCH,
228
+ ],
229
+ ],
230
+ T_DEFAULT => [
231
+ 'start' => [
232
+ T_COLON => T_COLON,
233
+ T_SEMICOLON => T_SEMICOLON,
234
+ ],
235
+ 'end' => [
236
+ T_BREAK => T_BREAK,
237
+ T_RETURN => T_RETURN,
238
+ T_CONTINUE => T_CONTINUE,
239
+ T_THROW => T_THROW,
240
+ T_EXIT => T_EXIT,
241
+ ],
242
+ 'strict' => true,
243
+ 'shared' => true,
244
+ 'with' => [
245
+ T_CASE => T_CASE,
246
+ T_SWITCH => T_SWITCH,
247
+ ],
248
+ ],
249
+ T_START_HEREDOC => [
250
+ 'start' => [T_START_HEREDOC => T_START_HEREDOC],
251
+ 'end' => [T_END_HEREDOC => T_END_HEREDOC],
252
+ 'strict' => true,
253
+ 'shared' => false,
254
+ 'with' => [],
255
+ ],
256
+ T_START_NOWDOC => [
257
+ 'start' => [T_START_NOWDOC => T_START_NOWDOC],
258
+ 'end' => [T_END_NOWDOC => T_END_NOWDOC],
259
+ 'strict' => true,
260
+ 'shared' => false,
261
+ 'with' => [],
262
+ ],
263
+ ];
264
+
265
+ /**
266
+ * A list of tokens that end the scope.
267
+ *
268
+ * This array is just a unique collection of the end tokens
269
+ * from the _scopeOpeners array. The data is duplicated here to
270
+ * save time during parsing of the file.
271
+ *
272
+ * @var array
273
+ */
274
+ public $endScopeTokens = [
275
+ T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
276
+ T_ENDIF => T_ENDIF,
277
+ T_ENDFOR => T_ENDFOR,
278
+ T_ENDFOREACH => T_ENDFOREACH,
279
+ T_ENDWHILE => T_ENDWHILE,
280
+ T_ENDSWITCH => T_ENDSWITCH,
281
+ T_BREAK => T_BREAK,
282
+ T_END_HEREDOC => T_END_HEREDOC,
283
+ ];
284
+
285
+ /**
286
+ * Known lengths of tokens.
287
+ *
288
+ * @var array<int, int>
289
+ */
290
+ public $knownLengths = [
291
+ T_ABSTRACT => 8,
292
+ T_AND_EQUAL => 2,
293
+ T_ARRAY => 5,
294
+ T_AS => 2,
295
+ T_BOOLEAN_AND => 2,
296
+ T_BOOLEAN_OR => 2,
297
+ T_BREAK => 5,
298
+ T_CALLABLE => 8,
299
+ T_CASE => 4,
300
+ T_CATCH => 5,
301
+ T_CLASS => 5,
302
+ T_CLASS_C => 9,
303
+ T_CLONE => 5,
304
+ T_CONCAT_EQUAL => 2,
305
+ T_CONST => 5,
306
+ T_CONTINUE => 8,
307
+ T_CURLY_OPEN => 2,
308
+ T_DEC => 2,
309
+ T_DECLARE => 7,
310
+ T_DEFAULT => 7,
311
+ T_DIR => 7,
312
+ T_DIV_EQUAL => 2,
313
+ T_DO => 2,
314
+ T_DOLLAR_OPEN_CURLY_BRACES => 2,
315
+ T_DOUBLE_ARROW => 2,
316
+ T_DOUBLE_COLON => 2,
317
+ T_ECHO => 4,
318
+ T_ELSE => 4,
319
+ T_ELSEIF => 6,
320
+ T_EMPTY => 5,
321
+ T_ENDDECLARE => 10,
322
+ T_ENDFOR => 6,
323
+ T_ENDFOREACH => 10,
324
+ T_ENDIF => 5,
325
+ T_ENDSWITCH => 9,
326
+ T_ENDWHILE => 8,
327
+ T_EVAL => 4,
328
+ T_EXTENDS => 7,
329
+ T_FILE => 8,
330
+ T_FINAL => 5,
331
+ T_FINALLY => 7,
332
+ T_FOR => 3,
333
+ T_FOREACH => 7,
334
+ T_FUNCTION => 8,
335
+ T_FUNC_C => 12,
336
+ T_GLOBAL => 6,
337
+ T_GOTO => 4,
338
+ T_HALT_COMPILER => 15,
339
+ T_IF => 2,
340
+ T_IMPLEMENTS => 10,
341
+ T_INC => 2,
342
+ T_INCLUDE => 7,
343
+ T_INCLUDE_ONCE => 12,
344
+ T_INSTANCEOF => 10,
345
+ T_INSTEADOF => 9,
346
+ T_INTERFACE => 9,
347
+ T_ISSET => 5,
348
+ T_IS_EQUAL => 2,
349
+ T_IS_GREATER_OR_EQUAL => 2,
350
+ T_IS_IDENTICAL => 3,
351
+ T_IS_NOT_EQUAL => 2,
352
+ T_IS_NOT_IDENTICAL => 3,
353
+ T_IS_SMALLER_OR_EQUAL => 2,
354
+ T_LINE => 8,
355
+ T_LIST => 4,
356
+ T_LOGICAL_AND => 3,
357
+ T_LOGICAL_OR => 2,
358
+ T_LOGICAL_XOR => 3,
359
+ T_METHOD_C => 10,
360
+ T_MINUS_EQUAL => 2,
361
+ T_POW_EQUAL => 3,
362
+ T_MOD_EQUAL => 2,
363
+ T_MUL_EQUAL => 2,
364
+ T_NAMESPACE => 9,
365
+ T_NS_C => 13,
366
+ T_NS_SEPARATOR => 1,
367
+ T_NEW => 3,
368
+ T_OBJECT_OPERATOR => 2,
369
+ T_OPEN_TAG_WITH_ECHO => 3,
370
+ T_OR_EQUAL => 2,
371
+ T_PLUS_EQUAL => 2,
372
+ T_PRINT => 5,
373
+ T_PRIVATE => 7,
374
+ T_PUBLIC => 6,
375
+ T_PROTECTED => 9,
376
+ T_REQUIRE => 7,
377
+ T_REQUIRE_ONCE => 12,
378
+ T_RETURN => 6,
379
+ T_STATIC => 6,
380
+ T_SWITCH => 6,
381
+ T_THROW => 5,
382
+ T_TRAIT => 5,
383
+ T_TRAIT_C => 9,
384
+ T_TRY => 3,
385
+ T_UNSET => 5,
386
+ T_USE => 3,
387
+ T_VAR => 3,
388
+ T_WHILE => 5,
389
+ T_XOR_EQUAL => 2,
390
+ T_YIELD => 5,
391
+ T_OPEN_CURLY_BRACKET => 1,
392
+ T_CLOSE_CURLY_BRACKET => 1,
393
+ T_OPEN_SQUARE_BRACKET => 1,
394
+ T_CLOSE_SQUARE_BRACKET => 1,
395
+ T_OPEN_PARENTHESIS => 1,
396
+ T_CLOSE_PARENTHESIS => 1,
397
+ T_COLON => 1,
398
+ T_STRING_CONCAT => 1,
399
+ T_INLINE_THEN => 1,
400
+ T_INLINE_ELSE => 1,
401
+ T_NULLABLE => 1,
402
+ T_NULL => 4,
403
+ T_FALSE => 5,
404
+ T_TRUE => 4,
405
+ T_SEMICOLON => 1,
406
+ T_EQUAL => 1,
407
+ T_MULTIPLY => 1,
408
+ T_DIVIDE => 1,
409
+ T_PLUS => 1,
410
+ T_MINUS => 1,
411
+ T_MODULUS => 1,
412
+ T_POW => 2,
413
+ T_SPACESHIP => 3,
414
+ T_COALESCE => 2,
415
+ T_COALESCE_EQUAL => 3,
416
+ T_BITWISE_AND => 1,
417
+ T_BITWISE_OR => 1,
418
+ T_BITWISE_XOR => 1,
419
+ T_SL => 2,
420
+ T_SR => 2,
421
+ T_SL_EQUAL => 3,
422
+ T_SR_EQUAL => 3,
423
+ T_GREATER_THAN => 1,
424
+ T_LESS_THAN => 1,
425
+ T_BOOLEAN_NOT => 1,
426
+ T_SELF => 4,
427
+ T_PARENT => 6,
428
+ T_COMMA => 1,
429
+ T_THIS => 4,
430
+ T_CLOSURE => 8,
431
+ T_BACKTICK => 1,
432
+ T_OPEN_SHORT_ARRAY => 1,
433
+ T_CLOSE_SHORT_ARRAY => 1,
434
+ ];
435
+
436
+
437
+ /**
438
+ * A cache of different token types, resolved into arrays.
439
+ *
440
+ * @var array
441
+ * @see standardiseToken()
442
+ */
443
+ private static $resolveTokenCache = [];
444
+
445
+
446
+ /**
447
+ * Creates an array of tokens when given some PHP code.
448
+ *
449
+ * Starts by using token_get_all() but does a lot of extra processing
450
+ * to insert information about the context of the token.
451
+ *
452
+ * @param string $string The string to tokenize.
453
+ *
454
+ * @return array
455
+ */
456
+ protected function tokenize($string)
457
+ {
458
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
459
+ echo "\t*** START PHP TOKENIZING ***".PHP_EOL;
460
+ $isWin = false;
461
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
462
+ $isWin = true;
463
+ }
464
+ }
465
+
466
+ $tokens = @token_get_all($string);
467
+ $finalTokens = [];
468
+
469
+ $newStackPtr = 0;
470
+ $numTokens = count($tokens);
471
+ $lastNotEmptyToken = 0;
472
+
473
+ $insideInlineIf = [];
474
+ $insideUseGroup = false;
475
+
476
+ $commentTokenizer = new Comment();
477
+
478
+ for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) {
479
+ // Special case for tokens we have needed to blank out.
480
+ if ($tokens[$stackPtr] === null) {
481
+ continue;
482
+ }
483
+
484
+ $token = (array) $tokens[$stackPtr];
485
+ $tokenIsArray = isset($token[1]);
486
+
487
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
488
+ if ($tokenIsArray === true) {
489
+ $type = Util\Tokens::tokenName($token[0]);
490
+ $content = Util\Common::prepareForOutput($token[1]);
491
+ } else {
492
+ $newToken = self::resolveSimpleToken($token[0]);
493
+ $type = $newToken['type'];
494
+ $content = Util\Common::prepareForOutput($token[0]);
495
+ }
496
+
497
+ echo "\tProcess token ";
498
+ if ($tokenIsArray === true) {
499
+ echo "[$stackPtr]";
500
+ } else {
501
+ echo " $stackPtr ";
502
+ }
503
+
504
+ echo ": $type => $content";
505
+ }//end if
506
+
507
+ if ($newStackPtr > 0 && $finalTokens[($newStackPtr - 1)]['code'] !== T_WHITESPACE) {
508
+ $lastNotEmptyToken = ($newStackPtr - 1);
509
+ }
510
+
511
+ /*
512
+ If we are using \r\n newline characters, the \r and \n are sometimes
513
+ split over two tokens. This normally occurs after comments. We need
514
+ to merge these two characters together so that our line endings are
515
+ consistent for all lines.
516
+ */
517
+
518
+ if ($tokenIsArray === true && substr($token[1], -1) === "\r") {
519
+ if (isset($tokens[($stackPtr + 1)]) === true
520
+ && is_array($tokens[($stackPtr + 1)]) === true
521
+ && $tokens[($stackPtr + 1)][1][0] === "\n"
522
+ ) {
523
+ $token[1] .= "\n";
524
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
525
+ if ($isWin === true) {
526
+ echo '\n';
527
+ } else {
528
+ echo "\033[30;1m\\n\033[0m";
529
+ }
530
+ }
531
+
532
+ if ($tokens[($stackPtr + 1)][1] === "\n") {
533
+ // This token's content has been merged into the previous,
534
+ // so we can skip it.
535
+ $tokens[($stackPtr + 1)] = '';
536
+ } else {
537
+ $tokens[($stackPtr + 1)][1] = substr($tokens[($stackPtr + 1)][1], 1);
538
+ }
539
+ }
540
+ }//end if
541
+
542
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
543
+ echo PHP_EOL;
544
+ }
545
+
546
+ /*
547
+ Parse doc blocks into something that can be easily iterated over.
548
+ */
549
+
550
+ if ($tokenIsArray === true
551
+ && ($token[0] === T_DOC_COMMENT
552
+ || ($token[0] === T_COMMENT && strpos($token[1], '/**') === 0))
553
+ ) {
554
+ $commentTokens = $commentTokenizer->tokenizeString($token[1], $this->eolChar, $newStackPtr);
555
+ foreach ($commentTokens as $commentToken) {
556
+ $finalTokens[$newStackPtr] = $commentToken;
557
+ $newStackPtr++;
558
+ }
559
+
560
+ continue;
561
+ }
562
+
563
+ /*
564
+ If this is a double quoted string, PHP will tokenize the whole
565
+ thing which causes problems with the scope map when braces are
566
+ within the string. So we need to merge the tokens together to
567
+ provide a single string.
568
+ */
569
+
570
+ if ($tokenIsArray === false && ($token[0] === '"' || $token[0] === 'b"')) {
571
+ // Binary casts need a special token.
572
+ if ($token[0] === 'b"') {
573
+ $finalTokens[$newStackPtr] = [
574
+ 'code' => T_BINARY_CAST,
575
+ 'type' => 'T_BINARY_CAST',
576
+ 'content' => 'b',
577
+ ];
578
+ $newStackPtr++;
579
+ }
580
+
581
+ $tokenContent = '"';
582
+ $nestedVars = [];
583
+ for ($i = ($stackPtr + 1); $i < $numTokens; $i++) {
584
+ $subToken = (array) $tokens[$i];
585
+ $subTokenIsArray = isset($subToken[1]);
586
+
587
+ if ($subTokenIsArray === true) {
588
+ $tokenContent .= $subToken[1];
589
+ if ($subToken[1] === '{'
590
+ && $subToken[0] !== T_ENCAPSED_AND_WHITESPACE
591
+ ) {
592
+ $nestedVars[] = $i;
593
+ }
594
+ } else {
595
+ $tokenContent .= $subToken[0];
596
+ if ($subToken[0] === '}') {
597
+ array_pop($nestedVars);
598
+ }
599
+ }
600
+
601
+ if ($subTokenIsArray === false
602
+ && $subToken[0] === '"'
603
+ && empty($nestedVars) === true
604
+ ) {
605
+ // We found the other end of the double quoted string.
606
+ break;
607
+ }
608
+ }//end for
609
+
610
+ $stackPtr = $i;
611
+
612
+ // Convert each line within the double quoted string to a
613
+ // new token, so it conforms with other multiple line tokens.
614
+ $tokenLines = explode($this->eolChar, $tokenContent);
615
+ $numLines = count($tokenLines);
616
+ $newToken = [];
617
+
618
+ for ($j = 0; $j < $numLines; $j++) {
619
+ $newToken['content'] = $tokenLines[$j];
620
+ if ($j === ($numLines - 1)) {
621
+ if ($tokenLines[$j] === '') {
622
+ break;
623
+ }
624
+ } else {
625
+ $newToken['content'] .= $this->eolChar;
626
+ }
627
+
628
+ $newToken['code'] = T_DOUBLE_QUOTED_STRING;
629
+ $newToken['type'] = 'T_DOUBLE_QUOTED_STRING';
630
+ $finalTokens[$newStackPtr] = $newToken;
631
+ $newStackPtr++;
632
+ }
633
+
634
+ // Continue, as we're done with this token.
635
+ continue;
636
+ }//end if
637
+
638
+ /*
639
+ Detect binary casting and assign the casts their own token.
640
+ */
641
+
642
+ if ($tokenIsArray === true
643
+ && $token[0] === T_CONSTANT_ENCAPSED_STRING
644
+ && (substr($token[1], 0, 2) === 'b"'
645
+ || substr($token[1], 0, 2) === "b'")
646
+ ) {
647
+ $finalTokens[$newStackPtr] = [
648
+ 'code' => T_BINARY_CAST,
649
+ 'type' => 'T_BINARY_CAST',
650
+ 'content' => 'b',
651
+ ];
652
+ $newStackPtr++;
653
+ $token[1] = substr($token[1], 1);
654
+ }
655
+
656
+ if ($tokenIsArray === true
657
+ && $token[0] === T_STRING_CAST
658
+ && preg_match('`^\(\s*binary\s*\)$`i', $token[1]) === 1
659
+ ) {
660
+ $finalTokens[$newStackPtr] = [
661
+ 'code' => T_BINARY_CAST,
662
+ 'type' => 'T_BINARY_CAST',
663
+ 'content' => $token[1],
664
+ ];
665
+ $newStackPtr++;
666
+ continue;
667
+ }
668
+
669
+ /*
670
+ If this is a heredoc, PHP will tokenize the whole
671
+ thing which causes problems when heredocs don't
672
+ contain real PHP code, which is almost never.
673
+ We want to leave the start and end heredoc tokens
674
+ alone though.
675
+ */
676
+
677
+ if ($tokenIsArray === true && $token[0] === T_START_HEREDOC) {
678
+ // Add the start heredoc token to the final array.
679
+ $finalTokens[$newStackPtr] = self::standardiseToken($token);
680
+
681
+ // Check if this is actually a nowdoc and use a different token
682
+ // to help the sniffs.
683
+ $nowdoc = false;
684
+ if (strpos($token[1], "'") !== false) {
685
+ $finalTokens[$newStackPtr]['code'] = T_START_NOWDOC;
686
+ $finalTokens[$newStackPtr]['type'] = 'T_START_NOWDOC';
687
+ $nowdoc = true;
688
+ }
689
+
690
+ $tokenContent = '';
691
+ for ($i = ($stackPtr + 1); $i < $numTokens; $i++) {
692
+ $subTokenIsArray = is_array($tokens[$i]);
693
+ if ($subTokenIsArray === true
694
+ && $tokens[$i][0] === T_END_HEREDOC
695
+ ) {
696
+ // We found the other end of the heredoc.
697
+ break;
698
+ }
699
+
700
+ if ($subTokenIsArray === true) {
701
+ $tokenContent .= $tokens[$i][1];
702
+ } else {
703
+ $tokenContent .= $tokens[$i];
704
+ }
705
+ }
706
+
707
+ if ($i === $numTokens) {
708
+ // We got to the end of the file and never
709
+ // found the closing token, so this probably wasn't
710
+ // a heredoc.
711
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
712
+ $type = $finalTokens[$newStackPtr]['type'];
713
+ echo "\t\t* failed to find the end of the here/nowdoc".PHP_EOL;
714
+ echo "\t\t* token $stackPtr changed from $type to T_STRING".PHP_EOL;
715
+ }
716
+
717
+ $finalTokens[$newStackPtr]['code'] = T_STRING;
718
+ $finalTokens[$newStackPtr]['type'] = 'T_STRING';
719
+ $newStackPtr++;
720
+ continue;
721
+ }
722
+
723
+ $stackPtr = $i;
724
+ $newStackPtr++;
725
+
726
+ // Convert each line within the heredoc to a
727
+ // new token, so it conforms with other multiple line tokens.
728
+ $tokenLines = explode($this->eolChar, $tokenContent);
729
+ $numLines = count($tokenLines);
730
+ $newToken = [];
731
+
732
+ for ($j = 0; $j < $numLines; $j++) {
733
+ $newToken['content'] = $tokenLines[$j];
734
+ if ($j === ($numLines - 1)) {
735
+ if ($tokenLines[$j] === '') {
736
+ break;
737
+ }
738
+ } else {
739
+ $newToken['content'] .= $this->eolChar;
740
+ }
741
+
742
+ if ($nowdoc === true) {
743
+ $newToken['code'] = T_NOWDOC;
744
+ $newToken['type'] = 'T_NOWDOC';
745
+ } else {
746
+ $newToken['code'] = T_HEREDOC;
747
+ $newToken['type'] = 'T_HEREDOC';
748
+ }
749
+
750
+ $finalTokens[$newStackPtr] = $newToken;
751
+ $newStackPtr++;
752
+ }//end for
753
+
754
+ // Add the end heredoc token to the final array.
755
+ $finalTokens[$newStackPtr] = self::standardiseToken($tokens[$stackPtr]);
756
+
757
+ if ($nowdoc === true) {
758
+ $finalTokens[$newStackPtr]['code'] = T_END_NOWDOC;
759
+ $finalTokens[$newStackPtr]['type'] = 'T_END_NOWDOC';
760
+ }
761
+
762
+ $newStackPtr++;
763
+
764
+ // Continue, as we're done with this token.
765
+ continue;
766
+ }//end if
767
+
768
+ /*
769
+ Before PHP 7.0, the "yield from" was tokenized as
770
+ T_YIELD, T_WHITESPACE and T_STRING. So look for
771
+ and change this token in earlier versions.
772
+ */
773
+
774
+ if (PHP_VERSION_ID < 70000
775
+ && PHP_VERSION_ID >= 50500
776
+ && $tokenIsArray === true
777
+ && $token[0] === T_YIELD
778
+ && isset($tokens[($stackPtr + 1)]) === true
779
+ && isset($tokens[($stackPtr + 2)]) === true
780
+ && $tokens[($stackPtr + 1)][0] === T_WHITESPACE
781
+ && $tokens[($stackPtr + 2)][0] === T_STRING
782
+ && strtolower($tokens[($stackPtr + 2)][1]) === 'from'
783
+ ) {
784
+ // Could be multi-line, so just the token stack.
785
+ $token[0] = T_YIELD_FROM;
786
+ $token[1] = $token[1].$tokens[($stackPtr + 1)][1].$tokens[($stackPtr + 2)][1];
787
+
788
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
789
+ for ($i = ($stackPtr + 1); $i <= ($stackPtr + 2); $i++) {
790
+ $type = Util\Tokens::tokenName($tokens[$i][0]);
791
+ $content = Util\Common::prepareForOutput($tokens[$i][1]);
792
+ echo "\t\t* token $i merged into T_YIELD_FROM; was: $type => $content".PHP_EOL;
793
+ }
794
+ }
795
+
796
+ $tokens[($stackPtr + 1)] = null;
797
+ $tokens[($stackPtr + 2)] = null;
798
+ }
799
+
800
+ /*
801
+ Before PHP 5.5, the yield keyword was tokenized as
802
+ T_STRING. So look for and change this token in
803
+ earlier versions.
804
+ Checks also if it is just "yield" or "yield from".
805
+ */
806
+
807
+ if (PHP_VERSION_ID < 50500
808
+ && $tokenIsArray === true
809
+ && $token[0] === T_STRING
810
+ && strtolower($token[1]) === 'yield'
811
+ ) {
812
+ if (isset($tokens[($stackPtr + 1)]) === true
813
+ && isset($tokens[($stackPtr + 2)]) === true
814
+ && $tokens[($stackPtr + 1)][0] === T_WHITESPACE
815
+ && $tokens[($stackPtr + 2)][0] === T_STRING
816
+ && strtolower($tokens[($stackPtr + 2)][1]) === 'from'
817
+ ) {
818
+ // Could be multi-line, so just just the token stack.
819
+ $token[0] = T_YIELD_FROM;
820
+ $token[1] = $token[1].$tokens[($stackPtr + 1)][1].$tokens[($stackPtr + 2)][1];
821
+
822
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
823
+ for ($i = ($stackPtr + 1); $i <= ($stackPtr + 2); $i++) {
824
+ $type = Util\Tokens::tokenName($tokens[$i][0]);
825
+ $content = Util\Common::prepareForOutput($tokens[$i][1]);
826
+ echo "\t\t* token $i merged into T_YIELD_FROM; was: $type => $content".PHP_EOL;
827
+ }
828
+ }
829
+
830
+ $tokens[($stackPtr + 1)] = null;
831
+ $tokens[($stackPtr + 2)] = null;
832
+ } else {
833
+ $newToken = [];
834
+ $newToken['code'] = T_YIELD;
835
+ $newToken['type'] = 'T_YIELD';
836
+ $newToken['content'] = $token[1];
837
+ $finalTokens[$newStackPtr] = $newToken;
838
+
839
+ $newStackPtr++;
840
+ continue;
841
+ }//end if
842
+ }//end if
843
+
844
+ /*
845
+ Before PHP 5.6, the ... operator was tokenized as three
846
+ T_STRING_CONCAT tokens in a row. So look for and combine
847
+ these tokens in earlier versions.
848
+ */
849
+
850
+ if ($tokenIsArray === false
851
+ && $token[0] === '.'
852
+ && isset($tokens[($stackPtr + 1)]) === true
853
+ && isset($tokens[($stackPtr + 2)]) === true
854
+ && $tokens[($stackPtr + 1)] === '.'
855
+ && $tokens[($stackPtr + 2)] === '.'
856
+ ) {
857
+ $newToken = [];
858
+ $newToken['code'] = T_ELLIPSIS;
859
+ $newToken['type'] = 'T_ELLIPSIS';
860
+ $newToken['content'] = '...';
861
+ $finalTokens[$newStackPtr] = $newToken;
862
+
863
+ $newStackPtr++;
864
+ $stackPtr += 2;
865
+ continue;
866
+ }
867
+
868
+ /*
869
+ Before PHP 5.6, the ** operator was tokenized as two
870
+ T_MULTIPLY tokens in a row. So look for and combine
871
+ these tokens in earlier versions.
872
+ */
873
+
874
+ if ($tokenIsArray === false
875
+ && $token[0] === '*'
876
+ && isset($tokens[($stackPtr + 1)]) === true
877
+ && $tokens[($stackPtr + 1)] === '*'
878
+ ) {
879
+ $newToken = [];
880
+ $newToken['code'] = T_POW;
881
+ $newToken['type'] = 'T_POW';
882
+ $newToken['content'] = '**';
883
+ $finalTokens[$newStackPtr] = $newToken;
884
+
885
+ $newStackPtr++;
886
+ $stackPtr++;
887
+ continue;
888
+ }
889
+
890
+ /*
891
+ Before PHP 5.6, the **= operator was tokenized as
892
+ T_MULTIPLY followed by T_MUL_EQUAL. So look for and combine
893
+ these tokens in earlier versions.
894
+ */
895
+
896
+ if ($tokenIsArray === false
897
+ && $token[0] === '*'
898
+ && isset($tokens[($stackPtr + 1)]) === true
899
+ && is_array($tokens[($stackPtr + 1)]) === true
900
+ && $tokens[($stackPtr + 1)][1] === '*='
901
+ ) {
902
+ $newToken = [];
903
+ $newToken['code'] = T_POW_EQUAL;
904
+ $newToken['type'] = 'T_POW_EQUAL';
905
+ $newToken['content'] = '**=';
906
+ $finalTokens[$newStackPtr] = $newToken;
907
+
908
+ $newStackPtr++;
909
+ $stackPtr++;
910
+ continue;
911
+ }
912
+
913
+ /*
914
+ Before PHP 7, the ??= operator was tokenized as
915
+ T_INLINE_THEN, T_INLINE_THEN, T_EQUAL.
916
+ Between PHP 7.0 and 7.2, the ??= operator was tokenized as
917
+ T_COALESCE, T_EQUAL.
918
+ So look for and combine these tokens in earlier versions.
919
+ */
920
+
921
+ if (($tokenIsArray === false
922
+ && $token[0] === '?'
923
+ && isset($tokens[($stackPtr + 1)]) === true
924
+ && $tokens[($stackPtr + 1)][0] === '?'
925
+ && isset($tokens[($stackPtr + 2)]) === true
926
+ && $tokens[($stackPtr + 2)][0] === '=')
927
+ || ($tokenIsArray === true
928
+ && $token[0] === T_COALESCE
929
+ && isset($tokens[($stackPtr + 1)]) === true
930
+ && $tokens[($stackPtr + 1)][0] === '=')
931
+ ) {
932
+ $newToken = [];
933
+ $newToken['code'] = T_COALESCE_EQUAL;
934
+ $newToken['type'] = 'T_COALESCE_EQUAL';
935
+ $newToken['content'] = '??=';
936
+ $finalTokens[$newStackPtr] = $newToken;
937
+
938
+ $newStackPtr++;
939
+ $stackPtr++;
940
+
941
+ if ($tokenIsArray === false) {
942
+ // Pre PHP 7.
943
+ $stackPtr++;
944
+ }
945
+
946
+ continue;
947
+ }
948
+
949
+ /*
950
+ Before PHP 7, the ?? operator was tokenized as
951
+ T_INLINE_THEN followed by T_INLINE_THEN.
952
+ So look for and combine these tokens in earlier versions.
953
+ */
954
+
955
+ if ($tokenIsArray === false
956
+ && $token[0] === '?'
957
+ && isset($tokens[($stackPtr + 1)]) === true
958
+ && $tokens[($stackPtr + 1)][0] === '?'
959
+ ) {
960
+ $newToken = [];
961
+ $newToken['code'] = T_COALESCE;
962
+ $newToken['type'] = 'T_COALESCE';
963
+ $newToken['content'] = '??';
964
+ $finalTokens[$newStackPtr] = $newToken;
965
+
966
+ $newStackPtr++;
967
+ $stackPtr++;
968
+ continue;
969
+ }
970
+
971
+ /*
972
+ Convert ? to T_NULLABLE OR T_INLINE_THEN
973
+ */
974
+
975
+ if ($tokenIsArray === false && $token[0] === '?') {
976
+ $newToken = [];
977
+ $newToken['content'] = '?';
978
+
979
+ $prevNonEmpty = null;
980
+ for ($i = ($stackPtr - 1); $i >= 0; $i--) {
981
+ if (is_array($tokens[$i]) === true) {
982
+ $tokenType = $tokens[$i][0];
983
+ } else {
984
+ $tokenType = $tokens[$i];
985
+ }
986
+
987
+ if ($prevNonEmpty === null
988
+ && isset(Util\Tokens::$emptyTokens[$tokenType]) === false
989
+ ) {
990
+ // Found the previous non-empty token.
991
+ if ($tokenType === ':' || $tokenType === ',') {
992
+ $newToken['code'] = T_NULLABLE;
993
+ $newToken['type'] = 'T_NULLABLE';
994
+ break;
995
+ }
996
+
997
+ $prevNonEmpty = $tokenType;
998
+ }
999
+
1000
+ if ($tokenType === T_FUNCTION) {
1001
+ $newToken['code'] = T_NULLABLE;
1002
+ $newToken['type'] = 'T_NULLABLE';
1003
+ break;
1004
+ } else if (in_array($tokenType, [T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, '=', '{', ';']) === true) {
1005
+ $newToken['code'] = T_INLINE_THEN;
1006
+ $newToken['type'] = 'T_INLINE_THEN';
1007
+
1008
+ $insideInlineIf[] = $stackPtr;
1009
+ break;
1010
+ }
1011
+ }//end for
1012
+
1013
+ $finalTokens[$newStackPtr] = $newToken;
1014
+ $newStackPtr++;
1015
+ continue;
1016
+ }//end if
1017
+
1018
+ /*
1019
+ Tokens after a double colon may be look like scope openers,
1020
+ such as when writing code like Foo::NAMESPACE, but they are
1021
+ only ever variables or strings.
1022
+ */
1023
+
1024
+ if ($stackPtr > 1
1025
+ && (is_array($tokens[($stackPtr - 1)]) === true
1026
+ && $tokens[($stackPtr - 1)][0] === T_PAAMAYIM_NEKUDOTAYIM)
1027
+ && $tokenIsArray === true
1028
+ && $token[0] !== T_STRING
1029
+ && $token[0] !== T_VARIABLE
1030
+ && $token[0] !== T_DOLLAR
1031
+ && isset(Util\Tokens::$emptyTokens[$token[0]]) === false
1032
+ ) {
1033
+ $newToken = [];
1034
+ $newToken['code'] = T_STRING;
1035
+ $newToken['type'] = 'T_STRING';
1036
+ $newToken['content'] = $token[1];
1037
+ $finalTokens[$newStackPtr] = $newToken;
1038
+
1039
+ $newStackPtr++;
1040
+ continue;
1041
+ }
1042
+
1043
+ /*
1044
+ The string-like token after a function keyword should always be
1045
+ tokenized as T_STRING even if it appears to be a different token,
1046
+ such as when writing code like: function default(): foo
1047
+ so go forward and change the token type before it is processed.
1048
+ */
1049
+
1050
+ if ($tokenIsArray === true
1051
+ && $token[0] === T_FUNCTION
1052
+ && $finalTokens[$lastNotEmptyToken]['code'] !== T_USE
1053
+ ) {
1054
+ for ($x = ($stackPtr + 1); $x < $numTokens; $x++) {
1055
+ if (is_array($tokens[$x]) === false
1056
+ || isset(Util\Tokens::$emptyTokens[$tokens[$x][0]]) === false
1057
+ ) {
1058
+ // Non-empty content.
1059
+ break;
1060
+ }
1061
+ }
1062
+
1063
+ if ($x < $numTokens && is_array($tokens[$x]) === true) {
1064
+ $tokens[$x][0] = T_STRING;
1065
+ }
1066
+
1067
+ /*
1068
+ This is a special condition for T_ARRAY tokens used for
1069
+ function return types. We want to keep the parenthesis map clean,
1070
+ so let's tag these tokens as T_STRING.
1071
+ */
1072
+
1073
+ // Go looking for the colon to start the return type hint.
1074
+ // Start by finding the closing parenthesis of the function.
1075
+ $parenthesisStack = [];
1076
+ $parenthesisCloser = false;
1077
+ for ($x = ($stackPtr + 1); $x < $numTokens; $x++) {
1078
+ if (is_array($tokens[$x]) === false && $tokens[$x] === '(') {
1079
+ $parenthesisStack[] = $x;
1080
+ } else if (is_array($tokens[$x]) === false && $tokens[$x] === ')') {
1081
+ array_pop($parenthesisStack);
1082
+ if (empty($parenthesisStack) === true) {
1083
+ $parenthesisCloser = $x;
1084
+ break;
1085
+ }
1086
+ }
1087
+ }
1088
+
1089
+ if ($parenthesisCloser !== false) {
1090
+ for ($x = ($parenthesisCloser + 1); $x < $numTokens; $x++) {
1091
+ if (is_array($tokens[$x]) === false
1092
+ || isset(Util\Tokens::$emptyTokens[$tokens[$x][0]]) === false
1093
+ ) {
1094
+ // Non-empty content.
1095
+ if (is_array($tokens[$x]) === true && $tokens[$x][0] === T_USE) {
1096
+ // Found a use statements, so search ahead for the closing parenthesis.
1097
+ for ($x += 1; $x < $numTokens; $x++) {
1098
+ if (is_array($tokens[$x]) === false && $tokens[$x] === ')') {
1099
+ continue(2);
1100
+ }
1101
+ }
1102
+ }
1103
+
1104
+ break;
1105
+ }
1106
+ }
1107
+
1108
+ if (isset($tokens[$x]) === true
1109
+ && is_array($tokens[$x]) === false
1110
+ && $tokens[$x] === ':'
1111
+ ) {
1112
+ $allowed = [
1113
+ T_STRING => T_STRING,
1114
+ T_ARRAY => T_ARRAY,
1115
+ T_CALLABLE => T_CALLABLE,
1116
+ T_SELF => T_SELF,
1117
+ T_PARENT => T_PARENT,
1118
+ T_NS_SEPARATOR => T_NS_SEPARATOR,
1119
+ ];
1120
+
1121
+ $allowed += Util\Tokens::$emptyTokens;
1122
+
1123
+ // Find the start of the return type.
1124
+ for ($x += 1; $x < $numTokens; $x++) {
1125
+ if (is_array($tokens[$x]) === true
1126
+ && isset(Util\Tokens::$emptyTokens[$tokens[$x][0]]) === true
1127
+ ) {
1128
+ // Whitespace or coments before the return type.
1129
+ continue;
1130
+ }
1131
+
1132
+ if (is_array($tokens[$x]) === false && $tokens[$x] === '?') {
1133
+ // Found a nullable operator, so skip it.
1134
+ // But also covert the token to save the tokenizer
1135
+ // a bit of time later on.
1136
+ $tokens[$x] = [
1137
+ T_NULLABLE,
1138
+ '?',
1139
+ ];
1140
+
1141
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1142
+ echo "\t\t* token $x changed from ? to T_NULLABLE".PHP_EOL;
1143
+ }
1144
+
1145
+ continue;
1146
+ }
1147
+
1148
+ break;
1149
+ }//end for
1150
+
1151
+ // Any T_ARRAY tokens we find between here and the next
1152
+ // token that can't be part of the return type need to be
1153
+ // converted to T_STRING tokens.
1154
+ for ($x; $x < $numTokens; $x++) {
1155
+ if (is_array($tokens[$x]) === false || isset($allowed[$tokens[$x][0]]) === false) {
1156
+ break;
1157
+ } else if ($tokens[$x][0] === T_ARRAY) {
1158
+ $tokens[$x][0] = T_STRING;
1159
+
1160
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1161
+ echo "\t\t* token $x changed from T_ARRAY to T_STRING".PHP_EOL;
1162
+ }
1163
+ }
1164
+ }
1165
+ }//end if
1166
+ }//end if
1167
+ }//end if
1168
+
1169
+ /*
1170
+ Before PHP 7, the <=> operator was tokenized as
1171
+ T_IS_SMALLER_OR_EQUAL followed by T_GREATER_THAN.
1172
+ So look for and combine these tokens in earlier versions.
1173
+ */
1174
+
1175
+ if ($tokenIsArray === true
1176
+ && $token[0] === T_IS_SMALLER_OR_EQUAL
1177
+ && isset($tokens[($stackPtr + 1)]) === true
1178
+ && $tokens[($stackPtr + 1)][0] === '>'
1179
+ ) {
1180
+ $newToken = [];
1181
+ $newToken['code'] = T_SPACESHIP;
1182
+ $newToken['type'] = 'T_SPACESHIP';
1183
+ $newToken['content'] = '<=>';
1184
+ $finalTokens[$newStackPtr] = $newToken;
1185
+
1186
+ $newStackPtr++;
1187
+ $stackPtr++;
1188
+ continue;
1189
+ }
1190
+
1191
+ /*
1192
+ PHP doesn't assign a token to goto labels, so we have to.
1193
+ These are just string tokens with a single colon after them. Double
1194
+ colons are already tokenized and so don't interfere with this check.
1195
+ But we do have to account for CASE statements, that look just like
1196
+ goto labels.
1197
+ */
1198
+
1199
+ if ($tokenIsArray === true
1200
+ && $token[0] === T_STRING
1201
+ && isset($tokens[($stackPtr + 1)]) === true
1202
+ && $tokens[($stackPtr + 1)] === ':'
1203
+ && $tokens[($stackPtr - 1)][0] !== T_PAAMAYIM_NEKUDOTAYIM
1204
+ ) {
1205
+ $stopTokens = [
1206
+ T_CASE => true,
1207
+ T_SEMICOLON => true,
1208
+ T_OPEN_CURLY_BRACKET => true,
1209
+ T_INLINE_THEN => true,
1210
+ ];
1211
+
1212
+ for ($x = ($newStackPtr - 1); $x > 0; $x--) {
1213
+ if (isset($stopTokens[$finalTokens[$x]['code']]) === true) {
1214
+ break;
1215
+ }
1216
+ }
1217
+
1218
+ if ($finalTokens[$x]['code'] !== T_CASE
1219
+ && $finalTokens[$x]['code'] !== T_INLINE_THEN
1220
+ ) {
1221
+ $finalTokens[$newStackPtr] = [
1222
+ 'content' => $token[1].':',
1223
+ 'code' => T_GOTO_LABEL,
1224
+ 'type' => 'T_GOTO_LABEL',
1225
+ ];
1226
+
1227
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1228
+ echo "\t\t* token $stackPtr changed from T_STRING to T_GOTO_LABEL".PHP_EOL;
1229
+ echo "\t\t* skipping T_COLON token ".($stackPtr + 1).PHP_EOL;
1230
+ }
1231
+
1232
+ $newStackPtr++;
1233
+ $stackPtr++;
1234
+ continue;
1235
+ }
1236
+ }//end if
1237
+
1238
+ /*
1239
+ If this token has newlines in its content, split each line up
1240
+ and create a new token for each line. We do this so it's easier
1241
+ to ascertain where errors occur on a line.
1242
+ Note that $token[1] is the token's content.
1243
+ */
1244
+
1245
+ if ($tokenIsArray === true && strpos($token[1], $this->eolChar) !== false) {
1246
+ $tokenLines = explode($this->eolChar, $token[1]);
1247
+ $numLines = count($tokenLines);
1248
+ $newToken = [
1249
+ 'type' => Util\Tokens::tokenName($token[0]),
1250
+ 'code' => $token[0],
1251
+ 'content' => '',
1252
+ ];
1253
+
1254
+ for ($i = 0; $i < $numLines; $i++) {
1255
+ $newToken['content'] = $tokenLines[$i];
1256
+ if ($i === ($numLines - 1)) {
1257
+ if ($tokenLines[$i] === '') {
1258
+ break;
1259
+ }
1260
+ } else {
1261
+ $newToken['content'] .= $this->eolChar;
1262
+ }
1263
+
1264
+ $finalTokens[$newStackPtr] = $newToken;
1265
+ $newStackPtr++;
1266
+ }
1267
+ } else {
1268
+ if ($tokenIsArray === true && $token[0] === T_STRING) {
1269
+ // Some T_STRING tokens should remain that way
1270
+ // due to their context.
1271
+ $context = [
1272
+ T_OBJECT_OPERATOR => true,
1273
+ T_FUNCTION => true,
1274
+ T_CLASS => true,
1275
+ T_EXTENDS => true,
1276
+ T_IMPLEMENTS => true,
1277
+ T_NEW => true,
1278
+ T_CONST => true,
1279
+ T_NS_SEPARATOR => true,
1280
+ T_USE => true,
1281
+ T_NAMESPACE => true,
1282
+ T_PAAMAYIM_NEKUDOTAYIM => true,
1283
+ ];
1284
+ if (isset($context[$finalTokens[$lastNotEmptyToken]['code']]) === true) {
1285
+ // Special case for syntax like: return new self
1286
+ // where self should not be a string.
1287
+ if ($finalTokens[$lastNotEmptyToken]['code'] === T_NEW
1288
+ && strtolower($token[1]) === 'self'
1289
+ ) {
1290
+ $finalTokens[$newStackPtr] = [
1291
+ 'content' => $token[1],
1292
+ 'code' => T_SELF,
1293
+ 'type' => 'T_SELF',
1294
+ ];
1295
+ } else {
1296
+ $finalTokens[$newStackPtr] = [
1297
+ 'content' => $token[1],
1298
+ 'code' => T_STRING,
1299
+ 'type' => 'T_STRING',
1300
+ ];
1301
+ }
1302
+
1303
+ $newStackPtr++;
1304
+ continue;
1305
+ }//end if
1306
+ }//end if
1307
+
1308
+ $newToken = null;
1309
+ if ($tokenIsArray === false) {
1310
+ if (isset(self::$resolveTokenCache[$token[0]]) === true) {
1311
+ $newToken = self::$resolveTokenCache[$token[0]];
1312
+ }
1313
+ } else {
1314
+ $cacheKey = null;
1315
+ if ($token[0] === T_STRING) {
1316
+ $cacheKey = strtolower($token[1]);
1317
+ } else if ($token[0] !== T_CURLY_OPEN) {
1318
+ $cacheKey = $token[0];
1319
+ }
1320
+
1321
+ if ($cacheKey !== null && isset(self::$resolveTokenCache[$cacheKey]) === true) {
1322
+ $newToken = self::$resolveTokenCache[$cacheKey];
1323
+ $newToken['content'] = $token[1];
1324
+ }
1325
+ }
1326
+
1327
+ if ($newToken === null) {
1328
+ $newToken = self::standardiseToken($token);
1329
+ }
1330
+
1331
+ // Convert colons that are actually the ELSE component of an
1332
+ // inline IF statement.
1333
+ if (empty($insideInlineIf) === false && $newToken['code'] === T_COLON) {
1334
+ // Make sure this isn't the return type separator of a closure.
1335
+ $isReturnType = false;
1336
+ for ($i = ($stackPtr - 1); $i > 0; $i--) {
1337
+ if (is_array($tokens[$i]) === false
1338
+ || ($tokens[$i][0] !== T_DOC_COMMENT
1339
+ && $tokens[$i][0] !== T_COMMENT
1340
+ && $tokens[$i][0] !== T_WHITESPACE)
1341
+ ) {
1342
+ break;
1343
+ }
1344
+ }
1345
+
1346
+ if ($tokens[$i] === ')') {
1347
+ $parenCount = 1;
1348
+ for ($i--; $i > 0; $i--) {
1349
+ if ($tokens[$i] === '(') {
1350
+ $parenCount--;
1351
+ if ($parenCount === 0) {
1352
+ break;
1353
+ }
1354
+ } else if ($tokens[$i] === ')') {
1355
+ $parenCount++;
1356
+ }
1357
+ }
1358
+
1359
+ // We've found the open parenthesis, so if the previous
1360
+ // non-empty token is FUNCTION or USE, this is a closure.
1361
+ for ($i--; $i > 0; $i--) {
1362
+ if (is_array($tokens[$i]) === false
1363
+ || ($tokens[$i][0] !== T_DOC_COMMENT
1364
+ && $tokens[$i][0] !== T_COMMENT
1365
+ && $tokens[$i][0] !== T_WHITESPACE)
1366
+ ) {
1367
+ break;
1368
+ }
1369
+ }
1370
+
1371
+ if ($tokens[$i][0] === T_FUNCTION || $tokens[$i][0] === T_USE) {
1372
+ $isReturnType = true;
1373
+ }
1374
+ }//end if
1375
+
1376
+ if ($isReturnType === false) {
1377
+ array_pop($insideInlineIf);
1378
+ $newToken['code'] = T_INLINE_ELSE;
1379
+ $newToken['type'] = 'T_INLINE_ELSE';
1380
+ }
1381
+ }//end if
1382
+
1383
+ // This is a special condition for T_ARRAY tokens used for
1384
+ // type hinting function arguments as being arrays. We want to keep
1385
+ // the parenthesis map clean, so let's tag these tokens as
1386
+ // T_STRING.
1387
+ if ($newToken['code'] === T_ARRAY) {
1388
+ for ($i = $stackPtr; $i < $numTokens; $i++) {
1389
+ if ($tokens[$i] === '(') {
1390
+ break;
1391
+ } else if ($tokens[$i][0] === T_VARIABLE) {
1392
+ $newToken['code'] = T_STRING;
1393
+ $newToken['type'] = 'T_STRING';
1394
+ break;
1395
+ }
1396
+ }
1397
+ }
1398
+
1399
+ // This is a special case when checking PHP 5.5+ code in PHP < 5.5
1400
+ // where "finally" should be T_FINALLY instead of T_STRING.
1401
+ if ($newToken['code'] === T_STRING
1402
+ && strtolower($newToken['content']) === 'finally'
1403
+ ) {
1404
+ $newToken['code'] = T_FINALLY;
1405
+ $newToken['type'] = 'T_FINALLY';
1406
+ }
1407
+
1408
+ // This is a special case for the PHP 5.5 classname::class syntax
1409
+ // where "class" should be T_STRING instead of T_CLASS.
1410
+ if (($newToken['code'] === T_CLASS
1411
+ || $newToken['code'] === T_FUNCTION)
1412
+ && $finalTokens[$lastNotEmptyToken]['code'] === T_DOUBLE_COLON
1413
+ ) {
1414
+ $newToken['code'] = T_STRING;
1415
+ $newToken['type'] = 'T_STRING';
1416
+ }
1417
+
1418
+ // This is a special case for PHP 5.6 use function and use const
1419
+ // where "function" and "const" should be T_STRING instead of T_FUNCTION
1420
+ // and T_CONST.
1421
+ if (($newToken['code'] === T_FUNCTION
1422
+ || $newToken['code'] === T_CONST)
1423
+ && ($finalTokens[$lastNotEmptyToken]['code'] === T_USE || $insideUseGroup === true)
1424
+ ) {
1425
+ $newToken['code'] = T_STRING;
1426
+ $newToken['type'] = 'T_STRING';
1427
+ }
1428
+
1429
+ // This is a special case for use groups in PHP 7+ where leaving
1430
+ // the curly braces as their normal tokens would confuse
1431
+ // the scope map and sniffs.
1432
+ if ($newToken['code'] === T_OPEN_CURLY_BRACKET
1433
+ && $finalTokens[$lastNotEmptyToken]['code'] === T_NS_SEPARATOR
1434
+ ) {
1435
+ $newToken['code'] = T_OPEN_USE_GROUP;
1436
+ $newToken['type'] = 'T_OPEN_USE_GROUP';
1437
+ $insideUseGroup = true;
1438
+ }
1439
+
1440
+ if ($insideUseGroup === true && $newToken['code'] === T_CLOSE_CURLY_BRACKET) {
1441
+ $newToken['code'] = T_CLOSE_USE_GROUP;
1442
+ $newToken['type'] = 'T_CLOSE_USE_GROUP';
1443
+ $insideUseGroup = false;
1444
+ }
1445
+
1446
+ $finalTokens[$newStackPtr] = $newToken;
1447
+ $newStackPtr++;
1448
+ }//end if
1449
+ }//end for
1450
+
1451
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1452
+ echo "\t*** END PHP TOKENIZING ***".PHP_EOL;
1453
+ }
1454
+
1455
+ return $finalTokens;
1456
+
1457
+ }//end tokenize()
1458
+
1459
+
1460
+ /**
1461
+ * Performs additional processing after main tokenizing.
1462
+ *
1463
+ * This additional processing checks for CASE statements that are using curly
1464
+ * braces for scope openers and closers. It also turns some T_FUNCTION tokens
1465
+ * into T_CLOSURE when they are not standard function definitions. It also
1466
+ * detects short array syntax and converts those square brackets into new tokens.
1467
+ * It also corrects some usage of the static and class keywords. It also
1468
+ * assigns tokens to function return types.
1469
+ *
1470
+ * @return void
1471
+ */
1472
+ protected function processAdditional()
1473
+ {
1474
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1475
+ echo "\t*** START ADDITIONAL PHP PROCESSING ***".PHP_EOL;
1476
+ }
1477
+
1478
+ $numTokens = count($this->tokens);
1479
+ for ($i = ($numTokens - 1); $i >= 0; $i--) {
1480
+ // Check for any unset scope conditions due to alternate IF/ENDIF syntax.
1481
+ if (isset($this->tokens[$i]['scope_opener']) === true
1482
+ && isset($this->tokens[$i]['scope_condition']) === false
1483
+ ) {
1484
+ $this->tokens[$i]['scope_condition'] = $this->tokens[$this->tokens[$i]['scope_opener']]['scope_condition'];
1485
+ }
1486
+
1487
+ if ($this->tokens[$i]['code'] === T_FUNCTION) {
1488
+ /*
1489
+ Detect functions that are actually closures and
1490
+ assign them a different token.
1491
+ */
1492
+
1493
+ if (isset($this->tokens[$i]['scope_opener']) === true) {
1494
+ for ($x = ($i + 1); $x < $numTokens; $x++) {
1495
+ if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false
1496
+ && $this->tokens[$x]['code'] !== T_BITWISE_AND
1497
+ ) {
1498
+ break;
1499
+ }
1500
+ }
1501
+
1502
+ if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) {
1503
+ $this->tokens[$i]['code'] = T_CLOSURE;
1504
+ $this->tokens[$i]['type'] = 'T_CLOSURE';
1505
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1506
+ $line = $this->tokens[$i]['line'];
1507
+ echo "\t* token $i on line $line changed from T_FUNCTION to T_CLOSURE".PHP_EOL;
1508
+ }
1509
+
1510
+ for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) {
1511
+ if (isset($this->tokens[$x]['conditions'][$i]) === false) {
1512
+ continue;
1513
+ }
1514
+
1515
+ $this->tokens[$x]['conditions'][$i] = T_CLOSURE;
1516
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1517
+ $type = $this->tokens[$x]['type'];
1518
+ echo "\t\t* cleaned $x ($type) *".PHP_EOL;
1519
+ }
1520
+ }
1521
+ }
1522
+ }//end if
1523
+
1524
+ continue;
1525
+ } else if ($this->tokens[$i]['code'] === T_CLASS && isset($this->tokens[$i]['scope_opener']) === true) {
1526
+ /*
1527
+ Detect anonymous classes and assign them a different token.
1528
+ */
1529
+
1530
+ for ($x = ($i + 1); $x < $numTokens; $x++) {
1531
+ if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) {
1532
+ break;
1533
+ }
1534
+ }
1535
+
1536
+ if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS
1537
+ || $this->tokens[$x]['code'] === T_OPEN_CURLY_BRACKET
1538
+ || $this->tokens[$x]['code'] === T_EXTENDS
1539
+ || $this->tokens[$x]['code'] === T_IMPLEMENTS
1540
+ ) {
1541
+ $this->tokens[$i]['code'] = T_ANON_CLASS;
1542
+ $this->tokens[$i]['type'] = 'T_ANON_CLASS';
1543
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1544
+ $line = $this->tokens[$i]['line'];
1545
+ echo "\t* token $i on line $line changed from T_CLASS to T_ANON_CLASS".PHP_EOL;
1546
+ }
1547
+
1548
+ for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) {
1549
+ if (isset($this->tokens[$x]['conditions'][$i]) === false) {
1550
+ continue;
1551
+ }
1552
+
1553
+ $this->tokens[$x]['conditions'][$i] = T_ANON_CLASS;
1554
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1555
+ $type = $this->tokens[$x]['type'];
1556
+ echo "\t\t* cleaned $x ($type) *".PHP_EOL;
1557
+ }
1558
+ }
1559
+ }
1560
+
1561
+ continue;
1562
+ } else if ($this->tokens[$i]['code'] === T_OPEN_SQUARE_BRACKET) {
1563
+ if (isset($this->tokens[$i]['bracket_closer']) === false) {
1564
+ continue;
1565
+ }
1566
+
1567
+ // Unless there is a variable or a bracket before this token,
1568
+ // it is the start of an array being defined using the short syntax.
1569
+ $isShortArray = false;
1570
+ $allowed = [
1571
+ T_CLOSE_SQUARE_BRACKET => T_CLOSE_SQUARE_BRACKET,
1572
+ T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
1573
+ T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS,
1574
+ T_VARIABLE => T_VARIABLE,
1575
+ T_OBJECT_OPERATOR => T_OBJECT_OPERATOR,
1576
+ T_STRING => T_STRING,
1577
+ T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING,
1578
+ ];
1579
+
1580
+ for ($x = ($i - 1); $x >= 0; $x--) {
1581
+ // If we hit a scope opener, the statement has ended
1582
+ // without finding anything, so it's probably an array
1583
+ // using PHP 7.1 short list syntax.
1584
+ if (isset($this->tokens[$x]['scope_opener']) === true) {
1585
+ $isShortArray = true;
1586
+ break;
1587
+ }
1588
+
1589
+ if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) {
1590
+ if (isset($allowed[$this->tokens[$x]['code']]) === false) {
1591
+ $isShortArray = true;
1592
+ }
1593
+
1594
+ break;
1595
+ }
1596
+ }
1597
+
1598
+ if ($isShortArray === true) {
1599
+ $this->tokens[$i]['code'] = T_OPEN_SHORT_ARRAY;
1600
+ $this->tokens[$i]['type'] = 'T_OPEN_SHORT_ARRAY';
1601
+
1602
+ $closer = $this->tokens[$i]['bracket_closer'];
1603
+ $this->tokens[$closer]['code'] = T_CLOSE_SHORT_ARRAY;
1604
+ $this->tokens[$closer]['type'] = 'T_CLOSE_SHORT_ARRAY';
1605
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1606
+ $line = $this->tokens[$i]['line'];
1607
+ echo "\t* token $i on line $line changed from T_OPEN_SQUARE_BRACKET to T_OPEN_SHORT_ARRAY".PHP_EOL;
1608
+ $line = $this->tokens[$closer]['line'];
1609
+ echo "\t* token $closer on line $line changed from T_CLOSE_SQUARE_BRACKET to T_CLOSE_SHORT_ARRAY".PHP_EOL;
1610
+ }
1611
+ }
1612
+
1613
+ continue;
1614
+ } else if ($this->tokens[$i]['code'] === T_STATIC) {
1615
+ for ($x = ($i - 1); $x > 0; $x--) {
1616
+ if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) {
1617
+ break;
1618
+ }
1619
+ }
1620
+
1621
+ if ($this->tokens[$x]['code'] === T_INSTANCEOF) {
1622
+ $this->tokens[$i]['code'] = T_STRING;
1623
+ $this->tokens[$i]['type'] = 'T_STRING';
1624
+
1625
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1626
+ $line = $this->tokens[$i]['line'];
1627
+ echo "\t* token $i on line $line changed from T_STATIC to T_STRING".PHP_EOL;
1628
+ }
1629
+ }
1630
+
1631
+ continue;
1632
+ } else if ($this->tokens[$i]['code'] === T_TRUE
1633
+ || $this->tokens[$i]['code'] === T_FALSE
1634
+ || $this->tokens[$i]['code'] === T_NULL
1635
+ ) {
1636
+ for ($x = ($i + 1); $i < $numTokens; $x++) {
1637
+ if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) {
1638
+ // Non-whitespace content.
1639
+ break;
1640
+ }
1641
+ }
1642
+
1643
+ $context = [
1644
+ T_OBJECT_OPERATOR => true,
1645
+ T_NS_SEPARATOR => true,
1646
+ T_PAAMAYIM_NEKUDOTAYIM => true,
1647
+ ];
1648
+ if (isset($context[$this->tokens[$x]['code']]) === true) {
1649
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1650
+ $line = $this->tokens[$i]['line'];
1651
+ $type = $this->tokens[$i]['type'];
1652
+ echo "\t* token $i on line $line changed from $type to T_STRING".PHP_EOL;
1653
+ }
1654
+
1655
+ $this->tokens[$i]['code'] = T_STRING;
1656
+ $this->tokens[$i]['type'] = 'T_STRING';
1657
+ }
1658
+ } else if ($this->tokens[$i]['code'] === T_CONST) {
1659
+ // Context sensitive keywords support.
1660
+ for ($x = ($i + 1); $i < $numTokens; $x++) {
1661
+ if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) {
1662
+ // Non-whitespace content.
1663
+ break;
1664
+ }
1665
+ }
1666
+
1667
+ if ($this->tokens[$x]['code'] !== T_STRING) {
1668
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1669
+ $line = $this->tokens[$x]['line'];
1670
+ $type = $this->tokens[$x]['type'];
1671
+ echo "\t* token $x on line $line changed from $type to T_STRING".PHP_EOL;
1672
+ }
1673
+
1674
+ $this->tokens[$x]['code'] = T_STRING;
1675
+ $this->tokens[$x]['type'] = 'T_STRING';
1676
+ }
1677
+ }//end if
1678
+
1679
+ if (($this->tokens[$i]['code'] !== T_CASE
1680
+ && $this->tokens[$i]['code'] !== T_DEFAULT)
1681
+ || isset($this->tokens[$i]['scope_opener']) === false
1682
+ ) {
1683
+ // Only interested in CASE and DEFAULT statements from here on in.
1684
+ continue;
1685
+ }
1686
+
1687
+ $scopeOpener = $this->tokens[$i]['scope_opener'];
1688
+ $scopeCloser = $this->tokens[$i]['scope_closer'];
1689
+
1690
+ // If the first char after the opener is a curly brace
1691
+ // and that brace has been ignored, it is actually
1692
+ // opening this case statement and the opener and closer are
1693
+ // probably set incorrectly.
1694
+ for ($x = ($scopeOpener + 1); $x < $numTokens; $x++) {
1695
+ if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) {
1696
+ // Non-whitespace content.
1697
+ break;
1698
+ }
1699
+ }
1700
+
1701
+ if ($this->tokens[$x]['code'] === T_CASE || $this->tokens[$x]['code'] === T_DEFAULT) {
1702
+ // Special case for multiple CASE statements that share the same
1703
+ // closer. Because we are going backwards through the file, this next
1704
+ // CASE statement is already fixed, so just use its closer and don't
1705
+ // worry about fixing anything.
1706
+ $newCloser = $this->tokens[$x]['scope_closer'];
1707
+ $this->tokens[$i]['scope_closer'] = $newCloser;
1708
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1709
+ $oldType = $this->tokens[$scopeCloser]['type'];
1710
+ $newType = $this->tokens[$newCloser]['type'];
1711
+ $line = $this->tokens[$i]['line'];
1712
+ echo "\t* token $i (T_CASE) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL;
1713
+ }
1714
+
1715
+ continue;
1716
+ }
1717
+
1718
+ if ($this->tokens[$x]['code'] !== T_OPEN_CURLY_BRACKET
1719
+ || isset($this->tokens[$x]['scope_condition']) === true
1720
+ ) {
1721
+ // Not a CASE/DEFAULT with a curly brace opener.
1722
+ continue;
1723
+ }
1724
+
1725
+ // The closer for this CASE/DEFAULT should be the closing curly brace and
1726
+ // not whatever it already is. The opener needs to be the opening curly
1727
+ // brace so everything matches up.
1728
+ $newCloser = $this->tokens[$x]['bracket_closer'];
1729
+ foreach ([$i, $x, $newCloser] as $index) {
1730
+ $this->tokens[$index]['scope_condition'] = $i;
1731
+ $this->tokens[$index]['scope_opener'] = $x;
1732
+ $this->tokens[$index]['scope_closer'] = $newCloser;
1733
+ }
1734
+
1735
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1736
+ $line = $this->tokens[$i]['line'];
1737
+ $tokenType = $this->tokens[$i]['type'];
1738
+
1739
+ $oldType = $this->tokens[$scopeOpener]['type'];
1740
+ $newType = $this->tokens[$x]['type'];
1741
+ echo "\t* token $i ($tokenType) on line $line opener changed from $scopeOpener ($oldType) to $x ($newType)".PHP_EOL;
1742
+
1743
+ $oldType = $this->tokens[$scopeCloser]['type'];
1744
+ $newType = $this->tokens[$newCloser]['type'];
1745
+ echo "\t* token $i ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL;
1746
+ }
1747
+
1748
+ if ($this->tokens[$scopeOpener]['scope_condition'] === $i) {
1749
+ unset($this->tokens[$scopeOpener]['scope_condition']);
1750
+ unset($this->tokens[$scopeOpener]['scope_opener']);
1751
+ unset($this->tokens[$scopeOpener]['scope_closer']);
1752
+ }
1753
+
1754
+ if ($this->tokens[$scopeCloser]['scope_condition'] === $i) {
1755
+ unset($this->tokens[$scopeCloser]['scope_condition']);
1756
+ unset($this->tokens[$scopeCloser]['scope_opener']);
1757
+ unset($this->tokens[$scopeCloser]['scope_closer']);
1758
+ } else {
1759
+ // We were using a shared closer. All tokens that were
1760
+ // sharing this closer with us, except for the scope condition
1761
+ // and it's opener, need to now point to the new closer.
1762
+ $condition = $this->tokens[$scopeCloser]['scope_condition'];
1763
+ $start = ($this->tokens[$condition]['scope_opener'] + 1);
1764
+ for ($y = $start; $y < $scopeCloser; $y++) {
1765
+ if (isset($this->tokens[$y]['scope_closer']) === true
1766
+ && $this->tokens[$y]['scope_closer'] === $scopeCloser
1767
+ ) {
1768
+ $this->tokens[$y]['scope_closer'] = $newCloser;
1769
+
1770
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1771
+ $line = $this->tokens[$y]['line'];
1772
+ $tokenType = $this->tokens[$y]['type'];
1773
+ $oldType = $this->tokens[$scopeCloser]['type'];
1774
+ $newType = $this->tokens[$newCloser]['type'];
1775
+ echo "\t\t* token $y ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL;
1776
+ }
1777
+ }
1778
+ }
1779
+ }//end if
1780
+
1781
+ unset($this->tokens[$x]['bracket_opener']);
1782
+ unset($this->tokens[$x]['bracket_closer']);
1783
+ unset($this->tokens[$newCloser]['bracket_opener']);
1784
+ unset($this->tokens[$newCloser]['bracket_closer']);
1785
+ $this->tokens[$scopeCloser]['conditions'][] = $i;
1786
+
1787
+ // Now fix up all the tokens that think they are
1788
+ // inside the CASE/DEFAULT statement when they are really outside.
1789
+ for ($x = $newCloser; $x < $scopeCloser; $x++) {
1790
+ foreach ($this->tokens[$x]['conditions'] as $num => $oldCond) {
1791
+ if ($oldCond === $this->tokens[$i]['code']) {
1792
+ $oldConditions = $this->tokens[$x]['conditions'];
1793
+ unset($this->tokens[$x]['conditions'][$num]);
1794
+
1795
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1796
+ $type = $this->tokens[$x]['type'];
1797
+ $oldConds = '';
1798
+ foreach ($oldConditions as $condition) {
1799
+ $oldConds .= Util\Tokens::tokenName($condition).',';
1800
+ }
1801
+
1802
+ $oldConds = rtrim($oldConds, ',');
1803
+
1804
+ $newConds = '';
1805
+ foreach ($this->tokens[$x]['conditions'] as $condition) {
1806
+ $newConds .= Util\Tokens::tokenName($condition).',';
1807
+ }
1808
+
1809
+ $newConds = rtrim($newConds, ',');
1810
+
1811
+ echo "\t\t* cleaned $x ($type) *".PHP_EOL;
1812
+ echo "\t\t\t=> conditions changed from $oldConds to $newConds".PHP_EOL;
1813
+ }
1814
+
1815
+ break;
1816
+ }//end if
1817
+ }//end foreach
1818
+ }//end for
1819
+ }//end for
1820
+
1821
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1822
+ echo "\t*** END ADDITIONAL PHP PROCESSING ***".PHP_EOL;
1823
+ }
1824
+
1825
+ }//end processAdditional()
1826
+
1827
+
1828
+ /**
1829
+ * Takes a token produced from <code>token_get_all()</code> and produces a
1830
+ * more uniform token.
1831
+ *
1832
+ * @param string|array $token The token to convert.
1833
+ *
1834
+ * @return array The new token.
1835
+ */
1836
+ public static function standardiseToken($token)
1837
+ {
1838
+ if (isset($token[1]) === false) {
1839
+ if (isset(self::$resolveTokenCache[$token[0]]) === true) {
1840
+ return self::$resolveTokenCache[$token[0]];
1841
+ }
1842
+ } else {
1843
+ $cacheKey = null;
1844
+ if ($token[0] === T_STRING) {
1845
+ $cacheKey = strtolower($token[1]);
1846
+ } else if ($token[0] !== T_CURLY_OPEN) {
1847
+ $cacheKey = $token[0];
1848
+ }
1849
+
1850
+ if ($cacheKey !== null && isset(self::$resolveTokenCache[$cacheKey]) === true) {
1851
+ $newToken = self::$resolveTokenCache[$cacheKey];
1852
+ $newToken['content'] = $token[1];
1853
+ return $newToken;
1854
+ }
1855
+ }
1856
+
1857
+ if (isset($token[1]) === false) {
1858
+ return self::resolveSimpleToken($token[0]);
1859
+ }
1860
+
1861
+ if ($token[0] === T_STRING) {
1862
+ switch ($cacheKey) {
1863
+ case 'false':
1864
+ $newToken['type'] = 'T_FALSE';
1865
+ break;
1866
+ case 'true':
1867
+ $newToken['type'] = 'T_TRUE';
1868
+ break;
1869
+ case 'null':
1870
+ $newToken['type'] = 'T_NULL';
1871
+ break;
1872
+ case 'self':
1873
+ $newToken['type'] = 'T_SELF';
1874
+ break;
1875
+ case 'parent':
1876
+ $newToken['type'] = 'T_PARENT';
1877
+ break;
1878
+ default:
1879
+ $newToken['type'] = 'T_STRING';
1880
+ break;
1881
+ }
1882
+
1883
+ $newToken['code'] = constant($newToken['type']);
1884
+
1885
+ self::$resolveTokenCache[$cacheKey] = $newToken;
1886
+ } else if ($token[0] === T_CURLY_OPEN) {
1887
+ $newToken = [
1888
+ 'code' => T_OPEN_CURLY_BRACKET,
1889
+ 'type' => 'T_OPEN_CURLY_BRACKET',
1890
+ ];
1891
+ } else {
1892
+ $newToken = [
1893
+ 'code' => $token[0],
1894
+ 'type' => Util\Tokens::tokenName($token[0]),
1895
+ ];
1896
+
1897
+ self::$resolveTokenCache[$token[0]] = $newToken;
1898
+ }//end if
1899
+
1900
+ $newToken['content'] = $token[1];
1901
+ return $newToken;
1902
+
1903
+ }//end standardiseToken()
1904
+
1905
+
1906
+ /**
1907
+ * Converts simple tokens into a format that conforms to complex tokens
1908
+ * produced by token_get_all().
1909
+ *
1910
+ * Simple tokens are tokens that are not in array form when produced from
1911
+ * token_get_all().
1912
+ *
1913
+ * @param string $token The simple token to convert.
1914
+ *
1915
+ * @return array The new token in array format.
1916
+ */
1917
+ public static function resolveSimpleToken($token)
1918
+ {
1919
+ $newToken = [];
1920
+
1921
+ switch ($token) {
1922
+ case '{':
1923
+ $newToken['type'] = 'T_OPEN_CURLY_BRACKET';
1924
+ break;
1925
+ case '}':
1926
+ $newToken['type'] = 'T_CLOSE_CURLY_BRACKET';
1927
+ break;
1928
+ case '[':
1929
+ $newToken['type'] = 'T_OPEN_SQUARE_BRACKET';
1930
+ break;
1931
+ case ']':
1932
+ $newToken['type'] = 'T_CLOSE_SQUARE_BRACKET';
1933
+ break;
1934
+ case '(':
1935
+ $newToken['type'] = 'T_OPEN_PARENTHESIS';
1936
+ break;
1937
+ case ')':
1938
+ $newToken['type'] = 'T_CLOSE_PARENTHESIS';
1939
+ break;
1940
+ case ':':
1941
+ $newToken['type'] = 'T_COLON';
1942
+ break;
1943
+ case '.':
1944
+ $newToken['type'] = 'T_STRING_CONCAT';
1945
+ break;
1946
+ case ';':
1947
+ $newToken['type'] = 'T_SEMICOLON';
1948
+ break;
1949
+ case '=':
1950
+ $newToken['type'] = 'T_EQUAL';
1951
+ break;
1952
+ case '*':
1953
+ $newToken['type'] = 'T_MULTIPLY';
1954
+ break;
1955
+ case '/':
1956
+ $newToken['type'] = 'T_DIVIDE';
1957
+ break;
1958
+ case '+':
1959
+ $newToken['type'] = 'T_PLUS';
1960
+ break;
1961
+ case '-':
1962
+ $newToken['type'] = 'T_MINUS';
1963
+ break;
1964
+ case '%':
1965
+ $newToken['type'] = 'T_MODULUS';
1966
+ break;
1967
+ case '^':
1968
+ $newToken['type'] = 'T_BITWISE_XOR';
1969
+ break;
1970
+ case '&':
1971
+ $newToken['type'] = 'T_BITWISE_AND';
1972
+ break;
1973
+ case '|':
1974
+ $newToken['type'] = 'T_BITWISE_OR';
1975
+ break;
1976
+ case '~':
1977
+ $newToken['type'] = 'T_BITWISE_NOT';
1978
+ break;
1979
+ case '<':
1980
+ $newToken['type'] = 'T_LESS_THAN';
1981
+ break;
1982
+ case '>':
1983
+ $newToken['type'] = 'T_GREATER_THAN';
1984
+ break;
1985
+ case '!':
1986
+ $newToken['type'] = 'T_BOOLEAN_NOT';
1987
+ break;
1988
+ case ',':
1989
+ $newToken['type'] = 'T_COMMA';
1990
+ break;
1991
+ case '@':
1992
+ $newToken['type'] = 'T_ASPERAND';
1993
+ break;
1994
+ case '$':
1995
+ $newToken['type'] = 'T_DOLLAR';
1996
+ break;
1997
+ case '`':
1998
+ $newToken['type'] = 'T_BACKTICK';
1999
+ break;
2000
+ default:
2001
+ $newToken['type'] = 'T_NONE';
2002
+ break;
2003
+ }//end switch
2004
+
2005
+ $newToken['code'] = constant($newToken['type']);
2006
+ $newToken['content'] = $token;
2007
+
2008
+ self::$resolveTokenCache[$token] = $newToken;
2009
+ return $newToken;
2010
+
2011
+ }//end resolveSimpleToken()
2012
+
2013
+
2014
+ }//end class
vendor/php_codesniffer-3.4.0/src/Tokenizers/Tokenizer.php ADDED
@@ -0,0 +1,1614 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The base tokenizer class.
4
+ *
5
+ * @author Greg Sherwood <gsherwood@squiz.net>
6
+ * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
+ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
+ */
9
+
10
+ namespace PHP_CodeSniffer\Tokenizers;
11
+
12
+ use PHP_CodeSniffer\Exceptions\RuntimeException;
13
+ use PHP_CodeSniffer\Util;
14
+
15
+ abstract class Tokenizer
16
+ {
17
+
18
+ /**
19
+ * The config data for the run.
20
+ *
21
+ * @var \PHP_CodeSniffer\Config
22
+ */
23
+ protected $config = null;
24
+
25
+ /**
26
+ * The EOL char used in the content.
27
+ *
28
+ * @var string
29
+ */
30
+ protected $eolChar = [];
31
+
32
+ /**
33
+ * A token-based representation of the content.
34
+ *
35
+ * @var array
36
+ */
37
+ protected $tokens = [];
38
+
39
+ /**
40
+ * Known lengths of tokens.
41
+ *
42
+ * @var array<int, int>
43
+ */
44
+ public $knownLengths = [];
45
+
46
+ /**
47
+ * A list of lines being ignored due to error suppression comments.
48
+ *
49
+ * @var array
50
+ */
51
+ public $ignoredLines = [];
52
+
53
+
54
+ /**
55
+ * Initialise and run the tokenizer.
56
+ *
57
+ * @param string $content The content to tokenize,
58
+ * @param \PHP_CodeSniffer\Config | null $config The config data for the run.
59
+ * @param string $eolChar The EOL char used in the content.
60
+ *
61
+ * @return void
62
+ * @throws TokenizerException If the file appears to be minified.
63
+ */
64
+ public function __construct($content, $config, $eolChar='\n')
65
+ {
66
+ $this->eolChar = $eolChar;
67
+
68
+ $this->config = $config;
69
+ $this->tokens = $this->tokenize($content);
70
+
71
+ if ($config === null) {
72
+ return;
73
+ }
74
+
75
+ $this->createPositionMap();
76
+ $this->createTokenMap();
77
+ $this->createParenthesisNestingMap();
78
+ $this->createScopeMap();
79
+ $this->createLevelMap();
80
+
81
+ // Allow the tokenizer to do additional processing if required.
82
+ $this->processAdditional();
83
+
84
+ }//end __construct()
85
+
86
+
87
+ /**
88
+ * Checks the content to see if it looks minified.
89
+ *
90
+ * @param string $content The content to tokenize.
91
+ * @param string $eolChar The EOL char used in the content.
92
+ *
93
+ * @return boolean
94
+ */
95
+ protected function isMinifiedContent($content, $eolChar='\n')
96
+ {
97
+ // Minified files often have a very large number of characters per line
98
+ // and cause issues when tokenizing.
99
+ $numChars = strlen($content);
100
+ $numLines = (substr_count($content, $eolChar) + 1);
101
+ $average = ($numChars / $numLines);
102
+ if ($average > 100) {
103
+ return true;
104
+ }
105
+
106
+ return false;
107
+
108
+ }//end isMinifiedContent()
109
+
110
+
111
+ /**
112
+ * Gets the array of tokens.
113
+ *
114
+ * @return array
115
+ */
116
+ public function getTokens()
117
+ {
118
+ return $this->tokens;
119
+
120
+ }//end getTokens()
121
+
122
+
123
+ /**
124
+ * Creates an array of tokens when given some content.
125
+ *
126
+ * @param string $string The string to tokenize.
127
+ *
128
+ * @return array
129
+ */
130
+ abstract protected function tokenize($string);
131
+
132
+
133
+ /**
134
+ * Performs additional processing after main tokenizing.
135
+ *
136
+ * @return void
137
+ */
138
+ abstract protected function processAdditional();
139
+
140
+
141
+ /**
142
+ * Sets token position information.
143
+ *
144
+ * Can also convert tabs into spaces. Each tab can represent between
145
+ * 1 and $width spaces, so this cannot be a straight string replace.
146
+ *
147
+ * @return void
148
+ */
149
+ private function createPositionMap()
150
+ {
151
+ $currColumn = 1;
152
+ $lineNumber = 1;
153
+ $eolLen = strlen($this->eolChar);
154
+ $ignoring = null;
155
+ $inTests = defined('PHP_CODESNIFFER_IN_TESTS');
156
+
157
+ $checkEncoding = false;
158
+ if (function_exists('iconv_strlen') === true) {
159
+ $checkEncoding = true;
160
+ }
161
+
162
+ $checkAnnotations = $this->config->annotations;
163
+ $encoding = $this->config->encoding;
164
+ $tabWidth = $this->config->tabWidth;
165
+
166
+ $this->tokensWithTabs = [
167
+ T_WHITESPACE => true,
168
+ T_COMMENT => true,
169
+ T_DOC_COMMENT => true,
170
+ T_DOC_COMMENT_WHITESPACE => true,
171
+ T_DOC_COMMENT_STRING => true,
172
+ T_CONSTANT_ENCAPSED_STRING => true,
173
+ T_DOUBLE_QUOTED_STRING => true,
174
+ T_HEREDOC => true,
175
+ T_NOWDOC => true,
176
+ T_INLINE_HTML => true,
177
+ ];
178
+
179
+ $this->numTokens = count($this->tokens);
180
+ for ($i = 0; $i < $this->numTokens; $i++) {
181
+ $this->tokens[$i]['line'] = $lineNumber;
182
+ $this->tokens[$i]['column'] = $currColumn;
183
+
184
+ if (isset($this->knownLengths[$this->tokens[$i]['code']]) === true) {
185
+ // There are no tabs in the tokens we know the length of.
186
+ $length = $this->knownLengths[$this->tokens[$i]['code']];
187
+ $currColumn += $length;
188
+ } else if ($tabWidth === 0
189
+ || isset($this->tokensWithTabs[$this->tokens[$i]['code']]) === false
190
+ || strpos($this->tokens[$i]['content'], "\t") === false
191
+ ) {
192
+ // There are no tabs in this content, or we aren't replacing them.
193
+ if ($checkEncoding === true) {
194
+ // Not using the default encoding, so take a bit more care.
195
+ $oldLevel = error_reporting();
196
+ error_reporting(0);
197
+ $length = iconv_strlen($this->tokens[$i]['content'], $encoding);
198
+ error_reporting($oldLevel);
199
+
200
+ if ($length === false) {
201
+ // String contained invalid characters, so revert to default.
202
+ $length = strlen($this->tokens[$i]['content']);
203
+ }
204
+ } else {
205
+ $length = strlen($this->tokens[$i]['content']);
206
+ }
207
+
208
+ $currColumn += $length;
209
+ } else {
210
+ $this->replaceTabsInToken($this->tokens[$i]);
211
+ $length = $this->tokens[$i]['length'];
212
+ $currColumn += $length;
213
+ }//end if
214
+
215
+ $this->tokens[$i]['length'] = $length;
216
+
217
+ if (isset($this->knownLengths[$this->tokens[$i]['code']]) === false
218
+ && strpos($this->tokens[$i]['content'], $this->eolChar) !== false
219
+ ) {
220
+ $lineNumber++;
221
+ $currColumn = 1;
222
+
223
+ // Newline chars are not counted in the token length.
224
+ $this->tokens[$i]['length'] -= $eolLen;
225
+ }
226
+
227
+ if ($this->tokens[$i]['code'] === T_COMMENT
228
+ || $this->tokens[$i]['code'] === T_DOC_COMMENT_STRING
229
+ || $this->tokens[$i]['code'] === T_DOC_COMMENT_TAG
230
+ || ($inTests === true && $this->tokens[$i]['code'] === T_INLINE_HTML)
231
+ ) {
232
+ $commentText = ltrim($this->tokens[$i]['content'], " \t/*");
233
+ $commentText = rtrim($commentText, " */\t\r\n");
234
+ $commentTextLower = strtolower($commentText);
235
+ if (strpos($commentText, '@codingStandards') !== false) {
236
+ // If this comment is the only thing on the line, it tells us
237
+ // to ignore the following line. If the line contains other content
238
+ // then we are just ignoring this one single line.
239
+ $ownLine = false;
240
+ if ($i > 0) {
241
+ for ($prev = ($i - 1); $prev >= 0; $prev--) {
242
+ if ($this->tokens[$prev]['code'] === T_WHITESPACE) {
243
+ continue;
244
+ }
245
+
246
+ break;
247
+ }
248
+
249
+ if ($this->tokens[$prev]['line'] !== $this->tokens[$i]['line']) {
250
+ $ownLine = true;
251
+ }
252
+ }
253
+
254
+ if ($ignoring === null
255
+ && strpos($commentText, '@codingStandardsIgnoreStart') !== false
256
+ ) {
257
+ $ignoring = ['.all' => true];
258
+ if ($ownLine === true) {
259
+ $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
260
+ }
261
+ } else if ($ignoring !== null
262
+ && strpos($commentText, '@codingStandardsIgnoreEnd') !== false
263
+ ) {
264
+ if ($ownLine === true) {
265
+ $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true];
266
+ } else {
267
+ $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
268
+ }
269
+
270
+ $ignoring = null;
271
+ } else if ($ignoring === null
272
+ && strpos($commentText, '@codingStandardsIgnoreLine') !== false
273
+ ) {
274
+ $ignoring = ['.all' => true];
275
+ if ($ownLine === true) {
276
+ $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
277
+ $this->ignoredLines[($this->tokens[$i]['line'] + 1)] = $ignoring;
278
+ } else {
279
+ $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
280
+ }
281
+
282
+ $ignoring = null;
283
+ }//end if
284
+ } else if (substr($commentTextLower, 0, 6) === 'phpcs:'
285
+ || substr($commentTextLower, 0, 7) === '@phpcs:'
286
+ ) {
287
+ // If the @phpcs: syntax is being used, strip the @ to make
288
+ // comparisons easier.
289
+ if ($commentText[0] === '@') {
290
+ $commentText = substr($commentText, 1);
291
+ $commentTextLower = strtolower($commentText);
292
+ }
293
+
294
+ // If there is a comment on the end, strip it off.
295
+ $commentStart = strpos($commentTextLower, ' --');
296
+ if ($commentStart !== false) {
297
+ $commentText = substr($commentText, 0, $commentStart);
298
+ $commentTextLower = strtolower($commentText);
299
+ }
300
+
301
+ // If this comment is the only thing on the line, it tells us
302
+ // to ignore the following line. If the line contains other content
303
+ // then we are just ignoring this one single line.
304
+ $lineHasOtherContent = false;
305
+ $lineHasOtherTokens = false;
306
+ if ($i > 0) {
307
+ for ($prev = ($i - 1); $prev > 0; $prev--) {
308
+ if ($this->tokens[$prev]['line'] !== $this->tokens[$i]['line']) {
309
+ // Changed lines.
310
+ break;
311
+ }
312
+
313
+ if ($this->tokens[$prev]['code'] === T_WHITESPACE
314
+ || ($this->tokens[$prev]['code'] === T_INLINE_HTML
315
+ && trim($this->tokens[$prev]['content']) === '')
316
+ ) {
317
+ continue;
318
+ }
319
+
320
+ $lineHasOtherTokens = true;
321
+
322
+ if ($this->tokens[$prev]['code'] === T_OPEN_TAG) {
323
+ continue;
324
+ }
325
+
326
+ $lineHasOtherContent = true;
327
+ break;
328
+ }//end for
329
+
330
+ $changedLines = false;
331
+ for ($next = $i; $next < $this->numTokens; $next++) {
332
+ if ($changedLines === true) {
333
+ // Changed lines.
334
+ break;
335
+ }
336
+
337
+ if (isset($this->knownLengths[$this->tokens[$next]['code']]) === false
338
+ && strpos($this->tokens[$next]['content'], $this->eolChar) !== false
339
+ ) {
340
+ // Last token on the current line.
341
+ $changedLines = true;
342
+ }
343
+
344
+ if ($next === $i) {
345
+ continue;
346
+ }
347
+
348
+ if ($this->tokens[$next]['code'] === T_WHITESPACE
349
+ || ($this->tokens[$next]['code'] === T_INLINE_HTML
350
+ && trim($this->tokens[$next]['content']) === '')
351
+ ) {
352
+ continue;
353
+ }
354
+
355
+ $lineHasOtherTokens = true;
356
+
357
+ if ($this->tokens[$next]['code'] === T_CLOSE_TAG) {
358
+ continue;
359
+ }
360
+
361
+ $lineHasOtherContent = true;
362
+ break;
363
+ }//end for
364
+ }//end if
365
+
366
+ if (substr($commentTextLower, 0, 9) === 'phpcs:set') {
367
+ // Ignore standards for complete lines that change sniff settings.
368
+ if ($lineHasOtherTokens === false) {
369
+ $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true];
370
+ }
371
+
372
+ $this->tokens[$i]['code'] = T_PHPCS_SET;
373
+ $this->tokens[$i]['type'] = 'T_PHPCS_SET';
374
+ } else if (substr($commentTextLower, 0, 16) === 'phpcs:ignorefile') {
375
+ // The whole file will be ignored, but at least set the correct token.
376
+ $this->tokens[$i]['code'] = T_PHPCS_IGNORE_FILE;
377
+ $this->tokens[$i]['type'] = 'T_PHPCS_IGNORE_FILE';
378
+ } else if (substr($commentTextLower, 0, 13) === 'phpcs:disable') {
379
+ if ($lineHasOtherContent === false) {
380
+ // Completely ignore the comment line.
381
+ $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true];
382
+ }
383
+
384
+ if ($ignoring === null) {
385
+ $ignoring = [];
386
+ }
387
+
388
+ $disabledSniffs = [];
389
+
390
+ $additionalText = substr($commentText, 14);
391
+ if ($additionalText === false) {
392
+ $ignoring = ['.all' => true];
393
+ } else {
394
+ $parts = explode(',', substr($commentText, 13));
395
+ foreach ($parts as $sniffCode) {
396
+ $sniffCode = trim($sniffCode);
397
+ $disabledSniffs[$sniffCode] = true;
398
+ $ignoring[$sniffCode] = true;
399
+
400
+ // This newly disabled sniff might be disabling an existing
401
+ // enabled exception that we are tracking.
402
+ if (isset($ignoring['.except']) === true) {
403
+ foreach (array_keys($ignoring['.except']) as $ignoredSniffCode) {
404
+ if ($ignoredSniffCode === $sniffCode
405
+ || strpos($ignoredSniffCode, $sniffCode.'.') === 0
406
+ ) {
407
+ unset($ignoring['.except'][$ignoredSniffCode]);
408
+ }
409
+ }
410
+
411
+ if (empty($ignoring['.except']) === true) {
412
+ unset($ignoring['.except']);
413
+ }
414
+ }
415
+ }//end foreach
416
+ }//end if
417
+
418
+ $this->tokens[$i]['code'] = T_PHPCS_DISABLE;
419
+ $this->tokens[$i]['type'] = 'T_PHPCS_DISABLE';
420
+ $this->tokens[$i]['sniffCodes'] = $disabledSniffs;
421
+ } else if (substr($commentTextLower, 0, 12) === 'phpcs:enable') {
422
+ if ($ignoring !== null) {
423
+ $enabledSniffs = [];
424
+
425
+ $additionalText = substr($commentText, 13);
426
+ if ($additionalText === false) {
427
+ $ignoring = null;
428
+ } else {
429
+ $parts = explode(',', substr($commentText, 13));
430
+ foreach ($parts as $sniffCode) {
431
+ $sniffCode = trim($sniffCode);
432
+ $enabledSniffs[$sniffCode] = true;
433
+
434
+ // This new enabled sniff might remove previously disabled
435
+ // sniffs if it is actually a standard or category of sniffs.
436
+ foreach (array_keys($ignoring) as $ignoredSniffCode) {
437
+ if ($ignoredSniffCode === $sniffCode
438
+ || strpos($ignoredSniffCode, $sniffCode.'.') === 0
439
+ ) {
440
+ unset($ignoring[$ignoredSniffCode]);
441
+ }
442
+ }
443
+
444
+ // This new enabled sniff might be able to clear up
445
+ // previously enabled sniffs if it is actually a standard or
446
+ // category of sniffs.
447
+ if (isset($ignoring['.except']) === true) {
448
+ foreach (array_keys($ignoring['.except']) as $ignoredSniffCode) {
449
+ if ($ignoredSniffCode === $sniffCode
450
+ || strpos($ignoredSniffCode, $sniffCode.'.') === 0
451
+ ) {
452
+ unset($ignoring['.except'][$ignoredSniffCode]);
453
+ }
454
+ }
455
+ }
456
+ }//end foreach
457
+
458
+ if (empty($ignoring) === true) {
459
+ $ignoring = null;
460
+ } else {
461
+ if (isset($ignoring['.except']) === true) {
462
+ $ignoring['.except'] += $enabledSniffs;
463
+ } else {
464
+ $ignoring['.except'] = $enabledSniffs;
465
+ }
466
+ }
467
+ }//end if
468
+
469
+ if ($lineHasOtherContent === false) {
470
+ // Completely ignore the comment line.
471
+ $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true];
472
+ } else {
473
+ // The comment is on the same line as the code it is ignoring,
474
+ // so respect the new ignore rules.
475
+ $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
476
+ }
477
+
478
+ $this->tokens[$i]['sniffCodes'] = $enabledSniffs;
479
+ }//end if
480
+
481
+ $this->tokens[$i]['code'] = T_PHPCS_ENABLE;
482
+ $this->tokens[$i]['type'] = 'T_PHPCS_ENABLE';
483
+ } else if (substr($commentTextLower, 0, 12) === 'phpcs:ignore') {
484
+ $ignoreRules = [];
485
+
486
+ $additionalText = substr($commentText, 13);
487
+ if ($additionalText === false) {
488
+ $ignoreRules = ['.all' => true];
489
+ } else {
490
+ $parts = explode(',', substr($commentText, 13));
491
+ foreach ($parts as $sniffCode) {
492
+ $ignoreRules[trim($sniffCode)] = true;
493
+ }
494
+ }
495
+
496
+ $this->tokens[$i]['code'] = T_PHPCS_IGNORE;
497
+ $this->tokens[$i]['type'] = 'T_PHPCS_IGNORE';
498
+ $this->tokens[$i]['sniffCodes'] = $ignoreRules;
499
+
500
+ if ($ignoring !== null) {
501
+ $ignoreRules += $ignoring;
502
+ }
503
+
504
+ if ($lineHasOtherContent === false) {
505
+ // Completely ignore the comment line, and set the folllowing
506
+ // line to include the ignore rules we've set.
507
+ $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true];
508
+ $this->ignoredLines[($this->tokens[$i]['line'] + 1)] = $ignoreRules;
509
+ } else {
510
+ // The comment is on the same line as the code it is ignoring,
511
+ // so respect the ignore rules it set.
512
+ $this->ignoredLines[$this->tokens[$i]['line']] = $ignoreRules;
513
+ }
514
+ }//end if
515
+ }//end if
516
+ }//end if
517
+
518
+ if ($ignoring !== null && isset($this->ignoredLines[$this->tokens[$i]['line']]) === false) {
519
+ $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
520
+ }
521
+ }//end for
522
+
523
+ // If annotations are being ignored, we clear out all the ignore rules
524
+ // but leave the annotations tokenized as normal.
525
+ if ($checkAnnotations === false) {
526
+ $this->ignoredLines = [];
527
+ }
528
+
529
+ }//end createPositionMap()
530
+
531
+
532
+ /**
533
+ * Replaces tabs in original token content with spaces.
534
+ *
535
+ * Each tab can represent between 1 and $config->tabWidth spaces,
536
+ * so this cannot be a straight string replace. The original content
537
+ * is placed into an orig_content index and the new token length is also
538
+ * set in the length index.
539
+ *
540
+ * @param array $token The token to replace tabs inside.
541
+ * @param string $prefix The character to use to represent the start of a tab.
542
+ * @param string $padding The character to use to represent the end of a tab.
543
+ * @param int $tabWidth The number of spaces each tab represents.
544
+ *
545
+ * @return void
546
+ */
547
+ public function replaceTabsInToken(&$token, $prefix=' ', $padding=' ', $tabWidth=null)
548
+ {
549
+ $checkEncoding = false;
550
+ if (function_exists('iconv_strlen') === true) {
551
+ $checkEncoding = true;
552
+ }
553
+
554
+ $currColumn = $token['column'];
555
+ if ($tabWidth === null) {
556
+ $tabWidth = $this->config->tabWidth;
557
+ if ($tabWidth === 0) {
558
+ $tabWidth = 1;
559
+ }
560
+ }
561
+
562
+ if (rtrim($token['content'], "\t") === '') {
563
+ // String only contains tabs, so we can shortcut the process.
564
+ $numTabs = strlen($token['content']);
565
+
566
+ $firstTabSize = ($tabWidth - (($currColumn - 1) % $tabWidth));
567
+ $length = ($firstTabSize + ($tabWidth * ($numTabs - 1)));
568
+ $newContent = $prefix.str_repeat($padding, ($length - 1));
569
+ } else {
570
+ // We need to determine the length of each tab.
571
+ $tabs = explode("\t", $token['content']);
572
+
573
+ $numTabs = (count($tabs) - 1);
574
+ $tabNum = 0;
575
+ $newContent = '';
576
+ $length = 0;
577
+
578
+ foreach ($tabs as $content) {
579
+ if ($content !== '') {
580
+ $newContent .= $content;
581
+ if ($checkEncoding === true) {
582
+ // Not using the default encoding, so take a bit more care.
583
+ $oldLevel = error_reporting();
584
+ error_reporting(0);
585
+ $contentLength = iconv_strlen($content, $this->config->encoding);
586
+ error_reporting($oldLevel);
587
+ if ($contentLength === false) {
588
+ // String contained invalid characters, so revert to default.
589
+ $contentLength = strlen($content);
590
+ }
591
+ } else {
592
+ $contentLength = strlen($content);
593
+ }
594
+
595
+ $currColumn += $contentLength;
596
+ $length += $contentLength;
597
+ }
598
+
599
+ // The last piece of content does not have a tab after it.
600
+ if ($tabNum === $numTabs) {
601
+ break;
602
+ }
603
+
604
+ // Process the tab that comes after the content.
605
+ $lastCurrColumn = $currColumn;
606
+ $tabNum++;
607
+
608
+ // Move the pointer to the next tab stop.
609
+ if (($currColumn % $tabWidth) === 0) {
610
+ // This is the first tab, and we are already at a
611
+ // tab stop, so this tab counts as a single space.
612
+ $currColumn++;
613
+ } else {
614
+ $currColumn++;
615
+ while (($currColumn % $tabWidth) !== 0) {
616
+ $currColumn++;
617
+ }
618
+
619
+ $currColumn++;
620
+ }
621
+
622
+ $length += ($currColumn - $lastCurrColumn);
623
+ $newContent .= $prefix.str_repeat($padding, ($currColumn - $lastCurrColumn - 1));
624
+ }//end foreach
625
+ }//end if
626
+
627
+ $token['orig_content'] = $token['content'];
628
+ $token['content'] = $newContent;
629
+ $token['length'] = $length;
630
+
631
+ }//end replaceTabsInToken()
632
+
633
+
634
+ /**
635
+ * Creates a map of brackets positions.
636
+ *
637
+ * @return void
638
+ */
639
+ private function createTokenMap()
640
+ {
641
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
642
+ echo "\t*** START TOKEN MAP ***".PHP_EOL;
643
+ }
644
+
645
+ $squareOpeners = [];
646
+ $curlyOpeners = [];
647
+ $this->numTokens = count($this->tokens);
648
+
649
+ $openers = [];
650
+ $openOwner = null;
651
+
652
+ for ($i = 0; $i < $this->numTokens; $i++) {
653
+ /*
654
+ Parenthesis mapping.
655
+ */
656
+
657
+ if (isset(Util\Tokens::$parenthesisOpeners[$this->tokens[$i]['code']]) === true) {
658
+ $this->tokens[$i]['parenthesis_opener'] = null;
659
+ $this->tokens[$i]['parenthesis_closer'] = null;
660
+ $this->tokens[$i]['parenthesis_owner'] = $i;
661
+ $openOwner = $i;
662
+ } else if ($this->tokens[$i]['code'] === T_OPEN_PARENTHESIS) {
663
+ $openers[] = $i;
664
+ $this->tokens[$i]['parenthesis_opener'] = $i;
665
+ if ($openOwner !== null) {
666
+ $this->tokens[$openOwner]['parenthesis_opener'] = $i;
667
+ $this->tokens[$i]['parenthesis_owner'] = $openOwner;
668
+ $openOwner = null;
669
+ }
670
+ } else if ($this->tokens[$i]['code'] === T_CLOSE_PARENTHESIS) {
671
+ // Did we set an owner for this set of parenthesis?
672
+ $numOpeners = count($openers);
673
+ if ($numOpeners !== 0) {
674
+ $opener = array_pop($openers);
675
+ if (isset($this->tokens[$opener]['parenthesis_owner']) === true) {
676
+ $owner = $this->tokens[$opener]['parenthesis_owner'];
677
+
678
+ $this->tokens[$owner]['parenthesis_closer'] = $i;
679
+ $this->tokens[$i]['parenthesis_owner'] = $owner;
680
+ }
681
+
682
+ $this->tokens[$i]['parenthesis_opener'] = $opener;
683
+ $this->tokens[$i]['parenthesis_closer'] = $i;
684
+ $this->tokens[$opener]['parenthesis_closer'] = $i;
685
+ }
686
+ }//end if
687
+
688
+ /*
689
+ Bracket mapping.
690
+ */
691
+
692
+ switch ($this->tokens[$i]['code']) {
693
+ case T_OPEN_SQUARE_BRACKET:
694
+ $squareOpeners[] = $i;
695
+
696
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
697
+ echo str_repeat("\t", count($squareOpeners));
698
+ echo str_repeat("\t", count($curlyOpeners));
699
+ echo "=> Found square bracket opener at $i".PHP_EOL;
700
+ }
701
+ break;
702
+ case T_OPEN_CURLY_BRACKET:
703
+ if (isset($this->tokens[$i]['scope_closer']) === false) {
704
+ $curlyOpeners[] = $i;
705
+
706
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
707
+ echo str_repeat("\t", count($squareOpeners));
708
+ echo str_repeat("\t", count($curlyOpeners));
709
+ echo "=> Found curly bracket opener at $i".PHP_EOL;
710
+ }
711
+ }
712
+ break;
713
+ case T_CLOSE_SQUARE_BRACKET:
714
+ if (empty($squareOpeners) === false) {
715
+ $opener = array_pop($squareOpeners);
716
+ $this->tokens[$i]['bracket_opener'] = $opener;
717
+ $this->tokens[$i]['bracket_closer'] = $i;
718
+ $this->tokens[$opener]['bracket_opener'] = $opener;
719
+ $this->tokens[$opener]['bracket_closer'] = $i;
720
+
721
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
722
+ echo str_repeat("\t", count($squareOpeners));
723
+ echo str_repeat("\t", count($curlyOpeners));
724
+ echo "\t=> Found square bracket closer at $i for $opener".PHP_EOL;
725
+ }
726
+ }
727
+ break;
728
+ case T_CLOSE_CURLY_BRACKET:
729
+ if (empty($curlyOpeners) === false
730
+ && isset($this->tokens[$i]['scope_opener']) === false
731
+ ) {
732
+ $opener = array_pop($curlyOpeners);
733
+ $this->tokens[$i]['bracket_opener'] = $opener;
734
+ $this->tokens[$i]['bracket_closer'] = $i;
735
+ $this->tokens[$opener]['bracket_opener'] = $opener;
736
+ $this->tokens[$opener]['bracket_closer'] = $i;
737
+
738
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
739
+ echo str_repeat("\t", count($squareOpeners));
740
+ echo str_repeat("\t", count($curlyOpeners));
741
+ echo "\t=> Found curly bracket closer at $i for $opener".PHP_EOL;
742
+ }
743
+ }
744
+ break;
745
+ default:
746
+ continue 2;
747
+ }//end switch
748
+ }//end for
749
+
750
+ // Cleanup for any openers that we didn't find closers for.
751
+ // This typically means there was a syntax error breaking things.
752
+ foreach ($openers as $opener) {
753
+ unset($this->tokens[$opener]['parenthesis_opener']);
754
+ unset($this->tokens[$opener]['parenthesis_owner']);
755
+ }
756
+
757
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
758
+ echo "\t*** END TOKEN MAP ***".PHP_EOL;
759
+ }
760
+
761
+ }//end createTokenMap()
762
+
763
+
764
+ /**
765
+ * Creates a map for the parenthesis tokens that surround other tokens.
766
+ *
767
+ * @return void
768
+ */
769
+ private function createParenthesisNestingMap()
770
+ {
771
+ $map = [];
772
+ for ($i = 0; $i < $this->numTokens; $i++) {
773
+ if (isset($this->tokens[$i]['parenthesis_opener']) === true
774
+ && $i === $this->tokens[$i]['parenthesis_opener']
775
+ ) {
776
+ if (empty($map) === false) {
777
+ $this->tokens[$i]['nested_parenthesis'] = $map;
778
+ }
779
+
780
+ if (isset($this->tokens[$i]['parenthesis_closer']) === true) {
781
+ $map[$this->tokens[$i]['parenthesis_opener']]
782
+ = $this->tokens[$i]['parenthesis_closer'];
783
+ }
784
+ } else if (isset($this->tokens[$i]['parenthesis_closer']) === true
785
+ && $i === $this->tokens[$i]['parenthesis_closer']
786
+ ) {
787
+ array_pop($map);
788
+ if (empty($map) === false) {
789
+ $this->tokens[$i]['nested_parenthesis'] = $map;
790
+ }
791
+ } else {
792
+ if (empty($map) === false) {
793
+ $this->tokens[$i]['nested_parenthesis'] = $map;
794
+ }
795
+ }//end if
796
+ }//end for
797
+
798
+ }//end createParenthesisNestingMap()
799
+
800
+
801
+ /**
802
+ * Creates a scope map of tokens that open scopes.
803
+ *
804
+ * @return void
805
+ * @see recurseScopeMap()
806
+ */
807
+ private function createScopeMap()
808
+ {
809
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
810
+ echo "\t*** START SCOPE MAP ***".PHP_EOL;
811
+ }
812
+
813
+ for ($i = 0; $i < $this->numTokens; $i++) {
814
+ // Check to see if the current token starts a new scope.
815
+ if (isset($this->scopeOpeners[$this->tokens[$i]['code']]) === true) {
816
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
817
+ $type = $this->tokens[$i]['type'];
818
+ $content = Util\Common::prepareForOutput($this->tokens[$i]['content']);
819
+ echo "\tStart scope map at $i:$type => $content".PHP_EOL;
820
+ }
821
+
822
+ if (isset($this->tokens[$i]['scope_condition']) === true) {
823
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
824
+ echo "\t* already processed, skipping *".PHP_EOL;
825
+ }
826
+
827
+ continue;
828
+ }
829
+
830
+ $i = $this->recurseScopeMap($i);
831
+ }//end if
832
+ }//end for
833
+
834
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
835
+ echo "\t*** END SCOPE MAP ***".PHP_EOL;
836
+ }
837
+
838
+ }//end createScopeMap()
839
+
840
+
841
+ /**
842
+ * Recurses though the scope openers to build a scope map.
843
+ *
844
+ * @param int $stackPtr The position in the stack of the token that
845
+ * opened the scope (eg. an IF token or FOR token).
846
+ * @param int $depth How many scope levels down we are.
847
+ * @param int $ignore How many curly braces we are ignoring.
848
+ *
849
+ * @return int The position in the stack that closed the scope.
850
+ */
851
+ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0)
852
+ {
853
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
854
+ echo str_repeat("\t", $depth);
855
+ echo "=> Begin scope map recursion at token $stackPtr with depth $depth".PHP_EOL;
856
+ }
857
+
858
+ $opener = null;
859
+ $currType = $this->tokens[$stackPtr]['code'];
860
+ $startLine = $this->tokens[$stackPtr]['line'];
861
+
862
+ // We will need this to restore the value if we end up
863
+ // returning a token ID that causes our calling function to go back
864
+ // over already ignored braces.
865
+ $originalIgnore = $ignore;
866
+
867
+ // If the start token for this scope opener is the same as
868
+ // the scope token, we have already found our opener.
869
+ if (isset($this->scopeOpeners[$currType]['start'][$currType]) === true) {
870
+ $opener = $stackPtr;
871
+ }
872
+
873
+ for ($i = ($stackPtr + 1); $i < $this->numTokens; $i++) {
874
+ $tokenType = $this->tokens[$i]['code'];
875
+
876
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
877
+ $type = $this->tokens[$i]['type'];
878
+ $line = $this->tokens[$i]['line'];
879
+ $content = Util\Common::prepareForOutput($this->tokens[$i]['content']);
880
+
881
+ echo str_repeat("\t", $depth);
882
+ echo "Process token $i on line $line [";
883
+ if ($opener !== null) {
884
+ echo "opener:$opener;";
885
+ }
886
+
887
+ if ($ignore > 0) {
888
+ echo "ignore=$ignore;";
889
+ }
890
+
891
+ echo "]: $type => $content".PHP_EOL;
892
+ }//end if
893
+
894
+ // Very special case for IF statements in PHP that can be defined without
895
+ // scope tokens. E.g., if (1) 1; 1 ? (1 ? 1 : 1) : 1;
896
+ // If an IF statement below this one has an opener but no
897
+ // keyword, the opener will be incorrectly assigned to this IF statement.
898
+ // The same case also applies to USE statements, which don't have to have
899
+ // openers, so a following USE statement can cause an incorrect brace match.
900
+ if (($currType === T_IF || $currType === T_ELSE || $currType === T_USE)
901
+ && $opener === null
902
+ && ($this->tokens[$i]['code'] === T_SEMICOLON
903
+ || $this->tokens[$i]['code'] === T_CLOSE_TAG)
904
+ ) {
905
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
906
+ $type = $this->tokens[$stackPtr]['type'];
907
+ echo str_repeat("\t", $depth);
908
+ if ($this->tokens[$i]['code'] === T_SEMICOLON) {
909
+ $closerType = 'semicolon';
910
+ } else {
911
+ $closerType = 'close tag';
912
+ }
913
+
914
+ echo "=> Found $closerType before scope opener for $stackPtr:$type, bailing".PHP_EOL;
915
+ }
916
+
917
+ return $i;
918
+ }
919
+
920
+ // Special case for PHP control structures that have no braces.
921
+ // If we find a curly brace closer before we find the opener,
922
+ // we're not going to find an opener. That closer probably belongs to
923
+ // a control structure higher up.
924
+ if ($opener === null
925
+ && $ignore === 0
926
+ && $tokenType === T_CLOSE_CURLY_BRACKET
927
+ && isset($this->scopeOpeners[$currType]['end'][$tokenType]) === true
928
+ ) {
929
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
930
+ $type = $this->tokens[$stackPtr]['type'];
931
+ echo str_repeat("\t", $depth);
932
+ echo "=> Found curly brace closer before scope opener for $stackPtr:$type, bailing".PHP_EOL;
933
+ }
934
+
935
+ return ($i - 1);
936
+ }
937
+
938
+ if ($opener !== null
939
+ && (isset($this->tokens[$i]['scope_opener']) === false
940
+ || $this->scopeOpeners[$this->tokens[$stackPtr]['code']]['shared'] === true)
941
+ && isset($this->scopeOpeners[$currType]['end'][$tokenType]) === true
942
+ ) {
943
+ if ($ignore > 0 && $tokenType === T_CLOSE_CURLY_BRACKET) {
944
+ // The last opening bracket must have been for a string
945
+ // offset or alike, so let's ignore it.
946
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
947
+ echo str_repeat("\t", $depth);
948
+ echo '* finished ignoring curly brace *'.PHP_EOL;
949
+ }
950
+
951
+ $ignore--;
952
+ continue;
953
+ } else if ($this->tokens[$opener]['code'] === T_OPEN_CURLY_BRACKET
954
+ && $tokenType !== T_CLOSE_CURLY_BRACKET
955
+ ) {
956
+ // The opener is a curly bracket so the closer must be a curly bracket as well.
957
+ // We ignore this closer to handle cases such as T_ELSE or T_ELSEIF being considered
958
+ // a closer of T_IF when it should not.
959
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
960
+ $type = $this->tokens[$stackPtr]['type'];
961
+ echo str_repeat("\t", $depth);
962
+ echo "=> Ignoring non-curly scope closer for $stackPtr:$type".PHP_EOL;
963
+ }
964
+ } else {
965
+ $scopeCloser = $i;
966
+ $todo = [
967
+ $stackPtr,
968
+ $opener,
969
+ ];
970
+
971
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
972
+ $type = $this->tokens[$stackPtr]['type'];
973
+ $closerType = $this->tokens[$scopeCloser]['type'];
974
+ echo str_repeat("\t", $depth);
975
+ echo "=> Found scope closer ($scopeCloser:$closerType) for $stackPtr:$type".PHP_EOL;
976
+ }
977
+
978
+ $validCloser = true;
979
+ if (($this->tokens[$stackPtr]['code'] === T_IF || $this->tokens[$stackPtr]['code'] === T_ELSEIF)
980
+ && ($tokenType === T_ELSE || $tokenType === T_ELSEIF)
981
+ ) {
982
+ // To be a closer, this token must have an opener.
983
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
984
+ echo str_repeat("\t", $depth);
985
+ echo "* closer needs to be tested *".PHP_EOL;
986
+ }
987
+
988
+ $i = self::recurseScopeMap($i, ($depth + 1), $ignore);
989
+
990
+ if (isset($this->tokens[$scopeCloser]['scope_opener']) === false) {
991
+ $validCloser = false;
992
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
993
+ echo str_repeat("\t", $depth);
994
+ echo "* closer is not valid (no opener found) *".PHP_EOL;
995
+ }
996
+ } else if ($this->tokens[$this->tokens[$scopeCloser]['scope_opener']]['code'] !== $this->tokens[$opener]['code']) {
997
+ $validCloser = false;
998
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
999
+ echo str_repeat("\t", $depth);
1000
+ $type = $this->tokens[$this->tokens[$scopeCloser]['scope_opener']]['type'];
1001
+ $openerType = $this->tokens[$opener]['type'];
1002
+ echo "* closer is not valid (mismatched opener type; $type != $openerType) *".PHP_EOL;
1003
+ }
1004
+ } else if (PHP_CODESNIFFER_VERBOSITY > 1) {
1005
+ echo str_repeat("\t", $depth);
1006
+ echo "* closer was valid *".PHP_EOL;
1007
+ }
1008
+ } else {
1009
+ // The closer was not processed, so we need to
1010
+ // complete that token as well.
1011
+ $todo[] = $scopeCloser;
1012
+ }//end if
1013
+
1014
+ if ($validCloser === true) {
1015
+ foreach ($todo as $token) {
1016
+ $this->tokens[$token]['scope_condition'] = $stackPtr;
1017
+ $this->tokens[$token]['scope_opener'] = $opener;
1018
+ $this->tokens[$token]['scope_closer'] = $scopeCloser;
1019
+ }
1020
+
1021
+ if ($this->scopeOpeners[$this->tokens[$stackPtr]['code']]['shared'] === true) {
1022
+ // As we are going back to where we started originally, restore
1023
+ // the ignore value back to its original value.
1024
+ $ignore = $originalIgnore;
1025
+ return $opener;
1026
+ } else if ($scopeCloser === $i
1027
+ && isset($this->scopeOpeners[$tokenType]) === true
1028
+ ) {
1029
+ // Unset scope_condition here or else the token will appear to have
1030
+ // already been processed, and it will be skipped. Normally we want that,
1031
+ // but in this case, the token is both a closer and an opener, so
1032
+ // it needs to act like an opener. This is also why we return the
1033
+ // token before this one; so the closer has a chance to be processed
1034
+ // a second time, but as an opener.
1035
+ unset($this->tokens[$scopeCloser]['scope_condition']);
1036
+ return ($i - 1);
1037
+ } else {
1038
+ return $i;
1039
+ }
1040
+ } else {
1041
+ continue;
1042
+ }//end if
1043
+ }//end if
1044
+ }//end if
1045
+
1046
+ // Is this an opening condition ?
1047
+ if (isset($this->scopeOpeners[$tokenType]) === true) {
1048
+ if ($opener === null) {
1049
+ if ($tokenType === T_USE) {
1050
+ // PHP use keywords are special because they can be
1051
+ // used as blocks but also inline in function definitions.
1052
+ // So if we find them nested inside another opener, just skip them.
1053
+ continue;
1054
+ }
1055
+
1056
+ if ($tokenType === T_FUNCTION
1057
+ && $this->tokens[$stackPtr]['code'] !== T_FUNCTION
1058
+ ) {
1059
+ // Probably a closure, so process it manually.
1060
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1061
+ $type = $this->tokens[$stackPtr]['type'];
1062
+ echo str_repeat("\t", $depth);
1063
+ echo "=> Found function before scope opener for $stackPtr:$type, processing manually".PHP_EOL;
1064
+ }
1065
+
1066
+ if (isset($this->tokens[$i]['scope_closer']) === true) {
1067
+ // We've already processed this closure.
1068
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1069
+ echo str_repeat("\t", $depth);
1070
+ echo '* already processed, skipping *'.PHP_EOL;
1071
+ }
1072
+
1073
+ $i = $this->tokens[$i]['scope_closer'];
1074
+ continue;
1075
+ }
1076
+
1077
+ $i = self::recurseScopeMap($i, ($depth + 1), $ignore);
1078
+ continue;
1079
+ }//end if
1080
+
1081
+ if ($tokenType === T_CLASS) {
1082
+ // Probably an anonymous class inside another anonymous class,
1083
+ // so process it manually.
1084
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1085
+ $type = $this->tokens[$stackPtr]['type'];
1086
+ echo str_repeat("\t", $depth);
1087
+ echo "=> Found class before scope opener for $stackPtr:$type, processing manually".PHP_EOL;
1088
+ }
1089
+
1090
+ if (isset($this->tokens[$i]['scope_closer']) === true) {
1091
+ // We've already processed this anon class.
1092
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1093
+ echo str_repeat("\t", $depth);
1094
+ echo '* already processed, skipping *'.PHP_EOL;
1095
+ }
1096
+
1097
+ $i = $this->tokens[$i]['scope_closer'];
1098
+ continue;
1099
+ }
1100
+
1101
+ $i = self::recurseScopeMap($i, ($depth + 1), $ignore);
1102
+ continue;
1103
+ }//end if
1104
+
1105
+ // Found another opening condition but still haven't
1106
+ // found our opener, so we are never going to find one.
1107
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1108
+ $type = $this->tokens[$stackPtr]['type'];
1109
+ echo str_repeat("\t", $depth);
1110
+ echo "=> Found new opening condition before scope opener for $stackPtr:$type, ";
1111
+ }
1112
+
1113
+ if (($this->tokens[$stackPtr]['code'] === T_IF
1114
+ || $this->tokens[$stackPtr]['code'] === T_ELSEIF
1115
+ || $this->tokens[$stackPtr]['code'] === T_ELSE)
1116
+ && ($this->tokens[$i]['code'] === T_ELSE
1117
+ || $this->tokens[$i]['code'] === T_ELSEIF)
1118
+ ) {
1119
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1120
+ echo "continuing".PHP_EOL;
1121
+ }
1122
+
1123
+ return ($i - 1);
1124
+ } else {
1125
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1126
+ echo "backtracking".PHP_EOL;
1127
+ }
1128
+
1129
+ return $stackPtr;
1130
+ }
1131
+ }//end if
1132
+
1133
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1134
+ echo str_repeat("\t", $depth);
1135
+ echo '* token is an opening condition *'.PHP_EOL;
1136
+ }
1137
+
1138
+ $isShared = ($this->scopeOpeners[$tokenType]['shared'] === true);
1139
+
1140
+ if (isset($this->tokens[$i]['scope_condition']) === true) {
1141
+ // We've been here before.
1142
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1143
+ echo str_repeat("\t", $depth);
1144
+ echo '* already processed, skipping *'.PHP_EOL;
1145
+ }
1146
+
1147
+ if ($isShared === false
1148
+ && isset($this->tokens[$i]['scope_closer']) === true
1149
+ ) {
1150
+ $i = $this->tokens[$i]['scope_closer'];
1151
+ }
1152
+
1153
+ continue;
1154
+ } else if ($currType === $tokenType
1155
+ && $isShared === false
1156
+ && $opener === null
1157
+ ) {
1158
+ // We haven't yet found our opener, but we have found another
1159
+ // scope opener which is the same type as us, and we don't
1160
+ // share openers, so we will never find one.
1161
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1162
+ echo str_repeat("\t", $depth);
1163
+ echo '* it was another token\'s opener, bailing *'.PHP_EOL;
1164
+ }
1165
+
1166
+ return $stackPtr;
1167
+ } else {
1168
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1169
+ echo str_repeat("\t", $depth);
1170
+ echo '* searching for opener *'.PHP_EOL;
1171
+ }
1172
+
1173
+ if (isset($this->scopeOpeners[$tokenType]['end'][T_CLOSE_CURLY_BRACKET]) === true) {
1174
+ $oldIgnore = $ignore;
1175
+ $ignore = 0;
1176
+ }
1177
+
1178
+ // PHP has a max nesting level for functions. Stop before we hit that limit
1179
+ // because too many loops means we've run into trouble anyway.
1180
+ if ($depth > 50) {
1181
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1182
+ echo str_repeat("\t", $depth);
1183
+ echo '* reached maximum nesting level; aborting *'.PHP_EOL;
1184
+ }
1185
+
1186
+ throw new RuntimeException('Maximum nesting level reached; file could not be processed');
1187
+ }
1188
+
1189
+ $oldDepth = $depth;
1190
+ if ($isShared === true
1191
+ && isset($this->scopeOpeners[$tokenType]['with'][$currType]) === true
1192
+ ) {
1193
+ // Don't allow the depth to increment because this is
1194
+ // possibly not a true nesting if we are sharing our closer.
1195
+ // This can happen, for example, when a SWITCH has a large
1196
+ // number of CASE statements with the same shared BREAK.
1197
+ $depth--;
1198
+ }
1199
+
1200
+ $i = self::recurseScopeMap($i, ($depth + 1), $ignore);
1201
+ $depth = $oldDepth;
1202
+
1203
+ if (isset($this->scopeOpeners[$tokenType]['end'][T_CLOSE_CURLY_BRACKET]) === true) {
1204
+ $ignore = $oldIgnore;
1205
+ }
1206
+ }//end if
1207
+ }//end if
1208
+
1209
+ if (isset($this->scopeOpeners[$currType]['start'][$tokenType]) === true
1210
+ && $opener === null
1211
+ ) {
1212
+ if ($tokenType === T_OPEN_CURLY_BRACKET) {
1213
+ if (isset($this->tokens[$stackPtr]['parenthesis_closer']) === true
1214
+ && $i < $this->tokens[$stackPtr]['parenthesis_closer']
1215
+ ) {
1216
+ // We found a curly brace inside the condition of the
1217
+ // current scope opener, so it must be a string offset.
1218
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1219
+ echo str_repeat("\t", $depth);
1220
+ echo '* ignoring curly brace inside condition *'.PHP_EOL;
1221
+ }
1222
+
1223
+ $ignore++;
1224
+ } else {
1225
+ // Make sure this is actually an opener and not a
1226
+ // string offset (e.g., $var{0}).
1227
+ for ($x = ($i - 1); $x > 0; $x--) {
1228
+ if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) {
1229
+ continue;
1230
+ } else {
1231
+ // If the first non-whitespace/comment token looks like this
1232
+ // brace is a string offset, or this brace is mid-way through
1233
+ // a new statement, it isn't a scope opener.
1234
+ $disallowed = Util\Tokens::$assignmentTokens;
1235
+ $disallowed += [
1236
+ T_DOLLAR => true,
1237
+ T_VARIABLE => true,
1238
+ T_OBJECT_OPERATOR => true,
1239
+ T_COMMA => true,
1240
+ T_OPEN_PARENTHESIS => true,
1241
+ ];
1242
+
1243
+ if (isset($disallowed[$this->tokens[$x]['code']]) === true) {
1244
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1245
+ echo str_repeat("\t", $depth);
1246
+ echo '* ignoring curly brace *'.PHP_EOL;
1247
+ }
1248
+
1249
+ $ignore++;
1250
+ }
1251
+
1252
+ break;
1253
+ }//end if
1254
+ }//end for
1255
+ }//end if
1256
+ }//end if
1257
+
1258
+ if ($ignore === 0 || $tokenType !== T_OPEN_CURLY_BRACKET) {
1259
+ // We found the opening scope token for $currType.
1260
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1261
+ $type = $this->tokens[$stackPtr]['type'];
1262
+ echo str_repeat("\t", $depth);
1263
+ echo "=> Found scope opener for $stackPtr:$type".PHP_EOL;
1264
+ }
1265
+
1266
+ $opener = $i;
1267
+ }
1268
+ } else if ($tokenType === T_OPEN_PARENTHESIS) {
1269
+ if (isset($this->tokens[$i]['parenthesis_owner']) === true) {
1270
+ $owner = $this->tokens[$i]['parenthesis_owner'];
1271
+ if (isset(Util\Tokens::$scopeOpeners[$this->tokens[$owner]['code']]) === true
1272
+ && isset($this->tokens[$i]['parenthesis_closer']) === true
1273
+ ) {
1274
+ // If we get into here, then we opened a parenthesis for
1275
+ // a scope (eg. an if or else if) so we need to update the
1276
+ // start of the line so that when we check to see
1277
+ // if the closing parenthesis is more than 3 lines away from
1278
+ // the statement, we check from the closing parenthesis.
1279
+ $startLine = $this->tokens[$this->tokens[$i]['parenthesis_closer']]['line'];
1280
+ }
1281
+ }
1282
+ } else if ($tokenType === T_OPEN_CURLY_BRACKET && $opener !== null) {
1283
+ // We opened something that we don't have a scope opener for.
1284
+ // Examples of this are curly brackets for string offsets etc.
1285
+ // We want to ignore this so that we don't have an invalid scope
1286
+ // map.
1287
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1288
+ echo str_repeat("\t", $depth);
1289
+ echo '* ignoring curly brace *'.PHP_EOL;
1290
+ }
1291
+
1292
+ $ignore++;
1293
+ } else if ($tokenType === T_CLOSE_CURLY_BRACKET && $ignore > 0) {
1294
+ // We found the end token for the opener we were ignoring.
1295
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1296
+ echo str_repeat("\t", $depth);
1297
+ echo '* finished ignoring curly brace *'.PHP_EOL;
1298
+ }
1299
+
1300
+ $ignore--;
1301
+ } else if ($opener === null
1302
+ && isset($this->scopeOpeners[$currType]) === true
1303
+ ) {
1304
+ // If we still haven't found the opener after 30 lines,
1305
+ // we're not going to find it, unless we know it requires
1306
+ // an opener (in which case we better keep looking) or the last
1307
+ // token was empty (in which case we'll just confirm there is
1308
+ // more code in this file and not just a big comment).
1309
+ if ($this->tokens[$i]['line'] >= ($startLine + 30)
1310
+ && isset(Util\Tokens::$emptyTokens[$this->tokens[($i - 1)]['code']]) === false
1311
+ ) {
1312
+ if ($this->scopeOpeners[$currType]['strict'] === true) {
1313
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1314
+ $type = $this->tokens[$stackPtr]['type'];
1315
+ $lines = ($this->tokens[$i]['line'] - $startLine);
1316
+ echo str_repeat("\t", $depth);
1317
+ echo "=> Still looking for $stackPtr:$type scope opener after $lines lines".PHP_EOL;
1318
+ }
1319
+ } else {
1320
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1321
+ $type = $this->tokens[$stackPtr]['type'];
1322
+ echo str_repeat("\t", $depth);
1323
+ echo "=> Couldn't find scope opener for $stackPtr:$type, bailing".PHP_EOL;
1324
+ }
1325
+
1326
+ return $stackPtr;
1327
+ }
1328
+ }
1329
+ } else if ($opener !== null
1330
+ && $tokenType !== T_BREAK
1331
+ && isset($this->endScopeTokens[$tokenType]) === true
1332
+ ) {
1333
+ if (isset($this->tokens[$i]['scope_condition']) === false) {
1334
+ if ($ignore > 0) {
1335
+ // We found the end token for the opener we were ignoring.
1336
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1337
+ echo str_repeat("\t", $depth);
1338
+ echo '* finished ignoring curly brace *'.PHP_EOL;
1339
+ }
1340
+
1341
+ $ignore--;
1342
+ } else {
1343
+ // We found a token that closes the scope but it doesn't
1344
+ // have a condition, so it belongs to another token and
1345
+ // our token doesn't have a closer, so pretend this is
1346
+ // the closer.
1347
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1348
+ $type = $this->tokens[$stackPtr]['type'];
1349
+ echo str_repeat("\t", $depth);
1350
+ echo "=> Found (unexpected) scope closer for $stackPtr:$type".PHP_EOL;
1351
+ }
1352
+
1353
+ foreach ([$stackPtr, $opener] as $token) {
1354
+ $this->tokens[$token]['scope_condition'] = $stackPtr;
1355
+ $this->tokens[$token]['scope_opener'] = $opener;
1356
+ $this->tokens[$token]['scope_closer'] = $i;
1357
+ }
1358
+
1359
+ return ($i - 1);
1360
+ }//end if
1361
+ }//end if
1362
+ }//end if
1363
+ }//end for
1364
+
1365
+ return $stackPtr;
1366
+
1367
+ }//end recurseScopeMap()
1368
+
1369
+
1370
+ /**
1371
+ * Constructs the level map.
1372
+ *
1373
+ * The level map adds a 'level' index to each token which indicates the
1374
+ * depth that a token within a set of scope blocks. It also adds a
1375
+ * 'conditions' index which is an array of the scope conditions that opened
1376
+ * each of the scopes - position 0 being the first scope opener.
1377
+ *
1378
+ * @return void
1379
+ */
1380
+ private function createLevelMap()
1381
+ {
1382
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1383
+ echo "\t*** START LEVEL MAP ***".PHP_EOL;
1384
+ }
1385
+
1386
+ $this->numTokens = count($this->tokens);
1387
+ $level = 0;
1388
+ $conditions = [];
1389
+ $lastOpener = null;
1390
+ $openers = [];
1391
+
1392
+ for ($i = 0; $i < $this->numTokens; $i++) {
1393
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1394
+ $type = $this->tokens[$i]['type'];
1395
+ $line = $this->tokens[$i]['line'];
1396
+ $len = $this->tokens[$i]['length'];
1397
+ $col = $this->tokens[$i]['column'];
1398
+
1399
+ $content = Util\Common::prepareForOutput($this->tokens[$i]['content']);
1400
+
1401
+ echo str_repeat("\t", ($level + 1));
1402
+ echo "Process token $i on line $line [col:$col;len:$len;lvl:$level;";
1403
+ if (empty($conditions) !== true) {
1404
+ $condString = 'conds;';
1405
+ foreach ($conditions as $condition) {
1406
+ $condString .= Util\Tokens::tokenName($condition).',';
1407
+ }
1408
+
1409
+ echo rtrim($condString, ',').';';
1410
+ }
1411
+
1412
+ echo "]: $type => $content".PHP_EOL;
1413
+ }//end if
1414
+
1415
+ $this->tokens[$i]['level'] = $level;
1416
+ $this->tokens[$i]['conditions'] = $conditions;
1417
+
1418
+ if (isset($this->tokens[$i]['scope_condition']) === true) {
1419
+ // Check to see if this token opened the scope.
1420
+ if ($this->tokens[$i]['scope_opener'] === $i) {
1421
+ $stackPtr = $this->tokens[$i]['scope_condition'];
1422
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1423
+ $type = $this->tokens[$stackPtr]['type'];
1424
+ echo str_repeat("\t", ($level + 1));
1425
+ echo "=> Found scope opener for $stackPtr:$type".PHP_EOL;
1426
+ }
1427
+
1428
+ $stackPtr = $this->tokens[$i]['scope_condition'];
1429
+
1430
+ // If we find a scope opener that has a shared closer,
1431
+ // then we need to go back over the condition map that we
1432
+ // just created and fix ourselves as we just added some
1433
+ // conditions where there was none. This happens for T_CASE
1434
+ // statements that are using the same break statement.
1435
+ if ($lastOpener !== null && $this->tokens[$lastOpener]['scope_closer'] === $this->tokens[$i]['scope_closer']) {
1436
+ // This opener shares its closer with the previous opener,
1437
+ // but we still need to check if the two openers share their
1438
+ // closer with each other directly (like CASE and DEFAULT)
1439
+ // or if they are just sharing because one doesn't have a
1440
+ // closer (like CASE with no BREAK using a SWITCHes closer).
1441
+ $thisType = $this->tokens[$this->tokens[$i]['scope_condition']]['code'];
1442
+ $opener = $this->tokens[$lastOpener]['scope_condition'];
1443
+
1444
+ $isShared = isset($this->scopeOpeners[$thisType]['with'][$this->tokens[$opener]['code']]);
1445
+
1446
+ reset($this->scopeOpeners[$thisType]['end']);
1447
+ reset($this->scopeOpeners[$this->tokens[$opener]['code']]['end']);
1448
+ $sameEnd = (current($this->scopeOpeners[$thisType]['end']) === current($this->scopeOpeners[$this->tokens[$opener]['code']]['end']));
1449
+
1450
+ if ($isShared === true && $sameEnd === true) {
1451
+ $badToken = $opener;
1452
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1453
+ $type = $this->tokens[$badToken]['type'];
1454
+ echo str_repeat("\t", ($level + 1));
1455
+ echo "* shared closer, cleaning up $badToken:$type *".PHP_EOL;
1456
+ }
1457
+
1458
+ for ($x = $this->tokens[$i]['scope_condition']; $x <= $i; $x++) {
1459
+ $oldConditions = $this->tokens[$x]['conditions'];
1460
+ $oldLevel = $this->tokens[$x]['level'];
1461
+ $this->tokens[$x]['level']--;
1462
+ unset($this->tokens[$x]['conditions'][$badToken]);
1463
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1464
+ $type = $this->tokens[$x]['type'];
1465
+ $oldConds = '';
1466
+ foreach ($oldConditions as $condition) {
1467
+ $oldConds .= Util\Tokens::tokenName($condition).',';
1468
+ }
1469
+
1470
+ $oldConds = rtrim($oldConds, ',');
1471
+
1472
+ $newConds = '';
1473
+ foreach ($this->tokens[$x]['conditions'] as $condition) {
1474
+ $newConds .= Util\Tokens::tokenName($condition).',';
1475
+ }
1476
+
1477
+ $newConds = rtrim($newConds, ',');
1478
+
1479
+ $newLevel = $this->tokens[$x]['level'];
1480
+ echo str_repeat("\t", ($level + 1));
1481
+ echo "* cleaned $x:$type *".PHP_EOL;
1482
+ echo str_repeat("\t", ($level + 2));
1483
+ echo "=> level changed from $oldLevel to $newLevel".PHP_EOL;
1484
+ echo str_repeat("\t", ($level + 2));
1485
+ echo "=> conditions changed from $oldConds to $newConds".PHP_EOL;
1486
+ }//end if
1487
+ }//end for
1488
+
1489
+ unset($conditions[$badToken]);
1490
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1491
+ $type = $this->tokens[$badToken]['type'];
1492
+ echo str_repeat("\t", ($level + 1));
1493
+ echo "* token $badToken:$type removed from conditions array *".PHP_EOL;
1494
+ }
1495
+
1496
+ unset($openers[$lastOpener]);
1497
+
1498
+ $level--;
1499
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1500
+ echo str_repeat("\t", ($level + 2));
1501
+ echo '* level decreased *'.PHP_EOL;
1502
+ }
1503
+ }//end if
1504
+ }//end if
1505
+
1506
+ $level++;
1507
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1508
+ echo str_repeat("\t", ($level + 1));
1509
+ echo '* level increased *'.PHP_EOL;
1510
+ }
1511
+
1512
+ $conditions[$stackPtr] = $this->tokens[$stackPtr]['code'];
1513
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1514
+ $type = $this->tokens[$stackPtr]['type'];
1515
+ echo str_repeat("\t", ($level + 1));
1516
+ echo "* token $stackPtr:$type added to conditions array *".PHP_EOL;
1517
+ }
1518
+
1519
+ $lastOpener = $this->tokens[$i]['scope_opener'];
1520
+ if ($lastOpener !== null) {
1521
+ $openers[$lastOpener] = $lastOpener;
1522
+ }
1523
+ } else if ($lastOpener !== null && $this->tokens[$lastOpener]['scope_closer'] === $i) {
1524
+ foreach (array_reverse($openers) as $opener) {
1525
+ if ($this->tokens[$opener]['scope_closer'] === $i) {
1526
+ $oldOpener = array_pop($openers);
1527
+ if (empty($openers) === false) {
1528
+ $lastOpener = array_pop($openers);
1529
+ $openers[$lastOpener] = $lastOpener;
1530
+ } else {
1531
+ $lastOpener = null;
1532
+ }
1533
+
1534
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1535
+ $type = $this->tokens[$oldOpener]['type'];
1536
+ echo str_repeat("\t", ($level + 1));
1537
+ echo "=> Found scope closer for $oldOpener:$type".PHP_EOL;
1538
+ }
1539
+
1540
+ $oldCondition = array_pop($conditions);
1541
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1542
+ echo str_repeat("\t", ($level + 1));
1543
+ echo '* token '.Util\Tokens::tokenName($oldCondition).' removed from conditions array *'.PHP_EOL;
1544
+ }
1545
+
1546
+ // Make sure this closer actually belongs to us.
1547
+ // Either the condition also has to think this is the
1548
+ // closer, or it has to allow sharing with us.
1549
+ $condition = $this->tokens[$this->tokens[$i]['scope_condition']]['code'];
1550
+ if ($condition !== $oldCondition) {
1551
+ if (isset($this->scopeOpeners[$oldCondition]['with'][$condition]) === false) {
1552
+ $badToken = $this->tokens[$oldOpener]['scope_condition'];
1553
+
1554
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1555
+ $type = Util\Tokens::tokenName($oldCondition);
1556
+ echo str_repeat("\t", ($level + 1));
1557
+ echo "* scope closer was bad, cleaning up $badToken:$type *".PHP_EOL;
1558
+ }
1559
+
1560
+ for ($x = ($oldOpener + 1); $x <= $i; $x++) {
1561
+ $oldConditions = $this->tokens[$x]['conditions'];
1562
+ $oldLevel = $this->tokens[$x]['level'];
1563
+ $this->tokens[$x]['level']--;
1564
+ unset($this->tokens[$x]['conditions'][$badToken]);
1565
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1566
+ $type = $this->tokens[$x]['type'];
1567
+ $oldConds = '';
1568
+ foreach ($oldConditions as $condition) {
1569
+ $oldConds .= Util\Tokens::tokenName($condition).',';
1570
+ }
1571
+
1572
+ $oldConds = rtrim($oldConds, ',');
1573
+
1574
+ $newConds = '';
1575
+ foreach ($this->tokens[$x]['conditions'] as $condition) {
1576
+ $newConds .= Util\Tokens::tokenName($condition).',';
1577
+ }
1578
+
1579
+ $newConds = rtrim($newConds, ',');
1580
+
1581
+ $newLevel = $this->tokens[$x]['level'];
1582
+ echo str_repeat("\t", ($level + 1));
1583
+ echo "* cleaned $x:$type *".PHP_EOL;
1584
+ echo str_repeat("\t", ($level + 2));
1585
+ echo "=> level changed from $oldLevel to $newLevel".PHP_EOL;
1586
+ echo str_repeat("\t", ($level + 2));
1587
+ echo "=> conditions changed from $oldConds to $newConds".PHP_EOL;
1588
+ }//end if
1589
+ }//end for
1590
+ }//end if
1591
+ }//end if
1592
+
1593
+ $level--;
1594
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1595
+ echo str_repeat("\t", ($level + 2));
1596
+ echo '* level decreased *'.PHP_EOL;
1597
+ }
1598
+
1599
+ $this->tokens[$i]['level'] = $level;
1600
+ $this->tokens[$i]['conditions'] = $conditions;
1601
+ }//end if
1602
+ }//end foreach
1603
+ }//end if
1604
+ }//end if
1605
+ }//end for
1606
+
1607
+ if (PHP_CODESNIFFER_VERBOSITY > 1) {
1608
+ echo "\t*** END LEVEL MAP ***".PHP_EOL;
1609
+ }
1610
+
1611
+ }//end createLevelMap()
1612
+
1613
+
1614
+ }//end class
vendor/php_codesniffer-3.4.0/src/Util/Standards.php ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Functions for helping process standards.
4
+ *
5
+ * @author Greg Sherwood <gsherwood@squiz.net>
6
+ * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
+ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
+ */
9
+
10
+ namespace PHP_CodeSniffer\Util;
11
+
12
+ use PHP_CodeSniffer\Config;
13
+
14
+ class Standards {
15
+
16
+
17
+ /**
18
+ * Get a list paths where standards are installed.
19
+ *
20
+ * @return array
21
+ */
22
+ public static function getInstalledStandardPaths() {
23
+ return array();
24
+
25
+ }//end getInstalledStandardPaths()
26
+
27
+
28
+ /**
29
+ * Get the details of all coding standards installed.
30
+ *
31
+ * Coding standards are directories located in the
32
+ * CodeSniffer/Standards directory. Valid coding standards
33
+ * include a Sniffs subdirectory.
34
+ *
35
+ * The details returned for each standard are:
36
+ * - path: the path to the coding standard's main directory
37
+ * - name: the name of the coding standard, as sourced from the ruleset.xml file
38
+ * - namespace: the namespace used by the coding standard, as sourced from the ruleset.xml file
39
+ *
40
+ * If you only need the paths to the installed standards,
41
+ * use getInstalledStandardPaths() instead as it performs less work to
42
+ * retrieve coding standard names.
43
+ *
44
+ * @param boolean $includeGeneric If true, the special "Generic"
45
+ * coding standard will be included
46
+ * if installed.
47
+ * @param string $standardsDir A specific directory to look for standards
48
+ * in. If not specified, PHP_CodeSniffer will
49
+ * look in its default locations.
50
+ *
51
+ * @return array
52
+ * @see getInstalledStandardPaths()
53
+ */
54
+ public static function getInstalledStandardDetails(
55
+ $includeGeneric = false,
56
+ $standardsDir = ''
57
+ ) {
58
+ return array();
59
+
60
+ }//end getInstalledStandardDetails()
61
+
62
+
63
+ /**
64
+ * Get a list of all coding standards installed.
65
+ *
66
+ * Coding standards are directories located in the
67
+ * CodeSniffer/Standards directory. Valid coding standards
68
+ * include a Sniffs subdirectory.
69
+ *
70
+ * @param boolean $includeGeneric If true, the special "Generic"
71
+ * coding standard will be included
72
+ * if installed.
73
+ * @param string $standardsDir A specific directory to look for standards
74
+ * in. If not specified, PHP_CodeSniffer will
75
+ * look in its default locations.
76
+ *
77
+ * @return array
78
+ * @see isInstalledStandard()
79
+ */
80
+ public static function getInstalledStandards(
81
+ $includeGeneric = false,
82
+ $standardsDir = ''
83
+ ) {
84
+
85
+ return array();
86
+
87
+ }//end getInstalledStandards()
88
+
89
+
90
+ /**
91
+ * Determine if a standard is installed.
92
+ *
93
+ * Coding standards are directories located in the
94
+ * CodeSniffer/Standards directory. Valid coding standards
95
+ * include a ruleset.xml file.
96
+ *
97
+ * @param string $standard The name of the coding standard.
98
+ *
99
+ * @return boolean
100
+ * @see getInstalledStandards()
101
+ */
102
+ public static function isInstalledStandard( $standard ) {
103
+ return false;
104
+
105
+ }//end isInstalledStandard()
106
+
107
+
108
+ /**
109
+ * Return the path of an installed coding standard.
110
+ *
111
+ * Coding standards are directories located in the
112
+ * CodeSniffer/Standards directory. Valid coding standards
113
+ * include a ruleset.xml file.
114
+ *
115
+ * @param string $standard The name of the coding standard.
116
+ *
117
+ * @return string|null
118
+ */
119
+ public static function getInstalledStandardPath( $standard ) {
120
+
121
+ return null;
122
+
123
+ }//end getInstalledStandardPath()
124
+
125
+
126
+ /**
127
+ * Prints out a list of installed coding standards.
128
+ *
129
+ * @return void
130
+ */
131
+ public static function printInstalledStandards() {
132
+
133
+
134
+ }//end printInstalledStandards()
135
+
136
+
137
+ }//end class
vendor/php_codesniffer-3.4.0/src/Util/Tokens.php ADDED
@@ -0,0 +1,644 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Stores weightings and groupings of tokens.
4
+ *
5
+ * @author Greg Sherwood <gsherwood@squiz.net>
6
+ * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
+ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
+ */
9
+
10
+ namespace PHP_CodeSniffer\Util;
11
+
12
+ define('T_NONE', 'PHPCS_T_NONE');
13
+ define('T_OPEN_CURLY_BRACKET', 'PHPCS_T_OPEN_CURLY_BRACKET');
14
+ define('T_CLOSE_CURLY_BRACKET', 'PHPCS_T_CLOSE_CURLY_BRACKET');
15
+ define('T_OPEN_SQUARE_BRACKET', 'PHPCS_T_OPEN_SQUARE_BRACKET');
16
+ define('T_CLOSE_SQUARE_BRACKET', 'PHPCS_T_CLOSE_SQUARE_BRACKET');
17
+ define('T_OPEN_PARENTHESIS', 'PHPCS_T_OPEN_PARENTHESIS');
18
+ define('T_CLOSE_PARENTHESIS', 'PHPCS_T_CLOSE_PARENTHESIS');
19
+ define('T_COLON', 'PHPCS_T_COLON');
20
+ define('T_NULLABLE', 'PHPCS_T_NULLABLE');
21
+ define('T_STRING_CONCAT', 'PHPCS_T_STRING_CONCAT');
22
+ define('T_INLINE_THEN', 'PHPCS_T_INLINE_THEN');
23
+ define('T_INLINE_ELSE', 'PHPCS_T_INLINE_ELSE');
24
+ define('T_NULL', 'PHPCS_T_NULL');
25
+ define('T_FALSE', 'PHPCS_T_FALSE');
26
+ define('T_TRUE', 'PHPCS_T_TRUE');
27
+ define('T_SEMICOLON', 'PHPCS_T_SEMICOLON');
28
+ define('T_EQUAL', 'PHPCS_T_EQUAL');
29
+ define('T_MULTIPLY', 'PHPCS_T_MULTIPLY');
30
+ define('T_DIVIDE', 'PHPCS_T_DIVIDE');
31
+ define('T_PLUS', 'PHPCS_T_PLUS');
32
+ define('T_MINUS', 'PHPCS_T_MINUS');
33
+ define('T_MODULUS', 'PHPCS_T_MODULUS');
34
+ define('T_BITWISE_AND', 'PHPCS_T_BITWISE_AND');
35
+ define('T_BITWISE_OR', 'PHPCS_T_BITWISE_OR');
36
+ define('T_BITWISE_XOR', 'PHPCS_T_BITWISE_XOR');
37
+ define('T_BITWISE_NOT', 'PHPCS_T_BITWISE_NOT');
38
+ define('T_ARRAY_HINT', 'PHPCS_T_ARRAY_HINT');
39
+ define('T_GREATER_THAN', 'PHPCS_T_GREATER_THAN');
40
+ define('T_LESS_THAN', 'PHPCS_T_LESS_THAN');
41
+ define('T_BOOLEAN_NOT', 'PHPCS_T_BOOLEAN_NOT');
42
+ define('T_SELF', 'PHPCS_T_SELF');
43
+ define('T_PARENT', 'PHPCS_T_PARENT');
44
+ define('T_DOUBLE_QUOTED_STRING', 'PHPCS_T_DOUBLE_QUOTED_STRING');
45
+ define('T_COMMA', 'PHPCS_T_COMMA');
46
+ define('T_HEREDOC', 'PHPCS_T_HEREDOC');
47
+ define('T_PROTOTYPE', 'PHPCS_T_PROTOTYPE');
48
+ define('T_THIS', 'PHPCS_T_THIS');
49
+ define('T_REGULAR_EXPRESSION', 'PHPCS_T_REGULAR_EXPRESSION');
50
+ define('T_PROPERTY', 'PHPCS_T_PROPERTY');
51
+ define('T_LABEL', 'PHPCS_T_LABEL');
52
+ define('T_OBJECT', 'PHPCS_T_OBJECT');
53
+ define('T_CLOSE_OBJECT', 'PHPCS_T_CLOSE_OBJECT');
54
+ define('T_COLOUR', 'PHPCS_T_COLOUR');
55
+ define('T_HASH', 'PHPCS_T_HASH');
56
+ define('T_URL', 'PHPCS_T_URL');
57
+ define('T_STYLE', 'PHPCS_T_STYLE');
58
+ define('T_ASPERAND', 'PHPCS_T_ASPERAND');
59
+ define('T_DOLLAR', 'PHPCS_T_DOLLAR');
60
+ define('T_TYPEOF', 'PHPCS_T_TYPEOF');
61
+ define('T_CLOSURE', 'PHPCS_T_CLOSURE');
62
+ define('T_ANON_CLASS', 'PHPCS_T_ANON_CLASS');
63
+ define('T_BACKTICK', 'PHPCS_T_BACKTICK');
64
+ define('T_START_NOWDOC', 'PHPCS_T_START_NOWDOC');
65
+ define('T_NOWDOC', 'PHPCS_T_NOWDOC');
66
+ define('T_END_NOWDOC', 'PHPCS_T_END_NOWDOC');
67
+ define('T_OPEN_SHORT_ARRAY', 'PHPCS_T_OPEN_SHORT_ARRAY');
68
+ define('T_CLOSE_SHORT_ARRAY', 'PHPCS_T_CLOSE_SHORT_ARRAY');
69
+ define('T_GOTO_LABEL', 'PHPCS_T_GOTO_LABEL');
70
+ define('T_BINARY_CAST', 'PHPCS_T_BINARY_CAST');
71
+ define('T_EMBEDDED_PHP', 'PHPCS_T_EMBEDDED_PHP');
72
+ define('T_RETURN_TYPE', 'PHPCS_T_RETURN_TYPE');
73
+ define('T_OPEN_USE_GROUP', 'PHPCS_T_OPEN_USE_GROUP');
74
+ define('T_CLOSE_USE_GROUP', 'PHPCS_T_CLOSE_USE_GROUP');
75
+ define('T_ZSR', 'PHPCS_T_ZSR');
76
+ define('T_ZSR_EQUAL', 'PHPCS_T_ZSR_EQUAL');
77
+
78
+ // Some PHP 5.5 tokens, replicated for lower versions.
79
+ if (defined('T_FINALLY') === false) {
80
+ define('T_FINALLY', 'PHPCS_T_FINALLY');
81
+ }
82
+
83
+ if (defined('T_YIELD') === false) {
84
+ define('T_YIELD', 'PHPCS_T_YIELD');
85
+ }
86
+
87
+ // Some PHP 5.6 tokens, replicated for lower versions.
88
+ if (defined('T_ELLIPSIS') === false) {
89
+ define('T_ELLIPSIS', 'PHPCS_T_ELLIPSIS');
90
+ }
91
+
92
+ if (defined('T_POW') === false) {
93
+ define('T_POW', 'PHPCS_T_POW');
94
+ }
95
+
96
+ if (defined('T_POW_EQUAL') === false) {
97
+ define('T_POW_EQUAL', 'PHPCS_T_POW_EQUAL');
98
+ }
99
+
100
+ // Some PHP 7 tokens, replicated for lower versions.
101
+ if (defined('T_SPACESHIP') === false) {
102
+ define('T_SPACESHIP', 'PHPCS_T_SPACESHIP');
103
+ }
104
+
105
+ if (defined('T_COALESCE') === false) {
106
+ define('T_COALESCE', 'PHPCS_T_COALESCE');
107
+ }
108
+
109
+ if (defined('T_COALESCE_EQUAL') === false) {
110
+ define('T_COALESCE_EQUAL', 'PHPCS_T_COALESCE_EQUAL');
111
+ }
112
+
113
+ if (defined('T_YIELD_FROM') === false) {
114
+ define('T_YIELD_FROM', 'PHPCS_T_YIELD_FROM');
115
+ }
116
+
117
+ // Tokens used for parsing doc blocks.
118
+ define('T_DOC_COMMENT_STAR', 'PHPCS_T_DOC_COMMENT_STAR');
119
+ define('T_DOC_COMMENT_WHITESPACE', 'PHPCS_T_DOC_COMMENT_WHITESPACE');
120
+ define('T_DOC_COMMENT_TAG', 'PHPCS_T_DOC_COMMENT_TAG');
121
+ define('T_DOC_COMMENT_OPEN_TAG', 'PHPCS_T_DOC_COMMENT_OPEN_TAG');
122
+ define('T_DOC_COMMENT_CLOSE_TAG', 'PHPCS_T_DOC_COMMENT_CLOSE_TAG');
123
+ define('T_DOC_COMMENT_STRING', 'PHPCS_T_DOC_COMMENT_STRING');
124
+
125
+ // Tokens used for PHPCS instruction comments.
126
+ define('T_PHPCS_ENABLE', 'PHPCS_T_PHPCS_ENABLE');
127
+ define('T_PHPCS_DISABLE', 'PHPCS_T_PHPCS_DISABLE');
128
+ define('T_PHPCS_SET', 'PHPCS_T_PHPCS_SET');
129
+ define('T_PHPCS_IGNORE', 'PHPCS_T_PHPCS_IGNORE');
130
+ define('T_PHPCS_IGNORE_FILE', 'PHPCS_T_PHPCS_IGNORE_FILE');
131
+
132
+ final class Tokens
133
+ {
134
+
135
+ /**
136
+ * The token weightings.
137
+ *
138
+ * @var array<int, int>
139
+ */
140
+ public static $weightings = [
141
+ T_CLASS => 1000,
142
+ T_INTERFACE => 1000,
143
+ T_TRAIT => 1000,
144
+ T_NAMESPACE => 1000,
145
+ T_FUNCTION => 100,
146
+ T_CLOSURE => 100,
147
+
148
+ /*
149
+ * Conditions.
150
+ */
151
+
152
+ T_WHILE => 50,
153
+ T_FOR => 50,
154
+ T_FOREACH => 50,
155
+ T_IF => 50,
156
+ T_ELSE => 50,
157
+ T_ELSEIF => 50,
158
+ T_DO => 50,
159
+ T_TRY => 50,
160
+ T_CATCH => 50,
161
+ T_FINALLY => 50,
162
+ T_SWITCH => 50,
163
+
164
+ T_SELF => 25,
165
+ T_PARENT => 25,
166
+
167
+ /*
168
+ * Operators and arithmetic.
169
+ */
170
+
171
+ T_BITWISE_AND => 8,
172
+ T_BITWISE_OR => 8,
173
+ T_BITWISE_XOR => 8,
174
+
175
+ T_MULTIPLY => 5,
176
+ T_DIVIDE => 5,
177
+ T_PLUS => 5,
178
+ T_MINUS => 5,
179
+ T_MODULUS => 5,
180
+ T_POW => 5,
181
+ T_SPACESHIP => 5,
182
+ T_COALESCE => 5,
183
+ T_COALESCE_EQUAL => 5,
184
+
185
+ T_SL => 5,
186
+ T_SR => 5,
187
+ T_SL_EQUAL => 5,
188
+ T_SR_EQUAL => 5,
189
+
190
+ T_EQUAL => 5,
191
+ T_AND_EQUAL => 5,
192
+ T_CONCAT_EQUAL => 5,
193
+ T_DIV_EQUAL => 5,
194
+ T_MINUS_EQUAL => 5,
195
+ T_MOD_EQUAL => 5,
196
+ T_MUL_EQUAL => 5,
197
+ T_OR_EQUAL => 5,
198
+ T_PLUS_EQUAL => 5,
199
+ T_XOR_EQUAL => 5,
200
+
201
+ T_BOOLEAN_AND => 5,
202
+ T_BOOLEAN_OR => 5,
203
+
204
+ /*
205
+ * Equality.
206
+ */
207
+
208
+ T_IS_EQUAL => 5,
209
+ T_IS_NOT_EQUAL => 5,
210
+ T_IS_IDENTICAL => 5,
211
+ T_IS_NOT_IDENTICAL => 5,
212
+ T_IS_SMALLER_OR_EQUAL => 5,
213
+ T_IS_GREATER_OR_EQUAL => 5,
214
+ ];
215
+
216
+ /**
217
+ * Tokens that represent assignments.
218
+ *
219
+ * @var array<int, int>
220
+ */
221
+ public static $assignmentTokens = [
222
+ T_EQUAL => T_EQUAL,
223
+ T_AND_EQUAL => T_AND_EQUAL,
224
+ T_OR_EQUAL => T_OR_EQUAL,
225
+ T_CONCAT_EQUAL => T_CONCAT_EQUAL,
226
+ T_DIV_EQUAL => T_DIV_EQUAL,
227
+ T_MINUS_EQUAL => T_MINUS_EQUAL,
228
+ T_POW_EQUAL => T_POW_EQUAL,
229
+ T_MOD_EQUAL => T_MOD_EQUAL,
230
+ T_MUL_EQUAL => T_MUL_EQUAL,
231
+ T_PLUS_EQUAL => T_PLUS_EQUAL,
232
+ T_XOR_EQUAL => T_XOR_EQUAL,
233
+ T_DOUBLE_ARROW => T_DOUBLE_ARROW,
234
+ T_SL_EQUAL => T_SL_EQUAL,
235
+ T_SR_EQUAL => T_SR_EQUAL,
236
+ T_COALESCE_EQUAL => T_COALESCE_EQUAL,
237
+ T_ZSR_EQUAL => T_ZSR_EQUAL,
238
+ ];
239
+
240
+ /**
241
+ * Tokens that represent equality comparisons.
242
+ *
243
+ * @var array<int, int>
244
+ */
245
+ public static $equalityTokens = [
246
+ T_IS_EQUAL => T_IS_EQUAL,
247
+ T_IS_NOT_EQUAL => T_IS_NOT_EQUAL,
248
+ T_IS_IDENTICAL => T_IS_IDENTICAL,
249
+ T_IS_NOT_IDENTICAL => T_IS_NOT_IDENTICAL,
250
+ T_IS_SMALLER_OR_EQUAL => T_IS_SMALLER_OR_EQUAL,
251
+ T_IS_GREATER_OR_EQUAL => T_IS_GREATER_OR_EQUAL,
252
+ ];
253
+
254
+ /**
255
+ * Tokens that represent comparison operator.
256
+ *
257
+ * @var array<int, int>
258
+ */
259
+ public static $comparisonTokens = [
260
+ T_IS_EQUAL => T_IS_EQUAL,
261
+ T_IS_IDENTICAL => T_IS_IDENTICAL,
262
+ T_IS_NOT_EQUAL => T_IS_NOT_EQUAL,
263
+ T_IS_NOT_IDENTICAL => T_IS_NOT_IDENTICAL,
264
+ T_LESS_THAN => T_LESS_THAN,
265
+ T_GREATER_THAN => T_GREATER_THAN,
266
+ T_IS_SMALLER_OR_EQUAL => T_IS_SMALLER_OR_EQUAL,
267
+ T_IS_GREATER_OR_EQUAL => T_IS_GREATER_OR_EQUAL,
268
+ T_SPACESHIP => T_SPACESHIP,
269
+ T_COALESCE => T_COALESCE,
270
+ ];
271
+
272
+ /**
273
+ * Tokens that represent arithmetic operators.
274
+ *
275
+ * @var array<int, int>
276
+ */
277
+ public static $arithmeticTokens = [
278
+ T_PLUS => T_PLUS,
279
+ T_MINUS => T_MINUS,
280
+ T_MULTIPLY => T_MULTIPLY,
281
+ T_DIVIDE => T_DIVIDE,
282
+ T_MODULUS => T_MODULUS,
283
+ T_POW => T_POW,
284
+ ];
285
+
286
+ /**
287
+ * Tokens that perform operations.
288
+ *
289
+ * @var array<int, int>
290
+ */
291
+ public static $operators = [
292
+ T_MINUS => T_MINUS,
293
+ T_PLUS => T_PLUS,
294
+ T_MULTIPLY => T_MULTIPLY,
295
+ T_DIVIDE => T_DIVIDE,
296
+ T_MODULUS => T_MODULUS,
297
+ T_POW => T_POW,
298
+ T_SPACESHIP => T_SPACESHIP,
299
+ T_COALESCE => T_COALESCE,
300
+ T_BITWISE_AND => T_BITWISE_AND,
301
+ T_BITWISE_OR => T_BITWISE_OR,
302
+ T_BITWISE_XOR => T_BITWISE_XOR,
303
+ T_SL => T_SL,
304
+ T_SR => T_SR,
305
+ ];
306
+
307
+ /**
308
+ * Tokens that perform boolean operations.
309
+ *
310
+ * @var array<int, int>
311
+ */
312
+ public static $booleanOperators = [
313
+ T_BOOLEAN_AND => T_BOOLEAN_AND,
314
+ T_BOOLEAN_OR => T_BOOLEAN_OR,
315
+ T_LOGICAL_AND => T_LOGICAL_AND,
316
+ T_LOGICAL_OR => T_LOGICAL_OR,
317
+ T_LOGICAL_XOR => T_LOGICAL_XOR,
318
+ ];
319
+
320
+ /**
321
+ * Tokens that represent casting.
322
+ *
323
+ * @var array<int, int>
324
+ */
325
+ public static $castTokens = [
326
+ T_INT_CAST => T_INT_CAST,
327
+ T_STRING_CAST => T_STRING_CAST,
328
+ T_DOUBLE_CAST => T_DOUBLE_CAST,
329
+ T_ARRAY_CAST => T_ARRAY_CAST,
330
+ T_BOOL_CAST => T_BOOL_CAST,
331
+ T_OBJECT_CAST => T_OBJECT_CAST,
332
+ T_UNSET_CAST => T_UNSET_CAST,
333
+ T_BINARY_CAST => T_BINARY_CAST,
334
+ ];
335
+
336
+ /**
337
+ * Token types that open parenthesis.
338
+ *
339
+ * @var array<int, int>
340
+ */
341
+ public static $parenthesisOpeners = [
342
+ T_ARRAY => T_ARRAY,
343
+ T_FUNCTION => T_FUNCTION,
344
+ T_CLOSURE => T_CLOSURE,
345
+ T_WHILE => T_WHILE,
346
+ T_FOR => T_FOR,
347
+ T_FOREACH => T_FOREACH,
348
+ T_SWITCH => T_SWITCH,
349
+ T_IF => T_IF,
350
+ T_ELSEIF => T_ELSEIF,
351
+ T_CATCH => T_CATCH,
352
+ T_DECLARE => T_DECLARE,
353
+ ];
354
+
355
+ /**
356
+ * Tokens that are allowed to open scopes.
357
+ *
358
+ * @var array<int, int>
359
+ */
360
+ public static $scopeOpeners = [
361
+ T_CLASS => T_CLASS,
362
+ T_ANON_CLASS => T_ANON_CLASS,
363
+ T_INTERFACE => T_INTERFACE,
364
+ T_TRAIT => T_TRAIT,
365
+ T_NAMESPACE => T_NAMESPACE,
366
+ T_FUNCTION => T_FUNCTION,
367
+ T_CLOSURE => T_CLOSURE,
368
+ T_IF => T_IF,
369
+ T_SWITCH => T_SWITCH,
370
+ T_CASE => T_CASE,
371
+ T_DECLARE => T_DECLARE,
372
+ T_DEFAULT => T_DEFAULT,
373
+ T_WHILE => T_WHILE,
374
+ T_ELSE => T_ELSE,
375
+ T_ELSEIF => T_ELSEIF,
376
+ T_FOR => T_FOR,
377
+ T_FOREACH => T_FOREACH,
378
+ T_DO => T_DO,
379
+ T_TRY => T_TRY,
380
+ T_CATCH => T_CATCH,
381
+ T_FINALLY => T_FINALLY,
382
+ T_PROPERTY => T_PROPERTY,
383
+ T_OBJECT => T_OBJECT,
384
+ T_USE => T_USE,
385
+ ];
386
+
387
+ /**
388
+ * Tokens that represent scope modifiers.
389
+ *
390
+ * @var array<int, int>
391
+ */
392
+ public static $scopeModifiers = [
393
+ T_PRIVATE => T_PRIVATE,
394
+ T_PUBLIC => T_PUBLIC,
395
+ T_PROTECTED => T_PROTECTED,
396
+ ];
397
+
398
+ /**
399
+ * Tokens that can prefix a method name
400
+ *
401
+ * @var array<int, int>
402
+ */
403
+ public static $methodPrefixes = [
404
+ T_PRIVATE => T_PRIVATE,
405
+ T_PUBLIC => T_PUBLIC,
406
+ T_PROTECTED => T_PROTECTED,
407
+ T_ABSTRACT => T_ABSTRACT,
408
+ T_STATIC => T_STATIC,
409
+ T_FINAL => T_FINAL,
410
+ ];
411
+
412
+ /**
413
+ * Tokens that open code blocks.
414
+ *
415
+ * @var array<int, int>
416
+ */
417
+ public static $blockOpeners = [
418
+ T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
419
+ T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET,
420
+ T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS,
421
+ T_OBJECT => T_OBJECT,
422
+ ];
423
+
424
+ /**
425
+ * Tokens that don't represent code.
426
+ *
427
+ * @var array<int, int>
428
+ */
429
+ public static $emptyTokens = [
430
+ T_WHITESPACE => T_WHITESPACE,
431
+ T_COMMENT => T_COMMENT,
432
+ T_DOC_COMMENT => T_DOC_COMMENT,
433
+ T_DOC_COMMENT_STAR => T_DOC_COMMENT_STAR,
434
+ T_DOC_COMMENT_WHITESPACE => T_DOC_COMMENT_WHITESPACE,
435
+ T_DOC_COMMENT_TAG => T_DOC_COMMENT_TAG,
436
+ T_DOC_COMMENT_OPEN_TAG => T_DOC_COMMENT_OPEN_TAG,
437
+ T_DOC_COMMENT_CLOSE_TAG => T_DOC_COMMENT_CLOSE_TAG,
438
+ T_DOC_COMMENT_STRING => T_DOC_COMMENT_STRING,
439
+ T_PHPCS_ENABLE => T_PHPCS_ENABLE,
440
+ T_PHPCS_DISABLE => T_PHPCS_DISABLE,
441
+ T_PHPCS_SET => T_PHPCS_SET,
442
+ T_PHPCS_IGNORE => T_PHPCS_IGNORE,
443
+ T_PHPCS_IGNORE_FILE => T_PHPCS_IGNORE_FILE,
444
+ ];
445
+
446
+ /**
447
+ * Tokens that are comments.
448
+ *
449
+ * @var array<int, int>
450
+ */
451
+ public static $commentTokens = [
452
+ T_COMMENT => T_COMMENT,
453
+ T_DOC_COMMENT => T_DOC_COMMENT,
454
+ T_DOC_COMMENT_STAR => T_DOC_COMMENT_STAR,
455
+ T_DOC_COMMENT_WHITESPACE => T_DOC_COMMENT_WHITESPACE,
456
+ T_DOC_COMMENT_TAG => T_DOC_COMMENT_TAG,
457
+ T_DOC_COMMENT_OPEN_TAG => T_DOC_COMMENT_OPEN_TAG,
458
+ T_DOC_COMMENT_CLOSE_TAG => T_DOC_COMMENT_CLOSE_TAG,
459
+ T_DOC_COMMENT_STRING => T_DOC_COMMENT_STRING,
460
+ T_PHPCS_ENABLE => T_PHPCS_ENABLE,
461
+ T_PHPCS_DISABLE => T_PHPCS_DISABLE,
462
+ T_PHPCS_SET => T_PHPCS_SET,
463
+ T_PHPCS_IGNORE => T_PHPCS_IGNORE,
464
+ T_PHPCS_IGNORE_FILE => T_PHPCS_IGNORE_FILE,
465
+ ];
466
+
467
+ /**
468
+ * Tokens that are comments containing PHPCS instructions.
469
+ *
470
+ * @var array<int, int>
471
+ */
472
+ public static $phpcsCommentTokens = [
473
+ T_PHPCS_ENABLE => T_PHPCS_ENABLE,
474
+ T_PHPCS_DISABLE => T_PHPCS_DISABLE,
475
+ T_PHPCS_SET => T_PHPCS_SET,
476
+ T_PHPCS_IGNORE => T_PHPCS_IGNORE,
477
+ T_PHPCS_IGNORE_FILE => T_PHPCS_IGNORE_FILE,
478
+ ];
479
+
480
+ /**
481
+ * Tokens that represent strings.
482
+ *
483
+ * Note that T_STRINGS are NOT represented in this list.
484
+ *
485
+ * @var array<int, int>
486
+ */
487
+ public static $stringTokens = [
488
+ T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING,
489
+ T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING,
490
+ ];
491
+
492
+ /**
493
+ * Tokens that represent text strings.
494
+ *
495
+ * @var array<int, int>
496
+ */
497
+ public static $textStringTokens = [
498
+ T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING,
499
+ T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING,
500
+ T_INLINE_HTML => T_INLINE_HTML,
501
+ T_HEREDOC => T_HEREDOC,
502
+ T_NOWDOC => T_NOWDOC,
503
+ ];
504
+
505
+ /**
506
+ * Tokens that represent brackets and parenthesis.
507
+ *
508
+ * @var array<int, int>
509
+ */
510
+ public static $bracketTokens = [
511
+ T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET,
512
+ T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET,
513
+ T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET,
514
+ T_CLOSE_SQUARE_BRACKET => T_CLOSE_SQUARE_BRACKET,
515
+ T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS,
516
+ T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS,
517
+ ];
518
+
519
+ /**
520
+ * Tokens that include files.
521
+ *
522
+ * @var array<int, int>
523
+ */
524
+ public static $includeTokens = [
525
+ T_REQUIRE_ONCE => T_REQUIRE_ONCE,
526
+ T_REQUIRE => T_REQUIRE,
527
+ T_INCLUDE_ONCE => T_INCLUDE_ONCE,
528
+ T_INCLUDE => T_INCLUDE,
529
+ ];
530
+
531
+ /**
532
+ * Tokens that make up a heredoc string.
533
+ *
534
+ * @var array<int, int>
535
+ */
536
+ public static $heredocTokens = [
537
+ T_START_HEREDOC => T_START_HEREDOC,
538
+ T_END_HEREDOC => T_END_HEREDOC,
539
+ T_HEREDOC => T_HEREDOC,
540
+ T_START_NOWDOC => T_START_NOWDOC,
541
+ T_END_NOWDOC => T_END_NOWDOC,
542
+ T_NOWDOC => T_NOWDOC,
543
+ ];
544
+
545
+ /**
546
+ * Tokens that represent the names of called functions.
547
+ *
548
+ * Mostly, these are just strings. But PHP tokenizes some language
549
+ * constructs and functions using their own tokens.
550
+ *
551
+ * @var array<int, int>
552
+ */
553
+ public static $functionNameTokens = [
554
+ T_STRING => T_STRING,
555
+ T_EVAL => T_EVAL,
556
+ T_EXIT => T_EXIT,
557
+ T_INCLUDE => T_INCLUDE,
558
+ T_INCLUDE_ONCE => T_INCLUDE_ONCE,
559
+ T_REQUIRE => T_REQUIRE,
560
+ T_REQUIRE_ONCE => T_REQUIRE_ONCE,
561
+ T_ISSET => T_ISSET,
562
+ T_UNSET => T_UNSET,
563
+ T_EMPTY => T_EMPTY,
564
+ T_SELF => T_SELF,
565
+ T_STATIC => T_STATIC,
566
+ ];
567
+
568
+ /**
569
+ * Tokens that open class and object scopes.
570
+ *
571
+ * @var array<int, int>
572
+ */
573
+ public static $ooScopeTokens = [
574
+ T_CLASS => T_CLASS,
575
+ T_ANON_CLASS => T_ANON_CLASS,
576
+ T_INTERFACE => T_INTERFACE,
577
+ T_TRAIT => T_TRAIT,
578
+ ];
579
+
580
+
581
+ /**
582
+ * Given a token, returns the name of the token.
583
+ *
584
+ * If passed an integer, the token name is sourced from PHP's token_name()
585
+ * function. If passed a string, it is assumed to be a PHPCS-supplied token
586
+ * that begins with PHPCS_T_, so the name is sourced from the token value itself.
587
+ *
588
+ * @param int|string $token The token to get the name for.
589
+ *
590
+ * @return string
591
+ */
592
+ public static function tokenName($token)
593
+ {
594
+ if (is_string($token) === false) {
595
+ // PHP-supplied token name.
596
+ return token_name($token);
597
+ }
598
+
599
+ return substr($token, 6);
600
+
601
+ }//end tokenName()
602
+
603
+
604
+ /**
605
+ * Returns the highest weighted token type.
606
+ *
607
+ * Tokens are weighted by their approximate frequency of appearance in code
608
+ * - the less frequently they appear in the code, the higher the weighting.
609
+ * For example T_CLASS tokens appear very infrequently in a file, and
610
+ * therefore have a high weighting.
611
+ *
612
+ * Returns false if there are no weightings for any of the specified tokens.
613
+ *
614
+ * @param array<int, int> $tokens The token types to get the highest weighted
615
+ * type for.
616
+ *
617
+ * @return int The highest weighted token.
618
+ */
619
+ public static function getHighestWeightedToken(array $tokens)
620
+ {
621
+ $highest = -1;
622
+ $highestType = false;
623
+
624
+ $weights = self::$weightings;
625
+
626
+ foreach ($tokens as $token) {
627
+ if (isset($weights[$token]) === true) {
628
+ $weight = $weights[$token];
629
+ } else {
630
+ $weight = 0;
631
+ }
632
+
633
+ if ($weight > $highest) {
634
+ $highest = $weight;
635
+ $highestType = $token;
636
+ }
637
+ }
638
+
639
+ return $highestType;
640
+
641
+ }//end getHighestWeightedToken()
642
+
643
+
644
+ }//end class
vendor/phpqrcode/qrvect.php CHANGED
@@ -142,7 +142,7 @@
142
  $vect = self::vectSVG($frame, $pixelPerPoint, $outerFrame, $back_color, $fore_color);
143
 
144
  if ($filename === false) {
145
- //@header("Content-Type: image/svg+xml");
146
  //header('Content-Disposition: attachment, filename="qrcode.svg"');
147
  echo $vect;
148
  } else {
142
  $vect = self::vectSVG($frame, $pixelPerPoint, $outerFrame, $back_color, $fore_color);
143
 
144
  if ($filename === false) {
145
+ //header("Content-Type: image/svg+xml");
146
  //header('Content-Disposition: attachment, filename="qrcode.svg"');
147
  echo $vect;
148
  } else {
wp-defender.php CHANGED
@@ -3,7 +3,7 @@
3
  /**
4
  * Plugin Name: Defender
5
  * Plugin URI: https://premium.wpmudev.org/project/wp-defender/
6
- * Version: 2.1.2
7
  * Description: Get regular security scans, vulnerability reports, safety recommendations and customized hardening for your site in just a few clicks. Defender is the analyst and enforcer who never sleeps.
8
  * Author: WPMU DEV
9
  * Author URI: http://premium.wpmudev.org/
@@ -119,7 +119,7 @@ class WP_Defender_Free {
119
  $this->global['bootstrap'] = new WD_Legacy_Activator( $this );
120
  }
121
  //for the new SUI
122
- add_filter( 'admin_body_class', array( &$this, 'adminBodyClasses' ) );
123
  do_action(
124
  'wpmudev-recommended-plugins-register-notice',
125
  plugin_basename( __FILE__ ), // Plugin basename
@@ -173,7 +173,7 @@ class WP_Defender_Free {
173
  }
174
 
175
  public function adminBodyClasses( $classes ) {
176
- $classes .= ' sui-2-3-20 ';
177
 
178
  return $classes;
179
  }
3
  /**
4
  * Plugin Name: Defender
5
  * Plugin URI: https://premium.wpmudev.org/project/wp-defender/
6
+ * Version: 2.1.4
7
  * Description: Get regular security scans, vulnerability reports, safety recommendations and customized hardening for your site in just a few clicks. Defender is the analyst and enforcer who never sleeps.
8
  * Author: WPMU DEV
9
  * Author URI: http://premium.wpmudev.org/
119
  $this->global['bootstrap'] = new WD_Legacy_Activator( $this );
120
  }
121
  //for the new SUI
122
+ add_filter( 'admin_body_class', array( &$this, 'adminBodyClasses' ), 20 );
123
  do_action(
124
  'wpmudev-recommended-plugins-register-notice',
125
  plugin_basename( __FILE__ ), // Plugin basename
173
  }
174
 
175
  public function adminBodyClasses( $classes ) {
176
+ $classes .= ' sui-2-3-22 ';
177
 
178
  return $classes;
179
  }