diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 000000000..048b1cf2c
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+github: [blueimp]
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 000000000..0153ebdf5
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,80 @@
+name: Test
+
+on: [push, pull_request]
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ node-version: [14, 16]
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v2
+ with:
+ node-version: ${{ matrix.node-version }}
+ - run: npm install
+ - run: npm run lint
+
+ mocha:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: chmod
+ run: chmod -R 777 server/php/files
+ - name: docker-compose build
+ run: docker-compose build example mocha
+ - name: mocha
+ run: docker-compose run --rm mocha
+ - name: docker-compose logs
+ if: always()
+ run: docker-compose logs example
+ - name: docker-compose down
+ if: always()
+ run: docker-compose down -v
+
+ wdio-chrome:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: chmod
+ run: chmod -R 777 server/php/files wdio/reports
+ - name: docker-compose build
+ run: docker-compose build example
+ - name: wdio chrome
+ run: docker-compose run --rm wdio
+ - name: docker-compose logs
+ if: always()
+ run: docker-compose logs example
+ - name: docker-compose down
+ if: always()
+ run: docker-compose down -v
+ - name: Upload reports
+ if: always()
+ uses: actions/upload-artifact@v2
+ with:
+ name: reports
+ path: wdio/reports
+
+ wdio-firefox:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: chmod
+ run: chmod -R 777 server/php/files wdio/reports
+ - name: docker-compose build
+ run: docker-compose build example
+ - name: wdio firefox
+ run: docker-compose run --rm wdio conf/firefox.js
+ - name: docker-compose logs
+ if: always()
+ run: docker-compose logs example
+ - name: docker-compose down
+ if: always()
+ run: docker-compose down -v
+ - name: Upload reports
+ if: always()
+ uses: actions/upload-artifact@v2
+ with:
+ name: reports
+ path: wdio/reports
diff --git a/.gitignore b/.gitignore
index 29a41a8c4..84901da00 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
-.DS_Store
*.pyc
+.env
node_modules
diff --git a/.jshintrc b/.jshintrc
deleted file mode 100644
index 4ad82e664..000000000
--- a/.jshintrc
+++ /dev/null
@@ -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
-}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index e182f9b37..000000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,15 +0,0 @@
-Please follow these pull request guidelines:
-
-1. Update your fork to the latest upstream version.
-
-2. Follow the coding conventions of the original source files (indentation, spaces, brackets layout).
-
-3. Code changes must pass JSHint validation with the `.jshintrc` settings of this project.
-
-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.
diff --git a/Gruntfile.js b/Gruntfile.js
deleted file mode 100644
index d9e5894dd..000000000
--- a/Gruntfile.js
+++ /dev/null
@@ -1,42 +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, require */
-
-module.exports = function (grunt) {
- 'use strict';
-
- function bowerJson() {
- require('bower-json').validate(require('./bower.json'));
- }
-
- 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('bower-json', bowerJson);
- grunt.registerTask('test', ['jshint', 'bower-json']);
- grunt.registerTask('default', ['test']);
-
-};
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 000000000..ca9e708c6
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,20 @@
+MIT License
+
+Copyright © 2010 Sebastian Tschan, https://blueimp.net
+
+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.
diff --git a/README.md b/README.md
index 664b25d71..9a093c6af 100644
--- a/README.md
+++ b/README.md
@@ -1,113 +1,224 @@
-# jQuery File Upload Plugin
-
-## Demo
-[Demo File Upload](https://blueimp.github.io/jQuery-File-Upload/)
+# jQuery File Upload
+
+## Contents
+
+- [Description](#description)
+- [Demo](#demo)
+- [Features](#features)
+- [Security](#security)
+- [Setup](#setup)
+- [Requirements](#requirements)
+ - [Mandatory requirements](#mandatory-requirements)
+ - [Optional requirements](#optional-requirements)
+ - [Cross-domain requirements](#cross-domain-requirements)
+- [Browsers](#browsers)
+ - [Desktop browsers](#desktop-browsers)
+ - [Mobile browsers](#mobile-browsers)
+ - [Extended browser support information](#extended-browser-support-information)
+- [Testing](#testing)
+- [Support](#support)
+- [License](#license)
## Description
-File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery.
-Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
-## Setup
-* [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)
+> File Upload widget with multiple file selection, drag&drop support, progress
+> bars, validation and preview images, audio and video for jQuery.
+> Supports cross-domain, chunked and resumable file uploads and client-side
+> image resizing.
+> Works with any server-side platform (PHP, Python, Ruby on Rails, Java,
+> Node.js, Go etc.) that supports standard HTML form file uploads.
+
+## Demo
+
+[Demo File Upload](https://blueimp.github.io/jQuery-File-Upload/)
## Features
-* **Multiple file upload:**
+
+- **Multiple file upload:**
Allows to select multiple files at once and upload them simultaneously.
-* **Drag & Drop support:**
- Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window.
-* **Upload progress bar:**
- Shows a progress bar indicating the upload progress for individual files and for all uploads combined.
-* **Cancelable uploads:**
+- **Drag & Drop support:**
+ Allows to upload files by dragging them from your desktop or file manager and
+ dropping them on your browser window.
+- **Upload progress bar:**
+ Shows a progress bar indicating the upload progress for individual files and
+ for all uploads combined.
+- **Cancelable uploads:**
Individual file uploads can be canceled to stop the upload progress.
-* **Resumable uploads:**
+- **Resumable uploads:**
Aborted uploads can be resumed with browsers supporting the Blob API.
-* **Chunked uploads:**
- Large files can be uploaded in smaller chunks with browsers supporting the Blob API.
-* **Client-side image resizing:**
- Images can be automatically resized on client-side with browsers supporting the required JS APIs.
-* **Preview images, audio and video:**
- A preview of image, audio and video files can be displayed before uploading with browsers supporting the required APIs.
-* **No browser plugins (e.g. Adobe Flash) required:**
- The implementation is based on open standards like HTML5 and JavaScript and requires no additional browser plugins.
-* **Graceful fallback for legacy browsers:**
- Uploads files via XMLHttpRequests if supported and uses iframes as fallback for legacy browsers.
-* **HTML file upload form fallback:**
- Allows progressive enhancement by using a standard HTML file upload form as widget element.
-* **Cross-site file uploads:**
- Supports uploading files to a different domain with cross-site XMLHttpRequests or iframe redirects.
-* **Multiple plugin instances:**
+- **Chunked uploads:**
+ Large files can be uploaded in smaller chunks with browsers supporting the
+ Blob API.
+- **Client-side image resizing:**
+ Images can be automatically resized on client-side with browsers supporting
+ the required JS APIs.
+- **Preview images, audio and video:**
+ A preview of image, audio and video files can be displayed before uploading
+ with browsers supporting the required APIs.
+- **No browser plugins (e.g. Adobe Flash) required:**
+ The implementation is based on open standards like HTML5 and JavaScript and
+ requires no additional browser plugins.
+- **Graceful fallback for legacy browsers:**
+ Uploads files via XMLHttpRequests if supported and uses iframes as fallback
+ for legacy browsers.
+- **HTML file upload form fallback:**
+ Allows progressive enhancement by using a standard HTML file upload form as
+ widget element.
+- **Cross-site file uploads:**
+ Supports uploading files to a different domain with cross-site XMLHttpRequests
+ or iframe redirects.
+- **Multiple plugin instances:**
Allows to use multiple plugin instances on the same webpage.
-* **Customizable and extensible:**
- Provides an API to set individual options and define callBack methods for various upload events.
-* **Multipart and file contents stream uploads:**
- Files can be uploaded as standard "multipart/form-data" or file contents stream (HTTP PUT file upload).
-* **Compatible with any server-side application platform:**
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
+- **Customizable and extensible:**
+ Provides an API to set individual options and define callback methods for
+ various upload events.
+- **Multipart and file contents stream uploads:**
+ Files can be uploaded as standard "multipart/form-data" or file contents
+ stream (HTTP PUT file upload).
+- **Compatible with any server-side application platform:**
+ Works with any server-side platform (PHP, Python, Ruby on Rails, Java,
+ Node.js, Go etc.) that supports standard HTML form file uploads.
-## Requirements
+## Security
-### 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)
+⚠️ Please read the [VULNERABILITIES](VULNERABILITIES.md) document for a list of
+fixed vulnerabilities
-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.
+Please also read the [SECURITY](SECURITY.md) document for instructions on how to
+securely configure your Web server for file uploads.
-The jQuery Iframe Transport is required for [browsers without XHR file upload support](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
+## Setup
-### 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](http://getbootstrap.com/) v. 3.2.0+
-* [Glyphicons](http://glyphicons.com/)
+jQuery File Upload can be installed via [NPM](https://www.npmjs.com/):
-The JavaScript Templates engine is used to render the selected and uploaded files for the Basic Plus UI and jQuery UI versions.
+```sh
+npm install blueimp-file-upload
+```
-The JavaScript Load Image library and JavaScript Canvas to Blob polyfill are required for the image previews and resizing functionality.
+This allows you to include [jquery.fileupload.js](js/jquery.fileupload.js) and
+its extensions via `node_modules`, e.g:
-The blueimp Gallery is used to display the uploaded images in a lightbox.
+```html
+
+```
-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/).
+The widget can then be initialized on a file upload form the following way:
+
+```js
+$('#fileupload').fileupload();
+```
+
+For further information, please refer to the following guides:
+
+- [Main documentation page](https://github.com/blueimp/jQuery-File-Upload/wiki)
+- [List of all available Options](https://github.com/blueimp/jQuery-File-Upload/wiki/Options)
+- [The plugin API](https://github.com/blueimp/jQuery-File-Upload/wiki/API)
+- [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup)
+- [How to use only the basic plugin.](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin)
+
+## Requirements
+
+### Mandatory requirements
+
+- [jQuery](https://jquery.com/) v1.7+
+- [jQuery UI widget factory](https://api.jqueryui.com/jQuery.widget/) v1.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)
+ v3+: Used to render the selected and uploaded files.
+- [JavaScript Load Image library](https://github.com/blueimp/JavaScript-Load-Image)
+ v2+: Required for the image previews and resizing functionality.
+- [JavaScript Canvas to Blob polyfill](https://github.com/blueimp/JavaScript-Canvas-to-Blob)
+ v3+:Required for the resizing functionality.
+- [blueimp Gallery](https://github.com/blueimp/Gallery) v2+: Used to display the
+ uploaded images in a lightbox.
+- [Bootstrap](https://getbootstrap.com/) v3+: Used for the demo design.
+- [Glyphicons](https://glyphicons.com/) Icon set used by Bootstrap.
### 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.
-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.
+[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.
+
+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.
## Browsers
### Desktop browsers
-The File Upload plugin is regularly tested with the latest browser versions and supports the following minimal versions:
-* Google Chrome
-* Apple Safari 4.0+
-* Mozilla Firefox 3.0+
-* Opera 11.0+
-* Microsoft Internet Explorer 6.0+
+The File Upload plugin is regularly tested with the latest browser versions and
+supports the following minimal versions:
+
+- Google Chrome
+- Apple Safari 4.0+
+- Mozilla Firefox 3.0+
+- Opera 11.0+
+- Microsoft Internet Explorer 6.0+
### Mobile browsers
-The File Upload plugin has been tested with and supports the following mobile browsers:
-* Apple Safari on iOS 6.0+
-* Google Chrome on iOS 6.0+
-* Google Chrome on Android 4.0+
-* Default Browser on Android 2.3+
-* Opera Mobile 12.0+
+The File Upload plugin has been tested with and supports the following mobile
+browsers:
-### 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).
+- Apple Safari on iOS 6.0+
+- Google Chrome on iOS 6.0+
+- Google Chrome on Android 4.0+
+- Default Browser on Android 2.3+
+- Opera Mobile 12.0+
-## 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.
+### Extended browser support information
+
+For a detailed overview of the features supported by each browser version and
+known operating system / browser bugs, please have a look at the
+[Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
+
+## Testing
+
+The project comes with three sets of tests:
+
+1. Code linting using [ESLint](https://eslint.org/).
+2. Unit tests using [Mocha](https://mochajs.org/).
+3. End-to-end tests using [blueimp/wdio](https://github.com/blueimp/wdio).
+
+To run the tests, follow these steps:
+
+1. Start [Docker](https://docs.docker.com/).
+2. Install development dependencies:
+ ```sh
+ npm install
+ ```
+3. Run the tests:
+ ```sh
+ npm test
+ ```
## 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`.
+If you have a question that another developer might help you with, please post
+to
+[Stack Overflow](https://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).
+
+Released under the [MIT license](https://opensource.org/licenses/MIT).
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..433a6853c
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,227 @@
+# File Upload Security
+
+## Contents
+
+- [Introduction](#introduction)
+- [Purpose of this project](#purpose-of-this-project)
+- [Mitigations against file upload risks](#mitigations-against-file-upload-risks)
+ - [Prevent code execution on the server](#prevent-code-execution-on-the-server)
+ - [Prevent code execution in the browser](#prevent-code-execution-in-the-browser)
+ - [Prevent distribution of malware](#prevent-distribution-of-malware)
+- [Secure file upload serving configurations](#secure-file-upload-serving-configurations)
+ - [Apache config](#apache-config)
+ - [NGINX config](#nginx-config)
+- [Secure image processing configurations](#secure-image-processing-configurations)
+- [ImageMagick config](#imagemagick-config)
+
+## Introduction
+
+For an in-depth understanding of the potential security risks of providing file
+uploads and possible mitigations, please refer to the
+[OWASP - Unrestricted File Upload](https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload)
+documentation.
+
+To securely setup the project to serve uploaded files, please refer to the
+sample
+[Secure file upload serving configurations](#secure-file-upload-serving-configurations).
+
+To mitigate potential vulnerabilities in image processing libraries, please
+refer to the
+[Secure image processing configurations](#secure-image-processing-configurations).
+
+By default, all sample upload handlers allow only upload of image files, which
+mitigates some attack vectors, but should not be relied on as the only
+protection.
+
+Please also have a look at the
+[list of fixed vulnerabilities](VULNERABILITIES.md) in jQuery File Upload, which
+relates mostly to the sample server-side upload handlers and how they have been
+configured.
+
+## Purpose of this project
+
+Please note that this project is not a complete file management product, but
+foremost a client-side file upload library for [jQuery](https://jquery.com/).
+The server-side sample upload handlers are just examples to demonstrate the
+client-side file upload functionality.
+
+To make this very clear, there is **no user authentication** by default:
+
+- **everyone can upload files**
+- **everyone can delete uploaded files**
+
+In some cases this can be acceptable, but for most projects you will want to
+extend the sample upload handlers to integrate user authentication, or implement
+your own.
+
+It is also up to you to configure your web server to securely serve the uploaded
+files, e.g. using the
+[sample server configurations](#secure-file-upload-serving-configurations).
+
+## Mitigations against file upload risks
+
+### Prevent code execution on the server
+
+To prevent execution of scripts or binaries on server-side, the upload directory
+must be configured to not execute files in the upload directory (e.g.
+`server/php/files` as the default for the PHP upload handler) and only treat
+uploaded files as static content.
+
+The recommended way to do this is to configure the upload directory path to
+point outside of the web application root.
+Then the web server can be configured to serve files from the upload directory
+with their default static files handler only.
+
+Limiting file uploads to a whitelist of safe file types (e.g. image files) also
+mitigates this issue, but should not be the only protection.
+
+### Prevent code execution in the browser
+
+To prevent execution of scripts on client-side, the following headers must be
+sent when delivering generic uploaded files to the client:
+
+```
+Content-Type: application/octet-stream
+X-Content-Type-Options: nosniff
+```
+
+The `Content-Type: application/octet-stream` header instructs browsers to
+display a download dialog instead of parsing it and possibly executing script
+content e.g. in HTML files.
+
+The `X-Content-Type-Options: nosniff` header prevents browsers to try to detect
+the file mime type despite the given content-type header.
+
+For known safe files, the content-type header can be adjusted using a
+**whitelist**, e.g. sending `Content-Type: image/png` for PNG files.
+
+### Prevent distribution of malware
+
+To prevent attackers from uploading and distributing malware (e.g. computer
+viruses), it is recommended to limit file uploads only to a whitelist of safe
+file types.
+
+Please note that the detection of file types in the sample file upload handlers
+is based on the file extension and not the actual file content. This makes it
+still possible for attackers to upload malware by giving their files an image
+file extension, but should prevent automatic execution on client computers when
+opening those files.
+
+It does not protect at all from exploiting vulnerabilities in image display
+programs, nor from users renaming file extensions to inadvertently execute the
+contained malicious code.
+
+## Secure file upload serving configurations
+
+The following configurations serve uploaded files as static files with the
+proper headers as
+[mitigation against file upload risks](#mitigations-against-file-upload-risks).
+Please do not simply copy&paste these configurations, but make sure you
+understand what they are doing and that you have implemented them correctly.
+
+> Always test your own setup and make sure that it is secure!
+
+e.g. try uploading PHP scripts (as "example.php", "example.php.png" and
+"example.png") to see if they get executed by your web server, e.g. the content
+of the following sample:
+
+```php
+GIF89ad
+ # Some of the directives require the Apache Headers module. If it is not
+ # already enabled, please execute the following command and reload Apache:
+ # sudo a2enmod headers
+ #
+ # Please note that the order of directives across configuration files matters,
+ # see also:
+ # https://httpd.apache.org/docs/current/sections.html#merging
+
+ # The following directive matches all files and forces them to be handled as
+ # static content, which prevents the server from parsing and executing files
+ # that are associated with a dynamic runtime, e.g. PHP files.
+ # It also forces their Content-Type header to "application/octet-stream" and
+ # adds a "Content-Disposition: attachment" header to force a download dialog,
+ # which prevents browsers from interpreting files in the context of the
+ # web server, e.g. HTML files containing JavaScript.
+ # Lastly it also prevents browsers from MIME-sniffing the Content-Type,
+ # preventing them from interpreting a file as a different Content-Type than
+ # the one sent by the webserver.
+
--File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for AngularJS.
-
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
--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 and client-side image resizing.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
--File Upload widget with multiple file selection, drag&drop support and progress bar for jQuery.
-
- Supports cross-domain, chunked and resumable file uploads.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.