I am frequenty getting "unexpected end of file" errors, I think they only happen on included files and not the base files themselves. But anyway they happen whenever I upload a file at the same time a user happens to load a page that uses the file that's being uploaded.
How would I go about detecting whether a file is being uploaded? Or is there some way to configure my FTP client (I use FileZilla) to read-lock files while uploading?
You should upload to an temporary directory, and switch the completely-uploaded file with the old file.
Related
I've tried to look around for some tricks on how I can do this safely, without executing the code.
Does the code get executed if i simply upload it to the file system, then leave it be until someone downloads it?
Or is this a potential threat aswell?
What I am trying to do is making the users able to upload their CV in pdf files. The administrator can then download this pdf file (not being viewed on server, but downloaded).
How should I do this to prevent malicious files from being executed on my server? Also, would it be risky to place this folder OUTSIDE the public_html folder?
There's not a lot of risk to upload .pdf in a folder.
the folder must be in 644 (chmod). and have a index.php with redirect to the index of the website
Inside or outsite the "public_html" .. it's not a problem
when you upload, you can check the extension (.pdf) and type mime:
with finfo_file (http://php.net/manual/en/function.finfo-file.php )
and
with $extension = substr($file, -3);
That depends on how your server is set. If it allows PDF files to be used as executable, or to be opened with particular application/processing script that could be used for malicious actions. Otherwise you have to follow simple instructions such as restriction of file name length and avoiding to perform read operation of that file. As I understand you need only to upload and safe them. I'd keep them in public_html and once uploaded correctly (you checked filesize, extension etc) moved them whenever you like.
My application is keeping watch on a set of folders where users can upload files. When a file upload is finished I have to apply a treatment, but I don't know how to detect that a file has not finish to upload.
Any way to detect if a file is not released yet by the FTP server?
There's no generic solution to this problem.
Some FTP servers lock the file being uploaded, preventing you from accessing it, while the file is still being uploaded. For example IIS FTP server does that. Most other FTP servers do not. See my answer at Prevent file from being accessed as it's being uploaded.
There are some common workarounds to the problem (originally posted in SFTP file lock mechanism, but relevant for the FTP too):
You can have the client upload a "done" file once the upload finishes. Make your automated system wait for the "done" file to appear.
You can have a dedicated "upload" folder and have the client (atomically) move the uploaded file to a "done" folder. Make your automated system look to the "done" folder only.
Have a file naming convention for files being uploaded (".filepart") and have the client (atomically) rename the file after upload to its final name. Make your automated system ignore the ".filepart" files.
See (my) article Locking files while uploading / Upload to temporary file name for an example of implementing this approach.
Also, some FTP servers have this functionality built-in. For example ProFTPD with its HiddenStores directive.
A gross hack is to periodically check for file attributes (size and time) and consider the upload finished, if the attributes have not changed for some time interval.
You can also make use of the fact that some file formats have clear end-of-the-file marker (like XML or ZIP). So you know, that the file is incomplete.
Some FTP servers allow you to configure a hook to be called, when an upload is finished. You can make use of that. For example ProFTPD has a mod_exec module (see the ExecOnCommand directive).
I use ftputil to implement this work-around:
connect to ftp server
list all files of the directory
call stat() on each file
wait N seconds
For each file: call stat() again. If result is different, then skip this file, since it was modified during the last seconds.
If stat() result is not different, then download the file.
This whole ftp-fetching is old and obsolete technology. I hope that the customer will use a modern http API the next time :-)
If you are reading files of particular extensions, then use WINSCP for File Transfer. It will create a temporary file with extension .filepart and it will turn to the actual file extension once it fully transfer the file.
I hope, it will help someone.
This is a classic problem with FTP transfers. The only mostly reliable method I've found is to send a file, then send a second short "marker" file just to tell the recipient the transfer of the first is complete. You can use a file naming convention and just check for existence of the second file.
You might get fancy and make the content of the second file a checksum of the first file. Then you could verify the first file. (You don't have the problem with the second file because you just wait until file size = checksum size).
And of course this only works if you can get the sender to send a second file.
I'm uploading files using php. The file has to be below a certain size. If it's not, the script returns an error.
I've noticed that php stores the uploaded file in (my case) C:\Windows\Temp\filename.extension
Right now, if the file is above the Max size, the script only returns an error. So what happens to the file that got uploaded? Does php delete it automatically or do I have to do that? Even if the the file was the right size, the temp file still remains there I guess. Should I be deleting this file in my script?
No, from the manual:
The file will be deleted from the temporary directory at the end of
the request if it has not been moved away or renamed.
I have a form page that posts to another page where multiple fields as well as file uploads are processed. Just wondering what happens to the 'tmp_name' files when/if the user enters some incorrect info and I send them back to the form page with a meta refesh?
If successful, I move the file to a new location. But if not successful, do the files get unset or erased if the user gets redirected? If they don't, can I reaccess them again so the user doesnt have to reupload? OTOH if there is a problem with the file, say it is not the expected MIME type, should I unlink($_FILES['userFile']['tmp_name']? Its easy to force the user to re-upload again, i think, but I dont want the server being filled up with files that will never be used? If the form passes inspection, and I use rename() to move the file, is the temp file really gone? Did it ever exist on the server's hard drive, or was it only in RAM? Whats the best practice here?
do the files get unset or erased if the user gets redirected?
The uploaded files are stored in the /tmp directory (or whatever is specified as PHP's temporary location). Once your script has run, files left there are subject to deletion any time. I don't think they usually get deleted straight away, but the contents of /tmp will be automatically purged by the OS when necessary.
/tmp is usually located on a hard drive, not in RAM.
Managing this is usually nothing you need to worry about.
If the form passes inspection, and I use rename() to move the file, is the temp file really gone?
Yes, but you must use move_uploaded_file() on uploaded files instead of rename() for security reasons.
The file is stored in the tmp folder and if you don't move it elsewhere it will stay there. It will be removed automatically by the OS on next cleanup.
Edit:
Please look at Marc's comment below.
http://www.php.net/manual/en/features.file-upload.post-method.php
The file will be deleted from the
temporary directory at the end of the
request if it has not been moved away
or renamed.
I'm uploading files via JS and storing the temp path in the session.
Than i use the following code to move the files.
if(move_uploaded_file($_SESSION['temp_img'][$key]['path'], $dest.$bigimg)){
$dest and $bigimg are defined earlier in the script with the id from the database.
Any Ideas or alternatives ?
MANCHUCK's answer was close but not quite there. You must call move_uploaded_file within the script where the file was uploaded. You cannot do what you're doing, that is, "storing temp path in the session" because that path is only valid for one request.
From the PHP manual:
The file will be deleted from the
temporary directory at the end of the
request if it has not been moved away
or renamed.
(Emphasis mine)
move_uploaded_file checks that a file has been uploaded to that page. You are actually uploading the file to a different PHP script then storing in a session. Instead of using move_upload_file use rename.
What is the output of $_SESSION['temp_img'][$key]['path'], also do you have permission to write to the web directory your placing the files. You may need to set it to 777 for some hosts to allow the webserver to write there.