Some privacy-aware sites may not like externally referenced files, like
[simple-upload.git] / index.php
index 778fd568c1240654c2937a320729e81d2b23f2e6..39abc27ccc62bba3b31702fe9e6614bfc161cac2 100644 (file)
--- a/index.php
+++ b/index.php
                along with this program.  If not, see <http://www.gnu.org/licenses/>.
        */
 
-       // ============== Configuration begin  ==============
-
+       // =============={ Configuration Begin }==============
        $settings = array(
 
+               // Website title
+               'title' => 'strace.club',
+
                // Directory to store uploaded files
-               uploaddir => '.',
+               'uploaddir' => '.',
 
                // Display list uploaded files
-               listfiles => true,
+               'listfiles' => true,
 
                // Allow users to delete files that they have uploaded (will enable sessions)
-               allow_deletion => true,
+               'allow_deletion' => true,
+
+               // Allow users to mark files as hidden
+               'allow_private' => true,
 
                // Display file sizes
-               listfiles_size => true,
+               'listfiles_size' => true,
 
                // Display file dates
-               listfiles_date => true,
+               'listfiles_date' => true,
 
                // Display file dates format
-               listfiles_date_format => 'F d Y H:i:s',
+               'listfiles_date_format' => 'F d Y H:i:s',
 
                // Randomize file names (number of 'false')
-               random_name_len => 4,
+               'random_name_len' => 8,
 
                // Keep filetype information (if random name is activated)
-               random_name_keep_type => true,
+               'random_name_keep_type' => true,
 
                // Random file name letters
-               random_name_alphabet => 'qwertyuiopasdfghjklzxcvbnm',
+               'random_name_alphabet' => 'qazwsxedcrfvtgbyhnujmikolp1234567890',
 
                // Display debugging information
-               debug => ($_SERVER['SERVER_NAME'] === 'localhost')
+               'debug' => false,
+
+               // Complete URL to your directory (including tracing slash)
+               'url' => 'http://strace.club/',
+
+               // Amount of seconds that each file should be stored for (0 for no limit)
+               // Default 30 days
+               'time_limit' => 60 * 60 * 24 * 30,
+
+               // Files that will be ignored
+               'ignores' => array('.', '..', 'LICENSE', 'README.md'),
+
+               // Language code
+               'lang' => 'en',
 
+               // Language direction
+               'lang_dir' => 'ltr',
+
+               // Remove old files?
+               'remove_old_files' => true,
+
+               // Privacy: Allow external references (the "fork me" ribbon)
+               'allow_external_refs' => true,
        );
+       // =============={ Configuration End }==============
 
-       // ============== Configuration end  ==============
+       // Is the local config file there?
+       if (isReadableFile('config-local.php')) {
+               // Load it then
+               include('config-local.php');
+       }
 
-    $data = array();
+       // Enabling error reporting
+       if ($settings['debug']) {
+               error_reporting(E_ALL);
+               ini_set('display_startup_errors',1);
+               ini_set('display_errors',1);
+       }
+
+       $data = array();
 
        // Name of this file
        $data['scriptname'] = pathinfo(__FILE__, PATHINFO_BASENAME);
 
-       // URL to upload page
-       $data['pageurl'] = "http" . (($_SERVER['SERVER_PORT']==443) ? "s://" : "://") . $_SERVER['SERVER_NAME'] . dirname($_SERVER['REQUEST_URI']) . '/';
+       // Adding current script name to ignore list
+       $data['ignores'] = $settings['ignores'];
+       $data['ignores'][] = $data['scriptname'];
 
        // Use canonized path
-       $data['uploaddir'] = realpath($settings['uploaddir']);
+       $data['uploaddir'] = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . $settings['uploaddir']);
 
        // Maximum upload size, set by system
        $data['max_upload_size'] = ini_get('upload_max_filesize');
 
-       if ($settings['allow_deletion']) {
+       // If file deletion or private files are allowed, starting a session.
+       // This is required for user authentification
+       if ($settings['allow_deletion'] || $settings['allow_private']) {
                session_start();
 
+               // 'User ID'
                if (!isset($_SESSION['upload_user_id']))
-                       $_SESSION['upload_user_id'] = rand(1000, 9999);
+                       $_SESSION['upload_user_id'] = mt_rand(100000, 999999);
 
+               // List of filenames that were uploaded by this user
                if (!isset($_SESSION['upload_user_files']))
                        $_SESSION['upload_user_files'] = array();
        }
 
+       // If debug is enabled, logging all variables
        if ($settings['debug']) {
-        // Enabling error reporting
-        error_reporting(E_ALL);
-        error_reporting(1);
-
-        // Displaying debug information
-               echo '<h2>Debugging information: settings</h2>';
+               // Displaying debug information
+               echo '<h2>Settings:</h2>';
                echo '<pre>';
                print_r($settings);
                echo '</pre>';
 
-        // Displaying debug information
-               echo '<h2>Debugging information: data</h2>';
+               // Displaying debug information
+               echo '<h2>Data:</h2>';
                echo '<pre>';
                print_r($data);
                echo '</pre>';
                echo '</pre>';
 
-        // Displaying debug information
-               echo '<h2>Debugging information: _SESSION</h2>';
+               // Displaying debug information
+               echo '<h2>SESSION:</h2>';
                echo '<pre>';
                print_r($_SESSION);
                echo '</pre>';
        }
 
-       function FormatSize ($bytes) {
+       // Format file size
+       function formatSize ($bytes) {
                $units = array('B', 'KB', 'MB', 'GB', 'TB');
 
                $bytes = max($bytes, 0);
                return ceil($bytes) . ' ' . $units[$pow];
        }
 
-       if (isset($_FILES['file']) && strlen($_FILES['file']['name']) > 1) {
-               $data['uploaded_file_name'] = basename($_FILES['file']['name']);
-               $data['target_file_name'] = $data['uploaded_file_name'];
-        if ($settings['random_name_len'] !== false) {
+       // Rotating a two-dimensional array
+       function diverseArray ($vector) {
+               $result = array();
+               foreach ($vector as $key1 => $value1)
+                       foreach ($value1 as $key2 => $value2)
+                               $result[$key2][$key1] = $value2;
+               return $result;
+       }
+
+       // Handling file upload
+       function uploadFile ($file_data) {
+               global $settings, $data;
+
+               $file_data['uploaded_file_name'] = basename($file_data['name']);
+               $file_data['target_file_name'] = $file_data['uploaded_file_name'];
+
+               // Generating random file name
+               if ($settings['random_name_len'] !== false) {
                        do {
-                   $data['target_file_name'] = '';
-                   while (strlen($data['target_file_name']) < $settings['random_name_len'])
-                       $data['target_file_name'] .= $settings['random_name_alphabet'][rand(0, strlen($settings['random_name_alphabet']) - 1)];
+                               $file_data['target_file_name'] = '';
+                               while (strlen($file_data['target_file_name']) < $settings['random_name_len'])
+                                       $file_data['target_file_name'] .= $settings['random_name_alphabet'][mt_rand(0, strlen($settings['random_name_alphabet']) - 1)];
                                if ($settings['random_name_keep_type'])
-                                       $data['target_file_name'] .= '.' . pathinfo($data['uploaded_file_name'], PATHINFO_EXTENSION);
-                       } while (file_exists($data['target_file_name']));
-        }
-               $data['upload_target_file'] = $data['uploaddir'] . DIRECTORY_SEPARATOR . $data['target_file_name'];
-               $data['tmp_name'] = $_FILES['file']['tmp_name'];
-
-       if ($settings['debug']) {
-            // Displaying debug information
-               echo '<h2>Debugging information: data</h2>';
-               echo '<pre>';
-               print_r($data);
-               echo '</pre>';
-       }
-
-               if (move_uploaded_file($data['tmp_name'], $data['upload_target_file'])) {
-                       if ($settings['allow_deletion'])
-                               $_SESSION['upload_user_files'][] = $data['target_file_name'];
-                       echo $data['pageurl'] .  $data['upload_target_file'];
-                       exit;
-                       // echo 'File: <b>' . $data['uploaded_file_name'] . '</b> successfully uploaded:<br />';
-                       // echo 'Size: <b>'. number_format($_FILES['file']['size'] / 1024, 3, '.', '') .'KB</b><br />';
-                       // echo 'File /URL: <b><a href="http://'.$_SERVER['HTTP_HOST'].rtrim(dirname($_SERVER['REQUEST_URI']), '\\/').'/'.$data['upload_target_file'].'">http://'.$_SERVER['HTTP_HOST'].rtrim(dirname($_SERVER['REQUEST_URI']), '\\/').'/'.$data['upload_target_file'].'</a></b>';
+                                       $file_data['target_file_name'] .= '.' . pathinfo($file_data['uploaded_file_name'], PATHINFO_EXTENSION);
+                       } while (isReadableFile($file_data['target_file_name']));
+               }
+               $file_data['upload_target_file'] = $data['uploaddir'] . DIRECTORY_SEPARATOR . $file_data['target_file_name'];
+
+               // Do now allow to overwriting files
+               if (isReadableFile($file_data['upload_target_file'])) {
+                       echo 'File name already exists' . "\n";
+                       return;
+               }
+
+               // Moving uploaded file OK
+               if (move_uploaded_file($file_data['tmp_name'], $file_data['upload_target_file'])) {
+                       if ($settings['allow_deletion'] || $settings['allow_private'])
+                               $_SESSION['upload_user_files'][] = $file_data['target_file_name'];
+                       echo $settings['url'] .  $file_data['target_file_name'] . "\n";
                } else {
                        echo 'Error: unable to upload the file.';
-                       exit;
                }
        }
 
-       if ($settings['allow_deletion'])
-               if (isset($_POST))
-                       if ($_POST['action'] === 'delete')
-                               if (in_array($_POST['target'], $_SESSION['upload_user_files']))
-                                       if (file_exists($_POST['target'])) {
-                                               unlink($_POST['target']);
-                                               echo 'File has been removed';
-                                               exit;
-                                       }
-?>
-<html lang="en-GB">
-       <head>
-               <meta charset="utf-8">
-               <title>Upload files</title>
-               <script charset="utf-8">
-                       !function(){function a(b){var c=a.modules[b];if(!c)throw new Error('failed to require "'+b+'"');return"exports"in c||"function"!=typeof c.definition||(c.client=c.component=!0,c.definition.call(this,c.exports={},c),delete c.definition),c.exports}a.modules={},a.register=function(b,c){a.modules[b]={definition:c}},a.define=function(b,c){a.modules[b]={exports:c}},a.register("component~emitter@1.1.2",function(a,b){function c(a){return a?d(a):void 0}function d(a){for(var b in c.prototype)a[b]=c.prototype[b];return a}b.exports=c,c.prototype.on=c.prototype.addEventListener=function(a,b){return this._callbacks=this._callbacks||{},(this._callbacks[a]=this._callbacks[a]||[]).push(b),this},c.prototype.once=function(a,b){function c(){d.off(a,c),b.apply(this,arguments)}var d=this;return this._callbacks=this._callbacks||{},c.fn=b,this.on(a,c),this},c.prototype.off=c.prototype.removeListener=c.prototype.removeAllListeners=c.prototype.removeEventListener=function(a,b){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var c=this._callbacks[a];if(!c)return this;if(1==arguments.length)return delete this._callbacks[a],this;for(var d,e=0;e<c.length;e++)if(d=c[e],d===b||d.fn===b){c.splice(e,1);break}return this},c.prototype.emit=function(a){this._callbacks=this._callbacks||{};var b=[].slice.call(arguments,1),c=this._callbacks[a];if(c){c=c.slice(0);for(var d=0,e=c.length;e>d;++d)c[d].apply(this,b)}return this},c.prototype.listeners=function(a){return this._callbacks=this._callbacks||{},this._callbacks[a]||[]},c.prototype.hasListeners=function(a){return!!this.listeners(a).length}}),a.register("dropzone",function(b,c){c.exports=a("dropzone/lib/dropzone.js")}),a.register("dropzone/lib/dropzone.js",function(b,c){(function(){var b,d,e,f,g,h,i,j,k={}.hasOwnProperty,l=function(a,b){function c(){this.constructor=a}for(var d in b)k.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},m=[].slice;d="undefined"!=typeof Emitter&&null!==Emitter?Emitter:a("component~emitter@1.1.2"),i=function(){},b=function(a){function b(a,d){var e,f,g;if(this.element=a,this.version=b.version,this.defaultOptions.previewTemplate=this.defaultOptions.previewTemplate.replace(/\n*/g,""),this.clickableElements=[],this.listeners=[],this.files=[],"string"==typeof this.element&&(this.element=document.querySelector(this.element)),!this.element||null==this.element.nodeType)throw new Error("Invalid dropzone element.");if(this.element.dropzone)throw new Error("Dropzone already attached.");if(b.instances.push(this),this.element.dropzone=this,e=null!=(g=b.optionsForElement(this.element))?g:{},this.options=c({},this.defaultOptions,e,null!=d?d:{}),this.options.forceFallback||!b.isBrowserSupported())return this.options.fallback.call(this);if(null==this.options.url&&(this.options.url=this.element.getAttribute("action")),!this.options.url)throw new Error("No URL provided.");if(this.options.acceptedFiles&&this.options.acceptedMimeTypes)throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");this.options.acceptedMimeTypes&&(this.options.acceptedFiles=this.options.acceptedMimeTypes,delete this.options.acceptedMimeTypes),this.options.method=this.options.method.toUpperCase(),(f=this.getExistingFallback())&&f.parentNode&&f.parentNode.removeChild(f),this.options.previewsContainer!==!1&&(this.previewsContainer=this.options.previewsContainer?b.getElement(this.options.previewsContainer,"previewsContainer"):this.element),this.options.clickable&&(this.clickableElements=this.options.clickable===!0?[this.element]:b.getElements(this.options.clickable,"clickable")),this.init()}var c;return l(b,a),b.prototype.events=["drop","dragstart","dragend","dragenter","dragover","dragleave","addedfile","removedfile","thumbnail","error","errormultiple","processing","processingmultiple","uploadprogress","totaluploadprogress","sending","sendingmultiple","success","successmultiple","canceled","canceledmultiple","complete","completemultiple","reset","maxfilesexceeded","maxfilesreached"],b.prototype.defaultOptions={url:null,method:"post",withCredentials:!1,parallelUploads:2,uploadMultiple:!1,maxFilesize:256,paramName:"file",createImageThumbnails:!0,maxThumbnailFilesize:10,thumbnailWidth:100,thumbnailHeight:100,maxFiles:null,params:{},clickable:!0,ignoreHiddenFiles:!0,acceptedFiles:null,acceptedMimeTypes:null,autoProcessQueue:!0,autoQueue:!0,addRemoveLinks:!1,previewsContainer:null,dictDefaultMessage:"Drop files here to upload",dictFallbackMessage:"Your browser does not support drag'n'drop file uploads.",dictFallbackText:"Please use the fallback form below to upload your files like in the olden days.",dictFileTooBig:"File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",dictInvalidFileType:"You can't upload files of this type.",dictResponseError:"Server responded with {{statusCode}} code.",dictCancelUpload:"Cancel upload",dictCancelUploadConfirmation:"Are you sure you want to cancel this upload?",dictRemoveFile:"Remove file",dictRemoveFileConfirmation:null,dictMaxFilesExceeded:"You can not upload any more files.",accept:function(a,b){return b()},init:function(){return i},forceFallback:!1,fallback:function(){var a,c,d,e,f,g;for(this.element.className=""+this.element.className+" dz-browser-not-supported",g=this.element.getElementsByTagName("div"),e=0,f=g.length;f>e;e++)a=g[e],/(^| )dz-message($| )/.test(a.className)&&(c=a,a.className="dz-message");return c||(c=b.createElement('<div class="dz-message"><span></span></div>'),this.element.appendChild(c)),d=c.getElementsByTagName("span")[0],d&&(d.textContent=this.options.dictFallbackMessage),this.element.appendChild(this.getFallbackForm())},resize:function(a){var b,c,d;return b={srcX:0,srcY:0,srcWidth:a.width,srcHeight:a.height},c=a.width/a.height,b.optWidth=this.options.thumbnailWidth,b.optHeight=this.options.thumbnailHeight,null==b.optWidth&&null==b.optHeight?(b.optWidth=b.srcWidth,b.optHeight=b.srcHeight):null==b.optWidth?b.optWidth=c*b.optHeight:null==b.optHeight&&(b.optHeight=1/c*b.optWidth),d=b.optWidth/b.optHeight,a.height<b.optHeight||a.width<b.optWidth?(b.trgHeight=b.srcHeight,b.trgWidth=b.srcWidth):c>d?(b.srcHeight=a.height,b.srcWidth=b.srcHeight*d):(b.srcWidth=a.width,b.srcHeight=b.srcWidth/d),b.srcX=(a.width-b.srcWidth)/2,b.srcY=(a.height-b.srcHeight)/2,b},drop:function(){return this.element.classList.remove("dz-drag-hover")},dragstart:i,dragend:function(){return this.element.classList.remove("dz-drag-hover")},dragenter:function(){return this.element.classList.add("dz-drag-hover")},dragover:function(){return this.element.classList.add("dz-drag-hover")},dragleave:function(){return this.element.classList.remove("dz-drag-hover")},paste:i,reset:function(){return this.element.classList.remove("dz-started")},addedfile:function(a){var c,d,e,f,g,h,i,j,k,l,m,n,o;if(this.element===this.previewsContainer&&this.element.classList.add("dz-started"),this.previewsContainer){for(a.previewElement=b.createElement(this.options.previewTemplate.trim()),a.previewTemplate=a.previewElement,this.previewsContainer.appendChild(a.previewElement),l=a.previewElement.querySelectorAll("[data-dz-name]"),f=0,i=l.length;i>f;f++)c=l[f],c.textContent=a.name;for(m=a.previewElement.querySelectorAll("[data-dz-size]"),g=0,j=m.length;j>g;g++)c=m[g],c.innerHTML=this.filesize(a.size);for(this.options.addRemoveLinks&&(a._removeLink=b.createElement('<a class="dz-remove" href="javascript:undefined;" data-dz-remove>'+this.options.dictRemoveFile+"</a>"),a.previewElement.appendChild(a._removeLink)),d=function(c){return function(d){return d.preventDefault(),d.stopPropagation(),a.status===b.UPLOADING?b.confirm(c.options.dictCancelUploadConfirmation,function(){return c.removeFile(a)}):c.options.dictRemoveFileConfirmation?b.confirm(c.options.dictRemoveFileConfirmation,function(){return c.removeFile(a)}):c.removeFile(a)}}(this),n=a.previewElement.querySelectorAll("[data-dz-remove]"),o=[],h=0,k=n.length;k>h;h++)e=n[h],o.push(e.addEventListener("click",d));return o}},removedfile:function(a){var b;return a.previewElement&&null!=(b=a.previewElement)&&b.parentNode.removeChild(a.previewElement),this._updateMaxFilesReachedClass()},thumbnail:function(a,b){var c,d,e,f,g;if(a.previewElement){for(a.previewElement.classList.remove("dz-file-preview"),a.previewElement.classList.add("dz-image-preview"),f=a.previewElement.querySelectorAll("[data-dz-thumbnail]"),g=[],d=0,e=f.length;e>d;d++)c=f[d],c.alt=a.name,g.push(c.src=b);return g}},error:function(a,b){var c,d,e,f,g;if(a.previewElement){for(a.previewElement.classList.add("dz-error"),"String"!=typeof b&&b.error&&(b=b.error),f=a.previewElement.querySelectorAll("[data-dz-errormessage]"),g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(c.textContent=b);return g}},errormultiple:i,processing:function(a){return a.previewElement&&(a.previewElement.classList.add("dz-processing"),a._removeLink)?a._removeLink.textContent=this.options.dictCancelUpload:void 0},processingmultiple:i,uploadprogress:function(a,b){var c,d,e,f,g;if(a.previewElement){for(f=a.previewElement.querySelectorAll("[data-dz-uploadprogress]"),g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(c.style.width=""+b+"%");return g}},totaluploadprogress:i,sending:i,sendingmultiple:i,success:function(a){return a.previewElement?a.previewElement.classList.add("dz-success"):void 0},successmultiple:i,canceled:function(a){return this.emit("error",a,"Upload canceled.")},canceledmultiple:i,complete:function(a){return a._removeLink?a._removeLink.textContent=this.options.dictRemoveFile:void 0},completemultiple:i,maxfilesexceeded:i,maxfilesreached:i,previewTemplate:'<div class="dz-preview dz-file-preview">\n  <div class="dz-details">\n    <div class="dz-filename"><span data-dz-name></span></div>\n    <div class="dz-size" data-dz-size></div>\n    <img data-dz-thumbnail />\n  </div>\n  <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>\n  <div class="dz-success-mark"><span>✔</span></div>\n  <div class="dz-error-mark"><span>✘</span></div>\n  <div class="dz-error-message"><span data-dz-errormessage></span></div>\n</div>'},c=function(){var a,b,c,d,e,f,g;for(d=arguments[0],c=2<=arguments.length?m.call(arguments,1):[],f=0,g=c.length;g>f;f++){b=c[f];for(a in b)e=b[a],d[a]=e}return d},b.prototype.getAcceptedFiles=function(){var a,b,c,d,e;for(d=this.files,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.accepted&&e.push(a);return e},b.prototype.getRejectedFiles=function(){var a,b,c,d,e;for(d=this.files,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.accepted||e.push(a);return e},b.prototype.getFilesWithStatus=function(a){var b,c,d,e,f;for(e=this.files,f=[],c=0,d=e.length;d>c;c++)b=e[c],b.status===a&&f.push(b);return f},b.prototype.getQueuedFiles=function(){return this.getFilesWithStatus(b.QUEUED)},b.prototype.getUploadingFiles=function(){return this.getFilesWithStatus(b.UPLOADING)},b.prototype.getActiveFiles=function(){var a,c,d,e,f;for(e=this.files,f=[],c=0,d=e.length;d>c;c++)a=e[c],(a.status===b.UPLOADING||a.status===b.QUEUED)&&f.push(a);return f},b.prototype.init=function(){var a,c,d,e,f,g,h;for("form"===this.element.tagName&&this.element.setAttribute("enctype","multipart/form-data"),this.element.classList.contains("dropzone")&&!this.element.querySelector(".dz-message")&&this.element.appendChild(b.createElement('<div class="dz-default dz-message"><span>'+this.options.dictDefaultMessage+"</span></div>")),this.clickableElements.length&&(d=function(a){return function(){return a.hiddenFileInput&&document.body.removeChild(a.hiddenFileInput),a.hiddenFileInput=document.createElement("input"),a.hiddenFileInput.setAttribute("type","file"),(null==a.options.maxFiles||a.options.maxFiles>1)&&a.hiddenFileInput.setAttribute("multiple","multiple"),a.hiddenFileInput.className="dz-hidden-input",null!=a.options.acceptedFiles&&a.hiddenFileInput.setAttribute("accept",a.options.acceptedFiles),a.hiddenFileInput.style.visibility="hidden",a.hiddenFileInput.style.position="absolute",a.hiddenFileInput.style.top="0",a.hiddenFileInput.style.left="0",a.hiddenFileInput.style.height="0",a.hiddenFileInput.style.width="0",document.body.appendChild(a.hiddenFileInput),a.hiddenFileInput.addEventListener("change",function(){var b,c,e,f;if(c=a.hiddenFileInput.files,c.length)for(e=0,f=c.length;f>e;e++)b=c[e],a.addFile(b);return d()})}}(this))(),this.URL=null!=(g=window.URL)?g:window.webkitURL,h=this.events,e=0,f=h.length;f>e;e++)a=h[e],this.on(a,this.options[a]);return this.on("uploadprogress",function(a){return function(){return a.updateTotalUploadProgress()}}(this)),this.on("removedfile",function(a){return function(){return a.updateTotalUploadProgress()}}(this)),this.on("canceled",function(a){return function(b){return a.emit("complete",b)}}(this)),this.on("complete",function(a){return function(){return 0===a.getUploadingFiles().length&&0===a.getQueuedFiles().length?setTimeout(function(){return a.emit("queuecomplete")},0):void 0}}(this)),c=function(a){return a.stopPropagation(),a.preventDefault?a.preventDefault():a.returnValue=!1},this.listeners=[{element:this.element,events:{dragstart:function(a){return function(b){return a.emit("dragstart",b)}}(this),dragenter:function(a){return function(b){return c(b),a.emit("dragenter",b)}}(this),dragover:function(a){return function(b){var d;try{d=b.dataTransfer.effectAllowed}catch(e){}return b.dataTransfer.dropEffect="move"===d||"linkMove"===d?"move":"copy",c(b),a.emit("dragover",b)}}(this),dragleave:function(a){return function(b){return a.emit("dragleave",b)}}(this),drop:function(a){return function(b){return c(b),a.drop(b)}}(this),dragend:function(a){return function(b){return a.emit("dragend",b)}}(this)}}],this.clickableElements.forEach(function(a){return function(c){return a.listeners.push({element:c,events:{click:function(d){return c!==a.element||d.target===a.element||b.elementInside(d.target,a.element.querySelector(".dz-message"))?a.hiddenFileInput.click():void 0}}})}}(this)),this.enable(),this.options.init.call(this)},b.prototype.destroy=function(){var a;return this.disable(),this.removeAllFiles(!0),(null!=(a=this.hiddenFileInput)?a.parentNode:void 0)&&(this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput),this.hiddenFileInput=null),delete this.element.dropzone,b.instances.splice(b.instances.indexOf(this),1)},b.prototype.updateTotalUploadProgress=function(){var a,b,c,d,e,f,g,h;if(d=0,c=0,a=this.getActiveFiles(),a.length){for(h=this.getActiveFiles(),f=0,g=h.length;g>f;f++)b=h[f],d+=b.upload.bytesSent,c+=b.upload.total;e=100*d/c}else e=100;return this.emit("totaluploadprogress",e,c,d)},b.prototype._getParamName=function(a){return"function"==typeof this.options.paramName?this.options.paramName(a):""+this.options.paramName+(this.options.uploadMultiple?"["+a+"]":"")},b.prototype.getFallbackForm=function(){var a,c,d,e;return(a=this.getExistingFallback())?a:(d='<div class="dz-fallback">',this.options.dictFallbackText&&(d+="<p>"+this.options.dictFallbackText+"</p>"),d+='<input type="file" name="'+this._getParamName(0)+'" '+(this.options.uploadMultiple?'multiple="multiple"':void 0)+' /><input type="submit" value="Upload!"></div>',c=b.createElement(d),"FORM"!==this.element.tagName?(e=b.createElement('<form action="'+this.options.url+'" enctype="multipart/form-data" method="'+this.options.method+'"></form>'),e.appendChild(c)):(this.element.setAttribute("enctype","multipart/form-data"),this.element.setAttribute("method",this.options.method)),null!=e?e:c)},b.prototype.getExistingFallback=function(){var a,b,c,d,e,f;for(b=function(a){var b,c,d;for(c=0,d=a.length;d>c;c++)if(b=a[c],/(^| )fallback($| )/.test(b.className))return b},f=["div","form"],d=0,e=f.length;e>d;d++)if(c=f[d],a=b(this.element.getElementsByTagName(c)))return a},b.prototype.setupEventListeners=function(){var a,b,c,d,e,f,g;for(f=this.listeners,g=[],d=0,e=f.length;e>d;d++)a=f[d],g.push(function(){var d,e;d=a.events,e=[];for(b in d)c=d[b],e.push(a.element.addEventListener(b,c,!1));return e}());return g},b.prototype.removeEventListeners=function(){var a,b,c,d,e,f,g;for(f=this.listeners,g=[],d=0,e=f.length;e>d;d++)a=f[d],g.push(function(){var d,e;d=a.events,e=[];for(b in d)c=d[b],e.push(a.element.removeEventListener(b,c,!1));return e}());return g},b.prototype.disable=function(){var a,b,c,d,e;for(this.clickableElements.forEach(function(a){return a.classList.remove("dz-clickable")}),this.removeEventListeners(),d=this.files,e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(this.cancelUpload(a));return e},b.prototype.enable=function(){return this.clickableElements.forEach(function(a){return a.classList.add("dz-clickable")}),this.setupEventListeners()},b.prototype.filesize=function(a){var b;return a>=109951162777.6?(a/=109951162777.6,b="TiB"):a>=107374182.4?(a/=107374182.4,b="GiB"):a>=104857.6?(a/=104857.6,b="MiB"):a>=102.4?(a/=102.4,b="KiB"):(a=10*a,b="b"),"<strong>"+Math.round(a)/10+"</strong> "+b},b.prototype._updateMaxFilesReachedClass=function(){return null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(this.getAcceptedFiles().length===this.options.maxFiles&&this.emit("maxfilesreached",this.files),this.element.classList.add("dz-max-files-reached")):this.element.classList.remove("dz-max-files-reached")},b.prototype.drop=function(a){var b,c;a.dataTransfer&&(this.emit("drop",a),b=a.dataTransfer.files,b.length&&(c=a.dataTransfer.items,c&&c.length&&null!=c[0].webkitGetAsEntry?this._addFilesFromItems(c):this.handleFiles(b)))},b.prototype.paste=function(a){var b,c;if(null!=(null!=a&&null!=(c=a.clipboardData)?c.items:void 0))return this.emit("paste",a),b=a.clipboardData.items,b.length?this._addFilesFromItems(b):void 0},b.prototype.handleFiles=function(a){var b,c,d,e;for(e=[],c=0,d=a.length;d>c;c++)b=a[c],e.push(this.addFile(b));return e},b.prototype._addFilesFromItems=function(a){var b,c,d,e,f;for(f=[],d=0,e=a.length;e>d;d++)c=a[d],f.push(null!=c.webkitGetAsEntry&&(b=c.webkitGetAsEntry())?b.isFile?this.addFile(c.getAsFile()):b.isDirectory?this._addFilesFromDirectory(b,b.name):void 0:null!=c.getAsFile?null==c.kind||"file"===c.kind?this.addFile(c.getAsFile()):void 0:void 0);return f},b.prototype._addFilesFromDirectory=function(a,b){var c,d;return c=a.createReader(),d=function(a){return function(c){var d,e,f;for(e=0,f=c.length;f>e;e++)d=c[e],d.isFile?d.file(function(c){return a.options.ignoreHiddenFiles&&"."===c.name.substring(0,1)?void 0:(c.fullPath=""+b+"/"+c.name,a.addFile(c))}):d.isDirectory&&a._addFilesFromDirectory(d,""+b+"/"+d.name)}}(this),c.readEntries(d,function(a){return"undefined"!=typeof console&&null!==console&&"function"==typeof console.log?console.log(a):void 0})},b.prototype.accept=function(a,c){return a.size>1024*this.options.maxFilesize*1024?c(this.options.dictFileTooBig.replace("{{filesize}}",Math.round(a.size/1024/10.24)/100).replace("{{maxFilesize}}",this.options.maxFilesize)):b.isValidFile(a,this.options.acceptedFiles)?null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(c(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}",this.options.maxFiles)),this.emit("maxfilesexceeded",a)):this.options.accept.call(this,a,c):c(this.options.dictInvalidFileType)},b.prototype.addFile=function(a){return a.upload={progress:0,total:a.size,bytesSent:0},this.files.push(a),a.status=b.ADDED,this.emit("addedfile",a),this._enqueueThumbnail(a),this.accept(a,function(b){return function(c){return c?(a.accepted=!1,b._errorProcessing([a],c)):(a.accepted=!0,b.options.autoQueue&&b.enqueueFile(a)),b._updateMaxFilesReachedClass()}}(this))},b.prototype.enqueueFiles=function(a){var b,c,d;for(c=0,d=a.length;d>c;c++)b=a[c],this.enqueueFile(b);return null},b.prototype.enqueueFile=function(a){if(a.status!==b.ADDED||a.accepted!==!0)throw new Error("This file can't be queued because it has already been processed or was rejected.");return a.status=b.QUEUED,this.options.autoProcessQueue?setTimeout(function(a){return function(){return a.processQueue()}}(this),0):void 0},b.prototype._thumbnailQueue=[],b.prototype._processingThumbnail=!1,b.prototype._enqueueThumbnail=function(a){return this.options.createImageThumbnails&&a.type.match(/image.*/)&&a.size<=1024*this.options.maxThumbnailFilesize*1024?(this._thumbnailQueue.push(a),setTimeout(function(a){return function(){return a._processThumbnailQueue()}}(this),0)):void 0},b.prototype._processThumbnailQueue=function(){return this._processingThumbnail||0===this._thumbnailQueue.length?void 0:(this._processingThumbnail=!0,this.createThumbnail(this._thumbnailQueue.shift(),function(a){return function(){return a._processingThumbnail=!1,a._processThumbnailQueue()}}(this)))},b.prototype.removeFile=function(a){return a.status===b.UPLOADING&&this.cancelUpload(a),this.files=j(this.files,a),this.emit("removedfile",a),0===this.files.length?this.emit("reset"):void 0},b.prototype.removeAllFiles=function(a){var c,d,e,f;for(null==a&&(a=!1),f=this.files.slice(),d=0,e=f.length;e>d;d++)c=f[d],(c.status!==b.UPLOADING||a)&&this.removeFile(c);return null},b.prototype.createThumbnail=function(a,b){var c;return c=new FileReader,c.onload=function(d){return function(){var e;return e=document.createElement("img"),e.onload=function(){var c,f,g,i,j,k,l,m;return a.width=e.width,a.height=e.height,g=d.options.resize.call(d,a),null==g.trgWidth&&(g.trgWidth=g.optWidth),null==g.trgHeight&&(g.trgHeight=g.optHeight),c=document.createElement("canvas"),f=c.getContext("2d"),c.width=g.trgWidth,c.height=g.trgHeight,h(f,e,null!=(j=g.srcX)?j:0,null!=(k=g.srcY)?k:0,g.srcWidth,g.srcHeight,null!=(l=g.trgX)?l:0,null!=(m=g.trgY)?m:0,g.trgWidth,g.trgHeight),i=c.toDataURL("image/png"),d.emit("thumbnail",a,i),null!=b?b():void 0},e.src=c.result}}(this),c.readAsDataURL(a)},b.prototype.processQueue=function(){var a,b,c,d;if(b=this.options.parallelUploads,c=this.getUploadingFiles().length,a=c,!(c>=b)&&(d=this.getQueuedFiles(),d.length>0)){if(this.options.uploadMultiple)return this.processFiles(d.slice(0,b-c));for(;b>a;){if(!d.length)return;this.processFile(d.shift()),a++}}},b.prototype.processFile=function(a){return this.processFiles([a])},b.prototype.processFiles=function(a){var c,d,e;for(d=0,e=a.length;e>d;d++)c=a[d],c.processing=!0,c.status=b.UPLOADING,this.emit("processing",c);return this.options.uploadMultiple&&this.emit("processingmultiple",a),this.uploadFiles(a)},b.prototype._getFilesWithXhr=function(a){var b,c;return c=function(){var c,d,e,f;for(e=this.files,f=[],c=0,d=e.length;d>c;c++)b=e[c],b.xhr===a&&f.push(b);return f}.call(this)},b.prototype.cancelUpload=function(a){var c,d,e,f,g,h,i;if(a.status===b.UPLOADING){for(d=this._getFilesWithXhr(a.xhr),e=0,g=d.length;g>e;e++)c=d[e],c.status=b.CANCELED;for(a.xhr.abort(),f=0,h=d.length;h>f;f++)c=d[f],this.emit("canceled",c);this.options.uploadMultiple&&this.emit("canceledmultiple",d)}else((i=a.status)===b.ADDED||i===b.QUEUED)&&(a.status=b.CANCELED,this.emit("canceled",a),this.options.uploadMultiple&&this.emit("canceledmultiple",[a]));return this.options.autoProcessQueue?this.processQueue():void 0},b.prototype.uploadFile=function(a){return this.uploadFiles([a])},b.prototype.uploadFiles=function(a){var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I;for(t=new XMLHttpRequest,u=0,y=a.length;y>u;u++)d=a[u],d.xhr=t;t.open(this.options.method,this.options.url,!0),t.withCredentials=!!this.options.withCredentials,q=null,f=function(b){return function(){var c,e,f;for(f=[],c=0,e=a.length;e>c;c++)d=a[c],f.push(b._errorProcessing(a,q||b.options.dictResponseError.replace("{{statusCode}}",t.status),t));return f}}(this),r=function(b){return function(c){var e,f,g,h,i,j,k,l,m;if(null!=c)for(f=100*c.loaded/c.total,g=0,j=a.length;j>g;g++)d=a[g],d.upload={progress:f,total:c.total,bytesSent:c.loaded};else{for(e=!0,f=100,h=0,k=a.length;k>h;h++)d=a[h],(100!==d.upload.progress||d.upload.bytesSent!==d.upload.total)&&(e=!1),d.upload.progress=f,d.upload.bytesSent=d.upload.total;if(e)return}for(m=[],i=0,l=a.length;l>i;i++)d=a[i],m.push(b.emit("uploadprogress",d,f,d.upload.bytesSent));return m}}(this),t.onload=function(c){return function(d){var e;if(a[0].status!==b.CANCELED&&4===t.readyState){if(q=t.responseText,t.getResponseHeader("content-type")&&~t.getResponseHeader("content-type").indexOf("application/json"))try{q=JSON.parse(q)}catch(g){d=g,q="Invalid JSON response from server."}return r(),200<=(e=t.status)&&300>e?c._finished(a,q,d):f()}}}(this),t.onerror=function(){return function(){return a[0].status!==b.CANCELED?f():void 0}}(this),p=null!=(D=t.upload)?D:t,p.onprogress=r,i={Accept:"application/json","Cache-Control":"no-cache","X-Requested-With":"XMLHttpRequest"},this.options.headers&&c(i,this.options.headers);for(g in i)h=i[g],t.setRequestHeader(g,h);if(e=new FormData,this.options.params){E=this.options.params;for(n in E)s=E[n],e.append(n,s)}for(v=0,z=a.length;z>v;v++)d=a[v],this.emit("sending",d,t,e);if(this.options.uploadMultiple&&this.emit("sendingmultiple",a,t,e),"FORM"===this.element.tagName)for(F=this.element.querySelectorAll("input, textarea, select, button"),w=0,A=F.length;A>w;w++)if(k=F[w],l=k.getAttribute("name"),m=k.getAttribute("type"),"SELECT"===k.tagName&&k.hasAttribute("multiple"))for(G=k.options,x=0,B=G.length;B>x;x++)o=G[x],o.selected&&e.append(l,o.value);else(!m||"checkbox"!==(H=m.toLowerCase())&&"radio"!==H||k.checked)&&e.append(l,k.value);for(j=C=0,I=a.length-1;I>=0?I>=C:C>=I;j=I>=0?++C:--C)e.append(this._getParamName(j),a[j],a[j].name);return t.send(e)},b.prototype._finished=function(a,c,d){var e,f,g;for(f=0,g=a.length;g>f;f++)e=a[f],e.status=b.SUCCESS,this.emit("success",e,c,d),this.emit("complete",e);return this.options.uploadMultiple&&(this.emit("successmultiple",a,c,d),this.emit("completemultiple",a)),this.options.autoProcessQueue?this.processQueue():void 0},b.prototype._errorProcessing=function(a,c,d){var e,f,g;for(f=0,g=a.length;g>f;f++)e=a[f],e.status=b.ERROR,this.emit("error",e,c,d),this.emit("complete",e);return this.options.uploadMultiple&&(this.emit("errormultiple",a,c,d),this.emit("completemultiple",a)),this.options.autoProcessQueue?this.processQueue():void 0},b}(d),b.version="3.10.2",b.options={},b.optionsForElement=function(a){return a.getAttribute("id")?b.options[e(a.getAttribute("id"))]:void 0},b.instances=[],b.forElement=function(a){if("string"==typeof a&&(a=document.querySelector(a)),null==(null!=a?a.dropzone:void 0))throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.");return a.dropzone},b.autoDiscover=!0,b.discover=function(){var a,c,d,e,f,g;for(document.querySelectorAll?d=document.querySelectorAll(".dropzone"):(d=[],a=function(a){var b,c,e,f;for(f=[],c=0,e=a.length;e>c;c++)b=a[c],f.push(/(^| )dropzone($| )/.test(b.className)?d.push(b):void 0);return f},a(document.getElementsByTagName("div")),a(document.getElementsByTagName("form"))),g=[],e=0,f=d.length;f>e;e++)c=d[e],g.push(b.optionsForElement(c)!==!1?new b(c):void 0);return g},b.blacklistedBrowsers=[/opera.*Macintosh.*version\/12/i],b.isBrowserSupported=function(){var a,c,d,e,f;if(a=!0,window.File&&window.FileReader&&window.FileList&&window.Blob&&window.FormData&&document.querySelector)if("classList"in document.createElement("a"))for(f=b.blacklistedBrowsers,d=0,e=f.length;e>d;d++)c=f[d],c.test(navigator.userAgent)&&(a=!1);else a=!1;else a=!1;return a},j=function(a,b){var c,d,e,f;for(f=[],d=0,e=a.length;e>d;d++)c=a[d],c!==b&&f.push(c);return f},e=function(a){return a.replace(/[\-_](\w)/g,function(a){return a.charAt(1).toUpperCase()})},b.createElement=function(a){var b;return b=document.createElement("div"),b.innerHTML=a,b.childNodes[0]},b.elementInside=function(a,b){if(a===b)return!0;for(;a=a.parentNode;)if(a===b)return!0;return!1},b.getElement=function(a,b){var c;if("string"==typeof a?c=document.querySelector(a):null!=a.nodeType&&(c=a),null==c)throw new Error("Invalid `"+b+"` option provided. Please provide a CSS selector or a plain HTML element.");return c},b.getElements=function(a,b){var c,d,e,f,g,h,i,j;if(a instanceof Array){e=[];try{for(f=0,h=a.length;h>f;f++)d=a[f],e.push(this.getElement(d,b))}catch(k){c=k,e=null}}else if("string"==typeof a)for(e=[],j=document.querySelectorAll(a),g=0,i=j.length;i>g;g++)d=j[g],e.push(d);else null!=a.nodeType&&(e=[a]);if(null==e||!e.length)throw new Error("Invalid `"+b+"` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");return e},b.confirm=function(a,b,c){return window.confirm(a)?b():null!=c?c():void 0},b.isValidFile=function(a,b){var c,d,e,f,g;if(!b)return!0;for(b=b.split(","),d=a.type,c=d.replace(/\/.*$/,""),f=0,g=b.length;g>f;f++)if(e=b[f],e=e.trim(),"."===e.charAt(0)){if(-1!==a.name.toLowerCase().indexOf(e.toLowerCase(),a.name.length-e.length))return!0}else if(/\/\*$/.test(e)){if(c===e.replace(/\/.*$/,""))return!0}else if(d===e)return!0;return!1},"undefined"!=typeof jQuery&&null!==jQuery&&(jQuery.fn.dropzone=function(a){return this.each(function(){return new b(this,a)})}),"undefined"!=typeof c&&null!==c?c.exports=b:window.Dropzone=b,b.ADDED="added",b.QUEUED="queued",b.ACCEPTED=b.QUEUED,b.UPLOADING="uploading",b.PROCESSING=b.UPLOADING,b.CANCELED="canceled",b.ERROR="error",b.SUCCESS="success",g=function(a){var b,c,d,e,f,g,h,i,j,k;for(h=a.naturalWidth,g=a.naturalHeight,c=document.createElement("canvas"),c.width=1,c.height=g,d=c.getContext("2d"),d.drawImage(a,0,0),e=d.getImageData(0,0,1,g).data,k=0,f=g,i=g;i>k;)b=e[4*(i-1)+3],0===b?f=i:k=i,i=f+k>>1;return j=i/g,0===j?1:j},h=function(a,b,c,d,e,f,h,i,j,k){var l;return l=g(b),a.drawImage(b,c,d,e,f,h,i,j,k/l)},f=function(a,b){var c,d,e,f,g,h,i,j,k;if(e=!1,k=!0,d=a.document,j=d.documentElement,c=d.addEventListener?"addEventListener":"attachEvent",i=d.addEventListener?"removeEventListener":"detachEvent",h=d.addEventListener?"":"on",f=function(c){return"readystatechange"!==c.type||"complete"===d.readyState?(("load"===c.type?a:d)[i](h+c.type,f,!1),!e&&(e=!0)?b.call(a,c.type||c):void 0):void 0},g=function(){var a;try{j.doScroll("left")}catch(b){return a=b,void setTimeout(g,50)}return f("poll")},"complete"!==d.readyState){if(d.createEventObject&&j.doScroll){try{k=!a.frameElement}catch(l){}k&&g()}return d[c](h+"DOMContentLoaded",f,!1),d[c](h+"readystatechange",f,!1),a[c](h+"load",f,!1)}},b._autoDiscoverFunction=function(){return b.autoDiscover?b.discover():void 0},f(window,b._autoDiscoverFunction)}).call(this)}),"object"==typeof exports?module.exports=a("dropzone"):"function"==typeof define&&define.amd?define([],function(){return a("dropzone")}):this.Dropzone=a("dropzone")}();
-               </script>
-               <script charset="utf-8">
-                       Dropzone.options.myAwesomeDropzone = {
-                               init: function() {
-                                       this.on("success", function (file, response) {
-                                               alert(response);
-                                       });
-                               },
-                       };
-               </script>
-               <style media="screen">
-                       /* The MIT License */
-                       .dropzone,
-                       .dropzone *,
-                       .dropzone-previews,
-                       .dropzone-previews * {
-                         -webkit-box-sizing: border-box;
-                         -moz-box-sizing: border-box;
-                         box-sizing: border-box;
-                       }
-                       .dropzone {
-                         position: relative;
-                         border: 1px solid rgba(0,0,0,0.08);
-                         background: rgba(0,0,0,0.02);
-                         padding: 1em;
-                       }
-                       .dropzone.dz-clickable {
-                         cursor: pointer;
-                       }
-                       .dropzone.dz-clickable .dz-message,
-                       .dropzone.dz-clickable .dz-message span {
-                         cursor: pointer;
-                       }
-                       .dropzone.dz-clickable * {
-                         cursor: default;
-                       }
-                       .dropzone .dz-message {
-                         opacity: 1;
-                         -ms-filter: none;
-                         filter: none;
-                       }
-                       .dropzone.dz-drag-hover {
-                         border-color: rgba(0,0,0,0.15);
-                         background: rgba(0,0,0,0.04);
-                       }
-                       .dropzone.dz-started .dz-message {
-                         display: none;
+       // Delete file
+       function deleteFile ($file) {
+               global $data;
+
+               if (in_array(substr($file, 1), $_SESSION['upload_user_files']) || in_array($file, $_SESSION['upload_user_files'])) {
+                       $fqfn = $data['uploaddir'] . DIRECTORY_SEPARATOR . $file;
+                       if (!in_array($file, $data['ignores']) && isReadableFile($fqfn)) {
+                               unlink($fqfn);
+                               echo 'File has been removed';
+                               exit;
                        }
-                       .dropzone .dz-preview,
-                       .dropzone-previews .dz-preview {
-                         background: rgba(255,255,255,0.8);
-                         position: relative;
-                         display: inline-block;
-                         margin: 17px;
-                         vertical-align: top;
-                         border: 1px solid #acacac;
-                         padding: 6px 6px 6px 6px;
+               }
+       }
+
+       // Mark/unmark file as hidden
+       function markUnmarkHidden ($file) {
+               global $data;
+
+               if (in_array(substr($file, 1), $_SESSION['upload_user_files']) || in_array($file, $_SESSION['upload_user_files'])) {
+                       $fqfn = $data['uploaddir'] . DIRECTORY_SEPARATOR . $file;
+                       if (!in_array($file, $data['ignores']) && isReadableFile($fqfn)) {
+                               if (substr($file, 0, 1) === '.') {
+                                       rename($fqfn, substr($fqfn, 1));
+                                       echo 'File has been made visible';
+                               } else {
+                                       rename($fqfn, $data['uploaddir'] . DIRECTORY_SEPARATOR . '.' . $file);
+                                       echo 'File has been hidden';
+                               }
+                               exit;
                        }
-                       .dropzone .dz-preview.dz-file-preview [data-dz-thumbnail],
-                       .dropzone-previews .dz-preview.dz-file-preview [data-dz-thumbnail] {
-                         display: none;
+               }
+       }
+
+       // Checks if the given file is a file and is readable
+       function isReadableFile ($file) {
+               return (is_file($file) && is_readable($file));
+       }
+
+       // Files are being POSEed. Uploading them one by one.
+       if (isset($_FILES['file'])) {
+               header('Content-type: text/plain');
+               if (is_array($_FILES['file'])) {
+                       $file_array = diverseArray($_FILES['file']);
+                       foreach ($file_array as $file_data)
+                               uploadFile($file_data);
+               } else
+                       uploadFile($_FILES['file']);
+               exit;
+       }
+
+       // Other file functions (delete, private).
+       if (isset($_POST)) {
+               if ($settings['allow_deletion'] && (isset($_POST['target'])) && isset($_POST['action']) && $_POST['action'] === 'delete')
+                       deleteFile($_POST['target']);
+
+               if ($settings['allow_private'] && (isset($_POST['target'])) && isset($_POST['action']) && $_POST['action'] === 'privatetoggle')
+                       markUnmarkHidden($_POST['target']);
+       }
+
+       // List files in a given directory, excluding certain files
+       function createArrayFromPath ($dir) {
+               global $data;
+
+               $file_array = array();
+               $dh = opendir($dir);
+                       while ($filename = readdir($dh)) {
+                               $fqfn = $dir . DIRECTORY_SEPARATOR . $filename;
+                               if (isReadableFile($fqfn) && !in_array($filename, $data['ignores']))
+                                       $file_array[filemtime($fqfn)] = $filename;
                        }
-                       .dropzone .dz-preview .dz-details,
-                       .dropzone-previews .dz-preview .dz-details {
-                         width: 100px;
-                         height: 100px;
-                         position: relative;
-                         background: #ebebeb;
-                         padding: 5px;
-                         margin-bottom: 22px;
+
+               ksort($file_array);
+               $file_array = array_reverse($file_array, true);
+               return $file_array;
+       }
+
+       // Removes old files
+       function removeOldFiles ($dir) {
+               global $file_array, $settings;
+
+               foreach ($file_array as $file) {
+                       $fqfn = $dir . DIRECTORY_SEPARATOR . $file;
+                       if ($settings['time_limit'] < time() - filemtime($fqfn))
+                               unlink($fqfn);
+               }
+       }
+
+       // Only read files if the feature is enabled
+       if ($settings['listfiles']) {
+               $file_array = createArrayFromPath($data['uploaddir']);
+
+               // Removing old files
+               if ($settings['remove_old_files'])
+                       removeOldFiles($data['uploaddir']);
+
+               $file_array = createArrayFromPath($data['uploaddir']);
+       }
+?>
+<!DOCTYPE html>
+<html lang="<?=$settings['lang']?>" dir="<?=$settings['lang_dir']?>">
+       <head>
+               <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+               <meta http-equiv="Content-Script-Type" content="text/javascript">
+               <meta name="robots" content="noindex">
+               <meta name="referrer" content="origin-when-crossorigin">
+               <title><?=$settings['title']?></title>
+               <style media="screen">
+               <!--
+                       body {
+                               background: #111;
+                               margin: 0;
+                               color: #ddd;
+                               font-family: sans-serif;
                        }
-                       .dropzone .dz-preview .dz-details .dz-filename,
-                       .dropzone-previews .dz-preview .dz-details .dz-filename {
-                         overflow: hidden;
-                         height: 100%;
+
+                       body > h1 {
+                               display: block;
+                               background: rgba(255, 255, 255, 0.05);
+                               padding: 8px 16px;
+                               text-align: center;
+                               margin: 0;
                        }
-                       .dropzone .dz-preview .dz-details img,
-                       .dropzone-previews .dz-preview .dz-details img {
-                         position: absolute;
-                         top: 0;
-                         left: 0;
-                         width: 100px;
-                         height: 100px;
+
+                       body > form {
+                               display: block;
+                               background: rgba(255, 255, 255, 0.075);
+                               padding: 16px 16px;
+                               margin: 0;
+                               text-align: center;
                        }
-                       .dropzone .dz-preview .dz-details .dz-size,
-                       .dropzone-previews .dz-preview .dz-details .dz-size {
-                         position: absolute;
-                         bottom: -28px;
-                         left: 3px;
-                         height: 28px;
-                         line-height: 28px;
+
+                       body > ul {
+                               display: block;
+                               padding: 0;
+                               max-width: 1000px;
+                               margin: 32px auto;
                        }
-                       .dropzone .dz-preview.dz-error .dz-error-mark,
-                       .dropzone-previews .dz-preview.dz-error .dz-error-mark {
-                         display: block;
+
+                       body > ul > li {
+                               display: block;
+                               margin: 0;
+                               padding: 0;
                        }
-                       .dropzone .dz-preview.dz-success .dz-success-mark,
-                       .dropzone-previews .dz-preview.dz-success .dz-success-mark {
-                         display: block;
+
+                       body > ul > li > a {
+                               display: block;
+                               margin: 0 0 1px 0;
+                               list-style: none;
+                               background: rgba(255, 255, 255, 0.1);
+                               padding: 8px 16px;
+                               text-decoration: none;
+                               color: inherit;
+                               opacity: 0.5;
                        }
-                       .dropzone .dz-preview:hover .dz-details img,
-                       .dropzone-previews .dz-preview:hover .dz-details img {
-                         display: none;
+
+                       body > ul > li > a:hover {
+                               opacity: 1;
                        }
-                       .dropzone .dz-preview .dz-success-mark,
-                       .dropzone-previews .dz-preview .dz-success-mark,
-                       .dropzone .dz-preview .dz-error-mark,
-                       .dropzone-previews .dz-preview .dz-error-mark {
-                         display: none;
-                         position: absolute;
-                         width: 40px;
-                         height: 40px;
-                         font-size: 30px;
-                         text-align: center;
-                         right: -10px;
-                         top: -10px;
+
+                       body > ul > li > a:active {
+                               opacity: 0.5;
                        }
-                       .dropzone .dz-preview .dz-success-mark,
-                       .dropzone-previews .dz-preview .dz-success-mark {
-                         color: #8cc657;
+
+                       body > ul > li > a > span {
+                               float: right;
+                               font-size: 90%;
                        }
-                       .dropzone .dz-preview .dz-error-mark,
-                       .dropzone-previews .dz-preview .dz-error-mark {
-                         color: #ee162d;
+
+                       body > ul > li > form {
+                               display: inline-block;
+                               padding: 0;
+                               margin: 0;
                        }
-                       .dropzone .dz-preview .dz-progress,
-                       .dropzone-previews .dz-preview .dz-progress {
-                         position: absolute;
-                         top: 100px;
-                         left: 6px;
-                         right: 6px;
-                         height: 6px;
-                         background: #d7d7d7;
-                         display: none;
+
+                       body > ul > li.owned {
+                               margin: 8px;
                        }
-                       .dropzone .dz-preview .dz-progress .dz-upload,
-                       .dropzone-previews .dz-preview .dz-progress .dz-upload {
-                         display: block;
-                         position: absolute;
-                         top: 0;
-                         bottom: 0;
-                         left: 0;
-                         width: 0%;
-                         background-color: #8cc657;
+
+                       body > ul > li > form > button {
+                               opacity: 0.5;
+                               display: inline-block;
+                               padding: 4px 16px;
+                               margin: 0;
+                               border: 0;
+                               background: rgba(255, 255, 255, 0.1);
+                               color: inherit;
                        }
-                       .dropzone .dz-preview.dz-processing .dz-progress,
-                       .dropzone-previews .dz-preview.dz-processing .dz-progress {
-                         display: block;
+
+                       body > ul > li > form > button:hover {
+                               opacity: 1;
                        }
-                       .dropzone .dz-preview .dz-error-message,
-                       .dropzone-previews .dz-preview .dz-error-message {
-                         display: none;
-                         position: absolute;
-                         top: -5px;
-                         left: -20px;
-                         background: rgba(245,245,245,0.8);
-                         padding: 8px 10px;
-                         color: #800;
-                         min-width: 140px;
-                         max-width: 500px;
-                         z-index: 500;
+
+                       body > ul > li > form > button:active {
+                               opacity: 0.5;
                        }
-                       .dropzone .dz-preview:hover.dz-error .dz-error-message,
-                       .dropzone-previews .dz-preview:hover.dz-error .dz-error-message {
-                         display: block;
+
+                       body > ul > li.uploading {
+                               animation: upanim 2s linear 0s infinite alternate;
                        }
 
+                       @keyframes upanim {
+                               from {
+                                       opacity: 0.3;
+                               }
+                               to {
+                                       opacity: 0.8;
+                               }
+                       }
+               //-->
                </style>
        </head>
        <body>
-               <h1>Simple PHP Upload</h1>
-               <p>
-                       Maximum upload size: <?php echo $data['max_upload_size']; ?>
-               </p>
-               <form action="<?= $data['scriptname'] ?>" method="POST" enctype="multipart/form-data" class="dropzone" id="my-awesome-dropzone">
-                       <div class="fallback">
-                               Choose File: <input type="file" name="file" /><br />
-                               <input type="submit" value="Upload" />
-                       </div>
+               <h1><?=$settings['title']?></h1>
+               <form action="<?= $data['scriptname'] ?>" method="POST" enctype="multipart/form-data" class="dropzone" id="simpleupload-form">
+                       Maximum upload size: <?php echo $data['max_upload_size']; ?><br />
+                       <input type="file" name="file[]" multiple required id="simpleupload-input"/>
                </form>
                <?php if ($settings['listfiles']) { ?>
-                       <strong>Uploaded files:</strong><br />
-                       <ul>
+                       <ul id="simpleupload-ul">
                                <?php
-                                       $dh = opendir($settings['uploaddir']);
-                                       while (false !== ($filename = readdir($dh)))
-                                               if (is_file($filename) && !in_array($filename, array('.', '..', $data['scriptname']))) {
-                                                       $file_info = array();
+                                       foreach ($file_array as $mtime => $filename) {
+                                               $fqfn = $data['uploaddir'] . DIRECTORY_SEPARATOR . $filename;
+                                               $file_info = array();
+                                               $file_owner = false;
+                                               $file_private = $filename[0] === '.';
+
+                                               if ($settings['listfiles_size'])
+                                                       $file_info[] = formatSize(filesize($fqfn));
+
+                                               if ($settings['listfiles_size'])
+                                                       $file_info[] = date($settings['listfiles_date_format'], $mtime);
 
-                                                       if ($settings['listfiles_size'])
-                                                               $file_info[] = FormatSize(filesize($filename));
+                                               if ($settings['allow_deletion'] || $settings['allow_private'])
+                                                       if (in_array(substr($filename, 1), $_SESSION['upload_user_files']) || in_array($filename, $_SESSION['upload_user_files']))
+                                                               $file_owner = true;
 
-                                                       if ($settings['listfiles_size'])
-                                                               $file_info[] = date($settings['listfiles_date_format'], filemtime($filename));
+                                               $file_info = implode(', ', $file_info);
 
-                                                       if ($settings['allow_deletion'])
-                                                               if (in_array($filename, $_SESSION['upload_user_files']))
-                                                                       $file_info[] = '<form action="' . $data['scriptname'] . '" method="POST"><input type="hidden" name="target" value="' . $filename . '" /><input type="hidden" name="action" value="delete" /><button type="submit">delete</button></form>';
+                                               if (strlen($file_info) > 0)
+                                                       $file_info = ' (' . $file_info . ')';
 
-                                                       $file_info = implode(', ', $file_info);
+                                               $class = '';
+                                               if ($file_owner)
+                                                       $class = 'owned';
 
-                                                       if (strlen($file_info) > 0)
-                                                               $file_info = ' (' . $file_info . ')';
+                                               if (!$file_private || $file_owner) {
+                                                       echo "<li class=\"' . $class . '\">";
 
-                                                       echo "<li><a href=\"$filename\">$filename</a>$file_info</li>";
+                                                       $url = str_replace('/./', '/', sprintf('%s%s/%s', $settings['url'], $settings['uploaddir'], $filename));
+
+                                                       echo "<a href=\"$url\" target=\"_blank\">$filename<span>$file_info</span></a>";
+
+                                                       if ($file_owner) {
+                                                               if ($settings['allow_deletion'])
+                                                                       echo '<form action="' . $data['scriptname'] . '" method="POST"><input type="hidden" name="target" value="' . $filename . '" /><input type="hidden" name="action" value="delete" /><button type="submit">delete</button></form>';
+
+                                                               if ($settings['allow_private'])
+                                                                       if ($file_private)
+                                                                               echo '<form action="' . $data['scriptname'] . '" method="POST"><input type="hidden" name="target" value="' . $filename . '" /><input type="hidden" name="action" value="privatetoggle" /><button type="submit">make public</button></form>';
+                                                                       else
+                                                                               echo '<form action="' . $data['scriptname'] . '" method="POST"><input type="hidden" name="target" value="' . $filename . '" /><input type="hidden" name="action" value="privatetoggle" /><button type="submit">make private</button></form>';
+                                                       }
+
+                                                       echo "</li>";
                                                }
+                                       }
                                ?>
                        </ul>
-               <?php } ?>
+               <?php
+               }
+
+               if ($settings['allow_external_refs']) {
+               ?>
+                       <a href="https://github.com/muchweb/simple-php-upload" target="_blank"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
+               <?php
+               } else {
+               ?>
+                       <a href="https://github.com/muchweb/simple-php-upload" target="_blank">Fork me on GitHub</a>
+               <?php
+               }
+               ?>
+               <script type="text/javascript">
+               <!--
+                       var target_form = document.getElementById('simpleupload-form'),
+                               target_ul = document.getElementById('simpleupload-ul'),
+                               target_input = document.getElementById('simpleupload-input');
+
+                       target_form.addEventListener('dragover', function (event) {
+                               event.preventDefault();
+                       }, false);
+
+                       function AddFileLi (name, info) {
+                               target_form.style.display = 'none';
+
+                               var new_li = document.createElement('li');
+                               new_li.className = 'uploading';
+
+                               var new_a = document.createElement('a');
+                               new_a.innerHTML = name;
+                               new_li.appendChild(new_a);
+
+                               var new_span = document.createElement('span');
+                               new_span.innerHTML = info;
+                               new_a.appendChild(new_span);
+
+                               target_ul.insertBefore(new_li, target_ul.firstChild);
+                       }
+
+                       function HandleFiles (event) {
+                               event.preventDefault();
+
+                               var i = 0,
+                                       files = event.dataTransfer.files,
+                                       len = files.length;
+
+                               var form = new FormData();
+
+                               for (; i < len; i++) {
+                                       form.append('file[]', files[i]);
+                                       AddFileLi(files[i].name, files[i].size + ' bytes');
+                               }
+
+                               var xhr = new XMLHttpRequest();
+                               xhr.onload = function() {
+                                       window.location.reload();
+                               };
+
+                               xhr.open('post', '<?php echo $data['scriptname']; ?>', true);
+                               xhr.send(form);
+                       }
+
+                       target_form.addEventListener('drop', HandleFiles, false);
+
+                       document.getElementById('simpleupload-input').onchange = function () {
+                               AddFileLi('Uploading...', '');
+                               target_form.submit();
+                       };
+               //-->
+               </script>
        </body>
 </html>