Relative to Absolute URLs Converter
Some web page creators and editors insist on creating relative links to local files like images, CSS, and JavaScript. Which is fine, so long as the page and the files it references all remain in the same relative directories.
Here are some example relative links.
<img src="images/image.jpg"> <img src="./images/image.jpg"> <img src="../adimages/image.jpg"> <script src="../../scripts/script.js"></script> <link href="css.css" rel="stylesheet" type="text/css">
The trouble comes when the web page is moved or a copy made to a different directory. The relative links break.
This is the situation a customer encountered.
The customer purchased Master Form V4 and is using it as a site replicator.
The page templates work fine in the directory where they're at; the files are pulled in as they should be. But when the page is replicated into a different directory, which the customer requires, the relative links break.
The HTML base
tag could be used to solve that problem except for one consideration — when the page is saved to someone's hard drive and viewed from there (as our customer expects to happen).
For the web page to render correctly even when saved to someone's hard drive, all relative links need to be converted to absolute http://... links. That's every href
and src
value with a relative link.
The location of the web page where the relative links work is known as the base URL. Assuming the base URL is http://example.com/one/two/index.html, the relative links from the previous example would need to be changed to these absolute http://... URLs.
<img src="https://example.com/one/two/images/image.jpg"> <img src="https://example.com/one/two/images/image.jpg"> <img src="https://example.com/one/adimages/image.jpg"> <script src="https://example.com/scripts/script.js"></script> <link href="http://example.com/one/two/css.css" rel="stylesheet" type="text/css">
The links can be changed manually by doing a search and updating links that need updating. Although the customer has dozens of templates, it's still doable.
Except, the links have to be changed all over again every time a template is edited with the page editing software.
I, being the automation guy, decided to write a script to run after every template page edit. The script changes relative URLs in the web page source code into absolute http://... URLs.
Here's the script. No customization required. Operation and installation notes follow.
<?php /* Relative to Absolute URLs Version 1.0 August 8, 2016 Will Bontrager Software LLC https://www.willmaster.com/ Copyright 2016 Will Bontrager Software LLC This software is provided "AS IS," without any warranty of any kind, without even any implied warranty such as merchantability or fitness for a particular purpose. Will Bontrager Software LLC grants you a royalty-free license to use or modify this software provided this notice appears on all copies. */ $Processed = false; $Errors = $Messages = array(); foreach( $_POST as $k => $v ) { $_POST[$k] = stripslashes(trim($v)); } if( isset($_POST['submitter']) ) { if( empty($_POST['baseURL']) or empty($_POST['fileName']) ) { $Errors[] = 'Both the base URL and the web page file name need to be provided.'; } if( ! preg_match('!^https?://.!',$_POST['baseURL']) ) { $Errors[] = 'The base URL needs to be an http://... or https://... URL.'; } if( ! file_exists($_POST['fileName']) ) { $Errors[] = "The file {$_POST['fileName']} doesn't exist in the directory where this software is running."; } if( ! count($Errors) ) { $page = ''; if( ! ($page = file_get_contents($_POST['fileName'])) ) { $Errors[] = "Unable to read file {$_POST['fileName']}"; return; } $backupfile = time() . "_{$_POST['fileName']}"; if( file_put_contents($backupfile,$page) ) { $Messages[] = "Backup of original file is $backupfile"; } else { $Errors[] = "Unable to create backup file $backupfile — verify this directory has sufficient write permissions."; return; } preg_match_all('!src=[\'"]?([^\'"\s]*)!si',$page,$src); foreach( $src[1] as $item ) { if( preg_match('!^[a-zA-Z]+\:!',$item) ) { continue; } if( preg_match('!^\#\?!',$item) ) { continue; } extract(parse_url($_POST['baseURL'])); if( strpos($item,'/')===0 ) { $path = ''; } if( $path ) { $path = preg_replace('!/[^/]*$!','',$path); } $abs = "$host$path/$item"; while( preg_match('!/\w+/\.\./!',$abs) ) { $abs = preg_replace('!/\w+/\.\./!','/',$abs,1); } $abs = preg_replace('!/\.{0,2}/!','/',$abs); $item = preg_quote($item,'/'); $page = preg_replace("!src=(['\"])?$item!i","src=\$1$scheme://$abs",$page); } preg_match_all('!href=[\'"]?([^\'"\s]*)!si',$page,$href); foreach( $href[1] as $item ) { if( preg_match('!^[a-zA-Z]+\:!',$item) ) { continue; } if( preg_match('!^\#\?!',$item) ) { continue; } extract(parse_url($_POST['baseURL'])); if( strpos($item,'/')===0 ) { $path = ''; } if( $path ) { $path = preg_replace('!/[^/]*$!','',$path); } $abs = "$host$path/$item"; while( preg_match('!/\w+/\.\./!',$abs) ) { $abs = preg_replace('!/\w+/\.\./!','/',$abs,1); } $abs = preg_replace('!/\.{0,2}/!','/',$abs); $item = preg_quote($item,'/'); $page = preg_replace("!href=(['\"])?$item!i","href=\$1$scheme://$abs",$page); } if( file_put_contents($_POST['fileName'],$page) ) { $Messages[] = "Webpage file {$_POST['fileName']} has been processed and updated."; $Processed = true; } else { $Errors[] = "Unable to update the file {$_POST['fileName']}"; } } } ?><!doctype html> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Relative to Absolute URLs</title> <style type="text/css"> body { font-size:100%; font-family:sans-serif; } #content { max-width:5.5in; margin:.75in auto; position:relative; } input { width:100%; box-sizing:border-box; font-size:1em; } input[type="text"] { padding:.25em; border:1px solid #ccc; border-radius:.25em; } a { text-decoration:none; } </style> </head> <body> <div id="content"> <a href="//www.willmaster.com/"> <img src="//www.willmaster.com/images/wmlogo_icon.gif" style="width:50px; height:50px; position:absolute; left:-.25in; top:-.75in; border:none; outline:none;"> </a> <h1> Relative to Absolute URLs </h1> <?php if( count($Errors) ): ?> <div style="border:3px solid red; padding:1em; border-radius:1em;"> <p style="margin-top:0; font-weight:bold;"> Notice: </p> <ul style="margin-bottom:0;"><li> <?php echo( implode('</li><li>',$Errors) ) ?> </li> </ul> </div> <?php elseif( $Processed ): ?> <?php if( count($Messages) ): ?> <p>• <?php echo( implode('</p><p>• ',$Messages) ) ?> </p> <?php endif; ?> <p> Do another? </p> <?php endif; ?> <h3> — Setup — </h3> <form method="post" enctype="multipart/form-data" action="<?php echo(htmlspecialchars($_SERVER['PHP_SELF'])); ?>"> <p> The base URL.<br> <input type="text" name="baseURL" required placeholder="The URL that relative links are relative to." value="<?php echo(@$_POST['baseURL']) ?>"> </p> <p> File name of web page to update.<br> <input type="text" name="fileName" required placeholder="The file name of the web page to update." value="<?php echo(@$_POST['fileName']) ?>"> </p> <p> <input type="submit" name="submitter" value="Update Web Page File"> </p> </form> <p>Copyright 2016 <a href="//www.willmaster.com/">Will Bontrager Software LLC</a></p> </div> </body> </html>
The PHP script is complete. Installation and operation is three steps:
-
Upload the script into the directory that contains the web page to convert, which would be the template with the relative URLs. The script file name needs to have a .php file name extension. Otherwise it can be any legal file name that suits you. (I use
Relative2AbsoluteURLs.php
for the script file name.)In order to convert the web page's relative URLs into absolute URLs, the directory needs to be writable. (If it's not, the software will let you know when you do step 3.)
-
Type the URL of the script into your browser.
-
Fill in the form, specifying these two items:
-
The base URL to use when constructing absolute URLs from relative URLs.
The base URL is the URL where the relative URLs in the web page actually work. If the web page currently pulls in all files correctly, the base URL would be the URL of the current web page.
-
The file name of the web page with relative URLs to be converted.
If the script encounters errors it recognizes, it will let you know what they are.
As mentioned in the first step, the directory with the web page to convert needs to be writable. What's writable and not writable depends on your server's configuration. If the script tells you it can't write in the directory, the directory may need to have its permissions temporarily changed to 777. (Or move the web page file to a different but writable directory to do the conversion.)
-
That's all there is to it. Upload the Relative to Absolute URLs script into the directory with the file to convert and type the scripts URL into your browser.
The software converts all src
and href
relative URLs in the web page to absolute URLs.
(This article first appeared in Possibilities ezine.)
Will Bontrager