javascriptphpjquerysymfonykcfinder

kcfinder have upload directory selected through URL


Problem: As found in kcfinder's definition I am using this link to open kcfinder:

window.open('/kcfinder/browse.php?type=files&dir=files/public&subDir=/PO/200836', 'kcfinder_textbox',
            ', width=800, height=600');

In here, I have modified the URL to also include the subdirectory path so that the URL becomes something like this http://192.168.212.200/kcfinder/browse.php?type=files&dir=files/public&subDir=/PO/200836 .

The subDir part has the directory name to be set to (and created if not exists). In the config.php I already have a directory set to be the root. So if the subDir is provided it will create the subDir inside the root of config.php. Now I would want this subDir to be the new root directory for kcfinder.

For example if my uploadURL in the config is /var/www/html/web/upload/ the new root for the above URL should become /var/www/html/web/upload/PO/200836/.

Attempt: I have been able to successfully create the directory /var/www/html/web/upload/PO/200836/ for the above URL (or any URL) provided. However, the root in kcfinder is still set to /var/www/html/web/upload/. So when I open the kcfinder, the directory gets created internally but the root is still set to the original root from config.php.

I added the following lines to change my root directory to the sub directory I pass through URL:

$this->config["uploadURL"] .= $_GET['subDir'];
$this->config["uploadDir"] .= $_GET['subDir'];
$this->typeDir = $this->config["uploadDir"] ."/files";
$this->typeURL = $this->config["uploadURL"] ."/files";

I have also raised this as an issue on github but no response from there yet. I am assuming the only change I need to do is set the root directory to display to the new directory being created but I am not sure where I am supposed to do this.

Is there a workaround for this?

PS: I am also open to any other open source web file manager PHP/jQuery solutions which has a way to do this. Using symfony as the framework.

UPDATE: I have tried replacing the default folder to the new modified folder like this in the __construct() of upload.php.

public function __construct() {

    // SET CMS INTEGRATION PROPERTY
    if (isset($_GET['cms']) &&
        $this->checkFilename($_GET['cms']) &&
        is_file("integration/{$_GET['cms']}.php")
    )
        $this->cms = $_GET['cms'];

    // LINKING UPLOADED FILE
    if (count($_FILES))
        $this->file = &$_FILES[key($_FILES)];

    // CONFIG & SESSION SETUP
    $session = new session("conf/config.php");
    $this->config = $session->getConfig();
    $this->session = &$session->values;
    $this->config["uploadURL"] .= $_GET["subDir"];


    // IMAGE DRIVER INIT
    if (isset($this->config['imageDriversPriority'])) {
        $this->config['imageDriversPriority'] =
            text::clearWhitespaces($this->config['imageDriversPriority']);
        $driver = image::getDriver(explode(' ', $this->config['imageDriversPriority']));
        if ($driver !== false)
            $this->imageDriver = $driver;
    }
    if ((!isset($driver) || ($driver === false)) &&
        (image::getDriver(array($this->imageDriver)) === false)
    )
        $this->backMsg("Cannot find any of the supported PHP image extensions!");

    // WATERMARK INIT
    if (isset($this->config['watermark']) && is_string($this->config['watermark']))
        $this->config['watermark'] = array('file' => $this->config['watermark']);

    // GET TYPE DIRECTORY
    $this->types = &$this->config['types'];
    $firstType = array_keys($this->types);
    $firstType = $firstType[0];
    $this->type = (
        isset($_GET['type']) &&
        isset($this->types[$_GET['type']])
    )
        ? $_GET['type'] : $firstType;

    // LOAD TYPE DIRECTORY SPECIFIC CONFIGURATION IF EXISTS
    if (is_array($this->types[$this->type])) {
        foreach ($this->types[$this->type] as $key => $val)
            if (in_array($key, $this->typeSettings))
                $this->config[$key] = $val;
        $this->types[$this->type] = isset($this->types[$this->type]['type'])
            ? $this->types[$this->type]['type'] : "";
    }

    // COOKIES INIT
    $ip = '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)';
    $ip = '/^' . implode('\.', array($ip, $ip, $ip, $ip)) . '$/';
    if (preg_match($ip, $_SERVER['HTTP_HOST']) ||
        preg_match('/^[^\.]+$/', $_SERVER['HTTP_HOST'])
    )
        $this->config['cookieDomain'] = "";
    elseif (!strlen($this->config['cookieDomain']))
        $this->config['cookieDomain'] = $_SERVER['HTTP_HOST'];
    if (!strlen($this->config['cookiePath']))
        $this->config['cookiePath'] = "/";

    // UPLOAD FOLDER INIT

    // FULL URL
    if (preg_match('/^([a-z]+)\:\/\/([^\/^\:]+)(\:(\d+))?\/(.+)\/?$/',
            $this->config['uploadURL'], $patt)
    ) {
        list($unused, $protocol, $domain, $unused, $port, $path) = $patt;
        $path = path::normalize($path);
        $this->config['uploadURL'] = "$protocol://$domain" . (strlen($port) ? ":$port" : "") . "/$path";
        $this->config['uploadDir'] = strlen($this->config['uploadDir'])
            ? path::normalize($this->config['uploadDir'])
            : path::url2fullPath("/$path");
        $this->typeDir = "{$this->config['uploadDir']}/{$this->type}";
        $this->typeURL = "{$this->config['uploadURL']}/{$this->type}";

    // SITE ROOT
    } elseif ($this->config['uploadURL'] == "/") {
        $this->config['uploadDir'] = strlen($this->config['uploadDir'])
            ? path::normalize($this->config['uploadDir'])
            : path::normalize(realpath($_SERVER['DOCUMENT_ROOT']));
        $this->typeDir = "{$this->config['uploadDir']}/{$this->type}";
        $this->typeURL = "/{$this->type}";

    // ABSOLUTE & RELATIVE
    } else {
        $this->config['uploadURL'] = (substr($this->config['uploadURL'], 0, 1) === "/")
            ? path::normalize($this->config['uploadURL'])
            : path::rel2abs_url($this->config['uploadURL']);
        $this->config['uploadDir'] = strlen($this->config['uploadDir'])
            ? path::normalize($this->config['uploadDir'])
            : path::url2fullPath($this->config['uploadURL']);
        $this->typeDir = "{$this->config['uploadDir']}/{$this->type}";
        $this->typeURL = "{$this->config['uploadURL']}/{$this->type}";
    }

    // HOST APPLICATIONS INIT
    if (isset($_GET['CKEditorFuncNum'])) {
        $this->opener['name'] = "ckeditor";
        $this->opener['CKEditor'] = array('funcNum' => $_GET['CKEditorFuncNum']);

    } elseif (isset($_GET['opener'])) {
        $this->opener['name'] = $_GET['opener'];

        if ($_GET['opener'] == "tinymce") {
            if (!isset($this->config['_tinyMCEPath']) || !strlen($this->config['_tinyMCEPath']))
                $this->opener['name'] = false;

        } elseif ($_GET['opener'] == "tinymce4") {
            if (!isset($_GET['field']))
                $this->opener['name'] = false;
            else
                $this->opener['TinyMCE'] = array('field' => $_GET['field']);
        }

    } else
        $this->opener['name'] = false;

    // LOCALIZATION
    foreach ($this->langInputNames as $key)
        if (isset($_GET[$key]) &&
            preg_match('/^[a-z][a-z\._\-]*$/i', $_GET[$key]) &&
            file_exists("lang/" . strtolower($_GET[$key]) . ".php")
        ) {
            $this->lang = $_GET[$key];
            break;
        }
    $this->localize($this->lang);

    // IF BROWSER IS ENABLED
    if (!$this->config['disabled']) {

        // TRY TO CREATE UPLOAD DIRECTORY IF NOT EXISTS
        if (!$this->config['disabled'] && !is_dir($this->config['uploadDir']))
            @mkdir($this->config['uploadDir'], $this->config['dirPerms'], true);
        // CHECK & MAKE DEFAULT .htaccess
        if (isset($this->config['_check4htaccess']) &&
            $this->config['_check4htaccess']
        ) {
            $htaccess = "{$this->config['uploadDir']}/.htaccess";
            $original = $this->get_htaccess();
            if (!file_exists($htaccess)) {
                if (!@file_put_contents($htaccess, $original))
                    $this->backMsg("Cannot write to upload folder. {$this->config['uploadDir']}");
            } else {
                if (false === ($data = @file_get_contents($htaccess)))
                    $this->backMsg("Cannot read .htaccess");
                if (($data != $original) && !@file_put_contents($htaccess, $original))
                    $this->backMsg("Incorrect .htaccess file. Cannot rewrite it!");
            }
        }

        // CHECK & CREATE UPLOAD FOLDER
        if (!is_dir($this->typeDir)) {
            if (!mkdir($this->typeDir, $this->config['dirPerms']))
                $this->backMsg("Cannot create {dir} folder.", array('dir' => $this->type));
        } elseif (!is_readable($this->typeDir))
            $this->backMsg("Cannot read upload folder.");
    }
}

This creates the directory and everything but it does not set the root folder to the newly created folder. The folder is still set to the default root.


Solution

  • For anyone looking for an answer here, I came up with an alternative solution using a Symfony bundle called EMElfinderBundle since KCFinder had used $_GET variables all over their code and I couldn't change it possibly everywhere. This bundle actually turned out to be a better bundle than kcfinder. For anyone using Symfony I would definitely recommend this.

    In the bundle, all I did was add up the following lines in its ElFinderConfigurationReader.php

    $dir="";
    parse_str(parse_url($this->requestStack->getCurrentRequest()->server->all()["HTTP_REFERER"])["query"]);
    $driverOptions["path"] .= $dir;