Search code examples
phpurlhttpspreg-matchout

How to correct HTTPS out URL error with preg-match?


This may be a very basic question, and I'm not too sure how to even ask it. I have top list website where people can get 'out' numbers by people vising their website from mine.
All works fine if the user adds a website with 'http://', however, if the user adds a website with 'https://' the link does not work.

The link will simply open as 'https//' . but the colon does not appear in the base URL for HTTPs. Therefore the link does not open correctly.

Does anyone know how I could perhaps use preg_matches like the below to sort this issue?

if(isset($_GET['action']) && $_GET['action'] == "out" && !empty($_GET['key']))
{
    //echo "<pre>";
    $site = ORM::for_table('topsite')->where_equal('hash_key',$_GET['key'])->find_one();

    //print_r($site);
    //echo $site->url;die();
    $count = ($site->hits_out) + 1;
    //echo $count;

    $query = ORM::get_db()->prepare("update `topsite` set hits_out='".$count."' where id='".$site->id."'");
    if(!preg_match('/http:/',$site->url))
    {
        $site->url = "http://".$site->url;
    }
    if( $query->execute() ) 
    {
        header("Location:$site->url");
    } 
    else
    {
        header("Location: $base_url");
    }
    exit;

Solution

  • Add an s to the protocol and make it optional with the ?. Then use the found match in the header so you know which protocol to use.

    if(!preg_match('/https?:/', $site->url, $protocol))
        {
            $site->url = $protocol[0] . '//' . $site->url;
        }
    

    (you probably can change your delimiter and include the //s with the protocol as well, a little less concatenation that way)

    Unrelated but additional note, you're prepared statement is insecure.

    $query = ORM::get_db()->prepare("update `topsite` set hits_out='".$count."' where id='".$site->id."'");
    

    should be written as:

    $query = ORM::get_db()->prepare("update `topsite` set hits_out=? where id= ?");
    

    then binding should be used. Depending on the driver the syntax will vary, for PDO this will work:

    $query->execute(array($count, $site->id))
    

    One more unrelated point, the incrementing of hits_out should be in SQL, not PHP. Multiple users could hit the page at the same time and you will lose counts with your current approach. I recommend:

    set hits_out = hits_out + 1
    

    instead of selecting then:

    $count = ($site->hits_out) + 1;