2020-08-19 14:55:38 +02:00
|
|
|
|
<?PHP
|
|
|
|
|
/**
|
|
|
|
|
* Gathers wrappers for handling inputs.
|
|
|
|
|
*/
|
|
|
|
|
declare(strict_types = 1);
|
|
|
|
|
|
|
|
|
|
/**
|
2021-03-09 20:09:11 +01:00
|
|
|
|
* Encapsulates functions for handling inputs.
|
2020-08-19 14:55:38 +02:00
|
|
|
|
*/
|
2020-08-29 17:22:16 +02:00
|
|
|
|
final class MD_STD_IN {
|
2020-08-19 14:55:38 +02:00
|
|
|
|
/**
|
2020-08-21 13:58:24 +02:00
|
|
|
|
* Validates and sanitizes input integers to be in line with MySQL
|
|
|
|
|
* autoincrement IDs.
|
2020-08-19 14:55:38 +02:00
|
|
|
|
*
|
|
|
|
|
* @param mixed $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return integer
|
|
|
|
|
*/
|
2021-09-17 15:52:37 +02:00
|
|
|
|
public static function sanitize_id(mixed $input):int {
|
2020-08-19 14:55:38 +02:00
|
|
|
|
|
2020-08-27 17:16:48 +02:00
|
|
|
|
$input = \filter_var($input, \FILTER_VALIDATE_INT, [
|
2020-08-19 14:55:38 +02:00
|
|
|
|
'options' => [
|
|
|
|
|
'min_range' => 1, // Minimum number of an ID generated.
|
|
|
|
|
'max_range' => 4294967295 // Max value for MySQL's int data type
|
|
|
|
|
],
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
|
2021-09-17 15:52:37 +02:00
|
|
|
|
if (!$input) {
|
2020-08-19 14:55:38 +02:00
|
|
|
|
throw new MDpageParameterNotNumericException("Value is not numeric.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $input;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-21 13:58:24 +02:00
|
|
|
|
/**
|
|
|
|
|
* Sanitizes and validates input integers to be either valid IDs or 0.
|
|
|
|
|
*
|
|
|
|
|
* @param mixed $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return integer
|
|
|
|
|
*/
|
2021-09-17 15:52:37 +02:00
|
|
|
|
public static function sanitize_id_or_zero(mixed $input):int {
|
2020-08-21 13:58:24 +02:00
|
|
|
|
|
2023-11-08 21:24:23 +01:00
|
|
|
|
if ($input === "" || $input === 0) {
|
2021-02-06 20:08:37 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2020-08-21 13:58:24 +02:00
|
|
|
|
|
2020-08-27 17:16:48 +02:00
|
|
|
|
$input = \filter_var($input, \FILTER_VALIDATE_INT, [
|
2020-08-21 13:58:24 +02:00
|
|
|
|
'options' => [
|
|
|
|
|
'min_range' => 0, // Minimum number of an ID generated.
|
|
|
|
|
'max_range' => 4294967295 // Max value for MySQL's int data type
|
|
|
|
|
],
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
|
2020-08-22 12:13:08 +02:00
|
|
|
|
if ($input === false) {
|
2020-08-21 13:58:24 +02:00
|
|
|
|
throw new MDpageParameterNotNumericException("Value is not numeric.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $input;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-19 14:55:38 +02:00
|
|
|
|
/**
|
|
|
|
|
* General string sanitization for all purposes. For use of inputs with MySQL's
|
|
|
|
|
* MATCH AGAINST, use the dedicated sanitization function.
|
|
|
|
|
*
|
|
|
|
|
* @param mixed $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2021-09-17 15:52:37 +02:00
|
|
|
|
public static function sanitize_text(mixed $input):string {
|
2020-08-19 14:55:38 +02:00
|
|
|
|
|
2022-02-02 02:18:33 +01:00
|
|
|
|
$output = \filter_var($input, FILTER_UNSAFE_RAW);
|
2020-08-20 11:08:27 +02:00
|
|
|
|
|
2021-02-06 20:08:37 +01:00
|
|
|
|
if ($output === false) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
2022-02-02 02:18:33 +01:00
|
|
|
|
$output = strip_tags($output);
|
2020-09-09 00:29:13 +02:00
|
|
|
|
while (strpos($output, " ") !== false) {
|
|
|
|
|
$output = str_replace(" ", " ", $output);
|
|
|
|
|
}
|
2020-08-19 14:55:38 +02:00
|
|
|
|
|
|
|
|
|
return trim($output);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-28 21:47:59 +01:00
|
|
|
|
/**
|
|
|
|
|
* String sanitization for 3 o4 6 characters RGB color codes (sans the leading #).
|
|
|
|
|
*
|
|
|
|
|
* @param mixed $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2021-09-17 15:52:37 +02:00
|
|
|
|
public static function sanitize_rgb_color(mixed $input):string {
|
2021-01-28 21:47:59 +01:00
|
|
|
|
|
2023-11-08 21:24:23 +01:00
|
|
|
|
if (($output = \filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH)) === false) {
|
|
|
|
|
throw new MDInvalidColorCode("Invalid color code provided: " . $output);
|
|
|
|
|
}
|
2021-01-28 21:47:59 +01:00
|
|
|
|
|
2023-11-08 21:24:23 +01:00
|
|
|
|
$output = \strtoupper($output);
|
|
|
|
|
|
|
|
|
|
if (!in_array(strlen($output), [3, 6], true)
|
|
|
|
|
|| (MD_STD::preg_replace_str('/[A-F0-9]/', '', $output) !== '')
|
2021-01-30 22:56:00 +01:00
|
|
|
|
) {
|
2021-01-28 21:47:59 +01:00
|
|
|
|
throw new MDInvalidColorCode("Invalid color code provided: " . $output);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-03 02:41:22 +01:00
|
|
|
|
/**
|
|
|
|
|
* Valiates a list of entries, ensuring all returned values are valid IDs.
|
|
|
|
|
*
|
|
|
|
|
* @param array<mixed> $inputs Input array.
|
|
|
|
|
*
|
2023-08-16 20:09:22 +02:00
|
|
|
|
* @return list<integer>
|
2021-11-03 02:41:22 +01:00
|
|
|
|
*/
|
|
|
|
|
public static function sanitize_id_array(array $inputs):array {
|
|
|
|
|
|
|
|
|
|
$output = [];
|
|
|
|
|
|
|
|
|
|
foreach ($inputs as $input) {
|
|
|
|
|
$output[] = self::sanitize_id($input);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-19 14:55:38 +02:00
|
|
|
|
/**
|
|
|
|
|
* Retrieves HTTP input texts from GET or POST variables, whatever is provided.
|
|
|
|
|
* If neither is given, returns a provided default.
|
|
|
|
|
*
|
2021-11-29 22:30:28 +01:00
|
|
|
|
* @param non-empty-string $var_name Variable name.
|
|
|
|
|
* @param string $default Default value for the output.
|
|
|
|
|
* @param array<string> $allowed List of allowed values. Defaults to empty (all values allowed).
|
2020-08-19 14:55:38 +02:00
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2020-09-30 00:58:58 +02:00
|
|
|
|
public static function get_http_input_text(string $var_name, string $default = "", array $allowed = []):string {
|
2020-08-19 14:55:38 +02:00
|
|
|
|
|
|
|
|
|
if (isset($_GET[$var_name])) {
|
2020-08-19 15:32:15 +02:00
|
|
|
|
$output = self::sanitize_text($_GET[$var_name]);
|
2020-08-19 14:55:38 +02:00
|
|
|
|
}
|
|
|
|
|
else if (isset($_POST[$var_name])) {
|
2020-08-19 15:32:15 +02:00
|
|
|
|
$output = self::sanitize_text($_POST[$var_name]);
|
2020-08-19 14:55:38 +02:00
|
|
|
|
}
|
2021-02-06 20:08:37 +01:00
|
|
|
|
else {
|
|
|
|
|
$output = self::sanitize_text($default);
|
|
|
|
|
}
|
2020-08-19 15:32:15 +02:00
|
|
|
|
|
2020-08-27 17:16:48 +02:00
|
|
|
|
if (!empty($allowed) and !\in_array($output, $allowed, true)) {
|
2021-02-06 19:55:54 +01:00
|
|
|
|
throw new MDpageParameterNotFromListException("Parameter `{$var_name}` must be any of the allowed values: '" . implode('\', \'', $allowed) . "'");
|
2020-08-19 15:32:15 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $output;
|
2020-08-19 14:55:38 +02:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Retrieves HTTP input texts from POST variables.
|
|
|
|
|
* If none is given, returns a provided default.
|
|
|
|
|
*
|
2021-11-29 22:30:28 +01:00
|
|
|
|
* @param non-empty-string $var_name Variable name.
|
|
|
|
|
* @param string $default Default value for the output.
|
|
|
|
|
* @param array<string> $allowed List of allowed values. Defaults to empty (all values allowed).
|
2020-08-19 14:55:38 +02:00
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2020-09-30 00:58:58 +02:00
|
|
|
|
public static function get_http_post_text(string $var_name, string $default = "", array $allowed = []):string {
|
2020-08-19 14:55:38 +02:00
|
|
|
|
|
|
|
|
|
if (isset($_POST[$var_name])) {
|
2020-08-19 15:32:15 +02:00
|
|
|
|
$output = self::sanitize_text($_POST[$var_name]);
|
2020-08-19 14:55:38 +02:00
|
|
|
|
}
|
2021-02-06 20:08:37 +01:00
|
|
|
|
else {
|
|
|
|
|
$output = self::sanitize_text($default);
|
|
|
|
|
}
|
2020-08-19 15:32:15 +02:00
|
|
|
|
|
2020-08-27 17:16:48 +02:00
|
|
|
|
if (!empty($allowed) and !\in_array($output, $allowed, true)) {
|
2021-02-06 19:55:54 +01:00
|
|
|
|
throw new MDpageParameterNotFromListException("Parameter `{$var_name}` must be any of the allowed values: '" . implode('\', \'', $allowed) . "'");
|
2020-08-19 15:32:15 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $output;
|
2020-08-19 14:55:38 +02:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-04 00:46:45 +02:00
|
|
|
|
/**
|
|
|
|
|
* Sanitizes and validates a URL. An empty string passes.
|
|
|
|
|
*
|
|
|
|
|
* @param mixed $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2021-09-17 15:52:37 +02:00
|
|
|
|
public static function sanitize_url(mixed $input):string {
|
2020-09-04 00:46:45 +02:00
|
|
|
|
|
2021-02-06 20:08:37 +01:00
|
|
|
|
if ($input === "") {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
2020-09-04 00:46:45 +02:00
|
|
|
|
|
2023-11-05 23:29:14 +01:00
|
|
|
|
try {
|
|
|
|
|
if (($output = \filter_var($input, FILTER_VALIDATE_URL)) === false) {
|
|
|
|
|
throw new MDInvalidUrl("Invalid input URL");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (MDInvalidUrl $e) {
|
2023-11-05 23:37:28 +01:00
|
|
|
|
if (($parsed = parse_url($input)) === false || empty($parsed['scheme']) || empty($parsed['host']) || empty($parsed['path'])) {
|
2023-11-05 23:29:14 +01:00
|
|
|
|
throw new MDInvalidUrl("Invalid input URL");
|
|
|
|
|
}
|
|
|
|
|
$rewritten = $parsed['scheme'] . '://';
|
|
|
|
|
if (!empty($parsed['user']) && !empty($parsed['pass'])) {
|
|
|
|
|
$rewritten .= $parsed['user'] . ':' . $parsed['pass'] . '@';
|
|
|
|
|
}
|
|
|
|
|
$rewritten .= $parsed['host'];
|
|
|
|
|
if (!empty($parsed['port'])) $rewritten .= ':' . $parsed['port'];
|
|
|
|
|
$rewritten .= str_replace('%2F' , '/', urlencode($parsed['path']));
|
2023-11-08 21:24:23 +01:00
|
|
|
|
if (!empty($parsed['query'])) {
|
|
|
|
|
$rewritten .= '?' . str_replace('%3D', '=', urlencode($parsed['query']));
|
|
|
|
|
}
|
2023-11-05 23:29:14 +01:00
|
|
|
|
if (($output = \filter_var($rewritten, FILTER_VALIDATE_URL)) === false) {
|
|
|
|
|
throw new MDInvalidUrl("Invalid input URL" . \urlencode($input));
|
|
|
|
|
}
|
2020-09-04 00:46:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-05 23:37:28 +01:00
|
|
|
|
if (empty($output)) return '';
|
2023-11-08 21:24:23 +01:00
|
|
|
|
// As per the RFC, URLs should not exceed 2048. Enough real-world ones
|
|
|
|
|
// do. But they certainly should not exceed 10000 characters.
|
|
|
|
|
if (\strlen($output) > 10000) {
|
|
|
|
|
throw new MDInvalidUrl("The entered URL seems to be valid otherwise, but is overly long.");
|
|
|
|
|
}
|
2023-11-05 23:37:28 +01:00
|
|
|
|
|
2022-03-30 13:03:04 +02:00
|
|
|
|
// Check for valid schemes
|
2023-11-09 16:40:28 +01:00
|
|
|
|
try {
|
|
|
|
|
if (MD_STD::startsWithAny($output, ['https://', 'http://', 'ftp://']) === false) {
|
|
|
|
|
throw new MDInvalidUrl("Invalid input URL" . PHP_EOL . $output . PHP_EOL . strtolower($output));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (MDInvalidUrl $e) {
|
|
|
|
|
if (MD_STD::startsWithAny(strtolower($output), ['https://', 'http://', 'ftp://']) === true) {
|
|
|
|
|
$output = strtolower(substr($output, 0, 8)) . substr($output, 8);
|
|
|
|
|
}
|
|
|
|
|
else throw $e;
|
2022-03-30 13:03:04 +02:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-08 21:24:23 +01:00
|
|
|
|
if (\str_contains($output, '.') === false) {
|
|
|
|
|
throw new MDInvalidUrl("Invalid input URL");
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-04 00:46:45 +02:00
|
|
|
|
return $output;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sanitizes and validates an e-mail address. An empty string passes.
|
|
|
|
|
*
|
|
|
|
|
* @param mixed $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2021-09-17 15:52:37 +02:00
|
|
|
|
public static function sanitize_email(mixed $input):string {
|
2020-09-04 00:46:45 +02:00
|
|
|
|
|
2021-02-06 20:08:37 +01:00
|
|
|
|
if ($input === "") {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
2020-09-04 00:46:45 +02:00
|
|
|
|
|
2023-11-07 22:50:18 +01:00
|
|
|
|
if (($output = \filter_var($input, FILTER_VALIDATE_EMAIL)) === false) {
|
2023-11-08 21:24:23 +01:00
|
|
|
|
throw new MDInvalidEmail("Invalid input email address" . ' '. $input);
|
2020-09-04 00:46:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-08 20:12:54 +01:00
|
|
|
|
/**
|
|
|
|
|
* Validates a password (minimum requirements: 8 characters, including
|
2022-03-08 21:23:45 +01:00
|
|
|
|
* one number and one special char) and returns a list of errors,
|
|
|
|
|
* if there are any.
|
2022-03-08 20:12:54 +01:00
|
|
|
|
*
|
|
|
|
|
* @param string $input Input string.
|
|
|
|
|
*
|
2022-03-08 21:23:45 +01:00
|
|
|
|
* @return array<string>
|
2022-03-08 20:12:54 +01:00
|
|
|
|
*/
|
2022-03-08 21:23:45 +01:00
|
|
|
|
public static function validate_password(string $input):array {
|
2022-03-08 20:12:54 +01:00
|
|
|
|
|
2022-03-08 21:23:45 +01:00
|
|
|
|
$errors = [];
|
2022-03-08 20:12:54 +01:00
|
|
|
|
if (mb_strlen($input) < 8) {
|
2022-03-08 21:23:45 +01:00
|
|
|
|
$errors[] = 'password_too_short';
|
2022-03-08 20:12:54 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-03-09 00:16:55 +01:00
|
|
|
|
if (!(\preg_match('@[0-9]@', $input)) && !(\preg_match('@[^\w]@', $input))) {
|
|
|
|
|
$errors[] = 'password_has_no_number_no_special_char';
|
2022-03-08 21:23:45 +01:00
|
|
|
|
}
|
2022-03-08 20:12:54 +01:00
|
|
|
|
|
2022-03-08 21:23:45 +01:00
|
|
|
|
return $errors;
|
2022-03-08 20:12:54 +01:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-25 21:56:01 +02:00
|
|
|
|
/**
|
|
|
|
|
* Sanitizes and validates a phone number. An empty string passes.
|
|
|
|
|
*
|
|
|
|
|
* @param mixed $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public static function validate_phone_number(mixed $input):string {
|
|
|
|
|
|
|
|
|
|
if ($input === "") {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!preg_match("#^[()0-9/ +-]+$#", $input)) {
|
|
|
|
|
throw new MDgenericInvalidInputsException("Invalid phone number entered.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $input;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 00:19:32 +02:00
|
|
|
|
/**
|
|
|
|
|
* Sanitizes a string to a float.
|
|
|
|
|
*
|
|
|
|
|
* @param string $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return float
|
|
|
|
|
*/
|
2020-09-30 00:58:58 +02:00
|
|
|
|
public static function sanitize_float(string $input):float {
|
2020-09-05 00:19:32 +02:00
|
|
|
|
|
|
|
|
|
$output = \str_replace(",", ".", $input);
|
|
|
|
|
if (($output = \filter_var($output, FILTER_VALIDATE_FLOAT)) === false) {
|
|
|
|
|
throw new MDgenericInvalidInputsException("Input is readable as a floating point value");
|
|
|
|
|
}
|
|
|
|
|
return $output;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-28 11:01:30 +02:00
|
|
|
|
/**
|
|
|
|
|
* Validates a coordinate.
|
|
|
|
|
*
|
|
|
|
|
* @param string|integer $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return float
|
|
|
|
|
*/
|
2023-11-07 22:50:18 +01:00
|
|
|
|
public static function validate_longitude(string|int|float $input):float {
|
2022-07-28 11:01:30 +02:00
|
|
|
|
|
|
|
|
|
if (is_string($input)) $output = self::sanitize_float($input);
|
|
|
|
|
else $output = $input;
|
|
|
|
|
|
|
|
|
|
if ($output < -180 || $output > 180) {
|
|
|
|
|
throw new MDCoordinateOutOfRange("Longitude out of range");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Validates a coordinate.
|
|
|
|
|
*
|
|
|
|
|
* @param string|integer $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return float
|
|
|
|
|
*/
|
2023-11-07 22:50:18 +01:00
|
|
|
|
public static function validate_latitude(string|int|float $input):float {
|
2022-07-28 11:01:30 +02:00
|
|
|
|
|
|
|
|
|
if (is_string($input)) $output = self::sanitize_float($input);
|
|
|
|
|
else $output = $input;
|
|
|
|
|
|
|
|
|
|
if ($output < -90 || $output > 90) {
|
|
|
|
|
throw new MDCoordinateOutOfRange("Latitude out of range");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-30 00:58:58 +02:00
|
|
|
|
/**
|
|
|
|
|
* Validates ISBNs. Empty strings are accepted as well.
|
|
|
|
|
*
|
|
|
|
|
* @param string $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public static function validate_isbn(string $input):string {
|
|
|
|
|
|
2021-02-06 20:08:37 +01:00
|
|
|
|
if ($input === "") {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
2020-09-30 00:58:58 +02:00
|
|
|
|
|
|
|
|
|
// Remove hyphens
|
|
|
|
|
$input = trim(strtr($input, ["-" => "", "–" => ""]));
|
|
|
|
|
|
|
|
|
|
// ISBN 10
|
|
|
|
|
if (\mb_strlen($input) === 10) {
|
|
|
|
|
|
|
|
|
|
if (\preg_match('/\d{9}[0-9xX]/i', $input)) {
|
|
|
|
|
return $input;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ISBN 13
|
2022-03-11 23:31:41 +01:00
|
|
|
|
if (\mb_strlen($input) === 13) {
|
2020-09-30 00:58:58 +02:00
|
|
|
|
|
|
|
|
|
if (\preg_match('/\d{13}/i', $input)) {
|
|
|
|
|
return $input;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new MDgenericInvalidInputsException("ISBNs must be either 10 or 13 characters long.");
|
|
|
|
|
|
|
|
|
|
}
|
2021-07-01 15:34:46 +02:00
|
|
|
|
|
2023-11-08 02:18:34 +01:00
|
|
|
|
/**
|
|
|
|
|
* Validates a ZIP code.
|
|
|
|
|
*
|
|
|
|
|
* @param string $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public static function validate_zip_code(string $input):string {
|
|
|
|
|
|
|
|
|
|
if (($input = trim($input)) === "") {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (\mb_strlen($input) > 7) {
|
|
|
|
|
throw new MDgenericInvalidInputsException("ZIP code is too long");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $input;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-01 15:34:46 +02:00
|
|
|
|
/**
|
|
|
|
|
* Returns an UTF8 version of a string.
|
|
|
|
|
*
|
|
|
|
|
* @param string $input Input string.
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public static function ensureStringIsUtf8(string $input):string {
|
|
|
|
|
|
|
|
|
|
// If the input is valid UTF8 from the start, it is simply returned in its
|
|
|
|
|
// original form.
|
|
|
|
|
if (\mb_check_encoding($input, 'UTF-8')) {
|
|
|
|
|
return $input;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// To detect and convert the encoding for non-UTF8 strings, the list of
|
|
|
|
|
// encodings known to PHP's mbstring functions is checked against the input string.
|
|
|
|
|
// If any encoding matches the string, it will be converted to UTF8 accordingly.
|
|
|
|
|
$suitableEncodings = [];
|
|
|
|
|
$encodings = \mb_list_encodings();
|
|
|
|
|
foreach ($encodings as $encoding) {
|
|
|
|
|
if (\mb_detect_encoding($input, $encoding, true) !== false) {
|
|
|
|
|
$suitableEncodings[] = $encoding;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If ISO-8859-1 is in the list of suitable encodings, try to convert with that.
|
|
|
|
|
if (\in_array('ISO-8859-1', $suitableEncodings, true)) {
|
|
|
|
|
if (($converted = \iconv('ISO-8859-1', "UTF-8//TRANSLIT", $input)) !== false) {
|
|
|
|
|
return $converted;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If a conversion from ISO-8859-1 doesn't work, just take any of the other ones.
|
|
|
|
|
$suitableEncodings = \array_reverse($suitableEncodings);
|
|
|
|
|
foreach ($suitableEncodings as $encoding) {
|
|
|
|
|
if (($converted = \iconv($encoding, "UTF-8//TRANSLIT", $input)) !== false) {
|
|
|
|
|
return $converted;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
if (count($suitableEncodings) === 1) {
|
|
|
|
|
return mb_convert_encoding($input, 'UTF-8', );
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
return $input;
|
|
|
|
|
|
|
|
|
|
}
|
2021-07-20 01:26:31 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Wrapper around move_uploaded_file that throws errors in case the upload failed
|
|
|
|
|
* for an identifiable reason.
|
|
|
|
|
*
|
2021-11-29 22:30:28 +01:00
|
|
|
|
* @param non-empty-string $filename Name of the file to upload.
|
|
|
|
|
* @param non-empty-string $destination Destination to move the file to.
|
|
|
|
|
* @param array<string> $mime_types Optional array of acceptable mime types. If this is
|
|
|
|
|
* not empty, the file will be checked for having one
|
|
|
|
|
* of the given mime types. If it does not, an error
|
|
|
|
|
* will be thrown.
|
2021-07-20 01:26:31 +02:00
|
|
|
|
*
|
|
|
|
|
* @return boolean
|
|
|
|
|
*/
|
2021-07-20 02:04:55 +02:00
|
|
|
|
public static function move_uploaded_file(string $filename, string $destination, array $mime_types = []):bool {
|
2021-07-20 01:26:31 +02:00
|
|
|
|
|
2021-07-20 02:04:55 +02:00
|
|
|
|
MD_STD::ensure_file($filename, $mime_types);
|
2021-11-29 22:30:28 +01:00
|
|
|
|
if (empty($destDir = dirname($destination))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
MD_STD::check_is_writable($destDir);
|
2021-07-20 01:26:31 +02:00
|
|
|
|
|
|
|
|
|
if (!(\move_uploaded_file($filename, $destination))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
}
|
2020-08-19 14:55:38 +02:00
|
|
|
|
}
|