Determining a website's 'root' location - php

I need some help with concepts and terminology regarding website 'root' urls and directories.
Is it possible to determine a website's root, or is that an arbitrary idea, and only the actual server's root can be established?
Let's say I'm writing a PHP plugin that that will be used by different websites in different locations, but needs to determine what the website's base directory is. Using PHP, I will always be able to determine the DOCUMENT_ROOT and SERVER_NAME, that is, the absolute URL and absolute directory path of the server (or virtual server). But I can't know if the website itself is 'installed' at the root directory or in a sub directory. If the website was in a subdirectory, I would need the user to explicitly set an "sub-path" variable. Correct?

Answer to question 1: Yes you need a variable which explicitly sets the root path of the website. It can be done with an htaccess file at the root of each website containing the following line :
SetEnv APP_ROOT_PATH /path/to/app
http://httpd.apache.org/docs/2.0/mod/mod_env.html
And you can access it anywhere in your php script by using :
<?php $appRootPath = getenv('APP_ROOT_PATH'); ?>
http://php.net/manual/en/function.getenv.php

Will $url and $dir always be pointing to the same place?
Yes
<?php
$some_relative_path = "hello";
$server_url = $_SERVER["SERVER_NAME"];
$doc_root = $_SERVER["DOCUMENT_ROOT"];
echo $url = $server_url.'/'. $some_relative_path."<br />";
echo $dir = $doc_root.'/'. $some_relative_path;
Output:
sandbox.phpcode.eu/hello
/data/sandbox//hello

You shouldn't need to ask the user to provide any info.
This snippet will let your code know whether it is running in the root or not:
<?php
// Load the absolute server path to the directory the script is running in
$fileDir = dirname(__FILE__);
// Make sure we end with a slash
if (substr($fileDir, -1) != '/') {
$fileDir .= '/';
}
// Load the absolute server path to the document root
$docRoot = $_SERVER['DOCUMENT_ROOT'];
// Make sure we end with a slash
if (substr($docRoot, -1) != '/') {
$docRoot .= '/';
}
// Remove docRoot string from fileDir string as subPath string
$subPath = preg_replace('~' . $docRoot . '~i', '', $fileDir);
// Add a slash to the beginning of subPath string
$subPath = '/' . $subPath;
// Test subPath string to determine if we are in the web root or not
if ($subPath == '/') {
// if subPath = single slash, docRoot and fileDir strings were the same
echo "We are running in the web foot folder of http://" . $_SERVER['SERVER_NAME'];
} else {
// Anyting else means the file is running in a subdirectory
echo "We are running in the '" . $subPath . "' subdirectory of http://" . $_SERVER['SERVER_NAME'];
}
?>

I have just had the same problem. I wanted to reference links and other files from the root directory of my website structure.
I tried the following but it would never work how I wanted it:
$root = $_SERVER['DOCUMENT_ROOT'];
echo "Link";
echo "Link";
But the obvious solution was just to use the following:
echo "Link";
echo "Link";

Related

PHP create directory name with forward slash

I'm beginner in php. With a scenario i wanted to create directory with forward slash in name(09/01/2017). How can i resolve it?
$my_date = "09/01/2017"
$new_path = "../Images/".$my_date;
if(!file_exists($new_path)) {
mkdir($new_path , 0777);
}
EDIT: I'm using macos with php server in it. In macos it is possible to create folder with slashes.
<?php
$my_date = "09/01/2017";
$new_path = "images/".$my_date;
if (!is_dir($new_path))
{
mkdir($new_path , 0777,true);
}
?>
mkdir($new_path , 0777,true);//true for recursive directory creation.
In your case if you create directory with 09/01/2017 it will be created
File Tree:
images
--09
--01
--2017
because file system not allowed forward slash as directory name.Instead of this you can create 09012017 or 09-01-2017.
Hey #Milan Mendpara i would like to tell you that you can not make any folder with name char /:*?"<>|, even you can not make a directory in you OS as well. when you try it in you OS then below case will arise
So i think you should change your directory from 09/01/2017 to 09-01-2017, IN my case i dont have ../'Image' directory so i just make a directory where my php file is present so below is you code
<?php
$my_date = "09-01-2017";
$tempDir = __DIR__ . DIRECTORY_SEPARATOR . $my_date; // __DIR__ means a path where your php file is present and DIRECTORY_SEPARATOR means __DIR__.'/' and then give you directory name like __DIR__ . DIRECTORY_SEPARATOR . $my_date
if(!is_dir($temp_dir)){
mkdir($temp_dir);
}
?>

Getting the content stored with file_get_contents

Alright so everything is being saved properly but how can I get the url of the file I am saving?
$songs = file_get_contents('https://example.com/tracks/'.$id.'/');
file_put_contents('./tmp/' . stripslashes(htmlspecialchars($songTitle)) . '.mp3', $songs);
Without manually having to get every url, please note I am a new developer still learning.. but is there not something I can just echo into an ??
Edit: ' . stripslashes(htmlspecialchars($songTitle)) . ' this is just the name of the file that we're downloading, nothing important about that string.
This depends on your setup, but if your script is in an externally accessible location and you trust $_SERVER client-defined fields, you can use __FILE__ and $_SERVER to accomplish what you want.
The code below assumes:
Your server is not on HTTPS;
Files in the subdirectory tmp can be accessed externally;
You can write to the subdirectory tmp.
$_SERVER['HTTP_HOST'] and $_SERVER['REQUEST_URI'] can be "trusted".
Try this:
// This is the only thing you need to set to your taste.
$dest_rel_path = 'tmp/' . stripslashes(htmlspecialchars($songTitle)) . '.mp3';
// This is the final file path in your filesystem.
// `dirname(__FILE__)` can be replaced with __DIR__ in PHP >= 5.3.0
// and the str_replace() part makes the code portable to Windows.
$filesystem_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $dest_rel_path);
$songs = file_get_contents('https://example.com/tracks/'.$id.'/');
file_put_contents($filesystem_path, $songs);
// This takes the URL that the user requested and replaces the
// part after the last '/' with our new .mp3 location.
$req_uri = $_SERVER['REQUEST_URI'];
$url_path = substr($req_uri, 0, 1 + strrpos($req_uri, '/')) . $dest_rel_path;
$url = 'http://' . $_SERVER['HTTP_HOST'] . $url_path;
echo "This is my link to $songTitle!";
You can't, at least not directly, since it does not work that way: the filesystem does not necessarily translate to an URL.
For instance, in your case, you're saving the file into the tmp directory. I doubt that directory is accessible in any way to the outside world, ie, that it has a public URL than you can access in your browser.

How to make a path that always points to the root directory of my website?

I want to make a path to be used with links and src attributes in my html - how do i achieve this?
my attempts:
Home
or
<img src="' . $_SERVER['DOCUMENT_ROOT'] . '.images/whatever.jpg">
Can anyone expound upon this?
$_SERVER['DOCUMENT_ROOT'] returns that path to the document root on the server, for instance: /var/www/my.website.org/src or C:/wamp/www/my.website.org/src.
You shouldn't use it to make URLs directly, you can use it to make relative paths, for instance:
$root = $_SERVER['DOCUMENT_ROOT'];
$file_path = __FILE__;
$relative_file_path = str_replace($root, "", $file_path); // needs better logic but works in some cases
$base_url = "http://my.website.org/";
$url = $base_url . $relative_file_path; // http://www.mywebsite.org/path/to/file.php

PHP Include based on REQUEST_URI

Is there any security risks involved in using $_SERVER['REQUEST_URI'] to include a file? Can you pass ../../.. through the request uri somehow?
What I'm thinking is something like this:
<?php
$path = $_SERVER['REQUEST_URI'];
$path = preg_replace('~\\.html?$~', '.php', $path);
include $path;
?>
This should substitute ".htm" or ".html" URIs for ".php" paths and render them. But I am concerned about security here.
$_SERVER['REQUEST_URI'] contains the requested URI path and query string as it appeared in the HTTP request line. So when http://example.com/foo/bar?baz=quux is requested and the server passes the request to the script file /request_handler.php, $_SERVER['REQUEST_URI'] would still be /foo/bar?baz=quux. I’ve used mod_rewrite to map any request to request_handler.php as follows:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /request_handler.php
So for correctness, before using $_SERVER['REQUEST_URI'] in a file system path, you would need to get rid of the query string. You can use parse_url to do so:
$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
But as this value comes directly from the HTTP request line without prior path resolution, it may still contain symbolic path segments like ...
However, path traversal is not even necessary as the requested URI path is already an absolute path reference and requesting http://example.com/etc/passwd should result in the inclusion of /etc/passwd.
So this is actually a local file inclusion vulnerability.
Now to fix this, requiring a certain root directory using the method that you, chowey, have presented is a good improvement. But you would actually need to prefix it with $basedir:
$path = realpath($basedir . $_SERVER['REQUEST_URI_PATH']);
if ($path && strpos($path, $basedir) === 0) {
include $path;
}
This solution provides several promises:
$path is either a valid, resolved path to an existing file, or false;
inclusion of that file does only happen if $basedir is a prefix path of $path.
However, this may still allow access to files which are protected using some other kind of access control like the one provided by Apache’s mod_authz_host module.
This does not actually answer the question...
Note that you can ensure the request uri points to an actual valid filepath in the current working directory. You can use the realpath function to normalize the path.
The following code would do the trick:
<?php
$basedir = getcwd();
$path = $_SERVER['REQUEST_URI'];
$path = preg_replace('~\\.html?$~', '.php', $path);
$path = realpath($path);
if ($path && strpos($path, $basedir) === 0) {
include $path;
} else {
return false;
}
?>
Here I used strpos to verify that the $path starts with $basepath. Since realpath will have removed any ../../.. funny business, this should safely keep you within the $basepath directory.
Indeed dont trust the $_SERVER['REQUEST_URI'] before checking the basepath.
And dont make a filter that removes ../ from the path attackers can craft a nieuw way to inject if they understand the filter proces.
I had the same question and chose to do the following basing myself on Gumbo's answer :
$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$path = realpath(FOLDER_ROOT . $_SERVER['REQUEST_URI_PATH']);
$directory_white_list_array = array('/safe_folder1', '/safe_folder1/safe_folder2');
if ($path && strpos($path, FOLDER_ROOT) === 0 && (in_array(dirname($path), $directory_white_list_array) && ('php' == pathinfo($path, PATHINFO_EXTENSION)))) {
include $path;
}else{
require_once FOLDER_ROOT."/miscellaneous_functions/navigation_error.php";
navigation_error('1');
}
Summary:
Added directory whitelist and .php extension restriction.

PHP : List Files of Type in Directory and Link to them

I've got the code
$directory = "C:/My file path";
$phpfiles = glob($directory . "*.html");
foreach($phpfiles as $phpfiles)
{
echo $phpfiles;
}
But how would I change it so that it doesn't just list the files, but actually links to them?
First of all, don't use same variable names at foreach(). You can link to files, like this.
foreach($phpfiles as $phpfile)
{
echo "<a href=$phpfile>".basename($phpfile)."</a>";
}
$phpfile containing full path of file (for example : /home/eray/Desktop/test.html)
basename() is returning just file name from path . basename($phpfile)'s output is test.html . If you want to print just test (without .html extension) , you can use this : basename($phpfile, ".html") Thanks, #aSeptik.
Assuming that the links are accessible via a web server you'll need a different root path for web access than you have on your computer. Also, your foreach is wrong. The second variable needs to be singular (well, at least different than the first). So assuming your web server sees the file path as a valid site path:
$rootPath = "/MyFilePath";
foreach ($phpfiles as $phpfile)
{
echo "$phpfile";
}
$files = glob("*.html");
echo '<ul>'.implode('', array_map('sprintf', array_fill(0, count($files), '<li>%s</li>'), $files, $files)).'</ul>';
This is ok "eray"
$phpfile containing full path of file (for example :
/home/eray/Desktop/test.html) basename() is returning just file name
from path . basename($phpfile)'s output is test.html . If you want to
print just test (without .html extension) , you can use this :
basename($phpfile, ".html") Thanks, #aSeptik.
how to remove. php extension and in the link.
exaple:
http//example.com/dir1/file.php **
(with out .php on end).
Thanks

Categories