How to refer back to public_html root file using i

2019-06-03 15:01发布

Based on some exceptionally helpful tips, I am using the following code to include PHP files outside my root directory which looks similar to this:

define('WEB_ROOT', __DIR__);
define('APP_ROOT', dirname(__DIR__));
define('PHP_ROOT', APP_ROOT . DIRECTORY_SEPARATOR . 'application');


include(PHP_ROOT . DIRECTORY_SEPARATOR . 'bootstrap.php');

My question is this, lets say for example you include the code bootstrap.php as per what you have above.

What if that PHP file bootstrap then had its own line of code the included a file BACK in the public_html root folder.... how would one code that? I am having some difficulty doing this, my objective here is that I dont want to put actual literal directories in full in the code and I want to avoid file traversal attacks

2条回答
趁早两清
2楼-- · 2019-06-03 15:25

To get the directory above public_html I use the following
$aboveRoot = explode('/public_html', $_SERVER['DOCUMENT_ROOT']);
define('ABOVE_THE_ROOT', $aboveRoot[0]);

查看更多
别忘想泡老子
3楼-- · 2019-06-03 15:40

Consider this project structure:

/path/to/projectroot/index.php
                     header.php
                     include/inc.php

If index.php had

include('include/inc.php');

and inc.php had

include('header.php');

You'd get that error since the line in inc.php would be looking for

/path/to/projectroot/include/header.php  (doesn't exist)

not

/path/to/projectroot/header.php (does exist)

There are a few ways people resolve this.

1: Absolute paths

The first, and most straightforward is to use absolute paths.

If index.php had

include('include/inc.php');

and inc.php had

include('/path/to/projectroot/header.php');

This would work.

2: Absolute paths with defines

Similar to #1, if index.php had

define('PROJECT_ROOT', '/path/to/projectroot/');
include(PROJECT_ROOT.'include/inc.php');

and inc.php had

include(PROJECT_ROOT.'header.php');

This would work.

Update: As noted in the comments by pichan, you could use one of the "magic" constants here in index.php, so:

index.php

define('PROJECT_ROOT', __DIR__.'/');
include(PROJECT_ROOT.'include/inc.php');

and inc.php

include(PROJECT_ROOT.'header.php');

Note we add a trailing slash to __DIR__ here since:

This directory name does not have a trailing slash unless it is the root directory.

3: Include both and hide errors

If inc.php had

@include('header.php');    # Try this directory
@include('../header.php'); # Try parent directory

This would work.[1]

4: Assume current directory unless otherwise specified

If index.php had

$rel_prefix_to_root = '../';
include('include/inc.php');

and inc.php had

if(!isset($rel_path_to_root)){ $rel_path_to_root = ''; }
include($rel_path_to_root . 'header.php');

This would work.

My take on these methods

1 and 2 are basically the same, but 2 is a little bit easier and more common for big projects since it allows you to make one constant definition and use it site-wide. It also allows you to deploy the project on multiple servers (placed in multiple paths) and only requires changing one line project-wide, as opposed to one line in each file for option 1.

3 is terrible, don't do it. Sometimes you'll see it, you might even see it in tutorials online. Don't do it.

4 should probably be avoided in favor of 1 or 2. But this approach might be necessary if you have some complex set of includes.

Some Notes:

[1] This is a terrible idea. It works, but don't do it.

查看更多
登录 后发表回答