diff --git a/lib/SimpleSAML/Utils/Config/Metadata.php b/lib/SimpleSAML/Utils/Config/Metadata.php new file mode 100644 index 0000000000000000000000000000000000000000..5f10c639d8abb49f1ccd4f1cbba370d5ccb59613 --- /dev/null +++ b/lib/SimpleSAML/Utils/Config/Metadata.php @@ -0,0 +1,138 @@ +<?php +/** + * Class with utilities to fetch different configuration objects from metadata configuration arrays. + * + * @package SimpleSAMLphp + * @author Jaime Pérez Crespo, UNINETT AS <jaime.perez@uninett.no> + */ +class SimpleSAML_Utils_Config_Metadata { + + /** + * Parse and sanitize a contact from an array. + * + * Accepts an array with the following elements: + * - contactType The type of the contact (as string). Mandatory. + * - emailAddress Email address (as string), or array of email addresses. Optional. + * - telephoneNumber Telephone number of contact (as string), or array of telephone numbers. Optional. + * - name Full name of contact, either as <GivenName> <SurName>, or as <SurName>, <GivenName>. Optional. + * - surName Surname of contact (as string). Optional. + * - givenName Givenname of contact (as string). Optional. + * - company Company name of contact (as string). Optional. + * + * The following values are allowed as "contactType": + * - technical + * - support + * - administrative + * - billing + * - other + * + * If given a "name" it will try to decompose it into its given name and surname, only if neither givenName nor + * surName are present. It works as follows: + * - "surname1 surname2, given_name1 given_name2" + * givenName: "given_name1 given_name2" + * surname: "surname1 surname2" + * - "given_name surname" + * givenName: "given_name" + * surname: "surname" + * + * otherwise it will just return the name as "givenName" in the resulting array. + * + * @param array $contact The contact to parse and sanitize. + * @return array An array holding valid contact configuration options. If a key 'name' was part of the input array, + * it will try to decompose the name into its parts, and place the parts into givenName and surName, if those are + * missing. + * @throws InvalidArgumentException if the contact does not conform to valid configuration rules for contacts. + */ + public static function getContact($contact) + { + assert('is_array($contact) || is_null($contact)'); + $valid_options = array('contactType', 'emailAddress', 'givenName', 'surName', 'telephoneNumber', 'company'); + $valid_types = array('technical', 'support', 'administrative', 'billing', 'other'); + + // check the type + if (!isset($contact['contactType']) || !in_array($contact['contactType'], $valid_types, true)) { + $types = join(', ', array_map( + function($t) { + return '"'.$t.'"'; + }, + $valid_types + )); + throw new InvalidArgumentException('"contactType" is mandatory and must be one of '. $types."."); + } + + // try to fill in givenName and surName from name + if (isset($contact['name']) && !isset($contact['givenName']) && !isset($contact['surName'])) { + // first check if it's comma separated + $names = explode(',', $contact['name'], 2); + if (count($names) === 2) { + $contact['surName'] = preg_replace('/\s+/', ' ', trim($names[0])); + $contact['givenName'] = preg_replace('/\s+/', ' ', trim($names[1])); + } else { + // check if it's in "given name surname" format + $names = explode(' ', preg_replace('/\s+/', ' ', trim($contact['name']))); + if (count($names) === 2) { + $contact['givenName'] = preg_replace('/\s+/', ' ', trim($names[0])); + $contact['surName'] = preg_replace('/\s+/', ' ', trim($names[1])); + } else { + // nothing works, return it as given name + $contact['givenName'] = preg_replace('/\s+/', ' ', trim($contact['name'])); + } + } + } + + // check givenName + if (isset($contact['givenName']) && ( + empty($contact['givenName']) || !is_string($contact['givenName']) + )) { + throw new InvalidArgumentException('"givenName" must be a string and cannot be empty.'); + } + + // check surName + if (isset($contact['surName']) && ( + empty($contact['surName']) || !is_string($contact['surName']) + )) { + throw new InvalidArgumentException('"surName" must be a string and cannot be empty.'); + } + + // check company + if (isset($contact['company']) && ( + empty($contact['company']) || !is_string($contact['company']) + )) { + throw new InvalidArgumentException('"company" must be a string and cannot be empty.'); + } + + // check emailAddress + if (isset($contact['emailAddress'])) { + if (empty($contact['emailAddress']) || + !(is_string($contact['emailAddress']) || is_array($contact['emailAddress']))) { + throw new InvalidArgumentException('"emailAddress" must be a string or an array and cannot be empty.'); + } + if (is_array($contact['emailAddress'])) { + foreach ($contact['emailAddress'] as $address) { + if (!is_string($address) || empty($address)) { + throw new InvalidArgumentException('Email addresses must be a string and cannot be empty.'); + } + } + } + } + + // check telephoneNumber + if (isset($contact['telephoneNumber'])) { + if (empty($contact['telephoneNumber']) || + !(is_string($contact['telephoneNumber']) || is_array($contact['telephoneNumber']))) { + throw new InvalidArgumentException('"telephoneNumber" must be a string or an array and cannot be empty.'); + } + if (is_array($contact['telephoneNumber'])) { + foreach ($contact['telephoneNumber'] as $address) { + if (!is_string($address) || empty($address)) { + throw new InvalidArgumentException('Telephone numbers must be a string and cannot be empty.'); + } + } + } + } + + // make sure only valid options are outputted + return array_intersect_key($contact, array_flip($valid_options)); + } + +}