diff --git a/apps/files/ajax/delete.php b/apps/files/ajax/delete.php index 6532b76df2..293543c547 100644 --- a/apps/files/ajax/delete.php +++ b/apps/files/ajax/delete.php @@ -21,8 +21,20 @@ foreach($files as $file) { } } +// updated max file size after upload +$l=new OC_L10N('files'); +$maxUploadFilesize=OCP\Util::maxUploadFilesize($dir); +$maxHumanFilesize=OCP\Util::humanFileSize($maxUploadFilesize); +$maxHumanFilesize=$l->t('Upload') . ' max. '.$maxHumanFilesize; + if($success) { - OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $files ))); + OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $files, + 'uploadMaxFilesize'=>$maxUploadFilesize, + 'maxHumanFilesize'=>$maxHumanFilesize + ))); } else { - OCP\JSON::error(array("data" => array( "message" => "Could not delete:\n" . $filesWithError ))); + OCP\JSON::error(array("data" => array( "message" => "Could not delete:\n" . $filesWithError, + 'uploadMaxFilesize'=>$maxUploadFilesize, + 'maxHumanFilesize'=>$maxHumanFilesize + ))); } diff --git a/apps/files/ajax/getstoragestats.php b/apps/files/ajax/getstoragestats.php new file mode 100644 index 0000000000..e55e346ed6 --- /dev/null +++ b/apps/files/ajax/getstoragestats.php @@ -0,0 +1,16 @@ +t('Upload') . ' max. ' . $maxHumanFilesize; + +// send back json +OCP\JSON::success(array('data' => array('uploadMaxFilesize' => $maxUploadFilesize, + 'maxHumanFilesize' => $maxHumanFilesize +))); diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index 2a2d935da6..9339801960 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -10,8 +10,17 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::callCheck(); $l=OC_L10N::get('files'); +// current max upload size +$l=new OC_L10N('files'); +$maxUploadFilesize=OCP\Util::maxUploadFilesize($dir); +$maxHumanFilesize=OCP\Util::humanFileSize($maxUploadFilesize); +$maxHumanFilesize=$l->t('Upload') . ' max. '.$maxHumanFilesize; + if (!isset($_FILES['files'])) { - OCP\JSON::error(array('data' => array( 'message' => $l->t( 'No file was uploaded. Unknown error' )))); + OCP\JSON::error(array('data' => array( 'message' => $l->t( 'No file was uploaded. Unknown error' ), + 'uploadMaxFilesize'=>$maxUploadFilesize, + 'maxHumanFilesize'=>$maxHumanFilesize + ))); exit(); } @@ -28,7 +37,10 @@ foreach ($_FILES['files']['error'] as $error) { UPLOAD_ERR_NO_TMP_DIR=>$l->t('Missing a temporary folder'), UPLOAD_ERR_CANT_WRITE=>$l->t('Failed to write to disk'), ); - OCP\JSON::error(array('data' => array( 'message' => $errors[$error] ))); + OCP\JSON::error(array('data' => array( 'message' => $errors[$error], + 'uploadMaxFilesize'=>$maxUploadFilesize, + 'maxHumanFilesize'=>$maxHumanFilesize + ))); exit(); } } @@ -42,7 +54,9 @@ foreach($files['size'] as $size) { $totalSize+=$size; } if($totalSize>OC_Filesystem::free_space($dir)) { - OCP\JSON::error(array('data' => array( 'message' => $l->t( 'Not enough space available' )))); + OCP\JSON::error(array('data' => array( 'message' => $l->t( 'Not enough space available' ), + 'uploadMaxFilesize'=>$maxUploadFilesize, + 'maxHumanFilesize'=>$maxHumanFilesize))); exit(); } @@ -56,11 +70,19 @@ if(strpos($dir, '..') === false) { if(is_uploaded_file($files['tmp_name'][$i]) and OC_Filesystem::fromTmpFile($files['tmp_name'][$i], $target)) { $meta = OC_FileCache::get($target); $id = OC_FileCache::getId($target); + // updated max file size after upload + $maxUploadFilesize=OCP\Util::maxUploadFilesize($dir); + $maxHumanFilesize=OCP\Util::humanFileSize($maxUploadFilesize); + $maxHumanFilesize=$l->t('Upload') . ' max. '.$maxHumanFilesize; + $result[]=array( 'status' => 'success', 'mime'=>$meta['mimetype'], 'size'=>$meta['size'], 'id'=>$id, - 'name'=>basename($target)); + 'name'=>basename($target), + 'uploadMaxFilesize'=>$maxUploadFilesize, + 'maxHumanFilesize'=>$maxHumanFilesize + ); } } OCP\JSON::encodedPrint($result); @@ -69,4 +91,7 @@ if(strpos($dir, '..') === false) { $error=$l->t( 'Invalid directory.' ); } -OCP\JSON::error(array('data' => array('message' => $error ))); +OCP\JSON::error(array('data' => array('message' => $error, + 'uploadMaxFilesize'=>$maxUploadFilesize, + 'maxHumanFilesize'=>$maxHumanFilesize +))); diff --git a/apps/files/index.php b/apps/files/index.php index 08193eaee7..1c4b7fbd49 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -28,6 +28,7 @@ OCP\User::checkLoggedIn(); OCP\Util::addStyle('files', 'files'); OCP\Util::addscript('files', 'jquery.iframe-transport'); OCP\Util::addscript('files', 'jquery.fileupload'); +OCP\Util::addscript('files', 'jquery-visibility'); OCP\Util::addscript('files', 'files'); OCP\Util::addscript('files', 'filelist'); OCP\Util::addscript('files', 'fileactions'); @@ -79,13 +80,7 @@ $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); $breadcrumbNav->assign('breadcrumb', $breadcrumb, false); $breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files', 'index.php') . '?dir=', false); -$upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize')); -$post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size')); -$maxUploadFilesize = min($upload_max_filesize, $post_max_size); - -$freeSpace = OC_Filesystem::free_space($dir); -$freeSpace = max($freeSpace, 0); -$maxUploadFilesize = min($maxUploadFilesize, $freeSpace); +$maxUploadFilesize=OCP\Util::maxUploadFilesize($dir); $permissions = OCP\PERMISSION_READ; if (OC_Filesystem::isUpdatable($dir . '/')) { diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 3a4af6416e..0488062dbc 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -26,6 +26,23 @@ Files={ }); procesSelection(); }, + updateMaxUploadFilesize:function(response) { + if(response == undefined) { + return; + } + if(response.data !== undefined && response.data.uploadMaxFilesize !== undefined) { + $('#max_upload').val(response.data.uploadMaxFilesize); + $('#data-upload-form a').attr('original-title', response.data.maxHumanFilesize); + } + if(response[0] == undefined) { + return; + } + if(response[0].uploadMaxFilesize !== undefined) { + $('#max_upload').val(response[0].uploadMaxFilesize); + $('#data-upload-form a').attr('original-title', response[0].maxHumanFilesize); + } + + }, isFileNameValid:function (name) { if (name === '.') { $('#notification').text(t('files', '\'.\' is an invalid file name.')); @@ -317,6 +334,7 @@ $(document).ready(function() { $('#notification').text(t('files', response.data.message)); $('#notification').fadeIn(); } + Files.updateMaxUploadFilesize(response); var file=response[0]; // TODO: this doesn't work if the file name has been changed server side delete uploadingFiles[dirName][file.name]; @@ -369,6 +387,8 @@ $(document).ready(function() { .success(function(result, textStatus, jqXHR) { var response; response=jQuery.parseJSON(result); + Files.updateMaxUploadFilesize(response); + if(response[0] != undefined && response[0].status == 'success') { var file=response[0]; delete uploadingFiles[file.name]; @@ -402,6 +422,7 @@ $(document).ready(function() { data.submit().success(function(data, status) { // in safari data is a string response = jQuery.parseJSON(typeof data === 'string' ? data : data[0].body.innerText); + Files.updateMaxUploadFilesize(response); if(response[0] != undefined && response[0].status == 'success') { var file=response[0]; delete uploadingFiles[file.name]; @@ -712,6 +733,32 @@ $(document).ready(function() { }); resizeBreadcrumbs(true); + + // file space size sync + function update_storage_statistics() { + $.getJSON(OC.filePath('files','ajax','getstoragestats.php'),function(response) { + Files.updateMaxUploadFilesize(response); + }); + } + + // start on load - we ask the server every 5 minutes + var update_storage_statistics_interval = 5*60*1000; + var update_storage_statistics_interval_id = setInterval(update_storage_statistics, update_storage_statistics_interval); + + // Use jquery-visibility to de-/re-activate file stats sync + if ($.support.pageVisibility) { + $(document).on({ + 'show.visibility': function() { + if (!update_storage_statistics_interval_id) { + update_storage_statistics_interval_id = setInterval(update_storage_statistics, update_storage_statistics_interval); + } + }, + 'hide.visibility': function() { + clearInterval(update_storage_statistics_interval_id); + update_storage_statistics_interval_id = 0; + } + }); + } }); function scanFiles(force,dir){ @@ -741,6 +788,7 @@ scanFiles.scanning=false; function boolOperationFinished(data, callback) { result = jQuery.parseJSON(data.responseText); + Files.updateMaxUploadFilesize(result); if(result.status == 'success'){ callback.call(); } else { diff --git a/apps/files/js/jquery-visibility.js b/apps/files/js/jquery-visibility.js new file mode 100644 index 0000000000..a824bf6873 --- /dev/null +++ b/apps/files/js/jquery-visibility.js @@ -0,0 +1,32 @@ +/*! http://mths.be/visibility v1.0.5 by @mathias */ +(function (window, document, $, undefined) { + + var prefix, + property, +// In Opera, `'onfocusin' in document == true`, hence the extra `hasFocus` check to detect IE-like behavior + eventName = 'onfocusin' in document && 'hasFocus' in document ? 'focusin focusout' : 'focus blur', + prefixes = ['', 'moz', 'ms', 'o', 'webkit'], + $support = $.support, + $event = $.event; + + while ((property = prefix = prefixes.pop()) != undefined) { + property = (prefix ? prefix + 'H' : 'h') + 'idden'; + if ($support.pageVisibility = typeof document[property] == 'boolean') { + eventName = prefix + 'visibilitychange'; + break; + } + } + + $(/blur$/.test(eventName) ? window : document).on(eventName, function (event) { + var type = event.type, + originalEvent = event.originalEvent, + toElement = originalEvent.toElement; +// If it’s a `{focusin,focusout}` event (IE), `fromElement` and `toElement` should both be `null` or `undefined`; +// else, the page visibility hasn’t changed, but the user just clicked somewhere in the doc. +// In IE9, we need to check the `relatedTarget` property instead. + if (!/^focus./.test(type) || (toElement == undefined && originalEvent.fromElement == undefined && originalEvent.relatedTarget == undefined)) { + $event.trigger((property && document[property] || /^(?:blur|focusout)$/.test(type) ? 'hide' : 'show') + '.visibility'); + } + }); + +}(this, document, jQuery)); diff --git a/lib/helper.php b/lib/helper.php index 5d7e3fa489..7be54cacbe 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -679,8 +679,8 @@ class OC_Helper { $start = intval($start); $length = intval($length); $string = mb_substr($string, 0, $start, $encoding) . - $replacement . - mb_substr($string, $start+$length, mb_strlen($string, 'UTF-8')-$start, $encoding); + $replacement . + mb_substr($string, $start+$length, mb_strlen($string, 'UTF-8')-$start, $encoding); return $string; } @@ -748,6 +748,23 @@ class OC_Helper { return $str; } + /** + * @brief calculates the maximum upload size respecting system settings, free space and user quota + * + * @param $dir the current folder where the user currently operates + * @return number of bytes representing + */ + public static function maxUploadFilesize($dir) { + $upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize')); + $post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size')); + $maxUploadFilesize = min($upload_max_filesize, $post_max_size); + + $freeSpace = OC_Filesystem::free_space($dir); + $freeSpace = max($freeSpace, 0); + + return min($maxUploadFilesize, $freeSpace); + } + /** * Checks if a function is available * @param string $function_name diff --git a/lib/public/util.php b/lib/public/util.php index 8197482c0d..413dbcccd2 100644 --- a/lib/public/util.php +++ b/lib/public/util.php @@ -367,4 +367,14 @@ class Util { public static function recursiveArraySearch($haystack, $needle, $index = null) { return(\OC_Helper::recursiveArraySearch($haystack, $needle, $index)); } + + /** + * @brief calculates the maximum upload size respecting system settings, free space and user quota + * + * @param $dir the current folder where the user currently operates + * @return number of bytes representing + */ + public static function maxUploadFilesize($dir) { + return \OC_Helper::maxUploadFilesize($dir); + } }