: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
return ctrl.getRuntime().uid;
function runtimeCan(file, cap) {
var info = o.Runtime.getInfo(file.ruid);
function bindEventListeners() {
this.bind('FilesAdded FilesRemoved', function(up) {
up.trigger('QueueChanged');
this.bind('CancelUpload', onCancelUpload);
this.bind('BeforeUpload', onBeforeUpload);
this.bind('UploadFile', onUploadFile);
this.bind('UploadProgress', onUploadProgress);
this.bind('StateChanged', onStateChanged);
this.bind('QueueChanged', calc);
this.bind('Error', onError);
this.bind('FileUploaded', onFileUploaded);
this.bind('Destroy', onDestroy);
function initControls(settings, cb) {
var self = this, inited = 0, queue = [];
runtime_order: settings.runtimes,
required_caps: settings.required_features,
preferred_caps: preferred_caps
// add runtime specific options if any
plupload.each(settings.runtimes.split(/\s*,\s*/), function(runtime) {
options[runtime] = settings[runtime];
// initialize file pickers - there can be many
if (settings.browse_button) {
plupload.each(settings.browse_button, function(el) {
queue.push(function(cb) {
var fileInput = new o.FileInput(plupload.extend({}, options, {
accept: settings.filters.mime_types,
name: settings.file_data_name,
multiple: settings.multi_selection,
container: settings.container,
fileInput.onready = function() {
var info = o.Runtime.getInfo(this.ruid);
// for backward compatibility
o.extend(self.features, {
chunks: info.can('slice_blob'),
multipart: info.can('send_multipart'),
multi_selection: info.can('select_multiple')
fileInput.onchange = function() {
self.addFile(this.files);
fileInput.bind('mouseenter mouseleave mousedown mouseup', function(e) {
if (settings.browse_button_hover) {
if ('mouseenter' === e.type) {
o.addClass(el, settings.browse_button_hover);
} else if ('mouseleave' === e.type) {
o.removeClass(el, settings.browse_button_hover);
if (settings.browse_button_active) {
if ('mousedown' === e.type) {
o.addClass(el, settings.browse_button_active);
} else if ('mouseup' === e.type) {
o.removeClass(el, settings.browse_button_active);
fileInput.bind('mousedown', function() {
fileInput.bind('error runtimeerror', function() {
if (settings.drop_element) {
plupload.each(settings.drop_element, function(el) {
queue.push(function(cb) {
var fileDrop = new o.FileDrop(plupload.extend({}, options, {
fileDrop.onready = function() {
var info = o.Runtime.getInfo(this.ruid);
// for backward compatibility
o.extend(self.features, {
chunks: info.can('slice_blob'),
multipart: info.can('send_multipart'),
dragdrop: info.can('drag_and_drop')
fileDrop.ondrop = function() {
self.addFile(this.files);
fileDrop.bind('error runtimeerror', function() {
o.inSeries(queue, function() {
if (typeof(cb) === 'function') {
function resizeImage(blob, params, cb) {
img.onload = function() {
// no manipulation required if...
if (params.width > this.width &&
params.height > this.height &&
params.quality === undef &&
params.preserve_headers &&
img.downsize(params.width, params.height, params.crop, params.preserve_headers);
img.onresize = function() {
cb(this.getAsBlob(blob.type, params.quality));
img.onerror = function() {
function setOption(option, value, init) {
var self = this, reinitRequired = false;
function _setOption(option, value, init) {
var oldValue = settings[option];
if (option === 'max_file_size') {
settings.max_file_size = settings.filters.max_file_size = value;
if (value = plupload.parseSize(value)) {
settings[option] = value;
settings.send_file_name = true;
settings[option] = value;
settings.send_file_name = true;
settings[option] = value;
settings.send_file_name = true;
// for sake of backward compatibility
if (plupload.typeOf(value) === 'array') {
plupload.extend(settings.filters, value);
settings.filters = value;
// if file format filters are being updated, regenerate the matching expressions
settings.filters.mime_types.regexp = (function(filters) {
var extensionsRegExp = [];
plupload.each(filters, function(filter) {
plupload.each(filter.extensions.split(/,/), function(ext) {
if (/^\s*\*\s*$/.test(ext)) {
extensionsRegExp.push('\\.*');
extensionsRegExp.push('\\.' + ext.replace(new RegExp('[' + ('/^$.*+?|()[]{}\\'.replace(/./g, '\\$&')) + ']', 'g'), '\\$&'));
return new RegExp('(' + extensionsRegExp.join('|') + ')$', 'i');
}(settings.filters.mime_types));
plupload.extend(settings.resize, value, {
case 'prevent_duplicates':
settings.prevent_duplicates = settings.filters.prevent_duplicates = !!value;
// options that require reinitialisation
value = 'container' === option
settings[option] = value;
settings[option] = value;
self.trigger('OptionChanged', option, value, oldValue);
if (typeof(option) === 'object') {
plupload.each(option, function(value, option) {
_setOption(option, value, init);
_setOption(option, value, init);
// Normalize the list of required capabilities
settings.required_features = normalizeCaps(plupload.extend({}, settings));
// Come up with the list of capabilities that can affect default mode in a multi-mode runtimes
preferred_caps = normalizeCaps(plupload.extend({}, settings, {
} else if (reinitRequired) {
initControls.call(self, settings, function(inited) {
self.runtime = o.Runtime.getInfo(getRUID()).type;
self.trigger('Init', { runtime: self.runtime });
self.trigger('PostInit');
code : plupload.INIT_ERROR,
message : plupload.translate('Init error.')
// Internal event handlers
function onBeforeUpload(up, file) {
// Generate unique target filenames
if (up.settings.unique_names) {
var matches = file.name.match(/\.([^.]+)$/), ext = "part";
file.target_name = file.id + '.' + ext;
function onUploadFile(up, file) {
var url = up.settings.url
, chunkSize = up.settings.chunk_size
, retries = up.settings.max_retries
// make sure we start at a predictable offset
offset = file.loaded = chunkSize ? chunkSize * Math.floor(file.loaded / chunkSize) : 0;
delay(uploadNextChunk, 1000);
file.loaded = offset; // reset all progress
code : plupload.HTTP_ERROR,
message : plupload.translate('HTTP Error.'),
response : xhr.responseText,
responseHeaders: xhr.getAllResponseHeaders()
function uploadNextChunk() {
var chunkBlob, formData, args = {}, curChunkSize;
// make sure that file wasn't cancelled and upload is not stopped in general
if (file.status !== plupload.UPLOADING || up.state === plupload.STOPPED) {
// send additional 'name' parameter only if required
if (up.settings.send_file_name) {
args.name = file.target_name || file.name;
if (chunkSize && features.chunks && blob.size > chunkSize) { // blob will be of type string if it was loaded in memory
curChunkSize = Math.min(chunkSize, blob.size - offset);
chunkBlob = blob.slice(offset, offset + curChunkSize);
curChunkSize = blob.size;
// If chunking is enabled add corresponding args, no matter if file is bigger than chunk or smaller
if (chunkSize && features.chunks) {
// Setup query string arguments
if (up.settings.send_chunk_number) {
args.chunk = Math.ceil(offset / chunkSize);
args.chunks = Math.ceil(blob.size / chunkSize);
} else { // keep support for experimental chunk format, just in case
xhr = new o.XMLHttpRequest();
// Do we have upload progress support
xhr.upload.onprogress = function(e) {
file.loaded = Math.min(file.size, offset + e.loaded);
up.trigger('UploadProgress', file);
xhr.onload = function() {
// check if upload made itself through
retries = up.settings.max_retries; // reset the counter
if (curChunkSize < blob.size) {
file.loaded = Math.min(offset, blob.size);
up.trigger('ChunkUploaded', file, {
response : xhr.responseText,
responseHeaders: xhr.getAllResponseHeaders()
// stock Android browser doesn't fire upload progress events, but in chunking mode we can fake them
if (o.Env.browser === 'Android Browser') {
// doesn't harm in general, but is not required anywhere else
up.trigger('UploadProgress', file);
chunkBlob = formData = null; // Free memory
// Check if file is uploaded
if (!offset || offset >= blob.size) {
// If file was modified, destory the copy
if (file.size != file.origSize) {
up.trigger('UploadProgress', file);
file.status = plupload.DONE;
up.trigger('FileUploaded', file, {
response : xhr.responseText,
responseHeaders: xhr.getAllResponseHeaders()
delay(uploadNextChunk, 1); // run detached, otherwise event handlers interfere
xhr.onerror = function() {
xhr.onloadend = function() {