drupal batch fails to copy (some) files - php

I have a working drupal batch process. In it I want to copy image files (JPGs) from a source directory into a target directory with PHP copy function. Both the directories exist. The source file does exist, too. But the copy does not succeed.
I checked for the file permissions of the source directory (0755) and the source file (0744) and the target directory (0755). The owner and group are that of the script.
I debugged by putting the success of the copy into watchdog. It says it was successfull. But the file is not there.
This is the code where the copy takes place
$copy_from = $_SERVER["DOCUMENT_ROOT"]."/".$file->filepath;
$copy_to = $_SERVER["DOCUMENT_ROOT"]."/".$path_new;
$success = false;
if (file_exists($copy_from)) {
$success = copy($copy_from, $copy_to);
watchdog('catalog_copy2', ($success ? 'yes' : 'no')
. ' | ' . "copy('{$copy_from}', '{$copy_to}')");
}
If I copy the watchdog output and edit it slightly to end up in an shell copy order
cp path/to/file dest_path
The file is copied with no fuzz at all. So no typos and no case sensitive issues are in order.
I'm clearly nearly out of my mind, because I do not understand why I cannot copy the files with PHP.
Strange thing though is, some of the files are copied with my batch and some are not.
I'd be grateful for any hint where to look for to find a solution.
edit
I've worked around the problem by using the shell cp command using php's exec command. I'm not happy with this, but I had to make it work.
edit
I circumvented the problem by using the API function from the file_field module

the problem was not solved, but I managed to use the API functions from the file_field modules which works perfectly

Related

Copy file from any given path in Laravel

I want to copy a file from outside the root directory of my Laravel application using an artisan command which i made myself. The user will call the command like so:
php artisan crawl:pdf {filepath}
Then the filepath will be processed and on this part:
File::copy($path, storage_path('pdfs') . '/' . $fileName . ".pdf");
it breaks every time i use a path outside of my root directory it says "Failed to open stream: No such file or directory" as error msg".
I've already googled about copying files in plain php using copy() and in Laravel using Storage::copy(). Also reading through articles that all describe creating a disk which can route outside of laravel-root-directory.
All of that is not the solution to my problem. The user should be able to use any path.
C:\dir1\pdf3.pdf ;
E:\dir456\pdf2222.pdf`
...
from his own filesystem to copy files to the laravel-application.
Is their a way todo it ? Thx for all the help in advance!
EDIT 1:
Before anyone asks if i have write and read permission: yes i do. if i use plain php i can write and read everywhere on my working drive. I also checked the user laravel is running on with echo whoami and it gives the same user as my plain php application which works fine.
EDIT 2:
Worked in comments regarding using File-Facad-copy
Ok i found a solution and now it is working as i want it.
But first why is this happening. Laravel is expecting to always work on files using disks. It is required.
the solution is On-demand Disks!!!
This way it is possible to take a path given by a user and create a temporary disk which only works in this instance through facades.
Important is to make sure that the path given is always a directory! Like so:
$diskpath = dirname($path);
$disk = Storage::build([
'driver' => 'local',
'root' => "$diskpath",
]);
In my case I only want to copy one specific file which makes it mandatory to get the file information for correct naming and copying. Like so:
$pathinf = pathinfo($path)
$fileName = time() . '_' . $pathinf['filename']
Next we need to safe it to the new location. Like so:
Storage::disk('pdfs')->putFileAs('/', $path, $fileName . ".pdf");
Notes:
'pdfs' disk is a disk i configured in my filesystems.php config-file
I always asume that the user is giving the full path from the file like C:\...\test.pdf or something similar so watch out for the dirname() function. It will always cut the last part of the path and delete it.
Thanks to apokryfos for helping solving this through his comments and hints.

Using PHP to create a new directory, and a file in that directory

I recently started to mess around with some HTML and PHP, and have run into what is probably a super easy to solve error, but one I have not for the life of me been able to fix.
In a nutshell, what I'm trying to do is create a directory, then create a .txt file in that directory with the same name, something to the effect of "/number/number.txt". While it seems simple to create a file, or to create a directory, I'm having no end of troubles trying to do both.
Here's my code:
mkdir($postnum, 0777);
chmod($postnum, 0777);
$post = "/" . $postnum . "/" . $postnum . ".txt";
$post = boards(__FILE__) . $post;
$po = fopen($post, 'w+') or die("Can't open file");
chmod($post, 0777);
A few issues I ran into writing this, I read that using mkdir I could set the permissions of the directory I create, but despite doing what I believe to be the right way of doing so, it didn't do anything. So I ran chmod right after.
Then, I had hoped that just /$postnum/$postnum.txt would work for the directory to open, but I get the die text when I try just that, I had to add in the "boards(FILE) part to get it to work. (Side note, "boards" is the directory I'm working in)
Even then, while it doesn't give me "Can't open file", it isn't creating the file or anything.
I've made certain that any file or folder even remotely interacting with the files has had it's permissions set to 0777, so it's likely not an issue with that. (Also, I know that having all my files completely open like that may not be the best idea; once I get this working properly, I'll be sure to set the permissions to something more safe)
Any idea what I'm doing wrong?
making directory and creating path:-
$new_folder=mkdir('uploads\\'.$folder_name, 0777, true);
('uploads\\'.$folder_name)->path where you create folder like www->upload->folder name(whatever you provide)
$path="uploads\\".$folder_name."\\";//if you want to provide path you can provide this way
The mkdir function takes a path relative to the root of the filesystem, not the document root.
If you're on a *nix system, your website document root is likely in a path such as /var/www/sitename/html, but you're trying to create /number/number.txt which your account doesn't have permissions to do. Change the path you pass into mkdir to somewhere in the filesystem you have permissions to create folders and files and your code should work.
Edit:
The code in your question doesn't actually attempt to write anything. By calling fopen you've created a file handle, but you need to call fwrite to actually write data to the file. As suggested by #JamesSwift, you may want to take a look at file_put_contents.
Here, try this :
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
mkdir("$root/root_website_folder/php/testing_folder", 0777);
PHP uses your real path not the virtual one, we assign to $root the real path on your machine than add the virtual path of your website root

Weird behaviour of rename() in 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)!

PHP Can't find tmp directory

I am having problems with functions that create files in the tmp directory such as tmpfile() and tempnam(). They all seem to fail to write to tmp and return false. upload_tmp_dir is set in php ini and file uploads work fine.
When debugging this error I found that sys_get_temp_dir() gets the location of the tmp directory unfortunately it's not supported in my PHP version (5.1.6). I also saw that using the following method replaces the functionality of sys_get_temp_dir():
if ( !function_exists('sys_get_temp_dir')) {
function sys_get_temp_dir() {
if (!empty($_ENV['TMP'])) { return realpath($_ENV['TMP']); }
if (!empty($_ENV['TMPDIR'])) { return realpath( $_ENV['TMPDIR']); }
if (!empty($_ENV['TEMP'])) { return realpath( $_ENV['TEMP']); }
$tempfile=tempnam(__FILE__,'');
if (file_exists($tempfile)) {
unlink($tempfile);
return realpath(dirname($tempfile));
}
return null;
}
}
But there is no reference to a tmp directory in the $_ENV array and tempnam() fails as I mentioned before.
Also open_basedir is not set which I've heard can cause similar problems
How can I find out where the tmp directory is or whether it is even set?
Is this a apache server configuration issue or a PHP one?
Thanks for your help
I am running Ubuntu 18.04 and I could create/modify files in the /tmp directory when I ran the PHP script from the CLI, but when I tried accessing the same script as a web page, I could never find the file that was being created. It turns out that Apache by default will create a private tmp directory. The following post provided some insight on the problem Odd Bits - Private /tmp directory. However, the /usr/lib/systemd directory mentioned in the post did not contain any services for http or apache2 on my machine. To help track down the problem I executed the following command:
sudo find / -mount -type f -exec grep -e "PrivateTmp" '{}' ';' -print
and found in /lib/systemd/system/apache2.service the PrivateTmp=true mentioned in the Odd Bits post. Copying the file from /lib/systemd/system to /etc/systemd/system/ and changing true to false and executing
systemctl daemon-restart
systemctl restart apache2
fixed the problem. A person wiser than me suggested copying the file to /etc instead of editing it in /lib was the correct course of action because /lib is 'owned' by the packages and local edits should be performed in /etc. systemd man page describes the systemd configuration processing in gory details.
you can set the upload temp dir in your php.ini -
something like that should work:
upload_tmp_dir=/your-www/tmp/
Also, in case you can't edit the php.ini or don't want to do it globally you can use this in the beginning of your script:
ini_set('upload_tmp_dir','/your-home-www/tmp/');
TMP, TEMP (and maybe TMPDIR) are valid on Windows only and usually pointing to C:\Windows\TEMP. On Linux default temp location is /tmp. To workaround this (works with tempnam() function) you can create a temp folder somewhere within your website space, specify appropriate access permissions and pass this as first parameter to the above function.
Not a great solution but better than nothing.
Probably not the cleanest but this works on my old 5.1.6 install:
function get_temp_path() {
static $path = null;
if ($path !== null) return $path;
$file = tmpfile();
$meta = stream_get_meta_data($file);
fclose($file);
$path = dirname($meta['uri']);
return $path;
}
I have the same problem and the solution is to change the apache configuration to expose the TEMP variable to PHP, see this post.
Tip for newbies like me: I THOUGHT that PHP couldn't move stuff from my temporary folder, but I was just confused because of the relative positions of folders. This may apply to someone else, so I'll explain, even though it's very tangentially related to this specific question (because this specific question is a likely search result for other people like me who are newbies).
My problem is that I was echoing an upload form FROM a functions.php file inside of /var/www/html/ TO a profile.php file in /var/www/html/user/ which CALLED an uploadphoto.php file in /var/www/html/. Uploaded files were ultimately intended to land in /var/www/html/uploads. This ultimately meant that most of my references to both uploadphoto.php AND uploads/ in functions.php were written "../uploadphoto.php" or "../uploads/[etc.jpg]", respectively, in order to step back into html/ from html/user/ (where the echoed code landed in html/user/profile.php). This led me to intuitively use the following command inside of uploadphoto.php without thinking it through:
move_uploaded_file($_FILES["file"]["tmp_name"][0], "../uploads/$filename")
See the problem? uploadphoto.php is in the same directory as uploads/, so I did not need the ../ here. For hours, I was sure I was messing up my folder permissions again, because I am new to image uploading. I had forgotten to check for more simple-minded errors. Hopefully this helps someone else.

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.

Categories