/* * jQuery UI Widget 1.10.3+amd * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2013 jQuery Foundation and other contributors * Released under the MIT license. * http://jquery.org/license * * http://api.jqueryui.com/jQuery.widget/ */ (function (factory) { if (typeof define === "function" && define.amd) { // Register as an anonymous AMD module: define(["jquery"], factory); } else { // Browser globals: factory(jQuery); } }(function( $, undefined ) { var uuid = 0, slice = Array.prototype.slice, _cleanData = $.cleanData; $.cleanData = function( elems ) { for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { try { $( elem ).triggerHandler( "remove" ); // http://bugs.jquery.com/ticket/8235 } catch( e ) {} } _cleanData( elems ); }; $.widget = function( name, base, prototype ) { var fullName, existingConstructor, constructor, basePrototype, // proxiedPrototype allows the provided prototype to remain unmodified // so that it can be used as a mixin for multiple widgets (#8876) proxiedPrototype = {}, namespace = name.split( "." )[ 0 ]; name = name.split( "." )[ 1 ]; fullName = namespace + "-" + name; if ( !prototype ) { prototype = base; base = $.Widget; } // create selector for plugin $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { return !!$.data( elem, fullName ); }; $[ namespace ] = $[ namespace ] || {}; existingConstructor = $[ namespace ][ name ]; constructor = $[ namespace ][ name ] = function( options, element ) { // allow instantiation without "new" keyword if ( !this._createWidget ) { return new constructor( options, element ); } // allow instantiation without initializing for simple inheritance // must use "new" keyword (the code above always passes args) if ( arguments.length ) { this._createWidget( options, element ); } }; // extend with the existing constructor to carry over any static properties $.extend( constructor, existingConstructor, { version: prototype.version, // copy the object used to create the prototype in case we need to // redefine the widget later _proto: $.extend( {}, prototype ), // track widgets that inherit from this widget in case this widget is // redefined after a widget inherits from it _childConstructors: [] }); basePrototype = new base(); // we need to make the options hash a property directly on the new instance // otherwise we'll modify the options hash on the prototype that we're // inheriting from basePrototype.options = $.widget.extend( {}, basePrototype.options ); $.each( prototype, function( prop, value ) { if ( !$.isFunction( value ) ) { proxiedPrototype[ prop ] = value; return; } proxiedPrototype[ prop ] = (function() { var _super = function() { return base.prototype[ prop ].apply( this, arguments ); }, _superApply = function( args ) { return base.prototype[ prop ].apply( this, args ); }; return function() { var __super = this._super, __superApply = this._superApply, returnValue; this._super = _super; this._superApply = _superApply; returnValue = value.apply( this, arguments ); this._super = __super; this._superApply = __superApply; return returnValue; }; })(); }); constructor.prototype = $.widget.extend( basePrototype, { // TODO: remove support for widgetEventPrefix // always use the name + a colon as the prefix, e.g., draggable:start // don't prefix for widgets that aren't DOM-based widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name }, proxiedPrototype, { constructor: constructor, namespace: namespace, widgetName: name, widgetFullName: fullName }); // If this widget is being redefined then we need to find all widgets that // are inheriting from it and redefine all of them so that they inherit from // the new version of this widget. We're essentially trying to replace one // level in the prototype chain. if ( existingConstructor ) { $.each( existingConstructor._childConstructors, function( i, child ) { var childPrototype = child.prototype; // redefine the child widget using the same prototype that was // originally used, but inherit from the new version of the base $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); }); // remove the list of existing child constructors from the old constructor // so the old child constructors can be garbage collected delete existingConstructor._childConstructors; } else { base._childConstructors.push( constructor ); } $.widget.bridge( name, constructor ); }; $.widget.extend = function( target ) { var input = slice.call( arguments, 1 ), inputIndex = 0, inputLength = input.length, key, value; for ( ; inputIndex < inputLength; inputIndex++ ) { for ( key in input[ inputIndex ] ) { value = input[ inputIndex ][ key ]; if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { // Clone objects if ( $.isPlainObject( value ) ) { target[ key ] = $.isPlainObject( target[ key ] ) ? $.widget.extend( {}, target[ key ], value ) : // Don't extend strings, arrays, etc. with objects $.widget.extend( {}, value ); // Copy everything else by reference } else { target[ key ] = value; } } } } return target; }; $.widget.bridge = function( name, object ) { var fullName = object.prototype.widgetFullName || name; $.fn[ name ] = function( options ) { var isMethodCall = typeof options === "string", args = slice.call( arguments, 1 ), returnValue = this; // allow multiple hashes to be passed on init options = !isMethodCall && args.length ? $.widget.extend.apply( null, [ options ].concat(args) ) : options; if ( isMethodCall ) { this.each(function() { var methodValue, instance = $.data( this, fullName ); if ( !instance ) { return $.error( "cannot call methods on " + name + " prior to initialization; " + "attempted to call method '" + options + "'" ); } if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { return $.error( "no such method '" + options + "' for " + name + " widget instance" ); } methodValue = instance[ options ].apply( instance, args ); if ( methodValue !== instance && methodValue !== undefined ) { returnValue = methodValue && methodValue.jquery ? returnValue.pushStack( methodValue.get() ) : methodValue; return false; } }); } else { this.each(function() { var instance = $.data( this, fullName ); if ( instance ) { instance.option( options || {} )._init(); } else { $.data( this, fullName, new object( options, this ) ); } }); } return returnValue; }; }; $.Widget = function( /* options, element */ ) {}; $.Widget._childConstructors = []; $.Widget.prototype = { widgetName: "widget", widgetEventPrefix: "", defaultElement: "
", options: { disabled: false, // callbacks create: null }, _createWidget: function( options, element ) { element = $( element || this.defaultElement || this )[ 0 ]; this.element = $( element ); this.uuid = uuid++; this.eventNamespace = "." + this.widgetName + this.uuid; this.options = $.widget.extend( {}, this.options, this._getCreateOptions(), options ); this.bindings = $(); this.hoverable = $(); this.focusable = $(); if ( element !== this ) { $.data( element, this.widgetFullName, this ); this._on( true, this.element, { remove: function( event ) { if ( event.target === element ) { this.destroy(); } } }); this.document = $( element.style ? // element within the document element.ownerDocument : // element is window or document element.document || element ); this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); } this._create(); this._trigger( "create", null, this._getCreateEventData() ); this._init(); }, _getCreateOptions: $.noop, _getCreateEventData: $.noop, _create: $.noop, _init: $.noop, destroy: function() { this._destroy(); // we can probably remove the unbind calls in 2.0 // all event bindings should go through this._on() this.element .unbind( this.eventNamespace ) // 1.9 BC for #7810 // TODO remove dual storage .removeData( this.widgetName ) .removeData( this.widgetFullName ) // support: jquery <1.6.3 // http://bugs.jquery.com/ticket/9413 .removeData( $.camelCase( this.widgetFullName ) ); this.widget() .unbind( this.eventNamespace ) .removeAttr( "aria-disabled" ) .removeClass( this.widgetFullName + "-disabled " + "ui-state-disabled" ); // clean up events and states this.bindings.unbind( this.eventNamespace ); this.hoverable.removeClass( "ui-state-hover" ); this.focusable.removeClass( "ui-state-focus" ); }, _destroy: $.noop, widget: function() { return this.element; }, option: function( key, value ) { var options = key, parts, curOption, i; if ( arguments.length === 0 ) { // don't return a reference to the internal hash return $.widget.extend( {}, this.options ); } if ( typeof key === "string" ) { // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } options = {}; parts = key.split( "." ); key = parts.shift(); if ( parts.length ) { curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); for ( i = 0; i < parts.length - 1; i++ ) { curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; curOption = curOption[ parts[ i ] ]; } key = parts.pop(); if ( value === undefined ) { return curOption[ key ] === undefined ? null : curOption[ key ]; } curOption[ key ] = value; } else { if ( value === undefined ) { return this.options[ key ] === undefined ? null : this.options[ key ]; } options[ key ] = value; } } this._setOptions( options ); return this; }, _setOptions: function( options ) { var key; for ( key in options ) { this._setOption( key, options[ key ] ); } return this; }, _setOption: function( key, value ) { this.options[ key ] = value; if ( key === "disabled" ) { this.widget() .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) .attr( "aria-disabled", value ); this.hoverable.removeClass( "ui-state-hover" ); this.focusable.removeClass( "ui-state-focus" ); } return this; }, enable: function() { return this._setOption( "disabled", false ); }, disable: function() { return this._setOption( "disabled", true ); }, _on: function( suppressDisabledCheck, element, handlers ) { var delegateElement, instance = this; // no suppressDisabledCheck flag, shuffle arguments if ( typeof suppressDisabledCheck !== "boolean" ) { handlers = element; element = suppressDisabledCheck; suppressDisabledCheck = false; } // no element argument, shuffle and use this.element if ( !handlers ) { handlers = element; element = this.element; delegateElement = this.widget(); } else { // accept selectors, DOM elements element = delegateElement = $( element ); this.bindings = this.bindings.add( element ); } $.each( handlers, function( event, handler ) { function handlerProxy() { // allow widgets to customize the disabled handling // - disabled as an array instead of boolean // - disabled class as method for disabling individual parts if ( !suppressDisabledCheck && ( instance.options.disabled === true || $( this ).hasClass( "ui-state-disabled" ) ) ) { return; } return ( typeof handler === "string" ? instance[ handler ] : handler ) .apply( instance, arguments ); } // copy the guid so direct unbinding works if ( typeof handler !== "string" ) { handlerProxy.guid = handler.guid = handler.guid || handlerProxy.guid || $.guid++; } var match = event.match( /^(\w+)\s*(.*)$/ ), eventName = match[1] + instance.eventNamespace, selector = match[2]; if ( selector ) { delegateElement.delegate( selector, eventName, handlerProxy ); } else { element.bind( eventName, handlerProxy ); } }); }, _off: function( element, eventName ) { eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; element.unbind( eventName ).undelegate( eventName ); }, _delay: function( handler, delay ) { function handlerProxy() { return ( typeof handler === "string" ? instance[ handler ] : handler ) .apply( instance, arguments ); } var instance = this; return setTimeout( handlerProxy, delay || 0 ); }, _hoverable: function( element ) { this.hoverable = this.hoverable.add( element ); this._on( element, { mouseenter: function( event ) { $( event.currentTarget ).addClass( "ui-state-hover" ); }, mouseleave: function( event ) { $( event.currentTarget ).removeClass( "ui-state-hover" ); } }); }, _focusable: function( element ) { this.focusable = this.focusable.add( element ); this._on( element, { focusin: function( event ) { $( event.currentTarget ).addClass( "ui-state-focus" ); }, focusout: function( event ) { $( event.currentTarget ).removeClass( "ui-state-focus" ); } }); }, _trigger: function( type, event, data ) { var prop, orig, callback = this.options[ type ]; data = data || {}; event = $.Event( event ); event.type = ( type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type ).toLowerCase(); // the original event may come from any element // so we need to reset the target on the new event event.target = this.element[ 0 ]; // copy original event properties over to the new event orig = event.originalEvent; if ( orig ) { for ( prop in orig ) { if ( !( prop in event ) ) { event[ prop ] = orig[ prop ]; } } } this.element.trigger( event, data ); return !( $.isFunction( callback ) && callback.apply( this.element[0], [ event ].concat( data ) ) === false || event.isDefaultPrevented() ); } }; $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { if ( typeof options === "string" ) { options = { effect: options }; } var hasOptions, effectName = !options ? method : options === true || typeof options === "number" ? defaultEffect : options.effect || defaultEffect; options = options || {}; if ( typeof options === "number" ) { options = { duration: options }; } hasOptions = !$.isEmptyObject( options ); options.complete = callback; if ( options.delay ) { element.delay( options.delay ); } if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { element[ method ]( options ); } else if ( effectName !== method && element[ effectName ] ) { element[ effectName ]( options.duration, options.easing, callback ); } else { element.queue(function( next ) { $( this )[ method ](); if ( callback ) { callback.call( element[ 0 ] ); } next(); }); } }; }); })); #!/usr/bin/env node /* * jQuery File Upload Plugin Node.js Example 2.1.1 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2012, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: * http://www.opensource.org/licenses/MIT */ /* jshint nomen:false */ /* global require, __dirname, unescape, console */ (function (port) { 'use strict'; var path = require('path'), fs = require('fs'), // Since Node 0.8, .existsSync() moved from path to fs: _existsSync = fs.existsSync || path.existsSync, formidable = require('formidable'), nodeStatic = require('node-static'), imageMagick = require('imagemagick'), options = { tmpDir: __dirname + '/tmp', publicDir: __dirname + '/public', uploadDir: __dirname + '/public/files', uploadUrl: '/files/', maxPostSize: 11000000000, // 11 GB minFileSize: 1, maxFileSize: 10000000000, // 10 GB acceptFileTypes: /.+/i, // Files not matched by this regular expression force a download dialog, // to prevent executing any scripts in the context of the service domain: inlineFileTypes: /\.(gif|jpe?g|png)$/i, imageTypes: /\.(gif|jpe?g|png)$/i, imageVersions: { 'thumbnail': { width: 80, height: 80 } }, accessControl: { allowOrigin: '*', allowMethods: 'OPTIONS, HEAD, GET, POST, PUT, DELETE', allowHeaders: 'Content-Type, Content-Range, Content-Disposition' }, /* Uncomment and edit this section to provide the service via HTTPS: ssl: { key: fs.readFileSync('/Applications/XAMPP/etc/ssl.key/server.key'), cert: fs.readFileSync('/Applications/XAMPP/etc/ssl.crt/server.crt') }, */ nodeStatic: { cache: 3600 // seconds to cache served files } }, utf8encode = function (str) { return unescape(encodeURIComponent(str)); }, fileServer = new nodeStatic.Server(options.publicDir, options.nodeStatic), nameCountRegexp = /(?:(?: \(([\d]+)\))?(\.[^.]+))?$/, nameCountFunc = function (s, index, ext) { return ' (' + ((parseInt(index, 10) || 0) + 1) + ')' + (ext || ''); }, FileInfo = function (file) { this.name = file.name; this.size = file.size; this.type = file.type; this.deleteType = 'DELETE'; }, UploadHandler = function (req, res, callback) { this.req = req; this.res = res; this.callback = callback; }, serve = function (req, res) { res.setHeader( 'Access-Control-Allow-Origin', options.accessControl.allowOrigin ); res.setHeader( 'Access-Control-Allow-Methods', options.accessControl.allowMethods ); res.setHeader( 'Access-Control-Allow-Headers', options.accessControl.allowHeaders ); var handleResult = function (result, redirect) { if (redirect) { res.writeHead(302, { 'Location': redirect.replace( /%s/, encodeURIComponent(JSON.stringify(result)) ) }); res.end(); } else { res.writeHead(200, { 'Content-Type': req.headers.accept .indexOf('application/json') !== -1 ? 'application/json' : 'text/plain' }); res.end(JSON.stringify(result)); } }, setNoCacheHeaders = function () { res.setHeader('Pragma', 'no-cache'); res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate'); res.setHeader('Content-Disposition', 'inline; filename="files.json"'); }, handler = new UploadHandler(req, res, handleResult); switch (req.method) { case 'OPTIONS': res.end(); break; case 'HEAD': case 'GET': if (req.url === '/') { setNoCacheHeaders(); if (req.method === 'GET') { handler.get(); } else { res.end(); } } else { fileServer.serve(req, res); } break; case 'POST': setNoCacheHeaders(); handler.post(); break; case 'DELETE': handler.destroy(); break; default: res.statusCode = 405; res.end(); } }; fileServer.respond = function (pathname, status, _headers, files, stat, req, res, finish) { // Prevent browsers from MIME-sniffing the content-type: _headers['X-Content-Type-Options'] = 'nosniff'; if (!options.inlineFileTypes.test(files[0])) { // Force a download dialog for unsafe file extensions: _headers['Content-Type'] = 'application/octet-stream'; _headers['Content-Disposition'] = 'attachment; filename="' + utf8encode(path.basename(files[0])) + '"'; } nodeStatic.Server.prototype.respond .call(this, pathname, status, _headers, files, stat, req, res, finish); }; FileInfo.prototype.validate = function () { if (options.minFileSize && options.minFileSize > this.size) { this.error = 'File is too small'; } else if (options.maxFileSize && options.maxFileSize < this.size) { this.error = 'File is too big'; } else if (!options.acceptFileTypes.test(this.name)) { this.error = 'Filetype not allowed'; } return !this.error; }; FileInfo.prototype.safeName = function () { // Prevent directory traversal and creating hidden system files: this.name = path.basename(this.name).replace(/^\.+/, ''); // Prevent overwriting existing files: while (_existsSync(options.uploadDir + '/' + this.name)) { this.name = this.name.replace(nameCountRegexp, nameCountFunc); } }; FileInfo.prototype.initUrls = function (req) { if (!this.error) { var that = this, baseUrl = (options.ssl ? 'https:' : 'http:') + '//' + req.headers.host + options.uploadUrl; this.url = this.deleteUrl = baseUrl + encodeURIComponent(this.name); Object.keys(options.imageVersions).forEach(function (version) { if (_existsSync( options.uploadDir + '/' + version + '/' + that.name )) { that[version + 'Url'] = baseUrl + version + '/' + encodeURIComponent(that.name); } }); } }; UploadHandler.prototype.get = function () { var handler = this, files = []; fs.readdir(options.uploadDir, function (err, list) { list.forEach(function (name) { var stats = fs.statSync(options.uploadDir + '/' + name), fileInfo; if (stats.isFile() && name[0] !== '.') { fileInfo = new FileInfo({ name: name, size: stats.size }); fileInfo.initUrls(handler.req); files.push(fileInfo); } }); handler.callback({files: files}); }); }; UploadHandler.prototype.post = function () { var handler = this, form = new formidable.IncomingForm(), tmpFiles = [], files = [], map = {}, counter = 1, redirect, finish = function () { counter -= 1; if (!counter) { files.forEach(function (fileInfo) { fileInfo.initUrls(handler.req); });