PluginProbe ʕ •ᴥ•ʔ
Widget Options – Advanced Conditional Visibility for Gutenberg Blocks & Classic Widgets / 4.0.9
Widget Options – Advanced Conditional Visibility for Gutenberg Blocks & Classic Widgets v4.0.9
4.2.5 4.2.4 trunk 3.7.10 3.7.11 3.7.12 3.7.13 3.7.14 3.7.2 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8 3.8.1 3.8.10 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.8.8 3.8.9 3.8.9.1 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.5.1 4.0.6 4.0.6.1 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.2 4.1.3 4.2.0 4.2.1 4.2.2 4.2.3
widget-options / includes / extras.php
widget-options / includes Last commit date
admin 1 year ago pagebuilders 1 year ago widgets 1 year ago ajax-functions.php 1 year ago extras.php 1 year ago install.php 2 years ago scripts.php 1 year ago transient.php 3 years ago
extras.php
902 lines
1 <?php
2
3 /**
4 * Extra Functions
5 *
6 * Collections of extra functions to avoid repeatition
7 *
8 * @copyright Copyright (c) 2016, Jeffrey Carandang
9 * @since 4.0
10 */
11
12 function widgetopts_sanitize_array(&$array)
13 {
14 foreach ($array as &$value) {
15 if (!is_array($value)) {
16 // sanitize if value is not an array
17 $value = sanitize_text_field($value);
18 } else {
19 // go inside this function again
20 widgetopts_sanitize_array($value);
21 }
22 }
23
24 return $array;
25 }
26
27 function widgetopts_is_checked($array, $key)
28 {
29 return (isset($array[$key]) && '1' == $array[$key]) ? 'checked="checked"' : '';
30 }
31
32 /*
33 * Check if http or https available on link
34 */
35 function widgetopts_addhttp($url)
36 {
37 if (!preg_match("~^(?:f|ht)tps?://~i", $url)) {
38 $url = "http://" . $url;
39 }
40 return $url;
41 }
42
43
44 /**
45 * Register Global Variables for easier access
46 *
47 *
48 * @since 5.0
49 * @return array
50 */
51 function widgetopts_global_taxonomies()
52 {
53 $taxonomies = get_option('widgetopts_global_taxonomies');
54
55 if (empty($taxonomies)) {
56
57 $tax_args = array(
58 'public' => true
59 );
60 $tax_output = 'objects'; // or objects
61 $tax_operator = 'and'; // 'and' or 'or'
62 $taxonomies = get_taxonomies($tax_args, $tax_output, $tax_operator);
63 unset($taxonomies['post_format']);
64
65 // Let's let devs alter that value coming in
66 $taxonomies = apply_filters('widgetopts_update_global_taxonomies', $taxonomies);
67 update_option('widgetopts_global_taxonomies', $taxonomies);
68 }
69
70 return apply_filters('widgetopts_get_global_taxonomies', $taxonomies);
71 }
72
73 function widgetopts_global_types()
74 {
75 /*$types = get_option( 'widgetopts_global_types' );
76 if( empty( $types ) ) {
77 $types = get_post_types( array(
78 'public' => true,
79 ), 'object' );
80 // Let's let devs alter that value coming in
81 $types = apply_filters( 'widgetopts_update_global_types', $types );
82 update_option( 'widgetopts_global_types', $types );
83 }*/
84
85 $types = get_post_types(array('public' => true), 'object');
86 $types = apply_filters('widgetopts_update_global_types', $types);
87
88 return apply_filters('widgetopts_get_global_types', $types);
89 }
90
91 function widgetopts_global_pages()
92 {
93 $pages = get_option('widgetopts_global_all_pages');
94
95 //old pages object
96 // if( empty( $pages ) ) {
97 // $pages = get_posts( array(
98 // 'post_type' => 'page',
99 // 'post_status' => 'publish',
100 // 'numberposts' => -1,
101 // 'orderby' => 'title',
102 // 'order' => 'ASC',
103 // 'fields' => array('ID', 'name')
104 // ));
105 //
106 // // Let's let devs alter that value coming in
107 // $pages = apply_filters( 'widgetopts_update_global_pages', $pages );
108 // update_option( 'widgetopts_global_pages', $pages );
109 // }
110
111 //create new pages object
112 if (empty($pages)) {
113 global $wpdb;
114
115 $pages = $wpdb->get_results("SELECT ID, post_title, post_parent FROM $wpdb->posts WHERE post_type = 'page' AND post_status = 'publish' ORDER BY post_title ASC ");
116
117 // Let's let devs alter that value coming in
118 $pages = apply_filters('widgetopts_update_global_pages', $pages);
119 update_option('widgetopts_global_all_pages', $pages);
120 }
121
122 return apply_filters('widgetopts_get_global_pages', $pages);
123 }
124
125 function widgetopts_global_categories()
126 {
127 $categories = get_option('widgetopts_global_categories');
128
129 if (empty($categories)) {
130 $categories = get_categories(array(
131 'hide_empty' => false
132 ));
133
134 // Let's let devs alter that value coming in
135 $categories = apply_filters('widgetopts_update_global_categories', $categories);
136 update_option('widgetopts_global_categories', $categories);
137 }
138
139 return apply_filters('widgetopts_global_categories', $categories);
140 }
141
142 /*
143 Page Walker Class
144 */
145 if (!class_exists('WidgetOpts_Pages_Checkboxes')) :
146 class WidgetOpts_Pages_Checkboxes extends Walker_Page
147 {
148
149 function start_lvl(&$output, $depth = 0, $args = array())
150 {
151 $output .= "\n<div class='widgetopts-chldrn'>\n";
152 }
153
154 function end_lvl(&$output, $depth = 0, $args = array())
155 {
156 $output .= "</div>\n";
157 }
158
159 function start_el(&$output, $page, $depth = 0, $args = array(), $current_page = 0)
160 {
161 if ($depth) {
162 $indent = str_repeat('&mdash; ', $depth);
163 } else {
164 $indent = '';
165 }
166
167
168
169 if ('' === $page->post_title) {
170 $page->post_title = sprintf(__('#%d (no title)', 'widget-options'), $page->ID);
171 }
172
173 $pages_values = array();
174 if (isset($args['params']['visibility']['pages'])) {
175 $pages_values = $args['params']['visibility']['pages'];
176 }
177
178 if (isset($pages_values[$page->ID]) && $pages_values[$page->ID] == '1') {
179 $checked = 'checked="checked"';
180 } else {
181 $checked = '';
182 }
183
184 $output .= '<p>' . $indent;
185
186 $output .= '<input type="checkbox" name="' . $args['namespace'] . '[extended_widget_opts][visibility][pages][' . $page->ID . ']" id="' . $args['id'] . '-opts-pages-' . $page->ID . '" value="1" ' . $checked . '/>';
187
188 $output .= '<label for="' . $args['id'] . '-opts-pages-' . $page->ID . '">' . $page->post_title . '</label>';
189 }
190
191 function end_el(&$output, $page, $depth = 0, $args = array())
192 {
193 $output .= "</p>\n";
194 }
195 }
196 endif;
197
198 function widgetopts_set_http_headers()
199 {
200 $httpheaders = [];
201 foreach ($_SERVER as $key => $value) {
202 if (substr($key, 0, 5) === 'HTTP_') {
203 $httpheaders[$key] = $value;
204 }
205 }
206 return $httpheaders;
207 }
208
209 /**
210 * Checks if the request is coming from a mobile device based on HTTP headers.
211 *
212 * @return bool True if the request is from a mobile device, false otherwise.
213 */
214 function widgetopts_is_mobile()
215 {
216 global $widgetopts_http_headers;
217
218 // Define mobile headers and their corresponding values
219 $mobile_headers = [
220 'HTTP_ACCEPT' => ['values' => ['application/x-obml2d', 'application/vnd.rim.html', 'text/vnd.wap.wml', 'application/vnd.wap.xhtml+xml']],
221 'HTTP_UA_CPU' => ['values' => ['ARM']],
222 'HTTP_X_WAP_PROFILE' => null,
223 'HTTP_PROFILE' => null,
224 'HTTP_X_HUAWEI_USERID' => null,
225 'HTTP_X_WAP_CLIENTID' => null,
226 'HTTP_WAP_CONNECTION' => null,
227 'HTTP_X_OPERAMINI_PHONE_UA' => null,
228 'HTTP_X_NOKIA_GATEWAY_ID' => null,
229 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null,
230 'HTTP_X_ORANGE_ID' => null,
231 'HTTP_X_ATT_DEVICEID' => null,
232 'HTTP_UA_OS' => null,
233 'HTTP_X_MOBILE_GATEWAY' => null,
234 ];
235
236 // Check each mobile header for a match
237 foreach ($mobile_headers as $key => $value) {
238 if (isset($widgetopts_http_headers[$key])) {
239 if (isset($value['values']) && is_array($value['values'])) {
240 foreach ($value['values'] as $_match) {
241 if (strpos($widgetopts_http_headers[$key], $_match) !== false) {
242 return true; // Found a match, request is from a mobile device
243 }
244 }
245 } else {
246 return true; // Found a match, request is from a mobile device
247 }
248 }
249 }
250
251 // If no match is found, try another method
252 return widgetopts_is_mobile_or_tablet();
253 }
254
255 function widgetopts_is_mobile_or_tablet($tablet_only = false)
256 {
257 global $widgetopts_user_agent;
258 $user_agent = $widgetopts_user_agent;
259
260 // Check for common mobile and tablet User-Agent patterns
261 $mobile_patterns = array(
262 '/android/i',
263 '/iphone|ipod/i',
264 '/blackberry/i',
265 '/iemobile/i',
266 '/windows phone/i',
267 '/opera mini/i',
268 '/mobile safari/i'
269 );
270
271 $tablet_patterns = array(
272 '/ipad/i',
273 '/android(?!.*mobile)/i',
274 '/kindle|silk/i',
275 '/playbook/i',
276 '/tablet/i'
277 );
278
279 if ($tablet_only === false) {
280 // Check if the User-Agent matches any of the mobile patterns
281 foreach ($mobile_patterns as $pattern) {
282 if (preg_match($pattern, $user_agent)) {
283 return true; // Request is from a mobile device
284 }
285 }
286 }
287
288 // Check if the User-Agent matches any of the tablet patterns
289 foreach ($tablet_patterns as $pattern) {
290 if (preg_match($pattern, $user_agent)) {
291 return true; // Request is from a tablet device
292 }
293 }
294
295 // Additional checks for specific tablet devices or browsers
296 if (stripos($user_agent, 'Macintosh') !== false && stripos($user_agent, 'iPad') !== false) {
297 return true; // Request is from an iPad
298 }
299
300 return false; // Request is neither from a mobile nor tablet device (default to desktop)
301 }
302
303 /**
304 * Check if the device is tablet.
305 * Returns true if any type of tablet device detected
306 * @return bool
307 */
308 function widgetopts_is_tablet()
309 {
310 global $widgetopts_user_agent;
311
312 $tablets = array(
313 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2',
314 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',
315 'GoogleTablet' => 'Android.*Pixel C',
316 'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)',
317 'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\b|W3-810|\bA3-A10\b|\bA3-A11\b|\bA3-A20\b|\bA3-A30|A3-A40',
318 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-T116BU|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y?|SM-T280|SM-T817A|SM-T820|SM-W700|SM-P580|SM-T587|SM-P350|SM-P555M|SM-P355M|SM-T113NU|SM-T815Y|SM-T585|SM-T285|SM-T825|SM-W708|SM-T835|SM-T830|SM-T837V|SM-T720|SM-T510|SM-T387V|SM-P610|SM-T290|SM-T515|SM-T590|SM-T595|SM-T725|SM-T817P|SM-P585N0|SM-T395|SM-T295|SM-T865|SM-P610N|SM-P615|SM-T970|SM-T380|SM-T5950|SM-T905|SM-T231|SM-T500|SM-T860|SM-T536|SM-T837A|SM-X200|SM-T220|SM-T870|SM-X906C',
319 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI|KFFOWI|KFGIWI|KFMEWI)\b|Android.*Silk/[0-9.]+ like Chrome/[0-9.]+ (?!Mobile)',
320 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)',
321 'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10',
322 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|\bK00C\b|\bK00E\b|\bK00L\b|TX201LA|ME176C|ME102A|\bM80TA\b|ME372CL|ME560CG|ME372CG|ME302KL| K01A | K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\bME70C\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z|\bP027\b|\bP024\b|\bP00C\b',
323 'BlackBerryTablet' => 'PlayBook|RIM Tablet',
324 'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410',
325 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
326 'LGTablet' => '\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\b',
327 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b',
328 'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002',
329 'LenovoTablet' => 'Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-850M|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)|TB-X103F|TB-X304X|TB-X304F|TB-X304L|TB-X505F|TB-X505L|TB-X505X|TB-X605F|TB-X605L|TB-8703F|TB-8703X|TB-8703N|TB-8704N|TB-8704F|TB-8704X|TB-8704V|TB-7304F|TB-7304I|TB-7304X|Tab2A7-10F|Tab2A7-20F|TB2-X30L|YT3-X50L|YT3-X50F|YT3-X50M|YT-X705F|YT-X703F|YT-X703L|YT-X705L|YT-X705X|TB2-X30F|TB2-X30L|TB2-X30M|A2107A-F|A2107A-H|TB3-730F|TB3-730M|TB3-730X|TB-7504F|TB-7504X|TB-X704F|TB-X104F|TB3-X70F|TB-X705F|TB-8504F|TB3-X70L|TB3-710F|TB-X704L|TB-J606F|TB-X606F|TB-X306X|YT-J706X',
330 'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7',
331 'XiaomiTablet' => '21051182G',
332 'iPad' => 'iPad|iPad.*Mobile',
333 'YarvikTablet' => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b',
334 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
335 'ArnovaTablet' => '97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2',
336 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004',
337 'IRUTablet' => 'M702pro',
338 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b',
339 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)',
340 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',
341 'ArchosTablet' => '\b(101G9|80G9|A101IT)\b|Qilive 97R|Archos5|\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|c|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\b',
342 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark',
343 'NokiaLumiaTablet' => 'Lumia 2520',
344 'SonyTablet' => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP641|SGP612|SOT31|SGP771|SGP611|SGP612|SGP712',
345 'PhilipsTablet' => '\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\b',
346 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
347 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
348 'MIDTablet' => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10',
349 'MSITablet' => 'MSI \b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\b',
350 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
351 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b',
352 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
353 'FlyTablet' => 'IQ310|Fly Vision',
354 'bqTablet' => 'Android.*(bq)?.*\b(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris ([E|M]10|M8))\b|Maxwell.*Lite|Maxwell.*Plus',
355 'HuaweiTablet' => 'MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim|M2-A01L|BAH-L09|BAH-W09|AGS-L09|CMR-AL19|KOB2-L09|BG2-U01|BG2-W09|BG2-U03',
356 'NecTablet' => '\bN-06D|\bN-08D',
357 'PantechTablet' => 'Pantech.*P4100',
358 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
359 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b',
360 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b',
361 'ZyncTablet' => 'z1000|Z99 2G|z930|z990|z909|Z919|z900',
362 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
363 'NabiTablet' => 'Android.*\bNabi',
364 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build',
365 'TexetTablet' => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE',
366 'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
367 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab',
368 'AdvanTablet' => 'Android.* \b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\b ',
369 'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1',
370 'GalapadTablet' => 'Android [0-9.]+; [a-z-]+; \bG1\b',
371 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b',
372 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b',
373 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide',
374 'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b',
375 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026',
376 'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503',
377 'GUTablet' => 'TX-A1301|TX-M9002|Q702|kf026',
378 'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10',
379 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)|Qualcore 1027',
380 'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync',
381 'DPSTablet' => 'DPS Dream 9|DPS Dual 7',
382 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10',
383 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989',
384 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b',
385 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan',
386 'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042',
387 'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003',
388 'VoninoTablet' => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b',
389 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1',
390 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab',
391 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497|VFD 1400',
392 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2',
393 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711',
394 'iMobileTablet' => 'i-mobile i-note',
395 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine',
396 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b',
397 'AMPETablet' => 'Android.* A78 ',
398 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)',
399 'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI',
400 'TecnoTablet' => 'TECNO P9|TECNO DP8D',
401 'JXDTablet' => 'Android.* \b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\b',
402 'iJoyTablet' => 'Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)',
403 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10',
404 'XoroTablet' => 'KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151',
405 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a',
406 'VerizonTablet' => 'QTAQZ3|QTAIR7|QTAQTZ3|QTASUN1|QTASUN2|QTAXIA1',
407 'OdysTablet' => 'LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\bXELIO\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10',
408 'CaptivaTablet' => 'CAPTIVA PAD',
409 'KocasoTablet' => '\b(TB-1207)\b',
410 'HisenseTablet' => '\b(F5281|E2371)\b',
411 'IconbitTablet' => 'NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S',
412 'TeclastTablet' => 'T98 4G|\bP80\b|\bX90HD\b|X98 Air|X98 Air 3G|\bX89\b|P80 3G|\bX80h\b|P98 Air|\bX89HD\b|P98 3G|\bP90HD\b|P89 3G|X98 3G|\bP70h\b|P79HD 3G|G18d 3G|\bP79HD\b|\bP89s\b|\bA88\b|\bP10HD\b|\bP19HD\b|G18 3G|\bP78HD\b|\bA78\b|\bP75\b|G17s 3G|G17h 3G|\bP85t\b|\bP90\b|\bP11\b|\bP98t\b|\bP98HD\b|\bG18d\b|\bP85s\b|\bP11HD\b|\bP88s\b|\bA80HD\b|\bA80se\b|\bA10h\b|\bP89\b|\bP78s\b|\bG18\b|\bP85\b|\bA70h\b|\bA70\b|\bG17\b|\bP18\b|\bA80s\b|\bA11s\b|\bP88HD\b|\bA80h\b|\bP76s\b|\bP76h\b|\bP98\b|\bA10HD\b|\bP78\b|\bP88\b|\bA11\b|\bA10t\b|\bP76a\b|\bP76t\b|\bP76e\b|\bP85HD\b|\bP85a\b|\bP86\b|\bP75HD\b|\bP76v\b|\bA12\b|\bP75a\b|\bA15\b|\bP76Ti\b|\bP81HD\b|\bA10\b|\bT760VE\b|\bT720HD\b|\bP76\b|\bP73\b|\bP71\b|\bP72\b|\bT720SE\b|\bC520Ti\b|\bT760\b|\bT720VE\b|T720-3GE|T720-WiFi',
413 'OndaTablet' => '\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\b[\s]+|V10 \b4G\b',
414 'JaytechTablet' => 'TPC-PA762',
415 'TelstraTablet' => 'T-Hub2',
416 'BlaupunktTablet' => 'Endeavour 800NG|Endeavour 1010',
417 'Hudl' => 'Hudl HT7S3|Hudl 2',
418 'DigmaTablet' => '\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\b',
419 'EvolioTablet' => 'ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\bEvotab\b|\bNeura\b',
420 'LavaTablet' => 'QPAD E704|\bIvoryS\b|E-TAB IVORY|\bE-TAB\b',
421 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\bM6pro\b|CT1020W|arc 10HD|\bTP750\b|\bQTAQZ3\b|WVT101|TM1088|KT107',
422 'AocTablet' => 'MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712',
423 'PocketBookTablet' => 'Pocketbook',
424 'MpmanTablet' => 'MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\bMPG7\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010',
425 'CelkonTablet' => 'CT695|CT888|CT[\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\bCT-1\b',
426 'WolderTablet' => 'miTab \b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\b',
427 'MediacomTablet' => 'M-MPI10C3G|M-SP10EG|M-SP10EGP|M-SP10HXAH|M-SP7HXAH|M-SP10HXBH|M-SP8HXAH|M-SP8MXA',
428 'MiTablet' => '\bMI PAD\b|\bHM NOTE 1W\b',
429 'UbislateTablet' => 'UbiSlate[\s]?7C',
430 'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One',
431 'LeaderTablet' => 'TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100',
432 );
433
434 $is_tablet = false;
435 foreach ($tablets as $brand => $pattern) {
436 // Check if the tablet matches the current brand's pattern
437 if (preg_match('#' . $pattern . '#i', $widgetopts_user_agent)) {
438 // Tablet matched, so echo the brand
439 $is_tablet = true;
440 break;
441 }
442 }
443
444 // If no match is found, try another method, check only the most common keyword
445 if (!$is_tablet) {
446 $is_tablet = widgetopts_is_mobile_or_tablet(true);
447 }
448
449 return $is_tablet;
450 }
451
452 /**
453 * Retrieves the user agent string from HTTP headers.
454 *
455 * @return string The concatenated user agent string.
456 */
457 function widgetopts_get_user_agent()
458 {
459 global $widgetopts_http_headers;
460
461 $user_agent = '';
462
463 // Define the user agent headers to check
464 $user_agents = [
465 'HTTP_USER_AGENT',
466 'HTTP_X_ORIGINAL_USER_AGENT',
467 'HTTP_X_OPERAMINI_PHONE_UA',
468 'HTTP_X_BOLT_PHONE_UA',
469 'HTTP_X_DEVICE_USER_AGENT',
470 'HTTP_X_SKYFIRE_PHONE',
471 'HTTP_X_UCBROWSER_DEVICE_UA',
472 'HTTP_DEVICE_STOCK_UA',
473 ];
474
475 // Concatenate user agents from available headers
476 foreach ($user_agents as $ua) {
477 if (isset($widgetopts_http_headers[$ua]) && !empty($widgetopts_http_headers[$ua])) {
478 $user_agent .= $widgetopts_http_headers[$ua] . " ";
479 }
480 }
481
482 return trim($user_agent); // Trim the concatenated user agent string and return
483 }
484
485 /**
486 * Safely evaluates a boolean expression and prevents any output from being printed.
487 *
488 * This function uses eval() to evaluate the provided expression. It performs
489 * basic validation to ensure that the expression consists of valid boolean logic.
490 * Output generated by the eval() is suppressed using output buffering.
491 *
492 * @param string $expression The boolean expression to evaluate.
493 * @return bool Returns true or false based on the evaluated expression, or false on error.
494 */
495 function widgetopts_safe_eval($expression)
496 {
497 // List of potentially harmful patterns
498 $dangerous_patterns = [
499 // Database-related keywords
500 '/\binsert\b/i',
501 '/\bupdate\b/i',
502 '/\bdelete\b/i',
503 '/\breplace\b/i',
504 '/\bselect\b/i',
505 '/\bdrop\b/i',
506 '/\balter\b/i',
507 '/\btruncate\b/i',
508 '/\bgrant\b/i/',
509 '/\brevoke\b/i/',
510
511 // WordPress-specific database functions
512 '/\bwp_insert_post\b/i',
513 '/\bwp_update_post\b/i',
514 '/\bwp_delete_post\b/i',
515 '/\bwp_insert_user\b/i',
516 '/\bwp_update_user\b/i',
517 '/\bwp_delete_user\b/i',
518 '/\badd_option\b/i',
519 '/\bupdate_option\b/i',
520 '/\bdelete_option\b/i',
521 '/\bwpdb\b/i',
522
523 // JavaScript, CSS, and HTML
524 '/<script\b[^>]*>(.*?)<\/script>/i',
525 '/<style\b[^>]*>(.*?)<\/style>/i',
526
527 // PHP file manipulation functions
528 '/\bfile_put_contents\b/i',
529 '/\bfile_get_contents\b/i',
530 '/\bfopen\b/i',
531 '/\bfwrite\b/i',
532 '/\bunlink\b/i',
533 '/\brename\b/i',
534 '/\bchmod\b/i',
535 '/\bchown\b/i',
536 '/\bchgrp\b/i',
537 '/\bcopy\b/i',
538 '/\bscandir\b/i',
539
540 // External connections
541 '/\bwp_remote_get\b/i',
542 '/\bwp_remote_post\b/i',
543 '/\bcurl_init\b/i',
544 '/\bcurl_exec\b/i',
545 '/\bcurl_setopt\b/i',
546
547 // Reflection and dynamic variable/function manipulation
548 '/\bReflectionClass\b/i',
549 '/\bReflectionMethod\b/i',
550 '/\bReflectionProperty\b/i',
551 '/\bcall_user_func\b/i',
552 '/\bcall_user_func_array\b/i',
553 '/\bextract\b/i',
554 '/\bparse_str\b/i',
555
556 // System commands
557 '/\beval\b/i', // Evaluating PHP code
558 '/\bsystem\b/i', // Executing system commands
559 '/\bexec\b/i', // Executing system commands
560 '/\bpopen\b/i', // Open a process file pointer
561 '/\bpassthru\b/i', // Passes data from the command line to the output
562 '/\bshell_exec\b/i', // Executing shell commands
563 '/\bproc_open\b/i', // Opens a process with a command
564 '/\bproc_close\b/i', // Closes a process
565 '/\bproc_get_status\b/i', // Gets the status of a process
566
567 // File manipulation commands (system-level)
568 '/\bchmod\b/i', // Changing file permissions
569 '/\bchown\b/i', // Changing file ownership
570 '/\blchown\b/i', // Changing file ownership (local)
571 '/\bdump\b/i', // Dumping file contents
572 '/\bzip\b/i', // Executing zipping commands
573 '/\btar\b/i', // Executing tar commands
574 '/\bgzip\b/i', // Executing gzip commands
575
576 // Remote execution functions
577 '/\bopen_basedir\b/i', // Access control on file paths
578 '/\bfsockopen\b/i', // Opening a socket connection
579 '/\bproc_nice\b/i', // Adjusting process priority
580 '/\bstream_socket_server\b/i', // Creating socket server
581 '/\bstream_socket_client\b/i', // Creating socket client
582
583 // Dangerous PHP and WordPress specific functions
584 '/\bwp_insert_post\b/i', // Inserting posts programmatically
585 '/\bwp_update_post\b/i', // Updating posts programmatically
586 '/\bwp_delete_post\b/i', // Deleting posts programmatically
587 '/\bwp_insert_user\b/i', // Inserting users programmatically
588 '/\bwp_update_user\b/i', // Updating users programmatically
589 '/\bwp_delete_user\b/i', // Deleting users programmatically
590 '/\badd_option\b/i', // Adding options to database
591 '/\bupdate_option\b/i', // Updating options in the database
592 '/\bdelete_option\b/i', // Deleting options from the database
593 '/\bwpdb\b/i', // Direct access to database with WP_DB class
594 ];
595
596 $return = true;
597 // Pattern matching
598 foreach ($dangerous_patterns as $pattern) {
599 if (preg_match($pattern, $expression)) {
600 $return = false;
601 break;
602 }
603 }
604
605 if ($return === false) {
606 return $return;
607 }
608
609 $allowed_php_functions = [
610 // String Manipulation
611 'strlen',
612 'substr',
613 'strtolower',
614 'strtoupper',
615 'trim',
616 'ltrim',
617 'rtrim',
618 'str_replace',
619 'str_ireplace',
620 'preg_replace',
621 'preg_match',
622 'explode',
623 'implode',
624 'htmlspecialchars',
625 'htmlentities',
626 'strip_tags',
627
628 // Array Manipulation
629 'array_merge',
630 'array_diff',
631 'array_filter',
632 'array_map',
633 'array_keys',
634 'array_values',
635 'in_array',
636 'count',
637 'sizeof',
638 'array_slice',
639 'array_push',
640 'array_pop',
641
642 // Math Functions
643 'abs',
644 'round',
645 'floor',
646 'ceil',
647 'min',
648 'max',
649 'pow',
650 'sqrt',
651
652 // Date/Time
653 'time',
654 'date',
655 'strtotime',
656 'mktime',
657 'checkdate',
658
659 // JSON Functions
660 'json_decode',
661
662 // Variable Handling
663 'isset',
664 'empty',
665 'unset',
666 'is_array',
667 'is_bool',
668 'is_callable',
669 'is_countable',
670 'is_double',
671 'is_float',
672 'is_int',
673 'is_integer',
674 'is_iterable',
675 'is_long',
676 'is_null',
677 'is_numeric',
678 'is_object',
679 'is_real',
680 'is_scalar',
681 'is_string',
682 'is_subclass_of',
683 'is_uploaded_file',
684 'is_writable',
685 'is_readable',
686 'is_dir',
687 'is_file',
688 'is_link',
689 'intval',
690 'strval',
691 'floatval',
692 'doubleval',
693 'boolval',
694
695 // File Operations (Read-Only)
696 'filesize',
697 'pathinfo',
698 'basename',
699 'dirname',
700 ];
701
702 $allowed_wp_functions = [
703 // Database Operations
704 'get_option',
705 'get_post',
706 'get_user_meta',
707 'get_bloginfo',
708 'get_theme_mod',
709
710 // Escaping and Sanitizing
711 'esc_url',
712 'esc_html',
713 'esc_attr',
714 'esc_js',
715 'sanitize_text_field',
716 'sanitize_email',
717 'sanitize_title',
718 'sanitize_key',
719
720 // URL and Links
721 'get_permalink',
722 'get_home_url',
723 'get_site_url',
724 'get_admin_url',
725 'wp_parse_url',
726
727 // Security and Authentication
728 'wp_verify_nonce',
729 'check_admin_referer',
730 'current_user_can',
731 'is_user_logged_in',
732
733 // Formatting
734 'wp_kses',
735 'wp_kses_post',
736
737 // Retrieval of Metadata and Post Details
738 'get_post_meta',
739 'get_page_template_slug',
740 'get_the_author_meta',
741 'get_the_terms',
742 'get_comments',
743 'get_category',
744 'get_terms',
745 'get_nav_menu_locations',
746 'get_posts',
747 'get_post_status',
748 'get_comment_meta',
749 'get_taxonomy',
750 'get_object_taxonomies',
751
752 // Plugins and Themes
753 'is_plugin_active',
754 'get_plugins',
755 'get_theme_support',
756
757 // Utilities
758 'wp_generate_uuid4',
759
760 // User and Authentication
761 'get_userdata',
762 'get_user_by',
763 'get_users',
764 'get_author_posts_url',
765 'get_user_roles',
766 'get_users_by_role',
767
768 // Media and Files
769 'wp_get_attachment_image_src',
770 'wp_get_attachment_url',
771 'wp_get_attachment_metadata',
772 'wp_get_attachment_image',
773 'wp_get_attachment_thumb_url',
774
775 // File Handling
776 'wp_get_upload_dir',
777 'wp_handle_upload',
778 'wp_check_filetype_and_ext',
779 'wp_get_file_upload_url',
780
781 // Taxonomies
782 'get_term_meta',
783 'get_the_category_list',
784 'get_the_tag_list',
785 'get_the_term_list',
786
787 // Checking Functions
788 'is_admin',
789 'is_network_admin',
790 'is_main_query',
791 'is_single',
792 'is_singular',
793 'is_category',
794 'is_tag',
795 'is_page',
796 'is_front_page',
797 'is_home',
798 'is_attachment',
799 'is_archive',
800 'is_date',
801 'is_year',
802 'is_month',
803 'is_day',
804 'is_author',
805 'is_search',
806 'is_404',
807 'is_multisite',
808 'is_customize_preview',
809 ];
810
811 $allowed_functions = array_merge($allowed_php_functions, $allowed_wp_functions);
812
813 // Ensure the expression only uses allowed functions
814 $is_safe = widgetopts_validate_code_with_tokens($expression, $allowed_functions);
815
816 if (!$is_safe) {
817 return false;
818 }
819
820 if (stristr($expression, "return") === false) {
821 $expression = "return (" . $expression . ");";
822 }
823
824 ob_start();
825 try {
826 $result = (bool) (@eval($expression));
827 } catch (\Exception $e) {
828 $result = false;
829 } catch (\Error $e) {
830 $result = false;
831 } catch (\ParseError $e) {
832 $result = false;
833 } catch (\Throwable $e) {
834 $result = false;
835 }
836 ob_end_clean();
837
838 return $result;
839 }
840
841 /**
842 * Validate the given PHP code against allowed functions and detect obfuscated or dynamic function calls.
843 *
844 * @param string $code The PHP code to validate.
845 * @param array $allowed_functions List of explicitly allowed functions.
846 * @return bool Returns true if the code is considered safe, false otherwise.
847 */
848 function widgetopts_validate_code_with_tokens($code, $allowed_functions)
849 {
850 $tokens = token_get_all("<?php " . $code); // Add PHP opening tag for tokenization
851 $is_safe = true;
852
853 foreach ($tokens as $index => $token) {
854 if (is_array($token)) {
855 // Dynamic variable function call (e.g., $cmd())
856 if ($token[0] === T_VARIABLE) {
857 $next_token = $tokens[$index + 1] ?? null;
858 if ($next_token === '(') {
859 $is_safe = false;
860 break;
861 }
862 }
863
864 // Grouped dynamic variable function call (e.g., ($cmd)())
865 if ($token[0] === T_VARIABLE) {
866 $prev_token = $tokens[$index - 1] ?? null;
867 $next_token = $tokens[$index + 1] ?? null;
868
869 if (
870 $prev_token === '(' && // Opening parenthesis before the variable
871 $next_token === ')' && // Closing parenthesis after the variable
872 ($tokens[$index + 2] ?? null) === '(' // Function invocation immediately after
873 ) {
874 $is_safe = false;
875 break;
876 }
877 }
878
879 // Invalid callable like ('string')()
880 if ($token[0] === T_CONSTANT_ENCAPSED_STRING) {
881 $next_token = $tokens[$index + 1] ?? null;
882 if ($next_token === '(') {
883 $is_safe = false;
884 break;
885 }
886 }
887
888 // Disallowed functions
889 if ($token[0] === T_STRING) {
890 $function_name = $token[1];
891 $next_token = $tokens[$index + 1] ?? null;
892 if ($next_token === '(' && !in_array($function_name, $allowed_functions)) {
893 $is_safe = false;
894 break;
895 }
896 }
897 }
898 }
899
900 return $is_safe;
901 }
902