Uploading data into the $_FILES without a form - php

Alright, so a little preface: I've been working on adding drag and drop file uploading to the course management system called Moodle (specifically 2.0.1). This version of Moodle uses the YUI3 framework and uploads the form data with the file to be uploaded and the save-as name through an io-upload-iframe. The file is stored in the super global $_FILES until the filesystem is sent the relevant data on where to store it permanently.
The trouble I'm having is that instead of using YUI3's drag and drop features (Which, from a cursory look at their website is not the kind of drag and drop I need anyways) I'm using the native HTML5 drag and drop code. This seems to work in most major browsers (I haven't had the time to test much, and it's outside the scope of this project). The trouble I'm having is that this design of DND immediately gives you a file from the Event object in javascript. I could send this file object off to wherever I want, but the filesystem is only designed to handle variables temporarily stored in the $_FILES variable. I've not been able to find any easy way of getting this file stored there, unfortunately. I could to an HTTP request of various forms (either one of YUI3's special Y.io() requests or an XHR), but this requires a lot of duplicated code from the original source code.
Anybody have some suggestions?

Hard to tell what your problem is. But whatever your server or filesystem is, it has nothing to do with the temporarity of the $_FILES array.
When you receive the DND event, and YUI subsequently sends the file, then you will receive some data either in $_FILES or in $_POST. If so, just use move_uploaded_file or file_put_contents and store it elsewhere.
Assign that moved file a md5() hash as name, and have that returned as file identifier for your AJAX-DND upload request.
You can then use that hash id in your Javascript code, and refer to the already uploaded image file by this reference. Should your app initiate a normal form request after the drag'n'dropping, then you just include the collected image reference ids. And thus your server-side code can associate it again.
You could even reconstruct the $_FILES array if you want to:
foreach ((array)$_POST["prev_image_ids"] as $md5) {
$md5 = basename($md5);
$_FILES["image"][] = array(
"tmp_name" => $fn="./already-uploaded/$md5",
"size" => filesize($fn), "type"=>"image/whatever",
"name" => "unknown.jpg", "error"=>UPLOAD_ERR_OK,
); // you could store away those original attributes too
}

Related

PHP: In the $_FILES superglobal, is the 'size' element supplied by the client?

I have created a nifty class for sanitizing inputs based on their source using PHP filter functions, but there is no INPUT_FILES for filter_input_array().
Obviously, the routine for checking out a file is very involved and that is not the focus of this question (so, you can skip the php.ini, examine the file, copy the file, don't use the user supplied file name, tricks of the trade stuff, references to the manual, etc).
I simply want to know, what is the source of the value for the size element in the $_FILES superglobal array. Yes, I still perform tests on it (and the actual file), but I would like to know the origin of the value. The origin of the 'key' is obviously PHP.
A YouTube video on file upload progress bars (8:50 - 9:10) shows a JavaScript method of determining the file size on the client. If that is true, the file size can definitely come from the user agent and then passed on to the web server / PHP via headers.
No, the size is provided by the server, but the mime-type (type) is provided by the client, so don't trust this value and check for yourself.
Yes, it's provided for every file. See http://php.net/manual/en/features.file-upload.php

Passing a file input to next code line in php

I am trying to get an image from the user by using file input method. It is successfully getting the image from the user. But I want this input to be passed to my next line of code.
Any help would be appreciated.
<input type='file' name='image'>
$two=createfrompng("Here i want this input to be passed");
You can use $_FILES global variable.
Example :
var_dump($_FILES['image']);
http://php.net/manual/en/reserved.variables.files.php
You can't. Your PHP code is executed server-side. Before the resulting html is send to the client so you don't know if the user WILL upload a file or not and even less it's contents.
The effect you are trying to achieve should be done client-side by altering the DOM with javascript.
But anyway you can't immediately access the image because, for security reasons, javascript can't access client's filesystem so you need to upload the file (the way you are doing) process it server-side and send back to the client, which is difficult if you haven't a websocket connection to start comunication to the client.
I suggest you to slightly change your approach and submit your form targetted to an existing container in your page (tipically a div) and respond with only the html to render the image inside it.
See the jQuery .load() function. It is a simple solution and I think it will be the best for you.
…or another even simpler solution is to reload the whole page and mantain state data server side (if you want to manage multiple images as I thought to understand). It is less responsive. But not to much expensive (if your html is not huge) because the browser cache will remember your images (if you does'nt change the url to download them).
Check first, if the file exists in $_FILES and the use it, in your case:
$image = getimagesize($_FILES['image']['tmp_name']);
if ($image !== false) {
$two = createfrompng($image);
}

fool php's move_uploaded_file without using cURL?

hello everyone my question has already been asked here -- How to fake $_FILES and fool move_uploaded_file()? -- but was never answered directly.
i am writing a wordpress plugin that needs to connect to a remote database, download a file, and then call another plugin's file import method. the other plugin is the store locator plus plugin. it has a bulk records upload function that takes a file upload from a form and gets geolocation data and then stores the form data in its database. i want to basically automate this process using wp-cron.
here is the line that is problematic in that plugin:
if(!move_uploaded_file($_FILES['csvfile']['tmp_name'],$updir.'/'.$_FILES['csvfile']['name'])){
return;
}
now, its easy to write a file to /tmp and spoof the $_FILES superglobal, but move_uploaded_file stops me dead in my tracks. i looked into the source for this and i'm still not clear on how it checks to make sure a form was uploaded since the source is obscure...
i want to avoid getting into a mess with curl because of authentication and security etc. i also don't want to edit the SLP plugins files in case an update happens.
TL;DR
does anyone know a way to fool move_uploaded_files to be convinced that what is in $_FILES is "uploaded"?
thanks in advance!

is it possible to serialize a $_FILES?

i need to mimic how an upload form work. i need to store a file into database and uploads the $_FILES into our folders. The problem every bit of code of the models and the form itself is based on legacy code. I don't have the the gut to strip all code and start over. I prefer to let it be
So, my goal is how to uplaod file without use the previous form and then only serialize/unserialize an object consist of filename and url. while the file itself have been story via copy function and not uploads form.
The only critical part of the $_FILES array for any particular request is the ...['tmp_name'] portion, since that points to where PHP saved the uploaded file. Save a copy of a $_FILES that's set up the way you want to test (with however many files you want), then manually change the tmp_name to point to actual files on your server, rather than the random garbage names that PHP autoassigns to uploads, and you could be able to reuse a copy of the data as many times as you want, as long as your scripts don't move/delete/munge the files you're pointing at.
So, something like:
$_FILES['file1']['tmp_name'] = '/path/to/file/to/test/with';
$_FILES['file2']['tmp_name'] = '/some/other/path/or/file/for/testing';
$savedfiles = serialize($_FILES);
and then you can stick a
$_FILES = unserialize($savedfiles);
wherever it's appropriate for testing your app.
Yes, it is possible to serialize $_FILES array;
$upload = serialize($_FILES["file"]);
If your code is dependent on the contents of the $_FILES variable then yes, assigning to it (whether the contents are from a serialised version in a database or wherever) should have the expected behaviour.
Generally speaking, contriving a small test is a much better way of finding out if something will work for your particular situation than asking people on the internet to speculate.

File uploads with php - displaying a list of files

I am in the middle of making a script to upload files via php. What I would like to know, is how to display the files already uploaded, and when clicking on them open them for download. Should I store the names and path in a database, or just list the conents of a directory with php?
Check out handling file uploads in PHP. A few points:
Ideally you want to allow the user to upload multiple files at the same time. Just create extra file inputs dynamically with Javascript for this;
When you get an upload, make sure you check that it is an upload with is_uploaded_file;
Use move_uploaded_file() to copy the file to wherever you're going to store it;
Don't rely on what the client tells you the MIME type is;
Sending them back to the client can be done trivially with a PHP script but you need to know the right MIME type;
Try and verify that what you get is what you expect (eg if it is a PDF file use a library to verify that it is), particularly if you use the file for anything or send it to anyone else; and
I would recommend you store the file name of the file from the client's computer and display that to them regardless of what you store it as. The user is just more likely to recognise this than anything else.
Storing paths in the database might be okay, depending on your specific application, but consider storing the filenames in the database and construct your paths to those files in PHP in a single place. That way, if you end up moving all uploaded files later, there is only one place in your code you need to change path generation, and you can avoid doing a large amount of data transformation on your "path" field in the database.
For example, for the file 1234.txt, you might store it in:
/your_web_directory/uploaded_files/1/2/3/1234.txt
You can use a configuration file or if you prefer, a global somewhere to define the path where your uploads are stored (/your web directory/uploaded files/) and then split characters from the filename (in the database) to figure out which subdirectory the file actually resides in.
As for displaying your files, you can simply load your list of files from the database and use a path-generating function to get download paths for each one based on their filenames. If you want to paginate the list of files, try using something like START 0, LIMIT 50; in mySQL. Just pass in a new start number with each successive page of upload results.
maybe you should use files, in this sense:
myfile.txt
My Uploaded File||my_upload_dir/my_uploaded_file.pdf
Other Uploaded File||my_upload_dir/other_uploaded.html
and go through them like this:
<?php
$file = "myfile.txt";
$lines = file($file);
$files = array();
for($i=0;$i<=count($lines)-1;$i++) {
$parts = explode($lines[$i]);
$name = parts[0];
$filename = parts[1];
$files[$i][0] = $name;
$files[$i][1] = $filename;
}
print_r($files);
?>
hope this helps. :)
What I always did (past tense, I haven't written an upload script for ages) is, I'd link up an upload script (any upload script) to a simple database.
This offers some advantages;
You do not offer your users direct insight to your file system (what if there is a leak in your 'browse'-script and you expose your whole harddrive?
You can store extra information and meta-data in an easy and efficient way
You can actually query for files / meta-data instead of just looping through all the files
You can enable a 'safe-delete', where you delete the row, but keep the file (for example)
You can enable logging way more easily
Showing files in pages is easier
You can 'mask' files. Using a database enables you to store a 'masked' filename, and a 'real' filename.
Obviously, there are some disadvantages as well;
It is a little harder to migrate, since your file system and database have to be in sync
If an operation fails (on one of both ends) you have either a 'corrupt' database or file system
As mentioned before (but we can not mention enough, I'm afraid); _Keep your uploading safe!_
The MIME type / extension issue is one that is going on for ages.. I think most of the web is solid nowadays, but there used to be a time when developers would check either MIME type or extension, but never both (why bother?). This resulted in websites being very, very leaky.
If not written properly, upload scripts are big hole in your security. A great example of that is a website I 'hacked' a while back (on their request, of course). They supported the upload of images to a photoalbum, but they only checked on file extension. So I uploaded a GIF, with a directory scanner inside. This allowed me to scan through their whole system (since it wasn't a dedicated server; I could see a little more then that).
Hope I helped ;)

Categories