<?php

/**
 * Based on what an IdP sends, generate a set of attributes that 
 * will always be available: fname, lname, organisation,
 * email, and country.
 *
 * @author Dick Visser <visser@terena.org>
 * @package simpleSAMLphp
 * @version $Id: BasicAtttibutes.php 26 2011-05-24 20:26:32Z visser $
 */
class sspmod_terena_Auth_Process_BasicAttributes extends SimpleSAML_Auth_ProcessingFilter {

	/**
	 * Attributes which should be added/appended.
	 *
	 * Assiciative array of arrays.
	 */
	private $attributes = array();

	private function getFirstName($attributes) {
		/* Look for the obvious */
		if (isset($attributes['givenName'][0])) {
			return $attributes['givenName'][0];
		}

		/* First word of cn */
		if (isset($attributes['cn'][0])) {
			$decomposed = explode(' ', $attributes['cn'][0]);
			if (count($decomposed) >= 2) {
				return $decomposed[0];
			}
		}
	
		/* First word of displayName */
		if (isset($attributes['displayName'][0])) {
			$decomposed = explode(' ', $attributes['displayName'][0]);
			if(count($decomposed) >= 2) {
				return $decomposed[0];
			}
		}
			
		/* Last resort */
		return 'first_name';
	}

	private function getLastName($attributes) {
		/* Look for the obvious */
		if (isset($attributes['sn'][0])) {
			return $attributes['sn'][0];
		}
		
		/* Last word of cn */
		if (isset($attributes['cn'][0])) {
			$decomposed = explode(' ', $attributes['cn'][0]);
			if(count($decomposed) >= 2) {
				array_shift($decomposed);
				return implode(' ', $decomposed);
			}
		}
		
		/* Last word of displayName */
		if (isset($attributes['displayName'][0])) {
			$decomposed = explode(' ', $attributes['displayName'][0]);
			if(count($decomposed) >= 2) {
				array_shift($decomposed);
				return implode(' ', $decomposed);
			}
		}
		
		/* Last resort */
		return 'last_name';
	}


	private function getIdpName($idpmeta) {
		if (!empty($idpmeta['name']['en'])) {
			return $idpmeta['name']['en'];
		} else {
			return $idpmeta['entityid'];
		}
	}

	
	private function getOrganisation($attributes, $idpmeta) {
		
		/* Look for the obvious */
		if (isset($attributes['organizationName'][0])) {
			return $attributes['organizationName'][0];
		}
		
		/* Uppercase version of schacHomeOrganization (domain without TLD) */
		if(isset($attributes['schacHomeOrganization'][0])) {
			return strtoupper(preg_replace('/([_a-z0-9-]+\.)?([_a-z0-9-]+)\.[_a-z0-9-]+$/', '$2',
			$attributes['schacHomeOrganization'][0]));
		}

		/* IdP name as displayed on login page */
        if (!empty($idpmeta['name']['en'])) {
            return $idpmeta['name']['en'];
        }

		/* Uppercase version of email domain without TLD */		
		if(isset($attributes['mail'][0])) {
			return strtoupper(preg_replace('/.*@([_a-z0-9-]+\.)?([_a-z0-9-]+)\.[_a-z0-9-]+$/', '$2',
			$attributes['mail'][0]));
		}
		
		/* Uppercase version of eduPersonPrincipalName domain without TLD) */
		if(isset($attributes['eduPersonPrincipalName'][0])) {
			return strtoupper(preg_replace('/.*@([_a-z0-9-]+\.)?([_a-z0-9-]+)\.[_a-z0-9-]+$/', '$2',
			$attributes['eduPersonPrincipalName'][0]));
		}
		
		/* Last resort */
		return 'Organisation';
	}
	
	
		private function getCountry($attributes) {
		/* See http://www.iso.org/iso/english_country_names_and_code_elements */
		$cc = array(
			'AF','AX','AL','DZ','AS','AD','AO','AI','AQ','AG','AR',
			'AM','AW','AU','AT','AZ','BS','BH','BD','BB','BY','BE',
			'BZ','BJ','BM','BT','BO','BA','BW','BV','BR','IO','BN',
			'BG','BF','BI','KH','CM','CA','CV','KY','CF','TD','CL',
			'CN','CX','CC','CO','KM','CG','CD','CK','CR','CI','HR',
			'CU','CY','CZ','DK','DJ','DM','DO','EC','EG','SV','GQ',
			'ER','EE','ET','FK','FO','FJ','FI','FR','GF','PF','TF',
			'GA','GM','GE','DE','GH','GI','GR','GL','GD','GP','GU',
			'GT','GG','GN','GW','GY','HT','HM','VA','HN','HK','HU',
			'IS','IN','ID','IR','IQ','IE','IM','IL','IT','JM','JP',
			'JE','JO','KZ','KE','KI','KP','KR','KW','KG','LA','LV',
			'LB','LS','LR','LY','LI','LT','LU','MO','MK','MG','MW',
			'MY','MV','ML','MT','MH','MQ','MR','MU','YT','MX','FM',
			'MD','MC','MN','ME','MS','MA','MZ','MM','NA','NR','NP',
			'NL','AN','NC','NZ','NI','NE','NG','NU','NF','MP','NO',
			'OM','PK','PW','PS','PA','PG','PY','PE','PH','PN','PL',
			'PT','PR','QA','RE','RO','RU','RW','BL','SH','KN','LC',
			'MF','PM','VC','WS','SM','ST','SA','SN','RS','SC','SL',
			'SG','SK','SI','SB','SO','ZA','GS','ES','LK','SD','SR',
			'SJ','SZ','SE','CH','SY','TW','TJ','TZ','TH','TL','TG',
			'TK','TO','TT','TN','TR','TM','TC','TV','UG','UA','AE',
			'GB','US','UM','UY','UZ','VU','VE','VN','VG','VI','WF',
			'EH','YE','ZM','ZW'
			);
		
		/* Look for the obvious */
		if (isset($attributes['countryName'][0])) {
			if(in_array(strtoupper($attributes['countryName'][0]), $cc)) {
				return strtoupper($attributes['countryName'][0]);
			}
		}
		
		/* TLD of e-mail */
		if (isset($attributes['mail'][0])) {
			if(preg_match('/.*\.([a-z][a-z])$/', $attributes['mail'][0], $matches)) {
				if(in_array(strtoupper($matches[1]), $cc)) {
					return strtoupper($matches[1]);
				}
			}
		}

		/* TLD of EPTI */
		if (isset($attributes['eduPersonTargetedID'][0])) {
			if(preg_match('/.*\.([a-z][a-z])$/', $attributes['eduPersonTargetedID'][0], $matches)) {
				if(in_array(strtoupper($matches[1]), $cc)) {
					return strtoupper($matches[1]);
				}
			}
		}

		/* TLD of EPPN */
		if (isset($attributes['eduPersonPrincipalName'][0])) {
			if(preg_match('/.*\.([a-z][a-z])$/', $attributes['eduPersonPrincipalName'][0], $matches)) {
				if(in_array(strtoupper($matches[1]), $cc)) {
					return strtoupper($matches[1]);
				}
			}
		}

		/* Last 2 letters of preferredLanguage */
		if (isset($attributes['preferredLanguage'][0])) {
			if(strlen($attributes['preferredLanguage'][0]) >= 2) {
				if(in_array(strtoupper(substr($attributes['preferredLanguage'][0], -2)), $cc)) {
					return  strtoupper(substr($attributes['preferredLanguage'][0], -2));
				}
			}
		}
		
		/* Last resort */
		return '0';
	}
	
	
	private function getEmail($attributes) {
		/* Look for the obvious */
		
		if (isset($attributes['mail'][0])) {
			return $attributes['mail'][0];
		}	

		// hack
		// turned off 2013-04-16 DV
/*       if (isset($attributes['eduPersonPrincipalName'][0])) {
           return $attributes['eduPersonPrincipalName'][0];
       }
*/

		/* Last resort
			We provide a non-valid address here, so that when a users logs in
			to edit his details, he is required to put in something valid.
		*/
		return 'invalid_email_needs_updating';
	}
	


	
	/**
	 * Apply filter to add or replace attributes.
	 *
	 * Add or replace existing attributes with the configured values.
	 *
	 * @param array &$request  The current request
	 */
	public function process(&$request) {
#		assert('is_array($request)');
#		assert('array_key_exists("Attributes", $request)');

		SimpleSAML_Logger::debug('State: ' . var_export($request,1));
		$attributes =& $request['Attributes'];
		#print_r($attributes); exit();

		$session = SimpleSAML_Session::getInstance();
		$idp = $session->getIdP();
		#SimpleSAML_Logger::debug('Session: ' . var_export($session,1));
		$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
		$idpmeta = $metadata->getMetaData($idp, 'saml20-idp-remote');

		#SimpleSAML_Logger::debug('idpmeta: ' . var_export($idpmeta,1));
		$collected = array(
			'fname' => $this->getFirstName($attributes),
			'lname' => $this->getLastName($attributes),
			'fullname' => $this->getFirstName($attributes) . ' ' . $this->getLastName($attributes),
			'idpname' => $this->getIdpName($idpmeta),
			'organisation' => $this->getOrganisation($attributes, $idpmeta),
			'email' => $this->getEmail($attributes),
			'country' => $this->getCountry($attributes),
		);

		foreach($collected as $c=>$v) {
			if(isset($c)) {
				$request['Attributes'][$c] = array($v);
			}
		}
	}
}

?>
