Skip to content
This repository was archived by the owner on Dec 25, 2018. It is now read-only.

function execute($queryParameters) and POST / No way to change a command argument on server side #29

Closed
Ronan-Lenor opened this issue Oct 16, 2015 · 15 comments

Comments

@Ronan-Lenor
Copy link
Contributor

Hello,
i noticed that when i upload a file on ELFinder, i can't change the argument "upload_path" on the server side.
The reason is simple, the whole configuration is done in the POST x(

$src    = $_SERVER["REQUEST_METHOD"] == 'POST' ? $_POST : $queryParameters;

can't you find a way to merge the $queryParameters with the POST parameters?
So my "upload_path" could write/overwrite the default "upload_path".

i don't know also the intire process inside Elfinder, but changing the "upload_path" from the client side, it isn't a security breach?

@helios-ag
Copy link
Owner

Ping @nicolasmure

@nicolasmure
Copy link
Contributor

Hello,

Does the home folder feature can suit your needs?
Or have you tried to declare an other instance of elFinder in your app/config/config.yml file with your wanted path parameter?

I agree with you about the security breach, so can you also explain more your use case please to make the problem easier to understand?

@Ronan-Lenor
Copy link
Contributor Author

Hello,

Yes thanks, i found that solution recently.

But consede that this actual script don't allow to access the entire ElFinder's Command properties =/
Hope you could improve that point on your future release :P

@Ronan-Lenor
Copy link
Contributor Author

Hello again, i thought that my problen was resolved with your solution. but finally not.

So first, let's imagine that i have a such homeFolder : domain.com/home
(with the "uploads" directory for my default instance)
then inside it, i create a "image" directory.
(so i get something like: domain.com/home/image )
inside it, i upload a .exe file.

Now, if before the upload i change the homefolder on the event onPreExecute:

$Request->attributes->set('homeFolder', $event->getHomeFolder().'/control');

i get an error "ERROR_TRGDIR_NOT_FOUND".

with few research, i noticed that in the ElFinderVolumeDriver.php > function file()
the $path return " uploads/home/control\image " which of course doesn't exist.

and here, i'm stuck. well, i could create an heavy solution where i create and delete some new Directory. but i'm sure that you can provide some more conveniente solution :P isn't it? :D

@nicolasmure
Copy link
Contributor

Oh ok,

then why don't you make sure the folder you're setting with your preExecute eventListener actually exists? If it doesn't exists, create one using the filesystem component

@Ronan-Lenor
Copy link
Contributor Author

Well, from onPreExecute i don't find how to get the directory which ElFinder is uploading.
that " image " directory appear nowhere.
(noting in the $Request or ElFinderPreExecutionEvent $Event about it, neither $_POST)

@nicolasmure
Copy link
Contributor

Yes, elFinder uses hashes to store its informations about files and folders. Maybe the comments in this PR can help you.
That's how I do to manage thumbnails with liipImagineBundle when I upload/delete an image file with elFinder. In fact, have to make a subrequest with the info command to get the image path.

But if you're hooking into a upload command (i.e. an HTTP POST request), subrequests may not work because of this line :

$src = $_SERVER["REQUEST_METHOD"] == 'POST' ? $_POST : $queryParameters;

then, maybe you could try to edit this line as it :

$src = array_merge($_POST, $queryParameters);

and make a new PR 😉

@nicolasmure
Copy link
Contributor

If you look to the $_POST parameters when you're uploading your file, you'll see that it's an array with 2 keys :

  • cmd which contains the command name to execute
  • and target which contains an hash to identify the folder to upload to.

If you make a subrequest with the info command and the target parameter from the $_POST array, you'll get infos about the upload dir.

An other workaround would be to let elFinder upload your file normally (i.e. no preExec eventListener), and then move the uploaded file in your custom directory with a postExec eventListener.

@nicolasmure
Copy link
Contributor

If you try to upload a file and have firebug (or any other tool) open, then look to the POST request response : elFinder controller returns the following json response :

{
    "removed": [],
    "added": [
        {
            "hash": "l1_Zm9sZGVyL0JpcmQuanBn",
            "name": "Bird.jpg",
            "read": 1,
            "ts": 1445356113,
            "write": 1,
            "tmb": 1,
            "mime": "image/jpeg",
            "phash": "l1_Zm9sZGVy",
            "path": "10/folder/Bird.jpg",
            "size": 63057
        }
    ]
}

You can see a path key indicating where the file has been stored to.
This response is accessible as an array by calling the ElFinderPostExecutionEvent::getResult function. You'll then be able to move your file where you want.

@Ronan-Lenor
Copy link
Contributor Author

Thanks,
but for security reason, i can't allow to let the user access the files between 2 request.
(my client want to let users upload php file lol)

that's why i have to change the upload path to a restricted area where i zip the files before moving it to the expected directory.

that "info" trick is good for the PreExecution. but as you will probably accept a PR for let develloper use the command's parameters on a POST request, then i prefer use it :D
By doing so, i would avoid a useless (sub)request for my server :P

@nicolasmure
Copy link
Contributor

By using a postExec eventListener, you won't have any sub requests and your zip'n'move operation will be transparent to the user.
Take a look to the following example :

// Acme/MyBundle/EventListener/ElFinder/PostExecutionEventListener.php
class PostExecutionEventListener
{
    public function onPostExecute(ElFinderPostExecutionEvent $event)
    {
        // be sure you're on a successful upload command
        if ($event->hasErrors() || $event->getCommand() != 'upload') {
            return;
        }
        $result = $event->getResult();
        foreach ($result['added'] as $key => $value) {
            // be sure you've uploaded a file you want to zip'n'move by checking its extension and its mimetype
            if (is_file_ok($value) === false) { // you can implement is_file_ok using $value['path'] and $value['mime']
                continue;
            }
            $filepath = $value['path'];
            try {
                zip_file($filepath);
                move_file($filepath, 'new/destination');
            } catch (ZipOrMoveException $e) { // any exception thrown by the zip or by the move operation
                remove_file($filepath); // do not keep the original file as you can't handle it
            }
            unset($result['added'][$key]); // do not send to elFinder client infos about the file.
        }
        // updating the result to send back to the client
        // to avoid elFinder.js to make operations on the moved files
        // and to list them in the current folder
        $event->setResult($result);
    }
}

Doing so, I think your file will be uploaded (+zipped and moved) and you won't see it in the current folder after the upload on elFinder.js client.
You won't have to edit the elFinderPHP lib neither 😉 .

@Ronan-Lenor
Copy link
Contributor Author

But by doing so, the original file will be accessible(through another tab) during the zipping process, as the upload is already done before the PostExecution's event.

@nicolasmure
Copy link
Contributor

Yep, that's right, but do you upload files that takes more than some milliseconds to zip?
Text files are usually lightweight.

@Ronan-Lenor
Copy link
Contributor Author

lol, it's not profesionnal at all! x)

(and it's easy to make an heavy text file.)

@nicolasmure
Copy link
Contributor

Yes, seems legit then if you want to be sure the file isn't uploaded at all in the current folder...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants