colindunn
colindunn

Reputation: 3163

PHP: Create variable based on hashtag

I'm using this tutorial to create an ajax site and am struggling with the PHP. This is the provided code:

PHP

if(!$_POST['page']) die("0");

$page = (int)$_POST['page'];

if(file_exists('pages/page_'.$page.'.html'))
echo file_get_contents('pages/page_'.$page.'.html');

else echo 'There is no such page!';

I would like to use a naming structure other than page_1.html, page_2.html etc. My HTML looks like this:

HTML

<ul id="navigation">
    <li><a href="#home">Home</a></li>
    <li><a href="#about">About</a></li>
    <li><a href="#services">Services</a></li>
    <li><a href="#page4">Page 4</a></li>
</ul>

Right now the only link that's working is 'Page 4'. How would I rewrite the PHP so that the first three links would work?

Javascript

var default_content="";

$(document).ready(function(){

    checkURL();
    $('ul li a').click(function (e){

            checkURL(this.hash);

    });

    //filling in the default content
    default_content = $('#pageContent').html();


    setInterval("checkURL()",250);

});

var lasturl="";

function checkURL(hash)
{
    if(!hash) hash=window.location.hash;

    if(hash != lasturl)
    {
        lasturl=hash;

        // FIX - if we've used the history buttons to return to the homepage,
        // fill the pageContent with the default_content

        if(hash=="")
        $('#pageContent').html(default_content);

        else
        loadPage(hash);
    }
}


function loadPage(url)
{
    url=url.replace('#page','');

    $('#loading').css('visibility','visible');

    $.ajax({
        type: "POST",
        url: "load_page.php",
        data: 'page='+url,
        dataType: "html",
        success: function(msg){

            if(parseInt(msg)!=0)
            {
                $('#pageContent').html(msg);
                $('#loading').css('visibility','hidden');
            }
        }

    });

}

Upvotes: 0

Views: 1165

Answers (3)

Michael Berkowski
Michael Berkowski

Reputation: 270637

Only the page4 works, because it is expecting the scripts to be named like page_number.html. Your home, about, services do not match that pattern. To make them work as well, you would need to change the file_get_contents() call to allow page/anything.html.

The first thing to modify is the function which posts:

function loadPage(url)
{
    // Instead of stripping off #page, only 
    // strip off the # to use the rest of the URL
    url=url.replace('#','');

    $('#loading').css('visibility','visible');

    $.ajax({
        type: "POST",
        url: "load_page.php",
        data: 'page='+url,
        dataType: "html",
        success: function(msg){

            if(parseInt(msg)!=0)
            {
                $('#pageContent').html(msg);
                $('#loading').css('visibility','hidden');
            }
        }

    });
}

Now, this introduces a security risk in PHP. You need to validate that the value of $_POST['page'] is strictly alphanumeric so that no one can inject a filename like ../../../../somefile to read your filesystem. Using the expression below will allow you to name your files with any alphabetic and numeric characters, but will reject dots and null bytes, which are the primary dangers in a file path-injection / directory traversal attack.

if(empty($_POST['page'])) die("0");
// Remove the typecast so you can use the whole string
//$page = (int)$_POST['page'];
// Just use the post val.  This is safe because we'll validate it with preg_match() before use...
$page = $_POST['page'];

// And validate it as alphanumeric before reading the filesystem
if (preg_match('/^[a-z0-9]+$/i', $_POST['page']) && file_exists('pages/'.$page.'.html')) {
  // Remove the page_ to use the whole thing
  echo file_get_contents('pages/'.$page.'.html');
}
else echo 'There is no such page!';

Upvotes: 1

James L.
James L.

Reputation: 4097

Change the PHP to this:

$page = $_POST['page'];
if(file_exists('pages/'.$page.'.html'))
echo file_get_contents('pages/'.$page.'.html');

Now you are using the whole hash tag so #about will lead to: pages/about.html

Change this in thee javascript function loadPage

url=url.replace('#page','');

becomes

url=url.replace('#','');

Upvotes: 0

nickb
nickb

Reputation: 59699

You'd need to alter more than just this to get it working.

  1. Change the JS so that it doesn't remove anything from the URL except the pound sign:

    url=url.replace('#page','');
    

    Needs to be:

    url=url.replace('#','');
    
  2. Change the PHP to handle strings:

    if(!$_POST['page']) die("0");
    
    // Only allow alphanumeric characters and an underscore in page names
    $page = preg_replace( "/[^\w]/", '', $_POST['page']);
    
    if(file_exists('pages/'.$page.'.html'))
        echo file_get_contents('pages/'.$page.'.html');
    else echo 'There is no such page!';
    
  3. Now create the pages in the pages/ directory.

    • <li><a href="#home">Home</a></li> would be home.html
    • <li><a href="#about">About</a></li> would be about.html
    • <li><a href="#services">Services</a></li> would be services.html
    • <li><a href="#page4">Page 4</a></li> would be page4.html

Upvotes: 1

Related Questions