upgrade blueimp from 9.8 to 9.18

This commit is contained in:
zotlabs 2017-06-26 17:32:38 -07:00
parent 4d81c498e2
commit a8374b25f1
54 changed files with 921 additions and 1125 deletions

View File

@ -1,3 +0,0 @@
.DS_Store
*.pyc
node_modules

View File

@ -1,81 +0,0 @@
{
"bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
"camelcase" : true, // true: Identifiers must be in camelCase
"curly" : true, // true: Require {} for every new block or scope
"eqeqeq" : true, // true: Require triple equals (===) for comparison
"forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
"immed" : true, // true: Require immediate invocations to be wrapped in parens
// e.g. `(function () { } ());`
"indent" : 4, // {int} Number of spaces to use for indentation
"latedef" : true, // true: Require variables/functions to be defined before being used
"newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()`
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
"noempty" : true, // true: Prohibit use of empty blocks
"nonew" : true, // true: Prohibit use of constructors for side-effects (without assignment)
"plusplus" : false, // true: Prohibit use of `++` & `--`
"quotmark" : "single", // Quotation mark consistency:
// false : do nothing (default)
// true : ensure whatever is used is consistent
// "single" : require single quotes
// "double" : require double quotes
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
"unused" : true, // true: Require all defined variables be used
"strict" : true, // true: Requires all functions run in ES5 Strict Mode
"trailing" : true, // true: Prohibit trailing whitespaces
"maxparams" : false, // {int} Max number of formal params allowed per function
"maxdepth" : false, // {int} Max depth of nested blocks (within functions)
"maxstatements" : false, // {int} Max number statements per function
"maxcomplexity" : false, // {int} Max cyclomatic complexity per function
"maxlen" : false, // {int} Max number of characters per line
// Relaxing
"asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
"boss" : false, // true: Tolerate assignments where comparisons would be expected
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
"eqnull" : false, // true: Tolerate use of `== null`
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
"esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
"moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
// (ex: `for each`, multiple try/catch, function expression…)
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
"expr" : false, // true: Tolerate `ExpressionStatement` as Programs
"funcscope" : false, // true: Tolerate defining variables inside control statements"
"globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
"iterator" : false, // true: Tolerate using the `__iterator__` property
"lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
"laxbreak" : false, // true: Tolerate possibly unsafe line breakings
"laxcomma" : false, // true: Tolerate comma-first style coding
"loopfunc" : false, // true: Tolerate functions being defined in loops
"multistr" : false, // true: Tolerate multi-line strings
"proto" : false, // true: Tolerate using the `__proto__` property
"scripturl" : false, // true: Tolerate script-targeted URLs
"smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
"shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
"sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
"supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
"validthis" : false, // true: Tolerate using this in a non-constructor function
// Environments
"browser" : false, // Web Browser (window, document, etc)
"couch" : false, // CouchDB
"devel" : false, // Development/debugging (alert, confirm, etc)
"dojo" : false, // Dojo Toolkit
"jquery" : false, // jQuery
"mootools" : false, // MooTools
"node" : false, // Node.js
"nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
"prototypejs" : false, // Prototype and Scriptaculous
"rhino" : false, // Rhino
"worker" : false, // Web Workers
"wsh" : false, // Windows Scripting Host
"yui" : false, // Yahoo User Interface
// Legacy
"nomen" : true, // true: Prohibit dangling `_` in variables
"onevar" : true, // true: Allow only one `var` statement per function
"passfail" : false, // true: Stop on first error
"white" : true, // true: Check against strict whitespace and indentation rules
// Custom Globals
"globals" : {} // additional predefined global variables
}

View File

@ -1,42 +1,15 @@
# Issue Guidelines
The issues tracker should only be used for **bugs** or **feature requests**.
Please post **support requests** and **general discussions** about this project to the [support forum](https://groups.google.com/d/forum/jquery-fileupload).
## Bugs
Please follow these guidelines before reporting a bug:
1. **Update to the latest version** — Check if you can reproduce the issue with the latest version from the `master` branch.
2. **Use the GitHub issue search** — check if the issue has already been reported. If it has been, please comment on the existing issue.
3. **Isolate the demonstrable problem** — Try to reproduce the problem with the [Demo](https://blueimp.github.io/jQuery-File-Upload/) or with a reduced test case that includes the least amount of code necessary to reproduce the problem.
4. **Provide a means to reproduce the problem** — Please provide as much details as possible, e.g. server information, browser and operating system versions, steps to reproduce the problem. If possible, provide a link to your reduced test case, e.g. via [JSFiddle](http://jsfiddle.net/).
## Feature requests
Please follow the bug guidelines above for feature requests, i.e. update to the latest version and search for exising issues before posting a new request.
Generally, feature requests might be accepted if the implementation would benefit a broader use case or the project could be considered incomplete without that feature.
If you need help integrating this project into another framework, please post your request to the [support forum](https://groups.google.com/d/forum/jquery-fileupload).
## Pull requests
[Pull requests](https://help.github.com/articles/using-pull-requests) are welcome and the preferred way of accepting code contributions.
However, if you add a server-side upload handler implementation for another framework, please continue to maintain this version in your own fork without sending a pull request. You are welcome to add a link and possibly documentation about your implementation to the [Wiki](https://github.com/blueimp/jQuery-File-Upload/wiki).
Please follow these guidelines before sending a pull request:
Please follow these pull request guidelines:
1. Update your fork to the latest upstream version.
2. Follow the coding conventions of the original repository. Changes to one of the JavaScript source files are required to pass the [JSHint](http://www.jshint.com/) validation tool.
2. Follow the coding conventions of the original source files (indentation, spaces, brackets layout).
3. Keep your commits as atomar as possible, i.e. create a new commit for every single bug fix or feature added.
3. Code changes must pass JSHint validation with the `.jshintrc` settings of this project.
4. Always add meaningfull commit messages.
4. Code changes must pass the QUnit tests defined in the `test` folder.
5. New features should be covered by accompanying QUnit tests.
6. Keep your commits as atomic as possible, i.e. create a new commit for every single bug fix or feature added.
7. Always add meaningful commit messages.

View File

@ -1,37 +0,0 @@
/*
* jQuery File Upload Gruntfile
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
*/
/*global module */
module.exports = function (grunt) {
'use strict';
grunt.initConfig({
jshint: {
options: {
jshintrc: '.jshintrc'
},
all: [
'Gruntfile.js',
'js/cors/*.js',
'js/*.js',
'server/node/server.js',
'test/test.js'
]
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-bump-build-git');
grunt.registerTask('test', ['jshint']);
grunt.registerTask('default', ['test']);
};

View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2017 jQuery-File-Upload Authors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -11,17 +11,6 @@ Supports cross-domain, chunked and resumable file uploads and client-side image
* [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup)
* [How to use only the basic plugin (minimal setup guide).](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin)
## Support
* **[Support Forum](https://groups.google.com/d/forum/jquery-fileupload)**
**Support requests** and **general discussions** about the File Upload plugin can be posted to the official
[Support Forum](https://groups.google.com/d/forum/jquery-fileupload).
If your question is not directly related to the File Upload plugin, you might have a better chance to get a reply by posting to [Stack Overflow](http://stackoverflow.com/questions/tagged/blueimp+jquery+file-upload).
* Bugs and Feature requests
**Bugs** and **Feature requests** can be reported using the [issues tracker](https://github.com/blueimp/jQuery-File-Upload/issues).
Please read the [issue guidelines](https://github.com/blueimp/jQuery-File-Upload/blob/master/CONTRIBUTING.md) before posting.
## Features
* **Multiple file upload:**
Allows to select multiple files at once and upload them simultaneously.
@ -60,28 +49,18 @@ Please read the [issue guidelines](https://github.com/blueimp/jQuery-File-Upload
### Mandatory requirements
* [jQuery](https://jquery.com/) v. 1.6+
* [jQuery UI widget factory](https://api.jqueryui.com/jQuery.widget/) v. 1.9+ (included)
* [jQuery Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) (included)
The jQuery UI widget factory is a requirement for the basic File Upload plugin, but very lightweight without any other dependencies from the jQuery UI suite.
The jQuery Iframe Transport is required for [browsers without XHR file upload support](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
* [jQuery UI widget factory](https://api.jqueryui.com/jQuery.widget/) v. 1.9+ (included): Required for the basic File Upload plugin, but very lightweight without any other dependencies from the jQuery UI suite.
* [jQuery Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) (included): Required for [browsers without XHR file upload support](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
### Optional requirements
* [JavaScript Templates engine](https://github.com/blueimp/JavaScript-Templates) v. 2.5.4+
* [JavaScript Load Image library](https://github.com/blueimp/JavaScript-Load-Image) v. 1.13.0+
* [JavaScript Canvas to Blob polyfill](https://github.com/blueimp/JavaScript-Canvas-to-Blob) v. 2.1.1+
* [blueimp Gallery](https://github.com/blueimp/Gallery) v. 2.15.1+
* [Bootstrap CSS framework](http://getbootstrap.com/) v. 3.2.0+
* [JavaScript Templates engine](https://github.com/blueimp/JavaScript-Templates) v. 2.5.4+: Used to render the selected and uploaded files for the Basic Plus UI and jQuery UI versions.
* [JavaScript Load Image library](https://github.com/blueimp/JavaScript-Load-Image) v. 1.13.0+: Required for the image previews and resizing functionality.
* [JavaScript Canvas to Blob polyfill](https://github.com/blueimp/JavaScript-Canvas-to-Blob) v. 2.1.1+:Required for the image previews and resizing functionality.
* [blueimp Gallery](https://github.com/blueimp/Gallery) v. 2.15.1+: Used to display the uploaded images in a lightbox.
* [Bootstrap](http://getbootstrap.com/) v. 3.2.0+
* [Glyphicons](http://glyphicons.com/)
The JavaScript Templates engine is used to render the selected and uploaded files for the Basic Plus UI and jQuery UI versions.
The JavaScript Load Image library and JavaScript Canvas to Blob polyfill are required for the image previews and resizing functionality.
The blueimp Gallery is used to display the uploaded images in a lightbox.
The user interface of all versions except the jQuery UI version is built with Twitter's [Bootstrap](http://getbootstrap.com/) framework and icons from [Glyphicons](http://glyphicons.com/).
The user interface of all versions except the jQuery UI version is built with [Bootstrap](http://getbootstrap.com/) and icons from [Glyphicons](http://glyphicons.com/).
### Cross-domain requirements
[Cross-domain File Uploads](https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads) using the [Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) require a redirect back to the origin server to retrieve the upload results. The [example implementation](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/main.js) makes use of [result.html](https://github.com/blueimp/jQuery-File-Upload/blob/master/cors/result.html) as a static redirect page for the origin server.
@ -89,6 +68,10 @@ The user interface of all versions except the jQuery UI version is built with Tw
The repository also includes the [jQuery XDomainRequest Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/cors/jquery.xdr-transport.js), which enables limited cross-domain AJAX requests in Microsoft Internet Explorer 8 and 9 (IE 10 supports cross-domain XHR requests).
The XDomainRequest object allows GET and POST requests only and doesn't support file uploads. It is used on the [Demo](https://blueimp.github.io/jQuery-File-Upload/) to delete uploaded files from the cross-domain demo file upload service.
### Custom Backends
You can add support for various backends by adhering to the specification [outlined here](https://github.com/blueimp/jQuery-File-Upload/wiki/JSON-Response).
## Browsers
### Desktop browsers
@ -110,14 +93,15 @@ The File Upload plugin has been tested with and supports the following mobile br
* Opera Mobile 12.0+
### Supported features
For a detailed overview of the features supported by each browser version please have a look at the [Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
For a detailed overview of the features supported by each browser version, please have a look at the [Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
## Contributing
**Bug fixes** and **new features** can be proposed using [pull requests](https://github.com/blueimp/jQuery-File-Upload/pulls).
Please read the [contribution guidelines](https://github.com/blueimp/jQuery-File-Upload/blob/master/CONTRIBUTING.md) before submitting a pull request.
## Support
This project is actively maintained, but there is no official support channel.
If you have a question that another developer might help you with, please post to [Stack Overflow](http://stackoverflow.com/questions/tagged/blueimp+jquery+file-upload) and tag your question with `blueimp jquery file upload`.
## License
Released under the [MIT license](http://www.opensource.org/licenses/MIT).
## Donations
jQuery File Upload is free software, but you can donate to support the developer, Sebastian Tschan:
Flattr: [![Flattr](https://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/thing/286433/jQuery-File-Upload-Plugin)
PayPal: [![PayPal](https://www.paypalobjects.com/WEBSCR-640-20110429-1/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PYWYSYP77KL54)
Released under the [MIT license](https://opensource.org/licenses/MIT).

View File

@ -1,14 +1,14 @@
<!DOCTYPE HTML>
<!--
/*
* jQuery File Upload Plugin AngularJS Demo 2.2.0
* jQuery File Upload Plugin AngularJS Demo
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
-->
<html lang="en">
@ -157,9 +157,9 @@
</div>
<div class="panel-body">
<ul>
<li>The maximum file size for uploads in this demo is <strong>5 MB</strong> (default file size is unlimited).</li>
<li>The maximum file size for uploads in this demo is <strong>999 KB</strong> (default file size is unlimited).</li>
<li>Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in this demo (by default there is no file type restriction).</li>
<li>Uploaded files will be deleted automatically after <strong>5 minutes</strong> (demo setting).</li>
<li>Uploaded files will be deleted automatically after <strong>5 minutes or less</strong> (demo files are stored in memory).</li>
<li>You can <strong>drag &amp; drop</strong> files from your desktop on this webpage (see <a href="https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support">Browser support</a>).</li>
<li>Please refer to the <a href="https://github.com/blueimp/jQuery-File-Upload">project website</a> and <a href="https://github.com/blueimp/jQuery-File-Upload/wiki">documentation</a> for more information.</li>
<li>Built with the <a href="http://getbootstrap.com/">Bootstrap</a> CSS framework and Icons from <a href="http://glyphicons.com/">Glyphicons</a>.</li>
@ -177,8 +177,8 @@
<a class="play-pause"></a>
<ol class="indicator"></ol>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="js/vendor/jquery.ui.widget.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->

View File

@ -1,14 +1,14 @@
<!DOCTYPE HTML>
<!--
/*
* jQuery File Upload Plugin Basic Plus Demo 1.4.0
* jQuery File Upload Plugin Basic Plus Demo
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
-->
<html lang="en">
@ -86,9 +86,9 @@
</div>
<div class="panel-body">
<ul>
<li>The maximum file size for uploads in this demo is <strong>5 MB</strong> (default file size is unlimited).</li>
<li>The maximum file size for uploads in this demo is <strong>999 KB</strong> (default file size is unlimited).</li>
<li>Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in this demo (by default there is no file type restriction).</li>
<li>Uploaded files will be deleted automatically after <strong>5 minutes</strong> (demo setting).</li>
<li>Uploaded files will be deleted automatically after <strong>5 minutes or less</strong> (demo files are stored in memory).</li>
<li>You can <strong>drag &amp; drop</strong> files from your desktop on this webpage (see <a href="https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support">Browser support</a>).</li>
<li>Please refer to the <a href="https://github.com/blueimp/jQuery-File-Upload">project website</a> and <a href="https://github.com/blueimp/jQuery-File-Upload/wiki">documentation</a> for more information.</li>
<li>Built with the <a href="http://getbootstrap.com/">Bootstrap</a> CSS framework and Icons from <a href="http://glyphicons.com/">Glyphicons</a>.</li>
@ -96,7 +96,7 @@
</div>
</div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="js/vendor/jquery.ui.widget.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
@ -150,7 +150,7 @@ $(function () {
dataType: 'json',
autoUpload: false,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
maxFileSize: 5000000, // 5 MB
maxFileSize: 999000,
// Enable image resizing, except for Android and Opera,
// which actually support image resizing, but fail to
// send Blob objects via XHR requests:

View File

@ -1,14 +1,14 @@
<!DOCTYPE HTML>
<!--
/*
* jQuery File Upload Plugin Basic Demo 1.3.0
* jQuery File Upload Plugin Basic Demo
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
-->
<html lang="en">
@ -86,17 +86,17 @@
</div>
<div class="panel-body">
<ul>
<li>The maximum file size for uploads in this demo is <strong>5 MB</strong> (default file size is unlimited).</li>
<li>The maximum file size for uploads in this demo is <strong>999 KB</strong> (default file size is unlimited).</li>
<li>Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in this demo (by default there is no file type restriction).</li>
<li>Uploaded files will be deleted automatically after <strong>5 minutes</strong> (demo setting).</li>
<li>Uploaded files will be deleted automatically after <strong>5 minutes or less</strong> (demo files are stored in memory).</li>
<li>You can <strong>drag &amp; drop</strong> files from your desktop on this webpage (see <a href="https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support">Browser support</a>).</li>
<li>Please refer to the <a href="https://github.com/blueimp/jQuery-File-Upload">project website</a> and <a href="https://github.com/blueimp/jQuery-File-Upload/wiki">documentation</a> for more information.</li>
<li>Built with Twitter's <a href="http://twitter.github.com/bootstrap/">Bootstrap</a> CSS framework and Icons from <a href="http://glyphicons.com/">Glyphicons</a>.</li>
<li>Built with the <a href="http://getbootstrap.com/">Bootstrap</a> CSS framework and Icons from <a href="http://glyphicons.com/">Glyphicons</a>.</li>
</ul>
</div>
</div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="js/vendor/jquery.ui.widget.js"></script>
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->

View File

@ -1,50 +0,0 @@
{
"name": "blueimp-file-upload",
"version": "9.8.0",
"title": "jQuery File Upload",
"author": {
"name": "Sebastian Tschan",
"url": "https://blueimp.net"
},
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/MIT"
}
],
"dependencies": {
"jquery": ">=1.6"
},
"description": "File Upload widget with multiple file selection, drag&amp;drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.",
"keywords": [
"jquery",
"file",
"upload",
"widget",
"multiple",
"selection",
"drag",
"drop",
"progress",
"preview",
"cross-domain",
"cross-site",
"chunk",
"resume",
"gae",
"go",
"python",
"php",
"bootstrap"
],
"homepage": "https://github.com/blueimp/jQuery-File-Upload",
"docs": "https://github.com/blueimp/jQuery-File-Upload/wiki",
"demo": "https://blueimp.github.io/jQuery-File-Upload/",
"bugs": "https://github.com/blueimp/jQuery-File-Upload/issues",
"maintainers": [
{
"name": "Sebastian Tschan",
"url": "https://blueimp.net"
}
]
}

View File

@ -0,0 +1,16 @@
#!/usr/bin/env node
'use strict';
var path = require('path');
var packageJSON = require(path.join(__dirname, 'package.json'));
var bowerFile = path.join(__dirname, 'bower.json');
var bowerJSON = require('bower-json').parse(
require(bowerFile),
{normalize: true}
);
bowerJSON.version = packageJSON.version;
require('fs').writeFileSync(
bowerFile,
JSON.stringify(bowerJSON, null, 2) + '\n'
);

View File

@ -1,8 +1,8 @@
{
"name": "blueimp-file-upload",
"version": "9.8.0",
"version": "9.18.0",
"title": "jQuery File Upload",
"description": "File Upload widget with multiple file selection, drag&amp;drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.",
"description": "File Upload widget with multiple file selection, drag&amp;drop support, progress bar, validation and preview images.",
"keywords": [
"jquery",
"file",
@ -40,12 +40,7 @@
"url": "git://github.com/blueimp/jQuery-File-Upload.git"
},
"bugs": "https://github.com/blueimp/jQuery-File-Upload/issues",
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/MIT"
}
],
"license": "MIT",
"dependencies": {
"jquery": ">=1.6",
"blueimp-tmpl": ">=2.5.4",
@ -53,23 +48,7 @@
"blueimp-canvas-to-blob": ">=2.1.1"
},
"main": [
"css/jquery.fileupload.css",
"css/jquery.fileupload-ui.css",
"css/jquery.fileupload-noscript.css",
"css/jquery.fileupload-ui-noscript.css",
"js/cors/jquery.postmessage-transport.js",
"js/cors/jquery.xdr-transport.js",
"js/vendor/jquery.ui.widget.js",
"js/jquery.fileupload.js",
"js/jquery.fileupload-process.js",
"js/jquery.fileupload-validate.js",
"js/jquery.fileupload-image.js",
"js/jquery.fileupload-audio.js",
"js/jquery.fileupload-video.js",
"js/jquery.fileupload-ui.js",
"js/jquery.fileupload-jquery-ui.js",
"js/jquery.fileupload-angular.js",
"js/jquery.iframe-transport.js"
"js/jquery.fileupload.js"
],
"ignore": [
"/*.*",

View File

@ -1,14 +1,14 @@
<!DOCTYPE HTML>
<!--
/*
* jQuery File Upload Plugin postMessage API 1.2.1
* jQuery File Upload Plugin postMessage API
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2011, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
-->
<html lang="en">

View File

@ -1,14 +1,14 @@
<!DOCTYPE HTML>
<!--
/*
* jQuery Iframe Transport Plugin Redirect Page 2.0.1
* jQuery Iframe Transport Plugin Redirect Page
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
-->
<html lang="en">

View File

@ -1,13 +1,13 @@
@charset "UTF-8";
/*
* jQuery File Upload Demo CSS Fixes for IE<9 1.0.0
* jQuery File Upload Demo CSS Fixes for IE<9
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
.navigation {

View File

@ -1,13 +1,13 @@
@charset "UTF-8";
/*
* jQuery File Upload Demo CSS 1.1.0
* jQuery File Upload Demo CSS
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
body {

View File

@ -1,20 +1,20 @@
@charset "UTF-8";
/*
* jQuery File Upload Plugin NoScript CSS 1.2.0
* jQuery File Upload Plugin NoScript CSS
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
.fileinput-button input {
position: static;
opacity: 1;
filter: none;
font-size: inherit;
font-size: inherit !important;
direction: inherit;
}
.fileinput-button span {

View File

@ -1,13 +1,13 @@
@charset "UTF-8";
/*
* jQuery File Upload UI Plugin NoScript CSS 8.8.5
* jQuery File Upload UI Plugin NoScript CSS
* 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
* https://opensource.org/licenses/MIT
*/
.fileinput-button i,

View File

@ -1,13 +1,13 @@
@charset "UTF-8";
/*
* jQuery File Upload UI Plugin CSS 9.0.0
* jQuery File Upload UI Plugin CSS
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
.fileupload-buttonbar .btn,

View File

@ -1,18 +1,19 @@
@charset "UTF-8";
/*
* jQuery File Upload Plugin CSS 1.3.0
* jQuery File Upload Plugin CSS
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
.fileinput-button {
position: relative;
overflow: hidden;
display: inline-block;
}
.fileinput-button input {
position: absolute;
@ -21,7 +22,7 @@
margin: 0;
opacity: 0;
-ms-filter: 'alpha(opacity=0)';
font-size: 200px;
font-size: 200px !important;
direction: ltr;
cursor: pointer;
}

View File

@ -1,13 +1,13 @@
@charset "UTF-8";
/*
* jQuery File Upload Plugin CSS Example 8.8.2
* jQuery File Upload Plugin CSS Example
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
body {

View File

@ -1,14 +1,14 @@
<!DOCTYPE HTML>
<!--
/*
* jQuery File Upload Plugin Demo 9.1.0
* jQuery File Upload Plugin Demo
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
-->
<html lang="en">
@ -121,9 +121,9 @@
</div>
<div class="panel-body">
<ul>
<li>The maximum file size for uploads in this demo is <strong>5 MB</strong> (default file size is unlimited).</li>
<li>The maximum file size for uploads in this demo is <strong>999 KB</strong> (default file size is unlimited).</li>
<li>Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in this demo (by default there is no file type restriction).</li>
<li>Uploaded files will be deleted automatically after <strong>5 minutes</strong> (demo setting).</li>
<li>Uploaded files will be deleted automatically after <strong>5 minutes or less</strong> (demo files are stored in memory).</li>
<li>You can <strong>drag &amp; drop</strong> files from your desktop on this webpage (see <a href="https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support">Browser support</a>).</li>
<li>Please refer to the <a href="https://github.com/blueimp/jQuery-File-Upload">project website</a> and <a href="https://github.com/blueimp/jQuery-File-Upload/wiki">documentation</a> for more information.</li>
<li>Built with the <a href="http://getbootstrap.com/">Bootstrap</a> CSS framework and Icons from <a href="http://glyphicons.com/">Glyphicons</a>.</li>
@ -216,7 +216,7 @@
</tr>
{% } %}
</script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="js/vendor/jquery.ui.widget.js"></script>
<!-- The Templates plugin is included to render the upload/download listings -->

View File

@ -1,14 +1,14 @@
<!DOCTYPE HTML>
<!--
/*
* jQuery File Upload Plugin jQuery UI Demo 9.1.0
* jQuery File Upload Plugin jQuery UI Demo
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
-->
<html lang="en">
@ -127,9 +127,9 @@
<br>
<h3>Demo Notes</h3>
<ul>
<li>The maximum file size for uploads in this demo is <strong>5 MB</strong> (default file size is unlimited).</li>
<li>The maximum file size for uploads in this demo is <strong>999 KB</strong> (default file size is unlimited).</li>
<li>Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in this demo (by default there is no file type restriction).</li>
<li>Uploaded files will be deleted automatically after <strong>5 minutes</strong> (demo setting).</li>
<li>Uploaded files will be deleted automatically after <strong>5 minutes or less</strong> (demo files are stored in memory).</li>
<li>You can <strong>drag &amp; drop</strong> files from your desktop on this webpage (see <a href="https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support">Browser support</a>).</li>
<li>Please refer to the <a href="https://github.com/blueimp/jQuery-File-Upload">project website</a> and <a href="https://github.com/blueimp/jQuery-File-Upload/wiki">documentation</a> for more information.</li>
<li>Built with <a href="https://jqueryui.com">jQuery UI</a>.</li>
@ -199,8 +199,8 @@
</tr>
{% } %}
</script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<!-- The Templates plugin is included to render the upload/download listings -->
<script src="//blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->

View File

@ -1,18 +1,18 @@
/*
* jQuery File Upload Plugin Angular JS Example 1.2.1
* jQuery File Upload Plugin Angular JS Example
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* jshint nomen:false */
/* global window, angular */
(function () {
;(function () {
'use strict';
var isOnGitHub = window.location.hostname === 'blueimp.github.io',
@ -37,7 +37,7 @@
// send Blob objects via XHR requests:
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator.userAgent),
maxFileSize: 5000000,
maxFileSize: 999000,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
});
}

View File

@ -1,21 +1,24 @@
/*
* jQuery postMessage Transport Plugin 1.1.1
* jQuery postMessage Transport Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2011, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* global define, window, document */
/* global define, require, window, document */
(function (factory) {
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(require('jquery'));
} else {
// Browser globals:
factory(window.jQuery);
@ -61,6 +64,12 @@
loc = $('<a>').prop('href', options.postMessage)[0],
target = loc.protocol + '//' + loc.host,
xhrUpload = options.xhr().upload;
// IE always includes the port for the host property of a link
// element, but not in the location.host or origin property for the
// default http port 80 and https port 443, so we strip it:
if (/^(http:\/\/.+:80)|(https:\/\/.+:443)$/.test(target)) {
target = target.replace(/:(80|443)$/, '');
}
return {
send: function (_, completeCallback) {
counter += 1;

View File

@ -1,24 +1,27 @@
/*
* jQuery XDomainRequest Transport Plugin 1.1.3
* jQuery XDomainRequest Transport Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2011, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*
* Based on Julian Aubourg's ajaxHooks xdr.js:
* https://github.com/jaubourg/ajaxHooks/
*/
/* global define, window, XDomainRequest */
/* global define, require, window, XDomainRequest */
(function (factory) {
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(require('jquery'));
} else {
// Browser globals:
factory(window.jQuery);

View File

@ -1,18 +1,18 @@
/*
* jQuery File Upload AngularJS Plugin 2.2.0
* jQuery File Upload AngularJS Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* jshint nomen:false */
/* global define, angular */
/* global define, angular, require */
(function (factory) {
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
@ -24,6 +24,16 @@
'./jquery.fileupload-video',
'./jquery.fileupload-validate'
], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(
require('jquery'),
require('angular'),
require('./jquery.fileupload-image'),
require('./jquery.fileupload-audio'),
require('./jquery.fileupload-video'),
require('./jquery.fileupload-validate')
);
} else {
factory();
}
@ -91,7 +101,7 @@
angular.forEach(data.files, function (file) {
filesCopy.push(file);
});
scope.$apply(function () {
scope.$parent.$applyAsync(function () {
addFileMethods(scope, data);
var method = scope.option('prependFiles') ?
'unshift' : 'push';
@ -100,7 +110,7 @@
data.process(function () {
return scope.process(data);
}).always(function () {
scope.$apply(function () {
scope.$parent.$applyAsync(function () {
addFileMethods(scope, data);
scope.replace(filesCopy, data.files);
});
@ -112,12 +122,6 @@
}
});
},
progress: function (e, data) {
if (e.isDefaultPrevented()) {
return false;
}
data.scope.$apply();
},
done: function (e, data) {
if (e.isDefaultPrevented()) {
return false;
@ -197,8 +201,8 @@
// The FileUploadController initializes the fileupload widget and
// provides scope methods to control the File Upload functionality:
.controller('FileUploadController', [
'$scope', '$element', '$attrs', '$window', 'fileUpload',
function ($scope, $element, $attrs, $window, fileUpload) {
'$scope', '$element', '$attrs', '$window', 'fileUpload','$q',
function ($scope, $element, $attrs, $window, fileUpload, $q) {
var uploadMethods = {
progress: function () {
return $element.fileupload('progress');
@ -260,19 +264,21 @@
$scope.applyOnQueue = function (method) {
var list = this.queue.slice(0),
i,
file;
file,
promises = [];
for (i = 0; i < list.length; i += 1) {
file = list[i];
if (file[method]) {
file[method]();
promises.push(file[method]());
}
}
return $q.all(promises);
};
$scope.submit = function () {
this.applyOnQueue('$submit');
return this.applyOnQueue('$submit');
};
$scope.cancel = function () {
this.applyOnQueue('$cancel');
return this.applyOnQueue('$cancel');
};
// Add upload methods to the scope:
angular.extend($scope, uploadMethods);
@ -320,9 +326,11 @@
'fileuploadprocessalways',
'fileuploadprocessstop'
].join(' '), function (e, data) {
if ($scope.$emit(e.type, data).defaultPrevented) {
e.preventDefault();
}
$scope.$parent.$applyAsync(function () {
if ($scope.$emit(e.type, data).defaultPrevented) {
e.preventDefault();
}
});
}).on('remove', function () {
// Remove upload methods from the scope,
// when the widget is removed:

View File

@ -1,18 +1,18 @@
/*
* jQuery File Upload Audio Preview Plugin 1.0.3
* jQuery File Upload Audio Preview Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* jshint nomen:false */
/* global define, window, document */
/* global define, require, window, document */
(function (factory) {
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
@ -21,6 +21,13 @@
'load-image',
'./jquery.fileupload-process'
], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(
require('jquery'),
require('blueimp-load-image/js/load-image'),
require('./jquery.fileupload-process')
);
} else {
// Browser globals:
factory(

View File

@ -1,18 +1,18 @@
/*
* jQuery File Upload Image Preview & Resize Plugin 1.7.2
* jQuery File Upload Image Preview & Resize Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* jshint nomen:false */
/* global define, window, Blob */
/* global define, require, window, Blob */
(function (factory) {
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
@ -20,11 +20,22 @@
'jquery',
'load-image',
'load-image-meta',
'load-image-scale',
'load-image-exif',
'load-image-ios',
'canvas-to-blob',
'./jquery.fileupload-process'
], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(
require('jquery'),
require('blueimp-load-image/js/load-image'),
require('blueimp-load-image/js/load-image-meta'),
require('blueimp-load-image/js/load-image-scale'),
require('blueimp-load-image/js/load-image-exif'),
require('blueimp-canvas-to-blob'),
require('./jquery.fileupload-process')
);
} else {
// Browser globals:
factory(
@ -236,7 +247,7 @@
blob.name = file.name;
} else if (file.name) {
blob.name = file.name.replace(
/\..+$/,
/\.\w+$/,
'.' + blob.type.substr(6)
);
}

View File

@ -1,22 +1,31 @@
/*
* jQuery File Upload jQuery UI Plugin 8.7.1
* jQuery File Upload jQuery UI Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* jshint nomen:false */
/* global define, window */
/* global define, require, window */
(function (factory) {
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
define(['jquery', './jquery.fileupload-ui'], factory);
define([
'jquery',
'./jquery.fileupload-ui'
], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(
require('jquery'),
require('./jquery.fileupload-ui')
);
} else {
// Browser globals:
factory(window.jQuery);

View File

@ -1,18 +1,18 @@
/*
* jQuery File Upload Processing Plugin 1.3.0
* jQuery File Upload Processing Plugin
* 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
* https://opensource.org/licenses/MIT
*/
/* jshint nomen:false */
/* global define, window */
/* global define, require, window */
(function (factory) {
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
@ -20,6 +20,12 @@
'jquery',
'./jquery.fileupload'
], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(
require('jquery'),
require('./jquery.fileupload')
);
} else {
// Browser globals:
factory(
@ -81,7 +87,7 @@
settings
);
};
chain = chain.pipe(func, settings.always && func);
chain = chain.then(func, settings.always && func);
});
chain
.done(function () {
@ -148,7 +154,7 @@
};
opts.index = index;
that._processing += 1;
that._processingQueue = that._processingQueue.pipe(func, func)
that._processingQueue = that._processingQueue.then(func, func)
.always(function () {
that._processing -= 1;
if (that._processing === 0) {

View File

@ -1,29 +1,38 @@
/*
* jQuery File Upload User Interface Plugin 9.6.0
* jQuery File Upload User Interface Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* jshint nomen:false */
/* global define, window */
/* global define, require, window */
(function (factory) {
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
define([
'jquery',
'tmpl',
'blueimp-tmpl',
'./jquery.fileupload-image',
'./jquery.fileupload-audio',
'./jquery.fileupload-video',
'./jquery.fileupload-validate'
], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(
require('jquery'),
require('blueimp-tmpl'),
require('./jquery.fileupload-image'),
require('./jquery.fileupload-video'),
require('./jquery.fileupload-validate')
);
} else {
// Browser globals:
factory(

View File

@ -1,17 +1,17 @@
/*
* jQuery File Upload Validation Plugin 1.1.2
* jQuery File Upload Validation Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* global define, window */
/* global define, require, window */
(function (factory) {
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
@ -19,6 +19,12 @@
'jquery',
'./jquery.fileupload-process'
], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(
require('jquery'),
require('./jquery.fileupload-process')
);
} else {
// Browser globals:
factory(

View File

@ -1,18 +1,18 @@
/*
* jQuery File Upload Video Preview Plugin 1.0.3
* jQuery File Upload Video Preview Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* jshint nomen:false */
/* global define, window, document */
/* global define, require, window, document */
(function (factory) {
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
@ -21,6 +21,13 @@
'load-image',
'./jquery.fileupload-process'
], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(
require('jquery'),
require('blueimp-load-image/js/load-image'),
require('./jquery.fileupload-process')
);
} else {
// Browser globals:
factory(

View File

@ -1,25 +1,31 @@
/*
* jQuery File Upload Plugin 5.42.0
* jQuery File Upload Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* jshint nomen:false */
/* global define, window, document, location, Blob, FormData */
/* global define, require, window, document, location, Blob, FormData */
(function (factory) {
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
define([
'jquery',
'jquery.ui.widget'
'jquery-ui/ui/widget'
], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(
require('jquery'),
require('./vendor/jquery.ui.widget')
);
} else {
// Browser globals:
factory(window.jQuery);
@ -271,7 +277,8 @@
// The following are jQuery ajax settings required for the file uploads:
processData: false,
contentType: false,
cache: false
cache: false,
timeout: 0
},
// A list of options that require reinitializing event listeners and/or
@ -645,7 +652,7 @@
data.process = function (resolveFunc, rejectFunc) {
if (resolveFunc || rejectFunc) {
data._processQueue = this._processQueue =
(this._processQueue || getPromise([this])).pipe(
(this._processQueue || getPromise([this])).then(
function () {
if (data.errorThrown) {
return $.Deferred()
@ -653,7 +660,7 @@
}
return getPromise(arguments);
}
).pipe(resolveFunc, rejectFunc);
).then(resolveFunc, rejectFunc);
}
return this._processQueue || getPromise([this]);
};
@ -938,9 +945,9 @@
if (this.options.limitConcurrentUploads > 1) {
slot = $.Deferred();
this._slots.push(slot);
pipe = slot.pipe(send);
pipe = slot.then(send);
} else {
this._sequence = this._sequence.pipe(send, send);
this._sequence = this._sequence.then(send, send);
pipe = this._sequence;
}
// Return the piped Promise object, enhanced with an abort method,
@ -977,7 +984,10 @@
fileSet,
i,
j = 0;
if (limitSize && (!filesLength || files[0].size === undefined)) {
if (!filesLength) {
return false;
}
if (limitSize && files[0].size === undefined) {
limitSize = undefined;
}
if (!(options.singleFileUploads || limit || limitSize) ||
@ -1036,13 +1046,19 @@
_replaceFileInput: function (data) {
var input = data.fileInput,
inputClone = input.clone(true);
inputClone = input.clone(true),
restoreFocus = input.is(document.activeElement);
// Add a reference for the new cloned file input to the data argument:
data.fileInputClone = inputClone;
$('<form></form>').append(inputClone)[0].reset();
// Detaching allows to insert the fileInput on another form
// without loosing the file input value:
input.after(inputClone).detach();
// If the fileInput had focus before it was detached,
// restore focus to the inputClone.
if (restoreFocus) {
inputClone.focus();
}
// Avoid memory leaks with the detached file input:
$.cleanData(input.unbind('remove'));
// Replace the original file input element in the fileInput
@ -1064,6 +1080,8 @@
_handleFileTreeEntry: function (entry, path) {
var that = this,
dfd = $.Deferred(),
entries = [],
dirReader,
errorHandler = function (e) {
if (e && !e.entry) {
e.entry = entry;
@ -1091,8 +1109,7 @@
readEntries();
}
}, errorHandler);
},
dirReader, entries = [];
};
path = path || '';
if (entry.isFile) {
if (entry._file) {
@ -1123,7 +1140,7 @@
$.map(entries, function (entry) {
return that._handleFileTreeEntry(entry, path);
})
).pipe(function () {
).then(function () {
return Array.prototype.concat.apply(
[],
arguments
@ -1192,7 +1209,7 @@
return $.when.apply(
$,
$.map(fileInput, this._getSingleFileInputFiles)
).pipe(function () {
).then(function () {
return Array.prototype.concat.apply(
[],
arguments
@ -1295,6 +1312,10 @@
this._off(this.options.fileInput, 'change');
},
_destroy: function () {
this._destroyEventHandlers();
},
_setOption: function (key, value) {
var reinit = $.inArray(key, this._specialOptions) !== -1;
if (reinit) {
@ -1338,15 +1359,19 @@
_initDataAttributes: function () {
var that = this,
options = this.options,
clone = $(this.element[0].cloneNode(false));
data = this.element.data();
// Initialize options set via HTML5 data-attributes:
$.each(
clone.data(),
function (key, value) {
var dataAttributeName = 'data-' +
// Convert camelCase to hyphen-ated key:
key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
if (clone.attr(dataAttributeName)) {
this.element[0].attributes,
function (index, attr) {
var key = attr.name.toLowerCase(),
value;
if (/^data-/.test(key)) {
// Convert hyphen-ated key to camelCase:
key = key.slice(5).replace(/-[a-z]/g, function (str) {
return str.charAt(1).toUpperCase();
});
value = data[key];
if (that._isRegExpOption(key, value)) {
value = that._getRegExp(value);
}

View File

@ -1,21 +1,24 @@
/*
* jQuery Iframe Transport Plugin 1.8.2
* jQuery Iframe Transport Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2011, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* global define, window, document */
/* global define, require, window, document, JSON */
(function (factory) {
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(require('jquery'));
} else {
// Browser globals:
factory(window.jQuery);
@ -24,7 +27,14 @@
'use strict';
// Helper variable to create unique names for the transport iframes:
var counter = 0;
var counter = 0,
jsonAPI = $,
jsonParse = 'parseJSON';
if ('JSON' in window && 'parse' in JSON) {
jsonAPI = JSON;
jsonParse = 'parse';
}
// The iframe transport accepts four additional options:
// options.fileInput: a jQuery collection of file input fields
@ -194,7 +204,7 @@
return iframe && $(iframe[0].body).text();
},
'iframe json': function (iframe) {
return iframe && $.parseJSON($(iframe[0].body).text());
return iframe && jsonAPI[jsonParse]($(iframe[0].body).text());
},
'iframe html': function (iframe) {
return iframe && $(iframe[0].body).html();

View File

@ -1,12 +1,12 @@
/*
* jQuery File Upload Plugin JS Example 8.9.1
* jQuery File Upload Plugin JS Example
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* global $, window */
@ -40,7 +40,7 @@ $(function () {
// send Blob objects via XHR requests:
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator.userAgent),
maxFileSize: 5000000,
maxFileSize: 999000,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
});
// Upload server status check for browsers with CORS support:

View File

@ -1,13 +1,19 @@
/*! jQuery UI - v1.11.1 - 2014-09-17
/*! jQuery UI - v1.11.4+CommonJS - 2015-08-28
* http://jqueryui.com
* Includes: widget.js
* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
(function( factory ) {
if ( typeof define === "function" && define.amd ) {
// AMD. Register as an anonymous module.
define([ "jquery" ], factory );
} else if ( typeof exports === "object" ) {
// Node/CommonJS
factory( require( "jquery" ) );
} else {
// Browser globals
@ -15,10 +21,10 @@
}
}(function( $ ) {
/*!
* jQuery UI Widget 1.11.1
* jQuery UI Widget 1.11.4
* http://jqueryui.com
*
* Copyright 2014 jQuery Foundation and other contributors
* Copyright jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
@ -42,7 +48,7 @@ $.cleanData = (function( orig ) {
}
// http://bugs.jquery.com/ticket/8235
} catch( e ) {}
} catch ( e ) {}
}
orig( elems );
};
@ -196,11 +202,6 @@ $.widget.bridge = function( name, object ) {
args = widget_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,
@ -225,6 +226,12 @@ $.widget.bridge = function( name, object ) {
}
});
} else {
// Allow multiple hashes to be passed on init
if ( args.length ) {
options = $.widget.extend.apply( null, [ options ].concat(args) );
}
this.each(function() {
var instance = $.data( this, fullName );
if ( instance ) {
@ -260,10 +267,6 @@ $.Widget.prototype = {
this.element = $( element );
this.uuid = widget_uuid++;
this.eventNamespace = "." + this.widgetName + this.uuid;
this.options = $.widget.extend( {},
this.options,
this._getCreateOptions(),
options );
this.bindings = $();
this.hoverable = $();
@ -286,6 +289,11 @@ $.Widget.prototype = {
this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
}
this.options = $.widget.extend( {},
this.options,
this._getCreateOptions(),
options );
this._create();
this._trigger( "create", null, this._getCreateEventData() );
this._init();
@ -448,8 +456,14 @@ $.Widget.prototype = {
},
_off: function( element, eventName ) {
eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
this.eventNamespace;
element.unbind( eventName ).undelegate( eventName );
// Clear the stack to avoid memory leaks (#10056)
this.bindings = $( this.bindings.not( element ).get() );
this.focusable = $( this.focusable.not( element ).get() );
this.hoverable = $( this.hoverable.not( element ).get() );
},
_delay: function( handler, delay ) {

View File

@ -1,8 +1,8 @@
{
"name": "blueimp-file-upload",
"version": "9.8.0",
"version": "9.18.0",
"title": "jQuery File Upload",
"description": "File Upload widget with multiple file selection, drag&amp;drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.",
"description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.",
"keywords": [
"jquery",
"file",
@ -29,26 +29,27 @@
"name": "Sebastian Tschan",
"url": "https://blueimp.net"
},
"maintainers": [
{
"name": "Sebastian Tschan",
"url": "https://blueimp.net"
}
],
"repository": {
"type": "git",
"url": "git://github.com/blueimp/jQuery-File-Upload.git"
},
"bugs": "https://github.com/blueimp/jQuery-File-Upload/issues",
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/MIT"
}
],
"license": "MIT",
"optionalDependencies": {
"blueimp-canvas-to-blob": "3.5.0",
"blueimp-load-image": "2.12.2",
"blueimp-tmpl": "3.6.0"
},
"devDependencies": {
"grunt": "~0.4.5",
"grunt-bump-build-git": "~1.1.1",
"grunt-contrib-jshint": "~0.10.0"
}
"bower-json": "0.8.1",
"jshint": "2.9.3"
},
"scripts": {
"bower-version-update": "./bower-version-update.js",
"lint": "jshint *.js js/*.js js/cors/*.js",
"test": "npm run lint",
"preversion": "npm test",
"version": "npm run bower-version-update && git add bower.json",
"postversion": "git push --tags origin master && npm publish"
},
"main": "js/jquery.fileupload.js"
}

View File

@ -1,59 +1,90 @@
/*
* jQuery File Upload Plugin GAE Go Example 3.2.0
* jQuery File Upload Plugin GAE Go Example
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2011, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
package app
import (
"appengine"
"appengine/blobstore"
"appengine/image"
"appengine/taskqueue"
"bufio"
"bytes"
"encoding/json"
"fmt"
"github.com/disintegration/gift"
"golang.org/x/net/context"
"google.golang.org/appengine"
"google.golang.org/appengine/memcache"
"hash/crc32"
"image"
"image/gif"
"image/jpeg"
"image/png"
"io"
"log"
"mime/multipart"
"net/http"
"net/url"
"path/filepath"
"regexp"
"strings"
"time"
)
const (
WEBSITE = "https://blueimp.github.io/jQuery-File-Upload/"
MIN_FILE_SIZE = 1 // bytes
MAX_FILE_SIZE = 5000000 // bytes
WEBSITE = "https://blueimp.github.io/jQuery-File-Upload/"
MIN_FILE_SIZE = 1 // bytes
// Max file size is memcache limit (1MB) minus key size minus overhead:
MAX_FILE_SIZE = 999000 // bytes
IMAGE_TYPES = "image/(gif|p?jpeg|(x-)?png)"
ACCEPT_FILE_TYPES = IMAGE_TYPES
THUMB_MAX_WIDTH = 80
THUMB_MAX_HEIGHT = 80
EXPIRATION_TIME = 300 // seconds
THUMBNAIL_PARAM = "=s80"
// If empty, only allow redirects to the referer protocol+host.
// Set to a regexp string for custom pattern matching:
REDIRECT_ALLOW_TARGET = ""
)
var (
imageTypes = regexp.MustCompile(IMAGE_TYPES)
acceptFileTypes = regexp.MustCompile(ACCEPT_FILE_TYPES)
thumbSuffix = "." + fmt.Sprint(THUMB_MAX_WIDTH) + "x" +
fmt.Sprint(THUMB_MAX_HEIGHT)
)
func escape(s string) string {
return strings.Replace(url.QueryEscape(s), "+", "%20", -1)
}
func extractKey(r *http.Request) string {
// Use RequestURI instead of r.URL.Path, as we need the encoded form:
path := strings.Split(r.RequestURI, "?")[0]
// Also adjust double encoded slashes:
return strings.Replace(path[1:], "%252F", "%2F", -1)
}
func check(err error) {
if err != nil {
panic(err)
}
}
type FileInfo struct {
Key appengine.BlobKey `json:"-"`
Url string `json:"url,omitempty"`
ThumbnailUrl string `json:"thumbnailUrl,omitempty"`
Name string `json:"name"`
Type string `json:"type"`
Size int64 `json:"size"`
Error string `json:"error,omitempty"`
DeleteUrl string `json:"deleteUrl,omitempty"`
DeleteType string `json:"deleteType,omitempty"`
Key string `json:"-"`
ThumbnailKey string `json:"-"`
Url string `json:"url,omitempty"`
ThumbnailUrl string `json:"thumbnailUrl,omitempty"`
Name string `json:"name"`
Type string `json:"type"`
Size int64 `json:"size"`
Error string `json:"error,omitempty"`
DeleteUrl string `json:"deleteUrl,omitempty"`
DeleteType string `json:"deleteType,omitempty"`
}
func (fi *FileInfo) ValidateType() (valid bool) {
@ -75,50 +106,58 @@ func (fi *FileInfo) ValidateSize() (valid bool) {
return false
}
func (fi *FileInfo) CreateUrls(r *http.Request, c appengine.Context) {
func (fi *FileInfo) CreateUrls(r *http.Request, c context.Context) {
u := &url.URL{
Scheme: r.URL.Scheme,
Host: appengine.DefaultVersionHostname(c),
Path: "/",
}
uString := u.String()
fi.Url = uString + escape(string(fi.Key)) + "/" +
escape(string(fi.Name))
fi.DeleteUrl = fi.Url + "?delete=true"
fi.Url = uString + fi.Key
fi.DeleteUrl = fi.Url
fi.DeleteType = "DELETE"
if fi.ThumbnailKey != "" {
fi.ThumbnailUrl = uString + fi.ThumbnailKey
}
}
func (fi *FileInfo) SetKey(checksum uint32) {
fi.Key = escape(string(fi.Type)) + "/" +
escape(fmt.Sprint(checksum)) + "/" +
escape(string(fi.Name))
}
func (fi *FileInfo) createThumb(buffer *bytes.Buffer, c context.Context) {
if imageTypes.MatchString(fi.Type) {
servingUrl, err := image.ServingURL(
c,
fi.Key,
&image.ServingURLOptions{
Secure: strings.HasSuffix(u.Scheme, "s"),
Size: 0,
Crop: false,
},
)
src, _, err := image.Decode(bytes.NewReader(buffer.Bytes()))
check(err)
fi.ThumbnailUrl = servingUrl.String() + THUMBNAIL_PARAM
}
}
func check(err error) {
if err != nil {
panic(err)
}
}
func escape(s string) string {
return strings.Replace(url.QueryEscape(s), "+", "%20", -1)
}
func delayedDelete(c appengine.Context, fi *FileInfo) {
if key := string(fi.Key); key != "" {
task := &taskqueue.Task{
Path: "/" + escape(key) + "/-",
Method: "DELETE",
Delay: time.Duration(EXPIRATION_TIME) * time.Second,
filter := gift.New(gift.ResizeToFit(
THUMB_MAX_WIDTH,
THUMB_MAX_HEIGHT,
gift.LanczosResampling,
))
dst := image.NewNRGBA(filter.Bounds(src.Bounds()))
filter.Draw(dst, src)
buffer.Reset()
bWriter := bufio.NewWriter(buffer)
switch fi.Type {
case "image/jpeg", "image/pjpeg":
err = jpeg.Encode(bWriter, dst, nil)
case "image/gif":
err = gif.Encode(bWriter, dst, nil)
default:
err = png.Encode(bWriter, dst)
}
taskqueue.Add(c, task, "")
check(err)
bWriter.Flush()
thumbnailKey := fi.Key + thumbSuffix + filepath.Ext(fi.Name)
item := &memcache.Item{
Key: thumbnailKey,
Value: buffer.Bytes(),
}
err = memcache.Set(c, item)
check(err)
fi.ThumbnailKey = thumbnailKey
}
}
@ -136,24 +175,26 @@ func handleUpload(r *http.Request, p *multipart.Part) (fi *FileInfo) {
fi.Error = rec.(error).Error()
}
}()
var buffer bytes.Buffer
hash := crc32.NewIEEE()
mw := io.MultiWriter(&buffer, hash)
lr := &io.LimitedReader{R: p, N: MAX_FILE_SIZE + 1}
context := appengine.NewContext(r)
w, err := blobstore.Create(context, fi.Type)
defer func() {
w.Close()
fi.Size = MAX_FILE_SIZE + 1 - lr.N
fi.Key, err = w.Key()
check(err)
if !fi.ValidateSize() {
err := blobstore.Delete(context, fi.Key)
check(err)
return
}
delayedDelete(context, fi)
fi.CreateUrls(r, context)
}()
_, err := io.Copy(mw, lr)
check(err)
_, err = io.Copy(w, lr)
fi.Size = MAX_FILE_SIZE + 1 - lr.N
if !fi.ValidateSize() {
return
}
fi.SetKey(hash.Sum32())
item := &memcache.Item{
Key: fi.Key,
Value: buffer.Bytes(),
}
context := appengine.NewContext(r)
err = memcache.Set(context, item)
check(err)
fi.createThumb(&buffer, context)
fi.CreateUrls(r, context)
return
}
@ -183,49 +224,70 @@ func handleUploads(r *http.Request) (fileInfos []*FileInfo) {
return
}
func validateRedirect(r *http.Request, redirect string) bool {
if redirect != "" {
var redirectAllowTarget *regexp.Regexp
if REDIRECT_ALLOW_TARGET != "" {
redirectAllowTarget = regexp.MustCompile(REDIRECT_ALLOW_TARGET)
} else {
referer := r.Referer()
if referer == "" {
return false
}
refererUrl, err := url.Parse(referer)
if err != nil {
return false
}
redirectAllowTarget = regexp.MustCompile("^" + regexp.QuoteMeta(
refererUrl.Scheme+"://"+refererUrl.Host+"/",
))
}
return redirectAllowTarget.MatchString(redirect)
}
return false
}
func get(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
http.Redirect(w, r, WEBSITE, http.StatusFound)
return
}
parts := strings.Split(r.URL.Path, "/")
// Use RequestURI instead of r.URL.Path, as we need the encoded form:
key := extractKey(r)
parts := strings.Split(key, "/")
if len(parts) == 3 {
if key := parts[1]; key != "" {
blobKey := appengine.BlobKey(key)
bi, err := blobstore.Stat(appengine.NewContext(r), blobKey)
if err == nil {
w.Header().Add("X-Content-Type-Options", "nosniff")
if !imageTypes.MatchString(bi.ContentType) {
w.Header().Add("Content-Type", "application/octet-stream")
w.Header().Add(
"Content-Disposition",
fmt.Sprintf("attachment; filename=\"%s\"", parts[2]),
)
}
w.Header().Add(
"Cache-Control",
fmt.Sprintf("public,max-age=%d", EXPIRATION_TIME),
)
blobstore.Send(w, blobKey)
return
context := appengine.NewContext(r)
item, err := memcache.Get(context, key)
if err == nil {
w.Header().Add("X-Content-Type-Options", "nosniff")
contentType, _ := url.QueryUnescape(parts[0])
if !imageTypes.MatchString(contentType) {
contentType = "application/octet-stream"
}
w.Header().Add("Content-Type", contentType)
w.Header().Add(
"Cache-Control",
fmt.Sprintf("public,max-age=%d", EXPIRATION_TIME),
)
w.Write(item.Value)
return
}
}
http.Error(w, "404 Not Found", http.StatusNotFound)
}
func post(w http.ResponseWriter, r *http.Request) {
result := make(map[string][]*FileInfo, 1)
result["files"] = handleUploads(r)
result := make(map[string][]*FileInfo, 1)
result["files"] = handleUploads(r)
b, err := json.Marshal(result)
check(err)
if redirect := r.FormValue("redirect"); redirect != "" {
if strings.Contains(redirect, "%s") {
redirect = fmt.Sprintf(
redirect,
escape(string(b)),
)
}
if redirect := r.FormValue("redirect"); validateRedirect(r, redirect) {
if strings.Contains(redirect, "%s") {
redirect = fmt.Sprintf(
redirect,
escape(string(b)),
)
}
http.Redirect(w, r, redirect, http.StatusFound)
return
}
@ -238,27 +300,30 @@ func post(w http.ResponseWriter, r *http.Request) {
}
func delete(w http.ResponseWriter, r *http.Request) {
parts := strings.Split(r.URL.Path, "/")
if len(parts) != 3 {
return
}
result := make(map[string]bool, 1)
if key := parts[1]; key != "" {
c := appengine.NewContext(r)
blobKey := appengine.BlobKey(key)
err := blobstore.Delete(c, blobKey)
key := extractKey(r)
parts := strings.Split(key, "/")
if len(parts) == 3 {
result := make(map[string]bool, 1)
context := appengine.NewContext(r)
err := memcache.Delete(context, key)
if err == nil {
result[key] = true
contentType, _ := url.QueryUnescape(parts[0])
if imageTypes.MatchString(contentType) {
thumbnailKey := key + thumbSuffix + filepath.Ext(parts[2])
err := memcache.Delete(context, thumbnailKey)
if err == nil {
result[thumbnailKey] = true
}
}
}
w.Header().Set("Content-Type", "application/json")
b, err := json.Marshal(result)
check(err)
err = image.DeleteServingURL(c, blobKey)
check(err)
result[key] = true
fmt.Fprintln(w, string(b))
} else {
http.Error(w, "405 Method not allowed", http.StatusMethodNotAllowed)
}
jsonType := "application/json"
if strings.Index(r.Header.Get("Accept"), jsonType) != -1 {
w.Header().Set("Content-Type", jsonType)
}
b, err := json.Marshal(result)
check(err)
fmt.Fprintln(w, string(b))
}
func handle(w http.ResponseWriter, r *http.Request) {
@ -267,15 +332,15 @@ func handle(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Access-Control-Allow-Origin", "*")
w.Header().Add(
"Access-Control-Allow-Methods",
"OPTIONS, HEAD, GET, POST, PUT, DELETE",
"OPTIONS, HEAD, GET, POST, DELETE",
)
w.Header().Add(
"Access-Control-Allow-Headers",
"Content-Type, Content-Range, Content-Disposition",
)
switch r.Method {
case "OPTIONS":
case "HEAD":
case "OPTIONS", "HEAD":
return
case "GET":
get(w, r)
case "POST":

View File

@ -4,8 +4,9 @@ runtime: python27
api_version: 1
threadsafe: true
builtins:
- deferred: on
libraries:
- name: PIL
version: latest
handlers:
- url: /(favicon\.ico|robots\.txt)

View File

@ -1,49 +1,57 @@
# -*- coding: utf-8 -*-
#
# jQuery File Upload Plugin GAE Python Example 2.2.0
# jQuery File Upload Plugin GAE Python Example
# https://github.com/blueimp/jQuery-File-Upload
#
# Copyright 2011, Sebastian Tschan
# https://blueimp.net
#
# Licensed under the MIT license:
# http://www.opensource.org/licenses/MIT
# https://opensource.org/licenses/MIT
#
from __future__ import with_statement
from google.appengine.api import files, images
from google.appengine.ext import blobstore, deferred
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.api import memcache, images
import json
import os
import re
import urllib
import webapp2
DEBUG=os.environ.get('SERVER_SOFTWARE', '').startswith('Dev')
WEBSITE = 'https://blueimp.github.io/jQuery-File-Upload/'
MIN_FILE_SIZE = 1 # bytes
MAX_FILE_SIZE = 5000000 # bytes
# Max file size is memcache limit (1MB) minus key size minus overhead:
MAX_FILE_SIZE = 999000 # bytes
IMAGE_TYPES = re.compile('image/(gif|p?jpeg|(x-)?png)')
ACCEPT_FILE_TYPES = IMAGE_TYPES
THUMBNAIL_MODIFICATOR = '=s80' # max width / height
THUMB_MAX_WIDTH = 80
THUMB_MAX_HEIGHT = 80
THUMB_SUFFIX = '.'+str(THUMB_MAX_WIDTH)+'x'+str(THUMB_MAX_HEIGHT)+'.png'
EXPIRATION_TIME = 300 # seconds
# If set to None, only allow redirects to the referer protocol+host.
# Set to a regexp for custom pattern matching against the redirect value:
REDIRECT_ALLOW_TARGET = None
def cleanup(blob_keys):
blobstore.delete(blob_keys)
class UploadHandler(webapp2.RequestHandler):
class CORSHandler(webapp2.RequestHandler):
def cors(self):
headers = self.response.headers
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] =\
'OPTIONS, HEAD, GET, POST, DELETE'
headers['Access-Control-Allow-Headers'] =\
'Content-Type, Content-Range, Content-Disposition'
def initialize(self, request, response):
super(UploadHandler, self).initialize(request, response)
self.response.headers['Access-Control-Allow-Origin'] = '*'
self.response.headers[
'Access-Control-Allow-Methods'
] = 'OPTIONS, HEAD, GET, POST, PUT, DELETE'
self.response.headers[
'Access-Control-Allow-Headers'
] = 'Content-Type, Content-Range, Content-Disposition'
super(CORSHandler, self).initialize(request, response)
self.cors()
def json_stringify(self, obj):
return json.dumps(obj, separators=(',', ':'))
def options(self, *args, **kwargs):
pass
class UploadHandler(CORSHandler):
def validate(self, file):
if file['size'] < MIN_FILE_SIZE:
file['error'] = 'File is too small'
@ -55,6 +63,20 @@ class UploadHandler(webapp2.RequestHandler):
return True
return False
def validate_redirect(self, redirect):
if redirect:
if REDIRECT_ALLOW_TARGET:
return REDIRECT_ALLOW_TARGET.match(redirect)
referer = self.request.headers['referer']
if referer:
from urlparse import urlparse
parts = urlparse(referer)
redirect_allow_target = '^' + re.escape(
parts.scheme + '://' + parts.netloc + '/'
)
return re.match(redirect_allow_target, redirect)
return False
def get_file_size(self, file):
file.seek(0, 2) # Seek to the end of the file
size = file.tell() # Get the position of EOF
@ -62,64 +84,58 @@ class UploadHandler(webapp2.RequestHandler):
return size
def write_blob(self, data, info):
blob = files.blobstore.create(
mime_type=info['type'],
_blobinfo_uploaded_filename=info['name']
)
with files.open(blob, 'a') as f:
f.write(data)
files.finalize(blob)
return files.blobstore.get_blob_key(blob)
key = urllib.quote(info['type'].encode('utf-8'), '') +\
'/' + str(hash(data)) +\
'/' + urllib.quote(info['name'].encode('utf-8'), '')
try:
memcache.set(key, data, time=EXPIRATION_TIME)
except: #Failed to add to memcache
return (None, None)
thumbnail_key = None
if IMAGE_TYPES.match(info['type']):
try:
img = images.Image(image_data=data)
img.resize(
width=THUMB_MAX_WIDTH,
height=THUMB_MAX_HEIGHT
)
thumbnail_data = img.execute_transforms()
thumbnail_key = key + THUMB_SUFFIX
memcache.set(
thumbnail_key,
thumbnail_data,
time=EXPIRATION_TIME
)
except: #Failed to resize Image or add to memcache
thumbnail_key = None
return (key, thumbnail_key)
def handle_upload(self):
results = []
blob_keys = []
for name, fieldStorage in self.request.POST.items():
if type(fieldStorage) is unicode:
continue
result = {}
result['name'] = re.sub(
r'^.*\\',
'',
fieldStorage.filename
)
result['name'] = urllib.unquote(fieldStorage.filename)
result['type'] = fieldStorage.type
result['size'] = self.get_file_size(fieldStorage.file)
if self.validate(result):
blob_key = str(
self.write_blob(fieldStorage.value, result)
key, thumbnail_key = self.write_blob(
fieldStorage.value,
result
)
blob_keys.append(blob_key)
result['deleteType'] = 'DELETE'
result['deleteUrl'] = self.request.host_url +\
'/?key=' + urllib.quote(blob_key, '')
if (IMAGE_TYPES.match(result['type'])):
try:
result['url'] = images.get_serving_url(
blob_key,
secure_url=self.request.host_url.startswith(
'https'
)
)
result['thumbnailUrl'] = result['url'] +\
THUMBNAIL_MODIFICATOR
except: # Could not get an image serving url
pass
if not 'url' in result:
result['url'] = self.request.host_url +\
'/' + blob_key + '/' + urllib.quote(
result['name'].encode('utf-8'), '')
if key is not None:
result['url'] = self.request.host_url + '/' + key
result['deleteUrl'] = result['url']
result['deleteType'] = 'DELETE'
if thumbnail_key is not None:
result['thumbnailUrl'] = self.request.host_url +\
'/' + thumbnail_key
else:
result['error'] = 'Failed to store uploaded file.'
results.append(result)
deferred.defer(
cleanup,
blob_keys,
_countdown=EXPIRATION_TIME
)
return results
def options(self):
pass
def head(self):
pass
@ -130,9 +146,9 @@ class UploadHandler(webapp2.RequestHandler):
if (self.request.get('_method') == 'DELETE'):
return self.delete()
result = {'files': self.handle_upload()}
s = json.dumps(result, separators=(',', ':'))
s = self.json_stringify(result)
redirect = self.request.get('redirect')
if redirect:
if self.validate_redirect(redirect):
return self.redirect(str(
redirect.replace('%s', urllib.quote(s, ''), 1)
))
@ -140,31 +156,49 @@ class UploadHandler(webapp2.RequestHandler):
self.response.headers['Content-Type'] = 'application/json'
self.response.write(s)
def delete(self):
key = self.request.get('key') or ''
blobstore.delete(key)
s = json.dumps({key: True}, separators=(',', ':'))
class FileHandler(CORSHandler):
def normalize(self, str):
return urllib.quote(urllib.unquote(str), '')
def get(self, content_type, data_hash, file_name):
content_type = self.normalize(content_type)
file_name = self.normalize(file_name)
key = content_type + '/' + data_hash + '/' + file_name
data = memcache.get(key)
if data is None:
return self.error(404)
# Prevent browsers from MIME-sniffing the content-type:
self.response.headers['X-Content-Type-Options'] = 'nosniff'
content_type = urllib.unquote(content_type)
if not IMAGE_TYPES.match(content_type):
# Force a download dialog for non-image types:
content_type = 'application/octet-stream'
elif file_name.endswith(THUMB_SUFFIX):
content_type = 'image/png'
self.response.headers['Content-Type'] = content_type
# Cache for the expiration time:
self.response.headers['Cache-Control'] = 'public,max-age=%d' \
% EXPIRATION_TIME
self.response.write(data)
def delete(self, content_type, data_hash, file_name):
content_type = self.normalize(content_type)
file_name = self.normalize(file_name)
key = content_type + '/' + data_hash + '/' + file_name
result = {key: memcache.delete(key)}
content_type = urllib.unquote(content_type)
if IMAGE_TYPES.match(content_type):
thumbnail_key = key + THUMB_SUFFIX
result[thumbnail_key] = memcache.delete(thumbnail_key)
if 'application/json' in self.request.headers.get('Accept'):
self.response.headers['Content-Type'] = 'application/json'
s = self.json_stringify(result)
self.response.write(s)
class DownloadHandler(blobstore_handlers.BlobstoreDownloadHandler):
def get(self, key, filename):
if not blobstore.get(key):
self.error(404)
else:
# Prevent browsers from MIME-sniffing the content-type:
self.response.headers['X-Content-Type-Options'] = 'nosniff'
# Cache for the expiration time:
self.response.headers['Cache-Control'] = 'public,max-age=%d' % EXPIRATION_TIME
# Send the file forcing a download dialog:
self.send_blob(key, save_as=filename, content_type='application/octet-stream')
app = webapp2.WSGIApplication(
[
('/', UploadHandler),
('/([^/]+)/([^/]+)', DownloadHandler)
('/(.+)/([^/]+)/([^/]+)', FileHandler)
],
debug=True
debug=DEBUG
)

View File

@ -1,2 +0,0 @@
.DS_Store
node_modules

View File

@ -1,41 +0,0 @@
{
"name": "blueimp-file-upload-node",
"version": "2.1.0",
"title": "jQuery File Upload Node.js example",
"description": "Node.js implementation example of a file upload handler for jQuery File Upload.",
"keywords": [
"file",
"upload",
"cross-domain",
"cross-site",
"node"
],
"homepage": "https://github.com/blueimp/jQuery-File-Upload",
"author": {
"name": "Sebastian Tschan",
"url": "https://blueimp.net"
},
"maintainers": [
{
"name": "Sebastian Tschan",
"url": "https://blueimp.net"
}
],
"repository": {
"type": "git",
"url": "git://github.com/blueimp/jQuery-File-Upload.git"
},
"bugs": "https://github.com/blueimp/jQuery-File-Upload/issues",
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/MIT"
}
],
"dependencies": {
"formidable": ">=1.0.11",
"node-static": ">=0.6.5",
"imagemagick": ">=0.1.3"
},
"main": "server.js"
}

View File

@ -1,2 +0,0 @@
*
!.gitignore

View File

@ -1,292 +0,0 @@
#!/usr/bin/nodejs
/*
* jQuery File Upload Plugin Node.js Example 2.1.2
* 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);
});
handler.callback({files: files}, redirect);
}
};
form.uploadDir = options.tmpDir;
form.on('fileBegin', function (name, file) {
tmpFiles.push(file.path);
var fileInfo = new FileInfo(file);
fileInfo.safeName();
map[path.basename(file.path)] = fileInfo;
files.push(fileInfo);
}).on('field', function (name, value) {
if (name === 'redirect') {
redirect = value;
}
}).on('file', function (name, file) {
var fileInfo = map[path.basename(file.path)];
fileInfo.size = file.size;
if (!fileInfo.validate()) {
fs.unlink(file.path);
return;
}
fs.renameSync(file.path, options.uploadDir + '/' + fileInfo.name);
if (options.imageTypes.test(fileInfo.name)) {
Object.keys(options.imageVersions).forEach(function (version) {
counter += 1;
var opts = options.imageVersions[version];
imageMagick.resize({
width: opts.width,
height: opts.height,
srcPath: options.uploadDir + '/' + fileInfo.name,
dstPath: options.uploadDir + '/' + version + '/' +
fileInfo.name
}, finish);
});
}
}).on('aborted', function () {
tmpFiles.forEach(function (file) {
fs.unlink(file);
});
}).on('error', function (e) {
console.log(e);
}).on('progress', function (bytesReceived) {
if (bytesReceived > options.maxPostSize) {
handler.req.connection.destroy();
}
}).on('end', finish).parse(handler.req);
};
UploadHandler.prototype.destroy = function () {
var handler = this,
fileName;
if (handler.req.url.slice(0, options.uploadUrl.length) === options.uploadUrl) {
fileName = path.basename(decodeURIComponent(handler.req.url));
if (fileName[0] !== '.') {
fs.unlink(options.uploadDir + '/' + fileName, function (ex) {
Object.keys(options.imageVersions).forEach(function (version) {
fs.unlink(options.uploadDir + '/' + version + '/' + fileName);
});
handler.callback({success: !ex});
});
return;
}
}
handler.callback({success: false});
};
if (options.ssl) {
require('https').createServer(options.ssl, serve).listen(port);
} else {
require('http').createServer(serve).listen(port);
}
}(8888));

View File

@ -0,0 +1,38 @@
FROM php:7.0-apache
# Enable the Apache Headers module:
RUN ln -s /etc/apache2/mods-available/headers.load \
/etc/apache2/mods-enabled/headers.load
# Enable the Apache Rewrite module:
RUN ln -s /etc/apache2/mods-available/rewrite.load \
/etc/apache2/mods-enabled/rewrite.load
# Install GD, Imagick and ImageMagick as image conversion options:
RUN DEBIAN_FRONTEND=noninteractive \
apt-get update && apt-get install -y --no-install-recommends \
libpng-dev \
libjpeg-dev \
libmagickwand-dev \
imagemagick \
&& pecl install \
imagick \
&& docker-php-ext-enable \
imagick \
&& docker-php-ext-configure \
gd --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install \
gd \
# Uninstall obsolete packages:
&& apt-get autoremove -y \
libpng-dev \
libjpeg-dev \
libmagickwand-dev \
# Remove obsolete files:
&& apt-get clean \
&& rm -rf \
/tmp/* \
/usr/share/doc/* \
/var/cache/* \
/var/lib/apt/lists/* \
/var/tmp/*

View File

@ -1,13 +1,13 @@
<?php
/*
* jQuery File Upload Plugin PHP Class 8.1.0
* jQuery File Upload Plugin PHP Class
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
class UploadHandler
@ -40,11 +40,13 @@ class UploadHandler
protected $image_objects = array();
function __construct($options = null, $initialize = true, $error_messages = null) {
public function __construct($options = null, $initialize = true, $error_messages = null) {
$this->response = array();
$this->options = array(
'script_url' => $this->get_full_url().'/',
'script_url' => $this->get_full_url().'/'.$this->basename($this->get_server_var('SCRIPT_NAME')),
'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/files/',
'upload_url' => $this->get_full_url().'/files/',
'input_stream' => 'php://input',
'user_dirs' => false,
'mkdir_mode' => 0755,
'param_name' => 'files',
@ -67,6 +69,14 @@ class UploadHandler
'Content-Range',
'Content-Disposition'
),
// By default, allow redirects to the referer protocol+host:
'redirect_allow_target' => '/^'.preg_quote(
parse_url($this->get_server_var('HTTP_REFERER'), PHP_URL_SCHEME)
.'://'
.parse_url($this->get_server_var('HTTP_REFERER'), PHP_URL_HOST)
.'/', // Trailing slash to not match subdomains by mistake
'/' // preg_quote delimiter param
).'/',
// Enable to provide file downloads via GET requests to the PHP script:
// 1. Set to 1 to download files via readfile method through PHP
// 2. Set to 2 to send a X-Sendfile header for lighttpd/Apache
@ -147,7 +157,8 @@ class UploadHandler
'max_width' => 80,
'max_height' => 80
)
)
),
'print_response' => true
);
if ($options) {
$this->options = $options + $this->options;
@ -167,15 +178,15 @@ class UploadHandler
$this->head();
break;
case 'GET':
$this->get();
$this->get($this->options['print_response']);
break;
case 'PATCH':
case 'PUT':
case 'POST':
$this->post();
$this->post($this->options['print_response']);
break;
case 'DELETE':
$this->delete();
$this->delete($this->options['print_response']);
break;
default:
$this->header('HTTP/1.1 405 Method Not Allowed');
@ -300,7 +311,7 @@ class UploadHandler
$this->get_upload_path($file_name)
);
$file->url = $this->get_download_url($file->name);
foreach($this->options['image_versions'] as $version => $options) {
foreach ($this->options['image_versions'] as $version => $options) {
if (!empty($version)) {
if (is_file($this->get_upload_path($file_name, $version))) {
$file->{$version.'Url'} = $this->get_download_url(
@ -332,14 +343,15 @@ class UploadHandler
}
protected function get_error_message($error) {
return array_key_exists($error, $this->error_messages) ?
return isset($this->error_messages[$error]) ?
$this->error_messages[$error] : $error;
}
function get_config_bytes($val) {
public function get_config_bytes($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
switch($last) {
$val = (int)$val;
switch ($last) {
case 'g':
$val *= 1024;
case 'm':
@ -355,9 +367,9 @@ class UploadHandler
$file->error = $this->get_error_message($error);
return false;
}
$content_length = $this->fix_integer_overflow(intval(
$this->get_server_var('CONTENT_LENGTH')
));
$content_length = $this->fix_integer_overflow(
(int)$this->get_server_var('CONTENT_LENGTH')
);
$post_max_size = $this->get_config_bytes(ini_get('post_max_size'));
if ($post_max_size && ($content_length > $post_max_size)) {
$file->error = $this->get_error_message('post_max_size');
@ -398,6 +410,21 @@ class UploadHandler
if (($max_width || $max_height || $min_width || $min_height)
&& preg_match($this->options['image_file_types'], $file->name)) {
list($img_width, $img_height) = $this->get_image_size($uploaded_file);
// If we are auto rotating the image by default, do the checks on
// the correct orientation
if (
@$this->options['image_versions']['']['auto_orient'] &&
function_exists('exif_read_data') &&
($exif = @exif_read_data($uploaded_file)) &&
(((int) @$exif['Orientation']) >= 5)
) {
$tmp = $img_width;
$img_width = $img_height;
$img_height = $tmp;
unset($tmp);
}
}
if (!empty($img_width)) {
if ($max_width && $img_width > $max_width) {
@ -421,7 +448,7 @@ class UploadHandler
}
protected function upcount_name_callback($matches) {
$index = isset($matches[1]) ? intval($matches[1]) + 1 : 1;
$index = isset($matches[1]) ? ((int)$matches[1]) + 1 : 1;
$ext = isset($matches[2]) ? $matches[2] : '';
return ' ('.$index.')'.$ext;
}
@ -441,8 +468,8 @@ class UploadHandler
$name = $this->upcount_name($name);
}
// Keep an existing filename if this is part of a chunked upload:
$uploaded_bytes = $this->fix_integer_overflow(intval($content_range[1]));
while(is_file($this->get_upload_path($name))) {
$uploaded_bytes = $this->fix_integer_overflow((int)$content_range[1]);
while (is_file($this->get_upload_path($name))) {
if ($uploaded_bytes === $this->get_file_size(
$this->get_upload_path($name))) {
break;
@ -461,7 +488,7 @@ class UploadHandler
}
if ($this->options['correct_image_extensions'] &&
function_exists('exif_imagetype')) {
switch(@exif_imagetype($file_path)){
switch (@exif_imagetype($file_path)){
case IMAGETYPE_JPEG:
$extensions = array('jpg', 'jpeg');
break;
@ -491,7 +518,7 @@ class UploadHandler
// Remove path information and dots around the filename, to prevent uploading
// into different directories or replacing hidden system files.
// Also remove control characters and spaces (\x00..\x20) around the filename:
$name = trim(basename(stripslashes($name)), ".\x00..\x20");
$name = trim($this->basename(stripslashes($name)), ".\x00..\x20");
// Use a timestamp for empty filenames:
if (!$name) {
$name = str_replace('.', '-', microtime(true));
@ -515,10 +542,6 @@ class UploadHandler
);
}
protected function handle_form_data($file, $index) {
// Handle form data, e.g. $_REQUEST['description'][$index]
}
protected function get_scaled_image_file_paths($file_name, $version) {
$file_path = $this->get_upload_path($file_name);
if (!empty($version)) {
@ -601,7 +624,7 @@ class UploadHandler
if ($exif === false) {
return false;
}
$orientation = intval(@$exif['Orientation']);
$orientation = (int)@$exif['Orientation'];
if ($orientation < 2 || $orientation > 8) {
return false;
}
@ -825,7 +848,7 @@ class UploadHandler
$this->get_scaled_image_file_paths($file_name, $version);
$image = $this->imagick_get_image_object(
$file_path,
!empty($options['no_cache'])
!empty($options['crop']) || !empty($options['no_cache'])
);
if ($image->getImageFormat() === 'GIF') {
// Handle animated GIFs:
@ -955,7 +978,7 @@ class UploadHandler
return $dimensions;
}
return false;
} catch (Exception $e) {
} catch (\Exception $e) {
error_log($e->getMessage());
}
}
@ -965,7 +988,7 @@ class UploadHandler
exec($cmd, $output, $error);
if (!$error && !empty($output)) {
// image.jpg JPEG 1920x1080 1920x1080+0+0 8-bit sRGB 465KB 0.000u 0:00.000
$infos = preg_split('/\s+/', $output[0]);
$infos = preg_split('/\s+/', substr($output[0], strlen($file_path)));
$dimensions = preg_split('/x/', $infos[2]);
return $dimensions;
}
@ -1008,7 +1031,7 @@ class UploadHandler
protected function handle_image_file($file_path, $file) {
$failed_versions = array();
foreach($this->options['image_versions'] as $version => $options) {
foreach ($this->options['image_versions'] as $version => $options) {
if ($this->create_scaled_image($file->name, $version, $options)) {
if (!empty($version)) {
$file->{$version.'Url'} = $this->get_download_url(
@ -1024,7 +1047,7 @@ class UploadHandler
}
if (count($failed_versions)) {
$file->error = $this->get_error_message('image_resize')
.' ('.implode($failed_versions,', ').')';
.' ('.implode($failed_versions, ', ').')';
}
// Free memory:
$this->destroy_image_object($file_path);
@ -1035,7 +1058,7 @@ class UploadHandler
$file = new \stdClass();
$file->name = $this->get_file_name($uploaded_file, $name, $size, $type, $error,
$index, $content_range);
$file->size = $this->fix_integer_overflow(intval($size));
$file->size = $this->fix_integer_overflow((int)$size);
$file->type = $type;
if ($this->validate($uploaded_file, $file, $error, $index)) {
$this->handle_form_data($file, $index);
@ -1061,7 +1084,7 @@ class UploadHandler
// Non-multipart uploads (PUT method support)
file_put_contents(
$file_path,
fopen('php://input', 'r'),
fopen($this->options['input_stream'], 'r'),
$append_file ? FILE_APPEND : 0
);
}
@ -1107,36 +1130,28 @@ class UploadHandler
header($str);
}
protected function get_server_var($id) {
return isset($_SERVER[$id]) ? $_SERVER[$id] : '';
protected function get_upload_data($id) {
return @$_FILES[$id];
}
protected function generate_response($content, $print_response = true) {
if ($print_response) {
$json = json_encode($content);
$redirect = isset($_REQUEST['redirect']) ?
stripslashes($_REQUEST['redirect']) : null;
if ($redirect) {
$this->header('Location: '.sprintf($redirect, rawurlencode($json)));
return;
}
$this->head();
if ($this->get_server_var('HTTP_CONTENT_RANGE')) {
$files = isset($content[$this->options['param_name']]) ?
$content[$this->options['param_name']] : null;
if ($files && is_array($files) && is_object($files[0]) && $files[0]->size) {
$this->header('Range: 0-'.(
$this->fix_integer_overflow(intval($files[0]->size)) - 1
));
}
}
$this->body($json);
}
return $content;
protected function get_post_param($id) {
return @$_POST[$id];
}
protected function get_query_param($id) {
return @$_GET[$id];
}
protected function get_server_var($id) {
return @$_SERVER[$id];
}
protected function handle_form_data($file, $index) {
// Handle form data, e.g. $_POST['description'][$index]
}
protected function get_version_param() {
return isset($_GET['version']) ? basename(stripslashes($_GET['version'])) : null;
return $this->basename(stripslashes($this->get_query_param('version')));
}
protected function get_singular_param_name() {
@ -1145,14 +1160,16 @@ class UploadHandler
protected function get_file_name_param() {
$name = $this->get_singular_param_name();
return isset($_REQUEST[$name]) ? basename(stripslashes($_REQUEST[$name])) : null;
return $this->basename(stripslashes($this->get_query_param($name)));
}
protected function get_file_names_params() {
$params = isset($_REQUEST[$this->options['param_name']]) ?
$_REQUEST[$this->options['param_name']] : array();
$params = $this->get_query_param($this->options['param_name']);
if (!$params) {
return null;
}
foreach ($params as $key => $value) {
$params[$key] = basename(stripslashes($value));
$params[$key] = $this->basename(stripslashes($value));
}
return $params;
}
@ -1232,6 +1249,34 @@ class UploadHandler
.implode(', ', $this->options['access_control_allow_headers']));
}
public function generate_response($content, $print_response = true) {
$this->response = $content;
if ($print_response) {
$json = json_encode($content);
$redirect = stripslashes($this->get_post_param('redirect'));
if ($redirect && preg_match($this->options['redirect_allow_target'], $redirect)) {
$this->header('Location: '.sprintf($redirect, rawurlencode($json)));
return;
}
$this->head();
if ($this->get_server_var('HTTP_CONTENT_RANGE')) {
$files = isset($content[$this->options['param_name']]) ?
$content[$this->options['param_name']] : null;
if ($files && is_array($files) && is_object($files[0]) && $files[0]->size) {
$this->header('Range: 0-'.(
$this->fix_integer_overflow((int)$files[0]->size) - 1
));
}
}
$this->body($json);
}
return $content;
}
public function get_response () {
return $this->response;
}
public function head() {
$this->header('Pragma: no-cache');
$this->header('Cache-Control: no-store, no-cache, must-revalidate');
@ -1245,7 +1290,7 @@ class UploadHandler
}
public function get($print_response = true) {
if ($print_response && isset($_GET['download'])) {
if ($print_response && $this->get_query_param('download')) {
return $this->download();
}
$file_name = $this->get_file_name_param();
@ -1262,58 +1307,59 @@ class UploadHandler
}
public function post($print_response = true) {
if (isset($_REQUEST['_method']) && $_REQUEST['_method'] === 'DELETE') {
if ($this->get_query_param('_method') === 'DELETE') {
return $this->delete($print_response);
}
$upload = isset($_FILES[$this->options['param_name']]) ?
$_FILES[$this->options['param_name']] : null;
$upload = $this->get_upload_data($this->options['param_name']);
// Parse the Content-Disposition header, if available:
$file_name = $this->get_server_var('HTTP_CONTENT_DISPOSITION') ?
$content_disposition_header = $this->get_server_var('HTTP_CONTENT_DISPOSITION');
$file_name = $content_disposition_header ?
rawurldecode(preg_replace(
'/(^[^"]+")|("$)/',
'',
$this->get_server_var('HTTP_CONTENT_DISPOSITION')
$content_disposition_header
)) : null;
// Parse the Content-Range header, which has the following form:
// Content-Range: bytes 0-524287/2000000
$content_range = $this->get_server_var('HTTP_CONTENT_RANGE') ?
preg_split('/[^0-9]+/', $this->get_server_var('HTTP_CONTENT_RANGE')) : null;
$content_range_header = $this->get_server_var('HTTP_CONTENT_RANGE');
$content_range = $content_range_header ?
preg_split('/[^0-9]+/', $content_range_header) : null;
$size = $content_range ? $content_range[3] : null;
$files = array();
if ($upload && is_array($upload['tmp_name'])) {
// param_name is an array identifier like "files[]",
// $_FILES is a multi-dimensional array:
foreach ($upload['tmp_name'] as $index => $value) {
if ($upload) {
if (is_array($upload['tmp_name'])) {
// param_name is an array identifier like "files[]",
// $upload is a multi-dimensional array:
foreach ($upload['tmp_name'] as $index => $value) {
$files[] = $this->handle_file_upload(
$upload['tmp_name'][$index],
$file_name ? $file_name : $upload['name'][$index],
$size ? $size : $upload['size'][$index],
$upload['type'][$index],
$upload['error'][$index],
$index,
$content_range
);
}
} else {
// param_name is a single object identifier like "file",
// $upload is a one-dimensional array:
$files[] = $this->handle_file_upload(
$upload['tmp_name'][$index],
$file_name ? $file_name : $upload['name'][$index],
$size ? $size : $upload['size'][$index],
$upload['type'][$index],
$upload['error'][$index],
$index,
isset($upload['tmp_name']) ? $upload['tmp_name'] : null,
$file_name ? $file_name : (isset($upload['name']) ?
$upload['name'] : null),
$size ? $size : (isset($upload['size']) ?
$upload['size'] : $this->get_server_var('CONTENT_LENGTH')),
isset($upload['type']) ?
$upload['type'] : $this->get_server_var('CONTENT_TYPE'),
isset($upload['error']) ? $upload['error'] : null,
null,
$content_range
);
}
} else {
// param_name is a single object identifier like "file",
// $_FILES is a one-dimensional array:
$files[] = $this->handle_file_upload(
isset($upload['tmp_name']) ? $upload['tmp_name'] : null,
$file_name ? $file_name : (isset($upload['name']) ?
$upload['name'] : null),
$size ? $size : (isset($upload['size']) ?
$upload['size'] : $this->get_server_var('CONTENT_LENGTH')),
isset($upload['type']) ?
$upload['type'] : $this->get_server_var('CONTENT_TYPE'),
isset($upload['error']) ? $upload['error'] : null,
null,
$content_range
);
}
return $this->generate_response(
array($this->options['param_name'] => $files),
$print_response
);
$response = array($this->options['param_name'] => $files);
return $this->generate_response($response, $print_response);
}
public function delete($print_response = true) {
@ -1322,11 +1368,11 @@ class UploadHandler
$file_names = array($this->get_file_name_param());
}
$response = array();
foreach($file_names as $file_name) {
foreach ($file_names as $file_name) {
$file_path = $this->get_upload_path($file_name);
$success = is_file($file_path) && $file_name[0] !== '.' && unlink($file_path);
if ($success) {
foreach($this->options['image_versions'] as $version => $options) {
foreach ($this->options['image_versions'] as $version => $options) {
if (!empty($version)) {
$file = $this->get_upload_path($file_name, $version);
if (is_file($file)) {
@ -1340,4 +1386,8 @@ class UploadHandler
return $this->generate_response($response, $print_response);
}
protected function basename($filepath, $suffix = null) {
$splited = preg_split('/\//', rtrim ($filepath, '/ '));
return substr(basename('X'.$splited[count($splited)-1], $suffix), 1);
}
}

View File

@ -0,0 +1,6 @@
apache:
build: ./
ports:
- "80:80"
volumes:
- "../../:/var/www/html"

View File

@ -1,8 +1,16 @@
# The following directives force the content-type application/octet-stream
# and force browsers to display a download dialog for non-image files.
# This prevents the execution of script files in the context of the website:
# To enable the Headers module, execute the following command and reload Apache:
# sudo a2enmod headers
# The following directives prevent the execution of script files
# in the context of the website.
# They also force the content-type application/octet-stream and
# force browsers to display a download dialog for non-image files.
SetHandler default-handler
ForceType application/octet-stream
Header set Content-Disposition attachment
# The following unsets the forced type and Content-Disposition headers
# for known image files:
<FilesMatch "(?i)\.(gif|jpe?g|png)$">
ForceType none
Header unset Content-Disposition

View File

@ -1,13 +1,13 @@
<?php
/*
* jQuery File Upload Plugin PHP Example 5.14
* jQuery File Upload Plugin PHP Example
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
error_reporting(E_ALL | E_STRICT);

View File

@ -1,14 +1,14 @@
<!DOCTYPE HTML>
<!--
/*
* jQuery File Upload Plugin Test 9.1.0
* jQuery File Upload Plugin Test
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
-->
<html lang="en">
@ -20,7 +20,7 @@
<meta charset="utf-8">
<title>jQuery File Upload Plugin Test</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="http://codeorigin.jquery.com/qunit/qunit-1.14.0.css">
<link rel="stylesheet" href="//codeorigin.jquery.com/qunit/qunit-1.14.0.css">
</head>
<body>
<h1 id="qunit-header">jQuery File Upload Plugin Test</h1>
@ -36,20 +36,20 @@
<div class="col-lg-7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="fa-plus fa fa-inverse"></i>
<i class="icon-plus icon-white"></i>
<span>Add files...</span>
<input type="file" name="files[]" multiple>
</span>
<button type="submit" class="btn btn-primary start">
<i class="fa-arrow-circle-o-up fa fa-inverse"></i>
<i class="icon-upload icon-white"></i>
<span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="fa-ban fa fa-inverse"></i>
<i class="icon-ban-circle icon-white"></i>
<span>Cancel upload</span>
</button>
<button type="button" class="btn btn-danger delete">
<i class="fa-trash-o fa fa-inverse"></i>
<i class="icon-trash icon-white"></i>
<span>Delete</span>
</button>
<input type="checkbox" class="toggle">

View File

@ -1,12 +1,12 @@
/*
* jQuery File Upload Plugin Test 9.4.0
* jQuery File Upload Plugin Test
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
* https://opensource.org/licenses/MIT
*/
/* global $, QUnit, window, document, expect, module, test, asyncTest, start, ok, strictEqual, notStrictEqual */
@ -83,7 +83,7 @@ $(function () {
});
test('Paste zone initialization', function () {
ok($('#fileupload').fileupload()
ok($('#fileupload').fileupload({pasteZone: document})
.fileupload('option', 'pasteZone').length);
});
@ -98,6 +98,7 @@ $(function () {
}
},
fu = $('#fileupload').fileupload({
pasteZone: document,
dragover: function () {
ok(true, 'Triggers dragover callback');
return false;
@ -135,6 +136,7 @@ $(function () {
}
},
options = {
pasteZone: document,
dragover: function () {
ok(true, 'Triggers dragover callback');
return false;
@ -178,6 +180,7 @@ $(function () {
}
},
fu = $('#fileupload').fileupload({
pasteZone: document,
dragover: function () {
ok(true, 'Triggers dragover callback');
return false;
@ -221,6 +224,7 @@ $(function () {
}
},
fu = $('#fileupload').fileupload({
pasteZone: document,
dragover: function () {
ok(true, 'Triggers dragover callback');
return false;