Weird behaviour of rename() in PHP - php

I am having a weird problem with my php. Whenever I try to move a file with rename(), not only the file is not moved, but also the directory to which it should be copied is deleted, together with all files within it. The original code is:
rename('temp.odt', 'tmp/report.odt');
but I have already tried other path delimiters like
rename('temp.odt', 'tmp\report.odt');
rename('temp.odt', 'tmp\\report.odt');
rename('temp.odt', 'tmp' . DIRECTORY_SEPARATOR . 'report.odt');
rename('C:\wamp\www\zaiko\temp.odt', 'C:\wamp\www\zaiko\tmp\report.odt');
all to no avail. The code comes from a 3rd-party module which is used in the system I am working on.
Points well checked:
The file 'temp.odt' does exist in the current directory;
The directory 'tmp' does exist and there are several files in it. Also it is not read only.
The target file does not already exist (the actual file name has a timestamp, I reduced it here for simplicity)
After running rename(), the 'temp.odt' file is intact in its original location, while the folder 'tmp' is vanished as well as everything inside it. The following warning is issued:
( ! ) Warning: rename(temp.odt,tmp\report.odt) [function.rename]: The system couldn't find the specified path*. (code: 3) in C:\wamp\www\zaiko\modules\mod_deliver.php on line 192
*translated from Portuguese
Running: Apache 2.2.17 with PHP 5.3.5 on Windows XP with NTFS
Editing:
Just found the cause of the problem. It turns out that the module used by the application uses, in turn, a compression library; this library uses a temporary folder with exactly the same name as the one used by the application.
It must use some sort of cache, which would explain why the error didn't appear 100% times.
Problem solved by changing the name of the 'tmp' folder to anything else.
Thank you all for your time, and sorry for bothering you with such a stupid thing that, as it turns out, had absolutely nothing to do with my initial guess and, consequently, with the question formulated.

The example on PHP.net tells you exactly what to do - use the ROOT PATH to the file - normally this can be got by using $_SERVER['DOCUMENT_ROOT'] (but this only goes to the htdocs/public_html directory - you need to specify the rest) or by manually typing the path in (but try to avoid this).
<?php
rename("/tmp/tmp_file.txt", "/home/user/login/docs/my_file.txt");
?>
At a guess, the following should work (assuming this is your path) - this also checks that your file actually exists so it can be renamed - you need to make sure that tmp/ actually exists in the first place, but you will get an error popping out if it didn't:
<?php
$root = getcwd().DIRECTORY_SEPARATOR; // Obtain the current working dir
$srcpath = $root."temp.odt"; // The file you want to rename
$destpath = $root."tmp/report.odt"; // Where you want to rename the file to
// make sure file exists and its movable
if(is_writable($srcpath)){
// if it exists, rename it
rename($srcpath, $dstpath);
echo "File was renamed!";
} else {
echo "It seems that the specified file doesn't exist!";
}
?>
You were escaping characters by using backslashes - always use forward slashes (I know this is within a single quote, which is ok, but if you use double quote then you would wonder what's gone wrong)!

Related

Invalid font filename (imagettfbox)

This question has been asked over and over but I could not find the correct answer to my problem... As a little background note, all the code was working perfectly before we moved the class file from /application/lib/class to /library/class ...
I have tried to play with GDFONTPATH, relative, absolute paths with and without the file extension to no avail. Here is some of the lines we have tried so far:
putenv('GDFONTPATH=' . realpath(dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'fonts'));
/*1*/ $FontName = dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'fonts'.DIRECTORY_SEPARATOR.basename($FontName,'.ttf');
/*2*/ $FontName = '\pChart\fonts\\'.basename($FontName);
/*3*/ $FontName =basename($FontName);
$coords = imagettfbbox($FontSize, 0, $FontName, $Text);
Multiple combination of those tries have also been used to no avail. I am really annoyed by this problem as the #1, when echo'ed gives a full path that opens up the correct font file if copy/pasted in win explorer.
It might help to know the absolute path of the file getting the error and the path of the fontname...
C:\wamp\www\application_bundle\Library\pChart\class\pImage.class.php
C:\wamp\www\application_bundle\Library\pChart\fonts\arialuni.ttf
We are experiencing this problem on all dev platforms (Win, Mac and Linux) PHP 5.3.13
Thank you for your assistance.
Edit: It seems as if the file is not found / the server is not looking at the right folder... If someone could help troubleshoot the problem by pointing out how to figure out what path GD is trying to open would really help.
We have figured out how to make it work.
To put it short, we were including the class file and then calling the methods to write the text. We were doing something like this:
$classPath = 'pChart/';
include($classPath.'/class/pImage.class.php');
//... inside the pImage.class we passed font like this: $FontName = $classPath.'/fonts/arialuni.ttf';
imagettfbbox($FontSize, 0, $FontName, $Text)
It did not work whatever we did before or after... Until we changed the $classPath to
$classpath = '../library/pChart/';
Note that they are (or should) point exactly to the same folder as the code is executed from a file in library root.
We have tried to find why absolute paths were not working but could not reproduce the bug in an isolated environment so there's something fishy with our architecture.
Thank you for your time everyone.
I know this has been answered and accepted but I didn't see anyone chiming in on why this solution worked and what was incorrect in the first place.
The short description of the problem
The current working directory is established at the point php get's it's hands on the request and all relative paths are resolved based on the current working directory, not the directory of the file that the path is referenced in.
The long description of the problem
Relative paths in php are resolved based on the current working directory.
For testing purposes you can always see what the current working directory is by calling getcwd
This value is initially arrived at on an http request as the directory that contains the file that the web server initially handed off the request to php.
So for example if you go to http://www.mydomain.com/index.php the current working directory will be the same as the document root ($_SERVER["DOCUMENT_ROOT"])
For a CLI request the cwd is the directory you are in when you execute the command. So if I am at /home/orangepill and I run /usr/bin/php /path/to/file.php the cwd will be /home/orangepill.
This causes a problem for relative file references within included files.
Lets take this example.
Client navigates to www.mydomain.com
Apache has index.php set in the DirectoryIndex directive and apache finds an index.php file in the document root. Current working directory is set to the document root.
/index.php contains the line include "library/myclass.php";
$_SERVER["DOCUMENT_ROOT"]."/library/myclass.php" exists and all is good
myclass.php contains the line include("myclass_helper.php"); this resolves to $_SERVER["DOCUMENT_ROOT"]."/myclass_helper.php". (remember relative references resolve relative to the current working directory)
$_SERVER["DOCUMENT_ROOT"]."/myclass_helper.php" doesn't exist its actually in $_SERVER["DOCUMENT_ROOT"]."/library/myclass_helper.php"
You are probably thing but wait... I've experienced different behavior in my scripts when including within an include. The reason for that is the include and require language constructs (along with a couple of other file system commands) try to include relative paths from each of the paths specified in the include path php directive. So in the above example if library directory off of the document root existed within the include paths then everything would work as expected.
A wholesale solution for requiring files relative to the current file is to structure your include paths using the __DIR__ contextual constant. So you would use include __DIR__."/myclass_helper.php"; (include dirname(__FILE__)."/myclass_helper.php in pre PHP 5.3 environments) and at runtime this would effectively convert your relative path to an absolute path based on the location of the file doing the include.
For common include directories I have gotten into the habit of specifying a few commonly used locations for use with relative file system references. for example
define ("APPLICATION_PATH", realpath($_SERVER["DOCUMENT_ROOT"]."/application");
define ("LIBRARY_PATH", realpath($_SERVER["DOCUMENT_ROOT"]."/library");
define ("CONFIG_PATH", APPLICATION_PATH."/etc/";
This gives you a lot of anchor points to include paths relative to.
Have you dumped $FontName before this piece of code to debug its value?
Anyway, if you're already setting GDFONTPATH, you don't need to use any path on $FontName, in this case you could just use the font name (arialuni.ttf or even just arialuni) or at most basename() function as in your #3 example.
Your putenv() call could be just putenv('GDFONTPATH=' . realpath('../fonts')).
Try that to see if it works:
putenv('GDFONTPATH=' . realpath('../fonts'));
$FontName = 'arialuni.ttf'; // note that I'm using font name directly
$coords = imagettfbbox($FontSize, 0, $FontName, $Text);
Update 1
Please, dump your GDFONTPATH and tell me what it prints. Add that after your putenv() call, it will force your code to raise an error with the GDFONTPATH it looked for:
trigger_error(sprint('GDFONTHPATH = %s', getenv('GDFONTPATH')), E_USER_ERROR);
One may also just try to state a link relative to the root directory. I had the same problem ("Invalid file font name", function "...") and fixed it like that in the main file where the pChart is being initialized:
$myPicture->setFontProperties(array("FontName"=>$_SERVER['DOCUMENT_ROOT']."/files/lib/pChart/fonts/verdana.ttf"));
Solved the issue for me.
This line USED to be like that:
$myPicture->setFontProperties(array("FontName"=>"fonts/verdana.ttf"));
which - I don't know why - provoked an error today.
Please note that this solution is not very elegant since it relies on the fact that your pChart folder is actually located at something like
http://myHomepage.com/files/lib
, meaning it does not work with relative directories.

PHP Polymorphic Root Requires

I have a directory/file tree as follows:
index.php
/frame/main_class.php
/frame/func/function_1.php
/frame/func/function_1.php
/cfg/config.php
//index.php
require('frame/main_class.php');
new main_class;
//frame/main_class.php
class main_class{
public function __construct(){
require('func/function_1.php');
require('func/function_2.php');
require('cfg/config.php');
}
}
The weird part is that it works. Maybe it is late and I am having a dumb-moment, but shouldn't "require('cfg/config');" be written "require('../cfg/config.php');" ?
And if it is using the root of index.php, then "require('func/function_1.php');" shouldn't work, right?
I have quadruple checked the remote server thinking that maybe there was a stray file or two... there isn't.
How can the two require statements have a different base path.....?
Does anyone know of a code snippet that could cause this to happen? I am working with some $_SERVER variables but I don't appear to be changing any of them....!?
"Files are included based on the file path given or, if none is given, the include_path specified. If the file isn't found in the include_path, include will finally check in the calling script's own directory and the current working directory before failing." Explicitly saying include dirname(__FILE__) . '/path/to/file.php';avoids this confusion. – DCoder
Link to PHP Manual on "dirname".
The PHP engine will look for the requested files in the current directory, but it will also look for them in the list of paths defined in INCLUDE_PATH. If the include path lists the path from where your script is running then the given code will work. If not then it wont.
For that reason amongst others it's not a good idea to rely on the include path to resolve the path of included files. You should give the full path instead.

Include files from parent or other directory

I'm needing to include a file from the parent directory, and other sub-directories, into a sub-directory. I've done it before by simply using include('/rootdirectory/file.php'); but now it won't seem to work.
Just wondering how I can do this, thanks.
Here's my exact line:
include('/forums/groups.php');
It's giving me this error(the page still runs):
Warning: include(/forums/groups.php) [function.include]: failed to
open stream: No such file or directory in
C:\xampp\htdocs\forums\blog\posts.php on line
Warning: include() [function.include]: Failed opening
'/forums/groups.php' for inclusion
(include_path='.;C:\xampp\php\PEAR') in
C:\xampp\htdocs\forums\blog\posts.php on line 3
include() and its relatives take filesystem paths, not web paths relative to the document root. To get the parent directory, use ../
include('../somefilein_parent.php');
include('../../somefile_2levels_up.php');
If you begin with a /, an absolute system file path will be used:
// Full absolute path...
include('/home/username/sites/project/include/config.php');
If your server is not resolving the file from the parent directory using
include '../somefilein_parent.php'
try this (using the parent directory relative to the script):
include __DIR__ . "/../somefilein_parent.php";
Here's something I wrote with that problem in mind:
<?
function absolute_include($file)
{
/*
$file is the file url relative to the root of your site.
Yourdomain.com/folder/file.inc would be passed as
"folder/file.inc"
*/
$folder_depth = substr_count($_SERVER["PHP_SELF"] , "/");
if($folder_depth == false)
$folder_depth = 1;
include(str_repeat("../", $folder_depth - 1) . $file);
}
?>
hope it helps.
Depends on where the file you are trying to include from is located.
Example:
/rootdir/pages/file.php
/someotherDir/index.php
If you wrote the following in index.php:
include('/rootdir/pages/file.php');it would error becuase it would try to get:
/someotherDir/rootdir/pages/file.php Which of course doesn't exist...
So you would have to use include('../rootdir/pages/file.php');
In laymans terms, and practicality, I see this as an old DOS trick/thing. Whoa! What was that? DOS? Never heard of it!
".." backs you out of the current sub-directory one time to a higher folder/directory, and .. enter typed twice backs you out too 2 higher parent folders. Keep adding the ".. enter" back to back and you will soon find yourself at the top level of the directory.
As for Newbies to understand this better, consider this (in terms of the home PC or "C:\ drive" if you know what that means, rather than the web-servers/host "root directory" ). While your at it, Consider your website existing somewhere on your home PC's hard drive, buried in some folder under the C:\ drive. Lastly, you can think of it as ".." is back one directory and "/" is forward one directory/folder.
Now!
If you are using the command prompt and are within the "myDocuments" folder of your PC you must back out of that folder to get closer to the higher directory "C:\" by typing the "../".
If you wanted to access a file that is located in the widows directory while you are still in the myDocuments folder you would theoretically type ../windows; in reality of DOS command prompt you would simply type .., but I am setting you up for the web. The / redirects forward to another directory naturally.
Using "myDocuments" lets pretend that you created 2 folders within it called "PHP1" and "PHP2", in such we now have the folders:
C:\myDocuments\PHP1
C:\myDocuments\PHP2
In PHP1 you place a file called index.php. and in PHP2 folder you placed a file called Found.php. it now becomes:
C:\myDocuments\PHP1\index.php
C:\myDocuments\PHP2\found.php
Inside the
C:\myDocuments\PHP1\index.php file you would need to edit and type something like:
<?php include ('../php2/found.php')?>
The ../ is positional thus it considers your current file location "C:\myDocuments\PHP1\index.php" and is a directive telling it to back out of PHP1 directory and enter or move forward into PHP2 directory to look for the Found.php file. But does it read it? See my thoughts on trouble shooting below.
Now! suppose you have 1 folder PHP1 and a sub-folder PHP2:
C:\myDocuments\PHP1\PHP2
you would simply reference/code
<?php include('/PHP2/found.php') ?>
as PHP2 exist as a sub-directory, below or within PHP1 directory.
If the above does not work it may have something to do with access/htaccess or permission to the directory or a typo. To enhance this...getting into trouble shooting...If the "found.php" file has errors/typo's within it, it will crash upon rendering at the error, such could be the reason (require/require_once) that you are experiencing the illusion that it is not changing directories or accessing the file.
At last thought on the matter, you may need to instantiate your functions or references in order to use the included/require "whatever" by creating a new variable or object such as
$newObject = new nameobject("origianlThingy");
Remember, just because you are including/requiring something, sometimes means just that, it is included/required to run, but it might need to be recreated to make it active or access it. New will surely re-create an instance of it "if it is readable" and make it available within the current document while preserving the original. However you should reference the newly created variable $newObject in all instances....if its global.
To put this in perspective of some web host account; the web host is some whopping over sized hard-drive (like that on your PC) and your domain is nothing more than a folder they have assigned to you. Your folder is called the root. Inside that folder you can do anything you are allowed to do.
your "one of many ways" to move between directories/folders is to use the ../ however many times to back out of your current in reference to folder position you want to find.
In my drunken state I realize that I know too much to be sane, and not
enough to be insane!"
Any path beginning with a slash will be an absolute path. From the root-folder of the server and not the root-folder of your document root. You can use ../ to go into the parent directory.
You may interest in using php's inbuilt function realpath().
and passing a constant DIR
for example:
$TargetDirectory = realpath(__DIR__."/../.."); //Will take you 2 folder's back
String realpath() :: Returns canonicalized absolute pathname ..
I took inspiration from frank and I added something like this in my "settings.php" file that is then included in all pages when there is a link:
"settings.php"
$folder_depth = substr_count($_SERVER["PHP_SELF"] , "/");
$slash="";
for ($i=1;$i<=($folder_depth-2);++$i){
$slash= $slash."../";
}
in my header.php to be included in all pages:
a href= .... php echo $slash.'index.php'....
seems it works both on local and hosted environment....
(NOTE: I am an absolute beginner )
Had same issue earlier solved like this :
include('/../includes/config.php'); //note '/' appearing before '../includes/config.php'
the root directory (in PHP) is the directory of the file that is pinged. For example, I go to http://localhost/directory/to/file/index.php, the root directory will be "/dictory/to/file", since it's the one that you've made a web request for.
I can't believe none of the answers pointed to the function dirname() (available since PHP 4).
Basically, it returns the full path for the referenced object. If you use a file as a reference, the function returns the full path of the file. If the referenced object is a folder, the function will return the parent folder of that folder.
https://www.php.net/manual/en/function.dirname.php
For the current folder of the current file, use $current = dirname(__FILE__);.
For a parent folder of the current folder, simply use $parent = dirname(__DIR__);.
If your configuration file PHP.ini is set up correctly then you can use:
include($_SERVER["DOCUMENT_ROOT"]."/my_script.php");
// or
require($_SERVER["DOCUMENT_ROOT"]."/my_script.php");

Using php oncli few questions ~ using XAMPP

Attempting to expand my knowledge by using PHP on the Command Line.
Currently I have a default installation of XAMPP, and have set up my Environment Variable.
I've been able to execute simple scripts like:
<?php echo 'hello world!'; ?>
Questions ~
Where do I store the scripts I am using? Currently I am doing:
C:\Users\Ross>php c:\helloworld.php
it works. Does this mean I need to specify a path every time? Or should I store php files inside my c:>xampp\php directory? I tried this and it doesn't appear to work.
What would be the accepted "best practice".
2nd question
Could someone explain why this doesn't work:
<?php
fwrite(STDOUT, "Enter file name:\n");
$file=fgets(STDIN);
print 'you entered...' . $file;
$fp=fopen($file,'r');
if(!$fp)
{
print 'File could not be opened..';
}
else
{
/* show file pointer */
print($fp);
}
?>
and then I do:
C:\Users\Ross>php c:\file.php
Enter file name:
c:\foo.txt
you entered...c:\foo.txt
Warning: fopen(c:\foo.txt): failed to open stream: Invalid argument in C:\file.php on line 6
File could not be opened..
"foo.txt" is in the same directory and does exist.
thanks for any clarification.
As far as were to store the files is concerned: I normally add the directory where php.exe is to my PATH environment variable, that way I can just call php in whatever directory contains the script I need to run. If you don't add the directory to PATH, then you would need to either run php from its directory and specify the full path to the PHP script, or run it from the directory where the PHP script is and specify the full path to the PHP executable.
Regarding opening the file: the reason this is occurring is because fgets is returning the newline from you pressing enter, too (it would seem). So in reality, it's trying to open a file whose name actually ends with a new line character.
Change the line:
$file=fgets(STDIN);
to:
$file=trim(fgets(STDIN));
and you should be fine.
question #1: all your php files should be inside the www folder of xampp (c:\xampp\www)
question #2: probably because you are not working in the correct folder.
xammp is good but I recommend you to use wamp, it's much easier to understand and use. Just google for it. xampp is more for those who are more techically skilled.

PHP Image Upload trouble

I am currently working on a Joomla! website. I am using the Jumi extension (which allows custom scripts to be made and executed within Joomla! itself) to create a simple file upload tool. The problem is that I get the following error:
Warning: copy(C:/xampp/htdocs/images/1253889508.jpg) [function.copy]: failed to open stream: No such file or directory in C:\xampp\htdocs\Joomla\components\com_jumi\jumi.php(25) : eval()'d code on line 61
The offending code is as follows:
//we will give an unique name, for example the time in unix time format
$image_name=time().'.'.$extension;
//the new name will be containing the full path where will be stored (images folder)
$newname='C:/xampp/htdocs/images/'.$image_name;
//we verify if the image has been uploaded, and print error instead
$copied = copy($_FILES['image']['tmp_name'], $newname);
The full code is available here. Once I get this working, I will be modifying it to meet the needs of my website.
I'm not sure if the problem is a permissions issue with Jumi or if there is some other problem. The best I can tell is that for whatever reason, the temp file is not being created.
Thanks for any tips you may have!
Try this:
if(move_uploaded_file($_FILES['image']['tmp_name'], $newname)){
// move worked, carry on
}
And use relative paths instead of absolute ones.
does your C:/xampp/htdocs/images directory actually exists?
if not create it manually or with mkdir()
also try to use the constant DIRECTORY_SEPARATOR instead of hardcoding slashes
Also you should use the move_uploaded_file() for this and not the copy() function.
And never hardcode absolute paths into your scripts! instead get the root path and preferibly set it as a constant, this is mostly done with the dirname() function in the entry file, but joomla allready has a constant you can use for this.
Forward slashes in the $namename path rather than backslashes?

Categories