Index: branches/RC/core/admin_templates/js/uploader/upload_manager.js =================================================================== diff -u -N --- branches/RC/core/admin_templates/js/uploader/upload_manager.js (revision 0) +++ branches/RC/core/admin_templates/js/uploader/upload_manager.js (revision 10621) @@ -0,0 +1,367 @@ +function UploadsManager() { + // hooking to standard toolbar select button to peform auto-upload when Save is clicked + if (isset(a_toolbar)) { + if (a_toolbar.ButtonExists('select')) { + var old_onclick = a_toolbar.Buttons['select'].onClick; + a_toolbar.Buttons['select'].onClick = function() { + UploadsManager.UploadAll(function() {old_onclick()}); + } + } + } + + addLoadEvent( + function() { + UploadsManager._initAll(); + } + ); +} + +UploadsManager = new UploadsManager(); + +UploadsManager._nextId = 0; +UploadsManager._debugMode = false; +UploadsManager.formContainerId = ''; +UploadsManager._Uploaders = new Object(); + +/* ==== Private methods ==== */ +UploadsManager._nextFlashId = function() { + this._nextId++; + return 'uploaderflash' + this._nextId; +} + +UploadsManager._getFromContainer = function() { + if (UploadsManager.formContainerId) { + return document.getElementById(UploadsManager.formContainerId); + } + + return Form.Div; +} + +UploadsManager._initAll = function() { + for (var i in this._Uploaders) { + this._Uploaders[i].init(); + } +} + +UploadsManager._hasQueue = function() { + var has_queue = false; + + for (var i in this._Uploaders) { + var tmp = this._Uploaders[i].hasQueue(); + has_queue = has_queue || tmp; + } + + return has_queue; +} + +UploadsManager._getUploader = function (file) { + var $flash_id = file.id.match(/(.*)_[\d]+/) ? RegExp.$1 : file.id; + + for (var $uploader_index in this._Uploaders) { + if (this._Uploaders[$uploader_index].flash_id == $flash_id) { + return this._Uploaders[$uploader_index]; + } + } + + return null; +} + +/* ==== Public methods ==== */ +UploadsManager.AddUploader = function(id, params) { + this._Uploaders[id] = new Uploader(id, params); +} + +UploadsManager.DeleteFile = function(uploader_id, fname, confirmed) { + if (!confirmed && !confirm('Are you sure you want to delete this file?')) { + return; + } + + var $uploader = this._Uploaders[uploader_id]; + + Request.makeRequest( + $uploader.deleteURL.replace('#FILE#', fname).replace('#FIELD#', $uploader.params.field), + false, '', + function(req, fname, $uploader) { + $uploader.removeFile({id:fname}) + $uploader.deleted.push(fname); + $uploader.updateInfo(); + }, + + function(req, fname, $uploader) { + alert('Error while deleting file'); + }, + fname, $uploader + ); +} + +UploadsManager.Browse = function(id) { + if (parseInt(this._Uploaders[id].params.multiple) > 1) { + this._Uploaders[id].flash.SelectFiles(); + } else { + this._Uploaders[id].flash.SelectFile(); + } +} + +UploadsManager.StartUpload = function(id) { + this.uploadCancelled = false; + this._Uploaders[id].startUpload(); +} + +UploadsManager.CancelFile = function(id, file_id) { + this._Uploaders[id].flash.CancelUpload(file_id); +} + +UploadsManager.UploadAll = function(onAllUploaded) { + if (!this._hasQueue()) { + onAllUploaded(); + return ; + } + + this.uploadCancelled = false; + for (var i in this._Uploaders) { + // could raise problems, when simultanious uploads from diffrent uploaders are made + this._Uploaders[i].startUpload(); + } + + this.OnAllUploaded = onAllUploaded; +} + +UploadsManager.UploadQueueComplete = function() { + Request.setOpacity(100, UploadsManager._getFromContainer()); + var all_done = true; + for (var i in this._Uploaders) { + this._Uploaders[i].div.style.display = 'none'; + all_done == all_done && !this._Uploaders[i].hasQueue(); + } + if (all_done && isset(this.OnAllUploaded) && !this.uploadCancelled) { + this.OnAllUploaded(); + } +} + +UploadsManager.CancelUpload = function(id) { + var $flash = this._Uploaders[id].flash; + + $flash.StopUpload(); + + var $stats = $flash.GetStats(); + while ($stats.files_queued > 0) { + $flash.CancelUpload(); + $stats = $flash.GetStats(); + } + + this.uploadCancelled = true; +} + +UploadsManager.setDebugMode = function ($enabled) { + /*for (var $uploader_index in this._Uploaders) { + this._Uploaders[$uploader_index].flash.SetDebugEnabled($enabled); + }*/ + + this._debugMode = $enabled; +} + + +/* ==== Flash event handlers ==== */ +UploadsManager.onHandleEverything = function () { + if (UploadsManager._debugMode) { + console.log('default swf handler'); + } +} + +UploadsManager.onUploadStart = function(file) { + var $uploader = UploadsManager._getUploader(file); + + $uploader.queueEvent( + function() { + this.UploadFileStart(file); + } + ); +} + +UploadsManager.onUploadProgress = function(file, bytesLoaded, bytesTotal) { + var $uploader = UploadsManager._getUploader(file); + + $uploader.queueEvent( + function() { + this.UploadProgress(file, bytesLoaded, bytesTotal); + } + ); +} + +UploadsManager.onUploadComplete = function(file) { + var $uploader = UploadsManager._getUploader(file); + + $uploader.queueEvent( + function() { + this.UploadFileComplete(file); + } + ); +} + +UploadsManager.onFileQueued = function(file) { + var $uploader = UploadsManager._getUploader(file); + + $uploader.queueEvent( + function() { + this.flash.AddFileParam(file.id, 'field', this.params.field); + this.flash.AddFileParam(file.id, 'id', file.id); + this.flash.AddFileParam(file.id, 'flashsid', this.params.flashsid); + + if (this.files_count >= this.params.multiple) { + // new file can exceed allowed file number + if (this.params.multiple > 1) { + // it definetly exceed it + UploadsManager.onFileQueueError(file, -100, this.params.multiple); + this.flash.CancelUpload(file.id); + } + else { + // delete file added + this.files_count++; + this.files.push(file); + this.total += file.size; + if (this.files[0].uploaded) { + UploadsManager.DeleteFile(UploadsManager._getUploader(file).id, this.files[0].name, true); + } + else { + this.flash.CancelUpload(this.files[0].id); + } + } + } + else { + // new file will not exceed allowed file number + this.files_count++; + this.files.push(file); + this.total += file.size; + } + this.updateInfo(); + } + ) +} + +UploadsManager.onUploadError = function(file, errorCode, message) { + var $uploader = UploadsManager._getUploader(file); + + $uploader.queueEvent( + function() { + this.removeFile(file); + + switch (errorCode) { + case -200: + // HTTP Error + message = parseInt(message); // HTTP Error Code + switch (message) { + case 403: + message = "You don't have permission to upload"; + break; + case 500: + message = 'Write permissions not set on the server, please contact server administrator'; + break; + } + + if (isNaN(message)) { + // message is processed + alert('Error: ' + message + "\n" + 'Occured on file ' + file.name); + return ; + } + break; + + case -280: + // File Cancelled + return ; + break; + + case -290: + // Upload Stopped + UploadsManager.UploadQueueComplete(); + return ; + break; + } + + // all not processed error messages go here + alert('Error [' + errorCode + ']: ' + message + "\n" + 'Occured on file ' + file.name); + } + ); +} + +UploadsManager.onFileQueueError = function(file, errorCode, message) { + switch (errorCode) { + case -100: + // maximal allowed file count reached + alert('Error: Files count exceeds allowed limit' + "\n" + 'Occured on file ' + file.name); + return ; + break; + + case -110: + // maximal allowed filesize reached + alert('Error: File size exceeds allowed limit' + "\n" + 'Occured on file ' + file.name); + return ; + break; + + case -130: + // maximal allowed filesize reached + alert('Error: File is not an allowed file type.' + "\n" + 'Occured on file ' + file.name); + return ; + break; + } + + // all not processed error messages go here + alert('Error [' + errorCode + ']: ' + message + "\n" + 'Occured on file ' + file.name); +} + +UploadsManager.onDebug = function (message) { + if (!UploadsManager._debugMode) { + return ; + } + + var exceptionMessage, exceptionValues = []; + + // Check for an exception object and print it nicely + if (typeof(message) === 'object' && typeof(message.name) === 'string' && typeof(message.message) === 'string') { + for (var key in message) { + if (message.hasOwnProperty(key)) { + exceptionValues.push(key + ': ' + message[key]); + } + } + exceptionMessage = exceptionValues.join("\n") || ''; + exceptionValues = exceptionMessage.split("\n"); + exceptionMessage = 'EXCEPTION: ' + exceptionValues.join("\nEXCEPTION: "); + + console.log(exceptionMessage); + } else { + console.log(message); + } +}; + +if (!window.console || !console.firebug) { + // emulate FireBug Console in other browsers to see flash debug messages + window.console = {}; + window.console.log = function (message) { + var console, documentForm; + + try { + console = document.getElementById('SWFUpload_Console'); + + if (!console) { + documentForm = document.createElement('form'); + document.getElementsByTagName('body')[0].appendChild(documentForm); + + console = document.createElement('textarea'); + console.id = 'SWFUpload_Console'; + console.style.fontFamily = 'monospace'; + console.setAttribute('wrap', 'off'); + console.wrap = 'off'; + console.style.overflow = 'auto'; + console.style.width = '700px'; + console.style.height = '350px'; + console.style.margin = '5px'; + documentForm.appendChild(console); + } + + console.value += message + "\n"; + + console.scrollTop = console.scrollHeight - console.clientHeight; + } catch (ex) { + alert('Exception: ' + ex.name + ' Message: ' + ex.message); + } + }; +} \ No newline at end of file Index: branches/RC/core/admin_templates/js/uploader.js =================================================================== diff -u -N -r9337 -r10621 --- branches/RC/core/admin_templates/js/uploader.js (.../uploader.js) (revision 9337) +++ branches/RC/core/admin_templates/js/uploader.js (.../uploader.js) (revision 10621) @@ -1,451 +1,6 @@ -function Uploader(id, params) -{ - this.id = id; - if (params.multiple.length == 0) params.multiple = 1; - this.params = params; - this.files_count = 0; - this.files = new Array(); - this.deleted = new Array() +var $uploader_scripts = [ + '', + '' +]; - this.uploadURL = params.uploadURL; - this.deleteURL = params.deleteURL; -} - -Uploader.prototype.Init = function() -{ - var holder = document.createElement('DIV'); - document.body.appendChild(holder); - - document.getElementById($form_name).style.display = 'block'; - - // moving out progress div to overcome loosing of flash object after setting opacity - this.div = document.getElementById(this.id+'_progress'); - var clone = this.div.cloneNode(true); - this.div.parentNode.removeChild(this.div) - this.div = document.body.appendChild(clone); - this.IconPath = this.params.IconPath ? this.params.IconPath : '../cmseditor/editor/images'; - - this.filename = document.getElementById(this.id+'_progress_filename'); - this.progress = document.getElementById(this.id+'_progress_progress'); - this.elapsed = document.getElementById(this.id+'_progress_elapsed'); - this.remaining = document.getElementById(this.id+'_progress_remaining'); - this.percent = document.getElementById(this.id+'_percent'); - this.done = document.getElementById(this.id+'_done'); - this.total = 0; - this.uploaded = 0; - - this.flash_id = UploadsManager.NextFlashId(); - this.swf = new SWFObject('swfupload.swf', this.flash_id, "0", "0", "8", "#000000"); - this.swf.setAttribute('style', ''); - this.swf.addVariable("uploadScript", ''); - this.swf.addVariable("maxFiles", escape(this.params.multiple)); - this.swf.addVariable("allowedFilesize", escape(this.params.allowedFilesize)); - this.swf.addVariable("allowedFiletypes", escape(this.params.allowedFiletypes)); - this.swf.addVariable("allowedFiletypesDescription", escape(this.params.allowedFiletypesDescription)); - - this.swf.addVariable("uploadFileQueuedCallback", escape('UploadsManager.FileSelected')); - this.swf.addVariable("uploadFileStartCallback", escape('UploadsManager.UploadFileStart')); - this.swf.addVariable("uploadProgressCallback", escape('UploadsManager.UploadProgress')); - this.swf.addVariable("uploadFileCompleteCallback", escape('UploadsManager.UploadFileComplete')); - this.swf.addVariable("uploadFileCancelCallback", escape('UploadsManager.FileCancelled')); - this.swf.addVariable("uploadQueueCompleteCallback", escape('UploadsManager.UploadQueueComplete')); - this.swf.addVariable("uploadFileErrorCallback", escape('UploadsManager.UploadError')); - this.swf.addVariable("autoUpload", escape('false')); -// this.swf.addVariable("flashLoadedCallback", 'flashLoadedCallback'); - - this.swf.addVariable("uploadScriptCallback", escape('UploadsManager.GetUploadScript')); - this.swf.addVariable("uploaderId", escape(this.id)); - this.swf.write(holder); - - this.flash = document.getElementById(this.flash_id); -/* if (this.flash != null) { - if(this.flash.PercentLoaded() == 100) { - alert('done movie: '+this.flash.PercentLoaded()); - } - } - else { - alert('this.flash is null') - }*/ - if (this.params.urls != '') { - var urls = this.params.urls.split('|'); - var names = this.params.names.split('|'); - var sizes = this.params.sizes.split('|'); - for (var i in urls) { - var a_file = { - id : names[i], - name : names[i], - url : urls[i], - size: sizes[i], - uploaded : 1 - } - this.files.push(a_file) - this.files_count++; - } - this.UpdateInfo(); - } -} - -Uploader.prototype.UpdateInfo = function() -{ - var o = ''; - for (var f in this.files) { - this.files[f].name.match(/\.([^.]*)$/); - var ext = RegExp.$1; - var icon = ext.match(/^(ai|avi|bmp|cs|dll|doc|dot|exe|fla|gif|htm|html|jpg|js|mdb|mp3|pdf|ppt|rdp|swf|swt|txt|vsd|xls|xml|zip)$/) ? ext : 'default.icon'; - o += ' '; - if (isset(this.files[f].uploaded)) { - o += ''+this.files[f].name + ' ('+this.FormatSize(this.files[f].size)+') [Delete]
'; - } - else { - o += this.files[f].name + ' ('+this.FormatSize(this.files[f].size)+') [Delete]
'; - } - } - document.getElementById(this.id+'_queueinfo').innerHTML = o; - this.PrepareFiles() -} - -Uploader.prototype.RemoveFile = function(file) -{ - var n_files = new Array(); - var count=0; - this.total=0; - for (var f in this.files) { - if (this.files[f].id != file.id && this.files[f].name != file.id ) { - n_files.push(this.files[f]); - if (!isset(this.files[f].uploaded)) { - this.total += file.size - } - count++; - } - } - this.files = n_files; - this.files_count = count; - this.UpdateInfo(); -} - -Uploader.prototype.GetUploadScript = function(file) -{ -// document.getElementById(this.id+'[my_tmp]').value = file.id; - return this.uploadURL.replace('#ID#', file.id).replace('#FIELD#', this.params.field).replace('#SID#', this.params.flashsid); -} - -Uploader.prototype.PrepareFiles = function() -{ - var ids = ''; - var names = ''; - for (var f in this.files) { - if (isset(this.files[f].uploaded) && !isset(this.files[f].temp)) continue; - ids += this.files[f].id + '|' - names += this.files[f].name + '|' - } - ids = ids.replace(/\|$/, '', ids); - names = names.replace(/\|$/, '', names); - document.getElementById(this.id+'[tmp_ids]').value = ids; - document.getElementById(this.id+'[tmp_names]').value = names; - document.getElementById(this.id+'[tmp_deleted]').value = this.deleted.join('|'); -} - - -Uploader.prototype.HasQueue = function() -{ - for (var f in this.files) { - if (isset(this.files[f].uploaded)) continue; - return true; - } - return false; -} - -Uploader.prototype.StartUpload = function() -{ - if (!this.HasQueue()) return; - - Request.setOpacity(30, UploadsManager.getFromContainer()); - - if (!document.all) { - var $winW = window.innerWidth; - var $winH = window.innerHeight; - } - else { - var $winW = window.document.body.offsetWidth; - var $winH = window.document.body.offsetHeight; - } - - var left = Math.round(($winW - 350)/2)+'px'; - var top = Math.round(($winH - 110)/2)+'px'; - - this.div.style.top = top; - this.div.style.left = left; - this.div.style.display = 'block'; - Request.setOpacity(100, this.div); - - this.StartTime = this.GetMicroTime(); - this.ProgressPercent = 0; // progress percent - this.ProgressTime = new Array(); - - this.uploaded = 0; - this.total = 0; - for (var f in this.files) { - if (isset(this.files[f].uploaded)) continue; - this.total += this.files[f].size; - } - - document.getElementById(this.flash_id).upload(); -} - -Uploader.prototype.GetMicroTime = function() { - var $now = new Date(); - return Math.round($now.getTime() / 1000); // because miliseconds are returned too -} -Uploader.prototype.GetEstimatedTime = function() { - return Math.ceil((100 - this.ProgressPercent) * this.ProgressTime / this.ProgressPercent); -} - -Uploader.prototype.FormatTime = function ($seconds) { - $seconds = parseInt($seconds); - - var $minutes = Math.floor($seconds / 60); - if ($minutes < 10) $minutes = '0' + $minutes; - $seconds = $seconds % 60; - if ($seconds < 10) $seconds = '0' + $seconds; - - return $minutes + ':' + $seconds; -} - -Uploader.prototype.FormatSize = function (bytes) { - var kb = Math.round(bytes / 1024); - if (kb < 1024) return kb+'Kb'; - var mb = Math.round(kb / 1024 * 100)/100; - return mb+'Mb'; -} - -Uploader.prototype.UploadFileStart = function(file, position, queuelength) -{ - this.filename.innerHTML = file.name; -} - -Uploader.prototype.UploadProgress = function(file, bytesLoaded) -{ - this.cur_file_uploaded = bytesLoaded; - var uploaded = this.uploaded+this.cur_file_uploaded; - this.ProgressTime = this.GetMicroTime() - this.StartTime; - - var speed = 0; - if (this.ProgressTime > 0) { - speed = Math.round(uploaded/this.ProgressTime*100)/100; - } - - this.progress.innerHTML = this.FormatSize(uploaded)+' / '+this.FormatSize(this.total) + ' ('+this.FormatSize(speed)+'/s)'; - this.ProgressPercent = Math.round(uploaded/this.total*100); - this.done.style.width = this.ProgressPercent+'%'; - this.percent.innerHTML = this.ProgressPercent+'%'; - - this.elapsed.innerHTML = this.FormatTime(this.ProgressTime ); - this.remaining.innerHTML = this.FormatTime( this.GetEstimatedTime() ); -} - -Uploader.prototype.UploadFileComplete = function(file) -{ - this.uploaded += this.cur_file_uploaded; - for (var f in this.files) { - if (this.files[f].id == file.id) { - this.files[f].uploaded = 1; - this.files[f].temp = 1; - this.files[f].url = this.params.tmp_url.replace('#ID#', file.id).replace('#FILE#', file.name).replace('#FIELD#', this.params.field); - } - } - this.UpdateInfo(); -} - - -// MANAGER - - -function UploadsManager() { - // hooking to standard toolbar select button to peform auto-upload when Save is clicked - if (isset(a_toolbar)) { - if (a_toolbar.ButtonExists('select')) { - var old_onclick = a_toolbar.Buttons['select'].onClick; - a_toolbar.Buttons['select'].onClick = function() { - UploadsManager.UploadAll(function() {old_onclick()}); - } - } - } - addLoadEvent(function() {UploadsManager.InitAll()}); -} - -UploadsManager = new UploadsManager(); -UploadsManager.Uploaders = new Object(); -UploadsManager.nextId = 0; -UploadsManager.formContainerId = ''; - -UploadsManager.NextFlashId = function() -{ - this.nextId++; - return 'uploaderflash'+this.nextId; -} - -UploadsManager.AddUploader = function(id, params ) -{ - this.Uploaders[id] = new Uploader(id, params); -} - -UploadsManager.getFromContainer = function() -{ - if (UploadsManager.formContainerId) { - return document.getElementById(UploadsManager.formContainerId); - } - - return Form.Div; -} - -UploadsManager.InitAll = function() -{ - for (var i in this.Uploaders) { - this.Uploaders[i].Init(); - } -} - -UploadsManager.FileSelected = function(file) -{ - var upl = this.Uploaders[file.uploader_id] - if (upl.files_count >= upl.params.multiple) { - if (upl.params.multiple > 1) { - alert('too many files'); - upl.flash.cancelFile(file.id); - } - else { - upl.files_count++; - upl.files.push(file); - upl.total += file.size; - if (upl.files[0].uploaded) { - UploadsManager.DeleteFile(file.uploader_id, upl.files[0].name, true); - } - else { - upl.flash.cancelFile(upl.files[0].id); - } - } - } - else { - upl.files_count++; - upl.files.push(file); - upl.total += file.size; - } - upl.UpdateInfo(); -} - -UploadsManager.FileCancelled = function(file) -{ - this.Uploaders[file.uploader_id].RemoveFile(file); -} - -UploadsManager.GetUploadScript = function(file) -{ - return this.Uploaders[file.uploader_id].GetUploadScript(file); -} - -UploadsManager.UploadError = function(errno, file, msg) -{ - this.Uploaders[file.uploader_id].RemoveFile(file); - - if (errno == -10) { - switch (msg.toString()) { - case '403': - msg = 'You don\'t have permission to upload'; - break; - case '500': - msg = 'Write permissions not set on the server, please contact server administrator'; - break; - } - } - alert('Error: '+msg+'\nOccured on file '+file.name); -} - -UploadsManager.DeleteFile = function(mov, fname, confirmed) -{ - if (!confirmed && !confirm('Are you sure you want to delete this file?')) return; - Request.makeRequest( - this.Uploaders[mov].deleteURL.replace('#FILE#', fname).replace('#FIELD#', this.Uploaders[mov].params.field), - false, '', - function(req, fname, upl) { - upl.RemoveFile({id:fname}) - upl.deleted.push(fname); - upl.UpdateInfo(); - }, - function(req, fname, upl) {alert('Error while deleting file')}, - fname, this.Uploaders[mov] - ); -} - - -UploadsManager.Browse = function(id) -{ - this.Uploaders[id].flash.browse() -} - -UploadsManager.StartUpload = function(id) -{ - this.uploadCancelled = false; - this.Uploaders[id].StartUpload(); -} - -UploadsManager.CancelFile = function(id, file_id) -{ - this.Uploaders[id].flash.cancelFile(file_id) -} - -UploadsManager.UploadAll = function(onAllUploaded) -{ - if (!this.HasQueue()) { - onAllUploaded(); - return; - } - this.uploadCancelled = false; - for (var i in this.Uploaders) { - this.Uploaders[i].StartUpload(); - } - this.OnAllUploaded = onAllUploaded; -} - -UploadsManager.UploadFileStart = function(file, position, queuelength) -{ - this.Uploaders[file.uploader_id].UploadFileStart(file, position, queuelength); -} - -UploadsManager.UploadProgress = function(file, bytesLoaded) -{ - this.Uploaders[file.uploader_id].UploadProgress(file, bytesLoaded); -} - -UploadsManager.UploadFileComplete = function(file) -{ - this.Uploaders[file.uploader_id].UploadFileComplete(file); -} - -UploadsManager.HasQueue = function() -{ - var has_queue = false; - for (var i in this.Uploaders) { - var tmp = this.Uploaders[i].HasQueue() - has_queue = has_queue || tmp; - } - return has_queue; -} - -UploadsManager.UploadQueueComplete = function(file) -{ - Request.setOpacity(100, UploadsManager.getFromContainer()); - var all_done = true; - for (var i in this.Uploaders) { - this.Uploaders[i].div.style.display='none'; - all_done == all_done && !this.Uploaders[i].HasQueue(); - } - if (all_done && isset(this.OnAllUploaded) && !this.uploadCancelled) { - this.OnAllUploaded(); - } -} - -UploadsManager.CancelUpload = function(id) -{ - this.Uploaders[id].flash.cancelQueue(); - this.uploadCancelled = true; -} \ No newline at end of file +document.write($uploader_scripts.join('')); \ No newline at end of file Index: branches/RC/core/admin_templates/js/uploader/uploader.js =================================================================== diff -u -N --- branches/RC/core/admin_templates/js/uploader/uploader.js (revision 0) +++ branches/RC/core/admin_templates/js/uploader/uploader.js (revision 10621) @@ -0,0 +1,327 @@ +// this js class name is hardcoded in flash object :( +var SWFUpload = function () {}; +SWFUpload.instances = {}; + +function Uploader(id, params) { + this.id = id; + + // normalize params + if (isNaN(parseInt(params.multiple))) { + // ensure that maximal file number is greather then zero + params.multiple = 1; + } + + params.allowedFilesize = this._normalizeFilesize(params.allowedFilesize); + + // set params to uploader + this._eventQueue = []; + + this.params = params; + this.files_count = 0; + this.files = new Array(); + this.deleted = new Array() + + this.uploadURL = params.uploadURL; + this.deleteURL = params.deleteURL; +} + +/* ==== Private methods ==== */ +Uploader.prototype._normalizeFilesize = function($file_size) { + var $normalize_size = parseInt($file_size); + if (isNaN($normalize_size)) { + return $file_size; + } + + // in kilobytes (flash doesn't recognize numbers, that are longer, then 9 digits) + return $normalize_size / 1024; +} + +Uploader.prototype._prepareFiles = function() { + var ids = ''; + var names = ''; + for (var f in this.files) { + if (isset(this.files[f].uploaded) && !isset(this.files[f].temp)) { + continue; + } + + ids += this.files[f].id + '|' + names += this.files[f].name + '|' + } + + ids = ids.replace(/\|$/, '', ids); + names = names.replace(/\|$/, '', names); + document.getElementById(this.id+'[tmp_ids]').value = ids; + document.getElementById(this.id+'[tmp_names]').value = names; + document.getElementById(this.id+'[tmp_deleted]').value = this.deleted.join('|'); +} + +Uploader.prototype._getMicroTime = function() { + var $now = new Date(); + return Math.round($now.getTime() / 1000); // because miliseconds are returned too +} + +Uploader.prototype._getEstimatedTime = function() { + return Math.ceil((100 - this.ProgressPercent) * this.ProgressTime / this.ProgressPercent); +} + +Uploader.prototype._formatTime = function ($seconds) { + $seconds = parseInt($seconds); + + var $minutes = Math.floor($seconds / 60); + if ($minutes < 10) $minutes = '0' + $minutes; + $seconds = $seconds % 60; + if ($seconds < 10) $seconds = '0' + $seconds; + + return $minutes + ':' + $seconds; +} + +Uploader.prototype._formatSize = function (bytes) { + var kb = Math.round(bytes / 1024); + if (kb < 1024) return kb+'Kb'; + var mb = Math.round(kb / 1024 * 100)/100; + return mb+'Mb'; +} + +Uploader.prototype._executeNextEvent = function () { + var f = this._eventQueue ? this._eventQueue.shift() : null; + if (typeof(f) === 'function') { + f.apply(this); + } +}; + +/* ==== Public methods ==== */ +Uploader.prototype.init = function() { + var holder = document.createElement('DIV'); + document.body.appendChild(holder); + + document.getElementById($form_name).style.display = 'block'; + + // moving out progress div to overcome loosing of flash object after setting opacity + this.div = document.getElementById(this.id+'_progress'); + var clone = this.div.cloneNode(true); + this.div.parentNode.removeChild(this.div) + this.div = document.body.appendChild(clone); + this.IconPath = this.params.IconPath ? this.params.IconPath : '../cmseditor/editor/images'; + + this.filename = document.getElementById(this.id+'_progress_filename'); + this.progress = document.getElementById(this.id+'_progress_progress'); + this.elapsed = document.getElementById(this.id+'_progress_elapsed'); + this.remaining = document.getElementById(this.id+'_progress_remaining'); + this.percent = document.getElementById(this.id+'_percent'); + this.done = document.getElementById(this.id+'_done'); + this.total = 0; + this.uploaded = 0; + + // initialize flash object + this.flash_id = UploadsManager._nextFlashId(); + + // add callbacks for every event, because none of callbacks will work in other case (see swfupload documentation) + SWFUpload.instances[this.flash_id] = this; + SWFUpload.instances[this.flash_id].flashReady = UploadsManager.onHandleEverything; + SWFUpload.instances[this.flash_id].fileDialogStart = UploadsManager.onHandleEverything; + SWFUpload.instances[this.flash_id].fileQueued = UploadsManager.onFileQueued; + SWFUpload.instances[this.flash_id].fileQueueError = UploadsManager.onFileQueueError; + SWFUpload.instances[this.flash_id].fileDialogComplete = UploadsManager.onHandleEverything; + + SWFUpload.instances[this.flash_id].uploadStart = UploadsManager.onUploadStart; + SWFUpload.instances[this.flash_id].uploadProgress = UploadsManager.onUploadProgress; + SWFUpload.instances[this.flash_id].uploadError = UploadsManager.onUploadError; + SWFUpload.instances[this.flash_id].uploadSuccess = UploadsManager.onHandleEverything; + SWFUpload.instances[this.flash_id].uploadComplete = UploadsManager.onUploadComplete; + SWFUpload.instances[this.flash_id].debug = UploadsManager.onDebug; + + this.swf = new SWFObject('swfupload.swf', this.flash_id, '0', '0', '8', '#FFFFFF'); + this.swf.setAttribute('style', ''); + + this.swf.addVariable('movieName', escape(this.flash_id)); + this.swf.addVariable('fileUploadLimit', escape(this.params.multiple)); + this.swf.addVariable('fileSizeLimit', escape(this.params.allowedFilesize)); // in kilobytes + this.swf.addVariable('fileTypes', escape(this.params.allowedFiletypes)); + this.swf.addVariable('fileTypesDescription', escape(this.params.allowedFiletypesDescription)); + this.swf.addVariable('uploadURL', escape(this.params.uploadURL)); + + if (UploadsManager._debugMode) { + this.swf.addVariable('debugEnabled', escape('true')); // flash var + } + + this.swf.write(holder); + + this.flash = document.getElementById(this.flash_id); + /*if (this.flash != null) { + if(this.flash.PercentLoaded() == 100) { + alert('done movie: '+this.flash.PercentLoaded()); + } + } + else { + alert('this.flash is null') + }*/ + + if (this.params.urls != '') { + var urls = this.params.urls.split('|'); + var names = this.params.names.split('|'); + var sizes = this.params.sizes.split('|'); + for (var i in urls) { + var a_file = { + id : names[i], + name : names[i], + url : urls[i], + size: sizes[i], + uploaded : 1 + } + this.files.push(a_file) + this.files_count++; + } + this.updateInfo(); + } +} + +Uploader.prototype.updateInfo = function() { + var o = ''; + for (var f in this.files) { + this.files[f].name.match(/\.([^.]*)$/); + var ext = RegExp.$1; + var icon = ext.match(/^(ai|avi|bmp|cs|dll|doc|dot|exe|fla|gif|htm|html|jpg|js|mdb|mp3|pdf|ppt|rdp|swf|swt|txt|vsd|xls|xml|zip)$/) ? ext : 'default.icon'; + o += ' '; + if (isset(this.files[f].uploaded)) { + o += ''+this.files[f].name + ' ('+this._formatSize(this.files[f].size)+') [Delete]
'; + } + else { + o += this.files[f].name + ' ('+this._formatSize(this.files[f].size)+') [Delete]
'; + } + } + document.getElementById(this.id+'_queueinfo').innerHTML = o; + this._prepareFiles() +} + +Uploader.prototype.removeFile = function (file) { + var n_files = new Array(); + var count = 0; + this.total = 0; + + for (var f in this.files) { + if (this.files[f].id != file.id && this.files[f].name != file.id) { + n_files.push(this.files[f]); + if (!isset(this.files[f].uploaded)) { + this.total += file.size; + } + count++; + } + } + + this.files = n_files; + this.files_count = count; + this.updateInfo(); +} + +Uploader.prototype.hasQueue = function() { + for (var f in this.files) { + if (isset(this.files[f].uploaded)) { + continue; + } + + return true; + } + + return false; +} + +Uploader.prototype.startUpload = function() { + if (!this.hasQueue()) { + return; + } + + Request.setOpacity(30, UploadsManager._getFromContainer()); + + if (!document.all) { + var $winW = window.innerWidth; + var $winH = window.innerHeight; + } + else { + var $winW = window.document.body.offsetWidth; + var $winH = window.document.body.offsetHeight; + } + + var left = Math.round(($winW - 350)/2)+'px'; + var top = Math.round(($winH - 110)/2)+'px'; + + this.div.style.top = top; + this.div.style.left = left; + this.div.style.display = 'block'; + Request.setOpacity(100, this.div); + + this.StartTime = this._getMicroTime(); + this.ProgressPercent = 0; // progress percent + this.ProgressTime = new Array(); + + this.uploaded = 0; + this.total = 0; + for (var f in this.files) { + if (isset(this.files[f].uploaded)) continue; + this.total += this.files[f].size; + } + + this.flash.StartUpload(); +} + +Uploader.prototype.UploadFileStart = function(file) { + this.filename.innerHTML = file.name; + + // we can prevent user from adding any files here :) + this.flash.ReturnUploadStart(true); +} + +Uploader.prototype.UploadProgress = function(file, bytesLoaded, bytesTotal) { + this.cur_file_uploaded = bytesLoaded; + var uploaded = this.uploaded+this.cur_file_uploaded; + this.ProgressTime = this._getMicroTime() - this.StartTime; + + var speed = 0; + if (this.ProgressTime > 0) { + speed = Math.round(uploaded/this.ProgressTime*100)/100; + } + + this.progress.innerHTML = this._formatSize(uploaded)+' / '+this._formatSize(this.total) + ' ('+this._formatSize(speed)+'/s)'; + this.ProgressPercent = Math.round(uploaded/this.total*100); + this.done.style.width = this.ProgressPercent+'%'; + this.percent.innerHTML = this.ProgressPercent+'%'; + + this.elapsed.innerHTML = this._formatTime(this.ProgressTime ); + this.remaining.innerHTML = this._formatTime( this._getEstimatedTime() ); +} + +Uploader.prototype.UploadFileComplete = function(file) { + // in use + this.uploaded += this.cur_file_uploaded; + for (var f in this.files) { + if (this.files[f].id == file.id) { + this.files[f].uploaded = 1; + this.files[f].temp = 1; + this.files[f].url = this.params.tmp_url.replace('#ID#', file.id).replace('#FILE#', file.name).replace('#FIELD#', this.params.field); + } + } + this.updateInfo(); + + // upload next file in queue + var $stats = this.flash.GetStats(); + if ($stats.files_queued > 0 && !UploadsManager.uploadCancelled) { + this.flash.StartUpload(); + } else if (!UploadsManager.uploadCancelled) { + // all files in queue are uploaded + UploadsManager.UploadQueueComplete(); + } +} + +Uploader.prototype.queueEvent = function (function_body) { + // Warning: Don't call this.debug inside here or you'll create an infinite loop + var self = this; + + // Queue the event + this._eventQueue.push(function_body); + + // Execute the next queued event + setTimeout( + function () { + self._executeNextEvent(); + }, 0 + ); +}; \ No newline at end of file Index: branches/RC/core/kernel/db/db_event_handler.php =================================================================== diff -u -N -r10599 -r10621 --- branches/RC/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 10599) +++ branches/RC/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 10621) @@ -2141,8 +2141,15 @@ } } + /** + * Used to save files uploaded via swfuploader + * + * @param kEvent $event + */ function OnUploadFile(&$event) { + $event->status = erSTOP; + // Flash uploader does NOT send correct cookies, so we need to make our own check $cookie_name = 'adm_'.$this->Application->ConfigValue('SessionCookieName'); $this->Application->HttpQuery->Cookie['cookies_on'] = 1; @@ -2152,18 +2159,18 @@ $admin_ses =& $this->Application->recallObject('Session.admin'); /* @var $admin_ses Session */ - $user = $admin_ses->RecallVar('user_id'); - $perm_helper =& $this->Application->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ $section = $event->getSection(); + $user_id = $admin_ses->RecallVar('user_id'); - if (!$perm_helper->CheckUserPermission($user, $section.'.add') && !$perm_helper->CheckUserPermission($user, $section.'.edit')) { + if (!$perm_helper->CheckUserPermission($user_id, $section.'.add') && !$perm_helper->CheckUserPermission($user_id, $section.'.edit')) { $event->status = erPERM_FAIL; + // 403 Forbidden header('HTTP/1.0 403 You don\'t have permissions to upload'); exit; - return; + return ; } if (!$cookie_name) { @@ -2172,21 +2179,29 @@ $value = $this->Application->GetVar('Filedata'); if (!$value) { - return ; + $event->status = erFAIL; + // 413 Request Entity Too Large (when uploaded file was to large for web server to accept) + header('HTTP/1.0 413 File size exceeds allowed limit'); + exit; } $tmp_path = defined('WRITEABLE') ? WRITEABLE.'/tmp/' : FULL_PATH.'/kernel/cache/'; $fname = $value['name']; $id = $this->Application->GetVar('id'); - if ($id) $fname = $id.'_'.$fname; + if ($id) { + $fname = $id.'_'.$fname; + } if (!is_writable($tmp_path)) { + $event->status = erFAIL; + // 500 Internal Server Error header('HTTP/1.0 500 Write permissions not set on the server'); exit; } move_uploaded_file($value['tmp_name'], $tmp_path.$fname); - exit; + + die("Flash requires that we output something or it won't fire the uploadSuccess event"); } /** @@ -2196,8 +2211,13 @@ */ function OnDeleteFile(&$event) { - if (strpos($this->Application->GetVar('file'), '../') !== false) return ; - $object =& $event->getObject(array('skip_autoload'=>true)); + $event->status = erSTOP; + + if (strpos($this->Application->GetVar('file'), '../') !== false) { + return ; + } + + $object =& $event->getObject( Array ('skip_autoload' => true)) ; $options = $object->GetFieldOptions($this->Application->GetVar('field')); $var_name = $event->getPrefixSpecial().'_file_pending_actions'.$this->Application->GetVar('m_wid'); Index: branches/RC/core/admin_templates/swfupload.swf =================================================================== diff -u -N -r8929 -r10621 Binary files differ