self::DEFAULT_SITE, 'slug' => '', 'name' => '', 'connected_at' => '', 'page_id' => 0, 'accent' => '', 'text' => '', ); } /** * A business code as Anybook writes them, or '' if it is not one. Letters, digits, '-' and '_' only, so it is * safe in a URL path and in an HTML attribute. * * @param mixed $value Raw input. */ public static function clean_code( $value ) { $value = is_string( $value ) ? trim( $value ) : ''; return preg_match( '/^[A-Za-z0-9_-]{1,64}$/', $value ) ? $value : ''; } /** * A colour as #rgb or #rrggbb, or '' if it is not one (the widget reads it into a CSS custom property). * * @param mixed $value Raw input. */ public static function clean_colour( $value ) { $value = is_string( $value ) ? trim( $value ) : ''; return preg_match( '/^#([0-9a-fA-F]{3}){1,2}$/', $value ) ? strtolower( $value ) : ''; } /** * A booking site address the plugin will talk to, or '' if it is not acceptable. * * Https only, with no user name, password, path, query or fragment. Plain http is allowed only for a local * test install (localhost, 127.0.0.1, *.localhost), the same list as Anybook's local guest pages. * * @param mixed $value Raw input. */ public static function clean_site( $value ) { $value = is_string( $value ) ? untrailingslashit( trim( $value ) ) : ''; $parts = wp_parse_url( $value ); if ( ! is_array( $parts ) || empty( $parts['scheme'] ) || empty( $parts['host'] ) ) { return ''; } if ( isset( $parts['user'] ) || isset( $parts['pass'] ) || isset( $parts['query'] ) || isset( $parts['fragment'] ) ) { return ''; } if ( isset( $parts['path'] ) && '' !== $parts['path'] && '/' !== $parts['path'] ) { return ''; } $scheme = strtolower( $parts['scheme'] ); $host = strtolower( $parts['host'] ); if ( 'https' !== $scheme && ! ( 'http' === $scheme && self::is_local_host( $host ) ) ) { return ''; } $port = isset( $parts['port'] ) ? ':' . (int) $parts['port'] : ''; return $scheme . '://' . $host . $port; } /** * Whether a host name is a developer's own machine. The same list as Anybook's (review S-I2): *.test is not on it. * * @param string $host Lower-case host. */ public static function is_local_host( $host ) { return in_array( $host, array( 'localhost', '127.0.0.1' ), true ) || (bool) preg_match( '/\.localhost$/', $host ); } /** * The origin (scheme://host[:port]) of this WordPress site's front end: the website Anybook allows. */ public static function site_origin() { return self::origin_of( home_url() ); } /** The origin of the WordPress admin, where Anybook sends the browser back to (review S-I1). */ public static function admin_origin() { return self::origin_of( admin_url() ); } /** * Whether other sites share this site's address, so whatever a business allows for this website it allows for * them as well (review S-L1): a subdirectory network, or WordPress in a folder of a bigger site. */ public static function shares_origin() { if ( is_multisite() && ! is_subdomain_install() ) { return true; } $path = wp_parse_url( home_url(), PHP_URL_PATH ); return is_string( $path ) && '' !== trim( $path, '/' ); } /** * The origin (scheme://host[:port]) of an address. * * @param string $url Address. */ private static function origin_of( $url ) { $parts = wp_parse_url( $url ); if ( ! is_array( $parts ) || empty( $parts['host'] ) ) { return ''; } $scheme = isset( $parts['scheme'] ) ? strtolower( $parts['scheme'] ) : 'https'; $port = isset( $parts['port'] ) ? ':' . (int) $parts['port'] : ''; return $scheme . '://' . strtolower( $parts['host'] ) . $port; } }