Relative urls naar absolute urls

Een website die gebruikt maakt van zaken als mod_rewrite maakt veelal gebruikt van relatieve urls.

Een absolute url bevat het protocol, het domeinnaam (eventueel met subdomein) en het aanvullende pad en/of bestandsnaam. Een relatieve url bevat enkel het pad en/of bestandsnaam.

Als je deze pagina wilt verwerken (denk aan het inlezen van alle items van een pagina), is het nodig om deze relatieve urls om te zetten naar absolute urls. Om dat in PHP voor elkaar te krijgen heb ik de volgende functie gemaakt.

Functie

<?php
function getAbsoluteLinks($text, $baseUrl) {
	// the base url should be given, otherwise there's nothing we can do here
	if (!$baseUrl) {
		return $text;
	}
	
    /* 
		array of html attributes (NOT elements!) which should be checked. This
		array can be adjusted to fit your needs
	*/
	$needles = array('href="', 'src="', 'background="');
    
	// the baseUrl should have a forward slash at the end (http://site.tld/)
    if (substr($baseUrl, -1) != '/') {
		$baseUrl .= '/';
    }
	
	// loop through the html attributes and see if it needs to be fixed
	foreach ($needles as $needle) {
		// fixed text
		$newText = '';		
		
		// is the previous text piece fixed?
		$prevFixed = false;
		
		while ($pos = strpos($text, $needle)) {
			$pos += strlen($needle);
			
			/*
				if the attribute value doesn't start with a protocol, we assume 
				it's a relative url instead of an absolute one. In case of a 
				relative url, we want to append the base url to the html 
				attribute
			*/
			if (substr($text, $pos, 7) != 'http://' && 
				substr($text, $pos, 8) != 'https://' && 
				substr($text, $pos, 6) != 'ftp://' && 
				substr($text, $pos, 9) != 'mailto://') {
				
				// add the needle and base url to the text
				$newText .= substr($text, 0, $pos) . $baseUrl;
				
				// set previous text piece to fixed
				$prevFixed = true;
			}
			else {
				/* 
					if previous text piece is fixed, check if the text doesn't 
					start with a forward slash because base url already starts 
					with a forward slash
					
					http://site.tld/ and /about, delivers http://site.tld/about
					but not http://site.tld//about
				*/
				$tempText = substr($text, 0, $pos);
				if ($prevFixed) {
					if (substr($tempText, 0, 1) == '/') {
						$tempText = substr($tempText, 1);
					}
				}
				
				// no need to be fixing something further, so just add the text
				$newText .= $tempText;
				
				// previous text piece isn't fixed (anymore)
				$prevFixed = false;
			}
			
			// remove the adjusted text for the while loop
			$text = substr($text, $pos);
		}
		
		/*
			add the remaining text to the final text (newText contains the 
			fixed text, text contains the remaining text)
		*/
		$text = $newText. $text;
    }
	
    return $text;
}
?>

Voorbeeld

De volgende html komt van nu.nl:

<ul>
	<li><a href="http://nu.nl/binnenland/2619262/schip-vast-westerschelde.html">Schip vast op Westerschelde</a></li>
	<li><a href="/binnenland/2619212/woonwijk-in-schagen-afgezet-bommelding.html">Woonwijk in Schagen afgezet na bommelding</a></li>
	<li><a href="/buitenland/2619184/navigator-russisch-ramptoestel-was-dronken.html">Navigator Russisch ramptoestel was dronken</a></li>
	<li><a href="/binnenland/2619170/fnv-bonden-uiten-zware-kritiek-jongerius.html">FNV-bonden uiten zware kritiek op Jongerius</a></li>
	<li><a href="/binnenland/2619130/reizigersorganisatie-klaagt-bij-nma-ns.html">Reizigersorganisatie klaagt bij NMa over NS</a></li>
	<li><a href="/politiek/2619113/aanvaring-kabinet-en-cpb-pgb.html">'Aanvaring kabinet en CPB over pgb'</a></li>
	<li><a href="/buitenland/2619085/geen-overeenstemming-nieuw-kabinet-libie.html">Geen overeenstemming over nieuw kabinet Libi&euml;</a></li>
</ul>

Hier is duidelijk te zien dat deze urls relatief zijn, ze missen het domein gedeelte. Om dit nu automatisch te herstellen gebruiken we bovenstaande functie, met als eerste parameter de html en de tweede parameter de url van de pagina waar deze html vanaf komt.

echo getAbsoluteLinks($html, 'http://nu.nl');

Levert:

<ul>
	<li><a href="http://nu.nl/binnenland/2619262/schip-vast-westerschelde.html">Schip vast op Westerschelde</a></li>
	<li><a href="http://nu.nl//binnenland/2619212/woonwijk-in-schagen-afgezet-bommelding.html">Woonwijk in Schagen afgezet na bommelding</a></li>
	<li><a href="http://nu.nl//buitenland/2619184/navigator-russisch-ramptoestel-was-dronken.html">Navigator Russisch ramptoestel was dronken</a></li>
	<li><a href="http://nu.nl//binnenland/2619170/fnv-bonden-uiten-zware-kritiek-jongerius.html">FNV-bonden uiten zware kritiek op Jongerius</a></li>
	<li><a href="http://nu.nl//binnenland/2619130/reizigersorganisatie-klaagt-bij-nma-ns.html">Reizigersorganisatie klaagt bij NMa over NS</a></li>
	<li><a href="http://nu.nl//politiek/2619113/aanvaring-kabinet-en-cpb-pgb.html">'Aanvaring kabinet en CPB over pgb'</a></li>
	<li><a href="http://nu.nl//buitenland/2619085/geen-overeenstemming-nieuw-kabinet-libie.html">Geen overeenstemming over nieuw kabinet Libi&euml;</a></li>
</ul>

En zo zijn de relatieve urls hersteld naar absolute urls en is de html klaar voor verdere verwerking.

Leave a Reply

Your email address will not be published. Required fields are marked *