diff --git a/modules/aggregator/lib/ARP.php b/modules/aggregator/lib/ARP.php
new file mode 100644
index 0000000000000000000000000000000000000000..5408b2e219385d15aab745ccf9c2ba762bef8297
--- /dev/null
+++ b/modules/aggregator/lib/ARP.php
@@ -0,0 +1,107 @@
+<?php
+/*
+ * @author Andreas Åkre Solberg <andreas.solberg@uninett.no>
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+class sspmod_aggregator_ARP {
+
+
+	private $metadata;
+	private $attributes;
+	private $prefix;
+	private $suffix;
+
+	/**
+	 * Constructor
+	 *
+	 * @param 
+	 */
+	public function __construct($metadata, $attributemap, $prefix, $suffix) {
+		$this->metadata = $metadata;
+		
+		$this->prefix = $prefix;
+		$this->suffix = $suffix;
+		
+		if (isset($attributemap)) $this->loadAttributeMap($attributemap);
+	}
+	
+	private function loadAttributeMap($attributemap) {
+		$config = SimpleSAML_Configuration::getInstance();
+		include($config->getPathValue('attributemap', 'attributemap/') . $attributemap . '.php');
+		$this->attributes = $attributemap;
+		
+	#	print_r($attributemap); exit;
+	}
+
+	private function surround($name) {
+		$ret = '';
+		if (!empty($this->prefix)) $ret .= htmlspecialchars($this->prefix);
+		$ret .= $name;
+		if (!empty($this->suffix)) $ret .= htmlspecialchars($this->suffix);
+		return $ret;
+	}
+
+	private function getAttributeID($name) {
+		if (empty($this->attributes)) {
+			return $this->surround($name);
+		} 
+		if (array_key_exists($name, $this->attributes)) {
+			return $this->surround($this->attributes[$name]);
+		}
+		return $this->surround($name);
+	}
+
+	public function getXML() {
+		
+		$xml = '<?xml version="1.0" encoding="UTF-8"?>
+<AttributeFilterPolicyGroup id="urn:mace:funet.fi:haka:kalmar" xmlns="urn:mace:shibboleth:2.0:afp"
+    xmlns:basic="urn:mace:shibboleth:2.0:afp:mf:basic" xmlns:saml="urn:mace:shibboleth:2.0:afp:mf:saml"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="urn:mace:shibboleth:2.0:afp classpath:/schema/shibboleth-2.0-afp.xsd
+                        urn:mace:shibboleth:2.0:afp:mf:basic classpath:/schema/shibboleth-2.0-afp-mf-basic.xsd
+                        urn:mace:shibboleth:2.0:afp:mf:saml classpath:/schema/shibboleth-2.0-afp-mf-saml.xsd">
+';
+		
+		
+		foreach($this->metadata AS $metadata) {
+			#echo '<pre>'; print_r($metadata); # exit;
+			if (isset($metadata['saml20-sp-remote'])) {
+				#echo '<pre>'; print_r($metadata); exit;
+				$xml .= $this->getEntryXML($metadata['saml20-sp-remote']);
+			}
+			
+		}
+		
+		$xml .= '</AttributeFilterPolicyGroup>';
+		return $xml;
+	}
+
+	private function getEntryXML($entry) {
+		$entityid = $entry['entityid'];
+		return '	<AttributeFilterPolicy id="' . $entityid . '">
+		<PolicyRequirementRule xsi:type="basic:AttributeRequesterString" value="' . $entityid . '" />
+' . $this->getEntryXMLcontent($entry) . '
+	</AttributeFilterPolicy>
+';
+	}
+	
+	private function getEntryXMLcontent($entry) {
+		$ids = array();
+		if (!array_key_exists('attributes', $entry)) 
+			return '';
+		
+		$ret = '';
+		foreach($entry['attributes'] AS $a) {
+			
+			$ret .= '			<AttributeRule attributeID="' . $this->getAttributeID($a) . '">
+				<PermitValueRule xsi:type="basic:ANY" />
+			</AttributeRule>
+';
+			
+		}
+		return $ret;
+	}
+
+}
+
diff --git a/modules/aggregator/www/arp.php b/modules/aggregator/www/arp.php
new file mode 100644
index 0000000000000000000000000000000000000000..ef7d329edb980de6ebcdc9193dbf3597d76d2788
--- /dev/null
+++ b/modules/aggregator/www/arp.php
@@ -0,0 +1,77 @@
+<?php
+
+$config = SimpleSAML_Configuration::getInstance();
+$gConfig = SimpleSAML_Configuration::getConfig('module_aggregator.php');
+
+
+// Get list of aggregators
+$aggregators = $gConfig->getConfigItem('aggregators');
+
+// If aggregator ID is not provided, show the list of available aggregates
+if (!array_key_exists('id', $_GET)) {
+	$t = new SimpleSAML_XHTML_Template($config, 'aggregator:list.php');
+	$t->data['sources'] = $aggregators->getOptions();
+	$t->show();
+	exit;
+}
+$id = $_GET['id'];
+if (!in_array($id, $aggregators->getOptions())) 
+	throw new SimpleSAML_Error_NotFound('No aggregator with id ' . var_export($id, TRUE) . ' found.');
+
+$aConfig = $aggregators->getConfigItem($id);
+
+
+$aggregator = new sspmod_aggregator_Aggregator($gConfig, $aConfig, $id);
+
+if (isset($_REQUEST['set'])) 
+	$aggregator->limitSets($_REQUEST['set']);
+
+if (isset($_REQUEST['exclude'])) 
+	$aggregator->exclude($_REQUEST['exclude']);
+
+
+$md = $aggregator->getSources();
+
+
+$attributemap = NULL;
+if (isset($_REQUEST['attributemap'])) $attributemap = $_REQUEST['attributemap'];
+$prefix = '';
+if (isset($_REQUEST['prefix'])) $prefix = $_REQUEST['prefix'];
+$suffix = '';
+if (isset($_REQUEST['suffix'])) $suffix = $_REQUEST['suffix'];
+
+
+$arp = new sspmod_aggregator_ARP($md, $attributemap, $prefix, $suffix);
+
+$arpxml = $arp->getXML();
+
+$xml = new DOMDocument();
+$xml->loadXML($arpxml);
+
+$firstelement = $xml->firstChild;
+
+if ($aggregator->shouldSign()) {
+	$signinfo = $aggregator->getSigningInfo();
+	$signer = new SimpleSAML_XML_Signer($signinfo);
+	$signer->sign($firstelement, $firstelement, $firstelement->firstChild);
+}
+
+
+
+
+// echo('<pre>' . $arpxml); exit;
+
+
+/* Show the metadata. */
+if(array_key_exists('mimetype', $_GET)) {
+	$mimeType = $_GET['mimetype'];
+} else {
+	$mimeType = 'application/samlmetadata+xml';
+}
+
+header('Content-Type: ' . $mimeType);
+
+echo($xml->saveXML());
+
+
+?>
\ No newline at end of file