diff options
author | Florian Pritz <bluewind@xinu.at> | 2013-01-17 18:54:35 +0100 |
---|---|---|
committer | Florian Pritz <bluewind@xinu.at> | 2013-01-17 21:25:44 +0100 |
commit | e1e658c6547a2b00a2b5b32bf3cd34ab8a5f2a52 (patch) | |
tree | f26e9ef785ff1d2f8d23b7235fb991e93d5e6d1c | |
parent | dc3afcb35744ec5d9036fc329dab25f0c8dcd7a5 (diff) |
Support multiple uploads in the same request
This change *should* be backwards compatible.
Signed-off-by: Florian Pritz <bluewind@xinu.at>
-rw-r--r-- | application/controllers/file.php | 165 | ||||
-rw-r--r-- | application/helpers/filebin_helper.php | 28 | ||||
-rw-r--r-- | application/views/file/show_url.php | 10 | ||||
-rw-r--r-- | application/views/file/upload_form.php | 5 | ||||
-rw-r--r-- | application/views/file_plaintext/show_url.php | 3 | ||||
-rw-r--r-- | application/views/file_plaintext/upload_form.php | 1 | ||||
-rw-r--r-- | data/js/script.js | 26 |
7 files changed, 155 insertions, 83 deletions
diff --git a/application/controllers/file.php b/application/controllers/file.php index 18e570b20..2b39309bb 100644 --- a/application/controllers/file.php +++ b/application/controllers/file.php @@ -84,7 +84,7 @@ class File extends CI_Controller { } // Try to guess what the user would like to do. $id = $this->uri->segment(1); - if(isset($_FILES['file'])) { + if(!empty($_FILES)) { $this->do_upload(); } elseif ($id != "file" && $this->mfile->id_exists($id)) { $this->_download(); @@ -264,7 +264,7 @@ class File extends CI_Controller { $this->load->view('footer', $this->data); } - function _show_url($id, $lexer) + function _show_url($ids, $lexer) { $redirect = false; @@ -272,35 +272,40 @@ class File extends CI_Controller { $this->muser->require_session(); // keep the upload but require the user to login $this->session->set_userdata("last_upload", array( - "id" => $id, + "ids" => $ids, "lexer" => $lexer )); $this->session->set_flashdata("uri", "file/claim_id"); $this->muser->require_access(); } - if ($lexer) { - $this->data['url'] = site_url($id).'/'.$lexer; - } else { - $this->data['url'] = site_url($id).'/'; - - $filedata = $this->mfile->get_filedata($id); - $file = $this->mfile->file($filedata['hash']); - $type = $filedata['mimetype']; - $lexer = $this->mfile->should_highlight($type); - - // If we detected a highlightable file redirect, - // otherwise show the URL because browsers would just show a DL dialog + foreach ($ids as $id) { if ($lexer) { - $redirect = true; + $this->data['urls'][] = site_url($id).'/'.$lexer; + } else { + $this->data['urls'][] = site_url($id).'/'; + + if (count($ids) == 1) { + $filedata = $this->mfile->get_filedata($id); + $file = $this->mfile->file($filedata['hash']); + $type = $filedata['mimetype']; + $lexer = $this->mfile->should_highlight($type); + + // If we detected a highlightable file redirect, + // otherwise show the URL because browsers would just show a DL dialog + if ($lexer) { + $redirect = true; + } + } } } if (is_cli_client()) { $redirect = false; } - if ($redirect) { - redirect($this->data['url'], "location", 303); + + if ($redirect && count($ids) == 1) { + redirect($this->data['urls'][0], "location", 303); } else { $this->load->view('header', $this->data); $this->load->view($this->var->view_dir.'/show_url', $this->data); @@ -533,66 +538,85 @@ class File extends CI_Controller { file_put_contents($file, $content); chmod($file, 0600); $this->mfile->add_file($hash, $id, $filename); - $this->_show_url($id, false); + $this->_show_url(array($id), false); } // Handles uploaded files function do_upload() { + $ids = array(); + $extension = $this->input->post('extension'); - if(!isset($_FILES['file']) || $_FILES['file']['error'] !== 0) { - $this->output->set_status_header(400); - $errors = array( - 0=>"There is no error, the file uploaded with success", - 1=>"The uploaded file exceeds the upload_max_filesize directive in php.ini", - 2=>"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form", - 3=>"The uploaded file was only partially uploaded", - 4=>"No file was uploaded", - 6=>"Missing a temporary folder" - ); - $this->data["msg"] = "Unknown error."; + $files = getNormalizedFILES(); - if (isset($_FILES["file"])) { - $this->data["msg"] = $errors[$_FILES['file']['error']]; - } - $this->load->view('header', $this->data); - $this->load->view($this->var->view_dir.'/upload_error', $this->data); - $this->load->view('footer'); - return; + if (empty($files)) { + show_error("No file was uploaded or unknown error occured."); } - $filesize = filesize($_FILES['file']['tmp_name']); - if ($filesize > $this->config->item('upload_max_size')) { - $this->output->set_status_header(413); - $this->load->view('header', $this->data); - $this->load->view($this->var->view_dir.'/too_big'); - $this->load->view('footer'); - return; - } + // Check for errors before doing anything + // First error wins and is displayed, these shouldn't happen that often anyway. + foreach ($files as $key => $file) { + // getNormalizedFILES() removes any file with error == 4 + if ($file['error'] !== 0) { + $this->output->set_status_header(400); + $errors = array( + 0=>"There is no error, the file uploaded with success", + 1=>"The uploaded file exceeds the upload_max_filesize directive in php.ini", + 2=>"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form", + 3=>"The uploaded file was only partially uploaded", + 4=>"No file was uploaded", + 6=>"Missing a temporary folder" + ); - $id = $this->mfile->new_id(); - $hash = md5_file($_FILES['file']['tmp_name']); + $this->data["msg"] = "Unknown error."; - // work around a curl bug and allow the client to send the real filename base64 encoded - $filename = $this->input->post("filename"); - if ($filename !== false) { - $filename = trim(base64_decode($filename, true), "\r\n\0\t\x0B"); - } + if (isset($file)) { + $this->data["msg"] = $errors[$file['error']]; + } + $this->load->view('header', $this->data); + $this->load->view($this->var->view_dir.'/upload_error', $this->data); + $this->load->view('footer'); + return; + } - // fall back if base64_decode failed - if ($filename === false) { - $filename = $_FILES['file']['name']; + $filesize = filesize($file['tmp_name']); + if ($filesize > $this->config->item('upload_max_size')) { + $this->output->set_status_header(413); + $this->load->view('header', $this->data); + $this->load->view($this->var->view_dir.'/too_big'); + $this->load->view('footer'); + return; + } } - $folder = $this->mfile->folder($hash); - file_exists($folder) || mkdir ($folder); - $file = $this->mfile->file($hash); + foreach ($files as $key => $file) { + $id = $this->mfile->new_id(); + $hash = md5_file($file['tmp_name']); - move_uploaded_file($_FILES['file']['tmp_name'], $file); - chmod($file, 0600); - $this->mfile->add_file($hash, $id, $filename); - $this->_show_url($id, $extension); + // work around a curl bug and allow the client to send the real filename base64 encoded + // TODO: this interface currently sets the same filename for every file if you use multiupload + $filename = $this->input->post("filename"); + if ($filename !== false) { + $filename = trim(base64_decode($filename, true), "\r\n\0\t\x0B"); + } + + // fall back if base64_decode failed + if ($filename === false) { + $filename = $file['name']; + } + + $folder = $this->mfile->folder($hash); + file_exists($folder) || mkdir ($folder); + $file_path = $this->mfile->file($hash); + + move_uploaded_file($file['tmp_name'], $file_path); + chmod($file_path, 0600); + $this->mfile->add_file($hash, $id, $filename); + $ids[] = $id; + } + + $this->_show_url($ids, $extension); } function claim_id() @@ -600,15 +624,22 @@ class File extends CI_Controller { $this->muser->require_access(); $last_upload = $this->session->userdata("last_upload"); - $id = $last_upload["id"]; + $ids = $last_upload["ids"]; + $errors = array(); - $filedata = $this->mfile->get_filedata($id); + foreach ($ids as $key => $id) { + $filedata = $this->mfile->get_filedata($id); - if ($filedata["user"] != 0) { - show_error("Someone already owns '$id', can't reassign."); + if ($filedata["user"] != 0) { + $errors[] = $id; + } + + $this->mfile->adopt($id); } - $this->mfile->adopt($id); + if (!empty($errors)) { + show_error("Someone already owns '".implode(", ", $errors)."', can't reassign."); + } $this->session->unset_userdata("last_upload"); diff --git a/application/helpers/filebin_helper.php b/application/helpers/filebin_helper.php index 2f073c902..0951527fe 100644 --- a/application/helpers/filebin_helper.php +++ b/application/helpers/filebin_helper.php @@ -256,4 +256,32 @@ function handle_etag($etag) } } +// Reference: http://php.net/manual/en/features.file-upload.multiple.php#109437 +// This is a little different because we don't care about the fieldname +function getNormalizedFILES() +{ + $newfiles = array(); + $ret = array(); + + foreach($_FILES as $fieldname => $fieldvalue) + foreach($fieldvalue as $paramname => $paramvalue) + foreach((array)$paramvalue as $index => $value) + $newfiles[$fieldname][$index][$paramname] = $value; + + $i = 0; + foreach ($newfiles as $fieldname => $field) { + foreach ($field as $file) { + // skip empty fields + if ($file["error"] === 4) { + continue; + } + $ret[$i] = $file; + $ret[$i]["formfield"] = $fieldname; + $i++; + } + } + + return $ret; +} + # vim: set noet: diff --git a/application/views/file/show_url.php b/application/views/file/show_url.php index 3c08ed952..a3d965717 100644 --- a/application/views/file/show_url.php +++ b/application/views/file/show_url.php @@ -1,6 +1,8 @@ <div class="center"> - <p> - You can get your file here:<br /> - <a href="<?php echo $url; ?>"><?php echo $url; ?></a><br /> - </p> + <p>You can get your file(s) here:</p> + <p> + <?php foreach ($urls as $key => $url) { ?> + <a href="<?php echo $url; ?>"><?php echo $url; ?></a><br /> + <?php } ?> + </p> </div> diff --git a/application/views/file/upload_form.php b/application/views/file/upload_form.php index a6f4eedc7..aaf36931a 100644 --- a/application/views/file/upload_form.php +++ b/application/views/file/upload_form.php @@ -13,7 +13,7 @@ <div class="span6"> <?php echo form_open_multipart('file/do_upload'); ?> <h2>File upload</h2> - <input id="file" type="file" name="file"><br> + <input class="file-upload" type="file" name="file[]" multiple="multiple"><br> <button type="submit" id="upload_button" class="btn btn-primary">Upload it!</button> </form> <div class="alert alert-block alert-info"> @@ -22,7 +22,8 @@ Uploads/pastes are deleted after <?php echo $upload_max_age; ?> days <?php if($small_upload_size > 0) { echo "unless they are smaller than ".format_bytes($small_upload_size); - } ?>. Maximum upload size is <?php echo format_bytes($max_upload_size); ?> + } ?>. Maximum upload size is <?php echo format_bytes($max_upload_size); ?>. + You can upload a maximum of <?php echo ini_get("max_file_uploads"); ?> files at once. </p> </div> </div> diff --git a/application/views/file_plaintext/show_url.php b/application/views/file_plaintext/show_url.php index bb94d7422..64050ddcd 100644 --- a/application/views/file_plaintext/show_url.php +++ b/application/views/file_plaintext/show_url.php @@ -1,2 +1,3 @@ -<?php echo $url; ?> +<?php +echo implode(" ", $urls)."\n"; diff --git a/application/views/file_plaintext/upload_form.php b/application/views/file_plaintext/upload_form.php index 7fe3aa801..a74e5d434 100644 --- a/application/views/file_plaintext/upload_form.php +++ b/application/views/file_plaintext/upload_form.php @@ -1,5 +1,6 @@ Uploads/pastes are deleted after <?php echo $upload_max_age; ?> days<?php if($small_upload_size > 0): ?> unless they are smaller than <?php echo format_bytes($small_upload_size); ?><?php endif; ?>. Maximum upload size is <?php echo format_bytes($max_upload_size); ?>. +You can upload a maximum of <?php echo ini_get("max_file_uploads"); ?> files at once. How to link your uploads: - "/<ID>/" automatically highlight the uploads diff --git a/data/js/script.js b/data/js/script.js index 4df973296..cb9afa66c 100644 --- a/data/js/script.js +++ b/data/js/script.js @@ -74,17 +74,25 @@ function fixedEncodeURIComponent (str) { // check file size before uploading if browser support html5 if (window.File && window.FileList) { function checkFileUpload(evt) { - var f = evt.target.files[0]; - if (f.size > max_upload_size) { - document.getElementById('upload_button').innerHTML = "File too big"; - document.getElementById('upload_button').disabled = true; - } else { - document.getElementById('upload_button').innerHTML = "Upload it!"; - document.getElementById('upload_button').disabled = false; - } + var sum = 0; + var files = evt.target.files; + + // TODO: check all forms, not only the one we are called from + for (var i = 0; i < files.length; i++) { + var f = evt.target.files[i]; + sum += f.size; + } + + if (sum > max_upload_size) { + document.getElementById('upload_button').innerHTML = "File(s) too big"; + document.getElementById('upload_button').disabled = true; + } else { + document.getElementById('upload_button').innerHTML = "Upload it!"; + document.getElementById('upload_button').disabled = false; + } } - $('#file').bind('change', checkFileUpload); + $('.file-upload').bind('change', checkFileUpload); } }); |