The Cache: Technology Expert's Forum
 
*
Welcome, Guest. Please login or register. September 19, 2019, 05:21:49 AM

Login with username, password and session length


Pages: [1]
  Print  
Author Topic: Relative url to full url  (Read 2007 times)
nattsurfaren
Journeyman
***
Offline Offline

Posts: 64


View Profile
« on: November 21, 2008, 04:07:12 PM »

Does anybody have a working function for this.
Currently I have:
Code:
function InternetCombineUrl($absolute, $relative)
{
    $p = parse_url($relative);
    if ($p["scheme"])
        return $relative;

    extract(parse_url($absolute));

    $path = dirname($path);

    if ($relative{0} == '/')
    {
        $cparts = array_filter(explode("/", $relative));
    }
    else
    {
        $aparts = array_filter(explode("/", $path));
        $rparts = array_filter(explode("/", $relative));
        $cparts = array_merge($aparts, $rparts);
        foreach ($cparts as $i => $part)
        {
            if ($part == '.')
            {
                $cparts[$i] = null;
            }
            if ($part == '..')
            {
                $cparts[$i - 1] = null;
                $cparts[$i] = null;
            }
        }
        $cparts = array_filter($cparts);
    }
    $path = implode("/", $cparts);
    $url = "";
    if ($scheme)
    {
        $url = "$scheme://";
    }
    if ($user)
    {
        $url .= "$user";
        if ($pass)
        {
            $url .= ":$pass";
        }
        $url .= "@";
    }
    if ($host)
    {
        $url .= "$host/";
    }
    $url .= $path;
    return $url;
}

But this one sometimes fails.

Sincerely
Natt

Logged
perkiset
Olde World Hacker
Administrator
Lifer
*****
Offline Offline

Posts: 10096



View Profile
« Reply #1 on: November 21, 2008, 07:18:14 PM »

The problem is that a "relative" URL is based on the previous location, not the absolute path.

For example -
if you had a page that referenced "deeperA/afile.html"
which referenced a page "deeperB/afile.html"
which referenced a page "deeperC/afile.html"

then your absolute path is now domain.com/deeperA/deeperB/deeperC/afile.html ... which cannot be ascertained from your function. To truly track relative URLs you need the notion of a stack, or at least to be aware of where you WERE so that you can decide what the relatives are pointing to.
Logged

It is now believed, that after having lived in one compound with 3 wives and never leaving the house for 5 years, Bin Laden called the U.S. Navy Seals himself.
vsloathe
vim ftw!
Global Moderator
Lifer
*****
Offline Offline

Posts: 1669



View Profile
« Reply #2 on: November 22, 2008, 09:36:38 AM »

I would just construct it from $_SERVER globals.

e.g. $_SERVER['HTTP_HOST'] and $_SERVER['REQUEST_URI']
Logged

hai
nattsurfaren
Journeyman
***
Offline Offline

Posts: 64


View Profile
« Reply #3 on: November 22, 2008, 01:39:18 PM »

Sorry I mean when using curl not for my own server. Smiley
I have found a function that seams to be working nice.

Code:
function make_abs($rel_uri, $base, $REMOVE_LEADING_DOTS = true)
{
    preg_match("'^([^:]+://[^/]+)/'", $base, $m);
    $base_start = $m[1];
    if (preg_match("'^/'", $rel_uri))
    {
        return $base_start . $rel_uri;
    }
    $base = preg_replace("{[^/]+$}", '', $base);
    $base .= $rel_uri;
    $base = preg_replace("{^[^:]+://[^/]+}", '', $base);
    $base_array = explode('/', $base);
    if (count($base_array) and !strlen($base_array[0]))
        array_shift($base_array);
    $i = 1;
    while ($i < count($base_array))
    {
        if ($base_array[$i - 1] == ".")
        {
            array_splice($base_array, $i - 1, 1);
            if ($i > 1)
                $i--;
        }
        elseif ($base_array[$i] == ".." and $base_array[$i - 1] != "..")
        {
            array_splice($base_array, $i - 1, 2);
            if ($i > 1)
            {
                $i--;
                if ($i == count($base_array))
                    array_push($base_array, "");
            }
        }
        else
        {
            $i++;
        }
    }
    if (count($base_array) and $base_array[-1] == ".")
        $base_array[-1] = "";
    /* How do we treat the case where there are still some leading ../
    segments left? According to RFC2396 we are free to handle that
    any way we want. The default is to remove them.
    #
    "If the resulting buffer string still begins with one or more
    complete path segments of "..", then the reference is considered
    to be in error. Implementations may handle this error by
    retaining these components in the resolved path (i.e., treating
    them as part of the final URI), by removing them from the
    resolved path (i.e., discarding relative levels above the root),
    or by avoiding traversal of the reference."
    #
    http://www.faqs.org/rfcs/rfc2396.html 5.2.6.g
    */
    if ($REMOVE_LEADING_DOTS)
    {
        while (count($base_array) and preg_match("/^\.\.?$/", $base_array[0]))
        {
            array_shift($base_array);
        }
    }
    return ($base_start . '/' . implode("/", $base_array));
}

Logged
Pages: [1]
  Print  
 
Jump to:  

Perkiset's Place Home   Best of The Cache   phpMyIDE: MySQL Stored Procedures, Functions & Triggers
Politics @ Perkiset's   Pinkhat's Perspective   
cache
mart
coder
programmers
ajax
php
javascript
Powered by MySQL Powered by PHP Powered by SMF 1.1.2 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks


Valid XHTML 1.0! Valid CSS!