Why doesn't Apache allow access to files outside the web root --from within index.html?

118

This doesn't really have anything to do with Apache or server-side permissions, but more to do with how the browser resolves relative client-side URLs (according to RFC 3986).

I'm assuming /html is your document root and index.html is accessed with an absolute URL of the form http://example.com/index.html.

The browser (user-agent) must resolve all relative URLs before it can make a request for that resource.

If in /index.html you reference a stylesheet with the relative URL ../css/style.css - how is the browser expected to resolve this? The browser can't construct a valid URL that goes above / (ie. http://example.com/) - this is already at the top of the URL path. And dot-segments (ie. ..) only work within the URL-path. (Note we are dealing with URL-paths in client-side HTML, not server-side filesystem paths.)

From RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax:

Parsers must be careful in handling cases where there are more ".." segments in a relative-path reference than there are hierarchical levels in the base URI's path. Note that the ".." syntax cannot be used to change the authority component of a URI.

(The "authority component" being the domain in this case.)

So, what happens in the above example (where ../css/style.css is requested from /index.html) is that the ../ prefix is simply stripped and the resulting absolute URL becomes http://example.com/css/style.css. This doesn't exist in your file system structure, so your server responds with a 404 Not Found.

Share:
118
DanielP
Author by

DanielP

Updated on September 18, 2022

Comments

  • DanielP
    DanielP over 1 year

    This has me stumped. print_r displays the correct array indices and values, but the foreach construct retrieves erroneous values and even changes the value for the last index even though I'm not retrieving the values by reference (not using the ampersand).

    <?php
    
    require './includes/dbal.php';
    require './includes/user.php';
    require './includes/book.php';
    
    session_start();
    
    $title='My Shopping Cart';
    include './template/header.php';
    
    if(!isset($_SESSION['user']))
    {
        die('You are not logged in.');
    }
    
    if(!isset($_SESSION['cart']))
    {
        $_SESSION['cart'] = array();
    }
    
    if(isset($_POST['submit']) && strcmp($_GET['mode'], 'add') == 0)
    {
        if(filter_var($_POST['qty'], FILTER_VALIDATE_INT) == FALSE)
        {
            echo '<div style="color: red;">Invalid quantity specified. Please go back and use a valid quantity.</div>';
        }
        else
        {
            $_SESSION['cart'][$_POST['book_id']] = $_POST['qty'];
        }
    }
    
    else if(isset($_POST['update']) && strcmp($_GET['mode'], 'update') == 0)
    {
        foreach($_SESSION['cart'] as $key => &$value)
        {
            if((int) $_POST["qty_$key"] === 0)
            {
                unset($_SESSION['cart']["$key"]);
            }
            else
            {
                $value = $_POST["qty_$key"];
            }
        }
    }
    
    echo '<h3>Your shopping cart</h3>';
    
    $db = new DBal();
    $total=0;
    echo '<div id="cart-items"><ul><form action="./cart.php?mode=update" method="post">';
    
    // echo 'Original array: '; print_r($_SESSION['cart']);
    foreach($_SESSION['cart'] as $key => $value)
    {
        // echo '<br />$key => $value for this iteration: ' . "$key => $value<br />";
        // print_r($_SESSION['cart']);
        $b = new Book($key, $db);
        $book = $b->get_book_details();
        $total += $value * $book['book_nprice']
    ?>
    <li>
        <div><img src="./images/books/thumbs/book-<?php echo $book['book_id']; ?>.jpg" title="<?php echo $book['book_name']; ?>" /></div>
        <span class="cart-price">Amount: Rs. <?php echo $value * $book['book_nprice']; ?></span>
        <h3><?php echo $book['book_name']; ?> by <?php echo $book['book_author']; ?></h3>
        Price: Rs. <?php echo $book['book_nprice']; ?><br /><br />
        Qty: <input type="number" name="qty_<?php echo $book['book_id']; ?>" maxlength="3" size="6" min="1" max="100" value="<?php echo $value; ?>" /><br />
    </li>
    <?php } echo "<span class=\"cart-price\">Total amount: $total</span>" ?>
    <br />
    <input type="submit" name="update" value="Update Cart" />
    </form></ul></div>
    
    <?php include './template/footer.html'; ?>
    

    Sample output after pressing the update button is like this :

    Original array:
    Array (
        [9] => 6
        [8] => 7
        [3] => 8
    )
    
    $key => $value for this iteration: 9 => 6
    Array (
        [9] => 6
        [8] => 7
        [3] => 6
    )
    
    $key => $value for this iteration: 8 => 7 
    Array (
        [9] => 6
        [8] => 7
        [3] => 7
    )
    
    $key => $value for this iteration: 3 => 7 
    Array (
        [9] => 6
        [8] => 7
        [3] => 7 
    )
    

    The value for the last index gets changes to the value of the current index in every iteration. This results in the last value output having the same value as the second-to-last index.

    Help?