Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 108 |
|
0.00% |
0 / 17 |
CRAP | n/a |
0 / 0 |
|
| zeroBSCRM_textProcess | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| zeroBSCRM_textExpose | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| zeroBSCRM_preDBStr | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| zeroBSCRM_stripExceptLineBreaks | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
| jpcrm_sanitize_text_field_allow_whitespace | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| zeroBSCRM_strings_stripNonAlphaNumeric_dash | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| zeroBSCRM_strings_stripNonNumeric | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| jpcrm_is_int | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
42 | |||
| jpcrm_is_url | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| jpcrm_has_valid_tld | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
20 | |||
| jpcrm_url_with_scheme | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
| zeroBSCRM_validateEmail | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| zeroBSCRM_dataIO_postedArrayOfInts | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
| jpcrm_dataIO_file_path_seems_unsafe | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
20 | |||
| jpcrm_url_appears_to_match_site | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
| zeroBSCRM_segments_filterConditions | |
0.00% |
0 / 42 |
|
0.00% |
0 / 1 |
306 | |||
| zeroBSCRM_segments_unencodeConditions | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
42 | |||
| 1 | <?php |
| 2 | /* |
| 3 | * Jetpack CRM |
| 4 | * https://jetpackcrm.com |
| 5 | * V1.20 |
| 6 | * |
| 7 | * Copyright 2020 Automattic |
| 8 | * |
| 9 | * Date: 01/11/16 |
| 10 | */ |
| 11 | |
| 12 | defined( 'ZEROBSCRM_PATH' ) || exit( 0 ); |
| 13 | |
| 14 | /* |
| 15 | ====================================================== |
| 16 | Data Processing Functions |
| 17 | ====================================================== */ |
| 18 | |
| 19 | // Ensures storage and return as UTF8 without slashes |
| 20 | function zeroBSCRM_textProcess( $string = '' ) { |
| 21 | return htmlentities( stripslashes( $string ), ENT_QUOTES, 'UTF-8' ); |
| 22 | } |
| 23 | function zeroBSCRM_textExpose( $string = '' ) { |
| 24 | return html_entity_decode( $string, ENT_QUOTES, 'UTF-8' ); |
| 25 | } |
| 26 | |
| 27 | // hitting this issue |
| 28 | // https://core.trac.wordpress.org/ticket/43087 |
| 29 | // + |
| 30 | // https://core.trac.wordpress.org/ticket/32315#comment:43 |
| 31 | // (pasted emoji's in inputs (log text) would cause a silent wpdb error) |
| 32 | // so for now, passing any emoji-ridden text through here: |
| 33 | function zeroBSCRM_preDBStr( $string = '' ) { |
| 34 | |
| 35 | // encode emoji's - https://core.trac.wordpress.org/ticket/43087 |
| 36 | return wp_encode_emoji( $string ); |
| 37 | } |
| 38 | |
| 39 | // strips all except <br /> |
| 40 | function zeroBSCRM_stripExceptLineBreaks( $string = '' ) { |
| 41 | |
| 42 | // simplistic switchout. can surely be done more elegantly |
| 43 | $brs = array( '<br />', '<br>', '<br/>', '<BR />', '<BR>', '<BR/>' ); |
| 44 | $str = str_replace( $brs, '###BR###', $string ); |
| 45 | $str = wp_strip_all_tags( $str, 1 ); |
| 46 | $str = str_replace( '###BR###', '<br />', $str ); |
| 47 | |
| 48 | return $str; |
| 49 | } |
| 50 | |
| 51 | /* |
| 52 | * sanitize_text_field, but allows whitespace through :roll-eyes: |
| 53 | * https://developer.wordpress.org/reference/functions/sanitize_text_field/ |
| 54 | */ |
| 55 | function jpcrm_sanitize_text_field_allow_whitespace( $string = '' ) { |
| 56 | |
| 57 | $string = str_replace( ' ', '**WHITESPACE**', $string ); |
| 58 | $string = sanitize_text_field( $string ); |
| 59 | return str_replace( '**WHITESPACE**', ' ', $string ); |
| 60 | } |
| 61 | |
| 62 | // lol https://stackoverflow.com/questions/6063184/how-to-strip-all-characters-except-for-alphanumeric-and-underscore-and-dash |
| 63 | function zeroBSCRM_strings_stripNonAlphaNumeric_dash( $str = '' ) { |
| 64 | return preg_replace( '/[^a-z0-9_\-\s]+/i', '', $str ); |
| 65 | } |
| 66 | |
| 67 | // https://stackoverflow.com/questions/33993461/php-remove-all-non-numeric-characters-from-a-string |
| 68 | function zeroBSCRM_strings_stripNonNumeric( $str = '' ) { |
| 69 | return preg_replace( '/[^0-9]/', '', $str ); |
| 70 | } |
| 71 | |
| 72 | /* |
| 73 | ====================================================== |
| 74 | / Data Processing Functions |
| 75 | ====================================================== */ |
| 76 | |
| 77 | /* |
| 78 | ====================================================== |
| 79 | Data Validation Functions |
| 80 | ====================================================== */ |
| 81 | |
| 82 | /* |
| 83 | * Taking a variable, this function checks if it could be an int |
| 84 | * (returns true if is an int or a string which could be an int) |
| 85 | .. with a little help from my friends: https://stackoverflow.com/questions/2012187/how-to-check-that-a-string-is-an-int-but-not-a-double-etc |
| 86 | */ |
| 87 | function jpcrm_is_int( $var = false ) { |
| 88 | |
| 89 | // straight check |
| 90 | if ( is_int( $var ) ) { |
| 91 | return true; |
| 92 | } |
| 93 | |
| 94 | // string check |
| 95 | if ( is_string( $var ) ) { |
| 96 | |
| 97 | // catch negative |
| 98 | if ( str_starts_with( $var, '-' ) ) { |
| 99 | |
| 100 | // use ctype where available |
| 101 | if ( function_exists( 'ctype_digit' ) ) { |
| 102 | return ctype_digit( substr( $var, 1 ) ); |
| 103 | } else { |
| 104 | return is_numeric( $var ); |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | // use ctype_digit where available to check the string only contains digits |
| 109 | if ( function_exists( 'ctype_digit' ) ) { |
| 110 | return ctype_digit( $var ); |
| 111 | } else { |
| 112 | return is_numeric( $var ); |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | return false; |
| 117 | } |
| 118 | |
| 119 | /** |
| 120 | * Checks if a given string is a URL |
| 121 | * |
| 122 | * @param string $s Potential URL string. |
| 123 | * @param boolean $do_tld_check use TLD check instead of regex to confirm if it is a valid URL. |
| 124 | * |
| 125 | * @return boolean |
| 126 | */ |
| 127 | function jpcrm_is_url( $s, $do_tld_check = false ) { |
| 128 | if ( $do_tld_check ) { |
| 129 | return jpcrm_has_valid_tld( $s ); |
| 130 | } |
| 131 | return preg_match( '/^(https?:\/\/|www\.)\w+(\.\w+)*?(\/[^\s]*)?$/', $s ); |
| 132 | } |
| 133 | |
| 134 | /** |
| 135 | * Checks if host of a given URL is using a whitelisted TLD |
| 136 | * |
| 137 | * @param string $s URL string. |
| 138 | * @param array $valid_tlds List of approved TLDs. |
| 139 | * |
| 140 | * @return boolean |
| 141 | */ |
| 142 | function jpcrm_has_valid_tld( $s, $valid_tlds = array( '.com', '.net', '.org', '.edu', '.gov', '.co.uk' ) ) { |
| 143 | $host = wp_parse_url( jpcrm_url_with_scheme( $s ), PHP_URL_HOST ); |
| 144 | if ( ! $host ) { |
| 145 | return false; |
| 146 | } |
| 147 | foreach ( $valid_tlds as $tld ) { |
| 148 | if ( str_ends_with( $host, $tld ) ) { |
| 149 | return true; |
| 150 | } |
| 151 | } |
| 152 | return false; |
| 153 | } |
| 154 | |
| 155 | /** |
| 156 | * Adds a scheme to a URL string if it doesn't exist |
| 157 | * adapted from https://stackoverflow.com/a/14701491 |
| 158 | * |
| 159 | * @param string $s as a URL string. |
| 160 | * @param string $scheme as an optional default scheme. |
| 161 | */ |
| 162 | function jpcrm_url_with_scheme( $s, $scheme = 'https' ) { |
| 163 | return wp_parse_url( $s, PHP_URL_SCHEME ) === null ? $scheme . '://' . ltrim( $s, '/' ) : $s; |
| 164 | } |
| 165 | |
| 166 | #} Checks an email addr |
| 167 | function zeroBSCRM_validateEmail( $emailAddr ) { |
| 168 | |
| 169 | if ( filter_var( $emailAddr, FILTER_VALIDATE_EMAIL ) ) { |
| 170 | return true; |
| 171 | } |
| 172 | |
| 173 | return false; |
| 174 | } |
| 175 | |
| 176 | function zeroBSCRM_dataIO_postedArrayOfInts( $array = false ) { |
| 177 | |
| 178 | $ret = array(); |
| 179 | if ( is_array( $array ) ) { |
| 180 | $ret = $array; |
| 181 | } |
| 182 | |
| 183 | // sanitize |
| 184 | $ret = array_map( 'sanitize_text_field', $ret ); |
| 185 | $ret = array_map( 'intval', $ret ); |
| 186 | |
| 187 | return $ret; |
| 188 | } |
| 189 | |
| 190 | /* |
| 191 | * Checks file path doesn't use unsafe/undesirable protocols |
| 192 | */ |
| 193 | function jpcrm_dataIO_file_path_seems_unsafe( $file_path_string ) { |
| 194 | |
| 195 | // this one is important enough to be hard typed here #gh-2501 |
| 196 | if ( str_contains( $file_path_string, 'phar' ) ) { |
| 197 | return true; |
| 198 | } |
| 199 | |
| 200 | // these we block with their full string (unless we find a reason to open them up) |
| 201 | $blocked_protocols = array( 'file', 'http', 'ftp', 'php', 'zlib', 'data', 'glob', 'ssh2', 'rar', 'ogg', 'expect' ); |
| 202 | foreach ( $blocked_protocols as $protocol ) { |
| 203 | |
| 204 | if ( str_contains( $file_path_string, $protocol . '://' ) ) { |
| 205 | return true; |
| 206 | } |
| 207 | } |
| 208 | // this is only as accurate as what we know here and now (!) |
| 209 | return false; |
| 210 | } |
| 211 | |
| 212 | /** |
| 213 | * A check which does its best to ensure a URI is an url with the same root as existing site |
| 214 | * |
| 215 | * @param string $url_string A URL string. |
| 216 | * @param string $site_path The site path if applicable. |
| 217 | */ |
| 218 | function jpcrm_url_appears_to_match_site( $url_string, $site_path = '' ) { |
| 219 | $this_site_url = site_url( $site_path ); |
| 220 | if ( str_starts_with( $url_string, $this_site_url ) ) { |
| 221 | return true; |
| 222 | } |
| 223 | return false; |
| 224 | } |
| 225 | |
| 226 | /* |
| 227 | ====================================================== |
| 228 | / Data Validation Functions |
| 229 | ====================================================== */ |
| 230 | |
| 231 | /* |
| 232 | ====================================================== |
| 233 | Data Validation Functions: Segments |
| 234 | ====================================================== */ |
| 235 | |
| 236 | // filters out segment conditions (From anything passed) which are not 'safe' |
| 237 | // e.g. on our zeroBSCRM_segments_availableConditions() list |
| 238 | // ACCEPTS a POST arr |
| 239 | // $processCharacters dictates whether or not to pass strings through zeroBSCRM_textProcess |
| 240 | // ... only do so pre-save, not pre "preview" because this html encodes special chars. |
| 241 | // note $processCharacters now legacy/defunct. |
| 242 | function zeroBSCRM_segments_filterConditions( $conditions = array(), $processCharacters = true ) { |
| 243 | |
| 244 | if ( is_array( $conditions ) && count( $conditions ) > 0 ) { |
| 245 | |
| 246 | $approvedConditions = array(); |
| 247 | |
| 248 | $availableConditions = zeroBSCRM_segments_availableConditions(); |
| 249 | $availableConditionOperators = zeroBSCRM_segments_availableConditionOperators(); |
| 250 | |
| 251 | foreach ( $conditions as $c ) { |
| 252 | |
| 253 | // has proper props |
| 254 | if ( isset( $c['type'] ) && isset( $c['operator'] ) && isset( $c['value'] ) ) { |
| 255 | |
| 256 | // retrieve val |
| 257 | $val = $c['value']; |
| 258 | if ( $processCharacters ) { |
| 259 | $val = zeroBSCRM_textProcess( $val ); // only pre-saving |
| 260 | } |
| 261 | $val = sanitize_text_field( $val ); |
| 262 | |
| 263 | // conversions (e.g. date to uts) |
| 264 | $val = zeroBSCRM_segments_typeConversions( $val, $c['type'], $c['operator'], 'in' ); |
| 265 | |
| 266 | // okay. (passing only expected + validated) |
| 267 | $addition = array( |
| 268 | |
| 269 | 'type' => $c['type'], |
| 270 | 'operator' => $c['operator'], |
| 271 | 'value' => $val, |
| 272 | |
| 273 | ); |
| 274 | |
| 275 | // ranges: |
| 276 | |
| 277 | // int/floatval |
| 278 | if ( isset( $c['value2'] ) ) { |
| 279 | |
| 280 | // retrieve val2 |
| 281 | $val2 = $c['value2']; |
| 282 | if ( $processCharacters ) { |
| 283 | $val2 = zeroBSCRM_textProcess( $val2 ); // only pre-saving |
| 284 | } |
| 285 | $val2 = sanitize_text_field( $val2 ); |
| 286 | |
| 287 | $addition['value2'] = $val2; |
| 288 | |
| 289 | } |
| 290 | |
| 291 | // daterange || datetimerange |
| 292 | if ( |
| 293 | ( |
| 294 | $c['operator'] == 'daterange' |
| 295 | || |
| 296 | $c['operator'] == 'datetimerange' |
| 297 | ) |
| 298 | && ! empty( $val ) |
| 299 | ) { |
| 300 | |
| 301 | // hmmm what if peeps use ' - ' in their date formats? This won't work if they do! |
| 302 | if ( str_contains( $val, ' - ' ) ) { |
| 303 | |
| 304 | $dates = explode( ' - ', $val ); |
| 305 | if ( count( $dates ) === 2 ) { |
| 306 | |
| 307 | $local_date_time = new DateTime( $dates[0], wp_timezone() ); |
| 308 | $local_date_time->setTimezone( new DateTimeZone( 'UTC' ) ); |
| 309 | $value = $local_date_time->format( 'Y-m-d H:i' ); |
| 310 | |
| 311 | $local_date_time_2 = new DateTime( $dates[1], wp_timezone() ); |
| 312 | $local_date_time_2->setTimezone( new DateTimeZone( 'UTC' ) ); |
| 313 | $value_2 = $local_date_time_2->format( 'Y-m-d H:i' ); |
| 314 | // Set the converted dates to UTC. |
| 315 | $addition['value'] = zeroBSCRM_locale_dateToUTS( $value ); |
| 316 | $addition['value2'] = zeroBSCRM_locale_dateToUTS( $value_2 ); |
| 317 | } |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | // if intrange force it |
| 322 | if ( $c['type'] == 'intrange' && ! isset( $addition['value2'] ) ) { |
| 323 | $addition['value2'] = 0; |
| 324 | } |
| 325 | |
| 326 | $approvedConditions[] = $addition; |
| 327 | |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | return $approvedConditions; |
| 332 | |
| 333 | } |
| 334 | |
| 335 | return array(); |
| 336 | } |
| 337 | |
| 338 | // uses zeroBSCRM_textExpose to make query-ready strings, |
| 339 | // .. because conditions are saved in encoded format, e.g. é = é |
| 340 | function zeroBSCRM_segments_unencodeConditions( $conditions = array() ) { |
| 341 | |
| 342 | if ( is_array( $conditions ) && count( $conditions ) > 0 ) { |
| 343 | |
| 344 | $ret = array(); |
| 345 | |
| 346 | foreach ( $conditions as $c ) { |
| 347 | |
| 348 | // for now it's just value we're concerned with |
| 349 | $nC = $c; |
| 350 | if ( isset( $nC['value'] ) ) { |
| 351 | $nC['value'] = zeroBSCRM_textExpose( $nC['value'] ); |
| 352 | } |
| 353 | if ( isset( $nC['value2'] ) ) { |
| 354 | $nC['value2'] = zeroBSCRM_textExpose( $nC['value2'] ); |
| 355 | } |
| 356 | |
| 357 | // simple. |
| 358 | $ret[] = $nC; |
| 359 | |
| 360 | } |
| 361 | |
| 362 | return $ret; |
| 363 | |
| 364 | } |
| 365 | |
| 366 | return array(); |
| 367 | } |
| 368 | /* |
| 369 | ====================================================== |
| 370 | / Data Validation Functions: Segments |
| 371 | ====================================================== */ |