I'm trying to host a PHP website developed on a Mac on IIS.
I have an upload form for images. The path to the images is saved to the database in Windows style (i.e. \images\foo.jpeg). In my template I use these images as background using css. Because of the Windows-style paths the images are not displayed, cause the path is incorrect.
Question: How can I convert a Windows path to a valid URL. So \uploads\images\25.jpeg should be changed to /uploads/images/25.jpeg . Is there a function like realpath that can do this or should I take the dirty way using a str_replace or regex?
You convert all windows path to UNIX path using the following function. it's a WordPress core function and well tested
function wp_normalize_path( $path ) {
$path = str_replace( '\\', '/', $path );
$path = preg_replace( '|(?<=.)/+|', '/', $path );
if ( ':' === substr( $path, 1, 1 ) ) {
$path = ucfirst( $path );
}
return $path;
}
Example :
E:\\xampp\\htdocs\\php\\index.php
Output :
E:/xampp/htdocs/php/index.php
Try to use the DIRECTORY_SEPARATOR instead of the '/' or '\' for paths (dir constants). This constant will recognize the OS for you and will use the right separator base on that.
To change the oldpath you can try to use:
str_replace("/", DIRECTORY_SEPARATOR, 'example/bla/bla.php');
As tip: __FILE__, __DIR__ or dirname() can help you in lot of situations to get the right path on the running OS.
Related
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);
}
?>
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.
Trying to setup a php website on my windows os. PHP code that I got from someone has lines like
$base_path = realpath('./../').'/';
This ends up with the string like c:\abc\xyz/
What settings I need to do on windows to force it to come with /. I read about DIRECTORY_SEPERATOR, but there are various places I need to worry about and hence if I could have it so that the realpath comes up with / it will be of great help to me.
A variation of Timothy's answer which uses the DIRECTORY_SEPARATOR constant instead of a conditional to simplify the function.
function platformSlashes($path) {
return str_replace('/', DIRECTORY_SEPARATOR, $path);
}
$path = "/some/path/here";
echo platformSlashes($path);
The backslash is the directory separator on the Windows platform. But from what I understand and have experienced, when resolving paths your PHP script will still work with forward slashes. As a consequence, you could write all your code with forward slashes and not worry about it. The forward/backwardslashes are really only important if you're displaying the path to the user, like in a setup/installer script (most users of a site would have no need to know about directory structures nor care what platform the service is running on). You could create a display function that would identify the platform and replace the slashes as appropriate, and then pass the paths through this before showing them. The following is an example of what I'm suggesting, though I haven't tested it.
<?php
function platformSlashes($path) {
if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
$path = str_replace('/', '\\', $path);
}
return $path;
}
$path = "/some/path/here";
echo platformSlashes($path);
Just do a replace on the string you have:
$base_path = realpath('./../') . '/';
$base_path_mod = str_replace('\\', '/', $base_path);
I'm having a very weird issue with file_exists(). I'm using this function to check if 2 different files in the same folders do exist. I've double-checked, they BOTH do exist.
echo $relative . $url['path'] . '/' . $path['filename'] . '.jpg';
Result: ../../images/example/001-001.jpg
echo $relative . $url['path'] . '/' . $path['filename'] . '.' . $path['extension'];
Result: ../../images/example/001-001.PNG
Now let's use file_exists() on these:
var_dump(file_exists($relative . $url['path'] . '/' . $path['filename'] . '.jpg'));
Result: bool(false)
var_dump(file_exists($relative . $url['path'] . '/' . $path['filename'] . '.' . $path['extension']));
Result: bool(true)
I don't get it - both of these files do exist. I'm running Windows, so it's not related to a case-sensitive issue. Safe Mode is off.
What might be worth mentioning though is that the .png one is uploaded by a user via FTP, while the .jpg one is created using a script. But as far as I know, that shouldn't make a difference.
Any tips?
Thanks
file_exists() just doesn't work with HTTP addresses.
It only supports filesystem paths (and FTP, if you're using PHP5.)
Please note:
Works :
if (file_exists($_SERVER['DOCUMENT_ROOT']."/folder/test.txt")
echo "file exists";
Does not work:
if (file_exists("www.mysite.com/folder/test.txt")
echo "file exists";
Results of the file_exists() are cached, so try using clearstatcache(). If that not helped, recheck names - they might be similar, but not same.
I found that what works for me to check if a file exists (relative to the current php file it is being executed from) is this piece of code:
$filename = 'myfile.jpg';
$file_path_and_name = dirname(__FILE__) . DIRECTORY_SEPARATOR . "{$filename}";
if ( file_exists($file_path_and_name) ){
// file exists. Do some magic...
} else {
// file does not exists...
}
Just my $.02: I just had this problem and it was due to a space at the end of the file name. It's not always a path problem - although that is the first thing I check - always. I could cut and paste the file name into a shell window using the ls -l command and of course that locates the file because the command line will ignore the space where as file_exists does not. Very frustrating indeed and nearly impossible to locate were it not for StackOverflow.
HINT: When outputting debug statements enclose values with delimiters () or [] and that will show a space pretty clearly. And always remember to trim your input.
It's because of safe mode. You can turn it off or include the directory in safe_mode_include_dir. Or change file ownership / permissions for those files.
php.net: file_exists()
php.net: safe mode
Try using DIRECTORY_SEPARATOR instead of '/' as separator. Windows uses a different separator for file system paths (backslash) than Linux and Unix systems.
A very simple trick is here that worked for me.
When I write following line, than it returns false.
if(file_exists('/my-dreams-files/'.$_GET['article'].'.html'))
And when I write with removing URL starting slash, then it returns true.
if(file_exists('my-dreams-files/'.$_GET['article'].'.html'))
I have a new reason this happens - I am using PHP inside a Docker container with a mounted volume for the codebase which resides on my local host machine.
I was getting file_exists == FALSE (inside Composer autoload), but if I copied the filepath into terminal - it did exist! I tried the clearstatche(), checked safe-mode was OFF.
Then I remembered the Docker volume mapping: the absolute path on my local host machine certainly doesn't exist inside the Docker container - which is PHP's perspective on the world.
(I keep forgetting I'm using Docker, because I've made shell functions which wrap the docker run commands so nicely...)
It can also be a permission problem on one of the parent folders or the file itself.
Try to open a session as the user running your webserver and cd into it. The folder must be accessible by this user and the file must be readable.
If not, php will return that the file doesn't exist.
have you tried manual entry. also your two extensions seem to be in different case
var_dump(file_exists('../../images/example/001-001.jpg'));
var_dump(file_exists('../../images/example/001-001.PNG'));
A custom_file_exists() function inspired by #Timur, #Brian, #Doug and #Shahar previous answers:
function custom_file_exists($file_path=''){
$file_exists=false;
//clear cached results
//clearstatcache();
//trim path
$file_dir=trim(dirname($file_path));
//normalize path separator
$file_dir=str_replace('/',DIRECTORY_SEPARATOR,$file_dir).DIRECTORY_SEPARATOR;
//trim file name
$file_name=trim(basename($file_path));
//rebuild path
$file_path=$file_dir."{$file_name}";
//If you simply want to check that some file (not directory) exists,
//and concerned about performance, try is_file() instead.
//It seems like is_file() is almost 2x faster when a file exists
//and about the same when it doesn't.
$file_exists=is_file($file_path);
//$file_exists=file_exists($file_path);
return $file_exists;
}
This answer may be a bit hacky, but its been working for me -
$file = 'path/to/file.jpg';
$file = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].'/'.$file;
$file_headers = #get_headers($file);
if($file_headers[0] == 'HTTP/1.1 404 Not Found') {
$exists = false;
}else{
$exists = true;
}
apparently $_SERVER['REQUEST_SCHEME'] is a bit dicey to use with IIS 7.0 + PHP 5.3 so you could probably look for a better way to add in the protocol.
I found this answer here http://php.net/manual/en/function.file-exists.php#75064
I spent the last two hours wondering what was wrong with my if statement: file_exists($file) was returning false, however I could call include($file) with no problem.
It turns out that I didn't realize that the php include_path value I had set in the .htaccess file didn't carry over to file_exists, is_file, etc.
Thus:
<?PHP
// .htaccess php_value include_path '/home/user/public_html/';
// includes lies in /home/user/public_html/includes/
//doesn't work, file_exists returns false
if ( file_exists('includes/config.php') )
{
include('includes/config.php');
}
//does work, file_exists returns true
if ( file_exists('/home/user/public_html/includes/config.php') )
{
include('includes/config.php');
}
?>
Just goes to show that "shortcuts for simplicity" like setting the include_path in .htaccess can just cause more grief in the long run.
In my case, the problem was a misconception of how file_exists() behaves with symbolic links and .. ("dotdot" or double period) parent dir references. In that regard, it differs from functions like require, include or even mkdir().
Given this directory structure:
/home/me/work/example/
www/
/var/www/example.local/
tmp/
public_html -> /home/me/work/example/www/
file_exists('/var/www/example.local/public_html/../tmp/'); would return FALSE even though the subdir exists as we see, because the function traversed up into /home/me/work/example/ which does not have that subdir.
For this reason, I have created this function:
/**
* Resolve any ".." ("dotdots" or double periods) in a given path.
*
* This is especially useful for avoiding the confusing behavior `file_exists()`
* shows with symbolic links.
*
* #param string $path
*
* #return string
*/
function resolve_dotdots( string $path ) {
if (empty($path)) {
return $path;
}
$source = array_reverse(explode(DIRECTORY_SEPARATOR, $path));
$balance = 0;
$parts = array();
// going backwards through the path, keep track of the dotdots and "work
// them off" by skipping a part. Only take over the respective part if the
// balance is at zero.
foreach ($source as $part) {
if ($part === '..') {
$balance++;
} else if ($balance > 0) {
$balance--;
} else {
array_push($parts, $part);
}
}
// special case: path begins with too many dotdots, references "outside
// knowledge".
if ($balance > 0) {
for ($i = 0; $i < $balance; $i++) {
array_push($parts, '..');
}
}
$parts = array_reverse($parts);
return implode(DIRECTORY_SEPARATOR, $parts);
}
I just encountered this same problem and I solved it in a mysterious way. After inserting a a filepath I copied from Windows File explorer. file_exists() keeps returning false continuously, but if I copy same path from VSCode editor it works perfectly.
After dumping variables with var_dump($path); I noticed something mysterious.
For path I copied from file explorer it shows length 94.
For path I copied from VSCode Editor it shows length 88.
Both path look same length on my code Editor.
My suggestion: if string contain hidden characters, it may fail and not work.
I want my php script to create an output file in a folder based on the date. The way I'm doing this is that its supposed to get the foldername/filename from a text file outputted by another program which I am unable to edit.
So the file its grabbing the data from looks like this:
data/newfolder/10302008/log_for_Today.txt | 24234234
Only with multiple lines, I just need the script to go through it line by line, grab the folder/filename and create an empty file with that name in that location.
The directories are all 777. Now I know how to create a new empty exe file in a folder but can't seem to figure out how to create the folder first then the exe inside of it, any ideas?
if(!file_exists(dirname($file)))
mkdir(dirname($file), 0777, true);
//do stuff with $file.
Use the third parameter to mkdir(), which makes it create directories recursively.
With
$directories = explode( '/', $path );
you can split the path to get single directory names. Then go through the array and create the directories setting chmod 777. (The system user, who executes php must have the ability to do that.)
$file = array_pop( $directories );
$base = '/my/base/dir';
foreach( $directories as $dir )
{
$path = sprintf( '%s/%s', $base, $dir )
mkdir( $path );
chmod( $path, 777 );
$base = $path;
}
// file_put_contents or something similar
file_put_contents( sprintf( '%s/%s', $base, $file ), $data );
The problem here is that you might not set chmod from your php script.
An alternative could be to use FTP. The user passes FTP login data to the script and it uses FTP functionality to manage files.
http://www.php.net/FTP
It's little too late but I found this question and I have a solution for this, here is an example code and it works good for me no matter how deep is your file. You should change directory separator for lines 1 and 3 if you're running it on Windows server.
$pathToFile = 'test1/test2/test3/test4/test.txt';
$fileName = basename($pathToFile);
$folders = explode('/', str_replace('/' . $fileName, '', $pathToFile));
$currentFolder = '';
foreach ($folders as $folder) {
$currentFolder .= $folder . DIRECTORY_SEPARATOR;
if (!file_exists($currentFolder)) {
mkdir($currentFolder, 0755);
}
}
file_put_contents($pathToFile, 'test');
Best regards, Georgi!
Create any missing folders using mkdir(), then create the empty file using touch().
You can use absolute paths in both cases, meaning:
mkdir('data');
mkdir('data/newfolder');
mkdir('data/newfolder/10302008');
touch('data/newfolder/10302008/log_for_Today.txt');
if you're curious about where it's starting-point it will be, you can use getcwd() to tell you the working directory.
Can't you just do this by creating the dir with mkdir (http://nl.php.net/manual/en/function.mkdir.php) then chmod it 777 (http://nl.php.net/manual/en/function.chmod.php) the change directory with chdir (http://nl.php.net/manual/en/function.chdir.php) and then create the file (touch)?